1 /* Copyright (c) 2013-2014, 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 
33 // JPEG dependencies
34 #include "mm_jpeg_dbg.h"
35 #include "mm_jpeg_interface.h"
36 #include "mm_jpeg.h"
37 #include "mm_jpeg_inlines.h"
38 
39 OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,
40   OMX_PTR pAppData,
41   OMX_BUFFERHEADERTYPE *pBuffer);
42 OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,
43     OMX_PTR pAppData,
44     OMX_BUFFERHEADERTYPE* pBuffer);
45 OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent,
46     OMX_PTR pAppData,
47     OMX_EVENTTYPE eEvent,
48     OMX_U32 nData1,
49     OMX_U32 nData2,
50     OMX_PTR pEventData);
51 
52 
53 /** mm_jpegdec_destroy_job
54  *
55  *  Arguments:
56  *    @p_session: Session obj
57  *
58  *  Return:
59  *       0 for success else failure
60  *
61  *  Description:
62  *       Destroy the job based paramenters
63  *
64  **/
mm_jpegdec_destroy_job(mm_jpeg_job_session_t * p_session)65 static int32_t mm_jpegdec_destroy_job(mm_jpeg_job_session_t *p_session)
66 {
67   int32_t rc = 0;
68 
69   return rc;
70 }
71 
72 /** mm_jpeg_job_done:
73  *
74  *  Arguments:
75  *    @p_session: decode session
76  *
77  *  Return:
78  *       OMX_ERRORTYPE
79  *
80  *  Description:
81  *       Finalize the job
82  *
83  **/
mm_jpegdec_job_done(mm_jpeg_job_session_t * p_session)84 static void mm_jpegdec_job_done(mm_jpeg_job_session_t *p_session)
85 {
86   mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
87   mm_jpeg_job_q_node_t *node = NULL;
88 
89   /*Destroy job related params*/
90   mm_jpegdec_destroy_job(p_session);
91 
92   /*remove the job*/
93   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
94     p_session->jobId);
95   if (node) {
96     free(node);
97   }
98   p_session->encoding = OMX_FALSE;
99 
100   /* wake up jobMgr thread to work on new job if there is any */
101   cam_sem_post(&my_obj->job_mgr.job_sem);
102 }
103 
104 
105 /** mm_jpegdec_session_send_buffers:
106  *
107  *  Arguments:
108  *    @data: job session
109  *
110  *  Return:
111  *       OMX error values
112  *
113  *  Description:
114  *       Send the buffers to OMX layer
115  *
116  **/
mm_jpegdec_session_send_buffers(void * data)117 OMX_ERRORTYPE mm_jpegdec_session_send_buffers(void *data)
118 {
119   uint32_t i = 0;
120   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
121   OMX_ERRORTYPE ret = OMX_ErrorNone;
122   QOMX_BUFFER_INFO lbuffer_info;
123   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
124 
125   memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
126   for (i = 0; i < p_params->num_src_bufs; i++) {
127     LOGD("Source buffer %d", i);
128     lbuffer_info.fd = (OMX_U32)p_params->src_main_buf[i].fd;
129     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0,
130       &lbuffer_info, p_params->src_main_buf[i].buf_size,
131       p_params->src_main_buf[i].buf_vaddr);
132     if (ret) {
133       LOGE("Error %d", ret);
134       return ret;
135     }
136   }
137 
138   LOGD("Exit");
139   return ret;
140 }
141 
142 /** mm_jpeg_session_free_buffers:
143  *
144  *  Arguments:
145  *    @data: job session
146  *
147  *  Return:
148  *       OMX error values
149  *
150  *  Description:
151  *       Free the buffers from OMX layer
152  *
153  **/
mm_jpegdec_session_free_buffers(void * data)154 OMX_ERRORTYPE mm_jpegdec_session_free_buffers(void *data)
155 {
156   OMX_ERRORTYPE ret = OMX_ErrorNone;
157   uint32_t i = 0;
158   mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
159   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
160 
161   for (i = 0; i < p_params->num_src_bufs; i++) {
162     LOGD("Source buffer %d", i);
163     ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]);
164     if (ret) {
165       LOGE("Error %d", ret);
166       return ret;
167     }
168   }
169 
170   for (i = 0; i < p_params->num_dst_bufs; i++) {
171     LOGD("Dest buffer %d", i);
172     ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]);
173     if (ret) {
174       LOGE("Error");
175       return ret;
176     }
177   }
178   LOGD("Exit");
179   return ret;
180 }
181 
182 /** mm_jpegdec_session_create:
183  *
184  *  Arguments:
185  *    @p_session: job session
186  *
187  *  Return:
188  *       OMX error types
189  *
190  *  Description:
191  *       Create a jpeg encode session
192  *
193  **/
mm_jpegdec_session_create(mm_jpeg_job_session_t * p_session)194 OMX_ERRORTYPE mm_jpegdec_session_create(mm_jpeg_job_session_t* p_session)
195 {
196   OMX_ERRORTYPE rc = OMX_ErrorNone;
197 
198   pthread_mutex_init(&p_session->lock, NULL);
199   pthread_cond_init(&p_session->cond, NULL);
200   cirq_reset(&p_session->cb_q);
201   p_session->state_change_pending = OMX_FALSE;
202   p_session->abort_state = MM_JPEG_ABORT_NONE;
203   p_session->error_flag = OMX_ErrorNone;
204   p_session->ebd_count = 0;
205   p_session->fbd_count = 0;
206   p_session->encode_pid = -1;
207   p_session->config = OMX_FALSE;
208 
209   p_session->omx_callbacks.EmptyBufferDone = mm_jpegdec_ebd;
210   p_session->omx_callbacks.FillBufferDone = mm_jpegdec_fbd;
211   p_session->omx_callbacks.EventHandler = mm_jpegdec_event_handler;
212   p_session->exif_count_local = 0;
213 
214   rc = OMX_GetHandle(&p_session->omx_handle,
215     "OMX.qcom.image.jpeg.decoder",
216     (void *)p_session,
217     &p_session->omx_callbacks);
218 
219   if (OMX_ErrorNone != rc) {
220     LOGE("OMX_GetHandle failed (%d)", rc);
221     return rc;
222   }
223   return rc;
224 }
225 
226 /** mm_jpegdec_session_destroy:
227  *
228  *  Arguments:
229  *    @p_session: job session
230  *
231  *  Return:
232  *       none
233  *
234  *  Description:
235  *       Destroy a jpeg encode session
236  *
237  **/
mm_jpegdec_session_destroy(mm_jpeg_job_session_t * p_session)238 void mm_jpegdec_session_destroy(mm_jpeg_job_session_t* p_session)
239 {
240   OMX_ERRORTYPE rc = OMX_ErrorNone;
241 
242   LOGD("E");
243   if (NULL == p_session->omx_handle) {
244     LOGE("invalid handle");
245     return;
246   }
247 
248   rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL);
249   if (rc) {
250     LOGE("Error");
251   }
252 
253   rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded,
254     mm_jpegdec_session_free_buffers);
255   if (rc) {
256     LOGE("Error");
257   }
258 
259   rc = OMX_FreeHandle(p_session->omx_handle);
260   if (0 != rc) {
261     LOGE("OMX_FreeHandle failed (%d)", rc);
262   }
263   p_session->omx_handle = NULL;
264 
265 
266   pthread_mutex_destroy(&p_session->lock);
267   pthread_cond_destroy(&p_session->cond);
268   LOGD("X");
269 }
270 
271 /** mm_jpeg_session_config_port:
272  *
273  *  Arguments:
274  *    @p_session: job session
275  *
276  *  Return:
277  *       OMX error values
278  *
279  *  Description:
280  *       Configure OMX ports
281  *
282  **/
mm_jpegdec_session_config_ports(mm_jpeg_job_session_t * p_session)283 OMX_ERRORTYPE mm_jpegdec_session_config_ports(mm_jpeg_job_session_t* p_session)
284 {
285   OMX_ERRORTYPE ret = OMX_ErrorNone;
286   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
287   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
288 
289   mm_jpeg_buf_t *p_src_buf =
290     &p_params->src_main_buf[p_jobparams->src_index];
291 
292   p_session->inputPort.nPortIndex = 0;
293   p_session->outputPort.nPortIndex = 1;
294 
295 
296   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
297     &p_session->inputPort);
298   if (ret) {
299     LOGE("failed");
300     return ret;
301   }
302 
303   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
304     &p_session->outputPort);
305   if (ret) {
306     LOGE("failed");
307     return ret;
308   }
309 
310   p_session->inputPort.format.image.nFrameWidth =
311     (OMX_U32)p_jobparams->main_dim.src_dim.width;
312   p_session->inputPort.format.image.nFrameHeight =
313     (OMX_U32)p_jobparams->main_dim.src_dim.height;
314   p_session->inputPort.format.image.nStride =
315     p_src_buf->offset.mp[0].stride;
316   p_session->inputPort.format.image.nSliceHeight =
317     (OMX_U32)p_src_buf->offset.mp[0].scanline;
318   p_session->inputPort.format.image.eColorFormat =
319     map_jpeg_format(p_params->color_format);
320   p_session->inputPort.nBufferSize =
321     p_params->src_main_buf[p_jobparams->src_index].buf_size;
322   p_session->inputPort.nBufferCountActual = (OMX_U32)p_params->num_src_bufs;
323   ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
324     &p_session->inputPort);
325   if (ret) {
326     LOGE("failed");
327     return ret;
328   }
329 
330   return ret;
331 }
332 
333 
334 /** mm_jpegdec_session_config_main:
335  *
336  *  Arguments:
337  *    @p_session: job session
338  *
339  *  Return:
340  *       OMX error values
341  *
342  *  Description:
343  *       Configure main image
344  *
345  **/
mm_jpegdec_session_config_main(mm_jpeg_job_session_t * p_session)346 OMX_ERRORTYPE mm_jpegdec_session_config_main(mm_jpeg_job_session_t *p_session)
347 {
348   OMX_ERRORTYPE rc = OMX_ErrorNone;
349 
350   /* config port */
351   LOGD("config port");
352   rc = mm_jpegdec_session_config_ports(p_session);
353   if (OMX_ErrorNone != rc) {
354     LOGE("config port failed");
355     return rc;
356   }
357 
358 
359   /* TODO: config crop */
360 
361   return rc;
362 }
363 
364 /** mm_jpeg_session_configure:
365  *
366  *  Arguments:
367  *    @data: encode session
368  *
369  *  Return:
370  *       none
371  *
372  *  Description:
373  *       Configure the session
374  *
375  **/
mm_jpegdec_session_configure(mm_jpeg_job_session_t * p_session)376 static OMX_ERRORTYPE mm_jpegdec_session_configure(mm_jpeg_job_session_t *p_session)
377 {
378   OMX_ERRORTYPE ret = OMX_ErrorNone;
379 
380   LOGD("E ");
381 
382   MM_JPEG_CHK_ABORT(p_session, ret, error);
383 
384   /* config main img */
385   ret = mm_jpegdec_session_config_main(p_session);
386   if (OMX_ErrorNone != ret) {
387     LOGE("config main img failed");
388     goto error;
389   }
390 
391   /* TODO: common config (if needed) */
392 
393   ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle,
394     mm_jpegdec_session_send_buffers);
395   if (ret) {
396     LOGE("change state to idle failed %d", ret);
397     goto error;
398   }
399 
400   ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting,
401     NULL);
402   if (ret) {
403     LOGE("change state to executing failed %d", ret);
404     goto error;
405   }
406 
407 error:
408   LOGD("X ret %d", ret);
409   return ret;
410 }
411 
mm_jpeg_session_port_enable(mm_jpeg_job_session_t * p_session,OMX_U32 nPortIndex,OMX_BOOL wait)412 static OMX_ERRORTYPE mm_jpeg_session_port_enable(
413     mm_jpeg_job_session_t *p_session,
414     OMX_U32 nPortIndex,
415     OMX_BOOL wait)
416 {
417   OMX_ERRORTYPE ret = OMX_ErrorNone;
418   OMX_EVENTTYPE lEvent;
419 
420   pthread_mutex_lock(&p_session->lock);
421   p_session->event_pending = OMX_TRUE;
422   pthread_mutex_unlock(&p_session->lock);
423 
424   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable,
425       nPortIndex, NULL);
426 
427   if (ret) {
428     LOGE("failed");
429     return ret;
430   }
431 
432   if (wait == OMX_TRUE) {
433     // Wait for cmd complete
434     pthread_mutex_lock(&p_session->lock);
435     if (p_session->event_pending == OMX_TRUE) {
436       LOGD("before wait");
437       pthread_cond_wait(&p_session->cond, &p_session->lock);
438       lEvent = p_session->omxEvent;
439       LOGD("after wait");
440     }
441     lEvent = p_session->omxEvent;
442     pthread_mutex_unlock(&p_session->lock);
443 
444     if (lEvent != OMX_EventCmdComplete) {
445       LOGD("Unexpected event %d",lEvent);
446       return OMX_ErrorUndefined;
447     }
448   }
449   return OMX_ErrorNone;
450 }
451 
mm_jpeg_session_port_disable(mm_jpeg_job_session_t * p_session,OMX_U32 nPortIndex,OMX_BOOL wait)452 static OMX_ERRORTYPE mm_jpeg_session_port_disable(
453     mm_jpeg_job_session_t *p_session,
454     OMX_U32 nPortIndex,
455     OMX_BOOL wait)
456 {
457   OMX_ERRORTYPE ret = OMX_ErrorNone;
458   OMX_EVENTTYPE lEvent;
459 
460   pthread_mutex_lock(&p_session->lock);
461   p_session->event_pending = OMX_TRUE;
462   pthread_mutex_unlock(&p_session->lock);
463 
464   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable,
465       nPortIndex, NULL);
466 
467   if (ret) {
468     LOGE("failed");
469     return ret;
470   }
471   if (wait == OMX_TRUE) {
472     // Wait for cmd complete
473     pthread_mutex_lock(&p_session->lock);
474     if (p_session->event_pending == OMX_TRUE) {
475       LOGD("before wait");
476       pthread_cond_wait(&p_session->cond, &p_session->lock);
477 
478       LOGD("after wait");
479     }
480     lEvent = p_session->omxEvent;
481     pthread_mutex_unlock(&p_session->lock);
482 
483     if (lEvent != OMX_EventCmdComplete) {
484       LOGD("Unexpected event %d",lEvent);
485       return OMX_ErrorUndefined;
486     }
487   }
488   return OMX_ErrorNone;
489 }
490 
491 
492 /** mm_jpegdec_session_decode:
493  *
494  *  Arguments:
495  *    @p_session: encode session
496  *
497  *  Return:
498  *       OMX_ERRORTYPE
499  *
500  *  Description:
501  *       Start the encoding
502  *
503  **/
mm_jpegdec_session_decode(mm_jpeg_job_session_t * p_session)504 static OMX_ERRORTYPE mm_jpegdec_session_decode(mm_jpeg_job_session_t *p_session)
505 {
506   OMX_ERRORTYPE ret = OMX_ErrorNone;
507   mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
508   mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
509   OMX_EVENTTYPE lEvent;
510   uint32_t i;
511   QOMX_BUFFER_INFO lbuffer_info;
512 
513   pthread_mutex_lock(&p_session->lock);
514   p_session->abort_state = MM_JPEG_ABORT_NONE;
515   p_session->encoding = OMX_FALSE;
516   pthread_mutex_unlock(&p_session->lock);
517 
518   if (OMX_FALSE == p_session->config) {
519     ret = mm_jpegdec_session_configure(p_session);
520     if (ret) {
521       LOGE("Error");
522       goto error;
523     }
524     p_session->config = OMX_TRUE;
525   }
526 
527   pthread_mutex_lock(&p_session->lock);
528   p_session->encoding = OMX_TRUE;
529   pthread_mutex_unlock(&p_session->lock);
530 
531   MM_JPEG_CHK_ABORT(p_session, ret, error);
532 
533   p_session->event_pending = OMX_TRUE;
534 
535   ret = OMX_EmptyThisBuffer(p_session->omx_handle,
536     p_session->p_in_omx_buf[p_jobparams->src_index]);
537   if (ret) {
538     LOGE("Error");
539     goto error;
540   }
541 
542   // Wait for port settings changed
543   pthread_mutex_lock(&p_session->lock);
544   if (p_session->event_pending == OMX_TRUE) {
545     LOGD("before wait");
546     pthread_cond_wait(&p_session->cond, &p_session->lock);
547   }
548   lEvent = p_session->omxEvent;
549   LOGD("after wait");
550   pthread_mutex_unlock(&p_session->lock);
551 
552   if (lEvent != OMX_EventPortSettingsChanged) {
553     LOGD("Unexpected event %d",lEvent);
554     goto error;
555   }
556 
557   // Disable output port (wait)
558   mm_jpeg_session_port_disable(p_session,
559       p_session->outputPort.nPortIndex,
560       OMX_TRUE);
561 
562   // Get port definition
563   ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
564       &p_session->outputPort);
565   if (ret) {
566     LOGE("failed");
567     return ret;
568   }
569 
570   // Set port definition
571   p_session->outputPort.format.image.nFrameWidth =
572     (OMX_U32)p_jobparams->main_dim.dst_dim.width;
573   p_session->outputPort.format.image.nFrameHeight =
574     (OMX_U32)p_jobparams->main_dim.dst_dim.height;
575   p_session->outputPort.format.image.eColorFormat =
576     map_jpeg_format(p_params->color_format);
577 
578   p_session->outputPort.nBufferSize =
579      p_params->dest_buf[p_jobparams->dst_index].buf_size;
580    p_session->outputPort.nBufferCountActual = (OMX_U32)p_params->num_dst_bufs;
581 
582    p_session->outputPort.format.image.nSliceHeight =
583        (OMX_U32)
584        p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].scanline;
585    p_session->outputPort.format.image.nStride =
586        p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].stride;
587 
588    ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
589      &p_session->outputPort);
590    if (ret) {
591      LOGE("failed");
592      return ret;
593    }
594 
595   // Enable port (no wait)
596   mm_jpeg_session_port_enable(p_session,
597       p_session->outputPort.nPortIndex,
598       OMX_FALSE);
599 
600   memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
601   // Use buffers
602   for (i = 0; i < p_params->num_dst_bufs; i++) {
603     lbuffer_info.fd = (OMX_U32)p_params->dest_buf[i].fd;
604     LOGD("Dest buffer %d", (unsigned int)i);
605     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]),
606         1, &lbuffer_info, p_params->dest_buf[i].buf_size,
607         p_params->dest_buf[i].buf_vaddr);
608     if (ret) {
609       LOGE("Error");
610       return ret;
611     }
612   }
613 
614   // Wait for port enable completion
615   pthread_mutex_lock(&p_session->lock);
616   if (p_session->event_pending == OMX_TRUE) {
617     LOGD("before wait");
618     pthread_cond_wait(&p_session->cond, &p_session->lock);
619     lEvent = p_session->omxEvent;
620     LOGD("after wait");
621   }
622   lEvent = p_session->omxEvent;
623   pthread_mutex_unlock(&p_session->lock);
624 
625   if (lEvent != OMX_EventCmdComplete) {
626     LOGD("Unexpected event %d",lEvent);
627     goto error;
628   }
629 
630   ret = OMX_FillThisBuffer(p_session->omx_handle,
631     p_session->p_out_omx_buf[p_jobparams->dst_index]);
632   if (ret) {
633     LOGE("Error");
634     goto error;
635   }
636 
637   MM_JPEG_CHK_ABORT(p_session, ret, error);
638 
639 error:
640 
641   LOGD("X ");
642   return ret;
643 }
644 
645 /** mm_jpegdec_process_decoding_job:
646  *
647  *  Arguments:
648  *    @my_obj: jpeg client
649  *    @job_node: job node
650  *
651  *  Return:
652  *       0 for success -1 otherwise
653  *
654  *  Description:
655  *       Start the encoding job
656  *
657  **/
mm_jpegdec_process_decoding_job(mm_jpeg_obj * my_obj,mm_jpeg_job_q_node_t * job_node)658 int32_t mm_jpegdec_process_decoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
659 {
660   mm_jpeg_q_data_t qdata;
661   int32_t rc = 0;
662   OMX_ERRORTYPE ret = OMX_ErrorNone;
663   mm_jpeg_job_session_t *p_session = NULL;
664 
665   /* check if valid session */
666   p_session = mm_jpeg_get_session(my_obj, job_node->dec_info.job_id);
667   if (NULL == p_session) {
668     LOGE("invalid job id %x",
669       job_node->dec_info.job_id);
670     return -1;
671   }
672 
673   /* sent encode cmd to OMX, queue job into ongoing queue */
674   qdata.p = job_node;
675   rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, qdata);
676   if (rc) {
677     LOGE("jpeg enqueue failed %d", ret);
678     goto error;
679   }
680 
681   p_session->decode_job = job_node->dec_info.decode_job;
682   p_session->jobId = job_node->dec_info.job_id;
683   ret = mm_jpegdec_session_decode(p_session);
684   if (ret) {
685     LOGE("encode session failed");
686     goto error;
687   }
688 
689   LOGD("Success X ");
690   return rc;
691 
692 error:
693 
694   if ((OMX_ErrorNone != ret) &&
695     (NULL != p_session->dec_params.jpeg_cb)) {
696     p_session->job_status = JPEG_JOB_STATUS_ERROR;
697     LOGD("send jpeg error callback %d",
698       p_session->job_status);
699     p_session->dec_params.jpeg_cb(p_session->job_status,
700       p_session->client_hdl,
701       p_session->jobId,
702       NULL,
703       p_session->dec_params.userdata);
704   }
705 
706   /*remove the job*/
707   mm_jpegdec_job_done(p_session);
708   LOGD("Error X ");
709 
710   return rc;
711 }
712 
713 /** mm_jpeg_start_decode_job:
714  *
715  *  Arguments:
716  *    @my_obj: jpeg object
717  *    @client_hdl: client handle
718  *    @job: pointer to encode job
719  *    @jobId: job id
720  *
721  *  Return:
722  *       0 for success else failure
723  *
724  *  Description:
725  *       Start the encoding job
726  *
727  **/
mm_jpegdec_start_decode_job(mm_jpeg_obj * my_obj,mm_jpeg_job_t * job,uint32_t * job_id)728 int32_t mm_jpegdec_start_decode_job(mm_jpeg_obj *my_obj,
729   mm_jpeg_job_t *job,
730   uint32_t *job_id)
731 {
732   mm_jpeg_q_data_t qdata;
733   int32_t rc = -1;
734   uint8_t session_idx = 0;
735   uint8_t client_idx = 0;
736   mm_jpeg_job_q_node_t* node = NULL;
737   mm_jpeg_job_session_t *p_session = NULL;
738   mm_jpeg_decode_job_t *p_jobparams  = &job->decode_job;
739 
740   *job_id = 0;
741 
742   /* check if valid session */
743   session_idx = GET_SESSION_IDX(p_jobparams->session_id);
744   client_idx = GET_CLIENT_IDX(p_jobparams->session_id);
745   LOGD("session_idx %d client idx %d",
746     session_idx, client_idx);
747 
748   if ((session_idx >= MM_JPEG_MAX_SESSION) ||
749     (client_idx >= MAX_JPEG_CLIENT_NUM)) {
750     LOGE("invalid session id %x",
751       job->decode_job.session_id);
752     return rc;
753   }
754 
755   p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
756   if (OMX_FALSE == p_session->active) {
757     LOGE("session not active %x",
758       job->decode_job.session_id);
759     return rc;
760   }
761 
762   if ((p_jobparams->src_index >= (int32_t)p_session->dec_params.num_src_bufs) ||
763     (p_jobparams->dst_index >= (int32_t)p_session->dec_params.num_dst_bufs)) {
764     LOGE("invalid buffer indices");
765     return rc;
766   }
767 
768   /* enqueue new job into todo job queue */
769   node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
770   if (NULL == node) {
771     LOGE("No memory for mm_jpeg_job_q_node_t");
772     return -1;
773   }
774 
775   *job_id = job->decode_job.session_id |
776     ((p_session->job_hist++ % JOB_HIST_MAX) << 16);
777 
778   memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
779   node->dec_info.decode_job = job->decode_job;
780   node->dec_info.job_id = *job_id;
781   node->dec_info.client_handle = p_session->client_hdl;
782   node->type = MM_JPEG_CMD_TYPE_DECODE_JOB;
783 
784   qdata.p = node;
785   rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, qdata);
786   if (0 == rc) {
787     cam_sem_post(&my_obj->job_mgr.job_sem);
788   }
789 
790   return rc;
791 }
792 
793 /** mm_jpegdec_create_session:
794  *
795  *  Arguments:
796  *    @my_obj: jpeg object
797  *    @client_hdl: client handle
798  *    @p_params: pointer to encode params
799  *    @p_session_id: session id
800  *
801  *  Return:
802  *       0 for success else failure
803  *
804  *  Description:
805  *       Start the encoding session
806  *
807  **/
mm_jpegdec_create_session(mm_jpeg_obj * my_obj,uint32_t client_hdl,mm_jpeg_decode_params_t * p_params,uint32_t * p_session_id)808 int32_t mm_jpegdec_create_session(mm_jpeg_obj *my_obj,
809   uint32_t client_hdl,
810   mm_jpeg_decode_params_t *p_params,
811   uint32_t* p_session_id)
812 {
813   int32_t rc = 0;
814   OMX_ERRORTYPE ret = OMX_ErrorNone;
815   uint8_t clnt_idx = 0;
816   int session_idx = -1;
817   mm_jpeg_job_session_t *p_session = NULL;
818   *p_session_id = 0;
819 
820   /* validate the parameters */
821   if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF)
822     || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) {
823     LOGE("invalid num buffers");
824     return rc;
825   }
826 
827   /* check if valid client */
828   clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
829   if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
830     LOGE("invalid client with handler (%d)", client_hdl);
831     return rc;
832   }
833 
834   session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session);
835   if (session_idx < 0) {
836     LOGE("invalid session id (%d)", session_idx);
837     return rc;
838   }
839 
840   ret = mm_jpegdec_session_create(p_session);
841   if (OMX_ErrorNone != ret) {
842     p_session->active = OMX_FALSE;
843     LOGE("jpeg session create failed");
844     return rc;
845   }
846 
847   *p_session_id = (JOB_ID_MAGICVAL << 24) |
848     ((unsigned)session_idx << 8) | clnt_idx;
849 
850   /*copy the params*/
851   p_session->dec_params = *p_params;
852   p_session->client_hdl = client_hdl;
853   p_session->sessionId = *p_session_id;
854   p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */
855   LOGD("session id %x", *p_session_id);
856 
857   return rc;
858 }
859 
860 /** mm_jpegdec_destroy_session:
861  *
862  *  Arguments:
863  *    @my_obj: jpeg object
864  *    @session_id: session index
865  *
866  *  Return:
867  *       0 for success else failure
868  *
869  *  Description:
870  *       Destroy the encoding session
871  *
872  **/
mm_jpegdec_destroy_session(mm_jpeg_obj * my_obj,mm_jpeg_job_session_t * p_session)873 int32_t mm_jpegdec_destroy_session(mm_jpeg_obj *my_obj,
874   mm_jpeg_job_session_t *p_session)
875 {
876   int32_t rc = 0;
877   mm_jpeg_job_q_node_t *node = NULL;
878 
879   if (NULL == p_session) {
880     LOGE("invalid session");
881     return rc;
882   }
883   uint32_t session_id = p_session->sessionId;
884   pthread_mutex_lock(&my_obj->job_lock);
885 
886   /* abort job if in todo queue */
887   LOGD("abort todo jobs");
888   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
889   while (NULL != node) {
890     free(node);
891     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
892   }
893 
894   /* abort job if in ongoing queue */
895   LOGD("abort ongoing jobs");
896   node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
897   while (NULL != node) {
898     free(node);
899     node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
900   }
901 
902   /* abort the current session */
903   mm_jpeg_session_abort(p_session);
904   mm_jpegdec_session_destroy(p_session);
905   mm_jpeg_remove_session_idx(my_obj, session_id);
906   pthread_mutex_unlock(&my_obj->job_lock);
907 
908   /* wake up jobMgr thread to work on new job if there is any */
909   cam_sem_post(&my_obj->job_mgr.job_sem);
910   LOGD("X");
911 
912   return rc;
913 }
914 
915 /** mm_jpegdec_destroy_session_by_id:
916  *
917  *  Arguments:
918  *    @my_obj: jpeg object
919  *    @session_id: session index
920  *
921  *  Return:
922  *       0 for success else failure
923  *
924  *  Description:
925  *       Destroy the encoding session
926  *
927  **/
mm_jpegdec_destroy_session_by_id(mm_jpeg_obj * my_obj,uint32_t session_id)928 int32_t mm_jpegdec_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id)
929 {
930   int32_t rc = 0;
931   mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id);
932 
933   if (NULL == p_session) {
934     LOGE("session is not valid");
935     return rc;
936   }
937 
938   return mm_jpegdec_destroy_session(my_obj, p_session);
939 }
940 
941 
942 
mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_BUFFERHEADERTYPE * pBuffer)943 OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,
944   OMX_PTR pAppData,
945   OMX_BUFFERHEADERTYPE *pBuffer)
946 {
947   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
948 
949   LOGD("count %d ", p_session->ebd_count);
950   pthread_mutex_lock(&p_session->lock);
951   p_session->ebd_count++;
952   pthread_mutex_unlock(&p_session->lock);
953   return 0;
954 }
955 
mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_BUFFERHEADERTYPE * pBuffer)956 OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,
957   OMX_PTR pAppData,
958   OMX_BUFFERHEADERTYPE *pBuffer)
959 {
960   OMX_ERRORTYPE ret = OMX_ErrorNone;
961   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
962   mm_jpeg_output_t output_buf;
963 
964   LOGD("count %d ", p_session->fbd_count);
965 
966   pthread_mutex_lock(&p_session->lock);
967 
968   if (MM_JPEG_ABORT_NONE != p_session->abort_state) {
969     pthread_mutex_unlock(&p_session->lock);
970     return ret;
971   }
972 
973   p_session->fbd_count++;
974   if (NULL != p_session->dec_params.jpeg_cb) {
975     p_session->job_status = JPEG_JOB_STATUS_DONE;
976     output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen;
977     output_buf.buf_vaddr = pBuffer->pBuffer;
978     output_buf.fd = -1;
979     LOGD("send jpeg callback %d",
980       p_session->job_status);
981     p_session->dec_params.jpeg_cb(p_session->job_status,
982       p_session->client_hdl,
983       p_session->jobId,
984       &output_buf,
985       p_session->dec_params.userdata);
986 
987     /* remove from ready queue */
988     mm_jpegdec_job_done(p_session);
989   }
990   pthread_mutex_unlock(&p_session->lock);
991   LOGD("Exit");
992 
993   return ret;
994 }
995 
mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_EVENTTYPE eEvent,OMX_U32 nData1,OMX_U32 nData2,OMX_PTR pEventData)996 OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent,
997   OMX_PTR pAppData,
998   OMX_EVENTTYPE eEvent,
999   OMX_U32 nData1,
1000   OMX_U32 nData2,
1001   OMX_PTR pEventData)
1002 {
1003   mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
1004 
1005   LOGD("%d %d %d state %d", eEvent, (int)nData1,
1006     (int)nData2, p_session->abort_state);
1007 
1008   LOGD("AppData=%p ", pAppData);
1009 
1010   pthread_mutex_lock(&p_session->lock);
1011   p_session->omxEvent = eEvent;
1012   if (MM_JPEG_ABORT_INIT == p_session->abort_state) {
1013     p_session->abort_state = MM_JPEG_ABORT_DONE;
1014     pthread_cond_signal(&p_session->cond);
1015     pthread_mutex_unlock(&p_session->lock);
1016     return OMX_ErrorNone;
1017   }
1018 
1019   if (eEvent == OMX_EventError) {
1020     if (p_session->encoding == OMX_TRUE) {
1021       LOGD("Error during encoding");
1022 
1023       /* send jpeg callback */
1024       if (NULL != p_session->dec_params.jpeg_cb) {
1025         p_session->job_status = JPEG_JOB_STATUS_ERROR;
1026         LOGD("send jpeg error callback %d",
1027           p_session->job_status);
1028         p_session->dec_params.jpeg_cb(p_session->job_status,
1029           p_session->client_hdl,
1030           p_session->jobId,
1031           NULL,
1032           p_session->dec_params.userdata);
1033       }
1034 
1035       /* remove from ready queue */
1036       mm_jpegdec_job_done(p_session);
1037     }
1038     pthread_cond_signal(&p_session->cond);
1039   } else if (eEvent == OMX_EventCmdComplete) {
1040     p_session->state_change_pending = OMX_FALSE;
1041     p_session->event_pending = OMX_FALSE;
1042     pthread_cond_signal(&p_session->cond);
1043   }  else if (eEvent == OMX_EventPortSettingsChanged) {
1044     p_session->event_pending = OMX_FALSE;
1045     pthread_cond_signal(&p_session->cond);
1046   }
1047 
1048   pthread_mutex_unlock(&p_session->lock);
1049   LOGD("Exit");
1050   return OMX_ErrorNone;
1051 }
1052 
1053 /** mm_jpegdec_abort_job:
1054  *
1055  *  Arguments:
1056  *    @my_obj: jpeg object
1057  *    @client_hdl: client handle
1058  *    @jobId: job id
1059  *
1060  *  Return:
1061  *       0 for success else failure
1062  *
1063  *  Description:
1064  *       Abort the encoding session
1065  *
1066  **/
mm_jpegdec_abort_job(mm_jpeg_obj * my_obj,uint32_t jobId)1067 int32_t mm_jpegdec_abort_job(mm_jpeg_obj *my_obj,
1068   uint32_t jobId)
1069 {
1070   int32_t rc = -1;
1071   mm_jpeg_job_q_node_t *node = NULL;
1072   mm_jpeg_job_session_t *p_session = NULL;
1073 
1074   LOGD("Enter");
1075   pthread_mutex_lock(&my_obj->job_lock);
1076 
1077   /* abort job if in todo queue */
1078   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId);
1079   if (NULL != node) {
1080     free(node);
1081     goto abort_done;
1082   }
1083 
1084   /* abort job if in ongoing queue */
1085   node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId);
1086   if (NULL != node) {
1087     /* find job that is OMX ongoing, ask OMX to abort the job */
1088     p_session = mm_jpeg_get_session(my_obj, node->dec_info.job_id);
1089     if (p_session) {
1090       mm_jpeg_session_abort(p_session);
1091     } else {
1092       LOGE("Invalid job id 0x%x",
1093         node->dec_info.job_id);
1094     }
1095     free(node);
1096     goto abort_done;
1097   }
1098 
1099 abort_done:
1100   pthread_mutex_unlock(&my_obj->job_lock);
1101 
1102   return rc;
1103 }
1104 /** mm_jpegdec_init:
1105  *
1106  *  Arguments:
1107  *    @my_obj: jpeg object
1108  *
1109  *  Return:
1110  *       0 for success else failure
1111  *
1112  *  Description:
1113  *       Initializes the jpeg client
1114  *
1115  **/
mm_jpegdec_init(mm_jpeg_obj * my_obj)1116 int32_t mm_jpegdec_init(mm_jpeg_obj *my_obj)
1117 {
1118   int32_t rc = 0;
1119 
1120   /* init locks */
1121   pthread_mutex_init(&my_obj->job_lock, NULL);
1122 
1123   /* init ongoing job queue */
1124   rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q);
1125   if (0 != rc) {
1126     LOGE("Error");
1127     return -1;
1128   }
1129 
1130   /* init job semaphore and launch jobmgr thread */
1131   LOGD("Launch jobmgr thread rc %d", rc);
1132   rc = mm_jpeg_jobmgr_thread_launch(my_obj);
1133   if (0 != rc) {
1134     LOGE("Error");
1135     return -1;
1136   }
1137 
1138   /* load OMX */
1139   if (OMX_ErrorNone != OMX_Init()) {
1140     /* roll back in error case */
1141     LOGE("OMX_Init failed (%d)", rc);
1142     mm_jpeg_jobmgr_thread_release(my_obj);
1143     mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1144     pthread_mutex_destroy(&my_obj->job_lock);
1145   }
1146 
1147   return rc;
1148 }
1149 
1150 /** mm_jpegdec_deinit:
1151  *
1152  *  Arguments:
1153  *    @my_obj: jpeg object
1154  *
1155  *  Return:
1156  *       0 for success else failure
1157  *
1158  *  Description:
1159  *       Deinits the jpeg client
1160  *
1161  **/
mm_jpegdec_deinit(mm_jpeg_obj * my_obj)1162 int32_t mm_jpegdec_deinit(mm_jpeg_obj *my_obj)
1163 {
1164   int32_t rc = 0;
1165 
1166   /* release jobmgr thread */
1167   rc = mm_jpeg_jobmgr_thread_release(my_obj);
1168   if (0 != rc) {
1169     LOGE("Error");
1170   }
1171 
1172   /* unload OMX engine */
1173   OMX_Deinit();
1174 
1175   /* deinit ongoing job and cb queue */
1176   rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1177   if (0 != rc) {
1178     LOGE("Error");
1179   }
1180 
1181   /* destroy locks */
1182   pthread_mutex_destroy(&my_obj->job_lock);
1183 
1184   return rc;
1185 }
1186