AV1 levels: add max bitrate

This is a tentative implementation where the bitrate is calculated over
a 1-second rolling window.

BUG=aomedia:2332

Change-Id: I86850620e1644b6059b39a4567b73dc11e686a71
diff --git a/av1/encoder/level.c b/av1/encoder/level.c
index 6f43d06..13e14e2 100644
--- a/av1/encoder/level.c
+++ b/av1/encoder/level.c
@@ -236,6 +236,7 @@
   DECODE_RATE_TOO_HIGH,
   CR_TOO_SMALL,
   TILE_SIZE_HEADER_RATE_TOO_HIGH,
+  BITRATE_TOO_HIGH,
 
   TARGET_LEVEL_FAIL_IDS,
   TARGET_LEVEL_OK,
@@ -260,6 +261,7 @@
   "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.",
+  "The bitrate is too high.",
 };
 
 void av1_init_level_info(AV1LevelInfo *level_info) {
@@ -304,6 +306,16 @@
   }
 }
 
+static double get_max_bitrate(const AV1LevelSpec *const level_spec, int tier,
+                              BITSTREAM_PROFILE profile) {
+  if (level_spec->level < SEQ_LEVEL_4_0) tier = 0;
+  const double bitrate_basis =
+      (tier ? level_spec->high_mbps : level_spec->main_mbps) * 1e6;
+  const double bitrate_profile_factor =
+      profile == PROFILE_0 ? 1.0 : (profile == PROFILE_1 ? 2.0 : 3.0);
+  return bitrate_basis * bitrate_profile_factor;
+}
+
 #define MAX_TILE_SIZE (4096 * 2304)
 #define MIN_CROPPED_TILE_WIDTH 8
 #define MIN_CROPPED_TILE_HEIGHT 8
@@ -314,9 +326,11 @@
 static TARGET_LEVEL_FAIL_ID check_level_constraints(
     const AV1LevelSpec *const target_level_spec,
     const AV1LevelSpec *const level_spec,
-    const AV1LevelStats *const level_stats, int tier, int is_still_picture) {
+    const AV1LevelStats *const level_stats, int tier, int is_still_picture,
+    BITSTREAM_PROFILE profile) {
   const double min_cr = get_min_cr(target_level_spec, tier, is_still_picture,
                                    level_spec->max_decode_rate);
+  const double max_bitrate = get_max_bitrate(target_level_spec, tier, profile);
   TARGET_LEVEL_FAIL_ID fail_id = TARGET_LEVEL_OK;
 
   do {
@@ -405,6 +419,11 @@
       break;
     }
 
+    if ((double)level_stats->max_bitrate > max_bitrate) {
+      fail_id = BITRATE_TOO_HIGH;
+      break;
+    }
+
     if (target_level_spec->level > SEQ_LEVEL_5_1) {
       int temporal_parallel_num;
       int temporal_parallel_denom;
@@ -484,7 +503,8 @@
   }
 }
 
