• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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