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
39OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,
40  OMX_PTR pAppData,
41  OMX_BUFFERHEADERTYPE *pBuffer);
42OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,
43    OMX_PTR pAppData,
44    OMX_BUFFERHEADERTYPE* pBuffer);
45OMX_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 **/
65static 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 **/
84static 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 **/
117OMX_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 **/
154OMX_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 **/
194OMX_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 **/
238void 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 **/
283OMX_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 **/
346OMX_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 **/
376static 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
407error:
408  LOGD("X ret %d", ret);
409  return ret;
410}
411
412static 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
452static 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 **/
504static 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
639error:
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 **/
658int32_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
692error:
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 **/
728int32_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 **/
808int32_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 **/
873int32_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 **/
928int32_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
943OMX_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
956OMX_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
996OMX_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 **/
1067int32_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
1099abort_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 **/
1116int32_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 **/
1162int32_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