1/*
2Copyright (c) 2012-2014, 2016, The Linux Foundation. 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 The Linux Foundation 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// Camera dependencies
31#include "mm_qcamera_app.h"
32#include "mm_qcamera_dbg.h"
33
34static void mm_app_reprocess_notify_cb(mm_camera_super_buf_t *bufs,
35                                   void *user_data)
36{
37    mm_camera_buf_def_t *frame = bufs->bufs[0];
38    mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
39    mm_camera_channel_t *channel = NULL;
40    mm_camera_stream_t *m_stream = NULL;
41    mm_camera_buf_def_t *m_frame = NULL;
42    mm_camera_super_buf_t *src_frame;
43    int i = 0;
44    int rc = 0;
45
46    LOGE(" BEGIN - length=%zu, frame idx = %d\n",
47          frame->frame_len, frame->frame_idx);
48
49    /* find channel */
50    for (i = 0; i < MM_CHANNEL_TYPE_MAX; i++) {
51        if (pme->channels[i].ch_id == bufs->ch_id) {
52            channel = &pme->channels[i];
53            break;
54        }
55    }
56    if (NULL == channel) {
57        LOGE(" Wrong channel id (%d)",  bufs->ch_id);
58        return;
59    }
60
61    // We have only one stream and buffer
62    // in the reprocess channel.
63    m_stream = &channel->streams[0];
64    m_frame = bufs->bufs[0];
65
66    if ( pme->encodeJpeg ) {
67        pme->jpeg_buf.buf.buffer = (uint8_t *)malloc(m_frame->frame_len);
68        if ( NULL == pme->jpeg_buf.buf.buffer ) {
69            LOGE(" error allocating jpeg output buffer");
70            goto exit;
71        }
72
73        pme->jpeg_buf.buf.frame_len = m_frame->frame_len;
74        /* create a new jpeg encoding session */
75        rc = createEncodingSession(pme, m_stream, m_frame);
76        if (0 != rc) {
77            LOGE(" error creating jpeg session");
78            free(pme->jpeg_buf.buf.buffer);
79            goto exit;
80        }
81
82        /* start jpeg encoding job */
83        LOGE("Encoding reprocessed frame!!");
84        rc = encodeData(pme, bufs, m_stream);
85        pme->encodeJpeg = 0;
86    } else {
87        if (MM_CAMERA_OK != pme->cam->ops->qbuf(bufs->camera_handle,
88                                                bufs->ch_id,
89                                                frame)) {
90            LOGE(" Failed in Reprocess Qbuf\n");
91        }
92        mm_app_cache_ops((mm_camera_app_meminfo_t *)frame->mem_info,
93                         ION_IOC_INV_CACHES);
94    }
95
96exit:
97
98// Release source frame
99    src_frame = ( mm_camera_super_buf_t * ) mm_qcamera_queue_dequeue(&pme->pp_frames, 1);
100    if ( NULL != src_frame ) {
101        mm_app_release_ppinput((void *) src_frame, (void *) pme);
102    }
103
104    LOGE(" END\n");
105}
106
107mm_camera_stream_t * mm_app_add_reprocess_stream_from_source(mm_camera_test_obj_t *test_obj,
108                                                             mm_camera_channel_t *channel,
109                                                             mm_camera_stream_t *source,
110                                                             mm_camera_buf_notify_t stream_cb,
111                                                             cam_pp_feature_config_t pp_config,
112                                                             void *userdata,
113                                                             uint8_t num_bufs)
114{
115    int rc = MM_CAMERA_OK;
116    mm_camera_stream_t *stream = NULL;
117    cam_capability_t *cam_cap = NULL;
118    cam_stream_info_t *source_stream_info;
119
120    if ( ( NULL == test_obj ) ||
121         ( NULL == channel ) ||
122         ( NULL == source ) ) {
123        LOGE(" Invalid input\n");
124        return NULL;
125    }
126
127    cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer);
128
129    stream = mm_app_add_stream(test_obj, channel);
130    if (NULL == stream) {
131        LOGE(" add stream failed\n");
132        return NULL;
133    }
134
135    stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
136    stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
137    stream->s_config.mem_vtbl.clean_invalidate_buf =
138      mm_app_stream_clean_invalidate_buf;
139    stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
140    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
141    stream->s_config.mem_vtbl.user_data = (void *)stream;
142    stream->s_config.stream_cb = stream_cb;
143    stream->s_config.stream_cb_sync = NULL;
144    stream->s_config.userdata = userdata;
145    stream->num_of_bufs = num_bufs;
146
147    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
148    source_stream_info = (cam_stream_info_t *) source->s_info_buf.buf.buffer;
149    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
150    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC;
151    stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
152    stream->s_config.stream_info->fmt = source_stream_info->fmt;
153    stream->s_config.stream_info->dim = source_stream_info->dim;
154    stream->s_config.padding_info = cam_cap->padding_info;
155    stream->s_config.stream_info->num_bufs = num_bufs;
156
157    stream->s_config.stream_info->reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
158    stream->s_config.stream_info->reprocess_config.online.input_stream_id = source->s_config.stream_info->stream_svr_id;
159    stream->s_config.stream_info->reprocess_config.online.input_stream_type = source->s_config.stream_info->stream_type;
160    stream->s_config.stream_info->reprocess_config.pp_feature_config = pp_config;
161
162    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
163    if (MM_CAMERA_OK != rc) {
164        LOGE("config preview stream err=%d\n",  rc);
165        return NULL;
166    }
167
168    return stream;
169}
170
171mm_camera_channel_t * mm_app_add_reprocess_channel(mm_camera_test_obj_t *test_obj,
172                                                   mm_camera_stream_t *source_stream)
173{
174    mm_camera_channel_t *channel = NULL;
175    mm_camera_stream_t *stream = NULL;
176
177    if ( NULL == source_stream ) {
178        LOGE(" add reprocess stream failed\n");
179        return NULL;
180    }
181
182    channel = mm_app_add_channel(test_obj,
183                                 MM_CHANNEL_TYPE_REPROCESS,
184                                 NULL,
185                                 NULL,
186                                 NULL);
187    if (NULL == channel) {
188        LOGE(" add channel failed");
189        return NULL;
190    }
191
192    // pp feature config
193    cam_pp_feature_config_t pp_config;
194    memset(&pp_config, 0, sizeof(cam_pp_feature_config_t));
195
196    cam_capability_t *caps = ( cam_capability_t * ) ( test_obj->cap_buf.buf.buffer );
197    if (caps->qcom_supported_feature_mask & CAM_QCOM_FEATURE_SHARPNESS) {
198        pp_config.feature_mask |= CAM_QCOM_FEATURE_SHARPNESS;
199        pp_config.sharpness = test_obj->reproc_sharpness;
200    }
201
202    if (test_obj->reproc_wnr.denoise_enable) {
203        pp_config.feature_mask |= CAM_QCOM_FEATURE_DENOISE2D;
204        pp_config.denoise2d = test_obj->reproc_wnr;
205    }
206
207    if (test_obj->enable_CAC) {
208        pp_config.feature_mask |= CAM_QCOM_FEATURE_CAC;
209    }
210
211    pp_config.feature_mask |= CAM_QCOM_FEATURE_FLIP;
212
213    uint8_t minStreamBufNum = source_stream->num_of_bufs;
214    stream = mm_app_add_reprocess_stream_from_source(test_obj,
215                                     channel,
216                                     source_stream,
217                                     mm_app_reprocess_notify_cb,
218                                     pp_config,
219                                     (void *)test_obj,
220                                     minStreamBufNum);
221    if (NULL == stream) {
222        LOGE(" add reprocess stream failed\n");
223        mm_app_del_channel(test_obj, channel);
224        return NULL;
225    }
226    test_obj->reproc_stream = stream;
227
228    return channel;
229}
230
231int mm_app_start_reprocess(mm_camera_test_obj_t *test_obj)
232{
233    int rc = MM_CAMERA_OK;
234    mm_camera_channel_t *r_ch = NULL;
235
236    mm_camera_queue_init(&test_obj->pp_frames,
237                         mm_app_release_ppinput,
238                         ( void * ) test_obj);
239
240    r_ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_REPROCESS);
241    if (MM_CAMERA_OK != rc) {
242        LOGE(" No initialized reprocess channel d rc=%d\n", rc);
243        return rc;
244    }
245
246    rc = mm_app_start_channel(test_obj, r_ch);
247    if (MM_CAMERA_OK != rc) {
248        LOGE("start reprocess failed rc=%d\n",  rc);
249        mm_app_del_channel(test_obj, r_ch);
250        return rc;
251    }
252
253    return rc;
254}
255
256int mm_app_stop_reprocess(mm_camera_test_obj_t *test_obj)
257{
258    int rc = MM_CAMERA_OK;
259    mm_camera_channel_t *r_ch = NULL;
260
261    r_ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_REPROCESS);
262    if (MM_CAMERA_OK != rc) {
263        LOGE(" No initialized reprocess channel d rc=%d\n", rc);
264        return rc;
265    }
266
267    rc = mm_app_stop_and_del_channel(test_obj, r_ch);
268    if (MM_CAMERA_OK != rc) {
269        LOGE("Stop Preview failed rc=%d\n",  rc);
270    }
271
272    mm_qcamera_queue_release(&test_obj->pp_frames);
273    test_obj->reproc_stream = NULL;
274
275    return rc;
276}
277
278int mm_app_do_reprocess(mm_camera_test_obj_t *test_obj,
279                        mm_camera_buf_def_t *frame,
280                        uint32_t meta_idx,
281                        mm_camera_super_buf_t *super_buf,
282                        mm_camera_stream_t *src_meta)
283{
284    int rc = MM_CAMERA_OK;
285    mm_camera_channel_t *r_ch = NULL;
286    mm_camera_super_buf_t *src_buf = NULL;
287
288    if ( ( NULL == test_obj ) ||
289         ( NULL == frame ) ||
290         ( NULL == super_buf )) {
291        LOGE(" Invalid input rc=%d\n", rc);
292        return rc;
293    }
294
295    if ( NULL == test_obj->reproc_stream ) {
296        LOGE(" No reprocess stream rc=%d\n", rc);
297        return rc;
298    }
299
300    r_ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_REPROCESS);
301    if (MM_CAMERA_OK != rc) {
302        LOGE(" No reprocess channel rc=%d\n", rc);
303        return rc;
304    }
305
306    src_buf = ( mm_camera_super_buf_t * ) malloc(sizeof(mm_camera_super_buf_t));
307    if ( NULL == src_buf ) {
308        LOGE(" No resources for src frame rc=%d\n", rc);
309        return -1;
310    }
311    memcpy(src_buf, super_buf, sizeof(mm_camera_super_buf_t));
312    mm_qcamera_queue_enqueue(&test_obj->pp_frames, src_buf);
313
314    cam_stream_parm_buffer_t param;
315    memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
316    param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
317    param.reprocess.buf_index = frame->buf_idx;
318    param.reprocess.frame_idx = frame->frame_idx;
319    if (src_meta != NULL) {
320        param.reprocess.meta_present = 1;
321        param.reprocess.meta_stream_handle = src_meta->s_config.stream_info->stream_svr_id;
322        param.reprocess.meta_buf_index = meta_idx;
323    } else {
324        LOGE(" No metadata source stream rc=%d\n", rc);
325    }
326
327    test_obj->reproc_stream->s_config.stream_info->parm_buf = param;
328    rc = test_obj->cam->ops->set_stream_parms(test_obj->cam->camera_handle,
329                                              r_ch->ch_id,
330                                              test_obj->reproc_stream->s_id,
331                                              &test_obj->reproc_stream->s_config.stream_info->parm_buf);
332
333    return rc;
334}
335
336void mm_app_release_ppinput(void *data, void *user_data)
337{
338    uint32_t i = 0;
339    mm_camera_super_buf_t *recvd_frame  = ( mm_camera_super_buf_t * ) data;
340    mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
341
342    for ( i = 0 ; i < recvd_frame->num_bufs ; i++) {
343        if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,
344                                                recvd_frame->ch_id,
345                                                recvd_frame->bufs[i])) {
346            LOGE(" Failed in Qbuf\n");
347        }
348        mm_app_cache_ops((mm_camera_app_meminfo_t *) recvd_frame->bufs[i]->mem_info,
349                         ION_IOC_INV_CACHES);
350    }
351}
352
353