Add option to encoder to force max frame w/h

Prior to this patch: when writing the sequence header at the start of
each sequence, max_frame_width and max_frame_height were set from the
dimensions of the current frame. This posed a problem for a resizing
video source, where the dimensions of the frames could have increased
within a sequence.

This patch adds an option to the encoder to force the values of
max_frame_width and max_frame_height. This feature is then used to fix
the resize tests that otherwise caused errors.

The number of frames tested (limit_) has been increased again to 350
after it was reduced in a previous patch to avoid the frames that
were causing errors.

BUG=aomedia:1431

Change-Id: Ic1d347a33ae8bf93c0ca5f631cfb1eeb09d25d30
diff --git a/aom/aom_encoder.h b/aom/aom_encoder.h
index c32e515..67e718f 100644
--- a/aom/aom_encoder.h
+++ b/aom/aom_encoder.h
@@ -282,6 +282,20 @@
    */
   unsigned int g_h;
 
+  /*!\brief Forced maximum width of the frame
+   *
+   * If this value is non-zero then it is used to force the maximum frame
+   * width written in write_sequence_header().
+   */
+  unsigned int g_forced_max_frame_width;
+
+  /*!\brief Forced maximum height of the frame
+   *
+   * If this value is non-zero then it is used to force the maximum frame
+   * height written in write_sequence_header().
+   */
+  unsigned int g_forced_max_frame_height;
+
   /*!\brief Bit-depth of the codec
    *
    * This value identifies the bit_depth of the codec,
diff --git a/aomenc.c b/aomenc.c
index 2b1cdda..7e4aff4 100644
--- a/aomenc.c
+++ b/aomenc.c
@@ -247,6 +247,12 @@
     ARG_DEF(NULL, "profile", 1, "Bitstream profile number to use");
 static const arg_def_t width = ARG_DEF("w", "width", 1, "Frame width");
 static const arg_def_t height = ARG_DEF("h", "height", 1, "Frame height");
+#if CONFIG_FRAME_SIZE
+static const arg_def_t forced_max_frame_width = ARG_DEF(
+    NULL, "forced_max_frame_width", 0, "Maximum frame width value to force");
+static const arg_def_t forced_max_frame_height = ARG_DEF(
+    NULL, "forced_max_frame_height", 0, "Maximum frame height value to force");
+#endif
 #if CONFIG_WEBM_IO
 static const struct arg_enum_list stereo_mode_enum[] = {
   { "mono", STEREO_FORMAT_MONO },
@@ -285,6 +291,10 @@
                                           &profile,
                                           &width,
                                           &height,
+#if CONFIG_FRAME_SIZE
+                                          &forced_max_frame_width,
+                                          &forced_max_frame_height,
+#endif
 #if CONFIG_WEBM_IO
                                           &stereo_mode,
 #endif
@@ -1215,6 +1225,12 @@
       config->cfg.g_w = arg_parse_uint(&arg);
     } else if (arg_match(&arg, &height, argi)) {
       config->cfg.g_h = arg_parse_uint(&arg);
+#if CONFIG_FRAME_SIZE
+    } else if (arg_match(&arg, &forced_max_frame_width, argi)) {
+      config->cfg.g_forced_max_frame_width = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &forced_max_frame_height, argi)) {
+      config->cfg.g_forced_max_frame_height = arg_parse_uint(&arg);
+#endif
     } else if (arg_match(&arg, &bitdeptharg, argi)) {
       config->cfg.g_bit_depth = arg_parse_enum_or_int(&arg);
     } else if (arg_match(&arg, &inbitdeptharg, argi)) {
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 620b3f7..de7f8c7 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -512,6 +512,10 @@
   oxcf->max_threads = (int)cfg->g_threads;
   oxcf->width = cfg->g_w;
   oxcf->height = cfg->g_h;
+#if CONFIG_FRAME_SIZE
+  oxcf->forced_max_frame_width = cfg->g_forced_max_frame_width;
+  oxcf->forced_max_frame_height = cfg->g_forced_max_frame_height;
+#endif
   oxcf->bit_depth = cfg->g_bit_depth;
   oxcf->input_bit_depth = cfg->g_input_bit_depth;
   // guess a frame rate if out of whack, use 30
@@ -1771,6 +1775,8 @@
 
         320,         // g_width
         240,         // g_height
+        0,           // g_forced_max_frame_width
+        0,           // g_forced_max_frame_height
         AOM_BITS_8,  // g_bit_depth
         8,           // g_input_bit_depth
 
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 64acf61..cad191d 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2836,8 +2836,12 @@
 #if CONFIG_FRAME_SIZE
   int num_bits_width = 16;
   int num_bits_height = 16;
-  int max_frame_width = cpi->oxcf.width;
-  int max_frame_height = cpi->oxcf.height;
+  int max_frame_width = cpi->oxcf.forced_max_frame_width
+                            ? cpi->oxcf.forced_max_frame_width
+                            : cpi->oxcf.width;
+  int max_frame_height = cpi->oxcf.forced_max_frame_height
+                             ? cpi->oxcf.forced_max_frame_height
+                             : cpi->oxcf.height;
 
   seq_params->num_bits_width = num_bits_width;
   seq_params->num_bits_height = num_bits_height;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 91a30fb..5bc7675 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -136,9 +136,13 @@
 
 typedef struct AV1EncoderConfig {
   BITSTREAM_PROFILE profile;
-  aom_bit_depth_t bit_depth;     // Codec bit-depth.
-  int width;                     // width of data passed to the compressor
-  int height;                    // height of data passed to the compressor
+  aom_bit_depth_t bit_depth;  // Codec bit-depth.
+  int width;                  // width of data passed to the compressor
+  int height;                 // height of data passed to the compressor
+#if CONFIG_FRAME_SIZE
+  int forced_max_frame_width;   // forced maximum width of frame (if != 0)
+  int forced_max_frame_height;  // forced maximum height of frame (if != 0)
+#endif
   unsigned int input_bit_depth;  // Input bit depth.
   double init_framerate;         // set to passed in framerate
   int64_t target_bandwidth;      // bandwidth to be used in bits per second
diff --git a/test/resize_test.cc b/test/resize_test.cc
index 5fc6fe0..534025d 100644
--- a/test/resize_test.cc
+++ b/test/resize_test.cc
@@ -11,6 +11,7 @@
 
 #include <climits>
 #include <vector>
+#include "aom_dsp/aom_dsp_common.h"
 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
 #include "test/codec_factory.h"
 #include "test/encode_test_driver.h"
@@ -247,7 +248,7 @@
  public:
   ResizingVideoSource() {
     SetSize(kInitialWidth, kInitialHeight);
-    limit_ = 250;
+    limit_ = 350;
   }
   int flag_codec_;
   virtual ~ResizingVideoSource() {}
@@ -289,6 +290,10 @@
   ResizingVideoSource video;
   video.flag_codec_ = 0;
   cfg_.g_lag_in_frames = 0;
+  // We use max(kInitialWidth, kInitialHeight) because during the test
+  // the width and height of the frame are swapped
+  cfg_.g_forced_max_frame_width = cfg_.g_forced_max_frame_height =
+      AOMMAX(kInitialWidth, kInitialHeight);
   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 
   // Check we decoded the same number of frames as we attempted to encode
@@ -490,6 +495,10 @@
     cfg_.g_error_resilient = 0;
     // Run at low bitrate.
     cfg_.rc_target_bitrate = 200;
+    // We use max(kInitialWidth, kInitialHeight) because during the test
+    // the width and height of the frame are swapped
+    cfg_.g_forced_max_frame_width = cfg_.g_forced_max_frame_height =
+        AOMMAX(kInitialWidth, kInitialHeight);
   }
 
   std::vector<FrameInfo> frame_info_list_;