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
63static uint32_t g_count = 1U, g_i;
64
65typedef 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
71typedef 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 */
91uint8_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 */
103uint8_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
114typedef 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
141static 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
153static 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
159static 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
193error:
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
202int 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
223void 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
236int 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 **/
274int 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
300static 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
469static 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
521end:
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)
544static 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
666static 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 **/
711int 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
757exit:
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