Home | History | Annotate | Download | only in test
      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