• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                                    &reg_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