1/* Copyright (c) 2012-2016, 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// System dependencies
31#include <stdlib.h>
32#include <pthread.h>
33#include <errno.h>
34#include <fcntl.h>
35#include <media/msm_media_info.h>
36#define TIME_H <SYSTEM_HEADER_PREFIX/time.h>
37#include TIME_H
38#define IOCTL_H <SYSTEM_HEADER_PREFIX/ioctl.h>
39#include IOCTL_H
40#include <cutils/properties.h>
41
42#define ATRACE_TAG ATRACE_TAG_CAMERA
43#include <cutils/trace.h>
44
45// Camera dependencies
46#include "cam_semaphore.h"
47#include "mm_camera_dbg.h"
48#include "mm_camera_interface.h"
49#include "mm_camera.h"
50#include "mm_camera_muxer.h"
51
52/* internal function decalre */
53int32_t mm_stream_qbuf(mm_stream_t *my_obj,
54                       mm_camera_buf_def_t *buf);
55int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
56int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
57int32_t mm_stream_cancel_buf(mm_stream_t * my_obj,
58                           uint32_t buf_idx);
59int32_t mm_stream_sync_info(mm_stream_t *my_obj);
60int32_t mm_stream_init_bufs(mm_stream_t * my_obj);
61int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj);
62int32_t mm_stream_request_buf(mm_stream_t * my_obj);
63int32_t mm_stream_unreg_buf(mm_stream_t * my_obj);
64int32_t mm_stream_release(mm_stream_t *my_obj);
65int32_t mm_stream_set_parm(mm_stream_t *my_obj,
66                           cam_stream_parm_buffer_t *value);
67int32_t mm_stream_get_parm(mm_stream_t *my_obj,
68                           cam_stream_parm_buffer_t *value);
69int32_t mm_stream_do_action(mm_stream_t *my_obj,
70                            void *in_value);
71int32_t mm_stream_streamon(mm_stream_t *my_obj);
72int32_t mm_stream_start_sensor_streaming(mm_stream_t *my_obj);
73int32_t mm_stream_streamoff(mm_stream_t *my_obj, bool stop_immediately);
74int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
75                                 mm_camera_buf_info_t* buf_info,
76                                 uint8_t num_planes);
77int32_t mm_stream_read_user_buf(mm_stream_t * my_obj,
78        mm_camera_buf_info_t* buf_info);
79int32_t mm_stream_write_user_buf(mm_stream_t * my_obj,
80        mm_camera_buf_def_t *buf);
81
82int32_t mm_stream_init(mm_stream_t *my_obj);
83int32_t mm_stream_deinit(mm_stream_t *my_obj);
84int32_t mm_stream_config(mm_stream_t *my_obj,
85                         mm_camera_stream_config_t *config);
86int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
87int32_t mm_stream_buf_done(mm_stream_t * my_obj,
88                           mm_camera_buf_def_t *frame);
89int32_t mm_stream_get_queued_buf_count(mm_stream_t * my_obj);
90
91int32_t mm_stream_calc_offset(mm_stream_t *my_obj);
92int32_t mm_stream_calc_offset_preview(cam_stream_info_t *stream_info,
93                                      cam_dimension_t *dim,
94                                      cam_padding_info_t *padding,
95                                      cam_stream_buf_plane_info_t *buf_planes);
96int32_t mm_stream_calc_offset_post_view(cam_stream_info_t *stream_info,
97                                      cam_dimension_t *dim,
98                                      cam_padding_info_t *padding,
99                                      cam_stream_buf_plane_info_t *buf_planes);
100
101int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
102                                       cam_dimension_t *dim,
103                                       cam_padding_info_t *padding,
104                                       cam_stream_buf_plane_info_t *buf_planes);
105int32_t mm_stream_calc_offset_raw(cam_format_t fmt,
106                                  cam_dimension_t *dim,
107                                  cam_padding_info_t *padding,
108                                  cam_stream_buf_plane_info_t *buf_planes);
109int32_t mm_stream_calc_offset_video(cam_format_t fmt,
110        cam_dimension_t *dim,
111        cam_stream_buf_plane_info_t *buf_planes);
112int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim,
113                                       cam_padding_info_t *padding,
114                                       cam_stream_buf_plane_info_t *buf_planes);
115int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info,
116                                       cam_padding_info_t *padding,
117                                       cam_stream_buf_plane_info_t *plns);
118uint32_t mm_stream_calc_lcm(int32_t num1, int32_t num2);
119
120
121/* state machine function declare */
122int32_t mm_stream_fsm_inited(mm_stream_t * my_obj,
123                             mm_stream_evt_type_t evt,
124                             void * in_val,
125                             void * out_val);
126int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj,
127                               mm_stream_evt_type_t evt,
128                               void * in_val,
129                               void * out_val);
130int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
131                          mm_stream_evt_type_t evt,
132                          void * in_val,
133                          void * out_val);
134int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
135                             mm_stream_evt_type_t evt,
136                             void * in_val,
137                             void * out_val);
138int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
139                          mm_stream_evt_type_t evt,
140                          void * in_val,
141                          void * out_val);
142int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
143                             mm_stream_evt_type_t evt,
144                             void * in_val,
145                             void * out_val);
146uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt);
147int32_t mm_stream_reg_frame_sync(mm_stream_t *my_obj,
148        mm_evt_paylod_reg_frame_sync *sync);
149int32_t mm_stream_handle_cache_ops(mm_stream_t* my_obj,
150        mm_camera_buf_def_t* buf, bool deque);
151int32_t mm_stream_trigger_frame_sync(mm_stream_t *my_obj,
152        mm_camera_cb_req_type type);
153
154/*===========================================================================
155 * FUNCTION   : mm_stream_notify_channel
156 *
157 * DESCRIPTION: function to notify channel object on received buffer
158 *
159 * PARAMETERS :
160 *   @ch_obj  : channel object
161 *   @buf_info: ptr to struct storing buffer information
162 *
163 * RETURN     : int32_t type of status
164 *              0  -- success
165 *              0> -- failure
166 *==========================================================================*/
167int32_t mm_stream_notify_channel(struct mm_channel* ch_obj,
168        mm_camera_buf_info_t *buf_info)
169{
170    int32_t rc = 0;
171    mm_camera_cmdcb_t* node = NULL;
172
173    if ((NULL == ch_obj) || (NULL == buf_info)) {
174        LOGD("Invalid channel/buffer");
175        return -ENODEV;
176    }
177
178    /* send cam_sem_post to wake up channel cmd thread to enqueue
179     * to super buffer */
180    node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
181    if (NULL != node) {
182        memset(node, 0, sizeof(mm_camera_cmdcb_t));
183        node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
184        node->u.buf = *buf_info;
185
186        /* enqueue to cmd thread */
187        cam_queue_enq(&(ch_obj->cmd_thread.cmd_queue), node);
188
189        /* wake up cmd thread */
190        cam_sem_post(&(ch_obj->cmd_thread.cmd_sem));
191    } else {
192        LOGE("No memory for mm_camera_node_t");
193        rc = -ENOMEM;
194    }
195
196    return rc;
197}
198
199/*===========================================================================
200 * FUNCTION   : mm_stream_handle_rcvd_buf
201 *
202 * DESCRIPTION: function to handle newly received stream buffer
203 *
204 * PARAMETERS :
205 *   @cam_obj : stream object
206 *   @buf_info: ptr to struct storing buffer information
207 *
208 * RETURN     : none
209 *==========================================================================*/
210void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj,
211                               mm_camera_buf_info_t *buf_info,
212                               uint8_t has_cb)
213{
214    int32_t rc = 0;
215    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
216          my_obj->my_hdl, my_obj->fd, my_obj->state);
217
218    /* enqueue to super buf thread */
219    if (my_obj->is_bundled) {
220        rc = mm_stream_notify_channel(my_obj->ch_obj, buf_info);
221        if (rc < 0) {
222            LOGE("Unable to notify channel");
223        }
224    }
225
226    pthread_mutex_lock(&my_obj->buf_lock);
227    if(my_obj->is_linked) {
228        /* need to add into super buf for linking, add ref count */
229        my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++;
230
231        rc = mm_stream_notify_channel(my_obj->linked_obj, buf_info);
232        if (rc < 0) {
233            LOGE("Unable to notify channel");
234        }
235    }
236    pthread_mutex_unlock(&my_obj->buf_lock);
237
238    pthread_mutex_lock(&my_obj->cmd_lock);
239    if(has_cb && my_obj->cmd_thread.is_active) {
240        mm_camera_cmdcb_t* node = NULL;
241
242        /* send cam_sem_post to wake up cmd thread to dispatch dataCB */
243        node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
244        if (NULL != node) {
245            memset(node, 0, sizeof(mm_camera_cmdcb_t));
246            node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
247            node->u.buf = *buf_info;
248
249            /* enqueue to cmd thread */
250            cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
251
252            /* wake up cmd thread */
253            cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
254        } else {
255            LOGE("No memory for mm_camera_node_t");
256        }
257    }
258    pthread_mutex_unlock(&my_obj->cmd_lock);
259}
260
261/*===========================================================================
262 * FUNCTION   : mm_stream_dispatch_sync_data
263 *
264 * DESCRIPTION: dispatch stream buffer to registered users on poll thread
265 *
266 * PARAMETERS :
267 *   @cmd_cb  : ptr storing stream buffer information
268 *   @userdata: user data ptr (stream object)
269 *
270 * RETURN     : none
271 *==========================================================================*/
272static void mm_stream_dispatch_sync_data(mm_stream_t * my_obj,
273         mm_stream_data_cb_t *buf_cb, mm_camera_buf_info_t *buf_info)
274{
275    mm_camera_super_buf_t super_buf;
276    mm_stream_t *m_obj = my_obj;
277
278    if (NULL == my_obj || buf_info == NULL ||
279            buf_cb == NULL) {
280        return;
281    }
282
283    if (m_obj->master_str_obj != NULL) {
284        m_obj = m_obj->master_str_obj;
285    }
286
287    memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
288    super_buf.num_bufs = 1;
289    super_buf.bufs[0] = buf_info->buf;
290    super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl;
291    super_buf.ch_id = my_obj->ch_obj->my_hdl;
292    if ((buf_cb != NULL) && (buf_cb->cb_type == MM_CAMERA_STREAM_CB_TYPE_SYNC)
293            && (buf_cb->cb_count != 0)
294            && my_obj->is_cb_active) {
295        /* callback */
296        buf_cb->cb(&super_buf, buf_cb->user_data);
297
298        /* if >0, reduce count by 1 every time we called CB until reaches 0
299             * when count reach 0, reset the buf_cb to have no CB */
300        if (buf_cb->cb_count > 0) {
301            buf_cb->cb_count--;
302            if (0 == buf_cb->cb_count) {
303                buf_cb->cb = NULL;
304                buf_cb->user_data = NULL;
305            }
306        }
307    }
308}
309
310/*===========================================================================
311 * FUNCTION   : mm_stream_data_notify
312 *
313 * DESCRIPTION: callback to handle data notify from kernel
314 *
315 * PARAMETERS :
316 *   @user_data : user data ptr (stream object)
317 *
318 * RETURN     : none
319 *==========================================================================*/
320static void mm_stream_data_notify(void* user_data)
321{
322    mm_stream_t *my_obj = (mm_stream_t*)user_data;
323    int32_t i, rc;
324    uint8_t has_cb = 0, length = 0;
325    mm_camera_buf_info_t buf_info;
326
327    if (NULL == my_obj) {
328        return;
329    }
330
331    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
332          my_obj->my_hdl, my_obj->fd, my_obj->state);
333    if (MM_STREAM_STATE_ACTIVE != my_obj->state) {
334        /* this Cb will only received in active_stream_on state
335         * if not so, return here */
336        LOGE("ERROR!! Wrong state (%d) to receive data notify!",
337                    my_obj->state);
338        return;
339    }
340
341    if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) {
342        length = 1;
343    } else {
344        length = my_obj->frame_offset.num_planes;
345    }
346
347    memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
348    rc = mm_stream_read_msm_frame(my_obj, &buf_info,
349        (uint8_t)length);
350    if (rc != 0) {
351        return;
352    }
353    uint32_t idx = buf_info.buf->buf_idx;
354
355    pthread_mutex_lock(&my_obj->cb_lock);
356    for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
357        if(NULL != my_obj->buf_cb[i].cb) {
358            if (my_obj->buf_cb[i].cb_type == MM_CAMERA_STREAM_CB_TYPE_SYNC) {
359                /*For every SYNC callback, send data*/
360                mm_stream_dispatch_sync_data(my_obj,
361                        &my_obj->buf_cb[i], &buf_info);
362            } else {
363                /* for every ASYNC CB, need ref count */
364                has_cb = 1;
365            }
366        }
367    }
368    pthread_mutex_unlock(&my_obj->cb_lock);
369
370    pthread_mutex_lock(&my_obj->buf_lock);
371    /* update buffer location */
372    my_obj->buf_status[idx].in_kernel = 0;
373
374    /* update buf ref count */
375    if (my_obj->is_bundled) {
376        /* need to add into super buf since bundled, add ref count */
377        my_obj->buf_status[idx].buf_refcnt++;
378    }
379    my_obj->buf_status[idx].buf_refcnt =
380        (uint8_t)(my_obj->buf_status[idx].buf_refcnt + has_cb);
381    pthread_mutex_unlock(&my_obj->buf_lock);
382
383    mm_stream_handle_rcvd_buf(my_obj, &buf_info, has_cb);
384}
385
386/*===========================================================================
387 * FUNCTION   : mm_stream_dispatch_app_data
388 *
389 * DESCRIPTION: dispatch stream buffer to registered users
390 *
391 * PARAMETERS :
392 *   @cmd_cb  : ptr storing stream buffer information
393 *   @userdata: user data ptr (stream object)
394 *
395 * RETURN     : none
396 *==========================================================================*/
397static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb,
398                                        void* user_data)
399{
400    int i;
401    mm_stream_t * my_obj = (mm_stream_t *)user_data;
402    mm_camera_buf_info_t* buf_info = NULL;
403    mm_camera_super_buf_t super_buf;
404    mm_stream_t *m_obj = my_obj;
405
406    if (NULL == my_obj) {
407        return;
408    }
409    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
410          my_obj->my_hdl, my_obj->fd, my_obj->state);
411
412    if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) {
413        LOGE("Wrong cmd_type (%d) for dataCB",
414                    cmd_cb->cmd_type);
415        return;
416    }
417
418    buf_info = &cmd_cb->u.buf;
419    memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
420    super_buf.num_bufs = 1;
421    super_buf.bufs[0] = buf_info->buf;
422    super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl;
423    super_buf.ch_id = my_obj->ch_obj->my_hdl;
424
425    if (m_obj->master_str_obj != NULL) {
426        m_obj = m_obj->master_str_obj;
427    }
428
429    pthread_mutex_lock(&m_obj->frame_sync.sync_lock);
430    if (m_obj->frame_sync.is_active) {
431        pthread_mutex_lock(&my_obj->buf_lock);
432        my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++;
433        pthread_mutex_unlock(&my_obj->buf_lock);
434        mm_camera_muxer_stream_frame_sync(&super_buf, my_obj);
435    } else if (my_obj->is_cb_active) {
436        pthread_mutex_lock(&my_obj->cb_lock);
437        for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
438            if(NULL != my_obj->buf_cb[i].cb
439                    && (my_obj->buf_cb[i].cb_type !=
440                    MM_CAMERA_STREAM_CB_TYPE_SYNC)) {
441                if (my_obj->buf_cb[i].cb_count != 0) {
442                    /* if <0, means infinite CB
443                     * if >0, means CB for certain times
444                     * both case we need to call CB */
445
446                    /* increase buf ref cnt */
447                    pthread_mutex_lock(&my_obj->buf_lock);
448                    my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++;
449                    pthread_mutex_unlock(&my_obj->buf_lock);
450
451                    /* callback */
452                    my_obj->buf_cb[i].cb(&super_buf,
453                            my_obj->buf_cb[i].user_data);
454                }
455
456                /* if >0, reduce count by 1 every time we called CB until reaches 0
457                 * when count reach 0, reset the buf_cb to have no CB */
458                if (my_obj->buf_cb[i].cb_count > 0) {
459                    my_obj->buf_cb[i].cb_count--;
460                    if (0 == my_obj->buf_cb[i].cb_count) {
461                        my_obj->buf_cb[i].cb = NULL;
462                        my_obj->buf_cb[i].user_data = NULL;
463                    }
464                }
465            }
466        }
467        pthread_mutex_unlock(&my_obj->cb_lock);
468    }
469    pthread_mutex_unlock(&m_obj->frame_sync.sync_lock);
470
471    /* do buf_done since we increased refcnt by one when has_cb */
472    mm_stream_buf_done(my_obj, buf_info->buf);
473}
474
475/*===========================================================================
476 * FUNCTION   : mm_stream_fsm_fn
477 *
478 * DESCRIPTION: stream finite state machine entry function. Depends on stream
479 *              state, incoming event will be handled differently.
480 *
481 * PARAMETERS :
482 *   @my_obj   : ptr to a stream object
483 *   @evt      : stream event to be processed
484 *   @in_val   : input event payload. Can be NULL if not needed.
485 *   @out_val  : output payload, Can be NULL if not needed.
486 *
487 * RETURN     : int32_t type of status
488 *              0  -- success
489 *              -1 -- failure
490 *==========================================================================*/
491int32_t mm_stream_fsm_fn(mm_stream_t *my_obj,
492                         mm_stream_evt_type_t evt,
493                         void * in_val,
494                         void * out_val)
495{
496    int32_t rc = -1;
497
498    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
499          my_obj->my_hdl, my_obj->fd, my_obj->state);
500    switch (my_obj->state) {
501    case MM_STREAM_STATE_NOTUSED:
502        LOGD("Not handling evt in unused state");
503        break;
504    case MM_STREAM_STATE_INITED:
505        rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val);
506        break;
507    case MM_STREAM_STATE_ACQUIRED:
508        rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val);
509        break;
510    case MM_STREAM_STATE_CFG:
511        rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val);
512        break;
513    case MM_STREAM_STATE_BUFFED:
514        rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val);
515        break;
516    case MM_STREAM_STATE_REG:
517        rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val);
518        break;
519    case MM_STREAM_STATE_ACTIVE:
520        rc = mm_stream_fsm_active(my_obj, evt, in_val, out_val);
521        break;
522    default:
523        LOGD("Not a valid state (%d)", my_obj->state);
524        break;
525    }
526    LOGD("X rc =%d",rc);
527    return rc;
528}
529
530/*===========================================================================
531 * FUNCTION   : mm_stream_fsm_inited
532 *
533 * DESCRIPTION: stream finite state machine function to handle event in INITED
534 *              state.
535 *
536 * PARAMETERS :
537 *   @my_obj   : ptr to a stream object
538 *   @evt      : stream event to be processed
539 *   @in_val   : input event payload. Can be NULL if not needed.
540 *   @out_val  : output payload, Can be NULL if not needed.
541 *
542 * RETURN     : int32_t type of status
543 *              0  -- success
544 *              -1 -- failure
545 *==========================================================================*/
546int32_t mm_stream_fsm_inited(mm_stream_t *my_obj,
547                             mm_stream_evt_type_t evt,
548                             void * in_val,
549                             void * out_val)
550{
551    int32_t rc = 0;
552    char dev_name[MM_CAMERA_DEV_NAME_LEN];
553    const char *dev_name_value = NULL;
554    if (NULL == my_obj) {
555      LOGE("NULL camera object\n");
556      return -1;
557    }
558
559    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
560          my_obj->my_hdl, my_obj->fd, my_obj->state);
561    switch(evt) {
562    case MM_STREAM_EVT_ACQUIRE:
563        if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) {
564            LOGE("NULL channel or camera obj\n");
565            rc = -1;
566            break;
567        }
568
569        mm_stream_init(my_obj);
570        uint32_t cam_handle = my_obj->ch_obj->cam_obj->my_hdl;
571        dev_name_value = mm_camera_util_get_dev_name_by_num(
572                my_obj->ch_obj->cam_obj->my_num, cam_handle);
573        if (NULL == dev_name_value) {
574            LOGE("NULL device name\n");
575            rc = -1;
576            mm_stream_deinit(my_obj);
577            break;
578        }
579
580        snprintf(dev_name, sizeof(dev_name), "/dev/%s",
581                 dev_name_value);
582
583        my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK);
584        if (my_obj->fd < 0) {
585            LOGE("open dev returned %d\n", my_obj->fd);
586            rc = -1;
587            mm_stream_deinit(my_obj);
588            break;
589        }
590        LOGD("open dev fd = %d\n", my_obj->fd);
591        rc = mm_stream_set_ext_mode(my_obj);
592        if (0 == rc) {
593            my_obj->state = MM_STREAM_STATE_ACQUIRED;
594        } else {
595            /* failed setting ext_mode
596             * close fd */
597            close(my_obj->fd);
598            my_obj->fd = -1;
599            mm_stream_deinit(my_obj);
600            break;
601        }
602        break;
603    default:
604        LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
605                    my_obj->state, evt, in_val, out_val);
606        break;
607    }
608    return rc;
609}
610
611/*===========================================================================
612 * FUNCTION   : mm_stream_fsm_acquired
613 *
614 * DESCRIPTION: stream finite state machine function to handle event in AQUIRED
615 *              state.
616 *
617 * PARAMETERS :
618 *   @my_obj   : ptr to a stream object
619 *   @evt      : stream event to be processed
620 *   @in_val   : input event payload. Can be NULL if not needed.
621 *   @out_val  : output payload, Can be NULL if not needed.
622 *
623 * RETURN     : int32_t type of status
624 *              0  -- success
625 *              -1 -- failure
626 *==========================================================================*/
627int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj,
628                               mm_stream_evt_type_t evt,
629                               void * in_val,
630                               void * out_val)
631{
632    int32_t rc = 0;
633
634    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
635          my_obj->my_hdl, my_obj->fd, my_obj->state);
636    switch(evt) {
637    case MM_STREAM_EVT_SET_FMT:
638        {
639            mm_camera_stream_config_t *config =
640                (mm_camera_stream_config_t *)in_val;
641
642            rc = mm_stream_config(my_obj, config);
643
644            /* change state to configed */
645            my_obj->state = MM_STREAM_STATE_CFG;
646
647            break;
648        }
649    case MM_STREAM_EVT_RELEASE:
650        rc = mm_stream_release(my_obj);
651        /* change state to not used */
652         my_obj->state = MM_STREAM_STATE_NOTUSED;
653        break;
654    case MM_STREAM_EVT_SET_PARM:
655        {
656            mm_evt_paylod_set_get_stream_parms_t *payload =
657                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
658            rc = mm_stream_set_parm(my_obj, payload->parms);
659        }
660        break;
661    case MM_STREAM_EVT_GET_PARM:
662        {
663            mm_evt_paylod_set_get_stream_parms_t *payload =
664                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
665            rc = mm_stream_get_parm(my_obj, payload->parms);
666        }
667        break;
668    case MM_STREAM_EVT_REG_FRAME_SYNC:
669        {
670            mm_evt_paylod_reg_frame_sync *payload =
671                (mm_evt_paylod_reg_frame_sync *)in_val;
672            rc = mm_stream_reg_frame_sync(my_obj, payload);
673        }
674        break;
675    case MM_STREAM_EVT_TRIGGER_FRAME_SYNC:
676        {
677            mm_camera_cb_req_type type =
678                    *((mm_camera_cb_req_type *)in_val);
679            rc = mm_stream_trigger_frame_sync(my_obj, type);
680        }
681        break;
682    default:
683        LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
684                    my_obj->state, evt, in_val, out_val);
685    }
686    LOGD("X rc = %d", rc);
687    return rc;
688}
689
690/*===========================================================================
691 * FUNCTION   : mm_stream_fsm_cfg
692 *
693 * DESCRIPTION: stream finite state machine function to handle event in CONFIGURED
694 *              state.
695 *
696 * PARAMETERS :
697 *   @my_obj   : ptr to a stream object
698 *   @evt      : stream event to be processed
699 *   @in_val   : input event payload. Can be NULL if not needed.
700 *   @out_val  : output payload, Can be NULL if not needed.
701 *
702 * RETURN     : int32_t type of status
703 *              0  -- success
704 *              -1 -- failure
705 *==========================================================================*/
706int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
707                          mm_stream_evt_type_t evt,
708                          void * in_val,
709                          void * out_val)
710{
711    int32_t rc = 0;
712    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
713          my_obj->my_hdl, my_obj->fd, my_obj->state);
714    switch(evt) {
715    case MM_STREAM_EVT_SET_FMT:
716        {
717            mm_camera_stream_config_t *config =
718                (mm_camera_stream_config_t *)in_val;
719
720            rc = mm_stream_config(my_obj, config);
721
722            /* change state to configed */
723            my_obj->state = MM_STREAM_STATE_CFG;
724
725            break;
726        }
727    case MM_STREAM_EVT_RELEASE:
728        rc = mm_stream_release(my_obj);
729        my_obj->state = MM_STREAM_STATE_NOTUSED;
730        break;
731    case MM_STREAM_EVT_SET_PARM:
732        {
733            mm_evt_paylod_set_get_stream_parms_t *payload =
734                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
735            rc = mm_stream_set_parm(my_obj, payload->parms);
736        }
737        break;
738    case MM_STREAM_EVT_GET_PARM:
739        {
740            mm_evt_paylod_set_get_stream_parms_t *payload =
741                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
742            rc = mm_stream_get_parm(my_obj, payload->parms);
743        }
744        break;
745    case MM_STREAM_EVT_GET_BUF:
746        rc = mm_stream_init_bufs(my_obj);
747        /* change state to buff allocated */
748        if(0 == rc) {
749            my_obj->state = MM_STREAM_STATE_BUFFED;
750        }
751        break;
752    case MM_STREAM_EVT_TRIGGER_FRAME_SYNC:
753        {
754            mm_camera_cb_req_type type =
755                    *((mm_camera_cb_req_type *)in_val);
756            rc = mm_stream_trigger_frame_sync(my_obj, type);
757        }
758        break;
759    default:
760        LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
761                    my_obj->state, evt, in_val, out_val);
762    }
763    LOGD("X rc = %d", rc);
764    return rc;
765}
766
767/*===========================================================================
768 * FUNCTION   : mm_stream_fsm_buffed
769 *
770 * DESCRIPTION: stream finite state machine function to handle event in BUFFED
771 *              state.
772 *
773 * PARAMETERS :
774 *   @my_obj   : ptr to a stream object
775 *   @evt      : stream event to be processed
776 *   @in_val   : input event payload. Can be NULL if not needed.
777 *   @out_val  : output payload, Can be NULL if not needed.
778 *
779 * RETURN     : int32_t type of status
780 *              0  -- success
781 *              -1 -- failure
782 *==========================================================================*/
783int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
784                             mm_stream_evt_type_t evt,
785                             void * in_val,
786                             void * out_val)
787{
788    int32_t rc = 0;
789    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
790          my_obj->my_hdl, my_obj->fd, my_obj->state);
791    switch(evt) {
792    case MM_STREAM_EVT_PUT_BUF:
793        rc = mm_stream_deinit_bufs(my_obj);
794        /* change state to configed */
795        my_obj->state = MM_STREAM_STATE_CFG;
796        break;
797    case MM_STREAM_EVT_REG_BUF:
798        rc = mm_stream_reg_buf(my_obj);
799        /* change state to regged */
800        if(0 == rc) {
801            my_obj->state = MM_STREAM_STATE_REG;
802        }
803        break;
804    case MM_STREAM_EVT_SET_PARM:
805        {
806            mm_evt_paylod_set_get_stream_parms_t *payload =
807                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
808            rc = mm_stream_set_parm(my_obj, payload->parms);
809        }
810        break;
811    case MM_STREAM_EVT_GET_PARM:
812        {
813            mm_evt_paylod_set_get_stream_parms_t *payload =
814                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
815            rc = mm_stream_get_parm(my_obj, payload->parms);
816        }
817        break;
818    default:
819        LOGW("invalid state (%d) for evt (%d), in(%p), out(%p)",
820                    my_obj->state, evt, in_val, out_val);
821    }
822    LOGD("X rc = %d", rc);
823    return rc;
824}
825
826/*===========================================================================
827 * FUNCTION   : mm_stream_fsm_reg
828 *
829 * DESCRIPTION: stream finite state machine function to handle event in REGGED
830 *              state.
831 *
832 * PARAMETERS :
833 *   @my_obj   : ptr to a stream object
834 *   @evt      : stream event to be processed
835 *   @in_val   : input event payload. Can be NULL if not needed.
836 *   @out_val  : output payload, Can be NULL if not needed.
837 *
838 * RETURN     : int32_t type of status
839 *              0  -- success
840 *              -1 -- failure
841 *==========================================================================*/
842int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
843                          mm_stream_evt_type_t evt,
844                          void * in_val,
845                          void * out_val)
846{
847    int32_t rc = 0;
848    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
849          my_obj->my_hdl, my_obj->fd, my_obj->state);
850
851    switch(evt) {
852    case MM_STREAM_EVT_UNREG_BUF:
853        rc = mm_stream_unreg_buf(my_obj);
854
855        /* change state to buffed */
856        my_obj->state = MM_STREAM_STATE_BUFFED;
857        break;
858    case MM_STREAM_EVT_START:
859        {
860            uint8_t has_cb = 0;
861            uint8_t i;
862            /* launch cmd thread if CB is not null */
863            pthread_mutex_lock(&my_obj->cb_lock);
864            for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
865                if((NULL != my_obj->buf_cb[i].cb) &&
866                        (my_obj->buf_cb[i].cb_type != MM_CAMERA_STREAM_CB_TYPE_SYNC)) {
867                    has_cb = 1;
868                    break;
869                }
870            }
871            pthread_mutex_unlock(&my_obj->cb_lock);
872
873            pthread_mutex_lock(&my_obj->cmd_lock);
874            if (has_cb) {
875                snprintf(my_obj->cmd_thread.threadName, THREAD_NAME_SIZE, "CAM_StrmAppData");
876                mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
877                                            mm_stream_dispatch_app_data,
878                                            (void *)my_obj);
879            }
880            pthread_mutex_unlock(&my_obj->cmd_lock);
881
882            my_obj->state = MM_STREAM_STATE_ACTIVE;
883            rc = mm_stream_streamon(my_obj);
884            if (0 != rc) {
885                /* failed stream on, need to release cmd thread if it's launched */
886                pthread_mutex_lock(&my_obj->cmd_lock);
887                if (has_cb) {
888                    mm_camera_cmd_thread_release(&my_obj->cmd_thread);
889                }
890                pthread_mutex_unlock(&my_obj->cmd_lock);
891                my_obj->state = MM_STREAM_STATE_REG;
892                break;
893            }
894        }
895        break;
896    case MM_STREAM_EVT_SET_PARM:
897        {
898            mm_evt_paylod_set_get_stream_parms_t *payload =
899                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
900            rc = mm_stream_set_parm(my_obj, payload->parms);
901        }
902        break;
903    case MM_STREAM_EVT_GET_PARM:
904        {
905            mm_evt_paylod_set_get_stream_parms_t *payload =
906                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
907            rc = mm_stream_get_parm(my_obj, payload->parms);
908        }
909        break;
910    default:
911        LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
912                    my_obj->state, evt, in_val, out_val);
913    }
914    LOGD("X rc = %d", rc);
915    return rc;
916}
917
918/*===========================================================================
919 * FUNCTION   : mm_stream_fsm_active
920 *
921 * DESCRIPTION: stream finite state machine function to handle event in ACTIVE
922 *              state.
923 *
924 * PARAMETERS :
925 *   @my_obj   : ptr to a stream object
926 *   @evt      : stream event to be processed
927 *   @in_val   : input event payload. Can be NULL if not needed.
928 *   @out_val  : output payload, Can be NULL if not needed.
929 *
930 * RETURN     : int32_t type of status
931 *              0  -- success
932 *              -1 -- failure
933 *==========================================================================*/
934int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
935                             mm_stream_evt_type_t evt,
936                             void * in_val,
937                             void * out_val)
938{
939    int32_t rc = 0;
940    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
941          my_obj->my_hdl, my_obj->fd, my_obj->state);
942    switch(evt) {
943    case MM_STREAM_EVT_QBUF:
944        rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
945        break;
946    case MM_STREAM_EVT_CANCEL_BUF:
947        rc = mm_stream_cancel_buf(my_obj, *((uint32_t*)in_val));
948        break;
949    case MM_STREAM_EVT_GET_QUEUED_BUF_COUNT:
950        rc = mm_stream_get_queued_buf_count(my_obj);
951        break;
952    case MM_STREAM_EVT_STOP:
953        {
954            bool stop_immediately = in_val ? *(bool*)in_val : FALSE;
955            uint8_t has_cb = 0;
956            uint8_t i;
957            rc = mm_stream_streamoff(my_obj, stop_immediately);
958
959            pthread_mutex_lock(&my_obj->cb_lock);
960            for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
961                if(NULL != my_obj->buf_cb[i].cb
962                        && my_obj->buf_cb[i].cb_type != MM_CAMERA_STREAM_CB_TYPE_SYNC) {
963                    has_cb = 1;
964                    break;
965                }
966            }
967            pthread_mutex_unlock(&my_obj->cb_lock);
968
969            pthread_mutex_lock(&my_obj->cmd_lock);
970            if (has_cb) {
971                mm_camera_cmd_thread_release(&my_obj->cmd_thread);
972            }
973            pthread_mutex_unlock(&my_obj->cmd_lock);
974            my_obj->state = MM_STREAM_STATE_REG;
975        }
976        break;
977    case MM_STREAM_EVT_SET_PARM:
978        {
979            mm_evt_paylod_set_get_stream_parms_t *payload =
980                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
981            rc = mm_stream_set_parm(my_obj, payload->parms);
982        }
983        break;
984    case MM_STREAM_EVT_GET_PARM:
985        {
986            mm_evt_paylod_set_get_stream_parms_t *payload =
987                (mm_evt_paylod_set_get_stream_parms_t *)in_val;
988            rc = mm_stream_get_parm(my_obj, payload->parms);
989        }
990        break;
991    case MM_STREAM_EVT_DO_ACTION:
992        rc = mm_stream_do_action(my_obj, in_val);
993        break;
994    case MM_STREAM_EVT_TRIGGER_FRAME_SYNC:
995        {
996            mm_camera_cb_req_type type =
997                    *((mm_camera_cb_req_type *)in_val);
998            rc = mm_stream_trigger_frame_sync(my_obj, type);
999        }
1000        break;
1001    case MM_STREAM_EVT_START_SENSOR_STREAMING:
1002        {
1003            rc = mm_stream_start_sensor_streaming(my_obj);
1004        }
1005        break;
1006    default:
1007        LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
1008                    my_obj->state, evt, in_val, out_val);
1009    }
1010    LOGD("X rc = %d", rc);
1011    return rc;
1012}
1013
1014int32_t mm_stream_init(mm_stream_t *my_obj)
1015{
1016    int32_t rc = 0;
1017    pthread_mutex_init(&my_obj->buf_lock, NULL);
1018    pthread_mutex_init(&my_obj->cb_lock, NULL);
1019    pthread_mutex_init(&my_obj->cmd_lock, NULL);
1020    pthread_cond_init(&my_obj->buf_cond, NULL);
1021    memset(my_obj->buf_status, 0,
1022            sizeof(my_obj->buf_status));
1023    memset(&my_obj->frame_sync, 0, sizeof(my_obj->frame_sync));
1024    pthread_mutex_init(&my_obj->frame_sync.sync_lock, NULL);
1025    mm_muxer_frame_sync_queue_init(&my_obj->frame_sync.superbuf_queue);
1026    if (my_obj->ch_obj->cam_obj->my_num == 0) {
1027        my_obj->is_cb_active = 1;
1028    } else {
1029        my_obj->is_cb_active = 0;
1030    }
1031    my_obj->is_res_shared = 0;
1032    my_obj->map_ops.map_ops = mm_camera_map_stream_buf_ops;
1033    my_obj->map_ops.bundled_map_ops = mm_camera_bundled_map_stream_buf_ops;
1034    my_obj->map_ops.unmap_ops = mm_camera_unmap_stream_buf_ops;
1035    my_obj->map_ops.userdata = my_obj;
1036    return rc;
1037}
1038
1039int32_t mm_stream_deinit(mm_stream_t *my_obj)
1040{
1041    int32_t rc = 0;
1042    /* destroy mutex */
1043    mm_muxer_frame_sync_queue_deinit(&my_obj->frame_sync.superbuf_queue);
1044    pthread_mutex_destroy(&my_obj->frame_sync.sync_lock);
1045    pthread_cond_destroy(&my_obj->buf_cond);
1046    pthread_mutex_destroy(&my_obj->buf_lock);
1047    pthread_mutex_destroy(&my_obj->cb_lock);
1048    pthread_mutex_destroy(&my_obj->cmd_lock);
1049    return rc;
1050}
1051
1052/*===========================================================================
1053 * FUNCTION   : mm_stream_config
1054 *
1055 * DESCRIPTION: configure a stream
1056 *
1057 * PARAMETERS :
1058 *   @my_obj       : stream object
1059 *   @config       : stream configuration
1060 *
1061 * RETURN     : int32_t type of status
1062 *              0  -- success
1063 *              -1 -- failure
1064 *==========================================================================*/
1065int32_t mm_stream_config(mm_stream_t *my_obj,
1066                         mm_camera_stream_config_t *config)
1067{
1068    int32_t rc = 0;
1069    int32_t cb_index = 0;
1070
1071    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
1072          my_obj->my_hdl, my_obj->fd, my_obj->state);
1073    my_obj->stream_info = config->stream_info;
1074
1075    if (config->stream_info->buf_cnt == 0) {
1076        my_obj->buf_num = (uint8_t)config->stream_info->num_bufs;
1077    } else {
1078        my_obj->buf_num = (uint8_t)config->stream_info->buf_cnt;
1079    }
1080    my_obj->total_buf_cnt = config->stream_info->num_bufs;
1081    my_obj->mem_vtbl = config->mem_vtbl;
1082    my_obj->padding_info = config->padding_info;
1083
1084    if (config->stream_cb_sync != NULL) {
1085        /* SYNC callback is always placed at index 0*/
1086        my_obj->buf_cb[cb_index].cb = config->stream_cb_sync;
1087        my_obj->buf_cb[cb_index].user_data = config->userdata;
1088        my_obj->buf_cb[cb_index].cb_count = -1; /* infinite by default */
1089        my_obj->buf_cb[cb_index].cb_type = MM_CAMERA_STREAM_CB_TYPE_SYNC;
1090        cb_index++;
1091    }
1092    my_obj->buf_cb[cb_index].cb = config->stream_cb;
1093    my_obj->buf_cb[cb_index].user_data = config->userdata;
1094    my_obj->buf_cb[cb_index].cb_count = -1; /* infinite by default */
1095    my_obj->buf_cb[cb_index].cb_type = MM_CAMERA_STREAM_CB_TYPE_ASYNC;
1096
1097    if ((my_obj->frame_sync.superbuf_queue.num_objs != 0)
1098            && (my_obj->frame_sync.super_buf_notify_cb == NULL)) {
1099        my_obj->frame_sync.super_buf_notify_cb = config->stream_cb;
1100    }
1101    if ((my_obj->frame_sync.superbuf_queue.num_objs != 0)
1102            && (my_obj->frame_sync.user_data == NULL)) {
1103        my_obj->frame_sync.user_data = config->userdata;
1104    }
1105
1106    rc = mm_stream_sync_info(my_obj);
1107    if (rc == 0) {
1108        rc = mm_stream_set_fmt(my_obj);
1109        if (rc < 0) {
1110            LOGE("mm_stream_set_fmt failed %d", rc);
1111        }
1112    }
1113
1114    if((my_obj->mem_vtbl.set_config_ops != NULL)
1115            && (!my_obj->is_res_shared)) {
1116        my_obj->mem_vtbl.set_config_ops(&my_obj->map_ops,
1117                my_obj->mem_vtbl.user_data);
1118    }
1119    return rc;
1120}
1121
1122/*===========================================================================
1123 * FUNCTION   : mm_stream_reg_frame_sync
1124 *
1125 * DESCRIPTION: reg stream frame sync
1126 *
1127 * PARAMETERS :
1128 *   @str_obj      : stream object
1129 *   @sync  : sync attribute
1130 *
1131 * RETURN     : uint32_t type of stream handle
1132 *              0  -- invalid stream handle, meaning the op failed
1133 *              >0 -- successfully added a stream with a valid handle
1134 *==========================================================================*/
1135int32_t mm_stream_reg_frame_sync(mm_stream_t *str_obj, mm_evt_paylod_reg_frame_sync *sync)
1136{
1137    int32_t rc = 0;
1138    mm_stream_t *my_obj = str_obj;
1139
1140    if (NULL == sync || sync->a_str_obj == NULL) {
1141        LOGE("Invalid stream link");
1142        return -1;
1143    }
1144
1145    if (str_obj->master_str_obj != NULL) {
1146        my_obj = str_obj->master_str_obj;
1147    }
1148
1149    mm_frame_sync_t *frame_sync = &my_obj->frame_sync;
1150    pthread_mutex_lock(&frame_sync->sync_lock);
1151    mm_frame_sync_queue_t *queue = NULL;
1152
1153    frame_sync->super_buf_notify_cb = sync->sync_attr->buf_cb;
1154    frame_sync->user_data = sync->sync_attr->userdata;
1155    queue = &frame_sync->superbuf_queue;
1156    queue->num_objs = 0;
1157    memset(&queue->bundled_objs, 0, sizeof(queue->bundled_objs));
1158    queue->bundled_objs[queue->num_objs] = my_obj->my_hdl;
1159    queue->num_objs++;
1160    queue->bundled_objs[queue->num_objs] = sync->a_str_obj->my_hdl;
1161    queue->num_objs++;
1162    queue->expected_frame_id = 0;
1163    queue->attr = sync->sync_attr->attr;
1164
1165    sync->a_str_obj->is_res_shared = sync->sync_attr->is_res_shared;
1166    my_obj->aux_str_obj[my_obj->num_s_cnt++] = sync->a_str_obj;
1167    sync->a_str_obj->master_str_obj = my_obj;
1168    pthread_mutex_unlock(&frame_sync->sync_lock);
1169    return rc;
1170}
1171
1172/*===========================================================================
1173 * FUNCTION   : mm_stream_trigger_frame_sync
1174 *
1175 * DESCRIPTION: start/stop stream frame sync
1176 *
1177 * PARAMETERS :
1178 *   @my_obj  : stream object
1179 *   @type  : flag to start/stop frame sync.
1180 *
1181 * RETURN     : uint32_t type of stream handle
1182 *              0  -- invalid stream handle, meaning the op failed
1183 *              >0 -- successfully added a stream with a valid handle
1184 *==========================================================================*/
1185int32_t mm_stream_trigger_frame_sync(mm_stream_t *my_obj,
1186        mm_camera_cb_req_type type)
1187{
1188    int32_t rc = 0;
1189    mm_stream_t *m_obj = my_obj;
1190    mm_stream_t *s_obj = NULL;
1191    mm_frame_sync_t *frame_sync = NULL;
1192
1193    if (m_obj->master_str_obj != NULL) {
1194        m_obj = m_obj->master_str_obj;
1195    }
1196    s_obj = m_obj->aux_str_obj[0];
1197
1198    frame_sync = &m_obj->frame_sync;
1199    pthread_mutex_lock(&frame_sync->sync_lock);
1200    switch (type) {
1201        case MM_CAMERA_CB_REQ_TYPE_SWITCH:
1202            if (m_obj->frame_sync.is_active) {
1203                mm_camera_muxer_stream_frame_sync_flush(m_obj);
1204            }
1205            m_obj->frame_sync.is_active = 0;
1206
1207            pthread_mutex_lock(&s_obj->cb_lock);
1208            s_obj->is_cb_active = !s_obj->is_cb_active;
1209            pthread_mutex_unlock(&s_obj->cb_lock);
1210
1211            pthread_mutex_lock(&m_obj->cb_lock);
1212            m_obj->is_cb_active = !m_obj->is_cb_active;
1213            if (s_obj->is_cb_active == 0
1214                    && m_obj->is_cb_active == 0) {
1215                m_obj->is_cb_active = 1;
1216            }
1217            pthread_mutex_unlock(&m_obj->cb_lock);
1218        break;
1219
1220        case MM_CAMERA_CB_REQ_TYPE_FRAME_SYNC:
1221            m_obj->frame_sync.is_active = 1;
1222        break;
1223
1224        case MM_CAMERA_CB_REQ_TYPE_ALL_CB:
1225            pthread_mutex_lock(&m_obj->cb_lock);
1226            m_obj->is_cb_active = 1;
1227            pthread_mutex_unlock(&m_obj->cb_lock);
1228
1229            pthread_mutex_lock(&s_obj->cb_lock);
1230            s_obj->is_cb_active = 1;
1231            pthread_mutex_unlock(&s_obj->cb_lock);
1232        break;
1233        default:
1234            //no-op
1235            break;
1236    }
1237    pthread_mutex_unlock(&frame_sync->sync_lock);
1238    return rc;
1239}
1240
1241/*===========================================================================
1242 * FUNCTION   : mm_stream_release
1243 *
1244 * DESCRIPTION: release a stream resource
1245 *
1246 * PARAMETERS :
1247 *   @my_obj       : stream object
1248 *
1249 * RETURN     : int32_t type of status
1250 *              0  -- success
1251 *              -1 -- failure
1252 *==========================================================================*/
1253int32_t mm_stream_release(mm_stream_t *my_obj)
1254{
1255    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
1256          my_obj->my_hdl, my_obj->fd, my_obj->state);
1257
1258    pthread_mutex_lock(&my_obj->buf_lock);
1259    memset(my_obj->buf_status, 0, sizeof(my_obj->buf_status));
1260    pthread_mutex_unlock(&my_obj->buf_lock);
1261
1262    /* close fd */
1263    if (my_obj->fd >= 0) {
1264#ifndef DAEMON_PRESENT
1265        int32_t rc = 0;
1266        cam_shim_packet_t *shim_cmd;
1267        cam_shim_cmd_data shim_cmd_data;
1268        mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
1269
1270        memset(&shim_cmd_data, 0, sizeof(shim_cmd_data));
1271        shim_cmd_data.command = MSM_CAMERA_PRIV_DEL_STREAM;
1272        shim_cmd_data.stream_id = my_obj->server_stream_id;
1273        shim_cmd_data.value = NULL;
1274        shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_SET_PARM,
1275                cam_obj->sessionid, &shim_cmd_data);
1276        rc = mm_camera_module_send_cmd(shim_cmd);
1277        if (rc < 0) {
1278            LOGE("failed to DELETE STREAM");
1279        }
1280        mm_camera_destroy_shim_cmd_packet(shim_cmd);
1281#endif /* DAEMON_PRESENT */
1282        close(my_obj->fd);
1283    }
1284
1285    if (my_obj->master_str_obj != NULL) {
1286        //Assuming order of stream release is maintained
1287        my_obj->master_str_obj->num_s_cnt--;
1288        my_obj->master_str_obj->aux_str_obj[
1289                my_obj->master_str_obj->num_s_cnt] = NULL;
1290    }
1291    mm_stream_deinit(my_obj);
1292
1293    /* reset stream obj */
1294    memset(my_obj, 0, sizeof(mm_stream_t));
1295    my_obj->fd = -1;
1296
1297    return 0;
1298}
1299
1300/*===========================================================================
1301 * FUNCTION   : mm_stream_streamon
1302 *
1303 * DESCRIPTION: stream on a stream. sending v4l2 request to kernel
1304 *
1305 * PARAMETERS :
1306 *   @my_obj       : stream object
1307 *
1308 * RETURN     : int32_t type of status
1309 *              0  -- success
1310 *              -1 -- failure
1311 *==========================================================================*/
1312int32_t mm_stream_streamon(mm_stream_t *my_obj)
1313{
1314    int32_t rc = 0;
1315    int8_t i;
1316    enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1317    uint8_t idx = mm_camera_util_get_index_by_num(
1318            my_obj->ch_obj->cam_obj->my_num, my_obj->my_hdl);
1319
1320    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
1321          my_obj->my_hdl, my_obj->fd, my_obj->state);
1322
1323    pthread_mutex_lock(&my_obj->buf_lock);
1324    for (i = my_obj->buf_idx; i < (my_obj->buf_idx + my_obj->buf_num); i++) {
1325        if ((my_obj->buf_status[i].map_status == 0) &&
1326                (my_obj->buf_status[i].in_kernel)) {
1327            LOGD("waiting for mapping to done: strm fd = %d",
1328                     my_obj->fd);
1329            struct timespec ts;
1330            clock_gettime(CLOCK_MONOTONIC, &ts);
1331            ts.tv_sec += WAIT_TIMEOUT;
1332            rc = pthread_cond_timedwait(&my_obj->buf_cond, &my_obj->buf_lock, &ts);
1333            if (rc == ETIMEDOUT) {
1334                LOGE("Timed out. Abort stream-on \n");
1335                rc = -1;
1336            }
1337            break;
1338        } else if (my_obj->buf_status[i].map_status < 0) {
1339            LOGD("Buffer mapping failed. Abort Stream On");
1340            rc = -1;
1341            break;
1342        }
1343    }
1344    pthread_mutex_unlock(&my_obj->buf_lock);
1345
1346    if (rc < 0) {
1347        /* remove fd from data poll thread in case of failure */
1348        mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1349                idx, my_obj->my_hdl, mm_camera_sync_call);
1350        return rc;
1351    }
1352    mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
1353    LOGD("E, my_handle = 0x%x, fd = %d, state = %d session_id:%d stream_id:%d",
1354            my_obj->my_hdl, my_obj->fd, my_obj->state, cam_obj->sessionid,
1355            my_obj->server_stream_id);
1356
1357    rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
1358    if (rc < 0 && my_obj->stream_info->num_bufs != 0) {
1359        LOGE("ioctl VIDIOC_STREAMON failed: rc=%d, errno %d",
1360                rc, errno);
1361        goto error_case;
1362    }
1363
1364#ifndef DAEMON_PRESENT
1365    cam_shim_packet_t *shim_cmd;
1366    cam_shim_cmd_data shim_cmd_data;
1367    // Only configure for stream on without starting sensor streaming.
1368    unsigned int value = CAM_STREAM_ON_TYPE_CONFIG;
1369
1370    memset(&shim_cmd_data, 0, sizeof(shim_cmd_data));
1371    shim_cmd_data.command = MSM_CAMERA_PRIV_STREAM_ON;
1372    shim_cmd_data.stream_id = my_obj->server_stream_id;
1373    shim_cmd_data.value = &value;
1374    shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_SET_PARM,
1375            cam_obj->sessionid, &shim_cmd_data);
1376    rc = mm_camera_module_send_cmd(shim_cmd);
1377    mm_camera_destroy_shim_cmd_packet(shim_cmd);
1378    if (rc < 0) {
1379        LOGE("Module StreamON failed: rc=%d", rc);
1380        ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
1381        goto error_case;
1382    }
1383#endif
1384    LOGD("X rc = %d",rc);
1385    return rc;
1386error_case:
1387     /* remove fd from data poll thread in case of failure */
1388     mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1389             idx, my_obj->my_hdl, mm_camera_sync_call);
1390
1391    LOGD("X rc = %d",rc);
1392    return rc;
1393}
1394
1395int32_t mm_stream_start_sensor_streaming(mm_stream_t *my_obj)
1396{
1397    int32_t rc = 0;
1398
1399    enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1400    uint8_t idx = mm_camera_util_get_index_by_num(
1401            my_obj->ch_obj->cam_obj->my_num, my_obj->my_hdl);
1402    mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
1403    LOGD("E, my_handle = 0x%x, fd = %d, state = %d session_id:%d stream_id:%d",
1404            my_obj->my_hdl, my_obj->fd, my_obj->state, cam_obj->sessionid,
1405            my_obj->server_stream_id);
1406
1407    cam_shim_packet_t *shim_cmd;
1408    cam_shim_cmd_data shim_cmd_data;
1409    unsigned int value = CAM_STREAM_ON_TYPE_START_SENSOR_STREAMING;
1410
1411    memset(&shim_cmd_data, 0, sizeof(shim_cmd_data));
1412    shim_cmd_data.command = MSM_CAMERA_PRIV_STREAM_ON;
1413    shim_cmd_data.stream_id = my_obj->server_stream_id;
1414    shim_cmd_data.value = &value;
1415    shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_SET_PARM,
1416            cam_obj->sessionid, &shim_cmd_data);
1417    rc = mm_camera_module_send_cmd(shim_cmd);
1418    mm_camera_destroy_shim_cmd_packet(shim_cmd);
1419    if (rc < 0) {
1420        LOGE("Module StreamON failed: rc=%d", rc);
1421        ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
1422        goto error_case;
1423    }
1424
1425    LOGD("X rc = %d",rc);
1426    return rc;
1427error_case:
1428     /* remove fd from data poll thread in case of failure */
1429     mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1430             idx, my_obj->my_hdl, mm_camera_sync_call);
1431
1432    LOGD("X rc = %d",rc);
1433    return rc;
1434}
1435
1436/*===========================================================================
1437 * FUNCTION   : mm_stream_streamoff
1438 *
1439 * DESCRIPTION: stream off a stream. sending v4l2 request to kernel
1440 *
1441 * PARAMETERS :
1442 *   @my_obj          : stream object
1443 *   @stop_immediately: stop stream immediately without waiting for frame
1444 *                      boundary.
1445 *
1446 * RETURN     : int32_t type of status
1447 *              0  -- success
1448 *              -1 -- failure
1449 *==========================================================================*/
1450int32_t mm_stream_streamoff(mm_stream_t *my_obj, bool stop_immediately)
1451{
1452    int32_t rc = 0;
1453    enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1454    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
1455          my_obj->my_hdl, my_obj->fd, my_obj->state);
1456
1457    uint8_t idx = mm_camera_util_get_index_by_num(
1458            my_obj->ch_obj->cam_obj->my_num, my_obj->my_hdl);
1459    /* step1: remove fd from data poll thread */
1460    rc = mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1461            idx, my_obj->my_hdl, mm_camera_sync_call);
1462    if (rc < 0) {
1463        /* The error might be due to async update. In this case
1464         * wait for all updates to complete before proceeding. */
1465        rc = mm_camera_poll_thread_commit_updates(&my_obj->ch_obj->poll_thread[0]);
1466        if (rc < 0) {
1467            LOGE("Poll sync failed %d", rc);
1468            rc = 0;
1469        }
1470    }
1471
1472#ifndef DAEMON_PRESENT
1473    cam_shim_packet_t *shim_cmd;
1474    cam_shim_cmd_data shim_cmd_data;
1475    mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
1476    unsigned int value = stop_immediately ? 1 : 0;
1477
1478    memset(&shim_cmd_data, 0, sizeof(shim_cmd_data));
1479    shim_cmd_data.command = MSM_CAMERA_PRIV_STREAM_OFF;
1480    shim_cmd_data.stream_id = my_obj->server_stream_id;
1481    shim_cmd_data.value = &value;
1482    shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_SET_PARM,
1483            cam_obj->sessionid, &shim_cmd_data);
1484
1485    rc |= mm_camera_module_send_cmd(shim_cmd);
1486    mm_camera_destroy_shim_cmd_packet(shim_cmd);
1487    if (rc < 0) {
1488        LOGE("Module StreamOFF failed: rc=%d", rc)
1489    }
1490#endif
1491
1492    /* step2: stream off */
1493    rc |= ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
1494    if (rc < 0) {
1495        LOGE("STREAMOFF ioctl failed: %s", strerror(errno));
1496    }
1497    return rc;
1498}
1499
1500/*===========================================================================
1501 * FUNCTION   : mm_stream_write_user_buf
1502 *
1503 * DESCRIPTION: dequeue a stream buffer from user buffer queue and fill internal structure
1504 *
1505 * PARAMETERS :
1506 *   @my_obj       : stream object
1507 *   @buf     : ptr to a struct storing buffer information
1508 *
1509 * RETURN     : int32_t type of status
1510 *              0  -- success
1511 *              -1 -- failure
1512 *==========================================================================*/
1513int32_t mm_stream_write_user_buf(mm_stream_t * my_obj,
1514        mm_camera_buf_def_t *buf)
1515{
1516    int32_t rc = 0, i;
1517    int32_t index = -1, count = 0;
1518    struct msm_camera_user_buf_cont_t *cont_buf = NULL;
1519
1520    if (buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) {
1521        pthread_mutex_lock(&my_obj->buf_lock);
1522        my_obj->buf_status[buf->buf_idx].buf_refcnt--;
1523        if (0 == my_obj->buf_status[buf->buf_idx].buf_refcnt) {
1524            pthread_mutex_unlock(&my_obj->buf_lock);
1525            cont_buf = (struct msm_camera_user_buf_cont_t *)my_obj->buf[buf->buf_idx].buffer;
1526            cont_buf->buf_cnt = my_obj->buf[buf->buf_idx].user_buf.bufs_used;
1527            for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) {
1528                cont_buf->buf_idx[i] = my_obj->buf[buf->buf_idx].user_buf.buf_idx[i];
1529            }
1530            rc = mm_stream_qbuf(my_obj, buf);
1531            if(rc < 0) {
1532                LOGE("mm_camera_stream_qbuf(idx=%d) err=%d\n",
1533                            buf->buf_idx, rc);
1534            } else {
1535                for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) {
1536                    my_obj->buf[buf->buf_idx].user_buf.buf_idx[i] = -1;
1537                }
1538                my_obj->buf_status[buf->buf_idx].in_kernel = 1;
1539                my_obj->buf[buf->buf_idx].user_buf.buf_in_use = 1;
1540            }
1541        } else {
1542            LOGD("<DEBUG> : ref count pending count :%d idx = %d",
1543                 my_obj->buf_status[buf->buf_idx].buf_refcnt, buf->buf_idx);
1544            pthread_mutex_unlock(&my_obj->buf_lock);
1545        }
1546        return rc;
1547    }
1548
1549    if ((my_obj->cur_buf_idx < 0)
1550            || (my_obj->cur_buf_idx >=
1551            (my_obj->buf_idx + my_obj->buf_num))) {
1552        for (i = 0; i < my_obj->buf_num; i++) {
1553            if ((my_obj->buf_status[i].in_kernel)
1554                    || (my_obj->buf[i].user_buf.buf_in_use)) {
1555                continue;
1556            }
1557
1558            my_obj->cur_buf_idx = index = i;
1559            break;
1560        }
1561    } else {
1562        index = my_obj->cur_buf_idx;
1563    }
1564
1565    if (index == -1) {
1566        LOGE("No Free batch buffer");
1567        rc = -1;
1568        return rc;
1569    }
1570
1571    //Insert Buffer to Batch structure.
1572    my_obj->buf[index].user_buf.buf_idx[count] = buf->buf_idx;
1573    my_obj->cur_bufs_staged++;
1574
1575    LOGD("index = %d filled = %d used = %d",
1576            index,
1577            my_obj->cur_bufs_staged,
1578            my_obj->buf[index].user_buf.bufs_used);
1579
1580    if (my_obj->cur_bufs_staged
1581            == my_obj->buf[index].user_buf.bufs_used){
1582        pthread_mutex_lock(&my_obj->buf_lock);
1583        my_obj->buf_status[index].buf_refcnt--;
1584        if (0 == my_obj->buf_status[index].buf_refcnt) {
1585            pthread_mutex_unlock(&my_obj->buf_lock);
1586            cont_buf = (struct msm_camera_user_buf_cont_t *)my_obj->buf[index].buffer;
1587            cont_buf->buf_cnt = my_obj->buf[index].user_buf.bufs_used;
1588            for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) {
1589                cont_buf->buf_idx[i] = my_obj->buf[index].user_buf.buf_idx[i];
1590            }
1591            rc = mm_stream_qbuf(my_obj, &my_obj->buf[index]);
1592            if(rc < 0) {
1593                LOGE("mm_camera_stream_qbuf(idx=%d) err=%d\n",
1594                            index, rc);
1595            } else {
1596                for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) {
1597                    my_obj->buf[index].user_buf.buf_idx[i] = -1;
1598                }
1599                my_obj->buf_status[index].in_kernel = 1;
1600                my_obj->buf[index].user_buf.buf_in_use = 1;
1601                my_obj->cur_bufs_staged = 0;
1602                my_obj->cur_buf_idx = -1;
1603            }
1604        }else{
1605            LOGD("<DEBUG> : ref count pending count :%d idx = %d",
1606                 my_obj->buf_status[index].buf_refcnt, index);
1607            pthread_mutex_unlock(&my_obj->buf_lock);
1608        }
1609    }
1610
1611    return rc;
1612}
1613
1614/*===========================================================================
1615 * FUNCTION   : mm_stream_read_user_buf
1616 *
1617 * DESCRIPTION: dequeue a stream buffer from user buffer queue and fill internal structure
1618 *
1619 * PARAMETERS :
1620 *   @my_obj       : stream object
1621 *   @buf_info     : ptr to a struct storing buffer information
1622 *
1623 * RETURN     : int32_t type of status
1624 *              0  -- success
1625 *              -1 -- failure
1626 *==========================================================================*/
1627int32_t mm_stream_read_user_buf(mm_stream_t * my_obj,
1628        mm_camera_buf_info_t* buf_info)
1629{
1630    int32_t rc = 0, i;
1631    mm_camera_buf_def_t *stream_buf  = NULL;
1632    struct msm_camera_user_buf_cont_t *user_buf = NULL;
1633    nsecs_t interval_nsec = 0, frame_ts = 0, timeStamp = 0;
1634    int ts_delta = 0;
1635    uint32_t frameID = 0;
1636
1637    user_buf = (struct msm_camera_user_buf_cont_t *)buf_info->buf->buffer;
1638
1639    if(user_buf != my_obj->buf[buf_info->buf->buf_idx].buffer) {
1640        LOGD("Buffer modified. ERROR");
1641        rc = -1;
1642        return rc;
1643    }
1644
1645    if (buf_info->buf->frame_idx == 1) {
1646        frameID = buf_info->buf->frame_idx;
1647    }else {
1648        frameID = (buf_info->buf->frame_idx - 1) * user_buf->buf_cnt;
1649    }
1650
1651    timeStamp = (nsecs_t)(buf_info->buf->ts.tv_sec) *
1652            1000000000LL + buf_info->buf->ts.tv_nsec;
1653
1654    if (timeStamp <= my_obj->prev_timestamp) {
1655        LOGE("TimeStamp received less than expected");
1656        mm_stream_qbuf(my_obj, buf_info->buf);
1657        return rc;
1658    } else if (my_obj->prev_timestamp == 0
1659            || (my_obj->prev_frameID != buf_info->buf->frame_idx + 1)) {
1660        /* For first frame or incase batch is droped */
1661        interval_nsec = ((my_obj->stream_info->user_buf_info.frameInterval) * 1000000);
1662        my_obj->prev_timestamp = (timeStamp - (nsecs_t)(user_buf->buf_cnt * interval_nsec));
1663    } else {
1664        ts_delta = timeStamp - my_obj->prev_timestamp;
1665        interval_nsec = (nsecs_t)(ts_delta / user_buf->buf_cnt);
1666        LOGD("Timestamp delta = %d timestamp = %lld", ts_delta, timeStamp);
1667    }
1668
1669    for (i = 0; i < (int32_t)user_buf->buf_cnt; i++) {
1670        buf_info->buf->user_buf.buf_idx[i] = user_buf->buf_idx[i];
1671        stream_buf = &my_obj->plane_buf[user_buf->buf_idx[i]];
1672        stream_buf->frame_idx = frameID + i;
1673
1674        frame_ts  = (i * interval_nsec) + my_obj->prev_timestamp;
1675
1676        stream_buf->ts.tv_sec  = (frame_ts / 1000000000LL);
1677        stream_buf->ts.tv_nsec = (frame_ts - (stream_buf->ts.tv_sec * 1000000000LL));
1678        stream_buf->is_uv_subsampled = buf_info->buf->is_uv_subsampled;
1679
1680        LOGD("buf_index %d, frame_idx %d, stream type %d, timestamp = %lld",
1681                 stream_buf->buf_idx, stream_buf->frame_idx,
1682                my_obj->stream_info->stream_type, frame_ts);
1683    }
1684
1685    buf_info->buf->ts.tv_sec  = (my_obj->prev_timestamp / 1000000000LL);
1686    buf_info->buf->ts.tv_nsec = (my_obj->prev_timestamp -
1687            (buf_info->buf->ts.tv_sec * 1000000000LL));
1688
1689    buf_info->buf->user_buf.bufs_used = user_buf->buf_cnt;
1690    buf_info->buf->user_buf.buf_in_use = 1;
1691
1692    my_obj->prev_timestamp = timeStamp;
1693    my_obj->prev_frameID = buf_info->buf->frame_idx;
1694
1695    LOGD("X rc = %d",rc);
1696    return rc;
1697}
1698
1699/*===========================================================================
1700 * FUNCTION   : mm_stream_read_msm_frame
1701 *
1702 * DESCRIPTION: dequeue a stream buffer from kernel queue
1703 *
1704 * PARAMETERS :
1705 *   @my_obj       : stream object
1706 *   @buf_info     : ptr to a struct storing buffer information
1707 *   @num_planes   : number of planes in the buffer
1708 *
1709 * RETURN     : int32_t type of status
1710 *              0  -- success
1711 *              -1 -- failure
1712 *==========================================================================*/
1713int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
1714                                 mm_camera_buf_info_t* buf_info,
1715                                 uint8_t num_planes)
1716{
1717    int32_t rc = 0;
1718    struct v4l2_buffer vb;
1719    struct v4l2_plane planes[VIDEO_MAX_PLANES];
1720    char frame_type[64] = "";
1721    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
1722          my_obj->my_hdl, my_obj->fd, my_obj->state);
1723
1724    if (ATRACE_ENABLED()) {
1725        snprintf(frame_type, sizeof(frame_type), "DQBUF: type %d",
1726            my_obj->stream_info->stream_type);
1727    }
1728    ATRACE_BEGIN(frame_type);
1729
1730    memset(&vb,  0,  sizeof(vb));
1731    vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1732    vb.memory = V4L2_MEMORY_USERPTR;
1733    vb.m.planes = &planes[0];
1734    vb.length = num_planes;
1735
1736    rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
1737    if (0 > rc) {
1738        LOGE("VIDIOC_DQBUF ioctl call failed on stream type %d (rc=%d): %s",
1739             my_obj->stream_info->stream_type, rc, strerror(errno));
1740    } else {
1741        pthread_mutex_lock(&my_obj->buf_lock);
1742        my_obj->queued_buffer_count--;
1743        if (0 == my_obj->queued_buffer_count) {
1744            uint8_t idx = mm_camera_util_get_index_by_num(
1745                    my_obj->ch_obj->cam_obj->my_num, my_obj->my_hdl);
1746            LOGH("Remove Poll stream %p type: %d FD = %d",
1747                    my_obj, my_obj->stream_info->stream_type, my_obj->fd);
1748            mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
1749                    idx, my_obj->my_hdl, mm_camera_async_call);
1750        }
1751        pthread_mutex_unlock(&my_obj->buf_lock);
1752        uint32_t idx = vb.index;
1753        buf_info->buf = &my_obj->buf[idx];
1754        buf_info->frame_idx = vb.sequence;
1755        buf_info->stream_id = my_obj->my_hdl;
1756
1757        buf_info->buf->stream_id = my_obj->my_hdl;
1758        buf_info->buf->buf_idx = idx;
1759        buf_info->buf->frame_idx = vb.sequence;
1760        buf_info->buf->ts.tv_sec  = vb.timestamp.tv_sec;
1761        buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
1762        buf_info->buf->flags = vb.flags;
1763        // Buffers are cleaned/invalidated when received by HAL
1764        // Cache ops not required on DQBUF
1765        buf_info->buf->cache_flags = 0;
1766
1767        LOGH("VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d,"
1768                "queued: %d, buf_type = %d flags = %d FD = %d",
1769                vb.index, buf_info->buf->frame_idx,
1770                my_obj->stream_info->stream_type, rc,
1771                my_obj->queued_buffer_count, buf_info->buf->buf_type,
1772                buf_info->buf->flags,
1773                my_obj->fd);
1774
1775        buf_info->buf->is_uv_subsampled =
1776            (vb.reserved == V4L2_PIX_FMT_NV14 || vb.reserved == V4L2_PIX_FMT_NV41);
1777
1778        if(buf_info->buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) {
1779            mm_stream_read_user_buf(my_obj, buf_info);
1780        }
1781
1782        rc = mm_stream_handle_cache_ops(my_obj, buf_info->buf, TRUE);
1783        if (rc != 0) {
1784            LOGE("Error cleaning/invalidating the buffer");
1785        }
1786    }
1787
1788    LOGD("X rc = %d",rc);
1789    ATRACE_END();
1790    return rc;
1791}
1792
1793/*===========================================================================
1794 * FUNCTION   : mm_stream_set_parms
1795 *
1796 * DESCRIPTION: set parameters per stream
1797 *
1798 * PARAMETERS :
1799 *   @my_obj       : stream object
1800 *   @in_value     : ptr to a param struct to be set to server
1801 *
1802 * RETURN     : int32_t type of status
1803 *              0  -- success
1804 *              -1 -- failure
1805 * NOTE       : Assume the parms struct buf is already mapped to server via
1806 *              domain socket. Corresponding fields of parameters to be set
1807 *              are already filled in by upper layer caller.
1808 *==========================================================================*/
1809int32_t mm_stream_set_parm(mm_stream_t *my_obj,
1810                           cam_stream_parm_buffer_t *in_value)
1811{
1812    int32_t rc = -1;
1813    int32_t value = 0;
1814    if (in_value != NULL) {
1815      mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
1816      int stream_id = my_obj->server_stream_id;
1817      rc = mm_camera_util_s_ctrl(cam_obj, stream_id, my_obj->fd,
1818              CAM_PRIV_STREAM_PARM, &value);
1819      if (rc < 0) {
1820        LOGE("Failed to set stream parameter type = %d", in_value->type);
1821      }
1822    }
1823    return rc;
1824}
1825
1826/*===========================================================================
1827 * FUNCTION   : mm_stream_get_parms
1828 *
1829 * DESCRIPTION: get parameters per stream
1830 *
1831 * PARAMETERS :
1832 *   @my_obj       : stream object
1833 *   @in_value     : ptr to a param struct to be get from server
1834 *
1835 * RETURN     : int32_t type of status
1836 *              0  -- success
1837 *              -1 -- failure
1838 * NOTE       : Assume the parms struct buf is already mapped to server via
1839 *              domain socket. Corresponding fields of parameters to be get
1840 *              are already filled in by upper layer caller.
1841 *==========================================================================*/
1842int32_t mm_stream_get_parm(mm_stream_t *my_obj,
1843                           cam_stream_parm_buffer_t *in_value)
1844{
1845    int32_t rc = -1;
1846    int32_t value = 0;
1847    if (in_value != NULL) {
1848        mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
1849        int stream_id = my_obj->server_stream_id;
1850        rc = mm_camera_util_g_ctrl(cam_obj, stream_id, my_obj->fd,
1851              CAM_PRIV_STREAM_PARM, &value);
1852    }
1853    return rc;
1854}
1855
1856/*===========================================================================
1857 * FUNCTION   : mm_stream_do_actions
1858 *
1859 * DESCRIPTION: request server to perform stream based actions
1860 *
1861 * PARAMETERS :
1862 *   @my_obj       : stream object
1863 *   @in_value     : ptr to a struct of actions to be performed by the server
1864 *
1865 * RETURN     : int32_t type of status
1866 *              0  -- success
1867 *              -1 -- failure
1868 * NOTE       : Assume the action struct buf is already mapped to server via
1869 *              domain socket. Corresponding fields of actions to be performed
1870 *              are already filled in by upper layer caller.
1871 *==========================================================================*/
1872int32_t mm_stream_do_action(mm_stream_t *my_obj,
1873                            void *in_value)
1874{
1875    int32_t rc = -1;
1876    int32_t value = 0;
1877    if (in_value != NULL) {
1878        mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
1879        int stream_id = my_obj->server_stream_id;
1880        rc = mm_camera_util_s_ctrl(cam_obj, stream_id, my_obj->fd,
1881              CAM_PRIV_STREAM_PARM, &value);
1882    }
1883    return rc;
1884}
1885
1886/*===========================================================================
1887 * FUNCTION   : mm_stream_set_ext_mode
1888 *
1889 * DESCRIPTION: set stream extended mode to server via v4l2 ioctl
1890 *
1891 * PARAMETERS :
1892 *   @my_obj       : stream object
1893 *
1894 * RETURN     : int32_t type of status
1895 *              0  -- success
1896 *              -1 -- failure
1897 * NOTE       : Server will return a server stream id that uniquely identify
1898 *              this stream on server side. Later on communication to server
1899 *              per stream should use this server stream id.
1900 *==========================================================================*/
1901int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
1902{
1903    int32_t rc = 0;
1904    struct v4l2_streamparm s_parm;
1905    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
1906          my_obj->my_hdl, my_obj->fd, my_obj->state);
1907
1908    memset(&s_parm, 0, sizeof(s_parm));
1909    s_parm.type =  V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1910
1911    rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
1912    LOGD("stream fd=%d, rc=%d, extended_mode=%d",
1913         my_obj->fd, rc, s_parm.parm.capture.extendedmode);
1914    if (rc == 0) {
1915        my_obj->server_stream_id = s_parm.parm.capture.extendedmode;
1916#ifndef DAEMON_PRESENT
1917        cam_shim_packet_t *shim_cmd;
1918        cam_shim_cmd_data shim_cmd_data;
1919        mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
1920
1921        memset(&shim_cmd_data, 0, sizeof(shim_cmd_data));
1922        shim_cmd_data.command = MSM_CAMERA_PRIV_NEW_STREAM;
1923        shim_cmd_data.stream_id = my_obj->server_stream_id;
1924        shim_cmd_data.value = NULL;
1925        shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_SET_PARM,
1926                cam_obj->sessionid, &shim_cmd_data);
1927        rc = mm_camera_module_send_cmd(shim_cmd);
1928        mm_camera_destroy_shim_cmd_packet(shim_cmd);
1929#endif /* DAEMON_PRESENT */
1930    } else {
1931        LOGE("VIDIOC_S_PARM  extendedmode error");
1932    }
1933    return rc;
1934}
1935
1936/*===========================================================================
1937 * FUNCTION   : mm_stream_qbuf
1938 *
1939 * DESCRIPTION: enqueue buffer back to kernel queue for furture use
1940 *
1941 * PARAMETERS :
1942 *   @my_obj       : stream object
1943 *   @buf          : ptr to a struct storing buffer information
1944 *
1945 * RETURN     : int32_t type of status
1946 *              0  -- success
1947 *              -1 -- failure
1948 *==========================================================================*/
1949int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
1950{
1951    int32_t rc = 0;
1952    uint32_t length = 0;
1953    struct v4l2_buffer buffer;
1954    struct v4l2_plane planes[VIDEO_MAX_PLANES];
1955    LOGD("E, my_handle = 0x%x, fd = %d, state = %d, stream type = %d",
1956          my_obj->my_hdl, my_obj->fd, my_obj->state,
1957         my_obj->stream_info->stream_type);
1958
1959    if (buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) {
1960        LOGD("USERPTR num_buf = %d, idx = %d",
1961                buf->user_buf.bufs_used, buf->buf_idx);
1962        memset(&planes, 0, sizeof(planes));
1963        planes[0].length = my_obj->stream_info->user_buf_info.size;
1964        planes[0].m.userptr = buf->fd;
1965        length = 1;
1966    } else {
1967        memcpy(planes, buf->planes_buf.planes, sizeof(planes));
1968        length = buf->planes_buf.num_planes;
1969    }
1970
1971    memset(&buffer, 0, sizeof(buffer));
1972    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1973    buffer.memory = V4L2_MEMORY_USERPTR;
1974    buffer.index = (__u32)buf->buf_idx;
1975    buffer.m.planes = &planes[0];
1976    buffer.length = (__u32)length;
1977
1978    rc = mm_stream_handle_cache_ops(my_obj, buf, FALSE);
1979    if (rc != 0) {
1980        LOGE("Error cleaning/invalidating the buffer");
1981    }
1982    pthread_mutex_lock(&my_obj->buf_lock);
1983    my_obj->queued_buffer_count++;
1984    if (1 == my_obj->queued_buffer_count) {
1985        uint8_t idx = mm_camera_util_get_index_by_num(
1986                my_obj->ch_obj->cam_obj->my_num, my_obj->my_hdl);
1987        /* Add fd to data poll thread */
1988        LOGH("Add Poll FD %p type: %d idx = %d num = %d fd = %d",
1989                my_obj,my_obj->stream_info->stream_type, idx,
1990                my_obj->ch_obj->cam_obj->my_num, my_obj->fd);
1991        rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
1992                idx, my_obj->my_hdl, my_obj->fd, mm_stream_data_notify,
1993                (void*)my_obj, mm_camera_async_call);
1994        if (0 > rc) {
1995            LOGE("Add poll on stream %p type: %d fd error (rc=%d)",
1996                 my_obj, my_obj->stream_info->stream_type, rc);
1997        } else {
1998            LOGH("Started poll on stream %p type: %d",
1999                my_obj, my_obj->stream_info->stream_type);
2000        }
2001    }
2002    pthread_mutex_unlock(&my_obj->buf_lock);
2003
2004    rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
2005    pthread_mutex_lock(&my_obj->buf_lock);
2006    if (0 > rc) {
2007        LOGE("VIDIOC_QBUF ioctl call failed on stream type %d (rc=%d): %s",
2008             my_obj->stream_info->stream_type, rc, strerror(errno));
2009        my_obj->queued_buffer_count--;
2010        if (0 == my_obj->queued_buffer_count) {
2011            uint8_t idx = mm_camera_util_get_index_by_num(
2012                    my_obj->ch_obj->cam_obj->my_num, my_obj->my_hdl);
2013            /* Remove fd from data poll in case of failing
2014             * first buffer queuing attempt */
2015            LOGH("Stoping poll on stream %p type: %d",
2016                my_obj, my_obj->stream_info->stream_type);
2017            mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0],
2018                    idx, my_obj->my_hdl, mm_camera_async_call);
2019            LOGH("Stopped poll on stream %p type: %d",
2020                my_obj, my_obj->stream_info->stream_type);
2021        }
2022    } else {
2023        LOGH("VIDIOC_QBUF buf_index %d, frame_idx %d stream type %d, rc %d,"
2024                " queued: %d, buf_type = %d stream-FD = %d",
2025                buffer.index, buf->frame_idx, my_obj->stream_info->stream_type, rc,
2026                my_obj->queued_buffer_count, buf->buf_type, my_obj->fd);
2027    }
2028    pthread_mutex_unlock(&my_obj->buf_lock);
2029
2030    return rc;
2031}
2032
2033/*===========================================================================
2034 * FUNCTION   : mm_stream_request_buf
2035 *
2036 * DESCRIPTION: This function let kernel know the amount of buffers need to
2037 *              be registered via v4l2 ioctl.
2038 *
2039 * PARAMETERS :
2040 *   @my_obj       : stream object
2041 *
2042 * RETURN     : int32_t type of status
2043 *              0  -- success
2044 *              -1 -- failure
2045 *==========================================================================*/
2046int32_t mm_stream_request_buf(mm_stream_t * my_obj)
2047{
2048    int32_t rc = 0;
2049    struct v4l2_requestbuffers bufreq;
2050    uint8_t buf_num = my_obj->total_buf_cnt;
2051    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
2052          my_obj->my_hdl, my_obj->fd, my_obj->state);
2053
2054    if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
2055        LOGE("buf num %d > max limit %d\n",
2056                    buf_num, MM_CAMERA_MAX_NUM_FRAMES);
2057        return -1;
2058    }
2059
2060    memset(&bufreq, 0, sizeof(bufreq));
2061    bufreq.count = buf_num;
2062    bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2063    bufreq.memory = V4L2_MEMORY_USERPTR;
2064    rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
2065    if (rc < 0) {
2066      LOGE("fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d, errno %d",
2067            my_obj->fd, rc, errno);
2068    }
2069
2070    LOGD("X rc = %d",rc);
2071    return rc;
2072}
2073
2074/*===========================================================================
2075 * FUNCTION   : mm_stream_need_wait_for_mapping
2076 *
2077 * DESCRIPTION: Utility function to determine whether to wait for mapping
2078 *
2079 * PARAMETERS :
2080 *   @my_obj       : stream object
2081 *
2082 * RETURN     : int8_t whether wait is necessary
2083 *              0  -- no wait
2084 *              1 -- wait
2085 *==========================================================================*/
2086int8_t mm_stream_need_wait_for_mapping(mm_stream_t * my_obj)
2087{
2088    uint32_t i;
2089    int8_t ret = 0;
2090
2091    for (i = my_obj->buf_idx; i < (my_obj->buf_idx + my_obj->buf_num); i++) {
2092        if ((my_obj->buf_status[i].map_status == 0)
2093                && (my_obj->buf_status[i].in_kernel)) {
2094            /*do not signal in case if any buffer is not mapped
2095              but queued to kernel.*/
2096            ret = 1;
2097        } else if (my_obj->buf_status[i].map_status < 0) {
2098            return 0;
2099        }
2100    }
2101
2102    return ret;
2103}
2104
2105/*===========================================================================
2106 * FUNCTION   : mm_stream_map_buf
2107 *
2108 * DESCRIPTION: mapping stream buffer via domain socket to server
2109 *
2110 * PARAMETERS :
2111 *   @my_obj       : stream object
2112 *   @buf_type     : type of buffer to be mapped. could be following values:
2113 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
2114 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
2115 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
2116 *   @frame_idx    : index of buffer within the stream buffers, only valid if
2117 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
2118 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
2119 *   @plane_idx    : plane index. If all planes share the same fd,
2120 *                   plane_idx = -1; otherwise, plean_idx is the
2121 *                   index to plane (0..num_of_planes)
2122 *   @fd           : file descriptor of the buffer
2123 *   @size         : size of the buffer
2124 *
2125 * RETURN     : int32_t type of status
2126 *              0  -- success
2127 *              -1 -- failure
2128 *==========================================================================*/
2129int32_t mm_stream_map_buf(mm_stream_t *my_obj,
2130        uint8_t buf_type, uint32_t frame_idx,
2131        int32_t plane_idx, int32_t fd,
2132        size_t size, void *buffer)
2133{
2134    int32_t rc = 0;
2135    if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
2136        LOGE("NULL obj of stream/channel/camera");
2137        return -1;
2138    }
2139
2140    cam_sock_packet_t packet;
2141    memset(&packet, 0, sizeof(cam_sock_packet_t));
2142    packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
2143    packet.payload.buf_map.type = buf_type;
2144    packet.payload.buf_map.fd = fd;
2145    packet.payload.buf_map.size = size;
2146    packet.payload.buf_map.stream_id = my_obj->server_stream_id;
2147    packet.payload.buf_map.frame_idx = frame_idx;
2148    packet.payload.buf_map.plane_idx = plane_idx;
2149    packet.payload.buf_map.buffer = buffer;
2150    LOGD("mapping buf_type %d, stream_id %d, frame_idx %d, fd %d, size %d",
2151             buf_type, my_obj->server_stream_id, frame_idx, fd, size);
2152
2153#ifdef DAEMON_PRESENT
2154    rc = mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
2155                                &packet, sizeof(cam_sock_packet_t), fd);
2156#else
2157    cam_shim_packet_t *shim_cmd;
2158    shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_REG_BUF,
2159            my_obj->ch_obj->cam_obj->sessionid, &packet);
2160    rc = mm_camera_module_send_cmd(shim_cmd);
2161    mm_camera_destroy_shim_cmd_packet(shim_cmd);
2162#endif
2163    if ((buf_type == CAM_MAPPING_BUF_TYPE_STREAM_BUF)
2164            || ((buf_type
2165            == CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF)
2166            && (my_obj->stream_info != NULL)
2167            && (my_obj->stream_info->streaming_mode
2168            == CAM_STREAMING_MODE_BATCH))) {
2169        pthread_mutex_lock(&my_obj->buf_lock);
2170        if (rc < 0) {
2171            my_obj->buf_status[frame_idx].map_status = -1;
2172            LOGE("fail status =%d", my_obj->buf_status[frame_idx].map_status);
2173        } else {
2174            my_obj->buf_status[frame_idx].map_status = 1;
2175        }
2176        if (mm_stream_need_wait_for_mapping(my_obj) == 0) {
2177            LOGD("Buffer mapping Done: Signal strm fd = %d",
2178                     my_obj->fd);
2179            pthread_cond_signal(&my_obj->buf_cond);
2180        }
2181        pthread_mutex_unlock(&my_obj->buf_lock);
2182    }
2183    return rc;
2184}
2185
2186/*===========================================================================
2187 * FUNCTION   : mm_stream_map_bufs
2188 *
2189 * DESCRIPTION: mapping stream buffers via domain socket to server
2190 *
2191 * PARAMETERS :
2192 *   @my_obj       : stream object
2193 *   @buf_map_list : list of buffer objects to map
2194 *
2195 * RETURN     : int32_t type of status
2196 *              0  -- success
2197 *              -1 -- failure
2198 *==========================================================================*/
2199
2200int32_t mm_stream_map_bufs(mm_stream_t * my_obj,
2201                           const cam_buf_map_type_list *buf_map_list)
2202{
2203    if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
2204        LOGE("NULL obj of stream/channel/camera");
2205        return -1;
2206    }
2207
2208    cam_sock_packet_t packet;
2209    memset(&packet, 0, sizeof(cam_sock_packet_t));
2210    packet.msg_type = CAM_MAPPING_TYPE_FD_BUNDLED_MAPPING;
2211
2212    memcpy(&packet.payload.buf_map_list, buf_map_list,
2213           sizeof(packet.payload.buf_map_list));
2214
2215    int sendfds[CAM_MAX_NUM_BUFS_PER_STREAM];
2216    uint32_t numbufs = packet.payload.buf_map_list.length;
2217    if (numbufs < 1) {
2218      LOGD("No buffers, suppressing the mapping command");
2219      return 0;
2220    }
2221
2222    uint32_t i;
2223    for (i = 0; i < numbufs; i++) {
2224        packet.payload.buf_map_list.buf_maps[i].stream_id = my_obj->server_stream_id;
2225        sendfds[i] = packet.payload.buf_map_list.buf_maps[i].fd;
2226    }
2227
2228    for (i = numbufs; i < CAM_MAX_NUM_BUFS_PER_STREAM; i++) {
2229        packet.payload.buf_map_list.buf_maps[i].fd = -1;
2230        sendfds[i] = -1;
2231    }
2232
2233#ifdef DAEMON_PRESENT
2234    int32_t ret = mm_camera_util_bundled_sendmsg(my_obj->ch_obj->cam_obj,
2235            &packet, sizeof(cam_sock_packet_t), sendfds, numbufs);
2236#else
2237    cam_shim_packet_t *shim_cmd;
2238    shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_REG_BUF,
2239            my_obj->ch_obj->cam_obj->sessionid, &packet);
2240    int32_t ret = mm_camera_module_send_cmd(shim_cmd);
2241    mm_camera_destroy_shim_cmd_packet(shim_cmd);
2242#endif
2243    if ((numbufs > 0) && ((buf_map_list->buf_maps[0].type
2244            == CAM_MAPPING_BUF_TYPE_STREAM_BUF)
2245            || ((buf_map_list->buf_maps[0].type ==
2246            CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF)
2247            && (my_obj->stream_info != NULL)
2248            && (my_obj->stream_info->streaming_mode
2249            == CAM_STREAMING_MODE_BATCH)))) {
2250        pthread_mutex_lock(&my_obj->buf_lock);
2251        for (i = 0; i < numbufs; i++) {
2252           if (ret < 0) {
2253               my_obj->buf_status[i].map_status = -1;
2254           } else {
2255               my_obj->buf_status[i].map_status = 1;
2256           }
2257        }
2258
2259        if (mm_stream_need_wait_for_mapping(my_obj) == 0) {
2260            LOGD("Buffer mapping Done: Signal strm fd = %d",
2261                     my_obj->fd);
2262            pthread_cond_signal(&my_obj->buf_cond);
2263        }
2264        pthread_mutex_unlock(&my_obj->buf_lock);
2265    }
2266    return ret;
2267}
2268
2269/*===========================================================================
2270 * FUNCTION   : mm_stream_unmap_buf
2271 *
2272 * DESCRIPTION: unmapping stream buffer via domain socket to server
2273 *
2274 * PARAMETERS :
2275 *   @my_obj       : stream object
2276 *   @buf_type     : type of buffer to be unmapped. could be following values:
2277 *                   CAM_MAPPING_BUF_TYPE_STREAM_BUF
2278 *                   CAM_MAPPING_BUF_TYPE_STREAM_INFO
2279 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
2280 *   @frame_idx    : index of buffer within the stream buffers, only valid if
2281 *                   buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
2282 *                   CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
2283 *   @plane_idx    : plane index. If all planes share the same fd,
2284 *                   plane_idx = -1; otherwise, plean_idx is the
2285 *                   index to plane (0..num_of_planes)
2286 *
2287 * RETURN     : int32_t type of status
2288 *              0  -- success
2289 *              -1 -- failure
2290 *==========================================================================*/
2291int32_t mm_stream_unmap_buf(mm_stream_t * my_obj,
2292                            uint8_t buf_type,
2293                            uint32_t frame_idx,
2294                            int32_t plane_idx)
2295{
2296    int32_t ret;
2297    if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) {
2298        LOGE("NULL obj of stream/channel/camera");
2299        return -1;
2300    }
2301    cam_sock_packet_t packet;
2302    memset(&packet, 0, sizeof(cam_sock_packet_t));
2303    packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
2304    packet.payload.buf_unmap.type = buf_type;
2305    packet.payload.buf_unmap.stream_id = my_obj->server_stream_id;
2306    packet.payload.buf_unmap.frame_idx = frame_idx;
2307    packet.payload.buf_unmap.plane_idx = plane_idx;
2308#ifdef DAEMON_PRESENT
2309    ret = mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
2310            &packet, sizeof(cam_sock_packet_t), -1);
2311#else
2312    cam_shim_packet_t *shim_cmd;
2313    shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_REG_BUF,
2314            my_obj->ch_obj->cam_obj->sessionid, &packet);
2315    ret = mm_camera_module_send_cmd(shim_cmd);
2316    mm_camera_destroy_shim_cmd_packet(shim_cmd);
2317#endif
2318    pthread_mutex_lock(&my_obj->buf_lock);
2319    my_obj->buf_status[frame_idx].map_status = 0;
2320    pthread_mutex_unlock(&my_obj->buf_lock);
2321    return ret;
2322}
2323
2324/*===========================================================================
2325 * FUNCTION   : mm_stream_init_bufs
2326 *
2327 * DESCRIPTION: initialize stream buffers needed. This function will request
2328 *              buffers needed from upper layer through the mem ops table passed
2329 *              during configuration stage.
2330 *
2331 * PARAMETERS :
2332 *   @my_obj  : stream object
2333 *
2334 * RETURN     : int32_t type of status
2335 *              0  -- success
2336 *              -1 -- failure
2337 *==========================================================================*/
2338int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
2339{
2340    int32_t i, rc = 0;
2341    uint8_t *reg_flags = NULL;
2342    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
2343          my_obj->my_hdl, my_obj->fd, my_obj->state);
2344
2345    /* deinit buf if it's not NULL*/
2346    if (NULL != my_obj->buf) {
2347        mm_stream_deinit_bufs(my_obj);
2348    }
2349
2350    if (!my_obj->is_res_shared) {
2351        rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset,
2352                &my_obj->total_buf_cnt, &reg_flags, &my_obj->buf,
2353                &my_obj->map_ops, my_obj->mem_vtbl.user_data);
2354        if (rc == 0) {
2355            for (i = 0; i < my_obj->total_buf_cnt; i++) {
2356                my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
2357            }
2358        }
2359    } else {
2360        rc = mm_camera_muxer_get_stream_bufs(my_obj);
2361    }
2362
2363    if (0 != rc) {
2364        LOGE("Error get buf, rc = %d\n", rc);
2365        return rc;
2366    }
2367
2368    LOGH("Buffer count = %d buf id = %d",my_obj->buf_num, my_obj->buf_idx);
2369    for (i = my_obj->buf_idx; i < (my_obj->buf_idx + my_obj->buf_num); i++) {
2370        my_obj->buf[i].stream_id = my_obj->my_hdl;
2371        my_obj->buf[i].stream_type = my_obj->stream_info->stream_type;
2372
2373        if (my_obj->buf[i].buf_type == CAM_STREAM_BUF_TYPE_USERPTR) {
2374            my_obj->buf[i].user_buf.bufs_used =
2375                    (int8_t)my_obj->stream_info->user_buf_info.frame_buf_cnt;
2376            if (reg_flags) {
2377                my_obj->buf[i].user_buf.buf_in_use = reg_flags[i];
2378            }
2379        }
2380    }
2381
2382    if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) {
2383        my_obj->plane_buf = my_obj->buf[0].user_buf.plane_buf;
2384        if (my_obj->plane_buf != NULL) {
2385            my_obj->plane_buf_num =
2386                    my_obj->buf_num *
2387                    my_obj->stream_info->user_buf_info.frame_buf_cnt;
2388            for (i = 0; i < my_obj->plane_buf_num; i++) {
2389                my_obj->plane_buf[i].stream_id = my_obj->my_hdl;
2390                my_obj->plane_buf[i].stream_type = my_obj->stream_info->stream_type;
2391            }
2392        }
2393        my_obj->cur_bufs_staged = 0;
2394        my_obj->cur_buf_idx = -1;
2395    }
2396
2397    free(reg_flags);
2398    reg_flags = NULL;
2399
2400    /* update in stream info about number of stream buffers */
2401    my_obj->stream_info->num_bufs = my_obj->total_buf_cnt;
2402
2403    return rc;
2404}
2405
2406/*===========================================================================
2407 * FUNCTION   : mm_stream_deinit_bufs
2408 *
2409 * DESCRIPTION: return stream buffers to upper layer through the mem ops table
2410 *              passed during configuration stage.
2411 *
2412 * PARAMETERS :
2413 *   @my_obj  : stream object
2414 *
2415 * RETURN     : int32_t type of status
2416 *              0  -- success
2417 *              -1 -- failure
2418 *==========================================================================*/
2419int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
2420{
2421    int32_t rc = 0;
2422    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
2423          my_obj->my_hdl, my_obj->fd, my_obj->state);
2424
2425    if (NULL == my_obj->buf) {
2426        LOGD("Buf is NULL, no need to deinit");
2427        return rc;
2428    }
2429
2430    if ((!my_obj->is_res_shared) &&
2431            (my_obj->mem_vtbl.put_bufs != NULL)) {
2432        rc = my_obj->mem_vtbl.put_bufs(&my_obj->map_ops,
2433                my_obj->mem_vtbl.user_data);
2434        if (my_obj->plane_buf != NULL) {
2435            free(my_obj->plane_buf);
2436            my_obj->plane_buf = NULL;
2437        }
2438
2439        free(my_obj->buf);
2440        my_obj->buf = NULL;
2441    } else {
2442        rc = mm_camera_muxer_put_stream_bufs(my_obj);
2443    }
2444
2445    return rc;
2446}
2447
2448/*===========================================================================
2449 * FUNCTION   : mm_stream_reg_buf
2450 *
2451 * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for
2452 *              each buffer in the stream
2453 *
2454 * PARAMETERS :
2455 *   @my_obj  : stream object
2456 *
2457 * RETURN     : int32_t type of status
2458 *              0  -- success
2459 *              -1 -- failure
2460 *==========================================================================*/
2461int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
2462{
2463    int32_t rc = 0;
2464    uint8_t i;
2465    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
2466          my_obj->my_hdl, my_obj->fd, my_obj->state);
2467
2468    rc = mm_stream_request_buf(my_obj);
2469    if (rc != 0) {
2470        return rc;
2471    }
2472
2473    my_obj->queued_buffer_count = 0;
2474    for(i = my_obj->buf_idx; i < (my_obj->buf_idx + my_obj->buf_num); i++){
2475        /* check if need to qbuf initially */
2476        if (my_obj->buf_status[i].initial_reg_flag) {
2477            rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
2478            if (rc != 0) {
2479                LOGE("VIDIOC_QBUF rc = %d\n", rc);
2480                break;
2481            }
2482            my_obj->buf_status[i].buf_refcnt = 0;
2483            my_obj->buf_status[i].in_kernel = 1;
2484        } else {
2485            /* the buf is held by upper layer, will not queue into kernel.
2486             * add buf reference count */
2487            my_obj->buf_status[i].buf_refcnt = 1;
2488            my_obj->buf_status[i].in_kernel = 0;
2489        }
2490    }
2491
2492    return rc;
2493}
2494
2495/*===========================================================================
2496 * FUNCTION   : mm_stream_unreg buf
2497 *
2498 * DESCRIPTION: unregister all stream buffers from kernel
2499 *
2500 * PARAMETERS :
2501 *   @my_obj  : stream object
2502 *
2503 * RETURN     : int32_t type of status
2504 *              0  -- success
2505 *              -1 -- failure
2506 *==========================================================================*/
2507int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
2508{
2509    struct v4l2_requestbuffers bufreq;
2510    int32_t i, rc = 0;
2511    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
2512          my_obj->my_hdl, my_obj->fd, my_obj->state);
2513
2514    /* unreg buf to kernel */
2515    bufreq.count = 0;
2516    bufreq.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2517    bufreq.memory = V4L2_MEMORY_USERPTR;
2518    rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
2519    if (rc < 0) {
2520        LOGE("fd=%d, VIDIOC_REQBUFS failed, rc=%d, errno %d",
2521               my_obj->fd, rc, errno);
2522    }
2523
2524    /* reset buf reference count */
2525    pthread_mutex_lock(&my_obj->buf_lock);
2526    for(i = my_obj->buf_idx; i < (my_obj->buf_idx + my_obj->buf_num); i++){
2527        my_obj->buf_status[i].buf_refcnt = 0;
2528        my_obj->buf_status[i].in_kernel = 0;
2529    }
2530    pthread_mutex_unlock(&my_obj->buf_lock);
2531
2532    return rc;
2533}
2534
2535/*===========================================================================
2536 * FUNCTION   : mm_stream_get_v4l2_fmt
2537 *
2538 * DESCRIPTION: translate camera image format into FOURCC code
2539 *
2540 * PARAMETERS :
2541 *   @fmt     : camera image format
2542 *
2543 * RETURN     : FOURCC code for image format
2544 *==========================================================================*/
2545uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt)
2546{
2547    uint32_t val = 0;
2548    switch(fmt) {
2549    case CAM_FORMAT_YUV_420_NV12:
2550    case CAM_FORMAT_YUV_420_NV12_VENUS:
2551    case CAM_FORMAT_YUV_420_NV12_UBWC:
2552        val = V4L2_PIX_FMT_NV12;
2553        break;
2554    case CAM_FORMAT_YUV_420_NV21:
2555    case CAM_FORMAT_YUV_420_NV21_VENUS:
2556        val = V4L2_PIX_FMT_NV21;
2557        break;
2558    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
2559    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG:
2560        val= V4L2_PIX_FMT_SGBRG10;
2561        break;
2562    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
2563    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG:
2564        val= V4L2_PIX_FMT_SGRBG10;
2565        break;
2566    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
2567    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB:
2568        val= V4L2_PIX_FMT_SRGGB10;
2569        break;
2570    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
2571    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR:
2572        val= V4L2_PIX_FMT_SBGGR10;
2573        break;
2574    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG:
2575    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG:
2576        val= V4L2_PIX_FMT_SGBRG12;
2577        break;
2578    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG:
2579    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG:
2580        val= V4L2_PIX_FMT_SGRBG12;
2581        break;
2582    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB:
2583    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB:
2584        val= V4L2_PIX_FMT_SRGGB12;
2585        break;
2586    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR:
2587    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR:
2588        val = V4L2_PIX_FMT_SBGGR12;
2589        break;
2590    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GBRG:
2591    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GBRG:
2592        val= V4L2_PIX_FMT_SGBRG14;
2593        break;
2594    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GRBG:
2595    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GRBG:
2596        val= V4L2_PIX_FMT_SGRBG14;
2597        break;
2598    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_RGGB:
2599    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_RGGB:
2600        val= V4L2_PIX_FMT_SRGGB14;
2601        break;
2602    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_BGGR:
2603    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_BGGR:
2604        val = V4L2_PIX_FMT_SBGGR14;
2605        break;
2606    case CAM_FORMAT_YUV_422_NV61:
2607        val= V4L2_PIX_FMT_NV61;
2608        break;
2609    case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
2610        val= V4L2_PIX_FMT_YUYV;
2611        break;
2612    case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
2613        val= V4L2_PIX_FMT_YVYU;
2614        break;
2615    case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
2616        val= V4L2_PIX_FMT_UYVY;
2617        break;
2618    case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
2619        val= V4L2_PIX_FMT_VYUY;
2620        break;
2621    case CAM_FORMAT_YUV_420_YV12:
2622        val= V4L2_PIX_FMT_NV12;
2623        break;
2624    case CAM_FORMAT_YUV_422_NV16:
2625        val= V4L2_PIX_FMT_NV16;
2626        break;
2627    case CAM_FORMAT_Y_ONLY:
2628        val= V4L2_PIX_FMT_GREY;
2629        break;
2630    case CAM_FORMAT_Y_ONLY_10_BPP:
2631        val= V4L2_PIX_FMT_Y10;
2632        break;
2633    case CAM_FORMAT_Y_ONLY_12_BPP:
2634        val= V4L2_PIX_FMT_Y12;
2635        break;
2636    case CAM_FORMAT_META_RAW_10BIT:
2637        val = V4L2_PIX_FMT_META10;
2638        break;
2639    case CAM_FORMAT_Y_ONLY_14_BPP:
2640        /* No v4l2 format is defined yet for CAM_FORMAT_Y_ONLY_14_BPP */
2641        /* val= V4L2_PIX_FMT_Y14; */
2642        val = 0;
2643        LOGE("Unknown fmt=%d", fmt);
2644        break;
2645    case CAM_FORMAT_MAX:
2646        /* CAM_STREAM_TYPE_DEFAULT,
2647         * CAM_STREAM_TYPE_OFFLINE_PROC,
2648         * and CAM_STREAM_TYPE_METADATA
2649         * set fmt to CAM_FORMAT_MAX*/
2650        val = 0;
2651        break;
2652    default:
2653        val = 0;
2654        LOGE("Unknown fmt=%d", fmt);
2655        break;
2656    }
2657    LOGD("fmt=%d, val =%d", fmt, val);
2658    return val;
2659}
2660
2661/*===========================================================================
2662 * FUNCTION   : mm_stream_calc_offset_preview
2663 *
2664 * DESCRIPTION: calculate preview frame offset based on format and
2665 *              padding information
2666 *
2667 * PARAMETERS :
2668 *   @fmt     : image format
2669 *   @dim     : image dimension
2670 *   @buf_planes : [out] buffer plane information
2671 *
2672 * RETURN     : int32_t type of status
2673 *              0  -- success
2674 *              -1 -- failure
2675 *==========================================================================*/
2676int32_t mm_stream_calc_offset_preview(cam_stream_info_t *stream_info,
2677                                      cam_dimension_t *dim,
2678                                      cam_padding_info_t *padding,
2679                                      cam_stream_buf_plane_info_t *buf_planes)
2680{
2681    int32_t rc = 0;
2682    int stride = 0, scanline = 0;
2683
2684    uint32_t width_padding = 0;
2685    uint32_t height_padding = 0;
2686
2687    switch (stream_info->fmt) {
2688    case CAM_FORMAT_YUV_420_NV12:
2689    case CAM_FORMAT_YUV_420_NV21:
2690    case CAM_FORMAT_Y_ONLY:
2691    case CAM_FORMAT_Y_ONLY_10_BPP:
2692    case CAM_FORMAT_Y_ONLY_12_BPP:
2693    case CAM_FORMAT_Y_ONLY_14_BPP:
2694        /* 2 planes: Y + CbCr */
2695        buf_planes->plane_info.num_planes = 2;
2696
2697        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2698            width_padding =  padding->width_padding;
2699            height_padding = CAM_PAD_TO_2;
2700        } else {
2701            width_padding =  padding->width_padding;
2702            height_padding = padding->height_padding;
2703        }
2704
2705        stride = PAD_TO_SIZE(dim->width, width_padding);
2706        scanline = PAD_TO_SIZE(dim->height, height_padding);
2707
2708        buf_planes->plane_info.mp[0].offset = 0;
2709        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2710        buf_planes->plane_info.mp[0].offset_x = 0;
2711        buf_planes->plane_info.mp[0].offset_y = 0;
2712        buf_planes->plane_info.mp[0].stride = stride;
2713        buf_planes->plane_info.mp[0].scanline = scanline;
2714        buf_planes->plane_info.mp[0].width = dim->width;
2715        buf_planes->plane_info.mp[0].height = dim->height;
2716
2717        stride = PAD_TO_SIZE(dim->width, width_padding);
2718        scanline = PAD_TO_SIZE(dim->height / 2, height_padding);
2719        buf_planes->plane_info.mp[1].offset = 0;
2720        buf_planes->plane_info.mp[1].len =
2721            (uint32_t)(stride * scanline);
2722        buf_planes->plane_info.mp[1].offset_x = 0;
2723        buf_planes->plane_info.mp[1].offset_y = 0;
2724        buf_planes->plane_info.mp[1].stride = stride;
2725        buf_planes->plane_info.mp[1].scanline = scanline;
2726        buf_planes->plane_info.mp[1].width = dim->width;
2727        buf_planes->plane_info.mp[1].height = dim->height / 2;
2728
2729        buf_planes->plane_info.frame_len =
2730                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2731                        buf_planes->plane_info.mp[1].len,
2732                        CAM_PAD_TO_4K);
2733        break;
2734    case CAM_FORMAT_YUV_420_NV21_ADRENO:
2735        /* 2 planes: Y + CbCr */
2736        buf_planes->plane_info.num_planes = 2;
2737
2738        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2739            stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
2740            scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
2741        } else {
2742            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
2743            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
2744        }
2745        buf_planes->plane_info.mp[0].offset = 0;
2746        buf_planes->plane_info.mp[0].len =
2747                PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
2748        buf_planes->plane_info.mp[0].offset_x = 0;
2749        buf_planes->plane_info.mp[0].offset_y = 0;
2750        buf_planes->plane_info.mp[0].stride = stride;
2751        buf_planes->plane_info.mp[0].scanline = scanline;
2752        buf_planes->plane_info.mp[0].width = dim->width;
2753        buf_planes->plane_info.mp[0].height = dim->height;
2754
2755        stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
2756        scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
2757        buf_planes->plane_info.mp[1].offset = 0;
2758        buf_planes->plane_info.mp[1].len =
2759                PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
2760        buf_planes->plane_info.mp[1].offset_x = 0;
2761        buf_planes->plane_info.mp[1].offset_y = 0;
2762        buf_planes->plane_info.mp[1].stride = stride;
2763        buf_planes->plane_info.mp[1].scanline = scanline;
2764        buf_planes->plane_info.mp[1].width = dim->width;
2765        buf_planes->plane_info.mp[1].height = dim->height / 2;
2766
2767        buf_planes->plane_info.frame_len =
2768                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2769                        buf_planes->plane_info.mp[1].len,
2770                        CAM_PAD_TO_4K);
2771        break;
2772    case CAM_FORMAT_YUV_420_YV12:
2773        /* 3 planes: Y + Cr + Cb */
2774        buf_planes->plane_info.num_planes = 3;
2775
2776        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2777            stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2778            scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
2779        } else {
2780            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
2781            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
2782        }
2783        buf_planes->plane_info.mp[0].offset = 0;
2784        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2785        buf_planes->plane_info.mp[0].offset_x = 0;
2786        buf_planes->plane_info.mp[0].offset_y = 0;
2787        buf_planes->plane_info.mp[0].stride = stride;
2788        buf_planes->plane_info.mp[0].scanline = scanline;
2789        buf_planes->plane_info.mp[0].width = dim->width;
2790        buf_planes->plane_info.mp[0].height = dim->height;
2791
2792        stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
2793        scanline = scanline / 2;
2794        buf_planes->plane_info.mp[1].offset = 0;
2795        buf_planes->plane_info.mp[1].len =
2796            (uint32_t)(stride * scanline);
2797        buf_planes->plane_info.mp[1].offset_x = 0;
2798        buf_planes->plane_info.mp[1].offset_y = 0;
2799        buf_planes->plane_info.mp[1].stride = stride;
2800        buf_planes->plane_info.mp[1].scanline = scanline;
2801        buf_planes->plane_info.mp[1].width = dim->width / 2;
2802        buf_planes->plane_info.mp[1].height = dim->height / 2;
2803
2804        buf_planes->plane_info.mp[2].offset = 0;
2805        buf_planes->plane_info.mp[2].len =
2806            (uint32_t)(stride * scanline);
2807        buf_planes->plane_info.mp[2].offset_x = 0;
2808        buf_planes->plane_info.mp[2].offset_y = 0;
2809        buf_planes->plane_info.mp[2].stride = stride;
2810        buf_planes->plane_info.mp[2].scanline = scanline;
2811        buf_planes->plane_info.mp[2].width = dim->width / 2;
2812        buf_planes->plane_info.mp[2].height = dim->height / 2;
2813
2814        buf_planes->plane_info.frame_len =
2815                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2816                        buf_planes->plane_info.mp[1].len +
2817                        buf_planes->plane_info.mp[2].len,
2818                        CAM_PAD_TO_4K);
2819        break;
2820    case CAM_FORMAT_YUV_422_NV16:
2821    case CAM_FORMAT_YUV_422_NV61:
2822        /* 2 planes: Y + CbCr */
2823        buf_planes->plane_info.num_planes = 2;
2824
2825        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2826            stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
2827            scanline = dim->height;
2828        } else {
2829            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
2830            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
2831        }
2832        buf_planes->plane_info.mp[0].offset = 0;
2833        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2834        buf_planes->plane_info.mp[0].offset_x = 0;
2835        buf_planes->plane_info.mp[0].offset_y = 0;
2836        buf_planes->plane_info.mp[0].stride = stride;
2837        buf_planes->plane_info.mp[0].scanline = scanline;
2838        buf_planes->plane_info.mp[0].width = dim->width;
2839        buf_planes->plane_info.mp[0].height = dim->height;
2840
2841        buf_planes->plane_info.mp[1].offset = 0;
2842        buf_planes->plane_info.mp[1].len = (uint32_t)(stride * scanline);
2843        buf_planes->plane_info.mp[1].offset_x = 0;
2844        buf_planes->plane_info.mp[1].offset_y = 0;
2845        buf_planes->plane_info.mp[1].stride = stride;
2846        buf_planes->plane_info.mp[1].scanline = scanline;
2847        buf_planes->plane_info.mp[1].width = dim->width;
2848        buf_planes->plane_info.mp[1].height = dim->height;
2849
2850        buf_planes->plane_info.frame_len =
2851                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
2852                        buf_planes->plane_info.mp[1].len,
2853                        CAM_PAD_TO_4K);
2854        break;
2855    case CAM_FORMAT_YUV_420_NV12_VENUS:
2856#ifdef VENUS_PRESENT
2857        // using Venus
2858        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2859            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
2860            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
2861        } else {
2862            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
2863            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
2864        }
2865        buf_planes->plane_info.frame_len =
2866                VENUS_BUFFER_SIZE(COLOR_FMT_NV12, stride, scanline);
2867        buf_planes->plane_info.num_planes = 2;
2868        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2869        buf_planes->plane_info.mp[0].offset = 0;
2870        buf_planes->plane_info.mp[0].offset_x =0;
2871        buf_planes->plane_info.mp[0].offset_y = 0;
2872        buf_planes->plane_info.mp[0].stride = stride;
2873        buf_planes->plane_info.mp[0].scanline = scanline;
2874        buf_planes->plane_info.mp[0].width = dim->width;
2875        buf_planes->plane_info.mp[0].height = dim->height;
2876        buf_planes->plane_info.mp[0].meta_stride = 0;
2877        buf_planes->plane_info.mp[0].meta_scanline = 0;
2878        buf_planes->plane_info.mp[0].meta_len = 0;
2879        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2880            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
2881            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
2882        } else {
2883            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
2884            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
2885        }
2886        buf_planes->plane_info.mp[1].len =
2887                buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2888        buf_planes->plane_info.mp[1].offset = 0;
2889        buf_planes->plane_info.mp[1].offset_x =0;
2890        buf_planes->plane_info.mp[1].offset_y = 0;
2891        buf_planes->plane_info.mp[1].stride = stride;
2892        buf_planes->plane_info.mp[1].scanline = scanline;
2893        buf_planes->plane_info.mp[1].width = dim->width;
2894        buf_planes->plane_info.mp[1].height = dim->height / 2;
2895        buf_planes->plane_info.mp[1].meta_stride = 0;
2896        buf_planes->plane_info.mp[1].meta_scanline = 0;
2897        buf_planes->plane_info.mp[1].meta_len = 0;
2898#else
2899        LOGE("Venus hardware not avail, cannot use this format");
2900        rc = -1;
2901#endif
2902        break;
2903    case CAM_FORMAT_YUV_420_NV21_VENUS:
2904#ifdef VENUS_PRESENT
2905        // using Venus
2906        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2907            stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width);
2908            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height);
2909        } else {
2910            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
2911            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
2912        }
2913        buf_planes->plane_info.frame_len =
2914                VENUS_BUFFER_SIZE(COLOR_FMT_NV21, stride, scanline);
2915        buf_planes->plane_info.num_planes = 2;
2916        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
2917        buf_planes->plane_info.mp[0].offset = 0;
2918        buf_planes->plane_info.mp[0].offset_x =0;
2919        buf_planes->plane_info.mp[0].offset_y = 0;
2920        buf_planes->plane_info.mp[0].stride = stride;
2921        buf_planes->plane_info.mp[0].scanline = scanline;
2922        buf_planes->plane_info.mp[0].width = dim->width;
2923        buf_planes->plane_info.mp[0].height = dim->height;
2924        buf_planes->plane_info.mp[0].meta_stride = 0;
2925        buf_planes->plane_info.mp[0].meta_scanline = 0;
2926        buf_planes->plane_info.mp[0].meta_len = 0;
2927        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2928            stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width);
2929            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height);
2930        } else {
2931            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
2932            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
2933        }
2934        buf_planes->plane_info.mp[1].len =
2935                buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
2936        buf_planes->plane_info.mp[1].offset = 0;
2937        buf_planes->plane_info.mp[1].offset_x =0;
2938        buf_planes->plane_info.mp[1].offset_y = 0;
2939        buf_planes->plane_info.mp[1].stride = stride;
2940        buf_planes->plane_info.mp[1].scanline = scanline;
2941        buf_planes->plane_info.mp[1].width = dim->width;
2942        buf_planes->plane_info.mp[1].height = dim->height / 2;
2943        buf_planes->plane_info.mp[1].meta_stride = 0;
2944        buf_planes->plane_info.mp[1].meta_scanline = 0;
2945        buf_planes->plane_info.mp[1].meta_len = 0;
2946#else
2947        LOGE("Venus hardware not avail, cannot use this format");
2948        rc = -1;
2949#endif
2950        break;
2951    case CAM_FORMAT_YUV_420_NV12_UBWC:
2952#ifdef UBWC_PRESENT
2953        {
2954            int meta_stride = 0,meta_scanline = 0;
2955            // using UBWC
2956            if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
2957                stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
2958                scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
2959            } else {
2960                stride = PAD_TO_SIZE(dim->width, padding->width_padding);
2961                scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
2962            }
2963            meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
2964            meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
2965
2966            buf_planes->plane_info.frame_len =
2967                    VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, stride, scanline);
2968            buf_planes->plane_info.num_planes = 2;
2969            buf_planes->plane_info.mp[0].offset = 0;
2970            buf_planes->plane_info.mp[0].offset_x =0;
2971            buf_planes->plane_info.mp[0].offset_y = 0;
2972            buf_planes->plane_info.mp[0].stride = stride;
2973            buf_planes->plane_info.mp[0].scanline = scanline;
2974            buf_planes->plane_info.mp[0].width = dim->width;
2975            buf_planes->plane_info.mp[0].height = dim->height;
2976            buf_planes->plane_info.mp[0].meta_stride = meta_stride;
2977            buf_planes->plane_info.mp[0].meta_scanline = meta_scanline;
2978            buf_planes->plane_info.mp[0].meta_len =
2979                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
2980            buf_planes->plane_info.mp[0].len =
2981                    (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) +
2982                    (buf_planes->plane_info.mp[0].meta_len));
2983
2984            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
2985            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
2986            meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
2987            meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
2988            buf_planes->plane_info.mp[1].offset = 0;
2989            buf_planes->plane_info.mp[1].offset_x =0;
2990            buf_planes->plane_info.mp[1].offset_y = 0;
2991            buf_planes->plane_info.mp[1].stride = stride;
2992            buf_planes->plane_info.mp[1].scanline = scanline;
2993            buf_planes->plane_info.mp[1].width = dim->width;
2994            buf_planes->plane_info.mp[1].height = dim->height/2;
2995            buf_planes->plane_info.mp[1].meta_stride = meta_stride;
2996            buf_planes->plane_info.mp[1].meta_scanline = meta_scanline;
2997            buf_planes->plane_info.mp[1].meta_len =
2998                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
2999            buf_planes->plane_info.mp[1].len =
3000                    buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
3001        }
3002#else
3003        LOGE("UBWC hardware not avail, cannot use this format");
3004        rc = -1;
3005#endif
3006        break;
3007
3008    default:
3009        LOGE("Invalid cam_format for preview %d",
3010                    stream_info->fmt);
3011        rc = -1;
3012        break;
3013    }
3014
3015    return rc;
3016}
3017/*===========================================================================
3018 * FUNCTION   : mm_stream_calc_offset_post_view
3019 *
3020 * DESCRIPTION: calculate postview frame offset based on format and
3021 *              padding information
3022 *
3023 * PARAMETERS :
3024 *   @stream_info  : Stream information
3025 *   @dim     : image dimension
3026 *   @padding : Padding info
3027 *   @buf_planes : [out] buffer plane information
3028 *
3029 * RETURN     : int32_t type of status
3030 *              0  -- success
3031 *              -1 -- failure
3032 *==========================================================================*/
3033int32_t mm_stream_calc_offset_post_view(cam_stream_info_t *stream_info,
3034                                      cam_dimension_t *dim,
3035                                      cam_padding_info_t *padding,
3036                                      cam_stream_buf_plane_info_t *buf_planes)
3037{
3038    int32_t rc = 0;
3039    int stride = 0, scanline = 0;
3040
3041    uint32_t width_padding = 0;
3042    uint32_t height_padding = 0;
3043
3044    switch (stream_info->fmt) {
3045    case CAM_FORMAT_YUV_420_NV12:
3046    case CAM_FORMAT_YUV_420_NV21:
3047    case CAM_FORMAT_Y_ONLY:
3048    case CAM_FORMAT_Y_ONLY_10_BPP:
3049    case CAM_FORMAT_Y_ONLY_12_BPP:
3050    case CAM_FORMAT_Y_ONLY_14_BPP:
3051        /* 2 planes: Y + CbCr */
3052        buf_planes->plane_info.num_planes = 2;
3053
3054        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3055            width_padding =  padding->width_padding;
3056            height_padding = CAM_PAD_TO_2;
3057        } else {
3058            width_padding =  padding->width_padding;
3059            height_padding = padding->height_padding;
3060        }
3061
3062        stride = PAD_TO_SIZE(dim->width, width_padding);
3063        scanline = PAD_TO_SIZE(dim->height, height_padding);
3064        buf_planes->plane_info.mp[0].offset = 0;
3065        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
3066        buf_planes->plane_info.mp[0].offset_x = 0;
3067        buf_planes->plane_info.mp[0].offset_y = 0;
3068        buf_planes->plane_info.mp[0].stride = stride;
3069        buf_planes->plane_info.mp[0].scanline = scanline;
3070        buf_planes->plane_info.mp[0].width = dim->width;
3071        buf_planes->plane_info.mp[0].height = dim->height;
3072
3073        stride = PAD_TO_SIZE(dim->width, width_padding);
3074        scanline = PAD_TO_SIZE(dim->height / 2, height_padding);
3075        buf_planes->plane_info.mp[1].offset = 0;
3076        buf_planes->plane_info.mp[1].len =
3077            (uint32_t)(stride * scanline);
3078        buf_planes->plane_info.mp[1].offset_x = 0;
3079        buf_planes->plane_info.mp[1].offset_y = 0;
3080        buf_planes->plane_info.mp[1].stride = stride;
3081        buf_planes->plane_info.mp[1].scanline = scanline;
3082        buf_planes->plane_info.mp[1].width = dim->width;
3083        buf_planes->plane_info.mp[1].height = dim->height / 2;
3084
3085        buf_planes->plane_info.frame_len =
3086                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3087                        buf_planes->plane_info.mp[1].len,
3088                        CAM_PAD_TO_4K);
3089        break;
3090    case CAM_FORMAT_YUV_420_NV21_ADRENO:
3091        /* 2 planes: Y + CbCr */
3092        buf_planes->plane_info.num_planes = 2;
3093
3094        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3095            width_padding =  CAM_PAD_TO_32;
3096            height_padding = CAM_PAD_TO_32;
3097        } else {
3098            width_padding =  padding->width_padding;
3099            height_padding = padding->height_padding;
3100        }
3101
3102        stride = PAD_TO_SIZE(dim->width, width_padding);
3103        scanline = PAD_TO_SIZE(dim->height, height_padding);
3104        buf_planes->plane_info.mp[0].offset = 0;
3105        buf_planes->plane_info.mp[0].len =
3106                PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
3107        buf_planes->plane_info.mp[0].offset_x = 0;
3108        buf_planes->plane_info.mp[0].offset_y = 0;
3109        buf_planes->plane_info.mp[0].stride = stride;
3110        buf_planes->plane_info.mp[0].scanline = scanline;
3111        buf_planes->plane_info.mp[0].width = dim->width;
3112        buf_planes->plane_info.mp[0].height = dim->height;
3113
3114        stride = PAD_TO_SIZE(dim->width / 2, width_padding) * 2;
3115        scanline = PAD_TO_SIZE(dim->height / 2, height_padding);
3116        buf_planes->plane_info.mp[1].offset = 0;
3117        buf_planes->plane_info.mp[1].len =
3118                PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
3119        buf_planes->plane_info.mp[1].offset_x = 0;
3120        buf_planes->plane_info.mp[1].offset_y = 0;
3121        buf_planes->plane_info.mp[1].stride = stride;
3122        buf_planes->plane_info.mp[1].scanline = scanline;
3123        buf_planes->plane_info.mp[1].width = dim->width;
3124        buf_planes->plane_info.mp[1].height = dim->height / 2;
3125
3126        buf_planes->plane_info.frame_len =
3127                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3128                        buf_planes->plane_info.mp[1].len,
3129                        CAM_PAD_TO_4K);
3130        break;
3131    case CAM_FORMAT_YUV_420_YV12:
3132        /* 3 planes: Y + Cr + Cb */
3133        buf_planes->plane_info.num_planes = 3;
3134
3135        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3136            width_padding =  CAM_PAD_TO_16;
3137            height_padding = CAM_PAD_TO_2;
3138        } else {
3139            width_padding =  padding->width_padding;
3140            height_padding = padding->height_padding;
3141        }
3142
3143        stride = PAD_TO_SIZE(dim->width, width_padding);
3144        scanline = PAD_TO_SIZE(dim->height, height_padding);
3145        buf_planes->plane_info.mp[0].offset = 0;
3146        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
3147        buf_planes->plane_info.mp[0].offset_x = 0;
3148        buf_planes->plane_info.mp[0].offset_y = 0;
3149        buf_planes->plane_info.mp[0].stride = stride;
3150        buf_planes->plane_info.mp[0].scanline = scanline;
3151        buf_planes->plane_info.mp[0].width = dim->width;
3152        buf_planes->plane_info.mp[0].height = dim->height;
3153
3154        stride = PAD_TO_SIZE(stride / 2, width_padding);
3155        scanline = PAD_TO_SIZE(stride / 2, height_padding);
3156        buf_planes->plane_info.mp[1].offset = 0;
3157        buf_planes->plane_info.mp[1].len =
3158            (uint32_t)(stride * scanline);
3159        buf_planes->plane_info.mp[1].offset_x = 0;
3160        buf_planes->plane_info.mp[1].offset_y = 0;
3161        buf_planes->plane_info.mp[1].stride = stride;
3162        buf_planes->plane_info.mp[1].scanline = scanline;
3163        buf_planes->plane_info.mp[1].width = dim->width / 2;
3164        buf_planes->plane_info.mp[1].height = dim->height / 2;
3165
3166        buf_planes->plane_info.mp[2].offset = 0;
3167        buf_planes->plane_info.mp[2].len =
3168            (uint32_t)(stride * scanline);
3169        buf_planes->plane_info.mp[2].offset_x = 0;
3170        buf_planes->plane_info.mp[2].offset_y = 0;
3171        buf_planes->plane_info.mp[2].stride = stride;
3172        buf_planes->plane_info.mp[2].scanline = scanline;
3173        buf_planes->plane_info.mp[2].width = dim->width / 2;
3174        buf_planes->plane_info.mp[2].height = dim->height / 2;
3175
3176        buf_planes->plane_info.frame_len =
3177                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3178                        buf_planes->plane_info.mp[1].len +
3179                        buf_planes->plane_info.mp[2].len,
3180                        CAM_PAD_TO_4K);
3181        break;
3182    case CAM_FORMAT_YUV_422_NV16:
3183    case CAM_FORMAT_YUV_422_NV61:
3184        /* 2 planes: Y + CbCr */
3185        buf_planes->plane_info.num_planes = 2;
3186
3187        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3188            stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
3189            scanline = dim->height;
3190        } else {
3191            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
3192            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
3193        }
3194        buf_planes->plane_info.mp[0].offset = 0;
3195        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
3196        buf_planes->plane_info.mp[0].offset_x = 0;
3197        buf_planes->plane_info.mp[0].offset_y = 0;
3198        buf_planes->plane_info.mp[0].stride = stride;
3199        buf_planes->plane_info.mp[0].scanline = scanline;
3200        buf_planes->plane_info.mp[0].width = dim->width;
3201        buf_planes->plane_info.mp[0].height = dim->height;
3202
3203        buf_planes->plane_info.mp[1].offset = 0;
3204        buf_planes->plane_info.mp[1].len = (uint32_t)(stride * scanline);
3205        buf_planes->plane_info.mp[1].offset_x = 0;
3206        buf_planes->plane_info.mp[1].offset_y = 0;
3207        buf_planes->plane_info.mp[1].stride = stride;
3208        buf_planes->plane_info.mp[1].scanline = scanline;
3209        buf_planes->plane_info.mp[1].width = dim->width;
3210        buf_planes->plane_info.mp[1].height = dim->height;
3211
3212        buf_planes->plane_info.frame_len =
3213                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3214                        buf_planes->plane_info.mp[1].len,
3215                        CAM_PAD_TO_4K);
3216        break;
3217    case CAM_FORMAT_YUV_420_NV12_VENUS:
3218#ifdef VENUS_PRESENT
3219        // using Venus
3220        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3221            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
3222            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
3223        } else {
3224            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
3225            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
3226        }
3227
3228        buf_planes->plane_info.frame_len =
3229            VENUS_BUFFER_SIZE(COLOR_FMT_NV12, stride, scanline);
3230        buf_planes->plane_info.num_planes = 2;
3231        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
3232        buf_planes->plane_info.mp[0].offset = 0;
3233        buf_planes->plane_info.mp[0].offset_x =0;
3234        buf_planes->plane_info.mp[0].offset_y = 0;
3235        buf_planes->plane_info.mp[0].stride = stride;
3236        buf_planes->plane_info.mp[0].scanline = scanline;
3237        buf_planes->plane_info.mp[0].width = dim->width;
3238        buf_planes->plane_info.mp[0].height = dim->height;
3239        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3240            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
3241            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
3242        } else {
3243            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
3244            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
3245        }
3246        buf_planes->plane_info.mp[1].len =
3247            buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
3248        buf_planes->plane_info.mp[1].offset = 0;
3249        buf_planes->plane_info.mp[1].offset_x =0;
3250        buf_planes->plane_info.mp[1].offset_y = 0;
3251        buf_planes->plane_info.mp[1].stride = stride;
3252        buf_planes->plane_info.mp[1].scanline = scanline;
3253        buf_planes->plane_info.mp[1].width = dim->width;
3254        buf_planes->plane_info.mp[1].height = dim->height / 2;
3255#else
3256        LOGE("Venus hardware not avail, cannot use this format");
3257        rc = -1;
3258#endif
3259        break;
3260    case CAM_FORMAT_YUV_420_NV21_VENUS:
3261#ifdef VENUS_PRESENT
3262        // using Venus
3263        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3264            stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width);
3265            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height);
3266        } else {
3267            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
3268            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
3269        }
3270        buf_planes->plane_info.frame_len =
3271                VENUS_BUFFER_SIZE(COLOR_FMT_NV21, dim->width, dim->height);
3272        buf_planes->plane_info.num_planes = 2;
3273        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
3274        buf_planes->plane_info.mp[0].offset = 0;
3275        buf_planes->plane_info.mp[0].offset_x =0;
3276        buf_planes->plane_info.mp[0].offset_y = 0;
3277        buf_planes->plane_info.mp[0].stride = stride;
3278        buf_planes->plane_info.mp[0].scanline = scanline;
3279        buf_planes->plane_info.mp[0].width = dim->width;
3280        buf_planes->plane_info.mp[0].height = dim->height;
3281        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3282            stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width);
3283            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height);
3284        } else {
3285            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
3286            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
3287        }
3288        buf_planes->plane_info.mp[1].len =
3289                buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
3290        buf_planes->plane_info.mp[1].offset = 0;
3291        buf_planes->plane_info.mp[1].offset_x =0;
3292        buf_planes->plane_info.mp[1].offset_y = 0;
3293        buf_planes->plane_info.mp[1].stride = stride;
3294        buf_planes->plane_info.mp[1].scanline = scanline;
3295        buf_planes->plane_info.mp[1].width = dim->width;
3296        buf_planes->plane_info.mp[1].height = dim->height / 2;
3297#else
3298        LOGE("Venus hardware not avail, cannot use this format");
3299        rc = -1;
3300#endif
3301        break;
3302    case CAM_FORMAT_YUV_420_NV12_UBWC:
3303#ifdef UBWC_PRESENT
3304        {
3305            int meta_stride = 0,meta_scanline = 0;
3306            // using UBWC
3307            if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
3308                stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
3309                scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
3310            } else {
3311                stride = PAD_TO_SIZE(dim->width, padding->width_padding);
3312                scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
3313            }
3314            meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
3315            meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
3316
3317            buf_planes->plane_info.frame_len =
3318                    VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, dim->width, dim->height);
3319            buf_planes->plane_info.num_planes = 2;
3320            buf_planes->plane_info.mp[0].offset = 0;
3321            buf_planes->plane_info.mp[0].offset_x =0;
3322            buf_planes->plane_info.mp[0].offset_y = 0;
3323            buf_planes->plane_info.mp[0].stride = stride;
3324            buf_planes->plane_info.mp[0].scanline = scanline;
3325            buf_planes->plane_info.mp[0].width = dim->width;
3326            buf_planes->plane_info.mp[0].height = dim->height;
3327            buf_planes->plane_info.mp[0].meta_stride = meta_stride;
3328            buf_planes->plane_info.mp[0].meta_scanline = meta_scanline;
3329            buf_planes->plane_info.mp[0].meta_len =
3330                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
3331            buf_planes->plane_info.mp[0].len =
3332                    (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) +
3333                    (buf_planes->plane_info.mp[0].meta_len));
3334
3335            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
3336            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
3337            meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
3338            meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
3339            buf_planes->plane_info.mp[1].offset = 0;
3340            buf_planes->plane_info.mp[1].offset_x =0;
3341            buf_planes->plane_info.mp[1].offset_y = 0;
3342            buf_planes->plane_info.mp[1].stride = stride;
3343            buf_planes->plane_info.mp[1].scanline = scanline;
3344            buf_planes->plane_info.mp[1].width = dim->width;
3345            buf_planes->plane_info.mp[1].height = dim->height/2;
3346            buf_planes->plane_info.mp[1].meta_stride = meta_stride;
3347            buf_planes->plane_info.mp[1].meta_scanline = meta_scanline;
3348            buf_planes->plane_info.mp[1].meta_len =
3349                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
3350            buf_planes->plane_info.mp[1].len =
3351                    buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
3352        }
3353#else
3354        LOGE("UBWC hardware not avail, cannot use this format");
3355        rc = -1;
3356#endif
3357        break;
3358    default:
3359        LOGE("Invalid cam_format for preview %d",
3360                    stream_info->fmt);
3361        rc = -1;
3362        break;
3363    }
3364
3365    return rc;
3366}
3367
3368/*===========================================================================
3369 * FUNCTION   : mm_stream_calc_offset_snapshot
3370 *
3371 * DESCRIPTION: calculate snapshot/postproc frame offset based on format and
3372 *              padding information
3373 *
3374 * PARAMETERS :
3375 *   @fmt     : image format
3376 *   @dim     : image dimension
3377 *   @padding : padding information
3378 *   @buf_planes : [out] buffer plane information
3379 *
3380 * RETURN     : int32_t type of status
3381 *              0  -- success
3382 *              -1 -- failure
3383 *==========================================================================*/
3384int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
3385                                       cam_dimension_t *dim,
3386                                       cam_padding_info_t *padding,
3387                                       cam_stream_buf_plane_info_t *buf_planes)
3388{
3389    int32_t rc = 0;
3390    uint8_t isAFamily = mm_camera_util_chip_is_a_family();
3391    int offset_x = 0, offset_y = 0;
3392    int stride = 0, scanline = 0;
3393    int stride_in_bytes = 0;
3394
3395    if (isAFamily) {
3396        stride = dim->width;
3397        scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16);
3398        offset_x = 0;
3399        offset_y = scanline - dim->height;
3400        scanline += offset_y; /* double padding */
3401    } else {
3402        offset_x = PAD_TO_SIZE(padding->offset_info.offset_x,
3403                padding->plane_padding);
3404        offset_y = PAD_TO_SIZE(padding->offset_info.offset_y,
3405                padding->plane_padding);
3406        stride = PAD_TO_SIZE((dim->width +
3407                (2 * offset_x)), padding->width_padding);
3408        scanline = PAD_TO_SIZE((dim->height +
3409                (2 * offset_y)), padding->height_padding);
3410    }
3411
3412    stride_in_bytes = stride;
3413
3414    switch (fmt) {
3415    case CAM_FORMAT_YUV_420_NV12:
3416    case CAM_FORMAT_YUV_420_NV21:
3417        /* 2 planes: Y + CbCr */
3418        buf_planes->plane_info.num_planes = 2;
3419
3420        buf_planes->plane_info.mp[0].len =
3421                PAD_TO_SIZE((uint32_t)(stride * scanline),
3422                padding->plane_padding);
3423        buf_planes->plane_info.mp[0].offset =
3424                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3425                padding->plane_padding);
3426        buf_planes->plane_info.mp[0].offset_x = offset_x;
3427        buf_planes->plane_info.mp[0].offset_y = offset_y;
3428        buf_planes->plane_info.mp[0].stride = stride;
3429        buf_planes->plane_info.mp[0].scanline = scanline;
3430        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3431        buf_planes->plane_info.mp[0].width = dim->width;
3432        buf_planes->plane_info.mp[0].height = dim->height;
3433
3434        scanline = scanline/2;
3435        buf_planes->plane_info.mp[1].len =
3436                PAD_TO_SIZE((uint32_t)(stride * scanline),
3437                padding->plane_padding);
3438        buf_planes->plane_info.mp[1].offset =
3439                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3440                padding->plane_padding);
3441        buf_planes->plane_info.mp[1].offset_x = offset_x;
3442        buf_planes->plane_info.mp[1].offset_y = offset_y;
3443        buf_planes->plane_info.mp[1].stride = stride;
3444        buf_planes->plane_info.mp[1].scanline = scanline;
3445        buf_planes->plane_info.mp[1].stride_in_bytes = stride_in_bytes;
3446        buf_planes->plane_info.mp[1].width = dim->width;
3447        buf_planes->plane_info.mp[1].height = dim->height / 2;
3448
3449        buf_planes->plane_info.frame_len =
3450                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3451                buf_planes->plane_info.mp[1].len,
3452                CAM_PAD_TO_4K);
3453        break;
3454    case CAM_FORMAT_YUV_420_YV12:
3455        /* 3 planes: Y + Cr + Cb */
3456        buf_planes->plane_info.num_planes = 3;
3457
3458        buf_planes->plane_info.mp[0].offset =
3459                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3460                        padding->plane_padding);
3461        buf_planes->plane_info.mp[0].len =
3462                PAD_TO_SIZE((uint32_t)(stride * scanline),
3463                        padding->plane_padding);
3464        buf_planes->plane_info.mp[0].offset_x = offset_x;
3465        buf_planes->plane_info.mp[0].offset_y = offset_y;
3466        buf_planes->plane_info.mp[0].stride = stride;
3467        buf_planes->plane_info.mp[0].scanline = scanline;
3468        buf_planes->plane_info.mp[0].width = dim->width;
3469        buf_planes->plane_info.mp[0].height = dim->height;
3470
3471        stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
3472        scanline = scanline / 2;
3473        buf_planes->plane_info.mp[1].offset =
3474                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3475                        padding->plane_padding);
3476        buf_planes->plane_info.mp[1].len =
3477                PAD_TO_SIZE((uint32_t)(stride * scanline),
3478                        padding->plane_padding);
3479        buf_planes->plane_info.mp[1].offset_x = offset_x;
3480        buf_planes->plane_info.mp[1].offset_y = offset_y;
3481        buf_planes->plane_info.mp[1].stride = stride;
3482        buf_planes->plane_info.mp[1].scanline = scanline;
3483        buf_planes->plane_info.mp[1].width = dim->width / 2;
3484        buf_planes->plane_info.mp[1].height = dim->height / 2;
3485
3486        buf_planes->plane_info.mp[2].offset =
3487                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3488                        padding->plane_padding);
3489        buf_planes->plane_info.mp[2].len =
3490                PAD_TO_SIZE((uint32_t)(stride * scanline),
3491                        padding->plane_padding);
3492        buf_planes->plane_info.mp[2].offset_x = offset_x;
3493        buf_planes->plane_info.mp[2].offset_y = offset_y;
3494        buf_planes->plane_info.mp[2].stride = stride;
3495        buf_planes->plane_info.mp[2].scanline = scanline;
3496        buf_planes->plane_info.mp[2].width = dim->width / 2;
3497        buf_planes->plane_info.mp[2].height = dim->height / 2;
3498
3499        buf_planes->plane_info.frame_len =
3500                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3501                        buf_planes->plane_info.mp[1].len +
3502                        buf_planes->plane_info.mp[2].len,
3503                        CAM_PAD_TO_4K);
3504        break;
3505    case CAM_FORMAT_YUV_422_NV16:
3506    case CAM_FORMAT_YUV_422_NV61:
3507        /* 2 planes: Y + CbCr */
3508        buf_planes->plane_info.num_planes = 2;
3509        buf_planes->plane_info.mp[0].len =
3510                PAD_TO_SIZE((uint32_t)(stride * scanline),
3511                        padding->plane_padding);
3512        buf_planes->plane_info.mp[0].offset =
3513                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3514                        padding->plane_padding);
3515        buf_planes->plane_info.mp[0].offset_x = offset_x;
3516        buf_planes->plane_info.mp[0].offset_y = offset_y;
3517        buf_planes->plane_info.mp[0].stride = stride;
3518        buf_planes->plane_info.mp[0].scanline = scanline;
3519        buf_planes->plane_info.mp[0].width = dim->width;
3520        buf_planes->plane_info.mp[0].height = dim->height;
3521
3522        buf_planes->plane_info.mp[1].len =
3523                PAD_TO_SIZE((uint32_t)(stride * scanline),
3524                        padding->plane_padding);
3525        buf_planes->plane_info.mp[1].offset =
3526                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
3527                        padding->plane_padding);
3528        buf_planes->plane_info.mp[1].offset_x = offset_x;
3529        buf_planes->plane_info.mp[1].offset_y = offset_y;
3530        buf_planes->plane_info.mp[1].stride = stride;
3531        buf_planes->plane_info.mp[1].scanline = scanline;
3532        buf_planes->plane_info.mp[1].width = dim->width;
3533        buf_planes->plane_info.mp[1].height = dim->height;
3534
3535        buf_planes->plane_info.frame_len = PAD_TO_SIZE(
3536            buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len,
3537            CAM_PAD_TO_4K);
3538        break;
3539    case CAM_FORMAT_YUV_420_NV12_UBWC:
3540#ifdef UBWC_PRESENT
3541        {
3542            int meta_stride = 0,meta_scanline = 0;
3543            // using UBWC
3544            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
3545            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
3546            meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
3547            meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
3548
3549            buf_planes->plane_info.frame_len =
3550                    VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, dim->width, dim->height);
3551            buf_planes->plane_info.num_planes = 2;
3552            buf_planes->plane_info.mp[0].offset = 0;
3553            buf_planes->plane_info.mp[0].offset_x = 0;
3554            buf_planes->plane_info.mp[0].offset_y = 0;
3555            buf_planes->plane_info.mp[0].stride = stride;
3556            buf_planes->plane_info.mp[0].scanline = scanline;
3557            buf_planes->plane_info.mp[0].width = dim->width;
3558            buf_planes->plane_info.mp[0].height = dim->height;
3559            buf_planes->plane_info.mp[0].meta_stride = meta_stride;
3560            buf_planes->plane_info.mp[0].meta_scanline = meta_scanline;
3561            buf_planes->plane_info.mp[0].meta_len =
3562                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
3563            buf_planes->plane_info.mp[0].len =
3564                    (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) +
3565                    (buf_planes->plane_info.mp[0].meta_len));
3566
3567            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
3568            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
3569            meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
3570            meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
3571            buf_planes->plane_info.mp[1].offset = 0;
3572            buf_planes->plane_info.mp[1].offset_x =0;
3573            buf_planes->plane_info.mp[1].offset_y = 0;
3574            buf_planes->plane_info.mp[1].stride = stride;
3575            buf_planes->plane_info.mp[1].scanline = scanline;
3576            buf_planes->plane_info.mp[1].width = dim->width;
3577            buf_planes->plane_info.mp[1].height = dim->height/2;
3578            buf_planes->plane_info.mp[1].meta_stride = meta_stride;
3579            buf_planes->plane_info.mp[1].meta_scanline = meta_scanline;
3580            buf_planes->plane_info.mp[1].meta_len =
3581                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
3582            buf_planes->plane_info.mp[1].len =
3583                    buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
3584        }
3585#else
3586        LOGE("UBWC hardware not avail, cannot use this format");
3587        rc = -1;
3588#endif
3589        break;
3590    case CAM_FORMAT_YUV_420_NV12_VENUS:
3591#ifdef VENUS_PRESENT
3592        // using Venus
3593        stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
3594        scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
3595
3596        buf_planes->plane_info.frame_len =
3597                VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
3598        buf_planes->plane_info.num_planes = 2;
3599        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
3600        buf_planes->plane_info.mp[0].offset = 0;
3601        buf_planes->plane_info.mp[0].offset_x =0;
3602        buf_planes->plane_info.mp[0].offset_y = 0;
3603        buf_planes->plane_info.mp[0].stride = stride;
3604        buf_planes->plane_info.mp[0].scanline = scanline;
3605        buf_planes->plane_info.mp[0].width = dim->width;
3606        buf_planes->plane_info.mp[0].height = dim->height;
3607        stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
3608        scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
3609        buf_planes->plane_info.mp[1].len =
3610                buf_planes->plane_info.frame_len -
3611                buf_planes->plane_info.mp[0].len;
3612        buf_planes->plane_info.mp[1].offset = 0;
3613        buf_planes->plane_info.mp[1].offset_x =0;
3614        buf_planes->plane_info.mp[1].offset_y = 0;
3615        buf_planes->plane_info.mp[1].stride = stride;
3616        buf_planes->plane_info.mp[1].scanline = scanline;
3617        buf_planes->plane_info.mp[1].width = dim->width;
3618        buf_planes->plane_info.mp[1].height = dim->height / 2;
3619#else
3620        LOGD("Video format VENUS is not supported = %d",
3621                 fmt);
3622#endif
3623        break;
3624    case CAM_FORMAT_YUV_420_NV21_VENUS:
3625#ifdef VENUS_PRESENT
3626        // using Venus
3627        stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width);
3628        scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height);
3629        buf_planes->plane_info.frame_len =
3630                VENUS_BUFFER_SIZE(COLOR_FMT_NV21, dim->width, dim->height);
3631        buf_planes->plane_info.num_planes = 2;
3632        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
3633        buf_planes->plane_info.mp[0].offset = 0;
3634        buf_planes->plane_info.mp[0].offset_x =0;
3635        buf_planes->plane_info.mp[0].offset_y = 0;
3636        buf_planes->plane_info.mp[0].stride = stride;
3637        buf_planes->plane_info.mp[0].scanline = scanline;
3638        buf_planes->plane_info.mp[0].width = dim->width;
3639        buf_planes->plane_info.mp[0].height = dim->height;
3640        stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width);
3641        scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height);
3642        buf_planes->plane_info.mp[1].len =
3643                buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
3644        buf_planes->plane_info.mp[1].offset = 0;
3645        buf_planes->plane_info.mp[1].offset_x =0;
3646        buf_planes->plane_info.mp[1].offset_y = 0;
3647        buf_planes->plane_info.mp[1].stride = stride;
3648        buf_planes->plane_info.mp[1].scanline = scanline;
3649        buf_planes->plane_info.mp[1].width = dim->width;
3650        buf_planes->plane_info.mp[1].height = dim->height / 2;
3651#else
3652        LOGE("Venus hardware not avail, cannot use this format");
3653        rc = -1;
3654#endif
3655        break;
3656    default:
3657        LOGE("Invalid cam_format for snapshot %d",
3658                    fmt);
3659        rc = -1;
3660        break;
3661    }
3662
3663    return rc;
3664}
3665
3666/*===========================================================================
3667 * FUNCTION   : mm_stream_calc_offset_raw
3668 *
3669 * DESCRIPTION: calculate raw frame offset based on format and padding information
3670 *
3671 * PARAMETERS :
3672 *   @fmt     : image format
3673 *   @dim     : image dimension
3674 *   @padding : padding information
3675 *   @buf_planes : [out] buffer plane information
3676 *
3677 * RETURN     : int32_t type of status
3678 *              0  -- success
3679 *              -1 -- failure
3680 *==========================================================================*/
3681int32_t mm_stream_calc_offset_raw(cam_format_t fmt,
3682                                  cam_dimension_t *dim,
3683                                  cam_padding_info_t *padding,
3684                                  cam_stream_buf_plane_info_t *buf_planes)
3685{
3686    int32_t rc = 0;
3687
3688    if ((NULL == dim) || (NULL == padding) || (NULL == buf_planes)) {
3689        return -1;
3690    }
3691
3692    int32_t stride = PAD_TO_SIZE(dim->width, (int32_t)padding->width_padding);
3693    int32_t stride_in_bytes = stride;
3694    int32_t scanline = PAD_TO_SIZE(dim->height, (int32_t)padding->height_padding);
3695
3696    switch (fmt) {
3697    case CAM_FORMAT_YUV_420_NV21:
3698        /* 2 planes: Y + CbCr */
3699        buf_planes->plane_info.num_planes = 2;
3700
3701        buf_planes->plane_info.mp[0].len =
3702                PAD_TO_SIZE((uint32_t)(stride * scanline),
3703                padding->plane_padding);
3704        buf_planes->plane_info.mp[0].offset = 0;
3705        buf_planes->plane_info.mp[0].offset_x = 0;
3706        buf_planes->plane_info.mp[0].offset_y = 0;
3707        buf_planes->plane_info.mp[0].stride = stride;
3708        buf_planes->plane_info.mp[0].stride_in_bytes = stride;
3709        buf_planes->plane_info.mp[0].scanline = scanline;
3710        buf_planes->plane_info.mp[0].width = dim->width;
3711        buf_planes->plane_info.mp[0].height = dim->height;
3712
3713        scanline = scanline / 2;
3714        buf_planes->plane_info.mp[1].len =
3715                PAD_TO_SIZE((uint32_t)(stride * scanline),
3716                padding->plane_padding);
3717        buf_planes->plane_info.mp[1].offset = 0;
3718        buf_planes->plane_info.mp[1].offset_x = 0;
3719        buf_planes->plane_info.mp[1].offset_y = 0;
3720        buf_planes->plane_info.mp[1].stride = stride;
3721        buf_planes->plane_info.mp[1].stride_in_bytes = stride;
3722        buf_planes->plane_info.mp[1].scanline = scanline;
3723        buf_planes->plane_info.mp[1].width = dim->width;
3724        buf_planes->plane_info.mp[1].height = dim->height / 2;
3725
3726        buf_planes->plane_info.frame_len =
3727                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
3728                buf_planes->plane_info.mp[1].len,
3729                CAM_PAD_TO_4K);
3730        break;
3731    case CAM_FORMAT_YUV_RAW_8BIT_YUYV:
3732    case CAM_FORMAT_YUV_RAW_8BIT_YVYU:
3733    case CAM_FORMAT_YUV_RAW_8BIT_UYVY:
3734    case CAM_FORMAT_YUV_RAW_8BIT_VYUY:
3735    case CAM_FORMAT_JPEG_RAW_8BIT:
3736        /* 1 plane */
3737        /* Every 16 pixels occupy 16 bytes */
3738        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
3739        stride_in_bytes = stride * 2;
3740        buf_planes->plane_info.num_planes = 1;
3741        buf_planes->plane_info.mp[0].offset = 0;
3742        buf_planes->plane_info.mp[0].len =
3743                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3744                        padding->plane_padding);
3745        buf_planes->plane_info.frame_len =
3746                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3747        buf_planes->plane_info.mp[0].offset_x =0;
3748        buf_planes->plane_info.mp[0].offset_y = 0;
3749        buf_planes->plane_info.mp[0].stride = stride;
3750        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3751        buf_planes->plane_info.mp[0].scanline = scanline;
3752        buf_planes->plane_info.mp[0].width =
3753                (int32_t)buf_planes->plane_info.mp[0].len;
3754        buf_planes->plane_info.mp[0].height = 1;
3755        break;
3756    case CAM_FORMAT_META_RAW_8BIT:
3757        // Every 16 pixels occupy 16 bytes
3758        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
3759        stride_in_bytes = stride * 2;
3760        buf_planes->plane_info.num_planes = 1;
3761        buf_planes->plane_info.mp[0].offset = 0;
3762        buf_planes->plane_info.mp[0].len =
3763                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3764                        padding->plane_padding);
3765        buf_planes->plane_info.frame_len =
3766                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3767        buf_planes->plane_info.mp[0].offset_x =0;
3768        buf_planes->plane_info.mp[0].offset_y = 0;
3769        buf_planes->plane_info.mp[0].stride = stride;
3770        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3771        buf_planes->plane_info.mp[0].scanline = scanline;
3772        break;
3773
3774    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG:
3775    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG:
3776    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB:
3777    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR:
3778    case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GREY:
3779    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG:
3780    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG:
3781    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB:
3782    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR:
3783    case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GREY:
3784    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG:
3785    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG:
3786    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB:
3787    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR:
3788    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GREY:
3789    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG:
3790    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG:
3791    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB:
3792    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR:
3793    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GREY:
3794    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG:
3795    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG:
3796    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB:
3797    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR:
3798        /* 1 plane */
3799        /* Every 16 pixels occupy 16 bytes */
3800        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
3801        stride_in_bytes = stride;
3802        buf_planes->plane_info.num_planes = 1;
3803        buf_planes->plane_info.mp[0].offset = 0;
3804        buf_planes->plane_info.mp[0].len =
3805                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3806                        padding->plane_padding);
3807        buf_planes->plane_info.frame_len =
3808                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3809        buf_planes->plane_info.mp[0].offset_x =0;
3810        buf_planes->plane_info.mp[0].offset_y = 0;
3811        buf_planes->plane_info.mp[0].stride = stride;
3812        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3813        buf_planes->plane_info.mp[0].scanline = scanline;
3814        buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
3815        buf_planes->plane_info.mp[0].height = 1;
3816        break;
3817    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG:
3818    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG:
3819    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB:
3820    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR:
3821    case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GREY:
3822    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG:
3823    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG:
3824    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB:
3825    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR:
3826    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GREY:
3827        /* Every 12 pixels occupy 16 bytes */
3828        stride = (dim->width + 11)/12 * 12;
3829        stride_in_bytes = stride * 8 / 6;
3830        buf_planes->plane_info.num_planes = 1;
3831        buf_planes->plane_info.mp[0].offset = 0;
3832        buf_planes->plane_info.mp[0].len =
3833                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3834                        padding->plane_padding);
3835        buf_planes->plane_info.frame_len =
3836                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3837        buf_planes->plane_info.mp[0].offset_x =0;
3838        buf_planes->plane_info.mp[0].offset_y = 0;
3839        buf_planes->plane_info.mp[0].stride = stride;
3840        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3841        buf_planes->plane_info.mp[0].scanline = scanline;
3842        buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
3843        buf_planes->plane_info.mp[0].height = 1;
3844        break;
3845    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG:
3846    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG:
3847    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB:
3848    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR:
3849    case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GREY:
3850    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG:
3851    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG:
3852    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB:
3853    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR:
3854    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GREY:
3855        /* Every 10 pixels occupy 16 bytes */
3856        stride = (dim->width + 9)/10 * 10;
3857        stride_in_bytes = stride * 8 / 5;
3858        buf_planes->plane_info.num_planes = 1;
3859        buf_planes->plane_info.mp[0].offset = 0;
3860        buf_planes->plane_info.mp[0].len =
3861                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3862                        padding->plane_padding);
3863        buf_planes->plane_info.frame_len =
3864                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3865        buf_planes->plane_info.mp[0].offset_x =0;
3866        buf_planes->plane_info.mp[0].offset_y = 0;
3867        buf_planes->plane_info.mp[0].stride = stride;
3868        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3869        buf_planes->plane_info.mp[0].scanline = scanline;
3870        buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
3871        buf_planes->plane_info.mp[0].height = 1;
3872        break;
3873    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG:
3874    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG:
3875    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB:
3876    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR:
3877    case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GREY:
3878    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG:
3879    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG:
3880    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB:
3881    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR:
3882    case CAM_FORMAT_META_RAW_10BIT:
3883    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GREY:
3884        /* Every 64 pixels occupy 80 bytes */
3885        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_4);
3886        stride_in_bytes = PAD_TO_SIZE(stride * 5 / 4, CAM_PAD_TO_8);
3887        buf_planes->plane_info.num_planes = 1;
3888        buf_planes->plane_info.mp[0].offset = 0;
3889        buf_planes->plane_info.mp[0].len =
3890                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3891                        padding->plane_padding);
3892        buf_planes->plane_info.frame_len =
3893                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3894        buf_planes->plane_info.mp[0].offset_x =0;
3895        buf_planes->plane_info.mp[0].offset_y = 0;
3896        buf_planes->plane_info.mp[0].stride = stride;
3897        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3898        buf_planes->plane_info.mp[0].scanline = scanline;
3899        buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
3900        buf_planes->plane_info.mp[0].height = 1;
3901        break;
3902    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG:
3903    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG:
3904    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB:
3905    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR:
3906    case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GREY:
3907    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG:
3908    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG:
3909    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB:
3910    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR:
3911    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GREY:
3912        /* Every 32 pixels occupy 48 bytes */
3913        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
3914        stride_in_bytes = stride * 3 / 2;
3915        buf_planes->plane_info.num_planes = 1;
3916        buf_planes->plane_info.mp[0].offset = 0;
3917        buf_planes->plane_info.mp[0].len =
3918                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3919                        padding->plane_padding);
3920        buf_planes->plane_info.frame_len =
3921                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3922        buf_planes->plane_info.mp[0].offset_x =0;
3923        buf_planes->plane_info.mp[0].offset_y = 0;
3924        buf_planes->plane_info.mp[0].stride = stride;
3925        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3926        buf_planes->plane_info.mp[0].scanline = scanline;
3927        buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
3928        buf_planes->plane_info.mp[0].height = 1;
3929        break;
3930    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG:
3931    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG:
3932    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB:
3933    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR:
3934    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG:
3935    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG:
3936    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB:
3937    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR:
3938    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG:
3939    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG:
3940    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB:
3941    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR:
3942    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_14BPP_GBRG:
3943    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_14BPP_GRBG:
3944    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_14BPP_RGGB:
3945    case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_14BPP_BGGR:
3946        /* Every 8 pixels occupy 16 bytes */
3947        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8);
3948        stride_in_bytes = stride * 2;
3949        buf_planes->plane_info.num_planes = 1;
3950        buf_planes->plane_info.mp[0].offset = 0;
3951        buf_planes->plane_info.mp[0].len =
3952                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3953                        padding->plane_padding);
3954        buf_planes->plane_info.frame_len =
3955                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3956        buf_planes->plane_info.mp[0].offset_x =0;
3957        buf_planes->plane_info.mp[0].offset_y = 0;
3958        buf_planes->plane_info.mp[0].stride = stride;
3959        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3960        buf_planes->plane_info.mp[0].scanline = scanline;
3961        buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
3962        buf_planes->plane_info.mp[0].height = 1;
3963        break;
3964    case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_GBRG:
3965    case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_GRBG:
3966    case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_RGGB:
3967    case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_BGGR:
3968    case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_GREY:
3969    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GBRG:
3970    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GRBG:
3971    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_RGGB:
3972    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_BGGR:
3973    case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GREY:
3974        /* Every 64 pixels occupy 112 bytes */
3975        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64);
3976        stride_in_bytes = stride * 7 / 4;
3977        buf_planes->plane_info.num_planes = 1;
3978        buf_planes->plane_info.mp[0].offset = 0;
3979        buf_planes->plane_info.mp[0].len =
3980                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
3981                padding->plane_padding);
3982        buf_planes->plane_info.frame_len =
3983                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
3984        buf_planes->plane_info.mp[0].offset_x =0;
3985        buf_planes->plane_info.mp[0].offset_y = 0;
3986        buf_planes->plane_info.mp[0].stride = stride;
3987        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
3988        buf_planes->plane_info.mp[0].scanline = scanline;
3989        buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
3990        buf_planes->plane_info.mp[0].height = 1;
3991        break;
3992    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GBRG:
3993    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GRBG:
3994    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_RGGB:
3995    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_BGGR:
3996    case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GREY:
3997    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_GBRG:
3998    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_GRBG:
3999    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_RGGB:
4000    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_BGGR:
4001    case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_GREY:
4002        /* Every 16 pixels occupy 32 bytes */
4003        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
4004        stride_in_bytes = stride * 2;
4005        buf_planes->plane_info.num_planes = 1;
4006        buf_planes->plane_info.mp[0].offset = 0;
4007        buf_planes->plane_info.mp[0].len =
4008                PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline),
4009                padding->plane_padding);
4010        buf_planes->plane_info.frame_len =
4011                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
4012        buf_planes->plane_info.mp[0].offset_x =0;
4013        buf_planes->plane_info.mp[0].offset_y = 0;
4014        buf_planes->plane_info.mp[0].stride = stride;
4015        buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes;
4016        buf_planes->plane_info.mp[0].scanline = scanline;
4017        buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len;
4018        buf_planes->plane_info.mp[0].height = 1;
4019        break;
4020    default:
4021        LOGE("Invalid cam_format %d for raw stream",
4022                    fmt);
4023        rc = -1;
4024        break;
4025    }
4026
4027    return rc;
4028}
4029
4030/*===========================================================================
4031 * FUNCTION   : mm_stream_calc_offset_video
4032 *
4033 * DESCRIPTION: calculate video frame offset based on format and
4034 *              padding information
4035 *
4036 * PARAMETERS :
4037  *   @fmt     : image format
4038 *   @dim     : image dimension
4039 *   @buf_planes : [out] buffer plane information
4040 *
4041 * RETURN     : int32_t type of status
4042 *              0  -- success
4043 *              -1 -- failure
4044 *==========================================================================*/
4045int32_t mm_stream_calc_offset_video(cam_format_t fmt,
4046        cam_dimension_t *dim, cam_stream_buf_plane_info_t *buf_planes)
4047{
4048    int32_t rc = 0;
4049    int stride = 0, scanline = 0;
4050
4051    #ifdef UBWC_PRESENT
4052    int meta_stride = 0,meta_scanline = 0;
4053    #endif
4054
4055
4056    switch (fmt) {
4057        case CAM_FORMAT_YUV_420_NV12:
4058        case CAM_FORMAT_Y_ONLY:
4059        case CAM_FORMAT_Y_ONLY_10_BPP:
4060        case CAM_FORMAT_Y_ONLY_12_BPP:
4061        case CAM_FORMAT_Y_ONLY_14_BPP:
4062            buf_planes->plane_info.num_planes = 2;
4063
4064            stride = dim->width;
4065            scanline = dim->height;
4066            buf_planes->plane_info.mp[0].len =
4067                    PAD_TO_SIZE((uint32_t)(stride * scanline),
4068                    CAM_PAD_TO_2K);
4069            buf_planes->plane_info.mp[0].offset = 0;
4070            buf_planes->plane_info.mp[0].offset_x =0;
4071            buf_planes->plane_info.mp[0].offset_y = 0;
4072            buf_planes->plane_info.mp[0].stride = stride;
4073            buf_planes->plane_info.mp[0].scanline = scanline;
4074            buf_planes->plane_info.mp[0].width = dim->width;
4075            buf_planes->plane_info.mp[0].height = dim->height;
4076
4077            stride = dim->width;
4078            scanline = dim->height / 2;
4079            buf_planes->plane_info.mp[1].len =
4080                    PAD_TO_SIZE((uint32_t)(stride * scanline),
4081                    CAM_PAD_TO_2K);
4082            buf_planes->plane_info.mp[1].offset = 0;
4083            buf_planes->plane_info.mp[1].offset_x =0;
4084            buf_planes->plane_info.mp[1].offset_y = 0;
4085            buf_planes->plane_info.mp[1].stride = stride;
4086            buf_planes->plane_info.mp[1].scanline = scanline;
4087            buf_planes->plane_info.mp[1].width = dim->width;
4088            buf_planes->plane_info.mp[1].height = dim->height / 2;
4089
4090            buf_planes->plane_info.frame_len =
4091                    PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
4092                    buf_planes->plane_info.mp[1].len,
4093                    CAM_PAD_TO_4K);
4094            break;
4095        case CAM_FORMAT_YUV_420_NV12_VENUS:
4096#ifdef VENUS_PRESENT
4097            // using Venus
4098            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
4099            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
4100
4101            buf_planes->plane_info.frame_len =
4102                    VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
4103            buf_planes->plane_info.num_planes = 2;
4104            buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
4105            buf_planes->plane_info.mp[0].offset = 0;
4106            buf_planes->plane_info.mp[0].offset_x =0;
4107            buf_planes->plane_info.mp[0].offset_y = 0;
4108            buf_planes->plane_info.mp[0].stride = stride;
4109            buf_planes->plane_info.mp[0].scanline = scanline;
4110            buf_planes->plane_info.mp[0].width = dim->width;
4111            buf_planes->plane_info.mp[0].height = dim->height;
4112            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
4113            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
4114            buf_planes->plane_info.mp[1].len =
4115                    buf_planes->plane_info.frame_len -
4116                    buf_planes->plane_info.mp[0].len;
4117            buf_planes->plane_info.mp[1].offset = 0;
4118            buf_planes->plane_info.mp[1].offset_x =0;
4119            buf_planes->plane_info.mp[1].offset_y = 0;
4120            buf_planes->plane_info.mp[1].stride = stride;
4121            buf_planes->plane_info.mp[1].scanline = scanline;
4122            buf_planes->plane_info.mp[1].width = dim->width;
4123            buf_planes->plane_info.mp[1].height = dim->height/2;
4124#else
4125            LOGD("Video format VENUS is not supported = %d",
4126                     fmt);
4127#endif
4128            break;
4129        case CAM_FORMAT_YUV_420_NV21_VENUS:
4130#ifdef VENUS_PRESENT
4131            // using Venus
4132            stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width);
4133            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height);
4134
4135            buf_planes->plane_info.frame_len =
4136                    VENUS_BUFFER_SIZE(COLOR_FMT_NV21, dim->width, dim->height);
4137            buf_planes->plane_info.num_planes = 2;
4138            buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
4139            buf_planes->plane_info.mp[0].offset = 0;
4140            buf_planes->plane_info.mp[0].offset_x =0;
4141            buf_planes->plane_info.mp[0].offset_y = 0;
4142            buf_planes->plane_info.mp[0].stride = stride;
4143            buf_planes->plane_info.mp[0].scanline = scanline;
4144            buf_planes->plane_info.mp[0].width = dim->width;
4145            buf_planes->plane_info.mp[0].height = dim->height;
4146            stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width);
4147            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height);
4148            buf_planes->plane_info.mp[1].len =
4149                    buf_planes->plane_info.frame_len -
4150                    buf_planes->plane_info.mp[0].len;
4151            buf_planes->plane_info.mp[1].offset = 0;
4152            buf_planes->plane_info.mp[1].offset_x =0;
4153            buf_planes->plane_info.mp[1].offset_y = 0;
4154            buf_planes->plane_info.mp[1].stride = stride;
4155            buf_planes->plane_info.mp[1].scanline = scanline;
4156            buf_planes->plane_info.mp[1].width = dim->width;
4157            buf_planes->plane_info.mp[1].height = dim->height / 2;
4158#else
4159            LOGD("Video format VENUS is not supported = %d",
4160                     fmt);
4161#endif
4162            break;
4163        case CAM_FORMAT_YUV_420_NV12_UBWC:
4164#ifdef UBWC_PRESENT
4165            // using UBWC
4166            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
4167            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
4168            meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
4169            meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
4170
4171            buf_planes->plane_info.frame_len =
4172                    VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, dim->width, dim->height);
4173            buf_planes->plane_info.num_planes = 2;
4174            buf_planes->plane_info.mp[0].offset = 0;
4175            buf_planes->plane_info.mp[0].offset_x =0;
4176            buf_planes->plane_info.mp[0].offset_y = 0;
4177            buf_planes->plane_info.mp[0].stride = stride;
4178            buf_planes->plane_info.mp[0].scanline = scanline;
4179            buf_planes->plane_info.mp[0].width = dim->width;
4180            buf_planes->plane_info.mp[0].height = dim->height;
4181            buf_planes->plane_info.mp[0].meta_stride = meta_stride;
4182            buf_planes->plane_info.mp[0].meta_scanline = meta_scanline;
4183            buf_planes->plane_info.mp[0].meta_len =
4184                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
4185            buf_planes->plane_info.mp[0].len =
4186                    (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) +
4187                    (buf_planes->plane_info.mp[0].meta_len));
4188
4189            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
4190            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
4191            meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
4192            meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
4193
4194            buf_planes->plane_info.mp[1].offset = 0;
4195            buf_planes->plane_info.mp[1].offset_x =0;
4196            buf_planes->plane_info.mp[1].offset_y = 0;
4197            buf_planes->plane_info.mp[1].stride = stride;
4198            buf_planes->plane_info.mp[1].scanline = scanline;
4199            buf_planes->plane_info.mp[1].width = dim->width;
4200            buf_planes->plane_info.mp[1].height = dim->height/2;
4201            buf_planes->plane_info.mp[1].meta_stride = meta_stride;
4202            buf_planes->plane_info.mp[1].meta_scanline = meta_scanline;
4203            buf_planes->plane_info.mp[1].meta_len =
4204                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
4205            buf_planes->plane_info.mp[1].len =
4206                    buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
4207
4208#else
4209            LOGD("Video format UBWC is not supported = %d",
4210                     fmt);
4211            rc = -1;
4212#endif
4213            break;
4214        default:
4215            LOGD("Invalid Video Format = %d", fmt);
4216            rc = -1;
4217            break;
4218    }
4219    return rc;
4220}
4221
4222/*===========================================================================
4223 * FUNCTION   : mm_stream_calc_offset_metadata
4224 *
4225 * DESCRIPTION: calculate metadata frame offset based on format and
4226 *              padding information
4227 *
4228 * PARAMETERS :
4229 *   @dim     : image dimension
4230 *   @padding : padding information
4231 *   @buf_planes : [out] buffer plane information
4232 *
4233 * RETURN     : int32_t type of status
4234 *              0  -- success
4235 *              -1 -- failure
4236 *==========================================================================*/
4237int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim,
4238                                       cam_padding_info_t *padding,
4239                                       cam_stream_buf_plane_info_t *buf_planes)
4240{
4241    int32_t rc = 0;
4242    buf_planes->plane_info.num_planes = 1;
4243    buf_planes->plane_info.mp[0].offset = 0;
4244    buf_planes->plane_info.mp[0].len =
4245            PAD_TO_SIZE((uint32_t)(dim->width * dim->height),
4246                    padding->plane_padding);
4247    buf_planes->plane_info.frame_len =
4248        buf_planes->plane_info.mp[0].len;
4249
4250    buf_planes->plane_info.mp[0].offset_x =0;
4251    buf_planes->plane_info.mp[0].offset_y = 0;
4252    buf_planes->plane_info.mp[0].stride = dim->width;
4253    buf_planes->plane_info.mp[0].scanline = dim->height;
4254    buf_planes->plane_info.mp[0].width = dim->width;
4255    buf_planes->plane_info.mp[0].height = dim->height;
4256    return rc;
4257}
4258
4259/*===========================================================================
4260 * FUNCTION   : mm_stream_calc_offset_analysis
4261 *
4262 * DESCRIPTION: calculate analysis frame offset based on format and
4263 *              padding information
4264 *
4265 * PARAMETERS :
4266 *   @fmt     : image format
4267 *   @dim     : image dimension
4268 *   @padding : padding information
4269 *   @buf_planes : [out] buffer plane information
4270 *
4271 * RETURN     : int32_t type of status
4272 *              0  -- success
4273 *              -1 -- failure
4274 *==========================================================================*/
4275int32_t mm_stream_calc_offset_analysis(cam_format_t fmt,
4276                                       cam_dimension_t *dim,
4277                                       cam_padding_info_t *padding,
4278                                       cam_stream_buf_plane_info_t *buf_planes)
4279{
4280    int32_t rc = 0;
4281    int32_t offset_x = 0, offset_y = 0;
4282    int32_t stride, scanline;
4283
4284    /* Clip to minimum supported bytes per line */
4285    if ((uint32_t)dim->width < padding->min_stride) {
4286        stride = (int32_t)padding->min_stride;
4287    } else {
4288        stride = dim->width;
4289    }
4290
4291    if ((uint32_t)dim->height < padding->min_scanline) {
4292      scanline = (int32_t)padding->min_scanline;
4293    } else {
4294      scanline = dim->height;
4295    }
4296
4297    stride = PAD_TO_SIZE(stride, padding->width_padding);
4298    scanline = PAD_TO_SIZE(scanline, padding->height_padding);
4299
4300    switch (fmt) {
4301    case CAM_FORMAT_YUV_420_NV12:
4302    case CAM_FORMAT_YUV_420_NV21:
4303        /* 2 planes: Y + CbCr */
4304        buf_planes->plane_info.num_planes = 2;
4305
4306        buf_planes->plane_info.mp[0].len =
4307                PAD_TO_SIZE((uint32_t)(stride * scanline),
4308                        padding->plane_padding);
4309        buf_planes->plane_info.mp[0].offset =
4310                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
4311                        padding->plane_padding);
4312        buf_planes->plane_info.mp[0].offset_x = offset_x;
4313        buf_planes->plane_info.mp[0].offset_y = offset_y;
4314        buf_planes->plane_info.mp[0].stride = stride;
4315        buf_planes->plane_info.mp[0].scanline = scanline;
4316        buf_planes->plane_info.mp[0].width = dim->width;
4317        buf_planes->plane_info.mp[0].height = dim->height;
4318
4319        scanline = scanline / 2;
4320        buf_planes->plane_info.mp[1].len =
4321                PAD_TO_SIZE((uint32_t)(stride * scanline),
4322                        padding->plane_padding);
4323        buf_planes->plane_info.mp[1].offset =
4324                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
4325                        padding->plane_padding);
4326        buf_planes->plane_info.mp[1].offset_x = offset_x;
4327        buf_planes->plane_info.mp[1].offset_y = offset_y;
4328        buf_planes->plane_info.mp[1].stride = stride;
4329        buf_planes->plane_info.mp[1].scanline = scanline;
4330        buf_planes->plane_info.mp[1].width = dim->width;
4331        buf_planes->plane_info.mp[1].height = dim->height / 2;
4332
4333        buf_planes->plane_info.frame_len =
4334                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
4335                        buf_planes->plane_info.mp[1].len,
4336                        CAM_PAD_TO_4K);
4337        break;
4338    case CAM_FORMAT_YUV_420_YV12:
4339        /* 3 planes: Y + Cr + Cb */
4340        buf_planes->plane_info.num_planes = 3;
4341
4342        buf_planes->plane_info.mp[0].offset =
4343                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
4344                        padding->plane_padding);
4345        buf_planes->plane_info.mp[0].len =
4346                PAD_TO_SIZE((uint32_t)(stride * scanline),
4347                        padding->plane_padding);
4348        buf_planes->plane_info.mp[0].offset_x = offset_x;
4349        buf_planes->plane_info.mp[0].offset_y = offset_y;
4350        buf_planes->plane_info.mp[0].stride = stride;
4351        buf_planes->plane_info.mp[0].scanline = scanline;
4352        buf_planes->plane_info.mp[0].width = dim->width;
4353        buf_planes->plane_info.mp[0].height = dim->height;
4354
4355        stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
4356        scanline = scanline / 2;
4357        buf_planes->plane_info.mp[1].offset =
4358                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
4359                        padding->plane_padding);
4360        buf_planes->plane_info.mp[1].len =
4361                PAD_TO_SIZE((uint32_t)(stride * scanline),
4362                        padding->plane_padding);
4363        buf_planes->plane_info.mp[1].offset_x = offset_x;
4364        buf_planes->plane_info.mp[1].offset_y = offset_y;
4365        buf_planes->plane_info.mp[1].stride = stride;
4366        buf_planes->plane_info.mp[1].scanline = scanline;
4367        buf_planes->plane_info.mp[1].width = dim->width / 2;
4368        buf_planes->plane_info.mp[1].height = dim->height / 2;
4369
4370        buf_planes->plane_info.mp[2].offset =
4371                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
4372                        padding->plane_padding);
4373        buf_planes->plane_info.mp[2].len =
4374                PAD_TO_SIZE((uint32_t)(stride * scanline),
4375                        padding->plane_padding);
4376        buf_planes->plane_info.mp[2].offset_x = offset_x;
4377        buf_planes->plane_info.mp[2].offset_y = offset_y;
4378        buf_planes->plane_info.mp[2].stride = stride;
4379        buf_planes->plane_info.mp[2].scanline = scanline;
4380        buf_planes->plane_info.mp[2].width = dim->width / 2;
4381        buf_planes->plane_info.mp[2].height = dim->height / 2;
4382
4383        buf_planes->plane_info.frame_len =
4384                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len +
4385                        buf_planes->plane_info.mp[1].len +
4386                        buf_planes->plane_info.mp[2].len,
4387                        CAM_PAD_TO_4K);
4388        break;
4389    case CAM_FORMAT_YUV_422_NV16:
4390    case CAM_FORMAT_YUV_422_NV61:
4391        /* 2 planes: Y + CbCr */
4392        buf_planes->plane_info.num_planes = 2;
4393        buf_planes->plane_info.mp[0].len =
4394                PAD_TO_SIZE((uint32_t)(stride * scanline),
4395                        padding->plane_padding);
4396        buf_planes->plane_info.mp[0].offset =
4397                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
4398                        padding->plane_padding);
4399        buf_planes->plane_info.mp[0].offset_x = offset_x;
4400        buf_planes->plane_info.mp[0].offset_y = offset_y;
4401        buf_planes->plane_info.mp[0].stride = stride;
4402        buf_planes->plane_info.mp[0].scanline = scanline;
4403        buf_planes->plane_info.mp[0].width = dim->width;
4404        buf_planes->plane_info.mp[0].height = dim->height;
4405
4406        buf_planes->plane_info.mp[1].len =
4407                PAD_TO_SIZE((uint32_t)(stride * scanline),
4408                        padding->plane_padding);
4409        buf_planes->plane_info.mp[1].offset =
4410                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
4411                        padding->plane_padding);
4412        buf_planes->plane_info.mp[1].offset_x = offset_x;
4413        buf_planes->plane_info.mp[1].offset_y = offset_y;
4414        buf_planes->plane_info.mp[1].stride = stride;
4415        buf_planes->plane_info.mp[1].scanline = scanline;
4416        buf_planes->plane_info.mp[1].width = dim->width;
4417        buf_planes->plane_info.mp[1].height = dim->height;
4418
4419        buf_planes->plane_info.frame_len = PAD_TO_SIZE(
4420            buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len,
4421            CAM_PAD_TO_4K);
4422        break;
4423    case CAM_FORMAT_Y_ONLY:
4424    case CAM_FORMAT_Y_ONLY_10_BPP:
4425    case CAM_FORMAT_Y_ONLY_12_BPP:
4426    case CAM_FORMAT_Y_ONLY_14_BPP:
4427        buf_planes->plane_info.num_planes = 1;
4428
4429        buf_planes->plane_info.mp[0].len =
4430                PAD_TO_SIZE((uint32_t)(stride * scanline),
4431                padding->plane_padding);
4432        buf_planes->plane_info.mp[0].offset =
4433                PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y),
4434                padding->plane_padding);
4435        buf_planes->plane_info.mp[0].offset_x = offset_x;
4436        buf_planes->plane_info.mp[0].offset_y = offset_y;
4437        buf_planes->plane_info.mp[0].stride = stride;
4438        buf_planes->plane_info.mp[0].scanline = scanline;
4439        buf_planes->plane_info.mp[0].width = dim->width;
4440        buf_planes->plane_info.mp[0].height = dim->height;
4441        buf_planes->plane_info.frame_len =
4442                PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
4443        break;
4444    case CAM_FORMAT_YUV_420_NV12_VENUS:
4445#ifdef VENUS_PRESENT
4446        // using Venus
4447        stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
4448        scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
4449
4450        buf_planes->plane_info.frame_len =
4451                VENUS_BUFFER_SIZE(COLOR_FMT_NV12, stride, scanline);
4452        buf_planes->plane_info.num_planes = 2;
4453        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
4454        buf_planes->plane_info.mp[0].offset = 0;
4455        buf_planes->plane_info.mp[0].offset_x =0;
4456        buf_planes->plane_info.mp[0].offset_y = 0;
4457        buf_planes->plane_info.mp[0].stride = stride;
4458        buf_planes->plane_info.mp[0].scanline = scanline;
4459        buf_planes->plane_info.mp[0].width = dim->width;
4460        buf_planes->plane_info.mp[0].height = dim->height;
4461        stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
4462        scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
4463        buf_planes->plane_info.mp[1].len =
4464                buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
4465        buf_planes->plane_info.mp[1].offset = 0;
4466        buf_planes->plane_info.mp[1].offset_x =0;
4467        buf_planes->plane_info.mp[1].offset_y = 0;
4468        buf_planes->plane_info.mp[1].stride = stride;
4469        buf_planes->plane_info.mp[1].scanline = scanline;
4470        buf_planes->plane_info.mp[1].width = dim->width;
4471        buf_planes->plane_info.mp[1].height = dim->height / 2;
4472#else
4473        LOGE("Venus hardware not avail, cannot use this format");
4474        rc = -1;
4475#endif
4476        break;
4477    case CAM_FORMAT_YUV_420_NV21_VENUS:
4478#ifdef VENUS_PRESENT
4479        // using Venus
4480        stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width);
4481        scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height);
4482
4483        buf_planes->plane_info.frame_len =
4484                VENUS_BUFFER_SIZE(COLOR_FMT_NV21, stride, scanline);
4485        buf_planes->plane_info.num_planes = 2;
4486        buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
4487        buf_planes->plane_info.mp[0].offset = 0;
4488        buf_planes->plane_info.mp[0].offset_x =0;
4489        buf_planes->plane_info.mp[0].offset_y = 0;
4490        buf_planes->plane_info.mp[0].stride = stride;
4491        buf_planes->plane_info.mp[0].scanline = scanline;
4492        buf_planes->plane_info.mp[0].width = dim->width;
4493        buf_planes->plane_info.mp[0].height = dim->height;
4494        stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width);
4495        scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height);
4496        buf_planes->plane_info.mp[1].len =
4497                buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
4498        buf_planes->plane_info.mp[1].offset = 0;
4499        buf_planes->plane_info.mp[1].offset_x =0;
4500        buf_planes->plane_info.mp[1].offset_y = 0;
4501        buf_planes->plane_info.mp[1].stride = stride;
4502        buf_planes->plane_info.mp[1].scanline = scanline;
4503        buf_planes->plane_info.mp[1].width = dim->width;
4504        buf_planes->plane_info.mp[1].height = dim->height / 2;
4505#else
4506        LOGE("Venus hardware not avail, cannot use this format");
4507        rc = -1;
4508#endif
4509        break;
4510    case CAM_FORMAT_YUV_420_NV12_UBWC:
4511#ifdef UBWC_PRESENT
4512        {
4513            int meta_stride = 0,meta_scanline = 0;
4514            // using UBWC
4515            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
4516            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
4517            meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
4518            meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
4519
4520            buf_planes->plane_info.frame_len =
4521                    VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, stride, scanline);
4522            buf_planes->plane_info.num_planes = 2;
4523            buf_planes->plane_info.mp[0].offset = 0;
4524            buf_planes->plane_info.mp[0].offset_x =0;
4525            buf_planes->plane_info.mp[0].offset_y = 0;
4526            buf_planes->plane_info.mp[0].stride = stride;
4527            buf_planes->plane_info.mp[0].scanline = scanline;
4528            buf_planes->plane_info.mp[0].width = dim->width;
4529            buf_planes->plane_info.mp[0].height = dim->height;
4530            buf_planes->plane_info.mp[0].meta_stride = meta_stride;
4531            buf_planes->plane_info.mp[0].meta_scanline = meta_scanline;
4532            buf_planes->plane_info.mp[0].meta_len =
4533                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
4534            buf_planes->plane_info.mp[0].len =
4535                    (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) +
4536                    (buf_planes->plane_info.mp[0].meta_len));
4537
4538            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
4539            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
4540            meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
4541            meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
4542            buf_planes->plane_info.mp[1].offset = 0;
4543            buf_planes->plane_info.mp[1].offset_x =0;
4544            buf_planes->plane_info.mp[1].offset_y = 0;
4545            buf_planes->plane_info.mp[1].stride = stride;
4546            buf_planes->plane_info.mp[1].scanline = scanline;
4547            buf_planes->plane_info.mp[1].width = dim->width;
4548            buf_planes->plane_info.mp[1].height = dim->height/2;
4549            buf_planes->plane_info.mp[1].meta_stride = meta_stride;
4550            buf_planes->plane_info.mp[1].meta_scanline = meta_scanline;
4551            buf_planes->plane_info.mp[1].meta_len =
4552                    MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096);
4553            buf_planes->plane_info.mp[1].len =
4554                    buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
4555        }
4556#else
4557        LOGE("UBWC hardware not avail, cannot use this format");
4558        rc = -1;
4559#endif
4560        break;
4561    default:
4562        LOGE("Invalid cam_format for anlysis %d",
4563                    fmt);
4564        rc = -1;
4565        break;
4566    }
4567
4568    return rc;
4569}
4570
4571/*===========================================================================
4572 * FUNCTION   : mm_stream_calc_offset_postproc
4573 *
4574 * DESCRIPTION: calculate postprocess frame offset
4575 *
4576 * PARAMETERS :
4577 *   @stream_info: ptr to stream info
4578 *   @padding : padding information
4579 *   @plns : [out] buffer plane information
4580 *
4581 * RETURN     : int32_t type of status
4582 *              0  -- success
4583 *              -1 -- failure
4584 *==========================================================================*/
4585int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info,
4586                                       cam_padding_info_t *padding,
4587                                       cam_stream_buf_plane_info_t *plns)
4588{
4589    int32_t rc = 0;
4590    cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT;
4591    if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) {
4592        type = stream_info->reprocess_config.offline.input_type;
4593        if (CAM_STREAM_TYPE_DEFAULT == type) {
4594            if (plns->plane_info.frame_len == 0) {
4595                // take offset from input source
4596                *plns = stream_info->reprocess_config.offline.input_buf_planes;
4597                return rc;
4598            }
4599        } else {
4600            type = stream_info->reprocess_config.offline.input_type;
4601        }
4602    } else {
4603        type = stream_info->reprocess_config.online.input_stream_type;
4604    }
4605
4606    switch (type) {
4607    case CAM_STREAM_TYPE_PREVIEW:
4608        rc = mm_stream_calc_offset_preview(stream_info,
4609                                           &stream_info->dim,
4610                                           padding,
4611                                           plns);
4612        break;
4613    case CAM_STREAM_TYPE_POSTVIEW:
4614        rc = mm_stream_calc_offset_post_view(stream_info,
4615                                           &stream_info->dim,
4616                                           padding,
4617                                           plns);
4618        break;
4619    case CAM_STREAM_TYPE_SNAPSHOT:
4620    case CAM_STREAM_TYPE_CALLBACK:
4621        rc = mm_stream_calc_offset_snapshot(stream_info->fmt,
4622                                            &stream_info->dim,
4623                                            padding,
4624                                            plns);
4625        break;
4626    case CAM_STREAM_TYPE_VIDEO:
4627        rc = mm_stream_calc_offset_video(stream_info->fmt,
4628                &stream_info->dim, plns);
4629        break;
4630    case CAM_STREAM_TYPE_RAW:
4631        rc = mm_stream_calc_offset_raw(stream_info->fmt,
4632                                       &stream_info->dim,
4633                                       padding,
4634                                       plns);
4635        break;
4636    case CAM_STREAM_TYPE_ANALYSIS:
4637        rc = mm_stream_calc_offset_analysis(stream_info->fmt,
4638                                            &stream_info->dim,
4639                                            padding,
4640                                            plns);
4641        break;
4642    case CAM_STREAM_TYPE_METADATA:
4643        rc = mm_stream_calc_offset_metadata(&stream_info->dim,
4644                                            padding,
4645                                            plns);
4646        break;
4647    case CAM_STREAM_TYPE_OFFLINE_PROC:
4648        rc = mm_stream_calc_offset_snapshot(stream_info->fmt,
4649                &stream_info->dim, padding, plns);
4650        break;
4651    default:
4652        LOGE("not supported for stream type %d",
4653                    type);
4654        rc = -1;
4655        break;
4656    }
4657    return rc;
4658}
4659
4660/*===========================================================================
4661* FUNCTION    : mm_stream_calc_lcm
4662*
4663* DESCRIPTION: calculate LCM of two numbers
4664*
4665* PARAMETERS :
4666*   @num1  : number 1
4667*   @num2  : number 2
4668*
4669* RETURN     : uint32_t type
4670*
4671*===========================================================================*/
4672uint32_t mm_stream_calc_lcm(int32_t num1, int32_t num2)
4673{
4674    uint32_t lcm = 0;
4675    uint32_t temp = 0;
4676
4677    if ((num1 < 1) && (num2 < 1)) {
4678        return 0;
4679    } else if (num1 < 1) {
4680        return num2;
4681    } else if (num2 < 1) {
4682        return num1;
4683    }
4684
4685    if (num1 > num2) {
4686        lcm = num1;
4687    } else {
4688        lcm = num2;
4689    }
4690    temp = lcm;
4691
4692    while (1) {
4693        if (((lcm%num1) == 0) && ((lcm%num2) == 0)) {
4694            break;
4695        }
4696        lcm += temp;
4697    }
4698    return lcm;
4699}
4700
4701/*===========================================================================
4702 * FUNCTION   : mm_stream_calc_offset
4703 *
4704 * DESCRIPTION: calculate frame offset based on format and padding information
4705 *
4706 * PARAMETERS :
4707 *   @my_obj  : stream object
4708 *
4709 * RETURN     : int32_t type of status
4710 *              0  -- success
4711 *              -1 -- failure
4712 *==========================================================================*/
4713int32_t mm_stream_calc_offset(mm_stream_t *my_obj)
4714{
4715    int32_t rc = 0;
4716    uint32_t i;
4717
4718    cam_dimension_t dim = my_obj->stream_info->dim;
4719    if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION &&
4720        my_obj->stream_info->stream_type != CAM_STREAM_TYPE_VIDEO) {
4721        if (my_obj->stream_info->pp_config.rotation == ROTATE_90 ||
4722            my_obj->stream_info->pp_config.rotation == ROTATE_270) {
4723            // rotated by 90 or 270, need to switch width and height
4724            dim.width = my_obj->stream_info->dim.height;
4725            dim.height = my_obj->stream_info->dim.width;
4726        }
4727    }
4728
4729    switch (my_obj->stream_info->stream_type) {
4730    case CAM_STREAM_TYPE_PREVIEW:
4731        rc = mm_stream_calc_offset_preview(my_obj->stream_info,
4732                                           &dim,
4733                                           &my_obj->padding_info,
4734                                           &my_obj->stream_info->buf_planes);
4735        break;
4736    case CAM_STREAM_TYPE_POSTVIEW:
4737      rc = mm_stream_calc_offset_post_view(my_obj->stream_info,
4738                                         &dim,
4739                                         &my_obj->padding_info,
4740                                         &my_obj->stream_info->buf_planes);
4741      break;
4742    case CAM_STREAM_TYPE_SNAPSHOT:
4743    case CAM_STREAM_TYPE_CALLBACK:
4744        rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt,
4745                                            &dim,
4746                                            &my_obj->padding_info,
4747                                            &my_obj->stream_info->buf_planes);
4748        break;
4749    case CAM_STREAM_TYPE_OFFLINE_PROC:
4750        rc = mm_stream_calc_offset_postproc(my_obj->stream_info,
4751                                            &my_obj->padding_info,
4752                                            &my_obj->stream_info->buf_planes);
4753        break;
4754    case CAM_STREAM_TYPE_VIDEO:
4755        rc = mm_stream_calc_offset_video(my_obj->stream_info->fmt,
4756                &dim, &my_obj->stream_info->buf_planes);
4757        break;
4758    case CAM_STREAM_TYPE_RAW:
4759        rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt,
4760                                       &dim,
4761                                       &my_obj->padding_info,
4762                                       &my_obj->stream_info->buf_planes);
4763        break;
4764    case CAM_STREAM_TYPE_ANALYSIS:
4765        rc = mm_stream_calc_offset_analysis(my_obj->stream_info->fmt,
4766                                            &dim,
4767                                            &my_obj->padding_info,
4768                                            &my_obj->stream_info->buf_planes);
4769        break;
4770    case CAM_STREAM_TYPE_METADATA:
4771        rc = mm_stream_calc_offset_metadata(&dim,
4772                                            &my_obj->padding_info,
4773                                            &my_obj->stream_info->buf_planes);
4774        break;
4775    default:
4776        LOGE("not supported for stream type %d",
4777                    my_obj->stream_info->stream_type);
4778        rc = -1;
4779        break;
4780    }
4781
4782    my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info;
4783    LOGH("Stream type %d num_planes %d", my_obj->stream_info->stream_type,
4784            my_obj->frame_offset.num_planes);
4785    for (i = 0; i < my_obj->frame_offset.num_planes; i++) {
4786        LOGH("Plane %d, stride %d, scanline %d, width %d, height %d, \
4787                length %d", i, my_obj->frame_offset.mp[i].stride,
4788                my_obj->frame_offset.mp[i].scanline,
4789                my_obj->frame_offset.mp[i].width,
4790                my_obj->frame_offset.mp[i].height,
4791                my_obj->frame_offset.mp[i].len);
4792    }
4793
4794    return rc;
4795}
4796
4797/*===========================================================================
4798 * FUNCTION   : mm_stream_sync_info
4799 *
4800 * DESCRIPTION: synchronize stream information with server
4801 *
4802 * PARAMETERS :
4803 *   @my_obj  : stream object
4804 *
4805 * RETURN     : int32_t type of status
4806 *              0  -- success
4807 *              -1 -- failure
4808 * NOTE       : assume stream info buffer is mapped to server and filled in with
4809 *              stream information by upper layer. This call will let server to
4810 *              synchornize the stream information with HAL. If server find any
4811 *              fields that need to be changed accroding to hardware configuration,
4812 *              server will modify corresponding fields so that HAL could know
4813 *              about it.
4814 *==========================================================================*/
4815int32_t mm_stream_sync_info(mm_stream_t *my_obj)
4816{
4817    int32_t rc = 0;
4818    int32_t value = 0;
4819    my_obj->stream_info->stream_svr_id = my_obj->server_stream_id;
4820    rc = mm_stream_calc_offset(my_obj);
4821
4822    if (rc == 0) {
4823        mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
4824        int stream_id  =  my_obj->server_stream_id;
4825        rc = mm_camera_util_s_ctrl(cam_obj, stream_id, my_obj->fd,
4826                CAM_PRIV_STREAM_INFO_SYNC, &value);
4827    }
4828    return rc;
4829}
4830
4831/*===========================================================================
4832 * FUNCTION   : mm_stream_set_fmt
4833 *
4834 * DESCRIPTION: set stream format to kernel via v4l2 ioctl
4835 *
4836 * PARAMETERS :
4837 *   @my_obj  : stream object
4838 *
4839 * RETURN     : int32_t type of status
4840 *              0  -- success
4841 *              -1 -- failure
4842 *==========================================================================*/
4843int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
4844{
4845    int32_t rc = 0;
4846    struct v4l2_format fmt;
4847    struct msm_v4l2_format_data msm_fmt;
4848    int i;
4849    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
4850          my_obj->my_hdl, my_obj->fd, my_obj->state);
4851
4852    if (my_obj->stream_info->dim.width == 0 ||
4853        my_obj->stream_info->dim.height == 0) {
4854        LOGE("invalid input[w=%d,h=%d,fmt=%d]\n",
4855                   my_obj->stream_info->dim.width,
4856                   my_obj->stream_info->dim.height,
4857                   my_obj->stream_info->fmt);
4858        return -1;
4859    }
4860
4861    memset(&fmt, 0, sizeof(fmt));
4862    memset(&msm_fmt, 0, sizeof(msm_fmt));
4863    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4864    msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4865
4866    msm_fmt.width = (unsigned int)my_obj->stream_info->dim.width;
4867    msm_fmt.height = (unsigned int)my_obj->stream_info->dim.height;
4868    msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt);
4869
4870    if (my_obj->stream_info->streaming_mode != CAM_STREAMING_MODE_BATCH) {
4871        msm_fmt.num_planes = (unsigned char)my_obj->frame_offset.num_planes;
4872        for (i = 0; i < msm_fmt.num_planes; i++) {
4873            msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len;
4874        }
4875    } else {
4876        msm_fmt.num_planes = 1;
4877        msm_fmt.plane_sizes[0] = my_obj->stream_info->user_buf_info.size;
4878    }
4879
4880    memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt));
4881    rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
4882    if (rc < 0) {
4883        LOGE("ioctl VIDIOC_S_FMT failed: rc=%d errno %d\n", rc, errno);
4884    } else {
4885#ifndef DAEMON_PRESENT
4886        mm_camera_obj_t *cam_obj = my_obj->ch_obj->cam_obj;
4887        cam_shim_packet_t *shim_cmd;
4888        cam_shim_cmd_data shim_cmd_data;
4889
4890        memset(&shim_cmd_data, 0, sizeof(shim_cmd_data));
4891        shim_cmd_data.command = MSM_CAMERA_PRIV_S_FMT;
4892        shim_cmd_data.stream_id = my_obj->server_stream_id;
4893        shim_cmd_data.value = NULL;
4894        shim_cmd = mm_camera_create_shim_cmd_packet(CAM_SHIM_SET_PARM,
4895                cam_obj->sessionid, &shim_cmd_data);
4896        rc = mm_camera_module_send_cmd(shim_cmd);
4897        mm_camera_destroy_shim_cmd_packet(shim_cmd);
4898#endif /* DAEMON_PRESENT */
4899    }
4900    return rc;
4901}
4902
4903/*===========================================================================
4904 * FUNCTION   : mm_stream_cancel_buf
4905 *
4906 * DESCRIPTION: Get buffer back from kernel
4907 *
4908 * PARAMETERS :
4909 *   @my_obj       : stream object
4910 *   @buf_idx        : frame index to be de-queued back from kernel
4911 *
4912 * RETURN     : int32_t type of status
4913 *              0  -- success
4914 *              -1 -- failure
4915 *==========================================================================*/
4916int32_t mm_stream_cancel_buf(mm_stream_t * my_obj,
4917                           uint32_t buf_idx)
4918{
4919    int32_t rc = 0;
4920    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
4921          my_obj->my_hdl, my_obj->fd, my_obj->state);
4922
4923    pthread_mutex_lock(&my_obj->buf_lock);
4924    if(my_obj->buf_status[buf_idx].buf_refcnt != 0) {
4925        LOGE("Error Trying to extract a frame already sent to HAL(idx=%d) count=%d\n",
4926                    buf_idx,
4927                   my_obj->buf_status[buf_idx].buf_refcnt);
4928        pthread_mutex_unlock(&my_obj->buf_lock);
4929        rc = -1;
4930        return rc;
4931    }
4932    pthread_mutex_unlock(&my_obj->buf_lock);
4933    if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) {
4934        /*rc = mm_stream_write_user_buf(my_obj, frame);*/
4935        // TODO handling batch buffers
4936    } else {
4937        pthread_mutex_lock(&my_obj->buf_lock);
4938        //my_obj->buf_status[buf_idx].buf_refcnt++;
4939        {
4940            pthread_mutex_unlock(&my_obj->buf_lock);
4941            LOGD("<DEBUG> : Cancel Buffer done for buffer:%d, stream type:%d", buf_idx, my_obj->stream_info->stream_type);
4942
4943            struct msm_camera_return_buf bufid;
4944            memset(&bufid, 0, sizeof(struct msm_camera_return_buf));
4945            bufid.index = buf_idx;
4946
4947            struct msm_camera_private_ioctl_arg arg;
4948            memset(&arg, 0, sizeof(struct msm_camera_private_ioctl_arg));
4949            arg.id = MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF;
4950            arg.size = sizeof(struct msm_camera_return_buf);
4951            arg.ioctl_ptr = (uint32_t) &bufid;
4952
4953
4954            rc = ioctl(my_obj->fd, VIDIOC_MSM_CAMERA_PRIVATE_IOCTL_CMD, &arg);
4955
4956            if(rc < 0) {
4957                LOGE("mm_stream_cancel_buf(idx=%d) err=%d\n",
4958                            buf_idx, rc);
4959            } else {
4960                //my_obj->buf_status[frame->buf_idx].in_kernel = 0;
4961            }
4962        }
4963    }
4964    return rc;
4965}
4966
4967
4968/*===========================================================================
4969 * FUNCTION   : mm_stream_buf_done
4970 *
4971 * DESCRIPTION: enqueue buffer back to kernel
4972 *
4973 * PARAMETERS :
4974 *   @my_obj       : stream object
4975 *   @frame        : frame to be enqueued back to kernel
4976 *
4977 * RETURN     : int32_t type of status
4978 *              0  -- success
4979 *              -1 -- failure
4980 *==========================================================================*/
4981int32_t mm_stream_buf_done(mm_stream_t * my_obj,
4982                           mm_camera_buf_def_t *frame)
4983{
4984    int32_t rc = 0;
4985    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
4986          my_obj->my_hdl, my_obj->fd, my_obj->state);
4987
4988    pthread_mutex_lock(&my_obj->buf_lock);
4989    if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
4990        LOGW("Warning: trying to free buffer for the second time?(idx=%d)\n",
4991                    frame->buf_idx);
4992        pthread_mutex_unlock(&my_obj->buf_lock);
4993        rc = -1;
4994        return rc;
4995    }
4996    pthread_mutex_unlock(&my_obj->buf_lock);
4997    if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) {
4998        rc = mm_stream_write_user_buf(my_obj, frame);
4999    } else {
5000        pthread_mutex_lock(&my_obj->buf_lock);
5001        my_obj->buf_status[frame->buf_idx].buf_refcnt--;
5002        if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
5003            pthread_mutex_unlock(&my_obj->buf_lock);
5004            LOGD("<DEBUG> : Buf done for buffer:%d, stream:%d", frame->buf_idx, frame->stream_type);
5005            rc = mm_stream_qbuf(my_obj, frame);
5006            if(rc < 0) {
5007                LOGE("mm_camera_stream_qbuf(idx=%d) err=%d\n",
5008                            frame->buf_idx, rc);
5009            } else {
5010                my_obj->buf_status[frame->buf_idx].in_kernel = 1;
5011            }
5012        }else{
5013            LOGD("<DEBUG> : Still ref count pending count :%d",
5014                 my_obj->buf_status[frame->buf_idx].buf_refcnt);
5015            LOGD("<DEBUG> : for buffer:%p:%d",
5016                 my_obj, frame->buf_idx);
5017            pthread_mutex_unlock(&my_obj->buf_lock);
5018        }
5019    }
5020    return rc;
5021}
5022
5023
5024/*===========================================================================
5025 * FUNCTION   : mm_stream_get_queued_buf_count
5026 *
5027 * DESCRIPTION: return queued buffer count
5028 *
5029 * PARAMETERS :
5030 *   @my_obj       : stream object
5031 *
5032 * RETURN     : queued buffer count
5033 *==========================================================================*/
5034int32_t mm_stream_get_queued_buf_count(mm_stream_t *my_obj)
5035{
5036    int32_t rc = 0;
5037    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
5038             my_obj->my_hdl, my_obj->fd, my_obj->state);
5039    pthread_mutex_lock(&my_obj->buf_lock);
5040    rc = my_obj->queued_buffer_count;
5041    pthread_mutex_unlock(&my_obj->buf_lock);
5042    return rc;
5043}
5044
5045/*===========================================================================
5046 * FUNCTION   : mm_stream_reg_buf_cb
5047 *
5048 * DESCRIPTION: Allow other stream to register dataCB at this stream.
5049 *
5050 * PARAMETERS :
5051 *   @my_obj       : stream object
5052 *   @val          : callback function to be registered
5053 *
5054 * RETURN     : int32_t type of status
5055 *              0  -- success
5056 *              -1 -- failure
5057 *==========================================================================*/
5058int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
5059        mm_stream_data_cb_t val)
5060{
5061    int32_t rc = -1;
5062    uint8_t i;
5063    LOGD("E, my_handle = 0x%x, fd = %d, state = %d",
5064          my_obj->my_hdl, my_obj->fd, my_obj->state);
5065
5066    pthread_mutex_lock(&my_obj->cb_lock);
5067    for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
5068        if(NULL == my_obj->buf_cb[i].cb) {
5069            my_obj->buf_cb[i] = val;
5070            rc = 0;
5071            break;
5072        }
5073    }
5074    pthread_mutex_unlock(&my_obj->cb_lock);
5075
5076    return rc;
5077}
5078
5079/*===========================================================================
5080 * FUNCTION   : mm_stream_handle_cache_ops
5081 *
5082 * DESCRIPTION: handles cache ops of a stream buffer
5083 *
5084 * PARAMETERS :
5085 *   @my_obj       : stream object
5086 *   @buf     : ptr to a stream buffer
5087 *   @deque  : specifies if enqueue or dequeue
5088 *
5089 * RETURN     : zero for success
5090 *                  non-zero error value
5091 *==========================================================================*/
5092int32_t mm_stream_handle_cache_ops(mm_stream_t* my_obj,
5093        mm_camera_buf_def_t* buf, bool deque)
5094{
5095    int32_t rc = 0;
5096    if(!my_obj || !buf) {
5097        LOGE("Error!! my_obj: %p, buf_info: %p", my_obj, buf);
5098        rc = -1;
5099        return rc;
5100    }
5101    if ((my_obj->mem_vtbl.clean_invalidate_buf  == NULL) ||
5102            (my_obj->mem_vtbl.invalidate_buf  == NULL) ||
5103            (my_obj->mem_vtbl.clean_buf  == NULL)) {
5104        LOGI("Clean/Invalidate cache ops not supported %p %p %p",
5105            my_obj->mem_vtbl.clean_invalidate_buf,
5106            my_obj->mem_vtbl.invalidate_buf,
5107            my_obj->mem_vtbl.clean_buf);
5108        // Not a fatal error
5109        rc = 0;
5110        return rc;
5111    }
5112
5113    // Modify clean and invalidate flags depending on cache ops for stream
5114    switch (my_obj->stream_info->cache_ops) {
5115        case CAM_STREAM_CACHE_OPS_CLEAR_FLAGS:
5116            buf->cache_flags = 0;
5117            break;
5118        case CAM_STREAM_CACHE_OPS_DISABLED:
5119            if (deque) {
5120                buf->cache_flags = CPU_HAS_READ_WRITTEN;
5121            }
5122            else {
5123                buf->cache_flags = CPU_HAS_READ;
5124            }
5125        case CAM_STREAM_CACHE_OPS_HONOUR_FLAGS:
5126        default:
5127            // Do not change flags
5128            break;
5129    }
5130
5131    if ((buf->cache_flags & CPU_HAS_READ_WRITTEN) ==
5132        CPU_HAS_READ_WRITTEN) {
5133        rc = my_obj->mem_vtbl.clean_invalidate_buf(
5134                buf->buf_idx, my_obj->mem_vtbl.user_data);
5135    } else if ((buf->cache_flags & CPU_HAS_READ) ==
5136        CPU_HAS_READ) {
5137        rc = my_obj->mem_vtbl.invalidate_buf(
5138                buf->buf_idx, my_obj->mem_vtbl.user_data);
5139    } else if ((buf->cache_flags & CPU_HAS_WRITTEN) ==
5140        CPU_HAS_WRITTEN) {
5141        rc = my_obj->mem_vtbl.clean_buf(
5142                buf->buf_idx, my_obj->mem_vtbl.user_data);
5143    }
5144
5145    LOGH("[CACHE_OPS] Stream type: %d buf index: %d cache ops flags: 0x%x",
5146            buf->stream_type, buf->buf_idx, buf->cache_flags);
5147
5148    if (rc != 0) {
5149        LOGE("Clean/Invalidate cache failed on buffer index: %d",
5150                buf->buf_idx);
5151    } else {
5152       // Reset buffer cache flags after cache ops
5153        buf->cache_flags = 0;
5154    }
5155
5156    return rc;
5157}
5158
5159