-static int store_frame_record(int64_t ts_start, int64_t ts_end, int pic_size,
+static int store_frame_record(int64_t ts_start, int64_t ts_end,
+                              size_t encoded_size, int pic_size,
                               int frame_header_count, int tiles, int show_frame,
                               int show_existing_frame,
                               FrameWindowBuffer *const buffer) {
@@ -497,6 +517,7 @@
   FrameRecord *const record = &buffer->buf[new_idx];
   record->ts_start = ts_start;
   record->ts_end = ts_end;
+  record->encoded_size_in_bytes = encoded_size;
   record->pic_size = pic_size;
   record->frame_header_count = frame_header_count;
   record->tiles = tiles;
@@ -532,13 +553,15 @@
 // Scan previously encoded frames and update level metrics accordingly.
 static void scan_past_frames(const FrameWindowBuffer *const buffer,
                              int num_frames_to_scan,
-                             AV1LevelSpec *const level_spec) {
+                             AV1LevelSpec *const level_spec,
+                             AV1LevelStats *const level_stats) {
   const int num_frames_in_buffer = buffer->num;
   int index = (buffer->start + num_frames_in_buffer - 1) % FRAME_WINDOW_SIZE;
   int frame_headers = 0;
   int tiles = 0;
   int64_t display_samples = 0;
   int64_t decoded_samples = 0;
+  size_t encoded_size_in_bytes = 0;
   for (int i = 0; i < AOMMIN(num_frames_in_buffer, num_frames_to_scan); ++i) {
     const FrameRecord *const record = &buffer->buf[index];
     if (!record->show_existing_frame) {
@@ -549,6 +572,7 @@
       display_samples += record->pic_size;
     }
     tiles += record->tiles;
+    encoded_size_in_bytes += record->encoded_size_in_bytes;
     --index;
     if (index < 0) index = FRAME_WINDOW_SIZE - 1;
   }
@@ -559,6 +583,8 @@
   level_spec->max_decode_rate =
       AOMMAX(level_spec->max_decode_rate, decoded_samples);
   level_spec->max_tile_rate = AOMMAX(level_spec->max_tile_rate, tiles);
+  level_stats->max_bitrate =
+      AOMMAX(level_stats->max_bitrate, (int)encoded_size_in_bytes * 8);
 }
 
 void av1_update_level_info(AV1_COMP *cpi, size_t size, int64_t ts_start,
@@ -577,8 +603,8 @@
 
   // Store info. of current frame into FrameWindowBuffer.
   FrameWindowBuffer *const buffer = &cpi->frame_window_buffer;
-  store_frame_record(ts_start, ts_end, luma_pic_size, frame_header_count, tiles,
-                     show_frame, show_existing_frame, buffer);
+  store_frame_record(ts_start, ts_end, size, luma_pic_size, frame_header_count,
+                     tiles, show_frame, show_existing_frame, buffer);
   // Count the number of frames encoded in the past 1 second.
   const int encoded_frames_in_last_second =
       show_frame ? count_frames(buffer, TICKS_PER_SEC) : 0;
@@ -633,7 +659,6 @@
     level_stats->min_frame_width = AOMMIN(level_stats->min_frame_width, width);
     level_stats->min_frame_height =
         AOMMIN(level_stats->min_frame_height, height);
-    level_stats->total_compressed_size += frame_compressed_size;
     if (show_frame) level_stats->total_time_encoded = total_time_encoded;
     level_stats->min_cr = AOMMIN(level_stats->min_cr, compression_ratio);
 
@@ -649,7 +674,8 @@
     level_spec->max_tiles = AOMMAX(level_spec->max_tiles, tiles);
 
     if (show_frame) {
-      scan_past_frames(buffer, encoded_frames_in_last_second, level_spec);
+      scan_past_frames(buffer, encoded_frames_in_last_second, level_spec,
+                       level_stats);
     }
 
     // Check whether target level is met.
@@ -658,8 +684,9 @@
       const AV1LevelSpec *const target_level_spec =
           av1_level_defs + target_seq_level_idx;
       const int tier = seq_params->tier[i];
-      const TARGET_LEVEL_FAIL_ID fail_id = check_level_constraints(
-          target_level_spec, level_spec, level_stats, tier, is_still_picture);
+      const TARGET_LEVEL_FAIL_ID fail_id =
+          check_level_constraints(target_level_spec, level_spec, level_stats,
+                                  tier, is_still_picture, profile);
       if (fail_id != TARGET_LEVEL_OK) {
         const int target_level_major = 2 + (target_seq_level_idx >> 2);
         const int target_level_minor = target_seq_level_idx & 3;
@@ -682,6 +709,7 @@
   }
 
   const int is_still_picture = seq_params->still_picture;
+  const BITSTREAM_PROFILE profile = seq_params->profile;
   for (int op = 0; op < seq_params->operating_points_cnt_minus_1 + 1; ++op) {
     seq_level_idx[op] = (int)SEQ_LEVEL_MAX;
     const int tier = seq_params->tier[op];
@@ -690,8 +718,9 @@
     const AV1LevelSpec *const level_spec = &level_info->level_spec;
     for (int level = 0; level < SEQ_LEVELS; ++level) {
       const AV1LevelSpec *const target_level_spec = av1_level_defs + level;
-      const TARGET_LEVEL_FAIL_ID fail_id = check_level_constraints(
-          target_level_spec, level_spec, level_stats, tier, is_still_picture);
+      const TARGET_LEVEL_FAIL_ID fail_id =
+          check_level_constraints(target_level_spec, level_spec, level_stats,
+                                  tier, is_still_picture, profile);
       if (fail_id == TARGET_LEVEL_OK) {
         seq_level_idx[op] = level;
         break;
diff --git a/av1/encoder/level.h b/av1/encoder/level.h
index b2c1156..c4e20c8 100644
--- a/av1/encoder/level.h
+++ b/av1/encoder/level.h
@@ -37,6 +37,7 @@
 typedef struct {
   int64_t ts_start;
   int64_t ts_end;
+  size_t encoded_size_in_bytes;
   int pic_size;
   int frame_header_count;
   int tiles;
@@ -54,7 +55,7 @@
 
 // Used to keep track of AV1 Level Stats. Currently unimplemented.
 typedef struct {
-  uint64_t total_compressed_size;
+  int max_bitrate;  // In bps.
   int max_tile_size;
   int max_superres_tile_width;
   int min_cropped_tile_width;