mm_qcamera_snapshot.c revision 6f83d735d8e3b918da42e6b559fcd0efb78133e5
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 */ 34static 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 75int 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 123int 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 158static 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 247error: 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 264mm_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 294mm_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.user_data = (void *)stream; 314 stream->s_config.stream_cb = stream_cb; 315 stream->s_config.userdata = userdata; 316 stream->num_of_bufs = num_bufs; 317 318 stream->s_config.stream_info = (cam_stream_info_t *)stream->s_info_buf.buf.buffer; 319 memset(stream->s_config.stream_info, 0, sizeof(cam_stream_info_t)); 320 stream->s_config.stream_info->stream_type = CAM_STREAM_TYPE_POSTVIEW; 321 if (num_burst == 0) { 322 stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS; 323 } else { 324 stream->s_config.stream_info->streaming_mode = CAM_STREAMING_MODE_BURST; 325 stream->s_config.stream_info->num_of_burst = num_burst; 326 } 327 stream->s_config.stream_info->fmt = DEFAULT_PREVIEW_FORMAT; 328 stream->s_config.stream_info->dim.width = DEFAULT_PREVIEW_WIDTH; 329 stream->s_config.stream_info->dim.height = DEFAULT_PREVIEW_HEIGHT; 330 stream->s_config.padding_info = cam_cap->padding_info; 331 332 rc = mm_app_config_stream(test_obj, channel, stream, &stream->s_config); 333 if (MM_CAMERA_OK != rc) { 334 CDBG_ERROR("%s:config preview stream err=%d\n", __func__, rc); 335 return NULL; 336 } 337 338 return stream; 339} 340 341int mm_app_start_capture(mm_camera_test_obj_t *test_obj, 342 uint8_t num_snapshots) 343{ 344 int32_t rc = MM_CAMERA_OK; 345 mm_camera_channel_t *channel = NULL; 346 mm_camera_stream_t *s_main = NULL; 347 mm_camera_stream_t *s_postview = NULL; 348 mm_camera_channel_attr_t attr; 349 350 memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); 351 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS; 352 attr.max_unmatched_frames = 3; 353 channel = mm_app_add_channel(test_obj, 354 MM_CHANNEL_TYPE_CAPTURE, 355 &attr, 356 mm_app_snapshot_notify_cb, 357 test_obj); 358 if (NULL == channel) { 359 CDBG_ERROR("%s: add channel failed", __func__); 360 return -MM_CAMERA_E_GENERAL; 361 } 362 363 s_postview = mm_app_add_postview_stream(test_obj, 364 channel, 365 NULL, 366 NULL, 367 num_snapshots, 368 num_snapshots); 369 if (NULL == s_postview) { 370 CDBG_ERROR("%s: add preview stream failed\n", __func__); 371 mm_app_del_channel(test_obj, channel); 372 return rc; 373 } 374 375 s_main = mm_app_add_snapshot_stream(test_obj, 376 channel, 377 NULL, 378 NULL, 379 num_snapshots, 380 num_snapshots); 381 if (NULL == s_main) { 382 CDBG_ERROR("%s: add main snapshot stream failed\n", __func__); 383 mm_app_del_stream(test_obj, channel, s_postview); 384 mm_app_del_channel(test_obj, channel); 385 return rc; 386 } 387 388 rc = mm_app_start_channel(test_obj, channel); 389 if (MM_CAMERA_OK != rc) { 390 CDBG_ERROR("%s:start zsl failed rc=%d\n", __func__, rc); 391 mm_app_del_stream(test_obj, channel, s_postview); 392 mm_app_del_stream(test_obj, channel, s_main); 393 mm_app_del_channel(test_obj, channel); 394 return rc; 395 } 396 397 return rc; 398} 399 400int mm_app_stop_capture(mm_camera_test_obj_t *test_obj) 401{ 402 int rc = MM_CAMERA_OK; 403 mm_camera_channel_t *ch = NULL; 404 405 ch = mm_app_get_channel_by_type(test_obj, MM_CHANNEL_TYPE_CAPTURE); 406 407 rc = mm_app_stop_channel(test_obj, ch); 408 if (MM_CAMERA_OK != rc) { 409 CDBG_ERROR("%s:stop recording failed rc=%d\n", __func__, rc); 410 } 411 412 return rc; 413} 414