2 * Copyright (c) 2017, 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.
15 // This is an example of a simple lightfield decoder. It builds upon the
16 // simple_decoder.c example. It takes an input file containing the compressed
17 // data (in ivf format), treating it as a lightfield instead of a video and
18 // will decode a single lightfield tile. The lf_width and lf_height arguments
19 // are the number of lightfield images in each dimension. The tile to decode
20 // is specified by the tile_u, tile_v, tile_s, tile_t arguments. The tile_u,
21 // tile_v specify the image and tile_s, tile_t specify the tile in the image.
22 // After running the lightfield encoder, run lightfield decoder to decode a
24 // examples/lightfield_decoder vase10x10.ivf vase_tile.yuv 10 10 3 4 5 10 5
30 #include "aom/aom_decoder.h"
31 #include "aom/aomdx.h"
32 #include "common/tools_common.h"
33 #include "common/video_reader.h"
35 #define MAX_EXTERNAL_REFERENCES 128
36 #define AOM_BORDER_IN_PIXELS 288
38 static const char *exec_name
;
40 void usage_exit(void) {
42 "Usage: %s <infile> <outfile> <lf_width> <lf_height> <tlie_u>"
43 " <tile_v> <tile_s> <tile_t> <lf_blocksize>\n",
48 int main(int argc
, char **argv
) {
50 aom_codec_ctx_t codec
;
51 AvxVideoReader
*reader
= NULL
;
52 const AvxInterface
*decoder
= NULL
;
53 const AvxVideoInfo
*info
= NULL
;
54 const char *lf_width_arg
;
55 const char *lf_height_arg
;
56 const char *tile_u_arg
;
57 const char *tile_v_arg
;
58 const char *tile_s_arg
;
59 const char *tile_t_arg
;
60 const char *lf_blocksize_arg
;
62 int lf_width
, lf_height
;
63 int tile_u
, tile_v
, tile_s
, tile_t
;
67 aom_image_t reference_images
[MAX_EXTERNAL_REFERENCES
];
68 size_t frame_size
= 0;
69 const unsigned char *frame
= NULL
;
74 if (argc
!= 10) die("Invalid number of arguments.");
76 reader
= aom_video_reader_open(argv
[1]);
77 if (!reader
) die("Failed to open %s for reading.", argv
[1]);
79 if (!(outfile
= fopen(argv
[2], "wb")))
80 die("Failed to open %s for writing.", argv
[2]);
82 lf_width_arg
= argv
[3];
83 lf_height_arg
= argv
[4];
88 lf_blocksize_arg
= argv
[9];
89 lf_width
= (int)strtol(lf_width_arg
, NULL
, 0);
90 lf_height
= (int)strtol(lf_height_arg
, NULL
, 0);
91 tile_u
= (int)strtol(tile_u_arg
, NULL
, 0);
92 tile_v
= (int)strtol(tile_v_arg
, NULL
, 0);
93 tile_s
= (int)strtol(tile_s_arg
, NULL
, 0);
94 tile_t
= (int)strtol(tile_t_arg
, NULL
, 0);
95 lf_blocksize
= (int)strtol(lf_blocksize_arg
, NULL
, 0);
97 info
= aom_video_reader_get_info(reader
);
98 width
= info
->frame_width
;
99 height
= info
->frame_height
;
101 decoder
= get_aom_decoder_by_fourcc(info
->codec_fourcc
);
102 if (!decoder
) die("Unknown input codec.");
103 printf("Using %s\n", aom_codec_iface_name(decoder
->codec_interface()));
105 if (aom_codec_dec_init(&codec
, decoder
->codec_interface(), NULL
, 0))
106 die_codec(&codec
, "Failed to initialize decoder.");
108 // How many anchor frames we have.
109 u_blocks
= (lf_width
+ lf_blocksize
- 1) / lf_blocksize
;
110 v_blocks
= (lf_height
+ lf_blocksize
- 1) / lf_blocksize
;
112 int num_references
= v_blocks
* u_blocks
;
115 // Allocate memory to store decoded references.
116 aom_img_fmt_t ref_fmt
= AOM_IMG_FMT_I420
;
117 if (!CONFIG_LOWBITDEPTH
) ref_fmt
|= AOM_IMG_FMT_HIGHBITDEPTH
;
118 // Allocate memory with the border so that it can be used as a reference.
119 for (i
= 0; i
< num_references
; i
++) {
120 unsigned int border
= AOM_BORDER_IN_PIXELS
;
121 if (!aom_img_alloc_with_border(&reference_images
[i
], ref_fmt
, width
, height
,
123 die("Failed to allocate references.");
127 // Decode anchor frames.
128 aom_codec_control_(&codec
, AV1_SET_TILE_MODE
, 0);
130 for (i
= 0; i
< num_references
; ++i
) {
131 aom_video_reader_read_frame(reader
);
132 frame
= aom_video_reader_get_frame(reader
, &frame_size
);
133 if (aom_codec_decode(&codec
, frame
, frame_size
, NULL
))
134 die_codec(&codec
, "Failed to decode frame.");
136 if (aom_codec_control(&codec
, AV1_COPY_NEW_FRAME_IMAGE
,
137 &reference_images
[i
]))
138 die_codec(&codec
, "Failed to copy decoded reference frame");
140 aom_codec_iter_t iter
= NULL
;
141 aom_image_t
*img
= NULL
;
142 while ((img
= aom_codec_get_frame(&codec
, &iter
)) != NULL
) {
144 snprintf(name
, sizeof(name
), "ref_%d.yuv", i
);
145 printf("writing ref image to %s, %d, %d\n", name
, img
->d_w
, img
->d_h
);
146 FILE *ref_file
= fopen(name
, "wb");
147 aom_img_write(img
, ref_file
);
153 int decode_frame_index
= tile_v
* lf_width
+ tile_u
;
155 aom_video_reader_read_frame(reader
);
156 } while (frame_count
++ != decode_frame_index
);
158 frame
= aom_video_reader_get_frame(reader
, &frame_size
);
159 int ref_bu
= tile_u
/ lf_blocksize
;
160 int ref_bv
= tile_v
/ lf_blocksize
;
161 int ref_bi
= ref_bu
+ ref_bv
* u_blocks
;
164 ref
.use_external_ref
= 1;
165 ref
.img
= reference_images
[ref_bi
];
167 if (aom_codec_control(&codec
, AV1_SET_REFERENCE
, &ref
)) {
168 die_codec(&codec
, "Failed to set reference frame.");
170 aom_codec_control_(&codec
, AV1_SET_TILE_MODE
, 1);
171 aom_codec_control_(&codec
, AV1_SET_DECODE_TILE_ROW
, tile_t
);
172 aom_codec_control_(&codec
, AV1_SET_DECODE_TILE_COL
, tile_s
);
173 aom_codec_control_(&codec
, AV1D_EXT_TILE_DEBUG
, 1);
174 aom_codec_err_t aom_status
=
175 aom_codec_decode(&codec
, frame
, frame_size
, NULL
);
176 if (aom_status
) die_codec(&codec
, "Failed to decode tile.");
177 aom_codec_iter_t iter
= NULL
;
178 aom_image_t
*img
= aom_codec_get_frame(&codec
, &iter
);
179 aom_img_write(img
, outfile
);
181 for (i
= 0; i
< num_references
; i
++) aom_img_free(&reference_images
[i
]);
182 if (aom_codec_destroy(&codec
)) die_codec(&codec
, "Failed to destroy codec");
183 aom_video_reader_close(reader
);