1 /* Copyright (c) 2011-2012, 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 //#define ALOG_NDEBUG 0
30 #define ALOG_NIDEBUG 0
31 #define LOG_TAG "QCameraMjpegDecode"
32 #include <utils/Log.h>
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <pthread.h>
37
38 extern "C" {
39 #include "jpeg_buffer.h"
40 #include "jpeg_common.h"
41 #include "jpegd.h"
42 }
43
44 #include "QCameraMjpegDecode.h"
45
46 /* TBDJ: Can be removed */
47 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
48
49 // Abstract the return type of the function to be run as a thread
50 #define OS_THREAD_FUNC_RET_T void *
51
52 // Abstract the argument type to the thread function
53 #define OS_THREAD_FUNC_ARG_T void *
54
55 // Helpful constants for return values in the thread functions
56 #define OS_THREAD_FUNC_RET_SUCCEEDED (OS_THREAD_FUNC_RET_T)0
57 #define OS_THREAD_FUNC_RET_FAILED (OS_THREAD_FUNC_RET_T)1
58
59 // Abstract the function modifier placed in the beginning of the thread
60 // declaration (empty for Linux)
61 #define OS_THREAD_FUNC_MODIFIER
62
63 #define os_mutex_init(a) pthread_mutex_init(a, NULL)
64 #define os_cond_init(a) pthread_cond_init(a, NULL)
65 #define os_mutex_lock pthread_mutex_lock
66 #define os_mutex_unlock pthread_mutex_unlock
67 #define os_cond_wait pthread_cond_wait
68 #define os_cond_signal pthread_cond_signal
69
70 const char event_to_string[4][14] =
71 {
72 "EVENT_DONE",
73 "EVENT_WARNING",
74 "EVENT_ERROR",
75 };
76
77 typedef struct
78 {
79 uint32_t width;
80 uint32_t height;
81 uint32_t format;
82 uint32_t preference;
83 uint32_t abort_time;
84 uint16_t back_to_back_count;
85 /* TBDJ: Is this required */
86 int32_t rotation;
87 /* TBDJ: Is this required */
88 jpeg_rectangle_t region;
89 /* TBDJ: Is this required */
90 jpegd_scale_type_t scale_factor;
91 uint32_t hw_rotation;
92
93 char* inputMjpegBuffer;
94 int inputMjpegBufferSize;
95 char* outputYptr;
96 char* outputUVptr;
97
98 } test_args_t;
99
100 typedef struct
101 {
102 int tid;
103 pthread_t thread;
104 jpegd_obj_t decoder;
105 uint8_t decoding;
106 uint8_t decode_success;
107 pthread_mutex_t mutex;
108 pthread_cond_t cond;
109 test_args_t *p_args;
110 jpegd_output_buf_t *p_whole_output_buf;
111
112 } thread_ctrl_blk_t;
113
114 OS_THREAD_FUNC_RET_T OS_THREAD_FUNC_MODIFIER decoder_test(OS_THREAD_FUNC_ARG_T p_thread_args);
115 void decoder_event_handler(void *p_user_data,
116 jpeg_event_t event,
117 void *p_arg);
118 int decoder_output_handler(void *p_user_data,
119 jpegd_output_buf_t *p_output_buffer,
120 uint32_t first_row_id,
121 uint8_t is_last_buffer);
122 uint32_t decoder_input_req_handler(void *p_user_data,
123 jpeg_buffer_t buffer,
124 uint32_t start_offset,
125 uint32_t length);
126 static void* insertHuffmanTable(void *p, int size);
127
128 static int mjpegd_timer_start(timespec *p_timer);
129 static int mjpegd_timer_get_elapsed(timespec *p_timer, int *elapsed_in_ms, uint8_t reset_start);
130 static int mjpegd_cond_timedwait(pthread_cond_t *p_cond, pthread_mutex_t *p_mutex, uint32_t ms);
131
132 // Global variables
133 /* TBDJ: can be removed */
134 thread_ctrl_blk_t *thread_ctrl_blks = NULL;
135
136 /*
137 * This function initializes the mjpeg decoder and returns the object
138 */
mjpegDecoderInit(void ** mjpegd_obj)139 MJPEGD_ERR mjpegDecoderInit(void** mjpegd_obj)
140 {
141 test_args_t* mjpegd;
142
143 ALOGD("%s: E", __func__);
144
145 mjpegd = (test_args_t *)malloc(sizeof(test_args_t));
146 if(!mjpegd)
147 return MJPEGD_INSUFFICIENT_MEM;
148
149 memset(mjpegd, 0, sizeof(test_args_t));
150
151 /* Defaults */
152 /* Due to current limitation, s/w decoder is selected always */
153 mjpegd->preference = JPEG_DECODER_PREF_HW_ACCELERATED_PREFERRED;
154 mjpegd->back_to_back_count = 1;
155 mjpegd->rotation = 0;
156 mjpegd->hw_rotation = 0;
157 mjpegd->scale_factor = (jpegd_scale_type_t)1;
158
159 /* TBDJ: can be removed */
160 mjpegd->width = 640;
161 mjpegd->height = 480;
162 mjpegd->abort_time = 0;
163
164 *mjpegd_obj = (void *)mjpegd;
165
166 ALOGD("%s: X", __func__);
167 return MJPEGD_NO_ERROR;
168 }
169
mjpegDecode(void * mjpegd_obj,char * inputMjpegBuffer,int inputMjpegBufferSize,char * outputYptr,char * outputUVptr,int outputFormat)170 MJPEGD_ERR mjpegDecode(
171 void* mjpegd_obj,
172 char* inputMjpegBuffer,
173 int inputMjpegBufferSize,
174 char* outputYptr,
175 char* outputUVptr,
176 int outputFormat)
177 {
178 int rc, c, i;
179 test_args_t* mjpegd;
180 test_args_t test_args;
181
182 ALOGD("%s: E", __func__);
183 /* store input arguments in the context */
184 mjpegd = (test_args_t*) mjpegd_obj;
185 mjpegd->inputMjpegBuffer = inputMjpegBuffer;
186 mjpegd->inputMjpegBufferSize = inputMjpegBufferSize;
187 mjpegd->outputYptr = outputYptr;
188 mjpegd->outputUVptr = outputUVptr;
189 mjpegd->format = outputFormat;
190
191 /* TBDJ: can be removed */
192 memcpy(&test_args, mjpegd, sizeof(test_args_t));
193
194 // check the formats
195 if (((test_args.format == YCRCBLP_H1V2) || (test_args.format == YCBCRLP_H1V2) ||
196 (test_args.format == YCRCBLP_H1V1) || (test_args.format == YCBCRLP_H1V1)) &&
197 !(test_args.preference == JPEG_DECODER_PREF_HW_ACCELERATED_ONLY)) {
198 ALOGE("%s:These formats are not supported by SW format %d", __func__, test_args.format);
199 return 1;
200 }
201
202 // Create thread control blocks
203 thread_ctrl_blks = (thread_ctrl_blk_t *)malloc( sizeof(thread_ctrl_blk_t));
204 if (!thread_ctrl_blks)
205 {
206 ALOGE("%s: decoder_test failed: insufficient memory in creating thread control blocks", __func__);
207 return 1;
208 }
209 memset(thread_ctrl_blks, 0, sizeof(thread_ctrl_blk_t));
210 // Initialize the blocks and kick off the threads
211 thread_ctrl_blks[i].tid = i;
212 thread_ctrl_blks[i].p_args = &test_args;
213 os_mutex_init(&thread_ctrl_blks[i].mutex);
214 os_cond_init(&thread_ctrl_blks[i].cond);
215
216 rc = (int)decoder_test(&thread_ctrl_blks[i]);
217
218 if (!rc)
219 ALOGD("%s: decoder_test finished successfully ", __func__);
220 else
221 ALOGE("%s: decoder_test failed",__func__);
222
223 ALOGD("%s: X rc: %d", __func__, rc);
224
225 return rc;
226 }
227
decoder_test(OS_THREAD_FUNC_ARG_T arg)228 OS_THREAD_FUNC_RET_T OS_THREAD_FUNC_MODIFIER decoder_test(OS_THREAD_FUNC_ARG_T arg)
229 {
230 int rc, i;
231 jpegd_obj_t decoder;
232 jpegd_src_t source;
233 jpegd_dst_t dest;
234 jpegd_cfg_t config;
235 jpeg_hdr_t header;
236 jpegd_output_buf_t p_output_buffers;
237 uint32_t output_buffers_count = 1; // currently only 1 buffer a time is supported
238 uint8_t use_pmem = true;
239 timespec os_timer;
240 thread_ctrl_blk_t *p_thread_arg = (thread_ctrl_blk_t *)arg;
241 test_args_t *p_args = p_thread_arg->p_args;
242 uint32_t output_width;
243 uint32_t output_height;
244 uint32_t total_time = 0;
245
246 ALOGD("%s: E", __func__);
247
248 // Determine whether pmem should be used (useful for pc environment testing where
249 // pmem is not available)
250 if ((jpegd_preference_t)p_args->preference == JPEG_DECODER_PREF_SOFTWARE_PREFERRED ||
251 (jpegd_preference_t)p_args->preference == JPEG_DECODER_PREF_SOFTWARE_ONLY) {
252 use_pmem = false;
253 }
254
255 if (((jpegd_preference_t)p_args->preference !=
256 JPEG_DECODER_PREF_HW_ACCELERATED_ONLY) &&
257 ((jpegd_preference_t)p_args->scale_factor > 0)) {
258 ALOGI("%s: Setting scale factor to 1x", __func__);
259 }
260
261 ALOGD("%s: before jpegd_init p_thread_arg: %p", __func__, p_thread_arg);
262
263 // Initialize decoder
264 rc = jpegd_init(&decoder,
265 &decoder_event_handler,
266 &decoder_output_handler,
267 p_thread_arg);
268
269 if (JPEG_FAILED(rc)) {
270 ALOGE("%s: decoder_test: jpegd_init failed", __func__);
271 goto fail;
272 }
273 p_thread_arg->decoder = decoder;
274
275 // Set source information
276 source.p_input_req_handler = &decoder_input_req_handler;
277 source.total_length = p_args->inputMjpegBufferSize & 0xffffffff;
278
279 rc = jpeg_buffer_init(&source.buffers[0]);
280 if (JPEG_SUCCEEDED(rc)) {
281 /* TBDJ: why buffer [1] */
282 rc = jpeg_buffer_init(&source.buffers[1]);
283 }
284 if (JPEG_SUCCEEDED(rc)) {
285 #if 1
286 rc = jpeg_buffer_allocate(source.buffers[0], 0xA000, use_pmem);
287 #else
288 rc = jpeg_buffer_use_external_buffer(source.buffers[0],
289 (uint8_t *)p_args->inputMjpegBuffer,
290 p_args->inputMjpegBufferSize,
291 0);
292 #endif
293 ALOGD("%s: source.buffers[0]:%p compressed buffer ptr = %p", __func__,
294 source.buffers[0], p_args->inputMjpegBuffer);
295 }
296 if (JPEG_SUCCEEDED(rc)) {
297 #if 1
298 rc = jpeg_buffer_allocate(source.buffers[1], 0xA000, use_pmem);
299 #else
300 rc = jpeg_buffer_use_external_buffer(source.buffers[1],
301 (uint8_t *)p_args->inputMjpegBuffer,
302 p_args->inputMjpegBufferSize,
303 0);
304 #endif
305 ALOGD("%s: source.buffers[1]:%p compressed buffer ptr = %p", __func__,
306 source.buffers[1], p_args->inputMjpegBuffer);
307 }
308 if (JPEG_FAILED(rc)) {
309 jpeg_buffer_destroy(&source.buffers[0]);
310 jpeg_buffer_destroy(&source.buffers[1]);
311 goto fail;
312 }
313
314 ALOGI("%s: *** Starting back-to-back decoding of %d frame(s)***\n",
315 __func__, p_args->back_to_back_count);
316
317 // Loop to perform n back-to-back decoding (to the same output file)
318 for(i = 0; i < p_args->back_to_back_count; i++) {
319 if(mjpegd_timer_start(&os_timer) < 0) {
320 ALOGE("%s: failed to get start time", __func__);
321 }
322
323 /* TBDJ: Every frame? */
324 ALOGD("%s: before jpegd_set_source source.p_arg:%p", __func__, source.p_arg);
325 rc = jpegd_set_source(decoder, &source);
326 if (JPEG_FAILED(rc))
327 {
328 ALOGE("%s: jpegd_set_source failed", __func__);
329 goto fail;
330 }
331
332 rc = jpegd_read_header(decoder, &header);
333 if (JPEG_FAILED(rc))
334 {
335 ALOGE("%s: jpegd_read_header failed", __func__);
336 goto fail;
337 }
338 p_args->width = header.main.width;
339 p_args->height = header.main.height;
340 ALOGD("%s: main dimension: (%dx%d) subsampling: (%d)", __func__,
341 header.main.width, header.main.height, (int)header.main.subsampling);
342
343 // main image decoding:
344 // Set destination information
345 dest.width = (p_args->width) ? (p_args->width) : header.main.width;
346 dest.height = (p_args->height) ? (p_args->height) : header.main.height;
347 dest.output_format = (jpeg_color_format_t) p_args->format;
348 dest.region = p_args->region;
349
350 // if region is defined, re-assign the output width/height
351 output_width = dest.width;
352 output_height = dest.height;
353
354 if (p_args->region.right || p_args->region.bottom)
355 {
356 if (0 == p_args->rotation || 180 == p_args->rotation)
357 {
358 output_width = MIN((dest.width),
359 (uint32_t)(dest.region.right - dest.region.left + 1));
360 output_height = MIN((dest.height),
361 (uint32_t)(dest.region.bottom - dest.region.top + 1));
362 }
363 // Swap output width/height for 90/270 rotation cases
364 else if (90 == p_args->rotation || 270 == p_args->rotation)
365 {
366 output_height = MIN((dest.height),
367 (uint32_t)(dest.region.right - dest.region.left + 1));
368 output_width = MIN((dest.width),
369 (uint32_t)(dest.region.bottom - dest.region.top + 1));
370 }
371 // Unsupported rotation cases
372 else
373 {
374 goto fail;
375 }
376 }
377
378 if (dest.output_format == YCRCBLP_H2V2 || dest.output_format == YCBCRLP_H2V2 ||
379 dest.output_format == YCRCBLP_H2V1 || dest.output_format == YCBCRLP_H2V1 ||
380 dest.output_format == YCRCBLP_H1V2 || dest.output_format == YCBCRLP_H1V2 ||
381 dest.output_format == YCRCBLP_H1V1 || dest.output_format == YCBCRLP_H1V1) {
382 jpeg_buffer_init(&p_output_buffers.data.yuv.luma_buf);
383 jpeg_buffer_init(&p_output_buffers.data.yuv.chroma_buf);
384 } else {
385 jpeg_buffer_init(&p_output_buffers.data.rgb.rgb_buf);
386
387 }
388
389 {
390 // Assign 0 to tile width and height
391 // to indicate that no tiling is requested.
392 p_output_buffers.tile_width = 0;
393 p_output_buffers.tile_height = 0;
394 }
395 p_output_buffers.is_in_q = 0;
396
397 switch (dest.output_format)
398 {
399 case YCRCBLP_H2V2:
400 case YCBCRLP_H2V2:
401 // case YCRCBLP_H2V1:
402 // case YCBCRLP_H2V1:
403 // case YCRCBLP_H1V2:
404 // case YCBCRLP_H1V2:
405 // case YCRCBLP_H1V1:
406 // case YCBCRLP_H1V1:
407 jpeg_buffer_use_external_buffer(
408 p_output_buffers.data.yuv.luma_buf,
409 (uint8_t*)p_args->outputYptr,
410 p_args->width * p_args->height * SQUARE(p_args->scale_factor),
411 0);
412 jpeg_buffer_use_external_buffer(
413 p_output_buffers.data.yuv.chroma_buf,
414 (uint8_t*)p_args->outputUVptr,
415 p_args->width * p_args->height / 2 * SQUARE(p_args->scale_factor),
416 0);
417 break;
418
419 default:
420 ALOGE("%s: decoder_test: unsupported output format", __func__);
421 goto fail;
422 }
423
424 // Set up configuration
425 memset(&config, 0, sizeof(jpegd_cfg_t));
426 config.preference = (jpegd_preference_t) p_args->preference;
427 config.decode_from = JPEGD_DECODE_FROM_AUTO;
428 config.rotation = p_args->rotation;
429 config.scale_factor = p_args->scale_factor;
430 config.hw_rotation = p_args->hw_rotation;
431 dest.back_to_back_count = p_args->back_to_back_count;
432
433 // Start decoding
434 p_thread_arg->decoding = true;
435
436 rc = jpegd_start(decoder, &config, &dest, &p_output_buffers, output_buffers_count);
437 dest.back_to_back_count--;
438
439 if(JPEG_FAILED(rc)) {
440 ALOGE("%s: decoder_test: jpegd_start failed (rc=%d)\n",
441 __func__, rc);
442 goto fail;
443 }
444
445 ALOGD("%s: decoder_test: jpegd_start succeeded", __func__);
446
447 // Do abort
448 if (p_args->abort_time) {
449 os_mutex_lock(&p_thread_arg->mutex);
450 while (p_thread_arg->decoding)
451 {
452 rc = mjpegd_cond_timedwait(&p_thread_arg->cond, &p_thread_arg->mutex, p_args->abort_time);
453 if (rc == JPEGERR_ETIMEDOUT)
454 {
455 // Do abort
456 os_mutex_unlock(&p_thread_arg->mutex);
457 rc = jpegd_abort(decoder);
458 if (rc)
459 {
460 ALOGE("%s: decoder_test: jpegd_abort failed: %d", __func__, rc);
461 goto fail;
462 }
463 break;
464 }
465 }
466 if (p_thread_arg->decoding)
467 os_mutex_unlock(&p_thread_arg->mutex);
468 } else {
469 // Wait until decoding is done or stopped due to error
470 os_mutex_lock(&p_thread_arg->mutex);
471 while (p_thread_arg->decoding)
472 {
473 os_cond_wait(&p_thread_arg->cond, &p_thread_arg->mutex);
474 }
475 os_mutex_unlock(&p_thread_arg->mutex);
476 }
477
478 int diff;
479 // Display the time elapsed
480 if (mjpegd_timer_get_elapsed(&os_timer, &diff, 0) < 0) {
481 ALOGE("%s: decoder_test: failed to get elapsed time", __func__);
482 } else {
483 if(p_args->abort_time) {
484 if(p_thread_arg->decoding) {
485 ALOGI("%s: decoder_test: decoding aborted successfully after %d ms", __func__, diff);
486 goto buffer_clean_up;
487 }
488 else
489 {
490 ALOGI("%s: decoder_test: decoding stopped before abort is issued. "
491 "decode time: %d ms", __func__, diff);
492 }
493 }
494 else {
495 if(p_thread_arg->decode_success) {
496 total_time += diff;
497 ALOGI("%s: decode time: %d ms (%d frame(s), total=%dms, avg=%dms/frame)",
498 __func__, diff, i+1, total_time, total_time/(i+1));
499 }
500 else
501 {
502 fprintf(stderr, "decoder_test: decode failed\n");
503 }
504 }
505 }
506 }
507
508 if(p_thread_arg->decode_success) {
509 ALOGD("%s: Frame(s) = %d, Total Time = %dms, Avg. decode time = %dms/frame)\n",
510 __func__, p_args->back_to_back_count, total_time, total_time/p_args->back_to_back_count);
511 }
512
513 buffer_clean_up:
514 // Clean up decoder and allocate buffers
515 jpeg_buffer_destroy(&source.buffers[0]);
516 jpeg_buffer_destroy(&source.buffers[1]);
517 switch (dest.output_format)
518 {
519 case YCRCBLP_H2V2:
520 case YCBCRLP_H2V2:
521 case YCRCBLP_H2V1:
522 case YCBCRLP_H2V1:
523 case YCRCBLP_H1V2:
524 case YCBCRLP_H1V2:
525 case YCRCBLP_H1V1:
526 case YCBCRLP_H1V1:
527 jpeg_buffer_destroy(&p_output_buffers.data.yuv.luma_buf);
528 jpeg_buffer_destroy(&p_output_buffers.data.yuv.chroma_buf);
529 break;
530 default:
531 break;
532 }
533 jpegd_destroy(&decoder);
534
535 if (!p_thread_arg->decode_success)
536 {
537 goto fail;
538 }
539
540 ALOGD("%s: X", __func__);
541 return OS_THREAD_FUNC_RET_SUCCEEDED;
542 fail:
543
544 ALOGD("%s: X", __func__);
545 return OS_THREAD_FUNC_RET_FAILED;
546 }
547
decoder_event_handler(void * p_user_data,jpeg_event_t event,void * p_arg)548 void decoder_event_handler(void *p_user_data,
549 jpeg_event_t event,
550 void *p_arg)
551 {
552 thread_ctrl_blk_t *p_thread_arg = (thread_ctrl_blk_t *)p_user_data;
553
554 ALOGD("%s: E", __func__);
555
556 ALOGD("%s: Event: %s\n", __func__, event_to_string[event]);
557 if (event == JPEG_EVENT_DONE)
558 {
559 p_thread_arg->decode_success = true;
560 ALOGD("%s: decode_success: %d\n", __func__, p_thread_arg->decode_success);
561 }
562 // If it is not a warning event, decoder has stopped; Signal
563 // main thread to clean up
564 if (event != JPEG_EVENT_WARNING)
565 {
566 os_mutex_lock(&p_thread_arg->mutex);
567 p_thread_arg->decoding = false;
568 os_cond_signal(&p_thread_arg->cond);
569 os_mutex_unlock(&p_thread_arg->mutex);
570 }
571 ALOGD("%s: X", __func__);
572
573 }
574
575 // consumes the output buffer.
576 /*TBDJ: Can be removed. Is this related to tiling */
decoder_output_handler(void * p_user_data,jpegd_output_buf_t * p_output_buffer,uint32_t first_row_id,uint8_t is_last_buffer)577 int decoder_output_handler(void *p_user_data,
578 jpegd_output_buf_t *p_output_buffer,
579 uint32_t first_row_id,
580 uint8_t is_last_buffer)
581 {
582 uint8_t* whole_output_buf_ptr, *tiling_buf_ptr;
583
584 ALOGD("%s: E", __func__);
585
586 thread_ctrl_blk_t *p_thread_arg = (thread_ctrl_blk_t *)p_user_data;
587
588 jpeg_buffer_get_addr(p_thread_arg->p_whole_output_buf->data.rgb.rgb_buf, &whole_output_buf_ptr);
589 jpeg_buffer_get_addr(p_output_buffer->data.rgb.rgb_buf, &tiling_buf_ptr);
590
591 if (p_output_buffer->tile_height != 1)
592 return JPEGERR_EUNSUPPORTED;
593
594 // testing purpose only
595 // This is to simulate that the user needs to bail out when error happens
596 // in the middle of decoding
597 //if (first_row_id == 162)
598 // return JPEGERR_EFAILED;
599
600 // do not enqueue any buffer if it reaches the last buffer
601 if (!is_last_buffer)
602 {
603 jpegd_enqueue_output_buf(p_thread_arg->decoder, p_output_buffer, 1);
604 }
605 ALOGD("%s: X", __func__);
606
607 return JPEGERR_SUCCESS;
608 }
609
610 // p_reader->p_input_req_handler(p_reader->decoder,
611 // p_reader->p_input_buf,
612 // p_reader->next_byte_offset,
613 // MAX_BYTES_TO_FETCH);
614
decoder_input_req_handler(void * p_user_data,jpeg_buffer_t buffer,uint32_t start_offset,uint32_t length)615 uint32_t decoder_input_req_handler(void *p_user_data,
616 jpeg_buffer_t buffer,
617 uint32_t start_offset,
618 uint32_t length)
619 {
620 uint32_t buf_size;
621 uint8_t *buf_ptr;
622 int bytes_to_read, bytes_read, rc;
623 thread_ctrl_blk_t *p_thread_arg = (thread_ctrl_blk_t *)p_user_data;
624 thread_ctrl_blk_t *thread_ctrl_blk = (thread_ctrl_blk_t *)p_user_data;
625 test_args_t* mjpegd = (test_args_t*) thread_ctrl_blk->p_args;
626
627 ALOGD("%s: E", __func__);
628
629 jpeg_buffer_get_max_size(buffer, &buf_size);
630 jpeg_buffer_get_addr(buffer, &buf_ptr);
631 bytes_to_read = (length < buf_size) ? length : buf_size;
632 bytes_read = 0;
633
634 ALOGD("%s: buf_ptr = %p, start_offset = %d, length = %d buf_size = %d bytes_to_read = %d", __func__, buf_ptr, start_offset, length, buf_size, bytes_to_read);
635 if (bytes_to_read)
636 {
637 /* TBDJ: Should avoid this Mem copy */
638 #if 1
639 memcpy(buf_ptr, (char *)mjpegd->inputMjpegBuffer + start_offset, bytes_to_read);
640 #else
641 if(JPEGERR_SUCCESS != jpeg_buffer_set_start_offset(buffer, start_offset))
642 ALOGE("%s: jpeg_buffer_set_start_offset failed", __func__);
643 #endif
644 bytes_read = bytes_to_read;
645 }
646
647 ALOGD("%s: X", __func__);
648 return bytes_read;
649 }
650
mjpegd_timer_start(timespec * p_timer)651 static int mjpegd_timer_start(timespec *p_timer)
652 {
653 if (!p_timer)
654 return JPEGERR_ENULLPTR;
655
656 if (clock_gettime(CLOCK_REALTIME, p_timer))
657 return JPEGERR_EFAILED;
658
659 return JPEGERR_SUCCESS;
660 }
661
mjpegd_timer_get_elapsed(timespec * p_timer,int * elapsed_in_ms,uint8_t reset_start)662 static int mjpegd_timer_get_elapsed(timespec *p_timer, int *elapsed_in_ms, uint8_t reset_start)
663 {
664 timespec now;
665 long diff;
666 int rc = mjpegd_timer_start(&now);
667
668 if (JPEG_FAILED(rc))
669 return rc;
670
671 diff = (long)(now.tv_sec - p_timer->tv_sec) * 1000;
672 diff += (long)(now.tv_nsec - p_timer->tv_nsec) / 1000000;
673 *elapsed_in_ms = (int)diff;
674
675 if (reset_start)
676 *p_timer = now;
677
678 return JPEGERR_SUCCESS;
679 }
680
mjpegd_cond_timedwait(pthread_cond_t * p_cond,pthread_mutex_t * p_mutex,uint32_t ms)681 int mjpegd_cond_timedwait(pthread_cond_t *p_cond, pthread_mutex_t *p_mutex, uint32_t ms)
682 {
683 struct timespec ts;
684 int rc = clock_gettime(CLOCK_REALTIME, &ts);
685 if (rc < 0) return rc;
686
687 if (ms >= 1000) {
688 ts.tv_sec += (ms/1000);
689 ts.tv_nsec += ((ms%1000) * 1000000);
690 } else {
691 ts.tv_nsec += (ms * 1000000);
692 }
693
694 rc = pthread_cond_timedwait(p_cond, p_mutex, &ts);
695 if (rc == ETIMEDOUT)
696 {
697 rc = JPEGERR_ETIMEDOUT;
698 }
699 return rc;
700 }
701
702