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