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 394 #ifdef MM_JPEG_USE_PIPELINE 395 rc = mm_jpeg_test_alloc(&p_obj->output[i], 1); 396 #else 397 rc = mm_jpeg_test_alloc(&p_obj->output[i], 0); 398 #endif 399 400 if (rc) { 401 LOGE("Error"); 402 return -1; 403 } 404 /* dest buffer config */ 405 p_params->dest_buf[i].buf_size = p_obj->output[i].size; 406 p_params->dest_buf[i].buf_vaddr = p_obj->output[i].addr; 407 p_params->dest_buf[i].fd = p_obj->output[i].p_pmem_fd; 408 p_params->dest_buf[i].index = i; 409 } 410 411 412 p_params->num_src_bufs = p_obj->num_bufs; 413 p_params->num_tmb_bufs = 0; 414 g_count = p_params->num_src_bufs; 415 416 p_params->encode_thumbnail = p_input->encode_thumbnail; 417 if (p_params->encode_thumbnail) { 418 p_params->num_tmb_bufs = p_obj->num_bufs; 419 } 420 p_params->quality = (uint32_t)p_input->main_quality; 421 p_params->thumb_quality = (uint32_t)p_input->thumb_quality; 422 423 p_job_params->dst_index = 0; 424 p_job_params->src_index = 0; 425 p_job_params->rotation = 0; 426 427 /* main dimension */ 428 p_job_params->main_dim.src_dim.width = p_obj->width; 429 p_job_params->main_dim.src_dim.height = p_obj->height; 430 p_job_params->main_dim.dst_dim.width = p_obj->width; 431 p_job_params->main_dim.dst_dim.height = p_obj->height; 432 p_job_params->main_dim.crop.top = 0; 433 p_job_params->main_dim.crop.left = 0; 434 p_job_params->main_dim.crop.width = p_obj->width; 435 p_job_params->main_dim.crop.height = p_obj->height; 436 437 p_params->main_dim = p_job_params->main_dim; 438 439 /* thumb dimension */ 440 p_job_params->thumb_dim.src_dim.width = p_obj->width; 441 p_job_params->thumb_dim.src_dim.height = p_obj->height; 442 p_job_params->thumb_dim.dst_dim.width = p_input->tmb_width; 443 p_job_params->thumb_dim.dst_dim.height = p_input->tmb_height; 444 p_job_params->thumb_dim.crop.top = 0; 445 p_job_params->thumb_dim.crop.left = 0; 446 p_job_params->thumb_dim.crop.width = 0; 447 p_job_params->thumb_dim.crop.height = 0; 448 449 p_params->thumb_dim = p_job_params->thumb_dim; 450 451 p_job_params->exif_info.numOfEntries = 0; 452 p_params->burst_mode = burst_mode; 453 454 /* Qtable */ 455 p_job_params->qtable[0].eQuantizationTable = 456 OMX_IMAGE_QuantizationTableLuma; 457 p_job_params->qtable[1].eQuantizationTable = 458 OMX_IMAGE_QuantizationTableChroma; 459 p_job_params->qtable_set[0] = 1; 460 p_job_params->qtable_set[1] = 1; 461 462 for (i = 0; i < QUANT_SIZE; i++) { 463 p_job_params->qtable[0].nQuantizationMatrix[i] = DEFAULT_QTABLE_0[i]; 464 p_job_params->qtable[1].nQuantizationMatrix[i] = DEFAULT_QTABLE_1[i]; 465 } 466 467 p_obj->pic_size.w = (uint32_t)p_input->width; 468 p_obj->pic_size.h = (uint32_t)p_input->height; 469 470 p_obj->clinet_id = client_id; 471 472 return 0; 473 } 474 475 static void *encode_test(void *data) 476 { 477 int rc = 0; 478 mm_jpeg_intf_test_t *jpeg_obj = (mm_jpeg_intf_test_t *)data; 479 char file_name[64]; 480 481 uint32_t i = 0; 482 jpeg_obj->handle = jpeg_open(&jpeg_obj->ops, NULL, jpeg_obj->pic_size, NULL); 483 if (jpeg_obj->handle == 0) { 484 LOGE("Error"); 485 jpeg_obj->ret = -1; 486 goto end; 487 } 488 489 rc = jpeg_obj->ops.create_session(jpeg_obj->handle, &jpeg_obj->params, 490 &jpeg_obj->job.encode_job.session_id); 491 if (jpeg_obj->job.encode_job.session_id == 0) { 492 LOGE("Error"); 493 jpeg_obj->ret = -1; 494 goto end; 495 } 496 497 for (i = 0; i < jpeg_obj->num_bufs; i++) { 498 jpeg_obj->job.job_type = JPEG_JOB_TYPE_ENCODE; 499 jpeg_obj->job.encode_job.src_index = (int32_t) i; 500 jpeg_obj->job.encode_job.dst_index = (int32_t) i; 501 jpeg_obj->job.encode_job.thumb_index = (uint32_t) i; 502 503 if (jpeg_obj->params.burst_mode && jpeg_obj->min_out_bufs) { 504 jpeg_obj->job.encode_job.dst_index = -1; 505 } 506 507 rc = jpeg_obj->ops.start_job(&jpeg_obj->job, &jpeg_obj->job_id[i]); 508 if (rc) { 509 LOGE("Error"); 510 jpeg_obj->ret = rc; 511 goto end; 512 } 513 } 514 jpeg_obj->job_id[i] = 0; 515 516 /* 517 usleep(5); 518 jpeg_obj->ops.abort_job(jpeg_obj->job_id[0]); 519 */ 520 pthread_mutex_lock(&jpeg_obj->lock); 521 pthread_cond_wait(&jpeg_obj->cond, &jpeg_obj->lock); 522 pthread_mutex_unlock(&jpeg_obj->lock); 523 524 jpeg_obj->ops.destroy_session(jpeg_obj->job.encode_job.session_id); 525 jpeg_obj->ops.close(jpeg_obj->handle); 526 527 end: 528 for (i = 0; i < jpeg_obj->num_bufs; i++) { 529 if (!jpeg_obj->min_out_bufs) { 530 // Save output files 531 LOGE("Saving file%s addr %p len %zu", 532 jpeg_obj->out_filename[i], 533 jpeg_obj->output[i].addr, jpeg_obj->buf_filled_len[i]); 534 535 snprintf(file_name, sizeof(file_name), "%s_%d.jpg", 536 jpeg_obj->out_filename[i], jpeg_obj->clinet_id); 537 fprintf(stderr, "Output file for client %d = %s\n", 538 jpeg_obj->clinet_id, file_name); 539 540 DUMP_TO_FILE(file_name, jpeg_obj->output[i].addr, 541 jpeg_obj->buf_filled_len[i]); 542 } 543 mm_jpeg_test_free(&jpeg_obj->input[i]); 544 mm_jpeg_test_free(&jpeg_obj->output[i]); 545 } 546 return NULL; 547 } 548 549 #define MAX_FILE_CNT (20) 550 static int mm_jpeg_test_get_input(int argc, char *argv[], 551 jpeg_test_input_t *p_test) 552 { 553 int c; 554 size_t in_file_cnt = 0, out_file_cnt = 0, i; 555 int idx = 0; 556 jpeg_test_input_t *p_test_base = p_test; 557 558 char *in_files[MAX_FILE_CNT]; 559 char *out_files[MAX_FILE_CNT]; 560 561 while ((c = getopt(argc, argv, "-I:O:W:H:F:BTx:y:Q:J:K:C:q:")) != -1) { 562 switch (c) { 563 case 'B': 564 fprintf(stderr, "%-25s\n", "Using burst mode"); 565 p_test->burst_mode = 1; 566 break; 567 case 'I': 568 for (idx = optind - 1; idx < argc; idx++) { 569 if (argv[idx][0] == '-') { 570 break; 571 } 572 in_files[in_file_cnt++] = argv[idx]; 573 } 574 optind = idx -1; 575 576 break; 577 case 'O': 578 for (idx = optind - 1; idx < argc; idx++) { 579 if (argv[idx][0] == '-') { 580 break; 581 } 582 out_files[out_file_cnt++] = argv[idx]; 583 } 584 optind = idx -1; 585 586 break; 587 case 'W': 588 p_test->width = atoi(optarg); 589 fprintf(stderr, "%-25s%d\n", "Width: ", p_test->width); 590 break; 591 case 'H': 592 p_test->height = atoi(optarg); 593 fprintf(stderr, "%-25s%d\n", "Height: ", p_test->height); 594 break; 595 case 'F': 596 p_test->col_fmt = color_formats[atoi(optarg)]; 597 fprintf(stderr, "%-25s%s\n", "Format: ", p_test->col_fmt.str); 598 break; 599 case 'M': 600 p_test->min_out_bufs = 1; 601 fprintf(stderr, "%-25s\n", "Using minimum number of output buffers"); 602 break; 603 case 'T': 604 p_test->encode_thumbnail = 1; 605 fprintf(stderr, "%-25s\n", "Encode thumbnail"); 606 break; 607 case 'x': 608 p_test->tmb_width = atoi(optarg); 609 fprintf(stderr, "%-25s%d\n", "Tmb Width: ", p_test->tmb_width); 610 break; 611 case 'y': 612 p_test->tmb_height = atoi(optarg); 613 fprintf(stderr, "%-25s%d\n", "Tmb Height: ", p_test->tmb_height); 614 break; 615 case 'Q': 616 p_test->main_quality = atoi(optarg); 617 fprintf(stderr, "%-25s%d\n", "Main quality: ", p_test->main_quality); 618 break; 619 case 'q': 620 p_test->thumb_quality = atoi(optarg); 621 fprintf(stderr, "%-25s%d\n", "Thumb quality: ", p_test->thumb_quality); 622 break; 623 case 'J': 624 p_test->qtable_luma_file = optarg; 625 fprintf(stderr, "%-25s%s\n", "Qtable luma path", 626 p_test->qtable_luma_file); 627 break; 628 case 'K': 629 p_test->qtable_chroma_file = optarg; 630 fprintf(stderr, "%-25s%s\n", "Qtable chroma path", 631 p_test->qtable_chroma_file); 632 break; 633 case 'C': 634 p_test->client_cnt = atoi(optarg); 635 fprintf(stderr, "%-25s%d\n", "Number of clients ", 636 p_test->client_cnt); 637 default:; 638 } 639 } 640 fprintf(stderr, "Infiles: %zu Outfiles: %zu\n", in_file_cnt, out_file_cnt); 641 642 if (p_test->client_cnt > MAX_NUM_CLIENT) { 643 fprintf(stderr, "Clients requested exceeds max limit %d\n", 644 MAX_NUM_CLIENT); 645 return 1; 646 } 647 if (in_file_cnt > out_file_cnt) { 648 fprintf(stderr, "%-25s\n", "Insufficient number of output files!"); 649 return 1; 650 } 651 652 // Discard the extra out files 653 out_file_cnt = in_file_cnt; 654 655 p_test = realloc(p_test, (in_file_cnt + 1) * sizeof(*p_test)); 656 if (!p_test) { 657 LOGE("Error"); 658 return 1; 659 } 660 memset(p_test+1, 0, (in_file_cnt) * sizeof(*p_test)); 661 662 for (i = 0; i < in_file_cnt; i++, p_test++) { 663 memcpy(p_test, p_test_base, sizeof(*p_test)); 664 p_test->filename = in_files[i]; 665 p_test->out_filename = out_files[i]; 666 fprintf(stderr, "Inf: %s Outf: %s\n", in_files[i], out_files[i]); 667 } 668 669 return 0; 670 } 671 672 static void mm_jpeg_test_print_usage() 673 { 674 fprintf(stderr, "Usage: program_name [options]\n"); 675 fprintf(stderr, "Mandatory options:\n"); 676 fprintf(stderr, " -I FILE1 [FILE2] [FILEN]\tList of input files\n"); 677 fprintf(stderr, " -O FILE1 [FILE2] [FILEN]\tList of output files\n"); 678 fprintf(stderr, " -W WIDTH\t\tOutput image width\n"); 679 fprintf(stderr, " -H HEIGHT\t\tOutput image height\n"); 680 fprintf(stderr, " -F \t\tColor format: \n"); 681 fprintf(stderr, "\t\t\t\t%s (0), %s (1), %s (2) %s (3)\n" 682 "\t\t\t\t%s (4), %s (5), %s (6) %s (7)\n ", 683 color_formats[0].str, color_formats[1].str, 684 color_formats[2].str, color_formats[3].str, 685 color_formats[4].str, color_formats[5].str, 686 color_formats[6].str, color_formats[7].str); 687 fprintf(stderr, "Optional:\n"); 688 fprintf(stderr, " -T \t\Encode thumbnail\n"); 689 fprintf(stderr, " -x TMB_WIDTH\t\tThumbnail width\n"); 690 fprintf(stderr, " -y TMB_HEIGHT\t\tThumbnail height\n"); 691 fprintf(stderr, " -Q MAIN_QUALITY\t\tMain image quality\n"); 692 fprintf(stderr, " -q TMB_QUALITY\t\tThumbnail image quality\n"); 693 fprintf(stderr, " -B \t\tBurst mode. Utilize both encoder engines on" 694 "supported targets\n"); 695 fprintf(stderr, " -M \t\tUse minimum number of output buffers \n"); 696 fprintf(stderr, " -J \t\tLuma QTable filename. Comma separated 8x8" 697 " matrix\n"); 698 fprintf(stderr, " -K \t\tChroma QTable filename. Comma separated" 699 " 8x8 matrix\n"); 700 fprintf(stderr, " -C \t\tNumber of clients to run in parllel\n"); 701 fprintf(stderr, "\n"); 702 } 703 704 /** main: 705 * 706 * Arguments: 707 * @argc 708 * @argv 709 * 710 * Return: 711 * 0 or -ve values 712 * 713 * Description: 714 * main function 715 * 716 **/ 717 int main(int argc, char* argv[]) 718 { 719 jpeg_test_input_t *p_test_input; 720 mm_jpeg_intf_test_t client[MAX_NUM_CLIENT]; 721 int ret = 0; 722 int i = 0; 723 int thread_cnt = 0; 724 725 if (argc > 1) { 726 p_test_input = calloc(2, sizeof(*p_test_input)); 727 if (!p_test_input) { 728 LOGE("Error"); 729 goto exit; 730 } 731 memcpy(p_test_input, &jpeg_input[0], sizeof(*p_test_input)); 732 ret = mm_jpeg_test_get_input(argc, argv, p_test_input); 733 if (ret) { 734 LOGE("Error"); 735 goto exit; 736 } 737 } else { 738 mm_jpeg_test_print_usage(); 739 return 1; 740 } 741 742 for (i = 0; i < p_test_input->client_cnt; i++) { 743 memset(&client[i], 0x0, sizeof(mm_jpeg_intf_test_t)); 744 ret = encode_init(p_test_input, &client[i], i); 745 if (ret) { 746 LOGE("Error"); 747 return -1; 748 } 749 750 ret = pthread_create(&client[i].thread_id, NULL, encode_test, 751 &client[i]); 752 if (ret != 0) { 753 fprintf(stderr, "Error in thread creation\n"); 754 break; 755 } 756 } 757 758 thread_cnt = i; 759 for (i = 0; i < thread_cnt; i++) { 760 pthread_join(client[i].thread_id, NULL); 761 } 762 763 exit: 764 for (i = 0; i < thread_cnt; i++) { 765 if (!client[i].ret) { 766 fprintf(stderr, "%-25s %d %s\n", "Client", i, "Success!"); 767 } else { 768 fprintf(stderr, "%-25s %d %s\n", "Client", i, "Fail!"); 769 } 770 } 771 772 if (argc > 1) { 773 if (p_test_input) { 774 free(p_test_input); 775 p_test_input = NULL; 776 } 777 } 778 779 return ret; 780 } 781 782 783