Add obu_util and reorganize OBU support code.

Decoding and encoding apps need OBU parsing support for
several reasons. Chiefly among them is the need to parse
Sequence Headers in decoding and encoding apps for support
of reading and writing the AV1 configuration structure. In
order to facilitate this do the following:

- Move the bitreader and bitwriter buffer implementations
  to common targets built for decode and encode only
  configurations.
- Move the OBU reading utilities from obu.c and obu.h in
  av1/decoder to obu_util.c and obu_util.h in av1/common.
- Expose the currently required bitreader and bitwriter functions to
  apps in shared builds in all configurations.
- Ditto for aom_read_obu_header_and_size(), which now resides
  in obu_util.

BUG=aomedia:2027

Change-Id: I1109c634006e69925f1244fa09ce4d6db18a65cd
diff --git a/aom/exports_com b/aom/exports_com
index 4d06b76..0ee7502 100644
--- a/aom/exports_com
+++ b/aom/exports_com
@@ -10,15 +10,21 @@
 text aom_codec_version_extra_str
 text aom_codec_version_str
 text aom_img_alloc
+text aom_img_alloc_with_border
 text aom_img_flip
 text aom_img_free
-text aom_img_plane_width
 text aom_img_plane_height
+text aom_img_plane_width
 text aom_img_set_rect
 text aom_img_wrap
-text aom_img_alloc_with_border
 text aom_malloc
+text aom_rb_read_bit
+text aom_rb_read_literal
+text aom_rb_read_uvlc
 text aom_uleb_decode
 text aom_uleb_encode
 text aom_uleb_encode_fixed_size
 text aom_uleb_size_in_bytes
+text aom_wb_write_bit
+text aom_wb_write_literal
+text aom_wb_write_unsigned_literal
diff --git a/aom/exports_enc b/aom/exports_enc
index 1fa872d..918d742 100644
--- a/aom/exports_enc
+++ b/aom/exports_enc
@@ -16,5 +16,3 @@
 text aom_noise_model_get_grain_parameters
 text aom_noise_model_save_latest
 text aom_noise_model_update
-text aom_wb_write_literal
-text aom_wb_write_unsigned_literal
diff --git a/aom_dsp/aom_dsp.cmake b/aom_dsp/aom_dsp.cmake
index 7f07dbd..767d1bb 100644
--- a/aom_dsp/aom_dsp.cmake
+++ b/aom_dsp/aom_dsp.cmake
@@ -19,6 +19,10 @@
             "${AOM_ROOT}/aom_dsp/aom_filter.h"
             "${AOM_ROOT}/aom_dsp/aom_simd.h"
             "${AOM_ROOT}/aom_dsp/aom_simd_inline.h"
+            "${AOM_ROOT}/aom_dsp/bitreader_buffer.c"
+            "${AOM_ROOT}/aom_dsp/bitreader_buffer.h"
+            "${AOM_ROOT}/aom_dsp/bitwriter_buffer.c"
+            "${AOM_ROOT}/aom_dsp/bitwriter_buffer.h"
             "${AOM_ROOT}/aom_dsp/blend.h"
             "${AOM_ROOT}/aom_dsp/blend_a64_hmask.c"
             "${AOM_ROOT}/aom_dsp/blend_a64_mask.c"
@@ -126,12 +130,9 @@
               "${AOM_ROOT}/aom_dsp/binary_codes_reader.c"
               "${AOM_ROOT}/aom_dsp/binary_codes_reader.h"
               "${AOM_ROOT}/aom_dsp/bitreader.h"
-              "${AOM_ROOT}/aom_dsp/bitreader_buffer.c"
-              "${AOM_ROOT}/aom_dsp/bitreader_buffer.h"
               "${AOM_ROOT}/aom_dsp/daalaboolreader.c"
               "${AOM_ROOT}/aom_dsp/daalaboolreader.h"
