2 * Copyright (c) 2018, Alliance for Open Media. All rights reserved
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.
12 // Lightfield Tile List Decoder
13 // ============================
15 // This is a lightfield tile list decoder example. It takes an input file that
16 // contains the anchor frames that are references of the coded tiles, the camera
17 // frame header, and tile list OBUs that include the tile information and the
18 // compressed tile data. This input file is reconstructed from the encoded
19 // lightfield ivf file, and is decodable by AV1 decoder. The lf_width and
20 // lf_height arguments are the number of lightfield images in each dimension.
21 // The lf_blocksize determines the number of reference images used.
22 // Run lightfield tile list decoder to decode an AV1 tile list file:
23 // examples/lightfield_tile_list_decoder vase_tile_list.ivf vase_tile_list.yuv
31 #include "aom/aom_decoder.h"
32 #include "aom/aomdx.h"
33 #include "common/tools_common.h"
34 #include "common/video_reader.h"
36 #define MAX_EXTERNAL_REFERENCES 128
37 #define AOM_BORDER_IN_PIXELS 288
39 static const char *exec_name
;
41 void usage_exit(void) {
43 "Usage: %s <infile> <outfile> <lf_width> <lf_height> <lf_blocksize> "
49 int main(int argc
, char **argv
) {
51 aom_codec_ctx_t codec
;
52 AvxVideoReader
*reader
= NULL
;
53 const AvxInterface
*decoder
= NULL
;
54 const AvxVideoInfo
*info
= NULL
;
55 const char *lf_width_arg
;
56 const char *lf_height_arg
;
57 const char *lf_blocksize_arg
;
59 int lf_width
, lf_height
, lf_blocksize
;
60 int u_blocks
, v_blocks
;
62 aom_image_t reference_images
[MAX_EXTERNAL_REFERENCES
];
63 size_t frame_size
= 0;
64 const unsigned char *frame
= NULL
;
69 if (argc
!= 7) die("Invalid number of arguments.");
71 reader
= aom_video_reader_open(argv
[1]);
72 if (!reader
) die("Failed to open %s for reading.", argv
[1]);
74 if (!(outfile
= fopen(argv
[2], "wb")))
75 die("Failed to open %s for writing.", argv
[2]);
77 lf_width_arg
= argv
[3];
78 lf_height_arg
= argv
[4];
79 lf_blocksize_arg
= argv
[5];
80 lf_width
= (int)strtol(lf_width_arg
, NULL
, 0);
81 lf_height
= (int)strtol(lf_height_arg
, NULL
, 0);
82 lf_blocksize
= (int)strtol(lf_blocksize_arg
, NULL
, 0);
83 num_tile_lists
= (int)strtol(argv
[6], NULL
, 0);
85 info
= aom_video_reader_get_info(reader
);
86 width
= info
->frame_width
;
87 height
= info
->frame_height
;
89 decoder
= get_aom_decoder_by_fourcc(info
->codec_fourcc
);
90 if (!decoder
) die("Unknown input codec.");
91 printf("Using %s\n", aom_codec_iface_name(decoder
->codec_interface()));
93 if (aom_codec_dec_init(&codec
, decoder
->codec_interface(), NULL
, 0))
94 die_codec(&codec
, "Failed to initialize decoder.");
96 // How many anchor frames we have.
97 u_blocks
= (lf_width
+ lf_blocksize
- 1) / lf_blocksize
;
98 v_blocks
= (lf_height
+ lf_blocksize
- 1) / lf_blocksize
;
100 int num_references
= v_blocks
* u_blocks
;
102 // Allocate memory to store decoded references.
103 aom_img_fmt_t ref_fmt
= AOM_IMG_FMT_I420
;
104 if (!CONFIG_LOWBITDEPTH
) ref_fmt
|= AOM_IMG_FMT_HIGHBITDEPTH
;
105 // Allocate memory with the border so that it can be used as a reference.
106 for (i
= 0; i
< num_references
; i
++) {
107 unsigned int border
= AOM_BORDER_IN_PIXELS
;
108 if (!aom_img_alloc_with_border(&reference_images
[i
], ref_fmt
, width
, height
,
110 die("Failed to allocate references.");
114 // Decode anchor frames.
115 aom_codec_control_(&codec
, AV1_SET_TILE_MODE
, 0);
117 for (i
= 0; i
< num_references
; ++i
) {
118 aom_video_reader_read_frame(reader
);
119 frame
= aom_video_reader_get_frame(reader
, &frame_size
);
120 if (aom_codec_decode(&codec
, frame
, frame_size
, NULL
))
121 die_codec(&codec
, "Failed to decode frame.");
123 if (aom_codec_control(&codec
, AV1_COPY_NEW_FRAME_IMAGE
,
124 &reference_images
[i
]))
125 die_codec(&codec
, "Failed to copy decoded reference frame");
127 aom_codec_iter_t iter
= NULL
;
128 aom_image_t
*img
= NULL
;
129 while ((img
= aom_codec_get_frame(&codec
, &iter
)) != NULL
) {
131 snprintf(name
, sizeof(name
), "ref_%d.yuv", i
);
132 printf("writing ref image to %s, %d, %d\n", name
, img
->d_w
, img
->d_h
);
133 FILE *ref_file
= fopen(name
, "wb");
134 aom_img_write(img
, ref_file
);
139 // Decode the lightfield.
140 aom_codec_control_(&codec
, AV1_SET_TILE_MODE
, 1);
142 // Set external references.
143 av1_ext_ref_frame_t set_ext_ref
= { &reference_images
[0], num_references
};
144 aom_codec_control_(&codec
, AV1D_SET_EXT_REF_PTR
, &set_ext_ref
);
146 // Must decode the camera frame header first.
147 aom_video_reader_read_frame(reader
);
148 frame
= aom_video_reader_get_frame(reader
, &frame_size
);
149 if (aom_codec_decode(&codec
, frame
, frame_size
, NULL
))
150 die_codec(&codec
, "Failed to decode the frame.");
152 // Decode tile lists one by one.
153 for (n
= 0; n
< num_tile_lists
; n
++) {
154 aom_video_reader_read_frame(reader
);
155 frame
= aom_video_reader_get_frame(reader
, &frame_size
);
157 if (aom_codec_decode(&codec
, frame
, frame_size
, NULL
))
158 die_codec(&codec
, "Failed to decode the tile list.");
160 aom_codec_iter_t iter
= NULL
;
162 while ((img
= aom_codec_get_frame(&codec
, &iter
))) {
163 aom_img_write(img
, outfile
);
167 for (i
= 0; i
< num_references
; i
++) aom_img_free(&reference_images
[i
]);
168 if (aom_codec_destroy(&codec
)) die_codec(&codec
, "Failed to destroy codec");
169 aom_video_reader_close(reader
);