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
mm_camera_read_raw_frame(mm_camera_obj_t * my_obj)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
mm_camera_zsl_frame_cmp_and_enq(mm_camera_obj_t * my_obj,mm_camera_frame_t * node,mm_camera_stream_t * mystream)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
mm_camera_read_preview_frame(mm_camera_obj_t * my_obj)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
mm_camera_snapshot_send_liveshot_notify(mm_camera_obj_t * my_obj)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
mm_camera_snapshot_send_snapshot_notify(mm_camera_obj_t * my_obj)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
mm_camera_read_snapshot_main_frame(mm_camera_obj_t * my_obj)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 }
mm_camera_read_snapshot_thumbnail_frame(mm_camera_obj_t * my_obj)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
mm_camera_read_video_frame(mm_camera_obj_t * my_obj)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
mm_camera_read_video_main_frame(mm_camera_obj_t * my_obj)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
mm_camera_read_zsl_main_frame(mm_camera_obj_t * my_obj)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
mm_camera_read_zsl_postview_frame(mm_camera_obj_t * my_obj)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
mm_camera_msm_data_notify(mm_camera_obj_t * my_obj,int fd,mm_camera_stream_type_t stream_type)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
mm_camera_image_mode_to_ch(int image_mode)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
mm_camera_dispatch_app_event(mm_camera_obj_t * my_obj,mm_camera_event_t * event)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
mm_camera_msm_evt_notify(mm_camera_obj_t * my_obj,int fd)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