Restore redundant frame header support.

The previous implementation of redundant frame header support
was broken. It unconditionally inserted OBU FHs before each
OBU TG.

This version inserts a redundant OBU FH before all OBU TGs
when error_resilient_mode is non-zero.

BUG=aomedia:1487

Change-Id: If5c0e471637695e89a7b4684849d935d5dc9cfab
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 26e8376..9061cb8 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -3629,11 +3629,17 @@
   return size;
 }
 
+typedef struct {
+  uint8_t *frame_header;
+  size_t total_length;
+} FrameHeaderInfo;
+
 static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
                                        unsigned int *max_tile_size,
                                        unsigned int *max_tile_col_size,
                                        struct aom_write_bit_buffer *saved_wb,
-                                       uint8_t obu_extension_header) {
+                                       uint8_t obu_extension_header,
+                                       const FrameHeaderInfo *fh_info) {
   AV1_COMMON *const cm = &cpi->common;
   aom_writer mode_bc;
   int tile_row, tile_col;
@@ -3655,6 +3661,7 @@
   uint8_t *data = dst;
   int new_tg = 1;
   const int have_tiles = tile_cols * tile_rows > 1;
+  int first_tg = 1;
 
   cm->largest_tile_id = 0;
   *max_tile_size = 0;
@@ -3806,6 +3813,7 @@
 
       if (new_tg) {
         data = dst + total_size;
+
         // A new tile group begins at this tile.  Write the obu header and
         // tile group header
         curr_tg_data_size = write_obu_header(
@@ -3813,11 +3821,13 @@
 #if CONFIG_OBU_SIZING
         obu_header_size = curr_tg_data_size;
 #endif  // CONFIG_OBU_SIZING
-        if (n_log2_tiles)
+
+        if (n_log2_tiles) {
           curr_tg_data_size += write_tile_group_header(
               data + curr_tg_data_size + PRE_OBU_SIZE_BYTES, tile_idx,
               AOMMIN(tile_idx + tg_size - 1, tile_cols * tile_rows - 1),
               n_log2_tiles);
+        }
         total_size += curr_tg_data_size + PRE_OBU_SIZE_BYTES;
         new_tg = 0;
         tile_count = 0;
@@ -3870,7 +3880,7 @@
         // size of this tile
         mem_put_le32(buf->data, tile_size);
       } else {
-// write current tile group size
+      // write current tile group size
 #if CONFIG_OBU_SIZING
         const uint32_t obu_payload_size = curr_tg_data_size - obu_header_size;
         const size_t length_field_size =
@@ -3884,6 +3894,19 @@
 #else
         mem_put_le32(data, curr_tg_data_size);
 #endif  // CONFIG_OBU_SIZING
+
+        if (!first_tg && cm->error_resilient_mode) {
+          // Make room for a duplicate Frame Header OBU.
+          memmove(data + fh_info->total_length, data, curr_tg_data_size);
+
+          // Insert a copy of the Frame Header OBU.
+          memcpy(data, fh_info->frame_header, fh_info->total_length);
+          data += fh_info->total_length;
+
+          curr_tg_data_size += fh_info->total_length;
+          total_size += fh_info->total_length;
+        }
+        first_tg = 0;
       }
 
       total_size += tile_size;
@@ -3900,6 +3923,7 @@
   AV1_COMMON *const cm = &cpi->common;
   uint32_t obu_header_size = 0;
   uint32_t obu_payload_size = 0;
+  FrameHeaderInfo fh_info;
 #if CONFIG_SCALABILITY
   const uint8_t enhancement_layers_cnt = cm->enhancement_layers_cnt;
   const uint8_t obu_extension_header =
@@ -3944,7 +3968,8 @@
 
   struct aom_write_bit_buffer saved_wb;
 
-  // write frame header obu, preceded by 4-byte size
+  // Write Frame Header OBU.
+  fh_info.frame_header = data;
   obu_header_size = write_obu_header(OBU_FRAME_HEADER, obu_extension_header,
                                      data + PRE_OBU_SIZE_BYTES);
   obu_payload_size = write_frame_header_obu(
@@ -3962,7 +3987,9 @@
   mem_put_le32(data, obu_header_size + obu_payload_size);
 #endif  // CONFIG_OBU_SIZING
 
-  data += obu_header_size + obu_payload_size + length_field_size;
+  fh_info.total_length = obu_header_size + obu_payload_size + length_field_size;
+  data += fh_info.total_length;
+
   // Since length_field_size is determined adaptively after frame header
   // encoding, saved_wb must be adjusted accordingly.
   saved_wb.bit_buffer += length_field_size;
@@ -3987,7 +4014,7 @@
     //  obu
     data_size =
         write_tiles_in_tg_obus(cpi, data, &max_tile_size, &max_tile_col_size,
-                               &saved_wb, obu_extension_header);
+                               &saved_wb, obu_extension_header, &fh_info);
   }
   data += data_size;
   *size = data - dst;