-              "${AOM_ROOT}/aom_dsp/entdec.c"
-              "${AOM_ROOT}/aom_dsp/entdec.h"
+              "${AOM_ROOT}/aom_dsp/entdec.c" "${AOM_ROOT}/aom_dsp/entdec.h"
               "${AOM_ROOT}/aom_dsp/grain_synthesis.c"
               "${AOM_ROOT}/aom_dsp/grain_synthesis.h")
 endif()
@@ -141,8 +142,6 @@
               "${AOM_ROOT}/aom_dsp/binary_codes_writer.c"
               "${AOM_ROOT}/aom_dsp/binary_codes_writer.h"
               "${AOM_ROOT}/aom_dsp/bitwriter.h"
-              "${AOM_ROOT}/aom_dsp/bitwriter_buffer.c"
-              "${AOM_ROOT}/aom_dsp/bitwriter_buffer.h"
               "${AOM_ROOT}/aom_dsp/daalaboolwriter.c"
               "${AOM_ROOT}/aom_dsp/daalaboolwriter.h"
               "${AOM_ROOT}/aom_dsp/entenc.c"
diff --git a/av1/av1.cmake b/av1/av1.cmake
index 7220a40..3a7cd7e 100644
--- a/av1/av1.cmake
+++ b/av1/av1.cmake
@@ -53,6 +53,8 @@
             "${AOM_ROOT}/av1/common/mv.h"
             "${AOM_ROOT}/av1/common/mvref_common.c"
             "${AOM_ROOT}/av1/common/mvref_common.h"
+            "${AOM_ROOT}/av1/common/obu_util.c"
+            "${AOM_ROOT}/av1/common/obu_util.h"
             "${AOM_ROOT}/av1/common/odintrin.c"
             "${AOM_ROOT}/av1/common/odintrin.h"
             "${AOM_ROOT}/av1/common/onyxc_int.h"
@@ -78,8 +80,8 @@
             "${AOM_ROOT}/av1/common/thread_common.h"
             "${AOM_ROOT}/av1/common/tile_common.c"
             "${AOM_ROOT}/av1/common/tile_common.h"
-            "${AOM_ROOT}/av1/common/timing.h"
             "${AOM_ROOT}/av1/common/timing.c"
+            "${AOM_ROOT}/av1/common/timing.h"
             "${AOM_ROOT}/av1/common/token_cdfs.h"
             "${AOM_ROOT}/av1/common/txb_common.c"
             "${AOM_ROOT}/av1/common/txb_common.h"
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index 5b26a48..a9153c4 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -26,6 +26,7 @@
 #include "av1/common/alloccommon.h"
 #include "av1/common/frame_buffers.h"
 #include "av1/common/enums.h"
+#include "av1/common/obu_util.h"
 
 #include "av1/decoder/decoder.h"
 #include "av1/decoder/decodeframe.h"
