reordered
authorPaul Kocialkowski <contact@paulk.fr>
Fri, 1 Feb 2013 17:24:56 +0000 (18:24 +0100)
committerPaul Kocialkowski <contact@paulk.fr>
Fri, 1 Feb 2013 17:24:56 +0000 (18:24 +0100)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
exynos_camera.c
exynos_camera.h

index c0ef9a5..3842d97 100644 (file)
@@ -134,28 +134,6 @@ struct exynox_camera_config exynos_camera_config_galaxys2 = {
 };
 
 /*
- * Exynos Params
- */
-
-/*
--> always alloc params string (strdup)
--> register internally with set (but with a _register function)
--> unregister it all at the same time (but with a _unregister function)
--> at set, look if there is already one, if not, add to the end of the list and alloc
--> if there is one, just free the value (if string) and replace it
-
-
-set value for a key
-get value for a key
-set all the values
-get all the values
--> pas oublier les negatifs
-
-*/
-
-
-
-/*
  * Exynos Camera
  */
 
@@ -532,479 +510,161 @@ int SecCamera::setObjectPosition(int x, int y)
        return 0;
 }
 
-// Preview
+// Auto-focus
 
-int exynos_camera_preview(struct exynos_camera *exynos_camera)
+void *exynos_camera_auto_focus_thread(void *data)
 {
-       buffer_handle_t *buffer;
-       int stride;
-
-       int width, height;
-       float format_bpp;
-
-       char *preview_format_string;
-       int frame_size, offset;
-       void *preview_data;
-       void *window_data;
-
-       int index;
+       struct exynos_camera *exynos_camera;
+       int auto_focus_status = -1;
+       int auto_focus_result = 0;
        int rc;
        int i;
 
-       if (exynos_camera == NULL || exynos_camera->preview_memory == NULL)
-               return -EINVAL;
-
-       // V4L2
+       if (data == NULL)
+               return NULL;
 
-       rc = exynos_v4l2_poll(exynos_camera, 0);
-       if (rc < 0) {
-               LOGE("%s: poll failed!", __func__);
-               return -1;
-       } else if (rc == 0) {
-               LOGE("%s: poll timeout!", __func__);
-               // TODO: it's probably a good idea to restart everything
-               return -1;
-       }
+       exynos_camera = (struct exynos_camera *) data;
 
-       index = exynos_v4l2_dqbuf_cap(exynos_camera, 0);
-       if (index < 0 || index >= exynos_camera->preview_buffers_count) {
-               LOGE("%s: dqbuf failed!", __func__);
-               return -1;
-       }
+       LOGE("%s: Starting thread", __func__);
+       exynos_camera->auto_focus_thread_running = 1;
 
-       rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, index);
+       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON);
        if (rc < 0) {
-               LOGE("%s: qbuf failed!", __func__);
-               return -1;
+               LOGE("%s: s ctrl failed!", __func__);
+               auto_focus_result = 0;
+               goto thread_exit;
        }
 
-       // Preview window
+       while (exynos_camera->auto_focus_enabled == 1) {
+               pthread_mutex_lock(&exynos_camera->auto_focus_mutex);
 
-       width = exynos_camera->preview_width;
-       height = exynos_camera->preview_height;
-       format_bpp = exynos_camera->preview_format_bpp;
+               rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT, &auto_focus_status);
+               if (rc < 0) {
+                       LOGE("%s: g ctrl failed!", __func__);
+                       auto_focus_result = 0;
+                       pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
+                       goto thread_exit;
+               }
 
-       exynos_camera->preview_window->dequeue_buffer(exynos_camera->preview_window,
-               &buffer, &stride);
-       exynos_camera->gralloc->lock(exynos_camera->gralloc, *buffer, GRALLOC_USAGE_SW_WRITE_OFTEN,
-               0, 0, width, height, &window_data);
+               switch (auto_focus_status) {
+                       case CAMERA_AF_STATUS_IN_PROGRESS:
+                               usleep(500);
+                               break;
+                       case CAMERA_AF_STATUS_SUCCESS:
+                       case CAMERA_AF_STATUS_1ST_SUCCESS:
+                               auto_focus_result = 1;
+                               pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
+                               goto thread_exit;
+                       case CAMERA_AF_STATUS_FAIL:
+                       default:
+                               auto_focus_result = 0;
+                               pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
+                               goto thread_exit;                               
+               }
 
-       if (window_data == NULL) {
-               LOGE("%s: gralloc lock failed!", __func__);
-               return -1;
+               pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
        }
 
-       frame_size = (int) ((float) width * (float) height * format_bpp);
-       offset = index * frame_size;
-
-       preview_data = (void *) ((int) exynos_camera->preview_memory->data + offset);
-       memcpy(window_data, preview_data, frame_size);
+thread_exit:
+       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF);
+       if (rc < 0)
+               LOGE("%s: s ctrl failed!", __func__);
 
-       exynos_camera->gralloc->unlock(exynos_camera->gralloc, *buffer);
-       exynos_camera->preview_window->enqueue_buffer(exynos_camera->preview_window,
-               buffer);
+       if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify))
+               exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS,
+                       (int32_t) auto_focus_result, 0, exynos_camera->callbacks.user);
+               
+       exynos_camera->auto_focus_thread_running = 0;
+       exynos_camera->auto_focus_enabled = 0;
 
