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