diff --git a/av1/common/obu_util.c b/av1/common/obu_util.c
new file mode 100644
index 0000000..823b700
--- /dev/null
+++ b/av1/common/obu_util.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2018, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+#include "av1/common/obu_util.h"
+
+#include "aom_dsp/bitreader_buffer.h"
+
+// Returns 1 when OBU type is valid, and 0 otherwise.
+static int valid_obu_type(int obu_type) {
+  int valid_type = 0;
+  switch (obu_type) {
+    case OBU_SEQUENCE_HEADER:
+    case OBU_TEMPORAL_DELIMITER:
+    case OBU_FRAME_HEADER:
+    case OBU_TILE_GROUP:
+    case OBU_METADATA:
+    case OBU_FRAME:
+    case OBU_REDUNDANT_FRAME_HEADER:
+    case OBU_TILE_LIST:
+    case OBU_PADDING: valid_type = 1; break;
+    default: break;
+  }
+  return valid_type;
+}
+
+static aom_codec_err_t read_obu_size(const uint8_t *data,
+                                     size_t bytes_available,
+                                     size_t *const obu_size,
+                                     size_t *const length_field_size) {
+  uint64_t u_obu_size = 0;
+  if (aom_uleb_decode(data, bytes_available, &u_obu_size, length_field_size) !=
+      0) {
+    return AOM_CODEC_CORRUPT_FRAME;
+  }
+
+  if (u_obu_size > UINT32_MAX) return AOM_CODEC_CORRUPT_FRAME;
+  *obu_size = (size_t)u_obu_size;
+  return AOM_CODEC_OK;
+}
+
+// Parses OBU header and stores values in 'header'.
+static aom_codec_err_t read_obu_header(struct aom_read_bit_buffer *rb,
+                                       int is_annexb, ObuHeader *header) {
+  if (!rb || !header) return AOM_CODEC_INVALID_PARAM;
+
+  const ptrdiff_t bit_buffer_byte_length = rb->bit_buffer_end - rb->bit_buffer;
+  if (bit_buffer_byte_length < 1) return AOM_CODEC_CORRUPT_FRAME;
+
+  header->size = 1;
+
+  if (aom_rb_read_bit(rb) != 0) {
+    // Forbidden bit. Must not be set.
+    return AOM_CODEC_CORRUPT_FRAME;
+  }
+
+  header->type = (OBU_TYPE)aom_rb_read_literal(rb, 4);
+
+  if (!valid_obu_type(header->type)) return AOM_CODEC_CORRUPT_FRAME;
+
+  header->has_extension = aom_rb_read_bit(rb);
+  header->has_size_field = aom_rb_read_bit(rb);
+
+  if (!header->has_size_field && !is_annexb) {
+    // section 5 obu streams must have obu_size field set.
+    return AOM_CODEC_UNSUP_BITSTREAM;
+  }
+
+  if (aom_rb_read_bit(rb) != 0) {
+    // obu_reserved_1bit must be set to 0.
+    return AOM_CODEC_CORRUPT_FRAME;
+  }
+
+  if (header->has_extension) {
+    if (bit_buffer_byte_length == 1) return AOM_CODEC_CORRUPT_FRAME;
+
+    header->size += 1;
+    header->temporal_layer_id = aom_rb_read_literal(rb, 3);
+    header->spatial_layer_id = aom_rb_read_literal(rb, 2);
+    if (aom_rb_read_literal(rb, 3) != 0) {
+      // extension_header_reserved_3bits must be set to 0.
+      return AOM_CODEC_CORRUPT_FRAME;
+    }
+  }
+
+  return AOM_CODEC_OK;
+}
+
+aom_codec_err_t aom_read_obu_header(uint8_t *buffer, size_t buffer_length,
+                                    size_t *consumed, ObuHeader *header,
+                                    int is_annexb) {
+  if (buffer_length < 1 || !consumed || !header) return AOM_CODEC_INVALID_PARAM;
+
+  // TODO(tomfinegan): Set the error handler here and throughout this file, and
+  // confirm parsing work done via aom_read_bit_buffer is successful.
+  struct aom_read_bit_buffer rb = { buffer, buffer + buffer_length, 0, NULL,
+                                    NULL };
+  aom_codec_err_t parse_result = read_obu_header(&rb, is_annexb, header);
+  if (parse_result == AOM_CODEC_OK) *consumed = header->size;
+  return parse_result;
+}
+
+aom_codec_err_t aom_read_obu_header_and_size(const uint8_t *data,
+                                             size_t bytes_available,
+                                             int is_annexb,
+                                             ObuHeader *obu_header,
+                                             size_t *const payload_size,
+                                             size_t *const bytes_read) {
+  size_t length_field_size = 0, obu_size = 0;
+  aom_codec_err_t status;
+
+  if (is_annexb) {
+    // Size field comes before the OBU header, and includes the OBU header
+    status =
+        read_obu_size(data, bytes_available, &obu_size, &length_field_size);
+
+    if (status != AOM_CODEC_OK) return status;
+  }
+
+  struct aom_read_bit_buffer rb = { data + length_field_size,
+                                    data + bytes_available, 0, NULL, NULL };
+
+  status = read_obu_header(&rb, is_annexb, obu_header);
+  if (status != AOM_CODEC_OK) return status;
+
+  if (is_annexb) {
+    // Derive the payload size from the data we've already read
+    if (obu_size < obu_header->size) return AOM_CODEC_CORRUPT_FRAME;
+
+    *payload_size = obu_size - obu_header->size;
+  } else {
+    // Size field comes after the OBU header, and is just the payload size
+    status = read_obu_size(data + obu_header->size,
+                           bytes_available - obu_header->size, payload_size,
+                           &length_field_size);
+    if (status != AOM_CODEC_OK) return status;
+  }
+
+  *bytes_read = length_field_size + obu_header->size;
+  return AOM_CODEC_OK;
+}
diff --git a/av1/common/obu_util.h b/av1/common/obu_util.h
new file mode 100644
index 0000000..3b92d1a
--- /dev/null
+++ b/av1/common/obu_util.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+#ifndef AV1_COMMON_OBU_UTIL_H
+#define AV1_COMMON_OBU_UTIL_H
+
+#include "aom/aom_codec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+  size_t size;  // Size (1 or 2 bytes) of the OBU header (including the
+                // optional OBU extension header) in the bitstream.
+  OBU_TYPE type;
+  int has_size_field;
+  int has_extension;
+  // The following fields come from the OBU extension header and therefore are
+  // only used if has_extension is true.
+  int temporal_layer_id;
+  int spatial_layer_id;
+} ObuHeader;
+
+aom_codec_err_t aom_read_obu_header(uint8_t *buffer, size_t buffer_length,
+                                    size_t *consumed, ObuHeader *header,
+                                    int is_annexb);
+
+aom_codec_err_t aom_read_obu_header_and_size(const uint8_t *data,
+                                             size_t bytes_available,
+                                             int is_annexb,
+                                             ObuHeader *obu_header,
+                                             size_t *const payload_size,
+                                             size_t *const bytes_read);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // AV1_COMMON_OBU_UTIL_H
diff --git a/av1/decoder/obu.c b/av1/decoder/obu.c
index d93b0f7..cf03ff1 100644
--- a/av1/decoder/obu.c
+++ b/av1/decoder/obu.c
@@ -18,6 +18,7 @@
 #include "aom_ports/mem_ops.h"
 
 #include "av1/common/common.h"