-       if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_PREVIEW_FRAME) && EXYNOS_CAMERA_CALLBACK_DEFINED(data)) {
-               exynos_camera->callbacks.data(CAMERA_MSG_PREVIEW_FRAME,
-                       exynos_camera->preview_memory, index, NULL, exynos_camera->callbacks.user);
-       }
+       LOGE("%s: Exiting thread", __func__);
 
-       return 0;
+       return NULL;
 }
 
-void *exynos_camera_preview_thread(void *data)
+int exynos_camera_auto_focus_start(struct exynos_camera *exynos_camera)
 {
-       struct exynos_camera *exynos_camera;
+       pthread_attr_t thread_attr;
        int rc;
 
-       if (data == NULL)
-               return NULL;
-
-       exynos_camera = (struct exynos_camera *) data;
+       if (exynos_camera == NULL)
+               return -EINVAL;
 
-       LOGE("%s: Starting thread", __func__);
-       exynos_camera->preview_thread_running = 1;
+       // Thread
 
-       if (exynos_camera->preview_window == NULL) {
-               // Lock preview lock mutex
-               pthread_mutex_lock(&exynos_camera->preview_lock_mutex);
+       if (exynos_camera->auto_focus_thread_running) {
+               LOGE("Auto-focus thread is already running!");
+               return -1;
        }
 
-       while (exynos_camera->preview_enabled == 1) {
-               pthread_mutex_lock(&exynos_camera->preview_mutex);
+       pthread_mutex_init(&exynos_camera->auto_focus_mutex, NULL);
 
-               rc = exynos_camera_preview(exynos_camera);
-               if (rc < 0) {
-                       LOGE("%s: preview failed!", __func__);
-                       // TODO FIXME WTF REMOVE THAT ASAP
-                       exynos_camera->preview_enabled = 0;
-               }
+       pthread_attr_init(&thread_attr);
+       pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
 
-               pthread_mutex_unlock(&exynos_camera->preview_mutex);
-       }
+       exynos_camera->auto_focus_enabled = 1;
 
-       exynos_camera->preview_thread_running = 0;
-       LOGE("%s: Exiting thread", __func__);
+       rc = pthread_create(&exynos_camera->auto_focus_thread, &thread_attr,
+               exynos_camera_auto_focus_thread, (void *) exynos_camera);
+       if (rc < 0) {
+               LOGE("%s: Unable to create thread", __func__);
+               return -1;
+       }
 
-       return NULL;
+       return 0;
 }
 
-int exynos_camera_preview_start(struct exynos_camera *exynos_camera)
+void exynos_camera_auto_focus_stop(struct exynos_camera *exynos_camera)
 {
-       struct v4l2_streamparm streamparm;
-       int width, height, format;
-       float format_bpp;
-       int fps, frame_size;
-       int fd;
-
-       pthread_attr_t thread_attr;
-
-       int id;
        int rc;
        int i;
 
-       if (exynos_camera->config == NULL)
-               return -EINVAL;
+       if (exynos_camera == NULL)
+               return;
 
-       if (exynos_camera->preview_enabled) {
-               LOGE("Preview was already started!");
-               return 0;
+       if (!exynos_camera->auto_focus_enabled) {
+               LOGE("Auto-focus was already stopped!");
+               return;
        }
 
-       // V4L2
+       pthread_mutex_lock(&exynos_camera->auto_focus_mutex);
 
-       format = exynos_camera->preview_format;
+       // Disable auto-focus to make the thread end
+       exynos_camera->auto_focus_enabled = 0;
 
-       rc = exynos_v4l2_enum_fmt_cap(exynos_camera, 0, format);
-       if (rc < 0) {
-               LOGE("%s: enum fmt failed!", __func__);
-               return -1;
-       }
+       pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
 
-       width = exynos_camera->preview_width;
-       height = exynos_camera->preview_height;
-       format_bpp = exynos_camera->preview_format_bpp;
+       // Wait for the thread to end
+       for (i=0 ; i < 10 ; i++) {
+               if (!exynos_camera->auto_focus_thread_running)
+                       break;
 
-       rc = exynos_v4l2_s_fmt_pix_cap(exynos_camera, 0, width, height, format, V4L2_PIX_FMT_MODE_PREVIEW);
-       if (rc < 0) {
-               LOGE("%s: s fmt failed!", __func__);
-               return -1;
+               usleep(500);
        }
 
-       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CACHEABLE, 1);
-       if (rc < 0) {
-               LOGE("%s: s ctrl failed!", __func__);
-               return -1;
-       }
+       pthread_mutex_destroy(&exynos_camera->auto_focus_mutex);
+}
 
-       rc = exynos_v4l2_reqbufs_cap(exynos_camera, 0, EXYNOS_CAMERA_MAX_BUFFERS_COUNT);
-       if (rc < 0) {
-               LOGE("%s: reqbufs failed!", __func__);
-               return -1;
-       }
+// Picture
 
-       exynos_camera->preview_buffers_count = rc;
-       LOGD("Found %d buffers available!", exynos_camera->preview_buffers_count);
+int exynos_camera_picture(struct exynos_camera *exynos_camera)
+{
+       camera_memory_t *data_memory = NULL;
+       camera_memory_t *exif_data_memory = NULL;
+       camera_memory_t *picture_data_memory = NULL;
+       camera_memory_t *jpeg_thumbnail_data_memory = NULL;
 
-       fps = exynos_camera->preview_fps;
-       memset(&streamparm, 0, sizeof(streamparm));
-       streamparm.parm.capture.timeperframe.numerator = 1;
-       streamparm.parm.capture.timeperframe.denominator = fps;
+       int camera_picture_format;
+       int picture_width;
+       int picture_height;
+       int picture_format;
 
-       rc = exynos_v4l2_s_parm_cap(exynos_camera, 0, &streamparm);
-       if (rc < 0) {
-               LOGE("%s: s parm failed!", __func__);
-               return -1;
-       }
+       int jpeg_thumbnail_width;
+       int jpeg_thumbnail_height;
+       int jpeg_thumbnail_quality;
+       int jpeg_quality;
 
-       frame_size = (int) ((float) width * (float) height * format_bpp);
-       for (i=0 ; i < exynos_camera->preview_buffers_count ; i++) {
-               rc = exynos_v4l2_querybuf_cap(exynos_camera, 0, i);
-               if (rc < 0) {
-                       LOGE("%s: querybuf failed!", __func__);
-                       return -1;
-               }
-
-               if (rc != frame_size)
-                       LOGE("%s: Frame size mismatch: %d/%d", __func__, frame_size, rc);
-       }
-
-       if (exynos_camera->callbacks.request_memory != NULL) {
-               fd = exynos_v4l2_find_fd(exynos_camera, 0);
-               if (fd < 0) {
-                       LOGE("%s: Unable to find v4l2 fd", __func__);
-                       return -1;
-               }
-
-               if (exynos_camera->preview_memory != NULL && exynos_camera->preview_memory->release != NULL)
-                       exynos_camera->preview_memory->release(exynos_camera->preview_memory);
-
-               exynos_camera->preview_memory =
-                       exynos_camera->callbacks.request_memory(fd,
-                               frame_size, exynos_camera->preview_buffers_count, 0);
-               if (exynos_camera->preview_memory == NULL) {
-                       LOGE("%s: memory request failed!", __func__);
-                       return -1;
-               }
-       } else {
-               LOGE("%s: No memory request function!", __func__);
-               return -1;
-       }
-
-       for (i=0 ; i < exynos_camera->preview_buffers_count ; i++) {
-               rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, i);
-               if (rc < 0) {
-                       LOGE("%s: qbuf failed!", __func__);
-                       return -1;
-               }
-       }
-
-       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_ROTATION,
-               exynos_camera->camera_rotation);
-       if (rc < 0) {
-               LOGE("%s: s ctrl failed!", __func__);
-               return -1;
-       }
-
-       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_HFLIP,
-               exynos_camera->camera_hflip);
-       if (rc < 0) {
-               LOGE("%s: s ctrl failed!", __func__);
-               return -1;
-       }
-
-       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_VFLIP,
-               exynos_camera->camera_vflip);
-       if (rc < 0) {
-               LOGE("%s: s ctrl failed!", __func__);
-               return -1;
-       }
-
-       rc = exynos_v4l2_streamon_cap(exynos_camera, 0);
-       if (rc < 0) {
-               LOGE("%s: streamon failed!", __func__);
-               return -1;
-       }
-
-       // Thread
-
-       pthread_mutex_init(&exynos_camera->preview_mutex, NULL);
-       pthread_mutex_init(&exynos_camera->preview_lock_mutex, NULL);
-
-       // Lock preview lock
-       pthread_mutex_lock(&exynos_camera->preview_lock_mutex);
-
-       pthread_attr_init(&thread_attr);
-       pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
-
-       exynos_camera->preview_enabled = 1;
-
-       rc = pthread_create(&exynos_camera->preview_thread, &thread_attr,
-               exynos_camera_preview_thread, (void *) exynos_camera);
-       if (rc < 0) {
-               LOGE("%s: Unable to create thread", __func__);
-               return -1;
-       }
-
-       return 0;
-}
-
-void exynos_camera_preview_stop(struct exynos_camera *exynos_camera)
-{
-       int rc;
-       int i;
-
-       if (exynos_camera == NULL)
-               return;
-
-       if (!exynos_camera->preview_enabled) {
-               LOGE("Preview was already stopped!");
-               return;
-       }
-
-       exynos_camera->preview_enabled = 0;
-
-       // Unlock preview lock
-       pthread_mutex_unlock(&exynos_camera->preview_lock_mutex);
-
-       pthread_mutex_lock(&exynos_camera->preview_mutex);
-
-       // Wait for the thread to end
-       for (i=0 ; i < 10 ; i++) {
-               if (!exynos_camera->preview_thread_running)
-                       break;
-
-               usleep(1000);
-       }
-
-       rc = exynos_v4l2_streamoff_cap(exynos_camera, 0);
-       if (rc < 0) {
-               LOGE("%s: streamoff failed!", __func__);
-       }
-
-       if (exynos_camera->preview_memory != NULL && exynos_camera->preview_memory->release != NULL) {
-               exynos_camera->preview_memory->release(exynos_camera->preview_memory);
-               exynos_camera->preview_memory = NULL;
-       }
-
-       pthread_mutex_unlock(&exynos_camera->preview_mutex);
-}
-
-// Auto-focus
-
-void *exynos_camera_auto_focus_thread(void *data)
-{
-       struct exynos_camera *exynos_camera;
-       int auto_focus_status = -1;
-       int auto_focus_result = 0;
-       int rc;
-       int i;
-
-       if (data == NULL)
-               return NULL;
-
-       exynos_camera = (struct exynos_camera *) data;
-
-       LOGE("%s: Starting thread", __func__);
-       exynos_camera->auto_focus_thread_running = 1;
-
-       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON);
-       if (rc < 0) {
-               LOGE("%s: s ctrl failed!", __func__);
-               auto_focus_result = 0;
-               goto thread_exit;
-       }
-
-       while (exynos_camera->auto_focus_enabled == 1) {
-               pthread_mutex_lock(&exynos_camera->auto_focus_mutex);
-
-               rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT, &auto_focus_status);
-               if (rc < 0) {
-                       LOGE("%s: g ctrl failed!", __func__);
-                       auto_focus_result = 0;
-                       pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
-                       goto thread_exit;
-               }
-
-               switch (auto_focus_status) {
-                       case CAMERA_AF_STATUS_IN_PROGRESS:
-                               usleep(500);
-                               break;
-                       case CAMERA_AF_STATUS_SUCCESS:
-                       case CAMERA_AF_STATUS_1ST_SUCCESS:
-                               auto_focus_result = 1;
-                               pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
-                               goto thread_exit;
-                       case CAMERA_AF_STATUS_FAIL:
-                       default:
-                               auto_focus_result = 0;
-                               pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
-                               goto thread_exit;                               
-               }
-
-               pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
-       }
-
-thread_exit:
-       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF);
-       if (rc < 0)
-               LOGE("%s: s ctrl failed!", __func__);
-
-       if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_FOCUS) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify))
-               exynos_camera->callbacks.notify(CAMERA_MSG_FOCUS,
-                       (int32_t) auto_focus_result, 0, exynos_camera->callbacks.user);
-               
-       exynos_camera->auto_focus_thread_running = 0;
-       exynos_camera->auto_focus_enabled = 0;
-
-       LOGE("%s: Exiting thread", __func__);
-
-       return NULL;
-}
-
-int exynos_camera_auto_focus_start(struct exynos_camera *exynos_camera)
-{
-       pthread_attr_t thread_attr;
-       int rc;
-
-       if (exynos_camera == NULL)
-               return -EINVAL;
-
-       // Thread
-
-       if (exynos_camera->auto_focus_thread_running) {
-               LOGE("Auto-focus thread is already running!");
-               return -1;
-       }
-
-       pthread_mutex_init(&exynos_camera->auto_focus_mutex, NULL);
-
-       pthread_attr_init(&thread_attr);
-       pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
-
-       exynos_camera->auto_focus_enabled = 1;
-
-       rc = pthread_create(&exynos_camera->auto_focus_thread, &thread_attr,
-               exynos_camera_auto_focus_thread, (void *) exynos_camera);
-       if (rc < 0) {
-               LOGE("%s: Unable to create thread", __func__);
-               return -1;
-       }
-
-       return 0;
-}
-
-void exynos_camera_auto_focus_stop(struct exynos_camera *exynos_camera)
-{
-       int rc;
-       int i;
-
-       if (exynos_camera == NULL)
-               return;
-
-       if (!exynos_camera->auto_focus_enabled) {
-               LOGE("Auto-focus was already stopped!");
-               return;
-       }
-
-       pthread_mutex_lock(&exynos_camera->auto_focus_mutex);
-
-       // Disable auto-focus to make the thread end
-       exynos_camera->auto_focus_enabled = 0;
-
-       pthread_mutex_unlock(&exynos_camera->auto_focus_mutex);
-
-       // Wait for the thread to end
-       for (i=0 ; i < 10 ; i++) {
-               if (!exynos_camera->auto_focus_thread_running)
-                       break;
-
-               usleep(500);
-       }
-
-       pthread_mutex_destroy(&exynos_camera->auto_focus_mutex);
-}
-
-// Picture
-
-int exynos_camera_picture(struct exynos_camera *exynos_camera)
-{
-       camera_memory_t *data_memory = NULL;
-       camera_memory_t *exif_data_memory = NULL;
-       camera_memory_t *picture_data_memory = NULL;
-       camera_memory_t *jpeg_thumbnail_data_memory = NULL;
-
-       int camera_picture_format;
-       int picture_width;
-       int picture_height;
-       int picture_format;
-
-       int jpeg_thumbnail_width;
-       int jpeg_thumbnail_height;
-       int jpeg_thumbnail_quality;
-       int jpeg_quality;
-
-       int data_size;
+       int data_size;
 
        int offset = 0;
        void *picture_addr = NULL;
@@ -1393,43 +1053,277 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera)
                exynos_camera->callbacks.data(CAMERA_MSG_COMPRESSED_IMAGE,
                        data_memory, 0, NULL, exynos_camera->callbacks.user);
 
