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