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