We have front pictures, problem is that it's not flipped/rotated correctly
authorPaul Kocialkowski <contact@paulk.fr>
Mon, 28 Jan 2013 21:31:38 +0000 (22:31 +0100)
committerPaul Kocialkowski <contact@paulk.fr>
Mon, 28 Jan 2013 21:31:38 +0000 (22:31 +0100)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Android.mk
exynos_camera.c
exynos_camera.h

index 674d63c..b1a3248 100644 (file)
@@ -1,13 +1,15 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
+# Rewrite this in a better way
+
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
 LOCAL_SRC_FILES:= \
        exynos_camera.c \
        exynos_param.c \
        exynos_v4l2.c
 
-LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware
+LOCAL_SHARED_LIBRARIES := libutils libcutils libbinder liblog libcamera_client libhardware libs5pjpeg
 
 LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
 LOCAL_MODULE := camera.exynos4
index 9562bee..8a7fe87 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/types.h>
 #include <linux/videodev2.h>
 #include <videodev2_samsung.h>
+#include <jpeg_api.h>
 
 #define LOG_TAG "exynos_camera"
 #include <utils/Log.h>
@@ -47,6 +48,7 @@ struct exynos_camera_preset exynos_camera_presets_galaxys2[] = {
                .rotation = 0,
                .hflip = 0,
                .vflip = 0,
+               .camera_picture_format = V4L2_PIX_FMT_JPEG,
                .params = {
                        .preview_size_values = "640x480,720x480,800x480,800x450,352x288,320x240,176x144",
                        .preview_size = "640x480",
@@ -81,6 +83,7 @@ struct exynos_camera_preset exynos_camera_presets_galaxys2[] = {
                .rotation = 0,
                .hflip = 1,
                .vflip = 1,
+               .camera_picture_format = V4L2_PIX_FMT_YUYV,
                .params = {
                        .preview_size_values = "640x480,352x288,320x240,176x144",
                        .preview_size = "640x480",
@@ -300,6 +303,9 @@ int exynos_camera_params_init(struct exynos_camera *exynos_camera, int id)
        exynos_param_int_set(exynos_camera, "jpeg-quality",
                exynos_camera->config->presets[id].params.jpeg_quality);
 
+       if (exynos_camera->config->presets[id].camera_picture_format != 0)
+               exynos_camera->camera_picture_format = exynos_camera->config->presets[id].camera_picture_format;
+
        // Zoom
        if (exynos_camera->config->presets[id].params.zoom_supported == 1) {
                exynos_param_string_set(exynos_camera, "zoom-supported", "true");
@@ -346,6 +352,11 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera)
        char *picture_format_string;
        int picture_format;
 
+       int jpeg_thumbnail_width;
+       int jpeg_thumbnail_height;
+       int jpeg_thumbnail_quality;
+       int jpeg_quality;
+
        char *zoom_supported_string;
        int zoom, max_zoom;
 
@@ -380,6 +391,7 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera)
                        preview_format = V4L2_PIX_FMT_RGB32;
                        preview_format_bpp = 4.0f;
                } else {
+                       LOGE("%s: Unsupported preview format: %s", __func__, preview_format_string);
                        preview_format = V4L2_PIX_FMT_NV21;
                        preview_format_bpp = 1.5f;
                }
@@ -412,23 +424,33 @@ int exynos_camera_params_apply(struct exynos_camera *exynos_camera)
 
        picture_format_string = exynos_param_string_get(exynos_camera, "picture-format");
        if (picture_format_string != NULL) {
-               if (strcmp(picture_format_string, "yuv420sp") == 0)
-                       picture_format = V4L2_PIX_FMT_YUV420;
-               else if (strcmp(picture_format_string, "yuv420p") == 0)
-                       picture_format = V4L2_PIX_FMT_YUV420;
-               else if (strcmp(picture_format_string, "rgb565") == 0)
-                       picture_format = V4L2_PIX_FMT_RGB565;
-               else if (strcmp(picture_format_string, "rgb8888") == 0)
-                       picture_format = V4L2_PIX_FMT_RGB32;
-               else if (strcmp(picture_format_string, "jpeg") == 0)
+               if (strcmp(picture_format_string, "jpeg") == 0) {
                        picture_format = V4L2_PIX_FMT_JPEG;
-               else
+               } else {
+                       LOGE("%s: Unsupported picture format: %s", __func__, picture_format_string);
                        picture_format = V4L2_PIX_FMT_JPEG;
+               }
 
                if (picture_format != exynos_camera->picture_format)
                        exynos_camera->picture_format = picture_format;
        }
 
+       jpeg_thumbnail_width = exynos_param_int_get(exynos_camera, "jpeg-thumbnail-width");
+       if (jpeg_thumbnail_width > 0)
+               exynos_camera->jpeg_thumbnail_width = jpeg_thumbnail_width;
+
+       jpeg_thumbnail_height = exynos_param_int_get(exynos_camera, "jpeg-thumbnail-height");
+       if (jpeg_thumbnail_height > 0)
+               exynos_camera->jpeg_thumbnail_height = jpeg_thumbnail_height;
+
+       jpeg_thumbnail_quality = exynos_param_int_get(exynos_camera, "jpeg-thumbnail-quality");
+       if (jpeg_thumbnail_quality > 0)
+               exynos_camera->jpeg_thumbnail_quality = jpeg_thumbnail_quality;
+
+       jpeg_quality = exynos_param_int_get(exynos_camera, "jpeg-quality");
+       if (jpeg_quality > 0)
+               exynos_camera->jpeg_quality = jpeg_quality;
+
        // Zoom
        zoom_supported_string = exynos_param_string_get(exynos_camera, "zoom-supported");
        if (zoom_supported_string != NULL && strcmp(zoom_supported_string, "true") == 0) {
@@ -927,16 +949,36 @@ void exynos_camera_auto_focus_stop(struct exynos_camera *exynos_camera)
 
 int exynos_camera_picture(struct exynos_camera *exynos_camera)
 {
-       camera_memory_t *picture_main_memory;
-       camera_memory_t *picture_thumb_memory;
+       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 value;
+       int jpeg_thumbnail_width;
+       int jpeg_thumbnail_height;
+       int jpeg_thumbnail_quality;
+       int jpeg_quality;
+
+       int offset = 0;
+       void *picture_addr = NULL;
+       int picture_size = 0;
+       void *jpeg_thumbnail_addr = NULL;
+       int jpeg_thumbnail_size = 0;
+
+       int jpeg_fd;
+       struct jpeg_enc_param jpeg_enc_params;
+       enum jpeg_frame_format jpeg_in_format;
+       enum jpeg_stream_format jpeg_out_format;
+       enum jpeg_ret_type jpeg_result;
+       void *jpeg_in_buffer;
+       int jpeg_in_size;
+       void *jpeg_out_buffer;
+       int jpeg_out_size;
 
-       int jpeg_main_size, jpeg_main_offset, jpeg_thumb_size, jpeg_thumb_offset;
        int exif_tv, exif_flash, exif_iso, exif_bv;
-       int jpeg_postview_offset;
-
-       void *jpeg_main_addr, *jpeg_thumb_addr;
 
        int index;
        int rc;
@@ -944,6 +986,18 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera)
        if (exynos_camera == NULL)
                return -EINVAL;
 
+       picture_width = exynos_camera->picture_width;
+       picture_height = exynos_camera->picture_height;
+       picture_format = exynos_camera->picture_format;
+       camera_picture_format = exynos_camera->camera_picture_format;
+       jpeg_thumbnail_width = exynos_camera->jpeg_thumbnail_width;
+       jpeg_thumbnail_height = exynos_camera->jpeg_thumbnail_height;
+       jpeg_thumbnail_quality = exynos_camera->jpeg_thumbnail_quality;
+       jpeg_quality = exynos_camera->jpeg_quality;
+
+       if (camera_picture_format == 0)
+               camera_picture_format = picture_format;
+
        // V4L2
 
        rc = exynos_v4l2_poll(exynos_camera, 0);
@@ -968,98 +1022,308 @@ int exynos_camera_picture(struct exynos_camera *exynos_camera)
                return -1;
        }
 
-       rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_MAIN_SIZE,
-               &jpeg_main_size);
-       if (rc < 0) {
-               LOGE("%s: g ctrl failed!", __func__);
-               return -1;
-       }
+       // This assumes that the output format is JPEG
 
-       rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_MAIN_OFFSET,
-               &jpeg_main_offset);
-       if (rc < 0) {
-               LOGE("%s: g ctrl failed!", __func__);
-               return -1;
-       }
+       if (camera_picture_format == V4L2_PIX_FMT_JPEG) {
+               rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_MAIN_SIZE,
+                       &picture_size);
+               if (rc < 0) {
+                       LOGE("%s: g ctrl failed!", __func__);
+                       return -1;
+               }
 
