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