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