xref: /aosp_15_r20/external/libopenapv/app/oapv_app_enc.c (revision abb65b4b03b69e1d508d4d9a44dcf199df16e7c3)
1*abb65b4bSAndroid Build Coastguard Worker /*
2*abb65b4bSAndroid Build Coastguard Worker  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3*abb65b4bSAndroid Build Coastguard Worker  * All Rights Reserved.
4*abb65b4bSAndroid Build Coastguard Worker  *
5*abb65b4bSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*abb65b4bSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
7*abb65b4bSAndroid Build Coastguard Worker  *
8*abb65b4bSAndroid Build Coastguard Worker  * - Redistributions of source code must retain the above copyright notice,
9*abb65b4bSAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer.
10*abb65b4bSAndroid Build Coastguard Worker  *
11*abb65b4bSAndroid Build Coastguard Worker  * - Redistributions in binary form must reproduce the above copyright notice,
12*abb65b4bSAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer in the documentation
13*abb65b4bSAndroid Build Coastguard Worker  *   and/or other materials provided with the distribution.
14*abb65b4bSAndroid Build Coastguard Worker  *
15*abb65b4bSAndroid Build Coastguard Worker  * - Neither the name of the copyright owner, nor the names of its contributors
16*abb65b4bSAndroid Build Coastguard Worker  *   may be used to endorse or promote products derived from this software
17*abb65b4bSAndroid Build Coastguard Worker  *   without specific prior written permission.
18*abb65b4bSAndroid Build Coastguard Worker  *
19*abb65b4bSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*abb65b4bSAndroid Build Coastguard Worker  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*abb65b4bSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*abb65b4bSAndroid Build Coastguard Worker  * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23*abb65b4bSAndroid Build Coastguard Worker  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*abb65b4bSAndroid Build Coastguard Worker  * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*abb65b4bSAndroid Build Coastguard Worker  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*abb65b4bSAndroid Build Coastguard Worker  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*abb65b4bSAndroid Build Coastguard Worker  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*abb65b4bSAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*abb65b4bSAndroid Build Coastguard Worker  * POSSIBILITY OF SUCH DAMAGE.
30*abb65b4bSAndroid Build Coastguard Worker  */
31*abb65b4bSAndroid Build Coastguard Worker 
32*abb65b4bSAndroid Build Coastguard Worker #include "oapv.h"
33*abb65b4bSAndroid Build Coastguard Worker #include "oapv_app_util.h"
34*abb65b4bSAndroid Build Coastguard Worker #include "oapv_app_args.h"
35*abb65b4bSAndroid Build Coastguard Worker #include "oapv_app_y4m.h"
36*abb65b4bSAndroid Build Coastguard Worker 
37*abb65b4bSAndroid Build Coastguard Worker #define MAX_BS_BUF   (128 * 1024 * 1024)
38*abb65b4bSAndroid Build Coastguard Worker #define MAX_NUM_FRMS (1)           // supports only 1-frame in an access unit
39*abb65b4bSAndroid Build Coastguard Worker #define FRM_IDX      (0)           // supports only 1-frame in an access unit
40*abb65b4bSAndroid Build Coastguard Worker #define MAX_NUM_CC   (OAPV_MAX_CC) // Max number of color componets (upto 4:4:4:4)
41*abb65b4bSAndroid Build Coastguard Worker 
42*abb65b4bSAndroid Build Coastguard Worker typedef enum _STATES {
43*abb65b4bSAndroid Build Coastguard Worker     STATE_ENCODING,
44*abb65b4bSAndroid Build Coastguard Worker     STATE_SKIPPING,
45*abb65b4bSAndroid Build Coastguard Worker     STATE_STOP
46*abb65b4bSAndroid Build Coastguard Worker } STATES;
47*abb65b4bSAndroid Build Coastguard Worker 
48*abb65b4bSAndroid Build Coastguard Worker // clang-format off
49*abb65b4bSAndroid Build Coastguard Worker 
50*abb65b4bSAndroid Build Coastguard Worker /* define various command line options as a table */
51*abb65b4bSAndroid Build Coastguard Worker static const args_opt_t enc_args_opts[] = {
52*abb65b4bSAndroid Build Coastguard Worker     {
53*abb65b4bSAndroid Build Coastguard Worker         'v',  "verbose", ARGS_VAL_TYPE_INTEGER, 0, NULL,
54*abb65b4bSAndroid Build Coastguard Worker         "verbose (log) level\n"
55*abb65b4bSAndroid Build Coastguard Worker         "      - 0: no message\n"
56*abb65b4bSAndroid Build Coastguard Worker         "      - 1: only error message\n"
57*abb65b4bSAndroid Build Coastguard Worker         "      - 2: simple messages\n"
58*abb65b4bSAndroid Build Coastguard Worker         "      - 3: frame-level messages"
59*abb65b4bSAndroid Build Coastguard Worker     },
60*abb65b4bSAndroid Build Coastguard Worker     {
61*abb65b4bSAndroid Build Coastguard Worker         'i', "input", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL,
62*abb65b4bSAndroid Build Coastguard Worker         "file name of input video"
63*abb65b4bSAndroid Build Coastguard Worker     },
64*abb65b4bSAndroid Build Coastguard Worker     {
65*abb65b4bSAndroid Build Coastguard Worker         'o', "output", ARGS_VAL_TYPE_STRING, 0, NULL,
66*abb65b4bSAndroid Build Coastguard Worker         "file name of output bitstream"
67*abb65b4bSAndroid Build Coastguard Worker     },
68*abb65b4bSAndroid Build Coastguard Worker     {
69*abb65b4bSAndroid Build Coastguard Worker         'r', "recon", ARGS_VAL_TYPE_STRING, 0, NULL,
70*abb65b4bSAndroid Build Coastguard Worker         "file name of reconstructed video"
71*abb65b4bSAndroid Build Coastguard Worker     },
72*abb65b4bSAndroid Build Coastguard Worker     {
73*abb65b4bSAndroid Build Coastguard Worker         'w',  "width", ARGS_VAL_TYPE_INTEGER | ARGS_VAL_TYPE_MANDATORY, 0, NULL,
74*abb65b4bSAndroid Build Coastguard Worker         "pixel width of input video"
75*abb65b4bSAndroid Build Coastguard Worker     },
76*abb65b4bSAndroid Build Coastguard Worker     {
77*abb65b4bSAndroid Build Coastguard Worker         'h',  "height", ARGS_VAL_TYPE_INTEGER | ARGS_VAL_TYPE_MANDATORY, 0, NULL,
78*abb65b4bSAndroid Build Coastguard Worker         "pixel height of input video"
79*abb65b4bSAndroid Build Coastguard Worker     },
80*abb65b4bSAndroid Build Coastguard Worker     {
81*abb65b4bSAndroid Build Coastguard Worker         'q',  "qp", ARGS_VAL_TYPE_INTEGER, 0, NULL,
82*abb65b4bSAndroid Build Coastguard Worker         "QP value (0~51)"
83*abb65b4bSAndroid Build Coastguard Worker     },
84*abb65b4bSAndroid Build Coastguard Worker     {
85*abb65b4bSAndroid Build Coastguard Worker         'z',  "fps", ARGS_VAL_TYPE_STRING | ARGS_VAL_TYPE_MANDATORY, 0, NULL,
86*abb65b4bSAndroid Build Coastguard Worker         "frame rate (frame per second))"
87*abb65b4bSAndroid Build Coastguard Worker     },
88*abb65b4bSAndroid Build Coastguard Worker     {
89*abb65b4bSAndroid Build Coastguard Worker         'm',  "threads", ARGS_VAL_TYPE_INTEGER, 0, NULL,
90*abb65b4bSAndroid Build Coastguard Worker         "force to use a specific number of threads"
91*abb65b4bSAndroid Build Coastguard Worker     },
92*abb65b4bSAndroid Build Coastguard Worker     {
93*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "preset", ARGS_VAL_TYPE_STRING, 0, NULL,
94*abb65b4bSAndroid Build Coastguard Worker         "encoder preset [fastest, fast, medium, slow, placebo]"
95*abb65b4bSAndroid Build Coastguard Worker     },
96*abb65b4bSAndroid Build Coastguard Worker     {
97*abb65b4bSAndroid Build Coastguard Worker         'd',  "input-depth", ARGS_VAL_TYPE_INTEGER, 0, NULL,
98*abb65b4bSAndroid Build Coastguard Worker         "input bit depth (8, 10) "
99*abb65b4bSAndroid Build Coastguard Worker     },
100*abb65b4bSAndroid Build Coastguard Worker     {
101*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "input-csp", ARGS_VAL_TYPE_INTEGER, 0, NULL,
102*abb65b4bSAndroid Build Coastguard Worker         "input color space (chroma format)\n"
103*abb65b4bSAndroid Build Coastguard Worker         "      - 0: YUV400\n"
104*abb65b4bSAndroid Build Coastguard Worker         "      - 1: YUV420\n"
105*abb65b4bSAndroid Build Coastguard Worker         "      - 2: YUV422\n"
106*abb65b4bSAndroid Build Coastguard Worker         "      - 3: YUV444\n"
107*abb65b4bSAndroid Build Coastguard Worker         "      - 4: YUV4444\n"
108*abb65b4bSAndroid Build Coastguard Worker         "      - 5: P2(Planar Y, Combined UV, 422)"
109*abb65b4bSAndroid Build Coastguard Worker     },
110*abb65b4bSAndroid Build Coastguard Worker     {
111*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "profile", ARGS_VAL_TYPE_STRING, 0, NULL,
112*abb65b4bSAndroid Build Coastguard Worker         "profile setting flag  (422-10)"
113*abb65b4bSAndroid Build Coastguard Worker     },
114*abb65b4bSAndroid Build Coastguard Worker     {
115*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "level", ARGS_VAL_TYPE_STRING, 0, NULL,
116*abb65b4bSAndroid Build Coastguard Worker         "level setting (1, 1.1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 6, 6.1, 7, 7.1)"
117*abb65b4bSAndroid Build Coastguard Worker     },
118*abb65b4bSAndroid Build Coastguard Worker     {
119*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "band", ARGS_VAL_TYPE_INTEGER, 0, NULL,
120*abb65b4bSAndroid Build Coastguard Worker         "band setting (0, 1, 2, 3)"
121*abb65b4bSAndroid Build Coastguard Worker     },
122*abb65b4bSAndroid Build Coastguard Worker     {
123*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "max-au", ARGS_VAL_TYPE_INTEGER, 0, NULL,
124*abb65b4bSAndroid Build Coastguard Worker         "maximum number of access units to be encoded"
125*abb65b4bSAndroid Build Coastguard Worker     },
126*abb65b4bSAndroid Build Coastguard Worker     {
127*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "seek", ARGS_VAL_TYPE_INTEGER, 0, NULL,
128*abb65b4bSAndroid Build Coastguard Worker         "number of skipped access units before encoding"
129*abb65b4bSAndroid Build Coastguard Worker     },
130*abb65b4bSAndroid Build Coastguard Worker     {
131*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "qp-cb-offset", ARGS_VAL_TYPE_INTEGER, 0, NULL,
132*abb65b4bSAndroid Build Coastguard Worker         "QP offset value for Cb"
133*abb65b4bSAndroid Build Coastguard Worker     },
134*abb65b4bSAndroid Build Coastguard Worker     {
135*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "qp-cr-offset", ARGS_VAL_TYPE_INTEGER, 0, NULL,
136*abb65b4bSAndroid Build Coastguard Worker         "QP offset value for Cr"
137*abb65b4bSAndroid Build Coastguard Worker     },
138*abb65b4bSAndroid Build Coastguard Worker     {
139*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "tile-w-mb", ARGS_VAL_TYPE_INTEGER, 0, NULL,
140*abb65b4bSAndroid Build Coastguard Worker         "width of tile in units of MBs"
141*abb65b4bSAndroid Build Coastguard Worker     },
142*abb65b4bSAndroid Build Coastguard Worker     {
143*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "tile-h-mb", ARGS_VAL_TYPE_INTEGER, 0, NULL,
144*abb65b4bSAndroid Build Coastguard Worker         "height of tile in units of MBs"
145*abb65b4bSAndroid Build Coastguard Worker     },
146*abb65b4bSAndroid Build Coastguard Worker     {
147*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "bitrate", ARGS_VAL_TYPE_STRING, 0, NULL,
148*abb65b4bSAndroid Build Coastguard Worker         "enable ABR rate control\n"
149*abb65b4bSAndroid Build Coastguard Worker         "      bitrate in terms of kilo-bits per second: Kbps(none,K,k), Mbps(M,m)\n"
150*abb65b4bSAndroid Build Coastguard Worker         "      ex) 100 = 100K = 0.1M"
151*abb65b4bSAndroid Build Coastguard Worker     },
152*abb65b4bSAndroid Build Coastguard Worker     {
153*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "use-filler", ARGS_VAL_TYPE_INTEGER, 0, NULL,
154*abb65b4bSAndroid Build Coastguard Worker         "user filler flag"
155*abb65b4bSAndroid Build Coastguard Worker     },
156*abb65b4bSAndroid Build Coastguard Worker     {
157*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "q-matrix-y", ARGS_VAL_TYPE_STRING, 0, NULL,
158*abb65b4bSAndroid Build Coastguard Worker         "custom quantization matrix for Y \"q1 q2 ... q63 q64\""
159*abb65b4bSAndroid Build Coastguard Worker     },
160*abb65b4bSAndroid Build Coastguard Worker     {
161*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "q-matrix-u", ARGS_VAL_TYPE_STRING, 0, NULL,
162*abb65b4bSAndroid Build Coastguard Worker         "custom quantization matrix for U \"q1 q2 ... q63 q64\""
163*abb65b4bSAndroid Build Coastguard Worker     },
164*abb65b4bSAndroid Build Coastguard Worker     {
165*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "q-matrix-v", ARGS_VAL_TYPE_STRING, 0, NULL,
166*abb65b4bSAndroid Build Coastguard Worker         "custom quantization matrix for V \"q1 q2 ... q63 q64\""
167*abb65b4bSAndroid Build Coastguard Worker     },
168*abb65b4bSAndroid Build Coastguard Worker     {
169*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "q-matrix-x", ARGS_VAL_TYPE_STRING, 0, NULL,
170*abb65b4bSAndroid Build Coastguard Worker         "custom quantization matrix for X \"q1 q2 ... q63 q64\""
171*abb65b4bSAndroid Build Coastguard Worker     },
172*abb65b4bSAndroid Build Coastguard Worker     {
173*abb65b4bSAndroid Build Coastguard Worker         ARGS_NO_KEY,  "hash", ARGS_VAL_TYPE_NONE, 0, NULL,
174*abb65b4bSAndroid Build Coastguard Worker         "embed frame hash value for conformance checking in decoding"
175*abb65b4bSAndroid Build Coastguard Worker     },
176*abb65b4bSAndroid Build Coastguard Worker     {ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, ""} /* termination */
177*abb65b4bSAndroid Build Coastguard Worker };
178*abb65b4bSAndroid Build Coastguard Worker 
179*abb65b4bSAndroid Build Coastguard Worker // clang-format on
180*abb65b4bSAndroid Build Coastguard Worker 
181*abb65b4bSAndroid Build Coastguard Worker #define NUM_ARGS_OPT ((int)(sizeof(enc_args_opts) / sizeof(enc_args_opts[0])))
182*abb65b4bSAndroid Build Coastguard Worker 
183*abb65b4bSAndroid Build Coastguard Worker typedef struct args_var {
184*abb65b4bSAndroid Build Coastguard Worker     /* variables for options */
185*abb65b4bSAndroid Build Coastguard Worker     char           fname_inp[256];
186*abb65b4bSAndroid Build Coastguard Worker     char           fname_out[256];
187*abb65b4bSAndroid Build Coastguard Worker     char           fname_rec[256];
188*abb65b4bSAndroid Build Coastguard Worker     int            max_au;
189*abb65b4bSAndroid Build Coastguard Worker     int            hash;
190*abb65b4bSAndroid Build Coastguard Worker     int            input_depth;
191*abb65b4bSAndroid Build Coastguard Worker     int            input_csp;
192*abb65b4bSAndroid Build Coastguard Worker     int            seek;
193*abb65b4bSAndroid Build Coastguard Worker     int            threads;
194*abb65b4bSAndroid Build Coastguard Worker     char           profile[32];
195*abb65b4bSAndroid Build Coastguard Worker     char           level[32];
196*abb65b4bSAndroid Build Coastguard Worker     int            band;
197*abb65b4bSAndroid Build Coastguard Worker     char           bitrate[64];
198*abb65b4bSAndroid Build Coastguard Worker     char           fps[256];
199*abb65b4bSAndroid Build Coastguard Worker     char           q_matrix_y[512];
200*abb65b4bSAndroid Build Coastguard Worker     char           q_matrix_u[512];
201*abb65b4bSAndroid Build Coastguard Worker     char           q_matrix_v[512];
202*abb65b4bSAndroid Build Coastguard Worker     char           q_matrix_x[512];
203*abb65b4bSAndroid Build Coastguard Worker     char           preset[32];
204*abb65b4bSAndroid Build Coastguard Worker     oapve_param_t *param;
205*abb65b4bSAndroid Build Coastguard Worker } args_var_t;
206*abb65b4bSAndroid Build Coastguard Worker 
args_init_vars(args_parser_t * args,oapve_param_t * param)207*abb65b4bSAndroid Build Coastguard Worker static args_var_t *args_init_vars(args_parser_t *args, oapve_param_t *param)
208*abb65b4bSAndroid Build Coastguard Worker {
209*abb65b4bSAndroid Build Coastguard Worker     args_opt_t *opts;
210*abb65b4bSAndroid Build Coastguard Worker     args_var_t *vars;
211*abb65b4bSAndroid Build Coastguard Worker 
212*abb65b4bSAndroid Build Coastguard Worker     opts = args->opts;
213*abb65b4bSAndroid Build Coastguard Worker     vars = malloc(sizeof(args_var_t));
214*abb65b4bSAndroid Build Coastguard Worker     assert_rv(vars != NULL, NULL);
215*abb65b4bSAndroid Build Coastguard Worker     memset(vars, 0, sizeof(args_var_t));
216*abb65b4bSAndroid Build Coastguard Worker 
217*abb65b4bSAndroid Build Coastguard Worker     vars->param = param;
218*abb65b4bSAndroid Build Coastguard Worker 
219*abb65b4bSAndroid Build Coastguard Worker     /*args_set_variable_by_key_long(opts, "config", args->fname_cfg);*/
220*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "input", vars->fname_inp);
221*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "output", vars->fname_out);
222*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "recon", vars->fname_rec);
223*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "max-au", &vars->max_au);
224*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "hash", &vars->hash);
225*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "verbose", &op_verbose);
226*abb65b4bSAndroid Build Coastguard Worker     op_verbose = VERBOSE_SIMPLE; /* default */
227*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "input-depth", &vars->input_depth);
228*abb65b4bSAndroid Build Coastguard Worker     vars->input_depth = 10; /* default */
229*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "input-csp", &vars->input_csp);
230*abb65b4bSAndroid Build Coastguard Worker     vars->input_csp = -1;
231*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "seek", &vars->seek);
232*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "profile", vars->profile);
233*abb65b4bSAndroid Build Coastguard Worker     strncpy(vars->profile, "422-10", sizeof(vars->profile) - 1);
234*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "level", vars->level);
235*abb65b4bSAndroid Build Coastguard Worker     strncpy(vars->level, "4.1", sizeof(vars->level) - 1);
236*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "band", &vars->band);
237*abb65b4bSAndroid Build Coastguard Worker     vars->band = 2; /* default */
238*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "bitrate", vars->bitrate);
239*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "fps", vars->fps);
240*abb65b4bSAndroid Build Coastguard Worker     strncpy(vars->fps, "60", sizeof(vars->fps) - 1);
241*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "q-matrix-y", vars->q_matrix_y);
242*abb65b4bSAndroid Build Coastguard Worker     strncpy(vars->q_matrix_y, "", sizeof(vars->q_matrix_y) - 1);
243*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "q-matrix-u", vars->q_matrix_u);
244*abb65b4bSAndroid Build Coastguard Worker     strncpy(vars->q_matrix_u, "", sizeof(vars->q_matrix_y) - 1);
245*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "q-matrix-v", vars->q_matrix_v);
246*abb65b4bSAndroid Build Coastguard Worker     strncpy(vars->q_matrix_v, "", sizeof(vars->q_matrix_y) - 1);
247*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "q-matrix-x", vars->q_matrix_x);
248*abb65b4bSAndroid Build Coastguard Worker     strncpy(vars->q_matrix_x, "", sizeof(vars->q_matrix_x) - 1);
249*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "threads", &vars->threads);
250*abb65b4bSAndroid Build Coastguard Worker     vars->threads = 1; /* default */
251*abb65b4bSAndroid Build Coastguard Worker     args_set_variable_by_key_long(opts, "preset", vars->preset);
252*abb65b4bSAndroid Build Coastguard Worker     strncpy(vars->preset, "", sizeof(vars->preset) - 1);
253*abb65b4bSAndroid Build Coastguard Worker 
254*abb65b4bSAndroid Build Coastguard Worker     ARGS_SET_PARAM_VAR_KEY(opts, param, w);
255*abb65b4bSAndroid Build Coastguard Worker     ARGS_SET_PARAM_VAR_KEY(opts, param, h);
256*abb65b4bSAndroid Build Coastguard Worker     ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, qp);
257*abb65b4bSAndroid Build Coastguard Worker     ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, use_filler);
258*abb65b4bSAndroid Build Coastguard Worker     ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, tile_w_mb);
259*abb65b4bSAndroid Build Coastguard Worker     ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, tile_h_mb);
260*abb65b4bSAndroid Build Coastguard Worker     ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, qp_cb_offset);
261*abb65b4bSAndroid Build Coastguard Worker     ARGS_SET_PARAM_VAR_KEY_LONG(opts, param, qp_cr_offset);
262*abb65b4bSAndroid Build Coastguard Worker 
263*abb65b4bSAndroid Build Coastguard Worker     return vars;
264*abb65b4bSAndroid Build Coastguard Worker }
265*abb65b4bSAndroid Build Coastguard Worker 
print_usage(const char ** argv)266*abb65b4bSAndroid Build Coastguard Worker static void print_usage(const char **argv)
267*abb65b4bSAndroid Build Coastguard Worker {
268*abb65b4bSAndroid Build Coastguard Worker     int            i;
269*abb65b4bSAndroid Build Coastguard Worker     char           str[1024];
270*abb65b4bSAndroid Build Coastguard Worker     args_parser_t *args;
271*abb65b4bSAndroid Build Coastguard Worker     args_var_t    *args_var = NULL;
272*abb65b4bSAndroid Build Coastguard Worker     oapve_param_t  default_param;
273*abb65b4bSAndroid Build Coastguard Worker 
274*abb65b4bSAndroid Build Coastguard Worker     oapve_param_default(&default_param);
275*abb65b4bSAndroid Build Coastguard Worker     args = args_create(enc_args_opts, NUM_ARGS_OPT);
276*abb65b4bSAndroid Build Coastguard Worker     if(args == NULL)
277*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
278*abb65b4bSAndroid Build Coastguard Worker     args_var = args_init_vars(args, &default_param);
279*abb65b4bSAndroid Build Coastguard Worker     if(args_var == NULL)
280*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
281*abb65b4bSAndroid Build Coastguard Worker 
282*abb65b4bSAndroid Build Coastguard Worker     logv2("Syntax: \n");
283*abb65b4bSAndroid Build Coastguard Worker     logv2("  %s -i 'input-file' [ options ] \n\n", argv[0]);
284*abb65b4bSAndroid Build Coastguard Worker 
285*abb65b4bSAndroid Build Coastguard Worker     logv2("Options:\n");
286*abb65b4bSAndroid Build Coastguard Worker     logv2("  --help\n    : list options\n");
287*abb65b4bSAndroid Build Coastguard Worker     for(i = 0; i < args->num_option; i++) {
288*abb65b4bSAndroid Build Coastguard Worker         if(args->get_help(args, i, str) < 0)
289*abb65b4bSAndroid Build Coastguard Worker             return;
290*abb65b4bSAndroid Build Coastguard Worker         logv2("%s\n", str);
291*abb65b4bSAndroid Build Coastguard Worker     }
292*abb65b4bSAndroid Build Coastguard Worker 
293*abb65b4bSAndroid Build Coastguard Worker ERR:
294*abb65b4bSAndroid Build Coastguard Worker     if(args)
295*abb65b4bSAndroid Build Coastguard Worker         args->release(args);
296*abb65b4bSAndroid Build Coastguard Worker     if(args_var)
297*abb65b4bSAndroid Build Coastguard Worker         free(args_var);
298*abb65b4bSAndroid Build Coastguard Worker }
299*abb65b4bSAndroid Build Coastguard Worker 
check_conf(oapve_cdesc_t * cdesc,args_var_t * vars)300*abb65b4bSAndroid Build Coastguard Worker static int check_conf(oapve_cdesc_t *cdesc, args_var_t *vars)
301*abb65b4bSAndroid Build Coastguard Worker {
302*abb65b4bSAndroid Build Coastguard Worker     int i;
303*abb65b4bSAndroid Build Coastguard Worker     for(i = 0; i < cdesc->max_num_frms; i++) {
304*abb65b4bSAndroid Build Coastguard Worker         if(vars->hash && strlen(vars->fname_rec) == 0) {
305*abb65b4bSAndroid Build Coastguard Worker             logerr("cannot use frame hash without reconstructed picture option!\n");
306*abb65b4bSAndroid Build Coastguard Worker             return -1;
307*abb65b4bSAndroid Build Coastguard Worker         }
308*abb65b4bSAndroid Build Coastguard Worker     }
309*abb65b4bSAndroid Build Coastguard Worker     return 0;
310*abb65b4bSAndroid Build Coastguard Worker }
311*abb65b4bSAndroid Build Coastguard Worker 
set_extra_config(oapve_t id,args_var_t * vars,oapve_param_t * param)312*abb65b4bSAndroid Build Coastguard Worker static int set_extra_config(oapve_t id, args_var_t *vars, oapve_param_t *param)
313*abb65b4bSAndroid Build Coastguard Worker {
314*abb65b4bSAndroid Build Coastguard Worker     int ret = 0, size, value;
315*abb65b4bSAndroid Build Coastguard Worker 
316*abb65b4bSAndroid Build Coastguard Worker     if(vars->hash) {
317*abb65b4bSAndroid Build Coastguard Worker         value = 1;
318*abb65b4bSAndroid Build Coastguard Worker         size = 4;
319*abb65b4bSAndroid Build Coastguard Worker         ret = oapve_config(id, OAPV_CFG_SET_USE_FRM_HASH, &value, &size);
320*abb65b4bSAndroid Build Coastguard Worker         if(OAPV_FAILED(ret)) {
321*abb65b4bSAndroid Build Coastguard Worker             logerr("failed to set config for using frame hash\n");
322*abb65b4bSAndroid Build Coastguard Worker             return -1;
323*abb65b4bSAndroid Build Coastguard Worker         }
324*abb65b4bSAndroid Build Coastguard Worker     }
325*abb65b4bSAndroid Build Coastguard Worker     return ret;
326*abb65b4bSAndroid Build Coastguard Worker }
327*abb65b4bSAndroid Build Coastguard Worker 
print_commandline(int argc,const char ** argv)328*abb65b4bSAndroid Build Coastguard Worker static void print_commandline(int argc, const char **argv)
329*abb65b4bSAndroid Build Coastguard Worker {
330*abb65b4bSAndroid Build Coastguard Worker     int i;
331*abb65b4bSAndroid Build Coastguard Worker     if(op_verbose < VERBOSE_FRAME)
332*abb65b4bSAndroid Build Coastguard Worker         return;
333*abb65b4bSAndroid Build Coastguard Worker 
334*abb65b4bSAndroid Build Coastguard Worker     logv3("Command line: ");
335*abb65b4bSAndroid Build Coastguard Worker     for(i = 0; i < argc; i++) {
336*abb65b4bSAndroid Build Coastguard Worker         logv3("%s ", argv[i]);
337*abb65b4bSAndroid Build Coastguard Worker     }
338*abb65b4bSAndroid Build Coastguard Worker     logv3("\n\n");
339*abb65b4bSAndroid Build Coastguard Worker }
340*abb65b4bSAndroid Build Coastguard Worker 
print_config(args_var_t * vars,oapve_param_t * param)341*abb65b4bSAndroid Build Coastguard Worker static void print_config(args_var_t *vars, oapve_param_t *param)
342*abb65b4bSAndroid Build Coastguard Worker {
343*abb65b4bSAndroid Build Coastguard Worker     if(op_verbose < VERBOSE_FRAME)
344*abb65b4bSAndroid Build Coastguard Worker         return;
345*abb65b4bSAndroid Build Coastguard Worker 
346*abb65b4bSAndroid Build Coastguard Worker     logv3_line("Configurations");
347*abb65b4bSAndroid Build Coastguard Worker     logv3("Input sequence : %s \n", vars->fname_inp);
348*abb65b4bSAndroid Build Coastguard Worker     if(strlen(vars->fname_out) > 0) {
349*abb65b4bSAndroid Build Coastguard Worker         logv3("Output bitstream : %s \n", vars->fname_out);
350*abb65b4bSAndroid Build Coastguard Worker     }
351*abb65b4bSAndroid Build Coastguard Worker     if(strlen(vars->fname_rec) > 0) {
352*abb65b4bSAndroid Build Coastguard Worker         logv3("Reconstructed sequence : %s \n", vars->fname_rec);
353*abb65b4bSAndroid Build Coastguard Worker     }
354*abb65b4bSAndroid Build Coastguard Worker     logv3("    profile             = %s\n", vars->profile);
355*abb65b4bSAndroid Build Coastguard Worker     logv3("    width               = %d\n", param->w);
356*abb65b4bSAndroid Build Coastguard Worker     logv3("    height              = %d\n", param->h);
357*abb65b4bSAndroid Build Coastguard Worker     logv3("    FPS                 = %.2f\n", (float)param->fps_num / param->fps_den);
358*abb65b4bSAndroid Build Coastguard Worker     logv3("    QP                  = %d\n", param->qp);
359*abb65b4bSAndroid Build Coastguard Worker     logv3("    max number of AUs   = %d\n", vars->max_au);
360*abb65b4bSAndroid Build Coastguard Worker     logv3("    rate control type   = %s\n", (param->rc_type == OAPV_RC_ABR) ? "average Bitrate" : "constant QP");
361*abb65b4bSAndroid Build Coastguard Worker     if(param->rc_type == OAPV_RC_ABR) {
362*abb65b4bSAndroid Build Coastguard Worker         logv3("    target bitrate      = %dkbps\n", param->bitrate);
363*abb65b4bSAndroid Build Coastguard Worker     }
364*abb65b4bSAndroid Build Coastguard Worker     logv3("    tile size           = %d x %d\n", param->tile_w_mb * OAPV_MB_W, param->tile_h_mb * OAPV_MB_H);
365*abb65b4bSAndroid Build Coastguard Worker }
366*abb65b4bSAndroid Build Coastguard Worker 
print_stat_au(oapve_stat_t * stat,int au_cnt,oapve_param_t * param,int max_au,double bitrate_tot,oapv_clk_t clk_au,oapv_clk_t clk_tot)367*abb65b4bSAndroid Build Coastguard Worker static void print_stat_au(oapve_stat_t *stat, int au_cnt, oapve_param_t *param, int max_au, double bitrate_tot, oapv_clk_t clk_au, oapv_clk_t clk_tot)
368*abb65b4bSAndroid Build Coastguard Worker {
369*abb65b4bSAndroid Build Coastguard Worker     if(op_verbose >= VERBOSE_FRAME) {
370*abb65b4bSAndroid Build Coastguard Worker         logv3_line("");
371*abb65b4bSAndroid Build Coastguard Worker         logv3("AU %-5d  %10d-bytes  %3d-frame(s) %10d msec\n", au_cnt, stat->write, stat->aui.num_frms, oapv_clk_msec(clk_au));
372*abb65b4bSAndroid Build Coastguard Worker     }
373*abb65b4bSAndroid Build Coastguard Worker     else {
374*abb65b4bSAndroid Build Coastguard Worker         int total_time = ((int)oapv_clk_msec(clk_tot) / 1000);
375*abb65b4bSAndroid Build Coastguard Worker         int h = total_time / 3600;
376*abb65b4bSAndroid Build Coastguard Worker         total_time = total_time % 3600;
377*abb65b4bSAndroid Build Coastguard Worker         int m = total_time / 60;
378*abb65b4bSAndroid Build Coastguard Worker         total_time = total_time % 60;
379*abb65b4bSAndroid Build Coastguard Worker         int    s = total_time;
380*abb65b4bSAndroid Build Coastguard Worker         double curr_bitrate = bitrate_tot;
381*abb65b4bSAndroid Build Coastguard Worker         curr_bitrate *= (((float)param->fps_num / param->fps_den) * 8);
382*abb65b4bSAndroid Build Coastguard Worker         curr_bitrate /= (au_cnt + 1);
383*abb65b4bSAndroid Build Coastguard Worker         curr_bitrate /= 1000;
384*abb65b4bSAndroid Build Coastguard Worker         logv2("[ %d / %d AU(s) ] [ %.2f AU/sec ] [ %.4f kbps ] [ %2dh %2dm %2ds ] \r",
385*abb65b4bSAndroid Build Coastguard Worker               au_cnt, max_au, ((float)(au_cnt + 1) * 1000) / ((float)oapv_clk_msec(clk_tot)), curr_bitrate, h, m, s);
386*abb65b4bSAndroid Build Coastguard Worker         fflush(stdout);
387*abb65b4bSAndroid Build Coastguard Worker     }
388*abb65b4bSAndroid Build Coastguard Worker }
389*abb65b4bSAndroid Build Coastguard Worker 
print_stat_frms(oapve_stat_t * stat,oapv_frms_t * ifrms,oapv_frms_t * rfrms,double psnr_avg[MAX_NUM_FRMS][MAX_NUM_CC])390*abb65b4bSAndroid Build Coastguard Worker static void print_stat_frms(oapve_stat_t *stat, oapv_frms_t *ifrms, oapv_frms_t *rfrms, double psnr_avg[MAX_NUM_FRMS][MAX_NUM_CC])
391*abb65b4bSAndroid Build Coastguard Worker {
392*abb65b4bSAndroid Build Coastguard Worker     int              i, j;
393*abb65b4bSAndroid Build Coastguard Worker     oapv_frm_info_t *finfo;
394*abb65b4bSAndroid Build Coastguard Worker     double           psnr[MAX_NUM_FRMS][MAX_NUM_CC] = { 0 };
395*abb65b4bSAndroid Build Coastguard Worker 
396*abb65b4bSAndroid Build Coastguard Worker     assert(stat->aui.num_frms == ifrms->num_frms);
397*abb65b4bSAndroid Build Coastguard Worker     assert(stat->aui.num_frms <= MAX_NUM_FRMS);
398*abb65b4bSAndroid Build Coastguard Worker 
399*abb65b4bSAndroid Build Coastguard Worker     // calculate PSNRs
400*abb65b4bSAndroid Build Coastguard Worker     if(rfrms != NULL) {
401*abb65b4bSAndroid Build Coastguard Worker         for(i = 0; i < stat->aui.num_frms; i++) {
402*abb65b4bSAndroid Build Coastguard Worker             if(rfrms->frm[i].imgb) {
403*abb65b4bSAndroid Build Coastguard Worker                 measure_psnr(ifrms->frm[i].imgb, rfrms->frm[i].imgb, psnr[i], OAPV_CS_GET_BIT_DEPTH(ifrms->frm[i].imgb->cs));
404*abb65b4bSAndroid Build Coastguard Worker                 for(j = 0; j < MAX_NUM_CC; j++) {
405*abb65b4bSAndroid Build Coastguard Worker                     psnr_avg[i][j] += psnr[i][j];
406*abb65b4bSAndroid Build Coastguard Worker                 }
407*abb65b4bSAndroid Build Coastguard Worker             }
408*abb65b4bSAndroid Build Coastguard Worker         }
409*abb65b4bSAndroid Build Coastguard Worker     }
410*abb65b4bSAndroid Build Coastguard Worker     // print verbose messages
411*abb65b4bSAndroid Build Coastguard Worker     if(op_verbose < VERBOSE_FRAME)
412*abb65b4bSAndroid Build Coastguard Worker         return;
413*abb65b4bSAndroid Build Coastguard Worker 
414*abb65b4bSAndroid Build Coastguard Worker     finfo = stat->aui.frm_info;
415*abb65b4bSAndroid Build Coastguard Worker 
416*abb65b4bSAndroid Build Coastguard Worker     for(i = 0; i < stat->aui.num_frms; i++) {
417*abb65b4bSAndroid Build Coastguard Worker         // clang-format off
418*abb65b4bSAndroid Build Coastguard Worker         const char* str_frm_type = finfo[i].pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME ? "PRIMARY"
419*abb65b4bSAndroid Build Coastguard Worker                                  : finfo[i].pbu_type == OAPV_PBU_TYPE_NON_PRIMARY_FRAME ? "NON-PRIMARY"
420*abb65b4bSAndroid Build Coastguard Worker                                  : finfo[i].pbu_type == OAPV_PBU_TYPE_PREVIEW_FRAME ? "PREVIEW"
421*abb65b4bSAndroid Build Coastguard Worker                                  : finfo[i].pbu_type == OAPV_PBU_TYPE_DEPTH_FRAME ? "DEPTH"
422*abb65b4bSAndroid Build Coastguard Worker                                  : finfo[i].pbu_type == OAPV_PBU_TYPE_ALPHA_FRAME ? "ALPHA"
423*abb65b4bSAndroid Build Coastguard Worker                                  : "UNKNOWN";
424*abb65b4bSAndroid Build Coastguard Worker         // clang-format on
425*abb65b4bSAndroid Build Coastguard Worker 
426*abb65b4bSAndroid Build Coastguard Worker         logv3("- FRM %-2d GID %-5d %-11s %9d-bytes %8.4fdB %8.4fdB %8.4fdB\n",
427*abb65b4bSAndroid Build Coastguard Worker               i, finfo[i].group_id, str_frm_type, stat->frm_size[i], psnr[i][0], psnr[i][1], psnr[i][2]);
428*abb65b4bSAndroid Build Coastguard Worker     }
429*abb65b4bSAndroid Build Coastguard Worker     fflush(stdout);
430*abb65b4bSAndroid Build Coastguard Worker     fflush(stderr);
431*abb65b4bSAndroid Build Coastguard Worker }
432*abb65b4bSAndroid Build Coastguard Worker 
kbps_str_to_int(char * str)433*abb65b4bSAndroid Build Coastguard Worker static int kbps_str_to_int(char *str)
434*abb65b4bSAndroid Build Coastguard Worker {
435*abb65b4bSAndroid Build Coastguard Worker     int kbps;
436*abb65b4bSAndroid Build Coastguard Worker     if(strchr(str, 'K') || strchr(str, 'k')) {
437*abb65b4bSAndroid Build Coastguard Worker         char *tmp = strtok(str, "Kk ");
438*abb65b4bSAndroid Build Coastguard Worker         kbps = (int)(atof(tmp));
439*abb65b4bSAndroid Build Coastguard Worker     }
440*abb65b4bSAndroid Build Coastguard Worker     else if(strchr(str, 'M') || strchr(str, 'm')) {
441*abb65b4bSAndroid Build Coastguard Worker         char *tmp = strtok(str, "Mm ");
442*abb65b4bSAndroid Build Coastguard Worker         kbps = (int)(atof(tmp) * 1000);
443*abb65b4bSAndroid Build Coastguard Worker     }
444*abb65b4bSAndroid Build Coastguard Worker     else {
445*abb65b4bSAndroid Build Coastguard Worker         kbps = atoi(str);
446*abb65b4bSAndroid Build Coastguard Worker     }
447*abb65b4bSAndroid Build Coastguard Worker     return kbps;
448*abb65b4bSAndroid Build Coastguard Worker }
449*abb65b4bSAndroid Build Coastguard Worker 
update_param(args_var_t * vars,oapve_param_t * param)450*abb65b4bSAndroid Build Coastguard Worker static int update_param(args_var_t *vars, oapve_param_t *param)
451*abb65b4bSAndroid Build Coastguard Worker {
452*abb65b4bSAndroid Build Coastguard Worker     /* update reate controller  parameters */
453*abb65b4bSAndroid Build Coastguard Worker     if(strlen(vars->bitrate) > 0) {
454*abb65b4bSAndroid Build Coastguard Worker         param->bitrate = kbps_str_to_int(vars->bitrate);
455*abb65b4bSAndroid Build Coastguard Worker         param->rc_type = OAPV_RC_ABR;
456*abb65b4bSAndroid Build Coastguard Worker     }
457*abb65b4bSAndroid Build Coastguard Worker 
458*abb65b4bSAndroid Build Coastguard Worker     /* update q_matrix */
459*abb65b4bSAndroid Build Coastguard Worker     int len_y = (int)strlen(vars->q_matrix_y);
460*abb65b4bSAndroid Build Coastguard Worker     if(len_y > 0) {
461*abb65b4bSAndroid Build Coastguard Worker         param->use_q_matrix = 1;
462*abb65b4bSAndroid Build Coastguard Worker         char *tmp = vars->q_matrix_y;
463*abb65b4bSAndroid Build Coastguard Worker         int   cnt = 0;
464*abb65b4bSAndroid Build Coastguard Worker         int   len_cnt = 0;
465*abb65b4bSAndroid Build Coastguard Worker         while(len_cnt < len_y && cnt < OAPV_BLK_D) {
466*abb65b4bSAndroid Build Coastguard Worker             sscanf(tmp, "%d", &param->q_matrix_y[cnt]);
467*abb65b4bSAndroid Build Coastguard Worker             if(param->q_matrix_y[cnt] < 1 || param->q_matrix_y[cnt] > 255) {
468*abb65b4bSAndroid Build Coastguard Worker                 logerr("input value of q_matrix_y is invalid\n");
469*abb65b4bSAndroid Build Coastguard Worker                 return -1;
470*abb65b4bSAndroid Build Coastguard Worker             }
471*abb65b4bSAndroid Build Coastguard Worker             len_cnt += (int)log10(param->q_matrix_y[cnt]) + 2;
472*abb65b4bSAndroid Build Coastguard Worker             tmp = vars->q_matrix_y + len_cnt;
473*abb65b4bSAndroid Build Coastguard Worker             cnt++;
474*abb65b4bSAndroid Build Coastguard Worker         }
475*abb65b4bSAndroid Build Coastguard Worker         if(cnt < OAPV_BLK_D) {
476*abb65b4bSAndroid Build Coastguard Worker             logerr("input number of q_matrix_y is not enough\n");
477*abb65b4bSAndroid Build Coastguard Worker             return -1;
478*abb65b4bSAndroid Build Coastguard Worker         }
479*abb65b4bSAndroid Build Coastguard Worker     }
480*abb65b4bSAndroid Build Coastguard Worker 
481*abb65b4bSAndroid Build Coastguard Worker     int len_u = (int)strlen(vars->q_matrix_u);
482*abb65b4bSAndroid Build Coastguard Worker     if(len_u > 0) {
483*abb65b4bSAndroid Build Coastguard Worker         param->use_q_matrix = 1;
484*abb65b4bSAndroid Build Coastguard Worker         char *tmp = vars->q_matrix_u;
485*abb65b4bSAndroid Build Coastguard Worker         int   cnt = 0;
486*abb65b4bSAndroid Build Coastguard Worker         int   len_cnt = 0;
487*abb65b4bSAndroid Build Coastguard Worker         while(len_cnt < len_u && cnt < OAPV_BLK_D) {
488*abb65b4bSAndroid Build Coastguard Worker             sscanf(tmp, "%d", &param->q_matrix_u[cnt]);
489*abb65b4bSAndroid Build Coastguard Worker             if(param->q_matrix_u[cnt] < 1 || param->q_matrix_u[cnt] > 255) {
490*abb65b4bSAndroid Build Coastguard Worker                 logerr("input value of q_matrix_u is invalid\n");
491*abb65b4bSAndroid Build Coastguard Worker                 return -1;
492*abb65b4bSAndroid Build Coastguard Worker             }
493*abb65b4bSAndroid Build Coastguard Worker             len_cnt += (int)log10(param->q_matrix_u[cnt]) + 2;
494*abb65b4bSAndroid Build Coastguard Worker             tmp = vars->q_matrix_u + len_cnt;
495*abb65b4bSAndroid Build Coastguard Worker             cnt++;
496*abb65b4bSAndroid Build Coastguard Worker         }
497*abb65b4bSAndroid Build Coastguard Worker         if(cnt < OAPV_BLK_D) {
498*abb65b4bSAndroid Build Coastguard Worker             logerr("input number of q_matrix_u is not enough\n");
499*abb65b4bSAndroid Build Coastguard Worker             return -1;
500*abb65b4bSAndroid Build Coastguard Worker         }
501*abb65b4bSAndroid Build Coastguard Worker     }
502*abb65b4bSAndroid Build Coastguard Worker 
503*abb65b4bSAndroid Build Coastguard Worker     int len_v = (int)strlen(vars->q_matrix_v);
504*abb65b4bSAndroid Build Coastguard Worker     if(len_v > 0) {
505*abb65b4bSAndroid Build Coastguard Worker         param->use_q_matrix = 1;
506*abb65b4bSAndroid Build Coastguard Worker         char *tmp = vars->q_matrix_v;
507*abb65b4bSAndroid Build Coastguard Worker         int   cnt = 0;
508*abb65b4bSAndroid Build Coastguard Worker         int   len_cnt = 0;
509*abb65b4bSAndroid Build Coastguard Worker         while(len_cnt < len_v && cnt < OAPV_BLK_D) {
510*abb65b4bSAndroid Build Coastguard Worker             sscanf(tmp, "%d", &param->q_matrix_v[cnt]);
511*abb65b4bSAndroid Build Coastguard Worker             if(param->q_matrix_v[cnt] < 1 || param->q_matrix_v[cnt] > 255) {
512*abb65b4bSAndroid Build Coastguard Worker                 logerr("input value of q_matrix_v is invalid\n");
513*abb65b4bSAndroid Build Coastguard Worker                 return -1;
514*abb65b4bSAndroid Build Coastguard Worker             }
515*abb65b4bSAndroid Build Coastguard Worker             len_cnt += (int)log10(param->q_matrix_v[cnt]) + 2;
516*abb65b4bSAndroid Build Coastguard Worker             tmp = vars->q_matrix_v + len_cnt;
517*abb65b4bSAndroid Build Coastguard Worker             cnt++;
518*abb65b4bSAndroid Build Coastguard Worker         }
519*abb65b4bSAndroid Build Coastguard Worker         if(cnt < OAPV_BLK_D) {
520*abb65b4bSAndroid Build Coastguard Worker             logerr("input number of q_matrix_v is not enough\n");
521*abb65b4bSAndroid Build Coastguard Worker             return -1;
522*abb65b4bSAndroid Build Coastguard Worker         }
523*abb65b4bSAndroid Build Coastguard Worker     }
524*abb65b4bSAndroid Build Coastguard Worker 
525*abb65b4bSAndroid Build Coastguard Worker     int len_x = (int)strlen(vars->q_matrix_x);
526*abb65b4bSAndroid Build Coastguard Worker     if (len_x > 0) {
527*abb65b4bSAndroid Build Coastguard Worker         param->use_q_matrix = 1;
528*abb65b4bSAndroid Build Coastguard Worker         char* tmp = vars->q_matrix_x;
529*abb65b4bSAndroid Build Coastguard Worker         int   cnt = 0;
530*abb65b4bSAndroid Build Coastguard Worker         int   len_cnt = 0;
531*abb65b4bSAndroid Build Coastguard Worker         while (len_cnt < len_x && cnt < OAPV_BLK_D) {
532*abb65b4bSAndroid Build Coastguard Worker             sscanf(tmp, "%d", &param->q_matrix_x[cnt]);
533*abb65b4bSAndroid Build Coastguard Worker             if (param->q_matrix_x[cnt] < 1 || param->q_matrix_x[cnt] > 255) {
534*abb65b4bSAndroid Build Coastguard Worker                 logerr("input value of q_matrix_x is invalid\n");
535*abb65b4bSAndroid Build Coastguard Worker                 return -1;
536*abb65b4bSAndroid Build Coastguard Worker             }
537*abb65b4bSAndroid Build Coastguard Worker             len_cnt += (int)log10(param->q_matrix_x[cnt]) + 2;
538*abb65b4bSAndroid Build Coastguard Worker             tmp = vars->q_matrix_x + len_cnt;
539*abb65b4bSAndroid Build Coastguard Worker             cnt++;
540*abb65b4bSAndroid Build Coastguard Worker         }
541*abb65b4bSAndroid Build Coastguard Worker         if (cnt < OAPV_BLK_D) {
542*abb65b4bSAndroid Build Coastguard Worker             logerr("input number of q_matrix_x is not enough\n");
543*abb65b4bSAndroid Build Coastguard Worker             return -1;
544*abb65b4bSAndroid Build Coastguard Worker         }
545*abb65b4bSAndroid Build Coastguard Worker     }
546*abb65b4bSAndroid Build Coastguard Worker 
547*abb65b4bSAndroid Build Coastguard Worker     if(param->use_q_matrix) {
548*abb65b4bSAndroid Build Coastguard Worker         if(len_y == 0) {
549*abb65b4bSAndroid Build Coastguard Worker             for(int i = 0; i < OAPV_BLK_D; i++) {
550*abb65b4bSAndroid Build Coastguard Worker                 param->q_matrix_y[i] = 16;
551*abb65b4bSAndroid Build Coastguard Worker             }
552*abb65b4bSAndroid Build Coastguard Worker         }
553*abb65b4bSAndroid Build Coastguard Worker 
554*abb65b4bSAndroid Build Coastguard Worker         if(len_u == 0) {
555*abb65b4bSAndroid Build Coastguard Worker             for(int i = 0; i < OAPV_BLK_D; i++) {
556*abb65b4bSAndroid Build Coastguard Worker                 param->q_matrix_u[i] = 16;
557*abb65b4bSAndroid Build Coastguard Worker             }
558*abb65b4bSAndroid Build Coastguard Worker         }
559*abb65b4bSAndroid Build Coastguard Worker 
560*abb65b4bSAndroid Build Coastguard Worker         if(len_v == 0) {
561*abb65b4bSAndroid Build Coastguard Worker             for(int i = 0; i < OAPV_BLK_D; i++) {
562*abb65b4bSAndroid Build Coastguard Worker                 param->q_matrix_v[i] = 16;
563*abb65b4bSAndroid Build Coastguard Worker             }
564*abb65b4bSAndroid Build Coastguard Worker         }
565*abb65b4bSAndroid Build Coastguard Worker 
566*abb65b4bSAndroid Build Coastguard Worker         if (len_x == 0) {
567*abb65b4bSAndroid Build Coastguard Worker             for (int i = 0; i < OAPV_BLK_D; i++) {
568*abb65b4bSAndroid Build Coastguard Worker                 param->q_matrix_x[i] = 16;
569*abb65b4bSAndroid Build Coastguard Worker             }
570*abb65b4bSAndroid Build Coastguard Worker         }
571*abb65b4bSAndroid Build Coastguard Worker     }
572*abb65b4bSAndroid Build Coastguard Worker 
573*abb65b4bSAndroid Build Coastguard Worker     param->csp = vars->input_csp;
574*abb65b4bSAndroid Build Coastguard Worker 
575*abb65b4bSAndroid Build Coastguard Worker     /* update level idc */
576*abb65b4bSAndroid Build Coastguard Worker     double tmp_level = 0;
577*abb65b4bSAndroid Build Coastguard Worker     sscanf(vars->level, "%lf", &tmp_level);
578*abb65b4bSAndroid Build Coastguard Worker     param->level_idc = tmp_level * 30;
579*abb65b4bSAndroid Build Coastguard Worker     /* update band idc */
580*abb65b4bSAndroid Build Coastguard Worker     param->band_idc = vars->band;
581*abb65b4bSAndroid Build Coastguard Worker 
582*abb65b4bSAndroid Build Coastguard Worker     /* update fps */
583*abb65b4bSAndroid Build Coastguard Worker     if(strpbrk(vars->fps, "/") != NULL) {
584*abb65b4bSAndroid Build Coastguard Worker         sscanf(vars->fps, "%d/%d", &param->fps_num, &param->fps_den);
585*abb65b4bSAndroid Build Coastguard Worker     }
586*abb65b4bSAndroid Build Coastguard Worker     else if(strpbrk(vars->fps, ".") != NULL) {
587*abb65b4bSAndroid Build Coastguard Worker         float tmp_fps = 0;
588*abb65b4bSAndroid Build Coastguard Worker         sscanf(vars->fps, "%f", &tmp_fps);
589*abb65b4bSAndroid Build Coastguard Worker         param->fps_num = tmp_fps * 10000;
590*abb65b4bSAndroid Build Coastguard Worker         param->fps_den = 10000;
591*abb65b4bSAndroid Build Coastguard Worker     }
592*abb65b4bSAndroid Build Coastguard Worker     else {
593*abb65b4bSAndroid Build Coastguard Worker         sscanf(vars->fps, "%d", &param->fps_num);
594*abb65b4bSAndroid Build Coastguard Worker         param->fps_den = 1;
595*abb65b4bSAndroid Build Coastguard Worker     }
596*abb65b4bSAndroid Build Coastguard Worker 
597*abb65b4bSAndroid Build Coastguard Worker     if(strlen(vars->preset) > 0) {
598*abb65b4bSAndroid Build Coastguard Worker         if(strcmp(vars->preset, "fastest") == 0) {
599*abb65b4bSAndroid Build Coastguard Worker             param->preset = OAPV_PRESET_FASTEST;
600*abb65b4bSAndroid Build Coastguard Worker         }
601*abb65b4bSAndroid Build Coastguard Worker         else if(strcmp(vars->preset, "fast") == 0) {
602*abb65b4bSAndroid Build Coastguard Worker             param->preset = OAPV_PRESET_FAST;
603*abb65b4bSAndroid Build Coastguard Worker         }
604*abb65b4bSAndroid Build Coastguard Worker         else if(strcmp(vars->preset, "medium") == 0) {
605*abb65b4bSAndroid Build Coastguard Worker             param->preset = OAPV_PRESET_MEDIUM;
606*abb65b4bSAndroid Build Coastguard Worker         }
607*abb65b4bSAndroid Build Coastguard Worker         else if(strcmp(vars->preset, "slow") == 0) {
608*abb65b4bSAndroid Build Coastguard Worker             param->preset = OAPV_PRESET_SLOW;
609*abb65b4bSAndroid Build Coastguard Worker         }
610*abb65b4bSAndroid Build Coastguard Worker         else if(strcmp(vars->preset, "placebo") == 0) {
611*abb65b4bSAndroid Build Coastguard Worker             param->preset = OAPV_PRESET_PLACEBO;
612*abb65b4bSAndroid Build Coastguard Worker         }
613*abb65b4bSAndroid Build Coastguard Worker         else {
614*abb65b4bSAndroid Build Coastguard Worker             logerr("input value of preset is invalid\n");
615*abb65b4bSAndroid Build Coastguard Worker             return -1;
616*abb65b4bSAndroid Build Coastguard Worker         }
617*abb65b4bSAndroid Build Coastguard Worker     }
618*abb65b4bSAndroid Build Coastguard Worker     else {
619*abb65b4bSAndroid Build Coastguard Worker         param->preset = OAPV_PRESET_DEFAULT;
620*abb65b4bSAndroid Build Coastguard Worker     }
621*abb65b4bSAndroid Build Coastguard Worker 
622*abb65b4bSAndroid Build Coastguard Worker     return 0;
623*abb65b4bSAndroid Build Coastguard Worker }
624*abb65b4bSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)625*abb65b4bSAndroid Build Coastguard Worker int main(int argc, const char **argv)
626*abb65b4bSAndroid Build Coastguard Worker {
627*abb65b4bSAndroid Build Coastguard Worker     args_parser_t *args = NULL;
628*abb65b4bSAndroid Build Coastguard Worker     args_var_t    *args_var = NULL;
629*abb65b4bSAndroid Build Coastguard Worker     STATES         state = STATE_ENCODING;
630*abb65b4bSAndroid Build Coastguard Worker     unsigned char *bs_buf = NULL;
631*abb65b4bSAndroid Build Coastguard Worker     FILE          *fp_inp = NULL;
632*abb65b4bSAndroid Build Coastguard Worker     oapve_t        id = NULL;
633*abb65b4bSAndroid Build Coastguard Worker     oapvm_t        mid = NULL;
634*abb65b4bSAndroid Build Coastguard Worker     oapve_cdesc_t  cdesc;
635*abb65b4bSAndroid Build Coastguard Worker     oapve_param_t *param = NULL;
636*abb65b4bSAndroid Build Coastguard Worker     oapv_bitb_t    bitb;
637*abb65b4bSAndroid Build Coastguard Worker     oapve_stat_t   stat;
638*abb65b4bSAndroid Build Coastguard Worker     oapv_imgb_t   *imgb_r = NULL; // image buffer for read
639*abb65b4bSAndroid Build Coastguard Worker     oapv_imgb_t   *imgb_w = NULL; // image buffer for write
640*abb65b4bSAndroid Build Coastguard Worker     oapv_imgb_t   *imgb_i = NULL; // image buffer for input
641*abb65b4bSAndroid Build Coastguard Worker     oapv_imgb_t   *imgb_o = NULL; // image buffer for output
642*abb65b4bSAndroid Build Coastguard Worker     oapv_frms_t    ifrms = { 0 }; // frames for input
643*abb65b4bSAndroid Build Coastguard Worker     oapv_frms_t    rfrms = { 0 }; // frames for reconstruction
644*abb65b4bSAndroid Build Coastguard Worker     int            ret;
645*abb65b4bSAndroid Build Coastguard Worker     oapv_clk_t     clk_beg, clk_end, clk_tot;
646*abb65b4bSAndroid Build Coastguard Worker     oapv_mtime_t   au_cnt, au_skip;
647*abb65b4bSAndroid Build Coastguard Worker     double         bitrate_tot; // total bitrate (byte)
648*abb65b4bSAndroid Build Coastguard Worker     double         psnr_avg[MAX_NUM_FRMS][MAX_NUM_CC] = { 0 };
649*abb65b4bSAndroid Build Coastguard Worker     int            is_y4m;
650*abb65b4bSAndroid Build Coastguard Worker     y4m_params_t   y4m;
651*abb65b4bSAndroid Build Coastguard Worker     int            is_out = 0, is_rec = 0;
652*abb65b4bSAndroid Build Coastguard Worker     char          *errstr = NULL;
653*abb65b4bSAndroid Build Coastguard Worker     int            cfmt;                      // color format
654*abb65b4bSAndroid Build Coastguard Worker     const int      num_frames = MAX_NUM_FRMS; // number of frames in an access unit
655*abb65b4bSAndroid Build Coastguard Worker 
656*abb65b4bSAndroid Build Coastguard Worker     /* help message */
657*abb65b4bSAndroid Build Coastguard Worker     if(argc < 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
658*abb65b4bSAndroid Build Coastguard Worker         print_usage(argv);
659*abb65b4bSAndroid Build Coastguard Worker         return 0;
660*abb65b4bSAndroid Build Coastguard Worker     }
661*abb65b4bSAndroid Build Coastguard Worker 
662*abb65b4bSAndroid Build Coastguard Worker     /* set default parameters */
663*abb65b4bSAndroid Build Coastguard Worker     memset(&cdesc, 0, sizeof(oapve_cdesc_t));
664*abb65b4bSAndroid Build Coastguard Worker     param = &cdesc.param[FRM_IDX];
665*abb65b4bSAndroid Build Coastguard Worker     ret = oapve_param_default(param);
666*abb65b4bSAndroid Build Coastguard Worker     if(OAPV_FAILED(ret)) {
667*abb65b4bSAndroid Build Coastguard Worker         logerr("cannot set default parameter\n");
668*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
669*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
670*abb65b4bSAndroid Build Coastguard Worker     }
671*abb65b4bSAndroid Build Coastguard Worker     /* parse command line */
672*abb65b4bSAndroid Build Coastguard Worker     args = args_create(enc_args_opts, NUM_ARGS_OPT);
673*abb65b4bSAndroid Build Coastguard Worker     if(args == NULL) {
674*abb65b4bSAndroid Build Coastguard Worker         logerr("cannot create argument parser\n");
675*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
676*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
677*abb65b4bSAndroid Build Coastguard Worker     }
678*abb65b4bSAndroid Build Coastguard Worker     args_var = args_init_vars(args, param);
679*abb65b4bSAndroid Build Coastguard Worker     if(args_var == NULL) {
680*abb65b4bSAndroid Build Coastguard Worker         logerr("cannot initialize argument parser\n");
681*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
682*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
683*abb65b4bSAndroid Build Coastguard Worker     }
684*abb65b4bSAndroid Build Coastguard Worker     if(args->parse(args, argc, argv, &errstr)) {
685*abb65b4bSAndroid Build Coastguard Worker         logerr("command parsing error (%s)\n", errstr);
686*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
687*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
688*abb65b4bSAndroid Build Coastguard Worker     }
689*abb65b4bSAndroid Build Coastguard Worker     // print logo
690*abb65b4bSAndroid Build Coastguard Worker     logv2("  ____                ___   ___ _   __\n");
691*abb65b4bSAndroid Build Coastguard Worker     logv2(" / __ \\___  ___ ___  / _ | / _ \\ | / / Encoder\n");
692*abb65b4bSAndroid Build Coastguard Worker     logv2("/ /_/ / _ \\/ -_) _ \\/ __ |/ ___/ |/ / \n");
693*abb65b4bSAndroid Build Coastguard Worker     logv2("\\____/ .__/\\__/_//_/_/ |_/_/   |___/  \n");
694*abb65b4bSAndroid Build Coastguard Worker     logv2("    /_/                               \n");
695*abb65b4bSAndroid Build Coastguard Worker     logv2("\n");
696*abb65b4bSAndroid Build Coastguard Worker 
697*abb65b4bSAndroid Build Coastguard Worker     // print command line string for information
698*abb65b4bSAndroid Build Coastguard Worker     print_commandline(argc, argv);
699*abb65b4bSAndroid Build Coastguard Worker 
700*abb65b4bSAndroid Build Coastguard Worker     // check mandatory arguments
701*abb65b4bSAndroid Build Coastguard Worker     if(args->check_mandatory(args, &errstr)) {
702*abb65b4bSAndroid Build Coastguard Worker         logerr("'--%s' argument is mandatory\n", errstr);
703*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
704*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
705*abb65b4bSAndroid Build Coastguard Worker     }
706*abb65b4bSAndroid Build Coastguard Worker 
707*abb65b4bSAndroid Build Coastguard Worker     /* try to open input file */
708*abb65b4bSAndroid Build Coastguard Worker     fp_inp = fopen(args_var->fname_inp, "rb");
709*abb65b4bSAndroid Build Coastguard Worker     if(fp_inp == NULL) {
710*abb65b4bSAndroid Build Coastguard Worker         logerr("ERROR: cannot open input file = (%s)\n", args_var->fname_inp);
711*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
712*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
713*abb65b4bSAndroid Build Coastguard Worker     }
714*abb65b4bSAndroid Build Coastguard Worker 
715*abb65b4bSAndroid Build Coastguard Worker     /* y4m header parsing  */
716*abb65b4bSAndroid Build Coastguard Worker     is_y4m = y4m_test(fp_inp);
717*abb65b4bSAndroid Build Coastguard Worker     if(is_y4m) {
718*abb65b4bSAndroid Build Coastguard Worker         if(y4m_header_parser(fp_inp, &y4m)) {
719*abb65b4bSAndroid Build Coastguard Worker             logerr("This y4m is not supported (%s)\n", args_var->fname_inp);
720*abb65b4bSAndroid Build Coastguard Worker             ret = -1;
721*abb65b4bSAndroid Build Coastguard Worker             goto ERR;
722*abb65b4bSAndroid Build Coastguard Worker         }
723*abb65b4bSAndroid Build Coastguard Worker         y4m_update_param(args, &y4m);
724*abb65b4bSAndroid Build Coastguard Worker         cfmt = y4m.color_format;
725*abb65b4bSAndroid Build Coastguard Worker         // clang-format off
726*abb65b4bSAndroid Build Coastguard Worker         args_var->input_csp = (cfmt == OAPV_CF_YCBCR400 ? 0 : \
727*abb65b4bSAndroid Build Coastguard Worker             (cfmt == OAPV_CF_YCBCR420 ? 1 : \
728*abb65b4bSAndroid Build Coastguard Worker             (cfmt == OAPV_CF_YCBCR422 ? 2 : \
729*abb65b4bSAndroid Build Coastguard Worker             (cfmt == OAPV_CF_YCBCR444 ? 3 : \
730*abb65b4bSAndroid Build Coastguard Worker             (cfmt == OAPV_CF_YCBCR4444 ? 4 : \
731*abb65b4bSAndroid Build Coastguard Worker             (cfmt == OAPV_CF_PLANAR2 ? 5 : -1))))));
732*abb65b4bSAndroid Build Coastguard Worker         // clang-format on
733*abb65b4bSAndroid Build Coastguard Worker 
734*abb65b4bSAndroid Build Coastguard Worker         if(args_var->input_csp != -1) {
735*abb65b4bSAndroid Build Coastguard Worker             // force "input-csp" argument has set
736*abb65b4bSAndroid Build Coastguard Worker             args->set_flag(args, "input-csp", 1);
737*abb65b4bSAndroid Build Coastguard Worker         }
738*abb65b4bSAndroid Build Coastguard Worker     }
739*abb65b4bSAndroid Build Coastguard Worker     else {
740*abb65b4bSAndroid Build Coastguard Worker         // clang-format off
741*abb65b4bSAndroid Build Coastguard Worker         cfmt = (args_var->input_csp == 0 ? OAPV_CF_YCBCR400 : \
742*abb65b4bSAndroid Build Coastguard Worker             (args_var->input_csp == 1 ? OAPV_CF_YCBCR420 : \
743*abb65b4bSAndroid Build Coastguard Worker             (args_var->input_csp == 2 ? OAPV_CF_YCBCR422 : \
744*abb65b4bSAndroid Build Coastguard Worker             (args_var->input_csp == 3 ? OAPV_CF_YCBCR444  : \
745*abb65b4bSAndroid Build Coastguard Worker             (args_var->input_csp == 4 ? OAPV_CF_YCBCR4444 : \
746*abb65b4bSAndroid Build Coastguard Worker             (args_var->input_csp == 5 ? OAPV_CF_PLANAR2   : OAPV_CF_UNKNOWN))))));
747*abb65b4bSAndroid Build Coastguard Worker         // clang-format on
748*abb65b4bSAndroid Build Coastguard Worker     }
749*abb65b4bSAndroid Build Coastguard Worker     if(args_var->input_csp == -1) {
750*abb65b4bSAndroid Build Coastguard Worker         logerr("Unknown input color space. set '--input-csp' argument\n");
751*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
752*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
753*abb65b4bSAndroid Build Coastguard Worker     }
754*abb65b4bSAndroid Build Coastguard Worker 
755*abb65b4bSAndroid Build Coastguard Worker     /* update parameters */
756*abb65b4bSAndroid Build Coastguard Worker     if(update_param(args_var, param)) {
757*abb65b4bSAndroid Build Coastguard Worker         logerr("parameters is not proper\n");
758*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
759*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
760*abb65b4bSAndroid Build Coastguard Worker     }
761*abb65b4bSAndroid Build Coastguard Worker 
762*abb65b4bSAndroid Build Coastguard Worker     cdesc.max_bs_buf_size = MAX_BS_BUF; /* maximum bitstream buffer size */
763*abb65b4bSAndroid Build Coastguard Worker     cdesc.max_num_frms = MAX_NUM_FRMS;
764*abb65b4bSAndroid Build Coastguard Worker     cdesc.threads = args_var->threads;
765*abb65b4bSAndroid Build Coastguard Worker 
766*abb65b4bSAndroid Build Coastguard Worker     if(check_conf(&cdesc, args_var)) {
767*abb65b4bSAndroid Build Coastguard Worker         logerr("invalid configuration\n");
768*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
769*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
770*abb65b4bSAndroid Build Coastguard Worker     }
771*abb65b4bSAndroid Build Coastguard Worker 
772*abb65b4bSAndroid Build Coastguard Worker     if(strlen(args_var->fname_out) > 0) {
773*abb65b4bSAndroid Build Coastguard Worker         clear_data(args_var->fname_out);
774*abb65b4bSAndroid Build Coastguard Worker         is_out = 1;
775*abb65b4bSAndroid Build Coastguard Worker     }
776*abb65b4bSAndroid Build Coastguard Worker 
777*abb65b4bSAndroid Build Coastguard Worker     if(strlen(args_var->fname_rec) > 0) {
778*abb65b4bSAndroid Build Coastguard Worker         clear_data(args_var->fname_rec);
779*abb65b4bSAndroid Build Coastguard Worker         is_rec = 1;
780*abb65b4bSAndroid Build Coastguard Worker     }
781*abb65b4bSAndroid Build Coastguard Worker 
782*abb65b4bSAndroid Build Coastguard Worker     /* allocate bitstream buffer */
783*abb65b4bSAndroid Build Coastguard Worker     bs_buf = (unsigned char *)malloc(MAX_BS_BUF);
784*abb65b4bSAndroid Build Coastguard Worker     if(bs_buf == NULL) {
785*abb65b4bSAndroid Build Coastguard Worker         logerr("cannot allocate bitstream buffer, size=%d", MAX_BS_BUF);
786*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
787*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
788*abb65b4bSAndroid Build Coastguard Worker     }
789*abb65b4bSAndroid Build Coastguard Worker 
790*abb65b4bSAndroid Build Coastguard Worker     /* create encoder */
791*abb65b4bSAndroid Build Coastguard Worker     id = oapve_create(&cdesc, NULL);
792*abb65b4bSAndroid Build Coastguard Worker     if(id == NULL) {
793*abb65b4bSAndroid Build Coastguard Worker         logerr("cannot create OAPV encoder\n");
794*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
795*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
796*abb65b4bSAndroid Build Coastguard Worker     }
797*abb65b4bSAndroid Build Coastguard Worker 
798*abb65b4bSAndroid Build Coastguard Worker     /* create metadata handler */
799*abb65b4bSAndroid Build Coastguard Worker     mid = oapvm_create(&ret);
800*abb65b4bSAndroid Build Coastguard Worker     if(mid == NULL || OAPV_FAILED(ret)) {
801*abb65b4bSAndroid Build Coastguard Worker         logerr("cannot create OAPV metadata handler\n");
802*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
803*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
804*abb65b4bSAndroid Build Coastguard Worker     }
805*abb65b4bSAndroid Build Coastguard Worker 
806*abb65b4bSAndroid Build Coastguard Worker     if(set_extra_config(id, args_var, param)) {
807*abb65b4bSAndroid Build Coastguard Worker         logerr("cannot set extra configurations\n");
808*abb65b4bSAndroid Build Coastguard Worker         ret = -1;
809*abb65b4bSAndroid Build Coastguard Worker         goto ERR;
810*abb65b4bSAndroid Build Coastguard Worker     }
811*abb65b4bSAndroid Build Coastguard Worker 
812*abb65b4bSAndroid Build Coastguard Worker     print_config(args_var, param);
813*abb65b4bSAndroid Build Coastguard Worker 
814*abb65b4bSAndroid Build Coastguard Worker     bitrate_tot = 0;
815*abb65b4bSAndroid Build Coastguard Worker     bitb.addr = bs_buf;
816*abb65b4bSAndroid Build Coastguard Worker     bitb.bsize = MAX_BS_BUF;
817*abb65b4bSAndroid Build Coastguard Worker 
818*abb65b4bSAndroid Build Coastguard Worker     if(args_var->seek > 0) {
819*abb65b4bSAndroid Build Coastguard Worker         state = STATE_SKIPPING;
820*abb65b4bSAndroid Build Coastguard Worker     }
821*abb65b4bSAndroid Build Coastguard Worker 
822*abb65b4bSAndroid Build Coastguard Worker     clk_tot = 0;
823*abb65b4bSAndroid Build Coastguard Worker     au_cnt = 0;
824*abb65b4bSAndroid Build Coastguard Worker     au_skip = 0;
825*abb65b4bSAndroid Build Coastguard Worker 
826*abb65b4bSAndroid Build Coastguard Worker     // create input and reconstruction image buffers
827*abb65b4bSAndroid Build Coastguard Worker     memset(&ifrms, 0, sizeof(oapv_frm_t));
828*abb65b4bSAndroid Build Coastguard Worker     memset(&rfrms, 0, sizeof(oapv_frm_t));
829*abb65b4bSAndroid Build Coastguard Worker 
830*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < num_frames; i++) {
831*abb65b4bSAndroid Build Coastguard Worker         if(args_var->input_depth == 10) {
832*abb65b4bSAndroid Build Coastguard Worker             ifrms.frm[i].imgb = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, args_var->input_depth, 0));
833*abb65b4bSAndroid Build Coastguard Worker         }
834*abb65b4bSAndroid Build Coastguard Worker         else {
835*abb65b4bSAndroid Build Coastguard Worker             imgb_r = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, args_var->input_depth, 0));
836*abb65b4bSAndroid Build Coastguard Worker             ifrms.frm[i].imgb = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, 10, 0));
837*abb65b4bSAndroid Build Coastguard Worker         }
838*abb65b4bSAndroid Build Coastguard Worker 
839*abb65b4bSAndroid Build Coastguard Worker         if(is_rec) {
840*abb65b4bSAndroid Build Coastguard Worker             if(args_var->input_depth == 10) {
841*abb65b4bSAndroid Build Coastguard Worker                 rfrms.frm[i].imgb = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, args_var->input_depth, 0));
842*abb65b4bSAndroid Build Coastguard Worker             }
843*abb65b4bSAndroid Build Coastguard Worker             else {
844*abb65b4bSAndroid Build Coastguard Worker                 imgb_w = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, args_var->input_depth, 0));
845*abb65b4bSAndroid Build Coastguard Worker                 rfrms.frm[i].imgb = imgb_create(param->w, param->h, OAPV_CS_SET(cfmt, 10, 0));
846*abb65b4bSAndroid Build Coastguard Worker             }
847*abb65b4bSAndroid Build Coastguard Worker             rfrms.num_frms++;
848*abb65b4bSAndroid Build Coastguard Worker         }
849*abb65b4bSAndroid Build Coastguard Worker         ifrms.num_frms++;
850*abb65b4bSAndroid Build Coastguard Worker     }
851*abb65b4bSAndroid Build Coastguard Worker 
852*abb65b4bSAndroid Build Coastguard Worker     /* encode pictures *******************************************************/
853*abb65b4bSAndroid Build Coastguard Worker     while(args_var->max_au == 0 || (au_cnt < args_var->max_au)) {
854*abb65b4bSAndroid Build Coastguard Worker         for(int i = 0; i < num_frames; i++) {
855*abb65b4bSAndroid Build Coastguard Worker             if(args_var->input_depth == 10) {
856*abb65b4bSAndroid Build Coastguard Worker                 imgb_i = ifrms.frm[i].imgb;
857*abb65b4bSAndroid Build Coastguard Worker             }
858*abb65b4bSAndroid Build Coastguard Worker             else {
859*abb65b4bSAndroid Build Coastguard Worker                 imgb_i = imgb_r;
860*abb65b4bSAndroid Build Coastguard Worker             }
861*abb65b4bSAndroid Build Coastguard Worker             ret = imgb_read(fp_inp, imgb_i, param->w, param->h, is_y4m);
862*abb65b4bSAndroid Build Coastguard Worker             if(ret < 0) {
863*abb65b4bSAndroid Build Coastguard Worker                 logv3("reached out the end of input file\n");
864*abb65b4bSAndroid Build Coastguard Worker                 ret = OAPV_OK;
865*abb65b4bSAndroid Build Coastguard Worker                 state = STATE_STOP;
866*abb65b4bSAndroid Build Coastguard Worker                 break;
867*abb65b4bSAndroid Build Coastguard Worker             }
868*abb65b4bSAndroid Build Coastguard Worker             if(args_var->input_depth != 10) {
869*abb65b4bSAndroid Build Coastguard Worker                 imgb_cpy(ifrms.frm[i].imgb, imgb_i);
870*abb65b4bSAndroid Build Coastguard Worker             }
871*abb65b4bSAndroid Build Coastguard Worker             ifrms.frm[i].group_id = 1; // FIX-ME : need to set properly in case of multi-frame
872*abb65b4bSAndroid Build Coastguard Worker             ifrms.frm[i].pbu_type = OAPV_PBU_TYPE_PRIMARY_FRAME;
873*abb65b4bSAndroid Build Coastguard Worker         }
874*abb65b4bSAndroid Build Coastguard Worker 
875*abb65b4bSAndroid Build Coastguard Worker         if(state == STATE_ENCODING) {
876*abb65b4bSAndroid Build Coastguard Worker             /* encoding */
877*abb65b4bSAndroid Build Coastguard Worker             clk_beg = oapv_clk_get();
878*abb65b4bSAndroid Build Coastguard Worker 
879*abb65b4bSAndroid Build Coastguard Worker             ret = oapve_encode(id, &ifrms, mid, &bitb, &stat, &rfrms);
880*abb65b4bSAndroid Build Coastguard Worker 
881*abb65b4bSAndroid Build Coastguard Worker             clk_end = oapv_clk_from(clk_beg);
882*abb65b4bSAndroid Build Coastguard Worker             clk_tot += clk_end;
883*abb65b4bSAndroid Build Coastguard Worker 
884*abb65b4bSAndroid Build Coastguard Worker             bitrate_tot += stat.frm_size[FRM_IDX];
885*abb65b4bSAndroid Build Coastguard Worker 
886*abb65b4bSAndroid Build Coastguard Worker             print_stat_au(&stat, au_cnt, param, args_var->max_au, bitrate_tot, clk_end, clk_tot);
887*abb65b4bSAndroid Build Coastguard Worker 
888*abb65b4bSAndroid Build Coastguard Worker             for(int i = 0; i < num_frames; i++) {
889*abb65b4bSAndroid Build Coastguard Worker                 if(is_rec) {
890*abb65b4bSAndroid Build Coastguard Worker                     if(args_var->input_depth != 10) {
891*abb65b4bSAndroid Build Coastguard Worker                         imgb_cpy(imgb_w, rfrms.frm[i].imgb);
892*abb65b4bSAndroid Build Coastguard Worker                         imgb_o = imgb_w;
893*abb65b4bSAndroid Build Coastguard Worker                     }
894*abb65b4bSAndroid Build Coastguard Worker                     else {
895*abb65b4bSAndroid Build Coastguard Worker                         imgb_o = rfrms.frm[i].imgb;
896*abb65b4bSAndroid Build Coastguard Worker                     }
897*abb65b4bSAndroid Build Coastguard Worker                 }
898*abb65b4bSAndroid Build Coastguard Worker 
899*abb65b4bSAndroid Build Coastguard Worker                 /* store bitstream */
900*abb65b4bSAndroid Build Coastguard Worker                 if(OAPV_SUCCEEDED(ret)) {
901*abb65b4bSAndroid Build Coastguard Worker                     if(is_out && stat.write > 0) {
902*abb65b4bSAndroid Build Coastguard Worker                         if(write_data(args_var->fname_out, bs_buf, stat.write)) {
903*abb65b4bSAndroid Build Coastguard Worker                             logerr("cannot write bitstream\n");
904*abb65b4bSAndroid Build Coastguard Worker                             ret = -1;
905*abb65b4bSAndroid Build Coastguard Worker                             goto ERR;
906*abb65b4bSAndroid Build Coastguard Worker                         }
907*abb65b4bSAndroid Build Coastguard Worker                     }
908*abb65b4bSAndroid Build Coastguard Worker                 }
909*abb65b4bSAndroid Build Coastguard Worker                 else {
910*abb65b4bSAndroid Build Coastguard Worker                     logerr("failed to encode\n");
911*abb65b4bSAndroid Build Coastguard Worker                     ret = -1;
912*abb65b4bSAndroid Build Coastguard Worker                     goto ERR;
913*abb65b4bSAndroid Build Coastguard Worker                 }
914*abb65b4bSAndroid Build Coastguard Worker 
915*abb65b4bSAndroid Build Coastguard Worker                 // store recon image
916*abb65b4bSAndroid Build Coastguard Worker                 if(is_rec) {
917*abb65b4bSAndroid Build Coastguard Worker                     if(imgb_write(args_var->fname_rec, imgb_o)) {
918*abb65b4bSAndroid Build Coastguard Worker                         logerr("cannot write reconstruction image\n");
919*abb65b4bSAndroid Build Coastguard Worker                         ret = -1;
920*abb65b4bSAndroid Build Coastguard Worker                         goto ERR;
921*abb65b4bSAndroid Build Coastguard Worker                     }
922*abb65b4bSAndroid Build Coastguard Worker                 }
923*abb65b4bSAndroid Build Coastguard Worker 
924*abb65b4bSAndroid Build Coastguard Worker                 print_stat_frms(&stat, &ifrms, &rfrms, psnr_avg);
925*abb65b4bSAndroid Build Coastguard Worker                 au_cnt++;
926*abb65b4bSAndroid Build Coastguard Worker             }
927*abb65b4bSAndroid Build Coastguard Worker         }
928*abb65b4bSAndroid Build Coastguard Worker         else if(state == STATE_SKIPPING) {
929*abb65b4bSAndroid Build Coastguard Worker             if(au_skip < args_var->seek) {
930*abb65b4bSAndroid Build Coastguard Worker                 au_skip++;
931*abb65b4bSAndroid Build Coastguard Worker                 continue;
932*abb65b4bSAndroid Build Coastguard Worker             }
933*abb65b4bSAndroid Build Coastguard Worker             else {
934*abb65b4bSAndroid Build Coastguard Worker                 state = STATE_ENCODING;
935*abb65b4bSAndroid Build Coastguard Worker             }
936*abb65b4bSAndroid Build Coastguard Worker         }
937*abb65b4bSAndroid Build Coastguard Worker         else if(state == STATE_STOP) {
938*abb65b4bSAndroid Build Coastguard Worker             break;
939*abb65b4bSAndroid Build Coastguard Worker         }
940*abb65b4bSAndroid Build Coastguard Worker         oapvm_rem_all(mid);
941*abb65b4bSAndroid Build Coastguard Worker     }
942*abb65b4bSAndroid Build Coastguard Worker 
943*abb65b4bSAndroid Build Coastguard Worker     logv2_line("Summary");
944*abb65b4bSAndroid Build Coastguard Worker     psnr_avg[FRM_IDX][0] /= au_cnt;
945*abb65b4bSAndroid Build Coastguard Worker     psnr_avg[FRM_IDX][1] /= au_cnt;
946*abb65b4bSAndroid Build Coastguard Worker     psnr_avg[FRM_IDX][2] /= au_cnt;
947*abb65b4bSAndroid Build Coastguard Worker     if(cfmt == OAPV_CF_YCBCR4444) {
948*abb65b4bSAndroid Build Coastguard Worker         psnr_avg[FRM_IDX][3] /= au_cnt;
949*abb65b4bSAndroid Build Coastguard Worker     }
950*abb65b4bSAndroid Build Coastguard Worker 
951*abb65b4bSAndroid Build Coastguard Worker     logv3("  PSNR Y(dB)       : %-5.4f\n", psnr_avg[FRM_IDX][0]);
952*abb65b4bSAndroid Build Coastguard Worker     logv3("  PSNR U(dB)       : %-5.4f\n", psnr_avg[FRM_IDX][1]);
953*abb65b4bSAndroid Build Coastguard Worker     logv3("  PSNR V(dB)       : %-5.4f\n", psnr_avg[FRM_IDX][2]);
954*abb65b4bSAndroid Build Coastguard Worker     if(cfmt == OAPV_CF_YCBCR4444) {
955*abb65b4bSAndroid Build Coastguard Worker         logv3("  PSNR T(dB)       : %-5.4f\n", psnr_avg[FRM_IDX][3]);
956*abb65b4bSAndroid Build Coastguard Worker     }
957*abb65b4bSAndroid Build Coastguard Worker     logv3("  Total bits(bits) : %.0f\n", bitrate_tot * 8);
958*abb65b4bSAndroid Build Coastguard Worker     bitrate_tot *= (((float)param->fps_num / param->fps_den) * 8);
959*abb65b4bSAndroid Build Coastguard Worker     bitrate_tot /= au_cnt;
960*abb65b4bSAndroid Build Coastguard Worker     bitrate_tot /= 1000;
961*abb65b4bSAndroid Build Coastguard Worker 
962*abb65b4bSAndroid Build Coastguard Worker     logv3("  -----------------: bitrate(kbps)\tPSNR-Y\tPSNR-U\tPSNR-V\n");
963*abb65b4bSAndroid Build Coastguard Worker     if(cfmt == OAPV_CF_YCBCR4444) {
964*abb65b4bSAndroid Build Coastguard Worker         logv3("  Summary          : %-4.4f\t%-5.4f\t%-5.4f\t%-5.4f\t%-5.4f\n",
965*abb65b4bSAndroid Build Coastguard Worker               bitrate_tot, psnr_avg[FRM_IDX][0], psnr_avg[FRM_IDX][1], psnr_avg[FRM_IDX][2], psnr_avg[FRM_IDX][3]);
966*abb65b4bSAndroid Build Coastguard Worker     }
967*abb65b4bSAndroid Build Coastguard Worker     else {
968*abb65b4bSAndroid Build Coastguard Worker         logv3("  Summary          : %-5.4f\t%-5.4f\t%-5.4f\t%-5.4f\n",
969*abb65b4bSAndroid Build Coastguard Worker               bitrate_tot, psnr_avg[FRM_IDX][0], psnr_avg[FRM_IDX][1], psnr_avg[FRM_IDX][2]);
970*abb65b4bSAndroid Build Coastguard Worker     }
971*abb65b4bSAndroid Build Coastguard Worker 
972*abb65b4bSAndroid Build Coastguard Worker     logv2("Bitrate                           = %.4f kbps\n", bitrate_tot);
973*abb65b4bSAndroid Build Coastguard Worker     logv2("Encoded frame count               = %d\n", (int)au_cnt);
974*abb65b4bSAndroid Build Coastguard Worker     logv2("Total encoding time               = %.3f msec,",
975*abb65b4bSAndroid Build Coastguard Worker           (float)oapv_clk_msec(clk_tot));
976*abb65b4bSAndroid Build Coastguard Worker     logv2(" %.3f sec\n", (float)(oapv_clk_msec(clk_tot) / 1000.0));
977*abb65b4bSAndroid Build Coastguard Worker 
978*abb65b4bSAndroid Build Coastguard Worker     logv2("Average encoding time for a frame = %.3f msec\n",
979*abb65b4bSAndroid Build Coastguard Worker           (float)oapv_clk_msec(clk_tot) / au_cnt);
980*abb65b4bSAndroid Build Coastguard Worker     logv2("Average encoding speed            = %.3f frames/sec\n",
981*abb65b4bSAndroid Build Coastguard Worker           ((float)au_cnt * 1000) / ((float)oapv_clk_msec(clk_tot)));
982*abb65b4bSAndroid Build Coastguard Worker     logv2_line(NULL);
983*abb65b4bSAndroid Build Coastguard Worker 
984*abb65b4bSAndroid Build Coastguard Worker     if(args_var->max_au > 0 && au_cnt != args_var->max_au) {
985*abb65b4bSAndroid Build Coastguard Worker         logv3("Wrong frames count: should be %d was %d\n", args_var->max_au, (int)au_cnt);
986*abb65b4bSAndroid Build Coastguard Worker     }
987*abb65b4bSAndroid Build Coastguard Worker ERR:
988*abb65b4bSAndroid Build Coastguard Worker 
989*abb65b4bSAndroid Build Coastguard Worker     if(imgb_r != NULL)
990*abb65b4bSAndroid Build Coastguard Worker         imgb_r->release(imgb_r);
991*abb65b4bSAndroid Build Coastguard Worker     if(imgb_w != NULL)
992*abb65b4bSAndroid Build Coastguard Worker         imgb_w->release(imgb_w);
993*abb65b4bSAndroid Build Coastguard Worker 
994*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < num_frames; i++) {
995*abb65b4bSAndroid Build Coastguard Worker         if(ifrms.frm[i].imgb != NULL) {
996*abb65b4bSAndroid Build Coastguard Worker             ifrms.frm[i].imgb->release(ifrms.frm[i].imgb);
997*abb65b4bSAndroid Build Coastguard Worker         }
998*abb65b4bSAndroid Build Coastguard Worker     }
999*abb65b4bSAndroid Build Coastguard Worker     for(int i = 0; i < num_frames; i++) {
1000*abb65b4bSAndroid Build Coastguard Worker         if(rfrms.frm[i].imgb != NULL) {
1001*abb65b4bSAndroid Build Coastguard Worker             rfrms.frm[i].imgb->release(rfrms.frm[i].imgb);
1002*abb65b4bSAndroid Build Coastguard Worker         }
1003*abb65b4bSAndroid Build Coastguard Worker     }
1004*abb65b4bSAndroid Build Coastguard Worker 
1005*abb65b4bSAndroid Build Coastguard Worker     if(id)
1006*abb65b4bSAndroid Build Coastguard Worker         oapve_delete(id);
1007*abb65b4bSAndroid Build Coastguard Worker     if(mid)
1008*abb65b4bSAndroid Build Coastguard Worker         oapvm_delete(mid);
1009*abb65b4bSAndroid Build Coastguard Worker     if(fp_inp)
1010*abb65b4bSAndroid Build Coastguard Worker         fclose(fp_inp);
1011*abb65b4bSAndroid Build Coastguard Worker     if(bs_buf)
1012*abb65b4bSAndroid Build Coastguard Worker         free(bs_buf); /* release bitstream buffer */
1013*abb65b4bSAndroid Build Coastguard Worker     if(args)
1014*abb65b4bSAndroid Build Coastguard Worker         args->release(args);
1015*abb65b4bSAndroid Build Coastguard Worker     if(args_var)
1016*abb65b4bSAndroid Build Coastguard Worker         free(args_var);
1017*abb65b4bSAndroid Build Coastguard Worker 
1018*abb65b4bSAndroid Build Coastguard Worker     return ret;
1019*abb65b4bSAndroid Build Coastguard Worker }
1020