AV1 levels: change max bitrate constraint

The spec does not spicify clearly how the max bitrate constraint should be
applied. Before this patch, we checked the bitrate of any 1-second window.
With this patch, we check the average bitrate across the whole sequence
instead. The bitrate spikes can be controlled by the (per frame) minimum
compression ratio.

BUG=aomedia:2332

Change-Id: I7f6bd8abf368074b72c83da9a0fcd67a82c0ac98
diff --git a/av1/encoder/level.c b/av1/encoder/level.c
index a182268..4b88631 100644
--- a/av1/encoder/level.c
+++ b/av1/encoder/level.c
@@ -747,7 +747,7 @@
 
 static TARGET_LEVEL_FAIL_ID check_level_constraints(
     const AV1LevelInfo *const level_info, AV1_LEVEL level, int tier,
-    int is_still_picture, BITSTREAM_PROFILE profile) {
+    int is_still_picture, BITSTREAM_PROFILE profile, int check_bitrate) {
   const DECODER_MODEL *const decoder_model = &level_info->decoder_models[level];
   const DECODER_MODEL_STATUS decoder_model_status = decoder_model->status;
   if (decoder_model_status != DECODER_MODEL_OK &&
@@ -851,11 +851,16 @@
       break;
     }
 
-    const double max_bitrate =
-        get_max_bitrate(target_level_spec, tier, profile);
-    if ((double)level_stats->max_bitrate > max_bitrate) {
-      fail_id = BITRATE_TOO_HIGH;
-      break;
+    if (check_bitrate) {
+      // Check average bitrate instead of max_bitrate.
+      const double bitrate_limit =
+          get_max_bitrate(target_level_spec, tier, profile);
+      const double avg_bitrate = level_stats->total_compressed_size * 8.0 /
+                                 level_stats->total_time_encoded;
+      if (avg_bitrate > bitrate_limit) {
+        fail_id = BITRATE_TOO_HIGH;
+        break;
+      }
     }
 
     if (target_level_spec->level > SEQ_LEVEL_5_1) {
@@ -1083,8 +1088,8 @@
     level_stats->min_frame_width = AOMMIN(level_stats->min_frame_width, width);
     level_stats->min_frame_height =
         AOMMIN(level_stats->min_frame_height, height);
-    if (show_frame) level_stats->total_time_encoded = total_time_encoded;
     level_stats->min_cr = AOMMIN(level_stats->min_cr, compression_ratio);
+    level_stats->total_compressed_size += (double)size;
 
     // update level_spec
     // TODO(kyslov@) update all spec fields
@@ -1108,6 +1113,7 @@
           show_frame ? count_frames(buffer, TICKS_PER_SEC) : 0;
       scan_past_frames(buffer, encoded_frames_in_last_second, level_spec,
                        level_stats);
+      level_stats->total_time_encoded = total_time_encoded;
     }
 
     DECODER_MODEL *const decoder_models = level_info->decoder_models;
@@ -1120,7 +1126,7 @@
     if (target_level < SEQ_LEVELS) {
       const int tier = seq_params->tier[i];
       const TARGET_LEVEL_FAIL_ID fail_id = check_level_constraints(
-          level_info, target_level, tier, is_still_picture, profile);
+          level_info, target_level, tier, is_still_picture, profile, 0);
       if (fail_id != TARGET_LEVEL_OK) {
         const int target_level_major = 2 + (target_level >> 2);
         const int target_level_minor = target_level & 3;
@@ -1145,7 +1151,7 @@
     assert(level_info != NULL);
     for (int level = 0; level < SEQ_LEVELS; ++level) {
       const TARGET_LEVEL_FAIL_ID fail_id = check_level_constraints(
-          level_info, level, tier, is_still_picture, profile);
+          level_info, level, tier, is_still_picture, profile, 1);
       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 2af9b2d..e826554 100644
--- a/av1/encoder/level.h
+++ b/av1/encoder/level.h
@@ -54,7 +54,7 @@
 } FrameWindowBuffer;
 
 typedef struct {
-  int max_bitrate;  // In bps.
+  int max_bitrate;  // Max bitrate in any 1-second window, in bps.
   int max_tile_size;
   int max_superres_tile_width;
   int min_cropped_tile_width;
@@ -62,7 +62,8 @@
   int tile_width_is_valid;
   int min_frame_width;
   int min_frame_height;
-  double total_time_encoded;
+  double total_compressed_size;  // In bytes.
+  double total_time_encoded;     // In seconds.
   double min_cr;
 } AV1LevelStats;