1 /* Copyright (c) 2012-2013, 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 
30 #include <pthread.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <poll.h>
37 
38 #include "mm_jpeg_dbg.h"
39 #include "mm_jpeg_interface.h"
40 #include "mm_jpeg.h"
41 
42 /* define max num of supported concurrent jpeg jobs by OMX engine.
43  * Current, only one per time */
44 #define NUM_MAX_JPEG_CNCURRENT_JOBS 1
45 
46 #define JOB_ID_MAGICVAL 0x1
47 #define JOB_HIST_MAX 10000
48 
49 /** DUMP_TO_FILE:
50  *  @filename: file name
51  *  @p_addr: address of the buffer
52  *  @len: buffer length
53  *
54  *  dump the image to the file
55  **/
56 #define DUMP_TO_FILE(filename, p_addr, len) ({ \
57   int rc = 0; \
58   FILE *fp = fopen(filename, "w+"); \
59   if (fp) { \
60     rc = fwrite(p_addr, 1, len, fp); \
61     CDBG_ERROR("%s:%d] written size %d", __func__, __LINE__, len); \
62     fclose(fp); \
63   } else { \
64     CDBG_ERROR("%s:%d] open %s failed", __func__, __LINE__, filename); \
65   } \
66 })
67 
68 /** DUMP_TO_FILE2:
69  *  @filename: file name
70  *  @p_addr: address of the buffer
71  *  @len: buffer length
72  *
73  *  dump the image to the file if the memory is non-contiguous
74  **/
75 #define DUMP_TO_FILE2(filename, p_addr1, len1, paddr2, len2) ({ \
76   int rc = 0; \
77   FILE *fp = fopen(filename, "w+"); \
78   if (fp) { \
79     rc = fwrite(p_addr1, 1, len1, fp); \
80     rc = fwrite(p_addr2, 1, len2, fp); \
81     CDBG_ERROR("%s:%d] written %d %d", __func__, __LINE__, len1, len2); \
82     fclose(fp); \
83   } else { \
84     CDBG_ERROR("%s:%d] open %s failed", __func__, __LINE__, filename); \
85   } \
86 })
87 
88 /** MM_JPEG_CHK_ABORT:
89  *  @p: client pointer
90  *  @ret: return value
91  *  @label: label to jump to
92  *
93  *  check the abort failure
94  **/
95 #define MM_JPEG_CHK_ABORT(p, ret, label) ({ \
96   if (OMX_TRUE == p->abort_flag) { \
97     CDBG_ERROR("%s:%d] jpeg abort", __func__, __LINE__); \
98     ret = OMX_ErrorNone; \
99     goto label; \
100   } \
101 })
102 
103 #define GET_CLIENT_IDX(x) ((x) & 0xff)
104 #define GET_SESSION_IDX(x) (((x) >> 8) & 0xff)
105 #define GET_JOB_IDX(x) (((x) >> 16) & 0xff)
106 
107 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
108     OMX_PTR pAppData,
109     OMX_BUFFERHEADERTYPE* pBuffer);
110 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent,
111     OMX_PTR pAppData,
112     OMX_BUFFERHEADERTYPE* pBuffer);
113 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,
114     OMX_PTR pAppData,
115     OMX_EVENTTYPE eEvent,
116     OMX_U32 nData1,
117     OMX_U32 nData2,
118     OMX_PTR pEventData);
119 
120 /** cirq_reset:
121  *
122  *  Arguments:
123  *    @q: circular queue
124  *
125  *  Return:
126  *       none
127  *
128  *  Description:
129  *       Resets the circular queue
130  *
131  **/
cirq_reset(mm_jpeg_cirq_t * q)132 static inline void cirq_reset(mm_jpeg_cirq_t *q)
133 {
134   q->front = 0;
135   q->rear = 0;
136   q->count = 0;
137   pthread_mutex_init(&q->lock, NULL);
138 }
139 
140 /** cirq_empty:
141  *
142  *  Arguments:
143  *    @q: circular queue
144  *
145  *  Return:
146  *       none
147  *
148  *  Description:
149  *       check if the curcular queue is empty
150  *
151  **/
152 #define cirq_empty(q) (q->count == 0)
153 
154 /** cirq_full:
155  *
156  *  Arguments:
157  *    @q: circular queue
158  *
159  *  Return:
160  *       none
161  *
162  *  Description:
163  *       check if the curcular queue is full
164  *
165  **/
166 #define cirq_full(q) (q->count == MM_JPEG_CIRQ_SIZE)
167 
168 /** cirq_enqueue:
169  *
170  *  Arguments:
171  *    @q: circular queue
172  *    @data: data to be inserted
173  *
174  *  Return:
175  *       true/false
176  *
177  *  Description:
178  *       enqueue an element into circular queue
179  *
180  **/
181 #define cirq_enqueue(q, type, data) ({ \
182   int rc = 0; \
183   pthread_mutex_lock(&q->lock); \
184   if (cirq_full(q)) { \
185     rc = -1; \
186   } else { \
187     q->type[q->rear] = data; \
188     q->rear = (q->rear + 1) % MM_JPEG_CIRQ_SIZE; \
189     q->count++; \
190   } \
191   pthread_mutex_unlock(&q->lock); \
192   rc; \
193 })
194 
195 /** cirq_dequeue:
196  *
197  *  Arguments:
198  *    @q: circular queue
199  *    @data: data to be popped
200  *
201  *  Return:
202  *       true/false
203  *
204  *  Description:
205  *       dequeue an element from the circular queue
206  *
207  **/
208 #define cirq_dequeue(q, type, data) ({ \
209   int rc = 0; \
210   pthread_mutex_lock(&q->lock); \
211   if (cirq_empty(q)) { \
212     pthread_mutex_unlock(&q->lock); \
213     rc = -1; \
214   } else { \
215     data = q->type[q->front]; \
216     q->count--; \
217   } \
218   pthread_mutex_unlock(&q->lock); \
219   rc; \
220 })
221 
222 /**
223  *
224  * special queue functions for job queue
225  **/
226 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id(
227   mm_jpeg_queue_t* queue, uint32_t client_hdl);
228 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id(
229   mm_jpeg_queue_t* queue, uint32_t job_id);
230 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id(
231   mm_jpeg_queue_t* queue, uint32_t session_id);
232 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_unlk(
233   mm_jpeg_queue_t* queue, uint32_t job_id);
234 
235 /** mm_jpeg_pending_func_t:
236  *
237  * Intermediate function for transition change
238  **/
239 typedef OMX_ERRORTYPE (*mm_jpeg_transition_func_t)(void *);
240 
241 
242 /** mm_jpeg_queue_func_t:
243  *
244  * Intermediate function for queue operation
245  **/
246 typedef void (*mm_jpeg_queue_func_t)(void *);
247 
248 /** mm_jpeg_session_send_buffers:
249  *
250  *  Arguments:
251  *    @data: job session
252  *
253  *  Return:
254  *       OMX error values
255  *
256  *  Description:
257  *       Send the buffers to OMX layer
258  *
259  **/
mm_jpeg_session_send_buffers(void * data)260 OMX_ERRORTYPE mm_jpeg_session_send_buffers(void *data)
261 {
262   uint32_t i = 0;
263   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
264   OMX_ERRORTYPE ret = OMX_ErrorNone;
265   QOMX_BUFFER_INFO lbuffer_info;
266   mm_jpeg_encode_params_t *p_params = &p_session->params;
267   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
268 
269   memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
270   for (i = 0; i < p_params->num_src_bufs; i++) {
271     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
272     lbuffer_info.fd = p_params->src_main_buf[i].fd;
273     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0,
274       &lbuffer_info, p_params->src_main_buf[i].buf_size,
275       p_params->src_main_buf[i].buf_vaddr);
276     if (ret) {
277       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
278       return ret;
279     }
280   }
281 
282   for (i = 0; i < p_params->num_tmb_bufs; i++) {
283     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
284     lbuffer_info.fd = p_params->src_thumb_buf[i].fd;
285     ret = OMX_UseBuffer(p_session->omx_handle,
286         &(p_session->p_in_omx_thumb_buf[i]), 2,
287         &lbuffer_info, p_params->src_thumb_buf[i].buf_size,
288         p_params->src_thumb_buf[i].buf_vaddr);
289     if (ret) {
290       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
291       return ret;
292     }
293   }
294 
295   for (i = 0; i < p_params->num_dst_bufs; i++) {
296     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
297     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]),
298       1, NULL, p_params->dest_buf[i].buf_size,
299       p_params->dest_buf[i].buf_vaddr);
300     if (ret) {
301       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
302       return ret;
303     }
304   }
305   CDBG("%s:%d]", __func__, __LINE__);
306   return ret;
307 }
308 
309 /** mm_jpeg_session_free_buffers:
310  *
311  *  Arguments:
312  *    @data: job session
313  *
314  *  Return:
315  *       OMX error values
316  *
317  *  Description:
318  *       Free the buffers from OMX layer
319  *
320  **/
mm_jpeg_session_free_buffers(void * data)321 OMX_ERRORTYPE mm_jpeg_session_free_buffers(void *data)
322 {
323   OMX_ERRORTYPE ret = OMX_ErrorNone;
324   uint32_t i = 0;
325   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
326   mm_jpeg_encode_params_t *p_params = &p_session->params;
327   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
328 
329   for (i = 0; i < p_params->num_src_bufs; i++) {
330     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
331     ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]);
332     if (ret) {
333       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
334       return ret;
335     }
336   }
337 
338   for (i = 0; i < p_params->num_tmb_bufs; i++) {
339     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
340     ret = OMX_FreeBuffer(p_session->omx_handle, 2, p_session->p_in_omx_thumb_buf[i]);
341     if (ret) {
342       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
343       return ret;
344     }
345   }
346 
347   for (i = 0; i < p_params->num_dst_bufs; i++) {
348     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
349     ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]);
350     if (ret) {
351       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
352       return ret;
353     }
354   }
355   CDBG("%s:%d]", __func__, __LINE__);
356   return ret;
357 }
358 
359 /** mm_jpeg_session_change_state:
360  *
361  *  Arguments:
362  *    @p_session: job session
363  *    @new_state: new state to be transitioned to
364  *    @p_exec: transition function
365  *
366  *  Return:
367  *       OMX error values
368  *
369  *  Description:
370  *       This method is used for state transition
371  *
372  **/
mm_jpeg_session_change_state(mm_jpeg_job_session_t * p_session,OMX_STATETYPE new_state,mm_jpeg_transition_func_t p_exec)373 OMX_ERRORTYPE mm_jpeg_session_change_state(mm_jpeg_job_session_t* p_session,
374   OMX_STATETYPE new_state,
375   mm_jpeg_transition_func_t p_exec)
376 {
377   OMX_ERRORTYPE ret = OMX_ErrorNone;
378   OMX_STATETYPE current_state;
379   CDBG("%s:%d] new_state %d p_exec %p", __func__, __LINE__,
380     new_state, p_exec);
381 
382 
383   pthread_mutex_lock(&p_session->lock);
384 
385   ret = OMX_GetState(p_session->omx_handle, &current_state);
386 
387   if (ret) {
388     pthread_mutex_unlock(&p_session->lock);
389     return ret;
390   }
391 
392   if (current_state == new_state) {
393     pthread_mutex_unlock(&p_session->lock);
394     return OMX_ErrorNone;
395   }
396 
397   p_session->state_change_pending = OMX_TRUE;
398   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
399     new_state, NULL);
400   if (ret) {
401     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
402     pthread_mutex_unlock(&p_session->lock);
403     return OMX_ErrorIncorrectStateTransition;
404   }
405   CDBG("%s:%d] ", __func__, __LINE__);
406   if (OMX_ErrorNone != p_session->error_flag) {
407     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, p_session->error_flag);
408     pthread_mutex_unlock(&p_session->lock);
409     return p_session->error_flag;
410   }
411   if (p_exec) {
412     ret = p_exec(p_session);
413     if (ret) {
414       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
415       pthread_mutex_unlock(&p_session->lock);
416       return ret;
417     }
418   }
419   CDBG("%s:%d] ", __func__, __LINE__);
420   if (p_session->state_change_pending) {
421     CDBG("%s:%d] before wait", __func__, __LINE__);
422     pthread_cond_wait(&p_session->cond, &p_session->lock);
423     CDBG("%s:%d] after wait", __func__, __LINE__);
424   }
425   pthread_mutex_unlock(&p_session->lock);
426   CDBG("%s:%d] ", __func__, __LINE__);
427   return ret;
428 }
429 
430 /** mm_jpeg_session_create:
431  *
432  *  Arguments:
433  *    @p_session: job session
434  *
435  *  Return:
436  *       OMX error types
437  *
438  *  Description:
439  *       Create a jpeg encode session
440  *
441  **/
mm_jpeg_session_create(mm_jpeg_job_session_t * p_session)442 OMX_ERRORTYPE mm_jpeg_session_create(mm_jpeg_job_session_t* p_session)
443 {
444   OMX_ERRORTYPE rc = OMX_ErrorNone;
445   mm_jpeg_cirq_t *p_cirq = NULL;
446 
447   pthread_mutex_init(&p_session->lock, NULL);
448   pthread_cond_init(&p_session->cond, NULL);
449   cirq_reset(&p_session->cb_q);
450   p_session->state_change_pending = OMX_FALSE;
451   p_session->abort_flag = OMX_FALSE;
452   p_session->error_flag = OMX_ErrorNone;
453   p_session->ebd_count = 0;
454   p_session->fbd_count = 0;
455   p_session->encode_pid = -1;
456   p_session->config = OMX_FALSE;
457 
458   p_session->omx_callbacks.EmptyBufferDone = mm_jpeg_ebd;
459   p_session->omx_callbacks.FillBufferDone = mm_jpeg_fbd;
460   p_session->omx_callbacks.EventHandler = mm_jpeg_event_handler;
461   rc = OMX_GetHandle(&p_session->omx_handle,
462     "OMX.qcom.image.jpeg.encoder",
463     (void *)p_session,
464     &p_session->omx_callbacks);
465 
466   if (OMX_ErrorNone != rc) {
467     CDBG_ERROR("%s:%d] OMX_GetHandle failed (%d)", __func__, __LINE__, rc);
468     return rc;
469   }
470   return rc;
471 }
472 
473 /** mm_jpeg_session_destroy:
474  *
475  *  Arguments:
476  *    @p_session: job session
477  *
478  *  Return:
479  *       none
480  *
481  *  Description:
482  *       Destroy a jpeg encode session
483  *
484  **/
mm_jpeg_session_destroy(mm_jpeg_job_session_t * p_session)485 void mm_jpeg_session_destroy(mm_jpeg_job_session_t* p_session)
486 {
487   OMX_ERRORTYPE rc = OMX_ErrorNone;
488 
489   CDBG("%s:%d] E", __func__, __LINE__);
490   if (NULL == p_session->omx_handle) {
491     CDBG_ERROR("%s:%d] invalid handle", __func__, __LINE__);
492     return;
493   }
494 
495   rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL);
496   if (rc) {
497     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
498   }
499 
500   rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded,
501     mm_jpeg_session_free_buffers);
502   if (rc) {
503     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
504   }
505 
506   rc = OMX_FreeHandle(p_session->omx_handle);
507   if (0 != rc) {
508     CDBG_ERROR("%s:%d] OMX_FreeHandle failed (%d)", __func__, __LINE__, rc);
509   }
510   p_session->omx_handle = NULL;
511 
512   rc = releaseExifEntry(&p_session->params.exif_info);
513   if (rc) {
514     CDBG_ERROR("%s:%d] Exif release failed (%d)", __func__, __LINE__, rc);
515   }
516   pthread_mutex_destroy(&p_session->lock);
517   pthread_cond_destroy(&p_session->cond);
518   CDBG("%s:%d] X", __func__, __LINE__);
519 }
520 
521 /** mm_jpeg_session_config_main_buffer_offset:
522  *
523  *  Arguments:
524  *    @p_session: job session
525  *
526  *  Return:
527  *       OMX error values
528  *
529  *  Description:
530  *       Configure the buffer offsets
531  *
532  **/
mm_jpeg_session_config_main_buffer_offset(mm_jpeg_job_session_t * p_session)533 OMX_ERRORTYPE mm_jpeg_session_config_main_buffer_offset(
534   mm_jpeg_job_session_t* p_session)
535 {
536   OMX_ERRORTYPE rc = 0;
537   int32_t i = 0;
538   OMX_INDEXTYPE buffer_index;
539   QOMX_YUV_FRAME_INFO frame_info;
540   int32_t totalSize = 0;
541   mm_jpeg_encode_params_t *p_params = &p_session->params;
542   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
543 
544   mm_jpeg_buf_t *p_src_buf =
545     &p_params->src_main_buf[p_jobparams->src_index];
546 
547   memset(&frame_info, 0x0, sizeof(QOMX_YUV_FRAME_INFO));
548 
549   frame_info.cbcrStartOffset[0] = p_src_buf->offset.mp[0].len;
550   frame_info.cbcrStartOffset[1] = p_src_buf->offset.mp[1].len;
551   frame_info.yOffset = p_src_buf->offset.mp[0].offset;
552   frame_info.cbcrOffset[0] = p_src_buf->offset.mp[1].offset;
553   frame_info.cbcrOffset[1] = p_src_buf->offset.mp[2].offset;
554   totalSize = p_src_buf->buf_size;
555 
556   rc = OMX_GetExtensionIndex(p_session->omx_handle,
557     QOMX_IMAGE_EXT_BUFFER_OFFSET_NAME, &buffer_index);
558   if (rc != OMX_ErrorNone) {
559     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
560     return rc;
561   }
562 
563   CDBG_HIGH("%s:%d] yOffset = %d, cbcrOffset = (%d %d), totalSize = %d,"
564     "cbcrStartOffset = (%d %d)", __func__, __LINE__,
565     (int)frame_info.yOffset,
566     (int)frame_info.cbcrOffset[0],
567     (int)frame_info.cbcrOffset[1],
568     totalSize,
569     (int)frame_info.cbcrStartOffset[0],
570     (int)frame_info.cbcrStartOffset[1]);
571 
572   rc = OMX_SetParameter(p_session->omx_handle, buffer_index, &frame_info);
573   if (rc != OMX_ErrorNone) {
574     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
575     return rc;
576   }
577   return rc;
578 }
579 
580 /** mm_jpeg_encoding_mode:
581  *
582  *  Arguments:
583  *    @p_session: job session
584  *
585  *  Return:
586  *       OMX error values
587  *
588  *  Description:
589  *       Configure the serial or parallel encoding
590  *       mode
591  *
592  **/
mm_jpeg_encoding_mode(mm_jpeg_job_session_t * p_session)593 OMX_ERRORTYPE mm_jpeg_encoding_mode(
594   mm_jpeg_job_session_t* p_session)
595 {
596   OMX_ERRORTYPE rc = 0;
597   int32_t i = 0;
598   OMX_INDEXTYPE indextype;
599   QOMX_ENCODING_MODE encoding_mode;
600   int32_t totalSize = 0;
601   mm_jpeg_encode_params_t *p_params = &p_session->params;
602   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
603 
604   rc = OMX_GetExtensionIndex(p_session->omx_handle,
605     QOMX_IMAGE_EXT_ENCODING_MODE_NAME, &indextype);
606   if (rc != OMX_ErrorNone) {
607     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
608     return rc;
609   }
610 
611   CDBG_HIGH("%s:%d] OMX_Serial_Encoding = %d, OMX_Parallel_Encoding = %d ", __func__, __LINE__,
612     (int)OMX_Serial_Encoding,
613     (int)OMX_Parallel_Encoding);
614 
615   encoding_mode = OMX_Serial_Encoding;
616   rc = OMX_SetParameter(p_session->omx_handle, indextype, &encoding_mode);
617   if (rc != OMX_ErrorNone) {
618     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
619     return rc;
620   }
621   return rc;
622 }
623 
624 /** map_jpeg_format:
625  *
626  *  Arguments:
627  *    @color_fmt: color format
628  *
629  *  Return:
630  *       OMX color format
631  *
632  *  Description:
633  *       Map mmjpeg color format to OMX color format
634  *
635  **/
map_jpeg_format(mm_jpeg_color_format color_fmt)636 int map_jpeg_format(mm_jpeg_color_format color_fmt)
637 {
638   switch (color_fmt) {
639   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2:
640     return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar;
641   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2:
642     return (int)OMX_COLOR_FormatYUV420SemiPlanar;
643   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1:
644     return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar;
645   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1:
646     return (int)OMX_COLOR_FormatYUV422SemiPlanar;
647   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2:
648     return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar_h1v2;
649   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2:
650     return (int)OMX_QCOM_IMG_COLOR_FormatYUV422SemiPlanar_h1v2;
651   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1:
652     return (int)OMX_QCOM_IMG_COLOR_FormatYVU444SemiPlanar;
653   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1:
654     return (int)OMX_QCOM_IMG_COLOR_FormatYUV444SemiPlanar;
655   default:
656     CDBG_ERROR("%s:%d] invalid format %d", __func__, __LINE__, color_fmt);
657     return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar;
658   }
659 }
660 
661 /** mm_jpeg_session_config_port:
662  *
663  *  Arguments:
664  *    @p_session: job session
665  *
666  *  Return:
667  *       OMX error values
668  *
669  *  Description:
670  *       Configure OMX ports
671  *
672  **/
mm_jpeg_session_config_ports(mm_jpeg_job_session_t * p_session)673 OMX_ERRORTYPE mm_jpeg_session_config_ports(mm_jpeg_job_session_t* p_session)
674 {
675   OMX_ERRORTYPE ret = OMX_ErrorNone;
676   mm_jpeg_encode_params_t *p_params = &p_session->params;
677   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
678 
679   mm_jpeg_buf_t *p_src_buf =
680     &p_params->src_main_buf[p_jobparams->src_index];
681 
682   p_session->inputPort.nPortIndex = 0;
683   p_session->outputPort.nPortIndex = 1;
684   p_session->inputTmbPort.nPortIndex = 2;
685 
686   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
687     &p_session->inputPort);
688   if (ret) {
689     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
690     return ret;
691   }
692 
693   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
694     &p_session->inputTmbPort);
695   if (ret) {
696     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
697     return ret;
698   }
699 
700   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
701     &p_session->outputPort);
702   if (ret) {
703     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
704     return ret;
705   }
706 
707   p_session->inputPort.format.image.nFrameWidth =
708     p_jobparams->main_dim.src_dim.width;
709   p_session->inputPort.format.image.nFrameHeight =
710     p_jobparams->main_dim.src_dim.height;
711   p_session->inputPort.format.image.nStride =
712     p_src_buf->offset.mp[0].stride;
713   p_session->inputPort.format.image.nSliceHeight =
714     p_src_buf->offset.mp[0].scanline;
715   p_session->inputPort.format.image.eColorFormat =
716     map_jpeg_format(p_params->color_format);
717   p_session->inputPort.nBufferSize =
718     p_params->src_main_buf[p_jobparams->src_index].buf_size;
719   p_session->inputPort.nBufferCountActual = p_params->num_src_bufs;
720   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
721     &p_session->inputPort);
722   if (ret) {
723     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
724     return ret;
725   }
726 
727   p_session->inputTmbPort.format.image.nFrameWidth =
728     p_jobparams->thumb_dim.src_dim.width;
729   p_session->inputTmbPort.format.image.nFrameHeight =
730     p_jobparams->thumb_dim.src_dim.height;
731   p_session->inputTmbPort.format.image.nStride =
732     p_session->inputTmbPort.format.image.nFrameWidth;
733   p_session->inputTmbPort.format.image.nSliceHeight =
734     p_session->inputTmbPort.format.image.nFrameHeight;
735   p_session->inputTmbPort.format.image.eColorFormat =
736     map_jpeg_format(p_params->color_format);
737   p_session->inputTmbPort.nBufferSize =
738     p_params->src_thumb_buf[p_jobparams->thumb_index].buf_size;
739   p_session->inputTmbPort.nBufferCountActual = p_params->num_tmb_bufs;
740   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
741     &p_session->inputTmbPort);
742 
743   if (ret) {
744     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
745     return ret;
746   }
747 
748   if (p_session->params.encode_thumbnail) {
749     // Enable thumbnail port
750     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable,
751         p_session->inputTmbPort.nPortIndex, NULL);
752 
753     if (ret) {
754       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
755       return ret;
756     }
757   } else {
758     // Disable thumbnail port
759     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable,
760         p_session->inputTmbPort.nPortIndex, NULL);
761 
762     if (ret) {
763       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
764       return ret;
765     }
766   }
767 
768   p_session->outputPort.nBufferSize =
769     p_params->dest_buf[p_jobparams->dst_index].buf_size;
770   p_session->outputPort.nBufferCountActual = p_params->num_dst_bufs;
771   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
772     &p_session->outputPort);
773   if (ret) {
774     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
775     return ret;
776   }
777 
778   return ret;
779 }
780 
781 /** mm_jpeg_omx_config_thumbnail:
782  *
783  *  Arguments:
784  *    @p_session: job session
785  *
786  *  Return:
787  *       OMX error values
788  *
789  *  Description:
790  *       Configure OMX ports
791  *
792  **/
mm_jpeg_session_config_thumbnail(mm_jpeg_job_session_t * p_session)793 OMX_ERRORTYPE mm_jpeg_session_config_thumbnail(mm_jpeg_job_session_t* p_session)
794 {
795   OMX_ERRORTYPE ret = OMX_ErrorNone;
796   QOMX_THUMBNAIL_INFO thumbnail_info;
797   OMX_INDEXTYPE thumb_indextype;
798   OMX_BOOL encode_thumbnail = OMX_FALSE;
799   mm_jpeg_encode_params_t *p_params = &p_session->params;
800   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
801   mm_jpeg_dim_t *p_thumb_dim = &p_jobparams->thumb_dim;
802   mm_jpeg_dim_t *p_main_dim = &p_jobparams->main_dim;
803   QOMX_YUV_FRAME_INFO *p_frame_info = &thumbnail_info.tmbOffset;
804   mm_jpeg_buf_t *p_tmb_buf = &p_params->src_thumb_buf[p_jobparams->thumb_index];
805 
806   CDBG_HIGH("%s:%d] encode_thumbnail %d", __func__, __LINE__,
807     p_params->encode_thumbnail);
808   if (OMX_FALSE == p_params->encode_thumbnail) {
809     return ret;
810   }
811 
812   if ((p_thumb_dim->dst_dim.width == 0) || (p_thumb_dim->dst_dim.height == 0)) {
813     CDBG_ERROR("%s:%d] Error invalid output dim for thumbnail",
814       __func__, __LINE__);
815     return OMX_ErrorBadParameter;
816   }
817 
818   if ((p_thumb_dim->src_dim.width == 0) || (p_thumb_dim->src_dim.height == 0)) {
819     CDBG_ERROR("%s:%d] Error invalid input dim for thumbnail",
820       __func__, __LINE__);
821     return OMX_ErrorBadParameter;
822   }
823 
824   if ((p_thumb_dim->crop.width == 0) || (p_thumb_dim->crop.height == 0)) {
825     p_thumb_dim->crop.width = p_thumb_dim->src_dim.width;
826     p_thumb_dim->crop.height = p_thumb_dim->src_dim.height;
827   }
828 
829   /* check crop boundary */
830   if ((p_thumb_dim->crop.width + p_thumb_dim->crop.left > p_thumb_dim->src_dim.width) ||
831     (p_thumb_dim->crop.height + p_thumb_dim->crop.top > p_thumb_dim->src_dim.height)) {
832     CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) offset (%d, %d) out of (%d, %d)",
833       __func__, __LINE__,
834       p_thumb_dim->crop.width,
835       p_thumb_dim->crop.height,
836       p_thumb_dim->crop.left,
837       p_thumb_dim->crop.top,
838       p_thumb_dim->src_dim.width,
839       p_thumb_dim->src_dim.height);
840     return OMX_ErrorBadParameter;
841   }
842 
843   memset(&thumbnail_info, 0x0, sizeof(QOMX_THUMBNAIL_INFO));
844   ret = OMX_GetExtensionIndex(p_session->omx_handle,
845     QOMX_IMAGE_EXT_THUMBNAIL_NAME,
846     &thumb_indextype);
847   if (ret) {
848     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
849     return ret;
850   }
851 
852   /* fill thumbnail info */
853   thumbnail_info.scaling_enabled = 1;
854   thumbnail_info.input_width = p_thumb_dim->src_dim.width;
855   thumbnail_info.input_height = p_thumb_dim->src_dim.height;
856   thumbnail_info.crop_info.nWidth = p_thumb_dim->crop.width;
857   thumbnail_info.crop_info.nHeight = p_thumb_dim->crop.height;
858   thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left;
859   thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top;
860 
861   if ((p_main_dim->src_dim.width < p_thumb_dim->src_dim.width) ||
862     (p_main_dim->src_dim.height < p_thumb_dim->src_dim.height)) {
863     CDBG_ERROR("%s:%d] Improper thumbnail dim %dx%d resetting to %dx%d",
864       __func__, __LINE__,
865       p_thumb_dim->src_dim.width,
866       p_thumb_dim->src_dim.height,
867       p_main_dim->src_dim.width,
868       p_main_dim->src_dim.height);
869     thumbnail_info.input_width = p_main_dim->src_dim.width;
870     thumbnail_info.input_height = p_main_dim->src_dim.height;
871     if ((thumbnail_info.crop_info.nWidth > thumbnail_info.input_width)
872       || (thumbnail_info.crop_info.nHeight > thumbnail_info.input_height)) {
873       thumbnail_info.crop_info.nLeft = 0;
874       thumbnail_info.crop_info.nTop = 0;
875       thumbnail_info.crop_info.nWidth = thumbnail_info.input_width;
876       thumbnail_info.crop_info.nHeight = thumbnail_info.input_height;
877     }
878   }
879 
880   if ((p_thumb_dim->dst_dim.width > p_thumb_dim->src_dim.width)
881     || (p_thumb_dim->dst_dim.height > p_thumb_dim->src_dim.height)) {
882     CDBG_ERROR("%s:%d] Incorrect thumbnail dim %dx%d resetting to %dx%d",
883       __func__, __LINE__,
884       p_thumb_dim->dst_dim.width,
885       p_thumb_dim->dst_dim.height,
886       p_thumb_dim->src_dim.width,
887       p_thumb_dim->src_dim.height);
888     thumbnail_info.output_width = p_thumb_dim->src_dim.width;
889     thumbnail_info.output_height = p_thumb_dim->src_dim.height;
890   } else {
891     thumbnail_info.output_width = p_thumb_dim->dst_dim.width;
892     thumbnail_info.output_height = p_thumb_dim->dst_dim.height;
893   }
894 
895   memset(p_frame_info, 0x0, sizeof(*p_frame_info));
896 
897   p_frame_info->cbcrStartOffset[0] = p_tmb_buf->offset.mp[0].len;
898   p_frame_info->cbcrStartOffset[1] = p_tmb_buf->offset.mp[1].len;
899   p_frame_info->yOffset = p_tmb_buf->offset.mp[0].offset;
900   p_frame_info->cbcrOffset[0] = p_tmb_buf->offset.mp[1].offset;
901   p_frame_info->cbcrOffset[1] = p_tmb_buf->offset.mp[2].offset;
902 
903   ret = OMX_SetParameter(p_session->omx_handle, thumb_indextype,
904     &thumbnail_info);
905   if (ret) {
906     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
907     return ret;
908   }
909 
910   return ret;
911 }
912 
913 /** mm_jpeg_session_config_main_crop:
914  *
915  *  Arguments:
916  *    @p_session: job session
917  *
918  *  Return:
919  *       OMX error values
920  *
921  *  Description:
922  *       Configure main image crop
923  *
924  **/
mm_jpeg_session_config_main_crop(mm_jpeg_job_session_t * p_session)925 OMX_ERRORTYPE mm_jpeg_session_config_main_crop(mm_jpeg_job_session_t *p_session)
926 {
927   OMX_CONFIG_RECTTYPE rect_type_in, rect_type_out;
928   OMX_ERRORTYPE ret = OMX_ErrorNone;
929   mm_jpeg_encode_params_t *p_params = &p_session->params;
930   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
931   mm_jpeg_dim_t *dim = &p_jobparams->main_dim;
932 
933   if ((dim->crop.width == 0) || (dim->crop.height == 0)) {
934     dim->crop.width = dim->src_dim.width;
935     dim->crop.height = dim->src_dim.height;
936   }
937   /* error check first */
938   if ((dim->crop.width + dim->crop.left > dim->src_dim.width) ||
939     (dim->crop.height + dim->crop.top > dim->src_dim.height)) {
940     CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) out of (%d, %d)",
941       __func__, __LINE__,
942       dim->crop.width + dim->crop.left,
943       dim->crop.height + dim->crop.top,
944       dim->src_dim.width,
945       dim->src_dim.height);
946     return OMX_ErrorBadParameter;
947   }
948 
949   memset(&rect_type_in, 0, sizeof(rect_type_in));
950   memset(&rect_type_out, 0, sizeof(rect_type_out));
951   rect_type_in.nPortIndex = 0;
952   rect_type_out.nPortIndex = 0;
953 
954   if ((dim->src_dim.width != dim->crop.width) ||
955     (dim->src_dim.height != dim->crop.height) ||
956     (dim->src_dim.width != dim->dst_dim.width) ||
957     (dim->src_dim.height != dim->dst_dim.height)) {
958     /* Scaler information */
959     rect_type_in.nWidth = CEILING2(dim->crop.width);
960     rect_type_in.nHeight = CEILING2(dim->crop.height);
961     rect_type_in.nLeft = dim->crop.left;
962     rect_type_in.nTop = dim->crop.top;
963 
964     if (dim->dst_dim.width && dim->dst_dim.height) {
965       rect_type_out.nWidth = dim->dst_dim.width;
966       rect_type_out.nHeight = dim->dst_dim.height;
967     }
968   }
969 
970   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonInputCrop,
971     &rect_type_in);
972   if (OMX_ErrorNone != ret) {
973     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
974     return ret;
975   }
976 
977   CDBG("%s:%d] OMX_IndexConfigCommonInputCrop w = %d, h = %d, l = %d, t = %d,"
978     " port_idx = %d", __func__, __LINE__,
979     (int)rect_type_in.nWidth, (int)rect_type_in.nHeight,
980     (int)rect_type_in.nLeft, (int)rect_type_in.nTop,
981     (int)rect_type_in.nPortIndex);
982 
983   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonOutputCrop,
984     &rect_type_out);
985   if (OMX_ErrorNone != ret) {
986     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
987     return ret;
988   }
989   CDBG("%s:%d] OMX_IndexConfigCommonOutputCrop w = %d, h = %d,"
990     " port_idx = %d", __func__, __LINE__,
991     (int)rect_type_out.nWidth, (int)rect_type_out.nHeight,
992     (int)rect_type_out.nPortIndex);
993 
994   return ret;
995 }
996 
997 /** mm_jpeg_session_config_main:
998  *
999  *  Arguments:
1000  *    @p_session: job session
1001  *
1002  *  Return:
1003  *       OMX error values
1004  *
1005  *  Description:
1006  *       Configure main image
1007  *
1008  **/
mm_jpeg_session_config_main(mm_jpeg_job_session_t * p_session)1009 OMX_ERRORTYPE mm_jpeg_session_config_main(mm_jpeg_job_session_t *p_session)
1010 {
1011   OMX_ERRORTYPE rc = OMX_ErrorNone;
1012   OMX_IMAGE_PARAM_QFACTORTYPE q_factor;
1013   mm_jpeg_encode_params_t *p_params = &p_session->params;
1014   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
1015 
1016   /* config port */
1017   CDBG("%s:%d] config port", __func__, __LINE__);
1018   rc = mm_jpeg_session_config_ports(p_session);
1019   if (OMX_ErrorNone != rc) {
1020     CDBG_ERROR("%s: config port failed", __func__);
1021     return rc;
1022   }
1023 
1024   /* config buffer offset */
1025   CDBG("%s:%d] config main buf offset", __func__, __LINE__);
1026   rc = mm_jpeg_session_config_main_buffer_offset(p_session);
1027   if (OMX_ErrorNone != rc) {
1028     CDBG_ERROR("%s: config buffer offset failed", __func__);
1029     return rc;
1030   }
1031 
1032   /* config crop */
1033   CDBG("%s:%d] config main crop", __func__, __LINE__);
1034   rc = mm_jpeg_session_config_main_crop(p_session);
1035   if (OMX_ErrorNone != rc) {
1036     CDBG_ERROR("%s: config crop failed", __func__);
1037     return rc;
1038   }
1039 
1040   /* set quality */
1041   memset(&q_factor, 0, sizeof(q_factor));
1042   q_factor.nPortIndex = 0;
1043   q_factor.nQFactor = p_params->quality;
1044   rc = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamQFactor, &q_factor);
1045   CDBG("%s:%d] config QFactor: %d", __func__, __LINE__, (int)q_factor.nQFactor);
1046   if (OMX_ErrorNone != rc) {
1047     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
1048     return rc;
1049   }
1050 
1051   return rc;
1052 }
1053 
1054 /** mm_jpeg_session_config_common:
1055  *
1056  *  Arguments:
1057  *    @p_session: job session
1058  *
1059  *  Return:
1060  *       OMX error values
1061  *
1062  *  Description:
1063  *       Configure common parameters
1064  *
1065  **/
mm_jpeg_session_config_common(mm_jpeg_job_session_t * p_session)1066 OMX_ERRORTYPE mm_jpeg_session_config_common(mm_jpeg_job_session_t *p_session)
1067 {
1068   OMX_ERRORTYPE rc = OMX_ErrorNone;
1069   int i;
1070   OMX_INDEXTYPE exif_idx;
1071   OMX_CONFIG_ROTATIONTYPE rotate;
1072   mm_jpeg_encode_params_t *p_params = &p_session->params;
1073   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
1074   QOMX_EXIF_INFO exif_info;
1075 
1076   /* set rotation */
1077   memset(&rotate, 0, sizeof(rotate));
1078   rotate.nPortIndex = 1;
1079   rotate.nRotation = p_jobparams->rotation;
1080   rc = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate,
1081     &rotate);
1082   if (OMX_ErrorNone != rc) {
1083       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
1084       return rc;
1085   }
1086   CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__,
1087     (int)p_jobparams->rotation, (int)rotate.nPortIndex);
1088 
1089   /* Set Exif data*/
1090   memset(&p_session->exif_info_all[0],  0,  sizeof(p_session->exif_info_all));
1091 
1092   exif_info.numOfEntries = p_params->exif_info.numOfEntries;
1093   exif_info.exif_data = &p_session->exif_info_all[0];
1094   /*If Exif data has been passed copy it*/
1095   if (p_params->exif_info.numOfEntries > 0) {
1096     CDBG("%s:%d] Num of exif entries passed from HAL: %d", __func__, __LINE__,
1097       p_params->exif_info.numOfEntries);
1098     memcpy(exif_info.exif_data, p_params->exif_info.exif_data,
1099       sizeof(QEXIF_INFO_DATA) * p_params->exif_info.numOfEntries);
1100   }
1101 
1102   if (exif_info.numOfEntries > 0) {
1103     /* set exif tags */
1104     CDBG("%s:%d] Set exif tags count %d", __func__, __LINE__,
1105       (int)exif_info.numOfEntries);
1106     rc = OMX_GetExtensionIndex(p_session->omx_handle, QOMX_IMAGE_EXT_EXIF_NAME,
1107       &exif_idx);
1108     if (OMX_ErrorNone != rc) {
1109       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
1110       return rc;
1111     }
1112 
1113     rc = OMX_SetParameter(p_session->omx_handle, exif_idx,
1114       &exif_info);
1115     if (OMX_ErrorNone != rc) {
1116       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
1117       return rc;
1118     }
1119   }
1120 
1121   return rc;
1122 }
1123 
1124 /** mm_jpeg_session_abort:
1125  *
1126  *  Arguments:
1127  *    @p_session: jpeg session
1128  *
1129  *  Return:
1130  *       OMX_BOOL
1131  *
1132  *  Description:
1133  *       Abort ongoing job
1134  *
1135  **/
mm_jpeg_session_abort(mm_jpeg_job_session_t * p_session)1136 OMX_BOOL mm_jpeg_session_abort(mm_jpeg_job_session_t *p_session)
1137 {
1138   OMX_ERRORTYPE ret = OMX_ErrorNone;
1139 
1140   CDBG("%s:%d] E", __func__, __LINE__);
1141   pthread_mutex_lock(&p_session->lock);
1142   if (OMX_TRUE == p_session->abort_flag) {
1143     pthread_mutex_unlock(&p_session->lock);
1144     CDBG("%s:%d] **** ALREADY ABORTED", __func__, __LINE__);
1145     return 0;
1146   }
1147   p_session->abort_flag = OMX_TRUE;
1148   if (OMX_TRUE == p_session->encoding) {
1149     p_session->state_change_pending = OMX_TRUE;
1150 
1151     CDBG("%s:%d] **** ABORTING", __func__, __LINE__);
1152 
1153     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
1154     OMX_StateIdle, NULL);
1155 
1156     if (ret != OMX_ErrorNone) {
1157       CDBG("%s:%d] OMX_SendCommand returned error %d", __func__, __LINE__, ret);
1158       pthread_mutex_unlock(&p_session->lock);
1159       return 1;
1160     }
1161 
1162     CDBG("%s:%d] before wait", __func__, __LINE__);
1163     pthread_cond_wait(&p_session->cond, &p_session->lock);
1164     CDBG("%s:%d] after wait", __func__, __LINE__);
1165   }
1166   pthread_mutex_unlock(&p_session->lock);
1167   CDBG("%s:%d] X", __func__, __LINE__);
1168   return 0;
1169 }
1170 
1171 /** mm_jpeg_get_job_idx:
1172  *
1173  *  Arguments:
1174  *    @my_obj: jpeg object
1175  *    @client_idx: client index
1176  *
1177  *  Return:
1178  *       job index
1179  *
1180  *  Description:
1181  *       Get job index by client id
1182  *
1183  **/
mm_jpeg_get_new_session_idx(mm_jpeg_obj * my_obj,int client_idx,mm_jpeg_job_session_t ** pp_session)1184 inline int mm_jpeg_get_new_session_idx(mm_jpeg_obj *my_obj, int client_idx,
1185   mm_jpeg_job_session_t **pp_session)
1186 {
1187   int i = 0;
1188   int index = -1;
1189   for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
1190     pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock);
1191     if (!my_obj->clnt_mgr[client_idx].session[i].active) {
1192       *pp_session = &my_obj->clnt_mgr[client_idx].session[i];
1193       my_obj->clnt_mgr[client_idx].session[i].active = OMX_TRUE;
1194       index = i;
1195       pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock);
1196       break;
1197     }
1198     pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock);
1199   }
1200   return index;
1201 }
1202 
1203 /** mm_jpeg_get_job_idx:
1204  *
1205  *  Arguments:
1206  *    @my_obj: jpeg object
1207  *    @client_idx: client index
1208  *
1209  *  Return:
1210  *       job index
1211  *
1212  *  Description:
1213  *       Get job index by client id
1214  *
1215  **/
mm_jpeg_remove_session_idx(mm_jpeg_obj * my_obj,uint32_t job_id)1216 inline void mm_jpeg_remove_session_idx(mm_jpeg_obj *my_obj, uint32_t job_id)
1217 {
1218   int client_idx =  GET_CLIENT_IDX(job_id);
1219   int session_idx= GET_SESSION_IDX(job_id);
1220   CDBG("%s:%d] client_idx %d session_idx %d", __func__, __LINE__,
1221     client_idx, session_idx);
1222   pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock);
1223   my_obj->clnt_mgr[client_idx].session[session_idx].active = OMX_FALSE;
1224   pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock);
1225 }
1226 
1227 /** mm_jpeg_get_session_idx:
1228  *
1229  *  Arguments:
1230  *    @my_obj: jpeg object
1231  *    @client_idx: client index
1232  *
1233  *  Return:
1234  *       job index
1235  *
1236  *  Description:
1237  *       Get job index by client id
1238  *
1239  **/
mm_jpeg_get_session(mm_jpeg_obj * my_obj,uint32_t job_id)1240 inline mm_jpeg_job_session_t *mm_jpeg_get_session(mm_jpeg_obj *my_obj, uint32_t job_id)
1241 {
1242   mm_jpeg_job_session_t *p_session = NULL;
1243   int client_idx =  GET_CLIENT_IDX(job_id);
1244   int session_idx= GET_SESSION_IDX(job_id);
1245 
1246   CDBG("%s:%d] client_idx %d session_idx %d", __func__, __LINE__,
1247     client_idx, session_idx);
1248   if ((session_idx >= MM_JPEG_MAX_SESSION) ||
1249     (client_idx >= MAX_JPEG_CLIENT_NUM)) {
1250     CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__,
1251       job_id);
1252     return NULL;
1253   }
1254   pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock);
1255   p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
1256   pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock);
1257   return p_session;
1258 }
1259 
1260 /** mm_jpeg_session_configure:
1261  *
1262  *  Arguments:
1263  *    @data: encode session
1264  *
1265  *  Return:
1266  *       none
1267  *
1268  *  Description:
1269  *       Configure the session
1270  *
1271  **/
mm_jpeg_session_configure(mm_jpeg_job_session_t * p_session)1272 static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session)
1273 {
1274   OMX_ERRORTYPE ret = OMX_ErrorNone;
1275   mm_jpeg_encode_params_t *p_params = &p_session->params;
1276   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
1277   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
1278 
1279   CDBG("%s:%d] E ", __func__, __LINE__);
1280 
1281   MM_JPEG_CHK_ABORT(p_session, ret, error);
1282 
1283   /* config main img */
1284   ret = mm_jpeg_session_config_main(p_session);
1285   if (OMX_ErrorNone != ret) {
1286     CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__);
1287     goto error;
1288   }
1289 
1290   /* config thumbnail */
1291   ret = mm_jpeg_session_config_thumbnail(p_session);
1292   if (OMX_ErrorNone != ret) {
1293     CDBG_ERROR("%s:%d] config thumbnail img failed", __func__, __LINE__);
1294     goto error;
1295   }
1296 
1297   /* config encoding mode */
1298   CDBG("%s:%d] config encoding mode", __func__, __LINE__);
1299   ret = mm_jpeg_encoding_mode(p_session);
1300   if (OMX_ErrorNone != ret) {
1301     CDBG_ERROR("%s: config encoding mode failed", __func__);
1302     return ret;
1303   }
1304 
1305   /* common config */
1306   ret = mm_jpeg_session_config_common(p_session);
1307   if (OMX_ErrorNone != ret) {
1308     CDBG_ERROR("%s:%d] config common failed", __func__, __LINE__);
1309     goto error;
1310   }
1311 
1312   ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle,
1313     mm_jpeg_session_send_buffers);
1314   if (ret) {
1315     CDBG_ERROR("%s:%d] change state to idle failed %d",
1316       __func__, __LINE__, ret);
1317     goto error;
1318   }
1319 
1320   ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting,
1321     NULL);
1322   if (ret) {
1323     CDBG_ERROR("%s:%d] change state to executing failed %d",
1324       __func__, __LINE__, ret);
1325     goto error;
1326   }
1327 
1328 error:
1329   CDBG("%s:%d] X ret %d", __func__, __LINE__, ret);
1330   return ret;
1331 }
1332 
1333 /** mm_jpeg_session_encode:
1334  *
1335  *  Arguments:
1336  *    @p_session: encode session
1337  *
1338  *  Return:
1339  *       OMX_ERRORTYPE
1340  *
1341  *  Description:
1342  *       Start the encoding
1343  *
1344  **/
mm_jpeg_job_done(mm_jpeg_job_session_t * p_session)1345 static inline void mm_jpeg_job_done(mm_jpeg_job_session_t *p_session)
1346 {
1347   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
1348   mm_jpeg_job_q_node_t *node = NULL;
1349 
1350   /*remove the job*/
1351   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
1352     p_session->jobId);
1353   if (node) {
1354     free(node);
1355   }
1356   p_session->encoding = OMX_FALSE;
1357 
1358   /* wake up jobMgr thread to work on new job if there is any */
1359   cam_sem_post(&my_obj->job_mgr.job_sem);
1360 }
1361 
1362 /** mm_jpeg_session_encode:
1363  *
1364  *  Arguments:
1365  *    @p_session: encode session
1366  *
1367  *  Return:
1368  *       OMX_ERRORTYPE
1369  *
1370  *  Description:
1371  *       Start the encoding
1372  *
1373  **/
mm_jpeg_session_encode(mm_jpeg_job_session_t * p_session)1374 static OMX_ERRORTYPE mm_jpeg_session_encode(mm_jpeg_job_session_t *p_session)
1375 {
1376   OMX_ERRORTYPE ret = OMX_ErrorNone;
1377   mm_jpeg_encode_params_t *p_params = &p_session->params;
1378   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
1379   int dest_idx = 0;
1380   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
1381 
1382   pthread_mutex_lock(&p_session->lock);
1383   p_session->abort_flag = OMX_FALSE;
1384   p_session->encoding = OMX_FALSE;
1385   pthread_mutex_unlock(&p_session->lock);
1386 
1387   if (OMX_FALSE == p_session->config) {
1388     ret = mm_jpeg_session_configure(p_session);
1389     if (ret) {
1390       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1391       goto error;
1392     }
1393     p_session->config = OMX_TRUE;
1394   }
1395 
1396   pthread_mutex_lock(&p_session->lock);
1397   p_session->encoding = OMX_TRUE;
1398   pthread_mutex_unlock(&p_session->lock);
1399 
1400   MM_JPEG_CHK_ABORT(p_session, ret, error);
1401 
1402 #ifdef MM_JPEG_DUMP_INPUT
1403   DUMP_TO_FILE("/data/mm_jpeg_int.yuv",
1404     p_session->p_in_omx_buf[p_jobparams->src_index]->pBuffer,
1405     (int)p_session->p_in_omx_buf[p_jobparams->src_index]->nAllocLen);
1406 #endif
1407 
1408   ret = OMX_EmptyThisBuffer(p_session->omx_handle,
1409     p_session->p_in_omx_buf[p_jobparams->src_index]);
1410   if (ret) {
1411     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1412     goto error;
1413   }
1414 
1415   if (p_session->params.encode_thumbnail) {
1416     ret = OMX_EmptyThisBuffer(p_session->omx_handle,
1417         p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]);
1418     if (ret) {
1419       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1420       goto error;
1421     }
1422   }
1423 
1424   ret = OMX_FillThisBuffer(p_session->omx_handle,
1425     p_session->p_out_omx_buf[p_jobparams->dst_index]);
1426   if (ret) {
1427     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1428     goto error;
1429   }
1430 
1431   MM_JPEG_CHK_ABORT(p_session, ret, error);
1432 
1433 error:
1434 
1435   CDBG("%s:%d] X ", __func__, __LINE__);
1436   return ret;
1437 }
1438 
1439 /** mm_jpeg_process_encoding_job:
1440  *
1441  *  Arguments:
1442  *    @my_obj: jpeg client
1443  *    @job_node: job node
1444  *
1445  *  Return:
1446  *       0 for success -1 otherwise
1447  *
1448  *  Description:
1449  *       Start the encoding job
1450  *
1451  **/
mm_jpeg_process_encoding_job(mm_jpeg_obj * my_obj,mm_jpeg_job_q_node_t * job_node)1452 int32_t mm_jpeg_process_encoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
1453 {
1454   int32_t rc = 0;
1455   OMX_ERRORTYPE ret = OMX_ErrorNone;
1456   mm_jpeg_job_session_t *p_session = NULL;
1457   mm_jpeg_job_q_node_t *node = NULL;
1458 
1459   /* check if valid session */
1460   p_session = mm_jpeg_get_session(my_obj, job_node->enc_info.job_id);
1461   if (NULL == p_session) {
1462     CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__,
1463       job_node->enc_info.job_id);
1464     return -1;
1465   }
1466 
1467   /* sent encode cmd to OMX, queue job into ongoing queue */
1468   rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, job_node);
1469   if (rc) {
1470     CDBG_ERROR("%s:%d] jpeg enqueue failed %d",
1471       __func__, __LINE__, ret);
1472     goto error;
1473   }
1474 
1475   p_session->encode_job = job_node->enc_info.encode_job;
1476   p_session->jobId = job_node->enc_info.job_id;
1477   ret = mm_jpeg_session_encode(p_session);
1478   if (ret) {
1479     CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__);
1480     goto error;
1481   }
1482 
1483   CDBG("%s:%d] Success X ", __func__, __LINE__);
1484   return rc;
1485 
1486 error:
1487 
1488   if ((OMX_ErrorNone != ret) &&
1489     (NULL != p_session->params.jpeg_cb)) {
1490     p_session->job_status = JPEG_JOB_STATUS_ERROR;
1491     CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
1492       p_session->job_status);
1493     p_session->params.jpeg_cb(p_session->job_status,
1494       p_session->client_hdl,
1495       p_session->jobId,
1496       NULL,
1497       p_session->params.userdata);
1498   }
1499 
1500   /*remove the job*/
1501   mm_jpeg_job_done(p_session);
1502   CDBG("%s:%d] Error X ", __func__, __LINE__);
1503 
1504   return rc;
1505 }
1506 
1507 /** mm_jpeg_jobmgr_thread:
1508  *
1509  *  Arguments:
1510  *    @my_obj: jpeg object
1511  *
1512  *  Return:
1513  *       0 for success else failure
1514  *
1515  *  Description:
1516  *       job manager thread main function
1517  *
1518  **/
mm_jpeg_jobmgr_thread(void * data)1519 static void *mm_jpeg_jobmgr_thread(void *data)
1520 {
1521   int rc = 0;
1522   int running = 1;
1523   uint32_t num_ongoing_jobs = 0;
1524   mm_jpeg_obj *my_obj = (mm_jpeg_obj*)data;
1525   mm_jpeg_job_cmd_thread_t *cmd_thread = &my_obj->job_mgr;
1526   mm_jpeg_job_q_node_t* node = NULL;
1527 
1528   do {
1529     do {
1530       rc = cam_sem_wait(&cmd_thread->job_sem);
1531       if (rc != 0 && errno != EINVAL) {
1532         CDBG_ERROR("%s: cam_sem_wait error (%s)",
1533           __func__, strerror(errno));
1534         return NULL;
1535       }
1536     } while (rc != 0);
1537 
1538     /* check ongoing q size */
1539     num_ongoing_jobs = mm_jpeg_queue_get_size(&my_obj->ongoing_job_q);
1540     if (num_ongoing_jobs >= NUM_MAX_JPEG_CNCURRENT_JOBS) {
1541       CDBG("%s:%d] ongoing job already reach max %d", __func__,
1542         __LINE__, num_ongoing_jobs);
1543       continue;
1544     }
1545 
1546     pthread_mutex_lock(&my_obj->job_lock);
1547     /* can go ahead with new work */
1548     node = (mm_jpeg_job_q_node_t*)mm_jpeg_queue_deq(&cmd_thread->job_queue);
1549     if (node != NULL) {
1550       switch (node->type) {
1551       case MM_JPEG_CMD_TYPE_JOB:
1552         rc = mm_jpeg_process_encoding_job(my_obj, node);
1553         break;
1554       case MM_JPEG_CMD_TYPE_EXIT:
1555       default:
1556         /* free node */
1557         free(node);
1558         /* set running flag to false */
1559         running = 0;
1560         break;
1561       }
1562     }
1563     pthread_mutex_unlock(&my_obj->job_lock);
1564 
1565   } while (running);
1566   return NULL;
1567 }
1568 
1569 /** mm_jpeg_jobmgr_thread_launch:
1570  *
1571  *  Arguments:
1572  *    @my_obj: jpeg object
1573  *
1574  *  Return:
1575  *       0 for success else failure
1576  *
1577  *  Description:
1578  *       launches the job manager thread
1579  *
1580  **/
mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj * my_obj)1581 int32_t mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj *my_obj)
1582 {
1583   int32_t rc = 0;
1584   mm_jpeg_job_cmd_thread_t *job_mgr = &my_obj->job_mgr;
1585 
1586   cam_sem_init(&job_mgr->job_sem, 0);
1587   mm_jpeg_queue_init(&job_mgr->job_queue);
1588 
1589   /* launch the thread */
1590   pthread_create(&job_mgr->pid,
1591     NULL,
1592     mm_jpeg_jobmgr_thread,
1593     (void *)my_obj);
1594   return rc;
1595 }
1596 
1597 /** mm_jpeg_jobmgr_thread_release:
1598  *
1599  *  Arguments:
1600  *    @my_obj: jpeg object
1601  *
1602  *  Return:
1603  *       0 for success else failure
1604  *
1605  *  Description:
1606  *       Releases the job manager thread
1607  *
1608  **/
mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj)1609 int32_t mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj)
1610 {
1611   int32_t rc = 0;
1612   mm_jpeg_job_cmd_thread_t * cmd_thread = &my_obj->job_mgr;
1613   mm_jpeg_job_q_node_t* node =
1614     (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
1615   if (NULL == node) {
1616     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
1617     return -1;
1618   }
1619 
1620   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
1621   node->type = MM_JPEG_CMD_TYPE_EXIT;
1622 
1623   mm_jpeg_queue_enq(&cmd_thread->job_queue, node);
1624   cam_sem_post(&cmd_thread->job_sem);
1625 
1626   /* wait until cmd thread exits */
1627   if (pthread_join(cmd_thread->pid, NULL) != 0) {
1628     CDBG("%s: pthread dead already", __func__);
1629   }
1630   mm_jpeg_queue_deinit(&cmd_thread->job_queue);
1631 
1632   cam_sem_destroy(&cmd_thread->job_sem);
1633   memset(cmd_thread, 0, sizeof(mm_jpeg_job_cmd_thread_t));
1634   return rc;
1635 }
1636 
1637 /** mm_jpeg_init:
1638  *
1639  *  Arguments:
1640  *    @my_obj: jpeg object
1641  *
1642  *  Return:
1643  *       0 for success else failure
1644  *
1645  *  Description:
1646  *       Initializes the jpeg client
1647  *
1648  **/
mm_jpeg_init(mm_jpeg_obj * my_obj)1649 int32_t mm_jpeg_init(mm_jpeg_obj *my_obj)
1650 {
1651   int32_t rc = 0;
1652 
1653   /* init locks */
1654   pthread_mutex_init(&my_obj->job_lock, NULL);
1655 
1656   /* init ongoing job queue */
1657   rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q);
1658   if (0 != rc) {
1659     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1660     return -1;
1661   }
1662 
1663   /* init job semaphore and launch jobmgr thread */
1664   CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc);
1665   rc = mm_jpeg_jobmgr_thread_launch(my_obj);
1666   if (0 != rc) {
1667     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1668     return -1;
1669   }
1670 
1671   /* load OMX */
1672   if (OMX_ErrorNone != OMX_Init()) {
1673     /* roll back in error case */
1674     CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc);
1675     mm_jpeg_jobmgr_thread_release(my_obj);
1676     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1677     pthread_mutex_destroy(&my_obj->job_lock);
1678   }
1679 
1680   return rc;
1681 }
1682 
1683 /** mm_jpeg_deinit:
1684  *
1685  *  Arguments:
1686  *    @my_obj: jpeg object
1687  *
1688  *  Return:
1689  *       0 for success else failure
1690  *
1691  *  Description:
1692  *       Deinits the jpeg client
1693  *
1694  **/
mm_jpeg_deinit(mm_jpeg_obj * my_obj)1695 int32_t mm_jpeg_deinit(mm_jpeg_obj *my_obj)
1696 {
1697   int32_t rc = 0;
1698 
1699   /* release jobmgr thread */
1700   rc = mm_jpeg_jobmgr_thread_release(my_obj);
1701   if (0 != rc) {
1702     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1703   }
1704 
1705   /* unload OMX engine */
1706   OMX_Deinit();
1707 
1708   /* deinit ongoing job and cb queue */
1709   rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1710   if (0 != rc) {
1711     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1712   }
1713 
1714   /* destroy locks */
1715   pthread_mutex_destroy(&my_obj->job_lock);
1716 
1717   return rc;
1718 }
1719 
1720 /** mm_jpeg_new_client:
1721  *
1722  *  Arguments:
1723  *    @my_obj: jpeg object
1724  *
1725  *  Return:
1726  *       0 for success else failure
1727  *
1728  *  Description:
1729  *       Create new jpeg client
1730  *
1731  **/
mm_jpeg_new_client(mm_jpeg_obj * my_obj)1732 uint32_t mm_jpeg_new_client(mm_jpeg_obj *my_obj)
1733 {
1734   uint32_t client_hdl = 0;
1735   uint8_t idx;
1736   int i = 0;
1737 
1738   if (my_obj->num_clients >= MAX_JPEG_CLIENT_NUM) {
1739     CDBG_ERROR("%s: num of clients reached limit", __func__);
1740     return client_hdl;
1741   }
1742 
1743   for (idx = 0; idx < MAX_JPEG_CLIENT_NUM; idx++) {
1744     if (0 == my_obj->clnt_mgr[idx].is_used) {
1745       break;
1746     }
1747   }
1748 
1749   if (idx < MAX_JPEG_CLIENT_NUM) {
1750     /* client session avail */
1751     /* generate client handler by index */
1752     client_hdl = mm_jpeg_util_generate_handler(idx);
1753 
1754     /* update client session */
1755     my_obj->clnt_mgr[idx].is_used = 1;
1756     my_obj->clnt_mgr[idx].client_handle = client_hdl;
1757 
1758     pthread_mutex_init(&my_obj->clnt_mgr[idx].lock, NULL);
1759     for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
1760       memset(&my_obj->clnt_mgr[idx].session[i], 0x0, sizeof(mm_jpeg_job_session_t));
1761     }
1762 
1763     /* increse client count */
1764     my_obj->num_clients++;
1765   }
1766 
1767   return client_hdl;
1768 }
1769 
1770 /** mm_jpeg_start_job:
1771  *
1772  *  Arguments:
1773  *    @my_obj: jpeg object
1774  *    @client_hdl: client handle
1775  *    @job: pointer to encode job
1776  *    @jobId: job id
1777  *
1778  *  Return:
1779  *       0 for success else failure
1780  *
1781  *  Description:
1782  *       Start the encoding job
1783  *
1784  **/
mm_jpeg_start_job(mm_jpeg_obj * my_obj,mm_jpeg_job_t * job,uint32_t * job_id)1785 int32_t mm_jpeg_start_job(mm_jpeg_obj *my_obj,
1786   mm_jpeg_job_t *job,
1787   uint32_t *job_id)
1788 {
1789   int32_t rc = -1;
1790   uint8_t session_idx = 0;
1791   uint8_t client_idx = 0;
1792   mm_jpeg_job_q_node_t* node = NULL;
1793   mm_jpeg_job_session_t *p_session = NULL;
1794   mm_jpeg_encode_job_t *p_jobparams  = &job->encode_job;
1795 
1796   *job_id = 0;
1797 
1798   /* check if valid session */
1799   session_idx = GET_SESSION_IDX(p_jobparams->session_id);
1800   client_idx = GET_CLIENT_IDX(p_jobparams->session_id);
1801   CDBG("%s:%d] session_idx %d client idx %d", __func__, __LINE__,
1802     session_idx, client_idx);
1803 
1804   if ((session_idx >= MM_JPEG_MAX_SESSION) ||
1805     (client_idx >= MAX_JPEG_CLIENT_NUM)) {
1806     CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__,
1807       job->encode_job.session_id);
1808     return rc;
1809   }
1810 
1811   p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
1812   if (OMX_FALSE == p_session->active) {
1813     CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__,
1814       job->encode_job.session_id);
1815     return rc;
1816   }
1817 
1818   if ((p_jobparams->src_index >= p_session->params.num_src_bufs) ||
1819     (p_jobparams->dst_index >= p_session->params.num_dst_bufs)) {
1820     CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__);
1821     return rc;
1822   }
1823 
1824   /* enqueue new job into todo job queue */
1825   node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
1826   if (NULL == node) {
1827     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
1828     return -1;
1829   }
1830 
1831   *job_id = job->encode_job.session_id |
1832     ((p_session->job_hist++ % JOB_HIST_MAX) << 16);
1833 
1834   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
1835   node->enc_info.encode_job = job->encode_job;
1836   node->enc_info.job_id = *job_id;
1837   node->enc_info.client_handle = p_session->client_hdl;
1838   node->type = MM_JPEG_CMD_TYPE_JOB;
1839 
1840   rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, node);
1841   if (0 == rc) {
1842     cam_sem_post(&my_obj->job_mgr.job_sem);
1843   }
1844 
1845   return rc;
1846 }
1847 
1848 /** mm_jpeg_abort_job:
1849  *
1850  *  Arguments:
1851  *    @my_obj: jpeg object
1852  *    @client_hdl: client handle
1853  *    @jobId: job id
1854  *
1855  *  Return:
1856  *       0 for success else failure
1857  *
1858  *  Description:
1859  *       Abort the encoding session
1860  *
1861  **/
mm_jpeg_abort_job(mm_jpeg_obj * my_obj,uint32_t jobId)1862 int32_t mm_jpeg_abort_job(mm_jpeg_obj *my_obj,
1863   uint32_t jobId)
1864 {
1865   int32_t rc = -1;
1866   uint8_t clnt_idx = 0;
1867   mm_jpeg_job_q_node_t *node = NULL;
1868   OMX_BOOL ret = OMX_FALSE;
1869   mm_jpeg_job_session_t *p_session = NULL;
1870 
1871   CDBG("%s:%d] ", __func__, __LINE__);
1872   pthread_mutex_lock(&my_obj->job_lock);
1873 
1874   /* abort job if in todo queue */
1875   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId);
1876   if (NULL != node) {
1877     free(node);
1878     goto abort_done;
1879   }
1880 
1881   /* abort job if in ongoing queue */
1882   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId);
1883   if (NULL != node) {
1884     /* find job that is OMX ongoing, ask OMX to abort the job */
1885     p_session = mm_jpeg_get_session(my_obj, node->enc_info.job_id);
1886     if (p_session) {
1887       mm_jpeg_session_abort(p_session);
1888     } else {
1889       CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__,
1890         node->enc_info.job_id);
1891     }
1892     free(node);
1893     goto abort_done;
1894   }
1895 
1896 abort_done:
1897   pthread_mutex_unlock(&my_obj->job_lock);
1898 
1899   return rc;
1900 }
1901 
1902 /** mm_jpeg_create_session:
1903  *
1904  *  Arguments:
1905  *    @my_obj: jpeg object
1906  *    @client_hdl: client handle
1907  *    @p_params: pointer to encode params
1908  *    @p_session_id: session id
1909  *
1910  *  Return:
1911  *       0 for success else failure
1912  *
1913  *  Description:
1914  *       Start the encoding session
1915  *
1916  **/
mm_jpeg_create_session(mm_jpeg_obj * my_obj,uint32_t client_hdl,mm_jpeg_encode_params_t * p_params,uint32_t * p_session_id)1917 int32_t mm_jpeg_create_session(mm_jpeg_obj *my_obj,
1918   uint32_t client_hdl,
1919   mm_jpeg_encode_params_t *p_params,
1920   uint32_t* p_session_id)
1921 {
1922   int32_t rc = 0;
1923   OMX_ERRORTYPE ret = OMX_ErrorNone;
1924   uint8_t clnt_idx = 0;
1925   int session_idx = -1;
1926   mm_jpeg_job_session_t *p_session = NULL;
1927   *p_session_id = 0;
1928 
1929   /* validate the parameters */
1930   if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF)
1931     || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) {
1932     CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__);
1933     return -1;
1934   }
1935 
1936   /* check if valid client */
1937   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
1938   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
1939     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
1940     return -1;
1941   }
1942 
1943   session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session);
1944   if (session_idx < 0) {
1945     CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx);
1946     return -1;
1947   }
1948 
1949   ret = mm_jpeg_session_create(p_session);
1950   if (OMX_ErrorNone != ret) {
1951     p_session->active = OMX_FALSE;
1952     CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__);
1953     return ret;
1954   }
1955 
1956   *p_session_id = (JOB_ID_MAGICVAL << 24) | (session_idx << 8) | clnt_idx;
1957 
1958   /*copy the params*/
1959   p_session->params = *p_params;
1960   p_session->client_hdl = client_hdl;
1961   p_session->sessionId = *p_session_id;
1962   p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */
1963   CDBG("%s:%d] session id %x", __func__, __LINE__, *p_session_id);
1964 
1965   return ret;
1966 }
1967 
1968 /** mm_jpeg_destroy_session:
1969  *
1970  *  Arguments:
1971  *    @my_obj: jpeg object
1972  *    @session_id: session index
1973  *
1974  *  Return:
1975  *       0 for success else failure
1976  *
1977  *  Description:
1978  *       Destroy the encoding session
1979  *
1980  **/
mm_jpeg_destroy_session(mm_jpeg_obj * my_obj,mm_jpeg_job_session_t * p_session)1981 int32_t mm_jpeg_destroy_session(mm_jpeg_obj *my_obj,
1982   mm_jpeg_job_session_t *p_session)
1983 {
1984   int32_t rc = 0;
1985   uint8_t clnt_idx = 0;
1986   mm_jpeg_job_q_node_t *node = NULL;
1987   OMX_BOOL ret = OMX_FALSE;
1988   uint32_t session_id = p_session->sessionId;
1989 
1990   if (NULL == p_session) {
1991     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
1992     return rc;
1993   }
1994 
1995   pthread_mutex_lock(&my_obj->job_lock);
1996 
1997   /* abort job if in todo queue */
1998   CDBG("%s:%d] abort todo jobs", __func__, __LINE__);
1999   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
2000   while (NULL != node) {
2001     free(node);
2002     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
2003   }
2004 
2005   /* abort job if in ongoing queue */
2006   CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__);
2007   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
2008   while (NULL != node) {
2009     free(node);
2010     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
2011   }
2012 
2013   /* abort the current session */
2014   mm_jpeg_session_abort(p_session);
2015   mm_jpeg_session_destroy(p_session);
2016   mm_jpeg_remove_session_idx(my_obj, session_id);
2017   pthread_mutex_unlock(&my_obj->job_lock);
2018 
2019   /* wake up jobMgr thread to work on new job if there is any */
2020   cam_sem_post(&my_obj->job_mgr.job_sem);
2021   CDBG("%s:%d] X", __func__, __LINE__);
2022 
2023   return rc;
2024 }
2025 
2026 /** mm_jpeg_destroy_session:
2027  *
2028  *  Arguments:
2029  *    @my_obj: jpeg object
2030  *    @session_id: session index
2031  *
2032  *  Return:
2033  *       0 for success else failure
2034  *
2035  *  Description:
2036  *       Destroy the encoding session
2037  *
2038  **/
mm_jpeg_destroy_session_unlocked(mm_jpeg_obj * my_obj,mm_jpeg_job_session_t * p_session)2039 int32_t mm_jpeg_destroy_session_unlocked(mm_jpeg_obj *my_obj,
2040   mm_jpeg_job_session_t *p_session)
2041 {
2042   int32_t rc = -1;
2043   uint8_t clnt_idx = 0;
2044   mm_jpeg_job_q_node_t *node = NULL;
2045   OMX_BOOL ret = OMX_FALSE;
2046   uint32_t session_id = p_session->sessionId;
2047 
2048   if (NULL == p_session) {
2049     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
2050     return rc;
2051   }
2052 
2053   /* abort job if in todo queue */
2054   CDBG("%s:%d] abort todo jobs", __func__, __LINE__);
2055   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
2056   while (NULL != node) {
2057     free(node);
2058     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
2059   }
2060 
2061   /* abort job if in ongoing queue */
2062   CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__);
2063   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
2064   while (NULL != node) {
2065     free(node);
2066     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
2067   }
2068 
2069   /* abort the current session */
2070   mm_jpeg_session_abort(p_session);
2071   mm_jpeg_remove_session_idx(my_obj, session_id);
2072 
2073   return rc;
2074 }
2075 
2076 /** mm_jpeg_destroy_session:
2077  *
2078  *  Arguments:
2079  *    @my_obj: jpeg object
2080  *    @session_id: session index
2081  *
2082  *  Return:
2083  *       0 for success else failure
2084  *
2085  *  Description:
2086  *       Destroy the encoding session
2087  *
2088  **/
mm_jpeg_destroy_session_by_id(mm_jpeg_obj * my_obj,uint32_t session_id)2089 int32_t mm_jpeg_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id)
2090 {
2091   mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id);
2092 
2093   return mm_jpeg_destroy_session(my_obj, p_session);
2094 }
2095 
2096 /** mm_jpeg_close:
2097  *
2098  *  Arguments:
2099  *    @my_obj: jpeg object
2100  *    @client_hdl: client handle
2101  *
2102  *  Return:
2103  *       0 for success else failure
2104  *
2105  *  Description:
2106  *       Close the jpeg client
2107  *
2108  **/
mm_jpeg_close(mm_jpeg_obj * my_obj,uint32_t client_hdl)2109 int32_t mm_jpeg_close(mm_jpeg_obj *my_obj, uint32_t client_hdl)
2110 {
2111   int32_t rc = -1;
2112   uint8_t clnt_idx = 0;
2113   mm_jpeg_job_q_node_t *node = NULL;
2114   OMX_BOOL ret = OMX_FALSE;
2115   int i = 0;
2116 
2117   /* check if valid client */
2118   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
2119   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
2120     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
2121     return rc;
2122   }
2123 
2124   CDBG("%s:%d] E", __func__, __LINE__);
2125 
2126   /* abort all jobs from the client */
2127   pthread_mutex_lock(&my_obj->job_lock);
2128 
2129   CDBG("%s:%d] ", __func__, __LINE__);
2130 
2131   for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
2132     if (OMX_TRUE == my_obj->clnt_mgr[clnt_idx].session[i].active)
2133       mm_jpeg_destroy_session_unlocked(my_obj,
2134         &my_obj->clnt_mgr[clnt_idx].session[i]);
2135   }
2136 
2137   CDBG("%s:%d] ", __func__, __LINE__);
2138 
2139   pthread_mutex_unlock(&my_obj->job_lock);
2140   CDBG("%s:%d] ", __func__, __LINE__);
2141 
2142   /* invalidate client session */
2143   pthread_mutex_destroy(&my_obj->clnt_mgr[clnt_idx].lock);
2144   memset(&my_obj->clnt_mgr[clnt_idx], 0, sizeof(mm_jpeg_client_t));
2145 
2146   rc = 0;
2147   CDBG("%s:%d] X", __func__, __LINE__);
2148   return rc;
2149 }
2150 
mm_jpeg_ebd(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_BUFFERHEADERTYPE * pBuffer)2151 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
2152   OMX_PTR pAppData,
2153   OMX_BUFFERHEADERTYPE *pBuffer)
2154 {
2155   OMX_ERRORTYPE ret = OMX_ErrorNone;
2156   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
2157 
2158   CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count);
2159   pthread_mutex_lock(&p_session->lock);
2160   p_session->ebd_count++;
2161   pthread_mutex_unlock(&p_session->lock);
2162   return 0;
2163 }
2164 
mm_jpeg_fbd(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_BUFFERHEADERTYPE * pBuffer)2165 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent,
2166   OMX_PTR pAppData,
2167   OMX_BUFFERHEADERTYPE *pBuffer)
2168 {
2169   OMX_ERRORTYPE ret = OMX_ErrorNone;
2170   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
2171   uint32_t i = 0;
2172   int rc = 0;
2173   mm_jpeg_output_t output_buf;
2174 
2175   CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count);
2176 
2177   if (OMX_TRUE == p_session->abort_flag) {
2178     pthread_cond_signal(&p_session->cond);
2179     return ret;
2180   }
2181 
2182   pthread_mutex_lock(&p_session->lock);
2183   p_session->fbd_count++;
2184   if (NULL != p_session->params.jpeg_cb) {
2185     p_session->job_status = JPEG_JOB_STATUS_DONE;
2186     output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen;
2187     output_buf.buf_vaddr = pBuffer->pBuffer;
2188     output_buf.fd = 0;
2189     CDBG("%s:%d] send jpeg callback %d", __func__, __LINE__,
2190       p_session->job_status);
2191     p_session->params.jpeg_cb(p_session->job_status,
2192       p_session->client_hdl,
2193       p_session->jobId,
2194       &output_buf,
2195       p_session->params.userdata);
2196 
2197     /* remove from ready queue */
2198     mm_jpeg_job_done(p_session);
2199   }
2200   pthread_mutex_unlock(&p_session->lock);
2201   CDBG("%s:%d] ", __func__, __LINE__);
2202 
2203   return ret;
2204 }
2205 
mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_EVENTTYPE eEvent,OMX_U32 nData1,OMX_U32 nData2,OMX_PTR pEventData)2206 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,
2207   OMX_PTR pAppData,
2208   OMX_EVENTTYPE eEvent,
2209   OMX_U32 nData1,
2210   OMX_U32 nData2,
2211   OMX_PTR pEventData)
2212 {
2213   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
2214 
2215   CDBG("%s:%d] %d %d %d", __func__, __LINE__, eEvent, (int)nData1,
2216     (int)nData2);
2217 
2218   pthread_mutex_lock(&p_session->lock);
2219 
2220   if (OMX_TRUE == p_session->abort_flag) {
2221     pthread_cond_signal(&p_session->cond);
2222     pthread_mutex_unlock(&p_session->lock);
2223     return OMX_ErrorNone;
2224   }
2225 
2226   if (eEvent == OMX_EventError) {
2227     p_session->error_flag = OMX_ErrorHardware;
2228     if (p_session->encoding == OMX_TRUE) {
2229       CDBG("%s:%d] Error during encoding", __func__, __LINE__);
2230 
2231       /* send jpeg callback */
2232       if (NULL != p_session->params.jpeg_cb) {
2233         p_session->job_status = JPEG_JOB_STATUS_ERROR;
2234         CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
2235           p_session->job_status);
2236         p_session->params.jpeg_cb(p_session->job_status,
2237           p_session->client_hdl,
2238           p_session->jobId,
2239           NULL,
2240           p_session->params.userdata);
2241       }
2242 
2243       /* remove from ready queue */
2244       mm_jpeg_job_done(p_session);
2245     }
2246     pthread_cond_signal(&p_session->cond);
2247   } else if (eEvent == OMX_EventCmdComplete) {
2248     if (p_session->state_change_pending == OMX_TRUE) {
2249       p_session->state_change_pending = OMX_FALSE;
2250       pthread_cond_signal(&p_session->cond);
2251     }
2252   }
2253 
2254   pthread_mutex_unlock(&p_session->lock);
2255   CDBG("%s:%d]", __func__, __LINE__);
2256   return OMX_ErrorNone;
2257 }
2258 
2259 /* remove the first job from the queue with matching client handle */
mm_jpeg_queue_remove_job_by_client_id(mm_jpeg_queue_t * queue,uint32_t client_hdl)2260 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id(
2261   mm_jpeg_queue_t* queue, uint32_t client_hdl)
2262 {
2263   mm_jpeg_q_node_t* node = NULL;
2264   mm_jpeg_job_q_node_t* data = NULL;
2265   mm_jpeg_job_q_node_t* job_node = NULL;
2266   struct cam_list *head = NULL;
2267   struct cam_list *pos = NULL;
2268 
2269   pthread_mutex_lock(&queue->lock);
2270   head = &queue->head.list;
2271   pos = head->next;
2272   while(pos != head) {
2273     node = member_of(pos, mm_jpeg_q_node_t, list);
2274     data = (mm_jpeg_job_q_node_t *)node->data;
2275 
2276     if (data && (data->enc_info.client_handle == client_hdl)) {
2277       CDBG_ERROR("%s:%d] found matching client handle", __func__, __LINE__);
2278       job_node = data;
2279       cam_list_del_node(&node->list);
2280       queue->size--;
2281       free(node);
2282       CDBG_ERROR("%s: queue size = %d", __func__, queue->size);
2283       break;
2284     }
2285     pos = pos->next;
2286   }
2287 
2288   pthread_mutex_unlock(&queue->lock);
2289 
2290   return job_node;
2291 }
2292 
2293 /* remove the first job from the queue with matching session id */
mm_jpeg_queue_remove_job_by_session_id(mm_jpeg_queue_t * queue,uint32_t session_id)2294 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id(
2295   mm_jpeg_queue_t* queue, uint32_t session_id)
2296 {
2297   mm_jpeg_q_node_t* node = NULL;
2298   mm_jpeg_job_q_node_t* data = NULL;
2299   mm_jpeg_job_q_node_t* job_node = NULL;
2300   struct cam_list *head = NULL;
2301   struct cam_list *pos = NULL;
2302 
2303   pthread_mutex_lock(&queue->lock);
2304   head = &queue->head.list;
2305   pos = head->next;
2306   while(pos != head) {
2307     node = member_of(pos, mm_jpeg_q_node_t, list);
2308     data = (mm_jpeg_job_q_node_t *)node->data;
2309 
2310     if (data && (data->enc_info.encode_job.session_id == session_id)) {
2311       CDBG_ERROR("%s:%d] found matching session id", __func__, __LINE__);
2312       job_node = data;
2313       cam_list_del_node(&node->list);
2314       queue->size--;
2315       free(node);
2316       CDBG_ERROR("%s: queue size = %d", __func__, queue->size);
2317       break;
2318     }
2319     pos = pos->next;
2320   }
2321 
2322   pthread_mutex_unlock(&queue->lock);
2323 
2324   return job_node;
2325 }
2326 
2327 /* remove job from the queue with matching job id */
mm_jpeg_queue_remove_job_by_job_id(mm_jpeg_queue_t * queue,uint32_t job_id)2328 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id(
2329   mm_jpeg_queue_t* queue, uint32_t job_id)
2330 {
2331   mm_jpeg_q_node_t* node = NULL;
2332   mm_jpeg_job_q_node_t* data = NULL;
2333   mm_jpeg_job_q_node_t* job_node = NULL;
2334   struct cam_list *head = NULL;
2335   struct cam_list *pos = NULL;
2336 
2337   pthread_mutex_lock(&queue->lock);
2338   head = &queue->head.list;
2339   pos = head->next;
2340   while(pos != head) {
2341     node = member_of(pos, mm_jpeg_q_node_t, list);
2342     data = (mm_jpeg_job_q_node_t *)node->data;
2343 
2344     if (data && (data->enc_info.job_id == job_id)) {
2345       CDBG_ERROR("%s:%d] found matching job id", __func__, __LINE__);
2346       job_node = data;
2347       cam_list_del_node(&node->list);
2348       queue->size--;
2349       free(node);
2350       break;
2351     }
2352     pos = pos->next;
2353   }
2354 
2355   pthread_mutex_unlock(&queue->lock);
2356 
2357   return job_node;
2358 }
2359 
2360 /* remove job from the queue with matching job id */
mm_jpeg_queue_remove_job_unlk(mm_jpeg_queue_t * queue,uint32_t job_id)2361 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_unlk(
2362   mm_jpeg_queue_t* queue, uint32_t job_id)
2363 {
2364   mm_jpeg_q_node_t* node = NULL;
2365   mm_jpeg_job_q_node_t* data = NULL;
2366   mm_jpeg_job_q_node_t* job_node = NULL;
2367   struct cam_list *head = NULL;
2368   struct cam_list *pos = NULL;
2369 
2370   head = &queue->head.list;
2371   pos = head->next;
2372   while(pos != head) {
2373     node = member_of(pos, mm_jpeg_q_node_t, list);
2374     data = (mm_jpeg_job_q_node_t *)node->data;
2375 
2376     if (data && (data->enc_info.job_id == job_id)) {
2377       job_node = data;
2378       cam_list_del_node(&node->list);
2379       queue->size--;
2380       free(node);
2381       break;
2382     }
2383     pos = pos->next;
2384   }
2385 
2386   return job_node;
2387 }
2388