1 /* 2 Copyright (c) 2012-2014, 2016, 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 // Camera dependencies 31 #include "mm_qcamera_app.h" 32 #include "mm_qcamera_dbg.h" 33 34 static 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 96 exit: 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 107 mm_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 171 mm_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 231 int 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 256 int 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 278 int 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(¶m, 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 336 void 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