+#include "av1/common/obu_util.h"
 #include "av1/common/timing.h"
 #include "av1/decoder/decoder.h"
 #include "av1/decoder/decodeframe.h"
@@ -42,85 +43,6 @@
   SCALABILITY_SS = 14
 } SCALABILITY_STRUCTURES;
 
-// Returns 1 when OBU type is valid, and 0 otherwise.
-static int valid_obu_type(int obu_type) {
-  int valid_type = 0;
-  switch (obu_type) {
-    case OBU_SEQUENCE_HEADER:
-    case OBU_TEMPORAL_DELIMITER:
-    case OBU_FRAME_HEADER:
-    case OBU_TILE_GROUP:
-    case OBU_METADATA:
-    case OBU_FRAME:
-    case OBU_REDUNDANT_FRAME_HEADER:
-    case OBU_TILE_LIST:
-    case OBU_PADDING: valid_type = 1; break;
-    default: break;
-  }
-  return valid_type;
-}
-
-// Parses OBU header and stores values in 'header'.
-static aom_codec_err_t read_obu_header(struct aom_read_bit_buffer *rb,
-                                       int is_annexb, ObuHeader *header) {
-  if (!rb || !header) return AOM_CODEC_INVALID_PARAM;
-
-  const ptrdiff_t bit_buffer_byte_length = rb->bit_buffer_end - rb->bit_buffer;
-  if (bit_buffer_byte_length < 1) return AOM_CODEC_CORRUPT_FRAME;
-
-  header->size = 1;
-
-  if (aom_rb_read_bit(rb) != 0) {
-    // Forbidden bit. Must not be set.
-    return AOM_CODEC_CORRUPT_FRAME;
-  }
-
-  header->type = (OBU_TYPE)aom_rb_read_literal(rb, 4);
-
-  if (!valid_obu_type(header->type)) return AOM_CODEC_CORRUPT_FRAME;
-
-  header->has_extension = aom_rb_read_bit(rb);
-  header->has_size_field = aom_rb_read_bit(rb);
-
-  if (!header->has_size_field && !is_annexb) {
-    // section 5 obu streams must have obu_size field set.
-    return AOM_CODEC_UNSUP_BITSTREAM;
-  }
-
-  if (aom_rb_read_bit(rb) != 0) {
-    // obu_reserved_1bit must be set to 0.
-    return AOM_CODEC_CORRUPT_FRAME;
-  }
-
-  if (header->has_extension) {
-    if (bit_buffer_byte_length == 1) return AOM_CODEC_CORRUPT_FRAME;
-
-    header->size += 1;
-    header->temporal_layer_id = aom_rb_read_literal(rb, 3);
-    header->spatial_layer_id = aom_rb_read_literal(rb, 2);
-    if (aom_rb_read_literal(rb, 3) != 0) {
-      // extension_header_reserved_3bits must be set to 0.
-      return AOM_CODEC_CORRUPT_FRAME;
-    }
-  }
-
-  return AOM_CODEC_OK;
-}
-
-aom_codec_err_t aom_read_obu_header(uint8_t *buffer, size_t buffer_length,
-                                    size_t *consumed, ObuHeader *header,
-                                    int is_annexb) {
-  if (buffer_length < 1 || !consumed || !header) return AOM_CODEC_INVALID_PARAM;
-
-  // TODO(tomfinegan): Set the error handler here and throughout this file, and
-  // confirm parsing work done via aom_read_bit_buffer is successful.
-  struct aom_read_bit_buffer rb = { buffer, buffer + buffer_length, 0, NULL,
-                                    NULL };
-  aom_codec_err_t parse_result = read_obu_header(&rb, is_annexb, header);
-  if (parse_result == AOM_CODEC_OK) *consumed = header->size;
-  return parse_result;
-}
-
 aom_codec_err_t aom_get_num_layers_from_operating_point_idc(
     int operating_point_idc, unsigned int *number_spatial_layers,
     unsigned int *number_temporal_layers) {
@@ -714,61 +636,6 @@
   return sz;
 }
 
