1 /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 // System dependencies 31 #include <pthread.h> 32 #include <stdlib.h> 33 #define TIME_H <SYSTEM_HEADER_PREFIX/time.h> 34 #include TIME_H 35 36 // JPEG dependencies 37 #include "mm_jpeg_interface.h" 38 #include "mm_jpeg_ionbuf.h" 39 40 // Camera dependencies 41 #include "mm_camera_dbg.h" 42 43 #define MAX_NUM_BUFS (12) 44 #define MAX_NUM_CLIENT (8) 45 46 /** DUMP_TO_FILE: 47 * @filename: file name 48 * @p_addr: address of the buffer 49 * @len: buffer length 50 * 51 * dump the image to the file 52 **/ 53 #define DUMP_TO_FILE(filename, p_addr, len) ({ \ 54 FILE *fp = fopen(filename, "w+"); \ 55 if (fp) { \ 56 fwrite(p_addr, 1, len, fp); \ 57 fclose(fp); \ 58 } else { \ 59 LOGE("cannot dump image"); \ 60 } \ 61 }) 62 63 static uint32_t g_count = 1U, g_i; 64 65 typedef struct { 66 mm_jpeg_color_format fmt; 67 cam_rational_type_t mult; 68 const char *str; 69 } mm_jpeg_intf_test_colfmt_t; 70 71 typedef struct { 72 char *filename; 73 int width; 74 int height; 75 char *out_filename; 76 uint32_t burst_mode; 77 uint32_t min_out_bufs; 78 mm_jpeg_intf_test_colfmt_t col_fmt; 79 uint32_t encode_thumbnail; 80 int tmb_width; 81 int tmb_height; 82 int main_quality; 83 int thumb_quality; 84 char *qtable_luma_file; 85 char *qtable_chroma_file; 86 int client_cnt; 87 } jpeg_test_input_t; 88 89 /* Static constants */ 90 /* default Luma Qtable */ 91 uint8_t DEFAULT_QTABLE_0[QUANT_SIZE] = { 92 16, 11, 10, 16, 24, 40, 51, 61, 93 12, 12, 14, 19, 26, 58, 60, 55, 94 14, 13, 16, 24, 40, 57, 69, 56, 95 14, 17, 22, 29, 51, 87, 80, 62, 96 18, 22, 37, 56, 68, 109, 103, 77, 97 24, 35, 55, 64, 81, 104, 113, 92, 98 49, 64, 78, 87, 103, 121, 120, 101, 99 72, 92, 95, 98, 112, 100, 103, 99 100 }; 101 102 /* default Chroma Qtable */ 103 uint8_t DEFAULT_QTABLE_1[QUANT_SIZE] = { 104 17, 18, 24, 47, 99, 99, 99, 99, 105 18, 21, 26, 66, 99, 99, 99, 99, 106 24, 26, 56, 99, 99, 99, 99, 99, 107 47, 66, 99, 99, 99, 99, 99, 99, 108 99, 99, 99, 99, 99, 99, 99, 99, 109 99, 99, 99, 99, 99, 99, 99, 99, 110 99, 99, 99, 99, 99, 99, 99, 99, 111 99, 99, 99, 99, 99, 99, 99, 99 112 }; 113 114 typedef struct { 115 char *filename[MAX_NUM_BUFS]; 116 int width; 117 int height; 118 char *out_filename[MAX_NUM_BUFS]; 119 pthread_mutex_t lock; 120 pthread_cond_t cond; 121 pthread_t thread_id; 122 buffer_t input[MAX_NUM_BUFS]; 123 buffer_t output[MAX_NUM_BUFS]; 124 int use_ion; 125 uint32_t handle; 126 mm_jpeg_ops_t ops; 127 uint32_t job_id[MAX_NUM_BUFS]; 128 mm_jpeg_encode_params_t params; 129 mm_jpeg_job_t job; 130 uint32_t session_id; 131 uint32_t num_bufs; 132 uint32_t min_out_bufs; 133 size_t buf_filled_len[MAX_NUM_BUFS]; 134 mm_dimension pic_size; 135 int ret; 136 int clinet_id; 137 } mm_jpeg_intf_test_t; 138 139 140 141 static const mm_jpeg_intf_test_colfmt_t color_formats[] = 142 { 143 { MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2, {3, 2}, "YCRCBLP_H2V2" }, 144 { MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2, {3, 2}, "YCBCRLP_H2V2" }, 145 { MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1, {2, 1}, "YCRCBLP_H2V1" }, 146 { MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1, {2, 1}, "YCBCRLP_H2V1" }, 147 { MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2, {2, 1}, "YCRCBLP_H1V2" }, 148 { MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2, {2, 1}, "YCBCRLP_H1V2" }, 149 { MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1, {3, 1}, "YCRCBLP_H1V1" }, 150 { MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1, {3, 1}, "YCBCRLP_H1V1" } 151 }; 152 153 static jpeg_test_input_t jpeg_input[] = { 154 { QCAMERA_DUMP_FRM_LOCATION"test_1.yuv", 4000, 3008, QCAMERA_DUMP_FRM_LOCATION"test_1.jpg", 0, 0, 155 { MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2, {3, 2}, "YCRCBLP_H2V2" }, 156 0, 320, 240, 80, 80, NULL, NULL, 1} 157 }; 158 159 static void mm_jpeg_encode_callback(jpeg_job_status_t status, 160 uint32_t client_hdl, 161 uint32_t jobId, 162 mm_jpeg_output_t *p_output, 163 void *userData) 164 { 165 mm_jpeg_intf_test_t *p_obj = (mm_jpeg_intf_test_t *)userData; 166 167 pthread_mutex_lock(&p_obj->lock); 168 169 if (status == JPEG_JOB_STATUS_ERROR) { 170 LOGE("Encode error"); 171 } else { 172 int i = 0; 173 for (i = 0; p_obj->job_id[i] && (jobId != p_obj->job_id[i]); i++) 174 ; 175 if (!p_obj->job_id[i]) { 176 LOGE("Cannot find job ID!!!"); 177 goto error; 178 } 179 LOGE("Encode success addr %p len %zu idx %d", 180 p_output->buf_vaddr, p_output->buf_filled_len, i); 181 182 p_obj->buf_filled_len[i] = p_output->buf_filled_len; 183 if (p_obj->min_out_bufs) { 184 LOGE("Saving file%s addr %p len %zu", 185 p_obj->out_filename[i], 186 p_output->buf_vaddr, p_output->buf_filled_len); 187 DUMP_TO_FILE(p_obj->out_filename[i], p_output->buf_vaddr, 188 p_output->buf_filled_len); 189 } 190 } 191 g_i++; 192 193 error: 194 195 if (g_i >= g_count) { 196 LOGE("Signal the thread"); 197 pthread_cond_signal(&p_obj->cond); 198 } 199 pthread_mutex_unlock(&p_obj->lock); 200 } 201 202 int mm_jpeg_test_alloc(buffer_t *p_buffer, int use_pmem) 203 { 204 int ret = 0; 205 /*Allocate buffers*/ 206 if (use_pmem) { 207 p_buffer->addr = (uint8_t *)buffer_allocate(p_buffer, 0); 208 if (NULL == p_buffer->addr) { 209 LOGE("Error"); 210 return -1; 211 } 212 } else { 213 /* Allocate heap memory */ 214 p_buffer->addr = (uint8_t *)malloc(p_buffer->size); 215 if (NULL == p_buffer->addr) { 216 LOGE("Error"); 217 return -1; 218 } 219 } 220 return ret; 221 } 222 223 void mm_jpeg_test_free(buffer_t *p_buffer) 224 { 225 if (p_buffer->addr == NULL) 226 return; 227 228 if (p_buffer->p_pmem_fd >= 0) 229 buffer_deallocate(p_buffer); 230 else 231 free(p_buffer->addr); 232 233 memset(p_buffer, 0x0, sizeof(buffer_t)); 234 } 235 236 int mm_jpeg_test_read(mm_jpeg_intf_test_t *p_obj, uint32_t idx) 237 { 238 FILE *fp = NULL; 239 size_t file_size = 0; 240 fp = fopen(p_obj->filename[idx], "rb"); 241 if (!fp) { 242 LOGE("error"); 243 return -1; 244 } 245 fseek(fp, 0, SEEK_END); 246 file_size = (size_t)ftell(fp); 247 fseek(fp, 0, SEEK_SET); 248 LOGE("input file size is %zu buf_size %zu", 249 file_size, p_obj->input[idx].size); 250 251 if (p_obj->input[idx].size > file_size) { 252 LOGE("error"); 253 fclose(fp); 254 return -1; 255 } 256 fread(p_obj->input[idx].addr, 1, p_obj->input[idx].size, fp); 257 fclose(fp); 258 return 0; 259 } 260 261 /** mm_jpeg_test_read_qtable: 262 * 263 * Arguments: 264 * @filename: Qtable filename 265 * @chroma_flag: Flag indicating chroma qtable 266 * 267 * Return: 268 * 0 success, failure otherwise 269 * 270 * Description: 271 * Reads qtable from file and sets it in appropriate qtable 272 * based on flag. 273 **/ 274 int mm_jpeg_test_read_qtable(const char *filename, bool chroma_flag) 275 { 276 FILE *fp = NULL; 277 int i; 278 279 if (filename == NULL) 280 return 0; 281 282 fp = fopen(filename, "r"); 283 if (!fp) { 284 LOGE("error cannot open file"); 285 return -1; 286 } 287 288 if (chroma_flag) { 289 for (i = 0; i < QUANT_SIZE; i++) 290 fscanf(fp, "%hhu,", &DEFAULT_QTABLE_1[i]); 291 } else { 292 for (i = 0; i < QUANT_SIZE; i++) 293 fscanf(fp, "%hhu,", &DEFAULT_QTABLE_0[i]); 294 } 295 296 fclose(fp); 297 return 0; 298 } 299 300 static int encode_init(jpeg_test_input_t *p_input, mm_jpeg_intf_test_t *p_obj, 301 int client_id) 302 { 303 int rc = -1; 304 size_t size = (size_t)(p_input->width * p_input->height); 305 mm_jpeg_encode_params_t *p_params = &p_obj->params; 306 mm_jpeg_encode_job_t *p_job_params = &p_obj->job.encode_job; 307 uint32_t i = 0; 308 uint32_t burst_mode = p_input->burst_mode; 309 jpeg_test_input_t *p_in = p_input; 310 311 do { 312 p_obj->filename[i] = p_in->filename; 313 p_obj->width = p_input->width; 314 p_obj->height = p_input->height; 315 p_obj->out_filename[i] = p_in->out_filename; 316 p_obj->use_ion = 1; 317 p_obj->min_out_bufs = p_input->min_out_bufs; 318 319 /* allocate buffers */ 320 p_obj->input[i].size = size * (size_t)p_input->col_fmt.mult.numerator / 321 (size_t)p_input->col_fmt.mult.denominator; 322 rc = mm_jpeg_test_alloc(&p_obj->input[i], p_obj->use_ion); 323 if (rc) { 324 LOGE("Error"); 325 return -1; 326 } 327 328 329 rc = mm_jpeg_test_read(p_obj, i); 330 if (rc) { 331 LOGE("Error, unable to read input image"); 332 return -1; 333 } 334 335 mm_jpeg_test_read_qtable(p_input->qtable_luma_file, false); 336 if (rc) { 337 LOGE("Error, unable to read luma qtable"); 338 return -1; 339 } 340 341 mm_jpeg_test_read_qtable(p_input->qtable_chroma_file, true); 342 if (rc) { 343 LOGE("Error, unable to read chrome qtable"); 344 return -1; 345 } 346 347 /* src buffer config*/ 348 p_params->src_main_buf[i].buf_size = p_obj->input[i].size; 349 p_params->src_main_buf[i].buf_vaddr = p_obj->input[i].addr; 350 p_params->src_main_buf[i].fd = p_obj->input[i].p_pmem_fd; 351 p_params->src_main_buf[i].index = i; 352 p_params->src_main_buf[i].format = MM_JPEG_FMT_YUV; 353 p_params->src_main_buf[i].offset.mp[0].len = (uint32_t)size; 354 p_params->src_main_buf[i].offset.mp[0].stride = p_input->width; 355 p_params->src_main_buf[i].offset.mp[0].scanline = p_input->height; 356 p_params->src_main_buf[i].offset.mp[1].len = (uint32_t)(size >> 1); 357 358 /* src buffer config*/ 359 p_params->src_thumb_buf[i].buf_size = p_obj->input[i].size; 360 p_params->src_thumb_buf[i].buf_vaddr = p_obj->input[i].addr; 361 p_params->src_thumb_buf[i].fd = p_obj->input[i].p_pmem_fd; 362 p_params->src_thumb_buf[i].index = i; 363 p_params->src_thumb_buf[i].format = MM_JPEG_FMT_YUV; 364 p_params->src_thumb_buf[i].offset.mp[0].len = (uint32_t)size; 365 p_params->src_thumb_buf[i].offset.mp[0].stride = p_input->width; 366 p_params->src_thumb_buf[i].offset.mp[0].scanline = p_input->height; 367 p_params->src_thumb_buf[i].offset.mp[1].len = (uint32_t)(size >> 1); 368 369 370 i++; 371 } while((++p_in)->filename); 372 373 p_obj->num_bufs = i; 374 375 pthread_mutex_init(&p_obj->lock, NULL); 376 pthread_cond_init(&p_obj->cond, NULL); 377 378 379 /* set encode parameters */ 380 p_params->jpeg_cb = mm_jpeg_encode_callback; 381 p_params->userdata = p_obj; 382 p_params->color_format = p_input->col_fmt.fmt; 383 p_params->thumb_color_format = p_input->col_fmt.fmt; 384 385 if (p_obj->min_out_bufs) { 386 p_params->num_dst_bufs = 2; 387 } else { 388 p_params->num_dst_bufs = p_obj->num_bufs; 389 } 390 391 for (i = 0; i < (uint32_t)p_params->num_dst_bufs; i++) { 392 p_obj->output[i].size = size * 3/2; 393 rc = mm_jpeg_test_alloc(&p_obj->output[i], 0); 394 if (rc) { 395 LOGE("Error"); 396 return -1; 397 } 398 /* dest buffer config */ 399 p_params->dest_buf[i].buf_size = p_obj->output[i].size; 400 p_params->dest_buf[i].buf_vaddr = p_obj->output[i].addr; 401 p_params->dest_buf[i].fd = p_obj->output[i].p_pmem_fd; 402 p_params->dest_buf[i].index = i; 403 } 404 405 406 p_params->num_src_bufs = p_obj->num_bufs; 407 p_params->num_tmb_bufs = 0; 408 g_count = p_params->num_src_bufs; 409 410 p_params->encode_thumbnail = p_input->encode_thumbnail; 411 if (p_params->encode_thumbnail) { 412 p_params->num_tmb_bufs = p_obj->num_bufs; 413 } 414 p_params->quality = (uint32_t)p_input->main_quality; 415 p_params->thumb_quality = (uint32_t)p_input->thumb_quality; 416 417 p_job_params->dst_index = 0; 418 p_job_params->src_index = 0; 419 p_job_params->rotation = 0; 420 421 /* main dimension */ 422 p_job_params->main_dim.src_dim.width = p_obj->width; 423 p_job_params->main_dim.src_dim.height = p_obj->height; 424 p_job_params->main_dim.dst_dim.width = p_obj->width; 425 p_job_params->main_dim.dst_dim.height = p_obj->height; 426 p_job_params->main_dim.crop.top = 0; 427 p_job_params->main_dim.crop.left = 0; 428 p_job_params->main_dim.crop.width = p_obj->width; 429 p_job_params->main_dim.crop.height = p_obj->height; 430 431 p_params->main_dim = p_job_params->main_dim; 432 433 /* thumb dimension */ 434 p_job_params->thumb_dim.src_dim.width = p_obj->width; 435 p_job_params->thumb_dim.src_dim.height = p_obj->height; 436 p_job_params->thumb_dim.dst_dim.width = p_input->tmb_width; 437 p_job_params->thumb_dim.dst_dim.height = p_input->tmb_height; 438 p_job_params->thumb_dim.crop.top = 0; 439 p_job_params->thumb_dim.crop.left = 0; 440 p_job_params->thumb_dim.crop.width = 0; 441 p_job_params->thumb_dim.crop.height = 0; 442 443 p_params->thumb_dim = p_job_params->thumb_dim; 444 445 p_job_params->exif_info.numOfEntries = 0; 446 p_params->burst_mode = burst_mode; 447 448 /* Qtable */ 449 p_job_params->qtable[0].eQuantizationTable = 450 OMX_IMAGE_QuantizationTableLuma; 451 p_job_params->qtable[1].eQuantizationTable = 452 OMX_IMAGE_QuantizationTableChroma; 453 p_job_params->qtable_set[0] = 1; 454 p_job_params->qtable_set[1] = 1; 455 456 for (i = 0; i < QUANT_SIZE; i++) { 457 p_job_params->qtable[0].nQuantizationMatrix[i] = DEFAULT_QTABLE_0[i]; 458 p_job_params->qtable[1].nQuantizationMatrix[i] = DEFAULT_QTABLE_1[i]; 459 } 460 461 p_obj->pic_size.w = (uint32_t)p_input->width; 462 p_obj->pic_size.h = (uint32_t)p_input->height; 463 464 p_obj->clinet_id = client_id; 465 466 return 0; 467 } 468 469 static void *encode_test(void *data) 470 { 471 int rc = 0; 472 mm_jpeg_intf_test_t *jpeg_obj = (mm_jpeg_intf_test_t *)data; 473 char file_name[64]; 474 475 uint32_t i = 0; 476 jpeg_obj->handle = jpeg_open(&jpeg_obj->ops, NULL, jpeg_obj->pic_size, NULL); 477 if (jpeg_obj->handle == 0) { 478 LOGE("Error"); 479 jpeg_obj->ret = -1; 480 goto end; 481 } 482 483 rc = jpeg_obj->ops.create_session(jpeg_obj->handle, &jpeg_obj->params, 484 &jpeg_obj->job.encode_job.session_id); 485 if (jpeg_obj->job.encode_job.session_id == 0) { 486 LOGE("Error"); 487 jpeg_obj->ret = -1; 488 goto end; 489 } 490 491 for (i = 0; i < jpeg_obj->num_bufs; i++) { 492 jpeg_obj->job.job_type = JPEG_JOB_TYPE_ENCODE; 493 jpeg_obj->job.encode_job.src_index = (int32_t) i; 494 jpeg_obj->job.encode_job.dst_index = (int32_t) i; 495 jpeg_obj->job.encode_job.thumb_index = (uint32_t) i; 496 497 if (jpeg_obj->params.burst_mode && jpeg_obj->min_out_bufs) { 498 jpeg_obj->job.encode_job.dst_index = -1; 499 } 500 501 rc = jpeg_obj->ops.start_job(&jpeg_obj->job, &jpeg_obj->job_id[i]); 502 if (rc) { 503 LOGE("Error"); 504 jpeg_obj->ret = rc; 505 goto end; 506 } 507 } 508 jpeg_obj->job_id[i] = 0; 509 510 /* 511 usleep(5); 512 jpeg_obj->ops.abort_job(jpeg_obj->job_id[0]); 513 */ 514 pthread_mutex_lock(&jpeg_obj->lock); 515 pthread_cond_wait(&jpeg_obj->cond, &jpeg_obj->lock); 516 pthread_mutex_unlock(&jpeg_obj->lock); 517 518 jpeg_obj->ops.destroy_session(jpeg_obj->job.encode_job.session_id); 519 jpeg_obj->ops.close(jpeg_obj->handle); 520 521 end: 522 for (i = 0; i < jpeg_obj->num_bufs; i++) { 523 if (!jpeg_obj->min_out_bufs) { 524 // Save output files 525 LOGE("Saving file%s addr %p len %zu", 526 jpeg_obj->out_filename[i], 527 jpeg_obj->output[i].addr, jpeg_obj->buf_filled_len[i]); 528 529 snprintf(file_name, sizeof(file_name), "%s_%d.jpg", 530 jpeg_obj->out_filename[i], jpeg_obj->clinet_id); 531 fprintf(stderr, "Output file for client %d = %s\n", 532 jpeg_obj->clinet_id, file_name); 533 534 DUMP_TO_FILE(file_name, jpeg_obj->output[i].addr, 535 jpeg_obj->buf_filled_len[i]); 536 } 537 mm_jpeg_test_free(&jpeg_obj->input[i]); 538 mm_jpeg_test_free(&jpeg_obj->output[i]); 539 } 540 return NULL; 541 } 542 543 #define MAX_FILE_CNT (20) 544 static int mm_jpeg_test_get_input(int argc, char *argv[], 545 jpeg_test_input_t *p_test) 546 { 547 int c; 548 size_t in_file_cnt = 0, out_file_cnt = 0, i; 549 int idx = 0; 550 jpeg_test_input_t *p_test_base = p_test; 551 552 char *in_files[MAX_FILE_CNT]; 553 char *out_files[MAX_FILE_CNT]; 554 555 while ((c = getopt(argc, argv, "-I:O:W:H:F:BTx:y:Q:J:K:C:q:")) != -1) { 556 switch (c) { 557 case 'B': 558 fprintf(stderr, "%-25s\n", "Using burst mode"); 559 p_test->burst_mode = 1; 560 break; 561 case 'I': 562 for (idx = optind - 1; idx < argc; idx++) { 563 if (argv[idx][0] == '-') { 564 break; 565 } 566 in_files[in_file_cnt++] = argv[idx]; 567 } 568 optind = idx -1; 569 570 break; 571 case 'O': 572 for (idx = optind - 1; idx < argc; idx++) { 573 if (argv[idx][0] == '-') { 574 break; 575 } 576 out_files[out_file_cnt++] = argv[idx]; 577 } 578 optind = idx -1; 579 580 break; 581 case 'W': 582 p_test->width = atoi(optarg); 583 fprintf(stderr, "%-25s%d\n", "Width: ", p_test->width); 584 break; 585 case 'H': 586 p_test->height = atoi(optarg); 587 fprintf(stderr, "%-25s%d\n", "Height: ", p_test->height); 588 break; 589 case 'F': 590 p_test->col_fmt = color_formats[atoi(optarg)]; 591 fprintf(stderr, "%-25s%s\n", "Format: ", p_test->col_fmt.str); 592 break; 593 case 'M': 594 p_test->min_out_bufs = 1; 595 fprintf(stderr, "%-25s\n", "Using minimum number of output buffers"); 596 break; 597 case 'T': 598 p_test->encode_thumbnail = 1; 599 fprintf(stderr, "%-25s\n", "Encode thumbnail"); 600 break; 601 case 'x': 602 p_test->tmb_width = atoi(optarg); 603 fprintf(stderr, "%-25s%d\n", "Tmb Width: ", p_test->tmb_width); 604 break; 605 case 'y': 606 p_test->tmb_height = atoi(optarg); 607 fprintf(stderr, "%-25s%d\n", "Tmb Height: ", p_test->tmb_height); 608 break; 609 case 'Q': 610 p_test->main_quality = atoi(optarg); 611 fprintf(stderr, "%-25s%d\n", "Main quality: ", p_test->main_quality); 612 break; 613 case 'q': 614 p_test->thumb_quality = atoi(optarg); 615 fprintf(stderr, "%-25s%d\n", "Thumb quality: ", p_test->thumb_quality); 616 break; 617 case 'J': 618 p_test->qtable_luma_file = optarg; 619 fprintf(stderr, "%-25s%s\n", "Qtable luma path", 620 p_test->qtable_luma_file); 621 break; 622 case 'K': 623 p_test->qtable_chroma_file = optarg; 624 fprintf(stderr, "%-25s%s\n", "Qtable chroma path", 625 p_test->qtable_chroma_file); 626 break; 627 case 'C': 628 p_test->client_cnt = atoi(optarg); 629 fprintf(stderr, "%-25s%d\n", "Number of clients ", 630 p_test->client_cnt); 631 default:; 632 } 633 } 634 fprintf(stderr, "Infiles: %zu Outfiles: %zu\n", in_file_cnt, out_file_cnt); 635 636 if (p_test->client_cnt > MAX_NUM_CLIENT) { 637 fprintf(stderr, "Clients requested exceeds max limit %d\n", 638 MAX_NUM_CLIENT); 639 return 1; 640 } 641 if (in_file_cnt > out_file_cnt) { 642 fprintf(stderr, "%-25s\n", "Insufficient number of output files!"); 643 return 1; 644 } 645 646 // Discard the extra out files 647 out_file_cnt = in_file_cnt; 648 649 p_test = realloc(p_test, (in_file_cnt + 1) * sizeof(*p_test)); 650 if (!p_test) { 651 LOGE("Error"); 652 return 1; 653 } 654 memset(p_test+1, 0, (in_file_cnt) * sizeof(*p_test)); 655 656 for (i = 0; i < in_file_cnt; i++, p_test++) { 657 memcpy(p_test, p_test_base, sizeof(*p_test)); 658 p_test->filename = in_files[i]; 659 p_test->out_filename = out_files[i]; 660 fprintf(stderr, "Inf: %s Outf: %s\n", in_files[i], out_files[i]); 661 } 662 663 return 0; 664 } 665 666 static void mm_jpeg_test_print_usage() 667 { 668 fprintf(stderr, "Usage: program_name [options]\n"); 669 fprintf(stderr, "Mandatory options:\n"); 670 fprintf(stderr, " -I FILE1 [FILE2] [FILEN]\tList of input files\n"); 671 fprintf(stderr, " -O FILE1 [FILE2] [FILEN]\tList of output files\n"); 672 fprintf(stderr, " -W WIDTH\t\tOutput image width\n"); 673 fprintf(stderr, " -H HEIGHT\t\tOutput image height\n"); 674 fprintf(stderr, " -F \t\tColor format: \n"); 675 fprintf(stderr, "\t\t\t\t%s (0), %s (1), %s (2) %s (3)\n" 676 "\t\t\t\t%s (4), %s (5), %s (6) %s (7)\n ", 677 color_formats[0].str, color_formats[1].str, 678 color_formats[2].str, color_formats[3].str, 679 color_formats[4].str, color_formats[5].str, 680 color_formats[6].str, color_formats[7].str); 681 fprintf(stderr, "Optional:\n"); 682 fprintf(stderr, " -T \t\Encode thumbnail\n"); 683 fprintf(stderr, " -x TMB_WIDTH\t\tThumbnail width\n"); 684 fprintf(stderr, " -y TMB_HEIGHT\t\tThumbnail height\n"); 685 fprintf(stderr, " -Q MAIN_QUALITY\t\tMain image quality\n"); 686 fprintf(stderr, " -q TMB_QUALITY\t\tThumbnail image quality\n"); 687 fprintf(stderr, " -B \t\tBurst mode. Utilize both encoder engines on" 688 "supported targets\n"); 689 fprintf(stderr, " -M \t\tUse minimum number of output buffers \n"); 690 fprintf(stderr, " -J \t\tLuma QTable filename. Comma separated 8x8" 691 " matrix\n"); 692 fprintf(stderr, " -K \t\tChroma QTable filename. Comma separated" 693 " 8x8 matrix\n"); 694 fprintf(stderr, " -C \t\tNumber of clients to run in parllel\n"); 695 fprintf(stderr, "\n"); 696 } 697 698 /** main: 699 * 700 * Arguments: 701 * @argc 702 * @argv 703 * 704 * Return: 705 * 0 or -ve values 706 * 707 * Description: 708 * main function 709 * 710 **/ 711 int main(int argc, char* argv[]) 712 { 713 jpeg_test_input_t *p_test_input; 714 mm_jpeg_intf_test_t client[MAX_NUM_CLIENT]; 715 int ret = 0; 716 int i = 0; 717 int thread_cnt = 0; 718 719 if (argc > 1) { 720 p_test_input = calloc(2, sizeof(*p_test_input)); 721 if (!p_test_input) { 722 LOGE("Error"); 723 goto exit; 724 } 725 memcpy(p_test_input, &jpeg_input[0], sizeof(*p_test_input)); 726 ret = mm_jpeg_test_get_input(argc, argv, p_test_input); 727 if (ret) { 728 LOGE("Error"); 729 goto exit; 730 } 731 } else { 732 mm_jpeg_test_print_usage(); 733 return 1; 734 } 735 736 for (i = 0; i < p_test_input->client_cnt; i++) { 737 memset(&client[i], 0x0, sizeof(mm_jpeg_intf_test_t)); 738 ret = encode_init(p_test_input, &client[i], i); 739 if (ret) { 740 LOGE("Error"); 741 return -1; 742 } 743 744 ret = pthread_create(&client[i].thread_id, NULL, encode_test, 745 &client[i]); 746 if (ret != 0) { 747 fprintf(stderr, "Error in thread creation\n"); 748 break; 749 } 750 } 751 752 thread_cnt = i; 753 for (i = 0; i < thread_cnt; i++) { 754 pthread_join(client[i].thread_id, NULL); 755 } 756 757 exit: 758 for (i = 0; i < thread_cnt; i++) { 759 if (!client[i].ret) { 760 fprintf(stderr, "%-25s %d %s\n", "Client", i, "Success!"); 761 } else { 762 fprintf(stderr, "%-25s %d %s\n", "Client", i, "Fail!"); 763 } 764 } 765 766 if (argc > 1) { 767 if (p_test_input) { 768 free(p_test_input); 769 p_test_input = NULL; 770 } 771 } 772 773 return ret; 774 } 775 776 777