-       // Release memory
+       // Release memory
+
+       if (jpeg_thumbnail_data_memory != NULL && jpeg_thumbnail_data_memory->release != NULL)
+               jpeg_thumbnail_data_memory->release(jpeg_thumbnail_data_memory);
+
+       if (picture_data_memory != NULL && picture_data_memory->release != NULL)
+               picture_data_memory->release(picture_data_memory);
+
+       if (exif_data_memory != NULL && exif_data_memory->release != NULL)
+               exif_data_memory->release(exif_data_memory);
+
+       if (data_memory != NULL && data_memory->release != NULL)
+               data_memory->release(data_memory);
+
+       return 0;
+
+error:
+       if (jpeg_thumbnail_data_memory != NULL && jpeg_thumbnail_data_memory->release != NULL)
+               jpeg_thumbnail_data_memory->release(jpeg_thumbnail_data_memory);
+
+       if (picture_data_memory != NULL && picture_data_memory->release != NULL)
+               picture_data_memory->release(picture_data_memory);
+
+       if (exif_data_memory != NULL && exif_data_memory->release != NULL)
+               exif_data_memory->release(exif_data_memory);
+
+       if (data_memory != NULL && data_memory->release != NULL)
+               data_memory->release(data_memory);
+
+       return -1;
+}
+
+void *exynos_camera_picture_thread(void *data)
+{
+       struct exynos_camera *exynos_camera;
+       int rc;
+       int i;
+
+       if (data == NULL)
+               return NULL;
+
+       exynos_camera = (struct exynos_camera *) data;
+
+       LOGE("%s: Starting thread", __func__);
+       exynos_camera->picture_thread_running = 1;
+
+       if (exynos_camera->picture_enabled == 1) {
+               pthread_mutex_lock(&exynos_camera->picture_mutex);
+
+               rc = exynos_camera_picture(exynos_camera);
+               if (rc < 0) {
+                       LOGE("%s: picture failed!", __func__);
+                       exynos_camera->picture_enabled = 0;
+               }
+
+               if (exynos_camera->picture_memory != NULL && exynos_camera->picture_memory->release != NULL) {
+                       exynos_camera->picture_memory->release(exynos_camera->picture_memory);
+                       exynos_camera->picture_memory = NULL;
+               }
+
+               pthread_mutex_unlock(&exynos_camera->picture_mutex);
+       }
+
+       exynos_camera->picture_thread_running = 0;
+       exynos_camera->picture_enabled = 0;
+
+       LOGE("%s: Exiting thread", __func__);
+
+       return NULL;
+}
+
+int exynos_camera_picture_start(struct exynos_camera *exynos_camera)
+{
+       pthread_attr_t thread_attr;
+
+       int width, height, format, camera_format;
+
+       int fd;
+       int rc;
+
+       if (exynos_camera == NULL)
+               return -EINVAL;
+
+       // Stop preview thread
+       exynos_camera_preview_stop(exynos_camera);
+
+       width = exynos_camera->picture_width;
+       height = exynos_camera->picture_height;
+       format = exynos_camera->picture_format;
+       camera_format = exynos_camera->camera_picture_format;
+
+       // V4L2
+
+       if (camera_format == 0)
+               camera_format = format;
+
+       rc = exynos_v4l2_enum_fmt_cap(exynos_camera, 0, camera_format);
+       if (rc < 0) {
+               LOGE("%s: enum fmt failed!", __func__);
+               return -1;
+       }
+
+       rc = exynos_v4l2_s_fmt_pix_cap(exynos_camera, 0, width, height, camera_format, V4L2_PIX_FMT_MODE_CAPTURE);
+       if (rc < 0) {
+               LOGE("%s: s fmt failed!", __func__);
+               return -1;
+       }
+
+       // Only use 1 buffer
+       rc = exynos_v4l2_reqbufs_cap(exynos_camera, 0, 1);
+       if (rc < 0) {
+               LOGE("%s: reqbufs failed!", __func__);
+               return -1;
+       }
+
+       rc = exynos_v4l2_querybuf_cap(exynos_camera, 0, 0);
+       if (rc < 0) {
+               LOGE("%s: querybuf failed!", __func__);
+               return -1;
+       }
+
+       exynos_camera->picture_buffer_length = rc;
+
+       if (exynos_camera->callbacks.request_memory != NULL) {
+               fd = exynos_v4l2_find_fd(exynos_camera, 0);
+               if (fd < 0) {
+                       LOGE("%s: Unable to find v4l2 fd", __func__);
+                       return -1;
+               }
+
+               if (exynos_camera->picture_memory != NULL && exynos_camera->picture_memory->release != NULL)
+                       exynos_camera->picture_memory->release(exynos_camera->picture_memory);
+
+               exynos_camera->picture_memory =
+                       exynos_camera->callbacks.request_memory(fd,
+                               exynos_camera->picture_buffer_length, 1, 0);
+               if (exynos_camera->picture_memory == NULL) {
+                       LOGE("%s: memory request failed!", __func__);
+                       return -1;
+               }
+       } else {
+               LOGE("%s: No memory request function!", __func__);
+               return -1;
+       }
+
+       rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, 0);
+       if (rc < 0) {
+               LOGE("%s: qbuf failed!", __func__);
+               return -1;
+       }
+
+       rc = exynos_v4l2_streamon_cap(exynos_camera, 0);
+       if (rc < 0) {
+               LOGE("%s: streamon failed!", __func__);
+               return -1;
+       }
+
+       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0);
+       if (rc < 0) {
+               LOGE("%s: s ctrl failed!", __func__);
+               return -1;
+       }
+
+       // Thread
+
+       if (exynos_camera->picture_thread_running) {
+               LOGE("Picture thread is already running!");
+               return -1;
+       }
+
+       pthread_mutex_init(&exynos_camera->picture_mutex, NULL);
+
+       pthread_attr_init(&thread_attr);
+       pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
+
+       exynos_camera->picture_enabled = 1;
+
+       rc = pthread_create(&exynos_camera->picture_thread, &thread_attr,
+               exynos_camera_picture_thread, (void *) exynos_camera);
+       if (rc < 0) {
+               LOGE("%s: Unable to create thread", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+// Preview
+
+int exynos_camera_preview(struct exynos_camera *exynos_camera)
+{
+       buffer_handle_t *buffer;
+       int stride;
+
+       int width, height;
+       float format_bpp;
+
+       char *preview_format_string;
+       int frame_size, offset;
+       void *preview_data;
+       void *window_data;
+
+       int index;
+       int rc;
+       int i;
+
+       if (exynos_camera == NULL || exynos_camera->preview_memory == NULL)
+               return -EINVAL;
+
+       // V4L2
+
+       rc = exynos_v4l2_poll(exynos_camera, 0);
+       if (rc < 0) {
+               LOGE("%s: poll failed!", __func__);
+               return -1;
+       } else if (rc == 0) {
+               LOGE("%s: poll timeout!", __func__);
+               // TODO: it's probably a good idea to restart everything
+               return -1;
+       }
+
+       index = exynos_v4l2_dqbuf_cap(exynos_camera, 0);
+       if (index < 0 || index >= exynos_camera->preview_buffers_count) {
+               LOGE("%s: dqbuf failed!", __func__);
+               return -1;
+       }
 
-       if (jpeg_thumbnail_data_memory != NULL && jpeg_thumbnail_data_memory->release != NULL)
-               jpeg_thumbnail_data_memory->release(jpeg_thumbnail_data_memory);
+       rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, index);
+       if (rc < 0) {
+               LOGE("%s: qbuf failed!", __func__);
+               return -1;
+       }
 
-       if (picture_data_memory != NULL && picture_data_memory->release != NULL)
-               picture_data_memory->release(picture_data_memory);
+       // Preview window
 
-       if (exif_data_memory != NULL && exif_data_memory->release != NULL)
-               exif_data_memory->release(exif_data_memory);
+       width = exynos_camera->preview_width;
+       height = exynos_camera->preview_height;
+       format_bpp = exynos_camera->preview_format_bpp;
 
-       if (data_memory != NULL && data_memory->release != NULL)
-               data_memory->release(data_memory);
+       exynos_camera->preview_window->dequeue_buffer(exynos_camera->preview_window,
+               &buffer, &stride);
+       exynos_camera->gralloc->lock(exynos_camera->gralloc, *buffer, GRALLOC_USAGE_SW_WRITE_OFTEN,
+               0, 0, width, height, &window_data);
 
-       return 0;
+       if (window_data == NULL) {
+               LOGE("%s: gralloc lock failed!", __func__);
+               return -1;
+       }
 
-error:
-       if (jpeg_thumbnail_data_memory != NULL && jpeg_thumbnail_data_memory->release != NULL)
-               jpeg_thumbnail_data_memory->release(jpeg_thumbnail_data_memory);
+       frame_size = (int) ((float) width * (float) height * format_bpp);
+       offset = index * frame_size;
 
-       if (picture_data_memory != NULL && picture_data_memory->release != NULL)
-               picture_data_memory->release(picture_data_memory);
+       preview_data = (void *) ((int) exynos_camera->preview_memory->data + offset);
+       memcpy(window_data, preview_data, frame_size);
 
-       if (exif_data_memory != NULL && exif_data_memory->release != NULL)
-               exif_data_memory->release(exif_data_memory);
+       exynos_camera->gralloc->unlock(exynos_camera->gralloc, *buffer);
+       exynos_camera->preview_window->enqueue_buffer(exynos_camera->preview_window,
+               buffer);
 
-       if (data_memory != NULL && data_memory->release != NULL)
-               data_memory->release(data_memory);
+       if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_PREVIEW_FRAME) && EXYNOS_CAMERA_CALLBACK_DEFINED(data)) {
+               exynos_camera->callbacks.data(CAMERA_MSG_PREVIEW_FRAME,
+                       exynos_camera->preview_memory, index, NULL, exynos_camera->callbacks.user);
+       }
 
