mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-10 01:07:31 +09:00
aom: update libaom to 0ec86ac7ae1e32a7e70410fa4972a655ec3670a4
This commit is contained in:
parent
bc3f20e378
commit
eb361970c5
438 changed files with 52661 additions and 21905 deletions
2
third_party/aom/examples/analyzer.cc
vendored
2
third_party/aom/examples/analyzer.cc
vendored
|
|
@ -162,7 +162,7 @@ bool AV1Decoder::setInspectionCallback() {
|
|||
|
||||
void AV1Decoder::inspect(void *pbi, void *data) {
|
||||
AV1Decoder *decoder = (AV1Decoder *)data;
|
||||
ifd_inspect(&decoder->frame_data, pbi);
|
||||
ifd_inspect(&decoder->frame_data, pbi, 0);
|
||||
}
|
||||
|
||||
#define MIN_ZOOM (1)
|
||||
|
|
|
|||
4
third_party/aom/examples/aom_cx_set_ref.c
vendored
4
third_party/aom/examples/aom_cx_set_ref.c
vendored
|
|
@ -141,9 +141,7 @@ static int encode_frame(aom_codec_ctx_t *ecodec, aom_image_t *img,
|
|||
if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
|
||||
const int keyframe = (pkt->data.frame.flags & AOM_FRAME_IS_KEY) != 0;
|
||||
|
||||
if (!(pkt->data.frame.flags & AOM_FRAME_IS_FRAGMENT)) {
|
||||
*frame_out += 1;
|
||||
}
|
||||
++*frame_out;
|
||||
|
||||
if (!aom_video_writer_write_frame(writer, pkt->data.frame.buf,
|
||||
pkt->data.frame.sz,
|
||||
|
|
|
|||
72
third_party/aom/examples/av1_dec_fuzzer.cc
vendored
Normal file
72
third_party/aom/examples/av1_dec_fuzzer.cc
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See build_av1_dec_fuzzer.sh for building instructions.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory>
|
||||
|
||||
#include "config/aom_config.h"
|
||||
#include "aom/aom_decoder.h"
|
||||
#include "aom/aomdx.h"
|
||||
#include "aom_ports/mem_ops.h"
|
||||
#include "common/ivfdec.h"
|
||||
|
||||
static void close_file(FILE *file) { fclose(file); }
|
||||
|
||||
extern "C" void usage_exit(void) { exit(EXIT_FAILURE); }
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
std::unique_ptr<FILE, decltype(&close_file)> file(
|
||||
fmemopen((void *)data, size, "rb"), &close_file);
|
||||
if (file == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char header[32];
|
||||
if (fread(header, 1, 32, file.get()) != 32) {
|
||||
return 0;
|
||||
}
|
||||
const AvxInterface *decoder = get_aom_decoder_by_name("av1");
|
||||
if (decoder == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aom_codec_ctx_t codec;
|
||||
// Set thread count in the range [1, 64].
|
||||
const unsigned int threads = (header[0] & 0x3f) + 1;
|
||||
aom_codec_dec_cfg_t cfg = { threads, 0, 0, CONFIG_LOWBITDEPTH };
|
||||
if (aom_codec_dec_init(&codec, decoder->codec_interface(), &cfg, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *buffer = nullptr;
|
||||
size_t buffer_size = 0;
|
||||
size_t frame_size = 0;
|
||||
while (!ivf_read_frame(file.get(), &buffer, &frame_size, &buffer_size,
|
||||
nullptr)) {
|
||||
const aom_codec_err_t err =
|
||||
aom_codec_decode(&codec, buffer, frame_size, nullptr);
|
||||
static_cast<void>(err);
|
||||
aom_codec_iter_t iter = nullptr;
|
||||
aom_image_t *img = nullptr;
|
||||
while ((img = aom_codec_get_frame(&codec, &iter)) != nullptr) {
|
||||
}
|
||||
}
|
||||
aom_codec_destroy(&codec);
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
78
third_party/aom/examples/build_av1_dec_fuzzer.sh
vendored
Normal file
78
third_party/aom/examples/build_av1_dec_fuzzer.sh
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2019, 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.
|
||||
#
|
||||
###############################################################################
|
||||
# Fuzzer for libaom decoder.
|
||||
# ==========================
|
||||
# Requirements
|
||||
# ---------------------
|
||||
# Clang6.0 or above (must support -fsanitize=fuzzer)
|
||||
#
|
||||
# References:
|
||||
# ---------------------
|
||||
# http://llvm.org/docs/LibFuzzer.html
|
||||
# https://github.com/google/oss-fuzz
|
||||
#
|
||||
# Steps to build / run
|
||||
# ---------------------
|
||||
|
||||
set -eu
|
||||
|
||||
# Have a copy of AOM and a build directory ready.
|
||||
if [[ $# -ne 2 ]]; then
|
||||
echo "Pass in the AOM source tree as first argument, and a build directory "
|
||||
echo "as the second argument. The AOM source tree can be obtained via: "
|
||||
echo " git clone https://aomedia.googlesource.com/aom"
|
||||
exit 2
|
||||
fi
|
||||
if [[ -z "$CC" ]]; then
|
||||
echo "Set the CC environment variable to point to your C compiler."
|
||||
exit 2
|
||||
fi
|
||||
if [[ -z "$CXX" ]]; then
|
||||
echo "Set the CXX environment variable to point to your C++ compiler."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
AOM_DIR=$1
|
||||
BUILD_DIR=$2
|
||||
# Run CMake with address sanitizer enabled and build the codec.
|
||||
# Enable DO_RANGE_CHECK_CLAMP to suppress the noise of integer overflows
|
||||
# in the transform functions. Also set memory limits.
|
||||
EXTRA_C_FLAGS='-DDO_RANGE_CHECK_CLAMP=1 -DAOM_MAX_ALLOCABLE_MEMORY=1073741824'
|
||||
cd "${BUILD_DIR}"
|
||||
cmake "${AOM_DIR}" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONFIG_PIC=1 \
|
||||
-DCONFIG_SCALABILITY=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_AV1_ENCODER=0 \
|
||||
-DENABLE_EXAMPLES=0 -DENABLE_DOCS=0 -DENABLE_TESTS=0 -DCONFIG_SIZE_LIMIT=1 \
|
||||
-DDECODE_HEIGHT_LIMIT=12288 -DDECODE_WIDTH_LIMIT=12288 \
|
||||
-DAOM_EXTRA_C_FLAGS="${EXTRA_C_FLAGS}" \
|
||||
-DAOM_EXTRA_CXX_FLAGS="${EXTRA_C_FLAGS}" -DSANITIZE=address
|
||||
|
||||
# Build the codec.
|
||||
make -j$(nproc)
|
||||
|
||||
# Build some libaom utils that are not part of the core lib.
|
||||
$CC -std=c99 -c -I${AOM_DIR} -I${BUILD_DIR} \
|
||||
${AOM_DIR}/common/ivfdec.c -o ${BUILD_DIR}/ivfdec.o
|
||||
|
||||
$CC -std=c99 -c -I${AOM_DIR} -I${BUILD_DIR} \
|
||||
${AOM_DIR}/common/tools_common.c -o ${BUILD_DIR}/tools_common.o
|
||||
|
||||
# Build the av1 fuzzer
|
||||
$CXX -std=c++11 -DDECODER=av1 -I${AOM_DIR} -I${BUILD_DIR} \
|
||||
-fsanitize=fuzzer -Wl,--start-group \
|
||||
${AOM_DIR}/examples/av1_dec_fuzzer.cc -o ${BUILD_DIR}/av1_dec_fuzzer \
|
||||
${BUILD_DIR}/libaom.a ${BUILD_DIR}/ivfdec.o ${BUILD_DIR}/tools_common.o \
|
||||
-Wl,--end-group
|
||||
|
||||
echo "Fuzzer built at ${BUILD_DIR}/av1_dec_fuzzer."
|
||||
echo "Create a corpus directory, copy IVF files in there, and run:"
|
||||
echo " av1_dec_fuzzer CORPUS_DIR"
|
||||
183
third_party/aom/examples/inspect.c
vendored
183
third_party/aom/examples/inspect.c
vendored
|
|
@ -60,7 +60,9 @@ typedef enum {
|
|||
DUAL_FILTER_LAYER = 1 << 12,
|
||||
Q_INDEX_LAYER = 1 << 13,
|
||||
SEGMENT_ID_LAYER = 1 << 14,
|
||||
ALL_LAYERS = (1 << 15) - 1
|
||||
MOTION_MODE_LAYER = 1 << 15,
|
||||
COMPOUND_TYPE_LAYER = 1 << 16,
|
||||
ALL_LAYERS = (1 << 17) - 1
|
||||
} LayerType;
|
||||
|
||||
static LayerType layers = 0;
|
||||
|
|
@ -84,6 +86,10 @@ static const arg_def_t dump_transform_size_arg =
|
|||
static const arg_def_t dump_transform_type_arg =
|
||||
ARG_DEF("tt", "transformType", 0, "Dump Transform Type");
|
||||
static const arg_def_t dump_mode_arg = ARG_DEF("m", "mode", 0, "Dump Mode");
|
||||
static const arg_def_t dump_motion_mode_arg =
|
||||
ARG_DEF("mm", "motion_mode", 0, "Dump Motion Modes");
|
||||
static const arg_def_t dump_compound_type_arg =
|
||||
ARG_DEF("ct", "compound_type", 0, "Dump Compound Types");
|
||||
static const arg_def_t dump_uv_mode_arg =
|
||||
ARG_DEF("uvm", "uv_mode", 0, "Dump UV Intra Prediction Modes");
|
||||
static const arg_def_t dump_skip_arg = ARG_DEF("s", "skip", 0, "Dump Skip");
|
||||
|
|
@ -101,6 +107,13 @@ static const arg_def_t dump_delta_q_arg =
|
|||
static const arg_def_t dump_seg_id_arg =
|
||||
ARG_DEF("si", "seg_id", 0, "Dump Segment ID");
|
||||
static const arg_def_t usage_arg = ARG_DEF("h", "help", 0, "Help");
|
||||
static const arg_def_t skip_non_transform_arg = ARG_DEF(
|
||||
"snt", "skip_non_transform", 1, "Skip is counted as a non transform.");
|
||||
static const arg_def_t combined_arg =
|
||||
ARG_DEF("comb", "combined", 1, "combinining parameters into one output.");
|
||||
|
||||
int combined_parm_list[5];
|
||||
int combined_parm_count = 0;
|
||||
|
||||
static const arg_def_t *main_args[] = { &limit_arg,
|
||||
&dump_all_arg,
|
||||
|
|
@ -113,6 +126,8 @@ static const arg_def_t *main_args[] = { &limit_arg,
|
|||
&dump_transform_type_arg,
|
||||
&dump_mode_arg,
|
||||
&dump_uv_mode_arg,
|
||||
&dump_motion_mode_arg,
|
||||
&dump_compound_type_arg,
|
||||
&dump_skip_arg,
|
||||
&dump_filter_arg,
|
||||
&dump_cdef_arg,
|
||||
|
|
@ -123,6 +138,8 @@ static const arg_def_t *main_args[] = { &limit_arg,
|
|||
&dump_delta_q_arg,
|
||||
&dump_seg_id_arg,
|
||||
&usage_arg,
|
||||
&skip_non_transform_arg,
|
||||
&combined_arg,
|
||||
NULL };
|
||||
#define ENUM(name) \
|
||||
{ #name, name }
|
||||
|
|
@ -150,12 +167,14 @@ const map_entry block_size_map[] = {
|
|||
ENUM(BLOCK_64X16), LAST_ENUM
|
||||
};
|
||||
|
||||
#define TX_SKIP -1
|
||||
|
||||
const map_entry tx_size_map[] = {
|
||||
ENUM(TX_4X4), ENUM(TX_8X8), ENUM(TX_16X16), ENUM(TX_32X32),
|
||||
ENUM(TX_64X64), ENUM(TX_4X8), ENUM(TX_8X4), ENUM(TX_8X16),
|
||||
ENUM(TX_16X8), ENUM(TX_16X32), ENUM(TX_32X16), ENUM(TX_32X64),
|
||||
ENUM(TX_64X32), ENUM(TX_4X16), ENUM(TX_16X4), ENUM(TX_8X32),
|
||||
ENUM(TX_32X8), LAST_ENUM
|
||||
ENUM(TX_32X8), ENUM(TX_16X64), ENUM(TX_64X16), LAST_ENUM
|
||||
};
|
||||
|
||||
const map_entry tx_type_map[] = { ENUM(DCT_DCT),
|
||||
|
|
@ -193,6 +212,15 @@ const map_entry prediction_mode_map[] = {
|
|||
ENUM(NEW_NEWMV), ENUM(INTRA_INVALID), LAST_ENUM
|
||||
};
|
||||
|
||||
const map_entry motion_mode_map[] = { ENUM(SIMPLE_TRANSLATION),
|
||||
ENUM(OBMC_CAUSAL), // 2-sided OBMC
|
||||
ENUM(WARPED_CAUSAL), // 2-sided WARPED
|
||||
LAST_ENUM };
|
||||
|
||||
const map_entry compound_type_map[] = { ENUM(COMPOUND_AVERAGE),
|
||||
ENUM(COMPOUND_WEDGE),
|
||||
ENUM(COMPOUND_DIFFWTD), LAST_ENUM };
|
||||
|
||||
const map_entry uv_prediction_mode_map[] = {
|
||||
ENUM(UV_DC_PRED), ENUM(UV_V_PRED),
|
||||
ENUM(UV_H_PRED), ENUM(UV_D45_PRED),
|
||||
|
|
@ -212,6 +240,43 @@ const map_entry config_map[] = { ENUM(MI_SIZE), LAST_ENUM };
|
|||
|
||||
static const char *exec_name;
|
||||
|
||||
struct parm_offset {
|
||||
char parm[60];
|
||||
char offset;
|
||||
};
|
||||
struct parm_offset parm_offsets[] = {
|
||||
{ "blockSize", offsetof(insp_mi_data, sb_type) },
|
||||
{ "transformSize", offsetof(insp_mi_data, tx_size) },
|
||||
{ "transformType", offsetof(insp_mi_data, tx_type) },
|
||||
{ "dualFilterType", offsetof(insp_mi_data, dual_filter_type) },
|
||||
{ "mode", offsetof(insp_mi_data, mode) },
|
||||
{ "uv_mode", offsetof(insp_mi_data, uv_mode) },
|
||||
{ "motion_mode", offsetof(insp_mi_data, motion_mode) },
|
||||
{ "compound_type", offsetof(insp_mi_data, compound_type) },
|
||||
{ "referenceFrame", offsetof(insp_mi_data, ref_frame) },
|
||||
{ "skip", offsetof(insp_mi_data, skip) },
|
||||
};
|
||||
int parm_count = sizeof(parm_offsets) / sizeof(parm_offsets[0]);
|
||||
|
||||
int convert_to_indices(char *str, int *indices, int maxCount, int *count) {
|
||||
*count = 0;
|
||||
do {
|
||||
char *comma = strchr(str, ',');
|
||||
int length = (comma ? (int)(comma - str) : (int)strlen(str));
|
||||
int i;
|
||||
for (i = 0; i < parm_count; ++i) {
|
||||
if (!strncmp(str, parm_offsets[i].parm, length)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == parm_count) return 0;
|
||||
indices[(*count)++] = i;
|
||||
if (*count > maxCount) return 0;
|
||||
str += length + 1;
|
||||
} while (strlen(str) > 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
insp_frame_data frame_data;
|
||||
int frame_count = 0;
|
||||
int decoded_frame_count = 0;
|
||||
|
|
@ -382,6 +447,38 @@ int put_motion_vectors(char *buffer) {
|
|||
return (int)(buf - buffer);
|
||||
}
|
||||
|
||||
int put_combined(char *buffer) {
|
||||
const int mi_rows = frame_data.mi_rows;
|
||||
const int mi_cols = frame_data.mi_cols;
|
||||
char *buf = buffer;
|
||||
int r, c, p;
|
||||
buf += put_str(buf, " \"");
|
||||
for (p = 0; p < combined_parm_count; ++p) {
|
||||
if (p) buf += put_str(buf, "&");
|
||||
buf += put_str(buf, parm_offsets[combined_parm_list[p]].parm);
|
||||
}
|
||||
buf += put_str(buf, "\": [");
|
||||
for (r = 0; r < mi_rows; ++r) {
|
||||
*(buf++) = '[';
|
||||
for (c = 0; c < mi_cols; ++c) {
|
||||
insp_mi_data *mi = &frame_data.mi_grid[r * mi_cols + c];
|
||||
*(buf++) = '[';
|
||||
for (p = 0; p < combined_parm_count; ++p) {
|
||||
if (p) *(buf++) = ',';
|
||||
int16_t *v = (int16_t *)(((int8_t *)mi) +
|
||||
parm_offsets[combined_parm_list[p]].offset);
|
||||
buf += put_num(buf, 0, v[0], 0);
|
||||
}
|
||||
*(buf++) = ']';
|
||||
if (c < mi_cols - 1) *(buf++) = ',';
|
||||
}
|
||||
*(buf++) = ']';
|
||||
if (r < mi_rows - 1) *(buf++) = ',';
|
||||
}
|
||||
buf += put_str(buf, "],\n");
|
||||
return (int)(buf - buffer);
|
||||
}
|
||||
|
||||
int put_block_info(char *buffer, const map_entry *map, const char *name,
|
||||
size_t offset, int len) {
|
||||
const int mi_rows = frame_data.mi_rows;
|
||||
|
|
@ -490,9 +587,16 @@ int put_accounting(char *buffer) {
|
|||
}
|
||||
#endif
|
||||
|
||||
int skip_non_transform = 0;
|
||||
|
||||
void inspect(void *pbi, void *data) {
|
||||
/* Fetch frame data. */
|
||||
ifd_inspect(&frame_data, pbi);
|
||||
ifd_inspect(&frame_data, pbi, skip_non_transform);
|
||||
|
||||
// Show existing frames just show a reference buffer we've already decoded.
|
||||
// There's no information to show.
|
||||
if (frame_data.show_existing_frame) return;
|
||||
|
||||
(void)data;
|
||||
// We allocate enough space and hope we don't write out of bounds. Totally
|
||||
// unsafe but this speeds things up, especially when compiled to Javascript.
|
||||
|
|
@ -523,6 +627,14 @@ void inspect(void *pbi, void *data) {
|
|||
buf += put_block_info(buf, uv_prediction_mode_map, "uv_mode",
|
||||
offsetof(insp_mi_data, uv_mode), 0);
|
||||
}
|
||||
if (layers & MOTION_MODE_LAYER) {
|
||||
buf += put_block_info(buf, motion_mode_map, "motion_mode",
|
||||
offsetof(insp_mi_data, motion_mode), 0);
|
||||
}
|
||||
if (layers & COMPOUND_TYPE_LAYER) {
|
||||
buf += put_block_info(buf, compound_type_map, "compound_type",
|
||||
offsetof(insp_mi_data, compound_type), 0);
|
||||
}
|
||||
if (layers & SKIP_LAYER) {
|
||||
buf +=
|
||||
put_block_info(buf, skip_map, "skip", offsetof(insp_mi_data, skip), 0);
|
||||
|
|
@ -554,6 +666,7 @@ void inspect(void *pbi, void *data) {
|
|||
if (layers & MOTION_VECTORS_LAYER) {
|
||||
buf += put_motion_vectors(buf);
|
||||
}
|
||||
if (combined_parm_count > 0) buf += put_combined(buf);
|
||||
if (layers & REFERENCE_FRAME_LAYER) {
|
||||
buf += put_block_info(buf, refs_map, "referenceFrame",
|
||||
offsetof(insp_mi_data, ref_frame), 2);
|
||||
|
|
@ -563,7 +676,8 @@ void inspect(void *pbi, void *data) {
|
|||
buf += put_accounting(buf);
|
||||
}
|
||||
#endif
|
||||
buf += snprintf(buf, MAX_BUFFER, " \"frame\": %d,\n", decoded_frame_count);
|
||||
buf +=
|
||||
snprintf(buf, MAX_BUFFER, " \"frame\": %d,\n", frame_data.frame_number);
|
||||
buf += snprintf(buf, MAX_BUFFER, " \"showFrame\": %d,\n",
|
||||
frame_data.show_frame);
|
||||
buf += snprintf(buf, MAX_BUFFER, " \"frameType\": %d,\n",
|
||||
|
|
@ -618,21 +732,51 @@ int open_file(char *file) {
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Av1DecodeReturn adr;
|
||||
int have_frame = 0;
|
||||
const unsigned char *frame;
|
||||
const unsigned char *end_frame;
|
||||
size_t frame_size = 0;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int read_frame() {
|
||||
if (!aom_video_reader_read_frame(reader)) return EXIT_FAILURE;
|
||||
img = NULL;
|
||||
aom_codec_iter_t iter = NULL;
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame = aom_video_reader_get_frame(reader, &frame_size);
|
||||
if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL) !=
|
||||
AOM_CODEC_OK) {
|
||||
die_codec(&codec, "Failed to decode frame.");
|
||||
}
|
||||
|
||||
// This loop skips over any frames that are show_existing_frames, as
|
||||
// there is nothing to analyze.
|
||||
do {
|
||||
if (!have_frame) {
|
||||
if (!aom_video_reader_read_frame(reader)) return EXIT_FAILURE;
|
||||
frame = aom_video_reader_get_frame(reader, &frame_size);
|
||||
|
||||
have_frame = 1;
|
||||
end_frame = frame + frame_size;
|
||||
}
|
||||
|
||||
if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, &adr) !=
|
||||
AOM_CODEC_OK) {
|
||||
die_codec(&codec, "Failed to decode frame.");
|
||||
}
|
||||
|
||||
frame = adr.buf;
|
||||
if (frame == end_frame) have_frame = 0;
|
||||
} while (adr.show_existing);
|
||||
|
||||
int got_any_frames = 0;
|
||||
aom_image_t *frame_img;
|
||||
while ((frame_img = aom_codec_get_frame(&codec, &iter))) {
|
||||
img = frame_img;
|
||||
struct av1_ref_frame ref_dec;
|
||||
ref_dec.idx = adr.idx;
|
||||
|
||||
// ref_dec.idx is the index to the reference buffer idx to AV1_GET_REFERENCE
|
||||
// if its -1 the decoder didn't update any reference buffer and the only
|
||||
// way to see the frame is aom_codec_get_frame.
|
||||
if (ref_dec.idx == -1) {
|
||||
aom_codec_iter_t iter = NULL;
|
||||
img = frame_img = aom_codec_get_frame(&codec, &iter);
|
||||
++frame_count;
|
||||
got_any_frames = 1;
|
||||
} else if (!aom_codec_control(&codec, AV1_GET_REFERENCE, &ref_dec)) {
|
||||
img = frame_img = &ref_dec.img;
|
||||
++frame_count;
|
||||
got_any_frames = 1;
|
||||
}
|
||||
|
|
@ -692,6 +836,10 @@ static void parse_args(char **argv) {
|
|||
layers |= MODE_LAYER;
|
||||
else if (arg_match(&arg, &dump_uv_mode_arg, argi))
|
||||
layers |= UV_MODE_LAYER;
|
||||
else if (arg_match(&arg, &dump_motion_mode_arg, argi))
|
||||
layers |= MOTION_MODE_LAYER;
|
||||
else if (arg_match(&arg, &dump_compound_type_arg, argi))
|
||||
layers |= COMPOUND_TYPE_LAYER;
|
||||
else if (arg_match(&arg, &dump_skip_arg, argi))
|
||||
layers |= SKIP_LAYER;
|
||||
else if (arg_match(&arg, &dump_filter_arg, argi))
|
||||
|
|
@ -718,6 +866,13 @@ static void parse_args(char **argv) {
|
|||
usage_exit();
|
||||
else if (arg_match(&arg, &limit_arg, argi))
|
||||
stop_after = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &skip_non_transform_arg, argi))
|
||||
skip_non_transform = arg_parse_uint(&arg);
|
||||
else if (arg_match(&arg, &combined_arg, argi))
|
||||
convert_to_indices(
|
||||
(char *)arg.val, combined_parm_list,
|
||||
sizeof(combined_parm_list) / sizeof(combined_parm_list[0]),
|
||||
&combined_parm_count);
|
||||
else
|
||||
argj++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,28 @@
|
|||
// ============================
|
||||
//
|
||||
// This is a lightfield bitstream parsing example. It takes an input file
|
||||
// containing the whole compressed lightfield bitstream(ivf file), and parses it
|
||||
// and constructs and outputs a new bitstream that can be decoded by an AV1
|
||||
// decoder. The output bitstream contains reference frames(i.e. anchor frames),
|
||||
// camera frame header, and tile list OBUs. num_references is the number of
|
||||
// anchor frames coded at the beginning of the light field file.
|
||||
// After running the lightfield encoder, run lightfield bitstream parsing:
|
||||
// containing the whole compressed lightfield bitstream(ivf file) and a text
|
||||
// file containing a stream of tiles to decode and then constructs and outputs
|
||||
// a new bitstream that can be decoded by an AV1 decoder. The output bitstream
|
||||
// contains reference frames(i.e. anchor frames), camera frame header, and
|
||||
// tile list OBUs. num_references is the number of anchor frames coded at the
|
||||
// beginning of the light field file. After running the lightfield encoder,
|
||||
// run lightfield bitstream parsing:
|
||||
// examples/lightfield_bitstream_parsing vase10x10.ivf vase_tile_list.ivf 4
|
||||
// tile_list.txt
|
||||
//
|
||||
// The tile_list.txt is expected to be of the form:
|
||||
// Frame <frame_index0>
|
||||
// <image_index0> <anchor_index0> <tile_col0> <tile_row0>
|
||||
// <image_index1> <anchor_index1> <tile_col1> <tile_row1>
|
||||
// ...
|
||||
// Frame <frame_index1)
|
||||
// ...
|
||||
//
|
||||
// The "Frame" markers indicate a new render frame and thus a new tile list
|
||||
// will be started and the old one flushed. The image_indexN, anchor_indexN,
|
||||
// tile_colN, and tile_rowN identify an individual tile to be decoded and
|
||||
// to use anchor_indexN anchor image for MCP.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -39,7 +54,7 @@
|
|||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <infile> <outfile> <num_references> \n",
|
||||
fprintf(stderr, "Usage: %s <infile> <outfile> <num_references> <tile_list>\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -47,9 +62,8 @@ void usage_exit(void) {
|
|||
#define ALIGN_POWER_OF_TWO(value, n) \
|
||||
(((value) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1))
|
||||
|
||||
// SB size: 64x64
|
||||
const uint8_t output_frame_width_in_tiles_minus_1 = 512 / 64 - 1;
|
||||
const uint8_t output_frame_height_in_tiles_minus_1 = 512 / 64 - 1;
|
||||
const int output_frame_width = 512;
|
||||
const int output_frame_height = 512;
|
||||
|
||||
// Spec:
|
||||
// typedef struct {
|
||||
|
|
@ -68,32 +82,6 @@ typedef struct {
|
|||
int tile_row;
|
||||
} TILE_LIST_INFO;
|
||||
|
||||
// M references: 0 - M-1; N images(including references): 0 - N-1;
|
||||
// Note: order the image index incrementally, so that we only go through the
|
||||
// bitstream once to construct the tile list.
|
||||
const int num_tile_lists = 2;
|
||||
const uint16_t tile_count_minus_1 = 9 - 1;
|
||||
const TILE_LIST_INFO tile_list[2][9] = {
|
||||
{ { 16, 0, 4, 5 },
|
||||
{ 83, 3, 13, 2 },
|
||||
{ 57, 2, 2, 6 },
|
||||
{ 31, 1, 11, 5 },
|
||||
{ 2, 0, 7, 4 },
|
||||
{ 77, 3, 9, 9 },
|
||||
{ 49, 1, 0, 1 },
|
||||
{ 6, 0, 3, 10 },
|
||||
{ 63, 2, 5, 8 } },
|
||||
{ { 65, 2, 11, 1 },
|
||||
{ 42, 1, 3, 7 },
|
||||
{ 88, 3, 8, 4 },
|
||||
{ 76, 3, 1, 15 },
|
||||
{ 1, 0, 2, 2 },
|
||||
{ 19, 0, 5, 6 },
|
||||
{ 60, 2, 4, 0 },
|
||||
{ 25, 1, 11, 15 },
|
||||
{ 50, 2, 5, 4 } },
|
||||
};
|
||||
|
||||
static int get_image_bps(aom_img_fmt_t fmt) {
|
||||
switch (fmt) {
|
||||
case AOM_IMG_FMT_I420: return 12;
|
||||
|
|
@ -107,6 +95,102 @@ static int get_image_bps(aom_img_fmt_t fmt) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void process_tile_list(const TILE_LIST_INFO *tiles, int num_tiles,
|
||||
aom_codec_pts_t tl_pts, unsigned char **frames,
|
||||
const size_t *frame_sizes, aom_codec_ctx_t *codec,
|
||||
unsigned char *tl_buf, AvxVideoWriter *writer,
|
||||
uint8_t output_frame_width_in_tiles_minus_1,
|
||||
uint8_t output_frame_height_in_tiles_minus_1) {
|
||||
unsigned char *tl = tl_buf;
|
||||
struct aom_write_bit_buffer wb = { tl, 0 };
|
||||
unsigned char *saved_obu_size_loc = NULL;
|
||||
uint32_t tile_list_obu_header_size = 0;
|
||||
uint32_t tile_list_obu_size = 0;
|
||||
int num_tiles_minus_1 = num_tiles - 1;
|
||||
int i;
|
||||
|
||||
// Write the tile list OBU header that is 1 byte long.
|
||||
aom_wb_write_literal(&wb, 0, 1); // forbidden bit.
|
||||
aom_wb_write_literal(&wb, 8, 4); // tile list OBU: "1000"
|
||||
aom_wb_write_literal(&wb, 0, 1); // obu_extension = 0
|
||||
aom_wb_write_literal(&wb, 1, 1); // obu_has_size_field
|
||||
aom_wb_write_literal(&wb, 0, 1); // reserved
|
||||
tl++;
|
||||
tile_list_obu_header_size++;
|
||||
|
||||
// Write the OBU size using a fixed length_field_size of 4 bytes.
|
||||
saved_obu_size_loc = tl;
|
||||
// aom_wb_write_unsigned_literal(&wb, data, bits) requires that bits <= 32.
|
||||
aom_wb_write_unsigned_literal(&wb, 0, 32);
|
||||
tl += 4;
|
||||
tile_list_obu_header_size += 4;
|
||||
|
||||
// write_tile_list_obu()
|
||||
aom_wb_write_literal(&wb, output_frame_width_in_tiles_minus_1, 8);
|
||||
aom_wb_write_literal(&wb, output_frame_height_in_tiles_minus_1, 8);
|
||||
aom_wb_write_literal(&wb, num_tiles_minus_1, 16);
|
||||
tl += 4;
|
||||
tile_list_obu_size += 4;
|
||||
|
||||
// Write each tile's data
|
||||
for (i = 0; i <= num_tiles_minus_1; i++) {
|
||||
aom_tile_data tile_data = { 0, NULL, 0 };
|
||||
|
||||
int image_idx = tiles[i].image_idx;
|
||||
int ref_idx = tiles[i].reference_idx;
|
||||
int tc = tiles[i].tile_col;
|
||||
int tr = tiles[i].tile_row;
|
||||
|
||||
// Reset bit writer to the right location.
|
||||
wb.bit_buffer = tl;
|
||||
wb.bit_offset = 0;
|
||||
|
||||
size_t frame_size = frame_sizes[image_idx];
|
||||
const unsigned char *frame = frames[image_idx];
|
||||
|
||||
aom_codec_control_(codec, AV1_SET_DECODE_TILE_ROW, tr);
|
||||
aom_codec_control_(codec, AV1_SET_DECODE_TILE_COL, tc);
|
||||
|
||||
aom_codec_err_t aom_status =
|
||||
aom_codec_decode(codec, frame, frame_size, NULL);
|
||||
if (aom_status) die_codec(codec, "Failed to decode tile.");
|
||||
|
||||
aom_codec_control_(codec, AV1D_GET_TILE_DATA, &tile_data);
|
||||
|
||||
// Copy over tile info.
|
||||
// uint8_t anchor_frame_idx;
|
||||
// uint8_t tile_row;
|
||||
// uint8_t tile_col;
|
||||
// uint16_t coded_tile_data_size_minus_1;
|
||||
// uint8_t *coded_tile_data;
|
||||
uint32_t tile_info_bytes = 5;
|
||||
aom_wb_write_literal(&wb, ref_idx, 8);
|
||||
aom_wb_write_literal(&wb, tr, 8);
|
||||
aom_wb_write_literal(&wb, tc, 8);
|
||||
aom_wb_write_literal(&wb, (int)tile_data.coded_tile_data_size - 1, 16);
|
||||
tl += tile_info_bytes;
|
||||
|
||||
memcpy(tl, (uint8_t *)tile_data.coded_tile_data,
|
||||
tile_data.coded_tile_data_size);
|
||||
tl += tile_data.coded_tile_data_size;
|
||||
|
||||
tile_list_obu_size +=
|
||||
tile_info_bytes + (uint32_t)tile_data.coded_tile_data_size;
|
||||
}
|
||||
|
||||
// Write tile list OBU size.
|
||||
size_t bytes_written = 0;
|
||||
if (aom_uleb_encode_fixed_size(tile_list_obu_size, 4, 4, saved_obu_size_loc,
|
||||
&bytes_written))
|
||||
die_codec(codec, "Failed to encode the tile list obu size.");
|
||||
|
||||
// Copy the tile list.
|
||||
if (!aom_video_writer_write_frame(
|
||||
writer, tl_buf, tile_list_obu_header_size + tile_list_obu_size,
|
||||
tl_pts))
|
||||
die_codec(codec, "Failed to copy compressed tile list.");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
aom_codec_ctx_t codec;
|
||||
AvxVideoReader *reader = NULL;
|
||||
|
|
@ -114,11 +198,12 @@ int main(int argc, char **argv) {
|
|||
const AvxInterface *decoder = NULL;
|
||||
const AvxVideoInfo *info = NULL;
|
||||
int num_references;
|
||||
int n, i;
|
||||
int i;
|
||||
aom_codec_pts_t pts;
|
||||
const char *tile_list_file = NULL;
|
||||
|
||||
exec_name = argv[0];
|
||||
if (argc != 4) die("Invalid number of arguments.");
|
||||
if (argc != 5) die("Invalid number of arguments.");
|
||||
|
||||
reader = aom_video_reader_open(argv[1]);
|
||||
if (!reader) die("Failed to open %s for reading.", argv[1]);
|
||||
|
|
@ -126,11 +211,15 @@ int main(int argc, char **argv) {
|
|||
num_references = (int)strtol(argv[3], NULL, 0);
|
||||
info = aom_video_reader_get_info(reader);
|
||||
|
||||
aom_video_reader_set_fourcc(reader, AV1_FOURCC);
|
||||
|
||||
// The writer to write out ivf file in tile list OBU, which can be decoded by
|
||||
// AV1 decoder.
|
||||
writer = aom_video_writer_open(argv[2], kContainerIVF, info);
|
||||
if (!writer) die("Failed to open %s for writing", argv[2]);
|
||||
|
||||
tile_list_file = argv[4];
|
||||
|
||||
decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface()));
|
||||
|
|
@ -141,6 +230,7 @@ int main(int argc, char **argv) {
|
|||
// Decode anchor frames.
|
||||
aom_codec_control_(&codec, AV1_SET_TILE_MODE, 0);
|
||||
|
||||
printf("Reading %d reference images.\n", num_references);
|
||||
for (i = 0; i < num_references; ++i) {
|
||||
aom_video_reader_read_frame(reader);
|
||||
|
||||
|
|
@ -165,16 +255,38 @@ int main(int argc, char **argv) {
|
|||
// Record the offset of the first camera image.
|
||||
const FileOffset camera_frame_pos = ftello(infile);
|
||||
|
||||
// Read out the first camera frame.
|
||||
aom_video_reader_read_frame(reader);
|
||||
printf("Loading compressed frames into memory.\n");
|
||||
|
||||
// Count the frames in the lightfield.
|
||||
int num_frames = 0;
|
||||
while (aom_video_reader_read_frame(reader)) {
|
||||
++num_frames;
|
||||
}
|
||||
if (num_frames < 1) die("Input light field has no frames.");
|
||||
|
||||
// Read all of the lightfield frames into memory.
|
||||
unsigned char **frames =
|
||||
(unsigned char **)malloc(num_frames * sizeof(unsigned char *));
|
||||
size_t *frame_sizes = (size_t *)malloc(num_frames * sizeof(size_t));
|
||||
// Seek to the first camera image.
|
||||
fseeko(infile, camera_frame_pos, SEEK_SET);
|
||||
for (int f = 0; f < num_frames; ++f) {
|
||||
aom_video_reader_read_frame(reader);
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame =
|
||||
aom_video_reader_get_frame(reader, &frame_size);
|
||||
frames[f] = (unsigned char *)malloc(frame_size * sizeof(unsigned char));
|
||||
memcpy(frames[f], frame, frame_size);
|
||||
frame_sizes[f] = frame_size;
|
||||
}
|
||||
printf("Read %d frames.\n", num_frames);
|
||||
|
||||
// Copy first camera frame for getting camera frame header. This is done
|
||||
// only once.
|
||||
{
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame =
|
||||
aom_video_reader_get_frame(reader, &frame_size);
|
||||
pts = (aom_codec_pts_t)aom_video_reader_get_frame_pts(reader);
|
||||
size_t frame_size = frame_sizes[0];
|
||||
const unsigned char *frame = frames[0];
|
||||
pts = num_references;
|
||||
aom_tile_data frame_header_info = { 0, NULL, 0 };
|
||||
|
||||
// Need to decode frame header to get camera frame header info. So, here
|
||||
|
|
@ -231,115 +343,68 @@ int main(int argc, char **argv) {
|
|||
// Allocate a buffer to store tile list bitstream.
|
||||
const size_t data_sz = MAX_TILES * ALIGN_POWER_OF_TWO(tile_width, 5) *
|
||||
ALIGN_POWER_OF_TWO(tile_height, 5) * bps / 8;
|
||||
|
||||
unsigned char *tl_buf = (unsigned char *)malloc(data_sz);
|
||||
if (tl_buf == NULL) die_codec(&codec, "Failed to allocate tile list buffer.");
|
||||
|
||||
aom_codec_pts_t tl_pts = pts;
|
||||
aom_codec_pts_t tl_pts = num_references;
|
||||
const uint8_t output_frame_width_in_tiles_minus_1 =
|
||||
output_frame_width / tile_width - 1;
|
||||
const uint8_t output_frame_height_in_tiles_minus_1 =
|
||||
output_frame_height / tile_height - 1;
|
||||
|
||||
// Process 1 tile list.
|
||||
for (n = 0; n < num_tile_lists; n++) {
|
||||
unsigned char *tl = tl_buf;
|
||||
struct aom_write_bit_buffer wb = { tl, 0 };
|
||||
unsigned char *saved_obu_size_loc = NULL;
|
||||
uint32_t tile_list_obu_header_size = 0;
|
||||
uint32_t tile_list_obu_size = 0;
|
||||
|
||||
// Write the tile list OBU header that is 1 byte long.
|
||||
aom_wb_write_literal(&wb, 0, 1); // forbidden bit.
|
||||
aom_wb_write_literal(&wb, 8, 4); // tile list OBU: "1000"
|
||||
aom_wb_write_literal(&wb, 0, 1); // obu_extension = 0
|
||||
aom_wb_write_literal(&wb, 1, 1); // obu_has_size_field
|
||||
aom_wb_write_literal(&wb, 0, 1); // reserved
|
||||
tl++;
|
||||
tile_list_obu_header_size++;
|
||||
|
||||
// Write the OBU size using a fixed length_field_size of 4 bytes.
|
||||
saved_obu_size_loc = tl;
|
||||
// aom_wb_write_unsigned_literal(&wb, data, bits) requires that bits <= 32.
|
||||
aom_wb_write_unsigned_literal(&wb, 0, 32);
|
||||
tl += 4;
|
||||
tile_list_obu_header_size += 4;
|
||||
|
||||
// write_tile_list_obu()
|
||||
aom_wb_write_literal(&wb, output_frame_width_in_tiles_minus_1, 8);
|
||||
aom_wb_write_literal(&wb, output_frame_height_in_tiles_minus_1, 8);
|
||||
aom_wb_write_literal(&wb, tile_count_minus_1, 16);
|
||||
tl += 4;
|
||||
tile_list_obu_size += 4;
|
||||
|
||||
// Write each tile's data
|
||||
for (i = 0; i <= tile_count_minus_1; i++) {
|
||||
aom_tile_data tile_data = { 0, NULL, 0 };
|
||||
|
||||
int image_idx = tile_list[n][i].image_idx;
|
||||
int ref_idx = tile_list[n][i].reference_idx;
|
||||
int tc = tile_list[n][i].tile_col;
|
||||
int tr = tile_list[n][i].tile_row;
|
||||
int frame_cnt = -1;
|
||||
|
||||
// Reset bit writer to the right location.
|
||||
wb.bit_buffer = tl;
|
||||
wb.bit_offset = 0;
|
||||
|
||||
// Seek to the first camera image.
|
||||
fseeko(infile, camera_frame_pos, SEEK_SET);
|
||||
|
||||
// Read out the camera image
|
||||
while (frame_cnt != image_idx) {
|
||||
aom_video_reader_read_frame(reader);
|
||||
frame_cnt++;
|
||||
printf("Reading tile list from file.\n");
|
||||
char line[1024];
|
||||
FILE *tile_list_fptr = fopen(tile_list_file, "r");
|
||||
if (!tile_list_fptr) die_codec(&codec, "Failed to open tile list file.");
|
||||
int num_tiles = 0;
|
||||
TILE_LIST_INFO tiles[MAX_TILES];
|
||||
while ((fgets(line, 1024, tile_list_fptr)) != NULL) {
|
||||
if (line[0] == 'F' || num_tiles >= MAX_TILES) {
|
||||
// Flush existing tile list and start another, either because we hit a
|
||||
// new render frame or because we've hit our max number of tiles per list.
|
||||
if (num_tiles > 0) {
|
||||
process_tile_list(tiles, num_tiles, tl_pts, frames, frame_sizes, &codec,
|
||||
tl_buf, writer, output_frame_width_in_tiles_minus_1,
|
||||
output_frame_height_in_tiles_minus_1);
|
||||
++tl_pts;
|
||||
}
|
||||
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame =
|
||||
aom_video_reader_get_frame(reader, &frame_size);
|
||||
|
||||
aom_codec_control_(&codec, AV1_SET_DECODE_TILE_ROW, tr);
|
||||
aom_codec_control_(&codec, AV1_SET_DECODE_TILE_COL, tc);
|
||||
|
||||
aom_codec_err_t aom_status =
|
||||
aom_codec_decode(&codec, frame, frame_size, NULL);
|
||||
if (aom_status) die_codec(&codec, "Failed to decode tile.");
|
||||
|
||||
aom_codec_control_(&codec, AV1D_GET_TILE_DATA, &tile_data);
|
||||
|
||||
// Copy over tile info.
|
||||
// uint8_t anchor_frame_idx;
|
||||
// uint8_t tile_row;
|
||||
// uint8_t tile_col;
|
||||
// uint16_t coded_tile_data_size_minus_1;
|
||||
// uint8_t *coded_tile_data;
|
||||
uint32_t tile_info_bytes = 5;
|
||||
aom_wb_write_literal(&wb, ref_idx, 8);
|
||||
aom_wb_write_literal(&wb, tr, 8);
|
||||
aom_wb_write_literal(&wb, tc, 8);
|
||||
aom_wb_write_literal(&wb, (int)tile_data.coded_tile_data_size - 1, 16);
|
||||
tl += tile_info_bytes;
|
||||
|
||||
memcpy(tl, (uint8_t *)tile_data.coded_tile_data,
|
||||
tile_data.coded_tile_data_size);
|
||||
tl += tile_data.coded_tile_data_size;
|
||||
|
||||
tile_list_obu_size +=
|
||||
tile_info_bytes + (uint32_t)tile_data.coded_tile_data_size;
|
||||
num_tiles = 0;
|
||||
}
|
||||
|
||||
// Write tile list OBU size.
|
||||
size_t bytes_written = 0;
|
||||
if (aom_uleb_encode_fixed_size(tile_list_obu_size, 4, 4, saved_obu_size_loc,
|
||||
&bytes_written))
|
||||
die_codec(&codec, "Failed to encode the tile list obu size.");
|
||||
|
||||
// Copy the tile list.
|
||||
if (!aom_video_writer_write_frame(
|
||||
writer, tl_buf, tile_list_obu_header_size + tile_list_obu_size,
|
||||
tl_pts))
|
||||
die_codec(&codec, "Failed to copy compressed tile list.");
|
||||
|
||||
tl_pts++;
|
||||
if (line[0] == 'F') {
|
||||
continue;
|
||||
}
|
||||
if (sscanf(line, "%d %d %d %d", &tiles[num_tiles].image_idx,
|
||||
&tiles[num_tiles].reference_idx, &tiles[num_tiles].tile_col,
|
||||
&tiles[num_tiles].tile_row) == 4) {
|
||||
if (tiles[num_tiles].image_idx >= num_frames) {
|
||||
die("Tile list image_idx out of bounds: %d >= %d.",
|
||||
tiles[num_tiles].image_idx, num_frames);
|
||||
}
|
||||
if (tiles[num_tiles].reference_idx >= num_references) {
|
||||
die("Tile list reference_idx out of bounds: %d >= %d.",
|
||||
tiles[num_tiles].reference_idx, num_references);
|
||||
}
|
||||
++num_tiles;
|
||||
}
|
||||
}
|
||||
if (num_tiles > 0) {
|
||||
// Flush out the last tile list.
|
||||
process_tile_list(tiles, num_tiles, tl_pts, frames, frame_sizes, &codec,
|
||||
tl_buf, writer, output_frame_width_in_tiles_minus_1,
|
||||
output_frame_height_in_tiles_minus_1);
|
||||
++tl_pts;
|
||||
}
|
||||
|
||||
const int num_tile_lists = (int)(tl_pts - pts);
|
||||
printf("Finished processing tile lists. Num tile lists: %d.\n",
|
||||
num_tile_lists);
|
||||
free(tl_buf);
|
||||
for (int f = 0; f < num_frames; ++f) {
|
||||
free(frames[f]);
|
||||
}
|
||||
free(frame_sizes);
|
||||
free(frames);
|
||||
if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
|
||||
aom_video_writer_close(writer);
|
||||
aom_video_reader_close(reader);
|
||||
|
|
|
|||
305
third_party/aom/examples/lightfield_decoder.c
vendored
305
third_party/aom/examples/lightfield_decoder.c
vendored
|
|
@ -14,10 +14,26 @@
|
|||
//
|
||||
// This is an example of a simple lightfield decoder. It builds upon the
|
||||
// simple_decoder.c example. It takes an input file containing the compressed
|
||||
// data (in ivf format), treating it as a lightfield instead of a video.
|
||||
// data (in ivf format), treating it as a lightfield instead of a video; and a
|
||||
// text file with a list of tiles to decode. There is an optional parameter
|
||||
// allowing to choose the output format, and the supported formats are
|
||||
// YUV1D(default), YUV, and NV12.
|
||||
// After running the lightfield encoder, run lightfield decoder to decode a
|
||||
// batch of tiles:
|
||||
// examples/lightfield_decoder vase10x10.ivf vase_reference.yuv 4
|
||||
// examples/lightfield_decoder vase10x10.ivf vase_reference.yuv 4 tile_list.txt
|
||||
// 0(optional)
|
||||
// The tile_list.txt is expected to be of the form:
|
||||
// Frame <frame_index0>
|
||||
// <image_index0> <anchor_index0> <tile_col0> <tile_row0>
|
||||
// <image_index1> <anchor_index1> <tile_col1> <tile_row1>
|
||||
// ...
|
||||
// Frame <frame_index1)
|
||||
// ...
|
||||
//
|
||||
// The "Frame" markers indicate a new render frame and thus a new tile list
|
||||
// will be started and the old one flushed. The image_indexN, anchor_indexN,
|
||||
// tile_colN, and tile_rowN identify an individual tile to be decoded and
|
||||
// to use anchor_indexN anchor image for MCP.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -33,43 +49,109 @@
|
|||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr, "Usage: %s <infile> <outfile> <num_references>\n", exec_name);
|
||||
fprintf(stderr,
|
||||
"Usage: %s <infile> <outfile> <num_references> <tile_list> <output "
|
||||
"format(optional)>\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Tile list entry provided by the application
|
||||
typedef struct {
|
||||
int image_idx;
|
||||
int reference_idx;
|
||||
int tile_col;
|
||||
int tile_row;
|
||||
} TILE_LIST_INFO;
|
||||
// Output frame size
|
||||
const int output_frame_width = 512;
|
||||
const int output_frame_height = 512;
|
||||
|
||||
// M references: 0 - M-1; N images(including references): 0 - N-1;
|
||||
// Note: order the image index incrementally, so that we only go through the
|
||||
// bitstream once to construct the tile list.
|
||||
const int num_tile_lists = 2;
|
||||
const uint16_t tile_count_minus_1 = 9 - 1;
|
||||
const TILE_LIST_INFO tile_list[2][9] = {
|
||||
{ { 16, 0, 4, 5 },
|
||||
{ 83, 3, 13, 2 },
|
||||
{ 57, 2, 2, 6 },
|
||||
{ 31, 1, 11, 5 },
|
||||
{ 2, 0, 7, 4 },
|
||||
{ 77, 3, 9, 9 },
|
||||
{ 49, 1, 0, 1 },
|
||||
{ 6, 0, 3, 10 },
|
||||
{ 63, 2, 5, 8 } },
|
||||
{ { 65, 2, 11, 1 },
|
||||
{ 42, 1, 3, 7 },
|
||||
{ 88, 3, 8, 4 },
|
||||
{ 76, 3, 1, 15 },
|
||||
{ 1, 0, 2, 2 },
|
||||
{ 19, 0, 5, 6 },
|
||||
{ 60, 2, 4, 0 },
|
||||
{ 25, 1, 11, 15 },
|
||||
{ 50, 2, 5, 4 } },
|
||||
};
|
||||
static void aom_img_copy_tile(const aom_image_t *src, const aom_image_t *dst,
|
||||
int dst_row_offset, int dst_col_offset) {
|
||||
const int shift = (src->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 1 : 0;
|
||||
int plane;
|
||||
|
||||
for (plane = 0; plane < 3; ++plane) {
|
||||
const unsigned char *src_buf = src->planes[plane];
|
||||
const int src_stride = src->stride[plane];
|
||||
unsigned char *dst_buf = dst->planes[plane];
|
||||
const int dst_stride = dst->stride[plane];
|
||||
const int roffset =
|
||||
(plane > 0) ? dst_row_offset >> dst->y_chroma_shift : dst_row_offset;
|
||||
const int coffset =
|
||||
(plane > 0) ? dst_col_offset >> dst->x_chroma_shift : dst_col_offset;
|
||||
|
||||
// col offset needs to be adjusted for HBD.
|
||||
dst_buf += roffset * dst_stride + (coffset << shift);
|
||||
|
||||
const int w = (aom_img_plane_width(src, plane) << shift);
|
||||
const int h = aom_img_plane_height(src, plane);
|
||||
int y;
|
||||
|
||||
for (y = 0; y < h; ++y) {
|
||||
memcpy(dst_buf, src_buf, w);
|
||||
src_buf += src_stride;
|
||||
dst_buf += dst_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void decode_tile(aom_codec_ctx_t *codec, const unsigned char *frame,
|
||||
size_t frame_size, int tr, int tc, int ref_idx,
|
||||
aom_image_t *reference_images, aom_image_t *output,
|
||||
int *tile_idx, unsigned int *output_bit_depth,
|
||||
aom_image_t **img_ptr, int output_format) {
|
||||
aom_codec_control_(codec, AV1_SET_TILE_MODE, 1);
|
||||
aom_codec_control_(codec, AV1D_EXT_TILE_DEBUG, 1);
|
||||
aom_codec_control_(codec, AV1_SET_DECODE_TILE_ROW, tr);
|
||||
aom_codec_control_(codec, AV1_SET_DECODE_TILE_COL, tc);
|
||||
|
||||
av1_ref_frame_t ref;
|
||||
ref.idx = 0;
|
||||
ref.use_external_ref = 1;
|
||||
ref.img = reference_images[ref_idx];
|
||||
if (aom_codec_control(codec, AV1_SET_REFERENCE, &ref)) {
|
||||
die_codec(codec, "Failed to set reference frame.");
|
||||
}
|
||||
|
||||
aom_codec_err_t aom_status = aom_codec_decode(codec, frame, frame_size, NULL);
|
||||
if (aom_status) die_codec(codec, "Failed to decode tile.");
|
||||
|
||||
aom_codec_iter_t iter = NULL;
|
||||
aom_image_t *img = aom_codec_get_frame(codec, &iter);
|
||||
if (!img) die_codec(codec, "Failed to get frame.");
|
||||
*img_ptr = img;
|
||||
|
||||
// aom_img_alloc() sets bit_depth as follows:
|
||||
// output->bit_depth = (fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 16 : 8;
|
||||
// Use img->bit_depth(read from bitstream), so that aom_shift_img()
|
||||
// works as expected.
|
||||
output->bit_depth = img->bit_depth;
|
||||
*output_bit_depth = img->bit_depth;
|
||||
|
||||
if (output_format != YUV1D) {
|
||||
// read out the tile size.
|
||||
unsigned int tile_size = 0;
|
||||
if (aom_codec_control(codec, AV1D_GET_TILE_SIZE, &tile_size))
|
||||
die_codec(codec, "Failed to get the tile size");
|
||||
const unsigned int tile_width = tile_size >> 16;
|
||||
const unsigned int tile_height = tile_size & 65535;
|
||||
const uint8_t output_frame_width_in_tiles = output_frame_width / tile_width;
|
||||
|
||||
// Copy the tile to the output frame.
|
||||
const int row_offset =
|
||||
(*tile_idx / output_frame_width_in_tiles) * tile_height;
|
||||
const int col_offset =
|
||||
(*tile_idx % output_frame_width_in_tiles) * tile_width;
|
||||
|
||||
aom_img_copy_tile(img, output, row_offset, col_offset);
|
||||
(*tile_idx)++;
|
||||
}
|
||||
}
|
||||
|
||||
static void img_write_to_file(const aom_image_t *img, FILE *file,
|
||||
int output_format) {
|
||||
if (output_format == YUV)
|
||||
aom_img_write(img, file);
|
||||
else if (output_format == NV12)
|
||||
aom_img_write_nv12(img, file);
|
||||
else
|
||||
die("Invalid output format");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *outfile = NULL;
|
||||
|
|
@ -78,13 +160,18 @@ int main(int argc, char **argv) {
|
|||
const AvxInterface *decoder = NULL;
|
||||
const AvxVideoInfo *info = NULL;
|
||||
int num_references;
|
||||
aom_img_fmt_t ref_fmt = 0;
|
||||
aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
|
||||
aom_image_t output;
|
||||
aom_image_t *output_shifted = NULL;
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame = NULL;
|
||||
int n, i, j;
|
||||
int i, j;
|
||||
const char *tile_list_file = NULL;
|
||||
int output_format = YUV1D;
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 4) die("Invalid number of arguments.");
|
||||
if (argc < 5) die("Invalid number of arguments.");
|
||||
|
||||
reader = aom_video_reader_open(argv[1]);
|
||||
if (!reader) die("Failed to open %s for reading.", argv[1]);
|
||||
|
|
@ -93,11 +180,18 @@ int main(int argc, char **argv) {
|
|||
die("Failed to open %s for writing.", argv[2]);
|
||||
|
||||
num_references = (int)strtol(argv[3], NULL, 0);
|
||||
tile_list_file = argv[4];
|
||||
|
||||
if (argc > 5) output_format = (int)strtol(argv[5], NULL, 0);
|
||||
if (output_format < YUV1D || output_format > NV12)
|
||||
die("Output format out of range [0, 2]");
|
||||
|
||||
info = aom_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
|
||||
if (!decoder) die("Unknown input codec.");
|
||||
if (info->codec_fourcc == LST_FOURCC)
|
||||
decoder = get_aom_decoder_by_fourcc(AV1_FOURCC);
|
||||
else
|
||||
die("Unknown input codec.");
|
||||
printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface()));
|
||||
|
||||
if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
|
||||
|
|
@ -116,7 +210,6 @@ int main(int argc, char **argv) {
|
|||
die_codec(&codec, "Failed to decode frame.");
|
||||
|
||||
if (i == 0) {
|
||||
aom_img_fmt_t ref_fmt = 0;
|
||||
if (aom_codec_control(&codec, AV1D_GET_IMG_FORMAT, &ref_fmt))
|
||||
die_codec(&codec, "Failed to get the image format");
|
||||
|
||||
|
|
@ -127,7 +220,7 @@ int main(int argc, char **argv) {
|
|||
// Allocate memory to store decoded references. Allocate memory with the
|
||||
// border so that it can be used as a reference.
|
||||
for (j = 0; j < num_references; j++) {
|
||||
unsigned int border = AOM_BORDER_IN_PIXELS;
|
||||
unsigned int border = AOM_DEC_BORDER_IN_PIXELS;
|
||||
if (!aom_img_alloc_with_border(&reference_images[j], ref_fmt,
|
||||
frame_res[0], frame_res[1], 32, 8,
|
||||
border)) {
|
||||
|
|
@ -156,50 +249,110 @@ int main(int argc, char **argv) {
|
|||
// Record the offset of the first camera image.
|
||||
const FileOffset camera_frame_pos = ftello(infile);
|
||||
|
||||
// Process 1 tile.
|
||||
for (n = 0; n < num_tile_lists; n++) {
|
||||
for (i = 0; i <= tile_count_minus_1; i++) {
|
||||
int image_idx = tile_list[n][i].image_idx;
|
||||
int ref_idx = tile_list[n][i].reference_idx;
|
||||
int tc = tile_list[n][i].tile_col;
|
||||
int tr = tile_list[n][i].tile_row;
|
||||
int frame_cnt = -1;
|
||||
printf("Loading compressed frames into memory.\n");
|
||||
|
||||
// Seek to the first camera image.
|
||||
fseeko(infile, camera_frame_pos, SEEK_SET);
|
||||
// Count the frames in the lightfield.
|
||||
int num_frames = 0;
|
||||
while (aom_video_reader_read_frame(reader)) {
|
||||
++num_frames;
|
||||
}
|
||||
if (num_frames < 1) die("Input light field has no frames.");
|
||||
|
||||
// Read out the camera image
|
||||
while (frame_cnt != image_idx) {
|
||||
aom_video_reader_read_frame(reader);
|
||||
frame_cnt++;
|
||||
// Read all of the lightfield frames into memory.
|
||||
unsigned char **frames =
|
||||
(unsigned char **)malloc(num_frames * sizeof(unsigned char *));
|
||||
size_t *frame_sizes = (size_t *)malloc(num_frames * sizeof(size_t));
|
||||
// Seek to the first camera image.
|
||||
fseeko(infile, camera_frame_pos, SEEK_SET);
|
||||
for (int f = 0; f < num_frames; ++f) {
|
||||
aom_video_reader_read_frame(reader);
|
||||
frame = aom_video_reader_get_frame(reader, &frame_size);
|
||||
frames[f] = (unsigned char *)malloc(frame_size * sizeof(unsigned char));
|
||||
memcpy(frames[f], frame, frame_size);
|
||||
frame_sizes[f] = frame_size;
|
||||
}
|
||||
printf("Read %d frames.\n", num_frames);
|
||||
|
||||
if (output_format != YUV1D) {
|
||||
// Allocate the output frame.
|
||||
aom_img_fmt_t out_fmt = ref_fmt;
|
||||
if (!CONFIG_LOWBITDEPTH) out_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
|
||||
if (!aom_img_alloc(&output, out_fmt, output_frame_width,
|
||||
output_frame_height, 32))
|
||||
die("Failed to allocate output image.");
|
||||
}
|
||||
|
||||
printf("Decoding tile list from file.\n");
|
||||
char line[1024];
|
||||
FILE *tile_list_fptr = fopen(tile_list_file, "r");
|
||||
int tile_list_cnt = 0;
|
||||
int tile_list_writes = 0;
|
||||
int tile_idx = 0;
|
||||
aom_image_t *out = NULL;
|
||||
unsigned int output_bit_depth = 0;
|
||||
|
||||
while ((fgets(line, 1024, tile_list_fptr)) != NULL) {
|
||||
if (line[0] == 'F') {
|
||||
if (output_format != YUV1D) {
|
||||
// Write out the tile list.
|
||||
if (tile_list_cnt) {
|
||||
out = &output;
|
||||
if (output_bit_depth != 0)
|
||||
aom_shift_img(output_bit_depth, &out, &output_shifted);
|
||||
img_write_to_file(out, outfile, output_format);
|
||||
tile_list_writes++;
|
||||
}
|
||||
|
||||
tile_list_cnt++;
|
||||
tile_idx = 0;
|
||||
// Then memset the frame.
|
||||
memset(output.img_data, 0, output.sz);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
frame = aom_video_reader_get_frame(reader, &frame_size);
|
||||
int image_idx, ref_idx, tc, tr;
|
||||
sscanf(line, "%d %d %d %d", &image_idx, &ref_idx, &tc, &tr);
|
||||
if (image_idx >= num_frames) {
|
||||
die("Tile list image_idx out of bounds: %d >= %d.", image_idx,
|
||||
num_frames);
|
||||
}
|
||||
if (ref_idx >= num_references) {
|
||||
die("Tile list ref_idx out of bounds: %d >= %d.", ref_idx,
|
||||
num_references);
|
||||
}
|
||||
frame = frames[image_idx];
|
||||
frame_size = frame_sizes[image_idx];
|
||||
|
||||
aom_codec_control_(&codec, AV1_SET_TILE_MODE, 1);
|
||||
aom_codec_control_(&codec, AV1D_EXT_TILE_DEBUG, 1);
|
||||
aom_codec_control_(&codec, AV1_SET_DECODE_TILE_ROW, tr);
|
||||
aom_codec_control_(&codec, AV1_SET_DECODE_TILE_COL, tc);
|
||||
|
||||
av1_ref_frame_t ref;
|
||||
ref.idx = 0;
|
||||
ref.use_external_ref = 1;
|
||||
ref.img = reference_images[ref_idx];
|
||||
if (aom_codec_control(&codec, AV1_SET_REFERENCE, &ref)) {
|
||||
die_codec(&codec, "Failed to set reference frame.");
|
||||
}
|
||||
|
||||
aom_codec_err_t aom_status =
|
||||
aom_codec_decode(&codec, frame, frame_size, NULL);
|
||||
if (aom_status) die_codec(&codec, "Failed to decode tile.");
|
||||
|
||||
aom_codec_iter_t iter = NULL;
|
||||
aom_image_t *img = aom_codec_get_frame(&codec, &iter);
|
||||
aom_img_write(img, outfile);
|
||||
aom_image_t *img = NULL;
|
||||
decode_tile(&codec, frame, frame_size, tr, tc, ref_idx, reference_images,
|
||||
&output, &tile_idx, &output_bit_depth, &img, output_format);
|
||||
if (output_format == YUV1D) {
|
||||
out = img;
|
||||
if (output_bit_depth != 0)
|
||||
aom_shift_img(output_bit_depth, &out, &output_shifted);
|
||||
aom_img_write(out, outfile);
|
||||
}
|
||||
}
|
||||
|
||||
if (output_format != YUV1D) {
|
||||
// Write out the last tile list.
|
||||
if (tile_list_writes < tile_list_cnt) {
|
||||
out = &output;
|
||||
if (output_bit_depth != 0)
|
||||
aom_shift_img(output_bit_depth, &out, &output_shifted);
|
||||
img_write_to_file(out, outfile, output_format);
|
||||
}
|
||||
}
|
||||
|
||||
if (output_shifted) aom_img_free(output_shifted);
|
||||
if (output_format != YUV1D) aom_img_free(&output);
|
||||
for (i = 0; i < num_references; i++) aom_img_free(&reference_images[i]);
|
||||
for (int f = 0; f < num_frames; ++f) {
|
||||
free(frames[f]);
|
||||
}
|
||||
free(frame_sizes);
|
||||
free(frames);
|
||||
if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
|
||||
aom_video_reader_close(reader);
|
||||
fclose(outfile);
|
||||
|
|
|
|||
10
third_party/aom/examples/lightfield_encoder.c
vendored
10
third_party/aom/examples/lightfield_encoder.c
vendored
|
|
@ -275,9 +275,13 @@ static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
|
|||
aom_img_fmt_t ref_fmt = AOM_IMG_FMT_I420;
|
||||
if (!CONFIG_LOWBITDEPTH) ref_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
|
||||
// Allocate memory with the border so that it can be used as a reference.
|
||||
int border_in_pixels =
|
||||
(codec.config.enc->rc_resize_mode || codec.config.enc->rc_superres_mode)
|
||||
? AOM_BORDER_IN_PIXELS
|
||||
: AOM_ENC_NO_SCALE_BORDER;
|
||||
for (i = 0; i < reference_image_num; i++) {
|
||||
if (!aom_img_alloc_with_border(&reference_images[i], ref_fmt, cfg->g_w,
|
||||
cfg->g_h, 32, 8, AOM_BORDER_IN_PIXELS)) {
|
||||
cfg->g_h, 32, 8, border_in_pixels)) {
|
||||
die("Failed to allocate image.");
|
||||
}
|
||||
}
|
||||
|
|
@ -393,6 +397,10 @@ static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
|
|||
for (i = 0; i < reference_image_num; i++) aom_img_free(&reference_images[i]);
|
||||
|
||||
if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
|
||||
|
||||
// Modify large_scale_file fourcc.
|
||||
if (cfg->large_scale_tile == 1)
|
||||
aom_video_writer_set_fourcc(writer, LST_FOURCC);
|
||||
aom_video_writer_close(writer);
|
||||
|
||||
printf("\nSecond pass complete. Processed %d frames.\n", frame_count);
|
||||
|
|
|
|||
|
|
@ -18,10 +18,12 @@
|
|||
// compressed tile data. This input file is reconstructed from the encoded
|
||||
// lightfield ivf file, and is decodable by AV1 decoder. num_references is
|
||||
// the number of anchor frames coded at the beginning of the light field file.
|
||||
// num_tile_lists is the number of tile lists need to be decoded.
|
||||
// num_tile_lists is the number of tile lists need to be decoded. There is an
|
||||
// optional parameter allowing to choose the output format, and the supported
|
||||
// formats are YUV1D(default), YUV, and NV12.
|
||||
// Run lightfield tile list decoder to decode an AV1 tile list file:
|
||||
// examples/lightfield_tile_list_decoder vase_tile_list.ivf vase_tile_list.yuv
|
||||
// 4 2
|
||||
// 4 2 0(optional)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -39,11 +41,61 @@ static const char *exec_name;
|
|||
|
||||
void usage_exit(void) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <infile> <outfile> <num_references> <num_tile_lists>\n",
|
||||
"Usage: %s <infile> <outfile> <num_references> <num_tile_lists> "
|
||||
"<output format(optional)>\n",
|
||||
exec_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void write_tile_yuv1d(aom_codec_ctx_t *codec, const aom_image_t *img,
|
||||
FILE *file) {
|
||||
// read out the tile size.
|
||||
unsigned int tile_size = 0;
|
||||
if (aom_codec_control(codec, AV1D_GET_TILE_SIZE, &tile_size))
|
||||
die_codec(codec, "Failed to get the tile size");
|
||||
const unsigned int tile_width = tile_size >> 16;
|
||||
const unsigned int tile_height = tile_size & 65535;
|
||||
const uint8_t output_frame_width_in_tiles = img->d_w / tile_width;
|
||||
|
||||
unsigned int tile_count = 0;
|
||||
if (aom_codec_control(codec, AV1D_GET_TILE_COUNT, &tile_count))
|
||||
die_codec(codec, "Failed to get the tile size");
|
||||
|
||||
// Write tile to file.
|
||||
const int shift = (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 1 : 0;
|
||||
unsigned int tile_idx;
|
||||
|
||||
for (tile_idx = 0; tile_idx < tile_count; ++tile_idx) {
|
||||
const int row_offset =
|
||||
(tile_idx / output_frame_width_in_tiles) * tile_height;
|
||||
const int col_offset =
|
||||
(tile_idx % output_frame_width_in_tiles) * tile_width;
|
||||
int plane;
|
||||
|
||||
for (plane = 0; plane < 3; ++plane) {
|
||||
const unsigned char *buf = img->planes[plane];
|
||||
const int stride = img->stride[plane];
|
||||
const int roffset =
|
||||
(plane > 0) ? row_offset >> img->y_chroma_shift : row_offset;
|
||||
const int coffset =
|
||||
(plane > 0) ? col_offset >> img->x_chroma_shift : col_offset;
|
||||
const int w = (plane > 0) ? ((tile_width >> img->x_chroma_shift) << shift)
|
||||
: (tile_width << shift);
|
||||
const int h =
|
||||
(plane > 0) ? (tile_height >> img->y_chroma_shift) : tile_height;
|
||||
int y;
|
||||
|
||||
// col offset needs to be adjusted for HBD.
|
||||
buf += roffset * stride + (coffset << shift);
|
||||
|
||||
for (y = 0; y < h; ++y) {
|
||||
fwrite(buf, 1, w, file);
|
||||
buf += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *outfile = NULL;
|
||||
aom_codec_ctx_t codec;
|
||||
|
|
@ -55,11 +107,12 @@ int main(int argc, char **argv) {
|
|||
aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
|
||||
size_t frame_size = 0;
|
||||
const unsigned char *frame = NULL;
|
||||
int output_format = YUV1D;
|
||||
int i, j, n;
|
||||
|
||||
exec_name = argv[0];
|
||||
|
||||
if (argc != 5) die("Invalid number of arguments.");
|
||||
if (argc < 5) die("Invalid number of arguments.");
|
||||
|
||||
reader = aom_video_reader_open(argv[1]);
|
||||
if (!reader) die("Failed to open %s for reading.", argv[1]);
|
||||
|
|
@ -70,6 +123,10 @@ int main(int argc, char **argv) {
|
|||
num_references = (int)strtol(argv[3], NULL, 0);
|
||||
num_tile_lists = (int)strtol(argv[4], NULL, 0);
|
||||
|
||||
if (argc > 5) output_format = (int)strtol(argv[5], NULL, 0);
|
||||
if (output_format < YUV1D || output_format > NV12)
|
||||
die("Output format out of range [0, 2]");
|
||||
|
||||
info = aom_video_reader_get_info(reader);
|
||||
|
||||
decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
|
||||
|
|
@ -103,7 +160,7 @@ int main(int argc, char **argv) {
|
|||
// Allocate memory to store decoded references. Allocate memory with the
|
||||
// border so that it can be used as a reference.
|
||||
for (j = 0; j < num_references; j++) {
|
||||
unsigned int border = AOM_BORDER_IN_PIXELS;
|
||||
unsigned int border = AOM_DEC_BORDER_IN_PIXELS;
|
||||
if (!aom_img_alloc_with_border(&reference_images[j], ref_fmt,
|
||||
frame_res[0], frame_res[1], 32, 8,
|
||||
border)) {
|
||||
|
|
@ -147,9 +204,17 @@ int main(int argc, char **argv) {
|
|||
if (aom_codec_decode(&codec, frame, frame_size, NULL))
|
||||
die_codec(&codec, "Failed to decode the tile list.");
|
||||
aom_codec_iter_t iter = NULL;
|
||||
aom_image_t *img;
|
||||
while ((img = aom_codec_get_frame(&codec, &iter)))
|
||||
fwrite(img->img_data, 1, img->sz, outfile);
|
||||
aom_image_t *img = aom_codec_get_frame(&codec, &iter);
|
||||
if (!img) die_codec(&codec, "Failed to get frame.");
|
||||
|
||||
if (output_format == YUV1D)
|
||||
// write the tile to the output file in 1D format.
|
||||
write_tile_yuv1d(&codec, img, outfile);
|
||||
else if (output_format == YUV)
|
||||
aom_img_write(img, outfile);
|
||||
else
|
||||
// NV12 output format
|
||||
aom_img_write_nv12(img, outfile);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_references; i++) aom_img_free(&reference_images[i]);
|
||||
|
|
|
|||
2
third_party/aom/examples/noise_model.c
vendored
2
third_party/aom/examples/noise_model.c
vendored
|
|
@ -114,7 +114,7 @@ typedef struct {
|
|||
const char *debug_file;
|
||||
} noise_model_args_t;
|
||||
|
||||
void parse_args(noise_model_args_t *noise_args, int *argc, char **argv) {
|
||||
static void parse_args(noise_model_args_t *noise_args, int *argc, char **argv) {
|
||||
struct arg arg;
|
||||
static const arg_def_t *main_args[] = { &help,
|
||||
&input_arg,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue