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 */ 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 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 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 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 */ 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 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 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 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 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