obudec.c 4.45 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Copyright (c) 2017, 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 <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "./obudec.h"

#include "aom_ports/mem_ops.h"
#include "av1/common/common.h"

#define OBU_HEADER_SIZE_BYTES 1
22 23 24
#if CONFIG_SCALABILITY
#define OBU_HEADER_EXTENSION_SIZE_BYTES 1
#endif
25 26 27

#if CONFIG_OBU_NO_IVF
int obu_read_temporal_unit(FILE *infile, uint8_t **buffer, size_t *bytes_read,
28 29 30
#if CONFIG_SCALABILITY
                           size_t *buffer_size, int last_layer_id) {
#else
31
                           size_t *buffer_size) {
32
#endif
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
  size_t ret;
  const size_t obu_length_header_size =
      PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES;
  uint32_t obu_size = 0;
  uint8_t *data = NULL;

  if (feof(infile)) {
    return 1;
  }

  *buffer_size = 0;
  *bytes_read = 0;
  while (1) {
    // augment the buffer to just contain the next size field
    // and the first byte of the header
    *buffer = realloc(*buffer, (*buffer_size) + obu_length_header_size);
    data = *buffer + (*buffer_size);
    *buffer_size += obu_length_header_size;
    ret = fread(data, 1, obu_length_header_size, infile);
    if (ret == 0) {
      // fprintf(stderr, "Found end of stream, ending temporal unit\n");
      break;
    }
    if (ret != obu_length_header_size) {
      warn("Failed to read OBU Header\n");
      return 1;
    }
    *bytes_read += obu_length_header_size;

    if (((data[PRE_OBU_SIZE_BYTES] >> 3) & 0xF) == OBU_TEMPORAL_DELIMITER) {
      // Stop when a temporal delimiter is found
      // fprintf(stderr, "Found temporal delimiter, ending temporal unit\n");
      // prevent decoder to start decoding another frame from this buffer
      *bytes_read -= obu_length_header_size;
      break;
    }

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
#if CONFIG_SCALABILITY
    // break if obu_extension_flag is found and enhancement_id change
    if ((data[PRE_OBU_SIZE_BYTES] & 0x1)) {
      uint8_t obu_extension_header;
      int total_obu_header_size =
          (int)obu_length_header_size + OBU_HEADER_EXTENSION_SIZE_BYTES;
      int curr_layer_id;
      fread(&obu_extension_header, 1, OBU_HEADER_EXTENSION_SIZE_BYTES, infile);
      curr_layer_id = (obu_extension_header >> 3) & 0x3;
      if (curr_layer_id && (curr_layer_id > last_layer_id)) {
        // new enhancement layer
        *bytes_read -= obu_length_header_size;
        fseek(infile, -total_obu_header_size, SEEK_CUR);
        break;
      } else {
        fseek(infile, -OBU_HEADER_EXTENSION_SIZE_BYTES, SEEK_CUR);
      }
    }
#endif

Tom Finegan's avatar
Tom Finegan committed
90 91 92 93
// otherwise, read the OBU payload into memory
#if CONFIG_OBU_SIZING
    aom_uleb_decode(data, PRE_OBU_SIZE_BYTES, &obu_size);
#else
94
    obu_size = mem_get_le32(data);
Tom Finegan's avatar
Tom Finegan committed
95 96
#endif  // CONFIG_OBU_SIZING

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    // fprintf(stderr, "Found OBU of type %d and size %d\n",
    //        ((data[PRE_OBU_SIZE_BYTES] >> 3) & 0xF), obu_size);
    obu_size--;  // removing the byte of the header already read
    if (obu_size) {
      *buffer = realloc(*buffer, (*buffer_size) + obu_size);
      data = *buffer + (*buffer_size);
      *buffer_size += obu_size;
      ret = fread(data, 1, obu_size, infile);
      if (ret != obu_size) {
        warn("Failed to read OBU Payload\n");
        return 1;
      }
      *bytes_read += obu_size;
    }
  }
  return 0;
}

int file_is_obu(struct AvxInputContext *input_ctx) {
  uint8_t obutd[PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES];
Tom Finegan's avatar
Tom Finegan committed
117
  uint32_t size;
118

119 120
#if !CONFIG_OBU
  warn("obudec.c requires CONFIG_OBU");
121 122 123 124 125
  return 0;
#endif

  // Reading the first OBU TD to enable TU end detection at TD start.
  fread(obutd, 1, PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES, input_ctx->file);
Tom Finegan's avatar
Tom Finegan committed
126 127 128 129

#if CONFIG_OBU_SIZING
  aom_uleb_decode(obutd, PRE_OBU_SIZE_BYTES, &size);
#else
130
  size = mem_get_le32(obutd);
Tom Finegan's avatar
Tom Finegan committed
131 132
#endif  // CONFIG_OBU_SIZING

133 134 135 136 137 138 139 140 141
  if (size != 1) {
    warn("Expected first OBU size to be 1, got %d", size);
    return 0;
  }
  if (((obutd[PRE_OBU_SIZE_BYTES] >> 3) & 0xF) != OBU_TEMPORAL_DELIMITER) {
    warn("Expected OBU TD at file start, got %d\n", obutd[PRE_OBU_SIZE_BYTES]);
    return 0;
  }
  // fprintf(stderr, "Starting to parse OBU stream\n");
142

143 144 145 146
  return 1;
}

#endif