1 /* Copyright (c) 2012-2015, 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 <pthread.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <poll.h>
37 #include <cam_semaphore.h>
38
39 #include "mm_camera_dbg.h"
40 #include "mm_camera_interface.h"
41 #include "mm_camera.h"
42
43 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
44 extern mm_channel_t * mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj,
45 uint32_t handler);
46
47 /* internal function declare goes here */
48 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
49 mm_camera_buf_def_t *buf);
50 int32_t mm_channel_init(mm_channel_t *my_obj,
51 mm_camera_channel_attr_t *attr,
52 mm_camera_buf_notify_t channel_cb,
53 void *userdata);
54 void mm_channel_release(mm_channel_t *my_obj);
55 uint32_t mm_channel_add_stream(mm_channel_t *my_obj);
56 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
57 uint32_t stream_id);
58 uint32_t mm_channel_link_stream(mm_channel_t *my_obj,
59 mm_camera_stream_link_t *stream_link);
60 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
61 uint32_t stream_id,
62 mm_camera_stream_config_t *config);
63 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
64 cam_bundle_config_t *bundle_info);
65 int32_t mm_channel_start(mm_channel_t *my_obj);
66 int32_t mm_channel_stop(mm_channel_t *my_obj);
67 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
68 uint32_t num_buf_requested, uint32_t num_reto_buf_requested);
69 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
70 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj,
71 uint32_t frame_idx);
72 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
73 mm_camera_super_buf_notify_mode_t notify_mode);
74 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj);
75 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj);
76 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
77 mm_channel_queue_t * queue, cam_stream_type_t cam_type);
78 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
79 mm_evt_paylod_set_get_stream_parms_t *payload);
80 int32_t mm_channel_get_queued_buf_count(mm_channel_t *my_obj,
81 uint32_t stream_id);
82
83 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
84 mm_evt_paylod_set_get_stream_parms_t *payload);
85 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
86 mm_evt_paylod_do_stream_action_t *payload);
87 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
88 mm_evt_paylod_map_stream_buf_t *payload);
89 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
90 mm_evt_paylod_unmap_stream_buf_t *payload);
91
92 /* state machine function declare */
93 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
94 mm_channel_evt_type_t evt,
95 void * in_val,
96 void * out_val);
97 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
98 mm_channel_evt_type_t evt,
99 void * in_val,
100 void * out_val);
101 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
102 mm_channel_evt_type_t evt,
103 void * in_val,
104 void * out_val);
105 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
106 mm_channel_evt_type_t evt,
107 void * in_val,
108 void * out_val);
109
110 /* channel super queue functions */
111 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
112 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
113 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
114 mm_channel_queue_t * queue,
115 mm_camera_buf_info_t *buf);
116 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue);
117 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj,
118 mm_channel_queue_t *queue);
119 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj,
120 mm_channel_queue_t *queue);
121
122 static int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
123 mm_camera_generic_cmd_t *p_gen_cmd);
124 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
125 mm_channel_queue_t * queue);
126 /*===========================================================================
127 * FUNCTION : mm_channel_util_get_stream_by_handler
128 *
129 * DESCRIPTION: utility function to get a stream object from its handle
130 *
131 * PARAMETERS :
132 * @cam_obj: ptr to a channel object
133 * @handler: stream handle
134 *
135 * RETURN : ptr to a stream object.
136 * NULL if failed.
137 *==========================================================================*/
mm_channel_util_get_stream_by_handler(mm_channel_t * ch_obj,uint32_t handler)138 mm_stream_t * mm_channel_util_get_stream_by_handler(
139 mm_channel_t * ch_obj,
140 uint32_t handler)
141 {
142 int i;
143 mm_stream_t *s_obj = NULL;
144 for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
145 if ((MM_STREAM_STATE_NOTUSED != ch_obj->streams[i].state) &&
146 (handler == ch_obj->streams[i].my_hdl)) {
147 s_obj = &ch_obj->streams[i];
148 break;
149 }
150 }
151 return s_obj;
152 }
153
154 /*===========================================================================
155 * FUNCTION : mm_channel_dispatch_super_buf
156 *
157 * DESCRIPTION: dispatch super buffer of bundle to registered user
158 *
159 * PARAMETERS :
160 * @cmd_cb : ptr storing matched super buf information
161 * @userdata: user data ptr
162 *
163 * RETURN : none
164 *==========================================================================*/
mm_channel_dispatch_super_buf(mm_camera_cmdcb_t * cmd_cb,void * user_data)165 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb,
166 void* user_data)
167 {
168 mm_camera_cmd_thread_name("mm_cam_cb");
169 mm_channel_t * my_obj = (mm_channel_t *)user_data;
170
171 if (NULL == my_obj) {
172 return;
173 }
174
175 if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) {
176 CDBG_ERROR("%s: Wrong cmd_type (%d) for super buf dataCB",
177 __func__, cmd_cb->cmd_type);
178 return;
179 }
180
181 if (my_obj->bundle.super_buf_notify_cb) {
182 my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data);
183 }
184 }
185
186 /*===========================================================================
187 * FUNCTION : mm_channel_process_stream_buf
188 *
189 * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function,
190 * matching logic will be performed on incoming stream frames.
191 * Will depends on the bundle attribute, either storing matched frames
192 * in the superbuf queue, or sending matched superbuf frames to upper
193 * layer through registered callback.
194 *
195 * PARAMETERS :
196 * @cmd_cb : ptr storing matched super buf information
197 * @userdata: user data ptr
198 *
199 * RETURN : none
200 *==========================================================================*/
mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,void * user_data)201 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
202 void *user_data)
203 {
204 mm_camera_cmd_thread_name("mm_cam_cmd");
205 mm_camera_super_buf_notify_mode_t notify_mode;
206 mm_channel_queue_node_t *node = NULL;
207 mm_channel_t *ch_obj = (mm_channel_t *)user_data;
208 uint32_t i = 0;
209
210 if (NULL == ch_obj) {
211 return;
212 }
213 if (MM_CAMERA_CMD_TYPE_DATA_CB == cmd_cb->cmd_type) {
214 /* comp_and_enqueue */
215 mm_channel_superbuf_comp_and_enqueue(
216 ch_obj,
217 &ch_obj->bundle.superbuf_queue,
218 &cmd_cb->u.buf);
219 } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB == cmd_cb->cmd_type) {
220 /* skip frames if needed */
221 ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested;
222 ch_obj->pending_retro_cnt = cmd_cb->u.req_buf.num_retro_buf_requested;
223 ch_obj->bWaitForPrepSnapshotDone = 0;
224
225 ALOGV("%s:[ZSL Retro] pending cnt (%d), retro count (%d)",
226 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
227 if (!ch_obj->pending_cnt || (ch_obj->pending_retro_cnt > ch_obj->pending_cnt)) {
228 ch_obj->pending_retro_cnt = ch_obj->pending_cnt;
229 }
230 if (ch_obj->pending_retro_cnt > 0) {
231 ALOGV("%s: [ZSL Retro] Resetting need Led Flash!!!",
232 __func__);
233 ch_obj->needLEDFlash = 0;
234 }
235 ch_obj->stopZslSnapshot = 0;
236 ch_obj->unLockAEC = 0;
237
238 mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
239
240 } else if (MM_CAMERA_CMD_TYPE_START_ZSL == cmd_cb->cmd_type) {
241 ch_obj->manualZSLSnapshot = TRUE;
242 mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
243 } else if (MM_CAMERA_CMD_TYPE_STOP_ZSL == cmd_cb->cmd_type) {
244 ch_obj->manualZSLSnapshot = FALSE;
245 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
246 } else if (MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY == cmd_cb->cmd_type) {
247 ch_obj->bundle.superbuf_queue.attr.notify_mode = cmd_cb->u.notify_mode;
248 } else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE == cmd_cb->cmd_type) {
249 ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.frame_idx;
250 mm_channel_superbuf_flush(ch_obj,
251 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
252 return;
253 } else if (MM_CAMERA_CMD_TYPE_GENERAL == cmd_cb->cmd_type) {
254 CDBG_HIGH("%s:%d] MM_CAMERA_CMD_TYPE_GENERAL", __func__, __LINE__);
255 switch (cmd_cb->u.gen_cmd.type) {
256 case MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING:
257 case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING: {
258 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
259 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_AF_BRACKETING %u",
260 __func__, __LINE__, start);
261 mm_channel_superbuf_flush(ch_obj,
262 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
263
264 if (start) {
265 CDBG_HIGH("%s:%d] need AE bracketing, start zsl snapshot",
266 __func__, __LINE__);
267 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_WAIT_GOOD_FRAME_IDX;
268 } else {
269 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
270 }
271 }
272 break;
273 case MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING: {
274 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
275 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_FLASH_BRACKETING %u",
276 __func__, __LINE__, start);
277 mm_channel_superbuf_flush(ch_obj,
278 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
279
280 if (start) {
281 CDBG_HIGH("%s:%d] need flash bracketing",
282 __func__, __LINE__);
283 ch_obj->isFlashBracketingEnabled = TRUE;
284 } else {
285 ch_obj->isFlashBracketingEnabled = FALSE;
286 }
287 }
288 break;
289 case MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X: {
290 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
291 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X %u",
292 __func__, __LINE__, start);
293 mm_channel_superbuf_flush(ch_obj,
294 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
295
296 if (start) {
297 CDBG_HIGH("%s:%d] need zoom 1x frame",
298 __func__, __LINE__);
299 ch_obj->isZoom1xFrameRequested = TRUE;
300 } else {
301 ch_obj->isZoom1xFrameRequested = FALSE;
302 }
303 }
304 break;
305 case MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING: {
306 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
307 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING %u",
308 __func__, __LINE__, start);
309
310 mm_channel_superbuf_flush(ch_obj,
311 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
312 if (start) {
313 ch_obj->frame_config =
314 (cam_capture_frame_config_t *)&cmd_cb->u.gen_cmd.frame_config;
315 CDBG_HIGH("%s:%d] Capture setting Batch Count %d",
316 __func__, __LINE__, ch_obj->frame_config->num_batch);
317 for (i = 0; i < ch_obj->frame_config->num_batch; i++) {
318 CDBG("capture setting frame = %d type = %d",
319 i,ch_obj->frame_config->configs[i].type);
320 }
321 } else {
322 ch_obj->frame_config = NULL;
323 }
324 ch_obj->cur_capture_idx = 0;
325 break;
326 }
327 default:
328 CDBG_ERROR("%s:%d] Error: Invalid command", __func__, __LINE__);
329 break;
330 }
331 }
332 notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
333
334 if ((ch_obj->pending_cnt > 0)
335 && (ch_obj->needLEDFlash == TRUE ||
336 MM_CHANNEL_BRACKETING_STATE_OFF != ch_obj->bracketingState)
337 && (ch_obj->manualZSLSnapshot == FALSE)
338 && ch_obj->startZSlSnapshotCalled == FALSE) {
339
340 CDBG_HIGH("%s: need flash, start zsl snapshot", __func__);
341 mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
342 ch_obj->startZSlSnapshotCalled = TRUE;
343 ch_obj->burstSnapNum = ch_obj->pending_cnt;
344 ch_obj->bWaitForPrepSnapshotDone = 0;
345 } else if (((ch_obj->pending_cnt == 0) || (ch_obj->stopZslSnapshot == 1))
346 && (ch_obj->manualZSLSnapshot == FALSE)
347 && (ch_obj->startZSlSnapshotCalled == TRUE)) {
348 CDBG_HIGH("%s: Got picture cancelled, stop zsl snapshot", __func__);
349 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
350 // Unlock AEC
351 ch_obj->startZSlSnapshotCalled = FALSE;
352 ch_obj->needLEDFlash = FALSE;
353 ch_obj->burstSnapNum = 0;
354 ch_obj->stopZslSnapshot = 0;
355 ch_obj->bWaitForPrepSnapshotDone = 0;
356 ch_obj->unLockAEC = 1;
357 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
358 }
359 /* bufdone for overflowed bufs */
360 mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
361
362 CDBG("%s: Super Buffer received, pending_cnt=%d",
363 __func__, ch_obj->pending_cnt);
364 /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
365
366 CDBG("%s: [ZSL Retro] Out loop pending cnt (%d), retro count (%d)",
367 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
368 while (((ch_obj->pending_cnt > 0) ||
369 (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode)) &&
370 (!ch_obj->bWaitForPrepSnapshotDone)) {
371
372 CDBG("%s: [ZSL Retro] In loop pending cnt (%d), retro count (%d)",
373 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
374 /* dequeue */
375 node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue);
376 if (NULL != node) {
377 uint8_t bReady = 0;
378 /* decrease pending_cnt */
379 if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) {
380 ch_obj->pending_cnt--;
381 if (ch_obj->pending_retro_cnt > 0) {
382 if (ch_obj->pending_retro_cnt == 1) {
383 ch_obj->bWaitForPrepSnapshotDone = 1;
384 // Retro Snaps are done..
385 bReady = 1;
386 }
387 ch_obj->pending_retro_cnt--;
388 }
389 CDBG("%s: [ZSL Retro] Super Buffer received, Call client callback,"
390 "pending_cnt=%d", __func__, ch_obj->pending_cnt);
391
392 if (((ch_obj->pending_cnt == 0) ||
393 (ch_obj->stopZslSnapshot == 1)) &&
394 (ch_obj->manualZSLSnapshot == FALSE) &&
395 ch_obj->startZSlSnapshotCalled == TRUE) {
396 CDBG("%s: [ZSL Retro] Received all frames requested, stop zsl snapshot", __func__);
397 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
398 ch_obj->startZSlSnapshotCalled = FALSE;
399 ch_obj->burstSnapNum = 0;
400 ch_obj->stopZslSnapshot = 0;
401 ch_obj->unLockAEC = 1;
402 ch_obj->needLEDFlash = FALSE;
403 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
404 }
405
406 if (ch_obj->frame_config != NULL) {
407 if (ch_obj->frame_config->configs[ch_obj->cur_capture_idx].num_frames != 0) {
408 ch_obj->frame_config->configs[ch_obj->cur_capture_idx].num_frames--;
409 CDBG("Need %d frames more for batch %d",
410 ch_obj->frame_config->configs[ch_obj->cur_capture_idx].num_frames,
411 ch_obj->cur_capture_idx);
412 }
413 }
414 }
415 /* dispatch superbuf */
416 if (NULL != ch_obj->bundle.super_buf_notify_cb) {
417 uint8_t i;
418 mm_camera_cmdcb_t* cb_node = NULL;
419
420 CDBG("%s: Send superbuf to HAL, pending_cnt=%d",
421 __func__, ch_obj->pending_cnt);
422
423 /* send cam_sem_post to wake up cb thread to dispatch super buffer */
424 cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
425 if (NULL != cb_node) {
426 memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
427 cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB;
428 cb_node->u.superbuf.num_bufs = node->num_of_bufs;
429 for (i=0; i<node->num_of_bufs; i++) {
430 cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf;
431 }
432 cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl;
433 cb_node->u.superbuf.ch_id = ch_obj->my_hdl;
434 cb_node->u.superbuf.bReadyForPrepareSnapshot = bReady;
435 if (ch_obj->unLockAEC == 1) {
436 cb_node->u.superbuf.bUnlockAEC = 1;
437 ALOGE("%s:[ZSL Retro] Unlocking AEC", __func__);
438 ch_obj->unLockAEC = 0;
439 }
440
441 /* enqueue to cb thread */
442 cam_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node);
443 /* wake up cb thread */
444 cam_sem_post(&(ch_obj->cb_thread.cmd_sem));
445 } else {
446 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
447 /* buf done with the nonuse super buf */
448 for (i=0; i<node->num_of_bufs; i++) {
449 mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
450 }
451 }
452 } else {
453 /* buf done with the nonuse super buf */
454 uint8_t i;
455 for (i=0; i<node->num_of_bufs; i++) {
456 mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
457 }
458 }
459 free(node);
460 } else {
461 /* no superbuf avail, break the loop */
462 break;
463 }
464 }
465 }
466
467 /*===========================================================================
468 * FUNCTION : mm_channel_fsm_fn
469 *
470 * DESCRIPTION: channel finite state machine entry function. Depends on channel
471 * state, incoming event will be handled differently.
472 *
473 * PARAMETERS :
474 * @my_obj : ptr to a channel object
475 * @evt : channel event to be processed
476 * @in_val : input event payload. Can be NULL if not needed.
477 * @out_val : output payload, Can be NULL if not needed.
478 *
479 * RETURN : int32_t type of status
480 * 0 -- success
481 * -1 -- failure
482 *==========================================================================*/
mm_channel_fsm_fn(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)483 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
484 mm_channel_evt_type_t evt,
485 void * in_val,
486 void * out_val)
487 {
488 int32_t rc = -1;
489
490 CDBG("%s : E state = %d", __func__, my_obj->state);
491 switch (my_obj->state) {
492 case MM_CHANNEL_STATE_NOTUSED:
493 rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
494 break;
495 case MM_CHANNEL_STATE_STOPPED:
496 rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
497 break;
498 case MM_CHANNEL_STATE_ACTIVE:
499 rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
500 break;
501 case MM_CHANNEL_STATE_PAUSED:
502 rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
503 break;
504 default:
505 CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
506 break;
507 }
508
509 /* unlock ch_lock */
510 pthread_mutex_unlock(&my_obj->ch_lock);
511 CDBG("%s : X rc = %d", __func__, rc);
512 return rc;
513 }
514
515 /*===========================================================================
516 * FUNCTION : mm_channel_fsm_fn_notused
517 *
518 * DESCRIPTION: channel finite state machine function to handle event
519 * in NOT_USED state.
520 *
521 * PARAMETERS :
522 * @my_obj : ptr to a channel object
523 * @evt : channel event to be processed
524 * @in_val : input event payload. Can be NULL if not needed.
525 * @out_val : output payload, Can be NULL if not needed.
526 *
527 * RETURN : int32_t type of status
528 * 0 -- success
529 * -1 -- failure
530 *==========================================================================*/
mm_channel_fsm_fn_notused(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)531 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
532 mm_channel_evt_type_t evt,
533 void * in_val,
534 void * out_val)
535 {
536 int32_t rc = -1;
537
538 switch (evt) {
539 default:
540 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
541 __func__, my_obj->state, evt, in_val, out_val);
542 break;
543 }
544
545 return rc;
546 }
547
548 /*===========================================================================
549 * FUNCTION : mm_channel_fsm_fn_stopped
550 *
551 * DESCRIPTION: channel finite state machine function to handle event
552 * in STOPPED state.
553 *
554 * PARAMETERS :
555 * @my_obj : ptr to a channel object
556 * @evt : channel event to be processed
557 * @in_val : input event payload. Can be NULL if not needed.
558 * @out_val : output payload, Can be NULL if not needed.
559 *
560 * RETURN : int32_t type of status
561 * 0 -- success
562 * -1 -- failure
563 *==========================================================================*/
mm_channel_fsm_fn_stopped(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)564 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
565 mm_channel_evt_type_t evt,
566 void * in_val,
567 void * out_val)
568 {
569 int32_t rc = 0;
570 CDBG("%s : E evt = %d", __func__, evt);
571 switch (evt) {
572 case MM_CHANNEL_EVT_ADD_STREAM:
573 {
574 uint32_t s_hdl = 0;
575 s_hdl = mm_channel_add_stream(my_obj);
576 *((uint32_t*)out_val) = s_hdl;
577 rc = 0;
578 }
579 break;
580 case MM_CHANNEL_EVT_LINK_STREAM:
581 {
582 mm_camera_stream_link_t *stream_link = NULL;
583 uint32_t s_hdl = 0;
584 stream_link = (mm_camera_stream_link_t *) in_val;
585 s_hdl = mm_channel_link_stream(my_obj, stream_link);
586 *((uint32_t*)out_val) = s_hdl;
587 rc = 0;
588 }
589 break;
590 case MM_CHANNEL_EVT_DEL_STREAM:
591 {
592 uint32_t s_id = *((uint32_t *)in_val);
593 rc = mm_channel_del_stream(my_obj, s_id);
594 }
595 break;
596 case MM_CHANNEL_EVT_START:
597 {
598 rc = mm_channel_start(my_obj);
599 /* first stream started in stopped state
600 * move to active state */
601 if (0 == rc) {
602 my_obj->state = MM_CHANNEL_STATE_ACTIVE;
603 }
604 }
605 break;
606 case MM_CHANNEL_EVT_CONFIG_STREAM:
607 {
608 mm_evt_paylod_config_stream_t *payload =
609 (mm_evt_paylod_config_stream_t *)in_val;
610 rc = mm_channel_config_stream(my_obj,
611 payload->stream_id,
612 payload->config);
613 }
614 break;
615 case MM_CHANNEL_EVT_GET_BUNDLE_INFO:
616 {
617 cam_bundle_config_t *payload =
618 (cam_bundle_config_t *)in_val;
619 rc = mm_channel_get_bundle_info(my_obj, payload);
620 }
621 break;
622 case MM_CHANNEL_EVT_DELETE:
623 {
624 mm_channel_release(my_obj);
625 rc = 0;
626 }
627 break;
628 case MM_CHANNEL_EVT_SET_STREAM_PARM:
629 {
630 mm_evt_paylod_set_get_stream_parms_t *payload =
631 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
632 rc = mm_channel_set_stream_parm(my_obj, payload);
633 }
634 break;
635 case MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT:
636 {
637 uint32_t stream_id = *((uint32_t *)in_val);
638 rc = mm_channel_get_queued_buf_count(my_obj, stream_id);
639 }
640 break;
641 case MM_CHANNEL_EVT_GET_STREAM_PARM:
642 {
643 mm_evt_paylod_set_get_stream_parms_t *payload =
644 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
645 rc = mm_channel_get_stream_parm(my_obj, payload);
646 }
647 break;
648 case MM_CHANNEL_EVT_DO_STREAM_ACTION:
649 {
650 mm_evt_paylod_do_stream_action_t *payload =
651 (mm_evt_paylod_do_stream_action_t *)in_val;
652 rc = mm_channel_do_stream_action(my_obj, payload);
653 }
654 break;
655 case MM_CHANNEL_EVT_MAP_STREAM_BUF:
656 {
657 mm_evt_paylod_map_stream_buf_t *payload =
658 (mm_evt_paylod_map_stream_buf_t *)in_val;
659 rc = mm_channel_map_stream_buf(my_obj, payload);
660 }
661 break;
662 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
663 {
664 mm_evt_paylod_unmap_stream_buf_t *payload =
665 (mm_evt_paylod_unmap_stream_buf_t *)in_val;
666 rc = mm_channel_unmap_stream_buf(my_obj, payload);
667 }
668 break;
669 default:
670 CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
671 __func__, my_obj->state, evt);
672 break;
673 }
674 CDBG("%s : E rc = %d", __func__, rc);
675 return rc;
676 }
677
678 /*===========================================================================
679 * FUNCTION : mm_channel_fsm_fn_active
680 *
681 * DESCRIPTION: channel finite state machine function to handle event
682 * in ACTIVE state.
683 *
684 * PARAMETERS :
685 * @my_obj : ptr to a channel object
686 * @evt : channel event to be processed
687 * @in_val : input event payload. Can be NULL if not needed.
688 * @out_val : output payload, Can be NULL if not needed.
689 *
690 * RETURN : int32_t type of status
691 * 0 -- success
692 * -1 -- failure
693 *==========================================================================*/
mm_channel_fsm_fn_active(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)694 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
695 mm_channel_evt_type_t evt,
696 void * in_val,
697 void * out_val)
698 {
699 int32_t rc = 0;
700
701 CDBG("%s : E evt = %d", __func__, evt);
702 switch (evt) {
703 case MM_CHANNEL_EVT_STOP:
704 {
705 rc = mm_channel_stop(my_obj);
706 my_obj->state = MM_CHANNEL_STATE_STOPPED;
707 }
708 break;
709 case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
710 {
711 uint32_t num_buf_requested = *((uint32_t *)in_val);
712 uint32_t num_retro_buf_requested = *((uint32_t *)out_val);
713 rc = mm_channel_request_super_buf(my_obj,
714 num_buf_requested, num_retro_buf_requested);
715 }
716 break;
717 case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
718 {
719 rc = mm_channel_cancel_super_buf_request(my_obj);
720 }
721 break;
722 case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE:
723 {
724 uint32_t frame_idx = *((uint32_t *)in_val);
725 rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx);
726 }
727 break;
728 case MM_CHANNEL_EVT_START_ZSL_SNAPSHOT:
729 {
730 rc = mm_channel_start_zsl_snapshot(my_obj);
731 }
732 break;
733 case MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT:
734 {
735 rc = mm_channel_stop_zsl_snapshot(my_obj);
736 }
737 break;
738 case MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE:
739 {
740 mm_camera_super_buf_notify_mode_t notify_mode =
741 *((mm_camera_super_buf_notify_mode_t *)in_val);
742 rc = mm_channel_config_notify_mode(my_obj, notify_mode);
743 }
744 break;
745 case MM_CHANNEL_EVT_SET_STREAM_PARM:
746 {
747 mm_evt_paylod_set_get_stream_parms_t *payload =
748 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
749 rc = mm_channel_set_stream_parm(my_obj, payload);
750 }
751 break;
752 case MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT:
753 {
754 uint32_t stream_id = *((uint32_t *)in_val);
755 rc = mm_channel_get_queued_buf_count(my_obj, stream_id);
756 }
757 break;
758 case MM_CHANNEL_EVT_GET_STREAM_PARM:
759 {
760 mm_evt_paylod_set_get_stream_parms_t *payload =
761 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
762 rc = mm_channel_get_stream_parm(my_obj, payload);
763 }
764 break;
765 case MM_CHANNEL_EVT_DO_STREAM_ACTION:
766 {
767 mm_evt_paylod_do_stream_action_t *payload =
768 (mm_evt_paylod_do_stream_action_t *)in_val;
769 rc = mm_channel_do_stream_action(my_obj, payload);
770 }
771 break;
772 case MM_CHANNEL_EVT_MAP_STREAM_BUF:
773 {
774 mm_evt_paylod_map_stream_buf_t *payload =
775 (mm_evt_paylod_map_stream_buf_t *)in_val;
776 if (payload != NULL) {
777 uint8_t type = payload->buf_type;
778 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
779 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
780 rc = mm_channel_map_stream_buf(my_obj, payload);
781 }
782 } else {
783 CDBG_ERROR("%s: cannot map regualr stream buf in active state", __func__);
784 }
785 }
786 break;
787 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
788 {
789 mm_evt_paylod_unmap_stream_buf_t *payload =
790 (mm_evt_paylod_unmap_stream_buf_t *)in_val;
791 if (payload != NULL) {
792 uint8_t type = payload->buf_type;
793 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
794 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
795 rc = mm_channel_unmap_stream_buf(my_obj, payload);
796 }
797 } else {
798 CDBG_ERROR("%s: cannot unmap regualr stream buf in active state", __func__);
799 }
800 }
801 break;
802 case MM_CHANNEL_EVT_AF_BRACKETING:
803 {
804 CDBG_HIGH("MM_CHANNEL_EVT_AF_BRACKETING");
805 uint32_t start_flag = *((uint32_t *)in_val);
806 mm_camera_generic_cmd_t gen_cmd;
807 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING;
808 gen_cmd.payload[0] = start_flag;
809 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
810 }
811 break;
812 case MM_CHANNEL_EVT_AE_BRACKETING:
813 {
814 CDBG_HIGH("MM_CHANNEL_EVT_AE_BRACKETING");
815 uint32_t start_flag = *((uint32_t *)in_val);
816 mm_camera_generic_cmd_t gen_cmd;
817 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING;
818 gen_cmd.payload[0] = start_flag;
819 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
820 }
821 break;
822 case MM_CHANNEL_EVT_FLASH_BRACKETING:
823 {
824 CDBG_HIGH("MM_CHANNEL_EVT_FLASH_BRACKETING");
825 uint32_t start_flag = *((uint32_t *)in_val);
826 mm_camera_generic_cmd_t gen_cmd;
827 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING;
828 gen_cmd.payload[0] = start_flag;
829 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
830 }
831 break;
832 case MM_CHANNEL_EVT_ZOOM_1X:
833 {
834 CDBG_HIGH("MM_CHANNEL_EVT_ZOOM_1X");
835 uint32_t start_flag = *((uint32_t *)in_val);
836 mm_camera_generic_cmd_t gen_cmd;
837 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X;
838 gen_cmd.payload[0] = start_flag;
839 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
840 }
841 break;
842 case MM_CAMERA_EVT_CAPTURE_SETTING:
843 {
844 mm_camera_generic_cmd_t gen_cmd;
845 cam_capture_frame_config_t *input;
846 uint32_t i = 0;
847 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING;
848 CDBG_HIGH("MM_CAMERA_EVT_CAPTURE_SETTING");
849 if (in_val == NULL) {
850 gen_cmd.payload[0] = 0;
851 memset(&gen_cmd.frame_config, 0, sizeof(cam_capture_frame_config_t));
852 } else {
853 gen_cmd.payload[0] = 1;
854 input = (cam_capture_frame_config_t *)in_val;
855 gen_cmd.frame_config = *input;
856 }
857 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
858 }
859 break;
860 default:
861 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
862 __func__, my_obj->state, evt, in_val, out_val);
863 break;
864 }
865 CDBG("%s : X rc = %d", __func__, rc);
866 return rc;
867 }
868
869 /*===========================================================================
870 * FUNCTION : mm_channel_fsm_fn_paused
871 *
872 * DESCRIPTION: channel finite state machine function to handle event
873 * in PAUSED state.
874 *
875 * PARAMETERS :
876 * @my_obj : ptr to a channel object
877 * @evt : channel event to be processed
878 * @in_val : input event payload. Can be NULL if not needed.
879 * @out_val : output payload, Can be NULL if not needed.
880 *
881 * RETURN : int32_t type of status
882 * 0 -- success
883 * -1 -- failure
884 *==========================================================================*/
mm_channel_fsm_fn_paused(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)885 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
886 mm_channel_evt_type_t evt,
887 void * in_val,
888 void * out_val)
889 {
890 int32_t rc = 0;
891
892 /* currently we are not supporting pause/resume channel */
893 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
894 __func__, my_obj->state, evt, in_val, out_val);
895
896 return rc;
897 }
898
899 /*===========================================================================
900 * FUNCTION : mm_channel_init
901 *
902 * DESCRIPTION: initialize a channel
903 *
904 * PARAMETERS :
905 * @my_obj : channel object be to initialized
906 * @attr : bundle attribute of the channel if needed
907 * @channel_cb : callback function for bundle data notify
908 * @userdata : user data ptr
909 *
910 * RETURN : int32_t type of status
911 * 0 -- success
912 * -1 -- failure
913 * NOTE : if no bundle data notify is needed, meaning each stream in the
914 * channel will have its own stream data notify callback, then
915 * attr, channel_cb, and userdata can be NULL. In this case,
916 * no matching logic will be performed in channel for the bundling.
917 *==========================================================================*/
mm_channel_init(mm_channel_t * my_obj,mm_camera_channel_attr_t * attr,mm_camera_buf_notify_t channel_cb,void * userdata)918 int32_t mm_channel_init(mm_channel_t *my_obj,
919 mm_camera_channel_attr_t *attr,
920 mm_camera_buf_notify_t channel_cb,
921 void *userdata)
922 {
923 int32_t rc = 0;
924
925 my_obj->bundle.super_buf_notify_cb = channel_cb;
926 my_obj->bundle.user_data = userdata;
927 if (NULL != attr) {
928 my_obj->bundle.superbuf_queue.attr = *attr;
929 }
930
931 CDBG("%s : Launch data poll thread in channel open", __func__);
932 snprintf(my_obj->threadName, THREAD_NAME_SIZE, "DataPoll");
933 mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
934 MM_CAMERA_POLL_TYPE_DATA);
935
936 /* change state to stopped state */
937 my_obj->state = MM_CHANNEL_STATE_STOPPED;
938 return rc;
939 }
940
941 /*===========================================================================
942 * FUNCTION : mm_channel_release
943 *
944 * DESCRIPTION: release a channel resource. Channel state will move to UNUSED
945 * state after this call.
946 *
947 * PARAMETERS :
948 * @my_obj : channel object
949 *
950 * RETURN : none
951 *==========================================================================*/
mm_channel_release(mm_channel_t * my_obj)952 void mm_channel_release(mm_channel_t *my_obj)
953 {
954 /* stop data poll thread */
955 mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
956
957 /* change state to notused state */
958 my_obj->state = MM_CHANNEL_STATE_NOTUSED;
959 }
960
961 /*===========================================================================
962 * FUNCTION : mm_channel_link_stream
963 *
964 * DESCRIPTION: link a stream from external channel into this channel
965 *
966 * PARAMETERS :
967 * @my_obj : channel object
968 * @stream_link : channel and stream to be linked
969 *
970 * RETURN : uint32_t type of stream handle
971 * 0 -- invalid stream handle, meaning the op failed
972 * >0 -- successfully added a stream with a valid handle
973 *==========================================================================*/
mm_channel_link_stream(mm_channel_t * my_obj,mm_camera_stream_link_t * stream_link)974 uint32_t mm_channel_link_stream(mm_channel_t *my_obj,
975 mm_camera_stream_link_t *stream_link)
976 {
977 uint8_t idx = 0;
978 uint32_t s_hdl = 0;
979 mm_stream_t *stream_obj = NULL;
980 mm_stream_t *stream = NULL;
981
982 if (NULL == stream_link) {
983 CDBG_ERROR("%s : Invalid stream link", __func__);
984 return 0;
985 }
986
987 stream = mm_channel_util_get_stream_by_handler(stream_link->ch,
988 stream_link->stream_id);
989 if (NULL == stream) {
990 return 0;
991 }
992
993 /* check available stream */
994 for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
995 if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
996 stream_obj = &my_obj->streams[idx];
997 break;
998 }
999 }
1000 if (NULL == stream_obj) {
1001 CDBG_ERROR("%s: streams reach max, no more stream allowed to add",
1002 __func__);
1003 return s_hdl;
1004 }
1005
1006 /* initialize stream object */
1007 *stream_obj = *stream;
1008 stream_obj->linked_stream = stream;
1009 s_hdl = stream->my_hdl;
1010
1011 CDBG("%s : stream handle = %d", __func__, s_hdl);
1012 return s_hdl;
1013 }
1014
1015 /*===========================================================================
1016 * FUNCTION : mm_channel_add_stream
1017 *
1018 * DESCRIPTION: add a stream into the channel
1019 *
1020 * PARAMETERS :
1021 * @my_obj : channel object
1022 *
1023 * RETURN : uint32_t type of stream handle
1024 * 0 -- invalid stream handle, meaning the op failed
1025 * >0 -- successfully added a stream with a valid handle
1026 *==========================================================================*/
mm_channel_add_stream(mm_channel_t * my_obj)1027 uint32_t mm_channel_add_stream(mm_channel_t *my_obj)
1028 {
1029 int32_t rc = 0;
1030 uint8_t idx = 0;
1031 uint32_t s_hdl = 0;
1032 mm_stream_t *stream_obj = NULL;
1033
1034 CDBG("%s : E", __func__);
1035 /* check available stream */
1036 for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
1037 if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
1038 stream_obj = &my_obj->streams[idx];
1039 break;
1040 }
1041 }
1042 if (NULL == stream_obj) {
1043 CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__);
1044 return s_hdl;
1045 }
1046
1047 /* initialize stream object */
1048 memset(stream_obj, 0, sizeof(mm_stream_t));
1049 stream_obj->fd = -1;
1050 stream_obj->my_hdl = mm_camera_util_generate_handler(idx);
1051 stream_obj->ch_obj = my_obj;
1052 pthread_mutex_init(&stream_obj->buf_lock, NULL);
1053 pthread_mutex_init(&stream_obj->cb_lock, NULL);
1054 stream_obj->state = MM_STREAM_STATE_INITED;
1055
1056 /* acquire stream */
1057 rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
1058 if (0 == rc) {
1059 s_hdl = stream_obj->my_hdl;
1060 } else {
1061 /* error during acquire, de-init */
1062 pthread_mutex_destroy(&stream_obj->buf_lock);
1063 pthread_mutex_destroy(&stream_obj->cb_lock);
1064 memset(stream_obj, 0, sizeof(mm_stream_t));
1065 }
1066 CDBG("%s : stream handle = %d", __func__, s_hdl);
1067 return s_hdl;
1068 }
1069
1070 /*===========================================================================
1071 * FUNCTION : mm_channel_del_stream
1072 *
1073 * DESCRIPTION: delete a stream from the channel bu its handle
1074 *
1075 * PARAMETERS :
1076 * @my_obj : channel object
1077 * @stream_id : stream handle
1078 *
1079 * RETURN : int32_t type of status
1080 * 0 -- success
1081 * -1 -- failure
1082 * NOTE : assume steam is stooped before it can be deleted
1083 *==========================================================================*/
mm_channel_del_stream(mm_channel_t * my_obj,uint32_t stream_id)1084 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
1085 uint32_t stream_id)
1086 {
1087 int rc = -1;
1088 mm_stream_t * stream_obj = NULL;
1089 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
1090
1091 if (NULL == stream_obj) {
1092 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d",
1093 __func__, stream_id);
1094 return rc;
1095 }
1096
1097 if (stream_obj->ch_obj != my_obj) {
1098 /* Only unlink stream */
1099 pthread_mutex_lock(&stream_obj->linked_stream->buf_lock);
1100 stream_obj->linked_stream->is_linked = 0;
1101 stream_obj->linked_stream->linked_obj = NULL;
1102 pthread_mutex_unlock(&stream_obj->linked_stream->buf_lock);
1103 memset(stream_obj, 0, sizeof(mm_stream_t));
1104
1105 return 0;
1106 }
1107
1108 rc = mm_stream_fsm_fn(stream_obj,
1109 MM_STREAM_EVT_RELEASE,
1110 NULL,
1111 NULL);
1112
1113 return rc;
1114 }
1115
1116 /*===========================================================================
1117 * FUNCTION : mm_channel_config_stream
1118 *
1119 * DESCRIPTION: configure a stream
1120 *
1121 * PARAMETERS :
1122 * @my_obj : channel object
1123 * @stream_id : stream handle
1124 * @config : stream configuration
1125 *
1126 * RETURN : int32_t type of status
1127 * 0 -- success
1128 * -1 -- failure
1129 *==========================================================================*/
mm_channel_config_stream(mm_channel_t * my_obj,uint32_t stream_id,mm_camera_stream_config_t * config)1130 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
1131 uint32_t stream_id,
1132 mm_camera_stream_config_t *config)
1133 {
1134 int rc = -1;
1135 mm_stream_t * stream_obj = NULL;
1136 CDBG("%s : E stream ID = %d", __func__, stream_id);
1137 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
1138
1139 if (NULL == stream_obj) {
1140 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d", __func__, stream_id);
1141 return rc;
1142 }
1143
1144 if (stream_obj->ch_obj != my_obj) {
1145 /* No op. on linked streams */
1146 return 0;
1147 }
1148
1149 /* set stream fmt */
1150 rc = mm_stream_fsm_fn(stream_obj,
1151 MM_STREAM_EVT_SET_FMT,
1152 (void *)config,
1153 NULL);
1154 CDBG("%s : X rc = %d",__func__,rc);
1155 return rc;
1156 }
1157
1158 /*===========================================================================
1159 * FUNCTION : mm_channel_get_bundle_info
1160 *
1161 * DESCRIPTION: query bundle info of the channel, which should include all
1162 * streams within this channel
1163 *
1164 * PARAMETERS :
1165 * @my_obj : channel object
1166 * @bundle_info : bundle info to be filled in
1167 *
1168 * RETURN : int32_t type of status
1169 * 0 -- success
1170 * -1 -- failure
1171 *==========================================================================*/
mm_channel_get_bundle_info(mm_channel_t * my_obj,cam_bundle_config_t * bundle_info)1172 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
1173 cam_bundle_config_t *bundle_info)
1174 {
1175 int i;
1176 mm_stream_t *s_obj = NULL;
1177 cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
1178 int32_t rc = 0;
1179
1180 memset(bundle_info, 0, sizeof(cam_bundle_config_t));
1181 bundle_info->bundle_id = my_obj->my_hdl;
1182 bundle_info->num_of_streams = 0;
1183 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
1184 if (my_obj->streams[i].my_hdl > 0) {
1185 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1186 my_obj->streams[i].my_hdl);
1187 if (NULL != s_obj) {
1188 stream_type = s_obj->stream_info->stream_type;
1189 if ((CAM_STREAM_TYPE_METADATA != stream_type) &&
1190 (s_obj->ch_obj == my_obj)) {
1191 bundle_info->stream_ids[bundle_info->num_of_streams++] =
1192 s_obj->server_stream_id;
1193 }
1194 } else {
1195 CDBG_ERROR("%s: cannot find stream obj (%d) by handler (%d)",
1196 __func__, i, my_obj->streams[i].my_hdl);
1197 rc = -1;
1198 break;
1199 }
1200 }
1201 }
1202 if (rc != 0) {
1203 /* error, reset to 0 */
1204 memset(bundle_info, 0, sizeof(cam_bundle_config_t));
1205 }
1206 return rc;
1207 }
1208
1209 /*===========================================================================
1210 * FUNCTION : mm_channel_start
1211 *
1212 * DESCRIPTION: start a channel, which will start all streams in the channel
1213 *
1214 * PARAMETERS :
1215 * @my_obj : channel object
1216 *
1217 * RETURN : int32_t type of status
1218 * 0 -- success
1219 * -1 -- failure
1220 *==========================================================================*/
mm_channel_start(mm_channel_t * my_obj)1221 int32_t mm_channel_start(mm_channel_t *my_obj)
1222 {
1223 int32_t rc = 0;
1224 int i = 0, j = 0;
1225 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
1226 uint8_t num_streams_to_start = 0;
1227 uint8_t num_streams_in_bundle_queue = 0;
1228 mm_stream_t *s_obj = NULL;
1229 int meta_stream_idx = 0;
1230 cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
1231
1232 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
1233 if (my_obj->streams[i].my_hdl > 0) {
1234 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1235 my_obj->streams[i].my_hdl);
1236 if (NULL != s_obj) {
1237 stream_type = s_obj->stream_info->stream_type;
1238 /* remember meta data stream index */
1239 if ((stream_type == CAM_STREAM_TYPE_METADATA) &&
1240 (s_obj->ch_obj == my_obj)) {
1241 meta_stream_idx = num_streams_to_start;
1242 }
1243 s_objs[num_streams_to_start++] = s_obj;
1244
1245 if (!s_obj->stream_info->noFrameExpected) {
1246 num_streams_in_bundle_queue++;
1247 }
1248 }
1249 }
1250 }
1251
1252 if (meta_stream_idx > 0 ) {
1253 /* always start meta data stream first, so switch the stream object with the first one */
1254 s_obj = s_objs[0];
1255 s_objs[0] = s_objs[meta_stream_idx];
1256 s_objs[meta_stream_idx] = s_obj;
1257 }
1258
1259 if (NULL != my_obj->bundle.super_buf_notify_cb) {
1260 /* need to send up cb, therefore launch thread */
1261 /* init superbuf queue */
1262 mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
1263 my_obj->bundle.superbuf_queue.num_streams = num_streams_in_bundle_queue;
1264 my_obj->bundle.superbuf_queue.expected_frame_id = 0;
1265 my_obj->bundle.superbuf_queue.expected_frame_id_without_led = 0;
1266 my_obj->bundle.superbuf_queue.led_off_start_frame_id = 0;
1267 my_obj->bundle.superbuf_queue.led_on_start_frame_id = 0;
1268 my_obj->bundle.superbuf_queue.led_on_num_frames = 0;
1269
1270 for (i = 0; i < num_streams_to_start; i++) {
1271 /* Only bundle streams that belong to the channel */
1272 if(!(s_objs[i]->stream_info->noFrameExpected)) {
1273 if (s_objs[i]->ch_obj == my_obj) {
1274 /* set bundled flag to streams */
1275 s_objs[i]->is_bundled = 1;
1276 }
1277 my_obj->bundle.superbuf_queue.bundled_streams[j++] = s_objs[i]->my_hdl;
1278 }
1279 }
1280
1281 /* launch cb thread for dispatching super buf through cb */
1282 snprintf(my_obj->cb_thread.threadName, THREAD_NAME_SIZE, "CAM_SuperBuf");
1283 mm_camera_cmd_thread_launch(&my_obj->cb_thread,
1284 mm_channel_dispatch_super_buf,
1285 (void*)my_obj);
1286
1287 /* launch cmd thread for super buf dataCB */
1288 snprintf(my_obj->cmd_thread.threadName, THREAD_NAME_SIZE, "CAM_SuperBufCB");
1289 mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
1290 mm_channel_process_stream_buf,
1291 (void*)my_obj);
1292
1293 /* set flag to TRUE */
1294 my_obj->bundle.is_active = TRUE;
1295 }
1296
1297 /* link any streams first before starting the rest of the streams */
1298 for (i = 0; i < num_streams_to_start; i++) {
1299 if (s_objs[i]->ch_obj != my_obj) {
1300 pthread_mutex_lock(&s_objs[i]->linked_stream->buf_lock);
1301 s_objs[i]->linked_stream->linked_obj = my_obj;
1302 s_objs[i]->linked_stream->is_linked = 1;
1303 pthread_mutex_unlock(&s_objs[i]->linked_stream->buf_lock);
1304 continue;
1305 }
1306 }
1307
1308 for (i = 0; i < num_streams_to_start; i++) {
1309 if (s_objs[i]->ch_obj != my_obj) {
1310 continue;
1311 }
1312 /* all streams within a channel should be started at the same time */
1313 if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) {
1314 CDBG_ERROR("%s: stream already started idx(%d)", __func__, i);
1315 rc = -1;
1316 break;
1317 }
1318
1319 /* allocate buf */
1320 rc = mm_stream_fsm_fn(s_objs[i],
1321 MM_STREAM_EVT_GET_BUF,
1322 NULL,
1323 NULL);
1324 if (0 != rc) {
1325 CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i);
1326 break;
1327 }
1328
1329 /* reg buf */
1330 rc = mm_stream_fsm_fn(s_objs[i],
1331 MM_STREAM_EVT_REG_BUF,
1332 NULL,
1333 NULL);
1334 if (0 != rc) {
1335 CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i);
1336 break;
1337 }
1338
1339 /* start stream */
1340 rc = mm_stream_fsm_fn(s_objs[i],
1341 MM_STREAM_EVT_START,
1342 NULL,
1343 NULL);
1344 if (0 != rc) {
1345 CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i);
1346 break;
1347 }
1348 }
1349
1350 /* error handling */
1351 if (0 != rc) {
1352 /* unlink the streams first */
1353 for (j = 0; j < num_streams_to_start; j++) {
1354 if (s_objs[j]->ch_obj != my_obj) {
1355 pthread_mutex_lock(&s_objs[j]->linked_stream->buf_lock);
1356 s_objs[j]->linked_stream->is_linked = 0;
1357 s_objs[j]->linked_stream->linked_obj = NULL;
1358 pthread_mutex_unlock(&s_objs[j]->linked_stream->buf_lock);
1359
1360 if (TRUE == my_obj->bundle.is_active) {
1361 mm_channel_superbuf_flush(my_obj,
1362 &my_obj->bundle.superbuf_queue,
1363 s_objs[j]->stream_info->stream_type);
1364 }
1365 memset(s_objs[j], 0, sizeof(mm_stream_t));
1366 continue;
1367 }
1368 }
1369
1370 for (j = 0; j <= i; j++) {
1371 if ((NULL == s_objs[j]) || (s_objs[j]->ch_obj != my_obj)) {
1372 continue;
1373 }
1374 /* stop streams*/
1375 mm_stream_fsm_fn(s_objs[j],
1376 MM_STREAM_EVT_STOP,
1377 NULL,
1378 NULL);
1379
1380 /* unreg buf */
1381 mm_stream_fsm_fn(s_objs[j],
1382 MM_STREAM_EVT_UNREG_BUF,
1383 NULL,
1384 NULL);
1385
1386 /* put buf back */
1387 mm_stream_fsm_fn(s_objs[j],
1388 MM_STREAM_EVT_PUT_BUF,
1389 NULL,
1390 NULL);
1391 }
1392
1393 /* destroy super buf cmd thread */
1394 if (TRUE == my_obj->bundle.is_active) {
1395 /* first stop bundle thread */
1396 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
1397 mm_camera_cmd_thread_release(&my_obj->cb_thread);
1398
1399 /* deinit superbuf queue */
1400 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
1401
1402 /* memset bundle info */
1403 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
1404 }
1405 }
1406 my_obj->bWaitForPrepSnapshotDone = 0;
1407
1408 return rc;
1409 }
1410
1411 /*===========================================================================
1412 * FUNCTION : mm_channel_stop
1413 *
1414 * DESCRIPTION: stop a channel, which will stop all streams in the channel
1415 *
1416 * PARAMETERS :
1417 * @my_obj : channel object
1418 *
1419 * RETURN : int32_t type of status
1420 * 0 -- success
1421 * -1 -- failure
1422 *==========================================================================*/
mm_channel_stop(mm_channel_t * my_obj)1423 int32_t mm_channel_stop(mm_channel_t *my_obj)
1424 {
1425 int32_t rc = 0;
1426 int i;
1427 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
1428 uint8_t num_streams_to_stop = 0;
1429 mm_stream_t *s_obj = NULL;
1430 int meta_stream_idx = 0;
1431 cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
1432
1433 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
1434 if (my_obj->streams[i].my_hdl > 0) {
1435 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1436 my_obj->streams[i].my_hdl);
1437 if (NULL != s_obj) {
1438 if (s_obj->ch_obj == my_obj) {
1439 stream_type = s_obj->stream_info->stream_type;
1440 /* remember meta data stream index */
1441 if (stream_type == CAM_STREAM_TYPE_METADATA) {
1442 meta_stream_idx = num_streams_to_stop;
1443 }
1444 }
1445 s_objs[num_streams_to_stop++] = s_obj;
1446 }
1447 }
1448 }
1449
1450 if (meta_stream_idx < num_streams_to_stop - 1 ) {
1451 /* always stop meta data stream last, so switch the stream object with the last one */
1452 s_obj = s_objs[num_streams_to_stop - 1];
1453 s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx];
1454 s_objs[meta_stream_idx] = s_obj;
1455 }
1456
1457 for (i = 0; i < num_streams_to_stop; i++) {
1458 /* stream that are linked to this channel should not be stopped */
1459 if (s_objs[i]->ch_obj != my_obj) {
1460 continue;
1461 }
1462
1463 /* stream off */
1464 mm_stream_fsm_fn(s_objs[i],
1465 MM_STREAM_EVT_STOP,
1466 NULL,
1467 NULL);
1468
1469 /* unreg buf at kernel */
1470 mm_stream_fsm_fn(s_objs[i],
1471 MM_STREAM_EVT_UNREG_BUF,
1472 NULL,
1473 NULL);
1474 }
1475
1476 for (i = 0; i < num_streams_to_stop; i++) {
1477 if (s_objs[i]->ch_obj != my_obj) {
1478 /* Only unlink stream */
1479 pthread_mutex_lock(&s_objs[i]->linked_stream->buf_lock);
1480 s_objs[i]->linked_stream->is_linked = 0;
1481 s_objs[i]->linked_stream->linked_obj = NULL;
1482 pthread_mutex_unlock(&s_objs[i]->linked_stream->buf_lock);
1483
1484 if (TRUE == my_obj->bundle.is_active) {
1485 mm_channel_flush_super_buf_queue(my_obj, 0);
1486 }
1487 break;
1488 } else {
1489 continue;
1490 }
1491 }
1492
1493 /* destroy super buf cmd thread */
1494 if (TRUE == my_obj->bundle.is_active) {
1495 /* first stop bundle thread */
1496 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
1497 mm_camera_cmd_thread_release(&my_obj->cb_thread);
1498
1499 /* deinit superbuf queue */
1500 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
1501 }
1502
1503 /* since all streams are stopped, we are safe to
1504 * release all buffers allocated in stream */
1505 for (i = 0; i < num_streams_to_stop; i++) {
1506 if (s_objs[i]->ch_obj != my_obj) {
1507 continue;
1508 }
1509 /* put buf back */
1510 mm_stream_fsm_fn(s_objs[i],
1511 MM_STREAM_EVT_PUT_BUF,
1512 NULL,
1513 NULL);
1514 }
1515
1516 for (i = 0; i < num_streams_to_stop; i++) {
1517 if (s_objs[i]->ch_obj != my_obj) {
1518 memset(s_objs[i], 0, sizeof(mm_stream_t));
1519 } else {
1520 continue;
1521 }
1522 }
1523
1524 return rc;
1525 }
1526
1527 /*===========================================================================
1528 * FUNCTION : mm_channel_request_super_buf
1529 *
1530 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
1531 * frames from superbuf queue
1532 *
1533 * PARAMETERS :
1534 * @my_obj : channel object
1535 * @num_buf_requested : number of matched frames needed
1536 * @num_retro_buf_requested : number of retro frames needed
1537 *
1538 * RETURN : int32_t type of status
1539 * 0 -- success
1540 * -1 -- failure
1541 *==========================================================================*/
mm_channel_request_super_buf(mm_channel_t * my_obj,uint32_t num_buf_requested,uint32_t num_retro_buf_requested)1542 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
1543 uint32_t num_buf_requested, uint32_t num_retro_buf_requested)
1544 {
1545 int32_t rc = 0;
1546 mm_camera_cmdcb_t* node = NULL;
1547
1548 /* set pending_cnt
1549 * will trigger dispatching super frames if pending_cnt > 0 */
1550 /* send cam_sem_post to wake up cmd thread to dispatch super buffer */
1551 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1552 if (NULL != node) {
1553 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1554 node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
1555 node->u.req_buf.num_buf_requested = num_buf_requested;
1556 node->u.req_buf.num_retro_buf_requested = num_retro_buf_requested;
1557
1558 /* enqueue to cmd thread */
1559 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1560
1561 /* wake up cmd thread */
1562 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1563 } else {
1564 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1565 rc = -1;
1566 }
1567
1568 return rc;
1569 }
1570
1571 /*===========================================================================
1572 * FUNCTION : mm_channel_cancel_super_buf_request
1573 *
1574 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
1575 * of matched frames from superbuf queue
1576 *
1577 * PARAMETERS :
1578 * @my_obj : channel object
1579 *
1580 * RETURN : int32_t type of status
1581 * 0 -- success
1582 * -1 -- failure
1583 *==========================================================================*/
mm_channel_cancel_super_buf_request(mm_channel_t * my_obj)1584 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
1585 {
1586 int32_t rc = 0;
1587 /* reset pending_cnt */
1588 rc = mm_channel_request_super_buf(my_obj, 0, 0);
1589 return rc;
1590 }
1591
1592 /*===========================================================================
1593 * FUNCTION : mm_channel_flush_super_buf_queue
1594 *
1595 * DESCRIPTION: flush superbuf queue
1596 *
1597 * PARAMETERS :
1598 * @my_obj : channel object
1599 * @frame_idx : frame idx until which to flush all superbufs
1600 *
1601 * RETURN : int32_t type of status
1602 * 0 -- success
1603 * -1 -- failure
1604 *==========================================================================*/
mm_channel_flush_super_buf_queue(mm_channel_t * my_obj,uint32_t frame_idx)1605 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx)
1606 {
1607 int32_t rc = 0;
1608 mm_camera_cmdcb_t* node = NULL;
1609
1610 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1611 if (NULL != node) {
1612 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1613 node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE;
1614 node->u.frame_idx = frame_idx;
1615
1616 /* enqueue to cmd thread */
1617 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1618
1619 /* wake up cmd thread */
1620 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1621 } else {
1622 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1623 rc = -1;
1624 }
1625
1626 return rc;
1627 }
1628
1629 /*===========================================================================
1630 * FUNCTION : mm_channel_config_notify_mode
1631 *
1632 * DESCRIPTION: configure notification mode
1633 *
1634 * PARAMETERS :
1635 * @my_obj : channel object
1636 * @notify_mode : notification mode
1637 *
1638 * RETURN : int32_t type of status
1639 * 0 -- success
1640 * -1 -- failure
1641 *==========================================================================*/
mm_channel_config_notify_mode(mm_channel_t * my_obj,mm_camera_super_buf_notify_mode_t notify_mode)1642 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
1643 mm_camera_super_buf_notify_mode_t notify_mode)
1644 {
1645 int32_t rc = 0;
1646 mm_camera_cmdcb_t* node = NULL;
1647
1648 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1649 if (NULL != node) {
1650 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1651 node->u.notify_mode = notify_mode;
1652 node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY;
1653
1654 /* enqueue to cmd thread */
1655 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1656
1657 /* wake up cmd thread */
1658 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1659 } else {
1660 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1661 rc = -1;
1662 }
1663
1664 return rc;
1665 }
1666
1667 /*===========================================================================
1668 * FUNCTION : mm_channel_start_zsl_snapshot
1669 *
1670 * DESCRIPTION: start zsl snapshot
1671 *
1672 * PARAMETERS :
1673 * @my_obj : channel object
1674 *
1675 * RETURN : int32_t type of status
1676 * 0 -- success
1677 * -1 -- failure
1678 *==========================================================================*/
mm_channel_start_zsl_snapshot(mm_channel_t * my_obj)1679 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj)
1680 {
1681 int32_t rc = 0;
1682 mm_camera_cmdcb_t* node = NULL;
1683
1684 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1685 if (NULL != node) {
1686 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1687 node->cmd_type = MM_CAMERA_CMD_TYPE_START_ZSL;
1688
1689 /* enqueue to cmd thread */
1690 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1691
1692 /* wake up cmd thread */
1693 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1694 } else {
1695 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1696 rc = -1;
1697 }
1698
1699 return rc;
1700 }
1701
1702 /*===========================================================================
1703 * FUNCTION : mm_channel_stop_zsl_snapshot
1704 *
1705 * DESCRIPTION: stop zsl snapshot
1706 *
1707 * PARAMETERS :
1708 * @my_obj : channel object
1709 *
1710 * RETURN : int32_t type of status
1711 * 0 -- success
1712 * -1 -- failure
1713 *==========================================================================*/
mm_channel_stop_zsl_snapshot(mm_channel_t * my_obj)1714 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj)
1715 {
1716 int32_t rc = 0;
1717 mm_camera_cmdcb_t* node = NULL;
1718
1719 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1720 if (NULL != node) {
1721 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1722 node->cmd_type = MM_CAMERA_CMD_TYPE_STOP_ZSL;
1723
1724 /* enqueue to cmd thread */
1725 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1726
1727 /* wake up cmd thread */
1728 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1729 } else {
1730 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1731 rc = -1;
1732 }
1733
1734 return rc;
1735 }
1736
1737 /*===========================================================================
1738 * FUNCTION : mm_channel_qbuf
1739 *
1740 * DESCRIPTION: enqueue buffer back to kernel
1741 *
1742 * PARAMETERS :
1743 * @my_obj : channel object
1744 * @buf : buf ptr to be enqueued
1745 *
1746 * RETURN : int32_t type of status
1747 * 0 -- success
1748 * -1 -- failure
1749 *==========================================================================*/
mm_channel_qbuf(mm_channel_t * my_obj,mm_camera_buf_def_t * buf)1750 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
1751 mm_camera_buf_def_t *buf)
1752 {
1753 int32_t rc = -1;
1754 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
1755
1756 if (NULL != s_obj) {
1757 if (s_obj->ch_obj != my_obj) {
1758 /* Redirect to linked stream */
1759 rc = mm_stream_fsm_fn(s_obj->linked_stream,
1760 MM_STREAM_EVT_QBUF,
1761 (void *)buf,
1762 NULL);
1763 } else {
1764 rc = mm_stream_fsm_fn(s_obj,
1765 MM_STREAM_EVT_QBUF,
1766 (void *)buf,
1767 NULL);
1768 }
1769 }
1770
1771 return rc;
1772 }
1773
1774 /*===========================================================================
1775 * FUNCTION : mm_channel_get_queued_buf_count
1776 *
1777 * DESCRIPTION: return queued buffer count
1778 *
1779 * PARAMETERS :
1780 * @my_obj : channel object
1781 * @stream_id : steam_id
1782 *
1783 * RETURN : queued buffer count
1784 *==========================================================================*/
mm_channel_get_queued_buf_count(mm_channel_t * my_obj,uint32_t stream_id)1785 int32_t mm_channel_get_queued_buf_count(mm_channel_t *my_obj, uint32_t stream_id)
1786 {
1787 int32_t rc = -1;
1788 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
1789
1790 if (NULL != s_obj) {
1791 if (s_obj->ch_obj != my_obj) {
1792 /* Redirect to linked stream */
1793 rc = mm_stream_fsm_fn(s_obj->linked_stream,
1794 MM_STREAM_EVT_GET_QUEUED_BUF_COUNT,
1795 NULL,
1796 NULL);
1797 } else {
1798 rc = mm_stream_fsm_fn(s_obj,
1799 MM_STREAM_EVT_GET_QUEUED_BUF_COUNT,
1800 NULL,
1801 NULL);
1802 }
1803 }
1804
1805 return rc;
1806 }
1807
1808 /*===========================================================================
1809 * FUNCTION : mm_channel_set_stream_parms
1810 *
1811 * DESCRIPTION: set parameters per stream
1812 *
1813 * PARAMETERS :
1814 * @my_obj : channel object
1815 * @s_id : stream handle
1816 * @parms : ptr to a param struct to be set to server
1817 *
1818 * RETURN : int32_t type of status
1819 * 0 -- success
1820 * -1 -- failure
1821 * NOTE : Assume the parms struct buf is already mapped to server via
1822 * domain socket. Corresponding fields of parameters to be set
1823 * are already filled in by upper layer caller.
1824 *==========================================================================*/
mm_channel_set_stream_parm(mm_channel_t * my_obj,mm_evt_paylod_set_get_stream_parms_t * payload)1825 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
1826 mm_evt_paylod_set_get_stream_parms_t *payload)
1827 {
1828 int32_t rc = -1;
1829 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1830 payload->stream_id);
1831 if (NULL != s_obj) {
1832 if (s_obj->ch_obj != my_obj) {
1833 /* No op. on linked streams */
1834 return 0;
1835 }
1836
1837 rc = mm_stream_fsm_fn(s_obj,
1838 MM_STREAM_EVT_SET_PARM,
1839 (void *)payload,
1840 NULL);
1841 }
1842
1843 return rc;
1844 }
1845
1846 /*===========================================================================
1847 * FUNCTION : mm_channel_get_stream_parms
1848 *
1849 * DESCRIPTION: get parameters per stream
1850 *
1851 * PARAMETERS :
1852 * @my_obj : channel object
1853 * @s_id : stream handle
1854 * @parms : ptr to a param struct to be get from server
1855 *
1856 * RETURN : int32_t type of status
1857 * 0 -- success
1858 * -1 -- failure
1859 * NOTE : Assume the parms struct buf is already mapped to server via
1860 * domain socket. Parameters to be get from server are already
1861 * filled in by upper layer caller. After this call, corresponding
1862 * fields of requested parameters will be filled in by server with
1863 * detailed information.
1864 *==========================================================================*/
mm_channel_get_stream_parm(mm_channel_t * my_obj,mm_evt_paylod_set_get_stream_parms_t * payload)1865 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
1866 mm_evt_paylod_set_get_stream_parms_t *payload)
1867 {
1868 int32_t rc = -1;
1869 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1870 payload->stream_id);
1871 if (NULL != s_obj) {
1872 if (s_obj->ch_obj != my_obj) {
1873 /* No op. on linked streams */
1874 return 0;
1875 }
1876
1877 rc = mm_stream_fsm_fn(s_obj,
1878 MM_STREAM_EVT_GET_PARM,
1879 (void *)payload,
1880 NULL);
1881 }
1882
1883 return rc;
1884 }
1885
1886 /*===========================================================================
1887 * FUNCTION : mm_channel_do_stream_action
1888 *
1889 * DESCRIPTION: request server to perform stream based action. Maybe removed later
1890 * if the functionality is included in mm_camera_set_parms
1891 *
1892 * PARAMETERS :
1893 * @my_obj : channel object
1894 * @s_id : stream handle
1895 * @actions : ptr to an action struct buf to be performed by server
1896 *
1897 * RETURN : int32_t type of status
1898 * 0 -- success
1899 * -1 -- failure
1900 * NOTE : Assume the action struct buf is already mapped to server via
1901 * domain socket. Actions to be performed by server are already
1902 * filled in by upper layer caller.
1903 *==========================================================================*/
mm_channel_do_stream_action(mm_channel_t * my_obj,mm_evt_paylod_do_stream_action_t * payload)1904 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
1905 mm_evt_paylod_do_stream_action_t *payload)
1906 {
1907 int32_t rc = -1;
1908 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1909 payload->stream_id);
1910 if (NULL != s_obj) {
1911 if (s_obj->ch_obj != my_obj) {
1912 /* No op. on linked streams */
1913 return 0;
1914 }
1915
1916 rc = mm_stream_fsm_fn(s_obj,
1917 MM_STREAM_EVT_DO_ACTION,
1918 (void *)payload,
1919 NULL);
1920 }
1921
1922 return rc;
1923 }
1924
1925 /*===========================================================================
1926 * FUNCTION : mm_channel_map_stream_buf
1927 *
1928 * DESCRIPTION: mapping stream buffer via domain socket to server
1929 *
1930 * PARAMETERS :
1931 * @my_obj : channel object
1932 * @payload : ptr to payload for mapping
1933 *
1934 * RETURN : int32_t type of status
1935 * 0 -- success
1936 * -1 -- failure
1937 *==========================================================================*/
mm_channel_map_stream_buf(mm_channel_t * my_obj,mm_evt_paylod_map_stream_buf_t * payload)1938 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
1939 mm_evt_paylod_map_stream_buf_t *payload)
1940 {
1941 int32_t rc = -1;
1942 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1943 payload->stream_id);
1944 if (NULL != s_obj) {
1945 if (s_obj->ch_obj != my_obj) {
1946 /* No op. on linked streams */
1947 return 0;
1948 }
1949
1950 rc = mm_stream_map_buf(s_obj,
1951 payload->buf_type,
1952 payload->buf_idx,
1953 payload->plane_idx,
1954 payload->fd,
1955 payload->size);
1956 }
1957
1958 return rc;
1959 }
1960
1961 /*===========================================================================
1962 * FUNCTION : mm_channel_unmap_stream_buf
1963 *
1964 * DESCRIPTION: unmapping stream buffer via domain socket to server
1965 *
1966 * PARAMETERS :
1967 * @my_obj : channel object
1968 * @payload : ptr to unmap payload
1969 *
1970 * RETURN : int32_t type of status
1971 * 0 -- success
1972 * -1 -- failure
1973 *==========================================================================*/
mm_channel_unmap_stream_buf(mm_channel_t * my_obj,mm_evt_paylod_unmap_stream_buf_t * payload)1974 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
1975 mm_evt_paylod_unmap_stream_buf_t *payload)
1976 {
1977 int32_t rc = -1;
1978 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1979 payload->stream_id);
1980 if (NULL != s_obj) {
1981 if (s_obj->ch_obj != my_obj) {
1982 /* No op. on linked streams */
1983 return 0;
1984 }
1985
1986 rc = mm_stream_unmap_buf(s_obj, payload->buf_type,
1987 payload->buf_idx, payload->plane_idx);
1988 }
1989
1990 return rc;
1991 }
1992
1993 /*===========================================================================
1994 * FUNCTION : mm_channel_superbuf_queue_init
1995 *
1996 * DESCRIPTION: initialize superbuf queue in the channel
1997 *
1998 * PARAMETERS :
1999 * @queue : ptr to superbuf queue to be initialized
2000 *
2001 * RETURN : int32_t type of status
2002 * 0 -- success
2003 * -1 -- failure
2004 *==========================================================================*/
mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)2005 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
2006 {
2007 return cam_queue_init(&queue->que);
2008 }
2009
2010 /*===========================================================================
2011 * FUNCTION : mm_channel_superbuf_queue_deinit
2012 *
2013 * DESCRIPTION: deinitialize superbuf queue in the channel
2014 *
2015 * PARAMETERS :
2016 * @queue : ptr to superbuf queue to be deinitialized
2017 *
2018 * RETURN : int32_t type of status
2019 * 0 -- success
2020 * -1 -- failure
2021 *==========================================================================*/
mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)2022 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
2023 {
2024 return cam_queue_deinit(&queue->que);
2025 }
2026
2027 /*===========================================================================
2028 * FUNCTION : mm_channel_util_seq_comp_w_rollover
2029 *
2030 * DESCRIPTION: utility function to handle sequence number comparison with rollover
2031 *
2032 * PARAMETERS :
2033 * @v1 : first value to be compared
2034 * @v2 : second value to be compared
2035 *
2036 * RETURN : int8_t type of comparison result
2037 * >0 -- v1 larger than v2
2038 * =0 -- vi equal to v2
2039 * <0 -- v1 smaller than v2
2040 *==========================================================================*/
mm_channel_util_seq_comp_w_rollover(uint32_t v1,uint32_t v2)2041 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
2042 uint32_t v2)
2043 {
2044 int8_t ret = 0;
2045
2046 /* TODO: need to handle the case if v2 roll over to 0 */
2047 if (v1 > v2) {
2048 ret = 1;
2049 } else if (v1 < v2) {
2050 ret = -1;
2051 }
2052
2053 return ret;
2054 }
2055
2056 /*===========================================================================
2057 * FUNCTION : mm_channel_handle_metadata
2058 *
2059 * DESCRIPTION: Handle frame matching logic change due to metadata
2060 *
2061 * PARAMETERS :
2062 * @ch_obj : channel object
2063 * @queue : superbuf queue
2064 * @buf_info: new buffer from stream
2065 *
2066 * RETURN : int32_t type of status
2067 * 0 -- success
2068 * -1 -- failure
2069 *==========================================================================*/
mm_channel_handle_metadata(mm_channel_t * ch_obj,mm_channel_queue_t * queue,mm_camera_buf_info_t * buf_info)2070 int32_t mm_channel_handle_metadata(
2071 mm_channel_t* ch_obj,
2072 mm_channel_queue_t * queue,
2073 mm_camera_buf_info_t *buf_info)
2074 {
2075
2076 int rc = 0 ;
2077 mm_stream_t* stream_obj = NULL;
2078 stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
2079 buf_info->stream_id);
2080 uint8_t is_prep_snapshot_done_valid = 0;
2081 uint8_t is_good_frame_idx_range_valid = 0;
2082 int32_t prep_snapshot_done_state = 0;
2083 cam_frame_idx_range_t good_frame_idx_range;
2084 uint8_t is_crop_1x_found = 0;
2085 uint32_t snapshot_stream_id = 0;
2086 uint32_t i;
2087 /* Set expected frame id to a future frame idx, large enough to wait
2088 * for good_frame_idx_range, and small enough to still capture an image */
2089 const uint32_t max_future_frame_offset = 100U;
2090
2091 memset(&good_frame_idx_range, 0, sizeof(good_frame_idx_range));
2092
2093 if (NULL == stream_obj) {
2094 CDBG_ERROR("%s: Invalid Stream Object for stream_id = %d",
2095 __func__, buf_info->stream_id);
2096 rc = -1;
2097 goto end;
2098 }
2099 if (NULL == stream_obj->stream_info) {
2100 CDBG_ERROR("%s: NULL stream info for stream_id = %d",
2101 __func__, buf_info->stream_id);
2102 rc = -1;
2103 goto end;
2104 }
2105
2106 if ((CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) &&
2107 (stream_obj->ch_obj == ch_obj)) {
2108 const metadata_buffer_t *metadata;
2109 metadata = (const metadata_buffer_t *)buf_info->buf->buffer;
2110
2111 if (NULL == metadata) {
2112 CDBG_ERROR("%s: NULL metadata buffer for metadata stream",
2113 __func__);
2114 rc = -1;
2115 goto end;
2116 }
2117 CDBG("%s: E , expected frame id: %d", __func__, queue->expected_frame_id);
2118
2119 IF_META_AVAILABLE(const int32_t, p_prep_snapshot_done_state,
2120 CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata) {
2121 prep_snapshot_done_state = *p_prep_snapshot_done_state;
2122 is_prep_snapshot_done_valid = 1;
2123 CDBG("%s: prepare snapshot done valid ", __func__);
2124 }
2125 IF_META_AVAILABLE(const cam_frame_idx_range_t, p_good_frame_idx_range,
2126 CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata) {
2127 good_frame_idx_range = *p_good_frame_idx_range;
2128 is_good_frame_idx_range_valid = 1;
2129 CDBG("%s: good_frame_idx_range : min: %d, max: %d , num frames = %d",
2130 __func__, good_frame_idx_range.min_frame_idx,
2131 good_frame_idx_range.max_frame_idx, good_frame_idx_range.num_led_on_frames);
2132 }
2133 IF_META_AVAILABLE(const cam_crop_data_t, p_crop_data,
2134 CAM_INTF_META_CROP_DATA, metadata) {
2135 cam_crop_data_t crop_data = *p_crop_data;
2136
2137 for (i = 0; i < ARRAY_SIZE(ch_obj->streams); i++) {
2138 if (MM_STREAM_STATE_NOTUSED == ch_obj->streams[i].state) {
2139 continue;
2140 }
2141 if (CAM_STREAM_TYPE_SNAPSHOT ==
2142 ch_obj->streams[i].stream_info->stream_type) {
2143 snapshot_stream_id = ch_obj->streams[i].server_stream_id;
2144 break;
2145 }
2146 }
2147
2148 for (i=0; i<crop_data.num_of_streams; i++) {
2149 if (snapshot_stream_id == crop_data.crop_info[i].stream_id) {
2150 if (!crop_data.crop_info[i].crop.left &&
2151 !crop_data.crop_info[i].crop.top) {
2152 is_crop_1x_found = 1;
2153 break;
2154 }
2155 }
2156 }
2157 }
2158
2159 IF_META_AVAILABLE(const cam_buf_divert_info_t, divert_info,
2160 CAM_INTF_BUF_DIVERT_INFO, metadata) {
2161 if (divert_info->frame_id >= buf_info->frame_idx) {
2162 ch_obj->diverted_frame_id = divert_info->frame_id;
2163 } else {
2164 ch_obj->diverted_frame_id = 0;
2165 }
2166 }
2167
2168 if (ch_obj->isZoom1xFrameRequested) {
2169 if (is_crop_1x_found) {
2170 ch_obj->isZoom1xFrameRequested = 0;
2171 queue->expected_frame_id = buf_info->frame_idx + 1;
2172 } else {
2173 queue->expected_frame_id += max_future_frame_offset;
2174 /* Flush unwanted frames */
2175 mm_channel_superbuf_flush_matched(ch_obj, queue);
2176 }
2177 goto end;
2178 }
2179
2180 if (is_prep_snapshot_done_valid) {
2181 ch_obj->bWaitForPrepSnapshotDone = 0;
2182 if (prep_snapshot_done_state == NEED_FUTURE_FRAME) {
2183 queue->expected_frame_id += max_future_frame_offset;
2184 CDBG("%s: [ZSL Retro] NEED_FUTURE_FRAME, expected frame id = %d ",
2185 __func__, queue->expected_frame_id);
2186
2187 mm_channel_superbuf_flush(ch_obj,
2188 queue, CAM_STREAM_TYPE_DEFAULT);
2189
2190 ch_obj->needLEDFlash = TRUE;
2191 } else {
2192 ch_obj->needLEDFlash = FALSE;
2193 }
2194 }
2195 if (is_good_frame_idx_range_valid) {
2196 if (good_frame_idx_range.min_frame_idx > queue->expected_frame_id) {
2197 CDBG_HIGH("%s: [ZSL Retro] min_frame_idx %d is greater than expected_frame_id %d",
2198 __func__, good_frame_idx_range.min_frame_idx, queue->expected_frame_id);
2199 }
2200 queue->expected_frame_id =
2201 good_frame_idx_range.min_frame_idx;
2202 if((ch_obj->needLEDFlash == TRUE) && (ch_obj->burstSnapNum > 1)) {
2203 queue->led_on_start_frame_id =
2204 good_frame_idx_range.min_frame_idx;
2205 queue->led_off_start_frame_id =
2206 good_frame_idx_range.max_frame_idx;
2207 queue->once = 0;
2208 queue->led_on_num_frames =
2209 good_frame_idx_range.num_led_on_frames;
2210 queue->frame_skip_count = good_frame_idx_range.frame_skip_count;
2211 CDBG("%s: [ZSL Retro] Need Flash, expected frame id = %d,"
2212 " led_on start = %d, led off start = %d, led on frames = %d ",
2213 __func__, queue->expected_frame_id, queue->led_on_start_frame_id,
2214 queue->led_off_start_frame_id, queue->led_on_num_frames);
2215 } else {
2216 CDBG("%s: [ZSL Retro]No flash, expected frame id = %d ",
2217 __func__, queue->expected_frame_id);
2218 }
2219 } else if ((MM_CHANNEL_BRACKETING_STATE_WAIT_GOOD_FRAME_IDX == ch_obj->bracketingState) &&
2220 !is_prep_snapshot_done_valid) {
2221 /* Flush unwanted frames */
2222 mm_channel_superbuf_flush_matched(ch_obj, queue);
2223 queue->expected_frame_id += max_future_frame_offset;
2224 }
2225 if (ch_obj->isFlashBracketingEnabled &&
2226 is_good_frame_idx_range_valid) {
2227 /* Flash bracketing needs two frames, with & without led flash.
2228 * in valid range min frame is with led flash and max frame is
2229 * without led flash */
2230 queue->expected_frame_id =
2231 good_frame_idx_range.min_frame_idx;
2232 /* max frame is without led flash */
2233 queue->expected_frame_id_without_led =
2234 good_frame_idx_range.max_frame_idx;
2235
2236 } else if (is_good_frame_idx_range_valid) {
2237 if (good_frame_idx_range.min_frame_idx >
2238 queue->expected_frame_id) {
2239 CDBG_HIGH("%s: min_frame_idx %d is greater than expected_frame_id %d",
2240 __func__, good_frame_idx_range.min_frame_idx,
2241 queue->expected_frame_id);
2242 }
2243 queue->expected_frame_id =
2244 good_frame_idx_range.min_frame_idx;
2245
2246 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_ACTIVE;
2247 }
2248
2249 if (ch_obj->frame_config != NULL && is_good_frame_idx_range_valid
2250 && (good_frame_idx_range.config_batch_idx < ch_obj->frame_config->num_batch)) {
2251 CDBG_HIGH("Frame Config: Expcted ID = %d batch index = %d",
2252 good_frame_idx_range.min_frame_idx, good_frame_idx_range.config_batch_idx);
2253 queue->expected_frame_id =
2254 good_frame_idx_range.min_frame_idx;
2255 if (ch_obj->frame_config->configs[ch_obj->cur_capture_idx].num_frames != 0) {
2256 CDBG_ERROR("Drop in frame or early PIC Done evet frame-id = %d",
2257 buf_info->frame_idx);
2258 }
2259 ch_obj->cur_capture_idx = good_frame_idx_range.config_batch_idx;
2260 }
2261
2262 if ((ch_obj->burstSnapNum > 1) && (ch_obj->needLEDFlash == TRUE)
2263 && !ch_obj->isFlashBracketingEnabled
2264 && (MM_CHANNEL_BRACKETING_STATE_OFF == ch_obj->bracketingState)
2265 && ch_obj->frame_config == NULL) {
2266 if((buf_info->frame_idx >= queue->led_off_start_frame_id)
2267 && !queue->once) {
2268 CDBG("%s: [ZSL Retro]Burst snap num = %d ",
2269 __func__, ch_obj->burstSnapNum);
2270 // Skip frames from LED OFF frame to get a good frame
2271 queue->expected_frame_id = queue->led_off_start_frame_id +
2272 queue->frame_skip_count;
2273 queue->once = 1;
2274 ch_obj->stopZslSnapshot = 1;
2275 ch_obj->needLEDFlash = FALSE;
2276 CDBG("%s:[ZSL Retro]Reached max led on frames = %d , expected id = %d",
2277 __func__, buf_info->frame_idx, queue->expected_frame_id);
2278 }
2279 }
2280 }
2281 end:
2282 return rc;
2283 }
2284
2285 /*===========================================================================
2286 * FUNCTION : mm_channel_superbuf_comp_and_enqueue
2287 *
2288 * DESCRIPTION: implementation for matching logic for superbuf
2289 *
2290 * PARAMETERS :
2291 * @ch_obj : channel object
2292 * @queue : superbuf queue
2293 * @buf_info: new buffer from stream
2294 *
2295 * RETURN : int32_t type of status
2296 * 0 -- success
2297 * -1 -- failure
2298 *==========================================================================*/
mm_channel_superbuf_comp_and_enqueue(mm_channel_t * ch_obj,mm_channel_queue_t * queue,mm_camera_buf_info_t * buf_info)2299 int32_t mm_channel_superbuf_comp_and_enqueue(
2300 mm_channel_t* ch_obj,
2301 mm_channel_queue_t *queue,
2302 mm_camera_buf_info_t *buf_info)
2303 {
2304 cam_node_t* node = NULL;
2305 struct cam_list *head = NULL;
2306 struct cam_list *pos = NULL;
2307 mm_channel_queue_node_t* super_buf = NULL;
2308 uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles;
2309 struct cam_list *last_buf, *insert_before_buf, *last_buf_ptr;
2310
2311 CDBG("%s: E", __func__);
2312
2313 for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) {
2314 if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
2315 break;
2316 }
2317 }
2318
2319 if (buf_s_idx == queue->num_streams) {
2320 CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id);
2321 return -1;
2322 }
2323
2324 if(buf_info->frame_idx == 0) {
2325 mm_channel_qbuf(ch_obj, buf_info->buf);
2326 return 0;
2327 }
2328
2329 if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) {
2330 mm_channel_qbuf(ch_obj, buf_info->buf);
2331 return -1;
2332 }
2333
2334 if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
2335 queue->expected_frame_id) < 0) {
2336 /* incoming buf is older than expected buf id, will discard it */
2337 mm_channel_qbuf(ch_obj, buf_info->buf);
2338 return 0;
2339 }
2340
2341 if((queue->nomatch_frame_id != 0)
2342 && (queue->nomatch_frame_id > buf_info->frame_idx)
2343 && (buf_info->buf->stream_type == CAM_STREAM_TYPE_METADATA)) {
2344 /*Incoming metadata is older than expected*/
2345 mm_channel_qbuf(ch_obj, buf_info->buf);
2346 return 0;
2347 }
2348
2349 /* comp */
2350 pthread_mutex_lock(&queue->que.lock);
2351 head = &queue->que.head.list;
2352 /* get the last one in the queue which is possibly having no matching */
2353 pos = head->next;
2354
2355 found_super_buf = 0;
2356 unmatched_bundles = 0;
2357 last_buf = NULL;
2358 insert_before_buf = NULL;
2359 last_buf_ptr = NULL;
2360
2361 while (pos != head) {
2362 node = member_of(pos, cam_node_t, list);
2363 super_buf = (mm_channel_queue_node_t*)node->data;
2364
2365 if (NULL != super_buf) {
2366 if (super_buf->matched) {
2367 /* find a matched super buf, move to next one */
2368 pos = pos->next;
2369 continue;
2370 } else if ( buf_info->frame_idx == super_buf->frame_idx
2371 /*Pick metadata greater than available frameID*/
2372 || ((queue->nomatch_frame_id != 0)
2373 && (queue->nomatch_frame_id <= buf_info->frame_idx)
2374 && (super_buf->super_buf[buf_s_idx].frame_idx == 0)
2375 && (buf_info->buf->stream_type == CAM_STREAM_TYPE_METADATA))
2376 /*Pick available metadata closest to frameID*/
2377 || ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW)
2378 && (buf_info->buf->stream_type != CAM_STREAM_TYPE_METADATA)
2379 && (super_buf->super_buf[buf_s_idx].frame_idx == 0)
2380 && (super_buf->frame_idx > buf_info->frame_idx))){
2381 /*super buffer frame IDs matching OR In low priority bundling
2382 metadata frameID greater than avialbale super buffer frameID OR
2383 metadata frame closest to incoming frameID will be bundled*/
2384 found_super_buf = 1;
2385 queue->nomatch_frame_id = 0;
2386 break;
2387 } else {
2388 unmatched_bundles++;
2389 if ( NULL == last_buf ) {
2390 if ( super_buf->frame_idx < buf_info->frame_idx ) {
2391 last_buf = pos;
2392 }
2393 }
2394 if ( NULL == insert_before_buf ) {
2395 if ( super_buf->frame_idx > buf_info->frame_idx ) {
2396 insert_before_buf = pos;
2397 }
2398 }
2399 pos = pos->next;
2400 }
2401 }
2402 }
2403
2404 if ( found_super_buf ) {
2405
2406 if(super_buf->super_buf[buf_s_idx].frame_idx != 0) {
2407 //This can cause frame drop. We are overwriting same memory.
2408 pthread_mutex_unlock(&queue->que.lock);
2409 //CDBG_FATAL("FATAL: frame is already in camera ZSL queue");
2410 CDBG_ERROR("***FATAL: frame is already in camera ZSL queue***");
2411 mm_channel_qbuf(ch_obj, buf_info->buf);
2412 return 0;
2413 }
2414
2415 /*Insert incoming buffer to super buffer*/
2416 super_buf->super_buf[buf_s_idx] = *buf_info;
2417
2418 /* check if superbuf is all matched */
2419 super_buf->matched = 1;
2420 for (i=0; i < super_buf->num_of_bufs; i++) {
2421 if (super_buf->super_buf[i].frame_idx == 0) {
2422 super_buf->matched = 0;
2423 break;
2424 }
2425 }
2426
2427 if (super_buf->matched) {
2428 if(ch_obj->isFlashBracketingEnabled) {
2429 queue->expected_frame_id =
2430 queue->expected_frame_id_without_led;
2431 if (buf_info->frame_idx >=
2432 queue->expected_frame_id_without_led) {
2433 ch_obj->isFlashBracketingEnabled = FALSE;
2434 }
2435 } else {
2436 queue->expected_frame_id = buf_info->frame_idx
2437 + queue->attr.post_frame_skip;
2438 }
2439
2440 super_buf->expected = FALSE;
2441
2442 CDBG("%s: curr = %d, skip = %d , Expected Frame ID: %d",
2443 __func__, buf_info->frame_idx,
2444 queue->attr.post_frame_skip, queue->expected_frame_id);
2445
2446 queue->match_cnt++;
2447
2448 /* Any older unmatched buffer need to be released */
2449 if ( last_buf ) {
2450 while ( last_buf != pos ) {
2451 node = member_of(last_buf, cam_node_t, list);
2452 super_buf = (mm_channel_queue_node_t*)node->data;
2453 if (NULL != super_buf) {
2454 for (i=0; i<super_buf->num_of_bufs; i++) {
2455 if (super_buf->super_buf[i].frame_idx != 0) {
2456 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
2457 }
2458 }
2459 queue->que.size--;
2460 last_buf = last_buf->next;
2461 cam_list_del_node(&node->list);
2462 free(node);
2463 free(super_buf);
2464 } else {
2465 CDBG_ERROR(" %s : Invalid superbuf in queue!", __func__);
2466 break;
2467 }
2468 }
2469 }
2470 }else {
2471 if (ch_obj->diverted_frame_id == buf_info->frame_idx) {
2472 super_buf->expected = TRUE;
2473 ch_obj->diverted_frame_id = 0;
2474 }
2475 }
2476 } else {
2477 if ((queue->attr.max_unmatched_frames < unmatched_bundles)
2478 && ( NULL == last_buf )) {
2479 /* incoming frame is older than the last bundled one */
2480 mm_channel_qbuf(ch_obj, buf_info->buf);
2481 } else {
2482 last_buf_ptr = last_buf;
2483
2484 /* Loop to remove unmatched frames */
2485 while ((queue->attr.max_unmatched_frames < unmatched_bundles)
2486 && (last_buf_ptr != NULL && last_buf_ptr != pos)) {
2487 node = member_of(last_buf_ptr, cam_node_t, list);
2488 super_buf = (mm_channel_queue_node_t*)node->data;
2489 if (NULL != super_buf && super_buf->expected == FALSE
2490 && (&node->list != insert_before_buf)) {
2491 for (i=0; i<super_buf->num_of_bufs; i++) {
2492 if (super_buf->super_buf[i].frame_idx != 0) {
2493 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
2494 }
2495 }
2496 queue->que.size--;
2497 cam_list_del_node(&node->list);
2498 free(node);
2499 free(super_buf);
2500 unmatched_bundles--;
2501 }
2502 last_buf_ptr = last_buf_ptr->next;
2503 }
2504
2505 if (queue->attr.max_unmatched_frames < unmatched_bundles) {
2506 node = member_of(last_buf, cam_node_t, list);
2507 super_buf = (mm_channel_queue_node_t*)node->data;
2508 for (i=0; i<super_buf->num_of_bufs; i++) {
2509 if (super_buf->super_buf[i].frame_idx != 0) {
2510 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
2511 }
2512 }
2513 queue->que.size--;
2514 cam_list_del_node(&node->list);
2515 free(node);
2516 free(super_buf);
2517 }
2518
2519 /* insert the new frame at the appropriate position. */
2520
2521 mm_channel_queue_node_t *new_buf = NULL;
2522 cam_node_t* new_node = NULL;
2523
2524 new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
2525 new_node = (cam_node_t*)malloc(sizeof(cam_node_t));
2526 if (NULL != new_buf && NULL != new_node) {
2527 memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
2528 memset(new_node, 0, sizeof(cam_node_t));
2529 new_node->data = (void *)new_buf;
2530 new_buf->num_of_bufs = queue->num_streams;
2531 new_buf->super_buf[buf_s_idx] = *buf_info;
2532 new_buf->frame_idx = buf_info->frame_idx;
2533
2534 if (ch_obj->diverted_frame_id == buf_info->frame_idx) {
2535 new_buf->expected = TRUE;
2536 ch_obj->diverted_frame_id = 0;
2537 }
2538
2539 /* enqueue */
2540 if ( insert_before_buf ) {
2541 cam_list_insert_before_node(&new_node->list, insert_before_buf);
2542 } else {
2543 cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
2544 }
2545 queue->que.size++;
2546
2547 if(queue->num_streams == 1) {
2548 new_buf->matched = 1;
2549 new_buf->expected = FALSE;
2550 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
2551 queue->match_cnt++;
2552 }
2553
2554 if ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW)
2555 && (buf_info->buf->stream_type != CAM_STREAM_TYPE_METADATA)) {
2556 CDBG_ERROR ("%s : No metadata matching for frame = %d",
2557 __func__, buf_info->frame_idx);
2558 queue->nomatch_frame_id = buf_info->frame_idx;
2559 }
2560 } else {
2561 /* No memory */
2562 if (NULL != new_buf) {
2563 free(new_buf);
2564 }
2565 if (NULL != new_node) {
2566 free(new_node);
2567 }
2568 /* qbuf the new buf since we cannot enqueue */
2569 mm_channel_qbuf(ch_obj, buf_info->buf);
2570 }
2571 }
2572 }
2573
2574 pthread_mutex_unlock(&queue->que.lock);
2575 CDBG("%s: X", __func__);
2576 return 0;
2577 }
2578
2579 /*===========================================================================
2580 * FUNCTION : mm_channel_superbuf_dequeue_internal
2581 *
2582 * DESCRIPTION: internal implementation for dequeue from the superbuf queue
2583 *
2584 * PARAMETERS :
2585 * @queue : superbuf queue
2586 * @matched_only : if dequeued buf should be matched
2587 *
2588 * RETURN : ptr to a node from superbuf queue
2589 *==========================================================================*/
mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue,uint8_t matched_only)2590 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue,
2591 uint8_t matched_only)
2592 {
2593 cam_node_t* node = NULL;
2594 struct cam_list *head = NULL;
2595 struct cam_list *pos = NULL;
2596 mm_channel_queue_node_t* super_buf = NULL;
2597
2598 head = &queue->que.head.list;
2599 pos = head->next;
2600 if (pos != head) {
2601 /* get the first node */
2602 node = member_of(pos, cam_node_t, list);
2603 super_buf = (mm_channel_queue_node_t*)node->data;
2604 if ( (NULL != super_buf) &&
2605 (matched_only == TRUE) &&
2606 (super_buf->matched == FALSE) ) {
2607 /* require to dequeue matched frame only, but this superbuf is not matched,
2608 simply set return ptr to NULL */
2609 super_buf = NULL;
2610 }
2611 if (NULL != super_buf) {
2612 /* remove from the queue */
2613 cam_list_del_node(&node->list);
2614 queue->que.size--;
2615 if (super_buf->matched == TRUE) {
2616 queue->match_cnt--;
2617 }
2618 free(node);
2619 }
2620 }
2621
2622 return super_buf;
2623 }
2624
2625 /*===========================================================================
2626 * FUNCTION : mm_channel_superbuf_dequeue
2627 *
2628 * DESCRIPTION: dequeue from the superbuf queue
2629 *
2630 * PARAMETERS :
2631 * @queue : superbuf queue
2632 *
2633 * RETURN : ptr to a node from superbuf queue
2634 *==========================================================================*/
mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)2635 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)
2636 {
2637 mm_channel_queue_node_t* super_buf = NULL;
2638
2639 pthread_mutex_lock(&queue->que.lock);
2640 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2641 pthread_mutex_unlock(&queue->que.lock);
2642
2643 return super_buf;
2644 }
2645
2646 /*===========================================================================
2647 * FUNCTION : mm_channel_superbuf_bufdone_overflow
2648 *
2649 * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer
2650 * via channel attribute
2651 *
2652 * PARAMETERS :
2653 * @my_obj : channel object
2654 * @queue : superbuf queue
2655 *
2656 * RETURN : int32_t type of status
2657 * 0 -- success
2658 * -1 -- failure
2659 *==========================================================================*/
mm_channel_superbuf_bufdone_overflow(mm_channel_t * my_obj,mm_channel_queue_t * queue)2660 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
2661 mm_channel_queue_t * queue)
2662 {
2663 int32_t rc = 0, i;
2664 mm_channel_queue_node_t* super_buf = NULL;
2665 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
2666 /* for continuous streaming mode, no overflow is needed */
2667 return 0;
2668 }
2669
2670 CDBG("%s: before match_cnt=%d, water_mark=%d",
2671 __func__, queue->match_cnt, queue->attr.water_mark);
2672 /* bufdone overflowed bufs */
2673 pthread_mutex_lock(&queue->que.lock);
2674 while (queue->match_cnt > queue->attr.water_mark) {
2675 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2676 if (NULL != super_buf) {
2677 for (i=0; i<super_buf->num_of_bufs; i++) {
2678 if (NULL != super_buf->super_buf[i].buf) {
2679 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
2680 }
2681 }
2682 free(super_buf);
2683 }
2684 }
2685 pthread_mutex_unlock(&queue->que.lock);
2686 CDBG("%s: after match_cnt=%d, water_mark=%d",
2687 __func__, queue->match_cnt, queue->attr.water_mark);
2688
2689 return rc;
2690 }
2691
2692 /*===========================================================================
2693 * FUNCTION : mm_channel_superbuf_skip
2694 *
2695 * DESCRIPTION: depends on the lookback configuration of the channel attribute,
2696 * unwanted superbufs will be removed from the superbuf queue.
2697 *
2698 * PARAMETERS :
2699 * @my_obj : channel object
2700 * @queue : superbuf queue
2701 *
2702 * RETURN : int32_t type of status
2703 * 0 -- success
2704 * -1 -- failure
2705 *==========================================================================*/
mm_channel_superbuf_skip(mm_channel_t * my_obj,mm_channel_queue_t * queue)2706 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
2707 mm_channel_queue_t * queue)
2708 {
2709 int32_t rc = 0, i;
2710 mm_channel_queue_node_t* super_buf = NULL;
2711 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
2712 /* for continuous streaming mode, no skip is needed */
2713 return 0;
2714 }
2715
2716 /* bufdone overflowed bufs */
2717 pthread_mutex_lock(&queue->que.lock);
2718 while (queue->match_cnt > queue->attr.look_back) {
2719 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2720 if (NULL != super_buf) {
2721 for (i=0; i<super_buf->num_of_bufs; i++) {
2722 if (NULL != super_buf->super_buf[i].buf) {
2723 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
2724 }
2725 }
2726 free(super_buf);
2727 }
2728 }
2729 pthread_mutex_unlock(&queue->que.lock);
2730
2731 return rc;
2732 }
2733
2734 /*===========================================================================
2735 * FUNCTION : mm_channel_superbuf_flush
2736 *
2737 * DESCRIPTION: flush the superbuf queue.
2738 *
2739 * PARAMETERS :
2740 * @my_obj : channel object
2741 * @queue : superbuf queue
2742 * @cam_type: flush only particular type (default flushes all)
2743 *
2744 * RETURN : int32_t type of status
2745 * 0 -- success
2746 * -1 -- failure
2747 *==========================================================================*/
mm_channel_superbuf_flush(mm_channel_t * my_obj,mm_channel_queue_t * queue,cam_stream_type_t cam_type)2748 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
2749 mm_channel_queue_t * queue, cam_stream_type_t cam_type)
2750 {
2751 int32_t rc = 0, i;
2752 mm_channel_queue_node_t* super_buf = NULL;
2753 cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
2754
2755 /* bufdone bufs */
2756 pthread_mutex_lock(&queue->que.lock);
2757 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE);
2758 while (super_buf != NULL) {
2759 for (i=0; i<super_buf->num_of_bufs; i++) {
2760 if (NULL != super_buf->super_buf[i].buf) {
2761 stream_type = super_buf->super_buf[i].buf->stream_type;
2762 if ((CAM_STREAM_TYPE_DEFAULT == cam_type) ||
2763 (cam_type == stream_type)) {
2764 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
2765 }
2766 }
2767 }
2768 free(super_buf);
2769 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE);
2770 }
2771 pthread_mutex_unlock(&queue->que.lock);
2772
2773 return rc;
2774 }
2775
2776 /*===========================================================================
2777 * FUNCTION : mm_channel_proc_general_cmd
2778 *
2779 * DESCRIPTION: process general command
2780 *
2781 * PARAMETERS :
2782 * @my_obj : channel object
2783 * @notify_mode : notification mode
2784 *
2785 * RETURN : int32_t type of status
2786 * 0 -- success
2787 * -1 -- failure
2788 *==========================================================================*/
mm_channel_proc_general_cmd(mm_channel_t * my_obj,mm_camera_generic_cmd_t * p_gen_cmd)2789 int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
2790 mm_camera_generic_cmd_t *p_gen_cmd)
2791 {
2792 CDBG("%s: E",__func__);
2793 int32_t rc = 0;
2794 mm_camera_cmdcb_t* node = NULL;
2795
2796 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
2797 if (NULL != node) {
2798 memset(node, 0, sizeof(mm_camera_cmdcb_t));
2799 node->u.gen_cmd = *p_gen_cmd;
2800 node->cmd_type = MM_CAMERA_CMD_TYPE_GENERAL;
2801
2802 /* enqueue to cmd thread */
2803 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
2804
2805 /* wake up cmd thread */
2806 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
2807 } else {
2808 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
2809 rc = -1;
2810 }
2811 CDBG("%s: X",__func__);
2812
2813 return rc;
2814 }
2815
2816 /*===========================================================================
2817 * FUNCTION : mm_channel_superbuf_flush_matched
2818 *
2819 * DESCRIPTION: flush matched buffers from the superbuf queue.
2820 *
2821 * PARAMETERS :
2822 * @my_obj : channel object
2823 * @queue : superbuf queue
2824 *
2825 * RETURN : int32_t type of status
2826 * 0 -- success
2827 * -1 -- failure
2828 *==========================================================================*/
mm_channel_superbuf_flush_matched(mm_channel_t * my_obj,mm_channel_queue_t * queue)2829 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
2830 mm_channel_queue_t * queue)
2831 {
2832 int32_t rc = 0, i;
2833 mm_channel_queue_node_t* super_buf = NULL;
2834
2835 /* bufdone bufs */
2836 pthread_mutex_lock(&queue->que.lock);
2837 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2838 while (super_buf != NULL) {
2839 for (i=0; i<super_buf->num_of_bufs; i++) {
2840 if (NULL != super_buf->super_buf[i].buf) {
2841 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
2842 }
2843 }
2844 free(super_buf);
2845 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2846 }
2847 pthread_mutex_unlock(&queue->que.lock);
2848
2849 return rc;
2850 }
2851