| /* | |
| * 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 <stdlib.h> | |
| #include <string.h> | |
| #include <memory> | |
| #include <string> | |
| #include "./aom_config.h" | |
| #include "./ivfdec.h" | |
| #include "tools/obu_parser.h" | |
| #include "./tools_common.h" | |
| #include "./webmdec.h" | |
| namespace { | |
| const size_t kInitialBufferSize = 100 * 1024; | |
| struct InputContext { | |
| InputContext() = default; | |
| ~InputContext() { free(unit_buffer); } | |
| void Init() { | |
| memset(avx_ctx, 0, sizeof(*avx_ctx)); | |
| #if CONFIG_WEBM_IO | |
| memset(webm_ctx, 0, sizeof(*webm_ctx)); | |
| #endif | |
| } | |
| AvxInputContext *avx_ctx = nullptr; | |
| #if CONFIG_WEBM_IO | |
| WebmInputContext *webm_ctx = nullptr; | |
| #endif | |
| uint8_t *unit_buffer = nullptr; | |
| size_t unit_buffer_size = 0; | |
| }; | |
| void PrintUsage() { | |
| printf("Libaom OBU dump.\nUsage: dump_obu <input_file>\n"); | |
| } | |
| VideoFileType GetFileType(InputContext *ctx) { | |
| if (file_is_ivf(ctx->avx_ctx)) return FILE_TYPE_IVF; | |
| #if CONFIG_WEBM_IO | |
| if (file_is_webm(ctx->webm_ctx, ctx->avx_ctx)) return FILE_TYPE_WEBM; | |
| #endif | |
| return FILE_TYPE_RAW; | |
| } | |
| bool ReadTemporalUnit(InputContext *ctx, size_t *unit_size) { | |
| const VideoFileType file_type = ctx->avx_ctx->file_type; | |
| switch (file_type) { | |
| case FILE_TYPE_IVF: { | |
| if (ivf_read_frame(ctx->avx_ctx->file, &ctx->unit_buffer, unit_size, | |
| &ctx->unit_buffer_size)) { | |
| return false; | |
| } | |
| break; | |
| } | |
| #if CONFIG_WEBM_IO | |
| case FILE_TYPE_WEBM: { | |
| size_t frame_size = ctx->unit_buffer_size; | |
| if (webm_read_frame(ctx->webm_ctx, &ctx->unit_buffer, &frame_size)) { | |
| return false; | |
| } | |
| if (frame_size != ctx->unit_buffer_size && | |
| frame_size > ctx->unit_buffer_size) { | |
| // webmdec realloc'd the buffer, store new size. | |
| ctx->unit_buffer_size = frame_size; | |
| } | |
| *unit_size = frame_size; | |
| break; | |
| } | |
| #endif | |
| default: | |
| // TODO(tomfinegan): Abuse FILE_TYPE_RAW for AV1/OBU elementary streams? | |
| fprintf(stderr, "Error: Unsupported file type.\n"); | |
| return false; | |
| } | |
| return true; | |
| } | |
| } // namespace | |
| int main(int argc, const char *argv[]) { | |
| // TODO(tomfinegan): Could do with some params for verbosity. | |
| if (argc < 2) { | |
| PrintUsage(); | |
| return EXIT_SUCCESS; | |
| } | |
| const std::string filename = argv[1]; | |
| using FilePtr = std::unique_ptr<FILE, decltype(&fclose)>; | |
| FilePtr input_file(fopen(filename.c_str(), "rb"), &fclose); | |
| if (input_file.get() == nullptr) { | |
| input_file.release(); | |
| fprintf(stderr, "Error: Cannot open input file.\n"); | |
| return EXIT_FAILURE; | |
| } | |
| AvxInputContext avx_ctx; | |
| InputContext input_ctx; | |
| input_ctx.avx_ctx = &avx_ctx; | |
| #if CONFIG_WEBM_IO | |
| WebmInputContext webm_ctx; | |
| input_ctx.webm_ctx = &webm_ctx; | |
| #endif | |
| input_ctx.Init(); | |
| avx_ctx.file = input_file.get(); | |
| avx_ctx.file_type = GetFileType(&input_ctx); | |
| // Note: the reader utilities will realloc the buffer using realloc() etc. | |
| // Can't have nice things like unique_ptr wrappers with that type of | |
| // behavior underneath the function calls. | |
| input_ctx.unit_buffer = | |
| reinterpret_cast<uint8_t *>(calloc(kInitialBufferSize, 1)); | |
| if (!input_ctx.unit_buffer) { | |
| fprintf(stderr, "Error: No memory, can't alloc input buffer.\n"); | |
| return EXIT_FAILURE; | |
| } | |
| input_ctx.unit_buffer_size = kInitialBufferSize; | |
| size_t unit_size = 0; | |
| int unit_number = 0; | |
| while (ReadTemporalUnit(&input_ctx, &unit_size)) { | |
| printf("Temporal unit %d\n", unit_number); | |
| if (!aom_tools::DumpObu(input_ctx.unit_buffer, unit_size)) { | |
| fprintf(stderr, "Error: Temporal Unit parse failed on unit number %d.\n", | |
| unit_number); | |
| return EXIT_FAILURE; | |
| } | |
| ++unit_number; | |
| } | |
| return EXIT_SUCCESS; | |
| } |