replace Annex-B with Annex-B-prime

Annex-B-prime has been fully adopted.
Replace Annex-B with Annex-B-prime for encoding/decoding

BUG=aomedia:1700

Change-Id: Ib1478daf9d78fd9684911e343b407b91c969e691
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 6f6bd4f..3471886 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -1270,6 +1270,55 @@
       if (frame_size) {
         if (ctx->pending_cx_data == 0) ctx->pending_cx_data = cx_data;
 
+        const int write_temporal_delimiter =
+            !cpi->common.enhancement_layer_id && !ctx->pending_frame_count;
+
+        if (write_temporal_delimiter) {
+          uint32_t obu_header_size = 1;
+          const uint32_t obu_payload_size = 0;
+          const size_t length_field_size =
+              aom_uleb_size_in_bytes(obu_payload_size);
+
+          if (ctx->pending_cx_data) {
+            const size_t move_offset = length_field_size + 1;
+            memmove(ctx->pending_cx_data + move_offset, ctx->pending_cx_data,
+                    frame_size);
+          }
+          const uint32_t obu_header_offset = 0;
+          obu_header_size = write_obu_header(
+              OBU_TEMPORAL_DELIMITER, 0,
+              (uint8_t *)(ctx->pending_cx_data + obu_header_offset));
+
+          // OBUs are preceded/succeeded by an unsigned leb128 coded integer.
+          if (write_uleb_obu_size(obu_header_size, obu_payload_size,
+                                  ctx->pending_cx_data) != AOM_CODEC_OK) {
+            return AOM_CODEC_ERROR;
+          }
+
+          frame_size += obu_header_size + obu_payload_size + length_field_size;
+        }
+
+        if (ctx->oxcf.save_as_annexb) {
+          size_t curr_frame_size = frame_size;
+          if (av1_convert_sect5obus_to_annexb(cx_data, &curr_frame_size) !=
+              AOM_CODEC_OK) {
+            return AOM_CODEC_ERROR;
+          }
+          frame_size = curr_frame_size;
+
+          // B_PRIME (add frame size)
+          const size_t length_field_size = aom_uleb_size_in_bytes(frame_size);
+          if (ctx->pending_cx_data) {
+            const size_t move_offset = length_field_size;
+            memmove(cx_data + move_offset, cx_data, frame_size);
+          }
+          if (write_uleb_obu_size(0, (uint32_t)frame_size, cx_data) !=
+              AOM_CODEC_OK) {
+            return AOM_CODEC_ERROR;
+          }
+          frame_size += length_field_size;
+        }
+
         ctx->pending_frame_sizes[ctx->pending_frame_count++] = frame_size;
         ctx->pending_cx_data_sz += frame_size;
 
@@ -1285,51 +1334,28 @@
       // Add the frame packet to the list of returned packets.
       aom_codec_cx_pkt_t pkt;
 
+      if (ctx->oxcf.save_as_annexb) {
+        //  B_PRIME (add TU size)
+        size_t tu_size = ctx->pending_cx_data_sz;
+        const size_t length_field_size = aom_uleb_size_in_bytes(tu_size);
+        if (ctx->pending_cx_data) {
+          const size_t move_offset = length_field_size;
+          memmove(ctx->pending_cx_data + move_offset, ctx->pending_cx_data,
+                  tu_size);
+        }
+        if (write_uleb_obu_size(0, (uint32_t)tu_size, ctx->pending_cx_data) !=
+            AOM_CODEC_OK) {
+          return AOM_CODEC_ERROR;
+        }
+        ctx->pending_cx_data_sz += length_field_size;
+      }
+
       pkt.kind = AOM_CODEC_CX_FRAME_PKT;
 
       pkt.data.frame.buf = ctx->pending_cx_data;
       pkt.data.frame.sz = ctx->pending_cx_data_sz;
       pkt.data.frame.partition_id = -1;
 
-      int write_temporal_delimiter = 1;
-      // only write OBU_TD if base layer
-      write_temporal_delimiter = !cpi->common.enhancement_layer_id;
-      if (write_temporal_delimiter) {
-        // move data and insert OBU_TD preceded by optional 4 byte size
-        uint32_t obu_header_size = 1;
-        const uint32_t obu_payload_size = 0;
-        const size_t length_field_size =
-            aom_uleb_size_in_bytes(obu_payload_size);
-
-        if (ctx->pending_cx_data) {
-          const size_t move_offset = length_field_size + 1;
-          memmove(ctx->pending_cx_data + move_offset, ctx->pending_cx_data,
-                  ctx->pending_cx_data_sz);
-        }
-        const uint32_t obu_header_offset = 0;
-        obu_header_size = write_obu_header(
-            OBU_TEMPORAL_DELIMITER, 0,
-            (uint8_t *)(ctx->pending_cx_data + obu_header_offset));
-
-        // OBUs are preceded/succeeded by an unsigned leb128 coded integer.
-        if (write_uleb_obu_size(obu_header_size, obu_payload_size,
-                                ctx->pending_cx_data) != AOM_CODEC_OK) {
-          return AOM_CODEC_ERROR;
-        }
-
-        pkt.data.frame.sz +=
-            obu_header_size + obu_payload_size + length_field_size;
-      }
-
-      if (ctx->oxcf.save_as_annexb) {
-        size_t curr_frame_size = pkt.data.frame.sz;
-        if (av1_convert_sect5obus_to_annexb(ctx->pending_cx_data,
-                                            &curr_frame_size) != AOM_CODEC_OK) {
-          return AOM_CODEC_ERROR;
-        }
-        pkt.data.frame.sz = curr_frame_size;
-      }
-
       pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp);
       pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
       pkt.data.frame.duration = (uint32_t)ticks_to_timebase_units(
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index f3ae661..64e3844 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -477,6 +477,17 @@
     if (res != AOM_CODEC_OK) return res;
   }
 