-static aom_codec_err_t read_obu_size(const uint8_t *data,
-                                     size_t bytes_available,
-                                     size_t *const obu_size,
-                                     size_t *const length_field_size) {
-  uint64_t u_obu_size = 0;
-  if (aom_uleb_decode(data, bytes_available, &u_obu_size, length_field_size) !=
-      0) {
-    return AOM_CODEC_CORRUPT_FRAME;
-  }
-
-  if (u_obu_size > UINT32_MAX) return AOM_CODEC_CORRUPT_FRAME;
-  *obu_size = (size_t)u_obu_size;
-  return AOM_CODEC_OK;
-}
-
-aom_codec_err_t aom_read_obu_header_and_size(const uint8_t *data,
-                                             size_t bytes_available,
-                                             int is_annexb,
-                                             ObuHeader *obu_header,
-                                             size_t *const payload_size,
-                                             size_t *const bytes_read) {
-  size_t length_field_size = 0, obu_size = 0;
-  aom_codec_err_t status;
-
-  if (is_annexb) {
-    // Size field comes before the OBU header, and includes the OBU header
-    status =
-        read_obu_size(data, bytes_available, &obu_size, &length_field_size);
-
-    if (status != AOM_CODEC_OK) return status;
-  }
-
-  struct aom_read_bit_buffer rb = { data + length_field_size,
-                                    data + bytes_available, 0, NULL, NULL };
-
-  status = read_obu_header(&rb, is_annexb, obu_header);
-  if (status != AOM_CODEC_OK) return status;
-
-  if (is_annexb) {
-    // Derive the payload size from the data we've already read
-    if (obu_size < obu_header->size) return AOM_CODEC_CORRUPT_FRAME;
-
-    *payload_size = obu_size - obu_header->size;
-  } else {
-    // Size field comes after the OBU header, and is just the payload size
-    status = read_obu_size(data + obu_header->size,
-                           bytes_available - obu_header->size, payload_size,
-                           &length_field_size);
-    if (status != AOM_CODEC_OK) return status;
-  }
-
-  *bytes_read = length_field_size + obu_header->size;
-  return AOM_CODEC_OK;
-}
-
 // On success, returns a boolean that indicates whether the decoding of the
 // current frame is finished. On failure, sets cm->error.error_code and
 // returns -1.
