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