dump_obu.cc (5118B)
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; 32 ~InputContext() { free(unit_buffer); } 33 34 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 52 void PrintUsage() { 53 printf("Libaom OBU dump.\nUsage: dump_obu <input_file>\n"); 54 } 55 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 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 void CloseFile(FILE *stream) { fclose(stream); } 105 106 } // namespace 107 108 int main(int argc, const char *argv[]) { 109 // TODO(tomfinegan): Could do with some params for verbosity. 110 if (argc < 2) { 111 PrintUsage(); 112 return EXIT_SUCCESS; 113 } 114 115 const std::string filename = argv[1]; 116 117 using FilePtr = std::unique_ptr<FILE, decltype(&CloseFile)>; 118 FilePtr input_file(fopen(filename.c_str(), "rb"), &CloseFile); 119 if (input_file.get() == nullptr) { 120 input_file.release(); 121 fprintf(stderr, "Error: Cannot open input file.\n"); 122 return EXIT_FAILURE; 123 } 124 125 AvxInputContext avx_ctx; 126 InputContext input_ctx; 127 input_ctx.avx_ctx = &avx_ctx; 128 ObuDecInputContext obu_ctx; 129 input_ctx.obu_ctx = &obu_ctx; 130 #if CONFIG_WEBM_IO 131 WebmInputContext webm_ctx; 132 input_ctx.webm_ctx = &webm_ctx; 133 #endif 134 135 input_ctx.Init(); 136 avx_ctx.file = input_file.get(); 137 avx_ctx.file_type = GetFileType(&input_ctx); 138 139 // Note: the reader utilities will realloc the buffer using realloc() etc. 140 // Can't have nice things like unique_ptr wrappers with that type of 141 // behavior underneath the function calls. 142 input_ctx.unit_buffer = 143 reinterpret_cast<uint8_t *>(calloc(kInitialBufferSize, 1)); 144 if (!input_ctx.unit_buffer) { 145 fprintf(stderr, "Error: No memory, can't alloc input buffer.\n"); 146 return EXIT_FAILURE; 147 } 148 input_ctx.unit_buffer_size = kInitialBufferSize; 149 150 size_t unit_size = 0; 151 int unit_number = 0; 152 int64_t obu_overhead_bytes_total = 0; 153 while (ReadTemporalUnit(&input_ctx, &unit_size)) { 154 printf("Temporal unit %d\n", unit_number); 155 156 int obu_overhead_current_unit = 0; 157 if (!aom_tools::DumpObu(input_ctx.unit_buffer, static_cast<int>(unit_size), 158 &obu_overhead_current_unit)) { 159 fprintf(stderr, "Error: Temporal Unit parse failed on unit number %d.\n", 160 unit_number); 161 return EXIT_FAILURE; 162 } 163 printf(" OBU overhead: %d\n", obu_overhead_current_unit); 164 ++unit_number; 165 obu_overhead_bytes_total += obu_overhead_current_unit; 166 } 167 168 printf("File total OBU overhead: %" PRId64 "\n", obu_overhead_bytes_total); 169 return EXIT_SUCCESS; 170 }