diff --git a/av1/decoder/obu.h b/av1/decoder/obu.h
index 5f21970..3f8226b 100644
--- a/av1/decoder/obu.h
+++ b/av1/decoder/obu.h
@@ -15,29 +15,6 @@
 #include "aom/aom_codec.h"
 #include "av1/decoder/decoder.h"
 
-typedef struct {
-  size_t size;  // Size (1 or 2 bytes) of the OBU header (including the
-                // optional OBU extension header) in the bitstream.
-  OBU_TYPE type;
-  int has_size_field;
-  int has_extension;
-  // The following fields come from the OBU extension header and therefore are
-  // only used if has_extension is true.
-  int temporal_layer_id;
-  int spatial_layer_id;
-} ObuHeader;
-
-aom_codec_err_t aom_read_obu_header(uint8_t *buffer, size_t buffer_length,
-                                    size_t *consumed, ObuHeader *header,
-                                    int is_annexb);
-
-aom_codec_err_t aom_read_obu_header_and_size(const uint8_t *data,
-                                             size_t bytes_available,
-                                             int is_annexb,
-                                             ObuHeader *obu_header,
-                                             size_t *const payload_size,
-                                             size_t *const bytes_read);
-
 // Try to decode one frame from a buffer.
 // Returns 1 if we decoded a frame,
 //         0 if we didn't decode a frame but that's okay
diff --git a/av1/exports_com b/av1/exports_com
index 4816472..5c8e0e0 100644
--- a/av1/exports_com
+++ b/av1/exports_com
@@ -1 +1,2 @@
+text aom_read_obu_header_and_size
 text av1_resize_frame420
diff --git a/common/obudec.c b/common/obudec.c
index cd88f16..acbd12e 100644
--- a/common/obudec.c
+++ b/common/obudec.c
@@ -17,7 +17,7 @@
 
 #include "aom_ports/mem_ops.h"
 #include "av1/common/common.h"
-#include "av1/decoder/obu.h"
+#include "av1/common/obu_util.h"
 
 #define OBU_BUFFER_SIZE (500 * 1024)
 
diff --git a/tools/obu_parser.cc b/tools/obu_parser.cc
index 2d0f5b2..7d71386 100644
--- a/tools/obu_parser.cc
+++ b/tools/obu_parser.cc
@@ -8,6 +8,7 @@
  * Media Patent License 1.0 was not distributed with this source code in the
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  */
+#include <string.h>
 
 #include <cstdio>
 #include <string>
@@ -15,7 +16,7 @@
 #include "aom/aom_codec.h"
 #include "aom/aom_integer.h"
 #include "aom_ports/mem_ops.h"
-#include "av1/decoder/obu.h"
+#include "av1/common/obu_util.h"
 #include "tools/obu_parser.h"
 
 namespace aom_tools {