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 MIN(a,b) (((a) < (b)) ? (a) : (b)) 44 #define MAX(a,b) (((a) > (b)) ? (a) : (b)) 45 #define CLAMP(x, min, max) MIN(MAX((x), (min)), (max)) 46 47 #define TIME_IN_US(r) ((uint64_t)r.tv_sec * 1000000LL + (uint64_t)r.tv_usec) 48 struct timeval dtime[2]; 49 50 51 /** DUMP_TO_FILE: 52 * @filename: file name 53 * @p_addr: address of the buffer 54 * @len: buffer length 55 * 56 * dump the image to the file 57 **/ 58 #define DUMP_TO_FILE(filename, p_addr, len) ({ \ 59 size_t rc = 0; \ 60 FILE *fp = fopen(filename, "w+"); \ 61 if (fp) { \ 62 rc = fwrite(p_addr, 1, len, fp); \ 63 fclose(fp); \ 64 } else { \ 65 LOGE("cannot dump image"); \ 66 } \ 67 }) 68 69 static int g_count = 1, g_i; 70 71 typedef struct { 72 char *filename; 73 int width; 74 int height; 75 char *out_filename; 76 int format; 77 } jpeg_test_input_t; 78 79 typedef struct { 80 char *filename; 81 int width; 82 int height; 83 char *out_filename; 84 pthread_mutex_t lock; 85 pthread_cond_t cond; 86 buffer_t input; 87 buffer_t output; 88 int use_ion; 89 uint32_t handle; 90 mm_jpegdec_ops_t ops; 91 uint32_t job_id[5]; 92 mm_jpeg_decode_params_t params; 93 mm_jpeg_job_t job; 94 uint32_t session_id; 95 } mm_jpegdec_intf_test_t; 96 97 typedef struct { 98 char *format_str; 99 int eColorFormat; 100 } mm_jpegdec_col_fmt_t; 101 102 #define ARR_SZ(a) (sizeof(a)/sizeof(a[0])) 103 104 static const mm_jpegdec_col_fmt_t col_formats[] = 105 { 106 { "YCRCBLP_H2V2", (int)MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2 }, 107 { "YCBCRLP_H2V2", (int)MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2 }, 108 { "YCRCBLP_H2V1", (int)MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1 }, 109 { "YCBCRLP_H2V1", (int)MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1 }, 110 { "YCRCBLP_H1V2", (int)MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2 }, 111 { "YCBCRLP_H1V2", (int)MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2 }, 112 { "YCRCBLP_H1V1", (int)MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1 }, 113 { "YCBCRLP_H1V1", (int)MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1 } 114 }; 115 116 static void mm_jpegdec_decode_callback(jpeg_job_status_t status, 117 uint32_t client_hdl, 118 uint32_t jobId, 119 mm_jpeg_output_t *p_output, 120 void *userData) 121 { 122 mm_jpegdec_intf_test_t *p_obj = (mm_jpegdec_intf_test_t *)userData; 123 124 if (status == JPEG_JOB_STATUS_ERROR) { 125 LOGE("Decode error"); 126 } else { 127 gettimeofday(&dtime[1], NULL); 128 LOGE("Decode time %llu ms", 129 ((TIME_IN_US(dtime[1]) - TIME_IN_US(dtime[0]))/1000)); 130 131 LOGE("Decode success file%s addr %p len %zu", 132 p_obj->out_filename, 133 p_output->buf_vaddr, p_output->buf_filled_len); 134 DUMP_TO_FILE(p_obj->out_filename, p_output->buf_vaddr, p_output->buf_filled_len); 135 } 136 g_i++; 137 if (g_i >= g_count) { 138 LOGE("Signal the thread"); 139 pthread_cond_signal(&p_obj->cond); 140 } 141 } 142 143 int mm_jpegdec_test_alloc(buffer_t *p_buffer, int use_pmem) 144 { 145 int ret = 0; 146 /*Allocate buffers*/ 147 if (use_pmem) { 148 p_buffer->addr = (uint8_t *)buffer_allocate(p_buffer, 0); 149 if (NULL == p_buffer->addr) { 150 LOGE("Error"); 151 return -1; 152 } 153 } else { 154 /* Allocate heap memory */ 155 p_buffer->addr = (uint8_t *)malloc(p_buffer->size); 156 if (NULL == p_buffer->addr) { 157 LOGE("Error"); 158 return -1; 159 } 160 } 161 return ret; 162 } 163 164 void mm_jpegdec_test_free(buffer_t *p_buffer) 165 { 166 if (p_buffer->addr == NULL) 167 return; 168 169 if (p_buffer->p_pmem_fd >= 0) 170 buffer_deallocate(p_buffer); 171 else 172 free(p_buffer->addr); 173 174 memset(p_buffer, 0x0, sizeof(buffer_t)); 175 } 176 177 int mm_jpegdec_test_read(mm_jpegdec_intf_test_t *p_obj) 178 { 179 int rc = 0; 180 FILE *fp = NULL; 181 size_t file_size = 0; 182 fp = fopen(p_obj->filename, "rb"); 183 if (!fp) { 184 LOGE("error"); 185 return -1; 186 } 187 fseek(fp, 0, SEEK_END); 188 file_size = (size_t)ftell(fp); 189 fseek(fp, 0, SEEK_SET); 190 191 LOGE("input file size is %zu", 192 file_size); 193 194 p_obj->input.size = file_size; 195 196 /* allocate buffers */ 197 rc = mm_jpegdec_test_alloc(&p_obj->input, p_obj->use_ion); 198 if (rc) { 199 LOGE("Error"); 200 return -1; 201 } 202 203 fread(p_obj->input.addr, 1, p_obj->input.size, fp); 204 fclose(fp); 205 return 0; 206 } 207 208 void chromaScale(mm_jpeg_color_format format, double *cScale) 209 { 210 double scale; 211 212 switch(format) { 213 case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2: 214 case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2: 215 scale = 1.5; 216 break; 217 case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1: 218 case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1: 219 case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2: 220 case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2: 221 scale = 2.0; 222 break; 223 case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1: 224 case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1: 225 scale = 3.0; 226 break; 227 case MM_JPEG_COLOR_FORMAT_MONOCHROME: 228 scale = 1.0; 229 break; 230 default: 231 scale = 0; 232 LOGE("color format Error"); 233 } 234 235 *cScale = scale; 236 } 237 238 static int decode_init(jpeg_test_input_t *p_input, mm_jpegdec_intf_test_t *p_obj) 239 { 240 int rc = -1; 241 size_t size = (size_t)(CEILING16(p_input->width) * CEILING16(p_input->height)); 242 double cScale; 243 mm_jpeg_decode_params_t *p_params = &p_obj->params; 244 mm_jpeg_decode_job_t *p_job_params = &p_obj->job.decode_job; 245 246 p_obj->filename = p_input->filename; 247 p_obj->width = p_input->width; 248 p_obj->height = p_input->height; 249 p_obj->out_filename = p_input->out_filename; 250 p_obj->use_ion = 1; 251 252 pthread_mutex_init(&p_obj->lock, NULL); 253 pthread_cond_init(&p_obj->cond, NULL); 254 255 chromaScale(p_input->format, &cScale); 256 p_obj->output.size = (size_t)((double)size * cScale); 257 rc = mm_jpegdec_test_alloc(&p_obj->output, p_obj->use_ion); 258 if (rc) { 259 LOGE("Error"); 260 return -1; 261 } 262 263 rc = mm_jpegdec_test_read(p_obj); 264 if (rc) { 265 LOGE("Error"); 266 return -1; 267 } 268 269 /* set encode parameters */ 270 p_params->jpeg_cb = mm_jpegdec_decode_callback; 271 p_params->userdata = p_obj; 272 p_params->color_format = p_input->format; 273 274 /* dest buffer config */ 275 p_params->dest_buf[0].buf_size = p_obj->output.size; 276 p_params->dest_buf[0].buf_vaddr = p_obj->output.addr; 277 p_params->dest_buf[0].fd = p_obj->output.p_pmem_fd; 278 p_params->dest_buf[0].format = MM_JPEG_FMT_YUV; 279 p_params->dest_buf[0].offset.mp[0].len = (uint32_t)size; 280 p_params->dest_buf[0].offset.mp[1].len = 281 (uint32_t)((double)size * (cScale - 1.0)); 282 p_params->dest_buf[0].offset.mp[0].stride = CEILING16(p_input->width); 283 p_params->dest_buf[0].offset.mp[0].scanline = CEILING16(p_input->height); 284 p_params->dest_buf[0].offset.mp[1].stride = CEILING16(p_input->width); 285 p_params->dest_buf[0].offset.mp[1].scanline = CEILING16(p_input->height); 286 p_params->dest_buf[0].index = 0; 287 p_params->num_dst_bufs = 1; 288 289 /* src buffer config*/ 290 p_params->src_main_buf[0].buf_size = p_obj->input.size; 291 p_params->src_main_buf[0].buf_vaddr = p_obj->input.addr; 292 p_params->src_main_buf[0].fd = p_obj->input.p_pmem_fd; 293 p_params->src_main_buf[0].index = 0; 294 p_params->src_main_buf[0].format = MM_JPEG_FMT_BITSTREAM; 295 /* 296 p_params->src_main_buf[0].offset.mp[0].len = size; 297 p_params->src_main_buf[0].offset.mp[1].len = size >> 1; 298 */ 299 p_params->num_src_bufs = 1; 300 301 p_job_params->dst_index = 0; 302 p_job_params->src_index = 0; 303 p_job_params->rotation = 0; 304 305 /* main dimension */ 306 p_job_params->main_dim.src_dim.width = p_obj->width; 307 p_job_params->main_dim.src_dim.height = p_obj->height; 308 p_job_params->main_dim.dst_dim.width = p_obj->width; 309 p_job_params->main_dim.dst_dim.height = p_obj->height; 310 p_job_params->main_dim.crop.top = 0; 311 p_job_params->main_dim.crop.left = 0; 312 p_job_params->main_dim.crop.width = p_obj->width; 313 p_job_params->main_dim.crop.height = p_obj->height; 314 315 316 return 0; 317 } 318 319 void omx_test_dec_print_usage() 320 { 321 fprintf(stderr, "Usage: program_name [options]\n"); 322 fprintf(stderr, "Mandatory options:\n"); 323 fprintf(stderr, " -I FILE\t\tPath to the input file.\n"); 324 fprintf(stderr, " -O FILE\t\tPath for the output file.\n"); 325 fprintf(stderr, " -W WIDTH\t\tOutput image width\n"); 326 fprintf(stderr, " -H HEIGHT\t\tOutput image height\n"); 327 fprintf(stderr, "Optional:\n"); 328 fprintf(stderr, " -F FORMAT\t\tDefault image format:\n"); 329 fprintf(stderr, "\t\t\t\t%s (0), %s (1), %s (2) %s (3)\n" 330 "%s (4), %s (5), %s (6) %s (7)\n", 331 col_formats[0].format_str, col_formats[1].format_str, 332 col_formats[2].format_str, col_formats[3].format_str, 333 col_formats[4].format_str, col_formats[5].format_str, 334 col_formats[6].format_str, col_formats[7].format_str 335 ); 336 337 fprintf(stderr, "\n"); 338 } 339 340 static int mm_jpegdec_test_get_input(int argc, char *argv[], 341 jpeg_test_input_t *p_test) 342 { 343 int c; 344 345 while ((c = getopt(argc, argv, "I:O:W:H:F:")) != -1) { 346 switch (c) { 347 case 'O': 348 p_test->out_filename = optarg; 349 fprintf(stderr, "%-25s%s\n", "Output image path", 350 p_test->out_filename); 351 break; 352 case 'I': 353 p_test->filename = optarg; 354 fprintf(stderr, "%-25s%s\n", "Input image path", p_test->filename); 355 break; 356 case 'W': 357 p_test->width = atoi(optarg); 358 fprintf(stderr, "%-25s%d\n", "Default width", p_test->width); 359 break; 360 case 'H': 361 p_test->height = atoi(optarg); 362 fprintf(stderr, "%-25s%d\n", "Default height", p_test->height); 363 break; 364 case 'F': { 365 int format = 0; 366 format = atoi(optarg); 367 int num_formats = ARR_SZ(col_formats); 368 format = CLAMP(format, 0, num_formats); 369 p_test->format = col_formats[format].eColorFormat; 370 fprintf(stderr, "%-25s%s\n", "Default image format", 371 col_formats[format].format_str); 372 break; 373 } 374 default:; 375 } 376 } 377 if (!p_test->filename || !p_test->filename || !p_test->width || 378 !p_test->height) { 379 fprintf(stderr, "Missing required arguments.\n"); 380 omx_test_dec_print_usage(); 381 return -1; 382 } 383 return 0; 384 } 385 386 static int decode_test(jpeg_test_input_t *p_input) 387 { 388 int rc = 0; 389 mm_jpegdec_intf_test_t jpeg_obj; 390 int i = 0; 391 392 memset(&jpeg_obj, 0x0, sizeof(jpeg_obj)); 393 rc = decode_init(p_input, &jpeg_obj); 394 if (rc) { 395 LOGE("Error"); 396 return -1; 397 } 398 399 jpeg_obj.handle = jpegdec_open(&jpeg_obj.ops); 400 if (jpeg_obj.handle == 0) { 401 LOGE("Error"); 402 goto end; 403 } 404 405 rc = jpeg_obj.ops.create_session(jpeg_obj.handle, &jpeg_obj.params, 406 &jpeg_obj.job.decode_job.session_id); 407 if (jpeg_obj.job.decode_job.session_id == 0) { 408 LOGE("Error"); 409 goto end; 410 } 411 412 for (i = 0; i < g_count; i++) { 413 jpeg_obj.job.job_type = JPEG_JOB_TYPE_DECODE; 414 415 LOGE("Starting decode job"); 416 gettimeofday(&dtime[0], NULL); 417 418 fprintf(stderr, "Starting decode of %s into %s outw %d outh %d\n\n", 419 p_input->filename, p_input->out_filename, 420 p_input->width, p_input->height); 421 rc = jpeg_obj.ops.start_job(&jpeg_obj.job, &jpeg_obj.job_id[i]); 422 if (rc) { 423 LOGE("Error"); 424 goto end; 425 } 426 } 427 428 /* 429 usleep(5); 430 jpeg_obj.ops.abort_job(jpeg_obj.job_id[0]); 431 */ 432 pthread_mutex_lock(&jpeg_obj.lock); 433 pthread_cond_wait(&jpeg_obj.cond, &jpeg_obj.lock); 434 pthread_mutex_unlock(&jpeg_obj.lock); 435 436 fprintf(stderr, "Decode time %llu ms\n", 437 ((TIME_IN_US(dtime[1]) - TIME_IN_US(dtime[0]))/1000)); 438 439 440 jpeg_obj.ops.destroy_session(jpeg_obj.job.decode_job.session_id); 441 442 jpeg_obj.ops.close(jpeg_obj.handle); 443 444 445 end: 446 mm_jpegdec_test_free(&jpeg_obj.input); 447 mm_jpegdec_test_free(&jpeg_obj.output); 448 return 0; 449 } 450 451 /** main: 452 * 453 * Arguments: 454 * @argc 455 * @argv 456 * 457 * Return: 458 * 0 or -ve values 459 * 460 * Description: 461 * main function 462 * 463 **/ 464 int main(int argc, char* argv[]) 465 { 466 jpeg_test_input_t dec_test_input; 467 int ret; 468 469 memset(&dec_test_input, 0, sizeof(dec_test_input)); 470 ret = mm_jpegdec_test_get_input(argc, argv, &dec_test_input); 471 472 if (ret) { 473 return -1; 474 } 475 476 return decode_test(&dec_test_input); 477 } 478 479 480