1 /* 2 Copyright (c) 2012-2013, 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 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=%d, 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 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 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 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 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 277 int mm_app_do_reprocess(mm_camera_test_obj_t *test_obj, 278 mm_camera_buf_def_t *frame, 279 uint8_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(¶m, 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 345 void mm_app_release_ppinput(void *data, void *user_data) 346 { 347 int 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