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 #define ATRACE_TAG ATRACE_TAG_CAMERA
31 
32 #include <pthread.h>
33 #include <errno.h>
34 #include <sys/ioctl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/prctl.h>
38 #include <fcntl.h>
39 #include <poll.h>
40 #include <cutils/trace.h>
41 #include <math.h>
42 
43 #include "mm_jpeg_dbg.h"
44 #include "mm_jpeg_interface.h"
45 #include "mm_jpeg.h"
46 #include "mm_jpeg_inlines.h"
47 
48 #ifdef LOAD_ADSP_RPC_LIB
49 #include <dlfcn.h>
50 #include <stdlib.h>
51 #endif
52 
53 #define ENCODING_MODE_PARALLEL 1
54 
55 #define META_KEYFILE QCAMERA_DUMP_FRM_LOCATION"metadata.key"
56 
57 /**
58  * minimal resolution needed for normal mode of ops
59  */
60 #define MM_JPEG_MIN_NOM_RESOLUTION 7680000 /*8MP*/
61 
62 #ifdef MM_JPEG_USE_PIPELINE
63 #undef MM_JPEG_CONCURRENT_SESSIONS_COUNT
64 #define MM_JPEG_CONCURRENT_SESSIONS_COUNT 1
65 #endif
66 
67 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
68     OMX_PTR pAppData,
69     OMX_BUFFERHEADERTYPE* pBuffer);
70 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent,
71     OMX_PTR pAppData,
72     OMX_BUFFERHEADERTYPE* pBuffer);
73 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,
74     OMX_PTR pAppData,
75     OMX_EVENTTYPE eEvent,
76     OMX_U32 nData1,
77     OMX_U32 nData2,
78     OMX_PTR pEventData);
79 
80 static int32_t mm_jpegenc_destroy_job(mm_jpeg_job_session_t *p_session);
81 static void mm_jpegenc_job_done(mm_jpeg_job_session_t *p_session);
82 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_dst_ptr(
83   mm_jpeg_queue_t* queue, void * dst_ptr);
84 static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session);
85 
86 /** mm_jpeg_session_send_buffers:
87  *
88  *  Arguments:
89  *    @data: job session
90  *
91  *  Return:
92  *       OMX error values
93  *
94  *  Description:
95  *       Send the buffers to OMX layer
96  *
97  **/
mm_jpeg_session_send_buffers(void * data)98 OMX_ERRORTYPE mm_jpeg_session_send_buffers(void *data)
99 {
100   uint32_t i = 0;
101   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
102   OMX_ERRORTYPE ret = OMX_ErrorNone;
103   QOMX_BUFFER_INFO lbuffer_info;
104   mm_jpeg_encode_params_t *p_params = &p_session->params;
105 
106   memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
107   for (i = 0; i < p_params->num_src_bufs; i++) {
108     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
109     lbuffer_info.fd = (OMX_U32)p_params->src_main_buf[i].fd;
110     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0,
111       &lbuffer_info, p_params->src_main_buf[i].buf_size,
112       p_params->src_main_buf[i].buf_vaddr);
113     if (ret) {
114       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
115       return ret;
116     }
117   }
118 
119   for (i = 0; i < p_params->num_tmb_bufs; i++) {
120     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
121     lbuffer_info.fd = (OMX_U32)p_params->src_thumb_buf[i].fd;
122     ret = OMX_UseBuffer(p_session->omx_handle,
123         &(p_session->p_in_omx_thumb_buf[i]), 2,
124         &lbuffer_info, p_params->src_thumb_buf[i].buf_size,
125         p_params->src_thumb_buf[i].buf_vaddr);
126     if (ret) {
127       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
128       return ret;
129     }
130   }
131 
132   for (i = 0; i < p_params->num_dst_bufs; i++) {
133     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
134     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]),
135       1, NULL, p_params->dest_buf[i].buf_size,
136       p_params->dest_buf[i].buf_vaddr);
137     if (ret) {
138       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
139       return ret;
140     }
141   }
142   CDBG("%s:%d]", __func__, __LINE__);
143   return ret;
144 }
145 
146 
147 /** mm_jpeg_session_free_buffers:
148  *
149  *  Arguments:
150  *    @data: job session
151  *
152  *  Return:
153  *       OMX error values
154  *
155  *  Description:
156  *       Free the buffers from OMX layer
157  *
158  **/
mm_jpeg_session_free_buffers(void * data)159 OMX_ERRORTYPE mm_jpeg_session_free_buffers(void *data)
160 {
161   OMX_ERRORTYPE ret = OMX_ErrorNone;
162   uint32_t i = 0;
163   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
164   mm_jpeg_encode_params_t *p_params = &p_session->params;
165 
166   for (i = 0; i < p_params->num_src_bufs; i++) {
167     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
168     ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]);
169     if (ret) {
170       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
171       return ret;
172     }
173   }
174 
175   for (i = 0; i < p_params->num_tmb_bufs; i++) {
176     CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
177     ret = OMX_FreeBuffer(p_session->omx_handle, 2, p_session->p_in_omx_thumb_buf[i]);
178     if (ret) {
179       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
180       return ret;
181     }
182   }
183 
184   for (i = 0; i < p_params->num_dst_bufs; i++) {
185     CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
186     ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]);
187     if (ret) {
188       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
189       return ret;
190     }
191   }
192   CDBG("%s:%d]", __func__, __LINE__);
193   return ret;
194 }
195 
196 
197 
198 
199 /** mm_jpeg_session_change_state:
200  *
201  *  Arguments:
202  *    @p_session: job session
203  *    @new_state: new state to be transitioned to
204  *    @p_exec: transition function
205  *
206  *  Return:
207  *       OMX error values
208  *
209  *  Description:
210  *       This method is used for state transition
211  *
212  **/
mm_jpeg_session_change_state(mm_jpeg_job_session_t * p_session,OMX_STATETYPE new_state,mm_jpeg_transition_func_t p_exec)213 OMX_ERRORTYPE mm_jpeg_session_change_state(mm_jpeg_job_session_t* p_session,
214   OMX_STATETYPE new_state,
215   mm_jpeg_transition_func_t p_exec)
216 {
217   OMX_ERRORTYPE ret = OMX_ErrorNone;
218   OMX_STATETYPE current_state;
219   CDBG("%s:%d] new_state %d p_exec %p", __func__, __LINE__,
220     new_state, p_exec);
221 
222 
223   pthread_mutex_lock(&p_session->lock);
224 
225   ret = OMX_GetState(p_session->omx_handle, &current_state);
226 
227   if (ret) {
228     pthread_mutex_unlock(&p_session->lock);
229     return ret;
230   }
231 
232   if (current_state == new_state) {
233     pthread_mutex_unlock(&p_session->lock);
234     return OMX_ErrorNone;
235   }
236 
237   p_session->state_change_pending = OMX_TRUE;
238   pthread_mutex_unlock(&p_session->lock);
239   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
240     new_state, NULL);
241   pthread_mutex_lock(&p_session->lock);
242   if (ret) {
243     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
244     pthread_mutex_unlock(&p_session->lock);
245     return OMX_ErrorIncorrectStateTransition;
246   }
247   CDBG("%s:%d] ", __func__, __LINE__);
248   if ((OMX_ErrorNone != p_session->error_flag) &&
249       (OMX_ErrorOverflow != p_session->error_flag)) {
250     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, p_session->error_flag);
251     pthread_mutex_unlock(&p_session->lock);
252     return p_session->error_flag;
253   }
254   if (p_exec) {
255     ret = p_exec(p_session);
256     if (ret) {
257       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
258       pthread_mutex_unlock(&p_session->lock);
259       return ret;
260     }
261   }
262   CDBG("%s:%d] ", __func__, __LINE__);
263   if (p_session->state_change_pending) {
264     CDBG("%s:%d] before wait", __func__, __LINE__);
265     pthread_cond_wait(&p_session->cond, &p_session->lock);
266     CDBG("%s:%d] after wait", __func__, __LINE__);
267   }
268   pthread_mutex_unlock(&p_session->lock);
269   CDBG("%s:%d] ", __func__, __LINE__);
270   return ret;
271 }
272 
273 /** mm_jpeg_session_create:
274  *
275  *  Arguments:
276  *    @p_session: job session
277  *
278  *  Return:
279  *       OMX error types
280  *
281  *  Description:
282  *       Create a jpeg encode session
283  *
284  **/
mm_jpeg_session_create(mm_jpeg_job_session_t * p_session)285 OMX_ERRORTYPE mm_jpeg_session_create(mm_jpeg_job_session_t* p_session)
286 {
287   OMX_ERRORTYPE rc = OMX_ErrorNone;
288   mm_jpeg_obj *my_obj = (mm_jpeg_obj *) p_session->jpeg_obj;
289   char *omx_lib = "OMX.qcom.image.jpeg.encoder";
290 
291   pthread_mutex_init(&p_session->lock, NULL);
292   pthread_cond_init(&p_session->cond, NULL);
293   cirq_reset(&p_session->cb_q);
294   p_session->state_change_pending = OMX_FALSE;
295   p_session->abort_state = MM_JPEG_ABORT_NONE;
296   p_session->error_flag = OMX_ErrorNone;
297   p_session->ebd_count = 0;
298   p_session->fbd_count = 0;
299   p_session->encode_pid = -1;
300   p_session->config = OMX_FALSE;
301   p_session->exif_count_local = 0;
302   p_session->auto_out_buf = OMX_FALSE;
303 
304   p_session->omx_callbacks.EmptyBufferDone = mm_jpeg_ebd;
305   p_session->omx_callbacks.FillBufferDone = mm_jpeg_fbd;
306   p_session->omx_callbacks.EventHandler = mm_jpeg_event_handler;
307 
308   p_session->thumb_from_main = 0;
309 #ifdef MM_JPEG_USE_PIPELINE
310   p_session->thumb_from_main = 1;
311   omx_lib = "OMX.qcom.image.jpeg.encoder_pipeline";
312 #endif
313 
314   rc = OMX_GetHandle(&p_session->omx_handle,
315       omx_lib,
316       (void *)p_session,
317       &p_session->omx_callbacks);
318   if (OMX_ErrorNone != rc) {
319     CDBG_ERROR("%s:%d] OMX_GetHandle failed (%d)", __func__, __LINE__, rc);
320     return rc;
321   }
322 
323   my_obj->num_sessions++;
324 
325   return rc;
326 }
327 
328 
329 
330 /** mm_jpeg_session_destroy:
331  *
332  *  Arguments:
333  *    @p_session: job session
334  *
335  *  Return:
336  *       none
337  *
338  *  Description:
339  *       Destroy a jpeg encode session
340  *
341  **/
mm_jpeg_session_destroy(mm_jpeg_job_session_t * p_session)342 void mm_jpeg_session_destroy(mm_jpeg_job_session_t* p_session)
343 {
344   OMX_ERRORTYPE rc = OMX_ErrorNone;
345   OMX_STATETYPE state;
346   mm_jpeg_obj *my_obj = (mm_jpeg_obj *) p_session->jpeg_obj;
347 
348   CDBG("%s:%d] E", __func__, __LINE__);
349   if (NULL == p_session->omx_handle) {
350     CDBG_ERROR("%s:%d] invalid handle", __func__, __LINE__);
351     return;
352   }
353 
354   rc = OMX_GetState(p_session->omx_handle, &state);
355 
356   //Check state before state transition
357   if ((state == OMX_StateExecuting) || (state == OMX_StatePause)) {
358     rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL);
359     if (rc) {
360       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
361     }
362   }
363 
364   rc = OMX_GetState(p_session->omx_handle, &state);
365 
366   if (state == OMX_StateIdle) {
367     rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded,
368       mm_jpeg_session_free_buffers);
369     if (rc) {
370       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
371     }
372   }
373 
374   rc = OMX_FreeHandle(p_session->omx_handle);
375   if (0 != rc) {
376     CDBG_ERROR("%s:%d] OMX_FreeHandle failed (%d)", __func__, __LINE__, rc);
377   }
378   p_session->omx_handle = NULL;
379 
380   pthread_mutex_destroy(&p_session->lock);
381   pthread_cond_destroy(&p_session->cond);
382 
383   if (NULL != p_session->meta_enc_key) {
384     free(p_session->meta_enc_key);
385     p_session->meta_enc_key = NULL;
386   }
387 
388   my_obj->num_sessions--;
389 
390   // Destroy next session
391   if (p_session->next_session) {
392     mm_jpeg_session_destroy(p_session->next_session);
393   }
394 
395   CDBG_HIGH("%s:%d] Session destroy successful. X", __func__, __LINE__);
396 }
397 
398 
399 
400 /** mm_jpeg_session_config_main_buffer_offset:
401  *
402  *  Arguments:
403  *    @p_session: job session
404  *
405  *  Return:
406  *       OMX error values
407  *
408  *  Description:
409  *       Configure the buffer offsets
410  *
411  **/
mm_jpeg_session_config_main_buffer_offset(mm_jpeg_job_session_t * p_session)412 OMX_ERRORTYPE mm_jpeg_session_config_main_buffer_offset(
413   mm_jpeg_job_session_t* p_session)
414 {
415   OMX_ERRORTYPE rc = 0;
416   OMX_INDEXTYPE buffer_index;
417   QOMX_YUV_FRAME_INFO frame_info;
418   size_t totalSize = 0;
419   mm_jpeg_encode_params_t *p_params = &p_session->params;
420 
421   mm_jpeg_buf_t *p_src_buf =
422     &p_params->src_main_buf[0];
423 
424   memset(&frame_info, 0x0, sizeof(QOMX_YUV_FRAME_INFO));
425 
426   frame_info.cbcrStartOffset[0] = p_src_buf->offset.mp[0].len;
427   frame_info.cbcrStartOffset[1] = p_src_buf->offset.mp[1].len;
428   frame_info.yOffset = p_src_buf->offset.mp[0].offset;
429   frame_info.cbcrOffset[0] = p_src_buf->offset.mp[1].offset;
430   frame_info.cbcrOffset[1] = p_src_buf->offset.mp[2].offset;
431   totalSize = p_src_buf->buf_size;
432 
433   rc = OMX_GetExtensionIndex(p_session->omx_handle,
434     QOMX_IMAGE_EXT_BUFFER_OFFSET_NAME, &buffer_index);
435   if (rc != OMX_ErrorNone) {
436     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
437     return rc;
438   }
439 
440   CDBG_HIGH("%s:%d] yOffset = %d, cbcrOffset = (%d %d), totalSize = %zd,"
441     "cbcrStartOffset = (%d %d)", __func__, __LINE__,
442     (int)frame_info.yOffset,
443     (int)frame_info.cbcrOffset[0],
444     (int)frame_info.cbcrOffset[1],
445     totalSize,
446     (int)frame_info.cbcrStartOffset[0],
447     (int)frame_info.cbcrStartOffset[1]);
448 
449   rc = OMX_SetParameter(p_session->omx_handle, buffer_index, &frame_info);
450   if (rc != OMX_ErrorNone) {
451     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
452     return rc;
453   }
454   return rc;
455 }
456 
457 /** mm_jpeg_encoding_mode:
458  *
459  *  Arguments:
460  *    @p_session: job session
461  *
462  *  Return:
463  *       OMX error values
464  *
465  *  Description:
466  *       Configure the serial or parallel encoding
467  *       mode
468  *
469  **/
mm_jpeg_encoding_mode(mm_jpeg_job_session_t * p_session)470 OMX_ERRORTYPE mm_jpeg_encoding_mode(
471   mm_jpeg_job_session_t* p_session)
472 {
473   OMX_ERRORTYPE rc = 0;
474   OMX_INDEXTYPE indextype;
475   QOMX_ENCODING_MODE encoding_mode;
476 
477   rc = OMX_GetExtensionIndex(p_session->omx_handle,
478     QOMX_IMAGE_EXT_ENCODING_MODE_NAME, &indextype);
479   if (rc != OMX_ErrorNone) {
480     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
481     return rc;
482   }
483 
484   if (ENCODING_MODE_PARALLEL) {
485     encoding_mode = OMX_Parallel_Encoding;
486   } else {
487     encoding_mode = OMX_Serial_Encoding;
488   }
489   CDBG("%s:%d] encoding mode = %d ", __func__, __LINE__,
490     (int)encoding_mode);
491   rc = OMX_SetParameter(p_session->omx_handle, indextype, &encoding_mode);
492   if (rc != OMX_ErrorNone) {
493     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
494     return rc;
495   }
496   return rc;
497 }
498 
499 /** mm_jpeg_get_speed:
500  *
501  *  Arguments:
502  *    @p_session: job session
503  *
504  *  Return:
505  *       ops speed type for jpeg
506  *
507  *  Description:
508  *      Configure normal or high speed jpeg
509  *
510  **/
mm_jpeg_get_speed(mm_jpeg_job_session_t * p_session)511 QOMX_JPEG_SPEED_MODE mm_jpeg_get_speed(
512   mm_jpeg_job_session_t* p_session)
513 {
514   mm_jpeg_encode_params_t *p_params = &p_session->params;
515   cam_dimension_t *p_dim = &p_params->main_dim.src_dim;
516   if (p_params->burst_mode ||
517     (MM_JPEG_MIN_NOM_RESOLUTION < (p_dim->width * p_dim->height))) {
518     return QOMX_JPEG_SPEED_MODE_HIGH;
519   }
520   return QOMX_JPEG_SPEED_MODE_NORMAL;
521 }
522 
523 /** mm_jpeg_speed_mode:
524  *
525  *  Arguments:
526  *    @p_session: job session
527  *
528  *  Return:
529  *       OMX error values
530  *
531  *  Description:
532  *      Configure normal or high speed jpeg
533  *
534  **/
mm_jpeg_speed_mode(mm_jpeg_job_session_t * p_session)535 OMX_ERRORTYPE mm_jpeg_speed_mode(
536   mm_jpeg_job_session_t* p_session)
537 {
538   OMX_ERRORTYPE rc = 0;
539   OMX_INDEXTYPE indextype;
540   QOMX_JPEG_SPEED jpeg_speed;
541 
542   rc = OMX_GetExtensionIndex(p_session->omx_handle,
543     QOMX_IMAGE_EXT_JPEG_SPEED_NAME, &indextype);
544   if (rc != OMX_ErrorNone) {
545     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
546     return rc;
547   }
548 
549   jpeg_speed.speedMode = mm_jpeg_get_speed(p_session);
550   CDBG_HIGH("%s:%d] speed %d", __func__, __LINE__, jpeg_speed.speedMode);
551 
552   rc = OMX_SetParameter(p_session->omx_handle, indextype, &jpeg_speed);
553   if (rc != OMX_ErrorNone) {
554     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
555     return rc;
556   }
557   return rc;
558 }
559 
560 
561 /** mm_jpeg_mem_ops:
562  *
563  *  Arguments:
564  *    @p_session: job session
565  *
566  *  Return:
567  *       OMX error values
568  *
569  *  Description:
570  *       Configure the serial or parallel encoding
571  *       mode
572  *
573  **/
mm_jpeg_mem_ops(mm_jpeg_job_session_t * p_session)574 OMX_ERRORTYPE mm_jpeg_mem_ops(
575   mm_jpeg_job_session_t* p_session)
576 {
577   OMX_ERRORTYPE rc = 0;
578   OMX_INDEXTYPE indextype;
579   QOMX_MEM_OPS mem_ops;
580   mm_jpeg_encode_params_t *p_params = &p_session->params;
581 
582   mem_ops.get_memory = p_params->get_memory;
583 
584   rc = OMX_GetExtensionIndex(p_session->omx_handle,
585     QOMX_IMAGE_EXT_MEM_OPS_NAME, &indextype);
586   if (rc != OMX_ErrorNone) {
587     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
588     return rc;
589   }
590 
591   rc = OMX_SetParameter(p_session->omx_handle, indextype, &mem_ops);
592   if (rc != OMX_ErrorNone) {
593     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
594     return rc;
595   }
596   return rc;
597 }
598 
599 /** mm_jpeg_metadata:
600  *
601  *  Arguments:
602  *    @p_session: job session
603  *
604  *  Return:
605  *       OMX error values
606  *
607  *  Description:
608  *       Pass meta data
609  *
610  **/
mm_jpeg_metadata(mm_jpeg_job_session_t * p_session)611 OMX_ERRORTYPE mm_jpeg_metadata(
612   mm_jpeg_job_session_t* p_session)
613 {
614   OMX_ERRORTYPE rc = OMX_ErrorNone;
615   OMX_INDEXTYPE indexType;
616   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
617   QOMX_METADATA lMeta;
618 
619   rc = OMX_GetExtensionIndex(p_session->omx_handle,
620       QOMX_IMAGE_EXT_METADATA_NAME, &indexType);
621 
622   if (rc != OMX_ErrorNone) {
623     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
624     return rc;
625   }
626 
627   lMeta.metadata = (OMX_U8 *)p_jobparams->p_metadata;
628   lMeta.metaPayloadSize = sizeof(*p_jobparams->p_metadata);
629   lMeta.mobicat_mask = p_jobparams->mobicat_mask;
630 
631   rc = OMX_SetConfig(p_session->omx_handle, indexType, &lMeta);
632   if (rc != OMX_ErrorNone) {
633     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
634     return rc;
635   }
636   return OMX_ErrorNone;
637 }
638 
639 /** mm_jpeg_meta_enc_key:
640  *
641  *  Arguments:
642  *    @p_session: job session
643  *
644  *  Return:
645  *       OMX error values
646  *
647  *  Description:
648  *       Pass metadata encrypt key
649  *
650  **/
mm_jpeg_meta_enc_key(mm_jpeg_job_session_t * p_session)651 OMX_ERRORTYPE mm_jpeg_meta_enc_key(
652   mm_jpeg_job_session_t* p_session)
653 {
654   OMX_ERRORTYPE rc = OMX_ErrorNone;
655   OMX_INDEXTYPE indexType;
656   QOMX_META_ENC_KEY lKey;
657 
658   lKey.metaKey = p_session->meta_enc_key;
659   lKey.keyLen = p_session->meta_enc_keylen;
660 
661   if ((!lKey.metaKey) || (!lKey.keyLen)){
662     CDBG_ERROR("%s:%d] Key is invalid", __func__, __LINE__);
663     return OMX_ErrorNone;
664   }
665 
666   rc = OMX_GetExtensionIndex(p_session->omx_handle,
667       QOMX_IMAGE_EXT_META_ENC_KEY_NAME, &indexType);
668 
669   if (rc != OMX_ErrorNone) {
670     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
671     return rc;
672   }
673 
674   rc = OMX_SetConfig(p_session->omx_handle, indexType, &lKey);
675   if (rc != OMX_ErrorNone) {
676     CDBG_ERROR("%s:%d] Failed", __func__, __LINE__);
677     return rc;
678   }
679   return OMX_ErrorNone;
680 }
681 
682 /** map_jpeg_format:
683  *
684  *  Arguments:
685  *    @color_fmt: color format
686  *
687  *  Return:
688  *       OMX color format
689  *
690  *  Description:
691  *       Map mmjpeg color format to OMX color format
692  *
693  **/
map_jpeg_format(mm_jpeg_color_format color_fmt)694 int map_jpeg_format(mm_jpeg_color_format color_fmt)
695 {
696   switch (color_fmt) {
697   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2:
698     return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar;
699   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2:
700     return (int)OMX_COLOR_FormatYUV420SemiPlanar;
701   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1:
702     return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar;
703   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1:
704     return (int)OMX_COLOR_FormatYUV422SemiPlanar;
705   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2:
706     return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar_h1v2;
707   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2:
708     return (int)OMX_QCOM_IMG_COLOR_FormatYUV422SemiPlanar_h1v2;
709   case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1:
710     return (int)OMX_QCOM_IMG_COLOR_FormatYVU444SemiPlanar;
711   case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1:
712     return (int)OMX_QCOM_IMG_COLOR_FormatYUV444SemiPlanar;
713   case MM_JPEG_COLOR_FORMAT_MONOCHROME:
714      return (int)OMX_COLOR_FormatMonochrome;
715   default:
716     CDBG_ERROR("%s:%d] invalid format %d", __func__, __LINE__, color_fmt);
717     return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar;
718   }
719 }
720 
721 /** mm_jpeg_session_config_port:
722  *
723  *  Arguments:
724  *    @p_session: job session
725  *
726  *  Return:
727  *       OMX error values
728  *
729  *  Description:
730  *       Configure OMX ports
731  *
732  **/
mm_jpeg_session_config_ports(mm_jpeg_job_session_t * p_session)733 OMX_ERRORTYPE mm_jpeg_session_config_ports(mm_jpeg_job_session_t* p_session)
734 {
735   OMX_ERRORTYPE ret = OMX_ErrorNone;
736   mm_jpeg_encode_params_t *p_params = &p_session->params;
737   OMX_CONFIG_ROTATIONTYPE rotate;
738 
739   mm_jpeg_buf_t *p_src_buf =
740     &p_params->src_main_buf[0];
741 
742   p_session->inputPort.nPortIndex = 0;
743   p_session->outputPort.nPortIndex = 1;
744   p_session->inputTmbPort.nPortIndex = 2;
745 
746   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
747     &p_session->inputPort);
748   if (ret) {
749     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
750     return ret;
751   }
752 
753   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
754     &p_session->inputTmbPort);
755   if (ret) {
756     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
757     return ret;
758   }
759 
760   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
761     &p_session->outputPort);
762   if (ret) {
763     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
764     return ret;
765   }
766 
767   p_session->inputPort.format.image.nFrameWidth =
768     (OMX_U32)p_params->main_dim.src_dim.width;
769   p_session->inputPort.format.image.nFrameHeight =
770     (OMX_U32)p_params->main_dim.src_dim.height;
771   p_session->inputPort.format.image.nStride =
772     p_src_buf->offset.mp[0].stride;
773   p_session->inputPort.format.image.nSliceHeight =
774     (OMX_U32)p_src_buf->offset.mp[0].scanline;
775   p_session->inputPort.format.image.eColorFormat =
776     map_jpeg_format(p_params->color_format);
777   p_session->inputPort.nBufferSize =
778     p_params->src_main_buf[0/*p_jobparams->src_index*/].buf_size;
779   p_session->inputPort.nBufferCountActual = (OMX_U32)p_params->num_src_bufs;
780   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
781     &p_session->inputPort);
782   if (ret) {
783     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
784     return ret;
785   }
786 
787   if (p_session->params.encode_thumbnail) {
788     mm_jpeg_buf_t *p_tmb_buf =
789       &p_params->src_thumb_buf[0];
790     p_session->inputTmbPort.format.image.nFrameWidth =
791       (OMX_U32)p_params->thumb_dim.src_dim.width;
792     p_session->inputTmbPort.format.image.nFrameHeight =
793       (OMX_U32)p_params->thumb_dim.src_dim.height;
794     p_session->inputTmbPort.format.image.nStride =
795       p_tmb_buf->offset.mp[0].stride;
796     p_session->inputTmbPort.format.image.nSliceHeight =
797       (OMX_U32)p_tmb_buf->offset.mp[0].scanline;
798     p_session->inputTmbPort.format.image.eColorFormat =
799       map_jpeg_format(p_params->thumb_color_format);
800     p_session->inputTmbPort.nBufferSize =
801       p_params->src_thumb_buf[0].buf_size;
802     p_session->inputTmbPort.nBufferCountActual = (OMX_U32)p_params->num_tmb_bufs;
803 
804     ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
805       &p_session->inputTmbPort);
806 
807     if (ret) {
808       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
809       return ret;
810     }
811 
812     // Enable thumbnail port
813     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable,
814         p_session->inputTmbPort.nPortIndex, NULL);
815 
816     if (ret) {
817       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
818       return ret;
819     }
820   } else {
821     // Disable thumbnail port
822     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable,
823         p_session->inputTmbPort.nPortIndex, NULL);
824 
825     if (ret) {
826       CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
827       return ret;
828     }
829   }
830 
831   p_session->outputPort.nBufferSize =
832     p_params->dest_buf[0].buf_size;
833   p_session->outputPort.nBufferCountActual = (OMX_U32)p_params->num_dst_bufs;
834   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
835     &p_session->outputPort);
836   if (ret) {
837     CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
838     return ret;
839   }
840 
841   /* set rotation */
842   memset(&rotate, 0, sizeof(rotate));
843   rotate.nPortIndex = 1;
844   rotate.nRotation = (OMX_S32)p_params->rotation;
845   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate,
846       &rotate);
847   if (OMX_ErrorNone != ret) {
848     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
849     return ret;
850   }
851   CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__,
852       (int)p_params->rotation, (int)rotate.nPortIndex);
853 
854   return ret;
855 }
856 
857 /** mm_jpeg_get_thumbnail_crop
858  *
859  *  Arguments:
860  *    @p_thumb_dim: thumbnail dimension
861  *    @p_main_dim: main image dimension
862  *    @crop_width : flag indicating if width needs to be cropped
863  *
864  *  Return:
865  *       OMX error values
866  *
867  *  Description:
868  *    If the main image and thumbnail ascpect ratios are differnt,
869  *    re-calculate the thumbnail crop info to prevent distortion
870  *
871  */
mm_jpeg_get_thumbnail_crop(mm_jpeg_dim_t * p_thumb_dim,mm_jpeg_dim_t * p_main_dim,uint8_t crop_width)872 OMX_ERRORTYPE mm_jpeg_get_thumbnail_crop(mm_jpeg_dim_t *p_thumb_dim,
873   mm_jpeg_dim_t *p_main_dim, uint8_t crop_width) {
874   OMX_ERRORTYPE ret = OMX_ErrorNone;
875   int cropped_width = 0, cropped_height = 0;
876 
877   if (crop_width) {
878    //Keep height constant
879    cropped_height = p_thumb_dim->src_dim.height;
880    cropped_width = floor((cropped_height * p_thumb_dim->dst_dim.width) /
881       p_thumb_dim->dst_dim.height);
882   } else {
883     //Keep width constant
884     cropped_width = p_thumb_dim->src_dim.width;
885     cropped_height = floor((cropped_width * p_thumb_dim->dst_dim.height) /
886       p_thumb_dim->dst_dim.width);
887   }
888   p_thumb_dim->crop.left = floor(p_thumb_dim->src_dim.width - cropped_width) / 2;
889   p_thumb_dim->crop.top = floor(p_thumb_dim->src_dim.height - cropped_height) / 2;
890   p_thumb_dim->crop.width = cropped_width;
891   p_thumb_dim->crop.height = cropped_height;
892 
893   CDBG_HIGH("%s %d New thumbnail crop: left %d, top %d, crop width %d, crop height %d",
894     __func__, __LINE__, p_thumb_dim->crop.left, p_thumb_dim->crop.top,
895     p_thumb_dim->crop.width, p_thumb_dim->crop.height);
896 
897   return ret;
898 }
899 
900 /** mm_jpeg_omx_config_thumbnail:
901  *
902  *  Arguments:
903  *    @p_session: job session
904  *
905  *  Return:
906  *       OMX error values
907  *
908  *  Description:
909  *       Configure OMX ports
910  *
911  **/
mm_jpeg_session_config_thumbnail(mm_jpeg_job_session_t * p_session)912 OMX_ERRORTYPE mm_jpeg_session_config_thumbnail(mm_jpeg_job_session_t* p_session)
913 {
914   OMX_ERRORTYPE ret = OMX_ErrorNone;
915   QOMX_THUMBNAIL_INFO thumbnail_info;
916   OMX_INDEXTYPE thumb_indextype;
917   mm_jpeg_encode_params_t *p_params = &p_session->params;
918   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
919   mm_jpeg_dim_t *p_thumb_dim = &p_jobparams->thumb_dim;
920   mm_jpeg_dim_t *p_main_dim = &p_jobparams->main_dim;
921   QOMX_YUV_FRAME_INFO *p_frame_info = &thumbnail_info.tmbOffset;
922   mm_jpeg_buf_t *p_tmb_buf = &p_params->src_thumb_buf[p_jobparams->thumb_index];
923 
924   CDBG_HIGH("%s:%d] encode_thumbnail %u", __func__, __LINE__,
925     p_params->encode_thumbnail);
926   if (OMX_FALSE == p_params->encode_thumbnail) {
927     return ret;
928   }
929 
930   if ((p_thumb_dim->dst_dim.width == 0) || (p_thumb_dim->dst_dim.height == 0)) {
931     CDBG_ERROR("%s:%d] Error invalid output dim for thumbnail",
932       __func__, __LINE__);
933     return OMX_ErrorBadParameter;
934   }
935 
936   if ((p_thumb_dim->src_dim.width == 0) || (p_thumb_dim->src_dim.height == 0)) {
937     CDBG_ERROR("%s:%d] Error invalid input dim for thumbnail",
938       __func__, __LINE__);
939     return OMX_ErrorBadParameter;
940   }
941 
942   if ((p_thumb_dim->crop.width == 0) || (p_thumb_dim->crop.height == 0)) {
943     p_thumb_dim->crop.width = p_thumb_dim->src_dim.width;
944     p_thumb_dim->crop.height = p_thumb_dim->src_dim.height;
945   }
946 
947   /* check crop boundary */
948   if ((p_thumb_dim->crop.width + p_thumb_dim->crop.left > p_thumb_dim->src_dim.width) ||
949     (p_thumb_dim->crop.height + p_thumb_dim->crop.top > p_thumb_dim->src_dim.height)) {
950     CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) offset (%d, %d) out of (%d, %d)",
951       __func__, __LINE__,
952       p_thumb_dim->crop.width,
953       p_thumb_dim->crop.height,
954       p_thumb_dim->crop.left,
955       p_thumb_dim->crop.top,
956       p_thumb_dim->src_dim.width,
957       p_thumb_dim->src_dim.height);
958     return OMX_ErrorBadParameter;
959   }
960 
961   memset(&thumbnail_info, 0x0, sizeof(QOMX_THUMBNAIL_INFO));
962   ret = OMX_GetExtensionIndex(p_session->omx_handle,
963     QOMX_IMAGE_EXT_THUMBNAIL_NAME,
964     &thumb_indextype);
965   if (ret) {
966     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
967     return ret;
968   }
969 
970   /* fill thumbnail info */
971   thumbnail_info.scaling_enabled = 1;
972   thumbnail_info.input_width = (OMX_U32)p_thumb_dim->src_dim.width;
973   thumbnail_info.input_height = (OMX_U32)p_thumb_dim->src_dim.height;
974   thumbnail_info.rotation = (OMX_U32)p_params->thumb_rotation;
975   thumbnail_info.quality = (OMX_U32)p_params->thumb_quality;
976   thumbnail_info.output_width = (OMX_U32)p_thumb_dim->dst_dim.width;
977   thumbnail_info.output_height = (OMX_U32)p_thumb_dim->dst_dim.height;
978 
979   if (p_session->thumb_from_main) {
980     if ((p_session->params.thumb_rotation == 90 ||
981       p_session->params.thumb_rotation == 270) &&
982       (p_session->params.rotation == 0 ||
983       p_session->params.rotation == 180)) {
984 
985       thumbnail_info.output_width = (OMX_U32)p_thumb_dim->dst_dim.height;
986       thumbnail_info.output_height = (OMX_U32)p_thumb_dim->dst_dim.width;
987       thumbnail_info.rotation = p_session->params.rotation;
988     }
989   } else if ((p_thumb_dim->dst_dim.width > p_thumb_dim->src_dim.width) ||
990     (p_thumb_dim->dst_dim.height > p_thumb_dim->src_dim.height)) {
991     CDBG_ERROR("%s:%d] Incorrect thumbnail dim %dx%d resetting to %dx%d",
992       __func__, __LINE__, p_thumb_dim->dst_dim.width,
993       p_thumb_dim->dst_dim.height, p_thumb_dim->src_dim.width,
994       p_thumb_dim->src_dim.height);
995     thumbnail_info.output_width = (OMX_U32)p_thumb_dim->src_dim.width;
996     thumbnail_info.output_height = (OMX_U32)p_thumb_dim->src_dim.height;
997   }
998 
999   //If the main image and thumbnail aspect ratio are different, reset the
1000   // thumbnail crop info to avoid distortion
1001   double main_aspect_ratio = (double)p_main_dim->dst_dim.width /
1002     (double)p_main_dim->dst_dim.height;
1003   double thumb_aspect_ratio = (double)thumbnail_info.output_width /
1004     (double)thumbnail_info.output_height;
1005 
1006   if ((thumb_aspect_ratio - main_aspect_ratio) > ASPECT_TOLERANCE) {
1007     mm_jpeg_get_thumbnail_crop(p_thumb_dim, p_main_dim, 0);
1008   } else if((main_aspect_ratio - thumb_aspect_ratio) > ASPECT_TOLERANCE){
1009     mm_jpeg_get_thumbnail_crop(p_thumb_dim, p_main_dim, 1);
1010   }
1011 
1012   //Fill thumbnail crop info
1013   thumbnail_info.crop_info.nWidth = (OMX_U32)p_thumb_dim->crop.width;
1014   thumbnail_info.crop_info.nHeight = (OMX_U32)p_thumb_dim->crop.height;
1015   thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left;
1016   thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top;
1017 
1018   //If main image cropping/scaling is enabled, thumb FOV should be within
1019   //main image FOV
1020   if ((p_main_dim->crop.width != p_main_dim->src_dim.width) ||
1021     (p_main_dim->crop.height != p_main_dim->src_dim.height)) {
1022     if ((p_thumb_dim->crop.left < p_main_dim->crop.left) ||
1023       ((p_thumb_dim->crop.left + p_thumb_dim->crop.width) >
1024       (p_main_dim->crop.left + p_main_dim->crop.width)) ||
1025       (p_thumb_dim->crop.top < p_main_dim->crop.top) ||
1026       ((p_thumb_dim->crop.top + p_thumb_dim->crop.height) >
1027       (p_main_dim->crop.top + p_main_dim->crop.height))) {
1028        //Reset the FOV for the thumbnail
1029        CDBG_HIGH("%s:%d] Resetting the thumbnail FOV wrt main image",
1030          __func__, __LINE__);
1031        thumbnail_info.crop_info.nLeft = p_main_dim->crop.left;
1032        thumbnail_info.crop_info.nTop = p_main_dim->crop.height;
1033        if ((p_thumb_dim->crop.width > p_main_dim->crop.width) ||
1034          (p_thumb_dim->crop.height > p_main_dim->crop.height)) {
1035          thumbnail_info.crop_info.nWidth = p_main_dim->crop.width;
1036          thumbnail_info.crop_info.nHeight = p_main_dim->crop.height;
1037        }
1038      }
1039   }
1040 
1041   memset(p_frame_info, 0x0, sizeof(*p_frame_info));
1042 
1043   p_frame_info->cbcrStartOffset[0] = p_tmb_buf->offset.mp[0].len;
1044   p_frame_info->cbcrStartOffset[1] = p_tmb_buf->offset.mp[1].len;
1045   p_frame_info->yOffset = p_tmb_buf->offset.mp[0].offset;
1046   p_frame_info->cbcrOffset[0] = p_tmb_buf->offset.mp[1].offset;
1047   p_frame_info->cbcrOffset[1] = p_tmb_buf->offset.mp[2].offset;
1048 
1049   ret = OMX_SetConfig(p_session->omx_handle, thumb_indextype,
1050     &thumbnail_info);
1051   if (ret) {
1052     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1053     return ret;
1054   }
1055 
1056   return ret;
1057 }
1058 
1059 /** mm_jpeg_session_config_main_crop:
1060  *
1061  *  Arguments:
1062  *    @p_session: job session
1063  *
1064  *  Return:
1065  *       OMX error values
1066  *
1067  *  Description:
1068  *       Configure main image crop
1069  *
1070  **/
mm_jpeg_session_config_main_crop(mm_jpeg_job_session_t * p_session)1071 OMX_ERRORTYPE mm_jpeg_session_config_main_crop(mm_jpeg_job_session_t *p_session)
1072 {
1073   OMX_CONFIG_RECTTYPE rect_type_in, rect_type_out;
1074   OMX_ERRORTYPE ret = OMX_ErrorNone;
1075   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
1076   mm_jpeg_dim_t *dim = &p_jobparams->main_dim;
1077 
1078   if ((dim->crop.width == 0) || (dim->crop.height == 0)) {
1079     dim->crop.width = dim->src_dim.width;
1080     dim->crop.height = dim->src_dim.height;
1081   }
1082   /* error check first */
1083   if ((dim->crop.width + dim->crop.left > dim->src_dim.width) ||
1084     (dim->crop.height + dim->crop.top > dim->src_dim.height)) {
1085     CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) out of (%d, %d)",
1086       __func__, __LINE__,
1087       dim->crop.width + dim->crop.left,
1088       dim->crop.height + dim->crop.top,
1089       dim->src_dim.width,
1090       dim->src_dim.height);
1091     return OMX_ErrorBadParameter;
1092   }
1093 
1094   memset(&rect_type_in, 0, sizeof(rect_type_in));
1095   memset(&rect_type_out, 0, sizeof(rect_type_out));
1096   rect_type_in.nPortIndex = 0;
1097   rect_type_out.nPortIndex = 0;
1098 
1099   if ((dim->src_dim.width != dim->crop.width) ||
1100     (dim->src_dim.height != dim->crop.height) ||
1101     (dim->src_dim.width != dim->dst_dim.width) ||
1102     (dim->src_dim.height != dim->dst_dim.height)) {
1103     /* Scaler information */
1104     rect_type_in.nWidth = CEILING2(dim->crop.width);
1105     rect_type_in.nHeight = CEILING2(dim->crop.height);
1106     rect_type_in.nLeft = dim->crop.left;
1107     rect_type_in.nTop = dim->crop.top;
1108 
1109     if (dim->dst_dim.width && dim->dst_dim.height) {
1110       rect_type_out.nWidth = (OMX_U32)dim->dst_dim.width;
1111       rect_type_out.nHeight = (OMX_U32)dim->dst_dim.height;
1112     }
1113   }
1114 
1115   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonInputCrop,
1116     &rect_type_in);
1117   if (OMX_ErrorNone != ret) {
1118     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1119     return ret;
1120   }
1121 
1122   CDBG_HIGH("%s:%d] OMX_IndexConfigCommonInputCrop w = %d, h = %d, l = %d, t = %d,"
1123     " port_idx = %d", __func__, __LINE__,
1124     (int)rect_type_in.nWidth, (int)rect_type_in.nHeight,
1125     (int)rect_type_in.nLeft, (int)rect_type_in.nTop,
1126     (int)rect_type_in.nPortIndex);
1127 
1128   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonOutputCrop,
1129     &rect_type_out);
1130   if (OMX_ErrorNone != ret) {
1131     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1132     return ret;
1133   }
1134   CDBG("%s:%d] OMX_IndexConfigCommonOutputCrop w = %d, h = %d,"
1135     " port_idx = %d", __func__, __LINE__,
1136     (int)rect_type_out.nWidth, (int)rect_type_out.nHeight,
1137     (int)rect_type_out.nPortIndex);
1138 
1139   return ret;
1140 }
1141 
1142 /** mm_jpeg_session_config_main:
1143  *
1144  *  Arguments:
1145  *    @p_session: job session
1146  *
1147  *  Return:
1148  *       OMX error values
1149  *
1150  *  Description:
1151  *       Configure main image
1152  *
1153  **/
mm_jpeg_session_config_main(mm_jpeg_job_session_t * p_session)1154 OMX_ERRORTYPE mm_jpeg_session_config_main(mm_jpeg_job_session_t *p_session)
1155 {
1156   OMX_ERRORTYPE rc = OMX_ErrorNone;
1157 
1158   /* config port */
1159   CDBG_HIGH("%s:%d] config port", __func__, __LINE__);
1160   rc = mm_jpeg_session_config_ports(p_session);
1161   if (OMX_ErrorNone != rc) {
1162     CDBG_ERROR("%s: config port failed", __func__);
1163     return rc;
1164   }
1165 
1166   /* config buffer offset */
1167   CDBG("%s:%d] config main buf offset", __func__, __LINE__);
1168   rc = mm_jpeg_session_config_main_buffer_offset(p_session);
1169   if (OMX_ErrorNone != rc) {
1170     CDBG_ERROR("%s: config buffer offset failed", __func__);
1171     return rc;
1172   }
1173 
1174   /* set the encoding mode */
1175   rc = mm_jpeg_encoding_mode(p_session);
1176   if (OMX_ErrorNone != rc) {
1177     CDBG_ERROR("%s: config encoding mode failed", __func__);
1178     return rc;
1179   }
1180 
1181   /* set the metadata encrypt key */
1182   rc = mm_jpeg_meta_enc_key(p_session);
1183   if (OMX_ErrorNone != rc) {
1184     CDBG_ERROR("%s: config session failed", __func__);
1185     return rc;
1186   }
1187 
1188   /* set the mem ops */
1189   rc = mm_jpeg_mem_ops(p_session);
1190   if (OMX_ErrorNone != rc) {
1191     CDBG_ERROR("%s: config mem ops failed", __func__);
1192     return rc;
1193   }
1194   /* set the jpeg speed mode */
1195   rc = mm_jpeg_speed_mode(p_session);
1196   if (OMX_ErrorNone != rc) {
1197     CDBG_ERROR("%s: config speed mode failed", __func__);
1198     return rc;
1199   }
1200 
1201   return rc;
1202 }
1203 
1204 /** mm_jpeg_session_config_common:
1205  *
1206  *  Arguments:
1207  *    @p_session: job session
1208  *
1209  *  Return:
1210  *       OMX error values
1211  *
1212  *  Description:
1213  *       Configure common parameters
1214  *
1215  **/
mm_jpeg_session_config_common(mm_jpeg_job_session_t * p_session)1216 OMX_ERRORTYPE mm_jpeg_session_config_common(mm_jpeg_job_session_t *p_session)
1217 {
1218   OMX_ERRORTYPE rc = OMX_ErrorNone;
1219   OMX_INDEXTYPE exif_idx;
1220   OMX_CONFIG_ROTATIONTYPE rotate;
1221   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
1222   QOMX_EXIF_INFO exif_info;
1223 
1224   /* set rotation */
1225   memset(&rotate, 0, sizeof(rotate));
1226   rotate.nPortIndex = 1;
1227   rotate.nRotation = (OMX_S32)p_jobparams->rotation;
1228   rc = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate,
1229     &rotate);
1230   if (OMX_ErrorNone != rc) {
1231       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
1232       return rc;
1233   }
1234   CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__,
1235     (int)p_jobparams->rotation, (int)rotate.nPortIndex);
1236 
1237   /* Set Exif data*/
1238   memset(&p_session->exif_info_local[0], 0, sizeof(p_session->exif_info_local));
1239   rc = OMX_GetExtensionIndex(p_session->omx_handle, QOMX_IMAGE_EXT_EXIF_NAME,
1240     &exif_idx);
1241   if (OMX_ErrorNone != rc) {
1242     CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
1243     return rc;
1244   }
1245 
1246   CDBG("%s:%d] Num of exif entries passed from HAL: %d", __func__, __LINE__,
1247       (int)p_jobparams->exif_info.numOfEntries);
1248   if (p_jobparams->exif_info.numOfEntries > 0) {
1249     rc = OMX_SetConfig(p_session->omx_handle, exif_idx,
1250         &p_jobparams->exif_info);
1251     if (OMX_ErrorNone != rc) {
1252       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
1253       return rc;
1254     }
1255   }
1256   /*parse aditional exif data from the metadata*/
1257   exif_info.numOfEntries = 0;
1258   exif_info.exif_data = &p_session->exif_info_local[0];
1259   process_meta_data(p_jobparams->p_metadata, &exif_info,
1260     &p_jobparams->cam_exif_params, p_jobparams->hal_version);
1261   /* After Parse metadata */
1262   p_session->exif_count_local = (int)exif_info.numOfEntries;
1263 
1264   if (exif_info.numOfEntries > 0) {
1265     /* set exif tags */
1266     CDBG("%s:%d] exif tags from metadata count %d", __func__, __LINE__,
1267       (int)exif_info.numOfEntries);
1268 
1269     rc = OMX_SetConfig(p_session->omx_handle, exif_idx,
1270       &exif_info);
1271     if (OMX_ErrorNone != rc) {
1272       CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc);
1273       return rc;
1274     }
1275   }
1276 
1277   return rc;
1278 }
1279 
1280 
1281 
1282 
1283 /** mm_jpeg_session_abort:
1284  *
1285  *  Arguments:
1286  *    @p_session: jpeg session
1287  *
1288  *  Return:
1289  *       OMX_BOOL
1290  *
1291  *  Description:
1292  *       Abort ongoing job
1293  *
1294  **/
mm_jpeg_session_abort(mm_jpeg_job_session_t * p_session)1295 OMX_BOOL mm_jpeg_session_abort(mm_jpeg_job_session_t *p_session)
1296 {
1297   OMX_ERRORTYPE ret = OMX_ErrorNone;
1298   int rc = 0;
1299 
1300   CDBG("%s:%d] E", __func__, __LINE__);
1301   pthread_mutex_lock(&p_session->lock);
1302   if (MM_JPEG_ABORT_NONE != p_session->abort_state) {
1303     pthread_mutex_unlock(&p_session->lock);
1304     CDBG_HIGH("%s:%d] **** ALREADY ABORTED", __func__, __LINE__);
1305     return 0;
1306   }
1307   p_session->abort_state = MM_JPEG_ABORT_INIT;
1308   if (OMX_TRUE == p_session->encoding) {
1309     p_session->state_change_pending = OMX_TRUE;
1310 
1311     CDBG_HIGH("%s:%d] **** ABORTING", __func__, __LINE__);
1312     pthread_mutex_unlock(&p_session->lock);
1313 
1314     ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
1315     OMX_StateIdle, NULL);
1316 
1317     if (ret != OMX_ErrorNone) {
1318       CDBG_ERROR("%s:%d] OMX_SendCommand returned error %d", __func__, __LINE__, ret);
1319       return 1;
1320     }
1321     rc = mm_jpegenc_destroy_job(p_session);
1322     if (rc != 0) {
1323       CDBG_ERROR("%s:%d] Destroy job returned error %d", __func__, __LINE__, rc);
1324     }
1325 
1326     pthread_mutex_lock(&p_session->lock);
1327     if (MM_JPEG_ABORT_INIT == p_session->abort_state) {
1328       CDBG("%s:%d] before wait", __func__, __LINE__);
1329       pthread_cond_wait(&p_session->cond, &p_session->lock);
1330     }
1331     CDBG("%s:%d] after wait", __func__, __LINE__);
1332   }
1333   p_session->abort_state = MM_JPEG_ABORT_DONE;
1334   pthread_mutex_unlock(&p_session->lock);
1335 
1336 
1337   // Abort next session
1338   if (p_session->next_session) {
1339     mm_jpeg_session_abort(p_session->next_session);
1340   }
1341 
1342   CDBG("%s:%d] X", __func__, __LINE__);
1343   return 0;
1344 }
1345 
1346 
1347 /** mm_jpeg_configure_params
1348  *
1349  *  Arguments:
1350  *    @p_session: encode session
1351  *
1352  *  Return:
1353  *       none
1354  *
1355  *  Description:
1356  *       Configure the job specific params
1357  *
1358  **/
mm_jpeg_configure_job_params(mm_jpeg_job_session_t * p_session)1359 static OMX_ERRORTYPE mm_jpeg_configure_job_params(
1360   mm_jpeg_job_session_t *p_session)
1361 {
1362   OMX_ERRORTYPE ret = OMX_ErrorNone;
1363   OMX_IMAGE_PARAM_QFACTORTYPE q_factor;
1364   QOMX_WORK_BUFFER work_buffer;
1365   OMX_INDEXTYPE work_buffer_index;
1366   mm_jpeg_encode_params_t *p_params = &p_session->params;
1367   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
1368   int i;
1369 
1370   /* common config */
1371   ret = mm_jpeg_session_config_common(p_session);
1372   if (OMX_ErrorNone != ret) {
1373     CDBG_ERROR("%s:%d] config common failed", __func__, __LINE__);
1374 
1375   }
1376 
1377   /* config Main Image crop */
1378   CDBG("%s:%d] config main crop", __func__, __LINE__);
1379   ret = mm_jpeg_session_config_main_crop(p_session);
1380   if (OMX_ErrorNone != ret) {
1381     CDBG_ERROR("%s: config crop failed", __func__);
1382     return ret;
1383   }
1384 
1385   /* set quality */
1386   memset(&q_factor, 0, sizeof(q_factor));
1387   q_factor.nPortIndex = 0;
1388   q_factor.nQFactor = p_params->quality;
1389   ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexParamQFactor, &q_factor);
1390   CDBG("%s:%d] config QFactor: %d", __func__, __LINE__, (int)q_factor.nQFactor);
1391   if (OMX_ErrorNone != ret) {
1392     CDBG_ERROR("%s:%d] Error setting Q factor %d", __func__, __LINE__, ret);
1393     return ret;
1394   }
1395 
1396   /* config thumbnail */
1397   ret = mm_jpeg_session_config_thumbnail(p_session);
1398   if (OMX_ErrorNone != ret) {
1399     CDBG_ERROR("%s:%d] config thumbnail img failed", __func__, __LINE__);
1400     return ret;
1401   }
1402 
1403   //Pass the ION buffer to be used as o/p for HW
1404   memset(&work_buffer, 0x0, sizeof(QOMX_WORK_BUFFER));
1405   ret = OMX_GetExtensionIndex(p_session->omx_handle,
1406     QOMX_IMAGE_EXT_WORK_BUFFER_NAME,
1407     &work_buffer_index);
1408   if (ret) {
1409     CDBG_ERROR("%s:%d] Error getting work buffer index %d",
1410       __func__, __LINE__, ret);
1411     return ret;
1412   }
1413   work_buffer.fd = p_session->work_buffer.p_pmem_fd;
1414   work_buffer.vaddr = p_session->work_buffer.addr;
1415   work_buffer.length = (uint32_t)p_session->work_buffer.size;
1416   CDBG_ERROR("%s:%d] Work buffer info %d %p WorkBufSize: %d invalidate", __func__, __LINE__,
1417     work_buffer.fd, work_buffer.vaddr, work_buffer.length);
1418 
1419   buffer_invalidate(&p_session->work_buffer);
1420 
1421   ret = OMX_SetConfig(p_session->omx_handle, work_buffer_index,
1422     &work_buffer);
1423   if (ret) {
1424     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1425     return ret;
1426   }
1427 
1428   /* set metadata */
1429   ret = mm_jpeg_metadata(p_session);
1430   if (OMX_ErrorNone != ret) {
1431     CDBG_ERROR("%s: config makernote data failed", __func__);
1432     return ret;
1433   }
1434 
1435   /* set QTable */
1436   for (i = 0; i < QTABLE_MAX; i++) {
1437     if (p_jobparams->qtable_set[i]) {
1438       ret = OMX_SetConfig(p_session->omx_handle,
1439         OMX_IndexParamQuantizationTable, &p_jobparams->qtable[i]);
1440       if (OMX_ErrorNone != ret) {
1441         CDBG_ERROR("%s:%d] set QTable Error", __func__, __LINE__);
1442         return ret;
1443       }
1444     }
1445   }
1446 
1447   return ret;
1448 }
1449 
1450 /** mm_jpeg_session_configure:
1451  *
1452  *  Arguments:
1453  *    @data: encode session
1454  *
1455  *  Return:
1456  *       none
1457  *
1458  *  Description:
1459  *       Configure the session
1460  *
1461  **/
mm_jpeg_session_configure(mm_jpeg_job_session_t * p_session)1462 static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session)
1463 {
1464   OMX_ERRORTYPE ret = OMX_ErrorNone;
1465 
1466   CDBG("%s:%d] E ", __func__, __LINE__);
1467 
1468   MM_JPEG_CHK_ABORT(p_session, ret, error);
1469 
1470   /* config main img */
1471   ret = mm_jpeg_session_config_main(p_session);
1472   if (OMX_ErrorNone != ret) {
1473     CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__);
1474     goto error;
1475   }
1476   ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle,
1477     mm_jpeg_session_send_buffers);
1478   if (ret) {
1479     CDBG_ERROR("%s:%d] change state to idle failed %d",
1480       __func__, __LINE__, ret);
1481     goto error;
1482   }
1483 
1484   ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting,
1485     NULL);
1486   if (ret) {
1487     CDBG_ERROR("%s:%d] change state to executing failed %d",
1488       __func__, __LINE__, ret);
1489     goto error;
1490   }
1491 
1492 error:
1493   CDBG("%s:%d] X ret %d", __func__, __LINE__, ret);
1494   return ret;
1495 }
1496 
1497 
1498 
1499 
1500 
1501 
1502 /** mm_jpeg_session_encode:
1503  *
1504  *  Arguments:
1505  *    @p_session: encode session
1506  *
1507  *  Return:
1508  *       OMX_ERRORTYPE
1509  *
1510  *  Description:
1511  *       Start the encoding
1512  *
1513  **/
mm_jpeg_session_encode(mm_jpeg_job_session_t * p_session)1514 static OMX_ERRORTYPE mm_jpeg_session_encode(mm_jpeg_job_session_t *p_session)
1515 {
1516   OMX_ERRORTYPE ret = OMX_ErrorNone;
1517   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
1518 
1519   pthread_mutex_lock(&p_session->lock);
1520   p_session->abort_state = MM_JPEG_ABORT_NONE;
1521   p_session->encoding = OMX_FALSE;
1522   pthread_mutex_unlock(&p_session->lock);
1523 
1524   if (p_session->thumb_from_main) {
1525     if (0 > p_jobparams->src_index) {
1526       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1527       ret = OMX_ErrorUnsupportedIndex;
1528       goto error;
1529     }
1530     p_jobparams->thumb_index = (uint32_t)p_jobparams->src_index;
1531     p_jobparams->thumb_dim.crop = p_jobparams->main_dim.crop;
1532   }
1533 
1534   if (OMX_FALSE == p_session->config) {
1535     ret = mm_jpeg_session_configure(p_session);
1536     if (ret) {
1537       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1538       goto error;
1539     }
1540     p_session->config = OMX_TRUE;
1541   }
1542 
1543   ret = mm_jpeg_configure_job_params(p_session);
1544   if (ret) {
1545       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1546       goto error;
1547   }
1548   pthread_mutex_lock(&p_session->lock);
1549   p_session->encoding = OMX_TRUE;
1550   pthread_mutex_unlock(&p_session->lock);
1551 
1552   MM_JPEG_CHK_ABORT(p_session, ret, error);
1553 
1554 #ifdef MM_JPEG_DUMP_INPUT
1555   char filename[256];
1556   snprintf(filename, sizeof(filename),
1557       QCAMERA_DUMP_FRM_LOCATION"jpeg/mm_jpeg_int%d.yuv", p_session->ebd_count);
1558   DUMP_TO_FILE(filename,
1559     p_session->p_in_omx_buf[p_jobparams->src_index]->pBuffer,
1560     (size_t)p_session->p_in_omx_buf[p_jobparams->src_index]->nAllocLen);
1561 #endif
1562 
1563   ret = OMX_EmptyThisBuffer(p_session->omx_handle,
1564     p_session->p_in_omx_buf[p_jobparams->src_index]);
1565   if (ret) {
1566     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1567     goto error;
1568   }
1569 
1570   if (p_session->params.encode_thumbnail) {
1571 #ifdef MM_JPEG_DUMP_INPUT
1572   char thumb_filename[FILENAME_MAX];
1573   snprintf(thumb_filename, sizeof(thumb_filename),
1574     QCAMERA_DUMP_FRM_LOCATION"jpeg/mm_jpeg_int_t%d.yuv", p_session->ebd_count);
1575   DUMP_TO_FILE(filename,
1576     p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]->pBuffer,
1577     (size_t)p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]->nAllocLen);
1578 #endif
1579     ret = OMX_EmptyThisBuffer(p_session->omx_handle,
1580         p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]);
1581     if (ret) {
1582       CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1583       goto error;
1584     }
1585   }
1586 
1587   ret = OMX_FillThisBuffer(p_session->omx_handle,
1588     p_session->p_out_omx_buf[p_jobparams->dst_index]);
1589   if (ret) {
1590     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1591     goto error;
1592   }
1593 
1594   MM_JPEG_CHK_ABORT(p_session, ret, error);
1595 
1596 error:
1597 
1598   CDBG("%s:%d] X ", __func__, __LINE__);
1599   return ret;
1600 }
1601 
1602 /** mm_jpeg_process_encoding_job:
1603  *
1604  *  Arguments:
1605  *    @my_obj: jpeg client
1606  *    @job_node: job node
1607  *
1608  *  Return:
1609  *       0 for success -1 otherwise
1610  *
1611  *  Description:
1612  *       Start the encoding job
1613  *
1614  **/
mm_jpeg_process_encoding_job(mm_jpeg_obj * my_obj,mm_jpeg_job_q_node_t * job_node)1615 int32_t mm_jpeg_process_encoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
1616 {
1617   mm_jpeg_q_data_t qdata;
1618   int32_t rc = 0;
1619   OMX_ERRORTYPE ret = OMX_ErrorNone;
1620   mm_jpeg_job_session_t *p_session = NULL;
1621   uint32_t buf_idx;
1622 
1623   /* check if valid session */
1624   p_session = mm_jpeg_get_session(my_obj, job_node->enc_info.job_id);
1625   if (NULL == p_session) {
1626     CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__,
1627         job_node->enc_info.job_id);
1628     return -1;
1629   }
1630 
1631   CDBG("%s:%d] before dequeue session %d",
1632                 __func__, __LINE__, ret);
1633 
1634   /* dequeue available omx handle */
1635   qdata = mm_jpeg_queue_deq(p_session->session_handle_q);
1636   p_session = qdata.p;
1637 
1638   if (NULL == p_session) {
1639     CDBG_HIGH("%s:%d] No available sessions %d",
1640           __func__, __LINE__, ret);
1641     /* No available handles */
1642     qdata.p = job_node;
1643     mm_jpeg_queue_enq_head(&my_obj->job_mgr.job_queue, qdata);
1644 
1645     CDBG_HIGH("%s:%d]end enqueue %d",
1646               __func__, __LINE__, ret);
1647     return rc;
1648 
1649   }
1650 
1651   p_session->auto_out_buf = OMX_FALSE;
1652   if (job_node->enc_info.encode_job.dst_index < 0) {
1653     /* dequeue available output buffer idx */
1654     qdata = mm_jpeg_queue_deq(p_session->out_buf_q);
1655     buf_idx = qdata.u32;
1656 
1657     if (0U == buf_idx) {
1658       CDBG_ERROR("%s:%d] No available output buffers %d",
1659           __func__, __LINE__, ret);
1660       return OMX_ErrorUndefined;
1661     }
1662 
1663     buf_idx--;
1664 
1665     job_node->enc_info.encode_job.dst_index = (int32_t)buf_idx;
1666     p_session->auto_out_buf = OMX_TRUE;
1667   }
1668 
1669   /* sent encode cmd to OMX, queue job into ongoing queue */
1670   qdata.p = job_node;
1671   rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, qdata);
1672   if (rc) {
1673     CDBG_ERROR("%s:%d] jpeg enqueue failed %d",
1674       __func__, __LINE__, ret);
1675     goto error;
1676   }
1677 
1678   p_session->encode_job = job_node->enc_info.encode_job;
1679   p_session->jobId = job_node->enc_info.job_id;
1680   ret = mm_jpeg_session_encode(p_session);
1681   if (ret) {
1682     CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__);
1683     goto error;
1684   }
1685 
1686   CDBG_HIGH("%s:%d] Success X ", __func__, __LINE__);
1687   return rc;
1688 
1689 error:
1690 
1691   if ((OMX_ErrorNone != ret) &&
1692     (NULL != p_session->params.jpeg_cb)) {
1693     p_session->job_status = JPEG_JOB_STATUS_ERROR;
1694     CDBG_ERROR("%s:%d] send jpeg error callback %d", __func__, __LINE__,
1695       p_session->job_status);
1696     p_session->params.jpeg_cb(p_session->job_status,
1697       p_session->client_hdl,
1698       p_session->jobId,
1699       NULL,
1700       p_session->params.userdata);
1701   }
1702 
1703   /*remove the job*/
1704   mm_jpegenc_job_done(p_session);
1705   CDBG("%s:%d] Error X ", __func__, __LINE__);
1706 
1707   return rc;
1708 }
1709 
1710 
1711 
1712 /** mm_jpeg_jobmgr_thread:
1713  *
1714  *  Arguments:
1715  *    @my_obj: jpeg object
1716  *
1717  *  Return:
1718  *       0 for success else failure
1719  *
1720  *  Description:
1721  *       job manager thread main function
1722  *
1723  **/
mm_jpeg_jobmgr_thread(void * data)1724 static void *mm_jpeg_jobmgr_thread(void *data)
1725 {
1726   mm_jpeg_q_data_t qdata;
1727   int rc = 0;
1728   int running = 1;
1729   uint32_t num_ongoing_jobs = 0;
1730   mm_jpeg_obj *my_obj = (mm_jpeg_obj*)data;
1731   mm_jpeg_job_cmd_thread_t *cmd_thread = &my_obj->job_mgr;
1732   mm_jpeg_job_q_node_t* node = NULL;
1733   prctl(PR_SET_NAME, (unsigned long)"mm_jpeg_thread", 0, 0, 0);
1734 
1735   do {
1736     do {
1737       rc = cam_sem_wait(&cmd_thread->job_sem);
1738       if (rc != 0 && errno != EINVAL) {
1739         CDBG_ERROR("%s: cam_sem_wait error (%s)",
1740           __func__, strerror(errno));
1741         return NULL;
1742       }
1743     } while (rc != 0);
1744 
1745     /* check ongoing q size */
1746     num_ongoing_jobs = mm_jpeg_queue_get_size(&my_obj->ongoing_job_q);
1747 
1748     CDBG("%s:%d] ongoing job  %d %d", __func__,
1749       __LINE__, num_ongoing_jobs, MM_JPEG_CONCURRENT_SESSIONS_COUNT);
1750     if (num_ongoing_jobs >= MM_JPEG_CONCURRENT_SESSIONS_COUNT) {
1751       CDBG_ERROR("%s:%d] ongoing job already reach max %d", __func__,
1752         __LINE__, num_ongoing_jobs);
1753       continue;
1754     }
1755 
1756     pthread_mutex_lock(&my_obj->job_lock);
1757     /* can go ahead with new work */
1758     qdata = mm_jpeg_queue_deq(&cmd_thread->job_queue);
1759     node = (mm_jpeg_job_q_node_t*)qdata.p;
1760     if (node != NULL) {
1761       switch (node->type) {
1762       case MM_JPEG_CMD_TYPE_JOB:
1763         rc = mm_jpeg_process_encoding_job(my_obj, node);
1764         break;
1765       case MM_JPEG_CMD_TYPE_DECODE_JOB:
1766         rc = mm_jpegdec_process_decoding_job(my_obj, node);
1767         break;
1768       case MM_JPEG_CMD_TYPE_EXIT:
1769       default:
1770         /* free node */
1771         free(node);
1772         /* set running flag to false */
1773         running = 0;
1774         break;
1775       }
1776     }
1777     pthread_mutex_unlock(&my_obj->job_lock);
1778 
1779   } while (running);
1780   return NULL;
1781 }
1782 
1783 /** mm_jpeg_jobmgr_thread_launch:
1784  *
1785  *  Arguments:
1786  *    @my_obj: jpeg object
1787  *
1788  *  Return:
1789  *       0 for success else failure
1790  *
1791  *  Description:
1792  *       launches the job manager thread
1793  *
1794  **/
mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj * my_obj)1795 int32_t mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj *my_obj)
1796 {
1797   int32_t rc = 0;
1798   mm_jpeg_job_cmd_thread_t *job_mgr = &my_obj->job_mgr;
1799 
1800   cam_sem_init(&job_mgr->job_sem, 0);
1801   mm_jpeg_queue_init(&job_mgr->job_queue);
1802 
1803   /* launch the thread */
1804   pthread_create(&job_mgr->pid,
1805     NULL,
1806     mm_jpeg_jobmgr_thread,
1807     (void *)my_obj);
1808   pthread_setname_np(job_mgr->pid, "CAM_jpeg_jobmgr");
1809   return rc;
1810 }
1811 
1812 /** mm_jpeg_jobmgr_thread_release:
1813  *
1814  *  Arguments:
1815  *    @my_obj: jpeg object
1816  *
1817  *  Return:
1818  *       0 for success else failure
1819  *
1820  *  Description:
1821  *       Releases the job manager thread
1822  *
1823  **/
mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj)1824 int32_t mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj)
1825 {
1826   mm_jpeg_q_data_t qdata;
1827   int32_t rc = 0;
1828   mm_jpeg_job_cmd_thread_t * cmd_thread = &my_obj->job_mgr;
1829   mm_jpeg_job_q_node_t* node =
1830     (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
1831   if (NULL == node) {
1832     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
1833     return -1;
1834   }
1835 
1836   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
1837   node->type = MM_JPEG_CMD_TYPE_EXIT;
1838 
1839   qdata.p = node;
1840   mm_jpeg_queue_enq(&cmd_thread->job_queue, qdata);
1841   cam_sem_post(&cmd_thread->job_sem);
1842 
1843   /* wait until cmd thread exits */
1844   if (pthread_join(cmd_thread->pid, NULL) != 0) {
1845     CDBG("%s: pthread dead already", __func__);
1846   }
1847   mm_jpeg_queue_deinit(&cmd_thread->job_queue);
1848 
1849   cam_sem_destroy(&cmd_thread->job_sem);
1850   memset(cmd_thread, 0, sizeof(mm_jpeg_job_cmd_thread_t));
1851   return rc;
1852 }
1853 
1854 /** mm_jpeg_init:
1855  *
1856  *  Arguments:
1857  *    @my_obj: jpeg object
1858  *
1859  *  Return:
1860  *       0 for success else failure
1861  *
1862  *  Description:
1863  *       Initializes the jpeg client
1864  *
1865  **/
mm_jpeg_init(mm_jpeg_obj * my_obj)1866 int32_t mm_jpeg_init(mm_jpeg_obj *my_obj)
1867 {
1868   int32_t rc = 0;
1869   uint32_t work_buf_size;
1870   unsigned int i = 0;
1871   unsigned int initial_workbufs_cnt = 1;
1872 
1873   /* init locks */
1874   pthread_mutex_init(&my_obj->job_lock, NULL);
1875 
1876   /* init ongoing job queue */
1877   rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q);
1878   if (0 != rc) {
1879     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1880     pthread_mutex_destroy(&my_obj->job_lock);
1881     return -1;
1882   }
1883 
1884 
1885   /* init job semaphore and launch jobmgr thread */
1886   CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc);
1887   rc = mm_jpeg_jobmgr_thread_launch(my_obj);
1888   if (0 != rc) {
1889     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1890     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1891     pthread_mutex_destroy(&my_obj->job_lock);
1892     return -1;
1893   }
1894 
1895   /* set work buf size from max picture size */
1896   if (my_obj->max_pic_w <= 0 || my_obj->max_pic_h <= 0) {
1897     CDBG_ERROR("%s:%d] Width and height are not valid "
1898       "dimensions, cannot calc work buf size",__func__, __LINE__);
1899     mm_jpeg_jobmgr_thread_release(my_obj);
1900     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1901     pthread_mutex_destroy(&my_obj->job_lock);
1902     return -1;
1903   }
1904   work_buf_size = CEILING64((uint32_t)my_obj->max_pic_w) *
1905     CEILING64((uint32_t)my_obj->max_pic_h) * 3U / 2U;
1906   for (i = 0; i < initial_workbufs_cnt; i++) {
1907     my_obj->ionBuffer[i].size = CEILING32(work_buf_size);
1908     CDBG_HIGH("Max picture size %d x %d, WorkBufSize = %zu",
1909         my_obj->max_pic_w, my_obj->max_pic_h, my_obj->ionBuffer[i].size);
1910 
1911     my_obj->ionBuffer[i].addr = (uint8_t *)buffer_allocate(&my_obj->ionBuffer[i], 1);
1912     if (NULL == my_obj->ionBuffer[i].addr) {
1913       while (i--) {
1914         buffer_deallocate(&my_obj->ionBuffer[i]);
1915       }
1916       mm_jpeg_jobmgr_thread_release(my_obj);
1917       mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1918       pthread_mutex_destroy(&my_obj->job_lock);
1919       CDBG_ERROR("%s:%d] Ion allocation failed",__func__, __LINE__);
1920       return -1;
1921     }
1922   }
1923 
1924   my_obj->work_buf_cnt = i;
1925 
1926   /* load OMX */
1927   if (OMX_ErrorNone != OMX_Init()) {
1928     /* roll back in error case */
1929     CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc);
1930     for (i = 0; i < initial_workbufs_cnt; i++) {
1931       buffer_deallocate(&my_obj->ionBuffer[i]);
1932     }
1933     mm_jpeg_jobmgr_thread_release(my_obj);
1934     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1935     pthread_mutex_destroy(&my_obj->job_lock);
1936   }
1937 
1938 #ifdef LOAD_ADSP_RPC_LIB
1939   my_obj->adsprpc_lib_handle = dlopen("libadsprpc.so", RTLD_NOW);
1940   if (NULL == my_obj->adsprpc_lib_handle) {
1941     CDBG_ERROR("%s:%d] Cannot load the library", __func__, __LINE__);
1942     /* not returning error here bcoz even if this loading fails
1943         we can go ahead with SW JPEG enc */
1944   }
1945 #endif
1946 
1947   return rc;
1948 }
1949 
1950 /** mm_jpeg_deinit:
1951  *
1952  *  Arguments:
1953  *    @my_obj: jpeg object
1954  *
1955  *  Return:
1956  *       0 for success else failure
1957  *
1958  *  Description:
1959  *       Deinits the jpeg client
1960  *
1961  **/
mm_jpeg_deinit(mm_jpeg_obj * my_obj)1962 int32_t mm_jpeg_deinit(mm_jpeg_obj *my_obj)
1963 {
1964   int32_t rc = 0;
1965   uint32_t i = 0;
1966 
1967   /* release jobmgr thread */
1968   rc = mm_jpeg_jobmgr_thread_release(my_obj);
1969   if (0 != rc) {
1970     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1971   }
1972 
1973   /* unload OMX engine */
1974   OMX_Deinit();
1975 
1976   /* deinit ongoing job and cb queue */
1977   rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1978   if (0 != rc) {
1979     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1980   }
1981 
1982   for (i = 0; i < my_obj->work_buf_cnt; i++) {
1983     /*Release the ION buffer*/
1984     rc = buffer_deallocate(&my_obj->ionBuffer[i]);
1985     if (0 != rc) {
1986       CDBG_ERROR("%s:%d] Error releasing ION buffer", __func__, __LINE__);
1987     }
1988   }
1989 
1990   /* destroy locks */
1991   pthread_mutex_destroy(&my_obj->job_lock);
1992 
1993   return rc;
1994 }
1995 
1996 /** mm_jpeg_new_client:
1997  *
1998  *  Arguments:
1999  *    @my_obj: jpeg object
2000  *
2001  *  Return:
2002  *       0 for success else failure
2003  *
2004  *  Description:
2005  *       Create new jpeg client
2006  *
2007  **/
mm_jpeg_new_client(mm_jpeg_obj * my_obj)2008 uint32_t mm_jpeg_new_client(mm_jpeg_obj *my_obj)
2009 {
2010   uint32_t client_hdl = 0;
2011   uint8_t idx;
2012   int i = 0;
2013 
2014   if (my_obj->num_clients >= MAX_JPEG_CLIENT_NUM) {
2015     CDBG_ERROR("%s: num of clients reached limit", __func__);
2016     return client_hdl;
2017   }
2018 
2019   for (idx = 0; idx < MAX_JPEG_CLIENT_NUM; idx++) {
2020     if (0 == my_obj->clnt_mgr[idx].is_used) {
2021       break;
2022     }
2023   }
2024 
2025   if (idx < MAX_JPEG_CLIENT_NUM) {
2026     /* client session avail */
2027     /* generate client handler by index */
2028     client_hdl = mm_jpeg_util_generate_handler(idx);
2029 
2030     /* update client session */
2031     my_obj->clnt_mgr[idx].is_used = 1;
2032     my_obj->clnt_mgr[idx].client_handle = client_hdl;
2033 
2034     pthread_mutex_init(&my_obj->clnt_mgr[idx].lock, NULL);
2035     for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
2036       memset(&my_obj->clnt_mgr[idx].session[i], 0x0, sizeof(mm_jpeg_job_session_t));
2037     }
2038 
2039     /* increse client count */
2040     my_obj->num_clients++;
2041   }
2042 
2043   return client_hdl;
2044 }
2045 
2046 /** mm_jpeg_start_job:
2047  *
2048  *  Arguments:
2049  *    @my_obj: jpeg object
2050  *    @client_hdl: client handle
2051  *    @job: pointer to encode job
2052  *    @jobId: job id
2053  *
2054  *  Return:
2055  *       0 for success else failure
2056  *
2057  *  Description:
2058  *       Start the encoding job
2059  *
2060  **/
mm_jpeg_start_job(mm_jpeg_obj * my_obj,mm_jpeg_job_t * job,uint32_t * job_id)2061 int32_t mm_jpeg_start_job(mm_jpeg_obj *my_obj,
2062   mm_jpeg_job_t *job,
2063   uint32_t *job_id)
2064 {
2065   mm_jpeg_q_data_t qdata;
2066   int32_t rc = -1;
2067   uint8_t session_idx = 0;
2068   uint8_t client_idx = 0;
2069   mm_jpeg_job_q_node_t* node = NULL;
2070   mm_jpeg_job_session_t *p_session = NULL;
2071   mm_jpeg_encode_job_t *p_jobparams  = &job->encode_job;
2072 
2073   *job_id = 0;
2074 
2075   /* check if valid session */
2076   session_idx = GET_SESSION_IDX(p_jobparams->session_id);
2077   client_idx = GET_CLIENT_IDX(p_jobparams->session_id);
2078   CDBG_HIGH("%s:%d] session_idx %d client idx %d", __func__, __LINE__,
2079     session_idx, client_idx);
2080 
2081   if ((session_idx >= MM_JPEG_MAX_SESSION) ||
2082     (client_idx >= MAX_JPEG_CLIENT_NUM)) {
2083     CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__,
2084       job->encode_job.session_id);
2085     return rc;
2086   }
2087 
2088   p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
2089   if (OMX_FALSE == p_session->active) {
2090     CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__,
2091       job->encode_job.session_id);
2092     return rc;
2093   }
2094 
2095   if ((p_jobparams->src_index >= (int32_t)p_session->params.num_src_bufs) ||
2096     (p_jobparams->dst_index >= (int32_t)p_session->params.num_dst_bufs)) {
2097     CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__);
2098     return rc;
2099   }
2100 
2101   /* enqueue new job into todo job queue */
2102   node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
2103   if (NULL == node) {
2104     CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
2105     return -1;
2106   }
2107 
2108   ATRACE_INT("Camera:JPEG",
2109       (int32_t)((uint32_t)session_idx<<16 | ++p_session->job_index));
2110 
2111   *job_id = job->encode_job.session_id |
2112     (((uint32_t)p_session->job_hist++ % JOB_HIST_MAX) << 16);
2113 
2114   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
2115   node->enc_info.encode_job = job->encode_job;
2116   if (p_session->thumb_from_main) {
2117     node->enc_info.encode_job.thumb_dim.src_dim =
2118       node->enc_info.encode_job.main_dim.src_dim;
2119     node->enc_info.encode_job.thumb_dim.crop =
2120       node->enc_info.encode_job.main_dim.crop;
2121   }
2122   node->enc_info.job_id = *job_id;
2123   node->enc_info.client_handle = p_session->client_hdl;
2124   node->type = MM_JPEG_CMD_TYPE_JOB;
2125 
2126 
2127 
2128   qdata.p = node;
2129   rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, qdata);
2130   if (0 == rc) {
2131       cam_sem_post(&my_obj->job_mgr.job_sem);
2132   }
2133 
2134   CDBG_HIGH("%s:%d] job_id %d X", __func__, __LINE__, *job_id);
2135 
2136   return rc;
2137 }
2138 
2139 
2140 
2141 /** mm_jpeg_abort_job:
2142  *
2143  *  Arguments:
2144  *    @my_obj: jpeg object
2145  *    @client_hdl: client handle
2146  *    @jobId: job id
2147  *
2148  *  Return:
2149  *       0 for success else failure
2150  *
2151  *  Description:
2152  *       Abort the encoding session
2153  *
2154  **/
mm_jpeg_abort_job(mm_jpeg_obj * my_obj,uint32_t jobId)2155 int32_t mm_jpeg_abort_job(mm_jpeg_obj *my_obj,
2156   uint32_t jobId)
2157 {
2158   int32_t rc = -1;
2159   mm_jpeg_job_q_node_t *node = NULL;
2160   mm_jpeg_job_session_t *p_session = NULL;
2161 
2162   CDBG("%s:%d] ", __func__, __LINE__);
2163   pthread_mutex_lock(&my_obj->job_lock);
2164 
2165   /* abort job if in todo queue */
2166   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId);
2167   if (NULL != node) {
2168     free(node);
2169     goto abort_done;
2170   }
2171 
2172   /* abort job if in ongoing queue */
2173   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId);
2174   if (NULL != node) {
2175     /* find job that is OMX ongoing, ask OMX to abort the job */
2176     p_session = mm_jpeg_get_session(my_obj, node->enc_info.job_id);
2177     if (p_session) {
2178       mm_jpeg_session_abort(p_session);
2179     } else {
2180       CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__,
2181         node->enc_info.job_id);
2182     }
2183     free(node);
2184     goto abort_done;
2185   }
2186 
2187 abort_done:
2188   pthread_mutex_unlock(&my_obj->job_lock);
2189 
2190   return rc;
2191 }
2192 
2193 
2194 #ifdef MM_JPEG_READ_META_KEYFILE
mm_jpeg_read_meta_keyfile(mm_jpeg_job_session_t * p_session,const char * filename)2195 static int32_t mm_jpeg_read_meta_keyfile(mm_jpeg_job_session_t *p_session,
2196     const char *filename)
2197 {
2198   int rc = 0;
2199   FILE *fp = NULL;
2200   size_t file_size = 0;
2201   fp = fopen(filename, "r");
2202   if (!fp) {
2203     CDBG_ERROR("%s:%d] Key not present", __func__, __LINE__);
2204     return -1;
2205   }
2206   fseek(fp, 0, SEEK_END);
2207   file_size = (size_t)ftell(fp);
2208   fseek(fp, 0, SEEK_SET);
2209 
2210   p_session->meta_enc_key = (uint8_t *) malloc((file_size + 1) * sizeof(uint8_t));
2211 
2212   if (!p_session->meta_enc_key) {
2213     CDBG_ERROR("%s:%d] error", __func__, __LINE__);
2214     return -1;
2215   }
2216 
2217   fread(p_session->meta_enc_key, 1, file_size, fp);
2218   fclose(fp);
2219 
2220   p_session->meta_enc_keylen = file_size;
2221 
2222   return rc;
2223 }
2224 #endif // MM_JPEG_READ_META_KEYFILE
2225 
2226 /** mm_jpeg_create_session:
2227  *
2228  *  Arguments:
2229  *    @my_obj: jpeg object
2230  *    @client_hdl: client handle
2231  *    @p_params: pointer to encode params
2232  *    @p_session_id: session id
2233  *
2234  *  Return:
2235  *       0 for success else failure
2236  *
2237  *  Description:
2238  *       Start the encoding session
2239  *
2240  **/
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)2241 int32_t mm_jpeg_create_session(mm_jpeg_obj *my_obj,
2242   uint32_t client_hdl,
2243   mm_jpeg_encode_params_t *p_params,
2244   uint32_t* p_session_id)
2245 {
2246   mm_jpeg_q_data_t qdata;
2247   int32_t rc = 0;
2248   OMX_ERRORTYPE ret = OMX_ErrorNone;
2249   uint8_t clnt_idx = 0;
2250   int session_idx = -1;
2251   mm_jpeg_job_session_t *p_session = NULL;
2252   mm_jpeg_job_session_t * p_prev_session = NULL;
2253   *p_session_id = 0;
2254   uint32_t i = 0;
2255   uint32_t num_omx_sessions;
2256   uint32_t work_buf_size;
2257   mm_jpeg_queue_t *p_session_handle_q, *p_out_buf_q;
2258   uint32_t work_bufs_need;
2259   char trace_tag[32];
2260 
2261   /* validate the parameters */
2262   if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF)
2263     || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) {
2264     CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__);
2265     return -1;
2266   }
2267 
2268   /* check if valid client */
2269   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
2270   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
2271     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
2272     return -1;
2273   }
2274 
2275   num_omx_sessions = 1;
2276   if (p_params->burst_mode) {
2277     num_omx_sessions = MM_JPEG_CONCURRENT_SESSIONS_COUNT;
2278   }
2279   work_bufs_need = num_omx_sessions;
2280   if (work_bufs_need > MM_JPEG_CONCURRENT_SESSIONS_COUNT) {
2281     work_bufs_need = MM_JPEG_CONCURRENT_SESSIONS_COUNT;
2282   }
2283   CDBG_HIGH("%s:%d] >>>> Work bufs need %d", __func__, __LINE__, work_bufs_need);
2284   work_buf_size = CEILING64((uint32_t)my_obj->max_pic_w) *
2285       CEILING64((uint32_t)my_obj->max_pic_h) * 3 / 2;
2286   for (i = my_obj->work_buf_cnt; i < work_bufs_need; i++) {
2287      my_obj->ionBuffer[i].size = CEILING32(work_buf_size);
2288      CDBG_HIGH("Max picture size %d x %d, WorkBufSize = %zu",
2289          my_obj->max_pic_w, my_obj->max_pic_h, my_obj->ionBuffer[i].size);
2290 
2291      my_obj->ionBuffer[i].addr = (uint8_t *)buffer_allocate(&my_obj->ionBuffer[i], 1);
2292      if (NULL == my_obj->ionBuffer[i].addr) {
2293        CDBG_ERROR("%s:%d] Ion allocation failed",__func__, __LINE__);
2294        goto error1;
2295      }
2296      my_obj->work_buf_cnt++;
2297   }
2298 
2299 
2300   /* init omx handle queue */
2301   p_session_handle_q = (mm_jpeg_queue_t *) malloc(sizeof(*p_session_handle_q));
2302   if (NULL == p_session_handle_q) {
2303     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
2304     goto error1;
2305   }
2306   rc = mm_jpeg_queue_init(p_session_handle_q);
2307   if (0 != rc) {
2308     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
2309     free(p_session_handle_q);
2310     goto error1;
2311   }
2312 
2313   /* init output buf queue */
2314   p_out_buf_q = (mm_jpeg_queue_t *) malloc(sizeof(*p_out_buf_q));
2315   if (NULL == p_out_buf_q) {
2316     CDBG_ERROR("%s:%d] Error: Cannot allocate memory\n", __func__, __LINE__);
2317     return -1;
2318   }
2319 
2320   /* init omx handle queue */
2321   rc = mm_jpeg_queue_init(p_out_buf_q);
2322   if (0 != rc) {
2323     CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
2324     free(p_out_buf_q);
2325     goto error1;
2326   }
2327 
2328   for (i = 0; i < num_omx_sessions; i++) {
2329     uint32_t buf_idx = 0U;
2330     session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session);
2331     if (session_idx < 0 || NULL == p_session) {
2332       CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx);
2333       goto error2;
2334     }
2335 
2336     snprintf(trace_tag, sizeof(trace_tag), "Camera:JPEGsession%d", session_idx);
2337     ATRACE_INT(trace_tag, 1);
2338 
2339     p_session->job_index = 0;
2340 
2341     p_session->next_session = NULL;
2342 
2343     if (p_prev_session) {
2344       p_prev_session->next_session = p_session;
2345     }
2346     p_prev_session = p_session;
2347 
2348     buf_idx = i;
2349     if (buf_idx < MM_JPEG_CONCURRENT_SESSIONS_COUNT) {
2350       p_session->work_buffer = my_obj->ionBuffer[buf_idx];
2351     } else {
2352       CDBG_ERROR("%s %d: Invalid Index, Setting buffer add to null", __func__, __LINE__);
2353       p_session->work_buffer.addr = NULL;
2354       p_session->work_buffer.ion_fd = -1;
2355       p_session->work_buffer.p_pmem_fd = -1;
2356     }
2357 
2358     p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */
2359 
2360     ret = mm_jpeg_session_create(p_session);
2361     if (OMX_ErrorNone != ret) {
2362       p_session->active = OMX_FALSE;
2363       CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__);
2364       goto error2;
2365     }
2366 
2367     uint32_t session_id = (JOB_ID_MAGICVAL << 24) |
2368         ((uint32_t)session_idx << 8) | clnt_idx;
2369 
2370     if (!*p_session_id) {
2371       *p_session_id = session_id;
2372     }
2373 
2374     /*copy the params*/
2375     p_session->params = *p_params;
2376     if (p_session->thumb_from_main) {
2377       memcpy(p_session->params.src_thumb_buf, p_session->params.src_main_buf,
2378         sizeof(p_session->params.src_thumb_buf));
2379       p_session->params.num_tmb_bufs =  p_session->params.num_src_bufs;
2380       if (!p_session->params.encode_thumbnail) {
2381          p_session->params.num_tmb_bufs = 0;
2382       }
2383       p_session->params.thumb_dim.src_dim = p_session->params.main_dim.src_dim;
2384       p_session->params.thumb_dim.crop = p_session->params.main_dim.crop;
2385     }
2386     p_session->client_hdl = client_hdl;
2387     p_session->sessionId = session_id;
2388     p_session->session_handle_q = p_session_handle_q;
2389     p_session->out_buf_q = p_out_buf_q;
2390 
2391     qdata.p = p_session;
2392     mm_jpeg_queue_enq(p_session_handle_q, qdata);
2393 
2394     p_session->meta_enc_key = NULL;
2395     p_session->meta_enc_keylen = 0;
2396 
2397 #ifdef MM_JPEG_READ_META_KEYFILE
2398     mm_jpeg_read_meta_keyfile(p_session, META_KEYFILE);
2399 #endif
2400 
2401     if (OMX_FALSE == p_session->config) {
2402       rc = mm_jpeg_session_configure(p_session);
2403       if (rc) {
2404         CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
2405         goto error2;
2406       }
2407       p_session->config = OMX_TRUE;
2408     }
2409     p_session->num_omx_sessions = num_omx_sessions;
2410 
2411     CDBG_HIGH("%s:%d] session id %x", __func__, __LINE__, session_id);
2412   }
2413 
2414   // Queue the output buf indexes
2415   for (i = 0; i < p_params->num_dst_bufs; i++) {
2416     qdata.u32 = i + 1;
2417     mm_jpeg_queue_enq(p_out_buf_q, qdata);
2418   }
2419 
2420   return rc;
2421 
2422 error1:
2423   rc = -1;
2424 error2:
2425   if (NULL != p_session) {
2426     ATRACE_INT(trace_tag, 0);
2427   }
2428   return rc;
2429 }
2430 
2431 /** mm_jpegenc_destroy_job
2432  *
2433  *  Arguments:
2434  *    @p_session: Session obj
2435  *
2436  *  Return:
2437  *       0 for success else failure
2438  *
2439  *  Description:
2440  *       Destroy the job based paramenters
2441  *
2442  **/
mm_jpegenc_destroy_job(mm_jpeg_job_session_t * p_session)2443 static int32_t mm_jpegenc_destroy_job(mm_jpeg_job_session_t *p_session)
2444 {
2445   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
2446   int i = 0, rc = 0;
2447 
2448   CDBG_HIGH("%s:%d] Exif entry count %d %d", __func__, __LINE__,
2449     (int)p_jobparams->exif_info.numOfEntries,
2450     (int)p_session->exif_count_local);
2451   for (i = 0; i < p_session->exif_count_local; i++) {
2452     rc = releaseExifEntry(&p_session->exif_info_local[i]);
2453     if (rc) {
2454       CDBG_ERROR("%s:%d] Exif release failed (%d)", __func__, __LINE__, rc);
2455     }
2456   }
2457   p_session->exif_count_local = 0;
2458 
2459   return rc;
2460 }
2461 
2462 /** mm_jpeg_session_encode:
2463  *
2464  *  Arguments:
2465  *    @p_session: encode session
2466  *
2467  *  Return:
2468  *       OMX_ERRORTYPE
2469  *
2470  *  Description:
2471  *       Start the encoding
2472  *
2473  **/
mm_jpegenc_job_done(mm_jpeg_job_session_t * p_session)2474 static void mm_jpegenc_job_done(mm_jpeg_job_session_t *p_session)
2475 {
2476   mm_jpeg_q_data_t qdata;
2477   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
2478   mm_jpeg_job_q_node_t *node = NULL;
2479 
2480   /*Destroy job related params*/
2481   mm_jpegenc_destroy_job(p_session);
2482 
2483   /*remove the job*/
2484   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
2485     p_session->jobId);
2486   if (node) {
2487     free(node);
2488   }
2489   p_session->encoding = OMX_FALSE;
2490 
2491   // Queue to available sessions
2492   qdata.p = p_session;
2493   mm_jpeg_queue_enq(p_session->session_handle_q, qdata);
2494 
2495   if (p_session->auto_out_buf) {
2496     //Queue out buf index
2497     qdata.u32 = (uint32_t)(p_session->encode_job.dst_index + 1);
2498     mm_jpeg_queue_enq(p_session->out_buf_q, qdata);
2499   }
2500 
2501   /* wake up jobMgr thread to work on new job if there is any */
2502   cam_sem_post(&my_obj->job_mgr.job_sem);
2503 }
2504 
2505 /** mm_jpeg_destroy_session:
2506  *
2507  *  Arguments:
2508  *    @my_obj: jpeg object
2509  *    @session_id: session index
2510  *
2511  *  Return:
2512  *       0 for success else failure
2513  *
2514  *  Description:
2515  *       Destroy the encoding session
2516  *
2517  **/
mm_jpeg_destroy_session(mm_jpeg_obj * my_obj,mm_jpeg_job_session_t * p_session)2518 int32_t mm_jpeg_destroy_session(mm_jpeg_obj *my_obj,
2519   mm_jpeg_job_session_t *p_session)
2520 {
2521   mm_jpeg_q_data_t qdata;
2522   int32_t rc = 0;
2523   mm_jpeg_job_q_node_t *node = NULL;
2524   uint32_t session_id = 0;
2525   mm_jpeg_job_session_t *p_cur_sess;
2526   char trace_tag[32];
2527 
2528   if (NULL == p_session) {
2529     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
2530     return rc;
2531   }
2532 
2533   session_id = p_session->sessionId;
2534 
2535   pthread_mutex_lock(&my_obj->job_lock);
2536 
2537   /* abort job if in todo queue */
2538   CDBG_HIGH("%s:%d] abort todo jobs", __func__, __LINE__);
2539   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
2540   while (NULL != node) {
2541     free(node);
2542     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
2543   }
2544 
2545   /* abort job if in ongoing queue */
2546   CDBG_HIGH("%s:%d] abort ongoing jobs", __func__, __LINE__);
2547   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
2548   while (NULL != node) {
2549     free(node);
2550     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
2551   }
2552 
2553   /* abort the current session */
2554   mm_jpeg_session_abort(p_session);
2555   mm_jpeg_session_destroy(p_session);
2556 
2557   p_cur_sess = p_session;
2558 
2559   do {
2560     mm_jpeg_remove_session_idx(my_obj, p_cur_sess->sessionId);
2561   } while (NULL != (p_cur_sess = p_cur_sess->next_session));
2562 
2563 
2564   pthread_mutex_unlock(&my_obj->job_lock);
2565 
2566   while (1) {
2567     qdata = mm_jpeg_queue_deq(p_session->session_handle_q);
2568     if (NULL == qdata.p)
2569       break;
2570   }
2571   mm_jpeg_queue_deinit(p_session->session_handle_q);
2572   free(p_session->session_handle_q);
2573   p_session->session_handle_q = NULL;
2574 
2575   while (1) {
2576     qdata = mm_jpeg_queue_deq(p_session->out_buf_q);
2577     if (0U == qdata.u32)
2578       break;
2579   }
2580   mm_jpeg_queue_deinit(p_session->out_buf_q);
2581   free(p_session->out_buf_q);
2582   p_session->out_buf_q = NULL;
2583 
2584 
2585   /* wake up jobMgr thread to work on new job if there is any */
2586   cam_sem_post(&my_obj->job_mgr.job_sem);
2587 
2588   snprintf(trace_tag, sizeof(trace_tag), "Camera:JPEGsession%d", GET_SESSION_IDX(session_id));
2589   ATRACE_INT(trace_tag, 0);
2590 
2591   CDBG_HIGH("%s:%d] destroy session successful. X", __func__, __LINE__);
2592 
2593   return rc;
2594 }
2595 
2596 
2597 
2598 
2599 /** mm_jpeg_destroy_session:
2600  *
2601  *  Arguments:
2602  *    @my_obj: jpeg object
2603  *    @session_id: session index
2604  *
2605  *  Return:
2606  *       0 for success else failure
2607  *
2608  *  Description:
2609  *       Destroy the encoding session
2610  *
2611  **/
mm_jpeg_destroy_session_unlocked(mm_jpeg_obj * my_obj,mm_jpeg_job_session_t * p_session)2612 int32_t mm_jpeg_destroy_session_unlocked(mm_jpeg_obj *my_obj,
2613   mm_jpeg_job_session_t *p_session)
2614 {
2615   int32_t rc = -1;
2616   mm_jpeg_job_q_node_t *node = NULL;
2617   uint32_t session_id = 0;
2618   if (NULL == p_session) {
2619     CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
2620     return rc;
2621   }
2622 
2623   session_id = p_session->sessionId;
2624 
2625   /* abort job if in todo queue */
2626   CDBG("%s:%d] abort todo jobs", __func__, __LINE__);
2627   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
2628   while (NULL != node) {
2629     free(node);
2630     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
2631   }
2632 
2633   /* abort job if in ongoing queue */
2634   CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__);
2635   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
2636   while (NULL != node) {
2637     free(node);
2638     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
2639   }
2640 
2641   /* abort the current session */
2642   mm_jpeg_session_abort(p_session);
2643   //mm_jpeg_remove_session_idx(my_obj, session_id);
2644 
2645   return rc;
2646 }
2647 
2648 /** mm_jpeg_destroy_session:
2649  *
2650  *  Arguments:
2651  *    @my_obj: jpeg object
2652  *    @session_id: session index
2653  *
2654  *  Return:
2655  *       0 for success else failure
2656  *
2657  *  Description:
2658  *       Destroy the encoding session
2659  *
2660  **/
mm_jpeg_destroy_session_by_id(mm_jpeg_obj * my_obj,uint32_t session_id)2661 int32_t mm_jpeg_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id)
2662 {
2663   mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id);
2664 
2665   return mm_jpeg_destroy_session(my_obj, p_session);
2666 }
2667 
2668 
2669 
2670 /** mm_jpeg_close:
2671  *
2672  *  Arguments:
2673  *    @my_obj: jpeg object
2674  *    @client_hdl: client handle
2675  *
2676  *  Return:
2677  *       0 for success else failure
2678  *
2679  *  Description:
2680  *       Close the jpeg client
2681  *
2682  **/
mm_jpeg_close(mm_jpeg_obj * my_obj,uint32_t client_hdl)2683 int32_t mm_jpeg_close(mm_jpeg_obj *my_obj, uint32_t client_hdl)
2684 {
2685   int32_t rc = -1;
2686   uint8_t clnt_idx = 0;
2687   int i = 0;
2688 
2689   /* check if valid client */
2690   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
2691   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
2692     CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
2693     return rc;
2694   }
2695 
2696   CDBG("%s:%d] E", __func__, __LINE__);
2697 
2698   /* abort all jobs from the client */
2699   pthread_mutex_lock(&my_obj->job_lock);
2700 
2701   CDBG("%s:%d] ", __func__, __LINE__);
2702 
2703   for (i = 0; i < MM_JPEG_MAX_SESSION; i++) {
2704     if (OMX_TRUE == my_obj->clnt_mgr[clnt_idx].session[i].active)
2705       mm_jpeg_destroy_session_unlocked(my_obj,
2706         &my_obj->clnt_mgr[clnt_idx].session[i]);
2707   }
2708 
2709   CDBG("%s:%d] ", __func__, __LINE__);
2710 
2711 #ifdef LOAD_ADSP_RPC_LIB
2712   if (NULL != my_obj->adsprpc_lib_handle) {
2713     dlclose(my_obj->adsprpc_lib_handle);
2714     my_obj->adsprpc_lib_handle = NULL;
2715   }
2716 #endif
2717 
2718   pthread_mutex_unlock(&my_obj->job_lock);
2719   CDBG("%s:%d] ", __func__, __LINE__);
2720 
2721   /* invalidate client session */
2722   pthread_mutex_destroy(&my_obj->clnt_mgr[clnt_idx].lock);
2723   memset(&my_obj->clnt_mgr[clnt_idx], 0, sizeof(mm_jpeg_client_t));
2724 
2725   rc = 0;
2726   CDBG("%s:%d] X", __func__, __LINE__);
2727   return rc;
2728 }
2729 
mm_jpeg_ebd(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_BUFFERHEADERTYPE * pBuffer)2730 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
2731   OMX_PTR pAppData,
2732   OMX_BUFFERHEADERTYPE *pBuffer)
2733 {
2734   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
2735 
2736   CDBG_HIGH("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count);
2737   pthread_mutex_lock(&p_session->lock);
2738   p_session->ebd_count++;
2739   pthread_mutex_unlock(&p_session->lock);
2740   return 0;
2741 }
2742 
mm_jpeg_fbd(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_BUFFERHEADERTYPE * pBuffer)2743 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent,
2744   OMX_PTR pAppData,
2745   OMX_BUFFERHEADERTYPE *pBuffer)
2746 {
2747   OMX_ERRORTYPE ret = OMX_ErrorNone;
2748   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
2749   mm_jpeg_output_t output_buf;
2750   CDBG_HIGH("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count);
2751   CDBG_HIGH("[KPI Perf] : PROFILE_JPEG_FBD");
2752 
2753   pthread_mutex_lock(&p_session->lock);
2754   ATRACE_INT("Camera:JPEG",
2755       (int32_t)((uint32_t)GET_SESSION_IDX(
2756         p_session->sessionId)<<16 | --p_session->job_index));
2757   if (MM_JPEG_ABORT_NONE != p_session->abort_state) {
2758     pthread_mutex_unlock(&p_session->lock);
2759     return ret;
2760   }
2761 #ifdef MM_JPEG_DUMP_OUT_BS
2762   char filename[256];
2763   static int bsc;
2764   snprintf(filename, sizeof(filename),
2765       QCAMERA_DUMP_FRM_LOCATION"jpeg/mm_jpeg_bs%d.jpg", bsc++);
2766   DUMP_TO_FILE(filename,
2767     pBuffer->pBuffer,
2768     (size_t)(uint32_t)pBuffer->nFilledLen);
2769 #endif
2770 
2771   p_session->fbd_count++;
2772   if (NULL != p_session->params.jpeg_cb) {
2773 
2774     p_session->job_status = JPEG_JOB_STATUS_DONE;
2775     output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen;
2776     output_buf.buf_vaddr = pBuffer->pBuffer;
2777     output_buf.fd = -1;
2778     CDBG_HIGH("%s:%d] send jpeg callback %d buf 0x%p len %u JobID %u",
2779       __func__, __LINE__,
2780       p_session->job_status, pBuffer->pBuffer,
2781       (unsigned int)pBuffer->nFilledLen, p_session->jobId);
2782     p_session->params.jpeg_cb(p_session->job_status,
2783       p_session->client_hdl,
2784       p_session->jobId,
2785       &output_buf,
2786       p_session->params.userdata);
2787 
2788     mm_jpegenc_job_done(p_session);
2789 
2790   }
2791   pthread_mutex_unlock(&p_session->lock);
2792   CDBG("%s:%d] ", __func__, __LINE__);
2793 
2794   return ret;
2795 }
2796 
2797 
2798 
mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_EVENTTYPE eEvent,OMX_U32 nData1,OMX_U32 nData2,OMX_PTR pEventData)2799 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent,
2800   OMX_PTR pAppData,
2801   OMX_EVENTTYPE eEvent,
2802   OMX_U32 nData1,
2803   OMX_U32 nData2,
2804   OMX_PTR pEventData)
2805 {
2806   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
2807 
2808   CDBG("%s:%d] %d %d %d state %d", __func__, __LINE__, eEvent, (int)nData1,
2809     (int)nData2, p_session->abort_state);
2810 
2811   pthread_mutex_lock(&p_session->lock);
2812 
2813   if (MM_JPEG_ABORT_INIT == p_session->abort_state) {
2814     p_session->abort_state = MM_JPEG_ABORT_DONE;
2815     pthread_cond_signal(&p_session->cond);
2816     pthread_mutex_unlock(&p_session->lock);
2817     return OMX_ErrorNone;
2818   }
2819 
2820   if (eEvent == OMX_EventError) {
2821     p_session->error_flag = nData2;
2822     if (p_session->encoding == OMX_TRUE) {
2823       CDBG_ERROR("%s:%d] Error during encoding", __func__, __LINE__);
2824 
2825       /* send jpeg callback */
2826       if (NULL != p_session->params.jpeg_cb) {
2827         p_session->job_status = JPEG_JOB_STATUS_ERROR;
2828         CDBG_ERROR("%s:%d] send jpeg error callback %d", __func__, __LINE__,
2829           p_session->job_status);
2830         p_session->params.jpeg_cb(p_session->job_status,
2831           p_session->client_hdl,
2832           p_session->jobId,
2833           NULL,
2834           p_session->params.userdata);
2835       }
2836 
2837       /* remove from ready queue */
2838       mm_jpegenc_job_done(p_session);
2839     }
2840     pthread_cond_signal(&p_session->cond);
2841   } else if (eEvent == OMX_EventCmdComplete) {
2842     if (p_session->state_change_pending == OMX_TRUE) {
2843       p_session->state_change_pending = OMX_FALSE;
2844       pthread_cond_signal(&p_session->cond);
2845     }
2846   }
2847 
2848   pthread_mutex_unlock(&p_session->lock);
2849   CDBG("%s:%d]", __func__, __LINE__);
2850   return OMX_ErrorNone;
2851 }
2852 
2853 
2854 
2855 /* 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)2856 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id(
2857   mm_jpeg_queue_t* queue, uint32_t client_hdl)
2858 {
2859   mm_jpeg_q_node_t* node = NULL;
2860   mm_jpeg_job_q_node_t* data = NULL;
2861   mm_jpeg_job_q_node_t* job_node = NULL;
2862   struct cam_list *head = NULL;
2863   struct cam_list *pos = NULL;
2864 
2865   pthread_mutex_lock(&queue->lock);
2866   head = &queue->head.list;
2867   pos = head->next;
2868   while(pos != head) {
2869     node = member_of(pos, mm_jpeg_q_node_t, list);
2870     data = (mm_jpeg_job_q_node_t *)node->data.p;
2871 
2872     if (data && (data->enc_info.client_handle == client_hdl)) {
2873       CDBG_HIGH("%s:%d] found matching client handle", __func__, __LINE__);
2874       job_node = data;
2875       cam_list_del_node(&node->list);
2876       queue->size--;
2877       free(node);
2878       CDBG_HIGH("%s: queue size = %d", __func__, queue->size);
2879       break;
2880     }
2881     pos = pos->next;
2882   }
2883 
2884   pthread_mutex_unlock(&queue->lock);
2885 
2886   return job_node;
2887 }
2888 
2889 /* 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)2890 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id(
2891   mm_jpeg_queue_t* queue, uint32_t session_id)
2892 {
2893   mm_jpeg_q_node_t* node = NULL;
2894   mm_jpeg_job_q_node_t* data = NULL;
2895   mm_jpeg_job_q_node_t* job_node = NULL;
2896   struct cam_list *head = NULL;
2897   struct cam_list *pos = NULL;
2898 
2899   pthread_mutex_lock(&queue->lock);
2900   head = &queue->head.list;
2901   pos = head->next;
2902   while(pos != head) {
2903     node = member_of(pos, mm_jpeg_q_node_t, list);
2904     data = (mm_jpeg_job_q_node_t *)node->data.p;
2905 
2906     if (data && (data->enc_info.encode_job.session_id == session_id)) {
2907       CDBG_HIGH("%s:%d] found matching session id", __func__, __LINE__);
2908       job_node = data;
2909       cam_list_del_node(&node->list);
2910       queue->size--;
2911       free(node);
2912       CDBG_HIGH("%s: queue size = %d", __func__, queue->size);
2913       break;
2914     }
2915     pos = pos->next;
2916   }
2917 
2918   pthread_mutex_unlock(&queue->lock);
2919 
2920   return job_node;
2921 }
2922 
2923 /* 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)2924 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id(
2925   mm_jpeg_queue_t* queue, uint32_t job_id)
2926 {
2927   mm_jpeg_q_node_t* node = NULL;
2928   mm_jpeg_job_q_node_t* data = NULL;
2929   mm_jpeg_job_q_node_t* job_node = NULL;
2930   struct cam_list *head = NULL;
2931   struct cam_list *pos = NULL;
2932   uint32_t lq_job_id;
2933 
2934   pthread_mutex_lock(&queue->lock);
2935   head = &queue->head.list;
2936   pos = head->next;
2937   while(pos != head) {
2938     node = member_of(pos, mm_jpeg_q_node_t, list);
2939     data = (mm_jpeg_job_q_node_t *)node->data.p;
2940 
2941     if(NULL == data) {
2942       CDBG_ERROR("%s:%d] Data is NULL", __func__, __LINE__);
2943       pthread_mutex_unlock(&queue->lock);
2944       return NULL;
2945     }
2946 
2947     if (data->type == MM_JPEG_CMD_TYPE_DECODE_JOB) {
2948       lq_job_id = data->dec_info.job_id;
2949     } else {
2950       lq_job_id = data->enc_info.job_id;
2951     }
2952 
2953     if (data && (lq_job_id == job_id)) {
2954       CDBG_HIGH("%s:%d] found matching job id", __func__, __LINE__);
2955       job_node = data;
2956       cam_list_del_node(&node->list);
2957       queue->size--;
2958       free(node);
2959       break;
2960     }
2961     pos = pos->next;
2962   }
2963 
2964   pthread_mutex_unlock(&queue->lock);
2965 
2966   return job_node;
2967 }
2968 
2969 /* remove job from the queue with matching job id */
mm_jpeg_queue_remove_job_unlk(mm_jpeg_queue_t * queue,uint32_t job_id)2970 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_unlk(
2971   mm_jpeg_queue_t* queue, uint32_t job_id)
2972 {
2973   mm_jpeg_q_node_t* node = NULL;
2974   mm_jpeg_job_q_node_t* data = NULL;
2975   mm_jpeg_job_q_node_t* job_node = NULL;
2976   struct cam_list *head = NULL;
2977   struct cam_list *pos = NULL;
2978 
2979   head = &queue->head.list;
2980   pos = head->next;
2981   while(pos != head) {
2982     node = member_of(pos, mm_jpeg_q_node_t, list);
2983     data = (mm_jpeg_job_q_node_t *)node->data.p;
2984 
2985     if (data && (data->enc_info.job_id == job_id)) {
2986       job_node = data;
2987       cam_list_del_node(&node->list);
2988       queue->size--;
2989       free(node);
2990       break;
2991     }
2992     pos = pos->next;
2993   }
2994 
2995   return job_node;
2996 }
2997