-       return -1;
+       return 0;
 }
 
-void *exynos_camera_picture_thread(void *data)
+void *exynos_camera_preview_thread(void *data)
 {
        struct exynos_camera *exynos_camera;
        int rc;
-       int i;
 
        if (data == NULL)
                return NULL;
@@ -1437,84 +1331,111 @@ void *exynos_camera_picture_thread(void *data)
        exynos_camera = (struct exynos_camera *) data;
 
        LOGE("%s: Starting thread", __func__);
-       exynos_camera->picture_thread_running = 1;
+       exynos_camera->preview_thread_running = 1;
 
-       if (exynos_camera->picture_enabled == 1) {
-               pthread_mutex_lock(&exynos_camera->picture_mutex);
+       if (exynos_camera->preview_window == NULL) {
+               // Lock preview lock mutex
+               pthread_mutex_lock(&exynos_camera->preview_lock_mutex);
+       }
 
-               rc = exynos_camera_picture(exynos_camera);
-               if (rc < 0) {
-                       LOGE("%s: picture failed!", __func__);
-                       exynos_camera->picture_enabled = 0;
-               }
+       while (exynos_camera->preview_enabled == 1) {
+               pthread_mutex_lock(&exynos_camera->preview_mutex);
 
-               if (exynos_camera->picture_memory != NULL && exynos_camera->picture_memory->release != NULL) {
-                       exynos_camera->picture_memory->release(exynos_camera->picture_memory);
-                       exynos_camera->picture_memory = NULL;
+               rc = exynos_camera_preview(exynos_camera);
+               if (rc < 0) {
+                       LOGE("%s: preview failed!", __func__);
+                       // TODO FIXME WTF REMOVE THAT ASAP
+                       exynos_camera->preview_enabled = 0;
                }
 
-               pthread_mutex_unlock(&exynos_camera->picture_mutex);
+               pthread_mutex_unlock(&exynos_camera->preview_mutex);
        }
 
-       exynos_camera->picture_thread_running = 0;
-       exynos_camera->picture_enabled = 0;
-
+       exynos_camera->preview_thread_running = 0;
        LOGE("%s: Exiting thread", __func__);
 
        return NULL;
 }
 
-int exynos_camera_picture_start(struct exynos_camera *exynos_camera)
+int exynos_camera_preview_start(struct exynos_camera *exynos_camera)
 {
-       pthread_attr_t thread_attr;
+       struct v4l2_streamparm streamparm;
+       int width, height, format;
+       float format_bpp;
+       int fps, frame_size;
+       int fd;
 
-       int width, height, format, camera_format;
+       pthread_attr_t thread_attr;
 
-       int fd;
+       int id;
        int rc;
+       int i;
 
-       if (exynos_camera == NULL)
+       if (exynos_camera->config == NULL)
                return -EINVAL;
 
-       // Stop preview thread
-       exynos_camera_preview_stop(exynos_camera);
-
-       width = exynos_camera->picture_width;
-       height = exynos_camera->picture_height;
-       format = exynos_camera->picture_format;
-       camera_format = exynos_camera->camera_picture_format;
+       if (exynos_camera->preview_enabled) {
+               LOGE("Preview was already started!");
+               return 0;
+       }
 
        // V4L2
 
-       if (camera_format == 0)
-               camera_format = format;
+       format = exynos_camera->preview_format;
 
-       rc = exynos_v4l2_enum_fmt_cap(exynos_camera, 0, camera_format);
+       rc = exynos_v4l2_enum_fmt_cap(exynos_camera, 0, format);
        if (rc < 0) {
                LOGE("%s: enum fmt failed!", __func__);
                return -1;
        }
 
-       rc = exynos_v4l2_s_fmt_pix_cap(exynos_camera, 0, width, height, camera_format, V4L2_PIX_FMT_MODE_CAPTURE);
+       width = exynos_camera->preview_width;
+       height = exynos_camera->preview_height;
+       format_bpp = exynos_camera->preview_format_bpp;
+
+       rc = exynos_v4l2_s_fmt_pix_cap(exynos_camera, 0, width, height, format, V4L2_PIX_FMT_MODE_PREVIEW);
        if (rc < 0) {
                LOGE("%s: s fmt failed!", __func__);
                return -1;
        }
 
-       // Only use 1 buffer
-       rc = exynos_v4l2_reqbufs_cap(exynos_camera, 0, 1);
+       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CACHEABLE, 1);
+       if (rc < 0) {
+               LOGE("%s: s ctrl failed!", __func__);
+               return -1;
+       }
+
+       rc = exynos_v4l2_reqbufs_cap(exynos_camera, 0, EXYNOS_CAMERA_MAX_BUFFERS_COUNT);
        if (rc < 0) {
                LOGE("%s: reqbufs failed!", __func__);
                return -1;
        }
 
-       rc = exynos_v4l2_querybuf_cap(exynos_camera, 0, 0);
+       exynos_camera->preview_buffers_count = rc;
+       LOGD("Found %d buffers available!", exynos_camera->preview_buffers_count);
+
+       fps = exynos_camera->preview_fps;
+       memset(&streamparm, 0, sizeof(streamparm));
+       streamparm.parm.capture.timeperframe.numerator = 1;
+       streamparm.parm.capture.timeperframe.denominator = fps;
+
+       rc = exynos_v4l2_s_parm_cap(exynos_camera, 0, &streamparm);
        if (rc < 0) {
-               LOGE("%s: querybuf failed!", __func__);
+               LOGE("%s: s parm failed!", __func__);
                return -1;
        }
 
-       exynos_camera->picture_buffer_length = rc;
+       frame_size = (int) ((float) width * (float) height * format_bpp);
+       for (i=0 ; i < exynos_camera->preview_buffers_count ; i++) {
+               rc = exynos_v4l2_querybuf_cap(exynos_camera, 0, i);
+               if (rc < 0) {
+                       LOGE("%s: querybuf failed!", __func__);
+                       return -1;
+               }
+
+               if (rc != frame_size)
+                       LOGE("%s: Frame size mismatch: %d/%d", __func__, frame_size, rc);
+       }
 
        if (exynos_camera->callbacks.request_memory != NULL) {
                fd = exynos_v4l2_find_fd(exynos_camera, 0);
@@ -1523,13 +1444,13 @@ int exynos_camera_picture_start(struct exynos_camera *exynos_camera)
                        return -1;
                }
 
-               if (exynos_camera->picture_memory != NULL && exynos_camera->picture_memory->release != NULL)
-                       exynos_camera->picture_memory->release(exynos_camera->picture_memory);
+               if (exynos_camera->preview_memory != NULL && exynos_camera->preview_memory->release != NULL)
+                       exynos_camera->preview_memory->release(exynos_camera->preview_memory);
 
-               exynos_camera->picture_memory =
+               exynos_camera->preview_memory =
                        exynos_camera->callbacks.request_memory(fd,
-                               exynos_camera->picture_buffer_length, 1, 0);
-               if (exynos_camera->picture_memory == NULL) {
+                               frame_size, exynos_camera->preview_buffers_count, 0);
+               if (exynos_camera->preview_memory == NULL) {
                        LOGE("%s: memory request failed!", __func__);
                        return -1;
                }
@@ -1538,40 +1459,56 @@ int exynos_camera_picture_start(struct exynos_camera *exynos_camera)
                return -1;
        }
 
-       rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, 0);
+       for (i=0 ; i < exynos_camera->preview_buffers_count ; i++) {
+               rc = exynos_v4l2_qbuf_cap(exynos_camera, 0, i);
+               if (rc < 0) {
+                       LOGE("%s: qbuf failed!", __func__);
+                       return -1;
+               }
+       }
+
+       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_ROTATION,
+               exynos_camera->camera_rotation);
        if (rc < 0) {
-               LOGE("%s: qbuf failed!", __func__);
+               LOGE("%s: s ctrl failed!", __func__);
                return -1;
        }
 
