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