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