1 /* Copyright (c) 2013-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 <fcntl.h>
36 #include <poll.h>
37
38 #include "mm_jpeg_dbg.h"
39 #include "mm_jpeg_interface.h"
40 #include "mm_jpeg.h"
41 #include "mm_jpeg_inlines.h"
42
43 OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,
44 OMX_PTR pAppData,
45 OMX_BUFFERHEADERTYPE *pBuffer);
46 OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,
47 OMX_PTR pAppData,
48 OMX_BUFFERHEADERTYPE* pBuffer);
49 OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent,
50 OMX_PTR pAppData,
51 OMX_EVENTTYPE eEvent,
52 OMX_U32 nData1,
53 OMX_U32 nData2,
54 OMX_PTR pEventData);
55
56
57 /** mm_jpegdec_destroy_job
58 *
59 * Arguments:
60 * @p_session: Session obj
61 *
62 * Return:
63 * 0 for success else failure
64 *
65 * Description:
66 * Destroy the job based paramenters
67 *
68 **/
mm_jpegdec_destroy_job(mm_jpeg_job_session_t * p_session)69 static int32_t mm_jpegdec_destroy_job(mm_jpeg_job_session_t *p_session)
70 {
71 int32_t rc = 0;
72
73 return rc;
74 }
75
76 /** mm_jpeg_job_done:
77 *
78 * Arguments:
79 * @p_session: decode session
80 *
81 * Return:
82 * OMX_ERRORTYPE
83 *
84 * Description:
85 * Finalize the job
86 *
87 **/
mm_jpegdec_job_done(mm_jpeg_job_session_t * p_session)88 static void mm_jpegdec_job_done(mm_jpeg_job_session_t *p_session)
89 {
90 mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
91 mm_jpeg_job_q_node_t *node = NULL;
92
93 /*Destroy job related params*/
94 mm_jpegdec_destroy_job(p_session);
95
96 /*remove the job*/
97 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
98 p_session->jobId);
99 if (node) {
100 free(node);
101 }
102 p_session->encoding = OMX_FALSE;
103
104 /* wake up jobMgr thread to work on new job if there is any */
105 cam_sem_post(&my_obj->job_mgr.job_sem);
106 }
107
108
109 /** mm_jpegdec_session_send_buffers:
110 *
111 * Arguments:
112 * @data: job session
113 *
114 * Return:
115 * OMX error values
116 *
117 * Description:
118 * Send the buffers to OMX layer
119 *
120 **/
mm_jpegdec_session_send_buffers(void * data)121 OMX_ERRORTYPE mm_jpegdec_session_send_buffers(void *data)
122 {
123 uint32_t i = 0;
124 mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
125 OMX_ERRORTYPE ret = OMX_ErrorNone;
126 QOMX_BUFFER_INFO lbuffer_info;
127 mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
128
129 memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
130 for (i = 0; i < p_params->num_src_bufs; i++) {
131 CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
132 lbuffer_info.fd = (OMX_U32)p_params->src_main_buf[i].fd;
133 ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0,
134 &lbuffer_info, p_params->src_main_buf[i].buf_size,
135 p_params->src_main_buf[i].buf_vaddr);
136 if (ret) {
137 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
138 return ret;
139 }
140 }
141
142 CDBG("%s:%d]", __func__, __LINE__);
143 return ret;
144 }
145
146 /** mm_jpeg_session_free_buffers:
147 *
148 * Arguments:
149 * @data: job session
150 *
151 * Return:
152 * OMX error values
153 *
154 * Description:
155 * Free the buffers from OMX layer
156 *
157 **/
mm_jpegdec_session_free_buffers(void * data)158 OMX_ERRORTYPE mm_jpegdec_session_free_buffers(void *data)
159 {
160 OMX_ERRORTYPE ret = OMX_ErrorNone;
161 uint32_t i = 0;
162 mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data;
163 mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
164
165 for (i = 0; i < p_params->num_src_bufs; i++) {
166 CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i);
167 ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]);
168 if (ret) {
169 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret);
170 return ret;
171 }
172 }
173
174 for (i = 0; i < p_params->num_dst_bufs; i++) {
175 CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i);
176 ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]);
177 if (ret) {
178 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
179 return ret;
180 }
181 }
182 CDBG("%s:%d]", __func__, __LINE__);
183 return ret;
184 }
185
186 /** mm_jpegdec_session_create:
187 *
188 * Arguments:
189 * @p_session: job session
190 *
191 * Return:
192 * OMX error types
193 *
194 * Description:
195 * Create a jpeg encode session
196 *
197 **/
mm_jpegdec_session_create(mm_jpeg_job_session_t * p_session)198 OMX_ERRORTYPE mm_jpegdec_session_create(mm_jpeg_job_session_t* p_session)
199 {
200 OMX_ERRORTYPE rc = OMX_ErrorNone;
201
202 pthread_mutex_init(&p_session->lock, NULL);
203 pthread_cond_init(&p_session->cond, NULL);
204 cirq_reset(&p_session->cb_q);
205 p_session->state_change_pending = OMX_FALSE;
206 p_session->abort_state = MM_JPEG_ABORT_NONE;
207 p_session->error_flag = OMX_ErrorNone;
208 p_session->ebd_count = 0;
209 p_session->fbd_count = 0;
210 p_session->encode_pid = -1;
211 p_session->config = OMX_FALSE;
212
213 p_session->omx_callbacks.EmptyBufferDone = mm_jpegdec_ebd;
214 p_session->omx_callbacks.FillBufferDone = mm_jpegdec_fbd;
215 p_session->omx_callbacks.EventHandler = mm_jpegdec_event_handler;
216 p_session->exif_count_local = 0;
217
218 rc = OMX_GetHandle(&p_session->omx_handle,
219 "OMX.qcom.image.jpeg.decoder",
220 (void *)p_session,
221 &p_session->omx_callbacks);
222
223 if (OMX_ErrorNone != rc) {
224 CDBG_ERROR("%s:%d] OMX_GetHandle failed (%d)", __func__, __LINE__, rc);
225 return rc;
226 }
227 return rc;
228 }
229
230 /** mm_jpegdec_session_destroy:
231 *
232 * Arguments:
233 * @p_session: job session
234 *
235 * Return:
236 * none
237 *
238 * Description:
239 * Destroy a jpeg encode session
240 *
241 **/
mm_jpegdec_session_destroy(mm_jpeg_job_session_t * p_session)242 void mm_jpegdec_session_destroy(mm_jpeg_job_session_t* p_session)
243 {
244 OMX_ERRORTYPE rc = OMX_ErrorNone;
245
246 CDBG("%s:%d] E", __func__, __LINE__);
247 if (NULL == p_session->omx_handle) {
248 CDBG_ERROR("%s:%d] invalid handle", __func__, __LINE__);
249 return;
250 }
251
252 rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL);
253 if (rc) {
254 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
255 }
256
257 rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded,
258 mm_jpegdec_session_free_buffers);
259 if (rc) {
260 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
261 }
262
263 rc = OMX_FreeHandle(p_session->omx_handle);
264 if (0 != rc) {
265 CDBG_ERROR("%s:%d] OMX_FreeHandle failed (%d)", __func__, __LINE__, rc);
266 }
267 p_session->omx_handle = NULL;
268
269
270 pthread_mutex_destroy(&p_session->lock);
271 pthread_cond_destroy(&p_session->cond);
272 CDBG("%s:%d] X", __func__, __LINE__);
273 }
274
275 /** mm_jpeg_session_config_port:
276 *
277 * Arguments:
278 * @p_session: job session
279 *
280 * Return:
281 * OMX error values
282 *
283 * Description:
284 * Configure OMX ports
285 *
286 **/
mm_jpegdec_session_config_ports(mm_jpeg_job_session_t * p_session)287 OMX_ERRORTYPE mm_jpegdec_session_config_ports(mm_jpeg_job_session_t* p_session)
288 {
289 OMX_ERRORTYPE ret = OMX_ErrorNone;
290 mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
291 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
292
293 mm_jpeg_buf_t *p_src_buf =
294 &p_params->src_main_buf[p_jobparams->src_index];
295
296 p_session->inputPort.nPortIndex = 0;
297 p_session->outputPort.nPortIndex = 1;
298
299
300 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
301 &p_session->inputPort);
302 if (ret) {
303 CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
304 return ret;
305 }
306
307 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
308 &p_session->outputPort);
309 if (ret) {
310 CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
311 return ret;
312 }
313
314 p_session->inputPort.format.image.nFrameWidth =
315 (OMX_U32)p_jobparams->main_dim.src_dim.width;
316 p_session->inputPort.format.image.nFrameHeight =
317 (OMX_U32)p_jobparams->main_dim.src_dim.height;
318 p_session->inputPort.format.image.nStride =
319 p_src_buf->offset.mp[0].stride;
320 p_session->inputPort.format.image.nSliceHeight =
321 (OMX_U32)p_src_buf->offset.mp[0].scanline;
322 p_session->inputPort.format.image.eColorFormat =
323 map_jpeg_format(p_params->color_format);
324 p_session->inputPort.nBufferSize =
325 p_params->src_main_buf[p_jobparams->src_index].buf_size;
326 p_session->inputPort.nBufferCountActual = (OMX_U32)p_params->num_src_bufs;
327 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
328 &p_session->inputPort);
329 if (ret) {
330 CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
331 return ret;
332 }
333
334 return ret;
335 }
336
337
338 /** mm_jpegdec_session_config_main:
339 *
340 * Arguments:
341 * @p_session: job session
342 *
343 * Return:
344 * OMX error values
345 *
346 * Description:
347 * Configure main image
348 *
349 **/
mm_jpegdec_session_config_main(mm_jpeg_job_session_t * p_session)350 OMX_ERRORTYPE mm_jpegdec_session_config_main(mm_jpeg_job_session_t *p_session)
351 {
352 OMX_ERRORTYPE rc = OMX_ErrorNone;
353
354 /* config port */
355 CDBG("%s:%d] config port", __func__, __LINE__);
356 rc = mm_jpegdec_session_config_ports(p_session);
357 if (OMX_ErrorNone != rc) {
358 CDBG_ERROR("%s: config port failed", __func__);
359 return rc;
360 }
361
362
363 /* TODO: config crop */
364
365 return rc;
366 }
367
368 /** mm_jpeg_session_configure:
369 *
370 * Arguments:
371 * @data: encode session
372 *
373 * Return:
374 * none
375 *
376 * Description:
377 * Configure the session
378 *
379 **/
mm_jpegdec_session_configure(mm_jpeg_job_session_t * p_session)380 static OMX_ERRORTYPE mm_jpegdec_session_configure(mm_jpeg_job_session_t *p_session)
381 {
382 OMX_ERRORTYPE ret = OMX_ErrorNone;
383
384 CDBG("%s:%d] E ", __func__, __LINE__);
385
386 MM_JPEG_CHK_ABORT(p_session, ret, error);
387
388 /* config main img */
389 ret = mm_jpegdec_session_config_main(p_session);
390 if (OMX_ErrorNone != ret) {
391 CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__);
392 goto error;
393 }
394
395 /* TODO: common config (if needed) */
396
397 ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle,
398 mm_jpegdec_session_send_buffers);
399 if (ret) {
400 CDBG_ERROR("%s:%d] change state to idle failed %d",
401 __func__, __LINE__, ret);
402 goto error;
403 }
404
405 ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting,
406 NULL);
407 if (ret) {
408 CDBG_ERROR("%s:%d] change state to executing failed %d",
409 __func__, __LINE__, ret);
410 goto error;
411 }
412
413 error:
414 CDBG("%s:%d] X ret %d", __func__, __LINE__, ret);
415 return ret;
416 }
417
mm_jpeg_session_port_enable(mm_jpeg_job_session_t * p_session,OMX_U32 nPortIndex,OMX_BOOL wait)418 static OMX_ERRORTYPE mm_jpeg_session_port_enable(
419 mm_jpeg_job_session_t *p_session,
420 OMX_U32 nPortIndex,
421 OMX_BOOL wait)
422 {
423 OMX_ERRORTYPE ret = OMX_ErrorNone;
424 OMX_EVENTTYPE lEvent;
425
426 pthread_mutex_lock(&p_session->lock);
427 p_session->event_pending = OMX_TRUE;
428 pthread_mutex_unlock(&p_session->lock);
429
430 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable,
431 nPortIndex, NULL);
432
433 if (ret) {
434 CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
435 return ret;
436 }
437
438 if (wait == OMX_TRUE) {
439 // Wait for cmd complete
440 pthread_mutex_lock(&p_session->lock);
441 if (p_session->event_pending == OMX_TRUE) {
442 CDBG("%s:%d] before wait", __func__, __LINE__);
443 pthread_cond_wait(&p_session->cond, &p_session->lock);
444 lEvent = p_session->omxEvent;
445 CDBG("%s:%d] after wait", __func__, __LINE__);
446 }
447 lEvent = p_session->omxEvent;
448 pthread_mutex_unlock(&p_session->lock);
449
450 if (lEvent != OMX_EventCmdComplete) {
451 CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent);
452 return OMX_ErrorUndefined;
453 }
454 }
455 return OMX_ErrorNone;
456 }
457
mm_jpeg_session_port_disable(mm_jpeg_job_session_t * p_session,OMX_U32 nPortIndex,OMX_BOOL wait)458 static OMX_ERRORTYPE mm_jpeg_session_port_disable(
459 mm_jpeg_job_session_t *p_session,
460 OMX_U32 nPortIndex,
461 OMX_BOOL wait)
462 {
463 OMX_ERRORTYPE ret = OMX_ErrorNone;
464 OMX_EVENTTYPE lEvent;
465
466 pthread_mutex_lock(&p_session->lock);
467 p_session->event_pending = OMX_TRUE;
468 pthread_mutex_unlock(&p_session->lock);
469
470 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable,
471 nPortIndex, NULL);
472
473 if (ret) {
474 CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
475 return ret;
476 }
477 if (wait == OMX_TRUE) {
478 // Wait for cmd complete
479 pthread_mutex_lock(&p_session->lock);
480 if (p_session->event_pending == OMX_TRUE) {
481 CDBG("%s:%d] before wait", __func__, __LINE__);
482 pthread_cond_wait(&p_session->cond, &p_session->lock);
483
484 CDBG("%s:%d] after wait", __func__, __LINE__);
485 }
486 lEvent = p_session->omxEvent;
487 pthread_mutex_unlock(&p_session->lock);
488
489 if (lEvent != OMX_EventCmdComplete) {
490 CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent);
491 return OMX_ErrorUndefined;
492 }
493 }
494 return OMX_ErrorNone;
495 }
496
497
498 /** mm_jpegdec_session_decode:
499 *
500 * Arguments:
501 * @p_session: encode session
502 *
503 * Return:
504 * OMX_ERRORTYPE
505 *
506 * Description:
507 * Start the encoding
508 *
509 **/
mm_jpegdec_session_decode(mm_jpeg_job_session_t * p_session)510 static OMX_ERRORTYPE mm_jpegdec_session_decode(mm_jpeg_job_session_t *p_session)
511 {
512 OMX_ERRORTYPE ret = OMX_ErrorNone;
513 mm_jpeg_decode_params_t *p_params = &p_session->dec_params;
514 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
515 OMX_EVENTTYPE lEvent;
516 uint32_t i;
517 QOMX_BUFFER_INFO lbuffer_info;
518
519 pthread_mutex_lock(&p_session->lock);
520 p_session->abort_state = MM_JPEG_ABORT_NONE;
521 p_session->encoding = OMX_FALSE;
522 pthread_mutex_unlock(&p_session->lock);
523
524 if (OMX_FALSE == p_session->config) {
525 ret = mm_jpegdec_session_configure(p_session);
526 if (ret) {
527 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
528 goto error;
529 }
530 p_session->config = OMX_TRUE;
531 }
532
533 pthread_mutex_lock(&p_session->lock);
534 p_session->encoding = OMX_TRUE;
535 pthread_mutex_unlock(&p_session->lock);
536
537 MM_JPEG_CHK_ABORT(p_session, ret, error);
538
539 p_session->event_pending = OMX_TRUE;
540
541 ret = OMX_EmptyThisBuffer(p_session->omx_handle,
542 p_session->p_in_omx_buf[p_jobparams->src_index]);
543 if (ret) {
544 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
545 goto error;
546 }
547
548 // Wait for port settings changed
549 pthread_mutex_lock(&p_session->lock);
550 if (p_session->event_pending == OMX_TRUE) {
551 CDBG("%s:%d] before wait", __func__, __LINE__);
552 pthread_cond_wait(&p_session->cond, &p_session->lock);
553 }
554 lEvent = p_session->omxEvent;
555 CDBG("%s:%d] after wait", __func__, __LINE__);
556 pthread_mutex_unlock(&p_session->lock);
557
558 if (lEvent != OMX_EventPortSettingsChanged) {
559 CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent);
560 goto error;
561 }
562
563 // Disable output port (wait)
564 mm_jpeg_session_port_disable(p_session,
565 p_session->outputPort.nPortIndex,
566 OMX_TRUE);
567
568 // Get port definition
569 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
570 &p_session->outputPort);
571 if (ret) {
572 CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
573 return ret;
574 }
575
576 // Set port definition
577 p_session->outputPort.format.image.nFrameWidth =
578 (OMX_U32)p_jobparams->main_dim.dst_dim.width;
579 p_session->outputPort.format.image.nFrameHeight =
580 (OMX_U32)p_jobparams->main_dim.dst_dim.height;
581 p_session->outputPort.format.image.eColorFormat =
582 map_jpeg_format(p_params->color_format);
583
584 p_session->outputPort.nBufferSize =
585 p_params->dest_buf[p_jobparams->dst_index].buf_size;
586 p_session->outputPort.nBufferCountActual = (OMX_U32)p_params->num_dst_bufs;
587
588 p_session->outputPort.format.image.nSliceHeight =
589 (OMX_U32)
590 p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].scanline;
591 p_session->outputPort.format.image.nStride =
592 p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].stride;
593
594 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition,
595 &p_session->outputPort);
596 if (ret) {
597 CDBG_ERROR("%s:%d] failed", __func__, __LINE__);
598 return ret;
599 }
600
601 // Enable port (no wait)
602 mm_jpeg_session_port_enable(p_session,
603 p_session->outputPort.nPortIndex,
604 OMX_FALSE);
605
606 memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO));
607 // Use buffers
608 for (i = 0; i < p_params->num_dst_bufs; i++) {
609 lbuffer_info.fd = (OMX_U32)p_params->dest_buf[i].fd;
610 CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, (unsigned int)i);
611 ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]),
612 1, &lbuffer_info, p_params->dest_buf[i].buf_size,
613 p_params->dest_buf[i].buf_vaddr);
614 if (ret) {
615 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
616 return ret;
617 }
618 }
619
620 // Wait for port enable completion
621 pthread_mutex_lock(&p_session->lock);
622 if (p_session->event_pending == OMX_TRUE) {
623 CDBG("%s:%d] before wait", __func__, __LINE__);
624 pthread_cond_wait(&p_session->cond, &p_session->lock);
625 lEvent = p_session->omxEvent;
626 CDBG("%s:%d] after wait", __func__, __LINE__);
627 }
628 lEvent = p_session->omxEvent;
629 pthread_mutex_unlock(&p_session->lock);
630
631 if (lEvent != OMX_EventCmdComplete) {
632 CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent);
633 goto error;
634 }
635
636 ret = OMX_FillThisBuffer(p_session->omx_handle,
637 p_session->p_out_omx_buf[p_jobparams->dst_index]);
638 if (ret) {
639 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
640 goto error;
641 }
642
643 MM_JPEG_CHK_ABORT(p_session, ret, error);
644
645 error:
646
647 CDBG("%s:%d] X ", __func__, __LINE__);
648 return ret;
649 }
650
651 /** mm_jpegdec_process_decoding_job:
652 *
653 * Arguments:
654 * @my_obj: jpeg client
655 * @job_node: job node
656 *
657 * Return:
658 * 0 for success -1 otherwise
659 *
660 * Description:
661 * Start the encoding job
662 *
663 **/
mm_jpegdec_process_decoding_job(mm_jpeg_obj * my_obj,mm_jpeg_job_q_node_t * job_node)664 int32_t mm_jpegdec_process_decoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
665 {
666 mm_jpeg_q_data_t qdata;
667 int32_t rc = 0;
668 OMX_ERRORTYPE ret = OMX_ErrorNone;
669 mm_jpeg_job_session_t *p_session = NULL;
670
671 /* check if valid session */
672 p_session = mm_jpeg_get_session(my_obj, job_node->dec_info.job_id);
673 if (NULL == p_session) {
674 CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__,
675 job_node->dec_info.job_id);
676 return -1;
677 }
678
679 /* sent encode cmd to OMX, queue job into ongoing queue */
680 qdata.p = job_node;
681 rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, qdata);
682 if (rc) {
683 CDBG_ERROR("%s:%d] jpeg enqueue failed %d",
684 __func__, __LINE__, ret);
685 goto error;
686 }
687
688 p_session->decode_job = job_node->dec_info.decode_job;
689 p_session->jobId = job_node->dec_info.job_id;
690 ret = mm_jpegdec_session_decode(p_session);
691 if (ret) {
692 CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__);
693 goto error;
694 }
695
696 CDBG("%s:%d] Success X ", __func__, __LINE__);
697 return rc;
698
699 error:
700
701 if ((OMX_ErrorNone != ret) &&
702 (NULL != p_session->dec_params.jpeg_cb)) {
703 p_session->job_status = JPEG_JOB_STATUS_ERROR;
704 CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
705 p_session->job_status);
706 p_session->dec_params.jpeg_cb(p_session->job_status,
707 p_session->client_hdl,
708 p_session->jobId,
709 NULL,
710 p_session->dec_params.userdata);
711 }
712
713 /*remove the job*/
714 mm_jpegdec_job_done(p_session);
715 CDBG("%s:%d] Error X ", __func__, __LINE__);
716
717 return rc;
718 }
719
720 /** mm_jpeg_start_decode_job:
721 *
722 * Arguments:
723 * @my_obj: jpeg object
724 * @client_hdl: client handle
725 * @job: pointer to encode job
726 * @jobId: job id
727 *
728 * Return:
729 * 0 for success else failure
730 *
731 * Description:
732 * Start the encoding job
733 *
734 **/
mm_jpegdec_start_decode_job(mm_jpeg_obj * my_obj,mm_jpeg_job_t * job,uint32_t * job_id)735 int32_t mm_jpegdec_start_decode_job(mm_jpeg_obj *my_obj,
736 mm_jpeg_job_t *job,
737 uint32_t *job_id)
738 {
739 mm_jpeg_q_data_t qdata;
740 int32_t rc = -1;
741 uint8_t session_idx = 0;
742 uint8_t client_idx = 0;
743 mm_jpeg_job_q_node_t* node = NULL;
744 mm_jpeg_job_session_t *p_session = NULL;
745 mm_jpeg_decode_job_t *p_jobparams = &job->decode_job;
746
747 *job_id = 0;
748
749 /* check if valid session */
750 session_idx = GET_SESSION_IDX(p_jobparams->session_id);
751 client_idx = GET_CLIENT_IDX(p_jobparams->session_id);
752 CDBG("%s:%d] session_idx %d client idx %d", __func__, __LINE__,
753 session_idx, client_idx);
754
755 if ((session_idx >= MM_JPEG_MAX_SESSION) ||
756 (client_idx >= MAX_JPEG_CLIENT_NUM)) {
757 CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__,
758 job->decode_job.session_id);
759 return rc;
760 }
761
762 p_session = &my_obj->clnt_mgr[client_idx].session[session_idx];
763 if (OMX_FALSE == p_session->active) {
764 CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__,
765 job->decode_job.session_id);
766 return rc;
767 }
768
769 if ((p_jobparams->src_index >= (int32_t)p_session->dec_params.num_src_bufs) ||
770 (p_jobparams->dst_index >= (int32_t)p_session->dec_params.num_dst_bufs)) {
771 CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__);
772 return rc;
773 }
774
775 /* enqueue new job into todo job queue */
776 node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
777 if (NULL == node) {
778 CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
779 return -1;
780 }
781
782 *job_id = job->decode_job.session_id |
783 ((p_session->job_hist++ % JOB_HIST_MAX) << 16);
784
785 memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
786 node->dec_info.decode_job = job->decode_job;
787 node->dec_info.job_id = *job_id;
788 node->dec_info.client_handle = p_session->client_hdl;
789 node->type = MM_JPEG_CMD_TYPE_DECODE_JOB;
790
791 qdata.p = node;
792 rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, qdata);
793 if (0 == rc) {
794 cam_sem_post(&my_obj->job_mgr.job_sem);
795 }
796
797 return rc;
798 }
799
800 /** mm_jpegdec_create_session:
801 *
802 * Arguments:
803 * @my_obj: jpeg object
804 * @client_hdl: client handle
805 * @p_params: pointer to encode params
806 * @p_session_id: session id
807 *
808 * Return:
809 * 0 for success else failure
810 *
811 * Description:
812 * Start the encoding session
813 *
814 **/
mm_jpegdec_create_session(mm_jpeg_obj * my_obj,uint32_t client_hdl,mm_jpeg_decode_params_t * p_params,uint32_t * p_session_id)815 int32_t mm_jpegdec_create_session(mm_jpeg_obj *my_obj,
816 uint32_t client_hdl,
817 mm_jpeg_decode_params_t *p_params,
818 uint32_t* p_session_id)
819 {
820 int32_t rc = 0;
821 OMX_ERRORTYPE ret = OMX_ErrorNone;
822 uint8_t clnt_idx = 0;
823 int session_idx = -1;
824 mm_jpeg_job_session_t *p_session = NULL;
825 *p_session_id = 0;
826
827 /* validate the parameters */
828 if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF)
829 || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) {
830 CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__);
831 return rc;
832 }
833
834 /* check if valid client */
835 clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
836 if (clnt_idx >= MAX_JPEG_CLIENT_NUM) {
837 CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
838 return rc;
839 }
840
841 session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session);
842 if (session_idx < 0) {
843 CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx);
844 return rc;
845 }
846
847 ret = mm_jpegdec_session_create(p_session);
848 if (OMX_ErrorNone != ret) {
849 p_session->active = OMX_FALSE;
850 CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__);
851 return rc;
852 }
853
854 *p_session_id = (JOB_ID_MAGICVAL << 24) |
855 ((unsigned)session_idx << 8) | clnt_idx;
856
857 /*copy the params*/
858 p_session->dec_params = *p_params;
859 p_session->client_hdl = client_hdl;
860 p_session->sessionId = *p_session_id;
861 p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */
862 CDBG("%s:%d] session id %x", __func__, __LINE__, *p_session_id);
863
864 return rc;
865 }
866
867 /** mm_jpegdec_destroy_session:
868 *
869 * Arguments:
870 * @my_obj: jpeg object
871 * @session_id: session index
872 *
873 * Return:
874 * 0 for success else failure
875 *
876 * Description:
877 * Destroy the encoding session
878 *
879 **/
mm_jpegdec_destroy_session(mm_jpeg_obj * my_obj,mm_jpeg_job_session_t * p_session)880 int32_t mm_jpegdec_destroy_session(mm_jpeg_obj *my_obj,
881 mm_jpeg_job_session_t *p_session)
882 {
883 int32_t rc = 0;
884 mm_jpeg_job_q_node_t *node = NULL;
885
886 if (NULL == p_session) {
887 CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__);
888 return rc;
889 }
890 uint32_t session_id = p_session->sessionId;
891 pthread_mutex_lock(&my_obj->job_lock);
892
893 /* abort job if in todo queue */
894 CDBG("%s:%d] abort todo jobs", __func__, __LINE__);
895 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
896 while (NULL != node) {
897 free(node);
898 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id);
899 }
900
901 /* abort job if in ongoing queue */
902 CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__);
903 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
904 while (NULL != node) {
905 free(node);
906 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id);
907 }
908
909 /* abort the current session */
910 mm_jpeg_session_abort(p_session);
911 mm_jpegdec_session_destroy(p_session);
912 mm_jpeg_remove_session_idx(my_obj, session_id);
913 pthread_mutex_unlock(&my_obj->job_lock);
914
915 /* wake up jobMgr thread to work on new job if there is any */
916 cam_sem_post(&my_obj->job_mgr.job_sem);
917 CDBG("%s:%d] X", __func__, __LINE__);
918
919 return rc;
920 }
921
922 /** mm_jpegdec_destroy_session_by_id:
923 *
924 * Arguments:
925 * @my_obj: jpeg object
926 * @session_id: session index
927 *
928 * Return:
929 * 0 for success else failure
930 *
931 * Description:
932 * Destroy the encoding session
933 *
934 **/
mm_jpegdec_destroy_session_by_id(mm_jpeg_obj * my_obj,uint32_t session_id)935 int32_t mm_jpegdec_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id)
936 {
937 int32_t rc = 0;
938 mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id);
939
940 if (NULL == p_session) {
941 CDBG_ERROR("%s:%d] session is not valid", __func__, __LINE__);
942 return rc;
943 }
944
945 return mm_jpegdec_destroy_session(my_obj, p_session);
946 }
947
948
949
mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_BUFFERHEADERTYPE * pBuffer)950 OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent,
951 OMX_PTR pAppData,
952 OMX_BUFFERHEADERTYPE *pBuffer)
953 {
954 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
955
956 CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count);
957 pthread_mutex_lock(&p_session->lock);
958 p_session->ebd_count++;
959 pthread_mutex_unlock(&p_session->lock);
960 return 0;
961 }
962
mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_BUFFERHEADERTYPE * pBuffer)963 OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent,
964 OMX_PTR pAppData,
965 OMX_BUFFERHEADERTYPE *pBuffer)
966 {
967 OMX_ERRORTYPE ret = OMX_ErrorNone;
968 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
969 mm_jpeg_output_t output_buf;
970
971 CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count);
972
973 pthread_mutex_lock(&p_session->lock);
974
975 if (MM_JPEG_ABORT_NONE != p_session->abort_state) {
976 pthread_mutex_unlock(&p_session->lock);
977 return ret;
978 }
979
980 p_session->fbd_count++;
981 if (NULL != p_session->dec_params.jpeg_cb) {
982 p_session->job_status = JPEG_JOB_STATUS_DONE;
983 output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen;
984 output_buf.buf_vaddr = pBuffer->pBuffer;
985 output_buf.fd = -1;
986 CDBG("%s:%d] send jpeg callback %d", __func__, __LINE__,
987 p_session->job_status);
988 p_session->dec_params.jpeg_cb(p_session->job_status,
989 p_session->client_hdl,
990 p_session->jobId,
991 &output_buf,
992 p_session->dec_params.userdata);
993
994 /* remove from ready queue */
995 mm_jpegdec_job_done(p_session);
996 }
997 pthread_mutex_unlock(&p_session->lock);
998 CDBG("%s:%d] ", __func__, __LINE__);
999
1000 return ret;
1001 }
1002
mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent,OMX_PTR pAppData,OMX_EVENTTYPE eEvent,OMX_U32 nData1,OMX_U32 nData2,OMX_PTR pEventData)1003 OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent,
1004 OMX_PTR pAppData,
1005 OMX_EVENTTYPE eEvent,
1006 OMX_U32 nData1,
1007 OMX_U32 nData2,
1008 OMX_PTR pEventData)
1009 {
1010 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData;
1011
1012 CDBG("%s:%d] %d %d %d state %d", __func__, __LINE__, eEvent, (int)nData1,
1013 (int)nData2, p_session->abort_state);
1014
1015 CDBG("%s:%d] AppData=%p ", __func__, __LINE__, pAppData);
1016
1017 pthread_mutex_lock(&p_session->lock);
1018 p_session->omxEvent = eEvent;
1019 if (MM_JPEG_ABORT_INIT == p_session->abort_state) {
1020 p_session->abort_state = MM_JPEG_ABORT_DONE;
1021 pthread_cond_signal(&p_session->cond);
1022 pthread_mutex_unlock(&p_session->lock);
1023 return OMX_ErrorNone;
1024 }
1025
1026 if (eEvent == OMX_EventError) {
1027 if (p_session->encoding == OMX_TRUE) {
1028 CDBG("%s:%d] Error during encoding", __func__, __LINE__);
1029
1030 /* send jpeg callback */
1031 if (NULL != p_session->dec_params.jpeg_cb) {
1032 p_session->job_status = JPEG_JOB_STATUS_ERROR;
1033 CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
1034 p_session->job_status);
1035 p_session->dec_params.jpeg_cb(p_session->job_status,
1036 p_session->client_hdl,
1037 p_session->jobId,
1038 NULL,
1039 p_session->dec_params.userdata);
1040 }
1041
1042 /* remove from ready queue */
1043 mm_jpegdec_job_done(p_session);
1044 }
1045 pthread_cond_signal(&p_session->cond);
1046 } else if (eEvent == OMX_EventCmdComplete) {
1047 p_session->state_change_pending = OMX_FALSE;
1048 p_session->event_pending = OMX_FALSE;
1049 pthread_cond_signal(&p_session->cond);
1050 } else if (eEvent == OMX_EventPortSettingsChanged) {
1051 p_session->event_pending = OMX_FALSE;
1052 pthread_cond_signal(&p_session->cond);
1053 }
1054
1055 pthread_mutex_unlock(&p_session->lock);
1056 CDBG("%s:%d]", __func__, __LINE__);
1057 return OMX_ErrorNone;
1058 }
1059
1060 /** mm_jpegdec_abort_job:
1061 *
1062 * Arguments:
1063 * @my_obj: jpeg object
1064 * @client_hdl: client handle
1065 * @jobId: job id
1066 *
1067 * Return:
1068 * 0 for success else failure
1069 *
1070 * Description:
1071 * Abort the encoding session
1072 *
1073 **/
mm_jpegdec_abort_job(mm_jpeg_obj * my_obj,uint32_t jobId)1074 int32_t mm_jpegdec_abort_job(mm_jpeg_obj *my_obj,
1075 uint32_t jobId)
1076 {
1077 int32_t rc = -1;
1078 mm_jpeg_job_q_node_t *node = NULL;
1079 mm_jpeg_job_session_t *p_session = NULL;
1080
1081 CDBG("%s:%d] ", __func__, __LINE__);
1082 pthread_mutex_lock(&my_obj->job_lock);
1083
1084 /* abort job if in todo queue */
1085 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId);
1086 if (NULL != node) {
1087 free(node);
1088 goto abort_done;
1089 }
1090
1091 /* abort job if in ongoing queue */
1092 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId);
1093 if (NULL != node) {
1094 /* find job that is OMX ongoing, ask OMX to abort the job */
1095 p_session = mm_jpeg_get_session(my_obj, node->dec_info.job_id);
1096 if (p_session) {
1097 mm_jpeg_session_abort(p_session);
1098 } else {
1099 CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__,
1100 node->dec_info.job_id);
1101 }
1102 free(node);
1103 goto abort_done;
1104 }
1105
1106 abort_done:
1107 pthread_mutex_unlock(&my_obj->job_lock);
1108
1109 return rc;
1110 }
1111 /** mm_jpegdec_init:
1112 *
1113 * Arguments:
1114 * @my_obj: jpeg object
1115 *
1116 * Return:
1117 * 0 for success else failure
1118 *
1119 * Description:
1120 * Initializes the jpeg client
1121 *
1122 **/
mm_jpegdec_init(mm_jpeg_obj * my_obj)1123 int32_t mm_jpegdec_init(mm_jpeg_obj *my_obj)
1124 {
1125 int32_t rc = 0;
1126
1127 /* init locks */
1128 pthread_mutex_init(&my_obj->job_lock, NULL);
1129
1130 /* init ongoing job queue */
1131 rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q);
1132 if (0 != rc) {
1133 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1134 return -1;
1135 }
1136
1137 /* init job semaphore and launch jobmgr thread */
1138 CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc);
1139 rc = mm_jpeg_jobmgr_thread_launch(my_obj);
1140 if (0 != rc) {
1141 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1142 return -1;
1143 }
1144
1145 /* load OMX */
1146 if (OMX_ErrorNone != OMX_Init()) {
1147 /* roll back in error case */
1148 CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc);
1149 mm_jpeg_jobmgr_thread_release(my_obj);
1150 mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1151 pthread_mutex_destroy(&my_obj->job_lock);
1152 }
1153
1154 return rc;
1155 }
1156
1157 /** mm_jpegdec_deinit:
1158 *
1159 * Arguments:
1160 * @my_obj: jpeg object
1161 *
1162 * Return:
1163 * 0 for success else failure
1164 *
1165 * Description:
1166 * Deinits the jpeg client
1167 *
1168 **/
mm_jpegdec_deinit(mm_jpeg_obj * my_obj)1169 int32_t mm_jpegdec_deinit(mm_jpeg_obj *my_obj)
1170 {
1171 int32_t rc = 0;
1172
1173 /* release jobmgr thread */
1174 rc = mm_jpeg_jobmgr_thread_release(my_obj);
1175 if (0 != rc) {
1176 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1177 }
1178
1179 /* unload OMX engine */
1180 OMX_Deinit();
1181
1182 /* deinit ongoing job and cb queue */
1183 rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
1184 if (0 != rc) {
1185 CDBG_ERROR("%s:%d] Error", __func__, __LINE__);
1186 }
1187
1188 /* destroy locks */
1189 pthread_mutex_destroy(&my_obj->job_lock);
1190
1191 return rc;
1192 }
1193