1 /*
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 <stdlib.h>
13 #include <string.h>
14
15 #include <memory>
16 #include <string>
17
18 #include "config/aom_config.h"
19
20 #include "common/ivfdec.h"
21 #include "common/obudec.h"
22 #include "common/tools_common.h"
23 #include "common/webmdec.h"
24 #include "tools/obu_parser.h"
25
26 namespace {
27
28 const size_t kInitialBufferSize = 100 * 1024;
29
30 struct InputContext {
31 InputContext() = default;
~InputContext__anon2b8b38080111::InputContext32 ~InputContext() { free(unit_buffer); }
33
Init__anon2b8b38080111::InputContext34 void Init() {
35 memset(avx_ctx, 0, sizeof(*avx_ctx));
36 memset(obu_ctx, 0, sizeof(*obu_ctx));
37 obu_ctx->avx_ctx = avx_ctx;
38 #if CONFIG_WEBM_IO
39 memset(webm_ctx, 0, sizeof(*webm_ctx));
40 #endif
41 }
42
43 AvxInputContext *avx_ctx = nullptr;
44 ObuDecInputContext *obu_ctx = nullptr;
45 #if CONFIG_WEBM_IO
46 WebmInputContext *webm_ctx = nullptr;
47 #endif
48 uint8_t *unit_buffer = nullptr;
49 size_t unit_buffer_size = 0;
50 };
51
PrintUsage()52 void PrintUsage() {
53 printf("Libaom OBU dump.\nUsage: dump_obu <input_file>\n");
54 }
55
GetFileType(InputContext * ctx)56 VideoFileType GetFileType(InputContext *ctx) {
57 // TODO(https://crbug.com/aomedia/1706): webm type does not support reading
58 // from stdin yet, and file_is_webm is not using the detect buffer when
59 // determining the type. Therefore it should only be checked when using a file
60 // and needs to be checked prior to other types.
61 #if CONFIG_WEBM_IO
62 if (file_is_webm(ctx->webm_ctx, ctx->avx_ctx)) return FILE_TYPE_WEBM;
63 #endif
64 if (file_is_ivf(ctx->avx_ctx)) return FILE_TYPE_IVF;
65 if (file_is_obu(ctx->obu_ctx)) return FILE_TYPE_OBU;
66 return FILE_TYPE_RAW;
67 }
68
ReadTemporalUnit(InputContext * ctx,size_t * unit_size)69 bool ReadTemporalUnit(InputContext *ctx, size_t *unit_size) {
70 const VideoFileType file_type = ctx->avx_ctx->file_type;
71 switch (file_type) {
72 case FILE_TYPE_IVF: {
73 if (ivf_read_frame(ctx->avx_ctx, &ctx->unit_buffer, unit_size,
74 &ctx->unit_buffer_size, NULL)) {
75 return false;
76 }
77 break;
78 }
79 case FILE_TYPE_OBU: {
80 if (obudec_read_temporal_unit(ctx->obu_ctx, &ctx->unit_buffer, unit_size,
81 &ctx->unit_buffer_size)) {
82 return false;
83 }
84 break;
85 }
86 #if CONFIG_WEBM_IO
87 case FILE_TYPE_WEBM: {
88 if (webm_read_frame(ctx->webm_ctx, &ctx->unit_buffer, unit_size,
89 &ctx->unit_buffer_size)) {
90 return false;
91 }
92 break;
93 }
94 #endif
95 default:
96 // TODO(tomfinegan): Abuse FILE_TYPE_RAW for AV1/OBU elementary streams?
97 fprintf(stderr, "Error: Unsupported file type.\n");
98 return false;
99 }
100
101 return true;
102 }
103
104 } // namespace
105
main(int argc,const char * argv[])106 int main(int argc, const char *argv[]) {
107 // TODO(tomfinegan): Could do with some params for verbosity.
108 if (argc < 2) {
109 PrintUsage();
110 return EXIT_SUCCESS;
111 }
112
113 const std::string filename = argv[1];
114
115 using FilePtr = std::unique_ptr<FILE, decltype(&fclose)>;
116 FilePtr input_file(fopen(filename.c_str(), "rb"), &fclose);
117 if (input_file.get() == nullptr) {
118 input_file.release();
119 fprintf(stderr, "Error: Cannot open input file.\n");
120 return EXIT_FAILURE;
121 }
122
123 AvxInputContext avx_ctx;
124 InputContext input_ctx;
125 input_ctx.avx_ctx = &avx_ctx;
126 ObuDecInputContext obu_ctx;
127 input_ctx.obu_ctx = &obu_ctx;
128 #if CONFIG_WEBM_IO
129 WebmInputContext webm_ctx;
130 input_ctx.webm_ctx = &webm_ctx;
131 #endif
132
133 input_ctx.Init();
134 avx_ctx.file = input_file.get();
135 avx_ctx.file_type = GetFileType(&input_ctx);
136
137 // Note: the reader utilities will realloc the buffer using realloc() etc.
138 // Can't have nice things like unique_ptr wrappers with that type of
139 // behavior underneath the function calls.
140 input_ctx.unit_buffer =
141 reinterpret_cast<uint8_t *>(calloc(kInitialBufferSize, 1));
142 if (!input_ctx.unit_buffer) {
143 fprintf(stderr, "Error: No memory, can't alloc input buffer.\n");
144 return EXIT_FAILURE;
145 }
146 input_ctx.unit_buffer_size = kInitialBufferSize;
147
148 size_t unit_size = 0;
149 int unit_number = 0;
150 int64_t obu_overhead_bytes_total = 0;
151 while (ReadTemporalUnit(&input_ctx, &unit_size)) {
152 printf("Temporal unit %d\n", unit_number);
153
154 int obu_overhead_current_unit = 0;
155 if (!aom_tools::DumpObu(input_ctx.unit_buffer, static_cast<int>(unit_size),
156 &obu_overhead_current_unit)) {
157 fprintf(stderr, "Error: Temporal Unit parse failed on unit number %d.\n",
158 unit_number);
159 return EXIT_FAILURE;
160 }
161 printf(" OBU overhead: %d\n", obu_overhead_current_unit);
162 ++unit_number;
163 obu_overhead_bytes_total += obu_overhead_current_unit;
164 }
165
166 printf("File total OBU overhead: %" PRId64 "\n", obu_overhead_bytes_total);
167 return EXIT_SUCCESS;
168 }
169