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.user_data = (void *)stream;
141    stream->s_config.stream_cb = stream_cb;
142    stream->s_config.stream_cb_sync = NULL;
143    stream->s_config.userdata = userdata;
144    stream->num_of_bufs = num_bufs;
145
146    stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer;
147    source_stream_info = (cam_stream_info_t *) source->s_info_buf.buf.buffer;
148    memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t));
149    stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC;
150    stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
151    stream->s_config.stream_info->fmt = source_stream_info->fmt;
152    stream->s_config.stream_info->dim = source_stream_info->dim;
153    stream->s_config.padding_info = cam_cap->padding_info;
154
155
156    stream->s_config.stream_info->reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
157    stream->s_config.stream_info->reprocess_config.online.input_stream_id = source->s_config.stream_info->stream_svr_id;
158    stream->s_config.stream_info->reprocess_config.online.input_stream_type = source->s_config.stream_info->stream_type;
159    stream->s_config.stream_info->reprocess_config.pp_feature_config = pp_config;
160
161    rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config);
162    if (MM_CAMERA_OK != rc) {
163        LOGE("config preview stream err=%d\n",  rc);
164        return NULL;
165    }
166
167    return stream;
168}
169
170mm_camera_channel_t * mm_app_add_reprocess_channel(mm_camera_test_obj_t *test_obj,
171                                                   mm_camera_stream_t *source_stream)
172{
173    mm_camera_channel_t *channel = NULL;
174    mm_camera_stream_t *stream = NULL;
175
176    if ( NULL == source_stream ) {
177        LOGE(" add reprocess stream failed\n");
178        return NULL;
179    }
180
181    channel = mm_app_add_channel(test_obj,
182                                 MM_CHANNEL_TYPE_REPROCESS,
183                                 NULL,
184                                 NULL,
185                                 NULL);
186    if (NULL == channel) {
187        LOGE(" add channel failed");
188        return NULL;
189    }
190
191    // pp feature config
192    cam_pp_feature_config_t pp_config;
193    memset(&pp_config, 0, sizeof(cam_pp_feature_config_t));
194
195    cam_capability_t *caps = ( cam_capability_t * ) ( test_obj->cap_buf.buf.buffer );
196    if (caps->qcom_supported_feature_mask & CAM_QCOM_FEATURE_SHARPNESS) {
197        pp_config.feature_mask |= CAM_QCOM_FEATURE_SHARPNESS;
198        pp_config.sharpness = test_obj->reproc_sharpness;
199    }
200
201    if (test_obj->reproc_wnr.denoise_enable) {
202        pp_config.feature_mask |= CAM_QCOM_FEATURE_DENOISE2D;
203        pp_config.denoise2d = test_obj->reproc_wnr;
204    }
205
206    if (test_obj->enable_CAC) {
207        pp_config.feature_mask |= CAM_QCOM_FEATURE_CAC;
208    }
209
210    uint8_t minStreamBufNum = source_stream->num_of_bufs;
211    stream = mm_app_add_reprocess_stream_from_source(test_obj,
212                                     channel,
213                                     source_stream,
214                                     mm_app_reprocess_notify_cb,
215                                     pp_config,
216                                     (void *)test_obj,
217                                     minStreamBufNum);
218    if (NULL == stream) {
219        LOGE(" add reprocess stream failed\n");
220        mm_app_del_channel(test_obj, channel);
221        return NULL;
222    }
223    test_obj->reproc_stream = stream;
224
225    return channel;
226}
227
228int mm_app_start_reprocess(mm_camera_test_obj_t *test_obj)
229{
230    int rc = MM_CAMERA_OK;
231    mm_camera_channel_t *r_ch = NULL;
232
233    mm_camera_queue_init(&test_obj->pp_frames,
234                         mm_app_release_ppinput,
235                         ( void * ) test_obj);
236
237    r_ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_REPROCESS);
238    if (MM_CAMERA_OK != rc) {
239        LOGE(" No initialized reprocess channel d rc=%d\n", rc);
240        return rc;
241    }
242
243    rc = mm_app_start_channel(test_obj, r_ch);
244    if (MM_CAMERA_OK != rc) {
245        LOGE("start reprocess failed rc=%d\n",  rc);
246        mm_app_del_channel(test_obj, r_ch);
247        return rc;
248    }
249
250    return rc;
251}
252
253int mm_app_stop_reprocess(mm_camera_test_obj_t *test_obj)
254{
255    int rc = MM_CAMERA_OK;
256    mm_camera_channel_t *r_ch = NULL;
257
258    r_ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_REPROCESS);
259    if (MM_CAMERA_OK != rc) {
260        LOGE(" No initialized reprocess channel d rc=%d\n", rc);
261        return rc;
262    }
263
264    rc = mm_app_stop_and_del_channel(test_obj, r_ch);
265    if (MM_CAMERA_OK != rc) {
266        LOGE("Stop Preview failed rc=%d\n",  rc);
267    }
268
269    mm_qcamera_queue_release(&test_obj->pp_frames);
270    test_obj->reproc_stream = NULL;
271
272    return rc;
273}
274
275int mm_app_do_reprocess(mm_camera_test_obj_t *test_obj,
276                        mm_camera_buf_def_t *frame,
277                        uint32_t meta_idx,
278                        mm_camera_super_buf_t *super_buf,
279                        mm_camera_stream_t *src_meta)
280{
281    int rc = MM_CAMERA_OK;
282    mm_camera_channel_t *r_ch = NULL;
283    mm_camera_super_buf_t *src_buf = NULL;
284
285    if ( ( NULL == test_obj ) ||
286         ( NULL == frame ) ||
287         ( NULL == super_buf )) {
288        LOGE(" Invalid input rc=%d\n", rc);
289        return rc;
290    }
291
292    if ( NULL == test_obj->reproc_stream ) {
293        LOGE(" No reprocess stream rc=%d\n", rc);
294        return rc;
295    }
296
297    r_ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_REPROCESS);
298    if (MM_CAMERA_OK != rc) {
299        LOGE(" No reprocess channel rc=%d\n", rc);
300        return rc;
301    }
302
303    src_buf = ( mm_camera_super_buf_t * ) malloc(sizeof(mm_camera_super_buf_t));
304    if ( NULL == src_buf ) {
305        LOGE(" No resources for src frame rc=%d\n", rc);
306        return -1;
307    }
308    memcpy(src_buf, super_buf, sizeof(mm_camera_super_buf_t));
309    mm_qcamera_queue_enqueue(&test_obj->pp_frames, src_buf);
310
311    cam_stream_parm_buffer_t param;
312    memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
313    param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
314    param.reprocess.buf_index = frame->buf_idx;
315    param.reprocess.frame_idx = frame->frame_idx;
316    if (src_meta != NULL) {
317        param.reprocess.meta_present = 1;
318        param.reprocess.meta_stream_handle = src_meta->s_config.stream_info->stream_svr_id;
319        param.reprocess.meta_buf_index = meta_idx;
320    } else {
321        LOGE(" No metadata source stream rc=%d\n", rc);
322    }
323
324    test_obj->reproc_stream->s_config.stream_info->parm_buf = param;
325    rc = test_obj->cam->ops->set_stream_parms(test_obj->cam->camera_handle,
326                                              r_ch->ch_id,
327                                              test_obj->reproc_stream->s_id,
328                                              &test_obj->reproc_stream->s_config.stream_info->parm_buf);
329
330    return rc;
331}
332
333void mm_app_release_ppinput(void *data, void *user_data)
334{
335    uint32_t i = 0;
336    mm_camera_super_buf_t *recvd_frame  = ( mm_camera_super_buf_t * ) data;
337    mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data;
338
339    for ( i = 0 ; i < recvd_frame->num_bufs ; i++) {
340        if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,
341                                                recvd_frame->ch_id,
342                                                recvd_frame->bufs[i])) {
343            LOGE(" Failed in Qbuf\n");
344        }
345        mm_app_cache_ops((mm_camera_app_meminfo_t *) recvd_frame->bufs[i]->mem_info,
346                         ION_IOC_INV_CACHES);
347    }
348}
349
350