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