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
38extern "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
70const char event_to_string[4][14] =
71{
72    "EVENT_DONE",
73    "EVENT_WARNING",
74    "EVENT_ERROR",
75};
76
77typedef 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
100typedef 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
114OS_THREAD_FUNC_RET_T OS_THREAD_FUNC_MODIFIER decoder_test(OS_THREAD_FUNC_ARG_T p_thread_args);
115void decoder_event_handler(void        *p_user_data,
116                           jpeg_event_t event,
117                           void        *p_arg);
118int 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);
122uint32_t decoder_input_req_handler(void           *p_user_data,
123                                   jpeg_buffer_t   buffer,
124                                   uint32_t        start_offset,
125                                   uint32_t        length);
126static void* insertHuffmanTable(void *p, int size);
127
128static int mjpegd_timer_start(timespec *p_timer);
129static int mjpegd_timer_get_elapsed(timespec *p_timer, int *elapsed_in_ms, uint8_t reset_start);
130static 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 */
134thread_ctrl_blk_t *thread_ctrl_blks = NULL;
135
136/*
137 * This function initializes the mjpeg decoder and returns the object
138 */
139MJPEGD_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
170MJPEGD_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
228OS_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
513buffer_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;
542fail:
543
544    ALOGD("%s: X", __func__);
545    return OS_THREAD_FUNC_RET_FAILED;
546}
547
548void 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 */
577int 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
615uint32_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
651static 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
662static 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
681int 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