1 /* 2 Copyright (c) 2011-2012, 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 <pthread.h> 31 #include "mm_camera_dbg.h" 32 #include <errno.h> 33 #include <sys/ioctl.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <poll.h> 38 #include <linux/msm_ion.h> 39 #include "mm_camera_interface2.h" 40 #include "mm_camera.h" 41 42 #if 0 43 #undef CDBG 44 #undef LOG_TAG 45 #define CDBG ALOGV 46 #define LOG_TAG "NotifyLogs" 47 #endif 48 49 static void mm_camera_read_raw_frame(mm_camera_obj_t * my_obj) 50 { 51 int rc = 0; 52 int idx; 53 int i; 54 int cnt = 0; 55 mm_camera_stream_t *stream; 56 mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX]; 57 mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX]; 58 59 stream = &my_obj->ch[MM_CAMERA_CH_RAW].raw.stream; 60 idx = mm_camera_read_msm_frame(my_obj, stream); 61 if (idx < 0) { 62 return; 63 } 64 pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_RAW].mutex); 65 for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) { 66 if((my_obj->ch[MM_CAMERA_CH_RAW].buf_cb[i].cb) && 67 (my_obj->poll_threads[MM_CAMERA_CH_RAW].data.used == 1)){ 68 data[cnt].type = MM_CAMERA_CH_RAW; 69 data[cnt].def.idx = idx; 70 data[cnt].def.frame = &my_obj->ch[MM_CAMERA_CH_RAW].raw.stream.frame.frame[idx].frame; 71 my_obj->ch[MM_CAMERA_CH_RAW].raw.stream.frame.ref_count[idx]++; 72 CDBG("%s:calling data notify cb 0x%x, 0x%x\n", __func__, 73 (uint32_t)my_obj->ch[MM_CAMERA_CH_RAW].buf_cb[i].cb, 74 (uint32_t)my_obj->ch[MM_CAMERA_CH_RAW].buf_cb[i].user_data); 75 memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_RAW].buf_cb[i], sizeof(mm_camera_buf_cb_t)); 76 cnt++; 77 } 78 } 79 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_RAW].mutex); 80 81 for( i=0;i<cnt;i++) { 82 if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_RAW].data.used == 1){ 83 buf_cb[i].cb(&data[i],buf_cb[i].user_data); 84 } 85 } 86 } 87 88 int mm_camera_zsl_frame_cmp_and_enq(mm_camera_obj_t * my_obj, 89 mm_camera_frame_t *node, 90 mm_camera_stream_t *mystream) 91 { 92 int watermark, interval; 93 mm_camera_frame_queue_t *myq; 94 mm_camera_frame_queue_t *peerq; 95 mm_camera_stream_t *peerstream; 96 int rc = 0; 97 int deliver_done = 0; 98 mm_camera_frame_t *peer_frame; 99 mm_camera_frame_t *peer_frame_prev; 100 mm_camera_frame_t *peer_frame_tmp; 101 mm_camera_notify_frame_t notify_frame; 102 uint32_t expected_id; 103 mm_camera_ch_data_buf_t data; 104 mm_camera_frame_t *my_frame = NULL; 105 int i; 106 mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX]; 107 108 pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex); 109 pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 110 111 if(mystream->stream_type == MM_CAMERA_STREAM_PREVIEW) { 112 peerstream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main; 113 } else 114 peerstream = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream; 115 myq = &mystream->frame.readyq; 116 peerq = &peerstream->frame.readyq; 117 watermark = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.water_mark; 118 interval = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.interval; 119 expected_id = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.expected_matching_id; 120 peer_frame = peerq->tail; 121 /* for 30-120 fps streaming no need to consider the wrapping back of frame_id 122 expected_matching_id is used when requires skipping bwtween frames */ 123 if(!peer_frame || (node->frame.frame_id > peer_frame->frame.frame_id && 124 node->frame.frame_id >= expected_id)) { 125 /* new frame is newer than all stored peer frames. simply keep the node */ 126 /* in case the frame_id wraps back, the peer frame's frame_id will be 127 larger than the new frame's frame id */ 128 CDBG("%s New frame. Just enqueue it into the queue ", __func__); 129 mm_camera_stream_frame_enq_no_lock(myq, node); 130 node->valid_entry = 1; 131 } 132 CDBG("%s Need to find match for the frame id %d ,exped_id =%d, strm type =%d", 133 __func__, node->frame.frame_id, expected_id, mystream->stream_type); 134 /* the node is older than the peer, we will either find a match or drop it */ 135 peer_frame = peerq->head; 136 peer_frame_prev = NULL; 137 peer_frame_tmp = NULL; 138 while(peer_frame) { 139 CDBG("%s peer frame_id = %d node frame_id = %d, expected_id =%d, interval=%d", __func__, 140 peer_frame->frame.frame_id, node->frame.frame_id, 141 expected_id, interval); 142 if(peer_frame->match) { 143 CDBG("%s Peer frame already matched, keep looking in the list ", 144 __func__); 145 /* matched frame., skip */ 146 peer_frame_prev = peer_frame; 147 peer_frame = peer_frame->next; 148 continue; 149 } 150 if(peer_frame->frame.frame_id == node->frame.frame_id && 151 node->frame.frame_id >= my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.expected_matching_id) { 152 /* find a match keep the frame */ 153 node->match = 1; 154 peer_frame->match = 1; 155 CDBG("%s Found match, add to myq, frame_id=%d ", __func__, node->frame.frame_id); 156 mm_camera_stream_frame_enq_no_lock(myq, node); 157 myq->match_cnt++; 158 peerq->match_cnt++; 159 /*set next min matching id*/ 160 my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.expected_matching_id = 161 node->frame.frame_id + interval; 162 goto water_mark; 163 } else { 164 /* no match */ 165 if(node->frame.frame_id > peer_frame->frame.frame_id) { 166 /* the incoming frame is newer than the peer's unmatched frame. 167 drop the peer frame */ 168 CDBG("%s node frame is newer, release old peer frame ", 169 __func__); 170 if(!peer_frame_prev) { 171 /* this is the head */ 172 peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(peerq); 173 notify_frame.frame = &peer_frame_tmp->frame; 174 notify_frame.idx = peer_frame_tmp->idx; 175 mm_camera_stream_util_buf_done(my_obj, peerstream, 176 ¬ify_frame); 177 peer_frame = peerq->head; 178 peer_frame_prev = NULL; 179 continue; 180 } else { 181 /* this is not the head. */ 182 peer_frame_tmp = peer_frame; 183 peer_frame_prev->next = peer_frame->next; 184 if(peer_frame == peerq->tail) { 185 /* peer_frame is the tail */ 186 peerq->tail = peer_frame_prev; 187 } 188 notify_frame.frame = &peer_frame_tmp->frame; 189 notify_frame.idx = peer_frame_tmp->idx; 190 mm_camera_stream_util_buf_done(my_obj, peerstream, 191 ¬ify_frame); 192 peer_frame = peer_frame_prev->next; 193 peerq->cnt--; 194 continue; 195 } 196 } else { 197 /* Current frame is older than peer's unmatched frame, dont add 198 * it into the queue. just drop it */ 199 CDBG("%s node frame is older than peer's unmatched frame. " 200 "Drop the current frame.", __func__); 201 notify_frame.frame = &node->frame; 202 notify_frame.idx = node->idx; 203 mm_camera_stream_util_buf_done(my_obj, mystream, ¬ify_frame); 204 goto end; 205 } 206 } 207 } 208 if(!node->match && !node->valid_entry) { 209 /* if no match and not a valid entry. 210 * the node is not added into the queue. it's dirty node */ 211 CDBG_ERROR("%s: stream type = %d and fd = %d, frame 0x%x is dirty" 212 " and queue back kernel", __func__, mystream->stream_type, 213 mystream->fd, node->frame.frame_id); 214 notify_frame.frame = &node->frame; 215 notify_frame.idx = node->idx; 216 mm_camera_stream_util_buf_done(my_obj, mystream, ¬ify_frame); 217 } 218 water_mark: 219 while((myq->match_cnt > watermark) && (peerq->match_cnt > watermark)) { 220 peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(peerq); 221 if (NULL == peer_frame_tmp) { 222 break; 223 } 224 notify_frame.frame = &peer_frame_tmp->frame; 225 notify_frame.idx = peer_frame_tmp->idx; 226 CDBG("%s match_cnt %d > watermark %d, buf_done on " 227 "peer frame idx %d id = %d", __func__, 228 myq->match_cnt, watermark, notify_frame.idx, 229 notify_frame.frame->frame_id); 230 mm_camera_stream_util_buf_done(my_obj, peerstream, ¬ify_frame); 231 peerq->match_cnt--; 232 peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(myq); 233 notify_frame.frame = &peer_frame_tmp->frame; 234 notify_frame.idx = peer_frame_tmp->idx; 235 mm_camera_stream_util_buf_done(my_obj, mystream, ¬ify_frame); 236 myq->match_cnt--; 237 } 238 end: 239 CDBG("%s myQ->cnt = %d myQ->match_cnt = %d ", __func__, 240 myq->cnt, myq->match_cnt); 241 if(myq->cnt > myq->match_cnt + 1) { 242 /* drop the first unmatched frame */ 243 mm_camera_frame_t *peer_frame = myq->head;; 244 mm_camera_frame_t *peer_frame_prev = NULL; 245 while(peer_frame) { 246 CDBG("%s myQ->cnt = %d myQ->match_cnt = %d ", __func__, 247 myq->cnt, myq->match_cnt); 248 if(peer_frame->match == 0) { 249 /* first unmatched frame */ 250 if(!peer_frame_prev) { 251 /* this is the head */ 252 peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(myq); 253 notify_frame.frame = &peer_frame_tmp->frame; 254 notify_frame.idx = peer_frame_tmp->idx; 255 CDBG("%s Head Issuing buf_done on my frame idx %d id %d", 256 __func__, notify_frame.idx, 257 notify_frame.frame->frame_id); 258 mm_camera_stream_util_buf_done(my_obj, mystream, 259 ¬ify_frame); 260 } else { 261 /* this is not the head. */ 262 peer_frame_tmp = peer_frame; 263 peer_frame_prev->next = peer_frame->next; 264 if(peer_frame == peerq->tail) { 265 /* peer_frame is the tail */ 266 myq->tail = peer_frame_prev; 267 } 268 notify_frame.frame = &peer_frame_tmp->frame; 269 notify_frame.idx = peer_frame_tmp->idx; 270 CDBG("%s Issuing buf_done on my frame idx %d id = %d", 271 __func__, notify_frame.idx, 272 notify_frame.frame->frame_id); 273 mm_camera_stream_util_buf_done(my_obj, mystream, 274 ¬ify_frame); 275 myq->cnt--; 276 } 277 break; 278 } else { 279 peer_frame_prev= peer_frame; 280 peer_frame = peer_frame_prev->next; 281 } 282 } 283 } 284 CDBG("%s peerQ->cnt = %d peerQ->match_cnt = %d ", __func__, 285 peerq->cnt, peerq->match_cnt); 286 if(peerq->cnt > peerq->match_cnt + 1) { 287 /* drop the first unmatched frame */ 288 mm_camera_frame_t *peer_frame = peerq->head; 289 mm_camera_frame_t *peer_frame_prev = NULL; 290 while(peer_frame) { 291 CDBG("%s Traverse peerq list frame idx %d frame_id = %d match %d ", 292 __func__, peer_frame->idx, peer_frame->frame.frame_id, 293 peer_frame->match); 294 if(peer_frame->match == 0) { 295 /* first unmatched frame */ 296 if(!peer_frame_prev) { 297 /* this is the head */ 298 peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(peerq); 299 notify_frame.frame = &peer_frame_tmp->frame; 300 notify_frame.idx = peer_frame_tmp->idx; 301 CDBG("%s Head Issuing buf_done on peer frame idx %d " 302 "id = %d", __func__, notify_frame.idx, 303 notify_frame.frame->frame_id); 304 mm_camera_stream_util_buf_done(my_obj, peerstream, 305 ¬ify_frame); 306 } else { 307 /* this is not the head. */ 308 peer_frame_tmp = peer_frame; 309 peer_frame_prev->next = peer_frame->next; 310 if(peer_frame == peerq->tail) { 311 /* peer_frame is the tail */ 312 peerq->tail = peer_frame_prev; 313 } 314 notify_frame.frame = &peer_frame_tmp->frame; 315 notify_frame.idx = peer_frame_tmp->idx; 316 CDBG("%s Issuing buf_done on peer frame idx %d id = %d", 317 __func__, notify_frame.idx, 318 notify_frame.frame->frame_id); 319 mm_camera_stream_util_buf_done(my_obj, peerstream, 320 ¬ify_frame); 321 peerq->cnt--; 322 } 323 break; 324 } else { 325 peer_frame_prev= peer_frame; 326 peer_frame = peer_frame_prev->next; 327 } 328 } 329 } 330 331 CDBG("%s Dispatching ZSL frame ", __func__); 332 if(my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.pending_cnt > 0) { 333 if(!myq->match_cnt || !peerq->match_cnt) { 334 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 335 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex); 336 return 0; 337 } 338 /* dequeue one by one and then pass to HAL */ 339 my_frame = mm_camera_stream_frame_deq_no_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq); 340 peer_frame = mm_camera_stream_frame_deq_no_lock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.readyq); 341 if (!my_frame || !peer_frame) { 342 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 343 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex); 344 return 0; 345 } 346 myq->match_cnt--; 347 peerq->match_cnt--; 348 CDBG("%s: Dequeued frame: main frame idx: %d thumbnail " 349 "frame idx: %d", __func__, my_frame->idx, peer_frame->idx); 350 /* dispatch this pair of frames */ 351 memset(&data, 0, sizeof(data)); 352 data.type = MM_CAMERA_CH_SNAPSHOT; 353 data.snapshot.main.frame = &my_frame->frame; 354 data.snapshot.main.idx = my_frame->idx; 355 data.snapshot.thumbnail.frame = &peer_frame->frame; 356 data.snapshot.thumbnail.idx = peer_frame->idx; 357 my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.pending_cnt--; 358 memcpy(&buf_cb[0], &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[0], 359 sizeof(mm_camera_buf_cb_t)* MM_CAMERA_BUF_CB_MAX); 360 if(my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.pending_cnt == 0) 361 deliver_done = 1; 362 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 363 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex); 364 365 goto send_to_hal; 366 } 367 368 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 369 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex); 370 return rc; 371 372 send_to_hal: 373 for( i=0;i < MM_CAMERA_BUF_CB_MAX;i++) { 374 if (buf_cb[i].cb && my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1) 375 buf_cb[i].cb(&data,buf_cb[i].user_data); 376 } 377 if(deliver_done > 0) { 378 mm_camera_event_t data_evt; 379 CDBG("%s: ZSL delivered", __func__); 380 data_evt.event_type = MM_CAMERA_EVT_TYPE_CH; 381 data_evt.e.ch.evt = MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE; 382 data_evt.e.ch.ch = MM_CAMERA_CH_SNAPSHOT; 383 mm_camera_poll_send_ch_event(my_obj, &data_evt); 384 } 385 return rc; 386 } 387 388 static void mm_camera_read_preview_frame(mm_camera_obj_t * my_obj) 389 { 390 int rc = 0; 391 int idx; 392 int i; 393 int cnt = 0; 394 mm_camera_stream_t *stream; 395 mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX]; 396 mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX]; 397 398 if (!my_obj->ch[MM_CAMERA_CH_PREVIEW].acquired) { 399 ALOGV("Preview channel is not in acquired state \n"); 400 return; 401 } 402 stream = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream; 403 idx = mm_camera_read_msm_frame(my_obj, stream); 404 if (idx < 0) { 405 return; 406 } 407 CDBG("%s Read Preview frame %d ", __func__, idx); 408 pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex); 409 for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) { 410 if((my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].cb) && 411 (my_obj->poll_threads[MM_CAMERA_CH_PREVIEW].data.used == 1)) { 412 data[cnt].type = MM_CAMERA_CH_PREVIEW; 413 data[cnt].def.idx = idx; 414 data[cnt].def.frame = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.frame[idx].frame; 415 /* Since the frame is originating here, reset the ref count to either 416 * 2(ZSL case) or 1(non-ZSL case). */ 417 if(my_obj->op_mode == MM_CAMERA_OP_MODE_ZSL) 418 my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.ref_count[idx] = 2; 419 else 420 my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.ref_count[idx] = 1; 421 CDBG("%s:calling data notify cb 0x%x, 0x%x\n", __func__, 422 (uint32_t)my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].cb, 423 (uint32_t)my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].user_data); 424 /*my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].cb(&data, 425 my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].user_data);*/ 426 memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i], 427 sizeof(mm_camera_buf_cb_t)); 428 cnt++; 429 } 430 } 431 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex); 432 433 if(my_obj->op_mode == MM_CAMERA_OP_MODE_ZSL) { 434 /* Reset match to 0. */ 435 stream->frame.frame[idx].match = 0; 436 stream->frame.frame[idx].valid_entry = 0; 437 mm_camera_zsl_frame_cmp_and_enq(my_obj, 438 &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.frame[idx], 439 stream); 440 } 441 442 for( i=0;i<cnt;i++) { 443 if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_PREVIEW].data.used == 1) { 444 buf_cb[i].cb(&data[i],buf_cb[i].user_data); 445 } 446 } 447 } 448 449 static void mm_camera_snapshot_send_liveshot_notify(mm_camera_obj_t * my_obj) 450 { 451 int delivered = 0; 452 mm_camera_frame_queue_t *s_q; 453 int i; 454 int cnt = 0; 455 // mm_camera_frame_queue_t *s_q, *t_q; 456 mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX]; 457 mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX]; 458 459 mm_camera_frame_t *frame; 460 s_q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq; 461 pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 462 463 for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) { 464 if(s_q->cnt && my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].cb) { 465 data[cnt].type = MM_CAMERA_CH_SNAPSHOT; 466 frame = mm_camera_stream_frame_deq(s_q); 467 data[cnt].snapshot.main.frame = &frame->frame; 468 data[cnt].snapshot.main.idx = frame->idx; 469 data[cnt].snapshot.thumbnail.frame = NULL; 470 my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.ref_count[data[cnt].snapshot.main.idx]++; 471 /*my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].cb(&data, 472 my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].user_data);*/ 473 memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i], 474 sizeof(mm_camera_buf_cb_t)); 475 cnt++; 476 477 my_obj->snap_burst_num_by_user -= 1; 478 CDBG("%s: burst number =%d", __func__, my_obj->snap_burst_num_by_user); 479 delivered = 1; 480 } 481 } 482 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 483 484 for( i=0;i<cnt;i++) { 485 if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1) { 486 buf_cb[i].cb(&data[i],buf_cb[i].user_data); 487 } 488 } 489 490 if(delivered) { 491 mm_camera_event_t data; 492 data.event_type = MM_CAMERA_EVT_TYPE_CH; 493 data.e.ch.evt = MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE; 494 data.e.ch.ch = MM_CAMERA_CH_SNAPSHOT; 495 mm_camera_poll_send_ch_event(my_obj, &data); 496 } 497 } 498 499 static void mm_camera_snapshot_send_snapshot_notify(mm_camera_obj_t * my_obj) 500 { 501 int delivered = 0; 502 int i; 503 int cnt = 0; 504 mm_camera_frame_queue_t *s_q, *t_q; 505 mm_camera_frame_t *frame; 506 //mm_camera_buf_cb_t buf_cb; 507 508 mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX]; 509 mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX]; 510 511 memset(&buf_cb, 0, sizeof(buf_cb)); 512 s_q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq; 513 t_q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq; 514 pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 515 516 for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) { 517 CDBG("%s Got notify: s_q->cnt = %d, t_q->cnt = %d, buf_cb = %x, " 518 "data.used = %d ", __func__, s_q->cnt, t_q->cnt, 519 (uint32_t)my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].cb, 520 my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used); 521 if((s_q->cnt && t_q->cnt && my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].cb) && 522 (my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1)) { 523 data[cnt].type = MM_CAMERA_CH_SNAPSHOT; 524 frame = mm_camera_stream_frame_deq(s_q); 525 data[cnt].snapshot.main.frame = &frame->frame; 526 data[cnt].snapshot.main.idx = frame->idx; 527 frame = mm_camera_stream_frame_deq(t_q); 528 data[cnt].snapshot.thumbnail.frame = &frame->frame; 529 data[cnt].snapshot.thumbnail.idx = frame->idx; 530 my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.ref_count[data[i].snapshot.main.idx]++; 531 my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.ref_count[data[i].snapshot.thumbnail.idx]++; 532 533 //bu = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i]; 534 memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i], 535 sizeof(mm_camera_buf_cb_t)); 536 cnt++; 537 538 //buf_cb.cb(&data,buf_cb.user_data); 539 my_obj->snap_burst_num_by_user -= 1; 540 CDBG("%s: burst number =%d", __func__, my_obj->snap_burst_num_by_user); 541 delivered = 1; 542 } 543 } 544 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex); 545 546 for( i=0;i<cnt;i++) { 547 if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1) { 548 buf_cb[i].cb(&data[i],buf_cb[i].user_data); 549 } 550 } 551 552 CDBG("%s Delivered = %d ", __func__, delivered ); 553 if(delivered) { 554 mm_camera_event_t edata; 555 /*for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++){ 556 buf_cb = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i]; 557 if((buf_cb) && (my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1)) { 558 buf_cb->cb(&data,buf_cb->user_data); 559 } 560 }*/ 561 edata.event_type = MM_CAMERA_EVT_TYPE_CH; 562 edata.e.ch.evt = MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE; 563 edata.e.ch.ch = MM_CAMERA_CH_SNAPSHOT; 564 mm_camera_poll_send_ch_event(my_obj, &edata); 565 } 566 } 567 568 static void mm_camera_read_snapshot_main_frame(mm_camera_obj_t * my_obj) 569 { 570 int rc = 0; 571 int idx; 572 mm_camera_stream_t *stream; 573 mm_camera_frame_queue_t *q; 574 if (!my_obj->ch[MM_CAMERA_CH_SNAPSHOT].acquired) { 575 ALOGV("Snapshot channel is not in acquired state \n"); 576 return; 577 } 578 q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq; 579 stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main; 580 idx = mm_camera_read_msm_frame(my_obj,stream); 581 if (idx < 0) 582 return; 583 584 CDBG("%s Read Snapshot frame %d ", __func__, idx); 585 if(my_obj->op_mode == MM_CAMERA_OP_MODE_ZSL) { 586 my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.ref_count[idx]++; 587 /* Reset match to 0. */ 588 stream->frame.frame[idx].match = 0; 589 stream->frame.frame[idx].valid_entry = 0; 590 mm_camera_zsl_frame_cmp_and_enq(my_obj, 591 &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.frame[idx], stream); 592 } else { 593 /* send to HAL */ 594 mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]); 595 if (!my_obj->full_liveshot) 596 mm_camera_snapshot_send_snapshot_notify(my_obj); 597 else 598 mm_camera_snapshot_send_liveshot_notify(my_obj); 599 } 600 } 601 static void mm_camera_read_snapshot_thumbnail_frame(mm_camera_obj_t * my_obj) 602 { 603 int idx, rc = 0; 604 mm_camera_stream_t *stream; 605 mm_camera_frame_queue_t *q; 606 607 if (!my_obj->ch[MM_CAMERA_CH_SNAPSHOT].acquired) { 608 ALOGV("Snapshot channel is not in acquired state \n"); 609 return; 610 } 611 q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq; 612 stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail; 613 idx = mm_camera_read_msm_frame(my_obj,stream); 614 if (idx < 0) 615 return; 616 if(my_obj->op_mode != MM_CAMERA_OP_MODE_ZSL) { 617 mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]); 618 mm_camera_snapshot_send_snapshot_notify(my_obj); 619 } else { 620 // CDBG("%s: ZSL does not use thumbnail stream", __func__); 621 rc = mm_camera_stream_qbuf(my_obj, stream, idx); 622 // CDBG("%s Q back thumbnail buffer rc = %d ", __func__, rc); 623 } 624 } 625 626 static void mm_camera_read_video_frame(mm_camera_obj_t * my_obj) 627 { 628 int idx, rc = 0; 629 mm_camera_stream_t *stream; 630 mm_camera_frame_queue_t *q; 631 int i; 632 int cnt = 0; 633 mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX]; 634 mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX]; 635 636 if (!my_obj->ch[MM_CAMERA_CH_VIDEO].acquired) { 637 ALOGV("Snapshot channel is not in acquired state \n"); 638 return; 639 } 640 stream = &my_obj->ch[MM_CAMERA_CH_VIDEO].video.video; 641 idx = mm_camera_read_msm_frame(my_obj,stream); 642 if (idx < 0) 643 return; 644 645 ALOGV("Video thread locked"); 646 pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_VIDEO].mutex); 647 for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) { 648 if((my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb) && 649 (my_obj->poll_threads[MM_CAMERA_CH_VIDEO].data.used == 1)){ 650 data[cnt].type = MM_CAMERA_CH_VIDEO; 651 data[cnt].video.main.frame = NULL; 652 data[cnt].video.main.idx = -1; 653 data[cnt].video.video.idx = idx; 654 data[cnt].video.video.frame = &my_obj->ch[MM_CAMERA_CH_VIDEO].video.video. 655 frame.frame[idx].frame; 656 my_obj->ch[MM_CAMERA_CH_VIDEO].video.video.frame.ref_count[idx]++; 657 ALOGV("Video thread callback issued"); 658 //my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb(&data, 659 // my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].user_data); 660 memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i], 661 sizeof(mm_camera_buf_cb_t)); 662 cnt++; 663 664 ALOGV("Video thread callback returned"); 665 if( my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb_type==MM_CAMERA_BUF_CB_COUNT ) { 666 ALOGV("<DEBUG>:%s: Additional cb called for buffer %p:%d",__func__,stream,idx); 667 if(--(my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb_count) == 0 ) 668 my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb=NULL; 669 } 670 } 671 } 672 pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_VIDEO].mutex); 673 674 for( i=0;i<cnt;i++) { 675 if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_VIDEO].data.used == 1) { 676 buf_cb[i].cb(&data[i],buf_cb[i].user_data); 677 } 678 /*if( buf_cb[i].cb_type==MM_CAMERA_BUF_CB_COUNT ) { 679 ALOGV("<DEBUG>:%s: Additional cb called for buffer %p:%d",__func__,stream,idx); 680 if(--(buf_cb[i].cb_count) == 0 ) 681 buf_cb[i].cb=NULL; 682 }*/ 683 } 684 685 ALOGV("Video thread unlocked"); 686 } 687 688 static void mm_camera_read_video_main_frame(mm_camera_obj_t * my_obj) 689 { 690 int rc = 0; 691 return;rc; 692 } 693 694 static void mm_camera_read_zsl_main_frame(mm_camera_obj_t * my_obj) 695 { 696 int idx, rc = 0; 697 mm_camera_stream_t *stream; 698 mm_camera_frame_queue_t *q; 699 mm_camera_frame_t *frame; 700 int cnt, watermark; 701 702 q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq; 703 stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main; 704 idx = mm_camera_read_msm_frame(my_obj,stream); 705 if (idx < 0) 706 return; 707 708 CDBG("%s: Enqueuing frame id: %d", __func__, idx); 709 mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]); 710 cnt = mm_camera_stream_frame_get_q_cnt(q); 711 watermark = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.water_mark; 712 713 CDBG("%s: Watermark: %d Queue in a frame: %d", __func__, watermark, cnt); 714 if(watermark < cnt) { 715 /* water overflow, queue head back to kernel */ 716 frame = mm_camera_stream_frame_deq(q); 717 if(frame) { 718 rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); 719 if(rc < 0) { 720 CDBG("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", 721 __func__, frame->idx, rc); 722 return; 723 } 724 } 725 } 726 mm_camera_check_pending_zsl_frames(my_obj, MM_CAMERA_CH_SNAPSHOT); 727 } 728 729 static void mm_camera_read_zsl_postview_frame(mm_camera_obj_t * my_obj) 730 { 731 int idx, rc = 0; 732 mm_camera_stream_t *stream; 733 mm_camera_frame_queue_t *q; 734 mm_camera_frame_t *frame; 735 int cnt, watermark; 736 q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq; 737 stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail; 738 idx = mm_camera_read_msm_frame(my_obj,stream); 739 if (idx < 0) 740 return; 741 mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]); 742 watermark = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.water_mark; 743 cnt = mm_camera_stream_frame_get_q_cnt(q); 744 if(watermark < cnt) { 745 /* water overflow, queue head back to kernel */ 746 frame = mm_camera_stream_frame_deq(q); 747 if(frame) { 748 rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); 749 if(rc < 0) { 750 CDBG("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", 751 __func__, frame->idx, rc); 752 return; 753 } 754 } 755 } 756 mm_camera_check_pending_zsl_frames(my_obj, MM_CAMERA_CH_SNAPSHOT); 757 } 758 759 void mm_camera_msm_data_notify(mm_camera_obj_t * my_obj, int fd, 760 mm_camera_stream_type_t stream_type) 761 { 762 switch(stream_type) { 763 case MM_CAMERA_STREAM_RAW: 764 mm_camera_read_raw_frame(my_obj); 765 break; 766 case MM_CAMERA_STREAM_PREVIEW: 767 mm_camera_read_preview_frame(my_obj); 768 break; 769 case MM_CAMERA_STREAM_SNAPSHOT: 770 mm_camera_read_snapshot_main_frame(my_obj); 771 break; 772 case MM_CAMERA_STREAM_THUMBNAIL: 773 mm_camera_read_snapshot_thumbnail_frame(my_obj); 774 break; 775 case MM_CAMERA_STREAM_VIDEO: 776 mm_camera_read_video_frame(my_obj); 777 break; 778 case MM_CAMERA_STREAM_VIDEO_MAIN: 779 mm_camera_read_video_main_frame(my_obj); 780 break; 781 default: 782 break; 783 } 784 } 785 786 static mm_camera_channel_type_t mm_camera_image_mode_to_ch(int image_mode) 787 { 788 switch(image_mode) { 789 case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW: 790 return MM_CAMERA_CH_PREVIEW; 791 case MSM_V4L2_EXT_CAPTURE_MODE_MAIN: 792 case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL: 793 return MM_CAMERA_CH_SNAPSHOT; 794 case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO: 795 return MM_CAMERA_CH_VIDEO; 796 case MSM_V4L2_EXT_CAPTURE_MODE_RAW: 797 return MM_CAMERA_CH_RAW; 798 default: 799 return MM_CAMERA_CH_MAX; 800 } 801 } 802 803 void mm_camera_dispatch_app_event(mm_camera_obj_t *my_obj, mm_camera_event_t *event) 804 { 805 int i; 806 mm_camera_evt_obj_t evtcb; 807 808 if(event->event_type < MM_CAMERA_EVT_TYPE_MAX) { 809 pthread_mutex_lock(&my_obj->mutex); 810 memcpy(&evtcb, 811 &my_obj->evt[event->event_type], 812 sizeof(mm_camera_evt_obj_t)); 813 pthread_mutex_unlock(&my_obj->mutex); 814 for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) { 815 if(evtcb.evt[i].evt_cb) { 816 evtcb.evt[i].evt_cb(event, evtcb.evt[i].user_data); 817 } 818 } 819 } 820 } 821 822 void mm_camera_msm_evt_notify(mm_camera_obj_t * my_obj, int fd) 823 { 824 struct v4l2_event ev; 825 int rc; 826 mm_camera_event_t *evt = NULL; 827 828 memset(&ev, 0, sizeof(ev)); 829 rc = ioctl(fd, VIDIOC_DQEVENT, &ev); 830 evt = (mm_camera_event_t *)ev.u.data; 831 832 if (rc >= 0) { 833 if(ev.type == V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_ERROR_EVENT) { 834 evt->event_type = MM_CAMERA_EVT_TYPE_CTRL; 835 evt->e.ctrl.evt = MM_CAMERA_CTRL_EVT_ERROR; 836 } 837 switch(evt->event_type) { 838 case MM_CAMERA_EVT_TYPE_INFO: 839 break; 840 case MM_CAMERA_EVT_TYPE_STATS: 841 break; 842 case MM_CAMERA_EVT_TYPE_CTRL: 843 break; 844 default: 845 break; 846 } 847 mm_camera_dispatch_app_event(my_obj, evt); 848 } 849 } 850