Implement the new level definitions from CWG-C013
Added support for levels 7.x and 8.x.
Bug: aomedia:3184
Bug: aomedia:2871
Change-Id: Ia8123643a3fbc7eeff5fed4b42e9e7beb4fafdcb
diff --git a/aom/aomcx.h b/aom/aomcx.h
index 8f129369..68e7daf 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -616,10 +616,11 @@
* point (OP), int parameter
* Possible values are in the form of "ABxy".
* - AB: OP index.
- * - xy: Target level index for the OP. Can be values 0~23 (corresponding to
- * level 2.0 ~ 7.3, note levels 2.2, 2.3, 3.2, 3.3, 4.2, 4.3, 7.0, 7.1, 7.2
- * & 7.3 are undefined) or 24 (keep level stats only for level monitoring)
- * or 31 (maximum level parameter, no level-based constraints).
+ * - xy: Target level index for the OP. Can be values 0~27 (corresponding to
+ * level 2.0 ~ 8.3, note levels 2.2, 2.3, 3.2, 3.3, 4.2 & 4.3 are
+ * undefined, and that levels 7.x and 8.x are in draft status), 31
+ * (maximum level parameter, no level-based constraints) or 32 (keep
+ * level stats only for level monitoring).
*
* E.g.:
* - "0" means target level index 0 (2.0) for the 0th OP;
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index ace6930..e8cc7e2 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -832,7 +832,8 @@
for (int i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) {
const int level_idx = extra_cfg->target_seq_level_idx[i];
- if (!is_valid_seq_level_idx(level_idx) && level_idx != SEQ_LEVELS) {
+ if (!is_valid_seq_level_idx(level_idx) &&
+ level_idx != SEQ_LEVEL_KEEP_STATS) {
ERROR("Target sequence level index is invalid");
}
}
diff --git a/av1/common/av1_common_int.h b/av1/common/av1_common_int.h
index fd2ec06..f3c19f4 100644
--- a/av1/common/av1_common_int.h
+++ b/av1/common/av1_common_int.h
@@ -1871,9 +1871,7 @@
// The following levels are currently undefined.
seq_level_idx != SEQ_LEVEL_2_2 && seq_level_idx != SEQ_LEVEL_2_3 &&
seq_level_idx != SEQ_LEVEL_3_2 && seq_level_idx != SEQ_LEVEL_3_3 &&
- seq_level_idx != SEQ_LEVEL_4_2 && seq_level_idx != SEQ_LEVEL_4_3 &&
- seq_level_idx != SEQ_LEVEL_7_0 && seq_level_idx != SEQ_LEVEL_7_1 &&
- seq_level_idx != SEQ_LEVEL_7_2 && seq_level_idx != SEQ_LEVEL_7_3);
+ seq_level_idx != SEQ_LEVEL_4_2 && seq_level_idx != SEQ_LEVEL_4_3);
}
/*!\endcond */
diff --git a/av1/common/enums.h b/av1/common/enums.h
index eb655c9..e73bf50 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -454,8 +454,13 @@
SEQ_LEVEL_7_1,
SEQ_LEVEL_7_2,
SEQ_LEVEL_7_3,
+ SEQ_LEVEL_8_0,
+ SEQ_LEVEL_8_1,
+ SEQ_LEVEL_8_2,
+ SEQ_LEVEL_8_3,
SEQ_LEVELS,
- SEQ_LEVEL_MAX = 31
+ SEQ_LEVEL_MAX = 31,
+ SEQ_LEVEL_KEEP_STATS = 32,
} UENUM1BYTE(AV1_LEVEL);
#define LEVEL_BITS 5
diff --git a/av1/common/tile_common.c b/av1/common/tile_common.c
index 6ecead8..71eaf01 100644
--- a/av1/common/tile_common.c
+++ b/av1/common/tile_common.c
@@ -9,6 +9,8 @@
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
+#include <stdbool.h>
+
#include "av1/common/av1_common_int.h"
#include "av1/common/resize.h"
#include "av1/common/tile_common.h"
@@ -37,7 +39,20 @@
const int sb_size_log2 = seq_params->mib_size_log2 + MI_SIZE_LOG2;
tiles->max_width_sb = MAX_TILE_WIDTH >> sb_size_log2;
- const int max_tile_area_sb = MAX_TILE_AREA >> (2 * sb_size_log2);
+
+ bool use_level_7_above = false;
+ for (int i = 0; i < seq_params->operating_points_cnt_minus_1 + 1; i++) {
+ if (seq_params->seq_level_idx[i] >= SEQ_LEVEL_7_0 &&
+ seq_params->seq_level_idx[i] <= SEQ_LEVEL_8_3) {
+ // Currently it is assumed that levels 7.x/8.x are either used for all
+ // operating points, or none of them.
+ assert(i == 0 || use_level_7_above);
+ use_level_7_above = true;
+ }
+ }
+ const int max_tile_area_sb =
+ (use_level_7_above ? MAX_TILE_AREA_LEVEL_7_AND_ABOVE : MAX_TILE_AREA) >>
+ (2 * sb_size_log2);
tiles->min_log2_cols = tile_log2(tiles->max_width_sb, sb_cols);
tiles->max_log2_cols = tile_log2(1, AOMMIN(sb_cols, MAX_TILE_COLS));
diff --git a/av1/common/tile_common.h b/av1/common/tile_common.h
index 5e90d95..68bf092 100644
--- a/av1/common/tile_common.h
+++ b/av1/common/tile_common.h
@@ -55,6 +55,7 @@
// The minimum tile width or height is fixed at one superblock
#define MAX_TILE_WIDTH (4096) // Max Tile width in pixels
#define MAX_TILE_AREA (4096 * 2304) // Maximum tile area in pixels
+#define MAX_TILE_AREA_LEVEL_7_AND_ABOVE (4096 * 4608)
void av1_get_uniform_tile_size(const struct AV1Common *cm, int *w, int *h);
void av1_get_tile_limits(struct AV1Common *const cm);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 63a56f2..1cdc670 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -380,6 +380,24 @@
} else if (does_level_match(width, height, init_framerate, 8192, 4352, 120.0,
2)) {
level = SEQ_LEVEL_6_2;
+ } else if (does_level_match(width, height, init_framerate, 16384, 8704, 30.0,
+ 2)) {
+ level = SEQ_LEVEL_7_0;
+ } else if (does_level_match(width, height, init_framerate, 16384, 8704, 60.0,
+ 2)) {
+ level = SEQ_LEVEL_7_1;
+ } else if (does_level_match(width, height, init_framerate, 16384, 8704, 120.0,
+ 2)) {
+ level = SEQ_LEVEL_7_2;
+ } else if (does_level_match(width, height, init_framerate, 32768, 17408, 30.0,
+ 2)) {
+ level = SEQ_LEVEL_8_0;
+ } else if (does_level_match(width, height, init_framerate, 32768, 17408, 60.0,
+ 2)) {
+ level = SEQ_LEVEL_8_1;
+ } else if (does_level_match(width, height, init_framerate, 32768, 17408,
+ 120.0, 2)) {
+ level = SEQ_LEVEL_8_2;
}
for (int i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) {
@@ -721,7 +739,8 @@
sizeof(level_params->target_seq_level_idx));
level_params->keep_level_stats = 0;
for (int i = 0; i < MAX_NUM_OPERATING_POINTS; ++i) {
- if (level_params->target_seq_level_idx[i] <= SEQ_LEVELS) {
+ if (level_params->target_seq_level_idx[i] < SEQ_LEVELS ||
+ level_params->target_seq_level_idx[i] == SEQ_LEVEL_KEEP_STATS) {
level_params->keep_level_stats |= 1u << i;
if (!level_params->level_info[i]) {
CHECK_MEM_ERROR(cm, level_params->level_info[i],
diff --git a/av1/encoder/level.c b/av1/encoder/level.c
index eab4728..4d17142 100644
--- a/av1/encoder/level.c
+++ b/av1/encoder/level.c
@@ -209,10 +209,110 @@
.high_cr = 4.0,
.max_tiles = 128,
.max_tile_cols = 16 },
- UNDEFINED_LEVEL,
- UNDEFINED_LEVEL,
- UNDEFINED_LEVEL,
- UNDEFINED_LEVEL,
+ { .level = SEQ_LEVEL_7_0,
+ .max_picture_size = 142606336,
+ .max_h_size = 32768,
+ .max_v_size = 17408,
+ .max_display_rate = 4278190080L,
+ .max_decode_rate = 4706009088L,
+ .max_header_rate = 300,
+ .main_mbps = 160.0,
+ .high_mbps = 800.0,
+ .main_cr = 8.0,
+ .high_cr = 4.0,
+ .max_tiles = 256,
+ .max_tile_cols = 32 },
+ { .level = SEQ_LEVEL_7_1,
+ .max_picture_size = 142606336,
+ .max_h_size = 32768,
+ .max_v_size = 17408,
+ .max_display_rate = 8556380160L,
+ .max_decode_rate = 8758886400L,
+ .max_header_rate = 300,
+ .main_mbps = 200.0,
+ .high_mbps = 960.0,
+ .main_cr = 8.0,
+ .high_cr = 4.0,
+ .max_tiles = 256,
+ .max_tile_cols = 32 },
+ { .level = SEQ_LEVEL_7_2,
+ .max_picture_size = 142606336,
+ .max_h_size = 32768,
+ .max_v_size = 17408,
+ .max_display_rate = 17112760320L,
+ .max_decode_rate = 17517772800L,
+ .max_header_rate = 300,
+ .main_mbps = 320.0,
+ .high_mbps = 1600.0,
+ .main_cr = 8.0,
+ .high_cr = 4.0,
+ .max_tiles = 256,
+ .max_tile_cols = 32 },
+ { .level = SEQ_LEVEL_7_3,
+ .max_picture_size = 142606336,
+ .max_h_size = 32768,
+ .max_v_size = 17408,
+ .max_display_rate = 17112760320L,
+ .max_decode_rate = 18824036352L,
+ .max_header_rate = 300,
+ .main_mbps = 320.0,
+ .high_mbps = 1600.0,
+ .main_cr = 8.0,
+ .high_cr = 4.0,
+ .max_tiles = 256,
+ .max_tile_cols = 32 },
+ { .level = SEQ_LEVEL_8_0,
+ .max_picture_size = 530841600,
+ .max_h_size = 65536,
+ .max_v_size = 34816,
+ .max_display_rate = 17112760320L,
+ .max_decode_rate = 18824036352L,
+ .max_header_rate = 300,
+ .main_mbps = 320.0,
+ .high_mbps = 1600.0,
+ .main_cr = 8.0,
+ .high_cr = 4.0,
+ .max_tiles = 512,
+ .max_tile_cols = 64 },
+ { .level = SEQ_LEVEL_8_1,
+ .max_picture_size = 530841600,
+ .max_h_size = 65536,
+ .max_v_size = 34816,
+ .max_display_rate = 34225520640L,
+ .max_decode_rate = 34910031052L,
+ .max_header_rate = 300,
+ .main_mbps = 400.0,
+ .high_mbps = 1920.0,
+ .main_cr = 8.0,
+ .high_cr = 4.0,
+ .max_tiles = 512,
+ .max_tile_cols = 64 },
+ { .level = SEQ_LEVEL_8_2,
+ .max_picture_size = 530841600,
+ .max_h_size = 65536,
+ .max_v_size = 34816,
+ .max_display_rate = 68451041280L,
+ .max_decode_rate = 69820062105L,
+ .max_header_rate = 300,
+ .main_mbps = 640.0,
+ .high_mbps = 3200.0,
+ .main_cr = 8.0,
+ .high_cr = 4.0,
+ .max_tiles = 512,
+ .max_tile_cols = 64 },
+ { .level = SEQ_LEVEL_8_3,
+ .max_picture_size = 530841600,
+ .max_h_size = 65536,
+ .max_v_size = 34816,
+ .max_display_rate = 68451041280L,
+ .max_decode_rate = 75296145408L,
+ .max_header_rate = 300,
+ .main_mbps = 640.0,
+ .high_mbps = 3200.0,
+ .main_cr = 8.0,
+ .high_cr = 4.0,
+ .max_tiles = 512,
+ .max_tile_cols = 64 },
};
typedef enum {
@@ -846,7 +946,6 @@
}
}
-#define MAX_TILE_SIZE (4096 * 2304)
#define MIN_CROPPED_TILE_WIDTH 8
#define MIN_CROPPED_TILE_HEIGHT 8
#define MIN_FRAME_WIDTH 16
@@ -917,7 +1016,10 @@
break;
}
- if (level_stats->max_tile_size > MAX_TILE_SIZE) {
+ const int max_tile_size = (level >= SEQ_LEVEL_7_0 && level <= SEQ_LEVEL_8_3)
+ ? MAX_TILE_AREA_LEVEL_7_AND_ABOVE
+ : MAX_TILE_AREA;
+ if (level_stats->max_tile_size > max_tile_size) {
fail_id = TILE_TOO_LARGE;
break;
}
diff --git a/test/invalid_file_test.cc b/test/invalid_file_test.cc
index 261ab31..1fc849e 100644
--- a/test/invalid_file_test.cc
+++ b/test/invalid_file_test.cc
@@ -146,7 +146,7 @@
{ 1, "invalid-oss-fuzz-10227.ivf", nullptr },
{ 4, "invalid-oss-fuzz-10555.ivf", nullptr },
{ 1, "invalid-oss-fuzz-10705.ivf", nullptr },
- { 1, "invalid-oss-fuzz-10723.ivf", "invalid-oss-fuzz-10723.ivf.res.2" },
+ { 1, "invalid-oss-fuzz-10723.ivf", "invalid-oss-fuzz-10723.ivf.res.3" },
{ 1, "invalid-oss-fuzz-10779.ivf", nullptr },
{ 1, "invalid-oss-fuzz-11477.ivf", nullptr },
{ 1, "invalid-oss-fuzz-11479.ivf", "invalid-oss-fuzz-11479.ivf.res.2" },
diff --git a/test/level_test.cc b/test/level_test.cc
index 9efd6c8..8759b9b 100644
--- a/test/level_test.cc
+++ b/test/level_test.cc
@@ -22,7 +22,7 @@
namespace {
const int kLevelMin = 0;
const int kLevelMax = 31;
-const int kLevelKeepStats = 24;
+const int kLevelKeepStats = 32;
// Speed settings tested
static const int kCpuUsedVectors[] = {
1,
@@ -87,10 +87,10 @@
for (int operating_point = 0; operating_point <= 32; ++operating_point) {
for (int level = 0; level <= 32; ++level) {
const int target_level = operating_point * 100 + level;
- if ((level <= 24 && level != 2 && level != 3 && level != 6 &&
- level != 7 && level != 10 && level != 11 && level != 20 &&
- level != 21 && level != 22 && level != 23) ||
- level == 31 || operating_point > 31) {
+ if ((level < 28 && level != 2 && level != 3 && level != 6 && level != 7 &&
+ level != 10 && level != 11) ||
+ level == kLevelMax || level == kLevelKeepStats ||
+ operating_point > 31) {
EXPECT_EQ(AOM_CODEC_OK,
AOM_CODEC_CONTROL_TYPECHECKED(
&enc, AV1E_SET_TARGET_SEQ_LEVEL_IDX, target_level));
diff --git a/test/test-data.sha1 b/test/test-data.sha1
index a3074ce..d790da4 100644
--- a/test/test-data.sha1
+++ b/test/test-data.sha1
@@ -22,7 +22,7 @@
cf5945085fe85456a1f74bf4cc7998b88b3f4b62 *invalid-oss-fuzz-10705.ivf
758671858368ffd2a2c0727898de5661f7cf7d68 *invalid-oss-fuzz-10705.ivf.res
88e29851122cca3f336824f7fa4d9f757f91110c *invalid-oss-fuzz-10723.ivf
-64f8a208dec7f1580fbe0371aa15e62bb1262715 *invalid-oss-fuzz-10723.ivf.res.2
+1af486cd2cc83ebeddc76ca7a1c512cc0ec568d5 *invalid-oss-fuzz-10723.ivf.res.3
0784acc8931090ec24eba752d6c27e359e68fe7d *invalid-oss-fuzz-10779.ivf
5d9474c0309b7ca09a182d888f73b37a8fe1362c *invalid-oss-fuzz-10779.ivf.res
7d37be9357f89a100ced694aee1ca5a6fad35ba9 *invalid-oss-fuzz-11477.ivf
diff --git a/test/test_data_util.cmake b/test/test_data_util.cmake
index a59ff45..20c5f34 100644
--- a/test/test_data_util.cmake
+++ b/test/test_data_util.cmake
@@ -551,7 +551,7 @@
"invalid-oss-fuzz-10705.ivf"
"invalid-oss-fuzz-10705.ivf.res"
"invalid-oss-fuzz-10723.ivf"
- "invalid-oss-fuzz-10723.ivf.res.2"
+ "invalid-oss-fuzz-10723.ivf.res.3"
"invalid-oss-fuzz-10779.ivf"
"invalid-oss-fuzz-10779.ivf.res"
"invalid-oss-fuzz-11477.ivf"