1 /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 #include "mm_qcamera_dbg.h" 31 #include "mm_qcamera_app.h" 32 33 /* This callback is received once the complete JPEG encoding is done */ 34 static void jpeg_encode_cb(jpeg_job_status_t status, 35 uint32_t client_hdl, 36 uint32_t jobId, 37 mm_jpeg_output_t *p_buf, 38 void *userData) 39 { 40 int i = 0; 41 mm_camera_test_obj_t *pme = NULL; 42 CDBG("%s: BEGIN\n", __func__); 43 44 pme = (mm_camera_test_obj_t *)userData; 45 if (pme->jpeg_hdl != client_hdl || 46 jobId != pme->current_job_id || 47 !pme->current_job_frames) { 48 CDBG_ERROR("%s: NULL current job frames or not matching job ID (%d, %d)", 49 __func__, jobId, pme->current_job_id); 50 return; 51 } 52 53 /* dump jpeg img */ 54 CDBG_ERROR("%s: job %d, status=%d", __func__, jobId, status); 55 if (status == JPEG_JOB_STATUS_DONE && p_buf != NULL) { 56 mm_app_dump_jpeg_frame(p_buf->buf_vaddr, p_buf->buf_filled_len, "jpeg_dump", "jpg", jobId); 57 } 58 59 /* buf done current encoding frames */ 60 pme->current_job_id = 0; 61 for (i = 0; i < pme->current_job_frames->num_bufs; i++) { 62 if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->current_job_frames->camera_handle, 63 pme->current_job_frames->ch_id, 64 pme->current_job_frames->bufs[i])) { 65 CDBG_ERROR("%s: Failed in Qbuf\n", __func__); 66 } 67 } 68 free(pme->current_job_frames); 69 pme->current_job_frames = NULL; 70 71 /* signal snapshot is done */ 72 mm_camera_app_done(); 73 } 74 75 int encodeData(mm_camera_test_obj_t *test_obj, mm_camera_super_buf_t* recvd_frame, 76 mm_camera_stream_t *m_stream) 77 { 78 cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer); 79 80 int rc = -MM_CAMERA_E_GENERAL; 81 mm_jpeg_job_t job; 82 83 /* remember current frames being encoded */ 84 test_obj->current_job_frames = 85 (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 86 if (!test_obj->current_job_frames) { 87 CDBG_ERROR("%s: No memory for current_job_frames", __func__); 88 return rc; 89 } 90 *(test_obj->current_job_frames) = *recvd_frame; 91 92 memset(&job, 0, sizeof(job)); 93 job.job_type = JPEG_JOB_TYPE_ENCODE; 94 job.encode_job.session_id = test_obj->current_jpeg_sess_id; 95 96 job.encode_job.rotation = 0; 97 if (cam_cap->position == CAM_POSITION_BACK) { 98 /* back camera, rotate 90 */ 99 job.encode_job.rotation = 90; 100 } 101 102 /* fill in main src img encode param */ 103 job.encode_job.main_dim.src_dim = m_stream->s_config.stream_info->dim; 104 job.encode_job.main_dim.dst_dim = m_stream->s_config.stream_info->dim; 105 job.encode_job.src_index = 0; 106 107 job.encode_job.thumb_dim.src_dim = m_stream->s_config.stream_info->dim; 108 job.encode_job.thumb_dim.dst_dim.width = DEFAULT_PREVIEW_WIDTH; 109 job.encode_job.thumb_dim.dst_dim.height = DEFAULT_PREVIEW_HEIGHT; 110 111 /* fill in sink img param */ 112 job.encode_job.dst_index = 0; 113 114 rc = test_obj->jpeg_ops.start_job(&job, &test_obj->current_job_id); 115 if ( 0 != rc ) { 116 free(test_obj->current_job_frames); 117 test_obj->current_job_frames = NULL; 118 } 119 120 return rc; 121 } 122 123 int createEncodingSession(mm_camera_test_obj_t *test_obj, 124 mm_camera_stream_t *m_stream, 125 mm_camera_buf_def_t *m_frame) 126 { 127 mm_jpeg_encode_params_t encode_param; 128 129 memset(&encode_param, 0, sizeof(mm_jpeg_encode_params_t)); 130 encode_param.jpeg_cb = jpeg_encode_cb; 131 encode_param.userdata = (void*)test_obj; 132 encode_param.encode_thumbnail = 1; 133 encode_param.quality = 85; 134 encode_param.color_format = MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2; 135 136 /* fill in main src img encode param */ 137 encode_param.num_src_bufs = 1; 138 encode_param.src_main_buf[0].index = 0; 139 encode_param.src_main_buf[0].buf_size = m_frame->frame_len; 140 encode_param.src_main_buf[0].buf_vaddr = (uint8_t *)m_frame->buffer; 141 encode_param.src_main_buf[0].fd = m_frame->fd; 142 encode_param.src_main_buf[0].format = MM_JPEG_FMT_YUV; 143 encode_param.src_main_buf[0].offset = m_stream->offset; 144 145 /* fill in sink img param */ 146 encode_param.num_dst_bufs = 1; 147 encode_param.dest_buf[0].index = 0; 148 encode_param.dest_buf[0].buf_size = test_obj->jpeg_buf.buf.frame_len; 149 encode_param.dest_buf[0].buf_vaddr = (uint8_t *)test_obj->jpeg_buf.buf.buffer; 150 encode_param.dest_buf[0].fd = test_obj->jpeg_buf.buf.fd; 151 encode_param.dest_buf[0].format = MM_JPEG_FMT_YUV; 152 153 return test_obj->jpeg_ops.create_session(test_obj->jpeg_hdl, 154 &encode_param, 155 &test_obj->current_jpeg_sess_id); 156 } 157 158 static void mm_app_snapshot_notify_cb(mm_camera_super_buf_t *bufs, 159 void *user_data) 160 { 161 162 int rc; 163 int i = 0; 164 mm_camera_test_obj_t *pme = (mm_camera_test_obj_t *)user_data; 165 mm_camera_channel_t *channel = NULL; 166 mm_camera_stream_t *p_stream = NULL; 167 mm_camera_stream_t *m_stream = NULL; 168 mm_camera_buf_def_t *p_frame = NULL; 169 mm_camera_buf_def_t *m_frame = NULL; 170 171 CDBG("%s: BEGIN\n", __func__); 172 173 /* find channel */ 174 for (i = 0; i < MM_CHANNEL_TYPE_MAX; i++) { 175 if (pme->channels[i].ch_id == bufs->ch_id) { 176 channel = &pme->channels[i]; 177 break; 178 } 179 } 180 if (NULL == channel) { 181 CDBG_ERROR("%s: Wrong channel id (%d)", __func__, bufs->ch_id); 182 rc = -1; 183 goto error; 184 } 185 186 /* find snapshot stream */ 187 for (i = 0; i < channel->num_streams; i++) { 188 if (channel->streams[i].s_config.stream_info->stream_type == CAM_STREAM_TYPE_SNAPSHOT) { 189 m_stream = &channel->streams[i]; 190 break; 191 } 192 } 193 if (NULL == m_stream) { 194 CDBG_ERROR("%s: cannot find snapshot stream", __func__); 195 rc = -1; 196 goto error; 197 } 198 199 /* find snapshot frame */ 200 for (i = 0; i < bufs->num_bufs; i++) { 201 if (bufs->bufs[i]->stream_id == m_stream->s_id) { 202 m_frame = bufs->bufs[i]; 203 break; 204 } 205 } 206 if (NULL == m_frame) { 207 CDBG_ERROR("%s: main frame is NULL", __func__); 208 rc = -1; 209 goto error; 210 } 211 212 mm_app_dump_frame(m_frame, "main", "yuv", m_frame->frame_idx); 213 214 /* find postview stream */ 215 for (i = 0; i < channel->num_streams; i++) { 216 if (channel->streams[i].s_config.stream_info->stream_type == CAM_STREAM_TYPE_POSTVIEW) { 217 p_stream = &channel->streams[i]; 218 break; 219 } 220 } 221 if (NULL != p_stream) { 222 /* find preview frame */ 223 for (i = 0; i < bufs->num_bufs; i++) { 224 if (bufs->bufs[i]->stream_id == p_stream->s_id) { 225 p_frame = bufs->bufs[i]; 226 break; 227 } 228 } 229 if (NULL != p_frame) { 230 mm_app_dump_frame(p_frame, "postview", "yuv", p_frame->frame_idx); 231 } 232 } 233 234 mm_app_cache_ops((mm_camera_app_meminfo_t *)m_frame->mem_info, 235 ION_IOC_CLEAN_INV_CACHES); 236 237 /* create a new jpeg encoding session */ 238 rc = createEncodingSession(pme, m_stream, m_frame); 239 if (0 != rc) { 240 CDBG_ERROR("%s: error creating jpeg session", __func__); 241 goto error; 242 } 243 244 /* start jpeg encoding job */ 245 rc = encodeData(pme, bufs, m_stream); 246 247 error: 248 /* buf done rcvd frames in error case */ 249 if ( 0 != rc ) { 250 for (i=0; i<bufs->num_bufs; i++) { 251 if (MM_CAMERA_OK != pme->cam->ops->qbuf(bufs->camera_handle, 252 bufs->ch_id, 253 bufs->bufs[i])) { 254 CDBG_ERROR("%s: Failed in Qbuf\n", __func__); 255 } 256 mm_app_cache_ops((mm_camera_app_meminfo_t *)bufs->bufs[i]->mem_info, 257 ION_IOC_INV_CACHES); 258 } 259 } 260 261 CDBG("%s: END\n", __func__); 262 } 263 264 mm_camera_channel_t * mm_app_add_snapshot_channel(mm_camera_test_obj_t *test_obj) 265 { 266 mm_camera_channel_t *channel = NULL; 267 mm_camera_stream_t *stream = NULL; 268 269 channel = mm_app_add_channel(test_obj, 270 MM_CHANNEL_TYPE_SNAPSHOT, 271 NULL, 272 NULL, 273 NULL); 274 if (NULL == channel) { 275 CDBG_ERROR("%s: add channel failed", __func__); 276 return NULL; 277 } 278 279 stream = mm_app_add_snapshot_stream(test_obj, 280 channel, 281 mm_app_snapshot_notify_cb, 282 (void *)test_obj, 283 1, 284 1); 285 if (NULL == stream) { 286 CDBG_ERROR("%s: add snapshot stream failed\n", __func__); 287 mm_app_del_channel(test_obj, channel); 288 return NULL; 289 } 290 291 return channel; 292 } 293 294 mm_camera_stream_t * mm_app_add_postview_stream(mm_camera_test_obj_t *test_obj, 295 mm_camera_channel_t *channel, 296 mm_camera_buf_notify_t stream_cb, 297 void *userdata, 298 uint8_t num_bufs, 299 uint8_t num_burst) 300 { 301 int rc = MM_CAMERA_OK; 302 mm_camera_stream_t *stream = NULL; 303 cam_capability_t *cam_cap = (cam_capability_t *)(test_obj->cap_buf.buf.buffer); 304 305 stream = mm_app_add_stream(test_obj, channel); 306 if (NULL == stream) { 307 CDBG_ERROR("%s: add stream failed\n", __func__); 308 return NULL; 309 } 310 311 stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf; 312 stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf; 313 stream->s_config.mem_vtbl.clean_invalidate_buf = 314 mm_app_stream_clean_invalidate_buf; 315 stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf; 316 stream->s_config.mem_vtbl.user_data = (void *)stream; 317 stream->s_config.stream_cb = stream_cb; 318 stream->s_config.userdata = userdata; 319 stream->num_of_bufs = num_bufs; 320 321 stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer; 322 memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t)); 323 stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_POSTVIEW; 324 if (num_burst == 0) { 325 stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS; 326 } else { 327 stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST; 328 stream->s_config.stream_info->num_of_burst = num_burst; 329 } 330 stream->s_config.stream_info->fmt = DEFAULT_PREVIEW_FORMAT; 331 stream->s_config.stream_info->dim.width = DEFAULT_PREVIEW_WIDTH; 332 stream->s_config.stream_info->dim.height = DEFAULT_PREVIEW_HEIGHT; 333 stream->s_config.padding_info = cam_cap->padding_info; 334 335 rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config); 336 if (MM_CAMERA_OK != rc) { 337 CDBG_ERROR("%s:config preview stream err=%d\n", __func__, rc); 338 return NULL; 339 } 340 341 return stream; 342 } 343 344 int mm_app_start_capture(mm_camera_test_obj_t *test_obj, 345 uint8_t num_snapshots) 346 { 347 int32_t rc = MM_CAMERA_OK; 348 mm_camera_channel_t *channel = NULL; 349 mm_camera_stream_t *s_main = NULL; 350 mm_camera_stream_t *s_postview = NULL; 351 mm_camera_channel_attr_t attr; 352 353 memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); 354 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS; 355 attr.max_unmatched_frames = 3; 356 channel = mm_app_add_channel(test_obj, 357 MM_CHANNEL_TYPE_CAPTURE, 358 &attr, 359 mm_app_snapshot_notify_cb, 360 test_obj); 361 if (NULL == channel) { 362 CDBG_ERROR("%s: add channel failed", __func__); 363 return -MM_CAMERA_E_GENERAL; 364 } 365 366 s_postview = mm_app_add_postview_stream(test_obj, 367 channel, 368 NULL, 369 NULL, 370 num_snapshots, 371 num_snapshots); 372 if (NULL == s_postview) { 373 CDBG_ERROR("%s: add preview stream failed\n", __func__); 374 mm_app_del_channel(test_obj, channel); 375 return rc; 376 } 377 378 s_main = mm_app_add_snapshot_stream(test_obj, 379 channel, 380 NULL, 381 NULL, 382 num_snapshots, 383 num_snapshots); 384 if (NULL == s_main) { 385 CDBG_ERROR("%s: add main snapshot stream failed\n", __func__); 386 mm_app_del_stream(test_obj, channel, s_postview); 387 mm_app_del_channel(test_obj, channel); 388 return rc; 389 } 390 391 rc = mm_app_start_channel(test_obj, channel); 392 if (MM_CAMERA_OK != rc) { 393 CDBG_ERROR("%s:start zsl failed rc=%d\n", __func__, rc); 394 mm_app_del_stream(test_obj, channel, s_postview); 395 mm_app_del_stream(test_obj, channel, s_main); 396 mm_app_del_channel(test_obj, channel); 397 return rc; 398 } 399 400 return rc; 401 } 402 403 int mm_app_stop_capture(mm_camera_test_obj_t *test_obj) 404 { 405 int rc = MM_CAMERA_OK; 406 mm_camera_channel_t *ch = NULL; 407 408 ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_CAPTURE); 409 410 rc = mm_app_stop_channel(test_obj, ch); 411 if (MM_CAMERA_OK != rc) { 412 CDBG_ERROR("%s:stop recording failed rc=%d\n", __func__, rc); 413 } 414 415 return rc; 416 } 417