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