1/*
2Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7    * Redistributions of source code must retain the above copyright
8      notice, this list of conditions and the following disclaimer.
9    * Redistributions in binary form must reproduce the above
10      copyright notice, this list of conditions and the following
11      disclaimer in the documentation and/or other materials provided
12      with the distribution.
13    * Neither the name of Code Aurora Forum, Inc. nor the names of its
14      contributors may be used to endorse or promote products derived
15      from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#include <pthread.h>
31#include "mm_camera_dbg.h"
32#include <errno.h>
33#include <linux/msm_ion.h>
34#include <sys/ioctl.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <fcntl.h>
38#include <poll.h>
39#include "mm_camera_interface2.h"
40#include "mm_camera.h"
41
42#if 0
43#undef CDBG
44#define CDBG ALOGV
45#endif
46/* static functions prototype declarations */
47static int mm_camera_channel_skip_frames(mm_camera_obj_t *my_obj,
48                                          mm_camera_frame_queue_t *mq,
49                                          mm_camera_frame_queue_t *sq,
50                                          mm_camera_stream_t *mstream,
51                                          mm_camera_stream_t *sstream,
52                                          mm_camera_channel_attr_buffering_frame_t *frame_attr);
53static int mm_camera_channel_get_starting_frame(mm_camera_obj_t *my_obj,
54                                                mm_camera_ch_t *ch,
55                                                mm_camera_stream_t *mstream,
56                                                mm_camera_stream_t *sstream,
57                                                mm_camera_frame_queue_t *mq,
58                                                mm_camera_frame_queue_t *sq,
59                                                mm_camera_frame_t **mframe,
60                                                mm_camera_frame_t **sframe);
61static int mm_camera_ch_search_frame_based_on_time(mm_camera_obj_t *my_obj,
62                                                   mm_camera_ch_t *ch,
63                                                   mm_camera_stream_t *mstream,
64                                                   mm_camera_stream_t *sstream,
65                                                   mm_camera_frame_queue_t *mq,
66                                                   mm_camera_frame_queue_t *sq,
67                                                   mm_camera_frame_t **mframe,
68                                                   mm_camera_frame_t **sframe);
69
70
71
72int mm_camera_ch_util_get_num_stream(mm_camera_obj_t * my_obj,mm_camera_channel_type_t ch_type)
73{
74    int num = 0;
75    switch(ch_type) {
76    case MM_CAMERA_CH_RAW:
77        num =  1;
78        break;
79    case MM_CAMERA_CH_PREVIEW:
80        num =  1;
81        break;
82    case MM_CAMERA_CH_VIDEO:
83        num =  1;
84        if(my_obj->ch[ch_type].video.has_main) {
85            num +=  1;
86        }
87        break;
88    case MM_CAMERA_CH_SNAPSHOT:
89        num =  2;
90        break;
91    default:
92        break;
93    }
94    return num;
95}
96
97void mm_camera_ch_util_get_stream_objs(mm_camera_obj_t * my_obj,
98                                       mm_camera_channel_type_t ch_type,
99                                       mm_camera_stream_t **stream1,
100                                       mm_camera_stream_t **stream2)
101{
102    *stream1 = NULL;
103    *stream2 = NULL;
104
105    switch(ch_type) {
106    case MM_CAMERA_CH_RAW:
107        *stream1 = &my_obj->ch[ch_type].raw.stream;
108        break;
109    case MM_CAMERA_CH_PREVIEW:
110        *stream1 = &my_obj->ch[ch_type].preview.stream;
111        break;
112    case MM_CAMERA_CH_VIDEO:
113        *stream1 = &my_obj->ch[ch_type].video.video;
114        if(my_obj->ch[ch_type].video.has_main) {
115            *stream2 = &my_obj->ch[ch_type].video.main;
116        }
117        break;
118    case MM_CAMERA_CH_SNAPSHOT:
119        *stream1 = &my_obj->ch[ch_type].snapshot.main;
120        if (!my_obj->full_liveshot)
121            *stream2 = &my_obj->ch[ch_type].snapshot.thumbnail;
122        break;
123    default:
124        break;
125    }
126}
127
128static int32_t mm_camera_ch_util_set_fmt(mm_camera_obj_t * my_obj,
129                                         mm_camera_channel_type_t ch_type,
130                                         mm_camera_ch_image_fmt_parm_t *fmt)
131{
132    int32_t rc = MM_CAMERA_OK;
133    mm_camera_stream_t *stream1 = NULL;
134    mm_camera_stream_t *stream2 = NULL;
135    mm_camera_image_fmt_t *fmt1 = NULL;
136    mm_camera_image_fmt_t *fmt2 = NULL;
137
138    switch(ch_type) {
139    case MM_CAMERA_CH_RAW:
140        stream1 = &my_obj->ch[ch_type].raw.stream;
141        fmt1 = &fmt->def;
142        break;
143    case MM_CAMERA_CH_PREVIEW:
144        stream1 = &my_obj->ch[ch_type].preview.stream;
145        fmt1 = &fmt->def;
146        break;
147    case MM_CAMERA_CH_VIDEO:
148        stream1 = &my_obj->ch[ch_type].video.video;
149        fmt1 = &fmt->video.video;
150        if(my_obj->ch[ch_type].video.has_main) {
151            CDBG("%s:video channel has main image stream\n", __func__);
152            stream2 = &my_obj->ch[ch_type].video.main;
153            fmt2 = &fmt->video.main;
154        }
155        break;
156    case MM_CAMERA_CH_SNAPSHOT:
157        stream1 = &my_obj->ch[ch_type].snapshot.main;
158        fmt1 = &fmt->snapshot.main;
159        if (!my_obj->full_liveshot) {
160            stream2 = &my_obj->ch[ch_type].snapshot.thumbnail;
161            fmt2 = &fmt->snapshot.thumbnail;
162        }
163        break;
164    default:
165        rc = -1;
166        break;
167    }
168    CDBG("%s:ch=%d, streams[0x%x,0x%x]\n", __func__, ch_type,
169             (uint32_t)stream1, (uint32_t)stream2);
170    if(stream1)
171        rc = mm_camera_stream_fsm_fn_vtbl(my_obj, stream1,
172                         MM_CAMERA_STATE_EVT_SET_FMT, fmt1);
173    if(stream2 && !rc)
174        rc = mm_camera_stream_fsm_fn_vtbl(my_obj, stream2,
175                         MM_CAMERA_STATE_EVT_SET_FMT, fmt2);
176    return rc;
177}
178
179static int32_t mm_camera_ch_util_acquire(mm_camera_obj_t * my_obj,
180                                         mm_camera_channel_type_t ch_type)
181{
182    int32_t rc = MM_CAMERA_OK;
183    mm_camera_stream_t *stream1 = NULL;
184    mm_camera_stream_t *stream2 = NULL;
185    mm_camera_stream_type_t type1;
186    mm_camera_stream_type_t type2;
187
188    if(my_obj->ch[ch_type].acquired) {
189        rc = MM_CAMERA_OK;
190        goto end;
191    }
192    pthread_mutex_init(&my_obj->ch[ch_type].mutex, NULL);
193    switch(ch_type) {
194    case MM_CAMERA_CH_RAW:
195        stream1 = &my_obj->ch[ch_type].raw.stream;
196        type1 = MM_CAMERA_STREAM_RAW;
197        break;
198    case MM_CAMERA_CH_PREVIEW:
199        stream1 = &my_obj->ch[ch_type].preview.stream;
200        type1 = MM_CAMERA_STREAM_PREVIEW;
201        break;
202    case MM_CAMERA_CH_VIDEO:
203        stream1 = &my_obj->ch[ch_type].video.video;
204        type1 = MM_CAMERA_STREAM_VIDEO;
205        /* no full image live shot by default */
206        my_obj->ch[ch_type].video.has_main = FALSE;
207        break;
208    case MM_CAMERA_CH_SNAPSHOT:
209        stream1 = &my_obj->ch[ch_type].snapshot.main;
210        type1 = MM_CAMERA_STREAM_SNAPSHOT;
211        if (!my_obj->full_liveshot) {
212            stream2 = &my_obj->ch[ch_type].snapshot.thumbnail;
213            type2 = MM_CAMERA_STREAM_THUMBNAIL;
214        }
215        break;
216    default:
217        return -1;
218        break;
219    }
220    if(stream1) rc = mm_camera_stream_fsm_fn_vtbl(my_obj, stream1,
221                                            MM_CAMERA_STATE_EVT_ACQUIRE, &type1);
222    if(stream2 && !rc) rc = mm_camera_stream_fsm_fn_vtbl(my_obj, stream2,
223                                            MM_CAMERA_STATE_EVT_ACQUIRE, &type2);
224    if(rc == MM_CAMERA_OK) {
225        if(!my_obj->ch[ch_type].acquired)    my_obj->ch[ch_type].acquired = TRUE;
226    }
227
228end:
229    return rc;
230}
231
232static int32_t mm_camera_ch_util_release(mm_camera_obj_t * my_obj,
233                                         mm_camera_channel_type_t ch_type,
234                                         mm_camera_state_evt_type_t evt)
235{
236    mm_camera_stream_t *stream1, *stream2;
237
238    if(!my_obj->ch[ch_type].acquired) return MM_CAMERA_OK;
239
240    mm_camera_ch_util_get_stream_objs(my_obj,ch_type, &stream1, &stream2);
241    if(stream1)
242        mm_camera_stream_fsm_fn_vtbl(my_obj, stream1, evt, NULL);
243    if(stream2)
244        mm_camera_stream_fsm_fn_vtbl(my_obj, stream2, evt, NULL);
245    pthread_mutex_destroy(&my_obj->ch[ch_type].mutex);
246    memset(&my_obj->ch[ch_type],0,sizeof(my_obj->ch[ch_type]));
247    return 0;
248}
249
250static int32_t mm_camera_ch_util_stream_null_val(mm_camera_obj_t * my_obj,
251                                                 mm_camera_channel_type_t ch_type,
252                                                            mm_camera_state_evt_type_t evt, void *val)
253{
254        int32_t rc = 0;
255        switch(ch_type) {
256        case MM_CAMERA_CH_RAW:
257            rc = mm_camera_stream_fsm_fn_vtbl(my_obj, &my_obj->ch[ch_type].raw.stream,
258                                              evt, NULL);
259            break;
260        case MM_CAMERA_CH_PREVIEW:
261            rc = mm_camera_stream_fsm_fn_vtbl(my_obj, &my_obj->ch[ch_type].preview.stream,
262                                              evt, NULL);
263            break;
264        case MM_CAMERA_CH_VIDEO:
265            rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
266                            &my_obj->ch[ch_type].video.video, evt,
267                            NULL);
268            if(!rc && my_obj->ch[ch_type].video.main.fd)
269                rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
270                                &my_obj->ch[ch_type].video.main, evt,
271                                NULL);
272            break;
273        case MM_CAMERA_CH_SNAPSHOT:
274            my_obj->ch[ch_type].snapshot.expected_matching_id = 0;
275            rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
276                            &my_obj->ch[ch_type].snapshot.main, evt,
277                            NULL);
278            if(!rc && !my_obj->full_liveshot)
279                rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
280                                &my_obj->ch[ch_type].snapshot.thumbnail, evt,
281                                NULL);
282            break;
283        default:
284            CDBG_ERROR("%s: Invalid ch_type=%d", __func__, ch_type);
285            rc = -1;
286            break;
287        }
288        return rc;
289}
290
291static int32_t mm_camera_ch_util_reg_buf(mm_camera_obj_t * my_obj,
292                                         mm_camera_channel_type_t ch_type,
293                                         mm_camera_state_evt_type_t evt, void *val)
294{
295        int32_t rc = 0;
296        switch(ch_type) {
297        case MM_CAMERA_CH_RAW:
298            rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
299                                             &my_obj->ch[ch_type].raw.stream, evt,
300                                             (mm_camera_buf_def_t *)val);
301            break;
302        case MM_CAMERA_CH_PREVIEW:
303            rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
304                                             &my_obj->ch[ch_type].preview.stream, evt,
305                                             (mm_camera_buf_def_t *)val);
306            break;
307        case MM_CAMERA_CH_VIDEO:
308            {
309                mm_camera_buf_video_t * buf = (mm_camera_buf_video_t *)val;
310                rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
311                                &my_obj->ch[ch_type].video.video, evt,
312                                &buf->video);
313                if(!rc && my_obj->ch[ch_type].video.has_main) {
314                    rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
315                                    &my_obj->ch[ch_type].video.main, evt,
316                                    &buf->main);
317                }
318            }
319            break;
320        case MM_CAMERA_CH_SNAPSHOT:
321            {
322                mm_camera_buf_snapshot_t * buf = (mm_camera_buf_snapshot_t *)val;
323                rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
324                                &my_obj->ch[ch_type].snapshot.main, evt,
325                                &buf->main);
326                if(!rc && !my_obj->full_liveshot) {
327                    rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
328                                    &my_obj->ch[ch_type].snapshot.thumbnail, evt,
329                                    & buf->thumbnail);
330                }
331            }
332            break;
333        default:
334            return -1;
335            break;
336        }
337        return rc;
338}
339
340static int32_t mm_camera_ch_util_attr(mm_camera_obj_t *my_obj,
341                                      mm_camera_channel_type_t ch_type,
342                                      mm_camera_channel_attr_t *val)
343{
344    int rc = -MM_CAMERA_E_NOT_SUPPORTED;
345    /*if(ch_type != MM_CAMERA_CH_RAW) {
346        CDBG("%s: attr type %d not support for ch %d\n", __func__, val->type, ch_type);
347        return rc;
348    }*/
349    if(my_obj->ch[ch_type].acquired== 0) {
350      CDBG_ERROR("%s Channel %d not yet acquired ", __func__, ch_type);
351      return -MM_CAMERA_E_INVALID_OPERATION;
352    }
353    switch(val->type) {
354    case MM_CAMERA_CH_ATTR_RAW_STREAMING_TYPE:
355        if(val->raw_streaming_mode == MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE) {
356            my_obj->ch[ch_type].raw.mode = val->raw_streaming_mode;
357            rc = MM_CAMERA_OK;
358        }
359        break;
360    case MM_CAMERA_CH_ATTR_BUFFERING_FRAME:
361      /* it's good to check the stream state. TBD later  */
362      memcpy(&my_obj->ch[ch_type].buffering_frame, &val->buffering_frame, sizeof(val->buffering_frame));
363      break;
364    default:
365        break;
366    }
367    return MM_CAMERA_OK;
368}
369
370static int32_t mm_camera_ch_util_reg_buf_cb(mm_camera_obj_t *my_obj,
371                                            mm_camera_channel_type_t ch_type,
372                                            mm_camera_buf_cb_t *val)
373{
374    /* TODOhere: Need to return failure in case of MAX Cb registered
375     * but in order to return fail case need to set up rc.
376     * but the rc value needs to be thread safe
377     */
378    int i;
379    ALOGV("%s: Trying to register",__func__);
380//    pthread_mutex_lock(&my_obj->ch[ch_type].mutex);
381    for( i=0 ;i < MM_CAMERA_BUF_CB_MAX; i++ ) {
382        if(my_obj->ch[ch_type].buf_cb[i].cb==NULL) {
383            memcpy(&my_obj->ch[ch_type].buf_cb[i],val,sizeof(mm_camera_buf_cb_t));
384            break;
385        }
386    }
387//    pthread_mutex_unlock(&my_obj->ch[ch_type].mutex);
388    ALOGV("%s: Done register",__func__);
389    return MM_CAMERA_OK;
390}
391
392static int32_t mm_camera_ch_util_qbuf(mm_camera_obj_t *my_obj,
393                                    mm_camera_channel_type_t ch_type,
394                                    mm_camera_state_evt_type_t evt,
395                                    mm_camera_ch_data_buf_t *val)
396{
397    int32_t rc = -1;
398    mm_camera_stream_t *stream;
399    struct ion_flush_data cache_inv_data;
400    int ion_fd;
401    struct msm_frame *cache_frame;
402    struct msm_frame *cache_frame1 = NULL;
403
404    CDBG("<DEBUG>: %s:ch_type:%d",__func__,ch_type);
405    switch(ch_type) {
406    case MM_CAMERA_CH_RAW:
407        rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
408                                          &my_obj->ch[ch_type].raw.stream, evt,
409                                                                     &val->def);
410        cache_frame = val->def.frame;
411        break;
412    case MM_CAMERA_CH_PREVIEW:
413        rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
414                                         &my_obj->ch[ch_type].preview.stream, evt,
415                                         &val->def);
416        cache_frame = val->def.frame;
417        CDBG("buffer fd = %d, length = %d, vaddr = %p\n",
418         val->def.frame->fd, val->def.frame->ion_alloc.len, val->def.frame->buffer);
419        break;
420    case MM_CAMERA_CH_VIDEO:
421        {
422            rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
423                            &my_obj->ch[ch_type].video.video, evt,
424                            &val->video.video);
425            cache_frame = val->video.video.frame;
426            CDBG("buffer fd = %d, length = %d, vaddr = %p\n",
427                 val->video.video.frame->fd, val->video.video.frame->ion_alloc.len, val->video.video.frame->buffer);
428
429            if(!rc && val->video.main.frame) {
430                rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
431                                &my_obj->ch[ch_type].video.main, evt,
432                                &val->video.main);
433                cache_frame1 = val->video.main.frame;
434            }
435        }
436        break;
437    case MM_CAMERA_CH_SNAPSHOT:
438        {
439            rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
440                            &my_obj->ch[ch_type].snapshot.main, evt,
441                            &val->snapshot.main);
442            cache_frame = val->snapshot.main.frame;
443            CDBG("buffer fd = %d, length = %d, vaddr = %p\n",
444                 val->snapshot.main.frame->fd, val->snapshot.main.frame->ion_alloc.len, val->snapshot.main.frame->buffer);
445            if(!rc) {
446                if (my_obj->op_mode == MM_CAMERA_OP_MODE_ZSL)
447                  stream = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream;
448                else
449                  stream = &my_obj->ch[ch_type].snapshot.thumbnail;
450                rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
451                                stream, evt,
452                                &val->snapshot.thumbnail);
453                cache_frame1 = val->snapshot.thumbnail.frame;
454                CDBG("buffer fd = %d, length = %d, vaddr = %p\n",
455                 val->snapshot.thumbnail.frame->fd, val->snapshot.thumbnail.frame->ion_alloc.len, val->snapshot.thumbnail.frame->buffer);
456            }
457        }
458        break;
459    default:
460        return -1;
461        break;
462    }
463#ifdef USE_ION
464    cache_inv_data.vaddr = cache_frame->buffer;
465    cache_inv_data.fd = cache_frame->fd;
466    cache_inv_data.handle = cache_frame->fd_data.handle;
467    cache_inv_data.length = cache_frame->ion_alloc.len;
468    ion_fd = cache_frame->ion_dev_fd;
469    if(ion_fd > 0) {
470        if(ioctl(ion_fd, ION_IOC_INV_CACHES, &cache_inv_data) < 0)
471            CDBG_ERROR("%s: Cache Invalidate failed\n", __func__);
472        else {
473            CDBG("%s: Successful cache invalidate\n", __func__);
474            if(cache_frame1) {
475              ion_fd = cache_frame1->ion_dev_fd;
476              cache_inv_data.vaddr = cache_frame1->buffer;
477              cache_inv_data.fd = cache_frame1->fd;
478              cache_inv_data.handle = cache_frame1->fd_data.handle;
479              cache_inv_data.length = cache_frame1->ion_alloc.len;
480              if(ioctl(ion_fd, ION_IOC_INV_CACHES, &cache_inv_data) < 0)
481                CDBG_ERROR("%s: Cache Invalidate failed\n", __func__);
482              else
483                CDBG("%s: Successful cache invalidate\n", __func__);
484            }
485        }
486    }
487#endif
488
489    return rc;
490}
491
492static int mm_camera_ch_util_get_crop(mm_camera_obj_t *my_obj,
493                                mm_camera_channel_type_t ch_type,
494                                mm_camera_state_evt_type_t evt,
495                                mm_camera_ch_crop_t *crop)
496{
497    int rc = MM_CAMERA_OK;
498    switch(ch_type) {
499    case MM_CAMERA_CH_RAW:
500        rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
501                                       &my_obj->ch[ch_type].raw.stream, evt,
502                                       &crop->crop);
503        break;
504    case MM_CAMERA_CH_PREVIEW:
505        rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
506                                    &my_obj->ch[ch_type].preview.stream, evt,
507                                    &crop->crop);
508        break;
509    case MM_CAMERA_CH_VIDEO:
510        rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
511                          &my_obj->ch[ch_type].video.video, evt,
512                          &crop->crop);
513        break;
514    case MM_CAMERA_CH_SNAPSHOT:
515        {
516            rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
517                          &my_obj->ch[ch_type].snapshot.main, evt,
518                          &crop->snapshot.main_crop);
519            if(!rc && !my_obj->full_liveshot) {
520              ALOGV("%s: should not come here for Live Shot", __func__);
521              rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
522                              &my_obj->ch[ch_type].snapshot.thumbnail, evt,
523                              &crop->snapshot.thumbnail_crop);
524            }
525        }
526        break;
527    default:
528        return -1;
529        break;
530    }
531    return rc;
532}
533
534static int mm_camera_ch_util_dispatch_buffered_frame(mm_camera_obj_t *my_obj,
535                mm_camera_channel_type_t ch_type)
536{
537    return mm_camera_poll_dispatch_buffered_frames(my_obj, ch_type);
538}
539
540int mm_camera_channel_get_time_diff(struct timespec *cur_ts, int usec_target, struct timespec *frame_ts)
541{
542    int dtusec = (cur_ts->tv_nsec - frame_ts->tv_nsec)/1000;
543    dtusec += (cur_ts->tv_sec - frame_ts->tv_sec)*1000000 - usec_target;
544    return dtusec;
545}
546
547static int mm_camera_channel_skip_frames(mm_camera_obj_t *my_obj,
548                                          mm_camera_frame_queue_t *mq,
549                                          mm_camera_frame_queue_t *sq,
550                                          mm_camera_stream_t *mstream,
551                                          mm_camera_stream_t *sstream,
552                                          mm_camera_channel_attr_buffering_frame_t *frame_attr)
553{
554    int count = 0;
555    int i = 0;
556    mm_camera_frame_t *mframe = NULL, *sframe = NULL;
557    mm_camera_notify_frame_t notify_frame;
558
559    count = mm_camera_stream_frame_get_q_cnt(mq);
560    if(count < mm_camera_stream_frame_get_q_cnt(sq))
561        count = mm_camera_stream_frame_get_q_cnt(sq);
562    CDBG("%s: Q-size=%d, look_back =%d, M_match=%d, T_match=%d", __func__,
563         count, frame_attr->look_back, mq->match_cnt, sq->match_cnt);
564
565    count -= frame_attr->look_back;
566    CDBG("count=%d, frame_attr->look_back=%d,mq->match_cnt=%d, sq->match_cnt=%d",
567               count, frame_attr->look_back, mq->match_cnt,sq->match_cnt);
568    for(i=0; i < count; i++) {
569        mframe = mm_camera_stream_frame_deq(mq);
570        sframe = mm_camera_stream_frame_deq(sq);
571        if(mframe && sframe && mframe->frame.frame_id ==
572           sframe->frame.frame_id) {
573          mq->match_cnt--;
574          sq->match_cnt--;
575        }
576        if(mframe) {
577            notify_frame.frame = &mframe->frame;
578            notify_frame.idx = mframe->idx;
579            mm_camera_stream_util_buf_done(my_obj, mstream, &notify_frame);
580        }
581        if(sframe) {
582            notify_frame.frame = &sframe->frame;
583            notify_frame.idx = sframe->idx;
584            mm_camera_stream_util_buf_done(my_obj, sstream, &notify_frame);
585        }
586    }
587
588    CDBG("Post %s: Q-size=%d, look_back =%d, M_match=%d, T_match=%d", __func__,
589         count, frame_attr->look_back, mq->match_cnt, sq->match_cnt);
590    return MM_CAMERA_OK;
591}
592
593/*for ZSL mode to send the image pair to client*/
594void mm_camera_dispatch_buffered_frames(mm_camera_obj_t *my_obj,
595                                        mm_camera_channel_type_t ch_type)
596{
597    int mcnt, i, rc = MM_CAMERA_E_GENERAL, scnt;
598    int num_of_req_frame = 0;
599    int j;
600    mm_camera_ch_data_buf_t data;
601    mm_camera_frame_t *mframe = NULL, *sframe = NULL;
602    mm_camera_frame_t *qmframe = NULL, *qsframe = NULL;
603    mm_camera_ch_t *ch = &my_obj->ch[ch_type];
604    mm_camera_frame_queue_t *mq = NULL;
605    mm_camera_frame_queue_t *sq = NULL;
606    mm_camera_stream_t *stream1 = NULL;
607    mm_camera_stream_t *stream2 = NULL;
608    ALOGV("%s: E", __func__);
609    mm_camera_ch_util_get_stream_objs(my_obj, ch_type, &stream1, &stream2);
610    stream2 = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream;
611    if(stream1) {
612      mq = &stream1->frame.readyq;
613    }
614    if(stream2) {
615      sq = &stream2->frame.readyq;
616    }
617    CDBG("mq=%p, sq=%p, stream1=%p, stream2=%p", mq, sq, stream1, stream2);
618    pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
619    pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
620    if (mq && sq && stream1 && stream2) {
621        rc = mm_camera_channel_skip_frames(my_obj, mq, sq, stream1, stream2, &ch->buffering_frame);
622        if(rc != MM_CAMERA_OK) {
623            CDBG_ERROR("%s: Error getting right frame!", __func__);
624            goto end;
625        }
626        num_of_req_frame = my_obj->snap_burst_num_by_user;
627        ch->snapshot.pending_cnt = num_of_req_frame;
628
629        CDBG("num_of_req_frame =%d", num_of_req_frame);
630        for(i = 0; i < num_of_req_frame; i++) {
631            mframe = mm_camera_stream_frame_deq(mq);
632            sframe = mm_camera_stream_frame_deq(sq);
633            if(mframe && sframe) {
634                CDBG("%s: frame_id = 0x%x|0x%x, main idx = %d, thumbnail idx = %d", __func__,
635                     mframe->frame.frame_id, sframe->frame.frame_id, mframe->idx, sframe->idx);
636                if(mframe->frame.frame_id != sframe->frame.frame_id) {
637                    CDBG_ERROR("%s: ZSL algorithm error, main and thumbnail "
638                        "frame_ids not same. Need bug fix", __func__);
639                }
640                memset(&data, 0, sizeof(data));
641                data.type = ch_type;
642                data.snapshot.main.frame = &mframe->frame;
643                data.snapshot.main.idx = mframe->idx;
644                data.snapshot.thumbnail.frame = &sframe->frame;
645                data.snapshot.thumbnail.idx = sframe->idx;
646                ch->snapshot.pending_cnt--;
647                mq->match_cnt--;
648                sq->match_cnt--;
649                for(j=0;j<MM_CAMERA_BUF_CB_MAX;j++) {
650                    if( ch->buf_cb[j].cb!=NULL )
651                        ch->buf_cb[j].cb(&data, ch->buf_cb[j].user_data);
652                }
653            } else {
654               CDBG_ERROR("%s: mframe %p, sframe = %p", __func__, mframe, sframe);
655                qmframe = mframe;
656                qsframe = sframe;
657                rc = -1;
658                break;
659            }
660        }
661        if(qmframe) {
662            mm_camera_stream_frame_enq(mq, &stream1->frame.frame[qmframe->idx]);
663            qmframe = NULL;
664        }
665        if(qsframe) {
666            mm_camera_stream_frame_enq(sq, &stream2->frame.frame[qsframe->idx]);
667            qsframe = NULL;
668        }
669    } else {
670      CDBG_ERROR(" mq =%p sq =%p stream1 =%p stream2 =%p", mq, sq , stream1 , stream2);
671
672    }
673    CDBG("%s: burst number: %d, pending_count: %d", __func__,
674        my_obj->snap_burst_num_by_user, ch->snapshot.pending_cnt);
675end:
676    pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
677    pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
678    /* If we are done sending callbacks for all the requested number of snapshots
679       send data delivery done event*/
680    if((rc == MM_CAMERA_OK) && (!ch->snapshot.pending_cnt)) {
681        mm_camera_event_t data;
682        data.event_type = MM_CAMERA_EVT_TYPE_CH;
683        data.e.ch.evt = MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE;
684        data.e.ch.ch = ch_type;
685        mm_camera_poll_send_ch_event(my_obj, &data);
686    }
687}
688
689int32_t mm_camera_ch_fn(mm_camera_obj_t * my_obj,
690        mm_camera_channel_type_t ch_type,
691        mm_camera_state_evt_type_t evt, void *val)
692{
693    int32_t rc = MM_CAMERA_OK;
694
695    CDBG("%s:ch = %d, evt=%d\n", __func__, ch_type, evt);
696    switch(evt) {
697    case MM_CAMERA_STATE_EVT_ACQUIRE:
698        rc = mm_camera_ch_util_acquire(my_obj, ch_type);
699        break;
700    case MM_CAMERA_STATE_EVT_RELEASE:
701      /* safe code in case no stream off before release. */
702        //mm_camera_poll_thread_release(my_obj, ch_type);
703        rc = mm_camera_ch_util_release(my_obj, ch_type, evt);
704        break;
705    case MM_CAMERA_STATE_EVT_ATTR:
706        rc = mm_camera_ch_util_attr(my_obj, ch_type,
707                                    (mm_camera_channel_attr_t *)val);
708        break;
709    case MM_CAMERA_STATE_EVT_REG_BUF_CB:
710        rc = mm_camera_ch_util_reg_buf_cb(my_obj, ch_type,
711                                          (mm_camera_buf_cb_t *)val);
712        break;
713    case MM_CAMERA_STATE_EVT_SET_FMT:
714        rc = mm_camera_ch_util_set_fmt(my_obj, ch_type,
715                                       (mm_camera_ch_image_fmt_parm_t *)val);
716        break;
717    case MM_CAMERA_STATE_EVT_REG_BUF:
718    case MM_CAMERA_STATE_EVT_REQUEST_BUF:
719    case MM_CAMERA_STATE_EVT_ENQUEUE_BUF:
720        rc = mm_camera_ch_util_reg_buf(my_obj, ch_type, evt, val);
721        break;
722    case MM_CAMERA_STATE_EVT_UNREG_BUF:
723        rc = mm_camera_ch_util_stream_null_val(my_obj, ch_type, evt, NULL);
724        break;
725    case MM_CAMERA_STATE_EVT_STREAM_ON: {
726        if(ch_type == MM_CAMERA_CH_RAW &&
727             my_obj->ch[ch_type].raw.mode == MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE) {
728            if( MM_CAMERA_OK != (rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
729                MSM_V4L2_PID_CAM_MODE, MSM_V4L2_CAM_OP_RAW))) {
730                CDBG("%s:set MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE err=%d\n", __func__, rc);
731                break;
732            }
733        }
734        mm_camera_poll_thread_add_ch(my_obj, ch_type);
735        rc = mm_camera_ch_util_stream_null_val(my_obj, ch_type, evt, NULL);
736        if(rc < 0) {
737          CDBG_ERROR("%s: Failed in STREAM ON", __func__);
738          mm_camera_poll_thread_release(my_obj, ch_type);
739        }
740        break;
741    }
742    case MM_CAMERA_STATE_EVT_STREAM_OFF: {
743        mm_camera_poll_thread_del_ch(my_obj, ch_type);
744        rc = mm_camera_ch_util_stream_null_val(my_obj, ch_type, evt, NULL);
745        break;
746    }
747    case MM_CAMERA_STATE_EVT_QBUF:
748        rc = mm_camera_ch_util_qbuf(my_obj, ch_type, evt,
749                                    (mm_camera_ch_data_buf_t *)val);
750        break;
751    case MM_CAMERA_STATE_EVT_GET_CROP:
752      rc = mm_camera_ch_util_get_crop(my_obj, ch_type, evt,
753                                  (mm_camera_ch_crop_t *)val);
754      break;
755    case MM_CAMERA_STATE_EVT_DISPATCH_BUFFERED_FRAME:
756      rc = mm_camera_ch_util_dispatch_buffered_frame(my_obj, ch_type);
757      break;
758    default:
759        break;
760    }
761    return rc;
762}
763