+  if (ctx->is_annexb) {
+    // read the size of this temporal unit
+    size_t length_of_size;
+    uint64_t size_of_unit;
+    if (aom_uleb_decode(data_start, data_sz, &size_of_unit, &length_of_size) !=
+        0) {
+      return AOM_CODEC_CORRUPT_FRAME;
+    }
+    data_start += length_of_size;
+  }
+
   // Decode in serial mode.
   if (frame_count > 0) {
     int i;
@@ -496,6 +507,17 @@
     }
   } else {
     while (data_start < data_end) {
+      if (ctx->is_annexb) {
+        // read the size of this frame unit
+        size_t length_of_size;
+        uint64_t size_of_frame_unit;
+        if (aom_uleb_decode(data_start, (uint32_t)(data_end - data_start),
+                            &size_of_frame_unit, &length_of_size) != 0) {
+          return AOM_CODEC_CORRUPT_FRAME;
+        }
+        data_start += length_of_size;
+      }
+
       const uint32_t frame_size = (uint32_t)(data_end - data_start);
       res = decode_one(ctx, &data_start, frame_size, user_priv);
       if (res != AOM_CODEC_OK) return res;
diff --git a/obudec.c b/obudec.c
index 0974178..988457b 100644
--- a/obudec.c
+++ b/obudec.c
@@ -25,7 +25,7 @@
 #define OBU_EXTENSION_SIZE 1
 #define OBU_MAX_LENGTH_FIELD_SIZE 8
 #define OBU_DETECTION_SIZE \
-  (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + OBU_MAX_LENGTH_FIELD_SIZE)
+  (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + 2 * OBU_MAX_LENGTH_FIELD_SIZE)
 
 // Reads unsigned LEB128 integer and returns 0 upon successful read and decode.
 // Stores raw bytes in 'value_buffer', length of the number in 'value_length',
@@ -209,9 +209,30 @@
   uint64_t obu_length = 0;
   ObuHeader obu_header;
   memset(&obu_header, 0, sizeof(obu_header));
+  size_t length_of_unit_size = 0;
+  uint64_t unit_size;
+  size_t annexb_header_length = 0;
 
-  if (obudec_read_one_obu(f, OBU_DETECTION_SIZE, is_annexb, &detect_buf[0],
-                          &obu_length, &obu_header) != 0) {
+  if (is_annexb) {
+    // read the size of first temporal unit
+    if (obudec_read_leb128(f, &detect_buf[0], &length_of_unit_size,
+                           &unit_size) != 0) {
+      fprintf(stderr, "obudec: Failure reading temporal unit header\n");
+      return 0;
+    }
+
+    // read the size of first frame unit
+    if (obudec_read_leb128(f, &detect_buf[length_of_unit_size],
+                           &annexb_header_length, &unit_size) != 0) {
+      fprintf(stderr, "obudec: Failure reading frame unit header\n");
+      return 0;
+    }
+    annexb_header_length += length_of_unit_size;
+  }
+
+  if (obudec_read_one_obu(f, OBU_DETECTION_SIZE, is_annexb,
+                          &detect_buf[annexb_header_length], &obu_length,
+                          &obu_header) != 0) {
     fprintf(stderr, "obudec: Failure reading first OBU.\n");
     rewind(f);
     return 0;
@@ -250,6 +271,10 @@
     return 0;
   }
   obu_ctx->buffer_capacity = OBU_BUFFER_SIZE;
+
+  if (is_annexb) {
+    obu_length += annexb_header_length;
+  }
   memcpy(obu_ctx->buffer, &detect_buf[0], (size_t)obu_length);
   obu_ctx->bytes_buffered = (size_t)obu_length;
 
@@ -269,51 +294,102 @@
     return 1;
   }
 
-  const int is_annexb = obu_ctx->is_annexb;
-  while (1) {
-    ObuHeader obu_header;
-    memset(&obu_header, 0, sizeof(obu_header));
+  size_t tu_size;
+  uint64_t obu_size = 0;
+  uint8_t *data = obu_ctx->buffer;
+  size_t length_of_temporal_unit_size = 0;
+  uint8_t tuheader[OBU_MAX_LENGTH_FIELD_SIZE] = { 0 };
 
-    uint64_t obu_size = 0;
-    uint8_t *data = obu_ctx->buffer + obu_ctx->bytes_buffered;
-    const size_t capacity = obu_ctx->buffer_capacity - obu_ctx->bytes_buffered;
+  if (obu_ctx->is_annexb) {
+    uint64_t size = 0;
 
-    if (obudec_read_one_obu(f, capacity, is_annexb, data, &obu_size,
-                            &obu_header) != 0) {
-      fprintf(stderr, "obudec: read_one_obu failed in TU loop\n");
-      return -1;
+    if (obu_ctx->bytes_buffered == 0) {
+      if (obudec_read_leb128(f, &tuheader[0], &length_of_temporal_unit_size,
+                             &size) != 0) {
+        fprintf(stderr, "obudec: Failure reading temporal unit header\n");
+        return -1;
+      }
+      if (size == 0 && feof(f)) {
+        return 1;
+      }
+    } else {
+      // temporal unit size was already stored in buffer
+      if (aom_uleb_decode(obu_ctx->buffer, obu_ctx->bytes_buffered, &size,
+                          &length_of_temporal_unit_size) != 0) {
+        fprintf(stderr, "obudec: Failure reading temporal unit header\n");
+        return -1;
+      }
     }
 
-    if (obu_header.type == OBU_TEMPORAL_DELIMITER || obu_size == 0 ||
-        (obu_header.has_extension &&
-         obu_header.enhancement_layer_id > obu_ctx->last_layer_id)) {
-      const size_t tu_size = obu_ctx->bytes_buffered;
+    size += length_of_temporal_unit_size;
+    tu_size = (size_t)size;
+  } else {
+    while (1) {
+      ObuHeader obu_header;
+      memset(&obu_header, 0, sizeof(obu_header));
 
-#if defined AOM_MAX_ALLOCABLE_MEMORY
-      if (tu_size > AOM_MAX_ALLOCABLE_MEMORY) {
-        fprintf(stderr, "obudec: Temporal Unit size exceeds max alloc size.\n");
+      data = obu_ctx->buffer + obu_ctx->bytes_buffered;
+      const size_t capacity =
+          obu_ctx->buffer_capacity - obu_ctx->bytes_buffered;
+
+      if (obudec_read_one_obu(f, capacity, 0, data, &obu_size, &obu_header) !=
+          0) {
+        fprintf(stderr, "obudec: read_one_obu failed in TU loop\n");
         return -1;
       }
-#endif
-      uint8_t *new_buffer = (uint8_t *)realloc(*buffer, tu_size);
-      if (!new_buffer) {
-        free(*buffer);
-        fprintf(stderr, "obudec: Out of memory.\n");
-        return -1;
-      }
-      *buffer = new_buffer;
-      *bytes_read = tu_size;
-      *buffer_size = tu_size;
-      memcpy(*buffer, obu_ctx->buffer, tu_size);
 
-      memmove(obu_ctx->buffer, data, (size_t)obu_size);
-      obu_ctx->bytes_buffered = (size_t)obu_size;
-      break;
-    } else {
-      obu_ctx->bytes_buffered += (size_t)obu_size;
+      if (obu_header.type == OBU_TEMPORAL_DELIMITER || obu_size == 0 ||
+          (obu_header.has_extension &&
+           obu_header.enhancement_layer_id > obu_ctx->last_layer_id)) {
+        tu_size = obu_ctx->bytes_buffered;
+        break;
+      } else {
+        obu_ctx->bytes_buffered += (size_t)obu_size;
+      }
     }
   }
 
+#if defined AOM_MAX_ALLOCABLE_MEMORY
+  if (tu_size > AOM_MAX_ALLOCABLE_MEMORY) {
+    fprintf(stderr, "obudec: Temporal Unit size exceeds max alloc size.\n");
+    return -1;
+  }
+#endif
+  uint8_t *new_buffer = (uint8_t *)realloc(*buffer, tu_size);
+  if (!new_buffer) {
+    free(*buffer);
+    fprintf(stderr, "obudec: Out of memory.\n");
+    return -1;
+  }
+  *buffer = new_buffer;
+  *bytes_read = tu_size;
+  *buffer_size = tu_size;
+
+  if (!obu_ctx->is_annexb) {
+    memcpy(*buffer, obu_ctx->buffer, tu_size);
+    memmove(obu_ctx->buffer, data, (size_t)obu_size);
+    obu_ctx->bytes_buffered = (size_t)obu_size;
+  } else {
+    if (!feof(f)) {
+      size_t data_size;
+      size_t offset;
+      if (!obu_ctx->bytes_buffered) {
+        data_size = (uint32_t)(tu_size - length_of_temporal_unit_size);
+        memcpy(*buffer, &tuheader[0], length_of_temporal_unit_size);
+        offset = length_of_temporal_unit_size;
+      } else {
+        memcpy(*buffer, obu_ctx->buffer, obu_ctx->bytes_buffered);
+        offset = obu_ctx->bytes_buffered;
+        data_size = tu_size - obu_ctx->bytes_buffered;
+        obu_ctx->bytes_buffered = 0;
+      }
+
+      if (fread(new_buffer + offset, 1, data_size, f) != data_size) {
+        fprintf(stderr, "obudec: Failed to read full temporal unit\n");
+        return -1;
+      }
+    }
+  }
   return 0;
 }