aboutsummaryrefslogtreecommitdiff
path: root/camera/usbcamcore
diff options
context:
space:
mode:
authorPrateek Chaubey <chaubeyprateek@gmail.com>2018-01-07 20:55:14 +0530
committerDavide Garberi <dade.garberi@gmail.com>2018-01-19 14:09:15 +0100
commit6616278131edd80a12545085e06ee6b0e0a0a788 (patch)
tree0aef88ed11809a9d67f6abe4dc2ff782a14737e2 /camera/usbcamcore
parentcc4ccf34871da343111bf68d16ba4e4c67cac1dc (diff)
msm8996-common: zuk: Import OSS Camera HAL
Tag: LA.HB.1.3.2-32600-8x96.0 Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
Diffstat (limited to 'camera/usbcamcore')
-rwxr-xr-xcamera/usbcamcore/inc/QCameraMjpegDecode.h49
-rwxr-xr-xcamera/usbcamcore/inc/QCameraUsbParm.h178
-rwxr-xr-xcamera/usbcamcore/inc/QCameraUsbPriv.h202
-rwxr-xr-xcamera/usbcamcore/inc/QualcommUsbCamera.h243
-rwxr-xr-xcamera/usbcamcore/src/QCameraMjpegDecode.cpp701
-rwxr-xr-xcamera/usbcamcore/src/QCameraUsbParm.cpp683
-rwxr-xr-xcamera/usbcamcore/src/QualcommUsbCamera.cpp2963
7 files changed, 5019 insertions, 0 deletions
diff --git a/camera/usbcamcore/inc/QCameraMjpegDecode.h b/camera/usbcamcore/inc/QCameraMjpegDecode.h
new file mode 100755
index 0000000..b04182b
--- /dev/null
+++ b/camera/usbcamcore/inc/QCameraMjpegDecode.h
@@ -0,0 +1,49 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __QCAMERA_MJPEG_DECODE_H
+#define __QCAMERA_MJPEG_DECODE_H
+
+typedef int MJPEGD_ERR;
+#define MJPEGD_NO_ERROR 0
+#define MJPEGD_ERROR -1
+#define MJPEGD_INSUFFICIENT_MEM -2
+
+MJPEGD_ERR mjpegDecoderInit(void**);
+
+MJPEGD_ERR mjpegDecoderDestroy(void* mjpegd);
+
+MJPEGD_ERR mjpegDecode(
+ void* mjpegd,
+ char* mjpegBuffer,
+ int mjpegBufferSize,
+ char* outputYptr,
+ char* outputUVptr,
+ int outputFormat);
+
+#endif /* __QCAMERA_MJPEG_DECODE_H */
diff --git a/camera/usbcamcore/inc/QCameraUsbParm.h b/camera/usbcamcore/inc/QCameraUsbParm.h
new file mode 100755
index 0000000..595bf42
--- /dev/null
+++ b/camera/usbcamcore/inc/QCameraUsbParm.h
@@ -0,0 +1,178 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_QCAMERA_USB_PARM_H
+#define ANDROID_HARDWARE_QCAMERA_USB_PARM_H
+
+
+#include <utils/threads.h>
+#include <hardware/camera.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/threads.h>
+#include <cutils/properties.h>
+#include <camera/Camera.h>
+#include <camera/QCameraParameters.h>
+#include <system/window.h>
+#include <system/camera.h>
+#include <hardware/camera.h>
+#include <gralloc_priv.h>
+#include <hardware/power.h>
+
+extern "C" {
+#include <linux/android_pmem.h>
+#include <linux/msm_ion.h>
+#include <camera.h>
+#include <camera_defs_i.h>
+} //extern C
+
+//Error codes
+#define NOT_FOUND -1
+
+/******************************************************************************
+* Macro definitions
+******************************************************************************/
+/* enum definitions for picture formats */
+static const int PICTURE_FORMAT_JPEG = 1;
+static const int PICTURE_FORMAT_RAW = 2;
+
+/* Default preview width in pixels */
+#define DEFAULT_USBCAM_PRVW_WD 1280//640
+
+/* Default preview height in pixels */
+#define DEFAULT_USBCAM_PRVW_HT 720//480
+
+/* Default picture format */
+#define DEFAULT_USBCAM_PICT_FMT PICTURE_FORMAT_JPEG
+
+/* Default picture width in pixels */
+#define DEFAULT_USBCAM_PICT_WD 640
+
+/* Default picture height in pixels */
+#define DEFAULT_USBCAM_PICT_HT 480
+
+/* Default picture JPEG quality 0-100 */
+#define DEFAULT_USBCAM_PICT_QLTY 85
+
+/* Default thumbnail width in pixels */
+#define DEFAULT_USBCAM_THUMBNAIL_WD 432
+
+/* Default thumbnail height in pixels */
+#define DEFAULT_USBCAM_THUMBNAIL_HT 288
+
+/* Default thumbnail JPEG quality 0-100 */
+#define DEFAULT_USBCAM_THUMBNAIL_QLTY 85
+
+/* Default preview format */
+#define DEFAULT_USBCAM_PRVW_FMT HAL_PIXEL_FORMAT_YCrCb_420_SP
+
+/* minimum of the default preview fps range in milli-Hz */
+#define MIN_PREV_FPS 5000
+
+/* maximum of the default preview fps range in milli-Hz */
+#define MAX_PREV_FPS 121000
+
+//for histogram stats
+#define HISTOGRAM_STATS_SIZE 257
+#define NUM_HISTOGRAM_BUFFERS 3
+
+namespace android {
+
+/******************************************************************************
+* Structure definitions
+******************************************************************************/
+typedef struct {
+ uint32_t aspect_ratio;
+ uint32_t width;
+ uint32_t height;
+} thumbnail_size_type;
+
+/******************************************************************************
+ * Function: usbCamInitDefaultParameters
+ * Description: This function sets default parameters to camera HAL context
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+int usbCamInitDefaultParameters(camera_hardware_t *camHal);
+
+/******************************************************************************
+ * Function: usbCamSetParameters
+ * Description: This function parses the parameter string and stores the
+ * parameters in the camera HAL handle
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * params - pointer to parameter string
+ *
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+int usbCamSetParameters(camera_hardware_t *camHal, const char *params);
+
+/******************************************************************************
+ * Function: usbCamGetParameters
+ * Description: This function allocates memory for parameter string,
+ * composes and returns the parameter string
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * Address to the parameter string
+ *
+ * Notes: none
+ *****************************************************************************/
+char* usbCamGetParameters(camera_hardware_t *camHal);
+
+/******************************************************************************
+ * Function: usbCamPutParameters
+ * Description: This function frees the memory allocated for parameter string
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * parms - Parameter string
+ *
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+void usbCamPutParameters(camera_hardware_t *camHal, char *parms);
+
+}; // namespace android
+
+#endif /* ANDROID_HARDWARE_QCAMERA_USB_PARM_H */
diff --git a/camera/usbcamcore/inc/QCameraUsbPriv.h b/camera/usbcamcore/inc/QCameraUsbPriv.h
new file mode 100755
index 0000000..9b60c11
--- /dev/null
+++ b/camera/usbcamcore/inc/QCameraUsbPriv.h
@@ -0,0 +1,202 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_QCAMERA_USB_PRIV_H
+#define ANDROID_HARDWARE_QCAMERA_USB_PRIV_H
+
+namespace android {
+
+/* File name length in number of characters */
+#define FILENAME_LENGTH (256)
+
+/* Number of display buffers (in addition to minimum number of undequed buffers */
+#define PRVW_DISP_BUF_CNT 2
+
+/* Number of V4L2 capture buffers. */
+#define PRVW_CAP_BUF_CNT 4
+
+/* Maximum buffer size for JPEG output in number of bytes */
+#define MAX_JPEG_BUFFER_SIZE (1024 * 1024)
+
+/* Preview loop commands */
+#define USB_CAM_PREVIEW_EXIT (0x100)
+#define USB_CAM_PREVIEW_PAUSE (0x101)
+#define USB_CAM_PREVIEW_TAKEPIC (0x200)
+
+/******************************************************************************
+ * Macro function to input validate device handle
+ *****************************************************************************/
+#define VALIDATE_DEVICE_HDL(camHal, device, ret_err_code) {\
+ if(device && device->priv){\
+ camHal = (camera_hardware_t *)device->priv;\
+ }else{\
+ ALOGE("%s: Null device or device->priv", __func__);\
+ return ret_err_code;\
+ }\
+}\
+
+/******************************************************************************
+ * Macro function to check return status of a function, log and exit the thread
+ *****************************************************************************/
+#define ERROR_CHECK_EXIT_THREAD(rc, string) {\
+ if(rc < 0) {\
+ ALOGE("%s: Error %s", __func__, string);\
+ return (void *)-1;\
+ }\
+}
+
+/******************************************************************************
+ * Macro function to check return status of a function, log and exit
+ *****************************************************************************/
+#define ERROR_CHECK_EXIT(rc, string) {\
+ if(rc < 0) {\
+ ALOGE("%s: Error %s", __func__, string);\
+ return -1;\
+ }\
+}
+
+/******************************************************************************
+* Macro function to Print the parameter string 1000 characters at a time
+******************************************************************************/
+#define PRINT_PARAM_STR(parms) {\
+ char temp[1001] = {0};\
+ int n=0;\
+ while(1) {\
+ strlcpy(temp,parms+n,1000);\
+ ALOGD("parms = %s", temp);\
+ if (strlen(temp) < 1000) break;\
+ n += 1000;\
+ }\
+ }\
+
+/******************************************************************************
+ * Macro function to open camera
+ *****************************************************************************/
+#define USB_CAM_OPEN(camHal) {\
+ camHal->fd = open(camHal->dev_name, O_RDWR | O_NONBLOCK, 0);\
+ if(!camHal->fd)\
+ ALOGE("%s: Error in open", __func__);\
+ else\
+ ALOGD("%s: Successfully opened", __func__);\
+ }\
+
+/******************************************************************************
+ * Macro function to close camera
+ *****************************************************************************/
+#define USB_CAM_CLOSE(camHal) {\
+ int rc;\
+ if(camHal->fd){\
+ rc = close(camHal->fd);\
+ if(0 > rc){\
+ ALOGE("%s: close failed ", __func__);\
+ }\
+ else{\
+ camHal->fd = 0;\
+ ALOGD("%s: close successful", __func__);\
+ }\
+ }\
+ }\
+
+struct bufObj {
+ void *data;
+ int len;
+};
+
+typedef struct {
+ camera_device hw_dev;
+ Mutex lock;
+ int previewEnabledFlag;
+ int prvwStoppedForPicture;
+ int msgEnabledFlag;
+ volatile int prvwCmdPending;
+ volatile int prvwCmd;
+ pthread_t previewThread;
+ pthread_t takePictureThread;
+
+ camera_notify_callback notify_cb;
+ camera_data_callback data_cb;
+ camera_data_timestamp_callback data_cb_timestamp;
+ camera_request_memory get_memory;
+ void* cb_ctxt;
+
+ /* capture related members */
+ /* prevFormat is pixel format of preview buffers that are exported */
+ int prevFormat;
+ int prevFps;
+ int prevWidth;
+ int prevHeight;
+ /* captureFormat is internal setting for USB camera buffers */
+ int captureFormat;
+ char dev_name[FILENAME_LENGTH];
+ int fd;
+ unsigned int n_buffers;
+ struct v4l2_buffer curCaptureBuf;
+ struct bufObj *buffers;
+
+ /* Display related members */
+ preview_stream_ops* window;
+ QCameraHalMemory_t previewMem;
+ /* dispFormat is preview display format.Same as preview buffer format*/
+ int dispFormat;
+ int dispWidth;
+ int dispHeight;
+
+ /* MJPEG decoder related members */
+ /* MJPEG decoder object */
+ void* mjpegd;
+
+ /* JPEG picture and thumbnail related members */
+ int pictFormat;
+ int pictWidth;
+ int pictHeight;
+ int pictJpegQlty;
+ int thumbnailWidth;
+ int thumbnailHeight;
+ int thumbnailJpegQlty;
+ QCameraHalMemory_t pictMem;
+ int takePictInProgress;
+ int jpegEncInProgress;
+ pthread_mutex_t jpegEncMutex;
+ pthread_cond_t jpegEncCond;
+
+ /* */
+ QCameraParameters qCamParams;
+ String8 prevSizeValues;
+ String8 pictSizeValues;
+ String8 thumbnailSizeValues;
+ String8 vidSizeValues;
+ String8 pictFormatValues;
+ String8 prevFormatValues;
+ String8 prevFpsRangesValues;
+
+} camera_hardware_t;
+
+
+}; // namespace android
+
+#endif /* ANDROID_HARDWARE_QCAMERA_USB_PRIV_H */
diff --git a/camera/usbcamcore/inc/QualcommUsbCamera.h b/camera/usbcamcore/inc/QualcommUsbCamera.h
new file mode 100755
index 0000000..e389c76
--- /dev/null
+++ b/camera/usbcamcore/inc/QualcommUsbCamera.h
@@ -0,0 +1,243 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_HARDWARE_QUALCOMM_CAMERA_USBCAM_H
+#define ANDROID_HARDWARE_QUALCOMM_CAMERA_USBCAM_H
+
+extern "C" {
+#include <sys/time.h>
+}
+
+#include "QCameraHWI.h"
+
+extern "C" {
+
+/*#include <hardware/camera.h>*/
+
+ int usbcam_get_number_of_cameras();
+ int usbcam_get_camera_info(int camera_id, struct camera_info *info);
+
+ int usbcam_camera_device_open(const struct hw_module_t* module, const char* id,
+ struct hw_device_t** device);
+
+ hw_device_t * usbcam_open_camera_device(int cameraId);
+
+ int usbcam_close_camera_device( hw_device_t *);
+
+namespace android {
+
+ /** Set the ANativeWindow to which preview frames are sent */
+ int usbcam_set_preview_window(struct camera_device *,
+ struct preview_stream_ops *window);
+
+ /** Set the notification and data callbacks */
+ void usbcam_set_CallBacks(struct camera_device *,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user);
+
+ /**
+ * The following three functions all take a msg_type, which is a bitmask of
+ * the messages defined in include/ui/Camera.h
+ */
+
+ /**
+ * Enable a message, or set of messages.
+ */
+ void usbcam_enable_msg_type(struct camera_device *, int32_t msg_type);
+
+ /**
+ * Disable a message, or a set of messages.
+ *
+ * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera
+ * HAL should not rely on its client to call releaseRecordingFrame() to
+ * release video recording frames sent out by the cameral HAL before and
+ * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL
+ * clients must not modify/access any video recording frame after calling
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME).
+ */
+ void usbcam_disable_msg_type(struct camera_device *, int32_t msg_type);
+
+ /**
+ * Query whether a message, or a set of messages, is enabled. Note that
+ * this is operates as an AND, if any of the messages queried are off, this
+ * will return false.
+ */
+ int usbcam_msg_type_enabled(struct camera_device *, int32_t msg_type);
+
+ /**
+ * Start preview mode.
+ */
+ int usbcam_start_preview(struct camera_device *);
+
+ /**
+ * Stop a previously started preview.
+ */
+ void usbcam_stop_preview(struct camera_device *);
+
+ /**
+ * Returns true if preview is enabled.
+ */
+ int usbcam_preview_enabled(struct camera_device *);
+
+ /**
+ * Request the camera HAL to store meta data or real YUV data in the video
+ * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If
+ * it is not called, the default camera HAL behavior is to store real YUV
+ * data in the video buffers.
+ *
+ * This method should be called before startRecording() in order to be
+ * effective.
+ *
+ * If meta data is stored in the video buffers, it is up to the receiver of
+ * the video buffers to interpret the contents and to find the actual frame
+ * data with the help of the meta data in the buffer. How this is done is
+ * outside of the scope of this method.
+ *
+ * Some camera HALs may not support storing meta data in the video buffers,
+ * but all camera HALs should support storing real YUV data in the video
+ * buffers. If the camera HAL does not support storing the meta data in the
+ * video buffers when it is requested to do do, INVALID_OPERATION must be
+ * returned. It is very useful for the camera HAL to pass meta data rather
+ * than the actual frame data directly to the video encoder, since the
+ * amount of the uncompressed frame data can be very large if video size is
+ * large.
+ *
+ * @param enable if true to instruct the camera HAL to store
+ * meta data in the video buffers; false to instruct
+ * the camera HAL to store real YUV data in the video
+ * buffers.
+ *
+ * @return OK on success.
+ */
+ int usbcam_store_meta_data_in_buffers(struct camera_device *, int enable);
+
+ /**
+ * Start record mode. When a record image is available, a
+ * CAMERA_MSG_VIDEO_FRAME message is sent with the corresponding
+ * frame. Every record frame must be released by a camera HAL client via
+ * releaseRecordingFrame() before the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+ * responsibility to manage the life-cycle of the video recording frames,
+ * and the client must not modify/access any video recording frames.
+ */
+ int usbcam_start_recording(struct camera_device *);
+
+ /**
+ * Stop a previously started recording.
+ */
+ void usbcam_stop_recording(struct camera_device *);
+
+ /**
+ * Returns true if recording is enabled.
+ */
+ int usbcam_recording_enabled(struct camera_device *);
+
+ /**
+ * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+ *
+ * It is camera HAL client's responsibility to release video recording
+ * frames sent out by the camera HAL before the camera HAL receives a call
+ * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+ * responsibility to manage the life-cycle of the video recording frames.
+ */
+ void usbcam_release_recording_frame(struct camera_device *,
+ const void *opaque);
+
+ /**
+ * Start auto focus, the notification callback routine is called with
+ * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() will be
+ * called again if another auto focus is needed.
+ */
+ int usbcam_auto_focus(struct camera_device *);
+
+ /**
+ * Cancels auto-focus function. If the auto-focus is still in progress,
+ * this function will cancel it. Whether the auto-focus is in progress or
+ * not, this function will return the focus position to the default. If
+ * the camera does not support auto-focus, this is a no-op.
+ */
+ int usbcam_cancel_auto_focus(struct camera_device *);
+
+ /**
+ * Take a picture.
+ */
+ int usbcam_take_picture(struct camera_device *);
+
+ /**
+ * Cancel a picture that was started with takePicture. Calling this method
+ * when no picture is being taken is a no-op.
+ */
+ int usbcam_cancel_picture(struct camera_device *);
+
+ /**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported.
+ */
+ int usbcam_set_parameters(struct camera_device *, const char *parms);
+
+ //status_t setParameters(const QCameraParameters& params);
+ /** Retrieve the camera parameters. The buffer returned by the camera HAL
+ must be returned back to it with put_parameters, if put_parameters
+ is not NULL.
+ */
+ char* usbcam_get_parameters(struct camera_device *);
+
+ /** The camera HAL uses its own memory to pass us the parameters when we
+ call get_parameters. Use this function to return the memory back to
+ the camera HAL, if put_parameters is not NULL. If put_parameters
+ is NULL, then you have to use free() to release the memory.
+ */
+ void usbcam_put_parameters(struct camera_device *, char *);
+
+ /**
+ * Send command to camera driver.
+ */
+ int usbcam_send_command(struct camera_device *,
+ int32_t cmd, int32_t arg1, int32_t arg2);
+
+ /**
+ * Release the hardware resources owned by this object. Note that this is
+ * *not* done in the destructor.
+ */
+ void usbcam_release(struct camera_device *);
+
+ /**
+ * Dump state of the camera hardware
+ */
+ int usbcam_dump(struct camera_device *, int fd);
+
+}; // namespace android
+
+} //extern "C"
+
+#endif
diff --git a/camera/usbcamcore/src/QCameraMjpegDecode.cpp b/camera/usbcamcore/src/QCameraMjpegDecode.cpp
new file mode 100755
index 0000000..dcf0aa2
--- /dev/null
+++ b/camera/usbcamcore/src/QCameraMjpegDecode.cpp
@@ -0,0 +1,701 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#define ALOG_NDEBUG 0
+#define ALOG_NIDEBUG 0
+#define LOG_TAG "QCameraMjpegDecode"
+#include <utils/Log.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+extern "C" {
+#include "jpeg_buffer.h"
+#include "jpeg_common.h"
+#include "jpegd.h"
+}
+
+#include "QCameraMjpegDecode.h"
+
+/* TBDJ: Can be removed */
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+// Abstract the return type of the function to be run as a thread
+#define OS_THREAD_FUNC_RET_T void *
+
+// Abstract the argument type to the thread function
+#define OS_THREAD_FUNC_ARG_T void *
+
+// Helpful constants for return values in the thread functions
+#define OS_THREAD_FUNC_RET_SUCCEEDED (OS_THREAD_FUNC_RET_T)0
+#define OS_THREAD_FUNC_RET_FAILED (OS_THREAD_FUNC_RET_T)1
+
+// Abstract the function modifier placed in the beginning of the thread
+// declaration (empty for Linux)
+#define OS_THREAD_FUNC_MODIFIER
+
+#define os_mutex_init(a) pthread_mutex_init(a, NULL)
+#define os_cond_init(a) pthread_cond_init(a, NULL)
+#define os_mutex_lock pthread_mutex_lock
+#define os_mutex_unlock pthread_mutex_unlock
+#define os_cond_wait pthread_cond_wait
+#define os_cond_signal pthread_cond_signal
+
+const char event_to_string[4][14] =
+{
+ "EVENT_DONE",
+ "EVENT_WARNING",
+ "EVENT_ERROR",
+};
+
+typedef struct
+{
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint32_t preference;
+ uint32_t abort_time;
+ uint16_t back_to_back_count;
+ /* TBDJ: Is this required */
+ int32_t rotation;
+ /* TBDJ: Is this required */
+ jpeg_rectangle_t region;
+ /* TBDJ: Is this required */
+ jpegd_scale_type_t scale_factor;
+ uint32_t hw_rotation;
+
+ char* inputMjpegBuffer;
+ int inputMjpegBufferSize;
+ char* outputYptr;
+ char* outputUVptr;
+
+} test_args_t;
+
+typedef struct
+{
+ int tid;
+ pthread_t thread;
+ jpegd_obj_t decoder;
+ uint8_t decoding;
+ uint8_t decode_success;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ test_args_t *p_args;
+ jpegd_output_buf_t *p_whole_output_buf;
+
+} thread_ctrl_blk_t;
+
+OS_THREAD_FUNC_RET_T OS_THREAD_FUNC_MODIFIER decoder_test(OS_THREAD_FUNC_ARG_T p_thread_args);
+void decoder_event_handler(void *p_user_data,
+ jpeg_event_t event,
+ void *p_arg);
+int decoder_output_handler(void *p_user_data,
+ jpegd_output_buf_t *p_output_buffer,
+ uint32_t first_row_id,
+ uint8_t is_last_buffer);
+uint32_t decoder_input_req_handler(void *p_user_data,
+ jpeg_buffer_t buffer,
+ uint32_t start_offset,
+ uint32_t length);
+static void* insertHuffmanTable(void *p, int size);
+
+static int mjpegd_timer_start(timespec *p_timer);
+static int mjpegd_timer_get_elapsed(timespec *p_timer, int *elapsed_in_ms, uint8_t reset_start);
+static int mjpegd_cond_timedwait(pthread_cond_t *p_cond, pthread_mutex_t *p_mutex, uint32_t ms);
+
+// Global variables
+/* TBDJ: can be removed */
+thread_ctrl_blk_t *thread_ctrl_blks = NULL;
+
+/*
+ * This function initializes the mjpeg decoder and returns the object
+ */
+MJPEGD_ERR mjpegDecoderInit(void** mjpegd_obj)
+{
+ test_args_t* mjpegd;
+
+ ALOGD("%s: E", __func__);
+
+ mjpegd = (test_args_t *)malloc(sizeof(test_args_t));
+ if(!mjpegd)
+ return MJPEGD_INSUFFICIENT_MEM;
+
+ memset(mjpegd, 0, sizeof(test_args_t));
+
+ /* Defaults */
+ /* Due to current limitation, s/w decoder is selected always */
+ mjpegd->preference = JPEG_DECODER_PREF_HW_ACCELERATED_PREFERRED;
+ mjpegd->back_to_back_count = 1;
+ mjpegd->rotation = 0;
+ mjpegd->hw_rotation = 0;
+ mjpegd->scale_factor = (jpegd_scale_type_t)1;
+
+ /* TBDJ: can be removed */
+ mjpegd->width = 640;
+ mjpegd->height = 480;
+ mjpegd->abort_time = 0;
+
+ *mjpegd_obj = (void *)mjpegd;
+
+ ALOGD("%s: X", __func__);
+ return MJPEGD_NO_ERROR;
+}
+
+MJPEGD_ERR mjpegDecode(
+ void* mjpegd_obj,
+ char* inputMjpegBuffer,
+ int inputMjpegBufferSize,
+ char* outputYptr,
+ char* outputUVptr,
+ int outputFormat)
+{
+ int rc, c, i;
+ test_args_t* mjpegd;
+ test_args_t test_args;
+
+ ALOGD("%s: E", __func__);
+ /* store input arguments in the context */
+ mjpegd = (test_args_t*) mjpegd_obj;
+ mjpegd->inputMjpegBuffer = inputMjpegBuffer;
+ mjpegd->inputMjpegBufferSize = inputMjpegBufferSize;
+ mjpegd->outputYptr = outputYptr;
+ mjpegd->outputUVptr = outputUVptr;
+ mjpegd->format = outputFormat;
+
+ /* TBDJ: can be removed */
+ memcpy(&test_args, mjpegd, sizeof(test_args_t));
+
+ // check the formats
+ if (((test_args.format == YCRCBLP_H1V2) || (test_args.format == YCBCRLP_H1V2) ||
+ (test_args.format == YCRCBLP_H1V1) || (test_args.format == YCBCRLP_H1V1)) &&
+ !(test_args.preference == JPEG_DECODER_PREF_HW_ACCELERATED_ONLY)) {
+ ALOGE("%s:These formats are not supported by SW format %d", __func__, test_args.format);
+ return 1;
+ }
+
+ // Create thread control blocks
+ thread_ctrl_blks = (thread_ctrl_blk_t *)malloc( sizeof(thread_ctrl_blk_t));
+ if (!thread_ctrl_blks)
+ {
+ ALOGE("%s: decoder_test failed: insufficient memory in creating thread control blocks", __func__);
+ return 1;
+ }
+ memset(thread_ctrl_blks, 0, sizeof(thread_ctrl_blk_t));
+ // Initialize the blocks and kick off the threads
+ thread_ctrl_blks[i].tid = i;
+ thread_ctrl_blks[i].p_args = &test_args;
+ os_mutex_init(&thread_ctrl_blks[i].mutex);
+ os_cond_init(&thread_ctrl_blks[i].cond);
+
+ rc = (int)decoder_test(&thread_ctrl_blks[i]);
+
+ if (!rc)
+ ALOGD("%s: decoder_test finished successfully ", __func__);
+ else
+ ALOGE("%s: decoder_test failed",__func__);
+
+ ALOGD("%s: X rc: %d", __func__, rc);
+
+ return rc;
+}
+
+OS_THREAD_FUNC_RET_T OS_THREAD_FUNC_MODIFIER decoder_test(OS_THREAD_FUNC_ARG_T arg)
+{
+ int rc, i;
+ jpegd_obj_t decoder;
+ jpegd_src_t source;
+ jpegd_dst_t dest;
+ jpegd_cfg_t config;
+ jpeg_hdr_t header;
+ jpegd_output_buf_t p_output_buffers;
+ uint32_t output_buffers_count = 1; // currently only 1 buffer a time is supported
+ uint8_t use_pmem = true;
+ timespec os_timer;
+ thread_ctrl_blk_t *p_thread_arg = (thread_ctrl_blk_t *)arg;
+ test_args_t *p_args = p_thread_arg->p_args;
+ uint32_t output_width;
+ uint32_t output_height;
+ uint32_t total_time = 0;
+
+ ALOGD("%s: E", __func__);
+
+ // Determine whether pmem should be used (useful for pc environment testing where
+ // pmem is not available)
+ if ((jpegd_preference_t)p_args->preference == JPEG_DECODER_PREF_SOFTWARE_PREFERRED ||
+ (jpegd_preference_t)p_args->preference == JPEG_DECODER_PREF_SOFTWARE_ONLY) {
+ use_pmem = false;
+ }
+
+ if (((jpegd_preference_t)p_args->preference !=
+ JPEG_DECODER_PREF_HW_ACCELERATED_ONLY) &&
+ ((jpegd_preference_t)p_args->scale_factor > 0)) {
+ ALOGI("%s: Setting scale factor to 1x", __func__);
+ }
+
+ ALOGD("%s: before jpegd_init p_thread_arg: %p", __func__, p_thread_arg);
+
+ // Initialize decoder
+ rc = jpegd_init(&decoder,
+ &decoder_event_handler,
+ &decoder_output_handler,
+ p_thread_arg);
+
+ if (JPEG_FAILED(rc)) {
+ ALOGE("%s: decoder_test: jpegd_init failed", __func__);
+ goto fail;
+ }
+ p_thread_arg->decoder = decoder;
+
+ // Set source information
+ source.p_input_req_handler = &decoder_input_req_handler;
+ source.total_length = p_args->inputMjpegBufferSize & 0xffffffff;
+
+ rc = jpeg_buffer_init(&source.buffers[0]);
+ if (JPEG_SUCCEEDED(rc)) {
+ /* TBDJ: why buffer [1] */
+ rc = jpeg_buffer_init(&source.buffers[1]);
+ }
+ if (JPEG_SUCCEEDED(rc)) {
+#if 1
+ rc = jpeg_buffer_allocate(source.buffers[0], 0xA000, use_pmem);
+#else
+ rc = jpeg_buffer_use_external_buffer(source.buffers[0],
+ (uint8_t *)p_args->inputMjpegBuffer,
+ p_args->inputMjpegBufferSize,
+ 0);
+#endif
+ ALOGD("%s: source.buffers[0]:%p compressed buffer ptr = %p", __func__,
+ source.buffers[0], p_args->inputMjpegBuffer);
+ }
+ if (JPEG_SUCCEEDED(rc)) {
+#if 1
+ rc = jpeg_buffer_allocate(source.buffers[1], 0xA000, use_pmem);
+#else
+ rc = jpeg_buffer_use_external_buffer(source.buffers[1],
+ (uint8_t *)p_args->inputMjpegBuffer,
+ p_args->inputMjpegBufferSize,
+ 0);
+#endif
+ ALOGD("%s: source.buffers[1]:%p compressed buffer ptr = %p", __func__,
+ source.buffers[1], p_args->inputMjpegBuffer);
+ }
+ if (JPEG_FAILED(rc)) {
+ jpeg_buffer_destroy(&source.buffers[0]);
+ jpeg_buffer_destroy(&source.buffers[1]);
+ goto fail;
+ }
+
+ ALOGI("%s: *** Starting back-to-back decoding of %d frame(s)***\n",
+ __func__, p_args->back_to_back_count);
+
+ // Loop to perform n back-to-back decoding (to the same output file)
+ for(i = 0; i < p_args->back_to_back_count; i++) {
+ if(mjpegd_timer_start(&os_timer) < 0) {
+ ALOGE("%s: failed to get start time", __func__);
+ }
+
+ /* TBDJ: Every frame? */
+ ALOGD("%s: before jpegd_set_source source.p_arg:%p", __func__, source.p_arg);
+ rc = jpegd_set_source(decoder, &source);
+ if (JPEG_FAILED(rc))
+ {
+ ALOGE("%s: jpegd_set_source failed", __func__);
+ goto fail;
+ }
+
+ rc = jpegd_read_header(decoder, &header);
+ if (JPEG_FAILED(rc))
+ {
+ ALOGE("%s: jpegd_read_header failed", __func__);
+ goto fail;
+ }
+ p_args->width = header.main.width;
+ p_args->height = header.main.height;
+ ALOGD("%s: main dimension: (%dx%d) subsampling: (%d)", __func__,
+ header.main.width, header.main.height, (int)header.main.subsampling);
+
+ // main image decoding:
+ // Set destination information
+ dest.width = (p_args->width) ? (p_args->width) : header.main.width;
+ dest.height = (p_args->height) ? (p_args->height) : header.main.height;
+ dest.output_format = (jpeg_color_format_t) p_args->format;
+ dest.region = p_args->region;
+
+ // if region is defined, re-assign the output width/height
+ output_width = dest.width;
+ output_height = dest.height;
+
+ if (p_args->region.right || p_args->region.bottom)
+ {
+ if (0 == p_args->rotation || 180 == p_args->rotation)
+ {
+ output_width = MIN((dest.width),
+ (uint32_t)(dest.region.right - dest.region.left + 1));
+ output_height = MIN((dest.height),
+ (uint32_t)(dest.region.bottom - dest.region.top + 1));
+ }
+ // Swap output width/height for 90/270 rotation cases
+ else if (90 == p_args->rotation || 270 == p_args->rotation)
+ {
+ output_height = MIN((dest.height),
+ (uint32_t)(dest.region.right - dest.region.left + 1));
+ output_width = MIN((dest.width),
+ (uint32_t)(dest.region.bottom - dest.region.top + 1));
+ }
+ // Unsupported rotation cases
+ else
+ {
+ goto fail;
+ }
+ }
+
+ if (dest.output_format == YCRCBLP_H2V2 || dest.output_format == YCBCRLP_H2V2 ||
+ dest.output_format == YCRCBLP_H2V1 || dest.output_format == YCBCRLP_H2V1 ||
+ dest.output_format == YCRCBLP_H1V2 || dest.output_format == YCBCRLP_H1V2 ||
+ dest.output_format == YCRCBLP_H1V1 || dest.output_format == YCBCRLP_H1V1) {
+ jpeg_buffer_init(&p_output_buffers.data.yuv.luma_buf);
+ jpeg_buffer_init(&p_output_buffers.data.yuv.chroma_buf);
+ } else {
+ jpeg_buffer_init(&p_output_buffers.data.rgb.rgb_buf);
+
+ }
+
+ {
+ // Assign 0 to tile width and height
+ // to indicate that no tiling is requested.
+ p_output_buffers.tile_width = 0;
+ p_output_buffers.tile_height = 0;
+ }
+ p_output_buffers.is_in_q = 0;
+
+ switch (dest.output_format)
+ {
+ case YCRCBLP_H2V2:
+ case YCBCRLP_H2V2:
+// case YCRCBLP_H2V1:
+// case YCBCRLP_H2V1:
+// case YCRCBLP_H1V2:
+// case YCBCRLP_H1V2:
+// case YCRCBLP_H1V1:
+// case YCBCRLP_H1V1:
+ jpeg_buffer_use_external_buffer(
+ p_output_buffers.data.yuv.luma_buf,
+ (uint8_t*)p_args->outputYptr,
+ p_args->width * p_args->height * SQUARE(p_args->scale_factor),
+ 0);
+ jpeg_buffer_use_external_buffer(
+ p_output_buffers.data.yuv.chroma_buf,
+ (uint8_t*)p_args->outputUVptr,
+ p_args->width * p_args->height / 2 * SQUARE(p_args->scale_factor),
+ 0);
+ break;
+
+ default:
+ ALOGE("%s: decoder_test: unsupported output format", __func__);
+ goto fail;
+ }
+
+ // Set up configuration
+ memset(&config, 0, sizeof(jpegd_cfg_t));
+ config.preference = (jpegd_preference_t) p_args->preference;
+ config.decode_from = JPEGD_DECODE_FROM_AUTO;
+ config.rotation = p_args->rotation;
+ config.scale_factor = p_args->scale_factor;
+ config.hw_rotation = p_args->hw_rotation;
+ dest.back_to_back_count = p_args->back_to_back_count;
+
+ // Start decoding
+ p_thread_arg->decoding = true;
+
+ rc = jpegd_start(decoder, &config, &dest, &p_output_buffers, output_buffers_count);
+ dest.back_to_back_count--;
+
+ if(JPEG_FAILED(rc)) {
+ ALOGE("%s: decoder_test: jpegd_start failed (rc=%d)\n",
+ __func__, rc);
+ goto fail;
+ }
+
+ ALOGD("%s: decoder_test: jpegd_start succeeded", __func__);
+
+ // Do abort
+ if (p_args->abort_time) {
+ os_mutex_lock(&p_thread_arg->mutex);
+ while (p_thread_arg->decoding)
+ {
+ rc = mjpegd_cond_timedwait(&p_thread_arg->cond, &p_thread_arg->mutex, p_args->abort_time);
+ if (rc == JPEGERR_ETIMEDOUT)
+ {
+ // Do abort
+ os_mutex_unlock(&p_thread_arg->mutex);
+ rc = jpegd_abort(decoder);
+ if (rc)
+ {
+ ALOGE("%s: decoder_test: jpegd_abort failed: %d", __func__, rc);
+ goto fail;
+ }
+ break;
+ }
+ }
+ if (p_thread_arg->decoding)
+ os_mutex_unlock(&p_thread_arg->mutex);
+ } else {
+ // Wait until decoding is done or stopped due to error
+ os_mutex_lock(&p_thread_arg->mutex);
+ while (p_thread_arg->decoding)
+ {
+ os_cond_wait(&p_thread_arg->cond, &p_thread_arg->mutex);
+ }
+ os_mutex_unlock(&p_thread_arg->mutex);
+ }
+
+ int diff;
+ // Display the time elapsed
+ if (mjpegd_timer_get_elapsed(&os_timer, &diff, 0) < 0) {
+ ALOGE("%s: decoder_test: failed to get elapsed time", __func__);
+ } else {
+ if(p_args->abort_time) {
+ if(p_thread_arg->decoding) {
+ ALOGI("%s: decoder_test: decoding aborted successfully after %d ms", __func__, diff);
+ goto buffer_clean_up;
+ }
+ else
+ {
+ ALOGI("%s: decoder_test: decoding stopped before abort is issued. "
+ "decode time: %d ms", __func__, diff);
+ }
+ }
+ else {
+ if(p_thread_arg->decode_success) {
+ total_time += diff;
+ ALOGI("%s: decode time: %d ms (%d frame(s), total=%dms, avg=%dms/frame)",
+ __func__, diff, i+1, total_time, total_time/(i+1));
+ }
+ else
+ {
+ fprintf(stderr, "decoder_test: decode failed\n");
+ }
+ }
+ }
+ }
+
+ if(p_thread_arg->decode_success) {
+ ALOGD("%s: Frame(s) = %d, Total Time = %dms, Avg. decode time = %dms/frame)\n",
+ __func__, p_args->back_to_back_count, total_time, total_time/p_args->back_to_back_count);
+ }
+
+buffer_clean_up:
+ // Clean up decoder and allocate buffers
+ jpeg_buffer_destroy(&source.buffers[0]);
+ jpeg_buffer_destroy(&source.buffers[1]);
+ switch (dest.output_format)
+ {
+ case YCRCBLP_H2V2:
+ case YCBCRLP_H2V2:
+ case YCRCBLP_H2V1:
+ case YCBCRLP_H2V1:
+ case YCRCBLP_H1V2:
+ case YCBCRLP_H1V2:
+ case YCRCBLP_H1V1:
+ case YCBCRLP_H1V1:
+ jpeg_buffer_destroy(&p_output_buffers.data.yuv.luma_buf);
+ jpeg_buffer_destroy(&p_output_buffers.data.yuv.chroma_buf);
+ break;
+ default:
+ break;
+ }
+ jpegd_destroy(&decoder);
+
+ if (!p_thread_arg->decode_success)
+ {
+ goto fail;
+ }
+
+ ALOGD("%s: X", __func__);
+ return OS_THREAD_FUNC_RET_SUCCEEDED;
+fail:
+
+ ALOGD("%s: X", __func__);
+ return OS_THREAD_FUNC_RET_FAILED;
+}
+
+void decoder_event_handler(void *p_user_data,
+ jpeg_event_t event,
+ void *p_arg)
+{
+ thread_ctrl_blk_t *p_thread_arg = (thread_ctrl_blk_t *)p_user_data;
+
+ ALOGD("%s: E", __func__);
+
+ ALOGD("%s: Event: %s\n", __func__, event_to_string[event]);
+ if (event == JPEG_EVENT_DONE)
+ {
+ p_thread_arg->decode_success = true;
+ ALOGD("%s: decode_success: %d\n", __func__, p_thread_arg->decode_success);
+ }
+ // If it is not a warning event, decoder has stopped; Signal
+ // main thread to clean up
+ if (event != JPEG_EVENT_WARNING)
+ {
+ os_mutex_lock(&p_thread_arg->mutex);
+ p_thread_arg->decoding = false;
+ os_cond_signal(&p_thread_arg->cond);
+ os_mutex_unlock(&p_thread_arg->mutex);
+ }
+ ALOGD("%s: X", __func__);
+
+}
+
+// consumes the output buffer.
+/*TBDJ: Can be removed. Is this related to tiling */
+int decoder_output_handler(void *p_user_data,
+ jpegd_output_buf_t *p_output_buffer,
+ uint32_t first_row_id,
+ uint8_t is_last_buffer)
+{
+ uint8_t* whole_output_buf_ptr, *tiling_buf_ptr;
+
+ ALOGD("%s: E", __func__);
+
+ thread_ctrl_blk_t *p_thread_arg = (thread_ctrl_blk_t *)p_user_data;
+
+ jpeg_buffer_get_addr(p_thread_arg->p_whole_output_buf->data.rgb.rgb_buf, &whole_output_buf_ptr);
+ jpeg_buffer_get_addr(p_output_buffer->data.rgb.rgb_buf, &tiling_buf_ptr);
+
+ if (p_output_buffer->tile_height != 1)
+ return JPEGERR_EUNSUPPORTED;
+
+ // testing purpose only
+ // This is to simulate that the user needs to bail out when error happens
+ // in the middle of decoding
+ //if (first_row_id == 162)
+ // return JPEGERR_EFAILED;
+
+ // do not enqueue any buffer if it reaches the last buffer
+ if (!is_last_buffer)
+ {
+ jpegd_enqueue_output_buf(p_thread_arg->decoder, p_output_buffer, 1);
+ }
+ ALOGD("%s: X", __func__);
+
+ return JPEGERR_SUCCESS;
+}
+
+// p_reader->p_input_req_handler(p_reader->decoder,
+// p_reader->p_input_buf,
+// p_reader->next_byte_offset,
+// MAX_BYTES_TO_FETCH);
+
+uint32_t decoder_input_req_handler(void *p_user_data,
+ jpeg_buffer_t buffer,
+ uint32_t start_offset,
+ uint32_t length)
+{
+ uint32_t buf_size;
+ uint8_t *buf_ptr;
+ int bytes_to_read, bytes_read, rc;
+ thread_ctrl_blk_t *p_thread_arg = (thread_ctrl_blk_t *)p_user_data;
+ thread_ctrl_blk_t *thread_ctrl_blk = (thread_ctrl_blk_t *)p_user_data;
+ test_args_t* mjpegd = (test_args_t*) thread_ctrl_blk->p_args;
+
+ ALOGD("%s: E", __func__);
+
+ jpeg_buffer_get_max_size(buffer, &buf_size);
+ jpeg_buffer_get_addr(buffer, &buf_ptr);
+ bytes_to_read = (length < buf_size) ? length : buf_size;
+ bytes_read = 0;
+
+ ALOGD("%s: buf_ptr = %p, start_offset = %d, length = %d buf_size = %d bytes_to_read = %d", __func__, buf_ptr, start_offset, length, buf_size, bytes_to_read);
+ if (bytes_to_read)
+ {
+ /* TBDJ: Should avoid this Mem copy */
+#if 1
+ memcpy(buf_ptr, (char *)mjpegd->inputMjpegBuffer + start_offset, bytes_to_read);
+#else
+ if(JPEGERR_SUCCESS != jpeg_buffer_set_start_offset(buffer, start_offset))
+ ALOGE("%s: jpeg_buffer_set_start_offset failed", __func__);
+#endif
+ bytes_read = bytes_to_read;
+ }
+
+ ALOGD("%s: X", __func__);
+ return bytes_read;
+}
+
+static int mjpegd_timer_start(timespec *p_timer)
+{
+ if (!p_timer)
+ return JPEGERR_ENULLPTR;
+
+ if (clock_gettime(CLOCK_REALTIME, p_timer))
+ return JPEGERR_EFAILED;
+
+ return JPEGERR_SUCCESS;
+}
+
+static int mjpegd_timer_get_elapsed(timespec *p_timer, int *elapsed_in_ms, uint8_t reset_start)
+{
+ timespec now;
+ long diff;
+ int rc = mjpegd_timer_start(&now);
+
+ if (JPEG_FAILED(rc))
+ return rc;
+
+ diff = (long)(now.tv_sec - p_timer->tv_sec) * 1000;
+ diff += (long)(now.tv_nsec - p_timer->tv_nsec) / 1000000;
+ *elapsed_in_ms = (int)diff;
+
+ if (reset_start)
+ *p_timer = now;
+
+ return JPEGERR_SUCCESS;
+}
+
+int mjpegd_cond_timedwait(pthread_cond_t *p_cond, pthread_mutex_t *p_mutex, uint32_t ms)
+{
+ struct timespec ts;
+ int rc = clock_gettime(CLOCK_REALTIME, &ts);
+ if (rc < 0) return rc;
+
+ if (ms >= 1000) {
+ ts.tv_sec += (ms/1000);
+ ts.tv_nsec += ((ms%1000) * 1000000);
+ } else {
+ ts.tv_nsec += (ms * 1000000);
+ }
+
+ rc = pthread_cond_timedwait(p_cond, p_mutex, &ts);
+ if (rc == ETIMEDOUT)
+ {
+ rc = JPEGERR_ETIMEDOUT;
+ }
+ return rc;
+}
+
diff --git a/camera/usbcamcore/src/QCameraUsbParm.cpp b/camera/usbcamcore/src/QCameraUsbParm.cpp
new file mode 100755
index 0000000..fda6e9d
--- /dev/null
+++ b/camera/usbcamcore/src/QCameraUsbParm.cpp
@@ -0,0 +1,683 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#define ALOG_NDEBUG 0
+#define ALOG_NIDEBUG 0
+#define LOG_TAG "QCameraUsbParm"
+#include <utils/Log.h>
+
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <utils/String16.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <cutils/properties.h>
+#include <math.h>
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#endif
+#include <linux/ioctl.h>
+#include <camera/QCameraParameters.h>
+#include <media/mediarecorder.h>
+#include <gralloc_priv.h>
+
+#include "linux/msm_mdp.h"
+#include <linux/fb.h>
+#include <limits.h>
+
+
+extern "C" {
+#include <fcntl.h>
+#include <time.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/system_properties.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <linux/msm_ion.h>
+#include <camera.h>
+#include <cam_fifo.h>
+#include <jpege.h>
+
+} // extern "C"
+
+#include "QCameraHWI.h"
+#include "QualcommUsbCamera.h"
+#include "QCameraUsbPriv.h"
+#include "QCameraUsbParm.h"
+
+namespace android {
+
+/********************************************************************/
+static const str_map preview_formats[] = {
+ {QCameraParameters::PIXEL_FORMAT_YUV420SP, HAL_PIXEL_FORMAT_YCrCb_420_SP},
+};
+
+static const preview_format_info_t preview_format_info_list[] = {
+ {HAL_PIXEL_FORMAT_YV12, CAMERA_YUV_420_YV12, CAMERA_PAD_TO_WORD, 3}
+};
+
+static struct camera_size_type previewSizes[] = {
+ { 1920, 1088}, //1080p
+ { 1280, 720}, // 720P,
+ { 640, 480}, // VGA
+ { 512, 384},
+ { 480, 320},
+ { 320, 240}, // QVGA
+};
+
+// All fps ranges which can be supported. This list will be filtered according
+// to the min and max fps supported by hardware
+// this list must be sorted first by max_fps and then min_fps
+// fps values are multiplied by 1000
+static android::FPSRange prevFpsRanges[] = {
+ android::FPSRange(5000, 121000),
+};
+
+/* TBR: Is frame rate mode mandatory */
+static const str_map frame_rate_modes[] = {
+ {QCameraParameters::KEY_QC_PREVIEW_FRAME_RATE_AUTO_MODE, FPS_MODE_AUTO},
+ {QCameraParameters::KEY_QC_PREVIEW_FRAME_RATE_FIXED_MODE, FPS_MODE_FIXED}
+};
+
+static const str_map picture_formats[] = {
+ {QCameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
+ //{QCameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
+};
+
+static camera_size_type picture_sizes[] = {
+ { 1920, 1088}, //HD1080
+ { 1280, 720}, //HD720
+ { 640, 480}, // VGA
+ { 320, 240}, // QVGA
+};
+
+/* aspect ratio removed */
+static camera_size_type thumbnail_sizes[] = {
+ { 512, 288 }, //1.777778
+ { 480, 288 }, //1.666667
+ { 256, 154 }, //1.66233
+ { 432, 288 }, //1.5
+ { 512, 384 }, //1.333333
+ { 352, 288 }, //1.222222
+ { 320, 240 }, //1.33333
+ { 176, 144 }, //1.222222
+};
+
+static const str_map recording_Hints[] = {
+ {"false", FALSE},
+ {"true", TRUE}
+};
+
+/* Static functions list */
+static String8 create_sizes_str(const camera_size_type *sizes, int len);
+static String8 create_values_str(const str_map *values, int len);
+static String8 create_fps_str(const android:: FPSRange* fps, int len);
+static String8 create_values_range_str(int min, int max);
+static int usbCamSetPrvwSize( camera_hardware_t *camHal,
+ const QCameraParameters& params);
+static int usbCamSetPictSize( camera_hardware_t *camHal,
+ const QCameraParameters& params);
+static int usbCamSetThumbnailSize( camera_hardware_t *camHal,
+ const QCameraParameters& params);
+static int usbCamSetJpegQlty( camera_hardware_t *camHal,
+ const QCameraParameters& params);
+
+/******************************************************************************
+ * Function: usbCamInitDefaultParameters
+ * Description: This function sets default parameters to camera HAL context
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * None
+ *
+ * Notes: none
+ *****************************************************************************/
+int usbCamInitDefaultParameters(camera_hardware_t *camHal)
+{
+ ALOGD("%s: E", __func__);
+ int rc = 0;
+ char tempStr[FILENAME_LENGTH];
+
+ /* Default initializations */
+ camHal->prevFormat = DEFAULT_USBCAM_PRVW_FMT;
+ camHal->prevWidth = DEFAULT_USBCAM_PRVW_WD;
+ camHal->prevHeight = DEFAULT_USBCAM_PRVW_HT;
+ camHal->dispFormat = camHal->prevFormat;
+ camHal->dispWidth = camHal->prevWidth;
+ camHal->dispHeight = camHal->prevHeight;
+ camHal->pictFormat = DEFAULT_USBCAM_PICT_FMT;
+ camHal->pictWidth = DEFAULT_USBCAM_PICT_WD;
+ camHal->pictHeight = DEFAULT_USBCAM_PICT_HT;
+ camHal->pictJpegQlty = DEFAULT_USBCAM_PICT_QLTY;
+ camHal->thumbnailWidth = DEFAULT_USBCAM_THUMBNAIL_WD;
+ camHal->thumbnailHeight = DEFAULT_USBCAM_THUMBNAIL_HT;
+ camHal->thumbnailJpegQlty = DEFAULT_USBCAM_THUMBNAIL_QLTY;
+ camHal->previewEnabledFlag = 0;
+ camHal->prvwStoppedForPicture = 0;
+ camHal->prvwCmdPending = 0;
+ camHal->takePictInProgress = 0;
+
+ //Set picture size values
+ camHal->pictSizeValues = create_sizes_str(
+ picture_sizes, sizeof(picture_sizes) / sizeof(camera_size_type));
+ camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ camHal->pictSizeValues.string());
+ camHal->qCamParams.setPictureSize(camHal->pictWidth, camHal->pictHeight);
+
+ //Set picture format
+ camHal->pictFormatValues = create_values_str(
+ picture_formats, sizeof(picture_formats) / sizeof(str_map));
+ camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
+ camHal->pictFormatValues.string());
+ if(PICTURE_FORMAT_JPEG == camHal->pictFormat)
+ camHal->qCamParams.setPictureFormat(QCameraParameters::PIXEL_FORMAT_JPEG);
+
+ //Set picture quality
+ sprintf(tempStr, "%d", camHal->pictJpegQlty);
+ camHal->qCamParams.set(QCameraParameters::KEY_JPEG_QUALITY, tempStr);
+
+ //Set Thumbnail size
+ camHal->thumbnailSizeValues = create_sizes_str(
+ thumbnail_sizes, sizeof(thumbnail_sizes) /sizeof(camera_size_type));
+ camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ camHal->thumbnailSizeValues.string());
+ sprintf(tempStr, "%d", camHal->thumbnailWidth);
+ camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
+ tempStr);
+ sprintf(tempStr, "%d", camHal->thumbnailHeight);
+ camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
+ tempStr);
+
+ //Set Thumbnail quality
+ sprintf(tempStr, "%d", camHal->thumbnailJpegQlty);
+ camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY,
+ tempStr);
+
+ //Set Preview Format
+ camHal->prevFormatValues = create_values_str(
+ preview_formats, sizeof(preview_formats) / sizeof(str_map));
+ camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
+ camHal->prevFormatValues.string());
+ if(HAL_PIXEL_FORMAT_YCrCb_420_SP == camHal->prevFormat)
+ camHal->qCamParams.setPreviewFormat(QCameraParameters::PIXEL_FORMAT_YUV420SP);
+
+ //Set Preview size
+ camHal->prevSizeValues = create_sizes_str(
+ previewSizes, sizeof(previewSizes) / sizeof(camera_size_type));
+ camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ camHal->prevSizeValues.string());
+ camHal->qCamParams.setPreviewSize(camHal->prevWidth, camHal->prevHeight);
+
+ //Set Preivew fps range
+ camHal->prevFpsRangesValues = create_fps_str(
+ prevFpsRanges, sizeof(prevFpsRanges) / sizeof(android::FPSRange));
+
+ camHal->qCamParams.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
+ camHal->prevFpsRangesValues);
+ camHal->qCamParams.setPreviewFpsRange(MIN_PREV_FPS, MAX_PREV_FPS);
+
+ ALOGD("%s: X", __func__);
+
+ return rc;
+} /* usbCamInitDefaultParameters */
+
+/******************************************************************************
+ * Function: usbCamSetParameters
+ * Description: This function parses the parameter string and stores the
+ * parameters in the camera HAL handle
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * params - pointer to parameter string
+ *
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+int usbCamSetParameters(camera_hardware_t *camHal, const char *params)
+{
+ int rc = 0;
+ String8 str = String8(params);
+ QCameraParameters qParam;
+
+ ALOGD("%s: E", __func__);
+
+ if(params)
+ PRINT_PARAM_STR(params);
+
+ qParam.unflatten(str);
+
+ if(usbCamSetPrvwSize(camHal, qParam))
+ rc = -1;
+ if(usbCamSetPictSize(camHal, qParam))
+ rc = -1;
+ if(usbCamSetThumbnailSize(camHal, qParam))
+ rc = -1;
+ if(usbCamSetJpegQlty(camHal, qParam))
+ rc = -1;
+
+ ALOGD("%s: X", __func__);
+ return rc;
+} /* usbCamSetParameters */
+
+/******************************************************************************
+ * Function: usbCamGetParameters
+ * Description: This function allocates memory for parameter string,
+ * composes and returns the parameter string
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * Address to the parameter string
+ *
+ * Notes: none
+ *****************************************************************************/
+char* usbCamGetParameters(camera_hardware_t *camHal)
+{
+ ALOGD("%s: E", __func__);
+ char *parms = NULL;
+ char* rc = NULL;
+ String8 str;
+
+ QCameraParameters qParam = camHal->qCamParams;
+ //qParam.dump();
+ str = qParam.flatten( );
+ rc = (char *)malloc(sizeof(char)*(str.length()+1));
+ if(rc != NULL){
+ memset(rc, 0, sizeof(char)*(str.length()+1));
+ strncpy(rc, str.string(), str.length());
+ rc[str.length()] = 0;
+ parms = rc;
+ }
+
+ PRINT_PARAM_STR(parms);
+
+ ALOGD("%s: X", __func__);
+ return (parms);
+} /* usbCamGetParameters */
+
+/******************************************************************************
+ * Function: usbCamPutParameters
+ * Description: This function frees the memory allocated for parameter string
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * parms - Parameter string
+ *
+ * Return values:
+ * None
+ *
+ * Notes: none
+ *****************************************************************************/
+void usbCamPutParameters(camera_hardware_t *camHal, char *parms)
+{
+ ALOGD("%s: E", __func__);
+ if(parms)
+ free(parms);
+ parms = NULL;
+ ALOGD("%s: X", __func__);
+} /* usbCamPutParameters */
+
+/******************************************************************************
+ * Function: create_sizes_str
+ * Description: This function loops through /dev/video entries and probes with
+ * UVCIOC query. If the device responds to the query, then it is
+ * detected as UVC webcam
+ * Input parameters:
+ * devname - String pointer. The function return dev entry
+ * name in this string
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+static String8 create_sizes_str(const camera_size_type *sizes, int len) {
+ String8 str;
+ char buffer[32];
+
+ if (len > 0) {
+ snprintf(buffer, sizeof(buffer), "%dx%d", sizes[0].width, sizes[0].height);
+ str.append(buffer);
+ }
+ for (int i = 1; i < len; i++) {
+ snprintf(buffer, sizeof(buffer), ",%dx%d", sizes[i].width, sizes[i].height);
+ str.append(buffer);
+ }
+ return str;
+}
+
+/******************************************************************************
+ * Function: create_values_str
+ * Description: This function loops through /dev/video entries and probes with
+ * UVCIOC query. If the device responds to the query, then it is
+ * detected as UVC webcam
+ * Input parameters:
+ * devname - String pointer. The function return dev entry
+ * name in this string
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+static String8 create_values_str(const str_map *values, int len) {
+ String8 str;
+
+ if (len > 0) {
+ str.append(values[0].desc);
+ }
+ for (int i = 1; i < len; i++) {
+ str.append(",");
+ str.append(values[i].desc);
+ }
+ return str;
+}
+
+/******************************************************************************
+ * Function: create_fps_str
+ * Description: This function loops through /dev/video entries and probes with
+ * UVCIOC query. If the device responds to the query, then it is
+ * detected as UVC webcam
+ * Input parameters:
+ * devname - String pointer. The function return dev entry
+ * name in this string
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+static String8 create_fps_str(const android:: FPSRange* fps, int len) {
+ String8 str;
+ char buffer[32];
+
+ if (len > 0) {
+ snprintf(buffer, sizeof(buffer), "(%d,%d)", fps[0].minFPS, fps[0].maxFPS);
+ str.append(buffer);
+ }
+ for (int i = 1; i < len; i++) {
+ snprintf(buffer, sizeof(buffer), ",(%d,%d)", fps[i].minFPS, fps[i].maxFPS);
+ str.append(buffer);
+ }
+ return str;
+}
+
+/******************************************************************************
+ * Function: create_values_range_str
+ * Description: This function loops through /dev/video entries and probes with
+ * UVCIOC query. If the device responds to the query, then it is
+ * detected as UVC webcam
+ * Input parameters:
+ * devname - String pointer. The function return dev entry
+ * name in this string
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+static String8 create_values_range_str(int min, int max){
+ String8 str;
+ char buffer[32];
+
+ if(min <= max){
+ snprintf(buffer, sizeof(buffer), "%d", min);
+ str.append(buffer);
+
+ for (int i = min + 1; i <= max; i++) {
+ snprintf(buffer, sizeof(buffer), ",%d", i);
+ str.append(buffer);
+ }
+ }
+ return str;
+}
+
+/******************************************************************************
+ * Function: usbCamSetPrvwSize
+ * Description: This function parses preview width and height from the input
+ * parameters and stores into the context
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * params - QCameraParameters reference
+ *
+ * Return values:
+ * 0 If parameters are valid
+ * -1 If parameters are invalid
+ *
+ * Notes: none
+ *****************************************************************************/
+static int usbCamSetPrvwSize( camera_hardware_t *camHal,
+ const QCameraParameters& params)
+{
+ int rc = 0, width, height, i, numPrvwSizes, validSize;
+ ALOGD("%s: E", __func__);
+
+ params.getPreviewSize(&width, &height);
+ ALOGI("%s: Requested preview size %d x %d", __func__, width, height);
+
+ // Validate the preview size
+ numPrvwSizes = sizeof(previewSizes) / sizeof(camera_size_type);
+ for (i = 0, validSize = 0; i < numPrvwSizes; i++) {
+ if (width == previewSizes[i].width
+ && height == previewSizes[i].height) {
+ validSize = 1;
+
+ camHal->qCamParams.setPreviewSize(width, height);
+ ALOGD("%s: setPreviewSize: width: %d height: %d",
+ __func__, width, height);
+
+ camHal->prevWidth = width;
+ camHal->prevHeight = height;
+ camHal->dispWidth = width;
+ camHal->dispHeight = height;
+
+ /* TBD: restrict pictures size and video to preview size */
+ }
+ }
+ if(!validSize)
+ ALOGE("%s: Invalid preview size %dx%d requested", __func__,
+ width, height);
+
+ rc = (validSize == 0)? -1:0;
+ ALOGD("%s: X", __func__);
+
+ return rc;
+} /* usbCamSetPrvwSize */
+
+/******************************************************************************
+ * Function: usbCamSetPictSize
+ * Description: This function parses picture width and height from the input
+ * parameters and stores into the context
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * params - QCameraParameters reference
+ *
+ * Return values:
+ * 0 If parameters are valid
+ * -1 If parameters are invalid
+ *
+ * Notes: none
+ *****************************************************************************/
+static int usbCamSetPictSize( camera_hardware_t *camHal,
+ const QCameraParameters& params)
+{
+ int rc = 0, width, height, i, numPictSizes, validSize;
+ ALOGD("%s: E", __func__);
+
+ /* parse for picture width and height */
+ params.getPictureSize(&width, &height);
+ ALOGI("%s: Requested picture size %d x %d", __func__, width, height);
+
+ // Validate the picture size
+ numPictSizes = sizeof(picture_sizes) / sizeof(camera_size_type);
+ for (i = 0, validSize = 0; i < numPictSizes; i++) {
+ if (width == picture_sizes[i].width
+ && height == picture_sizes[i].height) {
+ validSize = 1;
+
+ camHal->qCamParams.setPictureSize(width, height);
+ ALOGD("%s: setPictureSize: width: %d height: %d",
+ __func__, width, height);
+
+ /* TBD: If new pictSize is different from old size, restart prvw */
+ camHal->pictWidth = width;
+ camHal->pictHeight = height;
+ }
+ }
+ if(!validSize)
+ ALOGE("%s: Invalid picture size %dx%d requested", __func__,
+ width, height);
+ rc = (validSize == 0)? -1:0;
+ ALOGD("%s: X", __func__);
+
+ return rc;
+} /* usbCamSetPictSize */
+
+/******************************************************************************
+ * Function: usbCamSetThumbnailSize
+ * Description: This function parses picture width and height from the input
+ * parameters and stores into the context
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * params - QCameraParameters reference
+ *
+ * Return values:
+ * 0 If parameters are valid
+ * -1 If parameters are invalid
+ *
+ * Notes: none
+ *****************************************************************************/
+static int usbCamSetThumbnailSize( camera_hardware_t *camHal,
+ const QCameraParameters& params)
+{
+ int rc = 0, width, height, i, numThumbnailSizes, validSize;
+ char tempStr[FILENAME_LENGTH];
+ ALOGD("%s: E", __func__);
+
+ /* parse for thumbnail width and height */
+ width = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ height = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ ALOGI("%s: Requested thumbnail size %d x %d", __func__, width, height);
+
+ // Validate the thumbnail size
+ numThumbnailSizes = sizeof(thumbnail_sizes) / sizeof(camera_size_type);
+ for (i = 0, validSize = 0; i < numThumbnailSizes; i++) {
+ if (width == thumbnail_sizes[i].width
+ && height == thumbnail_sizes[i].height) {
+ validSize = 1;
+
+ camHal->thumbnailWidth = width;
+ camHal->thumbnailHeight = height;
+ sprintf(tempStr, "%d", camHal->thumbnailWidth);
+ camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
+ width);
+ sprintf(tempStr, "%d", camHal->thumbnailHeight);
+ camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
+ height);
+
+ }
+ }
+ if(!validSize)
+ ALOGE("%s: Invalid picture size %dx%d requested", __func__,
+ width, height);
+ rc = (validSize == 0)? -1:0;
+ ALOGD("%s: X", __func__);
+
+ return rc;
+} /* usbCamSetThumbnailSize */
+
+/******************************************************************************
+ * Function: usbCamSetJpegQlty
+ * Description: This function parses picture and thumbnail JPEG quality and
+ * validates before storing in the context
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * params - QCameraParameters reference
+ *
+ * Return values:
+ * 0 If parameters are valid
+ * -1 If parameters are invalid
+ *
+ * Notes: none
+ *****************************************************************************/
+static int usbCamSetJpegQlty( camera_hardware_t *camHal,
+ const QCameraParameters& params)
+{
+ int rc = 0, quality = 0;
+ char tempStr[FILENAME_LENGTH];
+ ALOGD("%s: E", __func__);
+
+ /**/
+ quality = params.getInt(QCameraParameters::KEY_JPEG_QUALITY);
+ ALOGI("%s: Requested picture qlty %d", __func__, quality);
+
+ if (quality >= 0 && quality <= 100) {
+ camHal->pictJpegQlty = quality;
+ sprintf(tempStr, "%d", camHal->pictJpegQlty);
+ camHal->qCamParams.set(QCameraParameters::KEY_JPEG_QUALITY, quality);
+ } else {
+ ALOGE("Invalid jpeg quality=%d", quality);
+ rc = -1;
+ }
+
+ quality = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ ALOGI("%s: Requested thumbnail qlty %d", __func__, quality);
+
+ if (quality >= 0 && quality <= 100) {
+ camHal->thumbnailJpegQlty = quality;
+ sprintf(tempStr, "%d", camHal->thumbnailJpegQlty);
+ camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY,
+ tempStr);
+ } else {
+ ALOGE("Invalid jpeg thumbnail quality=%d", quality);
+ rc = -1;
+ }
+
+ ALOGD("%s: X rc:%d", __func__, rc);
+
+ return rc;
+}
+
+}; /*namespace android */
diff --git a/camera/usbcamcore/src/QualcommUsbCamera.cpp b/camera/usbcamcore/src/QualcommUsbCamera.cpp
new file mode 100755
index 0000000..b274626
--- /dev/null
+++ b/camera/usbcamcore/src/QualcommUsbCamera.cpp
@@ -0,0 +1,2963 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+ /*#error uncomment this for compiler test!*/
+//#define ALOG_NDEBUG 0
+#define ALOG_NIDEBUG 0
+#define LOG_TAG "QualcommUsbCamera"
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <pthread.h>
+#include <linux/uvcvideo.h>
+
+#include "QCameraHAL.h"
+#include "QualcommUsbCamera.h"
+#include "QCameraUsbPriv.h"
+#include "QCameraMjpegDecode.h"
+#include "QCameraUsbParm.h"
+#include <gralloc_priv.h>
+#include <genlock.h>
+
+extern "C" {
+#include <sys/time.h>
+}
+
+camera_device_ops_t usbcam_camera_ops = {
+ set_preview_window: android::usbcam_set_preview_window,
+ set_callbacks: android::usbcam_set_CallBacks,
+ enable_msg_type: android::usbcam_enable_msg_type,
+ disable_msg_type: android::usbcam_disable_msg_type,
+ msg_type_enabled: android::usbcam_msg_type_enabled,
+
+ start_preview: android::usbcam_start_preview,
+ stop_preview: android::usbcam_stop_preview,
+ preview_enabled: android::usbcam_preview_enabled,
+ store_meta_data_in_buffers: android::usbcam_store_meta_data_in_buffers,
+
+ start_recording: android::usbcam_start_recording,
+ stop_recording: android::usbcam_stop_recording,
+ recording_enabled: android::usbcam_recording_enabled,
+ release_recording_frame: android::usbcam_release_recording_frame,
+
+ auto_focus: android::usbcam_auto_focus,
+ cancel_auto_focus: android::usbcam_cancel_auto_focus,
+
+ take_picture: android::usbcam_take_picture,
+ cancel_picture: android::usbcam_cancel_picture,
+
+ set_parameters: android::usbcam_set_parameters,
+ get_parameters: android::usbcam_get_parameters,
+ put_parameters: android::usbcam_put_parameters,
+ send_command: android::usbcam_send_command,
+
+ release: android::usbcam_release,
+ dump: android::usbcam_dump,
+};
+
+#define CAPTURE 1
+#define DISPLAY 1
+#define CALL_BACK 1
+#define MEMSET 0
+#define FREAD_JPEG_PICTURE 0
+#define JPEG_ON_USB_CAMERA 1
+#define FILE_DUMP_CAMERA 0
+#define FILE_DUMP_B4_DISP 0
+
+namespace android {
+
+static int initUsbCamera( camera_hardware_t *camHal,
+ int width, int height,
+ int pixelFormat);
+static int startUsbCamCapture( camera_hardware_t *camHal);
+static int stopUsbCamCapture( camera_hardware_t *camHal);
+static int initV4L2mmap( camera_hardware_t *camHal);
+static int unInitV4L2mmap( camera_hardware_t *camHal);
+static int launch_preview_thread( camera_hardware_t *camHal);
+static int launchTakePictureThread( camera_hardware_t *camHal);
+static int initDisplayBuffers( camera_hardware_t *camHal);
+static int deInitDisplayBuffers( camera_hardware_t *camHal);
+static int stopPreviewInternal( camera_hardware_t *camHal);
+static int get_buf_from_cam( camera_hardware_t *camHal);
+static int put_buf_to_cam( camera_hardware_t *camHal);
+static int prvwThreadTakePictureInternal(camera_hardware_t *camHal);
+static int get_buf_from_display( camera_hardware_t *camHal, int *buffer_id);
+static int put_buf_to_display( camera_hardware_t *camHal, int buffer_id);
+static int convert_data_frm_cam_to_disp(camera_hardware_t *camHal, int buffer_id);
+static void * previewloop(void *);
+static void * takePictureThread(void *);
+static int convert_YUYV_to_420_NV12(char *in_buf, char *out_buf, int wd, int ht);
+static int get_uvc_device(char *devname);
+static int getPreviewCaptureFmt(camera_hardware_t *camHal);
+static int allocate_ion_memory(QCameraHalMemInfo_t *mem_info, int ion_type);
+static int deallocate_ion_memory(QCameraHalMemInfo_t *mem_info);
+static int ioctlLoop(int fd, int ioctlCmd, void *args);
+static int readFromFile(char* fileName, char* buffer, int bufferSize);
+static int fileDump(const char* fileName, char* data, int length, int* frm_cnt);
+static int encodeJpeg( camera_hardware_t *camHal);
+void jpegEncodeCb (jpeg_job_status_t status,
+ uint8_t thumbnailDroppedFlag,
+ uint32_t client_hdl,
+ uint32_t jobId,
+ uint8_t* out_data,
+ uint32_t data_size,
+ void *userData);
+
+/* HAL function implementation goes here*/
+
+/**
+ * The functions need to be provided by the camera HAL.
+ *
+ * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo()
+ * and openCameraHardware() is 0 to N-1.
+ */
+
+extern "C" int usbcam_get_number_of_cameras()
+{
+ /* TBR: This is hardcoded currently to 1 USB camera */
+ int numCameras = 1;
+ ALOGI("%s: E", __func__);
+ ALOGI("%s: X", __func__);
+
+ return numCameras;
+}
+
+extern "C" int usbcam_get_camera_info(int camera_id, struct camera_info *info)
+{
+ int rc = -1;
+ ALOGI("%s: E", __func__);
+
+ /* TBR: This info is hardcoded currently irrespective of camera_id */
+ if(info) {
+ struct CameraInfo camInfo;
+ memset(&camInfo, -1, sizeof (struct CameraInfo));
+
+ info->facing = CAMERA_FACING_FRONT;//CAMERA_FACING_BACK;
+ info->orientation = 0;
+ rc = 0;
+ }
+ ALOGI("%s: X", __func__);
+ return rc;
+}
+
+/* HAL should return NULL handle if it fails to open camera hardware. */
+extern "C" int usbcam_camera_device_open(
+ const struct hw_module_t* module, const char* id,
+ struct hw_device_t** hw_device)
+{
+ int rc = -1;
+ camera_device *device = NULL;
+ camera_hardware_t *camHal;
+ char *dev_name;
+
+ ALOGI("%s: E", __func__);
+
+ /* initialize return handle value to NULL */
+ *hw_device = NULL;
+
+ camHal = new camera_hardware_t();
+ if(!camHal) {
+
+ ALOGE("%s: end in no mem", __func__);
+ return -1;
+ }
+
+ rc = usbCamInitDefaultParameters(camHal);
+ if(0 != rc)
+ {
+ ALOGE("%s: usbCamInitDefaultParameters error", __func__);
+ return rc;
+ }
+#if CAPTURE
+
+ dev_name = camHal->dev_name;
+
+ rc = get_uvc_device(dev_name);
+ if(rc || *dev_name == '\0'){
+ ALOGE("%s: No UVC node found \n", __func__);
+ return -1;
+ }
+
+ camHal->fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
+
+ if (camHal->fd < 0) {
+ ALOGE("%s: Cannot open '%s'", __func__, dev_name);
+ free(camHal);
+ rc = -1;
+ }else{
+ rc = 0;
+ }
+
+#else /* CAPTURE */
+ rc = 0;
+#endif /* CAPTURE */
+
+ device = &camHal->hw_dev;
+ device->common.close = usbcam_close_camera_device;
+ device->ops = &usbcam_camera_ops;
+ device->priv = (void *)camHal;
+ *hw_device = &(device->common);
+
+ ALOGD("%s: camHal: %p", __func__, camHal);
+ ALOGI("%s: X %d", __func__, rc);
+
+ return rc;
+}
+
+extern "C" int usbcam_close_camera_device( hw_device_t *hw_dev)
+{
+ ALOGI("%s: device =%p E", __func__, hw_dev);
+ int rc = -1;
+ camera_device_t *device = (camera_device_t *)hw_dev;
+
+ if(device) {
+ camera_hardware_t *camHal = (camera_hardware_t *)device->priv;
+ if(camHal) {
+ rc = close(camHal->fd);
+ if(rc < 0) {
+ ALOGE("%s: close failed ", __func__);
+ }
+ camHal->fd = 0;
+ delete camHal;
+ }else{
+ ALOGE("%s: camHal is NULL pointer ", __func__);
+ }
+ }
+ ALOGI("%s: X device =%p, rc = %d", __func__, hw_dev, rc);
+ return rc;
+}
+
+int usbcam_set_preview_window(struct camera_device * device,
+ struct preview_stream_ops *window)
+{
+ ALOGI("%s: E", __func__);
+ int rc = 0;
+ camera_hardware_t *camHal;
+
+ VALIDATE_DEVICE_HDL(camHal, device, -1);
+ Mutex::Autolock autoLock(camHal->lock);
+
+ /* if window is already set, then de-init previous buffers */
+ if(camHal->window){
+ rc = deInitDisplayBuffers(camHal);
+ if(rc < 0) {
+ ALOGE("%s: deInitDisplayBuffers returned error", __func__);
+ }
+ }
+ camHal->window = window;
+
+ if(camHal->window){
+ rc = initDisplayBuffers(camHal);
+ if(rc < 0) {
+ ALOGE("%s: initDisplayBuffers returned error", __func__);
+ }
+ }
+ ALOGI("%s: X. rc = %d", __func__, rc);
+ return rc;
+}
+
+void usbcam_set_CallBacks(struct camera_device * device,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user)
+{
+ ALOGI("%s: E", __func__);
+ camera_hardware_t *camHal;
+
+ if(device && device->priv){
+ camHal = (camera_hardware_t *)device->priv;
+ }else{
+ ALOGE("%s: Null device or device->priv", __func__);
+ return;
+ }
+
+ Mutex::Autolock autoLock(camHal->lock);
+
+ camHal->notify_cb = notify_cb;
+ camHal->data_cb = data_cb;
+ camHal->data_cb_timestamp = data_cb_timestamp;
+ camHal->get_memory = get_memory;
+ camHal->cb_ctxt = user;
+
+ ALOGI("%s: X", __func__);
+}
+
+void usbcam_enable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ ALOGI("%s: E", __func__);
+ ALOGI("%s: msg_type: %d", __func__, msg_type);
+
+ camera_hardware_t *camHal;
+
+ if(device && device->priv){
+ camHal = (camera_hardware_t *)device->priv;
+ }else{
+ ALOGE("%s: Null device or device->priv", __func__);
+ return;
+ }
+
+ Mutex::Autolock autoLock(camHal->lock);
+
+ camHal->msgEnabledFlag |= msg_type;
+
+ ALOGI("%s: X", __func__);
+}
+
+void usbcam_disable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ ALOGI("%s: E", __func__);
+ ALOGI("%s: msg_type: %d", __func__, msg_type);
+
+ camera_hardware_t *camHal;
+ if(device && device->priv){
+ camHal = (camera_hardware_t *)device->priv;
+ }else{
+ ALOGE("%s: Null device or device->priv", __func__);
+ return;
+ }
+
+ Mutex::Autolock autoLock(camHal->lock);
+
+ camHal->msgEnabledFlag &= ~msg_type;
+
+ ALOGI("%s: X", __func__);
+}
+
+int usbcam_msg_type_enabled(struct camera_device * device, int32_t msg_type)
+{
+ ALOGI("%s: E", __func__);
+
+ camera_hardware_t *camHal;
+ if(device && device->priv){
+ camHal = (camera_hardware_t *)device->priv;
+ }else{
+ ALOGE("%s: Null device or device->priv", __func__);
+ return -1;
+ }
+
+ Mutex::Autolock autoLock(camHal->lock);
+
+ ALOGI("%s: X", __func__);
+ return (camHal->msgEnabledFlag & msg_type);
+}
+
+int usbcam_start_preview(struct camera_device * device)
+{
+ ALOGI("%s: E", __func__);
+
+ int rc = -1;
+ camera_hardware_t *camHal = NULL;
+
+ VALIDATE_DEVICE_HDL(camHal, device, -1);
+ Mutex::Autolock autoLock(camHal->lock);
+
+ /* If preivew is already running, nothing to be done */
+ if(camHal->previewEnabledFlag){
+ ALOGI("%s: Preview is already running", __func__);
+ return 0;
+ }
+
+#if CAPTURE
+ rc = initUsbCamera(camHal, camHal->prevWidth,
+ camHal->prevHeight, getPreviewCaptureFmt(camHal));
+ if(rc < 0) {
+ ALOGE("%s: Failed to intialize the device", __func__);
+ }else{
+ rc = startUsbCamCapture(camHal);
+ if(rc < 0) {
+ ALOGE("%s: Failed to startUsbCamCapture", __func__);
+ }else{
+ rc = launch_preview_thread(camHal);
+ if(rc < 0) {
+ ALOGE("%s: Failed to launch_preview_thread", __func__);
+ }
+ }
+ }
+#else /* CAPTURE */
+ rc = launch_preview_thread(camHal);
+ if(rc < 0) {
+ ALOGE("%s: Failed to launch_preview_thread", __func__);
+ }
+#endif /* CAPTURE */
+ /* if no errors, then set the flag */
+ if(!rc)
+ camHal->previewEnabledFlag = 1;
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+void usbcam_stop_preview(struct camera_device * device)
+{
+ ALOGD("%s: E", __func__);
+
+ int rc = 0;
+ camera_hardware_t *camHal;
+
+ if(device && device->priv){
+ camHal = (camera_hardware_t *)device->priv;
+ }else{
+ ALOGE("%s: Null device or device->priv", __func__);
+ return;
+ }
+
+ Mutex::Autolock autoLock(camHal->lock);
+
+ rc = stopPreviewInternal(camHal);
+ if(rc)
+ ALOGE("%s: stopPreviewInternal returned error", __func__);
+
+ ALOGI("%s: X", __func__);
+ return;
+}
+
+/* This function is equivalent to is_preview_enabled */
+int usbcam_preview_enabled(struct camera_device * device)
+{
+ ALOGI("%s: E", __func__);
+ camera_hardware_t *camHal;
+
+ if(device && device->priv){
+ camHal = (camera_hardware_t *)device->priv;
+ }else{
+ ALOGE("%s: Null device or device->priv", __func__);
+ return -1;
+ }
+ Mutex::Autolock autoLock(camHal->lock);
+
+ ALOGI("%s: X", __func__);
+ return camHal->previewEnabledFlag;
+}
+
+/* TBD */
+int usbcam_store_meta_data_in_buffers(struct camera_device * device, int enable)
+{
+ ALOGI("%s: E", __func__);
+ int rc = 0;
+
+ ALOGI("%s: X", __func__);
+ return rc;
+}
+
+/* TBD */
+int usbcam_start_recording(struct camera_device * device)
+{
+ int rc = 0;
+ ALOGD("%s: E", __func__);
+
+ ALOGD("%s: X", __func__);
+
+ return rc;
+}
+
+/* TBD */
+void usbcam_stop_recording(struct camera_device * device)
+{
+ ALOGD("%s: E", __func__);
+
+ ALOGD("%s: X", __func__);
+}
+
+/* TBD */
+int usbcam_recording_enabled(struct camera_device * device)
+{
+ int rc = 0;
+ ALOGD("%s: E", __func__);
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/* TBD */
+void usbcam_release_recording_frame(struct camera_device * device,
+ const void *opaque)
+{
+ ALOGV("%s: E", __func__);
+
+ ALOGD("%s: X", __func__);
+}
+
+/* TBD */
+int usbcam_auto_focus(struct camera_device * device)
+{
+ ALOGD("%s: E", __func__);
+ int rc = 0;
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/* TBD */
+int usbcam_cancel_auto_focus(struct camera_device * device)
+{
+ int rc = 0;
+ ALOGD("%s: E", __func__);
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+int usbcam_take_picture(struct camera_device * device)
+{
+ ALOGI("%s: E", __func__);
+ int rc = 0;
+ camera_hardware_t *camHal;
+
+ VALIDATE_DEVICE_HDL(camHal, device, -1);
+
+ Mutex::Autolock autoLock(camHal->lock);
+
+ /* If take picture is already in progress, nothing t be done */
+ if(camHal->takePictInProgress){
+ ALOGI("%s: Take picture already in progress", __func__);
+ return 0;
+ }
+
+ if(camHal->previewEnabledFlag)
+ {
+ rc = stopPreviewInternal(camHal);
+ if(rc){
+ ALOGE("%s: stopPreviewInternal returned error", __func__);
+ }
+ USB_CAM_CLOSE(camHal);
+ camHal->prvwStoppedForPicture = 1;
+ }
+ /* TBD: Need to handle any dependencies on video recording state */
+ rc = launchTakePictureThread(camHal);
+ if(rc)
+ ALOGE("%s: launchTakePictureThread error", __func__);
+
+#if 0
+ /* This implementation requests preview thread to take picture */
+ if(camHal->previewEnabledFlag)
+ {
+ camHal->prvwCmdPending++;
+ camHal->prvwCmd = USB_CAM_PREVIEW_TAKEPIC;
+ ALOGD("%s: Take picture command set ", __func__);
+ }else{
+ ALOGE("%s: Take picture without preview started!", __func__);
+ rc = -1;
+ }
+#endif
+
+ if(!rc)
+ camHal->takePictInProgress = 1;
+
+ ALOGI("%s: X", __func__);
+ return rc;
+}
+
+/* TBD */
+int usbcam_cancel_picture(struct camera_device * device)
+
+{
+ ALOGI("%s: E", __func__);
+ int rc = 0;
+
+ ALOGI("%s: X", __func__);
+ return rc;
+}
+
+int usbcam_set_parameters(struct camera_device * device, const char *params)
+
+{
+ ALOGI("%s: E", __func__);
+ int rc = 0;
+ camera_hardware_t *camHal;
+
+ VALIDATE_DEVICE_HDL(camHal, device, -1);
+
+ Mutex::Autolock autoLock(camHal->lock);
+
+ rc = usbCamSetParameters(camHal, params);
+
+ ALOGI("%s: X", __func__);
+ return rc;
+}
+
+char* usbcam_get_parameters(struct camera_device * device)
+{
+ char *parms;
+ ALOGI("%s: E", __func__);
+
+ camera_hardware_t *camHal;
+ VALIDATE_DEVICE_HDL(camHal, device, NULL);
+
+ Mutex::Autolock autoLock(camHal->lock);
+
+ parms = usbCamGetParameters(camHal);
+
+ ALOGI("%s: X", __func__);
+ return parms;
+}
+
+void usbcam_put_parameters(struct camera_device * device, char *parm)
+
+{
+ ALOGI("%s: E", __func__);
+
+ camera_hardware_t *camHal;
+
+ if(device && device->priv){
+ camHal = (camera_hardware_t *)device->priv;
+ }else{
+ ALOGE("%s: Null device or device->priv", __func__);
+ return;
+ }
+
+ usbCamPutParameters(camHal, parm);
+
+ ALOGI("%s: X", __func__);
+ return;
+}
+
+/* TBD */
+int usbcam_send_command(struct camera_device * device,
+ int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ int rc = 0;
+ ALOGI("%s: E", __func__);
+ ALOGI("%d", cmd);
+
+ ALOGI("%s: X", __func__);
+ return rc;
+}
+
+/* TBD */
+void usbcam_release(struct camera_device * device)
+{
+ ALOGI("%s: E", __func__);
+#if 0
+ Mutex::Autolock l(&mLock);
+
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ break;
+ case QCAMERA_HAL_PREVIEW_START:
+ break;
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ stopPreviewInternal();
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ stopRecordingInternal();
+ stopPreviewInternal();
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ cancelPictureInternal();
+ break;
+ default:
+ break;
+ }
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+#endif
+ ALOGI("%s: X", __func__);
+}
+
+/* TBD */
+int usbcam_dump(struct camera_device * device, int fd)
+{
+ ALOGI("%s: E", __func__);
+ int rc = 0;
+
+ ALOGI("%s: X", __func__);
+ return rc;
+}
+/*****************************************************************************
+* Static function definitions below
+*****************************************************************************/
+
+/******************************************************************************/
+/* No in place conversion supported. Output buffer and input MUST should be */
+/* different input buffer for a 4x4 pixel video ***/
+/****** YUYVYUYV 00 01 02 03 04 05 06 07 ************/
+/****** YUYVYUYV 08 09 10 11 12 13 14 15 ************/
+/****** YUYVYUYV 16 17 18 19 20 21 22 23 ************/
+/****** YUYVYUYV 24 25 26 27 28 29 30 31 ************/
+/******************************************************************************/
+/* output generated by this function ******************************************/
+/************************** YYYY 00 02 04 06 ************/
+/************************** YYYY 08 10 12 14 ************/
+/************************** YYYY 16 18 20 22 ************/
+/************************** YYYY 24 26 28 30 ************/
+/************************** VUVU 03 01 07 05 ************/
+/************************** VUVU 19 17 23 21 ************/
+/******************************************************************************/
+
+static int convert_YUYV_to_420_NV12(char *in_buf, char *out_buf, int wd, int ht)
+{
+ int rc =0;
+ int row, col, uv_row;
+
+ ALOGD("%s: E", __func__);
+ /* Arrange Y */
+ for(row = 0; row < ht; row++)
+ for(col = 0; col < wd * 2; col += 2)
+ {
+ out_buf[row * wd + col / 2] = in_buf[row * wd * 2 + col];
+ }
+
+ /* Arrange UV */
+ for(row = 0, uv_row = ht; row < ht; row += 2, uv_row++)
+ for(col = 1; col < wd * 2; col += 4)
+ {
+ out_buf[uv_row * wd + col / 2]= in_buf[row * wd * 2 + col + 2];
+ out_buf[uv_row * wd + col / 2 + 1] = in_buf[row * wd * 2 + col];
+ }
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: initDisplayBuffers
+ * Description: This function initializes the preview buffers
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+static int initDisplayBuffers(camera_hardware_t *camHal)
+{
+ preview_stream_ops *mPreviewWindow;
+ struct ion_fd_data ion_info_fd;
+ int numMinUndequeuedBufs = 0;
+ int rc = 0;
+ int gralloc_usage = 0;
+ int err;
+ int color=30;
+
+ ALOGD("%s: E", __func__);
+
+#if DISPLAY
+ if(camHal == NULL) {
+ ALOGE("%s: camHal = NULL", __func__);
+ return -1;
+ }
+
+ mPreviewWindow = camHal->window;
+ if(!mPreviewWindow) {
+ ALOGE("%s: mPreviewWindow = NULL", __func__);
+ return -1;
+ }
+
+ /************************************************************************/
+ /* - get_min_undequeued_buffer_count */
+ /* - set_buffer_count */
+ /* - set_buffers_geometry */
+ /* - set_usage */
+ /* - dequeue all the display buffers */
+ /* - cancel buffers: release w/o displaying */
+ /************************************************************************/
+
+ /************************************************************************/
+ /* - get_min_undequeued_buffer_count */
+ /************************************************************************/
+ if(mPreviewWindow->get_min_undequeued_buffer_count) {
+ rc = mPreviewWindow->get_min_undequeued_buffer_count(
+ mPreviewWindow, &numMinUndequeuedBufs);
+ if (0 != rc) {
+ ALOGE("%s: get_min_undequeued_buffer_count returned error", __func__);
+ }
+ else
+ ALOGD("%s: get_min_undequeued_buffer_count returned: %d ",
+ __func__, numMinUndequeuedBufs);
+ }
+ else
+ ALOGE("%s: get_min_undequeued_buffer_count is NULL pointer", __func__);
+
+ /************************************************************************/
+ /* - set_buffer_count */
+ /************************************************************************/
+ if(mPreviewWindow->set_buffer_count) {
+ camHal->previewMem.buffer_count = numMinUndequeuedBufs
+ + PRVW_DISP_BUF_CNT;
+ rc = mPreviewWindow->set_buffer_count(
+ mPreviewWindow,
+ camHal->previewMem.buffer_count);
+ if (rc != 0) {
+ ALOGE("%s: set_buffer_count returned error", __func__);
+ }else
+ ALOGD("%s: set_buffer_count returned success", __func__);
+ }else
+ ALOGE("%s: set_buffer_count is NULL pointer", __func__);
+
+ /************************************************************************/
+ /* - set_buffers_geometry */
+ /************************************************************************/
+ if(mPreviewWindow->set_buffers_geometry) {
+ rc = mPreviewWindow->set_buffers_geometry(mPreviewWindow,
+ camHal->dispWidth,
+ camHal->dispHeight,
+ camHal->dispFormat);
+ if (rc != 0) {
+ ALOGE("%s: set_buffers_geometry returned error. %s (%d)",
+ __func__, strerror(-rc), -rc);
+ }else
+ ALOGD("%s: set_buffers_geometry returned success", __func__);
+ }else
+ ALOGE("%s: set_buffers_geometry is NULL pointer", __func__);
+
+ /************************************************************************/
+ /* - set_usage */
+ /************************************************************************/
+ gralloc_usage = CAMERA_GRALLOC_HEAP_ID | CAMERA_GRALLOC_FALLBACK_HEAP_ID |
+ GRALLOC_USAGE_PRIVATE_UNCACHED;
+
+ if(mPreviewWindow->set_usage) {
+ rc = mPreviewWindow->set_usage(mPreviewWindow, gralloc_usage);
+ if (rc != 0) {
+ ALOGE("%s: set_usage returned error", __func__);
+ }else
+ ALOGD("%s: set_usage returned success", __func__);
+ }
+ else
+ ALOGE("%s: set_usage is NULL pointer", __func__);
+
+ /************************************************************************/
+ /* - dequeue all the display buffers */
+ /************************************************************************/
+ for (int cnt = 0; cnt < camHal->previewMem.buffer_count; cnt++) {
+ int stride;
+ err = mPreviewWindow->dequeue_buffer(
+ mPreviewWindow,
+ &camHal->previewMem.buffer_handle[cnt],
+ &camHal->previewMem.stride[cnt]);
+ if(!err) {
+ ALOGD("%s: dequeue buf: %p\n",
+ __func__, camHal->previewMem.buffer_handle[cnt]);
+
+ if(mPreviewWindow->lock_buffer) {
+ err = mPreviewWindow->lock_buffer(
+ mPreviewWindow,
+ camHal->previewMem.buffer_handle[cnt]);
+ ALOGD("%s: mPreviewWindow->lock_buffer success",
+ __func__);
+ }
+
+ // lock the buffer using genlock
+ ALOGD("%s: camera call genlock_lock, hdl=%p",
+ __func__, (*camHal->previewMem.buffer_handle[cnt]));
+
+ if (GENLOCK_NO_ERROR !=
+ genlock_lock_buffer(
+ (native_handle_t *) (*camHal->previewMem.buffer_handle[cnt]),
+ GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT))
+ {
+ ALOGE("%s: genlock_lock_buffer(WRITE) failed",
+ __func__);
+ camHal->previewMem.local_flag[cnt] = BUFFER_UNLOCKED;
+ }else {
+ ALOGD("%s: genlock_lock_buffer hdl =%p",
+ __func__, *camHal->previewMem.buffer_handle[cnt]);
+ camHal->previewMem.local_flag[cnt] = BUFFER_LOCKED;
+ }
+
+ /* Store this buffer details in the context */
+ camHal->previewMem.private_buffer_handle[cnt] =
+ (struct private_handle_t *) (*camHal->previewMem.buffer_handle[cnt]);
+
+ ALOGD("%s: idx = %d, fd = %d, size = %d, offset = %d", __func__,
+ cnt, camHal->previewMem.private_buffer_handle[cnt]->fd,
+ camHal->previewMem.private_buffer_handle[cnt]->size,
+ camHal->previewMem.private_buffer_handle[cnt]->offset);
+
+ camHal->previewMem.camera_memory[cnt] =
+ camHal->get_memory(
+ camHal->previewMem.private_buffer_handle[cnt]->fd,
+ camHal->previewMem.private_buffer_handle[cnt]->size,
+ 1, camHal->cb_ctxt);
+
+ ALOGD("%s: data = %p, size = %d, handle = %p", __func__,
+ camHal->previewMem.camera_memory[cnt]->data,
+ camHal->previewMem.camera_memory[cnt]->size,
+ camHal->previewMem.camera_memory[cnt]->handle);
+
+#ifdef USE_ION
+ /* In case of ION usage, open ION fd */
+ camHal->previewMem.mem_info[cnt].main_ion_fd =
+ open("/dev/ion", O_RDONLY);
+ if (camHal->previewMem.mem_info[cnt].main_ion_fd < 0) {
+ ALOGE("%s: failed: could not open ion device\n", __func__);
+ }else{
+ memset(&ion_info_fd, 0, sizeof(ion_info_fd));
+ ion_info_fd.fd =
+ camHal->previewMem.private_buffer_handle[cnt]->fd;
+ if (ioctl(camHal->previewMem.mem_info[cnt].main_ion_fd,
+ ION_IOC_IMPORT, &ion_info_fd) < 0) {
+ ALOGE("ION import failed\n");
+ }
+ }
+ camHal->previewMem.mem_info[cnt].fd =
+ camHal->previewMem.private_buffer_handle[cnt]->fd;
+ camHal->previewMem.mem_info[cnt].size =
+ camHal->previewMem.private_buffer_handle[cnt]->size;
+ camHal->previewMem.mem_info[cnt].handle = ion_info_fd.handle;
+
+#endif
+ }
+ else
+ ALOGE("%s: dequeue buf %d failed \n", __func__, cnt);
+ }
+ /************************************************************************/
+ /* - cancel buffers: queue w/o displaying */
+ /************************************************************************/
+ for (int cnt = 0; cnt < camHal->previewMem.buffer_count; cnt++) {
+ if (GENLOCK_FAILURE == genlock_unlock_buffer(
+ (native_handle_t *)(*(camHal->previewMem.buffer_handle[cnt])))){
+ ALOGE("%s: genlock_unlock_buffer failed: hdl =%p", __func__,
+ (*(camHal->previewMem.buffer_handle[cnt])) );
+ } else {
+ camHal->previewMem.local_flag[cnt] = BUFFER_UNLOCKED;
+ ALOGD("%s: genlock_unlock_buffer success: hdl = %p",
+ __func__, (*(camHal->previewMem.buffer_handle[cnt])));
+ }
+
+ err = mPreviewWindow->cancel_buffer(mPreviewWindow,
+ (buffer_handle_t *)camHal->previewMem.buffer_handle[cnt]);
+ if(!err) {
+ ALOGD("%s: cancel_buffer successful: %p\n",
+ __func__, camHal->previewMem.buffer_handle[cnt]);
+ }else
+ ALOGE("%s: cancel_buffer failed: %p\n", __func__,
+ camHal->previewMem.buffer_handle[cnt]);
+ }
+#else
+ rc = 0;
+#endif /* #if DISPLAY */
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: deInitDisplayBuffers
+ * Description: This function de-initializes all the display buffers allocated
+ * in initDisplayBuffers
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+static int deInitDisplayBuffers(camera_hardware_t *camHal)
+{
+ int rc = 0;
+ preview_stream_ops *previewWindow;
+
+ ALOGD("%s: E", __func__);
+
+ if(!camHal || !camHal->window) {
+ ALOGE("%s: camHal = NULL or window = NULL ", __func__);
+ return -1;
+ }
+
+ previewWindow = camHal->window;
+
+ /************************************************************************/
+ /* - Release all buffers that were acquired using get_memory */
+ /* - If using ION memory, free ION related resources */
+ /* - genUnlock if buffer is genLocked */
+ /* - Cancel buffers: queue w/o displaying */
+ /************************************************************************/
+
+#if DISPLAY
+ for (int cnt = 0; cnt < camHal->previewMem.buffer_count; cnt++) {
+
+ /* Release all buffers that were acquired using get_memory */
+ camHal->previewMem.camera_memory[cnt]->release(
+ camHal->previewMem.camera_memory[cnt]);
+
+#ifdef USE_ION
+ /* If using ION memory, free ION related resources */
+ struct ion_handle_data ion_handle;
+ memset(&ion_handle, 0, sizeof(ion_handle));
+ ion_handle.handle = camHal->previewMem.mem_info[cnt].handle;
+ if (ioctl(camHal->previewMem.mem_info[cnt].main_ion_fd,
+ ION_IOC_FREE, &ion_handle) < 0) {
+ ALOGE("%s: ion free failed\n", __func__);
+ }
+ close(camHal->previewMem.mem_info[cnt].main_ion_fd);
+#endif
+
+ /* genUnlock if buffer is genLocked */
+ if(camHal->previewMem.local_flag[cnt] == BUFFER_LOCKED){
+ if (GENLOCK_FAILURE == genlock_unlock_buffer(
+ (native_handle_t *)(*(camHal->previewMem.buffer_handle[cnt])))){
+ ALOGE("%s: genlock_unlock_buffer failed: hdl =%p", __func__,
+ (*(camHal->previewMem.buffer_handle[cnt])) );
+ } else {
+ camHal->previewMem.local_flag[cnt] = BUFFER_UNLOCKED;
+ ALOGD("%s: genlock_unlock_buffer success: hdl = %p",
+ __func__, (*(camHal->previewMem.buffer_handle[cnt])));
+ }
+ }
+ /* cancel buffers: enqueue w/o displaying */
+ rc = previewWindow->cancel_buffer(previewWindow,
+ (buffer_handle_t *)camHal->previewMem.buffer_handle[cnt]);
+ if(!rc) {
+ ALOGD("%s: cancel_buffer successful: %p\n",
+ __func__, camHal->previewMem.buffer_handle[cnt]);
+ }else
+ ALOGE("%s: cancel_buffer failed: %p\n", __func__,
+ camHal->previewMem.buffer_handle[cnt]);
+ }
+#endif /* #if DISPLAY */
+ memset(&camHal->previewMem, 0, sizeof(camHal->previewMem));
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: getPreviewCaptureFmt
+ * Description: This function implements the logic to decide appropriate
+ * capture format from the USB camera
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * Capture format. Default (V4L2_PIX_FMT_MJPEG)
+ *
+ * Notes: none
+ *****************************************************************************/
+static int getPreviewCaptureFmt(camera_hardware_t *camHal)
+{
+ int i = 0, mjpegSupported = 0, h264Supported = 0;
+ struct v4l2_fmtdesc fmtdesc;
+
+ memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
+
+ /************************************************************************/
+ /* - Query the camera for all supported formats */
+ /* - Based on the resolution, pick an apporpriate format */
+ /************************************************************************/
+
+ /************************************************************************/
+ /* - Query the camera for all supported formats */
+ /************************************************************************/
+ for(i = 0; ; i++) {
+ fmtdesc.index = i;
+ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_ENUM_FMT, &fmtdesc)) {
+ if (EINVAL == errno) {
+ ALOGI("%s: Queried all formats till index %d\n", __func__, i);
+ break;
+ } else {
+ ALOGE("%s: VIDIOC_ENUM_FMT failed", __func__);
+ }
+ }
+ if(V4L2_PIX_FMT_MJPEG == fmtdesc.pixelformat){
+ mjpegSupported = 1;
+ ALOGI("%s: V4L2_PIX_FMT_MJPEG is supported", __func__ );
+ }
+ if(V4L2_PIX_FMT_H264 == fmtdesc.pixelformat){
+ h264Supported = 1;
+ ALOGI("%s: V4L2_PIX_FMT_H264 is supported", __func__ );
+ }
+
+ }
+
+ /************************************************************************/
+ /* - Based on the resolution, pick an apporpriate format */
+ /************************************************************************/
+ //V4L2_PIX_FMT_MJPEG; V4L2_PIX_FMT_YUYV; V4L2_PIX_FMT_H264 = 0x34363248;
+ camHal->captureFormat = V4L2_PIX_FMT_YUYV;
+ if(camHal->prevWidth > 640){
+ if(1 == mjpegSupported)
+ camHal->captureFormat = V4L2_PIX_FMT_MJPEG;
+ else if(1 == h264Supported)
+ camHal->captureFormat = V4L2_PIX_FMT_H264;
+ }
+ ALOGI("%s: Capture format chosen: 0x%x. 0x%x:YUYV. 0x%x:MJPEG. 0x%x: H264",
+ __func__, camHal->captureFormat, V4L2_PIX_FMT_YUYV,
+ V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_H264);
+
+ return camHal->captureFormat;
+}
+
+/******************************************************************************
+ * Function: getMjpegdOutputFormat
+ * Description: This function maps display pixel format enum to JPEG output
+ * format enum
+ *
+ * Input parameters:
+ * dispFormat - Display pixel format
+ *
+ * Return values:
+ * (int)mjpegOutputFormat
+ *
+ * Notes: none
+ *****************************************************************************/
+static int getMjpegdOutputFormat(int dispFormat)
+{
+ int mjpegOutputFormat = YCRCBLP_H2V2;
+
+ if(HAL_PIXEL_FORMAT_YCrCb_420_SP == dispFormat)
+ mjpegOutputFormat = YCRCBLP_H2V2;
+
+ return mjpegOutputFormat;
+}
+
+/******************************************************************************
+ * Function: ioctlLoop
+ * Description: This function is a blocking call around ioctl
+ *
+ * Input parameters:
+ * fd - IOCTL fd
+ * ioctlCmd - IOCTL command
+ * args - IOCTL arguments
+ *
+ * Return values:
+ * (int)mjpegOutputFormat
+ *
+ * Notes: none
+ *****************************************************************************/
+static int ioctlLoop(int fd, int ioctlCmd, void *args)
+{
+ int rc = -1;
+
+ while(1)
+ {
+ rc = ioctl(fd, ioctlCmd, args);
+ if(!((-1 == rc) && (EINTR == errno)))
+ break;
+ }
+ return rc;
+}
+
+/******************************************************************************
+ * Function: initV4L2mmap
+ * Description: This function requests for V4L2 driver allocated buffers
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int initV4L2mmap(camera_hardware_t *camHal)
+{
+ int rc = -1;
+ struct v4l2_requestbuffers reqBufs;
+ struct v4l2_buffer tempBuf;
+
+ ALOGD("%s: E", __func__);
+ memset(&reqBufs, 0, sizeof(v4l2_requestbuffers));
+ reqBufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ reqBufs.memory = V4L2_MEMORY_MMAP;
+ reqBufs.count = PRVW_CAP_BUF_CNT;
+
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_REQBUFS, &reqBufs)) {
+ if (EINVAL == errno) {
+ ALOGE("%s: does not support memory mapping\n", __func__);
+ } else {
+ ALOGE("%s: VIDIOC_REQBUFS failed", __func__);
+ }
+ }
+ ALOGD("%s: VIDIOC_REQBUFS success", __func__);
+
+ if (reqBufs.count < PRVW_CAP_BUF_CNT) {
+ ALOGE("%s: Insufficient buffer memory on\n", __func__);
+ }
+
+ camHal->buffers =
+ ( bufObj* ) calloc(reqBufs.count, sizeof(bufObj));
+
+ if (!camHal->buffers) {
+ ALOGE("%s: Out of memory\n", __func__);
+ }
+
+ /* Store the indexes in the context. Useful during releasing */
+ for (camHal->n_buffers = 0;
+ camHal->n_buffers < reqBufs.count;
+ camHal->n_buffers++) {
+
+ memset(&tempBuf, 0, sizeof(tempBuf));
+
+ tempBuf.index = camHal->n_buffers;
+ tempBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ tempBuf.memory = V4L2_MEMORY_MMAP;
+
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_QUERYBUF, &tempBuf))
+ ALOGE("%s: VIDIOC_QUERYBUF failed", __func__);
+
+ ALOGD("%s: VIDIOC_QUERYBUF success", __func__);
+
+ camHal->buffers[camHal->n_buffers].len = tempBuf.length;
+ camHal->buffers[camHal->n_buffers].data =
+ mmap(NULL /* start anywhere */,
+ tempBuf.length,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ camHal->fd, tempBuf.m.offset);
+
+ if (MAP_FAILED == camHal->buffers[camHal->n_buffers].data)
+ ALOGE("%s: mmap failed", __func__);
+ }
+ ALOGD("%s: X", __func__);
+ return 0;
+}
+
+/******************************************************************************
+ * Function: unInitV4L2mmap
+ * Description: This function unmaps the V4L2 driver buffers
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int unInitV4L2mmap(camera_hardware_t *camHal)
+{
+ int i, rc = 0;
+ ALOGD("%s: E", __func__);
+
+ for (i = 0; i < camHal->n_buffers; i++)
+ if (-1 == munmap(camHal->buffers[i].data, camHal->buffers[i].len)){
+ ALOGE("%s: munmap failed for buffer: %d", __func__, i);
+ rc = -1;
+ }
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: initUsbCamera
+ * Description: This function sets the resolution and pixel format of the
+ * USB camera
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * width - picture width in pixels
+ * height - picture height in pixels
+ * pixelFormat - capture format for the camera
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int initUsbCamera(camera_hardware_t *camHal, int width, int height,
+ int pixelFormat)
+{
+ int rc = -1;
+ struct v4l2_capability cap;
+ struct v4l2_cropcap cropcap;
+ struct v4l2_crop crop;
+ struct v4l2_format v4l2format;
+ unsigned int min;
+
+ ALOGI("%s: E", __func__);
+
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_QUERYCAP, &cap)) {
+ if (EINVAL == errno) {
+ ALOGE( "%s: This is not V4L2 device\n", __func__);
+ return -1;
+ } else {
+ ALOGE("%s: VIDIOC_QUERYCAP errno: %d", __func__, errno);
+ }
+ }
+ ALOGD("%s: VIDIOC_QUERYCAP success", __func__);
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+ ALOGE("%s: This is not video capture device\n", __func__);
+ return -1;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ ALOGE("%s: This does not support streaming i/o\n", __func__);
+ return -1;
+ }
+
+ /* Select video input, video standard and tune here. */
+ memset(&cropcap, 0, sizeof(cropcap));
+
+ cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (0 == ioctlLoop(camHal->fd, VIDIOC_CROPCAP, &cropcap)) {
+
+ /* reset to default */
+ crop.c = cropcap.defrect;
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ALOGD("%s: VIDIOC_CROPCAP success", __func__);
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_S_CROP, &crop)) {
+ switch (errno) {
+ case EINVAL:
+ /* Cropping not supported. */
+ break;
+ default:
+ /* Errors ignored. */
+ break;
+ }
+ }
+ ALOGD("%s: VIDIOC_S_CROP success", __func__);
+
+ } else {
+ /* Errors ignored. */
+ ALOGE("%s: VIDIOC_S_CROP failed", __func__);
+ }
+
+
+ memset(&v4l2format, 0, sizeof(v4l2format));
+
+ v4l2format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ {
+ v4l2format.fmt.pix.field = V4L2_FIELD_NONE;
+ v4l2format.fmt.pix.pixelformat = pixelFormat;
+ v4l2format.fmt.pix.width = width;
+ v4l2format.fmt.pix.height = height;
+
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_S_FMT, &v4l2format))
+ {
+ ALOGE("%s: VIDIOC_S_FMT failed", __func__);
+ return -1;
+ }
+ ALOGD("%s: VIDIOC_S_FMT success", __func__);
+
+ /* Note VIDIOC_S_FMT may change width and height. */
+ }
+
+ /* TBR: In case of user pointer buffers, v4l2format.fmt.pix.sizeimage */
+ /* might have to be calculated as per V4L2 sample application due to */
+ /* open source driver bug */
+
+ rc = initV4L2mmap(camHal);
+ ALOGI("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: startUsbCamCapture
+ * Description: This function queues buffer objects to the driver and sends
+ * STREAM ON command to the USB camera driver
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int startUsbCamCapture(camera_hardware_t *camHal)
+{
+ int rc = -1;
+ unsigned int i;
+ enum v4l2_buf_type v4l2BufType;
+ ALOGD("%s: E", __func__);
+
+ for (i = 0; i < camHal->n_buffers; ++i) {
+ struct v4l2_buffer tempBuf;
+
+ memset(&tempBuf, 0, sizeof(tempBuf));
+ tempBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ tempBuf.memory = V4L2_MEMORY_MMAP;
+ tempBuf.index = i;
+
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_QBUF, &tempBuf))
+ ALOGE("%s: VIDIOC_QBUF for %d buffer failed", __func__, i);
+ else
+ ALOGD("%s: VIDIOC_QBUF for %d buffer success", __func__, i);
+ }
+
+ v4l2BufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_STREAMON, &v4l2BufType))
+ ALOGE("%s: VIDIOC_STREAMON failed", __func__);
+ else
+ {
+ ALOGD("%s: VIDIOC_STREAMON success", __func__);
+ rc = 0;
+ }
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: stopUsbCamCapture
+ * Description: This function sends STREAM OFF command to the USB camera driver
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int stopUsbCamCapture(camera_hardware_t *camHal)
+{
+ int rc = -1;
+ unsigned int i;
+ enum v4l2_buf_type v4l2BufType;
+ ALOGD("%s: E", __func__);
+
+ if(!camHal->fd){
+ ALOGE("%s: camHal->fd = NULL ", __func__);
+ return -1;
+ }
+ v4l2BufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_STREAMOFF, &v4l2BufType)){
+ ALOGE("%s: VIDIOC_STREAMOFF failed", __func__);
+ rc = -1;
+ }else{
+ ALOGD("%s: VIDIOC_STREAMOFF success", __func__);
+ rc = 0;
+ }
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: stopPreviewInternal
+ * Description: This function sends EXIT command to prview loop thread,
+ * stops usb camera capture and uninitializes MMAP. This function
+ * assumes that calling function has locked camHal->lock
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int stopPreviewInternal(camera_hardware_t *camHal)
+{
+ int rc = 0;
+ ALOGD("%s: E", __func__);
+
+ if(camHal->previewEnabledFlag)
+ {
+ camHal->prvwCmdPending++;
+ camHal->prvwCmd = USB_CAM_PREVIEW_EXIT;
+
+ /* yield lock while waiting for the preview thread to exit */
+ camHal->lock.unlock();
+ if(pthread_join(camHal->previewThread, NULL)){
+ ALOGE("%s: Error in pthread_join preview thread", __func__);
+ }
+ camHal->lock.lock();
+
+ if(stopUsbCamCapture(camHal)){
+ ALOGE("%s: Error in stopUsbCamCapture", __func__);
+ rc = -1;
+ }
+ if(unInitV4L2mmap(camHal)){
+ ALOGE("%s: Error in stopUsbCamCapture", __func__);
+ rc = -1;
+ }
+ camHal->previewEnabledFlag = 0;
+ }
+
+ ALOGD("%s: X, rc: %d", __func__, rc);
+ return rc;
+}
+#if 1
+/******************************************************************************
+ * Function: prvwThreadTakePictureInternal
+ * Description: This function processes one camera frame to get JPEG encoded
+ * picture.
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int prvwThreadTakePictureInternal(camera_hardware_t *camHal)
+{
+ int rc = 0;
+ QCameraHalMemInfo_t *mem_info;
+ ALOGD("%s: E", __func__);
+
+ /************************************************************************/
+ /* - If requested for shutter notfication, callback */
+ /* - Dequeue capture buffer from USB camera */
+ /* - Send capture buffer to JPEG encoder for JPEG compression */
+ /* - If jpeg frames callback is requested, callback with jpeg buffers */
+ /* - Enqueue capture buffer back to USB camera */
+ /************************************************************************/
+
+ /************************************************************************/
+ /* - If requested for shutter notfication, callback */
+ /************************************************************************/
+ if (camHal->msgEnabledFlag & CAMERA_MSG_SHUTTER){
+ camHal->lock.unlock();
+ camHal->notify_cb(CAMERA_MSG_SHUTTER, 0, 0, camHal->cb_ctxt);
+ camHal->lock.lock();
+ }
+
+#if CAPTURE
+ /************************************************************************/
+ /* - Dequeue capture buffer from USB camera */
+ /************************************************************************/
+ if (0 == get_buf_from_cam(camHal))
+ ALOGD("%s: get_buf_from_cam success", __func__);
+ else
+ ALOGE("%s: get_buf_from_cam error", __func__);
+#endif
+
+ /************************************************************************/
+ /* - Send capture buffer to JPEG encoder for JPEG compression */
+ /************************************************************************/
+ /* Optimization: If camera capture is JPEG format, need not compress! */
+ /* instead, just data copy from capture buffer to picture buffer */
+ if(V4L2_PIX_FMT_MJPEG == camHal->captureFormat){
+ /* allocate heap memory for JPEG output */
+ mem_info = &camHal->pictMem.mem_info[0];
+ mem_info->size = camHal->curCaptureBuf.bytesused;
+ /* TBD: allocate_ion_memory
+ rc = QCameraHardwareInterface::allocate_ion_memory(mem_info,
+ ((0x1 << CAMERA_ZSL_ION_HEAP_ID) |
+ (0x1 << CAMERA_ZSL_ION_FALLBACK_HEAP_ID)));
+ */
+ if(rc)
+ ALOGE("%s: ION memory allocation failed", __func__);
+
+ camHal->pictMem.camera_memory[0] = camHal->get_memory(
+ mem_info->fd, mem_info->size, 1, camHal->cb_ctxt);
+ if(!camHal->pictMem.camera_memory[0])
+ ALOGE("%s: get_mem failed", __func__);
+
+ memcpy( camHal->pictMem.camera_memory[0]->data,
+ (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
+ camHal->curCaptureBuf.bytesused);
+ }
+
+ /************************************************************************/
+ /* - If jpeg frames callback is requested, callback with jpeg buffers */
+ /************************************************************************/
+ if ((camHal->msgEnabledFlag & CAMERA_MSG_COMPRESSED_IMAGE) &&
+ (camHal->data_cb)){
+ camHal->lock.unlock();
+ camHal->data_cb(CAMERA_MSG_COMPRESSED_IMAGE,
+ camHal->pictMem.camera_memory[0],
+ 0, NULL, camHal->cb_ctxt);
+ camHal->lock.lock();
+ }
+ /* release heap memory after the call back */
+ if(camHal->pictMem.camera_memory[0])
+ camHal->pictMem.camera_memory[0]->release(
+ camHal->pictMem.camera_memory[0]);
+
+ /* TBD: deallocate_ion_memory */
+ //rc = QCameraHardwareInterface::deallocate_ion_memory(mem_info);
+ if(rc)
+ ALOGE("%s: ION memory de-allocation failed", __func__);
+
+#if CAPTURE
+ /************************************************************************/
+ /* - Enqueue capture buffer back to USB camera */
+ /************************************************************************/
+ if(0 == put_buf_to_cam(camHal)) {
+ ALOGD("%s: put_buf_to_cam success", __func__);
+ }
+ else
+ ALOGE("%s: put_buf_to_cam error", __func__);
+#endif
+
+ ALOGD("%s: X, rc: %d", __func__, rc);
+ return rc;
+}
+#endif //#if 0
+/******************************************************************************
+ * Function: cache_ops
+ * Description: This function calls ION ioctl for cache related operations
+ *
+ * Input parameters:
+ * mem_info - QCameraHalMemInfo_t structure with ION info
+ * buf_ptr - Buffer pointer that needs to be cache operated
+ * cmd - Cache command - clean/invalidate
+ *
+ * Return values:
+ * MM_CAMERA_OK No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+int cache_ops(QCameraHalMemInfo_t *mem_info,
+ void *buf_ptr,
+ unsigned int cmd)
+{
+ struct ion_flush_data cache_inv_data;
+ struct ion_custom_data custom_data;
+ int ret = MM_CAMERA_OK;
+
+#ifdef USE_ION
+ if (NULL == mem_info) {
+ ALOGE("%s: mem_info is NULL, return here", __func__);
+ return -1;
+ }
+
+ memset(&cache_inv_data, 0, sizeof(cache_inv_data));
+ memset(&custom_data, 0, sizeof(custom_data));
+ cache_inv_data.vaddr = buf_ptr;
+ cache_inv_data.fd = mem_info->fd;
+ cache_inv_data.handle = mem_info->handle;
+ cache_inv_data.length = mem_info->size;
+ custom_data.cmd = cmd;
+ custom_data.arg = (unsigned long)&cache_inv_data;
+
+ ALOGD("%s: addr = %p, fd = %d, handle = %p length = %d, ION Fd = %d",
+ __func__, cache_inv_data.vaddr, cache_inv_data.fd,
+ cache_inv_data.handle, cache_inv_data.length,
+ mem_info->main_ion_fd);
+ if(mem_info->main_ion_fd > 0) {
+ if(ioctl(mem_info->main_ion_fd, ION_IOC_CUSTOM, &custom_data) < 0) {
+ ALOGE("%s: Cache Invalidate failed\n", __func__);
+ ret = -1;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+/******************************************************************************
+ * Function: get_buf_from_cam
+ * Description: This funtions gets/acquires 1 capture buffer from the camera
+ * driver. The fetched buffer is stored in curCaptureBuf
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int get_buf_from_cam(camera_hardware_t *camHal)
+{
+ int rc = -1;
+
+ ALOGD("%s: E", __func__);
+ {
+ memset(&camHal->curCaptureBuf, 0, sizeof(camHal->curCaptureBuf));
+
+ camHal->curCaptureBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ camHal->curCaptureBuf.memory = V4L2_MEMORY_MMAP;
+
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_DQBUF, &camHal->curCaptureBuf)){
+ switch (errno) {
+ case EAGAIN:
+ ALOGE("%s: EAGAIN error", __func__);
+ return 1;
+
+ case EIO:
+ /* Could ignore EIO, see spec. */
+
+ /* fall through */
+
+ default:
+ ALOGE("%s: VIDIOC_DQBUF error", __func__);
+ }
+ }
+ else
+ {
+ rc = 0;
+ ALOGD("%s: VIDIOC_DQBUF: %d successful, %d bytes",
+ __func__, camHal->curCaptureBuf.index,
+ camHal->curCaptureBuf.bytesused);
+ }
+ }
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: put_buf_to_cam
+ * Description: This funtion puts/releases 1 capture buffer back to the camera
+ * driver
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int put_buf_to_cam(camera_hardware_t *camHal)
+{
+ ALOGD("%s: E", __func__);
+
+ camHal->curCaptureBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ camHal->curCaptureBuf.memory = V4L2_MEMORY_MMAP;
+
+
+ if (-1 == ioctlLoop(camHal->fd, VIDIOC_QBUF, &camHal->curCaptureBuf))
+ {
+ ALOGE("%s: VIDIOC_QBUF failed ", __func__);
+ return 1;
+ }
+ ALOGD("%s: X", __func__);
+ return 0;
+}
+
+/******************************************************************************
+ * Function: put_buf_to_cam
+ * Description: This funtion gets/acquires 1 display buffer from the display
+ * window
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * buffer_id - Buffer id pointer. The id of buffer obtained
+ * by this function is returned in this arg
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int get_buf_from_display(camera_hardware_t *camHal, int *buffer_id)
+{
+ int err = 0;
+ preview_stream_ops *mPreviewWindow = NULL;
+ int stride = 0, cnt = 0;
+ buffer_handle_t *buffer_handle = NULL;
+ struct private_handle_t *private_buffer_handle = NULL;
+
+ ALOGD("%s: E", __func__);
+
+ if (camHal == NULL) {
+ ALOGE("%s: camHal = NULL", __func__);
+ return -1;
+ }
+
+ mPreviewWindow = camHal->window;
+ if( mPreviewWindow == NULL) {
+ ALOGE("%s: mPreviewWindow = NULL", __func__);
+ return -1;
+ }
+ err = mPreviewWindow->dequeue_buffer(mPreviewWindow,
+ &buffer_handle,
+ &stride);
+ if(!err) {
+ ALOGD("%s: dequeue buf buffer_handle: %p\n", __func__, buffer_handle);
+
+ ALOGD("%s: mPreviewWindow->lock_buffer: %p",
+ __func__, mPreviewWindow->lock_buffer);
+ if(mPreviewWindow->lock_buffer) {
+ err = mPreviewWindow->lock_buffer(mPreviewWindow, buffer_handle);
+ ALOGD("%s: mPreviewWindow->lock_buffer success", __func__);
+ }
+ ALOGD("%s: camera call genlock_lock, hdl=%p",
+ __func__, (*buffer_handle));
+
+ if (GENLOCK_NO_ERROR !=
+ genlock_lock_buffer((native_handle_t *)(*buffer_handle),
+ GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) {
+ ALOGE("%s: genlock_lock_buffer(WRITE) failed", __func__);
+ } else {
+ ALOGD("%s: genlock_lock_buffer hdl =%p", __func__, *buffer_handle);
+ }
+
+ private_buffer_handle = (struct private_handle_t *)(*buffer_handle);
+
+ ALOGD("%s: fd = %d, size = %d, offset = %d, stride = %d",
+ __func__, private_buffer_handle->fd,
+ private_buffer_handle->size, private_buffer_handle->offset, stride);
+
+ for(cnt = 0; cnt < camHal->previewMem.buffer_count + 2; cnt++) {
+ if(private_buffer_handle->fd ==
+ camHal->previewMem.private_buffer_handle[cnt]->fd) {
+ *buffer_id = cnt;
+ ALOGD("%s: deQueued fd = %d, index: %d",
+ __func__, private_buffer_handle->fd, cnt);
+ break;
+ }
+ }
+ }
+ else
+ ALOGE("%s: dequeue buf failed \n", __func__);
+
+ ALOGD("%s: X", __func__);
+
+ return err;
+}
+
+/******************************************************************************
+ * Function: put_buf_to_display
+ * Description: This funtion puts/enqueues 1 buffer back to the display window
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * buffer_id - id of the buffer that needs to be enqueued
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int put_buf_to_display(camera_hardware_t *camHal, int buffer_id)
+{
+ int err = 0;
+ preview_stream_ops *mPreviewWindow;
+
+ ALOGD("%s: E", __func__);
+
+ if (camHal == NULL) {
+ ALOGE("%s: camHal = NULL", __func__);
+ return -1;
+ }
+
+ mPreviewWindow = camHal->window;
+ if( mPreviewWindow == NULL) {
+ ALOGE("%s: mPreviewWindow = NULL", __func__);
+ return -1;
+ }
+
+ if (GENLOCK_FAILURE ==
+ genlock_unlock_buffer(
+ (native_handle_t *)
+ (*(camHal->previewMem.buffer_handle[buffer_id])))) {
+ ALOGE("%s: genlock_unlock_buffer failed: hdl =%p",
+ __func__, (*(camHal->previewMem.buffer_handle[buffer_id])) );
+ } else {
+ ALOGD("%s: genlock_unlock_buffer success: hdl =%p",
+ __func__, (*(camHal->previewMem.buffer_handle[buffer_id])) );
+ }
+
+ /* Cache clean the output buffer so that cache is written back */
+ cache_ops(&camHal->previewMem.mem_info[buffer_id],
+ (void *)camHal->previewMem.camera_memory[buffer_id]->data,
+ ION_IOC_CLEAN_CACHES);
+ /*
+ cache_ops(&camHal->previewMem.mem_info[buffer_id],
+ (void *)camHal->previewMem.camera_memory[buffer_id]->data,
+ ION_IOC_CLEAN_INV_CACHES);
+*/
+ err = mPreviewWindow->enqueue_buffer(mPreviewWindow,
+ (buffer_handle_t *)camHal->previewMem.buffer_handle[buffer_id]);
+ if(!err) {
+ ALOGD("%s: enqueue buf successful: %p\n",
+ __func__, camHal->previewMem.buffer_handle[buffer_id]);
+ }else
+ ALOGE("%s: enqueue buf failed: %p\n",
+ __func__, camHal->previewMem.buffer_handle[buffer_id]);
+
+ ALOGD("%s: X", __func__);
+
+ return err;
+}
+
+/******************************************************************************
+ * Function: put_buf_to_display
+ * Description: This funtion transfers the content from capture buffer to
+ * preiew display buffer after appropriate conversion
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ * buffer_id - id of the buffer that needs to be enqueued
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int convert_data_frm_cam_to_disp(camera_hardware_t *camHal, int buffer_id)
+{
+ int rc = -1;
+
+ if(!camHal) {
+ ALOGE("%s: camHal is NULL", __func__);
+ return -1;
+ }
+ /* If input and output are raw formats, but different color format, */
+ /* call color conversion routine */
+ if( (V4L2_PIX_FMT_YUYV == camHal->captureFormat) &&
+ (HAL_PIXEL_FORMAT_YCrCb_420_SP == camHal->dispFormat))
+ {
+ convert_YUYV_to_420_NV12(
+ (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
+ (char *)camHal->previewMem.camera_memory[buffer_id]->data,
+ camHal->prevWidth,
+ camHal->prevHeight);
+ ALOGD("%s: Copied %d bytes from camera buffer %d to display buffer: %d",
+ __func__, camHal->curCaptureBuf.bytesused,
+ camHal->curCaptureBuf.index, buffer_id);
+ rc = 0;
+ }
+
+ /* If camera buffer is MJPEG encoded, call mjpeg decode call */
+ if(V4L2_PIX_FMT_MJPEG == camHal->captureFormat)
+ {
+ if(NULL == camHal->mjpegd)
+ {
+ rc = mjpegDecoderInit(&camHal->mjpegd);
+ if(rc < 0)
+ ALOGE("%s: mjpegDecoderInit Error: %d", __func__, rc);
+ }
+ if(camHal->mjpegd)
+ {
+ rc = mjpegDecode(
+ (void*)camHal->mjpegd,
+ (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
+ camHal->curCaptureBuf.bytesused,
+ (char *)camHal->previewMem.camera_memory[buffer_id]->data,
+ (char *)camHal->previewMem.camera_memory[buffer_id]->data +
+ camHal->prevWidth * camHal->prevHeight,
+ getMjpegdOutputFormat(camHal->dispFormat));
+ if(rc < 0)
+ ALOGE("%s: mjpegDecode Error: %d", __func__, rc);
+ }
+ }
+ return rc;
+}
+
+/******************************************************************************
+ * Function: launch_preview_thread
+ * Description: This is a wrapper function to start preview thread
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int launch_preview_thread(camera_hardware_t *camHal)
+{
+ ALOGD("%s: E", __func__);
+ int rc = 0;
+
+ if(!camHal) {
+ ALOGE("%s: camHal is NULL", __func__);
+ return -1;
+ }
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_create(&camHal->previewThread, &attr, previewloop, camHal);
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: launch_preview_thread
+ * Description: This is thread funtion for preivew loop
+ *
+ * Input parameters:
+ * hcamHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static void * previewloop(void *hcamHal)
+{
+ int rc;
+ int buffer_id = 0;
+ pid_t tid = 0;
+ camera_hardware_t *camHal = NULL;
+ int msgType = 0;
+ camera_memory_t *data = NULL;
+ camera_frame_metadata_t *metadata= NULL;
+ camera_memory_t *previewMem = NULL;
+
+ camHal = (camera_hardware_t *)hcamHal;
+ ALOGD("%s: E", __func__);
+
+ if(!camHal) {
+ ALOGE("%s: camHal is NULL", __func__);
+ return NULL ;
+ }
+
+ tid = gettid();
+ /* TBR: Set appropriate thread priority */
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_NORMAL);
+ prctl(PR_SET_NAME, (unsigned long)"Camera HAL preview thread", 0, 0, 0);
+
+ /************************************************************************/
+ /* - Time wait (select) on camera fd for input read buffer */
+ /* - Check if any preview thread commands are set. If set, process */
+ /* - Dequeue display buffer from surface */
+ /* - Dequeue capture buffer from USB camera */
+ /* - Convert capture format to display format */
+ /* - If preview frames callback is requested, callback with prvw buffers*/
+ /* - Enqueue display buffer back to surface */
+ /* - Enqueue capture buffer back to USB camera */
+ /************************************************************************/
+ while(1) {
+ fd_set fds;
+ struct timeval tv;
+ int r = 0;
+
+ FD_ZERO(&fds);
+#if CAPTURE
+ FD_SET(camHal->fd, &fds);
+#endif /* CAPTURE */
+
+ /************************************************************************/
+ /* - Time wait (select) on camera fd for input read buffer */
+ /************************************************************************/
+ tv.tv_sec = 0;
+ tv.tv_usec = 500000;
+
+ ALOGD("%s: b4 select on camHal->fd + 1,fd: %d", __func__, camHal->fd);
+#if CAPTURE
+ r = select(camHal->fd + 1, &fds, NULL, NULL, &tv);
+#else
+ r = select(1, NULL, NULL, NULL, &tv);
+#endif /* CAPTURE */
+ ALOGD("%s: after select : %d", __func__, camHal->fd);
+
+ if (-1 == r) {
+ if (EINTR == errno)
+ continue;
+ ALOGE("%s: FDSelect error: %d", __func__, errno);
+ }
+
+ if (0 == r) {
+ ALOGD("%s: select timeout\n", __func__);
+ }
+
+ /* Protect the context for one iteration of preview loop */
+ /* this gets unlocked at the end of the while */
+ Mutex::Autolock autoLock(camHal->lock);
+
+ /************************************************************************/
+ /* - Check if any preview thread commands are set. If set, process */
+ /************************************************************************/
+ if(camHal->prvwCmdPending)
+ {
+ /* command is serviced. Hence command pending = 0 */
+ camHal->prvwCmdPending--;
+ //sempost(ack)
+ if(USB_CAM_PREVIEW_EXIT == camHal->prvwCmd){
+ /* unlock before exiting the thread */
+ camHal->lock.unlock();
+ ALOGI("%s: Exiting coz USB_CAM_PREVIEW_EXIT", __func__);
+ return (void *)0;
+ }else if(USB_CAM_PREVIEW_TAKEPIC == camHal->prvwCmd){
+ rc = prvwThreadTakePictureInternal(camHal);
+ if(rc)
+ ALOGE("%s: prvwThreadTakePictureInternal returned error",
+ __func__);
+ }
+ }
+
+ /* Null check on preview window. If null, sleep */
+ if(!camHal->window) {
+ ALOGD("%s: sleeping coz camHal->window = NULL",__func__);
+ camHal->lock.unlock();
+ sleep(2);
+ continue;
+ }
+#if DISPLAY
+ /************************************************************************/
+ /* - Dequeue display buffer from surface */
+ /************************************************************************/
+ if(0 == get_buf_from_display(camHal, &buffer_id)) {
+ ALOGD("%s: get_buf_from_display success: %d",
+ __func__, buffer_id);
+ }else{
+ ALOGE("%s: get_buf_from_display failed. Skipping the loop",
+ __func__);
+ continue;
+ }
+#endif
+
+#if CAPTURE
+ /************************************************************************/
+ /* - Dequeue capture buffer from USB camera */
+ /************************************************************************/
+ if (0 == get_buf_from_cam(camHal))
+ ALOGD("%s: get_buf_from_cam success", __func__);
+ else
+ ALOGE("%s: get_buf_from_cam error", __func__);
+#endif
+
+#if FILE_DUMP_CAMERA
+ /* Debug code to dump frames from camera */
+ {
+ static int frame_cnt = 0;
+ /* currently hardcoded for Bytes-Per-Pixel = 1.5 */
+ fileDump("/data/USBcam.yuv",
+ (char*)camHal->buffers[camHal->curCaptureBuf.index].data,
+ camHal->prevWidth * camHal->prevHeight * 1.5,
+ &frame_cnt);
+ }
+#endif
+
+#if MEMSET
+ static int color = 30;
+ color += 50;
+ if(color > 200) {
+ color = 30;
+ }
+ ALOGE("%s: Setting to the color: %d\n", __func__, color);
+ /* currently hardcoded for format of type Bytes-Per-Pixel = 1.5 */
+ memset(camHal->previewMem.camera_memory[buffer_id]->data,
+ color, camHal->dispWidth * camHal->dispHeight * 1.5 + 2 * 1024);
+#else
+ convert_data_frm_cam_to_disp(camHal, buffer_id);
+ ALOGD("%s: Copied data to buffer_id: %d", __func__, buffer_id);
+#endif
+
+#if FILE_DUMP_B4_DISP
+ /* Debug code to dump display buffers */
+ {
+ static int frame_cnt = 0;
+ /* currently hardcoded for Bytes-Per-Pixel = 1.5 */
+ fileDump("/data/display.yuv",
+ (char*) camHal->previewMem.camera_memory[buffer_id]->data,
+ camHal->dispWidth * camHal->dispHeight * 1.5,
+ &frame_cnt);
+ ALOGD("%s: Written buf_index: %d ", __func__, buffer_id);
+ }
+#endif
+
+#if DISPLAY
+ /************************************************************************/
+ /* - Enqueue display buffer back to surface */
+ /************************************************************************/
+ if(0 == put_buf_to_display(camHal, buffer_id)) {
+ ALOGD("%s: put_buf_to_display success: %d", __func__, buffer_id);
+ }
+ else
+ ALOGE("%s: put_buf_to_display error", __func__);
+#endif
+
+#if CAPTURE
+ /************************************************************************/
+ /* - Enqueue capture buffer back to USB camera */
+ /************************************************************************/
+ if(0 == put_buf_to_cam(camHal)) {
+ ALOGD("%s: put_buf_to_cam success", __func__);
+ }
+ else
+ ALOGE("%s: put_buf_to_cam error", __func__);
+#endif
+
+#if CALL_BACK
+ /************************************************************************/
+ /* - If preview frames callback is requested, callback with prvw buffers*/
+ /************************************************************************/
+ /* TBD: change the 1.5 hardcoding to Bytes Per Pixel */
+ int previewBufSize = camHal->prevWidth * camHal->prevHeight * 1.5;
+
+ msgType |= CAMERA_MSG_PREVIEW_FRAME;
+
+ if(previewBufSize !=
+ camHal->previewMem.private_buffer_handle[buffer_id]->size) {
+
+ previewMem = camHal->get_memory(
+ camHal->previewMem.private_buffer_handle[buffer_id]->fd,
+ previewBufSize,
+ 1,
+ camHal->cb_ctxt);
+
+ if (!previewMem || !previewMem->data) {
+ ALOGE("%s: get_memory failed.\n", __func__);
+ }
+ else {
+ data = previewMem;
+ ALOGD("%s: GetMemory successful. data = %p",
+ __func__, data);
+ ALOGD("%s: previewBufSize = %d, priv_buf_size: %d",
+ __func__, previewBufSize,
+ camHal->previewMem.private_buffer_handle[buffer_id]->size);
+ }
+ }
+ else{
+ data = camHal->previewMem.camera_memory[buffer_id];
+ ALOGD("%s: No GetMemory, no invalid fmt. data = %p, idx=%d",
+ __func__, data, buffer_id);
+ }
+ /* Unlock and lock around the callback. */
+ /* Sometimes 'disable_msg' is issued in the callback context, */
+ /* leading to deadlock */
+ camHal->lock.unlock();
+ if((camHal->msgEnabledFlag & CAMERA_MSG_PREVIEW_FRAME) &&
+ camHal->data_cb){
+ ALOGD("%s: before data callback", __func__);
+ camHal->data_cb(msgType, data, 0,metadata, camHal->cb_ctxt);
+ ALOGD("%s: after data callback: %p", __func__, camHal->data_cb);
+ }
+ camHal->lock.lock();
+ if (previewMem)
+ previewMem->release(previewMem);
+#endif
+
+ }//while(1)
+ ALOGD("%s: X", __func__);
+ return (void *)0;
+}
+
+/******************************************************************************
+ * Function: get_uvc_device
+ * Description: This function loops through /dev/video entries and probes with
+ * UVCIOC query. If the device responds to the query, then it is
+ * detected as UVC webcam
+ * Input parameters:
+ * devname - String pointer. The function return dev entry
+ * name in this string
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+static int get_uvc_device(char *devname)
+{
+ char temp_devname[FILENAME_LENGTH];
+ FILE *fp = NULL;
+ int i = 0, ret = 0, fd;
+
+ ALOGD("%s: E", __func__);
+#if 1
+ strncpy(devname, "/dev/video1", FILENAME_LENGTH);
+
+/*
+ struct stat st;
+
+ strncpy(dev_name, "/dev/video1", FILENAME_LENGTH);
+ if (-1 == stat(dev_name, &st)) {
+ ALOGE("%s: Cannot identify '%s': %d, %s\n",
+ __func__, dev_name, errno, strerror(errno));
+ }
+
+ if (!S_ISCHR(st.st_mode)) {
+ ALOGE("%s: %s is no device\n", __func__, dev_name);
+ rc = -1;
+ }
+*/
+
+#else
+
+ *devname = '\0';
+ /************************************************************************/
+ /* - List all /dev/video* entries to a file */
+ /* - Open the video list file and loop through the list */
+ /* - Send UVC specific control query and check the response */
+ /* - If device responds to the query as success, device is UVC webcam */
+ /************************************************************************/
+
+ /************************************************************************/
+ /* - List all /dev/video* entries to a file */
+ /************************************************************************/
+ /* Temporarily commented out. This logic doesnt seem to be working */
+ //system("ls > /data/video_dev_list");
+
+ /************************************************************************/
+ /* - Open the video list file and loop through the list */
+ /************************************************************************/
+
+ /* Temporarily commented out. This logic doesnt seem to be working */
+ /*
+ fp = fopen("/data/video_dev_list", "rb");
+ if(!fp) {
+ ALOGE("%s: Error in opening /data/video_dev_list ", __func__);
+ return -1;
+ }
+ */
+
+ /* Temporarily commented out. Looping logic changed due to issue in */
+ /* executing system("ls > /data/video_dev_list") */
+ //while(EOF != fscanf(fp, "%s", devname)){
+ while(1){
+ uvc_xu_control_query xqry;
+
+ sprintf(temp_devname, "/dev/video%d", i);
+ ALOGD("%s: Probing %s \n", __func__, temp_devname);
+
+ fd = open(temp_devname, O_RDWR /* required */ | O_NONBLOCK, 0);
+ if(-1 != fd){
+ memset(&xqry, 0, sizeof(uvc_xu_control_query));
+ ret = ioctl(fd, UVCIOC_CTRL_QUERY, &xqry);
+ ALOGD("%s: UVCIOC ret: %d, errno: %d", __func__, ret, errno);
+ /****************************************************************/
+ /* if UVCIOC is executed successfully, ret = 0 */
+ /* if UVCIOC is executed but Control Unit = 0 does not exist, */
+ /* ret = -1 and errno = ENOENT */
+ /* if UVCIOC doesnot execute, ret = -1 and errno = EINVAL */
+ /****************************************************************/
+ if((0 == ret) || (ret && (ENOENT == errno))){
+ ALOGD("%s: Found UVC node: %s\n", __func__, temp_devname);
+ strncpy(devname, temp_devname, FILENAME_LENGTH);
+ /* Exit the loop at the first UVC node detection */
+ break;
+ }
+ close(fd);
+ }
+ /* Temporarily logic to probe video0 to video10 nodes */
+ if(i++ > 10)
+ {
+ if(fp)
+ fclose(fp);
+ break;
+ }
+ }
+#endif /* #if 0 */
+ ALOGD("%s: X", __func__);
+ return 0;
+} /* get_uvc_device */
+
+/******************************************************************************
+ * Function: fileDump
+ * Description: This is a utility function to dump buffers into a file
+ *
+ * Input parameters:
+ * fn - File name string
+ * data - pointer to character buffer that needs to be dumped
+ * length - Length of the buffer to be dumped
+ * frm_cnt - Pointer to frame count. This count is incremented by this
+ * function on successful file write
+ * Return values:
+ * 0 Success
+ * -1 Error
+ * Notes: none
+ *****************************************************************************/
+static int fileDump(const char* fn, char* data, int length, int* frm_cnt)
+{
+
+ FILE *fp = NULL;
+ if (0 == *frm_cnt) {
+ fp = fopen(fn, "wb");
+ if (NULL == fp) {
+ ALOGE("%s: Error in opening %s", __func__, fn);
+ }
+ fclose(fp);
+ }
+ fp = fopen(fn, "ab");
+ if (NULL == fp) {
+ ALOGE("%s: Error in opening %s", __func__, fn);
+ }
+ fwrite(data, 1, length, fp);
+ fclose(fp);
+ (*frm_cnt)++;
+ ALOGD("%s: Written %d bytes for frame:%d, in %s",
+ __func__, length, *frm_cnt, fn);
+
+ return 0;
+}
+
+/******************************************************************************
+ * Function: launchTakePictureThread
+ * Description: This is a wrapper function to start take picture thread
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int launchTakePictureThread(camera_hardware_t *camHal)
+{
+ ALOGD("%s: E", __func__);
+ int rc = 0;
+
+ if(!camHal) {
+ ALOGE("%s: camHal is NULL", __func__);
+ return -1;
+ }
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ /* create the thread in detatched state, when the thread exits all */
+ /* memory resources are freed up */
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&camHal->takePictureThread, &attr, takePictureThread, camHal);
+
+ ALOGD("%s: X", __func__);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: takePictureThread
+ * Description: This function is associated with take picture thread
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static void * takePictureThread(void *hcamHal)
+{
+ int rc = 0;
+ int buffer_id = 0;
+ pid_t tid = 0;
+ camera_hardware_t *camHal = NULL;
+ int msgType = 0;
+ int jpegLength = 0;
+ QCameraHalMemInfo_t *mem_info = NULL;
+
+ camHal = (camera_hardware_t *)hcamHal;
+ ALOGI("%s: E", __func__);
+
+ if(!camHal) {
+ ALOGE("%s: camHal is NULL", __func__);
+ return NULL ;
+ }
+
+ tid = gettid();
+ /* TBR: Set appropriate thread priority */
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_NORMAL);
+ prctl(PR_SET_NAME, (unsigned long)"Camera HAL preview thread", 0, 0, 0);
+
+ /************************************************************************/
+ /* - If requested for shutter notfication, notify */
+ /* - Initialize USB camera with snapshot parameters */
+ /* - Time wait (select) on camera fd for camera frame availability */
+ /* - Dequeue capture buffer from USB camera */
+ /* - Send capture buffer to JPEG encoder for JPEG compression */
+ /* - If jpeg frames callback is requested, callback with jpeg buffers */
+ /* - Enqueue capture buffer back to USB camera */
+ /* - Free USB camera resources and close camera */
+ /* - If preview was stopped for taking picture, restart the preview */
+ /************************************************************************/
+
+ Mutex::Autolock autoLock(camHal->lock);
+ /************************************************************************/
+ /* - If requested for shutter notfication, notify */
+ /************************************************************************/
+#if 0 /* TBD: Temporarily commented out due to an issue. Sometimes it takes */
+ /* long time to get back the lock once unlocked and notify callback */
+ if (camHal->msgEnabledFlag & CAMERA_MSG_SHUTTER){
+ camHal->lock.unlock();
+ camHal->notify_cb(CAMERA_MSG_SHUTTER, 0, 0, camHal->cb_ctxt);
+ camHal->lock.lock();
+ }
+#endif
+ /************************************************************************/
+ /* - Initialize USB camera with snapshot parameters */
+ /************************************************************************/
+ USB_CAM_OPEN(camHal);
+
+#if JPEG_ON_USB_CAMERA
+ rc = initUsbCamera(camHal, camHal->pictWidth, camHal->pictHeight,
+ V4L2_PIX_FMT_MJPEG);
+#else
+ rc = initUsbCamera(camHal, camHal->pictWidth, camHal->pictHeight,
+ V4L2_PIX_FMT_YUYV);
+#endif
+ ERROR_CHECK_EXIT_THREAD(rc, "initUsbCamera");
+
+ rc = startUsbCamCapture(camHal);
+ ERROR_CHECK_EXIT_THREAD(rc, "startUsbCamCapture");
+
+ /************************************************************************/
+ /* - Time wait (select) on camera fd for camera frame availability */
+ /************************************************************************/
+ {
+ fd_set fds;
+ struct timeval tv;
+ int r = 0;
+
+ FD_ZERO(&fds);
+ FD_SET(camHal->fd, &fds);
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ do{
+ ALOGD("%s: b4 select on camHal->fd : %d", __func__, camHal->fd);
+ r = select(camHal->fd + 1, &fds, NULL, NULL, &tv);
+ ALOGD("%s: after select", __func__);
+ }while((0 == r) || ((-1 == r) && (EINTR == errno)));
+
+ if ((-1 == r) && (EINTR != errno)){
+ ALOGE("%s: FDSelect ret = %d error: %d", __func__, r, errno);
+ return (void *)-1;
+ }
+
+ }
+ /************************************************************************/
+ /* - Dequeue capture buffer from USB camera */
+ /************************************************************************/
+ if (0 == get_buf_from_cam(camHal))
+ ALOGD("%s: get_buf_from_cam success", __func__);
+ else
+ ALOGE("%s: get_buf_from_cam error", __func__);
+
+ /************************************************************************/
+ /* - Send capture buffer to JPEG encoder for JPEG compression */
+ /************************************************************************/
+ mem_info = &camHal->pictMem.mem_info[0];
+ mem_info->size = MAX_JPEG_BUFFER_SIZE;
+
+ rc = allocate_ion_memory(mem_info,
+ ((0x1 << CAMERA_ZSL_ION_HEAP_ID) |
+ (0x1 << CAMERA_ZSL_ION_FALLBACK_HEAP_ID)));
+ if(rc)
+ ALOGE("%s: ION memory allocation failed", __func__);
+
+ camHal->pictMem.camera_memory[0] = camHal->get_memory(
+ mem_info->fd, mem_info->size, 1, camHal->cb_ctxt);
+ if(!camHal->pictMem.camera_memory[0])
+ ALOGE("%s: get_mem failed", __func__);
+
+#if FREAD_JPEG_PICTURE
+ jpegLength = readFromFile("/data/tempVGA.jpeg",
+ (char*)camHal->pictMem.camera_memory[0]->data,
+ camHal->pictMem.camera_memory[0]->size);
+ camHal->pictMem.camera_memory[0]->size = jpegLength;
+
+#elif JPEG_ON_USB_CAMERA
+ memcpy((char*)camHal->pictMem.camera_memory[0]->data,
+ (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
+ camHal->curCaptureBuf.bytesused);
+ camHal->pictMem.camera_memory[0]->size = camHal->curCaptureBuf.bytesused;
+ jpegLength = camHal->curCaptureBuf.bytesused;
+
+#else
+ rc = encodeJpeg(camHal);
+ ERROR_CHECK_EXIT_THREAD(rc, "jpeg_encode");
+#endif
+ if(jpegLength <= 0)
+ ALOGI("%s: jpegLength : %d", __func__, jpegLength);
+
+ ALOGD("%s: jpegLength : %d", __func__, jpegLength);
+ /************************************************************************/
+ /* - If jpeg frames callback is requested, callback with jpeg buffers */
+ /************************************************************************/
+ /* TBD: CAMERA_MSG_RAW_IMAGE data call back */
+
+ if ((camHal->msgEnabledFlag & CAMERA_MSG_COMPRESSED_IMAGE) &&
+ (camHal->data_cb)){
+ /* Unlock temporarily, callback might call HAL api in turn */
+ camHal->lock.unlock();
+
+ camHal->data_cb(CAMERA_MSG_COMPRESSED_IMAGE,
+ camHal->pictMem.camera_memory[0],
+ 0, NULL, camHal->cb_ctxt);
+ camHal->lock.lock();
+ }
+
+ /* release heap memory after the call back */
+ if(camHal->pictMem.camera_memory[0])
+ camHal->pictMem.camera_memory[0]->release(
+ camHal->pictMem.camera_memory[0]);
+
+ rc = deallocate_ion_memory(mem_info);
+ if(rc)
+ ALOGE("%s: ION memory de-allocation failed", __func__);
+
+ /************************************************************************/
+ /* - Enqueue capture buffer back to USB camera */
+ /************************************************************************/
+ if(0 == put_buf_to_cam(camHal)) {
+ ALOGD("%s: put_buf_to_cam success", __func__);
+ }
+ else
+ ALOGE("%s: put_buf_to_cam error", __func__);
+
+ /************************************************************************/
+ /* - Free USB camera resources and close camera */
+ /************************************************************************/
+ rc = stopUsbCamCapture(camHal);
+ ERROR_CHECK_EXIT_THREAD(rc, "stopUsbCamCapture");
+
+ rc = unInitV4L2mmap(camHal);
+ ERROR_CHECK_EXIT_THREAD(rc, "unInitV4L2mmap");
+
+ USB_CAM_CLOSE(camHal);
+ /************************************************************************/
+ /* - If preview was stopped for taking picture, restart the preview */
+ /************************************************************************/
+ if(camHal->prvwStoppedForPicture)
+ {
+ struct camera_device device;
+ device.priv = (void *)camHal;
+
+ USB_CAM_OPEN(camHal);
+ /* Unlock temporarily coz usbcam_start_preview has a lock */
+ camHal->lock.unlock();
+ rc = usbcam_start_preview(&device);
+ if(rc)
+ ALOGE("%s: start_preview error after take picture", __func__);
+ camHal->lock.lock();
+ camHal->prvwStoppedForPicture = 0;
+ }
+
+ /* take picture activity is done */
+ camHal->takePictInProgress = 0;
+
+ ALOGI("%s: X", __func__);
+ return (void *)0;
+}
+
+/******************************************************************************
+ * Function: allocate_ion_memory
+ * Description: This function is allocates ION memory
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int allocate_ion_memory(QCameraHalMemInfo_t *mem_info, int ion_type)
+{
+ int rc = 0;
+ struct ion_handle_data handle_data;
+ struct ion_allocation_data alloc;
+ struct ion_fd_data ion_info_fd;
+ int main_ion_fd = 0;
+
+ main_ion_fd = open("/dev/ion", O_RDONLY);
+ if (main_ion_fd <= 0) {
+ ALOGE("Ion dev open failed %s\n", strerror(errno));
+ goto ION_OPEN_FAILED;
+ }
+
+ memset(&alloc, 0, sizeof(alloc));
+ alloc.len = mem_info->size;
+ /* to make it page size aligned */
+ alloc.len = (alloc.len + 4095) & (~4095);
+ alloc.align = 4096;
+ alloc.flags = ION_FLAG_CACHED;
+ alloc.heap_id_mask = ion_type;
+ rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
+ if (rc < 0) {
+ ALOGE("ION allocation failed\n");
+ goto ION_ALLOC_FAILED;
+ }
+
+ memset(&ion_info_fd, 0, sizeof(ion_info_fd));
+ ion_info_fd.handle = alloc.handle;
+ rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
+ if (rc < 0) {
+ ALOGE("ION map failed %s\n", strerror(errno));
+ goto ION_MAP_FAILED;
+ }
+
+ mem_info->main_ion_fd = main_ion_fd;
+ mem_info->fd = ion_info_fd.fd;
+ mem_info->handle = ion_info_fd.handle;
+ mem_info->size = alloc.len;
+ return 0;
+
+ION_MAP_FAILED:
+ memset(&handle_data, 0, sizeof(handle_data));
+ handle_data.handle = ion_info_fd.handle;
+ ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
+ION_ALLOC_FAILED:
+ close(main_ion_fd);
+ION_OPEN_FAILED:
+ return -1;
+}
+
+/******************************************************************************
+ * Function: deallocate_ion_memory
+ * Description: This function de allocates ION memory
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+static int deallocate_ion_memory(QCameraHalMemInfo_t *mem_info)
+{
+ struct ion_handle_data handle_data;
+ int rc = 0;
+
+ if (mem_info->fd > 0) {
+ close(mem_info->fd);
+ mem_info->fd = 0;
+ }
+
+ if (mem_info->main_ion_fd > 0) {
+ memset(&handle_data, 0, sizeof(handle_data));
+ handle_data.handle = mem_info->handle;
+ ioctl(mem_info->main_ion_fd, ION_IOC_FREE, &handle_data);
+ close(mem_info->main_ion_fd);
+ mem_info->main_ion_fd = 0;
+ }
+ return rc;
+}
+
+/******************************************************************************
+ * Function: readFromFile
+ * Description: This function reads data from the given file into given buffer
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * int bytesRead
+ *
+ * Notes: none
+ *****************************************************************************/
+static int readFromFile(char* fileName, char* buffer, int bufferSize)
+{
+ int bytesRead = 0, fileSize = 0;
+ FILE *fp;
+
+ fp = fopen(fileName, "rb");
+ if(!fp){
+ ALOGE("%s: Error in opening %s ", __func__, fileName);
+ return bytesRead;
+ }
+
+ /* If file is bigger for given buffer, exit */
+ if (fileSize > bufferSize){
+ ALOGE("%s: Error %d > %d", __func__, fileSize, bufferSize);
+ return bytesRead;
+ }
+
+ bytesRead = fread(buffer, 1, bufferSize, fp);
+ ALOGD(" %s: bytesRead: %d", __func__, bytesRead);
+
+ return bytesRead;
+}
+
+/******************************************************************************
+ * Function: encodeJpeg
+ * Description: This function initializes Jpeg encoder and calls jpeg encoder
+ * call and waits for the encode to complete
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No Error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+int encodeJpeg(camera_hardware_t *camHal)
+{
+ int rc = 0;
+ mm_jpeg_ops_t mmJpegOps;
+ int jpegEncHdl = 0;
+ mm_jpeg_job mmJpegJob;
+ src_image_buffer_info *srcBuf = NULL;
+ QCameraHalMemInfo_t jpegInMemInfo;
+ camera_memory_t* jpegInMem;
+ uint32_t jobId;
+
+ ALOGI("%s: E", __func__);
+
+ /************************************************************************/
+ /* - Allocate Jpeg input buffer from ION memory */
+ /************************************************************************/
+ jpegInMemInfo.size = camHal->pictWidth * camHal->pictHeight * 2;
+ rc = allocate_ion_memory(&jpegInMemInfo,
+ ((0x1 << CAMERA_ZSL_ION_HEAP_ID) |
+ (0x1 << CAMERA_ZSL_ION_FALLBACK_HEAP_ID)));
+ ERROR_CHECK_EXIT(rc, "allocate_ion_memory");
+
+ jpegInMem = camHal->get_memory(
+ jpegInMemInfo.fd, jpegInMemInfo.size, 1, camHal->cb_ctxt);
+ if(!jpegInMem){
+ ALOGE("%s: get_mem failed", __func__);
+ return -1;
+ }
+
+ rc = convert_YUYV_to_420_NV12(
+ (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
+ (char *)jpegInMem->data, camHal->pictWidth, camHal->pictHeight);
+ ERROR_CHECK_EXIT(rc, "convert_YUYV_to_420_NV12");
+ /************************************************************************/
+ /* - Populate JPEG encoding parameters from the camHal context */
+ /************************************************************************/
+ memset(&mmJpegJob, 0, sizeof(mmJpegJob));
+
+ mmJpegJob.job_type = JPEG_JOB_TYPE_ENCODE;
+ mmJpegJob.encode_job.jpeg_cb = jpegEncodeCb;
+ mmJpegJob.encode_job.userdata = (void *)camHal;
+ /* TBD: Rotation to be set from settings sent from app */
+ mmJpegJob.encode_job.encode_parm.rotation = 0;
+ mmJpegJob.encode_job.encode_parm.exif_numEntries = 0;
+ mmJpegJob.encode_job.encode_parm.exif_data = NULL;
+
+ /* TBD: Add thumbnail support */
+ mmJpegJob.encode_job.encode_parm.buf_info.src_imgs.src_img_num = 1;
+ mmJpegJob.encode_job.encode_parm.buf_info.src_imgs.is_video_frame = 0;
+
+ /* Fill main image information */
+ srcBuf = &mmJpegJob.encode_job.encode_parm.buf_info.src_imgs.src_img[0];
+ srcBuf->type = JPEG_SRC_IMAGE_TYPE_MAIN;
+ srcBuf->img_fmt = JPEG_SRC_IMAGE_FMT_YUV;
+ /* TBD: convert from YUYV to CRCBH2V2 */
+ srcBuf->color_format = MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
+ srcBuf->num_bufs = 1;
+ srcBuf->src_image[0].fd = jpegInMemInfo.fd;
+ srcBuf->src_image[0].buf_vaddr = (uint8_t*)jpegInMem->data;
+ //srcBuf->src_image[0].offset = 0;
+ srcBuf->src_dim.width = camHal->pictWidth;
+ srcBuf->src_dim.height = camHal->pictHeight;
+ srcBuf->out_dim.width = camHal->pictWidth;
+ srcBuf->out_dim.height = camHal->pictHeight;
+ srcBuf->crop.offset_x = 0;
+ srcBuf->crop.offset_y = 0;
+ srcBuf->crop.width = srcBuf->src_dim.width;
+ srcBuf->crop.height = srcBuf->src_dim.height;
+ srcBuf->quality = camHal->pictJpegQlty;
+
+ /* TBD:Fill thumbnail image information */
+
+ /* Fill out buf information */
+ mmJpegJob.encode_job.encode_parm.buf_info.sink_img.buf_vaddr =
+ (uint8_t*)camHal->pictMem.camera_memory[0]->data;
+ mmJpegJob.encode_job.encode_parm.buf_info.sink_img.fd = 0;
+ /* TBD: hard coded for 1.5 bytes per pixel */
+ mmJpegJob.encode_job.encode_parm.buf_info.sink_img.buf_len =
+ camHal->pictWidth * camHal->pictHeight * 1.5;
+
+ /************************************************************************/
+ /* - Initialize jpeg encoder and call Jpeg encoder start */
+ /************************************************************************/
+ memset(&mmJpegOps, 0, sizeof(mm_jpeg_ops_t));
+ jpegEncHdl = jpeg_open(&mmJpegOps);
+ if(!jpegEncHdl){
+ ALOGE("%s: Failed to open Jpeg Encoder instance", __func__);
+ }else
+ ALOGD("%s: jpegEncHdl = %d", __func__, jpegEncHdl);
+
+ camHal->jpegEncInProgress = 1;
+ rc = mmJpegOps.start_job(jpegEncHdl, &mmJpegJob, &jobId);
+
+ /************************************************************************/
+ /* - Wait for JPEG encoder to complete encoding */
+ /************************************************************************/
+ pthread_mutex_init(&camHal->jpegEncMutex, NULL);
+ pthread_cond_init(&camHal->jpegEncCond, NULL);
+
+ pthread_mutex_lock(&camHal->jpegEncMutex);
+ while(camHal->jpegEncInProgress)
+ pthread_cond_wait(&camHal->jpegEncCond, &camHal->jpegEncMutex);
+ pthread_mutex_unlock(&camHal->jpegEncMutex);
+
+ /************************************************************************/
+ /* - De-allocate Jpeg input buffer from ION memory */
+ /************************************************************************/
+ if(jpegInMem)
+ jpegInMem->release(jpegInMem);
+
+ rc = deallocate_ion_memory(&jpegInMemInfo);
+ if(rc)
+ ALOGE("%s: ION memory de-allocation failed", __func__);
+
+ ALOGI("%s: X rc = %d", __func__, rc);
+ return rc;
+}
+
+/******************************************************************************
+ * Function: jpegEncodeCb
+ * Description: This is a call back function registered with JPEG encoder.
+ * Jpeg encoder calls this function on completion of encoding
+ *
+ * Input parameters:
+ * camHal - camera HAL handle
+ *
+ * Return values:
+ * 0 No Error
+ * -1 Error
+ *
+ * Notes: none
+ *****************************************************************************/
+void jpegEncodeCb (jpeg_job_status_t status,
+ uint8_t thumbnailDroppedFlag,
+ uint32_t client_hdl,
+ uint32_t jobId,
+ uint8_t* out_data,
+ uint32_t data_size,
+ void *userData)
+{
+ int rc = 0;
+ camera_hardware_t *camHal = NULL;
+
+ ALOGI("%s: E status = %d", __func__, status);
+
+ camHal = (camera_hardware_t*) userData;
+
+ if(JPEG_JOB_STATUS_DONE == status){
+ ALOGD("%s: JPEG encode successful. out_data:%p, size: %d", __func__,
+ out_data, data_size);
+ camHal->jpegEncInProgress = 0;
+ }
+
+ pthread_mutex_lock(&camHal->jpegEncMutex);
+ pthread_cond_signal(&camHal->jpegEncCond);
+ pthread_mutex_unlock(&camHal->jpegEncMutex);
+
+ ALOGI("%s: X", __func__);
+ return;
+}
+
+/******************************************************************************/
+}; // namespace android