1 /* Copyright (c) 2012-2015, 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 <stdlib.h>
31 #include <pthread.h>
32 #include <errno.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <poll.h>
38 #include <time.h>
39 #include <cam_semaphore.h>
40 #ifdef VENUS_PRESENT
41 #include <media/msm_media_info.h>
42 #endif
43
44 #include "mm_camera_dbg.h"
45 #include "mm_camera_interface.h"
46 #include "mm_camera.h"
47
48 /* internal function decalre */
49 int32_t mm_stream_qbuf(mm_stream_t *my_obj,
50 mm_camera_buf_def_t *buf);
51 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
52 int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
53 int32_t mm_stream_sync_info(mm_stream_t *my_obj);
54 int32_t mm_stream_init_bufs(mm_stream_t * my_obj);
55 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj);
56 int32_t mm_stream_request_buf(mm_stream_t * my_obj);
57 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj);
58 int32_t mm_stream_release(mm_stream_t *my_obj);
59 int32_t mm_stream_set_parm(mm_stream_t *my_obj,
60 cam_stream_parm_buffer_t *value);
61 int32_t mm_stream_get_parm(mm_stream_t *my_obj,
62 cam_stream_parm_buffer_t *value);
63 int32_t mm_stream_do_action(mm_stream_t *my_obj,
64 void *in_value);
65 int32_t mm_stream_streamon(mm_stream_t *my_obj);
66 int32_t mm_stream_streamoff(mm_stream_t *my_obj);
67 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
68 mm_camera_buf_info_t* buf_info,
69 uint8_t num_planes);
70 int32_t mm_stream_read_user_buf(mm_stream_t * my_obj,
71 mm_camera_buf_info_t* buf_info);
72 int32_t mm_stream_write_user_buf(mm_stream_t * my_obj,
73 mm_camera_buf_def_t *buf);
74
75 int32_t mm_stream_config(mm_stream_t *my_obj,
76 mm_camera_stream_config_t *config);
77 int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
78 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
79 mm_camera_buf_def_t *frame);
80 int32_t mm_stream_get_queued_buf_count(mm_stream_t * my_obj);
81
82 int32_t mm_stream_calc_offset(mm_stream_t *my_obj);
83 int32_t mm_stream_calc_offset_preview(cam_format_t fmt,
84 cam_dimension_t *dim,
85 cam_stream_buf_plane_info_t *buf_planes);
86 int32_t mm_stream_calc_offset_post_view(cam_format_t fmt,
87 cam_dimension_t *dim,
88 cam_stream_buf_plane_info_t *buf_planes);
89
90 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
91 cam_dimension_t *dim,
92 cam_padding_info_t *padding,
93 cam_stream_buf_plane_info_t *buf_planes);
94 int32_t mm_stream_calc_offset_raw(cam_format_t fmt,
95 cam_dimension_t *dim,
96 cam_padding_info_t *padding,
97 cam_stream_buf_plane_info_t *buf_planes);
98 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
99 cam_stream_buf_plane_info_t *buf_planes);
100 int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim,
101 cam_padding_info_t *padding,
102 cam_stream_buf_plane_info_t *buf_planes);
103 int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info,
104 cam_padding_info_t *padding,
105 cam_stream_buf_plane_info_t *plns);
106
107
108 /* state machine function declare */
109 int32_t mm_stream_fsm_inited(mm_stream_t * my_obj,
110 mm_stream_evt_type_t evt,
111 void * in_val,
112 void * out_val);
113 int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj,
114 mm_stream_evt_type_t evt,
115 void * in_val,
116 void * out_val);
117 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
118 mm_stream_evt_type_t evt,
119 void * in_val,
120 void * out_val);
121 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
122 mm_stream_evt_type_t evt,
123 void * in_val,
124 void * out_val);
125 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
126 mm_stream_evt_type_t evt,
127 void * in_val,
128 void * out_val);
129 int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
130 mm_stream_evt_type_t evt,
131 void * in_val,
132 void * out_val);
133 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt);
134
135
136 /*===========================================================================
137 * FUNCTION : mm_stream_notify_channel
138 *
139 * DESCRIPTION: function to notify channel object on received buffer
140 *
141 * PARAMETERS :
142 * @ch_obj : channel object
143 * @buf_info: ptr to struct storing buffer information
144 *
145 * RETURN : int32_t type of status
146 * 0 -- success
147 * 0> -- failure
148 *==========================================================================*/
mm_stream_notify_channel(struct mm_channel * ch_obj,mm_camera_buf_info_t * buf_info)149 int32_t mm_stream_notify_channel(struct mm_channel* ch_obj,
150 mm_camera_buf_info_t *buf_info)
151 {
152 int32_t rc = 0;
153 mm_camera_cmdcb_t* node = NULL;
154
155 if ((NULL == ch_obj) || (NULL == buf_info)) {
156 CDBG_ERROR("%s : Invalid channel/buffer", __func__);
157 return -ENODEV;
158 }
159
160 /* send cam_sem_post to wake up channel cmd thread to enqueue
161 * to super buffer */
162 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
163 if (NULL != node) {
164 memset(node, 0, sizeof(mm_camera_cmdcb_t));
165 node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
166 node->u.buf = *buf_info;
167
168 /* enqueue to cmd thread */
169 cam_queue_enq(&(ch_obj->cmd_thread.cmd_queue), node);
170
171 /* wake up cmd thread */
172 cam_sem_post(&(ch_obj->cmd_thread.cmd_sem));
173 } else {
174 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
175 rc = -ENOMEM;
176 }
177
178 return rc;
179 }
180
181 /*===========================================================================
182 * FUNCTION : mm_stream_handle_rcvd_buf
183 *
184 * DESCRIPTION: function to handle newly received stream buffer
185 *
186 * PARAMETERS :
187 * @cam_obj : stream object
188 * @buf_info: ptr to struct storing buffer information
189 *
190 * RETURN : none
191 *==========================================================================*/
mm_stream_handle_rcvd_buf(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info,uint8_t has_cb)192 void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj,
193 mm_camera_buf_info_t *buf_info,
194 uint8_t has_cb)
195 {
196 int32_t rc = 0;
197 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
198 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
199
200 /* enqueue to super buf thread */
201 if (my_obj->is_bundled) {
202 rc = mm_stream_notify_channel(my_obj->ch_obj, buf_info);
203 if (rc < 0) {
204 CDBG_ERROR("%s: Unable to notify channel", __func__);
205 }
206 }
207
208 pthread_mutex_lock(&my_obj->buf_lock);
209 if(my_obj->is_linked) {
210 /* need to add into super buf for linking, add ref count */
211 my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++;
212
213 rc = mm_stream_notify_channel(my_obj->linked_obj, buf_info);
214 if (rc < 0) {
215 CDBG_ERROR("%s: Unable to notify channel", __func__);
216 }
217 }
218 pthread_mutex_unlock(&my_obj->buf_lock);
219
220 if(has_cb) {
221 mm_camera_cmdcb_t* node = NULL;
222
223 /* send cam_sem_post to wake up cmd thread to dispatch dataCB */
224 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
225 if (NULL != node) {
226 memset(node, 0, sizeof(mm_camera_cmdcb_t));
227 node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
228 node->u.buf = *buf_info;
229
230 /* enqueue to cmd thread */
231 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
232
233 /* wake up cmd thread */
234 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
235 } else {
236 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
237 }
238 }
239 }
240
241 /*===========================================================================
242 * FUNCTION : mm_stream_data_notify
243 *
244 * DESCRIPTION: callback to handle data notify from kernel
245 *
246 * PARAMETERS :
247 * @user_data : user data ptr (stream object)
248 *
249 * RETURN : none
250 *==========================================================================*/
mm_stream_data_notify(void * user_data)251 static void mm_stream_data_notify(void* user_data)
252 {
253 mm_stream_t *my_obj = (mm_stream_t*)user_data;
254 int32_t i, rc;
255 uint8_t has_cb = 0, length = 0;
256 mm_camera_buf_info_t buf_info;
257
258 if (NULL == my_obj) {
259 return;
260 }
261
262 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
263 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
264 if (MM_STREAM_STATE_ACTIVE != my_obj->state) {
265 /* this Cb will only received in active_stream_on state
266 * if not so, return here */
267 CDBG_ERROR("%s: ERROR!! Wrong state (%d) to receive data notify!",
268 __func__, my_obj->state);
269 return;
270 }
271
272 if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) {
273 length = 1;
274 } else {
275 length = my_obj->frame_offset.num_planes;
276 }
277
278 memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
279 rc = mm_stream_read_msm_frame(my_obj, &buf_info,
280 (uint8_t)length);
281 if (rc != 0) {
282 return;
283 }
284 uint32_t idx = buf_info.buf->buf_idx;
285
286 pthread_mutex_lock(&my_obj->cb_lock);
287 for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
288 if(NULL != my_obj->buf_cb[i].cb) {
289 /* for every CB, add ref count */
290 has_cb = 1;
291 break;
292 }
293 }
294 pthread_mutex_unlock(&my_obj->cb_lock);
295
296 pthread_mutex_lock(&my_obj->buf_lock);
297 /* update buffer location */
298 my_obj->buf_status[idx].in_kernel = 0;
299
300 /* update buf ref count */
301 if (my_obj->is_bundled) {
302 /* need to add into super buf since bundled, add ref count */
303 my_obj->buf_status[idx].buf_refcnt++;
304 }
305 my_obj->buf_status[idx].buf_refcnt =
306 (uint8_t)(my_obj->buf_status[idx].buf_refcnt + has_cb);
307 pthread_mutex_unlock(&my_obj->buf_lock);
308
309 mm_stream_handle_rcvd_buf(my_obj, &buf_info, has_cb);
310 }
311
312 /*===========================================================================
313 * FUNCTION : mm_stream_dispatch_app_data
314 *
315 * DESCRIPTION: dispatch stream buffer to registered users
316 *
317 * PARAMETERS :
318 * @cmd_cb : ptr storing stream buffer information
319 * @userdata: user data ptr (stream object)
320 *
321 * RETURN : none
322 *==========================================================================*/
mm_stream_dispatch_app_data(mm_camera_cmdcb_t * cmd_cb,void * user_data)323 static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb,
324 void* user_data)
325 {
326 int i;
327 mm_stream_t * my_obj = (mm_stream_t *)user_data;
328 mm_camera_buf_info_t* buf_info = NULL;
329 mm_camera_super_buf_t super_buf;
330 mm_camera_cmd_thread_name("mm_cam_stream");
331
332 if (NULL == my_obj) {
333 return;
334 }
335 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
336 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
337
338 if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) {
339 CDBG_ERROR("%s: Wrong cmd_type (%d) for dataCB",
340 __func__, cmd_cb->cmd_type);
341 return;
342 }
343
344 buf_info = &cmd_cb->u.buf;
345 memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
346 super_buf.num_bufs = 1;
347 super_buf.bufs[0] = buf_info->buf;
348 super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl;
349 super_buf.ch_id = my_obj->ch_obj->my_hdl;
350
351 pthread_mutex_lock(&my_obj->cb_lock);
352 for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
353 if(NULL != my_obj->buf_cb[i].cb) {
354 if (my_obj->buf_cb[i].cb_count != 0) {
355 /* if <0, means infinite CB
356 * if >0, means CB for certain times
357 * both case we need to call CB */
358
359 /* increase buf ref cnt */
360 pthread_mutex_lock(&my_obj->buf_lock);
361 my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++;
362 pthread_mutex_unlock(&my_obj->buf_lock);
363
364 /* callback */
365 my_obj->buf_cb[i].cb(&super_buf,
366 my_obj->buf_cb[i].user_data);
367 }
368
369 /* if >0, reduce count by 1 every time we called CB until reaches 0
370 * when count reach 0, reset the buf_cb to have no CB */
371 if (my_obj->buf_cb[i].cb_count > 0) {
372 my_obj->buf_cb[i].cb_count--;
373 if (0 == my_obj->buf_cb[i].cb_count) {
374 my_obj->buf_cb[i].cb = NULL;
375 my_obj->buf_cb[i].user_data = NULL;
376 }
377 }
378 }
379 }
380 pthread_mutex_unlock(&my_obj->cb_lock);
381
382 /* do buf_done since we increased refcnt by one when has_cb */
383 mm_stream_buf_done(my_obj, buf_info->buf);
384 }
385
386 /*===========================================================================
387 * FUNCTION : mm_stream_fsm_fn
388 *
389 * DESCRIPTION: stream finite state machine entry function. Depends on stream
390 * state, incoming event will be handled differently.
391 *
392 * PARAMETERS :
393 * @my_obj : ptr to a stream object
394 * @evt : stream event to be processed
395 * @in_val : input event payload. Can be NULL if not needed.
396 * @out_val : output payload, Can be NULL if not needed.
397 *
398 * RETURN : int32_t type of status
399 * 0 -- success
400 * -1 -- failure
401 *==========================================================================*/
mm_stream_fsm_fn(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)402 int32_t mm_stream_fsm_fn(mm_stream_t *my_obj,
403 mm_stream_evt_type_t evt,
404 void * in_val,
405 void * out_val)
406 {
407 int32_t rc = -1;
408
409 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
410 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
411 switch (my_obj->state) {
412 case MM_STREAM_STATE_NOTUSED:
413 CDBG("%s: Not handling evt in unused state", __func__);
414 break;
415 case MM_STREAM_STATE_INITED:
416 rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val);
417 break;
418 case MM_STREAM_STATE_ACQUIRED:
419 rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val);
420 break;
421 case MM_STREAM_STATE_CFG:
422 rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val);
423 break;
424 case MM_STREAM_STATE_BUFFED:
425 rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val);
426 break;
427 case MM_STREAM_STATE_REG:
428 rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val);
429 break;
430 case MM_STREAM_STATE_ACTIVE:
431 rc = mm_stream_fsm_active(my_obj, evt, in_val, out_val);
432 break;
433 default:
434 CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
435 break;
436 }
437 CDBG("%s : X rc =%d",__func__,rc);
438 return rc;
439 }
440
441 /*===========================================================================
442 * FUNCTION : mm_stream_fsm_inited
443 *
444 * DESCRIPTION: stream finite state machine function to handle event in INITED
445 * state.
446 *
447 * PARAMETERS :
448 * @my_obj : ptr to a stream object
449 * @evt : stream event to be processed
450 * @in_val : input event payload. Can be NULL if not needed.
451 * @out_val : output payload, Can be NULL if not needed.
452 *
453 * RETURN : int32_t type of status
454 * 0 -- success
455 * -1 -- failure
456 *==========================================================================*/
mm_stream_fsm_inited(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)457 int32_t mm_stream_fsm_inited(mm_stream_t *my_obj,
458 mm_stream_evt_type_t evt,
459 void * in_val,
460 void * out_val)
461 {
462 int32_t rc = 0;
463 char dev_name[MM_CAMERA_DEV_NAME_LEN];
464 const char *dev_name_value = NULL;
465 if (NULL == my_obj) {
466 CDBG_ERROR("%s: NULL camera object\n", __func__);
467 return -1;
468 }
469
470 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
471 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
472 switch(evt) {
473 case MM_STREAM_EVT_ACQUIRE:
474 if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) {
475 CDBG_ERROR("%s: NULL channel or camera obj\n", __func__);
476 rc = -1;
477 break;
478 }
479
480 dev_name_value = mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl);
481 if (NULL == dev_name_value) {
482 CDBG_ERROR("%s: NULL device name\n", __func__);
483 rc = -1;
484 break;
485 }
486
487 dev_name_value = mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl);
488 if (NULL == dev_name_value) {
489 CDBG_ERROR("%s: NULL device name\n", __func__);
490 rc = -1;
491 break;
492 }
493 snprintf(dev_name, sizeof(dev_name), "/dev/%s",
494 dev_name_value);
495
496 my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK);
497 if (my_obj->fd < 0) {
498 CDBG_ERROR("%s: open dev returned %d\n", __func__, my_obj->fd);
499 rc = -1;
500 break;
501 }
502 CDBG("%s: open dev fd = %d\n", __func__, my_obj->fd);
503 rc = mm_stream_set_ext_mode(my_obj);
504 if (0 == rc) {
505 my_obj->state = MM_STREAM_STATE_ACQUIRED;
506 } else {
507 /* failed setting ext_mode
508 * close fd */
509 close(my_obj->fd);
510 my_obj->fd = -1;
511 break;
512 }
513 break;
514 default:
515 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
516 __func__, my_obj->state, evt, in_val, out_val);
517 break;
518 }
519 return rc;
520 }
521
522 /*===========================================================================
523 * FUNCTION : mm_stream_fsm_acquired
524 *
525 * DESCRIPTION: stream finite state machine function to handle event in AQUIRED
526 * state.
527 *
528 * PARAMETERS :
529 * @my_obj : ptr to a stream object
530 * @evt : stream event to be processed
531 * @in_val : input event payload. Can be NULL if not needed.
532 * @out_val : output payload, Can be NULL if not needed.
533 *
534 * RETURN : int32_t type of status
535 * 0 -- success
536 * -1 -- failure
537 *==========================================================================*/
mm_stream_fsm_acquired(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)538 int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj,
539 mm_stream_evt_type_t evt,
540 void * in_val,
541 void * out_val)
542 {
543 int32_t rc = 0;
544
545 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
546 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
547 switch(evt) {
548 case MM_STREAM_EVT_SET_FMT:
549 {
550 mm_camera_stream_config_t *config =
551 (mm_camera_stream_config_t *)in_val;
552
553 rc = mm_stream_config(my_obj, config);
554
555 /* change state to configed */
556 my_obj->state = MM_STREAM_STATE_CFG;
557
558 break;
559 }
560 case MM_STREAM_EVT_RELEASE:
561 rc = mm_stream_release(my_obj);
562 /* change state to not used */
563 my_obj->state = MM_STREAM_STATE_NOTUSED;
564 break;
565 case MM_STREAM_EVT_SET_PARM:
566 {
567 mm_evt_paylod_set_get_stream_parms_t *payload =
568 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
569 rc = mm_stream_set_parm(my_obj, payload->parms);
570 }
571 break;
572 case MM_STREAM_EVT_GET_PARM:
573 {
574 mm_evt_paylod_set_get_stream_parms_t *payload =
575 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
576 rc = mm_stream_get_parm(my_obj, payload->parms);
577 }
578 break;
579 default:
580 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
581 __func__, my_obj->state, evt, in_val, out_val);
582 }
583 CDBG("%s :X rc = %d", __func__, rc);
584 return rc;
585 }
586
587 /*===========================================================================
588 * FUNCTION : mm_stream_fsm_cfg
589 *
590 * DESCRIPTION: stream finite state machine function to handle event in CONFIGURED
591 * state.
592 *
593 * PARAMETERS :
594 * @my_obj : ptr to a stream object
595 * @evt : stream event to be processed
596 * @in_val : input event payload. Can be NULL if not needed.
597 * @out_val : output payload, Can be NULL if not needed.
598 *
599 * RETURN : int32_t type of status
600 * 0 -- success
601 * -1 -- failure
602 *==========================================================================*/
mm_stream_fsm_cfg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)603 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
604 mm_stream_evt_type_t evt,
605 void * in_val,
606 void * out_val)
607 {
608 int32_t rc = 0;
609 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
610 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
611 switch(evt) {
612 case MM_STREAM_EVT_SET_FMT:
613 {
614 mm_camera_stream_config_t *config =
615 (mm_camera_stream_config_t *)in_val;
616
617 rc = mm_stream_config(my_obj, config);
618
619 /* change state to configed */
620 my_obj->state = MM_STREAM_STATE_CFG;
621
622 break;
623 }
624 case MM_STREAM_EVT_RELEASE:
625 rc = mm_stream_release(my_obj);
626 my_obj->state = MM_STREAM_STATE_NOTUSED;
627 break;
628 case MM_STREAM_EVT_SET_PARM:
629 {
630 mm_evt_paylod_set_get_stream_parms_t *payload =
631 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
632 rc = mm_stream_set_parm(my_obj, payload->parms);
633 }
634 break;
635 case MM_STREAM_EVT_GET_PARM:
636 {
637 mm_evt_paylod_set_get_stream_parms_t *payload =
638 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
639 rc = mm_stream_get_parm(my_obj, payload->parms);
640 }
641 break;
642 case MM_STREAM_EVT_GET_BUF:
643 rc = mm_stream_init_bufs(my_obj);
644 /* change state to buff allocated */
645 if(0 == rc) {
646 my_obj->state = MM_STREAM_STATE_BUFFED;
647 }
648 break;
649 default:
650 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
651 __func__, my_obj->state, evt, in_val, out_val);
652 }
653 CDBG("%s :X rc = %d", __func__, rc);
654 return rc;
655 }
656
657 /*===========================================================================
658 * FUNCTION : mm_stream_fsm_buffed
659 *
660 * DESCRIPTION: stream finite state machine function to handle event in BUFFED
661 * state.
662 *
663 * PARAMETERS :
664 * @my_obj : ptr to a stream object
665 * @evt : stream event to be processed
666 * @in_val : input event payload. Can be NULL if not needed.
667 * @out_val : output payload, Can be NULL if not needed.
668 *
669 * RETURN : int32_t type of status
670 * 0 -- success
671 * -1 -- failure
672 *==========================================================================*/
mm_stream_fsm_buffed(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)673 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
674 mm_stream_evt_type_t evt,
675 void * in_val,
676 void * out_val)
677 {
678 int32_t rc = 0;
679 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
680 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
681 switch(evt) {
682 case MM_STREAM_EVT_PUT_BUF:
683 rc = mm_stream_deinit_bufs(my_obj);
684 /* change state to configed */
685 my_obj->state = MM_STREAM_STATE_CFG;
686 break;
687 case MM_STREAM_EVT_REG_BUF:
688 rc = mm_stream_reg_buf(my_obj);
689 /* change state to regged */
690 if(0 == rc) {
691 my_obj->state = MM_STREAM_STATE_REG;
692 }
693 break;
694 case MM_STREAM_EVT_SET_PARM:
695 {
696 mm_evt_paylod_set_get_stream_parms_t *payload =
697 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
698 rc = mm_stream_set_parm(my_obj, payload->parms);
699 }
700 break;
701 case MM_STREAM_EVT_GET_PARM:
702 {
703 mm_evt_paylod_set_get_stream_parms_t *payload =
704 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
705 rc = mm_stream_get_parm(my_obj, payload->parms);
706 }
707 break;
708 default:
709 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
710 __func__, my_obj->state, evt, in_val, out_val);
711 }
712 CDBG("%s :X rc = %d", __func__, rc);
713 return rc;
714 }
715
716 /*===========================================================================
717 * FUNCTION : mm_stream_fsm_reg
718 *
719 * DESCRIPTION: stream finite state machine function to handle event in REGGED
720 * state.
721 *
722 * PARAMETERS :
723 * @my_obj : ptr to a stream object
724 * @evt : stream event to be processed
725 * @in_val : input event payload. Can be NULL if not needed.
726 * @out_val : output payload, Can be NULL if not needed.
727 *
728 * RETURN : int32_t type of status
729 * 0 -- success
730 * -1 -- failure
731 *==========================================================================*/
mm_stream_fsm_reg(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)732 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
733 mm_stream_evt_type_t evt,
734 void * in_val,
735 void * out_val)
736 {
737 int32_t rc = 0;
738 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
739 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
740
741 switch(evt) {
742 case MM_STREAM_EVT_UNREG_BUF:
743 rc = mm_stream_unreg_buf(my_obj);
744
745 /* change state to buffed */
746 my_obj->state = MM_STREAM_STATE_BUFFED;
747 break;
748 case MM_STREAM_EVT_START:
749 {
750 uint8_t has_cb = 0;
751 uint8_t i;
752 /* launch cmd thread if CB is not null */
753 pthread_mutex_lock(&my_obj->cb_lock);
754 for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
755 if(NULL != my_obj->buf_cb[i].cb) {
756 has_cb = 1;
757 break;
758 }
759 }
760 pthread_mutex_unlock(&my_obj->cb_lock);
761
762 if (has_cb) {
763 snprintf(my_obj->cmd_thread.threadName, THREAD_NAME_SIZE, "CAM_StrmAppData");
764 mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
765 mm_stream_dispatch_app_data,
766 (void *)my_obj);
767 }
768
769 my_obj->state = MM_STREAM_STATE_ACTIVE;
770 rc = mm_stream_streamon(my_obj);
771 if (0 != rc) {
772 /* failed stream on, need to release cmd thread if it's launched */
773 if (has_cb) {
774 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
775 }
776 my_obj->state = MM_STREAM_STATE_REG;
777 break;
778 }
779 }
780 break;
781 case MM_STREAM_EVT_SET_PARM:
782 {
783 mm_evt_paylod_set_get_stream_parms_t *payload =
784 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
785 rc = mm_stream_set_parm(my_obj, payload->parms);
786 }
787 break;
788 case MM_STREAM_EVT_GET_PARM:
789 {
790 mm_evt_paylod_set_get_stream_parms_t *payload =
791 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
792 rc = mm_stream_get_parm(my_obj, payload->parms);
793 }
794 break;
795 default:
796 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
797 __func__, my_obj->state, evt, in_val, out_val);
798 }
799 CDBG("%s :X rc = %d", __func__, rc);
800 return rc;
801 }
802
803 /*===========================================================================
804 * FUNCTION : mm_stream_fsm_active
805 *
806 * DESCRIPTION: stream finite state machine function to handle event in ACTIVE
807 * state.
808 *
809 * PARAMETERS :
810 * @my_obj : ptr to a stream object
811 * @evt : stream event to be processed
812 * @in_val : input event payload. Can be NULL if not needed.
813 * @out_val : output payload, Can be NULL if not needed.
814 *
815 * RETURN : int32_t type of status
816 * 0 -- success
817 * -1 -- failure
818 *==========================================================================*/
mm_stream_fsm_active(mm_stream_t * my_obj,mm_stream_evt_type_t evt,void * in_val,void * out_val)819 int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
820 mm_stream_evt_type_t evt,
821 void * in_val,
822 void * out_val)
823 {
824 int32_t rc = 0;
825 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
826 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
827 switch(evt) {
828 case MM_STREAM_EVT_QBUF:
829 rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
830 break;
831 case MM_STREAM_EVT_GET_QUEUED_BUF_COUNT:
832 rc = mm_stream_get_queued_buf_count(my_obj);
833 break;
834 case MM_STREAM_EVT_STOP:
835 {
836 uint8_t has_cb = 0;
837 uint8_t i;
838 rc = mm_stream_streamoff(my_obj);
839
840 pthread_mutex_lock(&my_obj->cb_lock);
841 for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
842 if(NULL != my_obj->buf_cb[i].cb) {
843 has_cb = 1;
844 break;
845 }
846 }
847 pthread_mutex_unlock(&my_obj->cb_lock);
848
849 if (has_cb) {
850 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
851 }
852 my_obj->state = MM_STREAM_STATE_REG;
853 }
854 break;
855 case MM_STREAM_EVT_SET_PARM:
856 {
857 mm_evt_paylod_set_get_stream_parms_t *payload =
858 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
859 rc = mm_stream_set_parm(my_obj, payload->parms);
860 }
861 break;
862 case MM_STREAM_EVT_GET_PARM:
863 {
864 mm_evt_paylod_set_get_stream_parms_t *payload =
865 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
866 rc = mm_stream_get_parm(my_obj, payload->parms);
867 }
868 break;
869 case MM_STREAM_EVT_DO_ACTION:
870 rc = mm_stream_do_action(my_obj, in_val);
871 break;
872 default:
873 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
874 __func__, my_obj->state, evt, in_val, out_val);
875 }
876 CDBG("%s :X rc = %d", __func__, rc);
877 return rc;
878 }
879
880 /*===========================================================================
881 * FUNCTION : mm_stream_config
882 *
883 * DESCRIPTION: configure a stream
884 *
885 * PARAMETERS :
886 * @my_obj : stream object
887 * @config : stream configuration
888 *
889 * RETURN : int32_t type of status
890 * 0 -- success
891 * -1 -- failure
892 *==========================================================================*/
mm_stream_config(mm_stream_t * my_obj,mm_camera_stream_config_t * config)893 int32_t mm_stream_config(mm_stream_t *my_obj,
894 mm_camera_stream_config_t *config)
895 {
896 int32_t rc = 0;
897 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
898 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
899 my_obj->stream_info = config->stream_info;
900 my_obj->buf_num = (uint8_t) config->stream_info->num_bufs;
901 my_obj->mem_vtbl = config->mem_vtbl;
902 my_obj->padding_info = config->padding_info;
903 /* cd through intf always palced at idx 0 of buf_cb */
904 my_obj->buf_cb[0].cb = config->stream_cb;
905 my_obj->buf_cb[0].user_data = config->userdata;
906 my_obj->buf_cb[0].cb_count = -1; /* infinite by default */
907
908 rc = mm_stream_sync_info(my_obj);
909 if (rc == 0) {
910 rc = mm_stream_set_fmt(my_obj);
911 }
912 return rc;
913 }
914
915 /*===========================================================================
916 * FUNCTION : mm_stream_release
917 *
918 * DESCRIPTION: release a stream resource
919 *
920 * PARAMETERS :
921 * @my_obj : stream object
922 *
923 * RETURN : int32_t type of status
924 * 0 -- success
925 * -1 -- failure
926 *==========================================================================*/
mm_stream_release(mm_stream_t * my_obj)927 int32_t mm_stream_release(mm_stream_t *my_obj)
928 {
929 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
930 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
931
932 /* close fd */
933 if(my_obj->fd >= 0)
934 {
935 close(my_obj->fd);
936 }
937
938 /* destroy mutex */
939 pthread_mutex_destroy(&my_obj->buf_lock);
940 pthread_mutex_destroy(&my_obj->cb_lock);
941
942 /* reset stream obj */
943 memset(my_obj, 0, sizeof(mm_stream_t));
944 my_obj->fd = -1;
945
946 return 0;
947 }
948
949 /*===========================================================================
950 * FUNCTION : mm_stream_streamon
951 *
952 * DESCRIPTION: stream on a stream. sending v4l2 request to kernel
953 *
954 * PARAMETERS :
955 * @my_obj : stream object
956 *
957 * RETURN : int32_t type of status
958 * 0 -- success
959 * -1 -- failure
960 *==========================================================================*/
mm_stream_streamon(mm_stream_t * my_obj)961 int32_t mm_stream_streamon(mm_stream_t *my_obj)
962 {
963 int32_t rc;
964 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
965
966 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
967 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
968
969 rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
970 if (rc < 0) {
971 CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n",
972 __func__, rc);
973 /* remove fd from data poll thread in case of failure */
974 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_sync_call);
975 }
976 CDBG("%s :X rc = %d",__func__,rc);
977 return rc;
978 }
979
980 /*===========================================================================
981 * FUNCTION : mm_stream_streamoff
982 *
983 * DESCRIPTION: stream off a stream. sending v4l2 request to kernel
984 *
985 * PARAMETERS :
986 * @my_obj : stream object
987 *
988 * RETURN : int32_t type of status
989 * 0 -- success
990 * -1 -- failure
991 *==========================================================================*/
mm_stream_streamoff(mm_stream_t * my_obj)992 int32_t mm_stream_streamoff(mm_stream_t *my_obj)
993 {
994 int32_t rc;
995 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
996 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
997 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
998
999 /* step1: remove fd from data poll thread */
1000 rc = mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1001 my_obj->my_hdl, mm_camera_sync_call);
1002 if (rc < 0) {
1003 /* The error might be due to async update. In this case
1004 * wait for all updates to complete before proceeding. */
1005 rc = mm_camera_poll_thread_commit_updates(&my_obj->ch_obj->poll_thread[0]);
1006 if (rc < 0) {
1007 CDBG_ERROR("%s: Poll sync failed %d",
1008 __func__, rc);
1009 }
1010 }
1011
1012 /* step2: stream off */
1013 rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
1014 if (rc < 0) {
1015 CDBG_ERROR("%s: STREAMOFF failed: %s\n",
1016 __func__, strerror(errno));
1017 }
1018 CDBG("%s :X rc = %d",__func__,rc);
1019 return rc;
1020 }
1021
1022 /*===========================================================================
1023 * FUNCTION : mm_stream_write_user_buf
1024 *
1025 * DESCRIPTION: dequeue a stream buffer from user buffer queue and fill internal structure
1026 *
1027 * PARAMETERS :
1028 * @my_obj : stream object
1029 * @buf : ptr to a struct storing buffer information
1030 *
1031 * RETURN : int32_t type of status
1032 * 0 -- success
1033 * -1 -- failure
1034 *==========================================================================*/
mm_stream_write_user_buf(mm_stream_t * my_obj,mm_camera_buf_def_t * buf)1035 int32_t mm_stream_write_user_buf(mm_stream_t * my_obj,
1036 mm_camera_buf_def_t *buf)
1037 {
1038 int32_t rc = 0, i;
1039 int32_t index = -1, count = 0;
1040 struct msm_camera_user_buf_cont_t *cont_buf = NULL;
1041
1042 if (buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) {
1043 my_obj->buf_status[buf->buf_idx].buf_refcnt--;
1044 if (0 == my_obj->buf_status[buf->buf_idx].buf_refcnt) {
1045 cont_buf = (struct msm_camera_user_buf_cont_t *)my_obj->buf[buf->buf_idx].buffer;
1046 cont_buf->buf_cnt = my_obj->buf[buf->buf_idx].user_buf.bufs_used;
1047 for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) {
1048 cont_buf->buf_idx[i] = my_obj->buf[buf->buf_idx].user_buf.buf_idx[i];
1049 }
1050 rc = mm_stream_qbuf(my_obj, buf);
1051 if(rc < 0) {
1052 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
1053 __func__, buf->buf_idx, rc);
1054 } else {
1055 for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) {
1056 my_obj->buf[buf->buf_idx].user_buf.buf_idx[i] = -1;
1057 }
1058 my_obj->buf_status[buf->buf_idx].in_kernel = 1;
1059 my_obj->buf[buf->buf_idx].user_buf.buf_in_use = 1;
1060 }
1061 } else {
1062 CDBG("<DEBUG> : ref count pending count :%d idx = %d",
1063 my_obj->buf_status[buf->buf_idx].buf_refcnt, buf->buf_idx);
1064 }
1065 return rc;
1066 }
1067
1068 if ((my_obj->cur_buf_idx < 0)
1069 || (my_obj->cur_buf_idx >= my_obj->buf_num)) {
1070 for (i = 0; i < my_obj->buf_num; i++) {
1071 if ((my_obj->buf_status[i].in_kernel)
1072 || (my_obj->buf[i].user_buf.buf_in_use)) {
1073 continue;
1074 }
1075
1076 my_obj->cur_buf_idx = index = i;
1077 break;
1078 }
1079 } else {
1080 index = my_obj->cur_buf_idx;
1081 }
1082
1083 if (index == -1) {
1084 CDBG_ERROR("%s: No Free batch buffer", __func__);
1085 rc = -1;
1086 return rc;
1087 }
1088
1089 //Insert Buffer to Batch structure.
1090 my_obj->buf[index].user_buf.buf_idx[count] = buf->buf_idx;
1091 my_obj->cur_bufs_staged++;
1092
1093 CDBG("%s index = %d filled = %d used = %d", __func__,
1094 index,
1095 my_obj->cur_bufs_staged,
1096 my_obj->buf[index].user_buf.bufs_used);
1097
1098 if (my_obj->cur_bufs_staged
1099 == my_obj->buf[index].user_buf.bufs_used){
1100 my_obj->buf_status[index].buf_refcnt--;
1101 if (0 == my_obj->buf_status[index].buf_refcnt) {
1102 cont_buf = (struct msm_camera_user_buf_cont_t *)my_obj->buf[index].buffer;
1103 cont_buf->buf_cnt = my_obj->buf[index].user_buf.bufs_used;
1104 for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) {
1105 cont_buf->buf_idx[i] = my_obj->buf[index].user_buf.buf_idx[i];
1106 }
1107 rc = mm_stream_qbuf(my_obj, &my_obj->buf[index]);
1108 if(rc < 0) {
1109 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
1110 __func__, index, rc);
1111 } else {
1112 for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) {
1113 my_obj->buf[index].user_buf.buf_idx[i] = -1;
1114 }
1115 my_obj->buf_status[index].in_kernel = 1;
1116 my_obj->buf[index].user_buf.buf_in_use = 1;
1117 my_obj->cur_bufs_staged = 0;
1118 my_obj->cur_buf_idx = -1;
1119 }
1120 }else{
1121 CDBG("<DEBUG> : ref count pending count :%d idx = %d",
1122 my_obj->buf_status[index].buf_refcnt, index);
1123 }
1124 }
1125
1126 return rc;
1127 }
1128
1129 /*===========================================================================
1130 * FUNCTION : mm_stream_read_user_buf
1131 *
1132 * DESCRIPTION: dequeue a stream buffer from user buffer queue and fill internal structure
1133 *
1134 * PARAMETERS :
1135 * @my_obj : stream object
1136 * @buf_info : ptr to a struct storing buffer information
1137 *
1138 * RETURN : int32_t type of status
1139 * 0 -- success
1140 * -1 -- failure
1141 *==========================================================================*/
mm_stream_read_user_buf(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info)1142 int32_t mm_stream_read_user_buf(mm_stream_t * my_obj,
1143 mm_camera_buf_info_t* buf_info)
1144 {
1145 int32_t rc = 0, i;
1146 mm_camera_buf_def_t *stream_buf = NULL;
1147 struct msm_camera_user_buf_cont_t *user_buf = NULL;
1148 nsecs_t interval_nsec = 0, frame_ts = 0, timeStamp = 0;
1149 int ts_delta = 0;
1150 uint32_t frameID = 0;
1151
1152 user_buf = (struct msm_camera_user_buf_cont_t *)buf_info->buf->buffer;
1153
1154 if(user_buf != my_obj->buf[buf_info->buf->buf_idx].buffer) {
1155 CDBG_ERROR("%s : Buffer modified. ERROR",__func__);
1156 rc = -1;
1157 return rc;
1158 }
1159
1160 if (buf_info->buf->frame_idx == 1) {
1161 frameID = buf_info->buf->frame_idx;
1162 }else {
1163 frameID = (buf_info->buf->frame_idx - 1) * user_buf->buf_cnt;
1164 }
1165
1166 timeStamp = (nsecs_t)(buf_info->buf->ts.tv_sec) *
1167 1000000000LL + buf_info->buf->ts.tv_nsec;
1168
1169 if (timeStamp <= my_obj->prev_timestamp) {
1170 CDBG_ERROR("%s: TimeStamp received less than expected", __func__);
1171 mm_stream_qbuf(my_obj, buf_info->buf);
1172 return rc;
1173 } else if (my_obj->prev_timestamp == 0
1174 || (my_obj->prev_frameID != buf_info->buf->frame_idx + 1)) {
1175 /* For first frame or incase batch is droped */
1176 interval_nsec = ((my_obj->stream_info->user_buf_info.frameInterval) * 1000000);
1177 my_obj->prev_timestamp = (timeStamp - (nsecs_t)(user_buf->buf_cnt * interval_nsec));
1178 } else {
1179 ts_delta = timeStamp - my_obj->prev_timestamp;
1180 interval_nsec = (nsecs_t)(ts_delta / user_buf->buf_cnt);
1181 CDBG("%s: Timestamp delta = %d timestamp = %lld",__func__, ts_delta, timeStamp);
1182 }
1183
1184 for (i = 0; i < (int32_t)user_buf->buf_cnt; i++) {
1185 buf_info->buf->user_buf.buf_idx[i] = user_buf->buf_idx[i];
1186 stream_buf = &my_obj->plane_buf[user_buf->buf_idx[i]];
1187 stream_buf->frame_idx = frameID + i;
1188
1189 frame_ts = (i * interval_nsec) + my_obj->prev_timestamp;
1190
1191 stream_buf->ts.tv_sec = (frame_ts / 1000000000LL);
1192 stream_buf->ts.tv_nsec = (frame_ts - (stream_buf->ts.tv_sec * 1000000000LL));
1193 stream_buf->is_uv_subsampled = buf_info->buf->is_uv_subsampled;
1194
1195 CDBG("%s: buf_index %d, frame_idx %d, stream type %d, timestamp = %lld",
1196 __func__, stream_buf->buf_idx, stream_buf->frame_idx,
1197 my_obj->stream_info->stream_type, frame_ts);
1198 }
1199
1200 buf_info->buf->ts.tv_sec = (my_obj->prev_timestamp / 1000000000LL);
1201 buf_info->buf->ts.tv_nsec = (my_obj->prev_timestamp -
1202 (buf_info->buf->ts.tv_sec * 1000000000LL));
1203
1204 buf_info->buf->user_buf.bufs_used = user_buf->buf_cnt;
1205 buf_info->buf->user_buf.buf_in_use = 1;
1206
1207 my_obj->prev_timestamp = timeStamp;
1208 my_obj->prev_frameID = buf_info->buf->frame_idx;
1209
1210 CDBG("%s :X rc = %d",__func__,rc);
1211 return rc;
1212 }
1213
1214 /*===========================================================================
1215 * FUNCTION : mm_stream_read_msm_frame
1216 *
1217 * DESCRIPTION: dequeue a stream buffer from kernel queue
1218 *
1219 * PARAMETERS :
1220 * @my_obj : stream object
1221 * @buf_info : ptr to a struct storing buffer information
1222 * @num_planes : number of planes in the buffer
1223 *
1224 * RETURN : int32_t type of status
1225 * 0 -- success
1226 * -1 -- failure
1227 *==========================================================================*/
mm_stream_read_msm_frame(mm_stream_t * my_obj,mm_camera_buf_info_t * buf_info,uint8_t num_planes)1228 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
1229 mm_camera_buf_info_t* buf_info,
1230 uint8_t num_planes)
1231 {
1232 int32_t rc = 0;
1233 struct v4l2_buffer vb;
1234 struct v4l2_plane planes[VIDEO_MAX_PLANES];
1235 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1236 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1237
1238 memset(&vb, 0, sizeof(vb));
1239 vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1240 vb.memory = V4L2_MEMORY_USERPTR;
1241 vb.m.planes = &planes[0];
1242 vb.length = num_planes;
1243
1244 rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
1245 if (0 > rc) {
1246 CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed on stream type %d (rc=%d): %s",
1247 __func__, my_obj->stream_info->stream_type, rc, strerror(errno));
1248 } else {
1249 pthread_mutex_lock(&my_obj->buf_lock);
1250 my_obj->queued_buffer_count--;
1251 if (0 == my_obj->queued_buffer_count) {
1252 CDBG_HIGH("%s: Stoping poll on stream %p type: %d", __func__,
1253 my_obj, my_obj->stream_info->stream_type);
1254 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1255 my_obj->my_hdl, mm_camera_async_call);
1256 CDBG_HIGH("%s: Stopped poll on stream %p type: %d", __func__,
1257 my_obj, my_obj->stream_info->stream_type);
1258 }
1259 uint32_t idx = vb.index;
1260 buf_info->buf = &my_obj->buf[idx];
1261 buf_info->frame_idx = vb.sequence;
1262 buf_info->stream_id = my_obj->my_hdl;
1263
1264 buf_info->buf->stream_id = my_obj->my_hdl;
1265 buf_info->buf->buf_idx = idx;
1266 buf_info->buf->frame_idx = vb.sequence;
1267 buf_info->buf->ts.tv_sec = vb.timestamp.tv_sec;
1268 buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
1269 buf_info->buf->flags = vb.flags;
1270
1271 CDBG_HIGH("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d,"
1272 "queued: %d, buf_type = %d flags = %d",
1273 __func__, vb.index, buf_info->buf->frame_idx,
1274 my_obj->stream_info->stream_type, rc,
1275 my_obj->queued_buffer_count, buf_info->buf->buf_type,
1276 buf_info->buf->flags);
1277
1278 buf_info->buf->is_uv_subsampled =
1279 (vb.reserved == V4L2_PIX_FMT_NV14 || vb.reserved == V4L2_PIX_FMT_NV41);
1280
1281 if(buf_info->buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) {
1282 mm_stream_read_user_buf(my_obj, buf_info);
1283 }
1284 pthread_mutex_unlock(&my_obj->buf_lock);
1285
1286 if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) {
1287 rc = my_obj->mem_vtbl.clean_invalidate_buf(idx,
1288 my_obj->mem_vtbl.user_data);
1289 if (0 > rc) {
1290 CDBG_ERROR("%s: Clean invalidate cache failed on buffer index: %d",
1291 __func__, idx);
1292 }
1293 } else {
1294 CDBG_ERROR("%s: Clean invalidate cache op not supported", __func__);
1295 }
1296 }
1297
1298 CDBG("%s :X rc = %d",__func__,rc);
1299 return rc;
1300 }
1301
1302 /*===========================================================================
1303 * FUNCTION : mm_stream_set_parms
1304 *
1305 * DESCRIPTION: set parameters per stream
1306 *
1307 * PARAMETERS :
1308 * @my_obj : stream object
1309 * @in_value : ptr to a param struct to be set to server
1310 *
1311 * RETURN : int32_t type of status
1312 * 0 -- success
1313 * -1 -- failure
1314 * NOTE : Assume the parms struct buf is already mapped to server via
1315 * domain socket. Corresponding fields of parameters to be set
1316 * are already filled in by upper layer caller.
1317 *==========================================================================*/
mm_stream_set_parm(mm_stream_t * my_obj,cam_stream_parm_buffer_t * in_value)1318 int32_t mm_stream_set_parm(mm_stream_t *my_obj,
1319 cam_stream_parm_buffer_t *in_value)
1320 {
1321 int32_t rc = -1;
1322 int32_t value = 0;
1323 if (in_value != NULL) {
1324 rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1325 }
1326 return rc;
1327 }
1328
1329 /*===========================================================================
1330 * FUNCTION : mm_stream_get_parms
1331 *
1332 * DESCRIPTION: get parameters per stream
1333 *
1334 * PARAMETERS :
1335 * @my_obj : stream object
1336 * @in_value : ptr to a param struct to be get from server
1337 *
1338 * RETURN : int32_t type of status
1339 * 0 -- success
1340 * -1 -- failure
1341 * NOTE : Assume the parms struct buf is already mapped to server via
1342 * domain socket. Corresponding fields of parameters to be get
1343 * are already filled in by upper layer caller.
1344 *==========================================================================*/
mm_stream_get_parm(mm_stream_t * my_obj,cam_stream_parm_buffer_t * in_value)1345 int32_t mm_stream_get_parm(mm_stream_t *my_obj,
1346 cam_stream_parm_buffer_t *in_value)
1347 {
1348 int32_t rc = -1;
1349 int32_t value = 0;
1350 if (in_value != NULL) {
1351 rc = mm_camera_util_g_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1352 }
1353 return rc;
1354 }
1355
1356 /*===========================================================================
1357 * FUNCTION : mm_stream_do_actions
1358 *
1359 * DESCRIPTION: request server to perform stream based actions
1360 *
1361 * PARAMETERS :
1362 * @my_obj : stream object
1363 * @in_value : ptr to a struct of actions to be performed by the server
1364 *
1365 * RETURN : int32_t type of status
1366 * 0 -- success
1367 * -1 -- failure
1368 * NOTE : Assume the action struct buf is already mapped to server via
1369 * domain socket. Corresponding fields of actions to be performed
1370 * are already filled in by upper layer caller.
1371 *==========================================================================*/
mm_stream_do_action(mm_stream_t * my_obj,void * in_value)1372 int32_t mm_stream_do_action(mm_stream_t *my_obj,
1373 void *in_value)
1374 {
1375 int32_t rc = -1;
1376 int32_t value = 0;
1377 if (in_value != NULL) {
1378 rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value);
1379 }
1380 return rc;
1381 }
1382
1383 /*===========================================================================
1384 * FUNCTION : mm_stream_set_ext_mode
1385 *
1386 * DESCRIPTION: set stream extended mode to server via v4l2 ioctl
1387 *
1388 * PARAMETERS :
1389 * @my_obj : stream object
1390 *
1391 * RETURN : int32_t type of status
1392 * 0 -- success
1393 * -1 -- failure
1394 * NOTE : Server will return a server stream id that uniquely identify
1395 * this stream on server side. Later on communication to server
1396 * per stream should use this server stream id.
1397 *==========================================================================*/
mm_stream_set_ext_mode(mm_stream_t * my_obj)1398 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
1399 {
1400 int32_t rc = 0;
1401 struct v4l2_streamparm s_parm;
1402 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1403 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1404
1405 memset(&s_parm, 0, sizeof(s_parm));
1406 s_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1407
1408 rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
1409 CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n",
1410 __func__, my_obj->fd, rc, s_parm.parm.capture.extendedmode);
1411 if (rc == 0) {
1412 /* get server stream id */
1413 my_obj->server_stream_id = s_parm.parm.capture.extendedmode;
1414 }
1415 return rc;
1416 }
1417
1418 /*===========================================================================
1419 * FUNCTION : mm_stream_qbuf
1420 *
1421 * DESCRIPTION: enqueue buffer back to kernel queue for furture use
1422 *
1423 * PARAMETERS :
1424 * @my_obj : stream object
1425 * @buf : ptr to a struct storing buffer information
1426 *
1427 * RETURN : int32_t type of status
1428 * 0 -- success
1429 * -1 -- failure
1430 *==========================================================================*/
mm_stream_qbuf(mm_stream_t * my_obj,mm_camera_buf_def_t * buf)1431 int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
1432 {
1433 int32_t rc = 0;
1434 uint32_t length = 0;
1435 struct v4l2_buffer buffer;
1436 struct v4l2_plane planes[VIDEO_MAX_PLANES];
1437 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d, stream type = %d",
1438 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state,
1439 my_obj->stream_info->stream_type);
1440
1441 if (buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) {
1442 CDBG("%s: USERPTR num_buf = %d, idx = %d", __func__,
1443 buf->user_buf.bufs_used, buf->buf_idx);
1444 memset(&planes, 0, sizeof(planes));
1445 planes[0].length = my_obj->stream_info->user_buf_info.size;
1446 planes[0].m.userptr = buf->fd;
1447 length = 1;
1448 } else {
1449 memcpy(planes, buf->planes_buf.planes, sizeof(planes));
1450 length = buf->planes_buf.num_planes;
1451
1452 CDBG("%s:plane 0: stream_hdl=%u,fd=%d,frame idx=%d,num_planes = %u, "
1453 "offset = %d, data_offset = %d\n", __func__,
1454 buf->stream_id, buf->fd, buffer.index, buffer.length,
1455 buf->planes_buf.planes[0].reserved[0],
1456 buf->planes_buf.planes[0].data_offset);
1457 CDBG("%s:plane 1: stream_hdl=%u,fd=%d,frame idx=%d,num_planes = %u, "
1458 "offset = %d, data_offset = %d\n", __func__,
1459 buf->stream_id, buf->fd, buffer.index, buffer.length,
1460 buf->planes_buf.planes[1].reserved[0],
1461 buf->planes_buf.planes[1].data_offset);
1462 }
1463
1464 memset(&buffer, 0, sizeof(buffer));
1465 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1466 buffer.memory = V4L2_MEMORY_USERPTR;
1467 buffer.index = (__u32)buf->buf_idx;
1468 buffer.m.planes = &planes[0];
1469 buffer.length = (__u32)length;
1470
1471 if ( NULL != my_obj->mem_vtbl.invalidate_buf ) {
1472 rc = my_obj->mem_vtbl.invalidate_buf(buffer.index,
1473 my_obj->mem_vtbl.user_data);
1474 if ( 0 > rc ) {
1475 CDBG_ERROR("%s: Cache invalidate failed on buffer index: %d",
1476 __func__,
1477 buffer.index);
1478 return rc;
1479 }
1480 } else {
1481 CDBG_ERROR("%s: Cache invalidate op not added", __func__);
1482 }
1483
1484 my_obj->queued_buffer_count++;
1485 if (1 == my_obj->queued_buffer_count) {
1486 /* Add fd to data poll thread */
1487 CDBG_HIGH("%s: Starting poll on stream %p type: %d", __func__,
1488 my_obj,my_obj->stream_info->stream_type);
1489 rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
1490 my_obj->my_hdl, my_obj->fd, mm_stream_data_notify, (void*)my_obj,
1491 mm_camera_async_call);
1492 if (0 > rc) {
1493 CDBG_ERROR("%s: Add poll on stream %p type: %d fd error (rc=%d)",
1494 __func__, my_obj, my_obj->stream_info->stream_type, rc);
1495 } else {
1496 CDBG_HIGH("%s: Started poll on stream %p type: %d", __func__,
1497 my_obj, my_obj->stream_info->stream_type);
1498 }
1499 }
1500
1501 rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
1502 if (0 > rc) {
1503 CDBG_ERROR("%s: VIDIOC_QBUF ioctl call failed on stream type %d (rc=%d): %s",
1504 __func__, my_obj->stream_info->stream_type, rc, strerror(errno));
1505 my_obj->queued_buffer_count--;
1506 if (0 == my_obj->queued_buffer_count) {
1507 /* Remove fd from data poll in case of failing
1508 * first buffer queuing attempt */
1509 CDBG_HIGH("%s: Stoping poll on stream %p type: %d", __func__,
1510 my_obj, my_obj->stream_info->stream_type);
1511 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1512 my_obj->my_hdl, mm_camera_async_call);
1513 CDBG_HIGH("%s: Stopped poll on stream %p type: %d", __func__,
1514 my_obj, my_obj->stream_info->stream_type);
1515 }
1516 } else {
1517 CDBG_HIGH("%s: VIDIOC_QBUF buf_index %d, stream type %d, rc %d, queued: %d", __func__,
1518 buffer.index, my_obj->stream_info->stream_type, rc, my_obj->queued_buffer_count);
1519 }
1520
1521 return rc;
1522 }
1523
1524 /*===========================================================================
1525 * FUNCTION : mm_stream_request_buf
1526 *
1527 * DESCRIPTION: This function let kernel know the amount of buffers need to
1528 * be registered via v4l2 ioctl.
1529 *
1530 * PARAMETERS :
1531 * @my_obj : stream object
1532 *
1533 * RETURN : int32_t type of status
1534 * 0 -- success
1535 * -1 -- failure
1536 *==========================================================================*/
mm_stream_request_buf(mm_stream_t * my_obj)1537 int32_t mm_stream_request_buf(mm_stream_t * my_obj)
1538 {
1539 int32_t rc = 0;
1540 struct v4l2_requestbuffers bufreq;
1541 uint8_t buf_num = my_obj->buf_num;
1542 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1543 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1544
1545 CDBG("%s: buf_num = %d, stream type = %d",
1546 __func__, buf_num, my_obj->stream_info->stream_type);
1547
1548 if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
1549 CDBG_ERROR("%s: buf num %d > max limit %d\n",
1550 __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES);
1551 return -1;
1552 }
1553
1554 memset(&bufreq, 0, sizeof(bufreq));
1555 bufreq.count = buf_num;
1556 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1557 bufreq.memory = V4L2_MEMORY_USERPTR;
1558 rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1559 if (rc < 0) {
1560 CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n",
1561 __func__, my_obj->fd, rc);
1562 }
1563
1564 CDBG("%s :X rc = %d",__func__,rc);
1565 return rc;
1566 }
1567
1568 /*===========================================================================
1569 * FUNCTION : mm_stream_map_buf
1570 *
1571 * DESCRIPTION: mapping stream buffer via domain socket to server
1572 *
1573 * PARAMETERS :
1574 * @my_obj : stream object
1575 * @buf_type : type of buffer to be mapped. could be following values:
1576 * CAM_MAPPING_BUF_TYPE_STREAM_BUF
1577 * CAM_MAPPING_BUF_TYPE_STREAM_INFO
1578 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1579 * @frame_idx : index of buffer within the stream buffers, only valid if
1580 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1581 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1582 * @plane_idx : plane index. If all planes share the same fd,
1583 * plane_idx = -1; otherwise, plean_idx is the
1584 * index to plane (0..num_of_planes)
1585 * @fd : file descriptor of the buffer
1586 * @size : size of the buffer
1587 *
1588 * RETURN : int32_t type of status
1589 * 0 -- success
1590 * -1 -- failure
1591 *==========================================================================*/
mm_stream_map_buf(mm_stream_t * my_obj,uint8_t buf_type,uint32_t frame_idx,int32_t plane_idx,int32_t fd,size_t size)1592 int32_t mm_stream_map_buf(mm_stream_t * my_obj,
1593 uint8_t buf_type,
1594 uint32_t frame_idx,
1595 int32_t plane_idx,
1596 int32_t fd,
1597 size_t size)
1598 {
1599 if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
1600 CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
1601 return -1;
1602 }
1603 cam_sock_packet_t packet;
1604 memset(&packet, 0, sizeof(cam_sock_packet_t));
1605 packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
1606 packet.payload.buf_map.type = buf_type;
1607 packet.payload.buf_map.fd = fd;
1608 packet.payload.buf_map.size = size;
1609 packet.payload.buf_map.stream_id = my_obj->server_stream_id;
1610 packet.payload.buf_map.frame_idx = frame_idx;
1611 packet.payload.buf_map.plane_idx = plane_idx;
1612
1613 CDBG("%s: mapping buf_type %d, stream_id %d, frame_idx %d, fd %d, size %d",
1614 __func__, buf_type, my_obj->server_stream_id, frame_idx, fd, size);
1615 return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
1616 &packet,
1617 sizeof(cam_sock_packet_t),
1618 fd);
1619 }
1620
1621 /*===========================================================================
1622 * FUNCTION : mm_stream_unmap_buf
1623 *
1624 * DESCRIPTION: unmapping stream buffer via domain socket to server
1625 *
1626 * PARAMETERS :
1627 * @my_obj : stream object
1628 * @buf_type : type of buffer to be unmapped. could be following values:
1629 * CAM_MAPPING_BUF_TYPE_STREAM_BUF
1630 * CAM_MAPPING_BUF_TYPE_STREAM_INFO
1631 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1632 * @frame_idx : index of buffer within the stream buffers, only valid if
1633 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1634 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1635 * @plane_idx : plane index. If all planes share the same fd,
1636 * plane_idx = -1; otherwise, plean_idx is the
1637 * index to plane (0..num_of_planes)
1638 *
1639 * RETURN : int32_t type of status
1640 * 0 -- success
1641 * -1 -- failure
1642 *==========================================================================*/
mm_stream_unmap_buf(mm_stream_t * my_obj,uint8_t buf_type,uint32_t frame_idx,int32_t plane_idx)1643 int32_t mm_stream_unmap_buf(mm_stream_t * my_obj,
1644 uint8_t buf_type,
1645 uint32_t frame_idx,
1646 int32_t plane_idx)
1647 {
1648 if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
1649 CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__);
1650 return -1;
1651 }
1652 cam_sock_packet_t packet;
1653 memset(&packet, 0, sizeof(cam_sock_packet_t));
1654 packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
1655 packet.payload.buf_unmap.type = buf_type;
1656 packet.payload.buf_unmap.stream_id = my_obj->server_stream_id;
1657 packet.payload.buf_unmap.frame_idx = frame_idx;
1658 packet.payload.buf_unmap.plane_idx = plane_idx;
1659 return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
1660 &packet,
1661 sizeof(cam_sock_packet_t),
1662 -1);
1663 }
1664
1665 /*===========================================================================
1666 * FUNCTION : mm_stream_map_buf_ops
1667 *
1668 * DESCRIPTION: ops for mapping stream buffer via domain socket to server.
1669 * This function will be passed to upper layer as part of ops table
1670 * to be used by upper layer when allocating stream buffers and mapping
1671 * buffers to server via domain socket.
1672 *
1673 * PARAMETERS :
1674 * @frame_idx : index of buffer within the stream buffers, only valid if
1675 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1676 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1677 * @plane_idx : plane index. If all planes share the same fd,
1678 * plane_idx = -1; otherwise, plean_idx is the
1679 * index to plane (0..num_of_planes)
1680 * @fd : file descriptor of the buffer
1681 * @size : size of the buffer
1682 * @userdata : user data ptr (stream object)
1683 *
1684 * RETURN : int32_t type of status
1685 * 0 -- success
1686 * -1 -- failure
1687 *==========================================================================*/
mm_stream_map_buf_ops(uint32_t frame_idx,int32_t plane_idx,int fd,size_t size,cam_mapping_buf_type type,void * userdata)1688 static int32_t mm_stream_map_buf_ops(uint32_t frame_idx,
1689 int32_t plane_idx,
1690 int fd,
1691 size_t size,
1692 cam_mapping_buf_type type,
1693 void *userdata)
1694 {
1695 mm_stream_t *my_obj = (mm_stream_t *)userdata;
1696 return mm_stream_map_buf(my_obj,
1697 type,
1698 frame_idx, plane_idx, fd, size);
1699 }
1700
1701 /*===========================================================================
1702 * FUNCTION : mm_stream_unmap_buf_ops
1703 *
1704 * DESCRIPTION: ops for unmapping stream buffer via domain socket to server.
1705 * This function will be passed to upper layer as part of ops table
1706 * to be used by upper layer when allocating stream buffers and unmapping
1707 * buffers to server via domain socket.
1708 *
1709 * PARAMETERS :
1710 * @frame_idx : index of buffer within the stream buffers, only valid if
1711 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1712 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1713 * @plane_idx : plane index. If all planes share the same fd,
1714 * plane_idx = -1; otherwise, plean_idx is the
1715 * index to plane (0..num_of_planes)
1716 * @userdata : user data ptr (stream object)
1717 *
1718 * RETURN : int32_t type of status
1719 * 0 -- success
1720 * -1 -- failure
1721 *==========================================================================*/
mm_stream_unmap_buf_ops(uint32_t frame_idx,int32_t plane_idx,cam_mapping_buf_type type,void * userdata)1722 static int32_t mm_stream_unmap_buf_ops(uint32_t frame_idx,
1723 int32_t plane_idx,
1724 cam_mapping_buf_type type,
1725 void *userdata)
1726 {
1727 mm_stream_t *my_obj = (mm_stream_t *)userdata;
1728 return mm_stream_unmap_buf(my_obj,
1729 type,
1730 frame_idx,
1731 plane_idx);
1732 }
1733
1734 /*===========================================================================
1735 * FUNCTION : mm_stream_init_bufs
1736 *
1737 * DESCRIPTION: initialize stream buffers needed. This function will request
1738 * buffers needed from upper layer through the mem ops table passed
1739 * during configuration stage.
1740 *
1741 * PARAMETERS :
1742 * @my_obj : stream object
1743 *
1744 * RETURN : int32_t type of status
1745 * 0 -- success
1746 * -1 -- failure
1747 *==========================================================================*/
mm_stream_init_bufs(mm_stream_t * my_obj)1748 int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
1749 {
1750 int32_t i, rc = 0;
1751 uint8_t *reg_flags = NULL;
1752 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1753 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1754
1755 /* deinit buf if it's not NULL*/
1756 if (NULL != my_obj->buf) {
1757 mm_stream_deinit_bufs(my_obj);
1758 }
1759
1760 my_obj->map_ops.map_ops = mm_stream_map_buf_ops;
1761 my_obj->map_ops.unmap_ops = mm_stream_unmap_buf_ops;
1762 my_obj->map_ops.userdata = my_obj;
1763
1764 rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset,
1765 &my_obj->buf_num,
1766 ®_flags,
1767 &my_obj->buf,
1768 &my_obj->map_ops,
1769 my_obj->mem_vtbl.user_data);
1770
1771 if (0 != rc) {
1772 CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc);
1773 return rc;
1774 }
1775
1776 my_obj->buf_status =
1777 (mm_stream_buf_status_t *)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1778
1779 if (NULL == my_obj->buf_status) {
1780 CDBG_ERROR("%s: No memory for buf_status", __func__);
1781 mm_stream_deinit_bufs(my_obj);
1782 free(reg_flags);
1783 return -1;
1784 }
1785
1786 memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
1787 for (i = 0; i < my_obj->buf_num; i++) {
1788 my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
1789 my_obj->buf[i].stream_id = my_obj->my_hdl;
1790 my_obj->buf[i].stream_type = my_obj->stream_info->stream_type;
1791
1792 if (my_obj->buf[i].buf_type == CAM_STREAM_BUF_TYPE_USERPTR) {
1793 my_obj->buf[i].user_buf.bufs_used =
1794 (int8_t)my_obj->stream_info->user_buf_info.frame_buf_cnt;
1795 my_obj->buf[i].user_buf.buf_in_use = reg_flags[i];
1796 }
1797 }
1798
1799 if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) {
1800 my_obj->plane_buf = my_obj->buf[0].user_buf.plane_buf;
1801 if (my_obj->plane_buf != NULL) {
1802 my_obj->plane_buf_num =
1803 my_obj->buf_num *
1804 my_obj->stream_info->user_buf_info.frame_buf_cnt;
1805 for (i = 0; i < my_obj->plane_buf_num; i++) {
1806 my_obj->plane_buf[i].stream_id = my_obj->my_hdl;
1807 my_obj->plane_buf[i].stream_type = my_obj->stream_info->stream_type;
1808 }
1809 }
1810 my_obj->cur_bufs_staged = 0;
1811 my_obj->cur_buf_idx = -1;
1812 }
1813
1814 free(reg_flags);
1815 reg_flags = NULL;
1816
1817 /* update in stream info about number of stream buffers */
1818 my_obj->stream_info->num_bufs = my_obj->buf_num;
1819
1820 return rc;
1821 }
1822
1823 /*===========================================================================
1824 * FUNCTION : mm_stream_deinit_bufs
1825 *
1826 * DESCRIPTION: return stream buffers to upper layer through the mem ops table
1827 * passed during configuration stage.
1828 *
1829 * PARAMETERS :
1830 * @my_obj : stream object
1831 *
1832 * RETURN : int32_t type of status
1833 * 0 -- success
1834 * -1 -- failure
1835 *==========================================================================*/
mm_stream_deinit_bufs(mm_stream_t * my_obj)1836 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
1837 {
1838 int32_t rc = 0;
1839
1840 mm_camera_map_unmap_ops_tbl_t ops_tbl;
1841 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1842 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1843
1844 if (NULL == my_obj->buf) {
1845 CDBG("%s: Buf is NULL, no need to deinit", __func__);
1846 return rc;
1847 }
1848
1849 /* release bufs */
1850 ops_tbl.map_ops = mm_stream_map_buf_ops;
1851 ops_tbl.unmap_ops = mm_stream_unmap_buf_ops;
1852 ops_tbl.userdata = my_obj;
1853
1854 rc = my_obj->mem_vtbl.put_bufs(&ops_tbl,
1855 my_obj->mem_vtbl.user_data);
1856
1857 if (my_obj->plane_buf != NULL) {
1858 free(my_obj->plane_buf);
1859 my_obj->plane_buf = NULL;
1860 }
1861
1862 free(my_obj->buf);
1863 my_obj->buf = NULL;
1864 if (my_obj->buf_status != NULL) {
1865 free(my_obj->buf_status);
1866 my_obj->buf_status = NULL;
1867 }
1868
1869 return rc;
1870 }
1871
1872 /*===========================================================================
1873 * FUNCTION : mm_stream_reg_buf
1874 *
1875 * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for
1876 * each buffer in the stream
1877 *
1878 * PARAMETERS :
1879 * @my_obj : stream object
1880 *
1881 * RETURN : int32_t type of status
1882 * 0 -- success
1883 * -1 -- failure
1884 *==========================================================================*/
mm_stream_reg_buf(mm_stream_t * my_obj)1885 int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
1886 {
1887 int32_t rc = 0;
1888 uint8_t i;
1889 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1890 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1891
1892 rc = mm_stream_request_buf(my_obj);
1893 if (rc != 0) {
1894 return rc;
1895 }
1896
1897 pthread_mutex_lock(&my_obj->buf_lock);
1898 my_obj->queued_buffer_count = 0;
1899 for(i = 0; i < my_obj->buf_num; i++){
1900 /* check if need to qbuf initially */
1901 if (my_obj->buf_status[i].initial_reg_flag) {
1902 rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
1903 if (rc != 0) {
1904 CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc);
1905 break;
1906 }
1907 my_obj->buf_status[i].buf_refcnt = 0;
1908 my_obj->buf_status[i].in_kernel = 1;
1909 } else {
1910 /* the buf is held by upper layer, will not queue into kernel.
1911 * add buf reference count */
1912 my_obj->buf_status[i].buf_refcnt = 1;
1913 my_obj->buf_status[i].in_kernel = 0;
1914 }
1915 }
1916 pthread_mutex_unlock(&my_obj->buf_lock);
1917
1918 return rc;
1919 }
1920
1921 /*===========================================================================
1922 * FUNCTION : mm_stream_unreg buf
1923 *
1924 * DESCRIPTION: unregister all stream buffers from kernel
1925 *
1926 * PARAMETERS :
1927 * @my_obj : stream object
1928 *
1929 * RETURN : int32_t type of status
1930 * 0 -- success
1931 * -1 -- failure
1932 *==========================================================================*/
mm_stream_unreg_buf(mm_stream_t * my_obj)1933 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
1934 {
1935 struct v4l2_requestbuffers bufreq;
1936 int32_t i, rc = 0;
1937 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
1938 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
1939
1940 /* unreg buf to kernel */
1941 bufreq.count = 0;
1942 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1943 bufreq.memory = V4L2_MEMORY_USERPTR;
1944 rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
1945 if (rc < 0) {
1946 CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n",
1947 __func__, my_obj->fd, rc);
1948 }
1949
1950 /* reset buf reference count */
1951 pthread_mutex_lock(&my_obj->buf_lock);
1952 if (NULL != my_obj->buf_status) {
1953 for(i = 0; i < my_obj->buf_num; i++){
1954 my_obj->buf_status[i].buf_refcnt = 0;
1955 my_obj->buf_status[i].in_kernel = 0;
1956 }
1957 }
1958 pthread_mutex_unlock(&my_obj->buf_lock);
1959
1960 return rc;
1961 }
1962
1963 /*===========================================================================
1964 * FUNCTION : mm_stream_get_v4l2_fmt
1965 *
1966 * DESCRIPTION: translate camera image format into FOURCC code
1967 *
1968 * PARAMETERS :
1969 * @fmt : camera image format
1970 *
1971 * RETURN : FOURCC code for image format
1972 *==========================================================================*/
mm_stream_get_v4l2_fmt(cam_format_t fmt)1973 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt)
1974 {
1975 uint32_t val;
1976 switch(fmt) {
1977 case CAM_FORMAT_YUV_420_NV12:
1978 case CAM_FORMAT_YUV_420_NV12_VENUS:
1979 val = V4L2_PIX_FMT_NV12;
1980 break;
1981 case CAM_FORMAT_YUV_420_NV21:
1982 val = V4L2_PIX_FMT_NV21;
1983 break;
1984 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
1985 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
1986 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
1987 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
1988 val= V4L2_PIX_FMT_SBGGR10;
1989 break;
1990 case CAM_FORMAT_YUV_422_NV61:
1991 val= V4L2_PIX_FMT_NV61;
1992 break;
1993 case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
1994 val= V4L2_PIX_FMT_YUYV;
1995 break;
1996 case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
1997 val= V4L2_PIX_FMT_YVYU;
1998 break;
1999 case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
2000 val= V4L2_PIX_FMT_UYVY;
2001 break;
2002 case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
2003 val= V4L2_PIX_FMT_VYUY;
2004 break;
2005 case CAM_FORMAT_YUV_420_YV12:
2006 val= V4L2_PIX_FMT_NV12;
2007 break;
2008 case CAM_FORMAT_YUV_422_NV16:
2009 val= V4L2_PIX_FMT_NV16;
2010 break;
2011 default:
2012 val = 0;
2013 CDBG_ERROR("%s: Unknown fmt=%d", __func__, fmt);
2014 break;
2015 }
2016 CDBG("%s: fmt=%d, val =%d", __func__, fmt, val);
2017 return val;
2018 }
2019
2020 /*===========================================================================
2021 * FUNCTION : mm_stream_calc_offset_preview
2022 *
2023 * DESCRIPTION: calculate preview frame offset based on format and
2024 * padding information
2025 *
2026 * PARAMETERS :
2027 * @fmt : image format
2028 * @dim : image dimension
2029 * @buf_planes : [out] buffer plane information
2030 *
2031 * RETURN : int32_t type of status
2032 * 0 -- success
2033 * -1 -- failure
2034 *==========================================================================*/
mm_stream_calc_offset_preview(cam_format_t fmt,cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)2035 int32_t mm_stream_calc_offset_preview(cam_format_t fmt,
2036 cam_dimension_t *dim,
2037 cam_stream_buf_plane_info_t *buf_planes)
2038 {
2039 int32_t rc = 0;
2040 int stride = 0, scanline = 0;
2041
2042 switch (fmt) {
2043 case CAM_FORMAT_YUV_420_NV12:
2044 case CAM_FORMAT_YUV_420_NV21:
2045 /* 2 planes: Y + CbCr */
2046 buf_planes->plane_info.num_planes = 2;
2047
2048 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
2049 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
2050
2051 buf_planes->plane_info.mp[0].offset = 0;
2052 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2053 buf_planes->plane_info.mp[0].offset_x = 0;
2054 buf_planes->plane_info.mp[0].offset_y = 0;
2055 buf_planes->plane_info.mp[0].stride = stride;
2056 buf_planes->plane_info.mp[0].scanline = scanline;
2057 buf_planes->plane_info.mp[0].width = dim->width;
2058 buf_planes->plane_info.mp[0].height = dim->height;
2059
2060 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
2061 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_2);
2062 buf_planes->plane_info.mp[1].offset = 0;
2063 buf_planes->plane_info.mp[1].len =
2064 (uint32_t)(stride * scanline);
2065 buf_planes->plane_info.mp[1].offset_x = 0;
2066 buf_planes->plane_info.mp[1].offset_y = 0;
2067 buf_planes->plane_info.mp[1].stride = stride;
2068 buf_planes->plane_info.mp[1].scanline = scanline;
2069 buf_planes->plane_info.mp[1].width = dim->width;
2070 buf_planes->plane_info.mp[1].height = dim->height / 2;
2071
2072 buf_planes->plane_info.frame_len =
2073 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2074 buf_planes->plane_info.mp[1].len,
2075 CAM_PAD_TO_4K);
2076 break;
2077 case CAM_FORMAT_YUV_420_NV21_ADRENO:
2078 /* 2 planes: Y + CbCr */
2079 buf_planes->plane_info.num_planes = 2;
2080
2081 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
2082 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
2083 buf_planes->plane_info.mp[0].offset = 0;
2084 buf_planes->plane_info.mp[0].len =
2085 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
2086 buf_planes->plane_info.mp[0].offset_x = 0;
2087 buf_planes->plane_info.mp[0].offset_y = 0;
2088 buf_planes->plane_info.mp[0].stride = stride;
2089 buf_planes->plane_info.mp[0].scanline = scanline;
2090 buf_planes->plane_info.mp[0].width = dim->width;
2091 buf_planes->plane_info.mp[0].height = dim->height;
2092
2093 stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
2094 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
2095 buf_planes->plane_info.mp[1].offset = 0;
2096 buf_planes->plane_info.mp[1].len =
2097 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
2098 buf_planes->plane_info.mp[1].offset_x = 0;
2099 buf_planes->plane_info.mp[1].offset_y = 0;
2100 buf_planes->plane_info.mp[1].stride = stride;
2101 buf_planes->plane_info.mp[1].scanline = scanline;
2102 buf_planes->plane_info.mp[1].width = dim->width;
2103 buf_planes->plane_info.mp[1].height = dim->height / 2;
2104
2105 buf_planes->plane_info.frame_len =
2106 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2107 buf_planes->plane_info.mp[1].len,
2108 CAM_PAD_TO_4K);
2109 break;
2110 case CAM_FORMAT_YUV_420_YV12:
2111 /* 3 planes: Y + Cr + Cb */
2112 buf_planes->plane_info.num_planes = 3;
2113
2114 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2115 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
2116 buf_planes->plane_info.mp[0].offset = 0;
2117 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2118 buf_planes->plane_info.mp[0].offset_x = 0;
2119 buf_planes->plane_info.mp[0].offset_y = 0;
2120 buf_planes->plane_info.mp[0].stride = stride;
2121 buf_planes->plane_info.mp[0].scanline = scanline;
2122 buf_planes->plane_info.mp[0].width = dim->width;
2123 buf_planes->plane_info.mp[0].height = dim->height;
2124
2125 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
2126 scanline = scanline / 2;
2127 buf_planes->plane_info.mp[1].offset = 0;
2128 buf_planes->plane_info.mp[1].len =
2129 (uint32_t)(stride * scanline);
2130 buf_planes->plane_info.mp[1].offset_x = 0;
2131 buf_planes->plane_info.mp[1].offset_y = 0;
2132 buf_planes->plane_info.mp[1].stride = stride;
2133 buf_planes->plane_info.mp[1].scanline = scanline;
2134 buf_planes->plane_info.mp[1].width = dim->width / 2;
2135 buf_planes->plane_info.mp[1].height = dim->height / 2;
2136
2137 buf_planes->plane_info.mp[2].offset = 0;
2138 buf_planes->plane_info.mp[2].len =
2139 (uint32_t)(stride * scanline);
2140 buf_planes->plane_info.mp[2].offset_x = 0;
2141 buf_planes->plane_info.mp[2].offset_y = 0;
2142 buf_planes->plane_info.mp[2].stride = stride;
2143 buf_planes->plane_info.mp[2].scanline = scanline;
2144 buf_planes->plane_info.mp[2].width = dim->width / 2;
2145 buf_planes->plane_info.mp[2].height = dim->height / 2;
2146
2147 buf_planes->plane_info.frame_len =
2148 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2149 buf_planes->plane_info.mp[1].len +
2150 buf_planes->plane_info.mp[2].len,
2151 CAM_PAD_TO_4K);
2152 break;
2153 case CAM_FORMAT_YUV_422_NV16:
2154 case CAM_FORMAT_YUV_422_NV61:
2155 /* 2 planes: Y + CbCr */
2156 buf_planes->plane_info.num_planes = 2;
2157
2158 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2159 scanline = dim->height;
2160 buf_planes->plane_info.mp[0].offset = 0;
2161 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2162 buf_planes->plane_info.mp[0].offset_x = 0;
2163 buf_planes->plane_info.mp[0].offset_y = 0;
2164 buf_planes->plane_info.mp[0].stride = stride;
2165 buf_planes->plane_info.mp[0].scanline = scanline;
2166 buf_planes->plane_info.mp[0].width = dim->width;
2167 buf_planes->plane_info.mp[0].height = dim->height;
2168
2169 buf_planes->plane_info.mp[1].offset = 0;
2170 buf_planes->plane_info.mp[1].len = (uint32_t)(stride * scanline);
2171 buf_planes->plane_info.mp[1].offset_x = 0;
2172 buf_planes->plane_info.mp[1].offset_y = 0;
2173 buf_planes->plane_info.mp[1].stride = stride;
2174 buf_planes->plane_info.mp[1].scanline = scanline;
2175 buf_planes->plane_info.mp[1].width = dim->width;
2176 buf_planes->plane_info.mp[1].height = dim->height;
2177
2178 buf_planes->plane_info.frame_len =
2179 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2180 buf_planes->plane_info.mp[1].len,
2181 CAM_PAD_TO_4K);
2182 break;
2183 case CAM_FORMAT_YUV_420_NV12_VENUS:
2184 #ifdef VENUS_PRESENT
2185 // using Venus
2186 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
2187 scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
2188
2189 buf_planes->plane_info.frame_len =
2190 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
2191 buf_planes->plane_info.num_planes = 2;
2192 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2193 buf_planes->plane_info.mp[0].offset = 0;
2194 buf_planes->plane_info.mp[0].offset_x =0;
2195 buf_planes->plane_info.mp[0].offset_y = 0;
2196 buf_planes->plane_info.mp[0].stride = stride;
2197 buf_planes->plane_info.mp[0].scanline = scanline;
2198 buf_planes->plane_info.mp[0].width = dim->width;
2199 buf_planes->plane_info.mp[0].height = dim->height;
2200 stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
2201 scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
2202 buf_planes->plane_info.mp[1].len =
2203 buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2204 buf_planes->plane_info.mp[1].offset = 0;
2205 buf_planes->plane_info.mp[1].offset_x =0;
2206 buf_planes->plane_info.mp[1].offset_y = 0;
2207 buf_planes->plane_info.mp[1].stride = stride;
2208 buf_planes->plane_info.mp[1].scanline = scanline;
2209 buf_planes->plane_info.mp[1].width = dim->width;
2210 buf_planes->plane_info.mp[1].height = dim->height / 2;
2211 #else
2212 CDBG_ERROR("%s: Venus hardware not avail, cannot use this format", __func__);
2213 rc = -1;
2214 #endif
2215 break;
2216 default:
2217 CDBG_ERROR("%s: Invalid cam_format for preview %d",
2218 __func__, fmt);
2219 rc = -1;
2220 break;
2221 }
2222
2223 return rc;
2224 }
2225 /*===========================================================================
2226 * FUNCTION : mm_stream_calc_offset_post_view
2227 *
2228 * DESCRIPTION: calculate postview frame offset based on format and
2229 * padding information
2230 *
2231 * PARAMETERS :
2232 * @fmt : image format
2233 * @dim : image dimension
2234 * @buf_planes : [out] buffer plane information
2235 *
2236 * RETURN : int32_t type of status
2237 * 0 -- success
2238 * -1 -- failure
2239 *==========================================================================*/
mm_stream_calc_offset_post_view(cam_format_t fmt,cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)2240 int32_t mm_stream_calc_offset_post_view(cam_format_t fmt,
2241 cam_dimension_t *dim,
2242 cam_stream_buf_plane_info_t *buf_planes)
2243 {
2244 int32_t rc = 0;
2245 int stride = 0, scanline = 0;
2246
2247 switch (fmt) {
2248 case CAM_FORMAT_YUV_420_NV12:
2249 case CAM_FORMAT_YUV_420_NV21:
2250 /* 2 planes: Y + CbCr */
2251 buf_planes->plane_info.num_planes = 2;
2252
2253 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64);
2254 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_64);
2255 buf_planes->plane_info.mp[0].offset = 0;
2256 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2257 buf_planes->plane_info.mp[0].offset_x = 0;
2258 buf_planes->plane_info.mp[0].offset_y = 0;
2259 buf_planes->plane_info.mp[0].stride = stride;
2260 buf_planes->plane_info.mp[0].scanline = scanline;
2261 buf_planes->plane_info.mp[0].width = dim->width;
2262 buf_planes->plane_info.mp[0].height = dim->height;
2263
2264 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64);
2265 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_64);
2266 buf_planes->plane_info.mp[1].offset = 0;
2267 buf_planes->plane_info.mp[1].len =
2268 (uint32_t)(stride * scanline);
2269 buf_planes->plane_info.mp[1].offset_x = 0;
2270 buf_planes->plane_info.mp[1].offset_y = 0;
2271 buf_planes->plane_info.mp[1].stride = stride;
2272 buf_planes->plane_info.mp[1].scanline = scanline;
2273 buf_planes->plane_info.mp[1].width = dim->width;
2274 buf_planes->plane_info.mp[1].height = dim->height / 2;
2275
2276 buf_planes->plane_info.frame_len =
2277 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2278 buf_planes->plane_info.mp[1].len,
2279 CAM_PAD_TO_4K);
2280 break;
2281 case CAM_FORMAT_YUV_420_NV21_ADRENO:
2282 /* 2 planes: Y + CbCr */
2283 buf_planes->plane_info.num_planes = 2;
2284
2285 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
2286 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
2287 buf_planes->plane_info.mp[0].offset = 0;
2288 buf_planes->plane_info.mp[0].len =
2289 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
2290 buf_planes->plane_info.mp[0].offset_x = 0;
2291 buf_planes->plane_info.mp[0].offset_y = 0;
2292 buf_planes->plane_info.mp[0].stride = stride;
2293 buf_planes->plane_info.mp[0].scanline = scanline;
2294 buf_planes->plane_info.mp[0].width = dim->width;
2295 buf_planes->plane_info.mp[0].height = dim->height;
2296
2297 stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
2298 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
2299 buf_planes->plane_info.mp[1].offset = 0;
2300 buf_planes->plane_info.mp[1].len =
2301 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
2302 buf_planes->plane_info.mp[1].offset_x = 0;
2303 buf_planes->plane_info.mp[1].offset_y = 0;
2304 buf_planes->plane_info.mp[1].stride = stride;
2305 buf_planes->plane_info.mp[1].scanline = scanline;
2306 buf_planes->plane_info.mp[1].width = dim->width;
2307 buf_planes->plane_info.mp[1].height = dim->height / 2;
2308
2309 buf_planes->plane_info.frame_len =
2310 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2311 buf_planes->plane_info.mp[1].len,
2312 CAM_PAD_TO_4K);
2313 break;
2314 case CAM_FORMAT_YUV_420_YV12:
2315 /* 3 planes: Y + Cr + Cb */
2316 buf_planes->plane_info.num_planes = 3;
2317
2318 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2319 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
2320 buf_planes->plane_info.mp[0].offset = 0;
2321 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2322 buf_planes->plane_info.mp[0].offset_x = 0;
2323 buf_planes->plane_info.mp[0].offset_y = 0;
2324 buf_planes->plane_info.mp[0].stride = stride;
2325 buf_planes->plane_info.mp[0].scanline = scanline;
2326 buf_planes->plane_info.mp[0].width = dim->width;
2327 buf_planes->plane_info.mp[0].height = dim->height;
2328
2329 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
2330 scanline = scanline / 2;
2331 buf_planes->plane_info.mp[1].offset = 0;
2332 buf_planes->plane_info.mp[1].len =
2333 (uint32_t)(stride * scanline);
2334 buf_planes->plane_info.mp[1].offset_x = 0;
2335 buf_planes->plane_info.mp[1].offset_y = 0;
2336 buf_planes->plane_info.mp[1].stride = stride;
2337 buf_planes->plane_info.mp[1].scanline = scanline;
2338 buf_planes->plane_info.mp[1].width = dim->width / 2;
2339 buf_planes->plane_info.mp[1].height = dim->height / 2;
2340
2341 buf_planes->plane_info.mp[2].offset = 0;
2342 buf_planes->plane_info.mp[2].len =
2343 (uint32_t)(stride * scanline);
2344 buf_planes->plane_info.mp[2].offset_x = 0;
2345 buf_planes->plane_info.mp[2].offset_y = 0;
2346 buf_planes->plane_info.mp[2].stride = stride;
2347 buf_planes->plane_info.mp[2].scanline = scanline;
2348 buf_planes->plane_info.mp[2].width = dim->width / 2;
2349 buf_planes->plane_info.mp[2].height = dim->height / 2;
2350
2351 buf_planes->plane_info.frame_len =
2352 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2353 buf_planes->plane_info.mp[1].len +
2354 buf_planes->plane_info.mp[2].len,
2355 CAM_PAD_TO_4K);
2356 break;
2357 case CAM_FORMAT_YUV_422_NV16:
2358 case CAM_FORMAT_YUV_422_NV61:
2359 /* 2 planes: Y + CbCr */
2360 buf_planes->plane_info.num_planes = 2;
2361
2362 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2363 scanline = dim->height;
2364 buf_planes->plane_info.mp[0].offset = 0;
2365 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2366 buf_planes->plane_info.mp[0].offset_x = 0;
2367 buf_planes->plane_info.mp[0].offset_y = 0;
2368 buf_planes->plane_info.mp[0].stride = stride;
2369 buf_planes->plane_info.mp[0].scanline = scanline;
2370 buf_planes->plane_info.mp[0].width = dim->width;
2371 buf_planes->plane_info.mp[0].height = dim->height;
2372
2373 buf_planes->plane_info.mp[1].offset = 0;
2374 buf_planes->plane_info.mp[1].len = (uint32_t)(stride * scanline);
2375 buf_planes->plane_info.mp[1].offset_x = 0;
2376 buf_planes->plane_info.mp[1].offset_y = 0;
2377 buf_planes->plane_info.mp[1].stride = stride;
2378 buf_planes->plane_info.mp[1].scanline = scanline;
2379 buf_planes->plane_info.mp[1].width = dim->width;
2380 buf_planes->plane_info.mp[1].height = dim->height;
2381
2382 buf_planes->plane_info.frame_len =
2383 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2384 buf_planes->plane_info.mp[1].len,
2385 CAM_PAD_TO_4K);
2386 break;
2387 case CAM_FORMAT_YUV_420_NV12_VENUS:
2388 #ifdef VENUS_PRESENT
2389 // using Venus
2390 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
2391 scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
2392
2393 buf_planes->plane_info.frame_len =
2394 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
2395 buf_planes->plane_info.num_planes = 2;
2396 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2397 buf_planes->plane_info.mp[0].offset = 0;
2398 buf_planes->plane_info.mp[0].offset_x =0;
2399 buf_planes->plane_info.mp[0].offset_y = 0;
2400 buf_planes->plane_info.mp[0].stride = stride;
2401 buf_planes->plane_info.mp[0].scanline = scanline;
2402 buf_planes->plane_info.mp[0].width = dim->width;
2403 buf_planes->plane_info.mp[0].height = dim->height;
2404 stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
2405 scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
2406 buf_planes->plane_info.mp[1].len =
2407 buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2408 buf_planes->plane_info.mp[1].offset = 0;
2409 buf_planes->plane_info.mp[1].offset_x =0;
2410 buf_planes->plane_info.mp[1].offset_y = 0;
2411 buf_planes->plane_info.mp[1].stride = stride;
2412 buf_planes->plane_info.mp[1].scanline = scanline;
2413 buf_planes->plane_info.mp[1].width = dim->width;
2414 buf_planes->plane_info.mp[1].height = dim->height / 2;
2415 #else
2416 CDBG_ERROR("%s: Venus hardware not avail, cannot use this format", __func__);
2417 rc = -1;
2418 #endif
2419 break;
2420 default:
2421 CDBG_ERROR("%s: Invalid cam_format for preview %d",
2422 __func__, fmt);
2423 rc = -1;
2424 break;
2425 }
2426
2427 return rc;
2428 }
2429
2430 /*===========================================================================
2431 * FUNCTION : mm_stream_calc_offset_snapshot
2432 *
2433 * DESCRIPTION: calculate snapshot/postproc frame offset based on format and
2434 * padding information
2435 *
2436 * PARAMETERS :
2437 * @fmt : image format
2438 * @dim : image dimension
2439 * @padding : padding information
2440 * @buf_planes : [out] buffer plane information
2441 *
2442 * RETURN : int32_t type of status
2443 * 0 -- success
2444 * -1 -- failure
2445 *==========================================================================*/
mm_stream_calc_offset_snapshot(cam_format_t fmt,cam_dimension_t * dim,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)2446 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
2447 cam_dimension_t *dim,
2448 cam_padding_info_t *padding,
2449 cam_stream_buf_plane_info_t *buf_planes)
2450 {
2451 int32_t rc = 0;
2452 uint8_t isAFamily = mm_camera_util_chip_is_a_family();
2453 int offset_x = 0, offset_y = 0;
2454 int stride = 0, scanline = 0;
2455
2456 if (isAFamily) {
2457 stride = dim->width;
2458 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16);
2459 offset_x = 0;
2460 offset_y = scanline - dim->height;
2461 scanline += offset_y; /* double padding */
2462 } else {
2463 stride = PAD_TO_SIZE(dim->width,
2464 padding->width_padding);
2465 scanline = PAD_TO_SIZE(dim->height,
2466 padding->height_padding);
2467 offset_x = 0;
2468 offset_y = 0;
2469 }
2470
2471 switch (fmt) {
2472 case CAM_FORMAT_YUV_420_NV12:
2473 case CAM_FORMAT_YUV_420_NV21:
2474 /* 2 planes: Y + CbCr */
2475 buf_planes->plane_info.num_planes = 2;
2476
2477 buf_planes->plane_info.mp[0].len =
2478 PAD_TO_SIZE((uint32_t)(stride * scanline),
2479 padding->plane_padding);
2480 buf_planes->plane_info.mp[0].offset =
2481 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
2482 padding->plane_padding);
2483 buf_planes->plane_info.mp[0].offset_x = offset_x;
2484 buf_planes->plane_info.mp[0].offset_y = offset_y;
2485 buf_planes->plane_info.mp[0].stride = stride;
2486 buf_planes->plane_info.mp[0].scanline = scanline;
2487 buf_planes->plane_info.mp[0].width = dim->width;
2488 buf_planes->plane_info.mp[0].height = dim->height;
2489
2490 scanline = scanline / 2;
2491 buf_planes->plane_info.mp[1].len =
2492 PAD_TO_SIZE((uint32_t)(stride * scanline),
2493 padding->plane_padding);
2494 buf_planes->plane_info.mp[1].offset =
2495 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
2496 padding->plane_padding);
2497 buf_planes->plane_info.mp[1].offset_x = offset_x;
2498 buf_planes->plane_info.mp[1].offset_y = offset_y;
2499 buf_planes->plane_info.mp[1].stride = stride;
2500 buf_planes->plane_info.mp[1].scanline = scanline;
2501 buf_planes->plane_info.mp[1].width = dim->width;
2502 buf_planes->plane_info.mp[1].height = dim->height / 2;
2503
2504 buf_planes->plane_info.frame_len =
2505 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2506 buf_planes->plane_info.mp[1].len,
2507 CAM_PAD_TO_4K);
2508 break;
2509 case CAM_FORMAT_YUV_420_YV12:
2510 /* 3 planes: Y + Cr + Cb */
2511 buf_planes->plane_info.num_planes = 3;
2512
2513 buf_planes->plane_info.mp[0].offset =
2514 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
2515 padding->plane_padding);
2516 buf_planes->plane_info.mp[0].len =
2517 PAD_TO_SIZE((uint32_t)(stride * scanline),
2518 padding->plane_padding);
2519 buf_planes->plane_info.mp[0].offset_x = offset_x;
2520 buf_planes->plane_info.mp[0].offset_y = offset_y;
2521 buf_planes->plane_info.mp[0].stride = stride;
2522 buf_planes->plane_info.mp[0].scanline = scanline;
2523 buf_planes->plane_info.mp[0].width = dim->width;
2524 buf_planes->plane_info.mp[0].height = dim->height;
2525
2526 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
2527 scanline = scanline / 2;
2528 buf_planes->plane_info.mp[1].offset =
2529 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
2530 padding->plane_padding);
2531 buf_planes->plane_info.mp[1].len =
2532 PAD_TO_SIZE((uint32_t)(stride * scanline),
2533 padding->plane_padding);
2534 buf_planes->plane_info.mp[1].offset_x = offset_x;
2535 buf_planes->plane_info.mp[1].offset_y = offset_y;
2536 buf_planes->plane_info.mp[1].stride = stride;
2537 buf_planes->plane_info.mp[1].scanline = scanline;
2538 buf_planes->plane_info.mp[1].width = dim->width / 2;
2539 buf_planes->plane_info.mp[1].height = dim->height / 2;
2540
2541 buf_planes->plane_info.mp[2].offset =
2542 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
2543 padding->plane_padding);
2544 buf_planes->plane_info.mp[2].len =
2545 PAD_TO_SIZE((uint32_t)(stride * scanline),
2546 padding->plane_padding);
2547 buf_planes->plane_info.mp[2].offset_x = offset_x;
2548 buf_planes->plane_info.mp[2].offset_y = offset_y;
2549 buf_planes->plane_info.mp[2].stride = stride;
2550 buf_planes->plane_info.mp[2].scanline = scanline;
2551 buf_planes->plane_info.mp[2].width = dim->width / 2;
2552 buf_planes->plane_info.mp[2].height = dim->height / 2;
2553
2554 buf_planes->plane_info.frame_len =
2555 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2556 buf_planes->plane_info.mp[1].len +
2557 buf_planes->plane_info.mp[2].len,
2558 CAM_PAD_TO_4K);
2559 break;
2560 case CAM_FORMAT_YUV_422_NV16:
2561 case CAM_FORMAT_YUV_422_NV61:
2562 /* 2 planes: Y + CbCr */
2563 buf_planes->plane_info.num_planes = 2;
2564 buf_planes->plane_info.mp[0].len =
2565 PAD_TO_SIZE((uint32_t)(stride * scanline),
2566 padding->plane_padding);
2567 buf_planes->plane_info.mp[0].offset =
2568 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
2569 padding->plane_padding);
2570 buf_planes->plane_info.mp[0].offset_x = offset_x;
2571 buf_planes->plane_info.mp[0].offset_y = offset_y;
2572 buf_planes->plane_info.mp[0].stride = stride;
2573 buf_planes->plane_info.mp[0].scanline = scanline;
2574 buf_planes->plane_info.mp[0].width = dim->width;
2575 buf_planes->plane_info.mp[0].height = dim->height;
2576
2577 buf_planes->plane_info.mp[1].len =
2578 PAD_TO_SIZE((uint32_t)(stride * scanline),
2579 padding->plane_padding);
2580 buf_planes->plane_info.mp[1].offset =
2581 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
2582 padding->plane_padding);
2583 buf_planes->plane_info.mp[1].offset_x = offset_x;
2584 buf_planes->plane_info.mp[1].offset_y = offset_y;
2585 buf_planes->plane_info.mp[1].stride = stride;
2586 buf_planes->plane_info.mp[1].scanline = scanline;
2587 buf_planes->plane_info.mp[1].width = dim->width;
2588 buf_planes->plane_info.mp[1].height = dim->height;
2589
2590 buf_planes->plane_info.frame_len = PAD_TO_SIZE(
2591 buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len,
2592 CAM_PAD_TO_4K);
2593 break;
2594 default:
2595 CDBG_ERROR("%s: Invalid cam_format for snapshot %d",
2596 __func__, fmt);
2597 rc = -1;
2598 break;
2599 }
2600
2601 return rc;
2602 }
2603
2604 /*===========================================================================
2605 * FUNCTION : mm_stream_calc_offset_raw
2606 *
2607 * DESCRIPTION: calculate raw frame offset based on format and padding information
2608 *
2609 * PARAMETERS :
2610 * @fmt : image format
2611 * @dim : image dimension
2612 * @padding : padding information
2613 * @buf_planes : [out] buffer plane information
2614 *
2615 * RETURN : int32_t type of status
2616 * 0 -- success
2617 * -1 -- failure
2618 *==========================================================================*/
mm_stream_calc_offset_raw(cam_format_t fmt,cam_dimension_t * dim,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)2619 int32_t mm_stream_calc_offset_raw(cam_format_t fmt,
2620 cam_dimension_t *dim,
2621 cam_padding_info_t *padding,
2622 cam_stream_buf_plane_info_t *buf_planes)
2623 {
2624 int32_t rc = 0;
2625
2626 if ((NULL == dim) || (NULL == padding) || (NULL == buf_planes)) {
2627 return -1;
2628 }
2629
2630 int32_t stride = PAD_TO_SIZE(dim->width, (int32_t)padding->width_padding);
2631 int32_t stride_in_bytes = stride;
2632 int32_t scanline = PAD_TO_SIZE(dim->height, (int32_t)padding->height_padding);
2633
2634 switch (fmt) {
2635 case CAM_FORMAT_YUV_420_NV21:
2636 /* 2 planes: Y + CbCr */
2637 buf_planes->plane_info.num_planes = 2;
2638
2639 buf_planes->plane_info.mp[0].len =
2640 PAD_TO_SIZE((uint32_t)(stride * scanline),
2641 padding->plane_padding);
2642 buf_planes->plane_info.mp[0].offset = 0;
2643 buf_planes->plane_info.mp[0].offset_x = 0;
2644 buf_planes->plane_info.mp[0].offset_y = 0;
2645 buf_planes->plane_info.mp[0].stride = stride;
2646 buf_planes->plane_info.mp[0].stride_in_bytes = stride;
2647 buf_planes->plane_info.mp[0].scanline = scanline;
2648 buf_planes->plane_info.mp[0].width = dim->width;
2649 buf_planes->plane_info.mp[0].height = dim->height;
2650
2651 scanline = scanline / 2;
2652 buf_planes->plane_info.mp[1].len =
2653 PAD_TO_SIZE((uint32_t)(stride * scanline),
2654 padding->plane_padding);
2655 buf_planes->plane_info.mp[1].offset = 0;
2656 buf_planes->plane_info.mp[1].offset_x = 0;
2657 buf_planes->plane_info.mp[1].offset_y = 0;
2658 buf_planes->plane_info.mp[1].stride = stride;
2659 buf_planes->plane_info.mp[1].stride_in_bytes = stride;
2660 buf_planes->plane_info.mp[1].scanline = scanline;
2661 buf_planes->plane_info.mp[1].width = dim->width;
2662 buf_planes->plane_info.mp[1].height = dim->height / 2;
2663
2664 buf_planes->plane_info.frame_len =
2665 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2666 buf_planes->plane_info.mp[1].len,
2667 CAM_PAD_TO_4K);
2668 break;
2669 case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
2670 case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
2671 case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
2672 case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
2673 case CAM_FORMAT_JPEG_RAW_8BIT:
2674 /* 1 plane */
2675 /* Every 16 pixels occupy 16 bytes */
2676 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2677 stride_in_bytes = stride * 2;
2678 buf_planes->plane_info.num_planes = 1;
2679 buf_planes->plane_info.mp[0].offset = 0;
2680 buf_planes->plane_info.mp[0].len =
2681 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
2682 padding->plane_padding);
2683 buf_planes->plane_info.frame_len =
2684 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2685 buf_planes->plane_info.mp[0].offset_x =0;
2686 buf_planes->plane_info.mp[0].offset_y = 0;
2687 buf_planes->plane_info.mp[0].stride = stride;
2688 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
2689 buf_planes->plane_info.mp[0].scanline = scanline;
2690 buf_planes->plane_info.mp[0].width =
2691 (int32_t)buf_planes->plane_info.mp[0].len;
2692 buf_planes->plane_info.mp[0].height = 1;
2693 break;
2694 case CAM_FORMAT_META_RAW_8BIT:
2695 // Every 16 pixels occupy 16 bytes
2696 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2697 stride_in_bytes = stride * 2;
2698 buf_planes->plane_info.num_planes = 1;
2699 buf_planes->plane_info.mp[0].offset = 0;
2700 buf_planes->plane_info.mp[0].len =
2701 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
2702 padding->plane_padding);
2703 buf_planes->plane_info.frame_len =
2704 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2705 buf_planes->plane_info.mp[0].offset_x =0;
2706 buf_planes->plane_info.mp[0].offset_y = 0;
2707 buf_planes->plane_info.mp[0].stride = stride;
2708 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
2709 buf_planes->plane_info.mp[0].scanline = scanline;
2710 break;
2711
2712 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG:
2713 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG:
2714 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB:
2715 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR:
2716 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG:
2717 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG:
2718 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB:
2719 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR:
2720 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG:
2721 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG:
2722 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB:
2723 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR:
2724 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG:
2725 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG:
2726 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB:
2727 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR:
2728 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG:
2729 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG:
2730 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB:
2731 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR:
2732 /* 1 plane */
2733 /* Every 16 pixels occupy 16 bytes */
2734 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2735 stride_in_bytes = stride;
2736 buf_planes->plane_info.num_planes = 1;
2737 buf_planes->plane_info.mp[0].offset = 0;
2738 buf_planes->plane_info.mp[0].len =
2739 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
2740 padding->plane_padding);
2741 buf_planes->plane_info.frame_len =
2742 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2743 buf_planes->plane_info.mp[0].offset_x =0;
2744 buf_planes->plane_info.mp[0].offset_y = 0;
2745 buf_planes->plane_info.mp[0].stride = stride;
2746 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
2747 buf_planes->plane_info.mp[0].scanline = scanline;
2748 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
2749 buf_planes->plane_info.mp[0].height = 1;
2750 break;
2751 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
2752 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
2753 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
2754 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
2755 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG:
2756 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG:
2757 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB:
2758 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR:
2759 /* Every 12 pixels occupy 16 bytes */
2760 stride = (dim->width + 11)/12 * 12;
2761 stride_in_bytes = stride * 8 / 6;
2762 buf_planes->plane_info.num_planes = 1;
2763 buf_planes->plane_info.mp[0].offset = 0;
2764 buf_planes->plane_info.mp[0].len =
2765 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
2766 padding->plane_padding);
2767 buf_planes->plane_info.frame_len =
2768 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2769 buf_planes->plane_info.mp[0].offset_x =0;
2770 buf_planes->plane_info.mp[0].offset_y = 0;
2771 buf_planes->plane_info.mp[0].stride = stride;
2772 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
2773 buf_planes->plane_info.mp[0].scanline = scanline;
2774 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
2775 buf_planes->plane_info.mp[0].height = 1;
2776 break;
2777 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG:
2778 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG:
2779 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB:
2780 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR:
2781 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG:
2782 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG:
2783 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB:
2784 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR:
2785 /* Every 10 pixels occupy 16 bytes */
2786 stride = (dim->width + 9)/10 * 10;
2787 stride_in_bytes = stride * 8 / 5;
2788 buf_planes->plane_info.num_planes = 1;
2789 buf_planes->plane_info.mp[0].offset = 0;
2790 buf_planes->plane_info.mp[0].len =
2791 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
2792 padding->plane_padding);
2793 buf_planes->plane_info.frame_len =
2794 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2795 buf_planes->plane_info.mp[0].offset_x =0;
2796 buf_planes->plane_info.mp[0].offset_y = 0;
2797 buf_planes->plane_info.mp[0].stride = stride;
2798 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
2799 buf_planes->plane_info.mp[0].scanline = scanline;
2800 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
2801 buf_planes->plane_info.mp[0].height = 1;
2802 break;
2803 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG:
2804 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG:
2805 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB:
2806 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR:
2807 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG:
2808 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG:
2809 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB:
2810 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR:
2811 /* Every 64 pixels occupy 80 bytes */
2812 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_4);
2813 stride_in_bytes = PAD_TO_SIZE(stride * 5 / 4, CAM_PAD_TO_8);
2814 buf_planes->plane_info.num_planes = 1;
2815 buf_planes->plane_info.mp[0].offset = 0;
2816 buf_planes->plane_info.mp[0].len =
2817 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
2818 padding->plane_padding);
2819 buf_planes->plane_info.frame_len =
2820 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2821 buf_planes->plane_info.mp[0].offset_x =0;
2822 buf_planes->plane_info.mp[0].offset_y = 0;
2823 buf_planes->plane_info.mp[0].stride = stride;
2824 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
2825 buf_planes->plane_info.mp[0].scanline = scanline;
2826 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
2827 buf_planes->plane_info.mp[0].height = 1;
2828 break;
2829 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG:
2830 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG:
2831 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB:
2832 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR:
2833 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG:
2834 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG:
2835 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB:
2836 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR:
2837 /* Every 32 pixels occupy 48 bytes */
2838 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
2839 stride_in_bytes = stride * 3 / 2;
2840 buf_planes->plane_info.num_planes = 1;
2841 buf_planes->plane_info.mp[0].offset = 0;
2842 buf_planes->plane_info.mp[0].len =
2843 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
2844 padding->plane_padding);
2845 buf_planes->plane_info.frame_len =
2846 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2847 buf_planes->plane_info.mp[0].offset_x =0;
2848 buf_planes->plane_info.mp[0].offset_y = 0;
2849 buf_planes->plane_info.mp[0].stride = stride;
2850 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
2851 buf_planes->plane_info.mp[0].scanline = scanline;
2852 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
2853 buf_planes->plane_info.mp[0].height = 1;
2854 break;
2855 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG:
2856 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG:
2857 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB:
2858 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR:
2859 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG:
2860 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG:
2861 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB:
2862 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR:
2863 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG:
2864 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG:
2865 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB:
2866 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR:
2867 /* Every 8 pixels occupy 16 bytes */
2868 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8);
2869 stride_in_bytes = stride * 2;
2870 buf_planes->plane_info.num_planes = 1;
2871 buf_planes->plane_info.mp[0].offset = 0;
2872 buf_planes->plane_info.mp[0].len =
2873 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
2874 padding->plane_padding);
2875 buf_planes->plane_info.frame_len =
2876 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
2877 buf_planes->plane_info.mp[0].offset_x =0;
2878 buf_planes->plane_info.mp[0].offset_y = 0;
2879 buf_planes->plane_info.mp[0].stride = stride;
2880 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
2881 buf_planes->plane_info.mp[0].scanline = scanline;
2882 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
2883 buf_planes->plane_info.mp[0].height = 1;
2884 break;
2885 default:
2886 CDBG_ERROR("%s: Invalid cam_format %d for raw stream",
2887 __func__, fmt);
2888 rc = -1;
2889 break;
2890 }
2891
2892 return rc;
2893 }
2894
2895 /*===========================================================================
2896 * FUNCTION : mm_stream_calc_offset_video
2897 *
2898 * DESCRIPTION: calculate video frame offset based on format and
2899 * padding information
2900 *
2901 * PARAMETERS :
2902 * @dim : image dimension
2903 * @buf_planes : [out] buffer plane information
2904 *
2905 * RETURN : int32_t type of status
2906 * 0 -- success
2907 * -1 -- failure
2908 *==========================================================================*/
2909 #ifdef VENUS_PRESENT
mm_stream_calc_offset_video(cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)2910 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
2911 cam_stream_buf_plane_info_t *buf_planes)
2912 {
2913 int stride = 0, scanline = 0;
2914
2915 // using Venus
2916 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
2917 scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
2918
2919 buf_planes->plane_info.frame_len =
2920 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
2921 buf_planes->plane_info.num_planes = 2;
2922 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2923 buf_planes->plane_info.mp[0].offset = 0;
2924 buf_planes->plane_info.mp[0].offset_x =0;
2925 buf_planes->plane_info.mp[0].offset_y = 0;
2926 buf_planes->plane_info.mp[0].stride = stride;
2927 buf_planes->plane_info.mp[0].scanline = scanline;
2928 buf_planes->plane_info.mp[0].width = dim->width;
2929 buf_planes->plane_info.mp[0].height = dim->height;
2930 stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
2931 scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
2932 buf_planes->plane_info.mp[1].len =
2933 buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2934 buf_planes->plane_info.mp[1].offset = 0;
2935 buf_planes->plane_info.mp[1].offset_x =0;
2936 buf_planes->plane_info.mp[1].offset_y = 0;
2937 buf_planes->plane_info.mp[1].stride = stride;
2938 buf_planes->plane_info.mp[1].scanline = scanline;
2939 buf_planes->plane_info.mp[1].width = dim->width;
2940 buf_planes->plane_info.mp[1].height = dim->height / 2;
2941
2942 return 0;
2943 }
2944 #else
mm_stream_calc_offset_video(cam_dimension_t * dim,cam_stream_buf_plane_info_t * buf_planes)2945 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim,
2946 cam_stream_buf_plane_info_t *buf_planes)
2947 {
2948 int stride = 0, scanline = 0;
2949
2950 buf_planes->plane_info.num_planes = 2;
2951
2952 stride = dim->width;
2953 scanline = dim->height;
2954 buf_planes->plane_info.mp[0].len =
2955 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_2K);
2956 buf_planes->plane_info.mp[0].offset = 0;
2957 buf_planes->plane_info.mp[0].offset_x =0;
2958 buf_planes->plane_info.mp[0].offset_y = 0;
2959 buf_planes->plane_info.mp[0].stride = stride;
2960 buf_planes->plane_info.mp[0].scanline = scanline;
2961 buf_planes->plane_info.mp[0].width = dim->width;
2962 buf_planes->plane_info.mp[0].height = dim->height;
2963
2964 stride = dim->width;
2965 scanline = dim->height / 2;
2966 buf_planes->plane_info.mp[1].len =
2967 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_2K);
2968 buf_planes->plane_info.mp[1].offset = 0;
2969 buf_planes->plane_info.mp[1].offset_x =0;
2970 buf_planes->plane_info.mp[1].offset_y = 0;
2971 buf_planes->plane_info.mp[1].stride = stride;
2972 buf_planes->plane_info.mp[1].scanline = scanline;
2973 buf_planes->plane_info.mp[1].width = dim->width;
2974 buf_planes->plane_info.mp[1].height = dim->height / 2;
2975
2976 buf_planes->plane_info.frame_len =
2977 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2978 buf_planes->plane_info.mp[1].len,
2979 CAM_PAD_TO_4K);
2980
2981 return 0;
2982 }
2983 #endif
2984
2985 /*===========================================================================
2986 * FUNCTION : mm_stream_calc_offset_metadata
2987 *
2988 * DESCRIPTION: calculate metadata frame offset based on format and
2989 * padding information
2990 *
2991 * PARAMETERS :
2992 * @dim : image dimension
2993 * @padding : padding information
2994 * @buf_planes : [out] buffer plane information
2995 *
2996 * RETURN : int32_t type of status
2997 * 0 -- success
2998 * -1 -- failure
2999 *==========================================================================*/
mm_stream_calc_offset_metadata(cam_dimension_t * dim,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)3000 int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim,
3001 cam_padding_info_t *padding,
3002 cam_stream_buf_plane_info_t *buf_planes)
3003 {
3004 int32_t rc = 0;
3005 buf_planes->plane_info.num_planes = 1;
3006 buf_planes->plane_info.mp[0].offset = 0;
3007 buf_planes->plane_info.mp[0].len =
3008 PAD_TO_SIZE((uint32_t)(dim->width * dim->height),
3009 padding->plane_padding);
3010 buf_planes->plane_info.frame_len =
3011 buf_planes->plane_info.mp[0].len;
3012
3013 buf_planes->plane_info.mp[0].offset_x =0;
3014 buf_planes->plane_info.mp[0].offset_y = 0;
3015 buf_planes->plane_info.mp[0].stride = dim->width;
3016 buf_planes->plane_info.mp[0].scanline = dim->height;
3017 buf_planes->plane_info.mp[0].width = dim->width;
3018 buf_planes->plane_info.mp[0].height = dim->height;
3019 return rc;
3020 }
3021
3022 /*===========================================================================
3023 * FUNCTION : mm_stream_calc_offset_analysis
3024 *
3025 * DESCRIPTION: calculate analysis frame offset based on format and
3026 * padding information
3027 *
3028 * PARAMETERS :
3029 * @fmt : image format
3030 * @dim : image dimension
3031 * @padding : padding information
3032 * @buf_planes : [out] buffer plane information
3033 *
3034 * RETURN : int32_t type of status
3035 * 0 -- success
3036 * -1 -- failure
3037 *==========================================================================*/
mm_stream_calc_offset_analysis(cam_format_t fmt,cam_dimension_t * dim,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * buf_planes)3038 int32_t mm_stream_calc_offset_analysis(cam_format_t fmt,
3039 cam_dimension_t *dim,
3040 cam_padding_info_t *padding,
3041 cam_stream_buf_plane_info_t *buf_planes)
3042 {
3043 int32_t rc = 0;
3044 int32_t offset_x = 0, offset_y = 0;
3045 int32_t stride, scanline;
3046
3047 /* Clip to minimum supported bytes per line */
3048 if ((uint32_t)dim->width < padding->min_stride) {
3049 stride = (int32_t)padding->min_stride;
3050 } else {
3051 stride = dim->width;
3052 }
3053
3054 if ((uint32_t)dim->height < padding->min_scanline) {
3055 scanline = (int32_t)padding->min_scanline;
3056 } else {
3057 scanline = dim->height;
3058 }
3059
3060 stride = PAD_TO_SIZE(stride, padding->width_padding);
3061 scanline = PAD_TO_SIZE(scanline, padding->height_padding);
3062
3063 switch (fmt) {
3064 case CAM_FORMAT_YUV_420_NV12:
3065 case CAM_FORMAT_YUV_420_NV21:
3066 /* 2 planes: Y + CbCr */
3067 buf_planes->plane_info.num_planes = 2;
3068
3069 buf_planes->plane_info.mp[0].len =
3070 PAD_TO_SIZE((uint32_t)(stride * scanline),
3071 padding->plane_padding);
3072 buf_planes->plane_info.mp[0].offset =
3073 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3074 padding->plane_padding);
3075 buf_planes->plane_info.mp[0].offset_x = offset_x;
3076 buf_planes->plane_info.mp[0].offset_y = offset_y;
3077 buf_planes->plane_info.mp[0].stride = stride;
3078 buf_planes->plane_info.mp[0].scanline = scanline;
3079 buf_planes->plane_info.mp[0].width = dim->width;
3080 buf_planes->plane_info.mp[0].height = dim->height;
3081
3082 scanline = scanline / 2;
3083 buf_planes->plane_info.mp[1].len =
3084 PAD_TO_SIZE((uint32_t)(stride * scanline),
3085 padding->plane_padding);
3086 buf_planes->plane_info.mp[1].offset =
3087 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3088 padding->plane_padding);
3089 buf_planes->plane_info.mp[1].offset_x = offset_x;
3090 buf_planes->plane_info.mp[1].offset_y = offset_y;
3091 buf_planes->plane_info.mp[1].stride = stride;
3092 buf_planes->plane_info.mp[1].scanline = scanline;
3093 buf_planes->plane_info.mp[1].width = dim->width;
3094 buf_planes->plane_info.mp[1].height = dim->height / 2;
3095
3096 buf_planes->plane_info.frame_len =
3097 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3098 buf_planes->plane_info.mp[1].len,
3099 CAM_PAD_TO_4K);
3100 break;
3101 case CAM_FORMAT_YUV_420_YV12:
3102 /* 3 planes: Y + Cr + Cb */
3103 buf_planes->plane_info.num_planes = 3;
3104
3105 buf_planes->plane_info.mp[0].offset =
3106 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3107 padding->plane_padding);
3108 buf_planes->plane_info.mp[0].len =
3109 PAD_TO_SIZE((uint32_t)(stride * scanline),
3110 padding->plane_padding);
3111 buf_planes->plane_info.mp[0].offset_x = offset_x;
3112 buf_planes->plane_info.mp[0].offset_y = offset_y;
3113 buf_planes->plane_info.mp[0].stride = stride;
3114 buf_planes->plane_info.mp[0].scanline = scanline;
3115 buf_planes->plane_info.mp[0].width = dim->width;
3116 buf_planes->plane_info.mp[0].height = dim->height;
3117
3118 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
3119 scanline = scanline / 2;
3120 buf_planes->plane_info.mp[1].offset =
3121 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3122 padding->plane_padding);
3123 buf_planes->plane_info.mp[1].len =
3124 PAD_TO_SIZE((uint32_t)(stride * scanline),
3125 padding->plane_padding);
3126 buf_planes->plane_info.mp[1].offset_x = offset_x;
3127 buf_planes->plane_info.mp[1].offset_y = offset_y;
3128 buf_planes->plane_info.mp[1].stride = stride;
3129 buf_planes->plane_info.mp[1].scanline = scanline;
3130 buf_planes->plane_info.mp[1].width = dim->width / 2;
3131 buf_planes->plane_info.mp[1].height = dim->height / 2;
3132
3133 buf_planes->plane_info.mp[2].offset =
3134 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3135 padding->plane_padding);
3136 buf_planes->plane_info.mp[2].len =
3137 PAD_TO_SIZE((uint32_t)(stride * scanline),
3138 padding->plane_padding);
3139 buf_planes->plane_info.mp[2].offset_x = offset_x;
3140 buf_planes->plane_info.mp[2].offset_y = offset_y;
3141 buf_planes->plane_info.mp[2].stride = stride;
3142 buf_planes->plane_info.mp[2].scanline = scanline;
3143 buf_planes->plane_info.mp[2].width = dim->width / 2;
3144 buf_planes->plane_info.mp[2].height = dim->height / 2;
3145
3146 buf_planes->plane_info.frame_len =
3147 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3148 buf_planes->plane_info.mp[1].len +
3149 buf_planes->plane_info.mp[2].len,
3150 CAM_PAD_TO_4K);
3151 break;
3152 case CAM_FORMAT_YUV_422_NV16:
3153 case CAM_FORMAT_YUV_422_NV61:
3154 /* 2 planes: Y + CbCr */
3155 buf_planes->plane_info.num_planes = 2;
3156 buf_planes->plane_info.mp[0].len =
3157 PAD_TO_SIZE((uint32_t)(stride * scanline),
3158 padding->plane_padding);
3159 buf_planes->plane_info.mp[0].offset =
3160 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3161 padding->plane_padding);
3162 buf_planes->plane_info.mp[0].offset_x = offset_x;
3163 buf_planes->plane_info.mp[0].offset_y = offset_y;
3164 buf_planes->plane_info.mp[0].stride = stride;
3165 buf_planes->plane_info.mp[0].scanline = scanline;
3166 buf_planes->plane_info.mp[0].width = dim->width;
3167 buf_planes->plane_info.mp[0].height = dim->height;
3168
3169 buf_planes->plane_info.mp[1].len =
3170 PAD_TO_SIZE((uint32_t)(stride * scanline),
3171 padding->plane_padding);
3172 buf_planes->plane_info.mp[1].offset =
3173 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3174 padding->plane_padding);
3175 buf_planes->plane_info.mp[1].offset_x = offset_x;
3176 buf_planes->plane_info.mp[1].offset_y = offset_y;
3177 buf_planes->plane_info.mp[1].stride = stride;
3178 buf_planes->plane_info.mp[1].scanline = scanline;
3179 buf_planes->plane_info.mp[1].width = dim->width;
3180 buf_planes->plane_info.mp[1].height = dim->height;
3181
3182 buf_planes->plane_info.frame_len = PAD_TO_SIZE(
3183 buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len,
3184 CAM_PAD_TO_4K);
3185 break;
3186 case CAM_FORMAT_Y_ONLY:
3187 buf_planes->plane_info.num_planes = 1;
3188
3189 buf_planes->plane_info.mp[0].len =
3190 PAD_TO_SIZE((uint32_t)(stride * scanline),
3191 padding->plane_padding);
3192 buf_planes->plane_info.mp[0].offset =
3193 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3194 padding->plane_padding);
3195 buf_planes->plane_info.mp[0].offset_x = offset_x;
3196 buf_planes->plane_info.mp[0].offset_y = offset_y;
3197 buf_planes->plane_info.mp[0].stride = stride;
3198 buf_planes->plane_info.mp[0].scanline = scanline;
3199 buf_planes->plane_info.mp[0].width = dim->width;
3200 buf_planes->plane_info.mp[0].height = dim->height;
3201 buf_planes->plane_info.frame_len =
3202 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3203 break;
3204 default:
3205 CDBG_ERROR("%s: Invalid cam_format for snapshot %d",
3206 __func__, fmt);
3207 rc = -1;
3208 break;
3209 }
3210
3211 return rc;
3212 }
3213
3214 /*===========================================================================
3215 * FUNCTION : mm_stream_calc_offset_postproc
3216 *
3217 * DESCRIPTION: calculate postprocess frame offset
3218 *
3219 * PARAMETERS :
3220 * @stream_info: ptr to stream info
3221 * @padding : padding information
3222 * @plns : [out] buffer plane information
3223 *
3224 * RETURN : int32_t type of status
3225 * 0 -- success
3226 * -1 -- failure
3227 *==========================================================================*/
mm_stream_calc_offset_postproc(cam_stream_info_t * stream_info,cam_padding_info_t * padding,cam_stream_buf_plane_info_t * plns)3228 int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info,
3229 cam_padding_info_t *padding,
3230 cam_stream_buf_plane_info_t *plns)
3231 {
3232 int32_t rc = 0;
3233 cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT;
3234 if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) {
3235 type = stream_info->reprocess_config.offline.input_type;
3236 if (CAM_STREAM_TYPE_DEFAULT == type) {
3237 if (plns->plane_info.frame_len == 0) {
3238 // take offset from input source
3239 *plns = stream_info->reprocess_config.offline.input_buf_planes;
3240 return rc;
3241 }
3242 } else {
3243 type = stream_info->reprocess_config.offline.input_type;
3244 }
3245 } else {
3246 type = stream_info->reprocess_config.online.input_stream_type;
3247 }
3248
3249 switch (type) {
3250 case CAM_STREAM_TYPE_PREVIEW:
3251 rc = mm_stream_calc_offset_preview(stream_info->fmt,
3252 &stream_info->dim,
3253 plns);
3254 break;
3255 case CAM_STREAM_TYPE_POSTVIEW:
3256 rc = mm_stream_calc_offset_post_view(stream_info->fmt,
3257 &stream_info->dim,
3258 plns);
3259 break;
3260 case CAM_STREAM_TYPE_SNAPSHOT:
3261 case CAM_STREAM_TYPE_CALLBACK:
3262 rc = mm_stream_calc_offset_snapshot(stream_info->fmt,
3263 &stream_info->dim,
3264 padding,
3265 plns);
3266 break;
3267 case CAM_STREAM_TYPE_VIDEO:
3268 rc = mm_stream_calc_offset_video(&stream_info->dim,
3269 plns);
3270 break;
3271 case CAM_STREAM_TYPE_RAW:
3272 rc = mm_stream_calc_offset_raw(stream_info->fmt,
3273 &stream_info->dim,
3274 padding,
3275 plns);
3276 break;
3277 case CAM_STREAM_TYPE_ANALYSIS:
3278 rc = mm_stream_calc_offset_analysis(stream_info->fmt,
3279 &stream_info->dim,
3280 padding,
3281 plns);
3282 break;
3283 case CAM_STREAM_TYPE_METADATA:
3284 rc = mm_stream_calc_offset_metadata(&stream_info->dim,
3285 padding,
3286 plns);
3287 break;
3288 case CAM_STREAM_TYPE_OFFLINE_PROC:
3289 rc = mm_stream_calc_offset_snapshot(stream_info->fmt,
3290 &stream_info->dim, padding, plns);
3291 break;
3292 default:
3293 CDBG_ERROR("%s: not supported for stream type %d",
3294 __func__, type);
3295 rc = -1;
3296 break;
3297 }
3298 return rc;
3299 }
3300
3301 /*===========================================================================
3302 * FUNCTION : mm_stream_calc_offset
3303 *
3304 * DESCRIPTION: calculate frame offset based on format and padding information
3305 *
3306 * PARAMETERS :
3307 * @my_obj : stream object
3308 *
3309 * RETURN : int32_t type of status
3310 * 0 -- success
3311 * -1 -- failure
3312 *==========================================================================*/
mm_stream_calc_offset(mm_stream_t * my_obj)3313 int32_t mm_stream_calc_offset(mm_stream_t *my_obj)
3314 {
3315 int32_t rc = 0;
3316
3317 cam_dimension_t dim = my_obj->stream_info->dim;
3318 if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION &&
3319 my_obj->stream_info->stream_type != CAM_STREAM_TYPE_VIDEO) {
3320 if (my_obj->stream_info->pp_config.rotation == ROTATE_90 ||
3321 my_obj->stream_info->pp_config.rotation == ROTATE_270) {
3322 // rotated by 90 or 270, need to switch width and height
3323 dim.width = my_obj->stream_info->dim.height;
3324 dim.height = my_obj->stream_info->dim.width;
3325 }
3326 }
3327
3328 switch (my_obj->stream_info->stream_type) {
3329 case CAM_STREAM_TYPE_PREVIEW:
3330 rc = mm_stream_calc_offset_preview(my_obj->stream_info->fmt,
3331 &dim,
3332 &my_obj->stream_info->buf_planes);
3333 break;
3334 case CAM_STREAM_TYPE_POSTVIEW:
3335 rc = mm_stream_calc_offset_post_view(my_obj->stream_info->fmt,
3336 &dim,
3337 &my_obj->stream_info->buf_planes);
3338 break;
3339 case CAM_STREAM_TYPE_SNAPSHOT:
3340 case CAM_STREAM_TYPE_CALLBACK:
3341 rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt,
3342 &dim,
3343 &my_obj->padding_info,
3344 &my_obj->stream_info->buf_planes);
3345 break;
3346 case CAM_STREAM_TYPE_OFFLINE_PROC:
3347 rc = mm_stream_calc_offset_postproc(my_obj->stream_info,
3348 &my_obj->padding_info,
3349 &my_obj->stream_info->buf_planes);
3350 break;
3351 case CAM_STREAM_TYPE_VIDEO:
3352 rc = mm_stream_calc_offset_video(&dim,
3353 &my_obj->stream_info->buf_planes);
3354 break;
3355 case CAM_STREAM_TYPE_RAW:
3356 rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt,
3357 &dim,
3358 &my_obj->padding_info,
3359 &my_obj->stream_info->buf_planes);
3360 break;
3361 case CAM_STREAM_TYPE_ANALYSIS:
3362 rc = mm_stream_calc_offset_analysis(my_obj->stream_info->fmt,
3363 &dim,
3364 &my_obj->padding_info,
3365 &my_obj->stream_info->buf_planes);
3366 break;
3367 case CAM_STREAM_TYPE_METADATA:
3368 rc = mm_stream_calc_offset_metadata(&dim,
3369 &my_obj->padding_info,
3370 &my_obj->stream_info->buf_planes);
3371 break;
3372 default:
3373 CDBG_ERROR("%s: not supported for stream type %d",
3374 __func__, my_obj->stream_info->stream_type);
3375 rc = -1;
3376 break;
3377 }
3378
3379 my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info;
3380 return rc;
3381 }
3382
3383 /*===========================================================================
3384 * FUNCTION : mm_stream_sync_info
3385 *
3386 * DESCRIPTION: synchronize stream information with server
3387 *
3388 * PARAMETERS :
3389 * @my_obj : stream object
3390 *
3391 * RETURN : int32_t type of status
3392 * 0 -- success
3393 * -1 -- failure
3394 * NOTE : assume stream info buffer is mapped to server and filled in with
3395 * stream information by upper layer. This call will let server to
3396 * synchornize the stream information with HAL. If server find any
3397 * fields that need to be changed accroding to hardware configuration,
3398 * server will modify corresponding fields so that HAL could know
3399 * about it.
3400 *==========================================================================*/
mm_stream_sync_info(mm_stream_t * my_obj)3401 int32_t mm_stream_sync_info(mm_stream_t *my_obj)
3402 {
3403 int32_t rc = 0;
3404 int32_t value = 0;
3405 my_obj->stream_info->stream_svr_id = my_obj->server_stream_id;
3406 rc = mm_stream_calc_offset(my_obj);
3407
3408 if (rc == 0) {
3409 rc = mm_camera_util_s_ctrl(my_obj->fd,
3410 CAM_PRIV_STREAM_INFO_SYNC,
3411 &value);
3412 }
3413 return rc;
3414 }
3415
3416 /*===========================================================================
3417 * FUNCTION : mm_stream_set_fmt
3418 *
3419 * DESCRIPTION: set stream format to kernel via v4l2 ioctl
3420 *
3421 * PARAMETERS :
3422 * @my_obj : stream object
3423 *
3424 * RETURN : int32_t type of status
3425 * 0 -- success
3426 * -1 -- failure
3427 *==========================================================================*/
mm_stream_set_fmt(mm_stream_t * my_obj)3428 int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
3429 {
3430 int32_t rc = 0;
3431 struct v4l2_format fmt;
3432 struct msm_v4l2_format_data msm_fmt;
3433 int i;
3434
3435 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
3436 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
3437
3438 if (my_obj->stream_info->dim.width == 0 ||
3439 my_obj->stream_info->dim.height == 0) {
3440 CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n",
3441 __func__,
3442 my_obj->stream_info->dim.width,
3443 my_obj->stream_info->dim.height,
3444 my_obj->stream_info->fmt);
3445 return -1;
3446 }
3447
3448 memset(&fmt, 0, sizeof(fmt));
3449 memset(&msm_fmt, 0, sizeof(msm_fmt));
3450 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3451 msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3452
3453
3454 msm_fmt.width = (unsigned int)my_obj->stream_info->dim.width;
3455 msm_fmt.height = (unsigned int)my_obj->stream_info->dim.height;
3456 msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt);
3457
3458 if (my_obj->stream_info->streaming_mode != CAM_STREAMING_MODE_BATCH) {
3459 msm_fmt.num_planes = (unsigned char)my_obj->frame_offset.num_planes;
3460 for (i = 0; i < msm_fmt.num_planes; i++) {
3461 msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len;
3462 }
3463 } else {
3464 msm_fmt.num_planes = 1;
3465 msm_fmt.plane_sizes[0] = my_obj->stream_info->user_buf_info.size;
3466 }
3467
3468 memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt));
3469 rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
3470 return rc;
3471 }
3472
3473 /*===========================================================================
3474 * FUNCTION : mm_stream_buf_done
3475 *
3476 * DESCRIPTION: enqueue buffer back to kernel
3477 *
3478 * PARAMETERS :
3479 * @my_obj : stream object
3480 * @frame : frame to be enqueued back to kernel
3481 *
3482 * RETURN : int32_t type of status
3483 * 0 -- success
3484 * -1 -- failure
3485 *==========================================================================*/
mm_stream_buf_done(mm_stream_t * my_obj,mm_camera_buf_def_t * frame)3486 int32_t mm_stream_buf_done(mm_stream_t * my_obj,
3487 mm_camera_buf_def_t *frame)
3488 {
3489 int32_t rc = 0;
3490 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
3491 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
3492
3493 pthread_mutex_lock(&my_obj->buf_lock);
3494 if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) {
3495 rc = mm_stream_write_user_buf(my_obj, frame);
3496 } else if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
3497 CDBG("%s: Error Trying to free second time?(idx=%d) count=%d\n",
3498 __func__, frame->buf_idx,
3499 my_obj->buf_status[frame->buf_idx].buf_refcnt);
3500 rc = -1;
3501 } else {
3502 my_obj->buf_status[frame->buf_idx].buf_refcnt--;
3503 if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
3504 CDBG("<DEBUG> : Buf done for buffer:%d, stream:%d", frame->buf_idx, frame->stream_type);
3505 rc = mm_stream_qbuf(my_obj, frame);
3506 if(rc < 0) {
3507 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
3508 __func__, frame->buf_idx, rc);
3509 } else {
3510 my_obj->buf_status[frame->buf_idx].in_kernel = 1;
3511 }
3512 }else{
3513 CDBG("<DEBUG> : Still ref count pending count :%d",
3514 my_obj->buf_status[frame->buf_idx].buf_refcnt);
3515 CDBG("<DEBUG> : for buffer:%p:%d",
3516 my_obj, frame->buf_idx);
3517 }
3518 }
3519 pthread_mutex_unlock(&my_obj->buf_lock);
3520 return rc;
3521 }
3522
3523
3524 /*===========================================================================
3525 * FUNCTION : mm_stream_get_queued_buf_count
3526 *
3527 * DESCRIPTION: return queued buffer count
3528 *
3529 * PARAMETERS :
3530 * @my_obj : stream object
3531 *
3532 * RETURN : queued buffer count
3533 *==========================================================================*/
mm_stream_get_queued_buf_count(mm_stream_t * my_obj)3534 int32_t mm_stream_get_queued_buf_count(mm_stream_t *my_obj)
3535 {
3536 int32_t rc = 0;
3537 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
3538 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
3539 pthread_mutex_lock(&my_obj->buf_lock);
3540 rc = my_obj->queued_buffer_count;
3541 pthread_mutex_unlock(&my_obj->buf_lock);
3542 return rc;
3543 }
3544
3545 /*===========================================================================
3546 * FUNCTION : mm_stream_reg_buf_cb
3547 *
3548 * DESCRIPTION: Allow other stream to register dataCB at this stream.
3549 *
3550 * PARAMETERS :
3551 * @my_obj : stream object
3552 * @val : ptr to info about the callback to be registered
3553 *
3554 * RETURN : int32_t type of status
3555 * 0 -- success
3556 * -1 -- failure
3557 *==========================================================================*/
mm_stream_reg_buf_cb(mm_stream_t * my_obj,mm_stream_data_cb_t * val)3558 int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
3559 mm_stream_data_cb_t *val)
3560 {
3561 int32_t rc = -1;
3562 uint8_t i;
3563 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d",
3564 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state);
3565
3566 pthread_mutex_lock(&my_obj->cb_lock);
3567 for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
3568 if(NULL == my_obj->buf_cb[i].cb) {
3569 my_obj->buf_cb[i] = *val;
3570 rc = 0;
3571 break;
3572 }
3573 }
3574 pthread_mutex_unlock(&my_obj->cb_lock);
3575
3576 return rc;
3577 }
3578