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