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