-       rc = exynos_v4l2_streamon_cap(exynos_camera, 0);
+       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_HFLIP,
+               exynos_camera->camera_hflip);
        if (rc < 0) {
-               LOGE("%s: streamon failed!", __func__);
+               LOGE("%s: s ctrl failed!", __func__);
                return -1;
        }
 
-       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_CAPTURE, 0);
+       rc = exynos_v4l2_s_ctrl(exynos_camera, 0, V4L2_CID_VFLIP,
+               exynos_camera->camera_vflip);
        if (rc < 0) {
                LOGE("%s: s ctrl failed!", __func__);
                return -1;
        }
 
-       // Thread
-
-       if (exynos_camera->picture_thread_running) {
-               LOGE("Picture thread is already running!");
+       rc = exynos_v4l2_streamon_cap(exynos_camera, 0);
+       if (rc < 0) {
+               LOGE("%s: streamon failed!", __func__);
                return -1;
        }
 
-       pthread_mutex_init(&exynos_camera->picture_mutex, NULL);
+       // Thread
+
+       pthread_mutex_init(&exynos_camera->preview_mutex, NULL);
+       pthread_mutex_init(&exynos_camera->preview_lock_mutex, NULL);
+
+       // Lock preview lock
+       pthread_mutex_lock(&exynos_camera->preview_lock_mutex);
 
        pthread_attr_init(&thread_attr);
        pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
 
-       exynos_camera->picture_enabled = 1;
+       exynos_camera->preview_enabled = 1;
 
-       rc = pthread_create(&exynos_camera->picture_thread, &thread_attr,
-               exynos_camera_picture_thread, (void *) exynos_camera);
+       rc = pthread_create(&exynos_camera->preview_thread, &thread_attr,
+               exynos_camera_preview_thread, (void *) exynos_camera);
        if (rc < 0) {
                LOGE("%s: Unable to create thread", __func__);
                return -1;
@@ -1580,6 +1517,47 @@ int exynos_camera_picture_start(struct exynos_camera *exynos_camera)
        return 0;
 }
 
+void exynos_camera_preview_stop(struct exynos_camera *exynos_camera)
+{
+       int rc;
+       int i;
+
+       if (exynos_camera == NULL)
+               return;
+
+       if (!exynos_camera->preview_enabled) {
+               LOGE("Preview was already stopped!");
+               return;
+       }
+
+       exynos_camera->preview_enabled = 0;
+
+       // Unlock preview lock
+       pthread_mutex_unlock(&exynos_camera->preview_lock_mutex);
+
+       pthread_mutex_lock(&exynos_camera->preview_mutex);
+
+       // Wait for the thread to end
+       for (i=0 ; i < 10 ; i++) {
+               if (!exynos_camera->preview_thread_running)
+                       break;
+
+               usleep(1000);
+       }
+
+       rc = exynos_v4l2_streamoff_cap(exynos_camera, 0);
+       if (rc < 0) {
+               LOGE("%s: streamoff failed!", __func__);
+       }
+
+       if (exynos_camera->preview_memory != NULL && exynos_camera->preview_memory->release != NULL) {
+               exynos_camera->preview_memory->release(exynos_camera->preview_memory);
+               exynos_camera->preview_memory = NULL;
+       }
+
+       pthread_mutex_unlock(&exynos_camera->preview_mutex);
+}
+
 /*
  * Exynos Camera OPS
  */
index 629587d..8022cb6 100644 (file)
@@ -209,6 +209,13 @@ struct exynos_v4l2_ext_control {
 } __attribute__ ((packed));
 
 /*
+ * Camera
+ */
+
+int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id);
+int exynos_camera_params_apply(struct exynos_camera *exynos_camera);
+
+/*
  * EXIF
  */