return CAMERA_ERROR_NONE;
}
-static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, uint8_t *plane_num)
+static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, guint32 *plane_num)
{
if (!fourcc || !plane_num) {
LOGE("NULL parameter %p %p", fourcc, plane_num);
ret = CAMERA_ERROR_INTERNAL;
goto _GET_DEVICE_INFO_LIST_DONE;
default:
- LOGE("unknown eror : %d", ret);
+ LOGE("unknown error : %d", ret);
ret = CAMERA_ERROR_INTERNAL;
goto _GET_DEVICE_INFO_LIST_DONE;
}
LOGD("buffer count[%d]", buffer_count);
/* stream off */
- ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, FALSE);
+ ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_type, FALSE);
LOGD("stream off : 0x%x", ret);
/* reqbufs 0 */
ret = __camera_v4l2_reqbufs(handle->device_fd,
- handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &buffer_count);
+ handle->buffer_type, V4L2_MEMORY_MMAP, 0, &buffer_count);
LOGD("reqbufs 0 : 0x%x", ret);
}
-static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *format,
- uint32_t request_buffer_count, uint32_t *result_buffer_count)
+static int __camera_start_stream(camera_hal_handle *handle, camera_pixel_format_t pixel_format,
+ camera_resolution_t *resolution, uint32_t fps, uint32_t request_buffer_count)
{
int i = 0;
int ret = CAMERA_ERROR_NONE;
camera_buffer_t *buffer = NULL;
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_streamparm v4l2_parm;
struct v4l2_buffer v4l2_buf;
- struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
+ struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];;
+ guint32 fourcc = 0;
+ guint32 plane_num = 0;
+
+ if (!handle || !resolution) {
+ LOGE("NULL param %p %p", handle, resolution);
+ return CAMERA_ERROR_INTERNAL;
+ }
+
+ /* S_FMT */
+ ret = __camera_get_fourcc_plane_num(pixel_format, &fourcc, &plane_num);
+ if (ret != CAMERA_ERROR_NONE) {
+ LOGE("get fourcc failed [format %d]", pixel_format);
+ return ret;
+ }
+
+ memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format));
+
+ v4l2_fmt.type = handle->buffer_type;
+ if (V4L2_TYPE_IS_MULTIPLANAR(handle->buffer_type)) {
+ v4l2_fmt.fmt.pix_mp.width = resolution->width;
+ v4l2_fmt.fmt.pix_mp.height = resolution->height;
+ v4l2_fmt.fmt.pix_mp.pixelformat = fourcc;
+ v4l2_fmt.fmt.pix_mp.num_planes = plane_num;
+ } else {
+ v4l2_fmt.fmt.pix.width = resolution->width;
+ v4l2_fmt.fmt.pix.height = resolution->height;
+ v4l2_fmt.fmt.pix.pixelformat = fourcc;
+ v4l2_fmt.fmt.pix.bytesperline = resolution->width;
+ }
+
+ if (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+ LOGE("S_FMT failed. errno %d", errno);
+ return CAMERA_ERROR_INTERNAL;
+ }
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(handle->buffer_type)) {
+ for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) {
+ LOGD("plane[%d] stride %u, sizeimage %u", i,
+ v4l2_fmt.fmt.pix_mp.plane_fmt[i].bytesperline,
+ v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+ }
+ } else {
+ LOGD("stride %d, sizeimage %d",
+ v4l2_fmt.fmt.pix.bytesperline,
+ v4l2_fmt.fmt.pix.sizeimage);
+ }
+
+ /* G_PARM */
+ memset(&v4l2_parm, 0x0, sizeof(struct v4l2_streamparm));
- if (!handle || !format || !result_buffer_count) {
- LOGE("NULL param %p %p", handle, result_buffer_count);
+ v4l2_parm.type = handle->buffer_type;
+
+ if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) {
+ LOGE("G_PARM failed. errno %d", errno);
+ return CAMERA_ERROR_INTERNAL;
+ }
+
+ /* S_PARM to set fps */
+ v4l2_parm.parm.capture.timeperframe.numerator = 1;
+ v4l2_parm.parm.capture.timeperframe.denominator = fps;
+
+ if (ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) {
+ LOGE("S_PARM failed. errno %d", errno);
return CAMERA_ERROR_INTERNAL;
}
/* request buffer */
ret = __camera_v4l2_reqbufs(handle->device_fd,
- handle->v4l2_type, V4L2_MEMORY_MMAP, request_buffer_count, result_buffer_count);
+ handle->buffer_type, V4L2_MEMORY_MMAP, request_buffer_count, &handle->buffer_count);
if (ret != CAMERA_ERROR_NONE) {
- g_mutex_unlock(&handle->lock);
return ret;
}
LOGD("buffer count : request %d -> result %d",
- request_buffer_count, *result_buffer_count);
+ request_buffer_count, handle->buffer_count);
/* query buffer, mmap and qbuf */
- for (i = 0 ; i < *result_buffer_count ; i++) {
+ for (i = 0 ; i < handle->buffer_count ; i++) {
memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
- v4l2_buf.type = handle->v4l2_type;
+ v4l2_buf.type = handle->buffer_type;
v4l2_buf.memory = V4L2_MEMORY_MMAP;
v4l2_buf.index = i;
v4l2_buf.m.planes = v4l2_planes;
- v4l2_buf.length = handle->plane_num;
-
- LOGD("%d", i);
+ v4l2_buf.length = plane_num;
if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
LOGE("[%d] query buf failed. errno %d", i, errno);
goto _START_STREAM_FAILED;
}
- LOGD("%d", i);
-
buffer = &handle->camera_buffers[i];
- LOGD("%d", i);
-
buffer->index = i;
- buffer->format = format->stream_format;
- buffer->resolution = format->stream_resolution;
+ buffer->format = pixel_format;
+ buffer->resolution.width = resolution->width;
+ buffer->resolution.height = resolution->height;
buffer->total_size = v4l2_buf.length;
- buffer->num_planes = handle->plane_num;
+ buffer->num_planes = plane_num;
buffer->planes[0].size = v4l2_buf.length;
buffer->planes[0].data = mmap(0,
v4l2_buf.length,
handle->device_fd,
v4l2_buf.m.offset);
- LOGD("%d", i);
-
if (buffer->planes[0].data == MAP_FAILED) {
LOGE("[%d] mmap failed (errno %d)", i, errno);
goto _START_STREAM_FAILED;
}
- LOGD("%d", i);
-
- if (__camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) {
+ if (__camera_v4l2_qbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) {
LOGE("[%d] qbuf failed (errno %d)", i, errno);
goto _START_STREAM_FAILED;
}
-
- LOGD("%d", i);
}
/* stream on */
- ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, TRUE);
+ ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_type, TRUE);
if (ret != CAMERA_ERROR_NONE) {
LOGE("stream on failed");
goto _START_STREAM_FAILED;
return CAMERA_ERROR_NONE;
_START_STREAM_FAILED:
- __camera_stop_stream(handle, *result_buffer_count);
+ __camera_stop_stream(handle, handle->buffer_count);
return ret;
}
+static void __camera_do_capture(camera_hal_handle *handle)
+{
+ int ret = CAMERA_ERROR_NONE;
+ int buffer_index = 0;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return;
+ }
+
+ LOGD("start");
+
+ /* restart stream for capture */
+ if (handle->capture_restart_stream) {
+ ret = __camera_stop_stream(handle, handle->buffer_count);
+ if (ret != CAMERA_ERROR_NONE) {
+ LOGE("stop stream failed for capture[0x%x]", ret);
+ goto _CAPTURE_DONE;
+ }
+
+ ret = __camera_start_stream(handle,
+ handle->preview_format.capture_format,
+ &handle->preview_format.capture_resolution,
+ handle->preview_format.stream_fps,
+ BUFFER_MAX);
+ if (ret != CAMERA_ERROR_NONE) {
+ LOGE("start stream failed for capture[0x%x]", ret);
+ goto _CAPTURE_DONE;
+ }
+ }
+
+ /* get capture buffer */
+ ret = __camera_v4l2_wait_frame(handle->device_fd, 5);
+ if (ret != CAMERA_ERROR_NONE) {
+ LOGE("frame wait failed for capture[0x%x]", ret);
+ goto _CAPTURE_DONE;
+ }
+
+ ret = __camera_v4l2_dqbuf(handle->device_fd,
+ handle->buffer_type, V4L2_MEMORY_MMAP, &buffer_index);
+ if (ret != CAMERA_ERROR_NONE) {
+ LOGE("dqbuf failed for capture[0x%x]", ret);
+ goto _CAPTURE_DONE;
+ }
+
+ g_mutex_lock(&handle->buffer_lock);
+
+ handle->captured_count++;
+
+ g_mutex_unlock(&handle->buffer_lock);
+
+ LOGD("capture cb[%p], buffer index[%d],count[%d]",
+ handle->capture_cb, buffer_index, handle->captured_count);
+
+ if (handle->capture_cb) {
+ ((camera_capture_cb)handle->capture_cb)(&handle->camera_buffers[buffer_index],
+ NULL, NULL, handle->capture_cb_data);
+ } else {
+ LOGW("capture callback is NULL");
+ /* Need to post error? */
+ }
+
+ ret = __camera_v4l2_qbuf(handle->device_fd,
+ handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index);
+ if (ret != CAMERA_ERROR_NONE)
+ LOGE("qbuf failed for capture[0x%x]", ret);
+
+ g_mutex_lock(&handle->buffer_lock);
+
+ if (handle->state == CAMERA_STATE_CAPTURING) {
+ LOGD("wait for capture stop signal");
+ g_cond_wait(&handle->buffer_cond, &handle->buffer_lock);
+ LOGD("signal received");
+ } else {
+ LOGD("The state is already changed.");
+ }
+
+ g_mutex_unlock(&handle->buffer_lock);
+
+_CAPTURE_DONE:
+ /* restart stream for preview */
+ if (handle->capture_restart_stream) {
+ ret = __camera_stop_stream(handle, handle->buffer_count);
+ if (ret != CAMERA_ERROR_NONE)
+ LOGE("stop stream failed for preview[0x%x]", ret);
+
+ ret = __camera_start_stream(handle,
+ handle->preview_format.stream_format,
+ &handle->preview_format.stream_resolution,
+ handle->preview_format.stream_fps,
+ BUFFER_MAX);
+ if (ret != CAMERA_ERROR_NONE)
+ LOGE("start stream failed for preview[0x%x]", ret);
+ }
+
+ LOGD("done");
+}
+
+
static void *__camera_buffer_handler_func(gpointer data)
{
int index = 0;
LOGD("enter - preview handler thread");
/* run buffer thread */
- g_mutex_lock(&handle->preview_cb_lock);
+ g_mutex_lock(&handle->buffer_lock);
while (handle->buffer_thread_run) {
- g_mutex_unlock(&handle->preview_cb_lock);
+ g_mutex_unlock(&handle->buffer_lock);
if (__camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) {
LOGE("frame wait failed");
- g_mutex_lock(&handle->preview_cb_lock);
+ g_mutex_lock(&handle->buffer_lock);
break;
}
- g_mutex_lock(&handle->preview_cb_lock);
+ g_mutex_lock(&handle->buffer_lock);
if (handle->buffer_thread_run == FALSE) {
LOGW("stop preview handler thread");
break;
}
- if (__camera_v4l2_dqbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) {
+ if (__camera_v4l2_dqbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) {
LOGE("dqbuf failed");
break;
}
- handle->live_buffer_num++;
+ handle->buffer_dequeued_count++;
- /*LOGD("live buffer num %d", handle->live_buffer_num);*/
+ /*LOGD("dequeued buffer count %d", handle->buffer_dequeued_count);*/
- g_mutex_unlock(&handle->preview_cb_lock);
+ g_mutex_unlock(&handle->buffer_lock);
if (handle->preview_cb) {
((camera_preview_frame_cb)handle->preview_cb)(&handle->camera_buffers[index], NULL, handle->preview_cb_data);
camera_release_preview_buffer((void *)handle, index);
}
+ /* check capture request flag */
+ if (handle->capture_request) {
+ __camera_do_capture(handle);
+ handle->capture_request = FALSE;
+ }
+
sched_yield();
- g_mutex_lock(&handle->preview_cb_lock);
+ g_mutex_lock(&handle->buffer_lock);
}
- g_mutex_unlock(&handle->preview_cb_lock);
+ g_mutex_unlock(&handle->buffer_lock);
LOGD("leave - preview handler thread");
LOGD("enter - message thread");
- g_mutex_lock(&handle->message_cb_lock);
+ g_mutex_lock(&handle->msg_cb_lock);
- while (handle->message_cb_run) {
- if (g_queue_is_empty(handle->message_list)) {
+ while (handle->msg_cb_run) {
+ if (g_queue_is_empty(handle->msg_list)) {
LOGD("wait for message");
- g_cond_wait(&handle->message_cb_cond, &handle->message_cb_lock);
+ g_cond_wait(&handle->msg_cb_cond, &handle->msg_cb_lock);
LOGD("message signal received");
}
- if (!handle->message_cb_run) {
+ if (!handle->msg_cb_run) {
LOGW("break message thread");
break;
}
- message = g_queue_pop_head(handle->message_list);
+ message = g_queue_pop_head(handle->msg_list);
if (!message) {
LOGW("NULL message");
continue;
}
- g_mutex_unlock(&handle->message_cb_lock);
+ g_mutex_unlock(&handle->msg_cb_lock);
for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) {
- if (handle->message_cb[i]) {
+ if (handle->msg_cb[i]) {
LOGD("call message callback type %d", message->type);
- ((camera_message_cb)handle->message_cb[i])(message, handle->message_cb_data[i]);
+ ((camera_message_cb)handle->msg_cb[i])(message, handle->msg_cb_data[i]);
}
}
g_free(message);
message = NULL;
- g_mutex_lock(&handle->message_cb_lock);
+ g_mutex_lock(&handle->msg_cb_lock);
}
- g_mutex_unlock(&handle->message_cb_lock);
+ g_mutex_unlock(&handle->msg_cb_lock);
LOGD("leave - message thread");
return;
}
- if (handle->message_thread) {
- g_mutex_lock(&handle->message_cb_lock);
- handle->message_cb_run = FALSE;
- g_cond_signal(&handle->message_cb_cond);
- g_mutex_unlock(&handle->message_cb_lock);
- g_thread_join(handle->message_thread);
- g_queue_free_full(handle->message_list, (GDestroyNotify)__camera_message_release_func);
- handle->message_list = NULL;
+ if (handle->msg_thread) {
+ g_mutex_lock(&handle->msg_cb_lock);
+ handle->msg_cb_run = FALSE;
+ g_cond_signal(&handle->msg_cb_cond);
+ g_mutex_unlock(&handle->msg_cb_lock);
+ g_thread_join(handle->msg_thread);
+ g_queue_free_full(handle->msg_list, (GDestroyNotify)__camera_message_release_func);
+ handle->msg_list = NULL;
}
g_mutex_clear(&handle->lock);
- g_mutex_clear(&handle->preview_cb_lock);
- g_mutex_clear(&handle->message_cb_lock);
- g_cond_clear(&handle->preview_cb_cond);
- g_cond_clear(&handle->message_cb_cond);
+ g_mutex_clear(&handle->buffer_lock);
+ g_mutex_clear(&handle->msg_cb_lock);
+ g_cond_clear(&handle->buffer_cond);
+ g_cond_clear(&handle->msg_cb_cond);
if (handle->bufmgr) {
tbm_bufmgr_deinit(handle->bufmgr);
new_handle->bufmgr = bufmgr;
g_mutex_init(&new_handle->lock);
- g_mutex_init(&new_handle->preview_cb_lock);
- g_mutex_init(&new_handle->message_cb_lock);
- g_cond_init(&new_handle->preview_cb_cond);
- g_cond_init(&new_handle->message_cb_cond);
+ g_mutex_init(&new_handle->buffer_lock);
+ g_mutex_init(&new_handle->msg_cb_lock);
+ g_cond_init(&new_handle->buffer_cond);
+ g_cond_init(&new_handle->msg_cb_cond);
/* message thread */
- new_handle->message_list = g_queue_new();
- new_handle->message_cb_run = TRUE;
- new_handle->message_thread = g_thread_try_new("camera_hal_message_thread",
+ new_handle->msg_list = g_queue_new();
+ new_handle->msg_cb_run = TRUE;
+ new_handle->msg_thread = g_thread_try_new("camera_hal_msg_thread",
_camera_message_handler_func, (gpointer)new_handle, NULL);
- if (!new_handle->message_thread) {
+ if (!new_handle->msg_thread) {
LOGE("failed to create message thread");
ret = CAMERA_ERROR_INTERNAL;
goto _INIT_ERROR;
}
if (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
- handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+ handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE;
else
- handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE;
+ handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE;
handle->state = CAMERA_STATE_OPENED;
handle->device_index = device_index;
handle->device_fd = device_fd;
LOGD("[%d] device[%s] opened [fd %d, type %d]",
- device_index, node_path, device_fd, handle->v4l2_type);
+ device_index, node_path, device_fd, handle->buffer_type);
_OPEN_DEVICE_DONE:
g_mutex_unlock(&handle->lock);
}
for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) {
- if (handle->message_cb[i] == NULL) {
- handle->message_cb[i] = callback;
- handle->message_cb_data[i] = user_data;
+ if (handle->msg_cb[i] == NULL) {
+ handle->msg_cb[i] = callback;
+ handle->msg_cb_data[i] = user_data;
*cb_id = i;
LOGD("message cb [%p] added, user data %p - id %u", callback, user_data, i);
g_mutex_unlock(&handle->lock);
return CAMERA_ERROR_INVALID_STATE;
}
- if (handle->message_cb[cb_id]) {
+ if (handle->msg_cb[cb_id]) {
LOGD("remove message callback %p, user data %p - cb_id %u",
- handle->message_cb[cb_id], handle->message_cb_data[cb_id], cb_id);
+ handle->msg_cb[cb_id], handle->msg_cb_data[cb_id], cb_id);
- handle->message_cb[cb_id] = NULL;
- handle->message_cb_data[cb_id] = NULL;
+ handle->msg_cb[cb_id] = NULL;
+ handle->msg_cb_data[cb_id] = NULL;
} else {
LOGE("already removed message cb");
g_mutex_unlock(&handle->lock);
int j = 0;
int ret = CAMERA_ERROR_NONE;
gboolean capability_check = FALSE;
- guint32 fourcc = 0;
camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
camera_device_info_t *device_info = NULL;
- struct v4l2_format v4l2_fmt;
- struct v4l2_streamparm v4l2_parm;
if (!handle || !format) {
LOGE("NULL param %p %p", handle, format);
g_mutex_lock(&handle->lock);
- if (handle->state != CAMERA_STATE_OPENED) {
+ if (handle->state != CAMERA_STATE_OPENED &&
+ handle->state != CAMERA_STATE_PREVIEWING) {
LOGE("invalid state %d", handle->state);
g_mutex_unlock(&handle->lock);
return CAMERA_ERROR_INVALID_STATE;
return CAMERA_ERROR_INVALID_PARAMETER;
}
- /* S_FMT */
- ret = __camera_get_fourcc_plane_num(format->stream_format, &fourcc, &handle->plane_num);
- if (ret != CAMERA_ERROR_NONE) {
- LOGE("get fourcc failed [format %d]", format->stream_format);
- g_mutex_unlock(&handle->lock);
- return ret;
- }
-
- memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format));
-
- v4l2_fmt.type = handle->v4l2_type;
- if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) {
- v4l2_fmt.fmt.pix_mp.width = format->stream_resolution.width;
- v4l2_fmt.fmt.pix_mp.height = format->stream_resolution.height;
- v4l2_fmt.fmt.pix_mp.pixelformat = fourcc;
- v4l2_fmt.fmt.pix_mp.num_planes = handle->plane_num;
- } else {
- v4l2_fmt.fmt.pix.width = format->stream_resolution.width;
- v4l2_fmt.fmt.pix.height = format->stream_resolution.height;
- v4l2_fmt.fmt.pix.pixelformat = fourcc;
- v4l2_fmt.fmt.pix.bytesperline = format->stream_resolution.width;
- }
-
- if (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
- LOGE("S_FMT failed. errno %d", errno);
- g_mutex_unlock(&handle->lock);
- return CAMERA_ERROR_INTERNAL;
- }
-
- if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) {
- for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) {
- LOGD("plane[%d] stride %u, sizeimage %u", i,
- v4l2_fmt.fmt.pix_mp.plane_fmt[i].bytesperline,
- v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+ /* compare with current settings */
+ if (handle->state == CAMERA_STATE_PREVIEWING) {
+ if (handle->preview_format.stream_format == format->stream_format &&
+ handle->preview_format.stream_resolution.width == format->stream_resolution.width &&
+ handle->preview_format.stream_resolution.height == format->stream_resolution.height &&
+ handle->preview_format.stream_fps == format->stream_fps &&
+ handle->preview_format.stream_rotation == format->stream_rotation) {
+ LOGD("no need to restart preview stream");
+ goto _SET_PREVIEW_STREAM_FORMAT_DONE;
}
- } else {
- LOGD("stride %d, sizeimage %d",
- v4l2_fmt.fmt.pix.bytesperline,
- v4l2_fmt.fmt.pix.sizeimage);
- }
- /* G_PARM */
- memset(&v4l2_parm, 0x0, sizeof(struct v4l2_streamparm));
+ LOGD("Preview setting is changed. Restart preview now.");
- v4l2_parm.type = handle->v4l2_type;
+ /* stop preview stream to change it */
+ ret = __camera_stop_stream(handle, handle->buffer_count);
+ if (ret != CAMERA_ERROR_NONE) {
+ LOGE("failed to stop stream");
+ g_mutex_unlock(&handle->lock);
+ return ret;
+ }
- if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) {
- LOGE("G_PARM failed. errno %d", errno);
- g_mutex_unlock(&handle->lock);
- return CAMERA_ERROR_INTERNAL;
+ /* restart preview stream to change it */
+ ret = __camera_start_stream(handle,
+ format->stream_format,
+ &format->stream_resolution,
+ format->stream_fps,
+ BUFFER_MAX);
+ if (ret != CAMERA_ERROR_NONE) {
+ LOGE("failed to start stream");
+ g_mutex_unlock(&handle->lock);
+ return ret;
+ }
}
- /* S_PARM to set fps */
- v4l2_parm.parm.capture.timeperframe.numerator = 1;
- v4l2_parm.parm.capture.timeperframe.denominator = format->stream_fps;
-
- if (ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) {
- LOGE("S_PARM failed. errno %d", errno);
- g_mutex_unlock(&handle->lock);
- return CAMERA_ERROR_INTERNAL;
- }
+_SET_PREVIEW_STREAM_FORMAT_DONE:
+ /* set capture restart flag */
+ if (format->stream_format == format->capture_format &&
+ format->stream_resolution.width == format->capture_resolution.width &&
+ format->stream_resolution.height == format->capture_resolution.height)
+ handle->capture_restart_stream = FALSE;
+ else
+ handle->capture_restart_stream = TRUE;
memcpy(&handle->preview_format, format, sizeof(camera_format_t));
- LOGD("set preview stream [%d: %dx%d, fps %d]",
+ LOGD("set format PREVIEW[%d:%dx%d,fps:%d], CAPTURE[%d:%dx%d,restart:%d]",
format->stream_format,
format->stream_resolution.width,
format->stream_resolution.height,
- format->stream_fps);
-
- LOGW("CAPTURE STREAM [%d: %dx%d] IS NOT SUPPORTED",
+ format->stream_fps,
format->capture_format,
format->capture_resolution.width,
- format->capture_resolution.height);
+ format->capture_resolution.height,
+ handle->capture_restart_stream);
g_mutex_unlock(&handle->lock);
return CAMERA_ERROR_INVALID_STATE;
}
- ret = __camera_start_stream(handle, &handle->preview_format, BUFFER_MAX, &handle->buffer_count);
+ ret = __camera_start_stream(handle,
+ handle->preview_format.stream_format,
+ &handle->preview_format.stream_resolution,
+ handle->preview_format.stream_fps,
+ BUFFER_MAX);
if (ret != CAMERA_ERROR_NONE) {
LOGE("__camera_start_stream failed[0x%x]", ret);
g_mutex_unlock(&handle->lock);
return ret;
}
- g_mutex_lock(&handle->preview_cb_lock);
+ g_mutex_lock(&handle->buffer_lock);
handle->buffer_thread_run = TRUE;
__camera_buffer_handler_func, (gpointer)handle, NULL);
if (!handle->buffer_thread) {
LOGE("failed to create buffer handler thread");
- g_mutex_unlock(&handle->preview_cb_lock);
+ g_mutex_unlock(&handle->buffer_lock);
__camera_stop_stream(handle, handle->buffer_count);
handle->preview_cb = callback;
handle->preview_cb_data = user_data;
- g_mutex_unlock(&handle->preview_cb_lock);
+ g_mutex_unlock(&handle->buffer_lock);
handle->state = CAMERA_STATE_PREVIEWING;
}
ret = __camera_v4l2_qbuf(handle->device_fd,
- handle->v4l2_type, V4L2_MEMORY_MMAP, buffer_index);
+ handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index);
- g_mutex_lock(&handle->preview_cb_lock);
+ g_mutex_lock(&handle->buffer_lock);
if (ret == CAMERA_ERROR_NONE) {
- handle->live_buffer_num--;
- LOGD("qbud done : index %d, live buffer num %d",
- buffer_index, handle->live_buffer_num);
+ if (handle->buffer_dequeued_count > 0)
+ handle->buffer_dequeued_count--;
+ else
+ LOGW("invalid dequeued buffer count[%u]", handle->buffer_dequeued_count);
+
+ /*LOGD("qbud done : index %d, dequeued buffer count %d",
+ buffer_index, handle->buffer_dequeued_count);*/
} else {
LOGE("qbuf failed [index %d]", buffer_index);
}
- g_cond_signal(&handle->preview_cb_cond);
+ g_cond_signal(&handle->buffer_cond);
- g_mutex_unlock(&handle->preview_cb_lock);
+ g_mutex_unlock(&handle->buffer_lock);
return ret;
}
return CAMERA_ERROR_INVALID_STATE;
}
- g_mutex_lock(&handle->preview_cb_lock);
+ g_mutex_lock(&handle->buffer_lock);
handle->buffer_thread_run = FALSE;
- while (handle->live_buffer_num > 0) {
- LOGD("wait for live buffer [num %d]", handle->live_buffer_num);
+ while (handle->buffer_dequeued_count > 0) {
+ LOGD("wait for dequeued buffer [%d]", handle->buffer_dequeued_count);
end_time = g_get_monotonic_time() + 3 * G_TIME_SPAN_SECOND;
- if (!g_cond_wait_until(&handle->preview_cb_cond, &handle->preview_cb_lock, end_time)) {
+ if (!g_cond_wait_until(&handle->buffer_cond, &handle->buffer_lock, end_time)) {
LOGE("buffer wait failed");
break;
} else {
}
}
- g_mutex_unlock(&handle->preview_cb_lock);
+ g_mutex_unlock(&handle->buffer_lock);
ret = __camera_stop_stream(handle, handle->buffer_count);
int camera_start_capture(void *camera_handle, camera_capture_cb callback, void *user_data)
{
- if (!camera_handle || !callback) {
+ camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
+
+ if (!handle || !callback) {
LOGE("NULL param %p %p", camera_handle, callback);
return CAMERA_ERROR_INVALID_PARAMETER;
}
- LOGE("NOT SUPPORTED");
+ g_mutex_lock(&handle->lock);
- /* capture function is not supported */
- return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+ if (handle->state != CAMERA_STATE_PREVIEWING) {
+ LOGE("invalid state %d", handle->state);
+ g_mutex_unlock(&handle->lock);
+ return CAMERA_ERROR_INVALID_STATE;
+ }
+
+ /* set callback and user data */
+ handle->capture_cb = callback;
+ handle->capture_cb_data = user_data;
+
+ /* reset captured count */
+ handle->captured_count = 0;
+
+ /* set capture request flag */
+ handle->capture_request = TRUE;
+
+ handle->state = CAMERA_STATE_CAPTURING;
+
+ LOGD("start capture");
+
+ g_mutex_unlock(&handle->lock);
+
+ return CAMERA_ERROR_NONE;
}
int camera_stop_capture(void *camera_handle)
{
- if (!camera_handle) {
+ camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
+
+ if (!handle) {
LOGE("NULL handle");
return CAMERA_ERROR_INVALID_PARAMETER;
}
- LOGE("NOT SUPPORTED");
+ g_mutex_lock(&handle->lock);
- /* capture function is not supported */
- return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+ if (handle->state != CAMERA_STATE_CAPTURING) {
+ LOGE("invalid state %d", handle->state);
+ g_mutex_unlock(&handle->lock);
+ return CAMERA_ERROR_INVALID_STATE;
+ }
+
+ g_mutex_lock(&handle->buffer_lock);
+
+ if (handle->captured_count == 0) {
+ LOGE("No captured image yet.");
+ g_mutex_unlock(&handle->buffer_lock);
+ g_mutex_unlock(&handle->lock);
+ return CAMERA_ERROR_INTERNAL;
+ }
+
+ LOGD("send signal to start preview after capture");
+
+ g_cond_signal(&handle->buffer_cond);
+ g_mutex_unlock(&handle->buffer_lock);
+
+ handle->state = CAMERA_STATE_PREVIEWING;
+
+ g_mutex_unlock(&handle->lock);
+
+ return CAMERA_ERROR_NONE;
}
int camera_set_video_stream_format(void *camera_handle, camera_format_t *format)