rtc-svc: Add set reference to SVC interface
Add set references to the SET_SVC_REF_FRAME_CONFIG
control, this allows user to completely specify
the layered pattern via the control, and avoids
the use of the flags AOM_EFLAG_NO_REF_.
Use this for the (3 spatial, 3 temporal) example
(mode >= 7) in the svc-rtc sample encoder.
Update SVC unittests with this reference set control.
Change-Id: I6b1403b1d00b2dd628714fb3161dbcba757ad416
diff --git a/aom/aomcx.h b/aom/aomcx.h
index c42725b..628c650 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -1320,6 +1320,7 @@
typedef struct aom_svc_ref_frame_config {
// 7 references: LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2),
// GOLDEN_FRAME(3), BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6).
+ int reference[7]; /**< Reference flag for each of the 7 references. */
/*! Buffer slot index for each of 7 references. */
int ref_idx[7];
int refresh[8]; /**< Refresh flag for each of the 8 slots. */
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 5ca8256..e13ed95 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -2523,8 +2523,10 @@
aom_svc_ref_frame_config_t *const data =
va_arg(args, aom_svc_ref_frame_config_t *);
cpi->svc.external_ref_frame_config = 1;
- for (unsigned int i = 0; i < INTER_REFS_PER_FRAME; ++i)
+ for (unsigned int i = 0; i < INTER_REFS_PER_FRAME; ++i) {
+ cpi->svc.reference[i] = data->reference[i];
cpi->svc.ref_idx[i] = data->ref_idx[i];
+ }
for (unsigned int i = 0; i < REF_FRAMES; ++i)
cpi->svc.refresh[i] = data->refresh[i];
return AOM_CODEC_OK;
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 44ce442..69e125c 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -6993,6 +6993,16 @@
}
}
+static int svc_set_references_external_ref_frame_config(AV1_COMP *cpi) {
+ // LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2), GOLDEN_FRAME(3),
+ // BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6).
+ int ref = AOM_REFFRAME_ALL;
+ for (int i = 0; i < INTER_REFS_PER_FRAME; i++) {
+ if (!cpi->svc.reference[i]) ref ^= (1 << i);
+ }
+ return ref;
+}
+
void av1_apply_encoding_flags(AV1_COMP *cpi, aom_enc_frame_flags_t flags) {
// TODO(yunqingwang): For what references to use, external encoding flags
// should be consistent with internal reference frame selection. Need to
@@ -7022,6 +7032,11 @@
}
av1_use_as_reference(cpi, ref);
+ } else {
+ if (cpi->svc.external_ref_frame_config) {
+ int ref = svc_set_references_external_ref_frame_config(cpi);
+ av1_use_as_reference(cpi, ref);
+ }
}
if (flags &
diff --git a/av1/encoder/svc_layercontext.h b/av1/encoder/svc_layercontext.h
index bbbd07a..7cb85a3 100644
--- a/av1/encoder/svc_layercontext.h
+++ b/av1/encoder/svc_layercontext.h
@@ -50,6 +50,9 @@
int number_temporal_layers;
int external_ref_frame_config;
int non_reference_frame;
+ // LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2), GOLDEN_FRAME(3),
+ // BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6).
+ int reference[INTER_REFS_PER_FRAME];
int ref_idx[INTER_REFS_PER_FRAME];
int refresh[REF_FRAMES];
double base_framerate;
diff --git a/examples/svc_encoder_rtc.c b/examples/svc_encoder_rtc.c
index 77ae897..1316c6c 100644
--- a/examples/svc_encoder_rtc.c
+++ b/examples/svc_encoder_rtc.c
@@ -258,8 +258,10 @@
// LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2), GOLDEN_FRAME(3),
// BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6).
for (i = 0; i < INTER_REFS_PER_FRAME; i++) ref_frame_config->ref_idx[i] = i;
+ for (i = 0; i < INTER_REFS_PER_FRAME; i++) ref_frame_config->reference[i] = 0;
for (i = 0; i < REF_FRAMES; i++) ref_frame_config->refresh[i] = 0;
- // Note only use LAST and GF for prediction in non-rd mode (speed 8).
+ // Note for this layered patterns only use LAST and GF for prediction in
+ // non-rd mode (speed >= 7).
int layer_flags = AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
AOM_EFLAG_NO_REF_ARF2;
@@ -347,7 +349,7 @@
}
break;
case 4:
- // 2-temporla layer with the old update flags, not with the new
+ // 2-temporal layer with the old update flags, not with the new
// SVC control.
*use_svc_control = 0;
// 1 3 5
@@ -420,6 +422,10 @@
// 3 spatial and 3 temporal layer.
// No overlap in buffer updates between TL2 and TL1.
// TL2 updates slot 3 and 4, TL1 updates 5, 6, 7.
+ // Set the references via the svc_ref_frame_config control.
+ layer_flags = 0;
+ // Always reference LAST.
+ ref_frame_config->reference[0] = 1;
if (superframe_cnt % 4 == 0) {
// Base temporal layer.
layer_id->temporal_layer_id = 0;
@@ -429,7 +435,6 @@
for (i = 0; i < INTER_REFS_PER_FRAME; i++)
ref_frame_config->ref_idx[i] = 0;
ref_frame_config->refresh[0] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1,
// GOLDEN (and all other refs) to slot 0.
@@ -458,7 +463,6 @@
ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[3] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1,
// GOLDEN (and all other refs) to slot 3.
@@ -487,7 +491,6 @@
ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[3] = 5 - shift;
ref_frame_config->refresh[5 - shift] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1,
// GOLDEN (and all other refs) to slot 5.
@@ -519,7 +522,6 @@
ref_frame_config->ref_idx[0] = 5 - shift;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[3] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 6,
// GOLDEN to slot 3. Set LAST2 to slot 4 and update slot 4.
@@ -538,6 +540,8 @@
ref_frame_config->ref_idx[3] = 4;
}
}
+ if (layer_id->spatial_layer_id > 0)
+ ref_frame_config->reference[3] = 1; // Reference GOLDEN.
break;
default: assert(0); die("Error: Unsupported temporal layering mode!\n");
}
diff --git a/test/svc_datarate_test.cc b/test/svc_datarate_test.cc
index f806f2d..1d950f9 100644
--- a/test/svc_datarate_test.cc
+++ b/test/svc_datarate_test.cc
@@ -19,6 +19,7 @@
#include "test/util.h"
#include "test/y4m_video_source.h"
#include "aom/aom_codec.h"
+#include "av1/common/enums.h"
namespace datarate_test {
namespace {
@@ -114,12 +115,15 @@
// Set the referende map buffer idx for the 7 references:
// LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2), GOLDEN_FRAME(3),
// BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6).
- for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = i;
- for (int i = 0; i < 8; i++) ref_frame_config->refresh[i] = 0;
- // Note only use LAST and GF for prediction in non-rd mode (speed 8).
- int layer_flags = AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
- AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
- AOM_EFLAG_NO_REF_ARF2;
+ for (int i = 0; i < INTER_REFS_PER_FRAME; i++) {
+ ref_frame_config->ref_idx[i] = i;
+ ref_frame_config->reference[i] = 0;
+ }
+ for (int i = 0; i < REF_FRAMES; i++) ref_frame_config->refresh[i] = 0;
+ // Set layer_flags to 0 when using ref_frame_config->reference.
+ int layer_flags = 0;
+ // Always reference LAST.
+ ref_frame_config->reference[0] = 1;
if (number_temporal_layers_ == 3 && number_spatial_layers_ == 1) {
// 3-layer:
// 1 3 5 7
@@ -130,15 +134,14 @@
layer_id->temporal_layer_id = 0;
// Update LAST on layer 0, reference LAST and GF.
ref_frame_config->refresh[0] = 1;
+ ref_frame_config->reference[3] = 1;
} else if ((frame_cnt - 1) % 4 == 0) {
layer_id->temporal_layer_id = 2;
// First top layer: no updates, only reference LAST (TL0).
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if ((frame_cnt - 2) % 4 == 0) {
layer_id->temporal_layer_id = 1;
// Middle layer (TL1): update LAST2, only reference LAST (TL0).
ref_frame_config->refresh[1] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if ((frame_cnt - 3) % 4 == 0) {
layer_id->temporal_layer_id = 2;
// Second top layer: no updates, only reference LAST.
@@ -146,7 +149,6 @@
// updated in previous frame. So LAST is TL1 frame.
ref_frame_config->ref_idx[0] = 1;
ref_frame_config->ref_idx[1] = 0;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
}
} else if (number_temporal_layers_ == 1 && number_spatial_layers_ == 2) {
layer_id->temporal_layer_id = 0;
@@ -155,7 +157,6 @@
ref_frame_config->ref_idx[0] = 0;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[0] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 3
// and GOLDEN to slot 0. Update slot 3 (LAST).
@@ -163,6 +164,8 @@
ref_frame_config->ref_idx[3] = 0;
ref_frame_config->refresh[3] = 1;
}
+ // Reference GOLDEN.
+ if (layer_id->spatial_layer_id > 0) ref_frame_config->reference[3] = 1;
} else if (number_temporal_layers_ == 1 && number_spatial_layers_ == 3) {
// 3 spatial layers, 1 temporal.
// Note for this case , we set the buffer idx for all references to be
@@ -174,7 +177,6 @@
// Reference LAST, update LAST. Set all other buffer_idx to 0.
for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->refresh[0] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1
// and GOLDEN (and all other refs) to slot 0.
@@ -190,6 +192,8 @@
ref_frame_config->ref_idx[0] = 2;
ref_frame_config->refresh[2] = 1;
}
+ // Reference GOLDEN.
+ if (layer_id->spatial_layer_id > 0) ref_frame_config->reference[3] = 1;
} else if (number_temporal_layers_ == 3 && number_spatial_layers_ == 3) {
// 3 spatial and 3 temporal layer.
if (superframe_cnt_ % 4 == 0) {
@@ -200,7 +204,6 @@
// Set all buffer_idx to 0.
for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->refresh[0] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1,
// GOLDEN (and all other refs) to slot 0.
@@ -226,7 +229,6 @@
for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[3] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1,
// GOLDEN (and all other refs) to slot 3.
@@ -252,7 +254,6 @@
for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
ref_frame_config->ref_idx[3] = 5;
ref_frame_config->refresh[5] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1,
// GOLDEN (and all other refs) to slot 5.
@@ -281,7 +282,6 @@
ref_frame_config->ref_idx[0] = 5;
ref_frame_config->ref_idx[3] = 3;
ref_frame_config->refresh[3] = 1;
- layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
// Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 6,
// GOLDEN to slot 3. Set LAST2 to slot 4 and update slot 4.
@@ -298,6 +298,8 @@
ref_frame_config->ref_idx[3] = 4;
}
}
+ // Reference GOLDEN.
+ if (layer_id->spatial_layer_id > 0) ref_frame_config->reference[3] = 1;
}
return layer_flags;
}