xref: /aosp_15_r20/external/libaom/examples/lightfield_encoder.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2017, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker // Lightfield Encoder
13*77c1e3ccSAndroid Build Coastguard Worker // ==================
14*77c1e3ccSAndroid Build Coastguard Worker //
15*77c1e3ccSAndroid Build Coastguard Worker // This is an example of a simple lightfield encoder.  It builds upon the
16*77c1e3ccSAndroid Build Coastguard Worker // twopass_encoder.c example. It takes an input file in YV12 format,
17*77c1e3ccSAndroid Build Coastguard Worker // treating it as a planar lightfield instead of a video. The img_width
18*77c1e3ccSAndroid Build Coastguard Worker // and img_height arguments are the dimensions of the lightfield images,
19*77c1e3ccSAndroid Build Coastguard Worker // while the lf_width and lf_height arguments are the number of
20*77c1e3ccSAndroid Build Coastguard Worker // lightfield images in each dimension. The lf_blocksize determines the
21*77c1e3ccSAndroid Build Coastguard Worker // number of reference images used for MCP. For example, 5 means that there
22*77c1e3ccSAndroid Build Coastguard Worker // is a reference image for every 5x5 lightfield image block. All images
23*77c1e3ccSAndroid Build Coastguard Worker // within a block will use the center image in that block as the reference
24*77c1e3ccSAndroid Build Coastguard Worker // image for MCP.
25*77c1e3ccSAndroid Build Coastguard Worker // Run "make test" to download lightfield test data: vase10x10.yuv.
26*77c1e3ccSAndroid Build Coastguard Worker // Run lightfield encoder to encode whole lightfield:
27*77c1e3ccSAndroid Build Coastguard Worker // examples/lightfield_encoder 1024 1024 vase10x10.yuv vase10x10.ivf 10 10 5
28*77c1e3ccSAndroid Build Coastguard Worker 
29*77c1e3ccSAndroid Build Coastguard Worker // Note: In bitstream.c and encoder.c, define EXT_TILE_DEBUG as 1 will print
30*77c1e3ccSAndroid Build Coastguard Worker // out the uncompressed header and the frame contexts, which can be used to
31*77c1e3ccSAndroid Build Coastguard Worker // test the bit exactness of the headers and the frame contexts for large scale
32*77c1e3ccSAndroid Build Coastguard Worker // tile coded frames.
33*77c1e3ccSAndroid Build Coastguard Worker 
34*77c1e3ccSAndroid Build Coastguard Worker #include <stdio.h>
35*77c1e3ccSAndroid Build Coastguard Worker #include <stdlib.h>
36*77c1e3ccSAndroid Build Coastguard Worker #include <string.h>
37*77c1e3ccSAndroid Build Coastguard Worker 
38*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_encoder.h"
39*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aomcx.h"
40*77c1e3ccSAndroid Build Coastguard Worker #include "aom_scale/yv12config.h"
41*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/enums.h"
42*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder_utils.h"
43*77c1e3ccSAndroid Build Coastguard Worker #include "common/tools_common.h"
44*77c1e3ccSAndroid Build Coastguard Worker #include "common/video_writer.h"
45*77c1e3ccSAndroid Build Coastguard Worker 
46*77c1e3ccSAndroid Build Coastguard Worker static const char *exec_name;
47*77c1e3ccSAndroid Build Coastguard Worker 
usage_exit(void)48*77c1e3ccSAndroid Build Coastguard Worker void usage_exit(void) {
49*77c1e3ccSAndroid Build Coastguard Worker   fprintf(stderr,
50*77c1e3ccSAndroid Build Coastguard Worker           "Usage: %s <img_width> <img_height> <infile> <outfile> "
51*77c1e3ccSAndroid Build Coastguard Worker           "<lf_width> <lf_height> <lf_blocksize>\n",
52*77c1e3ccSAndroid Build Coastguard Worker           exec_name);
53*77c1e3ccSAndroid Build Coastguard Worker   exit(EXIT_FAILURE);
54*77c1e3ccSAndroid Build Coastguard Worker }
55*77c1e3ccSAndroid Build Coastguard Worker 
img_size_bytes(aom_image_t * img)56*77c1e3ccSAndroid Build Coastguard Worker static int img_size_bytes(aom_image_t *img) {
57*77c1e3ccSAndroid Build Coastguard Worker   int image_size_bytes = 0;
58*77c1e3ccSAndroid Build Coastguard Worker   int plane;
59*77c1e3ccSAndroid Build Coastguard Worker   for (plane = 0; plane < 3; ++plane) {
60*77c1e3ccSAndroid Build Coastguard Worker     const int w = aom_img_plane_width(img, plane) *
61*77c1e3ccSAndroid Build Coastguard Worker                   ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
62*77c1e3ccSAndroid Build Coastguard Worker     const int h = aom_img_plane_height(img, plane);
63*77c1e3ccSAndroid Build Coastguard Worker     image_size_bytes += w * h;
64*77c1e3ccSAndroid Build Coastguard Worker   }
65*77c1e3ccSAndroid Build Coastguard Worker   return image_size_bytes;
66*77c1e3ccSAndroid Build Coastguard Worker }
67*77c1e3ccSAndroid Build Coastguard Worker 
get_frame_stats(aom_codec_ctx_t * ctx,const aom_image_t * img,aom_codec_pts_t pts,unsigned int duration,aom_enc_frame_flags_t flags,aom_fixed_buf_t * stats)68*77c1e3ccSAndroid Build Coastguard Worker static int get_frame_stats(aom_codec_ctx_t *ctx, const aom_image_t *img,
69*77c1e3ccSAndroid Build Coastguard Worker                            aom_codec_pts_t pts, unsigned int duration,
70*77c1e3ccSAndroid Build Coastguard Worker                            aom_enc_frame_flags_t flags,
71*77c1e3ccSAndroid Build Coastguard Worker                            aom_fixed_buf_t *stats) {
72*77c1e3ccSAndroid Build Coastguard Worker   int got_pkts = 0;
73*77c1e3ccSAndroid Build Coastguard Worker   aom_codec_iter_t iter = NULL;
74*77c1e3ccSAndroid Build Coastguard Worker   const aom_codec_cx_pkt_t *pkt = NULL;
75*77c1e3ccSAndroid Build Coastguard Worker   const aom_codec_err_t res = aom_codec_encode(ctx, img, pts, duration, flags);
76*77c1e3ccSAndroid Build Coastguard Worker   if (res != AOM_CODEC_OK) die_codec(ctx, "Failed to get frame stats.");
77*77c1e3ccSAndroid Build Coastguard Worker 
78*77c1e3ccSAndroid Build Coastguard Worker   while ((pkt = aom_codec_get_cx_data(ctx, &iter)) != NULL) {
79*77c1e3ccSAndroid Build Coastguard Worker     got_pkts = 1;
80*77c1e3ccSAndroid Build Coastguard Worker 
81*77c1e3ccSAndroid Build Coastguard Worker     if (pkt->kind == AOM_CODEC_STATS_PKT) {
82*77c1e3ccSAndroid Build Coastguard Worker       const uint8_t *const pkt_buf = pkt->data.twopass_stats.buf;
83*77c1e3ccSAndroid Build Coastguard Worker       const size_t pkt_size = pkt->data.twopass_stats.sz;
84*77c1e3ccSAndroid Build Coastguard Worker       stats->buf = realloc(stats->buf, stats->sz + pkt_size);
85*77c1e3ccSAndroid Build Coastguard Worker       if (!stats->buf) die("Failed to allocate frame stats buffer.");
86*77c1e3ccSAndroid Build Coastguard Worker       memcpy((uint8_t *)stats->buf + stats->sz, pkt_buf, pkt_size);
87*77c1e3ccSAndroid Build Coastguard Worker       stats->sz += pkt_size;
88*77c1e3ccSAndroid Build Coastguard Worker     }
89*77c1e3ccSAndroid Build Coastguard Worker   }
90*77c1e3ccSAndroid Build Coastguard Worker 
91*77c1e3ccSAndroid Build Coastguard Worker   return got_pkts;
92*77c1e3ccSAndroid Build Coastguard Worker }
93*77c1e3ccSAndroid Build Coastguard Worker 
encode_frame(aom_codec_ctx_t * ctx,const aom_image_t * img,aom_codec_pts_t pts,unsigned int duration,aom_enc_frame_flags_t flags,AvxVideoWriter * writer)94*77c1e3ccSAndroid Build Coastguard Worker static int encode_frame(aom_codec_ctx_t *ctx, const aom_image_t *img,
95*77c1e3ccSAndroid Build Coastguard Worker                         aom_codec_pts_t pts, unsigned int duration,
96*77c1e3ccSAndroid Build Coastguard Worker                         aom_enc_frame_flags_t flags, AvxVideoWriter *writer) {
97*77c1e3ccSAndroid Build Coastguard Worker   int got_pkts = 0;
98*77c1e3ccSAndroid Build Coastguard Worker   aom_codec_iter_t iter = NULL;
99*77c1e3ccSAndroid Build Coastguard Worker   const aom_codec_cx_pkt_t *pkt = NULL;
100*77c1e3ccSAndroid Build Coastguard Worker   const aom_codec_err_t res = aom_codec_encode(ctx, img, pts, duration, flags);
101*77c1e3ccSAndroid Build Coastguard Worker   if (res != AOM_CODEC_OK) die_codec(ctx, "Failed to encode frame.");
102*77c1e3ccSAndroid Build Coastguard Worker 
103*77c1e3ccSAndroid Build Coastguard Worker   while ((pkt = aom_codec_get_cx_data(ctx, &iter)) != NULL) {
104*77c1e3ccSAndroid Build Coastguard Worker     got_pkts = 1;
105*77c1e3ccSAndroid Build Coastguard Worker     if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
106*77c1e3ccSAndroid Build Coastguard Worker       const int keyframe = (pkt->data.frame.flags & AOM_FRAME_IS_KEY) != 0;
107*77c1e3ccSAndroid Build Coastguard Worker 
108*77c1e3ccSAndroid Build Coastguard Worker       if (!aom_video_writer_write_frame(writer, pkt->data.frame.buf,
109*77c1e3ccSAndroid Build Coastguard Worker                                         pkt->data.frame.sz,
110*77c1e3ccSAndroid Build Coastguard Worker                                         pkt->data.frame.pts))
111*77c1e3ccSAndroid Build Coastguard Worker         die_codec(ctx, "Failed to write compressed frame.");
112*77c1e3ccSAndroid Build Coastguard Worker       printf(keyframe ? "K" : ".");
113*77c1e3ccSAndroid Build Coastguard Worker       fflush(stdout);
114*77c1e3ccSAndroid Build Coastguard Worker     }
115*77c1e3ccSAndroid Build Coastguard Worker   }
116*77c1e3ccSAndroid Build Coastguard Worker 
117*77c1e3ccSAndroid Build Coastguard Worker   return got_pkts;
118*77c1e3ccSAndroid Build Coastguard Worker }
119*77c1e3ccSAndroid Build Coastguard Worker 
get_raw_image(aom_image_t ** frame_to_encode,aom_image_t * raw,aom_image_t * raw_shift)120*77c1e3ccSAndroid Build Coastguard Worker static void get_raw_image(aom_image_t **frame_to_encode, aom_image_t *raw,
121*77c1e3ccSAndroid Build Coastguard Worker                           aom_image_t *raw_shift) {
122*77c1e3ccSAndroid Build Coastguard Worker   if (FORCE_HIGHBITDEPTH_DECODING) {
123*77c1e3ccSAndroid Build Coastguard Worker     // Need to allocate larger buffer to use hbd internal.
124*77c1e3ccSAndroid Build Coastguard Worker     int input_shift = 0;
125*77c1e3ccSAndroid Build Coastguard Worker     aom_img_upshift(raw_shift, raw, input_shift);
126*77c1e3ccSAndroid Build Coastguard Worker     *frame_to_encode = raw_shift;
127*77c1e3ccSAndroid Build Coastguard Worker   } else {
128*77c1e3ccSAndroid Build Coastguard Worker     *frame_to_encode = raw;
129*77c1e3ccSAndroid Build Coastguard Worker   }
130*77c1e3ccSAndroid Build Coastguard Worker }
131*77c1e3ccSAndroid Build Coastguard Worker 
pass0(aom_image_t * raw,FILE * infile,aom_codec_iface_t * encoder,const aom_codec_enc_cfg_t * cfg,int lf_width,int lf_height,int lf_blocksize,int flags,aom_image_t * raw_shift)132*77c1e3ccSAndroid Build Coastguard Worker static aom_fixed_buf_t pass0(aom_image_t *raw, FILE *infile,
133*77c1e3ccSAndroid Build Coastguard Worker                              aom_codec_iface_t *encoder,
134*77c1e3ccSAndroid Build Coastguard Worker                              const aom_codec_enc_cfg_t *cfg, int lf_width,
135*77c1e3ccSAndroid Build Coastguard Worker                              int lf_height, int lf_blocksize, int flags,
136*77c1e3ccSAndroid Build Coastguard Worker                              aom_image_t *raw_shift) {
137*77c1e3ccSAndroid Build Coastguard Worker   aom_codec_ctx_t codec;
138*77c1e3ccSAndroid Build Coastguard Worker   int frame_count = 0;
139*77c1e3ccSAndroid Build Coastguard Worker   int image_size_bytes = img_size_bytes(raw);
140*77c1e3ccSAndroid Build Coastguard Worker   int u_blocks, v_blocks;
141*77c1e3ccSAndroid Build Coastguard Worker   int bu, bv;
142*77c1e3ccSAndroid Build Coastguard Worker   aom_fixed_buf_t stats = { NULL, 0 };
143*77c1e3ccSAndroid Build Coastguard Worker   aom_image_t *frame_to_encode;
144*77c1e3ccSAndroid Build Coastguard Worker 
145*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_enc_init(&codec, encoder, cfg, flags))
146*77c1e3ccSAndroid Build Coastguard Worker     die("Failed to initialize encoder");
147*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AOME_SET_ENABLEAUTOALTREF, 0))
148*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to turn off auto altref");
149*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 0))
150*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set frame parallel decoding");
151*77c1e3ccSAndroid Build Coastguard Worker 
152*77c1e3ccSAndroid Build Coastguard Worker   // How many reference images we need to encode.
153*77c1e3ccSAndroid Build Coastguard Worker   u_blocks = (lf_width + lf_blocksize - 1) / lf_blocksize;
154*77c1e3ccSAndroid Build Coastguard Worker   v_blocks = (lf_height + lf_blocksize - 1) / lf_blocksize;
155*77c1e3ccSAndroid Build Coastguard Worker 
156*77c1e3ccSAndroid Build Coastguard Worker   printf("\n First pass: ");
157*77c1e3ccSAndroid Build Coastguard Worker 
158*77c1e3ccSAndroid Build Coastguard Worker   for (bv = 0; bv < v_blocks; ++bv) {
159*77c1e3ccSAndroid Build Coastguard Worker     for (bu = 0; bu < u_blocks; ++bu) {
160*77c1e3ccSAndroid Build Coastguard Worker       const int block_u_min = bu * lf_blocksize;
161*77c1e3ccSAndroid Build Coastguard Worker       const int block_v_min = bv * lf_blocksize;
162*77c1e3ccSAndroid Build Coastguard Worker       int block_u_end = (bu + 1) * lf_blocksize;
163*77c1e3ccSAndroid Build Coastguard Worker       int block_v_end = (bv + 1) * lf_blocksize;
164*77c1e3ccSAndroid Build Coastguard Worker       int u_block_size, v_block_size;
165*77c1e3ccSAndroid Build Coastguard Worker       int block_ref_u, block_ref_v;
166*77c1e3ccSAndroid Build Coastguard Worker 
167*77c1e3ccSAndroid Build Coastguard Worker       block_u_end = block_u_end < lf_width ? block_u_end : lf_width;
168*77c1e3ccSAndroid Build Coastguard Worker       block_v_end = block_v_end < lf_height ? block_v_end : lf_height;
169*77c1e3ccSAndroid Build Coastguard Worker       u_block_size = block_u_end - block_u_min;
170*77c1e3ccSAndroid Build Coastguard Worker       v_block_size = block_v_end - block_v_min;
171*77c1e3ccSAndroid Build Coastguard Worker       block_ref_u = block_u_min + u_block_size / 2;
172*77c1e3ccSAndroid Build Coastguard Worker       block_ref_v = block_v_min + v_block_size / 2;
173*77c1e3ccSAndroid Build Coastguard Worker 
174*77c1e3ccSAndroid Build Coastguard Worker       printf("A%d, ", (block_ref_u + block_ref_v * lf_width));
175*77c1e3ccSAndroid Build Coastguard Worker       fseek(infile, (block_ref_u + block_ref_v * lf_width) * image_size_bytes,
176*77c1e3ccSAndroid Build Coastguard Worker             SEEK_SET);
177*77c1e3ccSAndroid Build Coastguard Worker       aom_img_read(raw, infile);
178*77c1e3ccSAndroid Build Coastguard Worker       get_raw_image(&frame_to_encode, raw, raw_shift);
179*77c1e3ccSAndroid Build Coastguard Worker 
180*77c1e3ccSAndroid Build Coastguard Worker       // Reference frames can be encoded encoded without tiles.
181*77c1e3ccSAndroid Build Coastguard Worker       ++frame_count;
182*77c1e3ccSAndroid Build Coastguard Worker       get_frame_stats(&codec, frame_to_encode, frame_count, 1,
183*77c1e3ccSAndroid Build Coastguard Worker                       AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
184*77c1e3ccSAndroid Build Coastguard Worker                           AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
185*77c1e3ccSAndroid Build Coastguard Worker                           AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
186*77c1e3ccSAndroid Build Coastguard Worker                           AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
187*77c1e3ccSAndroid Build Coastguard Worker                           AOM_EFLAG_NO_UPD_ARF,
188*77c1e3ccSAndroid Build Coastguard Worker                       &stats);
189*77c1e3ccSAndroid Build Coastguard Worker     }
190*77c1e3ccSAndroid Build Coastguard Worker   }
191*77c1e3ccSAndroid Build Coastguard Worker 
192*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 1))
193*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set frame parallel decoding");
194*77c1e3ccSAndroid Build Coastguard Worker 
195*77c1e3ccSAndroid Build Coastguard Worker   for (bv = 0; bv < v_blocks; ++bv) {
196*77c1e3ccSAndroid Build Coastguard Worker     for (bu = 0; bu < u_blocks; ++bu) {
197*77c1e3ccSAndroid Build Coastguard Worker       const int block_u_min = bu * lf_blocksize;
198*77c1e3ccSAndroid Build Coastguard Worker       const int block_v_min = bv * lf_blocksize;
199*77c1e3ccSAndroid Build Coastguard Worker       int block_u_end = (bu + 1) * lf_blocksize;
200*77c1e3ccSAndroid Build Coastguard Worker       int block_v_end = (bv + 1) * lf_blocksize;
201*77c1e3ccSAndroid Build Coastguard Worker       int u, v;
202*77c1e3ccSAndroid Build Coastguard Worker       block_u_end = block_u_end < lf_width ? block_u_end : lf_width;
203*77c1e3ccSAndroid Build Coastguard Worker       block_v_end = block_v_end < lf_height ? block_v_end : lf_height;
204*77c1e3ccSAndroid Build Coastguard Worker       for (v = block_v_min; v < block_v_end; ++v) {
205*77c1e3ccSAndroid Build Coastguard Worker         for (u = block_u_min; u < block_u_end; ++u) {
206*77c1e3ccSAndroid Build Coastguard Worker           printf("C%d, ", (u + v * lf_width));
207*77c1e3ccSAndroid Build Coastguard Worker           fseek(infile, (u + v * lf_width) * image_size_bytes, SEEK_SET);
208*77c1e3ccSAndroid Build Coastguard Worker           aom_img_read(raw, infile);
209*77c1e3ccSAndroid Build Coastguard Worker           get_raw_image(&frame_to_encode, raw, raw_shift);
210*77c1e3ccSAndroid Build Coastguard Worker 
211*77c1e3ccSAndroid Build Coastguard Worker           ++frame_count;
212*77c1e3ccSAndroid Build Coastguard Worker           get_frame_stats(&codec, frame_to_encode, frame_count, 1,
213*77c1e3ccSAndroid Build Coastguard Worker                           AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
214*77c1e3ccSAndroid Build Coastguard Worker                               AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
215*77c1e3ccSAndroid Build Coastguard Worker                               AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
216*77c1e3ccSAndroid Build Coastguard Worker                               AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
217*77c1e3ccSAndroid Build Coastguard Worker                               AOM_EFLAG_NO_UPD_ARF | AOM_EFLAG_NO_UPD_ENTROPY,
218*77c1e3ccSAndroid Build Coastguard Worker                           &stats);
219*77c1e3ccSAndroid Build Coastguard Worker         }
220*77c1e3ccSAndroid Build Coastguard Worker       }
221*77c1e3ccSAndroid Build Coastguard Worker     }
222*77c1e3ccSAndroid Build Coastguard Worker   }
223*77c1e3ccSAndroid Build Coastguard Worker   // Flush encoder.
224*77c1e3ccSAndroid Build Coastguard Worker   // No ARF, this should not be needed.
225*77c1e3ccSAndroid Build Coastguard Worker   while (get_frame_stats(&codec, NULL, frame_count, 1, 0, &stats)) {
226*77c1e3ccSAndroid Build Coastguard Worker   }
227*77c1e3ccSAndroid Build Coastguard Worker 
228*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
229*77c1e3ccSAndroid Build Coastguard Worker 
230*77c1e3ccSAndroid Build Coastguard Worker   printf("\nFirst pass complete. Processed %d frames.\n", frame_count);
231*77c1e3ccSAndroid Build Coastguard Worker 
232*77c1e3ccSAndroid Build Coastguard Worker   return stats;
233*77c1e3ccSAndroid Build Coastguard Worker }
234*77c1e3ccSAndroid Build Coastguard Worker 
pass1(aom_image_t * raw,FILE * infile,const char * outfile_name,aom_codec_iface_t * encoder,aom_codec_enc_cfg_t * cfg,int lf_width,int lf_height,int lf_blocksize,int flags,aom_image_t * raw_shift)235*77c1e3ccSAndroid Build Coastguard Worker static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
236*77c1e3ccSAndroid Build Coastguard Worker                   aom_codec_iface_t *encoder, aom_codec_enc_cfg_t *cfg,
237*77c1e3ccSAndroid Build Coastguard Worker                   int lf_width, int lf_height, int lf_blocksize, int flags,
238*77c1e3ccSAndroid Build Coastguard Worker                   aom_image_t *raw_shift) {
239*77c1e3ccSAndroid Build Coastguard Worker   AvxVideoInfo info = { get_fourcc_by_aom_encoder(encoder),
240*77c1e3ccSAndroid Build Coastguard Worker                         cfg->g_w,
241*77c1e3ccSAndroid Build Coastguard Worker                         cfg->g_h,
242*77c1e3ccSAndroid Build Coastguard Worker                         { cfg->g_timebase.num, cfg->g_timebase.den },
243*77c1e3ccSAndroid Build Coastguard Worker                         0 };
244*77c1e3ccSAndroid Build Coastguard Worker   AvxVideoWriter *writer = NULL;
245*77c1e3ccSAndroid Build Coastguard Worker   aom_codec_ctx_t codec;
246*77c1e3ccSAndroid Build Coastguard Worker   int frame_count = 0;
247*77c1e3ccSAndroid Build Coastguard Worker   int image_size_bytes = img_size_bytes(raw);
248*77c1e3ccSAndroid Build Coastguard Worker   int bu, bv;
249*77c1e3ccSAndroid Build Coastguard Worker   int u_blocks, v_blocks;
250*77c1e3ccSAndroid Build Coastguard Worker   aom_image_t *frame_to_encode;
251*77c1e3ccSAndroid Build Coastguard Worker   aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
252*77c1e3ccSAndroid Build Coastguard Worker   int reference_image_num = 0;
253*77c1e3ccSAndroid Build Coastguard Worker   int i;
254*77c1e3ccSAndroid Build Coastguard Worker 
255*77c1e3ccSAndroid Build Coastguard Worker   writer = aom_video_writer_open(outfile_name, kContainerIVF, &info);
256*77c1e3ccSAndroid Build Coastguard Worker   if (!writer) die("Failed to open %s for writing", outfile_name);
257*77c1e3ccSAndroid Build Coastguard Worker 
258*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_enc_init(&codec, encoder, cfg, flags))
259*77c1e3ccSAndroid Build Coastguard Worker     die("Failed to initialize encoder");
260*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AOME_SET_ENABLEAUTOALTREF, 0))
261*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to turn off auto altref");
262*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 0))
263*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set frame parallel decoding");
264*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_ENABLE_EXT_TILE_DEBUG, 1))
265*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to enable encoder ext_tile debug");
266*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AOME_SET_CPUUSED, 3))
267*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set cpu-used");
268*77c1e3ccSAndroid Build Coastguard Worker 
269*77c1e3ccSAndroid Build Coastguard Worker   // Note: The superblock is a sequence parameter and has to be the same for 1
270*77c1e3ccSAndroid Build Coastguard Worker   // sequence. In lightfield application, must choose the superblock size(either
271*77c1e3ccSAndroid Build Coastguard Worker   // 64x64 or 128x128) before the encoding starts. Otherwise, the default is
272*77c1e3ccSAndroid Build Coastguard Worker   // AOM_SUPERBLOCK_SIZE_DYNAMIC, and the superblock size will be set to 64x64
273*77c1e3ccSAndroid Build Coastguard Worker   // internally.
274*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_SUPERBLOCK_SIZE,
275*77c1e3ccSAndroid Build Coastguard Worker                         AOM_SUPERBLOCK_SIZE_64X64))
276*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set SB size");
277*77c1e3ccSAndroid Build Coastguard Worker 
278*77c1e3ccSAndroid Build Coastguard Worker   u_blocks = (lf_width + lf_blocksize - 1) / lf_blocksize;
279*77c1e3ccSAndroid Build Coastguard Worker   v_blocks = (lf_height + lf_blocksize - 1) / lf_blocksize;
280*77c1e3ccSAndroid Build Coastguard Worker 
281*77c1e3ccSAndroid Build Coastguard Worker   reference_image_num = u_blocks * v_blocks;
282*77c1e3ccSAndroid Build Coastguard Worker   // Set the max gf group length so the references are guaranteed to be in
283*77c1e3ccSAndroid Build Coastguard Worker   // a different gf group than any of the regular frames. This avoids using
284*77c1e3ccSAndroid Build Coastguard Worker   // both vbr and constant quality mode in a single group. The number of
285*77c1e3ccSAndroid Build Coastguard Worker   // references now cannot surpass 17 because of the enforced MAX_GF_INTERVAL of
286*77c1e3ccSAndroid Build Coastguard Worker   // 16. If it is necessary to exceed this reference frame limit, one will have
287*77c1e3ccSAndroid Build Coastguard Worker   // to do some additional handling to ensure references are in separate gf
288*77c1e3ccSAndroid Build Coastguard Worker   // groups from the regular frames.
289*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_MAX_GF_INTERVAL,
290*77c1e3ccSAndroid Build Coastguard Worker                         reference_image_num - 1))
291*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set max gf interval");
292*77c1e3ccSAndroid Build Coastguard Worker   aom_img_fmt_t ref_fmt = AOM_IMG_FMT_I420;
293*77c1e3ccSAndroid Build Coastguard Worker   if (FORCE_HIGHBITDEPTH_DECODING) ref_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
294*77c1e3ccSAndroid Build Coastguard Worker   // Allocate memory with the border so that it can be used as a reference.
295*77c1e3ccSAndroid Build Coastguard Worker   const bool resize =
296*77c1e3ccSAndroid Build Coastguard Worker       codec.config.enc->rc_resize_mode || codec.config.enc->rc_superres_mode;
297*77c1e3ccSAndroid Build Coastguard Worker   const bool all_intra = reference_image_num - 1 == 0;
298*77c1e3ccSAndroid Build Coastguard Worker   int border_in_pixels =
299*77c1e3ccSAndroid Build Coastguard Worker       av1_get_enc_border_size(resize, all_intra, BLOCK_64X64);
300*77c1e3ccSAndroid Build Coastguard Worker 
301*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < reference_image_num; i++) {
302*77c1e3ccSAndroid Build Coastguard Worker     if (!aom_img_alloc_with_border(&reference_images[i], ref_fmt, cfg->g_w,
303*77c1e3ccSAndroid Build Coastguard Worker                                    cfg->g_h, 32, 8, border_in_pixels)) {
304*77c1e3ccSAndroid Build Coastguard Worker       die("Failed to allocate image.");
305*77c1e3ccSAndroid Build Coastguard Worker     }
306*77c1e3ccSAndroid Build Coastguard Worker   }
307*77c1e3ccSAndroid Build Coastguard Worker 
308*77c1e3ccSAndroid Build Coastguard Worker   printf("\n Second pass: ");
309*77c1e3ccSAndroid Build Coastguard Worker 
310*77c1e3ccSAndroid Build Coastguard Worker   // Encode reference images first.
311*77c1e3ccSAndroid Build Coastguard Worker   printf("Encoding Reference Images\n");
312*77c1e3ccSAndroid Build Coastguard Worker   for (bv = 0; bv < v_blocks; ++bv) {
313*77c1e3ccSAndroid Build Coastguard Worker     for (bu = 0; bu < u_blocks; ++bu) {
314*77c1e3ccSAndroid Build Coastguard Worker       const int block_u_min = bu * lf_blocksize;
315*77c1e3ccSAndroid Build Coastguard Worker       const int block_v_min = bv * lf_blocksize;
316*77c1e3ccSAndroid Build Coastguard Worker       int block_u_end = (bu + 1) * lf_blocksize;
317*77c1e3ccSAndroid Build Coastguard Worker       int block_v_end = (bv + 1) * lf_blocksize;
318*77c1e3ccSAndroid Build Coastguard Worker       int u_block_size, v_block_size;
319*77c1e3ccSAndroid Build Coastguard Worker       int block_ref_u, block_ref_v;
320*77c1e3ccSAndroid Build Coastguard Worker 
321*77c1e3ccSAndroid Build Coastguard Worker       block_u_end = block_u_end < lf_width ? block_u_end : lf_width;
322*77c1e3ccSAndroid Build Coastguard Worker       block_v_end = block_v_end < lf_height ? block_v_end : lf_height;
323*77c1e3ccSAndroid Build Coastguard Worker       u_block_size = block_u_end - block_u_min;
324*77c1e3ccSAndroid Build Coastguard Worker       v_block_size = block_v_end - block_v_min;
325*77c1e3ccSAndroid Build Coastguard Worker       block_ref_u = block_u_min + u_block_size / 2;
326*77c1e3ccSAndroid Build Coastguard Worker       block_ref_v = block_v_min + v_block_size / 2;
327*77c1e3ccSAndroid Build Coastguard Worker 
328*77c1e3ccSAndroid Build Coastguard Worker       printf("A%d, ", (block_ref_u + block_ref_v * lf_width));
329*77c1e3ccSAndroid Build Coastguard Worker       fseek(infile, (block_ref_u + block_ref_v * lf_width) * image_size_bytes,
330*77c1e3ccSAndroid Build Coastguard Worker             SEEK_SET);
331*77c1e3ccSAndroid Build Coastguard Worker       aom_img_read(raw, infile);
332*77c1e3ccSAndroid Build Coastguard Worker 
333*77c1e3ccSAndroid Build Coastguard Worker       get_raw_image(&frame_to_encode, raw, raw_shift);
334*77c1e3ccSAndroid Build Coastguard Worker 
335*77c1e3ccSAndroid Build Coastguard Worker       // Reference frames may be encoded without tiles.
336*77c1e3ccSAndroid Build Coastguard Worker       ++frame_count;
337*77c1e3ccSAndroid Build Coastguard Worker       printf("Encoding reference image %d of %d\n", bv * u_blocks + bu,
338*77c1e3ccSAndroid Build Coastguard Worker              u_blocks * v_blocks);
339*77c1e3ccSAndroid Build Coastguard Worker       encode_frame(&codec, frame_to_encode, frame_count, 1,
340*77c1e3ccSAndroid Build Coastguard Worker                    AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
341*77c1e3ccSAndroid Build Coastguard Worker                        AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
342*77c1e3ccSAndroid Build Coastguard Worker                        AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
343*77c1e3ccSAndroid Build Coastguard Worker                        AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
344*77c1e3ccSAndroid Build Coastguard Worker                        AOM_EFLAG_NO_UPD_ARF | AOM_EFLAG_NO_UPD_ENTROPY,
345*77c1e3ccSAndroid Build Coastguard Worker                    writer);
346*77c1e3ccSAndroid Build Coastguard Worker 
347*77c1e3ccSAndroid Build Coastguard Worker       if (aom_codec_control(&codec, AV1_COPY_NEW_FRAME_IMAGE,
348*77c1e3ccSAndroid Build Coastguard Worker                             &reference_images[frame_count - 1]))
349*77c1e3ccSAndroid Build Coastguard Worker         die_codec(&codec, "Failed to copy decoder reference frame");
350*77c1e3ccSAndroid Build Coastguard Worker     }
351*77c1e3ccSAndroid Build Coastguard Worker   }
352*77c1e3ccSAndroid Build Coastguard Worker 
353*77c1e3ccSAndroid Build Coastguard Worker   cfg->large_scale_tile = 1;
354*77c1e3ccSAndroid Build Coastguard Worker   // Fixed q encoding for camera frames.
355*77c1e3ccSAndroid Build Coastguard Worker   cfg->rc_end_usage = AOM_Q;
356*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_enc_config_set(&codec, cfg))
357*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to configure encoder");
358*77c1e3ccSAndroid Build Coastguard Worker 
359*77c1e3ccSAndroid Build Coastguard Worker   // The fixed q value used in encoding.
360*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AOME_SET_CQ_LEVEL, 36))
361*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set cq level");
362*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 1))
363*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set frame parallel decoding");
364*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_SINGLE_TILE_DECODING, 1))
365*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to turn on single tile decoding");
366*77c1e3ccSAndroid Build Coastguard Worker   // Set tile_columns and tile_rows to MAX values, which guarantees the tile
367*77c1e3ccSAndroid Build Coastguard Worker   // size of 64 x 64 pixels(i.e. 1 SB) for <= 4k resolution.
368*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_TILE_COLUMNS, 6))
369*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set tile width");
370*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_control(&codec, AV1E_SET_TILE_ROWS, 6))
371*77c1e3ccSAndroid Build Coastguard Worker     die_codec(&codec, "Failed to set tile height");
372*77c1e3ccSAndroid Build Coastguard Worker 
373*77c1e3ccSAndroid Build Coastguard Worker   for (bv = 0; bv < v_blocks; ++bv) {
374*77c1e3ccSAndroid Build Coastguard Worker     for (bu = 0; bu < u_blocks; ++bu) {
375*77c1e3ccSAndroid Build Coastguard Worker       const int block_u_min = bu * lf_blocksize;
376*77c1e3ccSAndroid Build Coastguard Worker       const int block_v_min = bv * lf_blocksize;
377*77c1e3ccSAndroid Build Coastguard Worker       int block_u_end = (bu + 1) * lf_blocksize;
378*77c1e3ccSAndroid Build Coastguard Worker       int block_v_end = (bv + 1) * lf_blocksize;
379*77c1e3ccSAndroid Build Coastguard Worker       int u, v;
380*77c1e3ccSAndroid Build Coastguard Worker       block_u_end = block_u_end < lf_width ? block_u_end : lf_width;
381*77c1e3ccSAndroid Build Coastguard Worker       block_v_end = block_v_end < lf_height ? block_v_end : lf_height;
382*77c1e3ccSAndroid Build Coastguard Worker       for (v = block_v_min; v < block_v_end; ++v) {
383*77c1e3ccSAndroid Build Coastguard Worker         for (u = block_u_min; u < block_u_end; ++u) {
384*77c1e3ccSAndroid Build Coastguard Worker           av1_ref_frame_t ref;
385*77c1e3ccSAndroid Build Coastguard Worker           ref.idx = 0;
386*77c1e3ccSAndroid Build Coastguard Worker           ref.use_external_ref = 1;
387*77c1e3ccSAndroid Build Coastguard Worker           ref.img = reference_images[bv * u_blocks + bu];
388*77c1e3ccSAndroid Build Coastguard Worker           if (aom_codec_control(&codec, AV1_SET_REFERENCE, &ref))
389*77c1e3ccSAndroid Build Coastguard Worker             die_codec(&codec, "Failed to set reference frame");
390*77c1e3ccSAndroid Build Coastguard Worker 
391*77c1e3ccSAndroid Build Coastguard Worker           printf("C%d, ", (u + v * lf_width));
392*77c1e3ccSAndroid Build Coastguard Worker           fseek(infile, (u + v * lf_width) * image_size_bytes, SEEK_SET);
393*77c1e3ccSAndroid Build Coastguard Worker           aom_img_read(raw, infile);
394*77c1e3ccSAndroid Build Coastguard Worker           get_raw_image(&frame_to_encode, raw, raw_shift);
395*77c1e3ccSAndroid Build Coastguard Worker 
396*77c1e3ccSAndroid Build Coastguard Worker           ++frame_count;
397*77c1e3ccSAndroid Build Coastguard Worker           printf("Encoding image %d of %d\n",
398*77c1e3ccSAndroid Build Coastguard Worker                  frame_count - (u_blocks * v_blocks), lf_width * lf_height);
399*77c1e3ccSAndroid Build Coastguard Worker           encode_frame(&codec, frame_to_encode, frame_count, 1,
400*77c1e3ccSAndroid Build Coastguard Worker                        AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
401*77c1e3ccSAndroid Build Coastguard Worker                            AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
402*77c1e3ccSAndroid Build Coastguard Worker                            AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
403*77c1e3ccSAndroid Build Coastguard Worker                            AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
404*77c1e3ccSAndroid Build Coastguard Worker                            AOM_EFLAG_NO_UPD_ARF | AOM_EFLAG_NO_UPD_ENTROPY,
405*77c1e3ccSAndroid Build Coastguard Worker                        writer);
406*77c1e3ccSAndroid Build Coastguard Worker         }
407*77c1e3ccSAndroid Build Coastguard Worker       }
408*77c1e3ccSAndroid Build Coastguard Worker     }
409*77c1e3ccSAndroid Build Coastguard Worker   }
410*77c1e3ccSAndroid Build Coastguard Worker 
411*77c1e3ccSAndroid Build Coastguard Worker   // Flush encoder.
412*77c1e3ccSAndroid Build Coastguard Worker   // No ARF, this should not be needed.
413*77c1e3ccSAndroid Build Coastguard Worker   while (encode_frame(&codec, NULL, -1, 1, 0, writer)) {
414*77c1e3ccSAndroid Build Coastguard Worker   }
415*77c1e3ccSAndroid Build Coastguard Worker 
416*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < reference_image_num; i++) aom_img_free(&reference_images[i]);
417*77c1e3ccSAndroid Build Coastguard Worker 
418*77c1e3ccSAndroid Build Coastguard Worker   if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
419*77c1e3ccSAndroid Build Coastguard Worker 
420*77c1e3ccSAndroid Build Coastguard Worker   // Modify large_scale_file fourcc.
421*77c1e3ccSAndroid Build Coastguard Worker   if (cfg->large_scale_tile == 1)
422*77c1e3ccSAndroid Build Coastguard Worker     aom_video_writer_set_fourcc(writer, LST_FOURCC);
423*77c1e3ccSAndroid Build Coastguard Worker   aom_video_writer_close(writer);
424*77c1e3ccSAndroid Build Coastguard Worker 
425*77c1e3ccSAndroid Build Coastguard Worker   printf("\nSecond pass complete. Processed %d frames.\n", frame_count);
426*77c1e3ccSAndroid Build Coastguard Worker }
427*77c1e3ccSAndroid Build Coastguard Worker 
main(int argc,char ** argv)428*77c1e3ccSAndroid Build Coastguard Worker int main(int argc, char **argv) {
429*77c1e3ccSAndroid Build Coastguard Worker   FILE *infile = NULL;
430*77c1e3ccSAndroid Build Coastguard Worker   int w, h;
431*77c1e3ccSAndroid Build Coastguard Worker   // The number of lightfield images in the u and v dimensions.
432*77c1e3ccSAndroid Build Coastguard Worker   int lf_width, lf_height;
433*77c1e3ccSAndroid Build Coastguard Worker   // Defines how many images refer to the same reference image for MCP.
434*77c1e3ccSAndroid Build Coastguard Worker   // lf_blocksize X lf_blocksize images will all use the reference image
435*77c1e3ccSAndroid Build Coastguard Worker   // in the middle of the block of images.
436*77c1e3ccSAndroid Build Coastguard Worker   int lf_blocksize;
437*77c1e3ccSAndroid Build Coastguard Worker   aom_codec_ctx_t codec;
438*77c1e3ccSAndroid Build Coastguard Worker   aom_codec_enc_cfg_t cfg;
439*77c1e3ccSAndroid Build Coastguard Worker   aom_image_t raw;
440*77c1e3ccSAndroid Build Coastguard Worker   aom_image_t raw_shift;
441*77c1e3ccSAndroid Build Coastguard Worker   aom_codec_err_t res;
442*77c1e3ccSAndroid Build Coastguard Worker   aom_fixed_buf_t stats;
443*77c1e3ccSAndroid Build Coastguard Worker   int flags = 0;
444*77c1e3ccSAndroid Build Coastguard Worker 
445*77c1e3ccSAndroid Build Coastguard Worker   const int fps = 30;
446*77c1e3ccSAndroid Build Coastguard Worker   const int bitrate = 200;  // kbit/s
447*77c1e3ccSAndroid Build Coastguard Worker   const char *const width_arg = argv[1];
448*77c1e3ccSAndroid Build Coastguard Worker   const char *const height_arg = argv[2];
449*77c1e3ccSAndroid Build Coastguard Worker   const char *const infile_arg = argv[3];
450*77c1e3ccSAndroid Build Coastguard Worker   const char *const outfile_arg = argv[4];
451*77c1e3ccSAndroid Build Coastguard Worker   const char *const lf_width_arg = argv[5];
452*77c1e3ccSAndroid Build Coastguard Worker   const char *const lf_height_arg = argv[6];
453*77c1e3ccSAndroid Build Coastguard Worker   const char *lf_blocksize_arg = argv[7];
454*77c1e3ccSAndroid Build Coastguard Worker   exec_name = argv[0];
455*77c1e3ccSAndroid Build Coastguard Worker 
456*77c1e3ccSAndroid Build Coastguard Worker   if (argc < 8) die("Invalid number of arguments");
457*77c1e3ccSAndroid Build Coastguard Worker 
458*77c1e3ccSAndroid Build Coastguard Worker   aom_codec_iface_t *encoder = get_aom_encoder_by_short_name("av1");
459*77c1e3ccSAndroid Build Coastguard Worker   if (!encoder) die("Unsupported codec.");
460*77c1e3ccSAndroid Build Coastguard Worker 
461*77c1e3ccSAndroid Build Coastguard Worker   w = (int)strtol(width_arg, NULL, 0);
462*77c1e3ccSAndroid Build Coastguard Worker   h = (int)strtol(height_arg, NULL, 0);
463*77c1e3ccSAndroid Build Coastguard Worker   lf_width = (int)strtol(lf_width_arg, NULL, 0);
464*77c1e3ccSAndroid Build Coastguard Worker   lf_height = (int)strtol(lf_height_arg, NULL, 0);
465*77c1e3ccSAndroid Build Coastguard Worker   lf_blocksize = (int)strtol(lf_blocksize_arg, NULL, 0);
466*77c1e3ccSAndroid Build Coastguard Worker   lf_blocksize = lf_blocksize < lf_width ? lf_blocksize : lf_width;
467*77c1e3ccSAndroid Build Coastguard Worker   lf_blocksize = lf_blocksize < lf_height ? lf_blocksize : lf_height;
468*77c1e3ccSAndroid Build Coastguard Worker 
469*77c1e3ccSAndroid Build Coastguard Worker   if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0)
470*77c1e3ccSAndroid Build Coastguard Worker     die("Invalid frame size: %dx%d", w, h);
471*77c1e3ccSAndroid Build Coastguard Worker   if (lf_width <= 0 || lf_height <= 0)
472*77c1e3ccSAndroid Build Coastguard Worker     die("Invalid lf_width and/or lf_height: %dx%d", lf_width, lf_height);
473*77c1e3ccSAndroid Build Coastguard Worker   if (lf_blocksize <= 0) die("Invalid lf_blocksize: %d", lf_blocksize);
474*77c1e3ccSAndroid Build Coastguard Worker 
475*77c1e3ccSAndroid Build Coastguard Worker   if (!aom_img_alloc(&raw, AOM_IMG_FMT_I420, w, h, 32)) {
476*77c1e3ccSAndroid Build Coastguard Worker     die("Failed to allocate image.");
477*77c1e3ccSAndroid Build Coastguard Worker   }
478*77c1e3ccSAndroid Build Coastguard Worker   if (FORCE_HIGHBITDEPTH_DECODING) {
479*77c1e3ccSAndroid Build Coastguard Worker     // Need to allocate larger buffer to use hbd internal.
480*77c1e3ccSAndroid Build Coastguard Worker     aom_img_alloc(&raw_shift, AOM_IMG_FMT_I420 | AOM_IMG_FMT_HIGHBITDEPTH, w, h,
481*77c1e3ccSAndroid Build Coastguard Worker                   32);
482*77c1e3ccSAndroid Build Coastguard Worker   }
483*77c1e3ccSAndroid Build Coastguard Worker 
484*77c1e3ccSAndroid Build Coastguard Worker   printf("Using %s\n", aom_codec_iface_name(encoder));
485*77c1e3ccSAndroid Build Coastguard Worker 
486*77c1e3ccSAndroid Build Coastguard Worker   // Configuration
487*77c1e3ccSAndroid Build Coastguard Worker   res = aom_codec_enc_config_default(encoder, &cfg, 0);
488*77c1e3ccSAndroid Build Coastguard Worker   if (res) die_codec(&codec, "Failed to get default codec config.");
489*77c1e3ccSAndroid Build Coastguard Worker 
490*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_w = w;
491*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_h = h;
492*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_timebase.num = 1;
493*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_timebase.den = fps;
494*77c1e3ccSAndroid Build Coastguard Worker   cfg.rc_target_bitrate = bitrate;
495*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_error_resilient = 0;  // This is required.
496*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_lag_in_frames = 0;    // need to set this since default is 19.
497*77c1e3ccSAndroid Build Coastguard Worker   cfg.kf_mode = AOM_KF_DISABLED;
498*77c1e3ccSAndroid Build Coastguard Worker   cfg.large_scale_tile = 0;  // Only set it to 1 for camera frame encoding.
499*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_bit_depth = AOM_BITS_8;
500*77c1e3ccSAndroid Build Coastguard Worker   flags |= (cfg.g_bit_depth > AOM_BITS_8 || FORCE_HIGHBITDEPTH_DECODING)
501*77c1e3ccSAndroid Build Coastguard Worker                ? AOM_CODEC_USE_HIGHBITDEPTH
502*77c1e3ccSAndroid Build Coastguard Worker                : 0;
503*77c1e3ccSAndroid Build Coastguard Worker 
504*77c1e3ccSAndroid Build Coastguard Worker   if (!(infile = fopen(infile_arg, "rb")))
505*77c1e3ccSAndroid Build Coastguard Worker     die("Failed to open %s for reading", infile_arg);
506*77c1e3ccSAndroid Build Coastguard Worker 
507*77c1e3ccSAndroid Build Coastguard Worker   // Pass 0
508*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_pass = AOM_RC_FIRST_PASS;
509*77c1e3ccSAndroid Build Coastguard Worker   stats = pass0(&raw, infile, encoder, &cfg, lf_width, lf_height, lf_blocksize,
510*77c1e3ccSAndroid Build Coastguard Worker                 flags, &raw_shift);
511*77c1e3ccSAndroid Build Coastguard Worker 
512*77c1e3ccSAndroid Build Coastguard Worker   // Pass 1
513*77c1e3ccSAndroid Build Coastguard Worker   rewind(infile);
514*77c1e3ccSAndroid Build Coastguard Worker   cfg.g_pass = AOM_RC_LAST_PASS;
515*77c1e3ccSAndroid Build Coastguard Worker   cfg.rc_twopass_stats_in = stats;
516*77c1e3ccSAndroid Build Coastguard Worker   pass1(&raw, infile, outfile_arg, encoder, &cfg, lf_width, lf_height,
517*77c1e3ccSAndroid Build Coastguard Worker         lf_blocksize, flags, &raw_shift);
518*77c1e3ccSAndroid Build Coastguard Worker   free(stats.buf);
519*77c1e3ccSAndroid Build Coastguard Worker 
520*77c1e3ccSAndroid Build Coastguard Worker   if (FORCE_HIGHBITDEPTH_DECODING) aom_img_free(&raw_shift);
521*77c1e3ccSAndroid Build Coastguard Worker   aom_img_free(&raw);
522*77c1e3ccSAndroid Build Coastguard Worker   fclose(infile);
523*77c1e3ccSAndroid Build Coastguard Worker 
524*77c1e3ccSAndroid Build Coastguard Worker   return EXIT_SUCCESS;
525*77c1e3ccSAndroid Build Coastguard Worker }
526