int32_t mm_camera_stream_util_buf_done(mm_camera_obj_t * my_obj, mm_camera_stream_t *stream, mm_camera_notify_frame_t *frame) { int32_t rc = MM_CAMERA_OK; pthread_mutex_lock(&stream->frame.mutex); if(stream->frame.ref_count[frame->idx] == 0) { rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); CDBG_ERROR("%s: Error Trying to free second time?(idx=%d) count=%d, stream type=%d\n", __func__, frame->idx, stream->frame.ref_count[frame->idx], stream->stream_type); rc = -1; }else{ stream->frame.ref_count[frame->idx]--; if(0 == stream->frame.ref_count[frame->idx]) { CDBG("<DEBUG> : Buf done for buffer:%p:%d",stream,frame->idx); rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); if(rc < 0) CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", __func__, frame->idx, rc); }else{ CDBG("<DEBUG> : Still ref count pending count :%d",stream->frame.ref_count[frame->idx]); CDBG("<DEBUG> : for buffer:%p:%d, stream type=%d",stream,frame->idx, stream->stream_type); } } #if 0 stream->frame.ref_count[frame->idx]--; if(stream->frame.ref_count[frame->idx] == 0) { CDBG("%s: Queue the buffer (idx=%d) count=%d frame id = %d\n", __func__, frame->idx, stream->frame.ref_count[frame->idx], frame->frame->frame_id); rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); if(rc < 0) CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", __func__, frame->idx, rc); } else if(stream->frame.ref_count[frame->idx] == 1) { ALOGE("<DEBUG> : Buf done for buffer:%p:%d",stream,frame->idx); rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); if(rc < 0) CDBG("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", __func__, frame->idx, rc); } else { CDBG_ERROR("%s: Error Trying to free second time?(idx=%d) count=%d\n", __func__, frame->idx, stream->frame.ref_count[frame->idx]); rc = -1; } #endif pthread_mutex_unlock(&stream->frame.mutex); return rc; }
static void mm_camera_read_snapshot_thumbnail_frame(mm_camera_obj_t * my_obj) { int idx, rc = 0; mm_camera_stream_t *stream; mm_camera_frame_queue_t *q; mm_camera_frame_t *frame; q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq; stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail; frame = mm_camera_stream_frame_deq(&stream->frame.freeq); if(frame) { rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); if(rc < 0) { CDBG("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", __func__, frame->idx, rc); return; } } idx = mm_camera_read_msm_frame(my_obj,stream); if (idx < 0) return; mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]); mm_camera_snapshot_send_snapshot_notify(my_obj); }
/* This function enqueue existing buffers (not first time allocated buffers from Surface) to kernel */ static int mm_camera_stream_util_enqueue_buf(mm_camera_obj_t * my_obj, mm_camera_stream_t *stream, mm_camera_buf_def_t *vbuf) { int32_t i, rc = MM_CAMERA_OK, j; if(vbuf->num > MM_CAMERA_MAX_NUM_FRAMES) { rc = -MM_CAMERA_E_GENERAL; CDBG("%s: buf num %d > max limit %d\n", __func__, vbuf->num, MM_CAMERA_MAX_NUM_FRAMES); goto end; } for(i = 0; i < vbuf->num; i++){ int idx = vbuf->buf.mp[i].idx; CDBG("%s: enqueue buf index = %d\n",__func__, idx); if(idx < MM_CAMERA_MAX_NUM_FRAMES) { CDBG("%s: stream_fd = %d, frame_fd = %d, frame ID = %d, offset = %d\n", __func__, stream->fd, stream->frame.frame[i].frame.fd, idx, stream->frame.frame_offset[idx]); rc = mm_camera_stream_qbuf(my_obj, stream, stream->frame.frame[idx].idx); if (rc < 0) { CDBG("%s: VIDIOC_QBUF rc = %d\n", __func__, rc); goto end; } stream->frame.ref_count[idx] = 0; } } stream->frame.qbuf = 1; end: return rc; }
static void mm_camera_read_zsl_postview_frame(mm_camera_obj_t * my_obj) { int idx, rc = 0; mm_camera_stream_t *stream; mm_camera_frame_queue_t *q; mm_camera_frame_t *frame; int cnt, watermark; q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq; stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail; idx = mm_camera_read_msm_frame(my_obj,stream); if (idx < 0) return; mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]); watermark = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.water_mark; cnt = mm_camera_stream_frame_get_q_cnt(q); if(watermark < cnt) { /* water overflow, queue head back to kernel */ frame = mm_camera_stream_frame_deq(q); if(frame) { rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); if(rc < 0) { CDBG("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", __func__, frame->idx, rc); return; } } } mm_camera_check_pending_zsl_frames(my_obj, MM_CAMERA_CH_SNAPSHOT); }
static int32_t mm_camera_stream_fsm_reg(mm_camera_obj_t * my_obj, mm_camera_stream_t *stream, mm_camera_state_evt_type_t evt, void *val) { int32_t rc = 0; switch(evt) { case MM_CAMERA_STATE_EVT_GET_CROP: rc = mm_camera_stream_util_proc_get_crop(my_obj,stream, val); break; case MM_CAMERA_STATE_EVT_QBUF: break; case MM_CAMERA_STATE_EVT_RELEASE: mm_camera_stream_release(stream); break; case MM_CAMERA_STATE_EVT_UNREG_BUF: rc = mm_camera_stream_util_unreg_buf(my_obj, stream); if(!rc) mm_camera_stream_util_set_state(stream, MM_CAMERA_STREAM_STATE_CFG); break; case MM_CAMERA_STATE_EVT_STREAM_ON: { enum v4l2_buf_type buf_type; int i = 0; mm_camera_frame_t *frame; if(stream->frame.qbuf == 0) { for(i = 0; i < stream->frame.num_frame; i++) { rc = mm_camera_stream_qbuf(my_obj, stream, stream->frame.frame[i].idx); if (rc < 0) { CDBG_ERROR("%s: ioctl VIDIOC_QBUF error=%d, stream->type=%d\n", __func__, rc, stream->stream_type); return rc; } stream->frame.ref_count[i] = 0; } stream->frame.qbuf = 1; } buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; CDBG("%s: STREAMON,fd=%d,stream_type=%d\n", __func__, stream->fd, stream->stream_type); rc = ioctl(stream->fd, VIDIOC_STREAMON, &buf_type); if (rc < 0) { CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n", __func__, rc); } else mm_camera_stream_util_set_state(stream, MM_CAMERA_STREAM_STATE_ACTIVE); } break; case MM_CAMERA_STATE_EVT_ENQUEUE_BUF: rc = mm_camera_stream_util_enqueue_buf(my_obj, stream, (mm_camera_buf_def_t *)val); break; default: CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d", __func__, evt, stream->state); return -1; } return rc; }
static int mm_camera_qbuf_to_kernel(mm_camera_obj_t * my_obj, mm_camera_stream_t *stream) { int rc = MM_CAMERA_OK; mm_camera_frame_t *frame; frame = mm_camera_stream_frame_deq(&stream->frame.freeq); pthread_mutex_lock(&stream->frame.mutex); if(frame) { rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx); if(rc < 0) { CDBG("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", __func__, frame->idx, rc); } else stream->frame.no_buf = 0; } else { CDBG("%s:no free frame, fd=%d,type=%d\n", __func__, stream->fd, stream->stream_type); stream->frame.no_buf = 1; } pthread_mutex_unlock(&stream->frame.mutex); return rc; }
static void mm_camera_read_snapshot_thumbnail_frame(mm_camera_obj_t * my_obj) { int idx, rc = 0; mm_camera_stream_t *stream; mm_camera_frame_queue_t *q; q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq; stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail; idx = mm_camera_read_msm_frame(my_obj,stream); if (idx < 0) return; if(my_obj->op_mode != MM_CAMERA_OP_MODE_ZSL) { mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]); mm_camera_snapshot_send_snapshot_notify(my_obj); } else { // CDBG("%s: ZSL does not use thumbnail stream", __func__); rc = mm_camera_stream_qbuf(my_obj, stream, idx); // CDBG("%s Q back thumbnail buffer rc = %d ", __func__, rc); } }
static int mm_camera_stream_util_reg_buf(mm_camera_obj_t * my_obj, mm_camera_stream_t *stream, mm_camera_buf_def_t *vbuf) { int32_t i, rc = MM_CAMERA_OK, j; int *ret; struct v4l2_requestbuffers bufreq; int image_type; uint8_t num_planes; uint32_t planes[VIDEO_MAX_PLANES]; if(vbuf->num > MM_CAMERA_MAX_NUM_FRAMES) { rc = -MM_CAMERA_E_GENERAL; CDBG_ERROR("%s: buf num %d > max limit %d\n", __func__, vbuf->num, MM_CAMERA_MAX_NUM_FRAMES); goto end; } switch(stream->stream_type) { case MM_CAMERA_STREAM_PREVIEW: image_type = OUTPUT_TYPE_P; break; case MM_CAMERA_STREAM_RDI0: image_type = OUTPUT_TYPE_R; break; case MM_CAMERA_STREAM_SNAPSHOT: case MM_CAMERA_STREAM_RAW: image_type = OUTPUT_TYPE_S; break; case MM_CAMERA_STREAM_THUMBNAIL: image_type = OUTPUT_TYPE_T; break; case MM_CAMERA_STREAM_VIDEO: default: image_type = OUTPUT_TYPE_V; break; } stream->frame.frame_len = mm_camera_get_msm_frame_len(stream->cam_fmt, my_obj->current_mode, stream->fmt.fmt.pix.width, stream->fmt.fmt.pix.height, image_type, &num_planes, planes); if(stream->frame.frame_len == 0) { CDBG_ERROR("%s:incorrect frame size = %d\n", __func__, stream->frame.frame_len); rc = -1; goto end; } CDBG("%s frame_len =%d, mum_planes=%d", __func__, stream->frame.frame_len, num_planes); stream->frame.num_frame = vbuf->num; bufreq.count = stream->frame.num_frame; bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; bufreq.memory = V4L2_MEMORY_USERPTR; CDBG("%s: calling VIDIOC_REQBUFS - fd=%d, num_buf=%d, type=%d, memory=%d\n", __func__,stream->fd, bufreq.count, bufreq.type, bufreq.memory); rc = ioctl(stream->fd, VIDIOC_REQBUFS, &bufreq); if (rc < 0) { CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n", __func__, stream->fd, rc); goto end; } CDBG("%s: stream fd=%d, ioctl VIDIOC_REQBUFS: memtype = %d," "num_frames = %d, rc=%d\n", __func__, stream->fd, bufreq.memory, bufreq.count, rc); for(i = 0; i < vbuf->num; i++){ vbuf->buf.mp[i].idx = i; /* remember the index to stream frame if first time qbuf */ memcpy(&stream->frame.frame[i].frame, &(vbuf->buf.mp[i].frame), sizeof(vbuf->buf.mp[i].frame)); stream->frame.frame[i].idx = i; stream->frame.frame[i].num_planes = vbuf->buf.mp[i].num_planes; for(j = 0; j < vbuf->buf.mp[i].num_planes; j++) { stream->frame.frame[i].planes[j] = vbuf->buf.mp[i].planes[j]; } if(vbuf->buf.mp[i].frame_offset) { stream->frame.frame_offset[i] = vbuf->buf.mp[i].frame_offset; } else { stream->frame.frame_offset[i] = 0; } CDBG("%s: vbuf_mp[%d]num_planes =%d", __func__, i, stream->frame.frame[i].num_planes); rc = mm_camera_stream_qbuf(my_obj, stream, stream->frame.frame[i].idx); if (rc < 0) { CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc); goto end; } stream->frame.ref_count[i] = 0; CDBG("%s: stream_fd = %d, frame_fd = %d, frame ID = %d, offset = %d\n", __func__, stream->fd, stream->frame.frame[i].frame.fd, i, stream->frame.frame_offset[i]); } stream->frame.qbuf = 1; end: return rc; }