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