Add check for product of tile size and header rate

BUG=aomedia:2332

Change-Id: I4d4f0e3cfa438a5d9849f3210c4cd294cf5eb45e
diff --git a/av1/common/enums.h b/av1/common/enums.h
index fbacc89..b9767eb 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -625,6 +625,25 @@
   RESTORE_TYPES = 4,
 } UENUM1BYTE(RestorationType);
 
+// Picture prediction structures (0-12 are predefined) in scalability metadata.
+enum {
+  SCALABILITY_L1T2 = 0,
+  SCALABILITY_L1T3 = 1,
+  SCALABILITY_L2T1 = 2,
+  SCALABILITY_L2T2 = 3,
+  SCALABILITY_L2T3 = 4,
+  SCALABILITY_S2T1 = 5,
+  SCALABILITY_S2T2 = 6,
+  SCALABILITY_S2T3 = 7,
+  SCALABILITY_L2T1h = 8,
+  SCALABILITY_L2T2h = 9,
+  SCALABILITY_L2T3h = 10,
+  SCALABILITY_S2T1h = 11,
+  SCALABILITY_S2T2h = 12,
+  SCALABILITY_S2T3h = 13,
+  SCALABILITY_SS = 14
+} UENUM1BYTE(SCALABILITY_STRUCTURES);
+
 #define SUPERRES_SCALE_BITS 3
 #define SUPERRES_SCALE_DENOMINATOR_MIN (SCALE_NUMERATOR + 1)
 
diff --git a/av1/decoder/obu.c b/av1/decoder/obu.c
index aaea572..f4ea4af 100644
--- a/av1/decoder/obu.c
+++ b/av1/decoder/obu.c
@@ -25,25 +25,6 @@
 #include "av1/decoder/decodeframe.h"
 #include "av1/decoder/obu.h"
 
-// Picture prediction structures (0-12 are predefined) in scalability metadata.
-enum {
-  SCALABILITY_L1T2 = 0,
-  SCALABILITY_L1T3 = 1,
-  SCALABILITY_L2T1 = 2,
-  SCALABILITY_L2T2 = 3,
-  SCALABILITY_L2T3 = 4,
-  SCALABILITY_S2T1 = 5,
-  SCALABILITY_S2T2 = 6,
-  SCALABILITY_S2T3 = 7,
-  SCALABILITY_L2T1h = 8,
-  SCALABILITY_L2T2h = 9,
-  SCALABILITY_L2T3h = 10,
-  SCALABILITY_S2T1h = 11,
-  SCALABILITY_S2T2h = 12,
-  SCALABILITY_S2T3h = 13,
-  SCALABILITY_SS = 14
-} UENUM1BYTE(SCALABILITY_STRUCTURES);
-
 aom_codec_err_t aom_get_num_layers_from_operating_point_idc(
     int operating_point_idc, unsigned int *number_spatial_layers,
     unsigned int *number_temporal_layers) {
diff --git a/av1/encoder/level.c b/av1/encoder/level.c
index 1668bdf..48bb20e 100644
--- a/av1/encoder/level.c
+++ b/av1/encoder/level.c
@@ -235,6 +235,7 @@
   DISPLAY_RATE_TOO_HIGH,
   DECODE_RATE_TOO_HIGH,
   CR_TOO_SMALL,
+  TILE_SIZE_HEADER_RATE_TOO_HIGH,
 
   TARGET_LEVEL_FAIL_IDS,
   TARGET_LEVEL_OK,
@@ -258,6 +259,7 @@
   "The display luma sample rate is too high.",
   "The decoded luma sample rate is too high.",
   "The compression ratio is too small.",
+  "The product of max tile size and header rate is too high.",
 };
 
 static double get_min_cr(const AV1LevelSpec *const level_spec, int tier,
@@ -269,6 +271,30 @@
   return AOMMAX(min_cr_basis * speed_adj, 0.8);
 }
 
+static void get_temporal_parallel_params(int scalability_mode_idc,
+                                         int *temporal_parallel_num,
+                                         int *temporal_parallel_denom) {
+  if (scalability_mode_idc < 0) {
+    *temporal_parallel_num = 1;
+    *temporal_parallel_denom = 1;
+    return;
+  }
+
+  // TODO(huisu@): handle scalability cases.
+  if (scalability_mode_idc == SCALABILITY_SS) {
+    (void)scalability_mode_idc;
+  } else {
+    (void)scalability_mode_idc;
+  }
+}
+
+#define MAX_TILE_SIZE (4096 * 2304)
+#define MIN_CROPPED_TILE_WIDTH 8
+#define MIN_CROPPED_TILE_HEIGHT 8
+#define MIN_FRAME_WIDTH 16
+#define MIN_FRAME_HEIGHT 16
+#define MAX_TILE_SIZE_HEADER_RATE_PRODUCT 588251136
+
 static TARGET_LEVEL_FAIL_ID check_level_constraints(
     const AV1LevelSpec *const target_level_spec,
     const AV1LevelSpec *const level_spec,
@@ -323,7 +349,7 @@
       break;
     }
 
-    if (level_stats->max_tile_size > 4096 * 2304) {
+    if (level_stats->max_tile_size > MAX_TILE_SIZE) {
       fail_id = TILE_TOO_LARGE;
       break;
     }
@@ -333,22 +359,22 @@
       break;
     }
 
-    if (level_stats->min_cropped_tile_width < 8) {
+    if (level_stats->min_cropped_tile_width < MIN_CROPPED_TILE_WIDTH) {
       fail_id = CROPPED_TILE_WIDTH_TOO_SMALL;
       break;
     }
 
-    if (level_stats->min_cropped_tile_height < 8) {
+    if (level_stats->min_cropped_tile_height < MIN_CROPPED_TILE_HEIGHT) {
       fail_id = CROPPED_TILE_HEIGHT_TOO_SMALL;
       break;
     }
 
-    if (level_stats->min_frame_width < 16) {
+    if (level_stats->min_frame_width < MIN_FRAME_WIDTH) {
       fail_id = LUMA_PIC_H_SIZE_TOO_SMALL;
       break;
     }
 
-    if (level_stats->min_frame_height < 16) {
+    if (level_stats->min_frame_height < MIN_FRAME_HEIGHT) {
       fail_id = LUMA_PIC_V_SIZE_TOO_SMALL;
       break;
     }
@@ -362,6 +388,20 @@
       fail_id = CR_TOO_SMALL;
       break;
     }
+
+    if (target_level_spec->level > SEQ_LEVEL_5_1) {
+      int temporal_parallel_num;
+      int temporal_parallel_denom;
+      const int scalability_mode_idc = -1;
+      get_temporal_parallel_params(scalability_mode_idc, &temporal_parallel_num,
+                                   &temporal_parallel_denom);
+      const int val = level_stats->max_tile_size * level_spec->max_header_rate *
+                      temporal_parallel_denom / temporal_parallel_num;
+      if (val > MAX_TILE_SIZE_HEADER_RATE_PRODUCT) {
+        fail_id = TILE_SIZE_HEADER_RATE_TOO_HIGH;
+        break;
+      }
+    }
   } while (0);
 
   return fail_id;