-       rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_THUMB_SIZE,
-               &jpeg_thumb_size);
-       if (rc < 0) {
-               LOGE("%s: g ctrl failed!", __func__);
-               return -1;
-       }
+               rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_MAIN_OFFSET,
+                       &offset);
+               if (rc < 0) {
+                       LOGE("%s: g ctrl failed!", __func__);
+                       return -1;
+               }
 
-       rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_THUMB_OFFSET,
-               &jpeg_thumb_offset);
-       if (rc < 0) {
-               LOGE("%s: g ctrl failed!", __func__);
-               return -1;
-       }
+               picture_addr = (void *) ((int) exynos_camera->picture_memory->data + offset);
 
-       rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET,
-               &jpeg_postview_offset);
-       if (rc < 0) {
-               LOGE("%s: g ctrl failed!", __func__);
-               return -1;
-       }
+               rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_THUMB_SIZE,
+                       &jpeg_thumbnail_size);
+               if (rc < 0) {
+                       LOGE("%s: g ctrl failed!", __func__);
+                       return -1;
+               }
 
-       jpeg_main_addr = (void *) ((int) exynos_camera->picture_memory->data + jpeg_main_offset);
-       jpeg_thumb_addr = (void *) ((int) exynos_camera->picture_memory->data + jpeg_thumb_offset);
+               rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAM_JPEG_THUMB_OFFSET,
+                       &offset);
+               if (rc < 0) {
+                       LOGE("%s: g ctrl failed!", __func__);
+                       return -1;
+               }
+
+               jpeg_thumbnail_addr = (void *) ((int) exynos_camera->picture_memory->data + offset);
+       }
 
        if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_SHUTTER) && EXYNOS_CAMERA_CALLBACK_DEFINED(notify))
                exynos_camera->callbacks.notify(CAMERA_MSG_SHUTTER, 0, 0,
                        exynos_camera->callbacks.user);
 
        if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_RAW_IMAGE) && EXYNOS_CAMERA_CALLBACK_DEFINED(data)) {
-               if (exynos_camera->callbacks.request_memory != NULL) {
-                       picture_thumb_memory =
-                               exynos_camera->callbacks.request_memory(-1,
-                                       jpeg_thumb_size, 1, 0);
-                       if (picture_thumb_memory == NULL) {
-                               LOGE("%s: thumb memory request failed!", __func__);
-                               return -1;
+               if (camera_picture_format == V4L2_PIX_FMT_JPEG && jpeg_thumbnail_addr != NULL && jpeg_thumbnail_size >= 0) {
+                       if (exynos_camera->callbacks.request_memory != NULL) {
+                               jpeg_thumbnail_data_memory =
+                                       exynos_camera->callbacks.request_memory(-1,
+                                               jpeg_thumbnail_size, 1, 0);
+                               if (jpeg_thumbnail_data_memory == NULL) {
+                                       LOGE("%s: thumb memory request failed!", __func__);
+                                       goto error;
+                               }
+                       } else {
+                               LOGE("%s: No memory request function!", __func__);
+                               goto error;
                        }
+
+                       memcpy(jpeg_thumbnail_data_memory->data, jpeg_thumbnail_addr, jpeg_thumbnail_size);
+
+                       exynos_camera->callbacks.data(CAMERA_MSG_RAW_IMAGE,
+                               jpeg_thumbnail_data_memory, 0, NULL, exynos_camera->callbacks.user);
+
+                       jpeg_thumbnail_data_memory->release(jpeg_thumbnail_data_memory);
                } else {
-                       LOGE("%s: No memory request function!", __func__);
-                       return -1;
-               }
+                       jpeg_fd = api_jpeg_encode_init();
+                       if (jpeg_fd < 0) {
+                               LOGE("%s: Failed to init JPEG", __func__);
+                               goto error;
+                       }
+
+                       switch (camera_picture_format) {
+                               case V4L2_PIX_FMT_RGB565:
+                                       jpeg_in_format = RGB_565;
+                                       jpeg_out_format = JPEG_420;
+                                       jpeg_in_size = (picture_width * picture_height * 2);
+                                       break;
+                               case V4L2_PIX_FMT_NV12:
+                               case V4L2_PIX_FMT_NV21:
+                               case V4L2_PIX_FMT_NV12T:
+                               case V4L2_PIX_FMT_YUV420:
+                                       jpeg_in_format = YUV_420;
+                                       jpeg_out_format = JPEG_420;
+                                       jpeg_in_size = (picture_width * picture_height * 1.5);
+                                       break;
+                               case V4L2_PIX_FMT_YUYV:
+                               case V4L2_PIX_FMT_UYVY:
+                               case V4L2_PIX_FMT_YUV422P:
+                               default:
+                                       jpeg_in_format = YUV_422;
+                                       jpeg_out_format = JPEG_422;
+                                       jpeg_in_size = (picture_width * picture_height * 2);
+                                       break;
+                       }
+
+                       memset(&jpeg_enc_params, 0, sizeof(jpeg_enc_params));
+
+                       jpeg_enc_params.width = jpeg_thumbnail_width;
+                       jpeg_enc_params.height = jpeg_thumbnail_height;
+                       jpeg_enc_params.in_fmt = jpeg_in_format;
+                       jpeg_enc_params.out_fmt = jpeg_out_format;
+
+                       if (jpeg_thumbnail_quality >= 90)
+                               jpeg_enc_params.quality = QUALITY_LEVEL_1;
+                       else if (jpeg_thumbnail_quality >= 80)
+                               jpeg_enc_params.quality = QUALITY_LEVEL_2;
+                       else if (jpeg_thumbnail_quality >= 70)
+                               jpeg_enc_params.quality = QUALITY_LEVEL_3;
+                       else
+                               jpeg_enc_params.quality = QUALITY_LEVEL_4;
+
+                       api_jpeg_set_encode_param(&jpeg_enc_params);
+
+                       jpeg_in_buffer = api_jpeg_get_encode_in_buf(jpeg_fd, jpeg_in_size);
+                       if (jpeg_in_buffer == NULL) {
+                               LOGE("%s: Failed to get JPEG in buffer", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
+
+                       jpeg_out_buffer = api_jpeg_get_encode_out_buf(jpeg_fd);
+                       if (jpeg_out_buffer == NULL) {
+                               LOGE("%s: Failed to get JPEG out buffer", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
+
+                       memcpy(jpeg_in_buffer, exynos_camera->picture_memory->data, jpeg_in_size);
+
+                       jpeg_result = api_jpeg_encode_exe(jpeg_fd, &jpeg_enc_params);
+                       if (jpeg_result != JPEG_ENCODE_OK) {
+                               LOGE("%s: Failed to encode JPEG", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
+
+                       jpeg_out_size = jpeg_enc_params.size;
+                       if (jpeg_out_size <= 0) {
+                               LOGE("%s: Failed to get JPEG out size", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
 
-               memcpy(picture_thumb_memory->data, jpeg_thumb_addr, jpeg_thumb_size);
+                       if (exynos_camera->callbacks.request_memory != NULL) {
+                               jpeg_thumbnail_data_memory =
+                                       exynos_camera->callbacks.request_memory(-1,
+                                               jpeg_out_size, 1, 0);
+                               if (jpeg_thumbnail_data_memory == NULL) {
+                                       LOGE("%s: thumbnail memory request failed!", __func__);
+                                       api_jpeg_encode_deinit(jpeg_fd);
+                                       goto error;
+                               }
+                       } else {
+                               LOGE("%s: No memory request function!", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
 
-               exynos_camera->callbacks.data(CAMERA_MSG_RAW_IMAGE,
-                       picture_thumb_memory, 0, NULL, exynos_camera->callbacks.user);
+                       memcpy(jpeg_thumbnail_data_memory->data, jpeg_out_buffer, jpeg_out_size);
 
-               picture_thumb_memory->release(picture_thumb_memory);
+                       api_jpeg_encode_deinit(jpeg_fd);
+
+                       exynos_camera->callbacks.data(CAMERA_MSG_RAW_IMAGE,
+                               jpeg_thumbnail_data_memory, 0, NULL, exynos_camera->callbacks.user);
+
+                       jpeg_thumbnail_data_memory->release(jpeg_thumbnail_data_memory);
+               }
        }
 
        if (EXYNOS_CAMERA_MSG_ENABLED(CAMERA_MSG_COMPRESSED_IMAGE) && EXYNOS_CAMERA_CALLBACK_DEFINED(data)) {
-               if (exynos_camera->callbacks.request_memory != NULL) {
-                       picture_main_memory =
-                               exynos_camera->callbacks.request_memory(-1,
-                                       jpeg_main_size, 1, 0);
-                       if (picture_main_memory == NULL) {
-                               LOGE("%s: main memory request failed!", __func__);
-                               return -1;
+               if (camera_picture_format == V4L2_PIX_FMT_JPEG && picture_addr != NULL && picture_size >= 0) {
+                       if (exynos_camera->callbacks.request_memory != NULL) {
+                               picture_data_memory =
+                                       exynos_camera->callbacks.request_memory(-1,
+                                               picture_size, 1, 0);
+                               if (picture_data_memory == NULL) {
+                                       LOGE("%s: picture memory request failed!", __func__);
+                                       goto error;
+                               }
+                       } else {
+                               LOGE("%s: No memory request function!", __func__);
+                               goto error;
                        }
+
+                       memcpy(picture_data_memory->data, picture_addr, picture_size);
+
+                       exynos_camera->callbacks.data(CAMERA_MSG_COMPRESSED_IMAGE,
+                               picture_data_memory, 0, NULL, exynos_camera->callbacks.user);
+
+                       picture_data_memory->release(picture_data_memory);
                } else {
-                       LOGE("%s: No memory request function!", __func__);
-                       return -1;
-               }
+                       jpeg_fd = api_jpeg_encode_init();
+                       if (jpeg_fd < 0) {
+                               LOGE("%s: Failed to init JPEG", __func__);
+                               goto error;
+                       }
 
-               memcpy(picture_main_memory->data, jpeg_main_addr, jpeg_main_size);
+                       switch (camera_picture_format) {
+                               case V4L2_PIX_FMT_RGB565:
+                                       jpeg_in_format = RGB_565;
+                                       jpeg_out_format = JPEG_420;
+                                       jpeg_in_size = (picture_width * picture_height * 2);
+                                       break;
+                               case V4L2_PIX_FMT_NV12:
+                               case V4L2_PIX_FMT_NV21:
+                               case V4L2_PIX_FMT_NV12T:
+                               case V4L2_PIX_FMT_YUV420:
+                                       jpeg_in_format = YUV_420;
+                                       jpeg_out_format = JPEG_420;
+                                       jpeg_in_size = (picture_width * picture_height * 1.5);
+                                       break;
+                               case V4L2_PIX_FMT_YUYV:
+                               case V4L2_PIX_FMT_UYVY:
+                               case V4L2_PIX_FMT_YUV422P:
+                               default:
+                                       jpeg_in_format = YUV_422;
+                                       jpeg_out_format = JPEG_422;
+                                       jpeg_in_size = (picture_width * picture_height * 2);
+                                       break;
+                       }
 
-               exynos_camera->callbacks.data(CAMERA_MSG_COMPRESSED_IMAGE,
-                       picture_main_memory, 0, NULL, exynos_camera->callbacks.user);
+                       memset(&jpeg_enc_params, 0, sizeof(jpeg_enc_params));
+
+                       jpeg_enc_params.width = picture_width;
+                       jpeg_enc_params.height = picture_height;
+                       jpeg_enc_params.in_fmt = jpeg_in_format;
+                       jpeg_enc_params.out_fmt = jpeg_out_format;
+
+                       if (jpeg_quality >= 90)
+                               jpeg_enc_params.quality = QUALITY_LEVEL_1;
+                       else if (jpeg_quality >= 80)
+                               jpeg_enc_params.quality = QUALITY_LEVEL_2;
+                       else if (jpeg_quality >= 70)
+                               jpeg_enc_params.quality = QUALITY_LEVEL_3;
+                       else
+                               jpeg_enc_params.quality = QUALITY_LEVEL_4;
+
+                       api_jpeg_set_encode_param(&jpeg_enc_params);
+
+                       jpeg_in_buffer = api_jpeg_get_encode_in_buf(jpeg_fd, jpeg_in_size);
+                       if (jpeg_in_buffer == NULL) {
+                               LOGE("%s: Failed to get JPEG in buffer", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
 
-               picture_main_memory->release(picture_main_memory);
-       }
+                       jpeg_out_buffer = api_jpeg_get_encode_out_buf(jpeg_fd);
+                       if (jpeg_out_buffer == NULL) {
+                               LOGE("%s: Failed to get JPEG out buffer", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
 
-       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;
+                       memcpy(jpeg_in_buffer, exynos_camera->picture_memory->data, jpeg_in_size);
+
+                       jpeg_result = api_jpeg_encode_exe(jpeg_fd, &jpeg_enc_params);
+                       if (jpeg_result != JPEG_ENCODE_OK) {
+                               LOGE("%s: Failed to encode JPEG", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
+
+                       jpeg_out_size = jpeg_enc_params.size;
+                       if (jpeg_out_size <= 0) {
+                               LOGE("%s: Failed to get JPEG out size", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
+
+                       if (exynos_camera->callbacks.request_memory != NULL) {
+                               picture_data_memory =
+                                       exynos_camera->callbacks.request_memory(-1,
+                                               jpeg_out_size, 1, 0);
+                               if (picture_data_memory == NULL) {
+                                       LOGE("%s: picture memory request failed!", __func__);
+                                       api_jpeg_encode_deinit(jpeg_fd);
+                                       goto error;
+                               }
+                       } else {
+                               LOGE("%s: No memory request function!", __func__);
+                               api_jpeg_encode_deinit(jpeg_fd);
+                               goto error;
+                       }
+
+                       memcpy(picture_data_memory->data, jpeg_out_buffer, jpeg_out_size);
+
+                       api_jpeg_encode_deinit(jpeg_fd);
+
+                       exynos_camera->callbacks.data(CAMERA_MSG_COMPRESSED_IMAGE,
+                               picture_data_memory, 0, NULL, exynos_camera->callbacks.user);
+
+                       picture_data_memory->release(picture_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);
+
+       return -1;
 }
 
 void *exynos_camera_picture_thread(void *data)
@@ -1085,6 +1349,11 @@ void *exynos_camera_picture_thread(void *data)
                        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);
        }
 
@@ -1100,7 +1369,7 @@ int exynos_camera_picture_start(struct exynos_camera *exynos_camera)
 {
        pthread_attr_t thread_attr;
 
-       int width, height, format;
+       int width, height, format, camera_format;
 
        int fd;
        int rc;
@@ -1111,19 +1380,23 @@ int exynos_camera_picture_start(struct exynos_camera *exynos_camera)
        // Stop preview thread
        exynos_camera_preview_stop(exynos_camera);
 
-       // V4L2
-
        width = exynos_camera->picture_width;
        height = exynos_camera->picture_height;
        format = exynos_camera->picture_format;
+       camera_format = exynos_camera->camera_picture_format;
 
-       rc = exynos_v4l2_enum_fmt_cap(exynos_camera, 0, 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, format, V4L2_PIX_FMT_MODE_CAPTURE);
+       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;
index ce00c35..9c97753 100644 (file)
@@ -100,6 +100,8 @@ struct exynos_camera_preset {
        int hflip;
        int vflip;
 
+       int camera_picture_format;
+
        struct exynos_camera_params params;
 };
 
@@ -170,9 +172,14 @@ struct exynos_camera {
        int preview_format;
        float preview_format_bpp;
        int preview_fps;
+       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 zoom;
        int focus_object_x;
        int focus_object_y;