/* * 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.
*/
// Lightfield Decoder // ================== // // 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; 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 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.
staticvoid decode_tile(aom_codec_ctx_t *codec, constunsignedchar *frame,
size_t frame_size, int tr, int tc, int ref_idx,
aom_image_t *reference_images, aom_image_t *output, int *tile_idx, unsignedint *output_bit_depth,
aom_image_t **img_ptr, int output_format) {
AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1_SET_TILE_MODE, 1);
AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1D_EXT_TILE_DEBUG, 1);
AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1_SET_DECODE_TILE_ROW, tr);
AOM_CODEC_CONTROL_TYPECHECKED(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_TYPECHECKED(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. unsignedint tile_size = 0; if (AOM_CODEC_CONTROL_TYPECHECKED(codec, AV1D_GET_TILE_SIZE, &tile_size))
die_codec(codec, "Failed to get the tile size"); constunsignedint tile_width = tile_size >> 16; constunsignedint tile_height = tile_size & 65535; const uint32_t output_frame_width_in_tiles =
output_frame_width / tile_width;
// Copy the tile to the output frame. constint row_offset =
(*tile_idx / output_frame_width_in_tiles) * tile_height; constint col_offset =
(*tile_idx % output_frame_width_in_tiles) * tile_width;
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]");
aom_codec_ctx_t codec; if (aom_codec_dec_init(&codec, decoder, NULL, 0))
die_codec(&codec, "Failed to initialize decoder.");
if (AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1D_SET_IS_ANNEXB,
info->is_annexb)) {
die("Failed to set annex b status");
}
// Decode anchor frames.
AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1_SET_TILE_MODE, 0); for (i = 0; i < num_references; ++i) {
aom_video_reader_read_frame(reader);
frame = aom_video_reader_get_frame(reader, &frame_size); if (aom_codec_decode(&codec, frame, frame_size, NULL))
die_codec(&codec, "Failed to decode frame.");
if (i == 0) { if (AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1D_GET_IMG_FORMAT, &ref_fmt))
die_codec(&codec, "Failed to get the image format");
int frame_res[2]; if (AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1D_GET_FRAME_SIZE, frame_res))
die_codec(&codec, "Failed to get the image frame size");
// 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++) { unsignedint 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)) {
die("Failed to allocate references.");
}
}
}
if (AOM_CODEC_CONTROL_TYPECHECKED(&codec, AV1_COPY_NEW_FRAME_IMAGE,
&reference_images[i]))
die_codec(&codec, "Failed to copy decoded reference frame");
FILE *infile = aom_video_reader_get_file(reader); // Record the offset of the first camera image. const FileOffset camera_frame_pos = ftello(infile);
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. unsignedchar **frames =
(unsignedchar **)malloc(num_frames * sizeof(unsignedchar *));
size_t *frame_sizes = (size_t *)malloc(num_frames * sizeof(size_t)); if (!(frames && frame_sizes)) die("Failed to allocate frame data."); // 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] = (unsignedchar *)malloc(frame_size * sizeof(unsignedchar)); if (!frames[f]) die("Failed to allocate frame data.");
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 (FORCE_HIGHBITDEPTH_DECODING) 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"); if (!tile_list_fptr) die_codec(&codec, "Failed to open tile list file."); int tile_list_cnt = 0; int tile_list_writes = 0; int tile_idx = 0;
aom_image_t *out = NULL; unsignedint 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) { if (!aom_shift_img(output_bit_depth, &out, &output_shifted)) {
die("Error allocating image");
}
}
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;
}
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];
if (output_format != YUV1D) { // Write out the last tile list. if (tile_list_writes < tile_list_cnt) {
out = &output; if (output_bit_depth != 0) { if (!aom_shift_img(output_bit_depth, &out, &output_shifted)) {
die("Error allocating image");
}
}
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);
return EXIT_SUCCESS;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-04-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.