xref: /aosp_15_r20/external/libavc/examples/mvcdec/main.c (revision 495ae853bb871d1e5a258cb02c2cc13cde8ddb9a)
1 /******************************************************************************
2  *
3  * Copyright (C) 2021 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19  */
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdint.h>
25 #include <sys/time.h>
26 
27 #include "ih264_typedefs.h"
28 #include "iv.h"
29 #include "ivd.h"
30 #include "imvcd.h"
31 #include "ih264_debug.h"
32 #include "ih264d.h"
33 #include "ithread.h"
34 
35 /* Constants */
36 #define DEFAULT_NON_DEGRADE_INTERVAL 4
37 
38 #define MAX_DISP_BUFFERS 64
39 
40 #define STRLENGTH 1000
41 
42 #define PEAK_WINDOW_SIZE 8
43 
44 #define DEFAULT_COLOR_FORMAT IV_YUV_420P
45 
46 #define DEFAULT_NUM_CORES 1
47 
48 #define MAX_ARG_SHORTNAME_LENGTH 4
49 
50 #define MAX_ARG_NAME_LENGTH 128
51 
52 #define MAX_ARG_DESC_LENGTH 512
53 
54 #define MAX_NUM_VIEWS 6
55 
56 #undef PROFILE_ENABLE
57 
58 /* Macro functions */
59 #ifdef PROFILE_ENABLE
60 #define GETTIME(timer) gettimeofday(timer, NULL);
61 
62 #define ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency)     \
63     s_elapsed_time = ((s_end_timer.tv_sec - s_start_timer.tv_sec) * 1000000) + \
64                      (s_end_timer.tv_usec - s_start_timer.tv_usec);
65 #else
66 #define GETTIME(timer)
67 #define ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency)
68 #endif
69 
70 /* Typedefs */
71 typedef enum ARGUMENT_T
72 {
73     INVALID,
74     HELP,
75     INPUT_FILE,
76     OUTPUT,
77     CHKSUM,
78     SAVE_OUTPUT,
79     SAVE_CHKSUM,
80     NUM_FRAMES,
81     NUM_CORES,
82     DISABLE_DEBLOCK_LEVEL,
83     LOOPBACK,
84     CONFIG,
85     DEGRADE_TYPE,
86     DEGRADE_PICS,
87     ARCH
88 } ARGUMENT_T;
89 
90 typedef enum COMPONENT_TYPES_T
91 {
92     Y = 0,
93     UV = 1,
94     U = 1,
95     V = 2,
96     NUM_SP_COMPONENTS = 2,
97     NUM_COMPONENTS = 3
98 } COMPONENT_TYPES_T;
99 
100 #ifdef PROFILE_ENABLE
101 typedef struct timeval TIMER;
102 #else
103 typedef WORD32 TIMER;
104 #endif
105 
106 typedef struct mvc_app_files_t
107 {
108     UWORD8 au1_ip_fname[STRLENGTH];
109 
110     UWORD8 au1_op_fname[STRLENGTH];
111 
112     UWORD8 au1_op_chksum_fname[STRLENGTH];
113 
114     UWORD32 au4_disp_frm_id_queue[MAX_DISP_BUFFERS];
115 } mvc_app_files_t;
116 
117 typedef struct mvc_dec_ctx_t
118 {
119     mvc_app_files_t s_mvc_app_files;
120 
121     imvcd_get_buf_info_op_t s_disp_buf_props;
122 
123     iv_yuv_buf_t as_view_disp_bufs[MAX_NUM_VIEWS];
124 
125     iv_obj_t *ps_codec_obj;
126 
127     IV_COLOR_FORMAT_T e_output_chroma_format;
128 
129     IVD_ARCH_T e_arch;
130 
131     IVD_SOC_T e_soc;
132 
133     UWORD32 u4_max_frm_ts;
134 
135     UWORD32 u4_disable_dblk_level;
136 
137     WORD32 i4_degrade_type;
138 
139     WORD32 i4_degrade_pics;
140 
141     UWORD32 u4_num_cores;
142 
143     UWORD32 u4_disp_delay;
144 
145     UWORD32 u4_fps;
146 
147     UWORD32 u4_pic_wd;
148 
149     UWORD32 u4_pic_ht;
150 
151     UWORD32 u4_loopback;
152 
153     UWORD32 u4_file_save_flag;
154 
155     UWORD32 u4_chksum_save_flag;
156 
157     UWORD8 u1_quit;
158 
159 } mvc_dec_ctx_t;
160 
161 typedef struct argument_t
162 {
163     UWORD8 au1_argument_shortname[MAX_ARG_SHORTNAME_LENGTH];
164 
165     UWORD8 au1_argument_name[MAX_ARG_NAME_LENGTH];
166 
167     ARGUMENT_T e_argument;
168 
169     UWORD8 au1_description[MAX_ARG_DESC_LENGTH];
170 
171 } argument_t;
172 
173 /* Function declarations */
174 #ifndef MD5_DISABLE
175 void calc_md5_cksum(UWORD8 *pu1_inbuf, UWORD32 u4_stride, UWORD32 u4_width, UWORD32 u4_height,
176                     UWORD8 *pu1_cksum_p);
177 #else
178 #define calc_md5_cksum(a, b, c, d, e)
179 #endif
180 
mvcd_aligned_malloc(void * pv_ctxt,WORD32 alignment,WORD32 i4_size)181 static inline void *mvcd_aligned_malloc(void *pv_ctxt, WORD32 alignment, WORD32 i4_size)
182 {
183     void *buf = NULL;
184     (void) pv_ctxt;
185     if(0 != posix_memalign(&buf, alignment, i4_size))
186     {
187         return NULL;
188     }
189     return buf;
190 }
191 
mvcd_aligned_free(void * pv_ctxt,void * pv_buf)192 static inline void mvcd_aligned_free(void *pv_ctxt, void *pv_buf)
193 {
194     (void) pv_ctxt;
195     free(pv_buf);
196     return;
197 }
198 
199 static const argument_t argument_mapping[] = {
200     {"-h", "--help", HELP, "Print this help\n"},
201     {"-c", "--config", CONFIG, "config file (Default: test.cfg)\n"},
202     {"-i", "--input", INPUT_FILE, "Input file\n"},
203     {"-o", "--output", OUTPUT, "Output file\n"},
204     {"--", "--chksum", CHKSUM, "Output MD5 Checksum file\n"},
205     {"-s", "--save_output", SAVE_OUTPUT, "Save Output file\n"},
206     {"--", "--save_chksum", SAVE_CHKSUM, "Save Check sum file\n"},
207     {"-n", "--num_frames", NUM_FRAMES, "Number of frames to be decoded\n"},
208     {"--", "--num_cores", NUM_CORES, "Number of cores to be used\n"},
209     {"--", "--disable_deblock_level", DISABLE_DEBLOCK_LEVEL,
210      "Disable deblocking level : 0 to 4 - 0 Enable deblocking 4 Disable "
211      "deblocking completely\n"},
212     {"--", "--u4_loopback", LOOPBACK, "Enable playback in a loop\n"},
213     {"--", "--degrade_type", DEGRADE_TYPE,
214      "Degrade type : 0: No degrade 0th bit set : Disable SAO 1st bit set : "
215      "Disable deblocking 2nd bit set : Faster inter prediction filters 3rd bit "
216      "set : Fastest inter prediction filters\n"},
217     {"--", "--degrade_pics", DEGRADE_PICS,
218      "Degrade pics : 0 : No degrade  1 : Only on non-reference frames  2 : Do "
219      "not degrade every 4th or key frames  3 : All non-key frames  4 : All "
220      "frames\n"},
221     {"--", "--arch", ARCH,
222      "Set Architecture. Supported values - ARM_A9Q, ARMV8_GENERIC, "
223      "X86_GENERIC, X86_SSE4 \n"},
224 };
225 
226 #if ANDROID_NDK
227 /*****************************************************************************/
228 /*                                                                           */
229 /*  Function Name : raise                                                    */
230 /*                                                                           */
231 /*  Description   : Needed as a workaround when the application is built in  */
232 /*                  Android NDK. This is an exception to be called for divide*/
233 /*                  by zero error                                            */
234 /*                                                                           */
235 /*  Inputs        : a                                                        */
236 /*  Globals       :                                                          */
237 /*  Processing    : None                                                     */
238 /*                                                                           */
239 /*  Outputs       :                                                          */
240 /*  Returns       :                                                          */
241 /*                                                                           */
242 /*  Issues        :                                                          */
243 /*                                                                           */
244 /*  Revision History:                                                        */
245 /*                                                                           */
246 /*         DD MM YYYY   Author(s)       Changes                              */
247 /*         07 09 2012   100189          Initial Version                      */
248 /*                                                                           */
249 /*****************************************************************************/
raise(int a)250 static int raise(int a)
251 {
252     printf("Divide by zero\n");
253     return 0;
254 }
255 #endif
256 
mvcd_print_usage(void)257 static void mvcd_print_usage(void)
258 {
259     WORD32 i = 0;
260     WORD32 num_entries = sizeof(argument_mapping) / sizeof(argument_t);
261 
262     printf("\nUsage:\n");
263 
264     while(i < num_entries)
265     {
266         printf("%-32s\t %s", argument_mapping[i].au1_argument_name,
267                argument_mapping[i].au1_description);
268         i++;
269     }
270 }
271 
mvcd_get_argument(char * name)272 static ARGUMENT_T mvcd_get_argument(char *name)
273 {
274     WORD32 i = 0;
275     WORD32 num_entries = sizeof(argument_mapping) / sizeof(argument_t);
276 
277     while(i < num_entries)
278     {
279         if((0 == strcmp((char *) argument_mapping[i].au1_argument_name, name)) ||
280            ((0 == strcmp((char *) argument_mapping[i].au1_argument_shortname, name)) &&
281             (0 != strcmp((char *) argument_mapping[i].au1_argument_shortname, "--"))))
282         {
283             return argument_mapping[i].e_argument;
284         }
285         i++;
286     }
287 
288     return INVALID;
289 }
290 
mvcd_exit(UWORD8 * pu1_err_message)291 static void mvcd_exit(UWORD8 *pu1_err_message)
292 {
293     printf("%s\n", pu1_err_message);
294     exit(-1);
295 }
296 
mvcd_parse_argument(mvc_dec_ctx_t * ps_app_ctx,char * argument,char * value)297 static void mvcd_parse_argument(mvc_dec_ctx_t *ps_app_ctx, char *argument, char *value)
298 {
299     ARGUMENT_T arg;
300 
301     arg = mvcd_get_argument((char *) argument);
302 
303     switch(arg)
304     {
305         case HELP:
306         {
307             mvcd_print_usage();
308 
309             exit(-1);
310         }
311         case INPUT_FILE:
312         {
313             sscanf(value, "%s", ps_app_ctx->s_mvc_app_files.au1_ip_fname);
314 
315             break;
316         }
317         case OUTPUT:
318         {
319             sscanf(value, "%s", ps_app_ctx->s_mvc_app_files.au1_op_fname);
320 
321             break;
322         }
323         case CHKSUM:
324         {
325             sscanf(value, "%s", ps_app_ctx->s_mvc_app_files.au1_op_chksum_fname);
326 
327             break;
328         }
329         case SAVE_OUTPUT:
330         {
331             sscanf(value, "%u", &ps_app_ctx->u4_file_save_flag);
332 
333             break;
334         }
335         case SAVE_CHKSUM:
336         {
337             sscanf(value, "%u", &ps_app_ctx->u4_chksum_save_flag);
338 
339             break;
340         }
341         case NUM_FRAMES:
342         {
343             sscanf(value, "%u", &ps_app_ctx->u4_max_frm_ts);
344 
345             break;
346         }
347         case NUM_CORES:
348         {
349             sscanf(value, "%u", &ps_app_ctx->u4_num_cores);
350 
351             break;
352         }
353         case DEGRADE_PICS:
354         {
355             sscanf(value, "%d", &ps_app_ctx->i4_degrade_pics);
356 
357             break;
358         }
359         case DEGRADE_TYPE:
360         {
361             sscanf(value, "%d", &ps_app_ctx->i4_degrade_type);
362 
363             break;
364         }
365         case LOOPBACK:
366         {
367             sscanf(value, "%u", &ps_app_ctx->u4_loopback);
368 
369             break;
370         }
371         case ARCH:
372         {
373             if((strcmp(value, "ARM_A9Q")) == 0)
374             {
375                 ps_app_ctx->e_arch = ARCH_ARM_A9Q;
376             }
377             else if((strcmp(value, "X86_GENERIC")) == 0)
378             {
379                 ps_app_ctx->e_arch = ARCH_X86_GENERIC;
380             }
381             else if((strcmp(value, "X86_SSSE3")) == 0)
382             {
383                 ps_app_ctx->e_arch = ARCH_X86_SSSE3;
384             }
385             else if((strcmp(value, "X86_SSE42")) == 0)
386             {
387                 ps_app_ctx->e_arch = ARCH_X86_SSE42;
388             }
389             else if((strcmp(value, "ARMV8_GENERIC")) == 0)
390             {
391                 ps_app_ctx->e_arch = ARCH_ARMV8_GENERIC;
392             }
393             else
394             {
395                 printf("\nInvalid Arch. Setting it to ARCH_ARMV8_GENERIC\n");
396                 ps_app_ctx->e_arch = ARCH_ARMV8_GENERIC;
397             }
398 
399             break;
400         }
401         case DISABLE_DEBLOCK_LEVEL:
402         {
403             sscanf(value, "%u", &ps_app_ctx->u4_disable_dblk_level);
404 
405             break;
406         }
407         default:
408         {
409             printf("Ignoring argument :  %s\n", argument);
410 
411             break;
412         }
413     }
414 }
415 
mvcd_read_cfg_file(mvc_dec_ctx_t * ps_app_ctx,FILE * ps_cfg_file)416 static void mvcd_read_cfg_file(mvc_dec_ctx_t *ps_app_ctx, FILE *ps_cfg_file)
417 {
418     char line[STRLENGTH];
419     char description[STRLENGTH];
420     char value[STRLENGTH];
421     char argument[STRLENGTH];
422     void *ret;
423 
424     while(0 == feof(ps_cfg_file))
425     {
426         line[0] = '\0';
427         ret = fgets(line, STRLENGTH, ps_cfg_file);
428         if(NULL == ret) break;
429         argument[0] = '\0';
430         /* Reading Input File Name */
431         sscanf(line, "%s %s %s", argument, value, description);
432         if(argument[0] == '\0') continue;
433 
434         mvcd_parse_argument(ps_app_ctx, argument, value);
435     }
436 }
437 
mvcd_get_view_file_name(const UWORD8 * pu1_default_name,UWORD8 * pu1_view_file_name,UWORD16 u2_view_id)438 static void mvcd_get_view_file_name(const UWORD8 *pu1_default_name, UWORD8 *pu1_view_file_name,
439                              UWORD16 u2_view_id)
440 {
441     CHAR *apc_sub_str[2];
442     CHAR ac_string[STRLENGTH];
443 
444     const CHAR ac_delimiters[] = ".";
445 
446     strcpy(ac_string, (char *) pu1_default_name);
447 
448     apc_sub_str[0] = strtok(ac_string, ac_delimiters);
449     apc_sub_str[1] = strtok(NULL, ac_delimiters);
450 
451     ASSERT(NULL == strtok(NULL, ac_delimiters));
452     ASSERT((strlen(apc_sub_str[0]) + strlen(apc_sub_str[1]) + 3) < STRLENGTH);
453 
454     sprintf((char *) pu1_view_file_name, "%s_%d.%s", apc_sub_str[0], u2_view_id, apc_sub_str[1]);
455 }
456 
mvcd_in_buf_alloc(mvc_dec_ctx_t * ps_app_ctxt,UWORD8 ** ppu1_bs_buf)457 static IV_API_CALL_STATUS_T mvcd_in_buf_alloc(mvc_dec_ctx_t *ps_app_ctxt, UWORD8 **ppu1_bs_buf)
458 {
459     ppu1_bs_buf[0] =
460         (UWORD8 *) malloc(ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_in_buf_size[0]);
461 
462     if(ppu1_bs_buf[0] == NULL)
463     {
464         return IV_FAIL;
465     }
466 
467     return IV_SUCCESS;
468 }
469 
mvcd_in_buf_free(UWORD8 * pu1_bs_buf)470 static IV_API_CALL_STATUS_T mvcd_in_buf_free(UWORD8 *pu1_bs_buf)
471 {
472     free(pu1_bs_buf);
473 
474     return IV_SUCCESS;
475 }
476 
mvcd_out_buf_alloc(mvc_dec_ctx_t * ps_app_ctxt,ivd_out_bufdesc_t * ps_out_buf)477 static IV_API_CALL_STATUS_T mvcd_out_buf_alloc(mvc_dec_ctx_t *ps_app_ctxt, ivd_out_bufdesc_t *ps_out_buf)
478 {
479     UWORD32 i;
480 
481     UWORD16 u2_num_views = ps_app_ctxt->s_disp_buf_props.s_mvc_buf_info.u2_num_views;
482 
483     if(ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_num_out_bufs < (NUM_COMPONENTS * u2_num_views))
484     {
485         return IV_FAIL;
486     }
487 
488     ps_out_buf->u4_num_bufs = ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_num_out_bufs;
489 
490     for(i = 0; i < ps_out_buf->u4_num_bufs; i++)
491     {
492         ps_out_buf->u4_min_out_buf_size[i] =
493             ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_out_buf_size[i];
494         ps_out_buf->pu1_bufs[i] =
495             (UWORD8 *) malloc(ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_out_buf_size[i]);
496 
497         if(ps_out_buf->pu1_bufs[i] == NULL)
498         {
499             return IV_FAIL;
500         }
501     }
502 
503     return IV_SUCCESS;
504 }
505 
mvcd_out_buf_free(ivd_out_bufdesc_t * ps_out_buf)506 static IV_API_CALL_STATUS_T mvcd_out_buf_free(ivd_out_bufdesc_t *ps_out_buf)
507 {
508     UWORD32 i;
509 
510     for(i = 0; i < ps_out_buf->u4_num_bufs; i++)
511     {
512         free(ps_out_buf->pu1_bufs[i]);
513     }
514 
515     return IV_SUCCESS;
516 }
517 
mvcd_output_write_stall(UWORD8 * au1_fname,UWORD32 u4_cur_frm_idx)518 static void mvcd_output_write_stall(UWORD8 *au1_fname, UWORD32 u4_cur_frm_idx)
519 {
520     FILE *fp_fast_file = NULL;
521 
522     const UWORD8 threshold = 64;
523     char past_fname[1000];
524 
525     if(u4_cur_frm_idx >= threshold)
526     {
527         sprintf(past_fname, (char *) au1_fname, u4_cur_frm_idx - threshold);
528         do
529         {
530             fp_fast_file = fopen(past_fname, "rb");
531 
532             if(fp_fast_file != NULL)
533             {
534                 fclose(fp_fast_file);
535                 /* Wait until the resource is released by a third party app*/
536                 ithread_sleep(5000);
537             }
538             else
539             {
540                 break;
541             }
542         } while(1);
543     }
544 }
545 
mvcd_create_decoder(mvc_dec_ctx_t * ps_app_ctxt)546 static IV_API_CALL_STATUS_T mvcd_create_decoder(mvc_dec_ctx_t *ps_app_ctxt)
547 {
548     imvcd_create_ip_t s_create_ip;
549     imvcd_create_op_t s_create_op;
550 
551     IV_API_CALL_STATUS_T ret;
552 
553     s_create_ip.s_ivd_ip.e_cmd = IVD_CMD_CREATE;
554     s_create_ip.s_ivd_ip.e_output_format = ps_app_ctxt->e_output_chroma_format;
555     s_create_ip.s_ivd_ip.pf_aligned_alloc = mvcd_aligned_malloc;
556     s_create_ip.s_ivd_ip.pf_aligned_free = mvcd_aligned_free;
557     s_create_ip.s_ivd_ip.u4_share_disp_buf = 0;
558     s_create_ip.s_ivd_ip.pv_mem_ctxt = NULL;
559 
560     s_create_ip.s_ivd_ip.u4_size = sizeof(s_create_ip.s_ivd_ip);
561     s_create_op.s_ivd_op.u4_size = sizeof(s_create_op.s_ivd_op);
562 
563     ret = imvcd_api_function(NULL, &s_create_ip, &s_create_op);
564 
565     if(ret != IV_SUCCESS)
566     {
567         return ret;
568     }
569 
570     ps_app_ctxt->ps_codec_obj = (iv_obj_t *) s_create_op.s_ivd_op.pv_handle;
571 
572     return IV_SUCCESS;
573 }
574 
mvcd_set_decode_mode(mvc_dec_ctx_t * ps_app_ctxt,IVD_VIDEO_DECODE_MODE_T e_decode_mode)575 static IV_API_CALL_STATUS_T mvcd_set_decode_mode(mvc_dec_ctx_t *ps_app_ctxt,
576                                           IVD_VIDEO_DECODE_MODE_T e_decode_mode)
577 {
578     imvcd_set_config_ip_t s_ctl_ip;
579     imvcd_set_config_op_t s_ctl_op;
580 
581     s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip);
582     s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op);
583     s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL;
584     s_ctl_ip.s_ivd_ip.e_sub_cmd = (WORD32) IVD_CMD_CTL_SETPARAMS;
585     s_ctl_ip.s_ivd_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
586     s_ctl_ip.s_ivd_ip.e_frm_skip_mode = IVD_SKIP_NONE;
587     s_ctl_ip.s_ivd_ip.e_vid_dec_mode = e_decode_mode;
588 
589     return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op);
590 }
591 
mvcd_set_num_cores(mvc_dec_ctx_t * ps_app_ctxt)592 static IV_API_CALL_STATUS_T mvcd_set_num_cores(mvc_dec_ctx_t *ps_app_ctxt)
593 {
594     imvcd_set_num_cores_ip_t s_ctl_ip;
595     imvcd_set_num_cores_op_t s_ctl_op;
596 
597     s_ctl_ip.u4_size = sizeof(s_ctl_ip);
598     s_ctl_op.u4_size = sizeof(s_ctl_op);
599     s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
600     s_ctl_ip.e_sub_cmd = (WORD32) IMVCD_CTL_SET_NUM_CORES;
601     s_ctl_ip.u4_num_cores = ps_app_ctxt->u4_num_cores;
602 
603     return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op);
604 }
605 
mvcd_set_arch(mvc_dec_ctx_t * ps_app_ctxt)606 static IV_API_CALL_STATUS_T mvcd_set_arch(mvc_dec_ctx_t *ps_app_ctxt)
607 {
608     imvcd_set_arch_ip_t s_ctl_ip;
609     imvcd_set_arch_op_t s_ctl_op;
610 
611     s_ctl_ip.u4_size = sizeof(s_ctl_ip);
612     s_ctl_op.u4_size = sizeof(s_ctl_op);
613     s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
614     s_ctl_ip.e_sub_cmd = (WORD32) IMVCD_CTL_SET_PROCESSOR;
615     s_ctl_ip.e_arch = ps_app_ctxt->e_arch;
616     s_ctl_ip.e_soc = ps_app_ctxt->e_soc;
617 
618     return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op);
619 }
620 
mvcd_dump_output(mvc_dec_ctx_t * ps_app_ctxt,iv_yuv_buf_t * ps_view_disp_bufs,FILE ** pps_op_file,FILE ** pps_op_chksum_file,UWORD16 u2_num_views)621 static IV_API_CALL_STATUS_T mvcd_dump_output(mvc_dec_ctx_t *ps_app_ctxt,
622                                              iv_yuv_buf_t *ps_view_disp_bufs, FILE **pps_op_file,
623                                              FILE **pps_op_chksum_file, UWORD16 u2_num_views)
624 {
625     UWORD32 i, j;
626 
627     UWORD32 u4_file_save = ps_app_ctxt->u4_file_save_flag;
628     UWORD32 u4_chksum_save = ps_app_ctxt->u4_chksum_save_flag;
629 
630     if(!u4_file_save && !u4_chksum_save)
631     {
632         return IV_SUCCESS;
633     }
634 
635     if(NULL == ps_view_disp_bufs->pv_y_buf)
636     {
637         return IV_FAIL;
638     }
639 
640     for(i = 0; i < u2_num_views; i++)
641     {
642         iv_yuv_buf_t *ps_view_buf = &ps_view_disp_bufs[i];
643 
644         if(ps_app_ctxt->e_output_chroma_format == IV_YUV_420P)
645         {
646             if(u4_file_save)
647             {
648                 UWORD8 *pu1_buf = (UWORD8 *) ps_view_buf->pv_y_buf;
649                 UWORD16 u2_width = ps_view_buf->u4_y_wd;
650                 UWORD16 u2_height = ps_view_buf->u4_y_ht;
651 
652                 for(j = 0; j < u2_height; j++)
653                 {
654                     fwrite(pu1_buf, 1, u2_width, pps_op_file[i]);
655 
656                     pu1_buf += ps_view_buf->u4_y_strd;
657                 }
658 
659                 pu1_buf = (UWORD8 *) ps_view_buf->pv_u_buf;
660                 u2_width = ps_view_buf->u4_u_wd;
661                 u2_height = ps_view_buf->u4_u_ht;
662 
663                 for(j = 0; j < u2_height; j++)
664                 {
665                     fwrite(pu1_buf, 1, u2_width, pps_op_file[i]);
666 
667                     pu1_buf += ps_view_buf->u4_u_strd;
668                 }
669 
670                 pu1_buf = (UWORD8 *) ps_view_buf->pv_v_buf;
671                 u2_width = ps_view_buf->u4_v_wd;
672                 u2_height = ps_view_buf->u4_v_ht;
673 
674                 for(j = 0; j < u2_height; j++)
675                 {
676                     fwrite(pu1_buf, 1, u2_width, pps_op_file[i]);
677 
678                     pu1_buf += ps_view_buf->u4_v_strd;
679                 }
680             }
681 
682 #ifndef MD5_DISABLE
683             if(u4_chksum_save)
684             {
685                 UWORD8 au1_cksum[16];
686 
687                 UWORD8 *pu1_buf = (UWORD8 *) ps_view_buf->pv_y_buf;
688                 UWORD16 u2_width = ps_view_buf->u4_y_wd;
689                 UWORD16 u2_height = ps_view_buf->u4_y_ht;
690 
691                 calc_md5_cksum(pu1_buf, ps_view_buf->u4_y_strd, u2_width, u2_height, au1_cksum);
692 
693                 fwrite(au1_cksum, sizeof(UWORD8), 16, pps_op_chksum_file[i]);
694 
695                 pu1_buf = (UWORD8 *) ps_view_buf->pv_u_buf;
696                 u2_width = ps_view_buf->u4_u_wd;
697                 u2_height = ps_view_buf->u4_u_ht;
698 
699                 calc_md5_cksum(pu1_buf, ps_view_buf->u4_u_strd, u2_width, u2_height, au1_cksum);
700 
701                 fwrite(au1_cksum, sizeof(UWORD8), 16, pps_op_chksum_file[i]);
702 
703                 pu1_buf = (UWORD8 *) ps_view_buf->pv_v_buf;
704                 u2_width = ps_view_buf->u4_v_wd;
705                 u2_height = ps_view_buf->u4_v_ht;
706 
707                 calc_md5_cksum(pu1_buf, ps_view_buf->u4_v_strd, u2_width, u2_height, au1_cksum);
708 
709                 fwrite(au1_cksum, sizeof(UWORD8), 16, pps_op_chksum_file[i]);
710             }
711 #endif
712         }
713         else
714         {
715             return IV_FAIL;
716         }
717 
718         fflush(pps_op_file[i]);
719         fflush(pps_op_chksum_file[i]);
720     }
721 
722     return IV_SUCCESS;
723 }
724 
mvcd_flush(mvc_dec_ctx_t * ps_app_ctxt,ivd_out_bufdesc_t * ps_out_buf,FILE ** pps_op_file,FILE ** pps_op_chksum_file,UWORD8 * pu1_bs_buf,UWORD32 * pu4_op_frm_ts,UWORD32 u4_ip_frm_ts,UWORD32 u4_bytes_remaining,UWORD16 u2_num_views)725 static IV_API_CALL_STATUS_T mvcd_flush(mvc_dec_ctx_t *ps_app_ctxt, ivd_out_bufdesc_t *ps_out_buf,
726                                 FILE **pps_op_file, FILE **pps_op_chksum_file, UWORD8 *pu1_bs_buf,
727                                 UWORD32 *pu4_op_frm_ts, UWORD32 u4_ip_frm_ts,
728                                 UWORD32 u4_bytes_remaining, UWORD16 u2_num_views)
729 {
730     IV_API_CALL_STATUS_T ret = IV_SUCCESS;
731 
732     do
733     {
734         imvcd_flush_dec_ip_t s_ctl_ip;
735         imvcd_flush_dec_op_t s_ctl_op;
736 
737         if(*(pu4_op_frm_ts) >= u4_ip_frm_ts)
738         {
739             break;
740         }
741 
742         s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip);
743         s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op);
744         s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL;
745         s_ctl_ip.s_ivd_ip.e_sub_cmd = (WORD32) IVD_CMD_CTL_FLUSH;
746 
747         ret = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op);
748 
749         if(IV_SUCCESS == ret)
750         {
751             imvcd_video_decode_ip_t s_video_decode_ip;
752             imvcd_video_decode_op_t s_video_decode_op;
753 
754             s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
755             s_video_decode_ip.s_ivd_ip.u4_ts = u4_ip_frm_ts;
756             s_video_decode_ip.s_ivd_ip.pv_stream_buffer = pu1_bs_buf;
757             s_video_decode_ip.s_ivd_ip.u4_num_Bytes = u4_bytes_remaining;
758             s_video_decode_ip.s_ivd_ip.s_out_buffer = ps_out_buf[0];
759             s_video_decode_op.ps_view_disp_bufs = ps_app_ctxt->as_view_disp_bufs;
760 
761             s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip);
762             s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op);
763 
764             ret = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_video_decode_ip,
765                                      &s_video_decode_op);
766 
767             if(1 == s_video_decode_op.s_ivd_op.u4_output_present)
768             {
769                 ret = mvcd_dump_output(ps_app_ctxt, s_video_decode_op.ps_view_disp_bufs,
770                                        pps_op_file, pps_op_chksum_file, u2_num_views);
771 
772                 (*pu4_op_frm_ts)++;
773             }
774             else
775             {
776                 break;
777             }
778         }
779     } while(IV_SUCCESS == ret);
780 
781     return ret;
782 }
783 
mvcd_decode_header(mvc_dec_ctx_t * ps_app_ctxt,ivd_out_bufdesc_t * ps_out_buf,FILE * ps_ip_file,IVD_ERROR_CODES_T * pe_error_code,UWORD32 * pu4_num_bytes_dec,UWORD32 u4_ip_frm_ts)784 static IV_API_CALL_STATUS_T mvcd_decode_header(mvc_dec_ctx_t *ps_app_ctxt, ivd_out_bufdesc_t *ps_out_buf,
785                                         FILE *ps_ip_file, IVD_ERROR_CODES_T *pe_error_code,
786                                         UWORD32 *pu4_num_bytes_dec, UWORD32 u4_ip_frm_ts)
787 {
788     IV_API_CALL_STATUS_T ret;
789 
790     UWORD32 u4_ip_buf_len;
791     UWORD8 *pu1_bs_buf;
792 
793     imvcd_video_decode_ip_t s_video_decode_ip = {0};
794     imvcd_video_decode_op_t s_video_decode_op = {0};
795 
796     UWORD32 u4_file_pos = 0;
797     UWORD32 u4_num_bytes_dec = 0;
798 
799     ret = mvcd_set_decode_mode(ps_app_ctxt, IVD_DECODE_HEADER);
800 
801     if(ret != IV_SUCCESS)
802     {
803         pe_error_code[0] = IVD_INIT_DEC_FAILED;
804 
805         return ret;
806     }
807 
808     /* Allocate input buffer for header */
809     u4_ip_buf_len = 256 * 1024;
810     pu1_bs_buf = (UWORD8 *) malloc(u4_ip_buf_len);
811 
812     if(pu1_bs_buf == NULL)
813     {
814         pe_error_code[0] = IVD_MEM_ALLOC_FAILED;
815 
816         return IV_FAIL;
817     }
818 
819     do
820     {
821         WORD32 u4_numbytes;
822         UWORD32 u4_bytes_remaining;
823 
824         fseek(ps_ip_file, u4_file_pos, SEEK_SET);
825         u4_numbytes = u4_ip_buf_len;
826 
827         u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), u4_numbytes, ps_ip_file);
828 
829         if(0 == u4_bytes_remaining)
830         {
831             pe_error_code[0] = IVD_UNEXPECTED_END_OF_STREAM;
832 
833             return IV_FAIL;
834         }
835 
836         s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
837         s_video_decode_ip.s_ivd_ip.u4_ts = u4_ip_frm_ts;
838         s_video_decode_ip.s_ivd_ip.pv_stream_buffer = pu1_bs_buf;
839         s_video_decode_ip.s_ivd_ip.u4_num_Bytes = u4_bytes_remaining;
840         s_video_decode_ip.s_ivd_ip.s_out_buffer = ps_out_buf[0];
841         s_video_decode_op.ps_view_disp_bufs = ps_app_ctxt->as_view_disp_bufs;
842 
843         s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip);
844         s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op);
845 
846         ret = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_video_decode_ip, &s_video_decode_op);
847 
848         if(ret != IV_SUCCESS)
849         {
850             pe_error_code[0] = s_video_decode_op.s_ivd_op.u4_error_code;
851 
852             return ret;
853         }
854 
855         u4_num_bytes_dec += s_video_decode_op.s_ivd_op.u4_num_bytes_consumed;
856 
857 #ifndef PROFILE_ENABLE
858         printf("%d\n", s_video_decode_op.s_ivd_op.u4_num_bytes_consumed);
859 #endif
860     } while(ret != IV_SUCCESS);
861 
862     ps_app_ctxt->u4_pic_wd = s_video_decode_op.s_ivd_op.u4_pic_wd;
863     ps_app_ctxt->u4_pic_ht = s_video_decode_op.s_ivd_op.u4_pic_ht;
864 
865     pu4_num_bytes_dec[0] = u4_num_bytes_dec;
866     pe_error_code[0] = IVD_ERROR_NONE;
867 
868     free(pu1_bs_buf);
869 
870     return IV_SUCCESS;
871 }
872 
mvcd_get_buf_info(mvc_dec_ctx_t * ps_app_ctxt)873 static IV_API_CALL_STATUS_T mvcd_get_buf_info(mvc_dec_ctx_t *ps_app_ctxt)
874 {
875     imvcd_get_buf_info_ip_t s_ctl_ip;
876     imvcd_get_buf_info_op_t s_ctl_op;
877 
878     IV_API_CALL_STATUS_T e_retval;
879 
880     s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip);
881     s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op);
882     s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL;
883     s_ctl_ip.s_ivd_ip.e_sub_cmd = (WORD32) IVD_CMD_CTL_GETBUFINFO;
884 
885     e_retval = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op);
886 
887     ps_app_ctxt->s_disp_buf_props = s_ctl_op;
888 
889     return e_retval;
890 }
891 
mvcd_set_degrade_type(mvc_dec_ctx_t * ps_app_ctxt)892 static IV_API_CALL_STATUS_T mvcd_set_degrade_type(mvc_dec_ctx_t *ps_app_ctxt)
893 {
894     imvcd_set_degrade_mode_ip_t s_ctl_ip;
895     imvcd_set_degrade_mode_op_t s_ctl_op;
896 
897     s_ctl_ip.u4_size = sizeof(s_ctl_ip);
898     s_ctl_op.u4_size = sizeof(s_ctl_op);
899     s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
900     s_ctl_ip.e_sub_cmd = (WORD32) IMVCD_CTL_DEGRADE;
901     s_ctl_ip.i4_degrade_type = ps_app_ctxt->i4_degrade_type;
902     s_ctl_ip.i4_degrade_pics = ps_app_ctxt->i4_degrade_pics;
903     s_ctl_ip.i4_nondegrade_interval = DEFAULT_NON_DEGRADE_INTERVAL;
904 
905     return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op);
906 }
907 
mvcd_decode_frame(mvc_dec_ctx_t * ps_app_ctxt,ivd_out_bufdesc_t * ps_out_buf,FILE * ps_ip_file,FILE ** pps_op_file,FILE ** pps_op_chksum_file,UWORD8 * pu1_bs_buf,IVD_ERROR_CODES_T * pe_error_code,UWORD32 * pu4_num_bytes_consumed,UWORD32 * pu4_file_pos,UWORD32 * pu4_ip_frm_ts,UWORD32 * pu4_op_frm_ts,UWORD32 u4_ip_buf_len)908 static IV_API_CALL_STATUS_T mvcd_decode_frame(mvc_dec_ctx_t *ps_app_ctxt, ivd_out_bufdesc_t *ps_out_buf,
909                                        FILE *ps_ip_file, FILE **pps_op_file,
910                                        FILE **pps_op_chksum_file, UWORD8 *pu1_bs_buf,
911                                        IVD_ERROR_CODES_T *pe_error_code,
912                                        UWORD32 *pu4_num_bytes_consumed, UWORD32 *pu4_file_pos,
913                                        UWORD32 *pu4_ip_frm_ts, UWORD32 *pu4_op_frm_ts,
914                                        UWORD32 u4_ip_buf_len)
915 {
916     imvcd_video_decode_ip_t s_video_decode_ip;
917     imvcd_video_decode_op_t s_video_decode_op;
918 #ifdef PROFILE_ENABLE
919     TIMER s_start_timer;
920     TIMER s_end_timer;
921 #ifdef WINDOWS_TIMER
922     TIMER frequency;
923 #endif
924 
925     UWORD32 au4_peak_window[PEAK_WINDOW_SIZE];
926     UWORD32 s_elapsed_time;
927 #endif
928     UWORD32 u4_max_op_frm_ts;
929     UWORD32 u4_bytes_remaining;
930     UWORD32 u4_numbytes;
931 
932     IV_API_CALL_STATUS_T ret;
933 
934     UWORD32 u4_num_bytes_dec = 0;
935     UWORD16 u2_num_views = ps_app_ctxt->s_disp_buf_props.s_mvc_buf_info.u2_num_views;
936 #ifdef PROFILE_ENABLE
937     UWORD32 u4_frm_cnt = 0;
938     UWORD32 u4_tot_cycles = 0;
939     UWORD32 u4_tot_fmt_cycles = 0;
940     UWORD32 u4_peak_window_idx = 0;
941     UWORD32 u4_peak_avg_max = 0;
942 #endif
943 
944 #ifdef PROFILE_ENABLE
945     memset(au4_peak_window, 0, sizeof(WORD32) * PEAK_WINDOW_SIZE);
946 
947 #ifdef WINDOWS_TIMER
948     QueryPerformanceFrequency(&frequency);
949 #endif
950 #endif
951 
952     /*************************************************************************/
953     /* Set the decoder in frame decode mode. It was set in header decode     */
954     /* mode earlier                                                          */
955     /*************************************************************************/
956     ret = mvcd_set_decode_mode(ps_app_ctxt, IVD_DECODE_FRAME);
957 
958     if(IV_SUCCESS != ret)
959     {
960         pe_error_code[0] = IVD_INIT_DEC_FAILED;
961 
962         return ret;
963     }
964 
965     /*************************************************************************/
966     /* If required disable deblocking and sao at given level                 */
967     /*************************************************************************/
968     ret = mvcd_set_degrade_type(ps_app_ctxt);
969 
970     if(IV_SUCCESS != ret)
971     {
972         pe_error_code[0] = IVD_INIT_DEC_FAILED;
973 
974         return ret;
975     }
976 
977     u4_max_op_frm_ts = ps_app_ctxt->u4_max_frm_ts + ps_app_ctxt->u4_disp_delay;
978 
979     if(u4_max_op_frm_ts < ps_app_ctxt->u4_disp_delay)
980     {
981         /* clip as overflow has occured*/
982         u4_max_op_frm_ts = UINT32_MAX;
983     }
984 
985     if(IV_SUCCESS != ret)
986     {
987         pe_error_code[0] = IVD_INIT_DEC_FAILED;
988 
989         return ret;
990     }
991 
992     while(pu4_op_frm_ts[0] < u4_max_op_frm_ts)
993     {
994         fseek(ps_ip_file, pu4_file_pos[0], SEEK_SET);
995         u4_numbytes = u4_ip_buf_len;
996 
997         u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), u4_numbytes, ps_ip_file);
998 
999         if(0 == u4_bytes_remaining)
1000         {
1001             if(ps_app_ctxt->u4_loopback)
1002             {
1003                 pu4_file_pos[0] = 0;
1004 
1005                 fseek(ps_ip_file, pu4_file_pos[0], SEEK_SET);
1006                 u4_numbytes = u4_ip_buf_len;
1007 
1008                 u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), u4_numbytes, ps_ip_file);
1009             }
1010             else
1011             {
1012                 break;
1013             }
1014         }
1015 
1016         s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
1017         s_video_decode_ip.s_ivd_ip.u4_ts = pu4_ip_frm_ts[0];
1018         s_video_decode_ip.s_ivd_ip.pv_stream_buffer = pu1_bs_buf;
1019         s_video_decode_ip.s_ivd_ip.u4_num_Bytes = u4_bytes_remaining;
1020         s_video_decode_ip.s_ivd_ip.s_out_buffer = ps_out_buf[0];
1021         s_video_decode_op.ps_view_disp_bufs = ps_app_ctxt->as_view_disp_bufs;
1022 
1023         s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip);
1024         s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op);
1025 
1026         /****************/
1027         /* Video Decode */
1028         /****************/
1029         GETTIME(&s_start_timer);
1030 
1031         ret = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_video_decode_ip, &s_video_decode_op);
1032 
1033         GETTIME(&s_end_timer);
1034         ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency);
1035 
1036 #ifdef PROFILE_ENABLE
1037         {
1038             UWORD32 peak_avg, id;
1039 
1040             u4_tot_cycles += s_elapsed_time;
1041             au4_peak_window[u4_peak_window_idx++] = s_elapsed_time;
1042 
1043             if(u4_peak_window_idx == PEAK_WINDOW_SIZE)
1044             {
1045                 u4_peak_window_idx = 0;
1046             }
1047 
1048             peak_avg = 0;
1049             for(id = 0; id < PEAK_WINDOW_SIZE; id++)
1050             {
1051                 peak_avg += au4_peak_window[id];
1052             }
1053 
1054             peak_avg /= PEAK_WINDOW_SIZE;
1055             if(peak_avg > u4_peak_avg_max) u4_peak_avg_max = peak_avg;
1056             u4_frm_cnt++;
1057 
1058             printf(
1059                 "FrameNum: %4d TimeTaken(microsec): %6d AvgTime: %6d "
1060                 "PeakAvgTimeMax: "
1061                 "%6d Output: %2d NumBytes: %6d \n",
1062                 u4_frm_cnt, s_elapsed_time, u4_tot_cycles / u4_frm_cnt, u4_peak_avg_max,
1063                 s_video_decode_op.s_ivd_op.u4_output_present,
1064                 s_video_decode_op.s_ivd_op.u4_num_bytes_consumed);
1065         }
1066 #else
1067         printf("%d\n", s_video_decode_op.s_ivd_op.u4_num_bytes_consumed);
1068 #endif
1069 
1070         if(ret != IV_SUCCESS)
1071         {
1072             pe_error_code[0] = s_video_decode_op.s_ivd_op.u4_error_code;
1073 
1074             return ret;
1075         }
1076 
1077         u4_num_bytes_dec = s_video_decode_op.s_ivd_op.u4_num_bytes_consumed;
1078 
1079         pu4_file_pos[0] += u4_num_bytes_dec;
1080         pu4_num_bytes_consumed[0] += u4_num_bytes_dec;
1081         pu4_ip_frm_ts[0]++;
1082 
1083         if(s_video_decode_op.s_ivd_op.u4_output_present)
1084         {
1085             char cur_fname[1000];
1086 
1087             char *extn = NULL;
1088 
1089             /* The objective is to dump the decoded frames into separate files
1090              * instead of dumping all the frames in one common file. Also, the
1091              * number of dumped frames at any given instance of time cannot exceed
1092              * 'frame_memory'
1093              */
1094             if(ps_app_ctxt->u4_file_save_flag)
1095             {
1096                 /* Locate the position of extension yuv */
1097                 extn = strstr((char *) ps_app_ctxt->s_mvc_app_files.au1_op_fname, "%d");
1098 
1099                 if(extn != NULL)
1100                 {
1101                     mvcd_output_write_stall(ps_app_ctxt->s_mvc_app_files.au1_op_fname,
1102                                             pu4_op_frm_ts[0]);
1103 
1104                     sprintf(cur_fname, (char *) ps_app_ctxt->s_mvc_app_files.au1_op_fname,
1105                             pu4_op_frm_ts[0]);
1106 
1107                     pps_op_file[0] = fopen(cur_fname, "wb");
1108 
1109                     if(NULL == pps_op_file[0])
1110                     {
1111                         pe_error_code[0] = IVD_MEM_ALLOC_FAILED;
1112 
1113                         return IV_FAIL;
1114                     }
1115                 }
1116             }
1117 
1118             if(u2_num_views > 1)
1119             {
1120                 if(s_video_decode_op.ps_view_disp_bufs[0].u4_y_wd !=
1121                    s_video_decode_op.ps_view_disp_bufs[1].u4_y_wd)
1122                 {
1123                     pe_error_code[0] = IVD_MEM_ALLOC_FAILED;
1124 
1125                     return IV_FAIL;
1126                 }
1127 
1128                 if(s_video_decode_op.ps_view_disp_bufs[0].u4_y_ht !=
1129                    s_video_decode_op.ps_view_disp_bufs[1].u4_y_ht)
1130                 {
1131                     pe_error_code[0] = IVD_MEM_ALLOC_FAILED;
1132 
1133                     return IV_FAIL;
1134                 }
1135             }
1136 
1137             mvcd_dump_output(ps_app_ctxt, s_video_decode_op.ps_view_disp_bufs, pps_op_file,
1138                              pps_op_chksum_file, u2_num_views);
1139 
1140             pu4_op_frm_ts[0]++;
1141         }
1142         else if((s_video_decode_op.s_ivd_op.u4_error_code >> IVD_FATALERROR) & 1)
1143         {
1144             pe_error_code[0] = s_video_decode_op.s_ivd_op.u4_error_code;
1145 
1146             return IV_FAIL;
1147         }
1148     }
1149 
1150 #ifdef PROFILE_ENABLE
1151     printf("Summary\n");
1152     printf("Input filename                  : %s\n", ps_app_ctxt->s_mvc_app_files.au1_ip_fname);
1153     printf("Output Width                    : %-4d\n", ps_app_ctxt->u4_pic_wd);
1154     printf("Output Height                   : %-4d\n", ps_app_ctxt->u4_pic_ht);
1155 
1156     if(u4_frm_cnt)
1157     {
1158         double avg = u4_tot_cycles / u4_frm_cnt;
1159         double bytes_avg = pu4_num_bytes_consumed[0] / u4_frm_cnt;
1160         double bitrate = (bytes_avg * 8 * ps_app_ctxt->u4_fps) / 1000000;
1161 
1162         printf("Bitrate @ %2d u4_fps(mbps)          : %-6.2f\n", ps_app_ctxt->u4_fps, bitrate);
1163         printf("Average decode time(micro sec)  : %-6d\n", (WORD32) avg);
1164         printf("Avg Peak decode time(%2d frames) : %-6d\n", PEAK_WINDOW_SIZE,
1165                (WORD32) u4_peak_avg_max);
1166 
1167         avg = (u4_tot_cycles + u4_tot_fmt_cycles) * 1.0 / u4_frm_cnt;
1168         printf("FPS achieved (with format conv) : %-3.2f\n", 1000000 / avg);
1169     }
1170 #endif
1171 
1172     return IV_SUCCESS;
1173 }
1174 
mvcd_delete_decoder(mvc_dec_ctx_t * ps_app_ctxt)1175 static IV_API_CALL_STATUS_T mvcd_delete_decoder(mvc_dec_ctx_t *ps_app_ctxt)
1176 {
1177     imvcd_delete_ip_t s_delete_ip;
1178     imvcd_delete_op_t s_delete_op;
1179 
1180     s_delete_ip.s_ivd_ip.e_cmd = IVD_CMD_DELETE;
1181 
1182     s_delete_ip.s_ivd_ip.u4_size = sizeof(s_delete_ip.s_ivd_ip);
1183     s_delete_op.s_ivd_op.u4_size = sizeof(s_delete_op.s_ivd_op);
1184 
1185     return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_delete_ip, &s_delete_op);
1186 }
1187 
main(WORD32 argc,char * argv[])1188 int main(WORD32 argc, char *argv[])
1189 {
1190     mvc_dec_ctx_t s_app_ctxt;
1191     ivd_out_bufdesc_t s_out_buf;
1192 
1193     IV_API_CALL_STATUS_T ret;
1194     IVD_ERROR_CODES_T e_error_code;
1195 
1196     UWORD8 au1_cfg_fname[STRLENGTH];
1197     UWORD8 au1_error_str[STRLENGTH];
1198     UWORD32 i;
1199     UWORD32 u4_ip_buf_len;
1200     UWORD32 u4_total_bytes_consumed;
1201     UWORD8 au1_view_file_names[STRLENGTH];
1202     UWORD16 u2_num_views;
1203     UWORD32 u4_num_header_bytes;
1204 
1205     FILE *ps_cfg_file = NULL;
1206     FILE *ps_ip_file = NULL;
1207     FILE *aps_op_file[MAX_NUM_VIEWS] = {NULL};
1208     FILE *aps_op_chksum_file[MAX_NUM_VIEWS] = {NULL};
1209 
1210     UWORD8 *pu1_bs_buf = NULL;
1211     UWORD32 u4_file_pos = 0;
1212     UWORD32 u4_ip_frm_ts = 0, u4_op_frm_ts = 0;
1213     UWORD32 u4_bytes_remaining = 0;
1214 
1215     /* Usage */
1216     if(argc < 2)
1217     {
1218         mvcd_print_usage();
1219 
1220         exit(-1);
1221     }
1222     else if(argc == 2)
1223     {
1224         strcpy((char *) au1_cfg_fname, argv[1]);
1225     }
1226 
1227     /***********************************************************************/
1228     /*                  Initialize Application parameters                  */
1229     /***********************************************************************/
1230     strcpy((char *) s_app_ctxt.s_mvc_app_files.au1_ip_fname, "\0");
1231     s_app_ctxt.u4_disp_delay = 0;
1232     s_app_ctxt.u4_max_frm_ts = 100;
1233     s_app_ctxt.u4_loopback = 0;
1234     u4_file_pos = 0;
1235     u4_total_bytes_consumed = 0;
1236     u4_ip_frm_ts = 0;
1237     u4_op_frm_ts = 0;
1238 
1239     s_app_ctxt.u4_num_cores = DEFAULT_NUM_CORES;
1240     s_app_ctxt.i4_degrade_type = 0;
1241     s_app_ctxt.i4_degrade_pics = 0;
1242     s_app_ctxt.e_arch = ARCH_X86_SSE42;
1243     s_app_ctxt.e_soc = SOC_GENERIC;
1244     s_app_ctxt.u1_quit = 0;
1245     s_app_ctxt.u4_disable_dblk_level = 0;
1246     s_app_ctxt.u4_file_save_flag = 0;
1247     s_app_ctxt.u4_chksum_save_flag = 0;
1248     s_app_ctxt.e_output_chroma_format = DEFAULT_COLOR_FORMAT;
1249 
1250     /*************************************************************************/
1251     /* Parse arguments                                                       */
1252     /*************************************************************************/
1253 
1254     /* Read command line arguments */
1255     if(argc > 2)
1256     {
1257         for(i = 1; i < (UWORD32) argc; i += 2)
1258         {
1259             if(CONFIG == mvcd_get_argument(argv[i]))
1260             {
1261                 strcpy((char *) au1_cfg_fname, argv[i + 1]);
1262 
1263                 if((ps_cfg_file = fopen((char *) au1_cfg_fname, "r")) == NULL)
1264                 {
1265                     sprintf((char *) au1_error_str, "Could not open Configuration file %s",
1266                             au1_cfg_fname);
1267 
1268                     mvcd_exit(au1_error_str);
1269                 }
1270                 mvcd_read_cfg_file(&s_app_ctxt, ps_cfg_file);
1271                 fclose(ps_cfg_file);
1272             }
1273             else
1274             {
1275                 mvcd_parse_argument(&s_app_ctxt, argv[i], argv[i + 1]);
1276             }
1277         }
1278     }
1279     else
1280     {
1281         if((ps_cfg_file = fopen((char *) au1_cfg_fname, "r")) == NULL)
1282         {
1283             sprintf((char *) au1_error_str, "Could not open Configuration file %s", au1_cfg_fname);
1284             mvcd_exit(au1_error_str);
1285         }
1286 
1287         mvcd_read_cfg_file(&s_app_ctxt, ps_cfg_file);
1288 
1289         fclose(ps_cfg_file);
1290     }
1291 
1292     if(strcmp((char *) s_app_ctxt.s_mvc_app_files.au1_ip_fname, "\0") == 0)
1293     {
1294         printf("\nNo input file given for decoding\n");
1295 
1296         exit(-1);
1297     }
1298 
1299     /***********************************************************************/
1300     /*          create the file object for input file                      */
1301     /***********************************************************************/
1302     ps_ip_file = fopen((char *) s_app_ctxt.s_mvc_app_files.au1_ip_fname, "rb");
1303 
1304     if(NULL == ps_ip_file)
1305     {
1306         sprintf((char *) au1_error_str, "Could not open input file %s",
1307                 s_app_ctxt.s_mvc_app_files.au1_ip_fname);
1308 
1309         mvcd_exit(au1_error_str);
1310     }
1311 
1312     /***********************************************************************/
1313     /*          create the file object for output file                     */
1314     /***********************************************************************/
1315     /* If the filename does not contain %d, then output will be dumped to
1316        a single file and it is opened here */
1317     if((1 == s_app_ctxt.u4_file_save_flag) &&
1318        (strstr((char *) s_app_ctxt.s_mvc_app_files.au1_op_fname, "%d") == NULL))
1319     {
1320         mvcd_get_view_file_name(s_app_ctxt.s_mvc_app_files.au1_op_fname, au1_view_file_names, 0);
1321 
1322         aps_op_file[0] = fopen((char *) au1_view_file_names, "wb");
1323 
1324         if(NULL == aps_op_file[0])
1325         {
1326             const CHAR au1_explanatory_string[] = "Could not open output file ";
1327             UWORD8 au1_error_str[STRLENGTH + sizeof(au1_explanatory_string) + 1];
1328 
1329             sprintf((char *) au1_error_str, "%s%s", au1_explanatory_string, au1_view_file_names);
1330             mvcd_exit(au1_error_str);
1331         }
1332     }
1333 
1334     /***********************************************************************/
1335     /*          create the file object for check sum file                  */
1336     /***********************************************************************/
1337     if((1 == s_app_ctxt.u4_chksum_save_flag) &&
1338        (strstr((char *) s_app_ctxt.s_mvc_app_files.au1_op_chksum_fname, "%d") == NULL))
1339     {
1340         mvcd_get_view_file_name(s_app_ctxt.s_mvc_app_files.au1_op_chksum_fname, au1_view_file_names,
1341                                 0);
1342         aps_op_chksum_file[0] = fopen((char *) au1_view_file_names, "wb");
1343 
1344         if(NULL == aps_op_chksum_file[0])
1345         {
1346             const CHAR au1_explanatory_string[] = "Could not open check sum file ";
1347             UWORD8 au1_error_str[STRLENGTH + sizeof(au1_explanatory_string) + 1];
1348 
1349             sprintf((char *) au1_error_str, "%s%s", au1_explanatory_string, au1_view_file_names);
1350             mvcd_exit(au1_error_str);
1351         }
1352     }
1353 
1354     /***************************/
1355     /* Create decoder instance */
1356     /***************************/
1357     ret = mvcd_create_decoder(&s_app_ctxt);
1358 
1359     if(ret != IV_SUCCESS)
1360     {
1361         sprintf((char *) au1_error_str, "Error in Create %8x\n", ret);
1362 
1363         mvcd_exit(au1_error_str);
1364     }
1365 
1366     /**************/
1367     /* set params */
1368     /**************/
1369     ret = mvcd_set_decode_mode(&s_app_ctxt, IVD_DECODE_HEADER);
1370 
1371     if(ret != IV_SUCCESS)
1372     {
1373         sprintf((char *) au1_error_str, "\nError in Dec mode");
1374         mvcd_exit(au1_error_str);
1375     }
1376 
1377     /*************************************************************************/
1378     /* set num of cores                                                      */
1379     /*************************************************************************/
1380     ret = mvcd_set_num_cores(&s_app_ctxt);
1381 
1382     if(ret != IV_SUCCESS)
1383     {
1384         sprintf((char *) au1_error_str, "\nError in setting number of cores");
1385         mvcd_exit(au1_error_str);
1386     }
1387 
1388     /*************************************************************************/
1389     /* set processsor                                                        */
1390     /*************************************************************************/
1391     ret = mvcd_set_arch(&s_app_ctxt);
1392 
1393     if(ret != IV_SUCCESS)
1394     {
1395         sprintf((char *) au1_error_str, "\nError in setting Processor type");
1396         mvcd_exit(au1_error_str);
1397     }
1398 
1399     /*****************/
1400     /* Header Decode */
1401     /*****************/
1402     ret = mvcd_decode_header(&s_app_ctxt, &s_out_buf, ps_ip_file, &e_error_code,
1403                              &u4_num_header_bytes, u4_ip_frm_ts);
1404 
1405     if(ret != IV_SUCCESS)
1406     {
1407         sprintf((char *) au1_error_str, "Error in header decode 0x%x\n", e_error_code);
1408         mvcd_exit(au1_error_str);
1409     }
1410 
1411     u4_file_pos += u4_num_header_bytes;
1412     u4_total_bytes_consumed += u4_num_header_bytes;
1413 
1414     /****************/
1415     /* Get buf info */
1416     /****************/
1417     ret = mvcd_get_buf_info(&s_app_ctxt);
1418 
1419     if(ret != IV_SUCCESS)
1420     {
1421         sprintf((char *) au1_error_str, "Error in Get Buf Info %x",
1422                 s_app_ctxt.s_disp_buf_props.s_ivd_op.u4_error_code);
1423         mvcd_exit(au1_error_str);
1424     }
1425 
1426     u2_num_views = s_app_ctxt.s_disp_buf_props.s_mvc_buf_info.u2_num_views;
1427     ASSERT(u2_num_views <= MAX_NUM_VIEWS);
1428 
1429     ret = mvcd_out_buf_alloc(&s_app_ctxt, &s_out_buf);
1430 
1431     if(IV_SUCCESS != ret)
1432     {
1433         sprintf((char *) au1_error_str, "Error in Out buf alloc\n");
1434         mvcd_exit(au1_error_str);
1435     }
1436 
1437     /***************************************************************************/
1438     /*   create the file object for output file for other views(if present) */
1439     /***************************************************************************/
1440     for(i = 1; i < u2_num_views; i++)
1441     {
1442         if((1 == s_app_ctxt.u4_file_save_flag) &&
1443            (strstr((char *) s_app_ctxt.s_mvc_app_files.au1_op_fname, "%d") == NULL))
1444         {
1445             mvcd_get_view_file_name(s_app_ctxt.s_mvc_app_files.au1_op_fname, au1_view_file_names,
1446                                     i);
1447 
1448             aps_op_file[i] = fopen((char *) au1_view_file_names, "wb");
1449 
1450             if(NULL == aps_op_file[i])
1451             {
1452                 const UWORD8 au1_explanatory_string[] = "Could not open output file ";
1453                 UWORD8 au1_error_str[STRLENGTH + sizeof(au1_explanatory_string) + 1];
1454 
1455                 sprintf((char *) au1_error_str, "%s%s", au1_explanatory_string,
1456                         au1_view_file_names);
1457                 mvcd_exit(au1_error_str);
1458             }
1459         }
1460 
1461         if((1 == s_app_ctxt.u4_chksum_save_flag) &&
1462            (strstr((char *) s_app_ctxt.s_mvc_app_files.au1_op_chksum_fname, "%d") == NULL))
1463         {
1464             mvcd_get_view_file_name(s_app_ctxt.s_mvc_app_files.au1_op_chksum_fname,
1465                                     au1_view_file_names, i);
1466             aps_op_chksum_file[i] = fopen((char *) au1_view_file_names, "wb");
1467 
1468             if(NULL == aps_op_chksum_file[i])
1469             {
1470                 const UWORD8 au1_explanatory_string[] = "Could not open check sum file ";
1471                 UWORD8 au1_error_str[STRLENGTH + sizeof(au1_explanatory_string) + 1];
1472 
1473                 sprintf((char *) au1_error_str, "%s%s", au1_explanatory_string,
1474                         au1_view_file_names);
1475                 mvcd_exit(au1_error_str);
1476             }
1477         }
1478     }
1479 
1480     u4_ip_buf_len = s_app_ctxt.s_disp_buf_props.s_ivd_op.u4_min_in_buf_size[0];
1481     ret = mvcd_in_buf_alloc(&s_app_ctxt, &pu1_bs_buf);
1482 
1483     if(IV_SUCCESS != ret)
1484     {
1485         sprintf((char *) au1_error_str, "Error in In buf alloc\n");
1486         mvcd_exit(au1_error_str);
1487     }
1488 
1489     ret = mvcd_decode_frame(&s_app_ctxt, &s_out_buf, ps_ip_file, aps_op_file, aps_op_chksum_file,
1490                             pu1_bs_buf, &e_error_code, &u4_total_bytes_consumed, &u4_file_pos,
1491                             &u4_ip_frm_ts, &u4_op_frm_ts, u4_ip_buf_len);
1492 
1493     if(ret != IV_SUCCESS)
1494     {
1495         sprintf((char *) au1_error_str, "Error in Frame decode 0x%x\n", e_error_code);
1496         mvcd_exit(au1_error_str);
1497     }
1498 
1499     /***********************************************************************/
1500     /*      To get the last decoded frames, call process with NULL input    */
1501     /***********************************************************************/
1502     ret = mvcd_flush(&s_app_ctxt, &s_out_buf, aps_op_file, aps_op_chksum_file, pu1_bs_buf,
1503                      &u4_op_frm_ts, u4_ip_frm_ts, u4_bytes_remaining, u2_num_views);
1504 
1505     if(ret != IV_SUCCESS)
1506     {
1507         sprintf((char *) au1_error_str, "\nError in Setting the decoder in flush mode");
1508         mvcd_exit(au1_error_str);
1509     }
1510 
1511     s_app_ctxt.u1_quit = 1;
1512 
1513     ret = mvcd_delete_decoder(&s_app_ctxt);
1514 
1515     if(IV_SUCCESS != ret)
1516     {
1517         sprintf((char *) au1_error_str, "Error in Codec delete");
1518         mvcd_exit(au1_error_str);
1519     }
1520 
1521     /***********************************************************************/
1522     /*              Close all the files and free all the memory            */
1523     /***********************************************************************/
1524     fclose(ps_ip_file);
1525 
1526     for(i = 0; i < u2_num_views; i++)
1527     {
1528         if(aps_op_file[i])
1529         {
1530             fclose(aps_op_file[i]);
1531         }
1532 
1533         if(aps_op_chksum_file[i])
1534         {
1535             fclose(aps_op_chksum_file[i]);
1536         }
1537     }
1538 
1539     mvcd_in_buf_free(pu1_bs_buf);
1540 
1541     mvcd_out_buf_free(&s_out_buf);
1542 
1543     return (0);
1544 }
1545