blob: f859a68679bd4a27b40c4e4b96f73b26ba5da3cb [file] [log] [blame]
Cyril Concolato6c788832017-10-30 16:30:35 -07001/*
2 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include "./obudec.h"
17
18#include "aom_ports/mem_ops.h"
19#include "av1/common/common.h"
20
21#define OBU_HEADER_SIZE_BYTES 1
Soo-Chul Hanf8589862018-01-24 03:13:14 +000022#if CONFIG_SCALABILITY
23#define OBU_HEADER_EXTENSION_SIZE_BYTES 1
24#endif
Cyril Concolato6c788832017-10-30 16:30:35 -070025
26#if CONFIG_OBU_NO_IVF
27int obu_read_temporal_unit(FILE *infile, uint8_t **buffer, size_t *bytes_read,
Soo-Chul Hanf8589862018-01-24 03:13:14 +000028#if CONFIG_SCALABILITY
29 size_t *buffer_size, int last_layer_id) {
30#else
Cyril Concolato6c788832017-10-30 16:30:35 -070031 size_t *buffer_size) {
Soo-Chul Hanf8589862018-01-24 03:13:14 +000032#endif
Cyril Concolato6c788832017-10-30 16:30:35 -070033 size_t ret;
34 const size_t obu_length_header_size =
35 PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES;
36 uint32_t obu_size = 0;
37 uint8_t *data = NULL;
38
39 if (feof(infile)) {
40 return 1;
41 }
42
43 *buffer_size = 0;
44 *bytes_read = 0;
45 while (1) {
46 // augment the buffer to just contain the next size field
47 // and the first byte of the header
48 *buffer = realloc(*buffer, (*buffer_size) + obu_length_header_size);
49 data = *buffer + (*buffer_size);
50 *buffer_size += obu_length_header_size;
51 ret = fread(data, 1, obu_length_header_size, infile);
52 if (ret == 0) {
53 // fprintf(stderr, "Found end of stream, ending temporal unit\n");
54 break;
55 }
56 if (ret != obu_length_header_size) {
57 warn("Failed to read OBU Header\n");
58 return 1;
59 }
60 *bytes_read += obu_length_header_size;
61
62 if (((data[PRE_OBU_SIZE_BYTES] >> 3) & 0xF) == OBU_TEMPORAL_DELIMITER) {
63 // Stop when a temporal delimiter is found
64 // fprintf(stderr, "Found temporal delimiter, ending temporal unit\n");
65 // prevent decoder to start decoding another frame from this buffer
66 *bytes_read -= obu_length_header_size;
67 break;
68 }
69
Soo-Chul Hanf8589862018-01-24 03:13:14 +000070#if CONFIG_SCALABILITY
71 // break if obu_extension_flag is found and enhancement_id change
72 if ((data[PRE_OBU_SIZE_BYTES] & 0x1)) {
73 uint8_t obu_extension_header;
74 int total_obu_header_size =
75 (int)obu_length_header_size + OBU_HEADER_EXTENSION_SIZE_BYTES;
76 int curr_layer_id;
77 fread(&obu_extension_header, 1, OBU_HEADER_EXTENSION_SIZE_BYTES, infile);
78 curr_layer_id = (obu_extension_header >> 3) & 0x3;
79 if (curr_layer_id && (curr_layer_id > last_layer_id)) {
80 // new enhancement layer
81 *bytes_read -= obu_length_header_size;
82 fseek(infile, -total_obu_header_size, SEEK_CUR);
83 break;
84 } else {
85 fseek(infile, -OBU_HEADER_EXTENSION_SIZE_BYTES, SEEK_CUR);
86 }
87 }
88#endif
89
Tom Finegan41150ad2018-01-23 11:42:55 -080090// otherwise, read the OBU payload into memory
91#if CONFIG_OBU_SIZING
92 aom_uleb_decode(data, PRE_OBU_SIZE_BYTES, &obu_size);
93#else
Cyril Concolato6c788832017-10-30 16:30:35 -070094 obu_size = mem_get_le32(data);
Tom Finegan41150ad2018-01-23 11:42:55 -080095#endif // CONFIG_OBU_SIZING
96
Cyril Concolato6c788832017-10-30 16:30:35 -070097 // fprintf(stderr, "Found OBU of type %d and size %d\n",
98 // ((data[PRE_OBU_SIZE_BYTES] >> 3) & 0xF), obu_size);
99 obu_size--; // removing the byte of the header already read
100 if (obu_size) {
101 *buffer = realloc(*buffer, (*buffer_size) + obu_size);
102 data = *buffer + (*buffer_size);
103 *buffer_size += obu_size;
104 ret = fread(data, 1, obu_size, infile);
105 if (ret != obu_size) {
106 warn("Failed to read OBU Payload\n");
107 return 1;
108 }
109 *bytes_read += obu_size;
110 }
111 }
112 return 0;
113}
114
115int file_is_obu(struct AvxInputContext *input_ctx) {
116 uint8_t obutd[PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES];
Tom Finegan41150ad2018-01-23 11:42:55 -0800117 uint32_t size;
Cyril Concolato6c788832017-10-30 16:30:35 -0700118
Tom Fineganff863952017-12-22 11:41:14 -0800119#if !CONFIG_OBU
120 warn("obudec.c requires CONFIG_OBU");
Cyril Concolato6c788832017-10-30 16:30:35 -0700121 return 0;
122#endif
123
124 // Reading the first OBU TD to enable TU end detection at TD start.
125 fread(obutd, 1, PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES, input_ctx->file);
Tom Finegan41150ad2018-01-23 11:42:55 -0800126
127#if CONFIG_OBU_SIZING
128 aom_uleb_decode(obutd, PRE_OBU_SIZE_BYTES, &size);
129#else
Cyril Concolato6c788832017-10-30 16:30:35 -0700130 size = mem_get_le32(obutd);
Tom Finegan41150ad2018-01-23 11:42:55 -0800131#endif // CONFIG_OBU_SIZING
132
Cyril Concolato6c788832017-10-30 16:30:35 -0700133 if (size != 1) {
134 warn("Expected first OBU size to be 1, got %d", size);
135 return 0;
136 }
137 if (((obutd[PRE_OBU_SIZE_BYTES] >> 3) & 0xF) != OBU_TEMPORAL_DELIMITER) {
138 warn("Expected OBU TD at file start, got %d\n", obutd[PRE_OBU_SIZE_BYTES]);
139 return 0;
140 }
141 // fprintf(stderr, "Starting to parse OBU stream\n");
Soo-Chul Hanf8589862018-01-24 03:13:14 +0000142
Cyril Concolato6c788832017-10-30 16:30:35 -0700143 return 1;
144}
145
146#endif