mm_camera_channel_t * mm_app_add_preview_channel(mm_camera_test_obj_t *test_obj)
{
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *stream = NULL;

    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_PREVIEW,
                                 NULL,
                                 NULL,
                                 NULL);
    if (NULL == channel) {
        CDBG_ERROR("%s: add channel failed", __func__);
        return NULL;
    }

    stream = mm_app_add_preview_stream(test_obj,
                                       channel,
                                       mm_app_preview_notify_cb,
                                       (void *)test_obj,
                                       PREVIEW_BUF_NUM);
    if (NULL == stream) {
        CDBG_ERROR("%s: add stream failed\n", __func__);
        mm_app_del_channel(test_obj, channel);
        return NULL;
    }

    return channel;
}
mm_camera_channel_t * mm_app_add_rdi_channel(mm_camera_test_obj_t *test_obj, uint8_t num_burst)
{
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *stream = NULL;

    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_RDI,
                                 NULL,
                                 NULL,
                                 NULL);
    if (NULL == channel) {
        CDBG_ERROR("%s: add channel failed", __func__);
        return NULL;
    }

    stream = mm_app_add_rdi_stream(test_obj,
                                       channel,
                                       mm_app_rdi_notify_cb,
                                       (void *)test_obj,
                                       RDI_BUF_NUM,
                                       num_burst);
    if (NULL == stream) {
        CDBG_ERROR("%s: add stream failed\n", __func__);
        mm_app_del_channel(test_obj, channel);
        return NULL;
    }

    CDBG("%s: channel=%d stream=%d\n", __func__, channel->ch_id, stream->s_id);
    return channel;
}
mm_camera_channel_t * mm_app_add_snapshot_channel(mm_camera_test_obj_t *test_obj)
{
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *stream = NULL;

    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_SNAPSHOT,
                                 NULL,
                                 NULL,
                                 NULL);
    if (NULL == channel) {
        LOGE(" add channel failed");
        return NULL;
    }

    stream = mm_app_add_snapshot_stream(test_obj,
                                        channel,
                                        mm_app_snapshot_notify_cb,
                                        (void *)test_obj,
                                        1,
                                        1);
    if (NULL == stream) {
        LOGE(" add snapshot stream failed\n");
        mm_app_del_channel(test_obj, channel);
        return NULL;
    }

    return channel;
}
int mm_app_start_preview_zsl(mm_camera_test_obj_t *test_obj)
{
    int32_t rc = MM_CAMERA_OK;
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *s_preview = NULL;
    mm_camera_stream_t *s_main = NULL;
    mm_camera_channel_attr_t attr;

    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
    attr.look_back = 2;
    attr.post_frame_skip = 0;
    attr.water_mark = 2;
    attr.max_unmatched_frames = 3;
    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_ZSL,
                                 &attr,
                                 mm_app_zsl_notify_cb,
                                 test_obj);
    if (NULL == channel) {
        CDBG_ERROR("%s: add channel failed", __func__);
        return -MM_CAMERA_E_GENERAL;
    }

    s_preview = mm_app_add_preview_stream(test_obj,
                                          channel,
                                          mm_app_preview_notify_cb,
                                          (void *)test_obj,
                                          PREVIEW_BUF_NUM);
    if (NULL == s_preview) {
        CDBG_ERROR("%s: add preview stream failed\n", __func__);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    s_main = mm_app_add_snapshot_stream(test_obj,
                                        channel,
                                        NULL,
                                        NULL,
                                        PREVIEW_BUF_NUM,
                                        0);
    if (NULL == s_main) {
        CDBG_ERROR("%s: add main snapshot stream failed\n", __func__);
        mm_app_del_stream(test_obj, channel, s_preview);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    rc = mm_app_start_channel(test_obj, channel);
    if (MM_CAMERA_OK != rc) {
        CDBG_ERROR("%s:start zsl failed rc=%d\n", __func__, rc);
        mm_app_del_stream(test_obj, channel, s_preview);
        mm_app_del_stream(test_obj, channel, s_main);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    return rc;
}
mm_camera_channel_t * mm_app_add_reprocess_channel(mm_camera_test_obj_t *test_obj,
                                                   mm_camera_stream_t *source_stream)
{
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *stream = NULL;

    if ( NULL == source_stream ) {
        CDBG_ERROR("%s: add reprocess stream failed\n", __func__);
        return NULL;
    }

    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_REPROCESS,
                                 NULL,
                                 NULL,
                                 NULL);
    if (NULL == channel) {
        CDBG_ERROR("%s: add channel failed", __func__);
        return NULL;
    }

    // pp feature config
    cam_pp_feature_config_t pp_config;
    memset(&pp_config, 0, sizeof(cam_pp_feature_config_t));

    cam_capability_t *caps = ( cam_capability_t * ) ( test_obj->cap_buf.buf.buffer );
    if (caps->min_required_pp_mask & CAM_QCOM_FEATURE_SHARPNESS) {
        pp_config.feature_mask |= CAM_QCOM_FEATURE_SHARPNESS;
        pp_config.sharpness = test_obj->reproc_sharpness;
    }

    if (test_obj->reproc_wnr.denoise_enable) {
        pp_config.feature_mask |= CAM_QCOM_FEATURE_DENOISE2D;
        pp_config.denoise2d = test_obj->reproc_wnr;
    }

    if (test_obj->enable_CAC) {
        pp_config.feature_mask |= CAM_QCOM_FEATURE_CAC;
    }

    uint8_t minStreamBufNum = source_stream->num_of_bufs;
    stream = mm_app_add_reprocess_stream_from_source(test_obj,
                                     channel,
                                     source_stream,
                                     mm_app_reprocess_notify_cb,
                                     pp_config,
                                     (void *)test_obj,
                                     minStreamBufNum);
    if (NULL == stream) {
        CDBG_ERROR("%s: add reprocess stream failed\n", __func__);
        mm_app_del_channel(test_obj, channel);
        return NULL;
    }
    test_obj->reproc_stream = stream;

    return channel;
}
int mm_app_start_capture(mm_camera_test_obj_t *test_obj,
                         uint8_t num_snapshots)
{
    int32_t rc = MM_CAMERA_OK;
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *s_main = NULL;
    mm_camera_stream_t *s_metadata = NULL;
    mm_camera_channel_attr_t attr;

    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
    attr.max_unmatched_frames = 3;
    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_CAPTURE,
                                 &attr,
                                 mm_app_snapshot_notify_cb,
                                 test_obj);
    if (NULL == channel) {
        CDBG_ERROR("%s: add channel failed", __func__);
        return -MM_CAMERA_E_GENERAL;
    }
#if 0 // Removing metadata stream for snapshot in qcamera app.
    s_metadata = mm_app_add_metadata_stream(test_obj,
                                            channel,
                                            mm_app_snapshot_metadata_notify_cb,
                                            (void *)test_obj,
                                            CAPTURE_BUF_NUM);
     if (NULL == s_metadata) {
        CDBG_ERROR("%s: add metadata stream failed\n", __func__);
        mm_app_del_channel(test_obj, channel);
        return -MM_CAMERA_E_GENERAL;
    }
#endif
    s_main = mm_app_add_snapshot_stream(test_obj,
                                        channel,
                                        NULL,
                                        NULL,
                                        CAPTURE_BUF_NUM,
                                        num_snapshots);
    if (NULL == s_main) {
        CDBG_ERROR("%s: add main snapshot stream failed\n", __func__);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    rc = mm_app_start_channel(test_obj, channel);
    if (MM_CAMERA_OK != rc) {
        CDBG_ERROR("%s:start zsl failed rc=%d\n", __func__, rc);
        mm_app_del_stream(test_obj, channel, s_main);
        mm_app_del_stream(test_obj, channel, s_metadata);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    return rc;
}
int mm_app_start_capture(mm_camera_test_obj_t *test_obj,
                         uint8_t num_snapshots)
{
    int32_t rc = MM_CAMERA_OK;
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *s_main = NULL;
    mm_camera_stream_t *s_post = NULL;
    mm_camera_channel_attr_t attr;
    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
    attr.max_unmatched_frames = 3;
    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_CAPTURE,
                                 &attr,
                                 mm_app_snapshot_notify_cb,
                                 test_obj);
    if (NULL == channel) {
        LOGE(" add channel failed");
        return -MM_CAMERA_E_GENERAL;
    }

    s_main = mm_app_add_snapshot_stream(test_obj,
                                        channel,
                                        mm_app_snapshot_notify_cb,
                                        (void *)test_obj,
                                        CAPTURE_BUF_NUM,
                                        num_snapshots);
    if (NULL == s_main) {
        LOGE(" add main snapshot stream failed\n");
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    s_post = mm_app_add_postview_stream(test_obj,
                                        channel,
                                        NULL,
                                        NULL,
                                        CAPTURE_BUF_NUM,
                                        num_snapshots);
    if (NULL == s_main) {
        LOGE(" add main postview stream failed\n");
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    rc = mm_app_start_channel(test_obj, channel);
    if (MM_CAMERA_OK != rc) {
        LOGE("start zsl failed rc=%d\n",  rc);
        mm_app_del_stream(test_obj, channel, s_main);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    return rc;
}
int mm_app_start_capture_raw(mm_camera_test_obj_t *test_obj, uint8_t num_snapshots)
{
    int32_t rc = MM_CAMERA_OK;
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *s_main = NULL;
    mm_camera_channel_attr_t attr;

    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
    attr.max_unmatched_frames = 3;
    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_CAPTURE,
                                 &attr,
                                 mm_app_snapshot_notify_cb_raw,
                                 test_obj);
    if (NULL == channel) {
        LOGE(" add channel failed");
        return -MM_CAMERA_E_GENERAL;
    }

    test_obj->buffer_format = DEFAULT_RAW_FORMAT;
    s_main = mm_app_add_raw_stream(test_obj,
                                   channel,
                                   mm_app_snapshot_notify_cb_raw,
                                   test_obj,
                                   num_snapshots,
                                   num_snapshots);
    if (NULL == s_main) {
        LOGE(" add main snapshot stream failed\n");
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    rc = mm_app_start_channel(test_obj, channel);
    if (MM_CAMERA_OK != rc) {
        LOGE("start zsl failed rc=%d\n",  rc);
        mm_app_del_stream(test_obj, channel, s_main);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    return rc;
}
int mm_app_start_preview_zsl(mm_camera_test_obj_t *test_obj)
{
    int32_t rc = MM_CAMERA_OK;
    mm_camera_channel_t *channel = NULL;
    mm_camera_stream_t *s_preview = NULL;
    mm_camera_stream_t *s_metadata = NULL;
    mm_camera_stream_t *s_main = NULL;
    mm_camera_channel_attr_t attr;

    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
    attr.look_back = 2;
    attr.post_frame_skip = 0;
    attr.water_mark = 2;
    attr.max_unmatched_frames = 3;
    channel = mm_app_add_channel(test_obj,
                                 MM_CHANNEL_TYPE_ZSL,
                                 &attr,
                                 mm_app_zsl_notify_cb,
                                 test_obj);
    if (NULL == channel) {
        CDBG_ERROR("%s: add channel failed", __func__);
        return -MM_CAMERA_E_GENERAL;
    }

    s_preview = mm_app_add_preview_stream(test_obj,
                                          channel,
                                          mm_app_preview_notify_cb,
                                          (void *)test_obj,
                                          PREVIEW_BUF_NUM);
    if (NULL == s_preview) {
        CDBG_ERROR("%s: add preview stream failed\n", __func__);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    s_metadata = mm_app_add_metadata_stream(test_obj,
                                            channel,
                                            mm_app_metadata_notify_cb,
                                            (void *)test_obj,
                                            PREVIEW_BUF_NUM);
    if (NULL == s_metadata) {
        CDBG_ERROR("%s: add metadata stream failed\n", __func__);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    s_main = mm_app_add_snapshot_stream(test_obj,
                                        channel,
                                        NULL,
                                        NULL,
                                        PREVIEW_BUF_NUM,
                                        0);
    if (NULL == s_main) {
        CDBG_ERROR("%s: add main snapshot stream failed\n", __func__);
        mm_app_del_stream(test_obj, channel, s_preview);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    rc = mm_app_start_channel(test_obj, channel);
    if (MM_CAMERA_OK != rc) {
        CDBG_ERROR("%s:start zsl failed rc=%d\n", __func__, rc);
        mm_app_del_stream(test_obj, channel, s_preview);
        mm_app_del_stream(test_obj, channel, s_metadata);
        mm_app_del_stream(test_obj, channel, s_main);
        mm_app_del_channel(test_obj, channel);
        return rc;
    }

    if ( test_obj->enable_reproc ) {
        if ( NULL == mm_app_add_reprocess_channel(test_obj, s_main) ) {
            CDBG_ERROR("%s: Reprocess channel failed to initialize \n", __func__);
            mm_app_del_stream(test_obj, channel, s_preview);
#ifdef USE_METADATA_STREAM
            mm_app_del_stream(test_obj, channel, s_metadata);
#endif
            mm_app_del_stream(test_obj, channel, s_main);
            mm_app_del_channel(test_obj, channel);
            return rc;
        }
        rc = mm_app_start_reprocess(test_obj);
        if (MM_CAMERA_OK != rc) {
            CDBG_ERROR("%s: reprocess start failed rc=%d\n", __func__, rc);
            mm_app_del_stream(test_obj, channel, s_preview);
#ifdef USE_METADATA_STREAM
            mm_app_del_stream(test_obj, channel, s_metadata);
#endif
            mm_app_del_stream(test_obj, channel, s_main);
            mm_app_del_channel(test_obj, channel);
            return rc;
        }
    }

    return rc;
}