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