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(¶m, 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