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// Camera dependencies
31#include "mm_qcamera_app.h"
32#include "mm_qcamera_dbg.h"
33
34/* This callback is received once the complete JPEG encoding is done */
35static void jpeg_encode_cb(jpeg_job_status_t status,
36                           uint32_t client_hdl,
37                           uint32_t jobId,
38                           mm_jpeg_output_t *p_buf,
39                           void *userData)
40{
41    uint32_t i = 0;
42    mm_camera_test_obj_t *pme = NULL;
43    LOGD(" BEGIN\n");
44
45    pme = (mm_camera_test_obj_t *)userData;
46    if (pme->jpeg_hdl != client_hdl ||
47        jobId != pme->current_job_id ||
48        !pme->current_job_frames) {
49        LOGE(" NULL current job frames or not matching job ID (%d, %d)",
50                    jobId, pme->current_job_id);
51        return;
52    }
53
54    /* dump jpeg img */
55    LOGE(" job %d, status=%d",  jobId, status);
56    if (status == JPEG_JOB_STATUS_DONE && p_buf != NULL) {
57        mm_app_dump_jpeg_frame(p_buf->buf_vaddr, p_buf->buf_filled_len, "jpeg", "jpg", jobId);
58    }
59
60    /* buf done current encoding frames */
61    pme->current_job_id = 0;
62    for (i = 0; i < pme->current_job_frames->num_bufs; i++) {
63        if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->current_job_frames->camera_handle,
64                                                pme->current_job_frames->ch_id,
65                                                pme->current_job_frames->bufs[i])) {
66            LOGE(" Failed in Qbuf\n");
67        }
68        mm_app_cache_ops((mm_camera_app_meminfo_t *) pme->current_job_frames->bufs[i]->mem_info,
69                         ION_IOC_INV_CACHES);
70    }
71
72    free(pme->jpeg_buf.buf.buffer);
73    free(pme->current_job_frames);
74    pme->current_job_frames = NULL;
75
76    /* signal snapshot is done */
77    mm_camera_app_done();
78}
79
80int encodeData(mm_camera_test_obj_t *test_obj, mm_camera_super_buf_t* recvd_frame,
81               mm_camera_stream_t *m_stream)
82{
83    cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
84
85    int rc = -MM_CAMERA_E_GENERAL;
86    mm_jpeg_job_t job;
87
88    /* remember current frames being encoded */
89    test_obj->current_job_frames =
90        (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
91    if (!test_obj->current_job_frames) {
92        LOGE(" No memory for current_job_frames");
93        return rc;
94    }
95    *(test_obj->current_job_frames) = *recvd_frame;
96
97    memset(&job, 0, sizeof(job));
98    job.job_type = JPEG_JOB_TYPE_ENCODE;
99    job.encode_job.session_id = test_obj->current_jpeg_sess_id;
100
101    // TODO: Rotation should be set according to
102    //       sensor&device orientation
103    job.encode_job.rotation = 0;
104    if (cam_cap->position == CAM_POSITION_BACK) {
105        job.encode_job.rotation = 270;
106    }
107
108    /* fill in main src img encode param */
109    job.encode_job.main_dim.src_dim = m_stream->s_config.stream_info->dim;
110    job.encode_job.main_dim.dst_dim = m_stream->s_config.stream_info->dim;
111    job.encode_job.src_index = 0;
112
113    job.encode_job.thumb_dim.src_dim = m_stream->s_config.stream_info->dim;
114    job.encode_job.thumb_dim.dst_dim.width = DEFAULT_PREVIEW_WIDTH;
115    job.encode_job.thumb_dim.dst_dim.height = DEFAULT_PREVIEW_HEIGHT;
116
117    /* fill in sink img param */
118    job.encode_job.dst_index = 0;
119
120    if (test_obj->metadata != NULL) {
121        job.encode_job.p_metadata = test_obj->metadata;
122    } else {
123        LOGE(" Metadata null, not set for jpeg encoding");
124    }
125
126    rc = test_obj->jpeg_ops.start_job(&job, &test_obj->current_job_id);
127    if ( 0 != rc ) {
128        free(test_obj->current_job_frames);
129        test_obj->current_job_frames = NULL;
130    }
131
132    return rc;
133}
134
135int createEncodingSession(mm_camera_test_obj_t *test_obj,
136                          mm_camera_stream_t *m_stream,
137                          mm_camera_buf_def_t *m_frame)
138{
139    mm_jpeg_encode_params_t encode_param;
140
141    memset(&encode_param, 0, sizeof(mm_jpeg_encode_params_t));
142    encode_param.jpeg_cb = jpeg_encode_cb;
143    encode_param.userdata = (void*)test_obj;
144    encode_param.encode_thumbnail = 0;
145    encode_param.quality = 85;
146    encode_param.color_format = MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
147    encode_param.thumb_color_format = MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
148
149    /* fill in main src img encode param */
150    encode_param.num_src_bufs = 1;
151    encode_param.src_main_buf[0].index = 0;
152    encode_param.src_main_buf[0].buf_size = m_frame->frame_len;
153    encode_param.src_main_buf[0].buf_vaddr = (uint8_t *)m_frame->buffer;
154    encode_param.src_main_buf[0].fd = m_frame->fd;
155    encode_param.src_main_buf[0].format = MM_JPEG_FMT_YUV;
156    encode_param.src_main_buf[0].offset = m_stream->offset;
157
158    /* fill in sink img param */
159    encode_param.num_dst_bufs = 1;
160    encode_param.dest_buf[0].index = 0;
161    encode_param.dest_buf[0].buf_size = test_obj->jpeg_buf.buf.frame_len;
162    encode_param.dest_buf[0].buf_vaddr = (uint8_t *)test_obj->jpeg_buf.buf.buffer;
163    encode_param.dest_buf[0].fd = test_obj->jpeg_buf.buf.fd;
164    encode_param.dest_buf[0].format = MM_JPEG_FMT_YUV;
165
166    /* main dimension */
167    encode_param.main_dim.src_dim = m_stream->s_config.stream_info->dim;
168    encode_param.main_dim.dst_dim = m_stream->s_config.stream_info->dim;
169
170    return test_obj->jpeg_ops.create_session(test_obj->jpeg_hdl,
171                                             &encode_param,
172                                             &test_obj->current_jpeg_sess_id);
173}
174
175/** mm_app_snapshot_metadata_notify_cb
176 *  @bufs: Pointer to super buffer
177 *  @user_data: Pointer to user data
178 *
179 *
180 **/
181__unused
182static void mm_app_snapshot_metadata_notify_cb(mm_camera_super_buf_t *bufs,
183  void *user_data)
184{
185  uint32_t i = 0;
186  mm_camera_channel_t *channel = NULL;
187  mm_camera_stream_t *p_stream = NULL;
188  mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
189  mm_camera_buf_def_t *frame;
190  metadata_buffer_t *pMetadata;
191
192  if (NULL == bufs || NULL == user_data) {
193    LOGE(" bufs or user_data are not valid ");
194    return;
195  }
196  frame = bufs->bufs[0];
197
198  /* find channel */
199  for (i = 0; i < MM_CHANNEL_TYPE_MAX; i++) {
200    if (pme->channels[i].ch_id == bufs->ch_id) {
201      channel = &pme->channels[i];
202      break;
203    }
204  }
205
206  if (NULL == channel) {
207    LOGE(" Channel object is null");
208    return;
209  }
210
211  /* find meta stream */
212  for (i = 0; i < channel->num_streams; i++) {
213    if (channel->streams[i].s_config.stream_info->stream_type == CAM_STREAM_TYPE_METADATA) {
214      p_stream = &channel->streams[i];
215      break;
216    }
217  }
218
219  if (NULL == p_stream) {
220    LOGE(" cannot find metadata stream");
221    return;
222  }
223
224  /* find meta frame */
225  for (i = 0; i < bufs->num_bufs; i++) {
226    if (bufs->bufs[i]->stream_id == p_stream->s_id) {
227      frame = bufs->bufs[i];
228      break;
229    }
230  }
231
232  if (!pme->metadata) {
233    /* The app will free the metadata, we don't need to bother here */
234    pme->metadata = malloc(sizeof(metadata_buffer_t));
235    if (NULL == pme->metadata) {
236        LOGE(" malloc failed");
237        return;
238    }
239  }
240
241  memcpy(pme->metadata , frame->buffer, sizeof(metadata_buffer_t));
242
243  pMetadata = (metadata_buffer_t *)frame->buffer;
244
245  IF_META_AVAILABLE(cam_auto_focus_data_t, focus_data,
246        CAM_INTF_META_AUTOFOCUS_DATA, pMetadata) {
247    if (focus_data->focus_state == CAM_AF_STATE_FOCUSED_LOCKED) {
248      LOGE(" AutoFocus Done Call Back Received\n");
249      mm_camera_app_done();
250    } else if (focus_data->focus_state == CAM_AF_STATE_NOT_FOCUSED_LOCKED) {
251      LOGE(" AutoFocus failed\n");
252      mm_camera_app_done();
253    }
254  }
255
256  if (MM_CAMERA_OK != pme->cam->ops->qbuf(bufs->camera_handle,
257                                          bufs->ch_id,
258                                          frame)) {
259    LOGE(" Failed in Preview Qbuf\n");
260  }
261  mm_app_cache_ops((mm_camera_app_meminfo_t *)frame->mem_info,
262                   ION_IOC_INV_CACHES);
263}
264
265static void mm_app_snapshot_notify_cb_raw(mm_camera_super_buf_t *bufs,
266                                          void *user_data)
267{
268
269    int rc;
270    uint32_t i = 0;
271    mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
272    mm_camera_channel_t *channel = NULL;
273    mm_camera_stream_t *m_stream = NULL;
274    mm_camera_buf_def_t *m_frame = NULL;
275
276    LOGD(" BEGIN\n");
277
278    /* find channel */
279    for (i = 0; i < MM_CHANNEL_TYPE_MAX; i++) {
280        if (pme->channels[i].ch_id == bufs->ch_id) {
281            channel = &pme->channels[i];
282            break;
283        }
284    }
285    if (NULL == channel) {
286        LOGE(" Wrong channel id (%d)",  bufs->ch_id);
287        rc = -1;
288        goto EXIT;
289    }
290
291    /* find snapshot stream */
292    for (i = 0; i < channel->num_streams; i++) {
293        if (channel->streams[i].s_config.stream_info->stream_type == CAM_STREAM_TYPE_RAW) {
294            m_stream = &channel->streams[i];
295            break;
296        }
297    }
298    if (NULL == m_stream) {
299        LOGE(" cannot find snapshot stream");
300        rc = -1;
301        goto EXIT;
302    }
303
304    /* find snapshot frame */
305    for (i = 0; i < bufs->num_bufs; i++) {
306        if (bufs->bufs[i]->stream_id == m_stream->s_id) {
307            m_frame = bufs->bufs[i];
308            break;
309        }
310    }
311    if (NULL == m_frame) {
312        LOGE(" main frame is NULL");
313        rc = -1;
314        goto EXIT;
315    }
316
317    mm_app_dump_frame(m_frame, "main", "raw", m_frame->frame_idx);
318
319EXIT:
320    for (i=0; i<bufs->num_bufs; i++) {
321        if (MM_CAMERA_OK != pme->cam->ops->qbuf(bufs->camera_handle,
322                                                bufs->ch_id,
323                                                bufs->bufs[i])) {
324            LOGE(" Failed in Qbuf\n");
325        }
326    }
327
328    mm_camera_app_done();
329
330    LOGD(" END\n");
331}
332
333static void mm_app_snapshot_notify_cb(mm_camera_super_buf_t *bufs,
334                                      void *user_data)
335{
336
337    int rc = 0;
338    uint32_t i = 0;
339    mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
340    mm_camera_channel_t *channel = NULL;
341    mm_camera_stream_t *p_stream = NULL;
342    mm_camera_stream_t *m_stream = NULL;
343    mm_camera_buf_def_t *p_frame = NULL;
344    mm_camera_buf_def_t *m_frame = NULL;
345
346    /* find channel */
347    for (i = 0; i < MM_CHANNEL_TYPE_MAX; i++) {
348        if (pme->channels[i].ch_id == bufs->ch_id) {
349            channel = &pme->channels[i];
350            break;
351        }
352    }
353    if (NULL == channel) {
354        LOGE(" Wrong channel id (%d)",  bufs->ch_id);
355        rc = -1;
356        goto error;
357    }
358
359    /* find snapshot stream */
360    for (i = 0; i < channel->num_streams; i++) {
361        if (channel->streams[i].s_config.stream_info->stream_type == CAM_STREAM_TYPE_SNAPSHOT) {
362            m_stream = &channel->streams[i];
363            break;
364        }
365    }
366    if (NULL == m_stream) {
367        LOGE(" cannot find snapshot stream");
368        rc = -1;
369        goto error;
370    }
371
372    /* find snapshot frame */
373    for (i = 0; i < bufs->num_bufs; i++) {
374        if (bufs->bufs[i]->stream_id == m_stream->s_id) {
375            m_frame = bufs->bufs[i];
376            break;
377        }
378    }
379    if (NULL == m_frame) {
380        LOGE(" main frame is NULL");
381        rc = -1;
382        goto error;
383    }
384
385    mm_app_dump_frame(m_frame, "main", "yuv", m_frame->frame_idx);
386
387    /* find postview stream */
388    for (i = 0; i < channel->num_streams; i++) {
389        if (channel->streams[i].s_config.stream_info->stream_type == CAM_STREAM_TYPE_POSTVIEW) {
390            p_stream = &channel->streams[i];
391            break;
392        }
393    }
394    if (NULL != p_stream) {
395        /* find preview frame */
396        for (i = 0; i < bufs->num_bufs; i++) {
397            if (bufs->bufs[i]->stream_id == p_stream->s_id) {
398                p_frame = bufs->bufs[i];
399                break;
400            }
401        }
402        if (NULL != p_frame) {
403            mm_app_dump_frame(p_frame, "postview", "yuv", p_frame->frame_idx);
404        }
405    }
406
407    mm_app_cache_ops((mm_camera_app_meminfo_t *)m_frame->mem_info,
408                     ION_IOC_CLEAN_INV_CACHES);
409
410    pme->jpeg_buf.buf.buffer = (uint8_t *)malloc(m_frame->frame_len);
411    if ( NULL == pme->jpeg_buf.buf.buffer ) {
412        LOGE(" error allocating jpeg output buffer");
413        goto error;
414    }
415
416    pme->jpeg_buf.buf.frame_len = m_frame->frame_len;
417    /* create a new jpeg encoding session */
418    rc = createEncodingSession(pme, m_stream, m_frame);
419    if (0 != rc) {
420        LOGE(" error creating jpeg session");
421        free(pme->jpeg_buf.buf.buffer);
422        goto error;
423    }
424
425    /* start jpeg encoding job */
426    rc = encodeData(pme, bufs, m_stream);
427    if (0 != rc) {
428        LOGE(" error creating jpeg session");
429        free(pme->jpeg_buf.buf.buffer);
430        goto error;
431    }
432
433error:
434    /* buf done rcvd frames in error case */
435    if ( 0 != rc ) {
436        for (i=0; i<bufs->num_bufs; i++) {
437            if (MM_CAMERA_OK != pme->cam->ops->qbuf(bufs->camera_handle,
438                                                    bufs->ch_id,
439                                                    bufs->bufs[i])) {
440                LOGE(" Failed in Qbuf\n");
441            }
442            mm_app_cache_ops((mm_camera_app_meminfo_t *)bufs->bufs[i]->mem_info,
443                             ION_IOC_INV_CACHES);
444        }
445    }
446
447    LOGD(" END\n");
448}
449
450mm_camera_channel_t * mm_app_add_snapshot_channel(mm_camera_test_obj_t *test_obj)
451{
452    mm_camera_channel_t *channel = NULL;
453    mm_camera_stream_t *stream = NULL;
454
455    channel = mm_app_add_channel(test_obj,
456                                 MM_CHANNEL_TYPE_SNAPSHOT,
457                                 NULL,
458                                 NULL,
459                                 NULL);
460    if (NULL == channel) {
461        LOGE(" add channel failed");
462        return NULL;
463    }
464
465    stream = mm_app_add_snapshot_stream(test_obj,
466                                        channel,
467                                        mm_app_snapshot_notify_cb,
468                                        (void *)test_obj,
469                                        1,
470                                        1);
471    if (NULL == stream) {
472        LOGE(" add snapshot stream failed\n");
473        mm_app_del_channel(test_obj, channel);
474        return NULL;
475    }
476
477    return channel;
478}
479
480mm_camera_stream_t * mm_app_add_postview_stream(mm_camera_test_obj_t *test_obj,
481                                                mm_camera_channel_t *channel,
482                                                mm_camera_buf_notify_t stream_cb,
483                                                void *userdata,
484                                                uint8_t num_bufs,
485                                                uint8_t num_burst)
486{
487    int rc = MM_CAMERA_OK;
488    mm_camera_stream_t *stream = NULL;
489    cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
490
491    stream = mm_app_add_stream(test_obj, channel);
492    if (NULL == stream) {
493        LOGE(" add stream failed\n");
494        return NULL;
495    }
496
497    stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
498    stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
499    stream->s_config.mem_vtbl.clean_invalidate_buf =
500      mm_app_stream_clean_invalidate_buf;
501    stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
502    stream->s_config.mem_vtbl.user_data = (void *)stream;
503    stream->s_config.stream_cb = stream_cb;
504    stream->s_config.stream_cb_sync = NULL;
505    stream->s_config.userdata = userdata;
506    stream->num_of_bufs = num_bufs;
507
508    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
509    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
510    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_POSTVIEW;
511    if (num_burst == 0) {
512        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
513    } else {
514        stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST;
515        stream->s_config.stream_info->num_of_burst = num_burst;
516    }
517    stream->s_config.stream_info->fmt = DEFAULT_PREVIEW_FORMAT;
518    stream->s_config.stream_info->dim.width = DEFAULT_PREVIEW_WIDTH;
519    stream->s_config.stream_info->dim.height = DEFAULT_PREVIEW_HEIGHT;
520    stream->s_config.padding_info = cam_cap->padding_info;
521
522    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
523    if (MM_CAMERA_OK != rc) {
524        LOGE("config postview stream err=%d\n",  rc);
525        return NULL;
526    }
527
528    return stream;
529}
530
531int mm_app_start_capture_raw(mm_camera_test_obj_t *test_obj, uint8_t num_snapshots)
532{
533    int32_t rc = MM_CAMERA_OK;
534    mm_camera_channel_t *channel = NULL;
535    mm_camera_stream_t *s_main = NULL;
536    mm_camera_channel_attr_t attr;
537
538    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
539    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
540    attr.max_unmatched_frames = 3;
541    channel = mm_app_add_channel(test_obj,
542                                 MM_CHANNEL_TYPE_CAPTURE,
543                                 &attr,
544                                 mm_app_snapshot_notify_cb_raw,
545                                 test_obj);
546    if (NULL == channel) {
547        LOGE(" add channel failed");
548        return -MM_CAMERA_E_GENERAL;
549    }
550
551    test_obj->buffer_format = DEFAULT_RAW_FORMAT;
552    s_main = mm_app_add_raw_stream(test_obj,
553                                   channel,
554                                   mm_app_snapshot_notify_cb_raw,
555                                   test_obj,
556                                   num_snapshots,
557                                   num_snapshots);
558    if (NULL == s_main) {
559        LOGE(" add main snapshot stream failed\n");
560        mm_app_del_channel(test_obj, channel);
561        return rc;
562    }
563
564    rc = mm_app_start_channel(test_obj, channel);
565    if (MM_CAMERA_OK != rc) {
566        LOGE("start zsl failed rc=%d\n",  rc);
567        mm_app_del_stream(test_obj, channel, s_main);
568        mm_app_del_channel(test_obj, channel);
569        return rc;
570    }
571
572    return rc;
573}
574
575int mm_app_stop_capture_raw(mm_camera_test_obj_t *test_obj)
576{
577    int rc = MM_CAMERA_OK;
578    mm_camera_channel_t *ch = NULL;
579    int i;
580    cam_stream_size_info_t abc ;
581    memset (&abc , 0, sizeof (cam_stream_size_info_t));
582
583    ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_CAPTURE);
584
585    rc = mm_app_stop_channel(test_obj, ch);
586    if (MM_CAMERA_OK != rc) {
587        LOGE("stop recording failed rc=%d\n",  rc);
588    }
589
590    for ( i = 0 ; i < ch->num_streams ; i++ ) {
591        mm_app_del_stream(test_obj, ch, &ch->streams[i]);
592    }
593    rc = setmetainfoCommand(test_obj, &abc);
594    if (rc != MM_CAMERA_OK) {
595       LOGE(" meta info command failed\n");
596    }
597    mm_app_del_channel(test_obj, ch);
598
599    return rc;
600}
601
602int mm_app_start_capture(mm_camera_test_obj_t *test_obj,
603                         uint8_t num_snapshots)
604{
605    int32_t rc = MM_CAMERA_OK;
606    mm_camera_channel_t *channel = NULL;
607    mm_camera_stream_t *s_main = NULL;
608    mm_camera_stream_t *s_post = NULL;
609    mm_camera_channel_attr_t attr;
610    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
611    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
612    attr.max_unmatched_frames = 3;
613    channel = mm_app_add_channel(test_obj,
614                                 MM_CHANNEL_TYPE_CAPTURE,
615                                 &attr,
616                                 mm_app_snapshot_notify_cb,
617                                 test_obj);
618    if (NULL == channel) {
619        LOGE(" add channel failed");
620        return -MM_CAMERA_E_GENERAL;
621    }
622
623    s_main = mm_app_add_snapshot_stream(test_obj,
624                                        channel,
625                                        mm_app_snapshot_notify_cb,
626                                        (void *)test_obj,
627                                        CAPTURE_BUF_NUM,
628                                        num_snapshots);
629    if (NULL == s_main) {
630        LOGE(" add main snapshot stream failed\n");
631        mm_app_del_channel(test_obj, channel);
632        return rc;
633    }
634
635    s_post = mm_app_add_postview_stream(test_obj,
636                                        channel,
637                                        NULL,
638                                        NULL,
639                                        CAPTURE_BUF_NUM,
640                                        num_snapshots);
641    if (NULL == s_main) {
642        LOGE(" add main postview stream failed\n");
643        mm_app_del_channel(test_obj, channel);
644        return rc;
645    }
646
647    rc = mm_app_start_channel(test_obj, channel);
648    if (MM_CAMERA_OK != rc) {
649        LOGE("start zsl failed rc=%d\n",  rc);
650        mm_app_del_stream(test_obj, channel, s_main);
651        mm_app_del_channel(test_obj, channel);
652        return rc;
653    }
654
655    return rc;
656}
657
658int mm_app_stop_capture(mm_camera_test_obj_t *test_obj)
659{
660    int rc = MM_CAMERA_OK;
661    mm_camera_channel_t *ch = NULL;
662
663    ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_CAPTURE);
664
665    rc = mm_app_stop_and_del_channel(test_obj, ch);
666    if (MM_CAMERA_OK != rc) {
667        LOGE("stop capture channel failed rc=%d\n",  rc);
668    }
669
670    return rc;
671}
672
673int mm_app_take_picture(mm_camera_test_obj_t *test_obj, uint8_t is_burst_mode)
674{
675    LOGH("\nEnter %s!!\n");
676    int rc = MM_CAMERA_OK;
677    uint8_t num_snapshot = 1;
678    int num_rcvd_snapshot = 0;
679
680    if (is_burst_mode)
681       num_snapshot = 6;
682
683    //stop preview before starting capture.
684    rc = mm_app_stop_preview(test_obj);
685    if (rc != MM_CAMERA_OK) {
686        LOGE(" stop preview failed before capture!!, err=%d\n", rc);
687        return rc;
688    }
689
690    rc = mm_app_start_capture(test_obj, num_snapshot);
691    if (rc != MM_CAMERA_OK) {
692        LOGE(" mm_app_start_capture(), err=%d\n", rc);
693        return rc;
694    }
695    while (num_rcvd_snapshot < num_snapshot) {
696        LOGH("\nWaiting mm_camera_app_wait !!\n");
697        mm_camera_app_wait();
698        num_rcvd_snapshot++;
699    }
700    rc = mm_app_stop_capture(test_obj);
701    if (rc != MM_CAMERA_OK) {
702       LOGE(" mm_app_stop_capture(), err=%d\n", rc);
703       return rc;
704    }
705    //start preview after capture.
706    rc = mm_app_start_preview(test_obj);
707    if (rc != MM_CAMERA_OK) {
708        LOGE(" start preview failed after capture!!, err=%d\n",rc);
709    }
710    return rc;
711}
712