summaryrefslogtreecommitdiffstats
path: root/camera
diff options
context:
space:
mode:
authorZiyan <jaraidaniel@gmail.com>2016-01-03 14:19:34 +0100
committerDániel Járai <jaraidaniel@gmail.com>2016-01-03 06:57:39 -0800
commite0c5a929875a3f858926d7fec7e236d6db1006a3 (patch)
tree175f7cedf1c33e09e5ede924348530827637e4fb /camera
parent0b9a81bcf50f519eaaf7933984ec975f275f0530 (diff)
downloaddevice_samsung_tuna-e0c5a929875a3f858926d7fec7e236d6db1006a3.zip
device_samsung_tuna-e0c5a929875a3f858926d7fec7e236d6db1006a3.tar.gz
device_samsung_tuna-e0c5a929875a3f858926d7fec7e236d6db1006a3.tar.bz2
Add camera sources in-tree
From hardware/ti/omap4 revision e57f2b6. Change-Id: I2e6164fdf6c0e2a2e75aee3bba3fe58a9c470add
Diffstat (limited to 'camera')
-rw-r--r--camera/ANativeWindowDisplayAdapter.cpp1263
-rw-r--r--camera/Android.mk297
-rw-r--r--camera/AppCallbackNotifier.cpp2002
-rw-r--r--camera/BaseCameraAdapter.cpp2744
-rw-r--r--camera/BufferSourceAdapter.cpp1007
-rw-r--r--camera/CameraHal.cpp5012
-rw-r--r--camera/CameraHalCommon.cpp233
-rw-r--r--camera/CameraHalUtilClasses.cpp361
-rw-r--r--camera/CameraHal_Module.cpp840
-rw-r--r--camera/CameraParameters.cpp240
-rw-r--r--camera/CameraProperties.cpp135
-rw-r--r--camera/DecoderFactory.cpp59
-rw-r--r--camera/Decoder_libjpeg.cpp301
-rw-r--r--camera/Encoder_libjpeg.cpp549
-rw-r--r--camera/FrameDecoder.cpp204
-rw-r--r--camera/MemoryManager.cpp237
-rw-r--r--camera/NV12_resize.cpp290
-rw-r--r--camera/OMXCameraAdapter/OMX3A.cpp2161
-rw-r--r--camera/OMXCameraAdapter/OMXAlgo.cpp1355
-rw-r--r--camera/OMXCameraAdapter/OMXCameraAdapter.cpp4534
-rw-r--r--camera/OMXCameraAdapter/OMXCapabilities.cpp2513
-rw-r--r--camera/OMXCameraAdapter/OMXCapture.cpp2098
-rw-r--r--camera/OMXCameraAdapter/OMXDCC.cpp227
-rw-r--r--camera/OMXCameraAdapter/OMXDccDataSave.cpp361
-rw-r--r--camera/OMXCameraAdapter/OMXDefaults.cpp87
-rw-r--r--camera/OMXCameraAdapter/OMXExif.cpp838
-rw-r--r--camera/OMXCameraAdapter/OMXFD.cpp504
-rw-r--r--camera/OMXCameraAdapter/OMXFocus.cpp892
-rw-r--r--camera/OMXCameraAdapter/OMXMetadata.cpp181
-rw-r--r--camera/OMXCameraAdapter/OMXReprocess.cpp382
-rw-r--r--camera/OMXCameraAdapter/OMXZoom.cpp289
-rw-r--r--camera/OmxFrameDecoder.cpp1077
-rw-r--r--camera/SensorListener.cpp236
-rw-r--r--camera/SwFrameDecoder.cpp85
-rw-r--r--camera/TICameraParameters.cpp241
-rw-r--r--camera/V4LCameraAdapter/V4LCameraAdapter.cpp1684
-rw-r--r--camera/V4LCameraAdapter/V4LCapabilities.cpp365
-rw-r--r--camera/android-api.mk39
-rw-r--r--camera/inc/ANativeWindowDisplayAdapter.h196
-rw-r--r--camera/inc/BaseCameraAdapter.h308
-rw-r--r--camera/inc/BufferSourceAdapter.h228
-rw-r--r--camera/inc/CameraHal.h1562
-rw-r--r--camera/inc/CameraProperties.h244
-rw-r--r--camera/inc/Common.h65
-rw-r--r--camera/inc/DecoderFactory.h35
-rw-r--r--camera/inc/Decoder_libjpeg.h58
-rw-r--r--camera/inc/Encoder_libjpeg.h226
-rw-r--r--camera/inc/FrameDecoder.h173
-rw-r--r--camera/inc/General3A_Settings.h295
-rw-r--r--camera/inc/NV12_resize.h135
-rw-r--r--camera/inc/OMXCameraAdapter/OMXCameraAdapter.h1235
-rw-r--r--camera/inc/OMXCameraAdapter/OMXDCC.h44
-rw-r--r--camera/inc/OMXCameraAdapter/OMXSceneModeTables.h759
-rw-r--r--camera/inc/OmxFrameDecoder.h204
-rw-r--r--camera/inc/SensorListener.h105
-rw-r--r--camera/inc/SwFrameDecoder.h47
-rw-r--r--camera/inc/TICameraParameters.h270
-rw-r--r--camera/inc/V4LCameraAdapter/V4LCameraAdapter.h262
-rw-r--r--camera/inc/VideoMetadata.h32
59 files changed, 42406 insertions, 0 deletions
diff --git a/camera/ANativeWindowDisplayAdapter.cpp b/camera/ANativeWindowDisplayAdapter.cpp
new file mode 100644
index 0000000..396e6d4
--- /dev/null
+++ b/camera/ANativeWindowDisplayAdapter.cpp
@@ -0,0 +1,1263 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ANativeWindowDisplayAdapter.h"
+#include <OMX_IVCommon.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferMapper.h>
+#include <hal_public.h>
+
+namespace Ti {
+namespace Camera {
+
+///Constant declarations
+///@todo Check the time units
+const int ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT = 1000; // seconds
+
+//Suspends buffers after given amount of failed dq's
+const int ANativeWindowDisplayAdapter::FAILED_DQS_TO_SUSPEND = 3;
+
+
+OMX_COLOR_FORMATTYPE toOMXPixFormat(const char* parameters_format)
+{
+ OMX_COLOR_FORMATTYPE pixFormat;
+
+ if ( parameters_format != NULL )
+ {
+ if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
+ {
+ CAMHAL_LOGDA("CbYCrY format selected");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ }
+ else if(strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
+ {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+ else if(strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0)
+ {
+ CAMHAL_LOGDA("RGB565 format selected");
+ pixFormat = OMX_COLOR_Format16bitRGB565;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Invalid format, NV12 format selected as default");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+ }
+ else {
+ CAMHAL_LOGEA("Preview format is NULL, defaulting to NV12");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+
+ return pixFormat;
+}
+
+/*--------------------ANativeWindowDisplayAdapter Class STARTS here-----------------------------*/
+
+
+/**
+ * Display Adapter class STARTS here..
+ */
+ANativeWindowDisplayAdapter::ANativeWindowDisplayAdapter():mDisplayThread(NULL),
+ mDisplayState(ANativeWindowDisplayAdapter::DISPLAY_INIT),
+ mDisplayEnabled(false),
+ mBufferCount(0),
+ mUseExternalBufferLocking(false)
+
+
+
+{
+ LOG_FUNCTION_NAME;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ mShotToShot = false;
+ mStartCapture.tv_sec = 0;
+ mStartCapture.tv_usec = 0;
+ mStandbyToShot.tv_sec = 0;
+ mStandbyToShot.tv_usec = 0;
+ mMeasureStandby = false;
+#endif
+
+ mPixelFormat = NULL;
+ mBuffers = NULL;
+ mOffsetsMap = NULL;
+ mFrameProvider = NULL;
+ mANativeWindow = NULL;
+
+ mFrameWidth = 0;
+ mFrameHeight = 0;
+ mPreviewWidth = 0;
+ mPreviewHeight = 0;
+
+ mSuspend = false;
+ mFailedDQs = 0;
+
+ mPaused = false;
+ mXOff = -1;
+ mYOff = -1;
+ mFirstInit = false;
+
+ mFD = -1;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+ANativeWindowDisplayAdapter::~ANativeWindowDisplayAdapter()
+{
+ Utils::Semaphore sem;
+ Utils::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ ///If Frame provider exists
+ if (mFrameProvider) {
+ // Unregister with the frame provider
+ mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
+ delete mFrameProvider;
+ mFrameProvider = NULL;
+ }
+
+ ///The ANativeWindow object will get destroyed here
+ destroy();
+
+ ///If Display thread exists
+ if(mDisplayThread.get())
+ {
+ ///Kill the display thread
+ sem.Create();
+ msg.command = DisplayThread::DISPLAY_EXIT;
+
+ // Send the semaphore to signal once the command is completed
+ msg.arg1 = &sem;
+
+ ///Post the message to display thread
+ mDisplayThread->msgQ().put(&msg);
+
+ ///Wait for the ACK - implies that the thread is now started and waiting for frames
+ sem.Wait();
+
+ // Exit and cleanup the thread
+ mDisplayThread->requestExitAndWait();
+
+ // Delete the display thread
+ mDisplayThread.clear();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+status_t ANativeWindowDisplayAdapter::initialize()
+{
+ LOG_FUNCTION_NAME;
+
+ ///Create the display thread
+ mDisplayThread = new DisplayThread(this);
+ if ( !mDisplayThread.get() )
+ {
+ CAMHAL_LOGEA("Couldn't create display thread");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_MEMORY;
+ }
+
+ ///Start the display thread
+ status_t ret = mDisplayThread->run("DisplayThread", android::PRIORITY_URGENT_DISPLAY);
+ if ( ret != NO_ERROR )
+ {
+ CAMHAL_LOGEA("Couldn't run display thread");
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+int ANativeWindowDisplayAdapter::setPreviewWindow(preview_stream_ops_t* window)
+{
+ LOG_FUNCTION_NAME;
+ ///Note that Display Adapter cannot work without a valid window object
+ if ( !window)
+ {
+ CAMHAL_LOGEA("NULL window object passed to DisplayAdapter");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ if ( window == mANativeWindow ) {
+ return ALREADY_EXISTS;
+ }
+
+ ///Destroy the existing window object, if it exists
+ destroy();
+
+ ///Move to new window obj
+ mANativeWindow = window;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+int ANativeWindowDisplayAdapter::setFrameProvider(FrameNotifier *frameProvider)
+{
+ LOG_FUNCTION_NAME;
+
+ // Check for NULL pointer
+ if ( !frameProvider ) {
+ CAMHAL_LOGEA("NULL passed for frame provider");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ //Release any previous frame providers
+ if ( NULL != mFrameProvider ) {
+ delete mFrameProvider;
+ }
+
+ /** Dont do anything here, Just save the pointer for use when display is
+ actually enabled or disabled
+ */
+ mFrameProvider = new FrameProvider(frameProvider, this, frameCallbackRelay);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+int ANativeWindowDisplayAdapter::setErrorHandler(ErrorNotifier *errorNotifier)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == errorNotifier ) {
+ CAMHAL_LOGEA("Invalid Error Notifier reference");
+ ret = BAD_VALUE;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mErrorNotifier = errorNotifier;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+status_t ANativeWindowDisplayAdapter::setSnapshotTimeRef(struct timeval *refTime)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL != refTime )
+ {
+ android::AutoMutex lock(mLock);
+ memcpy(&mStartCapture, refTime, sizeof(struct timeval));
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+#endif
+
+
+int ANativeWindowDisplayAdapter::enableDisplay(int width, int height, struct timeval *refTime)
+{
+ Utils::Semaphore sem;
+ Utils::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ if ( mDisplayEnabled )
+ {
+ CAMHAL_LOGDA("Display is already enabled");
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ if ( NULL != refTime )
+ {
+ android::AutoMutex lock(mLock);
+ memcpy(&mStandbyToShot, refTime, sizeof(struct timeval));
+ mMeasureStandby = true;
+ }
+
+#endif
+
+ //Send START_DISPLAY COMMAND to display thread. Display thread will start and then wait for a message
+ sem.Create();
+ msg.command = DisplayThread::DISPLAY_START;
+
+ // Send the semaphore to signal once the command is completed
+ msg.arg1 = &sem;
+
+ ///Post the message to display thread
+ mDisplayThread->msgQ().put(&msg);
+
+ ///Wait for the ACK - implies that the thread is now started and waiting for frames
+ sem.Wait();
+
+ // Register with the frame provider for frames
+ mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
+
+ mDisplayEnabled = true;
+ mPreviewWidth = width;
+ mPreviewHeight = height;
+
+ CAMHAL_LOGVB("mPreviewWidth = %d mPreviewHeight = %d", mPreviewWidth, mPreviewHeight);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+int ANativeWindowDisplayAdapter::disableDisplay(bool cancel_buffer)
+{
+ status_t ret = NO_ERROR;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+
+ LOG_FUNCTION_NAME;
+
+ if(!mDisplayEnabled)
+ {
+ CAMHAL_LOGDA("Display is already disabled");
+ LOG_FUNCTION_NAME_EXIT;
+ return ALREADY_EXISTS;
+ }
+
+ // Unregister with the frame provider here
+ mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ mFrameProvider->disableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
+ mFrameProvider->removeFramePointers();
+
+ if ( NULL != mDisplayThread.get() )
+ {
+ //Send STOP_DISPLAY COMMAND to display thread. Display thread will stop and dequeue all messages
+ // and then wait for message
+ Utils::Semaphore sem;
+ sem.Create();
+ Utils::Message msg;
+ msg.command = DisplayThread::DISPLAY_STOP;
+
+ // Send the semaphore to signal once the command is completed
+ msg.arg1 = &sem;
+
+ ///Post the message to display thread
+ mDisplayThread->msgQ().put(&msg);
+
+ ///Wait for the ACK for display to be disabled
+
+ sem.Wait();
+
+ }
+
+ android::AutoMutex lock(mLock);
+ {
+ ///Reset the display enabled flag
+ mDisplayEnabled = false;
+
+ // Reset pause flag since display is being disabled
+ mPaused = false;
+
+ ///Reset the offset values
+ mXOff = -1;
+ mYOff = -1;
+
+ ///Reset the frame width and height values
+ mFrameWidth =0;
+ mFrameHeight = 0;
+ mPreviewWidth = 0;
+ mPreviewHeight = 0;
+
+ if(cancel_buffer)
+ {
+ // Return the buffers to ANativeWindow here, the mFramesWithCameraAdapterMap is also cleared inside
+ returnBuffersToWindow();
+ }
+ else
+ {
+ mANativeWindow = NULL;
+ // Clear the frames with camera adapter map
+ mFramesWithCameraAdapterMap.clear();
+ }
+
+
+ }
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+status_t ANativeWindowDisplayAdapter::pauseDisplay(bool pause)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ {
+ android::AutoMutex lock(mLock);
+ mPaused = pause;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+
+void ANativeWindowDisplayAdapter::destroy()
+{
+ LOG_FUNCTION_NAME;
+
+ ///Check if the display is disabled, if not disable it
+ if ( mDisplayEnabled )
+ {
+ CAMHAL_LOGDA("WARNING: Calling destroy of Display adapter when display enabled. Disabling display..");
+ disableDisplay(false);
+ }
+
+ mBufferCount = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+// Implementation of inherited interfaces
+CameraBuffer* ANativeWindowDisplayAdapter::allocateBufferList(int width, int height, const char* format, int &bytes, int numBufs)
+{
+ LOG_FUNCTION_NAME;
+ status_t err;
+ int i = -1;
+ const int lnumBufs = numBufs;
+ int undequeued = 0;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ android::Rect bounds;
+
+ mBuffers = new CameraBuffer [lnumBufs];
+ memset (mBuffers, 0, sizeof(CameraBuffer) * lnumBufs);
+
+ mFramesType.clear();
+
+ if ( NULL == mANativeWindow ) {
+ return NULL;
+ }
+
+ // Set gralloc usage bits for window.
+ err = mANativeWindow->set_usage(mANativeWindow, CAMHAL_GRALLOC_USAGE);
+ if ( NO_ERROR != err ) {
+ CAMHAL_LOGE("Surface::setUsage failed: %s (%d)", strerror(-err), -err);
+
+ if ( NO_INIT == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+
+ return NULL;
+ }
+
+ CAMHAL_LOGDB("Number of buffers set to ANativeWindow %d", numBufs);
+ ///Set the number of buffers needed for camera preview
+ err = mANativeWindow->set_buffer_count(mANativeWindow, numBufs);
+ if ( NO_ERROR != err ) {
+ CAMHAL_LOGE("Surface::setBufferCount failed: %s (%d)", strerror(-err), -err);
+
+ if ( NO_INIT == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+
+ return NULL;
+ }
+ CAMHAL_LOGDB("Configuring %d buffers for ANativeWindow", numBufs);
+ mBufferCount = numBufs;
+
+
+ // Set window geometry
+ err = mANativeWindow->set_buffers_geometry(
+ mANativeWindow,
+ width,
+ height,
+ /*toOMXPixFormat(format)*/HAL_PIXEL_FORMAT_TI_NV12); // Gralloc only supports NV12 alloc!
+
+ if ( NO_ERROR != err ) {
+ CAMHAL_LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err);
+
+ if ( NO_INIT == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+
+ return NULL;
+ }
+
+ ///We just return the buffers from ANativeWindow, if the width and height are same, else (vstab, vnf case)
+ ///re-allocate buffers using ANativeWindow and then get them
+ ///@todo - Re-allocate buffers for vnf and vstab using the width, height, format, numBufs etc
+ if ( mBuffers == NULL )
+ {
+ CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers");
+ LOG_FUNCTION_NAME_EXIT;
+ return NULL;
+ }
+
+ mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued);
+ mPixelFormat = CameraHal::getPixelFormatConstant(format);
+
+ for ( i=0; i < mBufferCount; i++ )
+ {
+ buffer_handle_t *handle;
+ int stride; // dummy variable to get stride
+ // TODO(XXX): Do we need to keep stride information in camera hal?
+
+ err = mANativeWindow->dequeue_buffer(mANativeWindow, &handle, &stride);
+
+ if ( NO_ERROR != err ) {
+ CAMHAL_LOGE("Surface::dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+
+ if ( NO_INIT == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+
+ goto fail;
+ }
+
+ CAMHAL_LOGDB("got handle %p", handle);
+ mBuffers[i].opaque = (void *)handle;
+ mBuffers[i].type = CAMERA_BUFFER_ANW;
+ mBuffers[i].format = mPixelFormat;
+ mFramesWithCameraAdapterMap.add(handle, i);
+
+ // Tag remaining preview buffers as preview frames
+ if ( i >= ( mBufferCount - undequeued ) ) {
+ mFramesType.add( (int) mBuffers[i].opaque,
+ CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+
+ bytes = CameraHal::calculateBufferSize(format, width, height);
+
+ }
+
+ // lock the initial queueable buffers
+ bounds.left = 0;
+ bounds.top = 0;
+ bounds.right = width;
+ bounds.bottom = height;
+
+ for( i = 0; i < mBufferCount-undequeued; i++ )
+ {
+ void *y_uv[2];
+ buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
+
+ mANativeWindow->lock_buffer(mANativeWindow, handle);
+
+ mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+ mBuffers[i].mapped = y_uv[0];
+ mFrameProvider->addFramePointers(&mBuffers[i], y_uv);
+ if (mUseExternalBufferLocking) {
+ mapper.unlock(*handle);
+ }
+ }
+
+ // return the rest of the buffers back to ANativeWindow
+ for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++)
+ {
+ buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
+ err = mANativeWindow->cancel_buffer(mANativeWindow, handle);
+ if ( NO_ERROR != err ) {
+ CAMHAL_LOGE("Surface::cancelBuffer failed: %s (%d)", strerror(-err), -err);
+
+ if ( NO_INIT == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+
+ goto fail;
+ }
+ mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) mBuffers[i].opaque);
+ //LOCK UNLOCK TO GET YUV POINTERS
+ void *y_uv[2];
+ mapper.lock(*(buffer_handle_t *) mBuffers[i].opaque, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+ mBuffers[i].mapped = y_uv[0];
+ mFrameProvider->addFramePointers(&mBuffers[i], y_uv);
+ mapper.unlock(*(buffer_handle_t *) mBuffers[i].opaque);
+ }
+
+ mFirstInit = true;
+ mFrameWidth = width;
+ mFrameHeight = height;
+
+ return mBuffers;
+
+ fail:
+ // need to cancel buffers if any were dequeued
+ for (int start = 0; start < i && i > 0; start++) {
+ status_t err = mANativeWindow->cancel_buffer(mANativeWindow,
+ (buffer_handle_t *) mBuffers[start].opaque);
+ if ( NO_ERROR != err ) {
+ CAMHAL_LOGE("Surface::cancelBuffer failed w/ error 0x%08x", err);
+ break;
+ }
+ mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) mBuffers[start].opaque);
+ }
+
+ freeBufferList(mBuffers);
+
+ CAMHAL_LOGEA("Error occurred, performing cleanup");
+
+ if ( NULL != mErrorNotifier.get() ) {
+ mErrorNotifier->errorNotify(NO_MEMORY);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NULL;
+
+}
+
+CameraBuffer* ANativeWindowDisplayAdapter::getBufferList(int *numBufs) {
+ LOG_FUNCTION_NAME;
+ if (numBufs) *numBufs = -1;
+
+ return NULL;
+}
+
+uint32_t * ANativeWindowDisplayAdapter::getOffsets()
+{
+ const int lnumBufs = mBufferCount;
+
+ LOG_FUNCTION_NAME;
+
+ // TODO(XXX): Need to remove getOffsets from the API. No longer needed
+
+ if ( NULL == mANativeWindow )
+ {
+ CAMHAL_LOGEA("mANativeWindow reference is missing");
+ goto fail;
+ }
+
+ if( mBuffers == NULL)
+ {
+ CAMHAL_LOGEA("Buffers not allocated yet!!");
+ goto fail;
+ }
+
+ if(mOffsetsMap == NULL)
+ {
+ mOffsetsMap = new uint32_t[lnumBufs];
+ for(int i = 0; i < mBufferCount; i++)
+ {
+ mOffsetsMap[i] = 0;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return mOffsetsMap;
+
+ fail:
+
+ if ( NULL != mOffsetsMap )
+ {
+ delete [] mOffsetsMap;
+ mOffsetsMap = NULL;
+ }
+
+ if ( NULL != mErrorNotifier.get() ) {
+ mErrorNotifier->errorNotify(INVALID_OPERATION);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NULL;
+}
+
+status_t ANativeWindowDisplayAdapter::minUndequeueableBuffers(int& undequeueable) {
+ LOG_FUNCTION_NAME;
+ status_t ret = NO_ERROR;
+
+ if(!mANativeWindow) {
+ ret = INVALID_OPERATION;
+ goto end;
+ }
+
+ ret = mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeueable);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("get_min_undequeued_buffer_count failed: %s (%d)", strerror(-ret), -ret);
+
+ if ( NO_INIT == ret ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+
+ return ret;
+ }
+
+ end:
+ return ret;
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+status_t ANativeWindowDisplayAdapter::maxQueueableBuffers(unsigned int& queueable)
+{
+ LOG_FUNCTION_NAME;
+ status_t ret = NO_ERROR;
+ int undequeued = 0;
+
+ if(mBufferCount == 0)
+ {
+ ret = INVALID_OPERATION;
+ goto end;
+ }
+
+ ret = minUndequeueableBuffers(undequeued);
+ if (ret != NO_ERROR) {
+ goto end;
+ }
+
+ queueable = mBufferCount - undequeued;
+
+ end:
+ return ret;
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+int ANativeWindowDisplayAdapter::getFd()
+{
+ LOG_FUNCTION_NAME;
+
+ if(mFD == -1)
+ {
+ buffer_handle_t *handle = (buffer_handle_t *)mBuffers[0].opaque;
+ IMG_native_handle_t *img = (IMG_native_handle_t *)handle;
+ // TODO: should we dup the fd? not really necessary and another thing for ANativeWindow
+ // to manage and close...
+
+ mFD = dup(img->fd[0]);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return mFD;
+
+}
+
+status_t ANativeWindowDisplayAdapter::returnBuffersToWindow()
+{
+ status_t ret = NO_ERROR;
+
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ //Give the buffers back to display here - sort of free it
+ if (mANativeWindow)
+ for(unsigned int i = 0; i < mFramesWithCameraAdapterMap.size(); i++) {
+ int value = mFramesWithCameraAdapterMap.valueAt(i);
+ buffer_handle_t *handle = (buffer_handle_t *) mBuffers[value].opaque;
+
+ // if buffer index is out of bounds skip
+ if ((value < 0) || (value >= mBufferCount)) {
+ CAMHAL_LOGEA("Potential out bounds access to handle...skipping");
+ continue;
+ }
+
+ if (!mUseExternalBufferLocking) {
+ // unlock buffer before giving it up
+ mapper.unlock(*handle);
+ }
+
+ ret = mANativeWindow->cancel_buffer(mANativeWindow, handle);
+ if ( NO_INIT == ret ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ return ret;
+ } else if ( NO_ERROR != ret ) {
+ CAMHAL_LOGE("Surface::cancelBuffer() failed: %s (%d)",
+ strerror(-ret),
+ -ret);
+ return ret;
+ }
+ }
+ else
+ CAMHAL_LOGE("mANativeWindow is NULL");
+
+ ///Clear the frames with camera adapter map
+ mFramesWithCameraAdapterMap.clear();
+
+ return ret;
+
+}
+
+int ANativeWindowDisplayAdapter::freeBufferList(CameraBuffer * buflist)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+
+ android::AutoMutex lock(mLock);
+
+ if(mBuffers != buflist)
+ {
+ CAMHAL_LOGEA("CameraHal passed wrong set of buffers to free!!!");
+ if (mBuffers != NULL)
+ delete []mBuffers;
+ mBuffers = NULL;
+ }
+
+ /* FIXME this will probably want the list that was just deleted */
+ returnBuffersToWindow();
+
+ if ( NULL != buflist )
+ {
+ delete [] buflist;
+ mBuffers = NULL;
+ }
+
+ if( mBuffers != NULL)
+ {
+ delete [] mBuffers;
+ mBuffers = NULL;
+ }
+
+ if ( NULL != mOffsetsMap )
+ {
+ delete [] mOffsetsMap;
+ mOffsetsMap = NULL;
+ }
+
+ if( mFD != -1)
+ {
+ close(mFD); // close duped handle
+ mFD = -1;
+ }
+
+ mFramesType.clear();
+
+ return NO_ERROR;
+}
+
+
+bool ANativeWindowDisplayAdapter::supportsExternalBuffering()
+{
+ return false;
+}
+
+void ANativeWindowDisplayAdapter::displayThread()
+{
+ bool shouldLive = true;
+ int timeout = 0;
+ status_t ret;
+
+ LOG_FUNCTION_NAME;
+
+ while(shouldLive)
+ {
+ ret = Utils::MessageQueue::waitForMsg(&mDisplayThread->msgQ()
+ , &mDisplayQ
+ , NULL
+ , ANativeWindowDisplayAdapter::DISPLAY_TIMEOUT);
+
+ if ( !mDisplayThread->msgQ().isEmpty() )
+ {
+ ///Received a message from CameraHal, process it
+ shouldLive = processHalMsg();
+
+ }
+ else if( !mDisplayQ.isEmpty())
+ {
+ if ( mDisplayState== ANativeWindowDisplayAdapter::DISPLAY_INIT )
+ {
+
+ ///If display adapter is not started, continue
+ continue;
+
+ }
+ else
+ {
+ Utils::Message msg;
+ ///Get the dummy msg from the displayQ
+ if(mDisplayQ.get(&msg)!=NO_ERROR)
+ {
+ CAMHAL_LOGEA("Error in getting message from display Q");
+ continue;
+ }
+
+ // There is a frame from ANativeWindow for us to dequeue
+ // We dequeue and return the frame back to Camera adapter
+ if(mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED)
+ {
+ handleFrameReturn();
+ }
+
+ if (mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_EXITED)
+ {
+ ///we exit the thread even though there are frames still to dequeue. They will be dequeued
+ ///in disableDisplay
+ shouldLive = false;
+ }
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+bool ANativeWindowDisplayAdapter::processHalMsg()
+{
+ Utils::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+
+ mDisplayThread->msgQ().get(&msg);
+ bool ret = true, invalidCommand = false;
+
+ switch ( msg.command )
+ {
+
+ case DisplayThread::DISPLAY_START:
+
+ CAMHAL_LOGDA("Display thread received DISPLAY_START command from Camera HAL");
+ mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STARTED;
+
+ break;
+
+ case DisplayThread::DISPLAY_STOP:
+
+ ///@bug There is no API to disable SF without destroying it
+ ///@bug Buffers might still be w/ display and will get displayed
+ ///@remarks Ideal seqyence should be something like this
+ ///mOverlay->setParameter("enabled", false);
+ CAMHAL_LOGDA("Display thread received DISPLAY_STOP command from Camera HAL");
+ mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_STOPPED;
+
+ // flush frame message queue
+ while ( !mDisplayQ.isEmpty() ) {
+ Utils::Message message;
+ mDisplayQ.get(&message);
+ }
+
+ break;
+
+ case DisplayThread::DISPLAY_EXIT:
+
+ CAMHAL_LOGDA("Display thread received DISPLAY_EXIT command from Camera HAL.");
+ CAMHAL_LOGDA("Stopping display thread...");
+ mDisplayState = ANativeWindowDisplayAdapter::DISPLAY_EXITED;
+ ///Note that the SF can have pending buffers when we disable the display
+ ///This is normal and the expectation is that they may not be displayed.
+ ///This is to ensure that the user experience is not impacted
+ ret = false;
+ break;
+
+ default:
+
+ CAMHAL_LOGEB("Invalid Display Thread Command 0x%x.", msg.command);
+ invalidCommand = true;
+
+ break;
+ }
+
+ ///Signal the semaphore if it is sent as part of the message
+ if ( ( msg.arg1 ) && ( !invalidCommand ) )
+ {
+
+ CAMHAL_LOGDA("+Signalling display semaphore");
+ Utils::Semaphore &sem = *((Utils::Semaphore*)msg.arg1);
+
+ sem.Signal();
+
+ CAMHAL_LOGDA("-Signalling display semaphore");
+ }
+
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+
+status_t ANativeWindowDisplayAdapter::PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame)
+{
+ status_t ret = NO_ERROR;
+ uint32_t actualFramesWithDisplay = 0;
+ android_native_buffer_t *buffer = NULL;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ int i;
+
+ ///@todo Do cropping based on the stabilized frame coordinates
+ ///@todo Insert logic to drop frames here based on refresh rate of
+ ///display or rendering rate whichever is lower
+ ///Queue the buffer to overlay
+
+ if ( NULL == mANativeWindow ) {
+ return NO_INIT;
+ }
+
+ if (!mBuffers || !dispFrame.mBuffer) {
+ CAMHAL_LOGEA("NULL sent to PostFrame");
+ return BAD_VALUE;
+ }
+
+ for ( i = 0; i < mBufferCount; i++ )
+ {
+ if ( dispFrame.mBuffer == &mBuffers[i] )
+ {
+ break;
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ if ( mMeasureStandby ) {
+ CameraHal::PPM("Standby to first shot: Sensor Change completed - ", &mStandbyToShot);
+ mMeasureStandby = false;
+ } else if (CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) {
+ CameraHal::PPM("Shot to snapshot: ", &mStartCapture);
+ mShotToShot = true;
+ } else if ( mShotToShot ) {
+ CameraHal::PPM("Shot to shot: ", &mStartCapture);
+ mShotToShot = false;
+ }
+
+#endif
+
+ android::AutoMutex lock(mLock);
+
+ mFramesType.add( (int)mBuffers[i].opaque, dispFrame.mType);
+
+ if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&
+ (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&
+ !mSuspend)
+ {
+ uint32_t xOff, yOff;
+
+ CameraHal::getXYFromOffset(&xOff, &yOff, dispFrame.mOffset, PAGE_SIZE, mPixelFormat);
+
+ // Set crop only if current x and y offsets do not match with frame offsets
+ if ((mXOff != xOff) || (mYOff != yOff)) {
+ CAMHAL_LOGDB("offset = %u left = %d top = %d right = %d bottom = %d",
+ dispFrame.mOffset, xOff, yOff ,
+ xOff + mPreviewWidth, yOff + mPreviewHeight);
+
+ // We'll ignore any errors here, if the surface is
+ // already invalid, we'll know soon enough.
+ mANativeWindow->set_crop(mANativeWindow, xOff, yOff,
+ xOff + mPreviewWidth, yOff + mPreviewHeight);
+
+ // Update the current x and y offsets
+ mXOff = xOff;
+ mYOff = yOff;
+ }
+
+ {
+ buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
+ if (!mUseExternalBufferLocking) {
+ // unlock buffer before sending to display
+ mapper.unlock(*handle);
+ }
+ ret = mANativeWindow->enqueue_buffer(mANativeWindow, handle);
+ }
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret);
+ }
+
+ mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque);
+
+
+ // HWComposer has not minimum buffer requirement. We should be able to dequeue
+ // the buffer immediately
+ Utils::Message msg;
+ mDisplayQ.put(&msg);
+
+ }
+ else
+ {
+ buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
+ if (!mUseExternalBufferLocking) {
+ // unlock buffer before giving it up
+ mapper.unlock(*handle);
+ }
+
+ // cancel buffer and dequeue another one
+ ret = mANativeWindow->cancel_buffer(mANativeWindow, handle);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGE("Surface::cancelBuffer returned error %d", ret);
+ }
+
+ mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) dispFrame.mBuffer->opaque);
+
+ Utils::Message msg;
+ mDisplayQ.put(&msg);
+ ret = NO_ERROR;
+ }
+
+ return ret;
+}
+
+
+bool ANativeWindowDisplayAdapter::handleFrameReturn()
+{
+ status_t err;
+ buffer_handle_t *buf;
+ int i = 0;
+ unsigned int k;
+ int stride; // dummy variable to get stride
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ android::Rect bounds;
+ CameraFrame::FrameType frameType = CameraFrame::PREVIEW_FRAME_SYNC;
+
+ void *y_uv[2];
+
+ // TODO(XXX): Do we need to keep stride information in camera hal?
+
+ if ( NULL == mANativeWindow ) {
+ return false;
+ }
+
+ err = mANativeWindow->dequeue_buffer(mANativeWindow, &buf, &stride);
+ if (err != 0) {
+ CAMHAL_LOGE("Surface::dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+
+ if ( NO_INIT == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+
+ return false;
+ }
+
+ err = mANativeWindow->lock_buffer(mANativeWindow, buf);
+ if ( NO_ERROR != err ) {
+ CAMHAL_LOGE("Surface::lockBuffer failed: %s (%d)", strerror(-err), -err);
+
+ if ( NO_INIT == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mANativeWindow = NULL;
+ }
+
+ return false;
+ }
+
+ for(i = 0; i < mBufferCount; i++)
+ {
+ if (mBuffers[i].opaque == buf)
+ break;
+ }
+ if (i == mBufferCount) {
+ CAMHAL_LOGEB("Failed to find handle %p", buf);
+ }
+ if (!mUseExternalBufferLocking) {
+ // lock buffer before sending to FrameProvider for filling
+ bounds.left = 0;
+ bounds.top = 0;
+ bounds.right = mFrameWidth;
+ bounds.bottom = mFrameHeight;
+
+ int lock_try_count = 0;
+ while (mapper.lock(*(buffer_handle_t *) mBuffers[i].opaque, CAMHAL_GRALLOC_USAGE, bounds, y_uv) < 0){
+ if (++lock_try_count > LOCK_BUFFER_TRIES){
+ if ( NULL != mErrorNotifier.get() ){
+ mErrorNotifier->errorNotify(CAMERA_ERROR_UNKNOWN);
+ }
+ return false;
+ }
+ CAMHAL_LOGEA("Gralloc Lock FrameReturn Error: Sleeping 15ms");
+ usleep(15000);
+ }
+ }
+
+ {
+ android::AutoMutex lock(mLock);
+ mFramesWithCameraAdapterMap.add((buffer_handle_t *) mBuffers[i].opaque, i);
+
+ for( k = 0; k < mFramesType.size() ; k++) {
+ if(mFramesType.keyAt(k) == (int)mBuffers[i].opaque)
+ break;
+ }
+
+ if ( k == mFramesType.size() ) {
+ CAMHAL_LOGE("Frame type for preview buffer 0%x not found!!", mBuffers[i].opaque);
+ return false;
+ }
+
+ frameType = (CameraFrame::FrameType) mFramesType.valueAt(k);
+ mFramesType.removeItem((int) mBuffers[i].opaque);
+ }
+
+ CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount-1);
+ mFrameProvider->returnFrame(&mBuffers[i], frameType);
+
+ return true;
+}
+
+void ANativeWindowDisplayAdapter::frameCallbackRelay(CameraFrame* caFrame)
+{
+
+ if ( NULL != caFrame )
+ {
+ if ( NULL != caFrame->mCookie )
+ {
+ ANativeWindowDisplayAdapter *da = (ANativeWindowDisplayAdapter*) caFrame->mCookie;
+ da->frameCallback(caFrame);
+ }
+ else
+ {
+ CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p", caFrame, caFrame->mCookie);
+ }
+ }
+ else
+ {
+ CAMHAL_LOGEB("Invalid Camera Frame = %p", caFrame);
+ }
+
+}
+
+void ANativeWindowDisplayAdapter::frameCallback(CameraFrame* caFrame)
+{
+ ///Call queueBuffer of overlay in the context of the callback thread
+
+ DisplayFrame df;
+ df.mBuffer = caFrame->mBuffer;
+ df.mType = (CameraFrame::FrameType) caFrame->mFrameType;
+ df.mOffset = caFrame->mOffset;
+ df.mWidthStride = caFrame->mAlignment;
+ df.mLength = caFrame->mLength;
+ df.mWidth = caFrame->mWidth;
+ df.mHeight = caFrame->mHeight;
+ PostFrame(df);
+}
+
+void ANativeWindowDisplayAdapter::setExternalLocking(bool extBuffLocking)
+{
+ mUseExternalBufferLocking = extBuffLocking;
+}
+
+/*--------------------ANativeWindowDisplayAdapter Class ENDS here-----------------------------*/
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/Android.mk b/camera/Android.mk
new file mode 100644
index 0000000..1789304
--- /dev/null
+++ b/camera/Android.mk
@@ -0,0 +1,297 @@
+LOCAL_PATH:= $(call my-dir)
+OMAP4_NEXT_FOLDER := hardware/ti/omap4
+
+include $(LOCAL_PATH)/android-api.mk
+
+TI_CAMERAHAL_INTERFACE ?= ALL
+
+TI_CAMERAHAL_COMMON_CFLAGS := \
+ $(ANDROID_API_CFLAGS) \
+ -DLOG_TAG=\"CameraHal\" \
+ -DCOPY_IMAGE_BUFFER \
+ -fno-short-enums
+
+ifdef TI_CAMERAHAL_DEBUG_ENABLED
+ # Enable CameraHAL debug logs
+ TI_CAMERAHAL_COMMON_CFLAGS += -DCAMERAHAL_DEBUG
+endif
+
+ifdef TI_CAMERAHAL_VERBOSE_DEBUG_ENABLED
+ # Enable CameraHAL verbose debug logs
+ TI_CAMERAHAL_COMMON_CFLAGS += -DCAMERAHAL_DEBUG_VERBOSE
+endif
+
+ifdef TI_CAMERAHAL_DEBUG_FUNCTION_NAMES
+ # Enable CameraHAL function enter/exit logging
+ TI_CAMERAHAL_COMMON_CFLAGS += -DTI_UTILS_FUNCTION_LOGGER_ENABLE
+endif
+
+ifdef TI_CAMERAHAL_DEBUG_TIMESTAMPS
+ # Enable timestamp logging
+ TI_CAMERAHAL_COMMON_CFLAGS += -DTI_UTILS_DEBUG_USE_TIMESTAMPS
+endif
+
+ifndef TI_CAMERAHAL_DONT_USE_RAW_IMAGE_SAVING
+ # Enabled saving RAW images to file
+ TI_CAMERAHAL_COMMON_CFLAGS += -DCAMERAHAL_USE_RAW_IMAGE_SAVING
+endif
+
+ifdef TI_CAMERAHAL_PROFILING
+ # Enable OMX Camera component profiling
+ TI_CAMERAHAL_COMMON_CFLAGS += -DCAMERAHAL_OMX_PROFILING
+endif
+
+ifdef TI_CAMERAHAL_MAX_CAMERAS_SUPPORTED
+ TI_CAMERAHAL_COMMON_CFLAGS += -DMAX_CAMERAS_SUPPORTED=$(TI_CAMERAHAL_MAX_CAMERAS_SUPPORTED)
+endif
+
+ifdef TI_CAMERAHAL_TREAT_FRONT_AS_BACK
+ TI_CAMERAHAL_COMMON_CFLAGS += -DTREAT_FRONT_AS_BACK
+endif
+
+ifeq ($(findstring omap5, $(TARGET_BOARD_PLATFORM)),omap5)
+ TI_CAMERAHAL_COMMON_CFLAGS += -DCAMERAHAL_OMAP5_CAPTURE_MODES
+endif
+
+ifeq ($(ENHANCED_DOMX),true)
+ TI_CAMERAHAL_COMMON_CFLAGS += -DENHANCED_DOMX
+endif
+
+ifdef ARCH_ARM_HAVE_NEON
+ TI_CAMERAHAL_COMMON_CFLAGS += -DARCH_ARM_HAVE_NEON
+endif
+
+ifeq ($(BOARD_VENDOR),motorola-omap4)
+ TI_CAMERAHAL_COMMON_CFLAGS += -DMOTOROLA_CAMERA
+endif
+
+ifeq ($(TARGET_BOOTLOADER_BOARD_NAME),piranha)
+ TI_CAMERAHAL_COMMON_CFLAGS += -DCAMERAHAL_PIRANHA
+endif
+
+ifeq ($(TARGET_BOOTLOADER_BOARD_NAME),tuna)
+ TI_CAMERAHAL_COMMON_CFLAGS += -DCAMERAHAL_TUNA
+endif
+
+TI_CAMERAHAL_OMX_CFLAGS := -DOMX_CAMERA_ADAPTER
+TI_CAMERAHAL_USB_CFLAGS := -DV4L_CAMERA_ADAPTER
+
+
+TI_CAMERAHAL_COMMON_INCLUDES := \
+ $(OMAP4_NEXT_FOLDER)/include \
+ $(OMAP4_NEXT_FOLDER)/hwc \
+ external/jpeg \
+ external/jhead \
+ $(OMAP4_NEXT_FOLDER)/libtiutils \
+ $(LOCAL_PATH)/inc \
+ system/media/camera/include
+
+ifdef ANDROID_API_JB_OR_LATER
+TI_CAMERAHAL_COMMON_INCLUDES += \
+ frameworks/native/include/media/hardware
+else
+TI_CAMERAHAL_COMMON_INCLUDES += \
+ frameworks/base/include/media/stagefright
+endif
+
+TI_CAMERAHAL_OMX_INCLUDES := \
+ frameworks/native/include/media/openmax \
+ $(DOMX_PATH)/mm_osal/inc \
+ $(DOMX_PATH)/omx_core/inc \
+ $(LOCAL_PATH)/inc/OMXCameraAdapter
+
+TI_CAMERAHAL_USB_INCLUDES := \
+ $(LOCAL_PATH)/inc/V4LCameraAdapter
+
+
+TI_CAMERAHAL_COMMON_SRC := \
+ CameraHal_Module.cpp \
+ CameraHal.cpp \
+ CameraHalUtilClasses.cpp \
+ AppCallbackNotifier.cpp \
+ ANativeWindowDisplayAdapter.cpp \
+ BufferSourceAdapter.cpp \
+ CameraProperties.cpp \
+ BaseCameraAdapter.cpp \
+ MemoryManager.cpp \
+ Encoder_libjpeg.cpp \
+ Decoder_libjpeg.cpp \
+ SensorListener.cpp \
+ NV12_resize.cpp \
+ CameraParameters.cpp \
+ TICameraParameters.cpp \
+ CameraHalCommon.cpp \
+ FrameDecoder.cpp \
+ SwFrameDecoder.cpp \
+ OmxFrameDecoder.cpp \
+ DecoderFactory.cpp
+
+TI_CAMERAHAL_OMX_SRC := \
+ OMXCameraAdapter/OMX3A.cpp \
+ OMXCameraAdapter/OMXAlgo.cpp \
+ OMXCameraAdapter/OMXCameraAdapter.cpp \
+ OMXCameraAdapter/OMXCapabilities.cpp \
+ OMXCameraAdapter/OMXCapture.cpp \
+ OMXCameraAdapter/OMXReprocess.cpp \
+ OMXCameraAdapter/OMXDefaults.cpp \
+ OMXCameraAdapter/OMXExif.cpp \
+ OMXCameraAdapter/OMXFD.cpp \
+ OMXCameraAdapter/OMXFocus.cpp \
+ OMXCameraAdapter/OMXMetadata.cpp \
+ OMXCameraAdapter/OMXZoom.cpp \
+ OMXCameraAdapter/OMXDccDataSave.cpp
+
+ifdef TI_CAMERAHAL_USES_LEGACY_DOMX_DCC
+TI_CAMERAHAL_OMX_CFLAGS += -DUSES_LEGACY_DOMX_DCC
+else
+TI_CAMERAHAL_OMX_SRC += OMXCameraAdapter/OMXDCC.cpp
+endif
+
+TI_CAMERAHAL_USB_SRC := \
+ V4LCameraAdapter/V4LCameraAdapter.cpp \
+ V4LCameraAdapter/V4LCapabilities.cpp
+
+
+TI_CAMERAHAL_EXIF_LIBRARY := libexif
+# libexif is now libjhead in later API levels.
+
+ifdef ANDROID_API_KK_OR_LATER
+ifdef ANDROID_API_LP_OR_LATER
+ TI_CAMERAHAL_EXIF_LIBRARY := libjhead
+else ifneq ($(filter 4.4.3 4.4.4,$(PLATFORM_VERSION)),)
+ # Only 4.4.3 and 4.4.4 KK use libjhead
+ TI_CAMERAHAL_EXIF_LIBRARY := libjhead
+endif
+endif
+
+TI_CAMERAHAL_COMMON_SHARED_LIBRARIES := \
+ libui \
+ libbinder \
+ libutils \
+ libcutils \
+ liblog \
+ libtiutils \
+ libcamera_client \
+ libgui \
+ libjpeg \
+ $(TI_CAMERAHAL_EXIF_LIBRARY)
+
+ifdef ANDROID_API_JB_MR1_OR_LATER
+TI_CAMERAHAL_COMMON_SHARED_LIBRARIES += \
+ libion_ti
+TI_CAMERAHAL_COMMON_CFLAGS += -DUSE_LIBION_TI
+else
+TI_CAMERAHAL_COMMON_SHARED_LIBRARIES += \
+ libion
+endif
+
+TI_CAMERAHAL_OMX_SHARED_LIBRARIES := \
+ libmm_osal \
+ libOMX_Core \
+ libdomx
+
+
+ifdef OMAP_ENHANCEMENT_CPCAM
+TI_CAMERAHAL_COMMON_STATIC_LIBRARIES += \
+ libcpcamcamera_client
+endif
+
+
+ifeq ($(TI_CAMERAHAL_INTERFACE),OMX)
+# ====================
+# OMX Camera Adapter
+# --------------------
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(TI_CAMERAHAL_COMMON_SRC) \
+ $(TI_CAMERAHAL_OMX_SRC)
+
+LOCAL_C_INCLUDES := \
+ $(TI_CAMERAHAL_COMMON_INCLUDES) \
+ $(TI_CAMERAHAL_OMX_INCLUDES)
+
+LOCAL_SHARED_LIBRARIES := \
+ $(TI_CAMERAHAL_COMMON_SHARED_LIBRARIES) \
+ $(TI_CAMERAHAL_OMX_SHARED_LIBRARIES)
+
+LOCAL_STATIC_LIBRARIES := $(TI_CAMERAHAL_COMMON_STATIC_LIBRARIES)
+
+LOCAL_CFLAGS := \
+ $(TI_CAMERAHAL_COMMON_CFLAGS) \
+ $(TI_CAMERAHAL_OMX_CFLAGS)
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE := camera.tuna
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+else ifeq ($(TI_CAMERAHAL_INTERFACE),USB)
+# ====================
+# USB Camera Adapter
+# --------------------
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(TI_CAMERAHAL_COMMON_SRC) \
+ $(TI_CAMERAHAL_USB_SRC)
+
+LOCAL_C_INCLUDES := \
+ $(TI_CAMERAHAL_COMMON_INCLUDES) \
+ $(TI_CAMERAHAL_USB_INCLUDES)
+
+LOCAL_SHARED_LIBRARIES := \
+ $(TI_CAMERAHAL_COMMON_SHARED_LIBRARIES)
+
+LOCAL_STATIC_LIBRARIES := $(TI_CAMERAHAL_COMMON_STATIC_LIBRARIES)
+
+LOCAL_CFLAGS := \
+ $(TI_CAMERAHAL_COMMON_CFLAGS) \
+ $(TI_CAMERAHAL_USB_CFLAGS)
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE := camera.tuna
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+else ifeq ($(TI_CAMERAHAL_INTERFACE),ALL)
+# =====================
+# ALL Camera Adapters
+# ---------------------
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(TI_CAMERAHAL_COMMON_SRC) \
+ $(TI_CAMERAHAL_OMX_SRC) \
+ $(TI_CAMERAHAL_USB_SRC)
+
+LOCAL_C_INCLUDES := \
+ $(TI_CAMERAHAL_COMMON_INCLUDES) \
+ $(TI_CAMERAHAL_OMX_INCLUDES) \
+ $(TI_CAMERAHAL_USB_INCLUDES)
+
+LOCAL_SHARED_LIBRARIES := \
+ $(TI_CAMERAHAL_COMMON_SHARED_LIBRARIES) \
+ $(TI_CAMERAHAL_OMX_SHARED_LIBRARIES)
+
+LOCAL_STATIC_LIBRARIES := $(TI_CAMERAHAL_COMMON_STATIC_LIBRARIES)
+
+LOCAL_CFLAGS := \
+ $(TI_CAMERAHAL_COMMON_CFLAGS) \
+ $(TI_CAMERAHAL_OMX_CFLAGS) \
+ $(TI_CAMERAHAL_USB_CFLAGS)
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE := camera.tuna
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
+
+$(clear-android-api-vars)
diff --git a/camera/AppCallbackNotifier.cpp b/camera/AppCallbackNotifier.cpp
new file mode 100644
index 0000000..8bc10b1
--- /dev/null
+++ b/camera/AppCallbackNotifier.cpp
@@ -0,0 +1,2002 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CameraHal.h"
+#include "VideoMetadata.h"
+#include "Encoder_libjpeg.h"
+#include <MetadataBufferType.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferMapper.h>
+#include "NV12_resize.h"
+#include "TICameraParameters.h"
+
+namespace Ti {
+namespace Camera {
+
+const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1;
+android::KeyedVector<void*, android::sp<Encoder_libjpeg> > gEncoderQueue;
+
+void AppCallbackNotifierEncoderCallback(void* main_jpeg,
+ void* thumb_jpeg,
+ CameraFrame::FrameType type,
+ void* cookie1,
+ void* cookie2,
+ void* cookie3,
+ void* cookie4,
+ bool canceled)
+{
+ if (cookie1 && !canceled) {
+ AppCallbackNotifier* cb = (AppCallbackNotifier*) cookie1;
+ cb->EncoderDoneCb(main_jpeg, thumb_jpeg, type, cookie2, cookie3, cookie4);
+ }
+
+ if (main_jpeg) {
+ free(main_jpeg);
+ }
+
+ if (thumb_jpeg) {
+ if (((Encoder_libjpeg::params *) thumb_jpeg)->dst) {
+ free(((Encoder_libjpeg::params *) thumb_jpeg)->dst);
+ }
+ free(thumb_jpeg);
+ }
+}
+
+/*--------------------NotificationHandler Class STARTS here-----------------------------*/
+
+void AppCallbackNotifier::EncoderDoneCb(void* main_jpeg, void* thumb_jpeg, CameraFrame::FrameType type, void* cookie1, void* cookie2, void *cookie3)
+{
+ camera_memory_t* encoded_mem = NULL;
+ Encoder_libjpeg::params *main_param = NULL, *thumb_param = NULL;
+ size_t jpeg_size;
+ uint8_t* src = NULL;
+ CameraBuffer *camera_buffer;
+ android::sp<Encoder_libjpeg> encoder = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ camera_memory_t* picture = NULL;
+
+ {
+ android::AutoMutex lock(mLock);
+
+ if (!main_jpeg) {
+ goto exit;
+ }
+
+ encoded_mem = (camera_memory_t*) cookie1;
+ main_param = (Encoder_libjpeg::params *) main_jpeg;
+ jpeg_size = main_param->jpeg_size;
+ camera_buffer = (CameraBuffer *)cookie3;
+ src = main_param->src;
+
+ if(encoded_mem && encoded_mem->data && (jpeg_size > 0)) {
+ if (cookie2) {
+ ExifElementsTable* exif = (ExifElementsTable*) cookie2;
+ Section_t* exif_section = NULL;
+
+ exif->insertExifToJpeg((unsigned char*) encoded_mem->data, jpeg_size);
+
+ if(thumb_jpeg) {
+ thumb_param = (Encoder_libjpeg::params *) thumb_jpeg;
+ exif->insertExifThumbnailImage((const char*)thumb_param->dst,
+ (int)thumb_param->jpeg_size);
+ }
+
+ exif_section = FindSection(M_EXIF);
+
+ if (exif_section) {
+ picture = mRequestMemory(-1, jpeg_size + exif_section->Size, 1, NULL);
+ if (picture && picture->data) {
+ exif->saveJpeg((unsigned char*) picture->data, jpeg_size + exif_section->Size);
+ }
+ }
+ delete exif;
+ cookie2 = NULL;
+ } else {
+ picture = mRequestMemory(-1, jpeg_size, 1, NULL);
+ if (picture && picture->data) {
+ memcpy(picture->data, encoded_mem->data, jpeg_size);
+ }
+ }
+ }
+ } // scope for mutex lock
+
+ if (!mRawAvailable) {
+ dummyRaw();
+ } else {
+ mRawAvailable = false;
+ }
+
+ // Send the callback to the application only if the notifier is started and the message is enabled
+ if(picture && (mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED) &&
+ (mCameraHal->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE)))
+ {
+ android::AutoMutex lock(mBurstLock);
+
+#ifdef OMAP_ENHANCEMENT_BURST_CAPTURE
+ if ( mBurst )
+ {
+ mDataCb(CAMERA_MSG_COMPRESSED_BURST_IMAGE, picture, 0, NULL, mCallbackCookie);
+
+ }
+ else
+#endif
+ {
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, picture, 0, NULL, mCallbackCookie);
+ }
+ }
+
+ exit:
+
+ if (picture) {
+ picture->release(picture);
+ }
+
+ if (mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) {
+ if (encoded_mem) {
+ encoded_mem->release(encoded_mem);
+ }
+ if (cookie2) {
+ delete (ExifElementsTable*) cookie2;
+ }
+ encoder = gEncoderQueue.valueFor(src);
+ if (encoder.get()) {
+ gEncoderQueue.removeItem(src);
+ encoder.clear();
+ }
+ mFrameProvider->returnFrame(camera_buffer, type);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ * NotificationHandler class
+ */
+
+///Initialization function for AppCallbackNotifier
+status_t AppCallbackNotifier::initialize()
+{
+ LOG_FUNCTION_NAME;
+
+ mPreviewMemory = 0;
+
+ mMeasurementEnabled = false;
+
+ mNotifierState = NOTIFIER_STOPPED;
+
+ ///Create the app notifier thread
+ mNotificationThread = new NotificationThread(this);
+ if(!mNotificationThread.get())
+ {
+ CAMHAL_LOGEA("Couldn't create Notification thread");
+ return NO_MEMORY;
+ }
+
+ ///Start the display thread
+ status_t ret = mNotificationThread->run("NotificationThread", android::PRIORITY_URGENT_DISPLAY);
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEA("Couldn't run NotificationThread");
+ mNotificationThread.clear();
+ return ret;
+ }
+
+ mUseMetaDataBufferMode = true;
+ mRawAvailable = false;
+
+ mRecording = false;
+ mPreviewing = false;
+ mExternalLocking = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+void AppCallbackNotifier::setCallbacks(CameraHal* cameraHal,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user)
+{
+ android::AutoMutex lock(mLock);
+
+ LOG_FUNCTION_NAME;
+
+ mCameraHal = cameraHal;
+ mNotifyCb = notify_cb;
+ mDataCb = data_cb;
+ mDataCbTimestamp = data_cb_timestamp;
+ mRequestMemory = get_memory;
+ mCallbackCookie = user;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::setMeasurements(bool enable)
+{
+ android::AutoMutex lock(mLock);
+
+ LOG_FUNCTION_NAME;
+
+ mMeasurementEnabled = enable;
+
+ if ( enable )
+ {
+ mFrameProvider->enableFrameNotification(CameraFrame::FRAME_DATA_SYNC);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+//All sub-components of Camera HAL call this whenever any error happens
+void AppCallbackNotifier::errorNotify(int error)
+{
+ LOG_FUNCTION_NAME;
+
+ CAMHAL_LOGEB("AppCallbackNotifier received error %d", error);
+
+ // If it is a fatal error abort here!
+ // If TILER is Out of memory we notify Mediaserver so that Memory is cleared and we can restart usecase
+ if((error == CAMERA_ERROR_FATAL) || (error == CAMERA_ERROR_HARD) || (error == -ENOMEM))
+ {
+ //We kill media server if we encounter these errors as there is
+ //no point continuing and apps also don't handle errors other
+ //than media server death always.
+ abort();
+ return;
+ }
+
+ if ( ( NULL != mCameraHal ) &&
+ ( NULL != mNotifyCb ) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ERROR) ) )
+ {
+ CAMHAL_LOGEB("AppCallbackNotifier mNotifyCb %d", error);
+ mNotifyCb(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, mCallbackCookie);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+bool AppCallbackNotifier::notificationThread()
+{
+ bool shouldLive = true;
+ status_t ret;
+
+ LOG_FUNCTION_NAME;
+
+ //CAMHAL_LOGDA("Notification Thread waiting for message");
+ ret = Utils::MessageQueue::waitForMsg(&mNotificationThread->msgQ(),
+ &mEventQ,
+ &mFrameQ,
+ AppCallbackNotifier::NOTIFIER_TIMEOUT);
+
+ //CAMHAL_LOGDA("Notification Thread received message");
+
+ if (mNotificationThread->msgQ().hasMsg()) {
+ ///Received a message from CameraHal, process it
+ CAMHAL_LOGDA("Notification Thread received message from Camera HAL");
+ shouldLive = processMessage();
+ if(!shouldLive) {
+ CAMHAL_LOGDA("Notification Thread exiting.");
+ return shouldLive;
+ }
+ }
+
+ if(mEventQ.hasMsg()) {
+ ///Received an event from one of the event providers
+ CAMHAL_LOGDA("Notification Thread received an event from event provider (CameraAdapter)");
+ notifyEvent();
+ }
+
+ if(mFrameQ.hasMsg()) {
+ ///Received a frame from one of the frame providers
+ //CAMHAL_LOGDA("Notification Thread received a frame from frame provider (CameraAdapter)");
+ notifyFrame();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return shouldLive;
+}
+
+void AppCallbackNotifier::notifyEvent()
+{
+ ///Receive and send the event notifications to app
+ Utils::Message msg;
+ LOG_FUNCTION_NAME;
+ {
+ android::AutoMutex lock(mLock);
+ if ( !mEventQ.hasMsg() ) {
+ return;
+ } else {
+ mEventQ.get(&msg);
+ }
+ }
+ bool ret = true;
+ CameraHalEvent *evt = NULL;
+ CameraHalEvent::FocusEventData *focusEvtData;
+ CameraHalEvent::ZoomEventData *zoomEvtData;
+ CameraHalEvent::MetaEventData metaEvtData;
+
+ if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED)
+ {
+ return;
+ }
+
+ switch(msg.command)
+ {
+ case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_EVENT:
+
+ evt = ( CameraHalEvent * ) msg.arg1;
+
+ if ( NULL == evt )
+ {
+ CAMHAL_LOGEA("Invalid CameraHalEvent");
+ return;
+ }
+
+ switch(evt->mEventType)
+ {
+ case CameraHalEvent::EVENT_SHUTTER:
+
+ if ( ( NULL != mCameraHal ) &&
+ ( NULL != mNotifyCb ) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_SHUTTER) ) )
+ {
+ mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
+ }
+ mRawAvailable = false;
+
+ break;
+
+ case CameraHalEvent::EVENT_FOCUS_LOCKED:
+ case CameraHalEvent::EVENT_FOCUS_ERROR:
+ if ( mCameraHal && mNotifyCb ) {
+ focusEvtData = &evt->mEventData->focusEvent;
+
+ switch ( focusEvtData->focusStatus ) {
+ case CameraHalEvent::FOCUS_STATUS_SUCCESS:
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) {
+ mCameraHal->disableMsgType(CAMERA_MSG_FOCUS);
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ }
+ break;
+
+ case CameraHalEvent::FOCUS_STATUS_FAIL:
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) {
+ mCameraHal->disableMsgType(CAMERA_MSG_FOCUS);
+ mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
+ }
+ break;
+
+#ifdef ANDROID_API_JB_OR_LATER
+ case CameraHalEvent::FOCUS_STATUS_PENDING:
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS_MOVE) ) {
+ mNotifyCb(CAMERA_MSG_FOCUS_MOVE, true, 0, mCallbackCookie);
+ }
+ break;
+
+ case CameraHalEvent::FOCUS_STATUS_DONE:
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS_MOVE) ) {
+ mNotifyCb(CAMERA_MSG_FOCUS_MOVE, false, 0, mCallbackCookie);
+ }
+ break;
+#endif
+ }
+ }
+
+ break;
+
+ case CameraHalEvent::EVENT_ZOOM_INDEX_REACHED:
+
+ zoomEvtData = &evt->mEventData->zoomEvent;
+
+ if ( ( NULL != mCameraHal ) &&
+ ( NULL != mNotifyCb) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ZOOM) ) )
+ {
+ mNotifyCb(CAMERA_MSG_ZOOM, zoomEvtData->currentZoomIndex, zoomEvtData->targetZoomIndexReached, mCallbackCookie);
+ }
+
+ break;
+
+ case CameraHalEvent::EVENT_METADATA:
+
+ metaEvtData = evt->mEventData->metadataEvent;
+
+ if ( ( NULL != mCameraHal ) &&
+ ( NULL != mNotifyCb) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) ) )
+ {
+ // WA for an issue inside CameraService
+ camera_memory_t *tmpBuffer = mRequestMemory(-1, 1, 1, NULL);
+
+ mDataCb(CAMERA_MSG_PREVIEW_METADATA,
+ tmpBuffer,
+ 0,
+ metaEvtData->getMetadataResult(),
+ mCallbackCookie);
+
+ metaEvtData.clear();
+
+ if ( NULL != tmpBuffer ) {
+ tmpBuffer->release(tmpBuffer);
+ }
+
+ }
+
+ break;
+
+ case CameraHalEvent::ALL_EVENTS:
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ if ( NULL != evt )
+ {
+ delete evt;
+ }
+
+
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+static void alignYV12(int width,
+ int height,
+ size_t &yStride,
+ size_t &uvStride,
+ size_t &ySize,
+ size_t &uvSize,
+ size_t &size)
+{
+ yStride = ( width + 0xF ) & ~0xF;
+ uvStride = ( yStride / 2 + 0xF ) & ~0xF;
+ ySize = yStride * height;
+ uvSize = uvStride * height / 2;
+ size = ySize + uvSize * 2;
+}
+
+static void copy2Dto1D(void *dst,
+ void *src,
+ int width,
+ int height,
+ size_t stride,
+ uint32_t offset,
+ unsigned int bytesPerPixel,
+ size_t length,
+ const char *pixelFormat)
+{
+ unsigned int alignedRow, row;
+ unsigned char *bufferDst, *bufferSrc;
+ unsigned char *bufferDstEnd, *bufferSrcEnd;
+ uint16_t *bufferSrc_UV;
+
+ unsigned int *y_uv = (unsigned int *)src;
+
+ CAMHAL_LOGVB("copy2Dto1D() y= %p ; uv=%p.",y_uv[0], y_uv[1]);
+ CAMHAL_LOGVB("pixelFormat = %s; offset=%d",pixelFormat,offset);
+
+ if (pixelFormat!=NULL) {
+ if (strcmp(pixelFormat, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ bytesPerPixel = 2;
+ bufferSrc = ( unsigned char * ) y_uv[0] + offset;
+ uint32_t xOff = offset % stride;
+ uint32_t yOff = offset / stride;
+ uint8_t *bufferSrcUV = ((uint8_t*)y_uv[1] + (stride/2)*yOff + xOff);
+ uint8_t *bufferSrcUVEven = bufferSrcUV;
+
+ uint8_t *bufferDstY = ( uint8_t * ) dst;
+ uint8_t *bufferDstU = bufferDstY + 1;
+ uint8_t *bufferDstV = bufferDstY + 3;
+
+ // going to convert from NV12 here and return
+ for ( int i = 0 ; i < height; i ++ ) {
+ for ( int j = 0 ; j < width / 2 ; j++ ) {
+
+ // Y
+ *bufferDstY = *bufferSrc;
+ bufferSrc++;
+ bufferDstY += 2;
+
+ *bufferDstY = *bufferSrc;
+ bufferSrc++;
+ bufferDstY += 2;
+
+ // V
+ *bufferDstV = *(bufferSrcUV + 1);
+ bufferDstV += 4;
+
+ // U
+ *bufferDstU = *bufferSrcUV;
+ bufferDstU += 4;
+
+ bufferSrcUV += 2;
+ }
+ if ( i % 2 ) {
+ bufferSrcUV += ( stride - width);
+ bufferSrcUVEven = bufferSrcUV;
+ } else {
+ bufferSrcUV = bufferSrcUVEven;
+ }
+ bufferSrc += ( stride - width);
+ }
+
+ return;
+ } else if (strcmp(pixelFormat, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
+ strcmp(pixelFormat, android::CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
+ bytesPerPixel = 1;
+ bufferDst = ( unsigned char * ) dst;
+ bufferDstEnd = ( unsigned char * ) dst + width*height*bytesPerPixel;
+ bufferSrc = ( unsigned char * ) y_uv[0] + offset;
+ bufferSrcEnd = ( unsigned char * ) ( ( size_t ) y_uv[0] + length + offset);
+ row = width*bytesPerPixel;
+ alignedRow = stride-width;
+ int stride_bytes = stride / 8;
+ uint32_t xOff = offset % stride;
+ uint32_t yOff = offset / stride;
+
+ // going to convert from NV12 here and return
+ // Step 1: Y plane: iterate through each row and copy
+ for ( int i = 0 ; i < height ; i++) {
+ memcpy(bufferDst, bufferSrc, row);
+ bufferSrc += stride;
+ bufferDst += row;
+ if ( ( bufferSrc > bufferSrcEnd ) || ( bufferDst > bufferDstEnd ) ) {
+ break;
+ }
+ }
+
+ bufferSrc_UV = ( uint16_t * ) ((uint8_t*)y_uv[1] + (stride/2)*yOff + xOff);
+
+ if (strcmp(pixelFormat, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ uint16_t *bufferDst_UV;
+
+ // Step 2: UV plane: convert NV12 to NV21 by swapping U & V
+ bufferDst_UV = (uint16_t *) (((uint8_t*)dst)+row*height);
+
+#ifdef ARCH_ARM_HAVE_NEON
+ for (int i = 0 ; i < height/2 ; i++, bufferSrc_UV += alignedRow/2) {
+ int n = width;
+ asm volatile (
+ " pld [%[src], %[src_stride], lsl #2] \n\t"
+ " cmp %[n], #32 \n\t"
+ " blt 1f \n\t"
+ "0: @ 32 byte swap \n\t"
+ " sub %[n], %[n], #32 \n\t"
+ " vld2.8 {q0, q1} , [%[src]]! \n\t"
+ " vswp q0, q1 \n\t"
+ " cmp %[n], #32 \n\t"
+ " vst2.8 {q0,q1},[%[dst]]! \n\t"
+ " bge 0b \n\t"
+ "1: @ Is there enough data? \n\t"
+ " cmp %[n], #16 \n\t"
+ " blt 3f \n\t"
+ "2: @ 16 byte swap \n\t"
+ " sub %[n], %[n], #16 \n\t"
+ " vld2.8 {d0, d1} , [%[src]]! \n\t"
+ " vswp d0, d1 \n\t"
+ " cmp %[n], #16 \n\t"
+ " vst2.8 {d0,d1},[%[dst]]! \n\t"
+ " bge 2b \n\t"
+ "3: @ Is there enough data? \n\t"
+ " cmp %[n], #8 \n\t"
+ " blt 5f \n\t"
+ "4: @ 8 byte swap \n\t"
+ " sub %[n], %[n], #8 \n\t"
+ " vld2.8 {d0, d1} , [%[src]]! \n\t"
+ " vswp d0, d1 \n\t"
+ " cmp %[n], #8 \n\t"
+ " vst2.8 {d0[0],d1[0]},[%[dst]]! \n\t"
+ " bge 4b \n\t"
+ "5: @ end \n\t"
+#ifdef NEEDS_ARM_ERRATA_754319_754320
+ " vmov s0,s0 @ add noop for errata item \n\t"
+#endif
+ : [dst] "+r" (bufferDst_UV), [src] "+r" (bufferSrc_UV), [n] "+r" (n)
+ : [src_stride] "r" (stride_bytes)
+ : "cc", "memory", "q0", "q1"
+ );
+ }
+#else
+ for ( int i = 0; i < height/2; ++i ) {
+ for ( int j = 0; j < width/2; ++j ) {
+ bufferDst_UV[j] = (bufferSrc_UV[j] >> 8) | (bufferSrc_UV[j] << 8);
+ }
+ bufferSrc_UV += stride/bytesPerPixel/2;
+ bufferDst_UV += width/2;
+ }
+#endif
+ } else if (strcmp(pixelFormat, android::CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
+ // Step 2: UV plane: convert NV12 to YV12 by de-interleaving U & V
+ // TODO(XXX): This version of CameraHal assumes NV12 format it set at
+ // camera adapter to support YV12. Need to address for
+ // USBCamera
+
+ size_t yStride, uvStride, ySize, uvSize, size;
+ alignYV12(width, height, yStride, uvStride, ySize, uvSize, size);
+
+ uint16_t *bufferDst_V = (uint16_t *) (((uint8_t*)dst) + ySize);
+ uint16_t *bufferDst_U = (uint16_t *) (((uint8_t*)dst) + ySize + uvSize);
+
+#ifdef ARCH_ARM_HAVE_NEON
+ int inc = (uvStride - width/2)/2;
+
+ for (int i = 0 ; i < height/2 ; i++, bufferSrc_UV += alignedRow/2) {
+ int n = width;
+ asm volatile (
+ " pld [%[src], %[src_stride], lsl #2] \n\t"
+ " cmp %[n], #32 \n\t"
+ " blt 1f \n\t"
+ "0: @ 32 byte swap \n\t"
+ " sub %[n], %[n], #32 \n\t"
+ " vld2.8 {q0, q1} , [%[src]]! \n\t"
+ " cmp %[n], #32 \n\t"
+ " vst1.8 {q1},[%[dst_v]]! \n\t"
+ " vst1.8 {q0},[%[dst_u]]! \n\t"
+ " bge 0b \n\t"
+ "1: @ Is there enough data? \n\t"
+ " cmp %[n], #16 \n\t"
+ " blt 3f \n\t"
+ "2: @ 16 byte swap \n\t"
+ " sub %[n], %[n], #16 \n\t"
+ " vld2.8 {d0, d1} , [%[src]]! \n\t"
+ " cmp %[n], #16 \n\t"
+ " vst1.8 {d1},[%[dst_v]]! \n\t"
+ " vst1.8 {d0},[%[dst_u]]! \n\t"
+ " bge 2b \n\t"
+ "3: @ Is there enough data? \n\t"
+ " cmp %[n], #8 \n\t"
+ " blt 5f \n\t"
+ "4: @ 8 byte swap \n\t"
+ " sub %[n], %[n], #8 \n\t"
+ " vld2.8 {d0, d1} , [%[src]]! \n\t"
+ " cmp %[n], #8 \n\t"
+ " vst1.8 {d1[0]},[%[dst_v]]! \n\t"
+ " vst1.8 {d0[0]},[%[dst_u]]! \n\t"
+ " bge 4b \n\t"
+ "5: @ end \n\t"
+#ifdef NEEDS_ARM_ERRATA_754319_754320
+ " vmov s0,s0 @ add noop for errata item \n\t"
+#endif
+ : [dst_u] "+r" (bufferDst_U), [dst_v] "+r" (bufferDst_V),
+ [src] "+r" (bufferSrc_UV), [n] "+r" (n)
+ : [src_stride] "r" (stride_bytes)
+ : "cc", "memory", "q0", "q1"
+ );
+
+ bufferDst_U += inc;
+ bufferDst_V += inc;
+ }
+#else
+ uint8_t * udst = reinterpret_cast<uint8_t*>(bufferDst_V);
+ uint8_t * vdst = reinterpret_cast<uint8_t*>(bufferDst_U);
+
+ for ( int i = 0; i < height/2; ++i ) {
+ for ( int j = 0; j < width/2; ++j ) {
+ udst[j] = bufferSrc_UV[j] >> 8;
+ vdst[j] = bufferSrc_UV[j] & 0x00ff;
+ }
+ bufferSrc_UV += stride/bytesPerPixel/2;
+ udst += width/2;
+ vdst += width/2;
+ }
+#endif
+ }
+ return ;
+
+ } else if(strcmp(pixelFormat, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
+ bytesPerPixel = 2;
+ }
+ }
+
+ bufferDst = ( unsigned char * ) dst;
+ bufferSrc = ( unsigned char * ) y_uv[0];
+ row = width*bytesPerPixel;
+ alignedRow = ( row + ( stride -1 ) ) & ( ~ ( stride -1 ) );
+
+ //iterate through each row
+ for ( int i = 0 ; i < height ; i++, bufferSrc += alignedRow, bufferDst += row) {
+ memcpy(bufferDst, bufferSrc, row);
+ }
+}
+
+static void copyCroppedNV12(CameraFrame* frame, unsigned char *dst)
+{
+ unsigned int stride, width, height;
+ uint32_t offset, uvoffset;
+ size_t size;
+
+ CAMHAL_ASSERT(frame && dst);
+
+ offset = frame->mOffset;
+ stride = frame->mAlignment;
+ width = frame->mWidth;
+ height = frame->mHeight;
+ size = frame->mLength;
+ unsigned const char *src = (unsigned char *) frame->mBuffer->mapped;
+
+ // offset to beginning of uv plane
+ uvoffset = (offset + size) * 2 / 3;
+ // offset to beginning of valid region of uv plane
+ uvoffset += (offset - (offset % stride)) / 2 + (offset % stride);
+
+ // start of valid luma region
+ unsigned const char *luma = src + offset;
+ // start of valid chroma region
+ unsigned const char *chroma = src + uvoffset;
+
+ // copy luma and chroma line x line
+ for (unsigned int i = 0; i < height; i++) {
+ memcpy(dst, luma, width);
+ luma += stride;
+ dst += width;
+ }
+ for (unsigned int i = 0; i < height / 2; i++) {
+ memcpy(dst, chroma, width);
+ chroma += stride;
+ dst += width;
+ }
+}
+
+void AppCallbackNotifier::copyAndSendPictureFrame(CameraFrame* frame, int32_t msgType)
+{
+ camera_memory_t* picture = NULL;
+ void *dest = NULL, *src = NULL;
+
+ // scope for lock
+ if (mCameraHal->msgTypeEnabled(msgType)) {
+ android::AutoMutex lock(mLock);
+
+ if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) {
+ goto exit;
+ }
+
+ if (frame->mBuffer->format &&
+ (strcmp(frame->mBuffer->format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) &&
+ (frame->mAlignment != frame->mWidth) &&
+ ( msgType == CAMERA_MSG_RAW_IMAGE )) {
+ size_t size;
+
+ size = CameraHal::calculateBufferSize(frame->mBuffer->format, frame->mWidth, frame->mHeight);
+ picture = mRequestMemory(-1, size, 1, NULL);
+ if (picture && picture->data) {
+ copyCroppedNV12(frame, (unsigned char*) picture->data);
+ }
+ } else {
+ picture = mRequestMemory(-1, frame->mLength, 1, NULL);
+
+ if (NULL != picture) {
+ dest = picture->data;
+ if (NULL != dest) {
+ src = (void *) ((unsigned int) frame->mBuffer->mapped + frame->mOffset);
+ memcpy(dest, src, frame->mLength);
+ }
+ }
+ }
+ }
+
+ exit:
+ mFrameProvider->returnFrame(frame->mBuffer, (CameraFrame::FrameType) frame->mFrameType);
+
+ if(picture) {
+ if((mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) &&
+ mCameraHal->msgTypeEnabled(msgType)) {
+ mDataCb(msgType, picture, 0, NULL, mCallbackCookie);
+ }
+ picture->release(picture);
+ }
+}
+
+void AppCallbackNotifier::lockBufferAndUpdatePtrs(CameraFrame* frame)
+{
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ android::Rect bounds;
+
+ bounds.left = 0;
+ bounds.top = 0;
+ bounds.right = frame->mWidth;
+ bounds.bottom = frame->mHeight;
+ void *y_uv[2];
+ buffer_handle_t *handle = reinterpret_cast<buffer_handle_t *>(frame->mBuffer->opaque);
+ mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+ frame->mBuffer->mapped = y_uv[0];
+ frame->mYuv[0] = reinterpret_cast<int>(frame->mBuffer->mapped);
+ frame->mYuv[1] = frame->mYuv[0] + (frame->mLength + frame->mOffset)*2/3;
+}
+
+void AppCallbackNotifier::unlockBufferAndUpdatePtrs(CameraFrame* frame)
+{
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ buffer_handle_t *handle = reinterpret_cast<buffer_handle_t *>(frame->mBuffer->opaque);
+ mapper.unlock(*handle);
+ frame->mBuffer->mapped = NULL;
+ frame->mYuv[0] = NULL;
+ frame->mYuv[1] = NULL;
+}
+
+void AppCallbackNotifier::setExternalLocking(bool extBuffLocking)
+{
+ mExternalLocking = extBuffLocking;
+}
+
+void AppCallbackNotifier::copyAndSendPreviewFrame(CameraFrame* frame, int32_t msgType)
+{
+ camera_memory_t* picture = NULL;
+ CameraBuffer * dest = NULL;
+
+ // scope for lock
+ {
+ android::AutoMutex lock(mLock);
+
+ if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) {
+ goto exit;
+ }
+
+ if (!mPreviewMemory || !frame->mBuffer) {
+ CAMHAL_LOGDA("Error! One of the buffer is NULL");
+ goto exit;
+ }
+
+ dest = &mPreviewBuffers[mPreviewBufCount];
+ if (mExternalLocking) {
+ lockBufferAndUpdatePtrs(frame);
+ }
+ CAMHAL_LOGVB("%d:copy2Dto1D(%p, %p, %d, %d, %d, %d, %d,%s)",
+ __LINE__,
+ dest,
+ frame->mBuffer,
+ mPreviewWidth,
+ mPreviewHeight,
+ mPreviewStride,
+ 2,
+ frame->mLength,
+ mPreviewPixelFormat);
+
+ /* FIXME map dest */
+ if ( NULL != dest && dest->mapped != NULL ) {
+ // data sync frames don't need conversion
+ if (CameraFrame::FRAME_DATA_SYNC == frame->mFrameType) {
+ if ( (mPreviewMemory->size / MAX_BUFFERS) >= frame->mLength ) {
+ memcpy(dest->mapped, (void*) frame->mBuffer->mapped, frame->mLength);
+ } else {
+ memset(dest->mapped, 0, (mPreviewMemory->size / MAX_BUFFERS));
+ }
+ } else {
+ if ((NULL == frame->mYuv[0]) || (NULL == frame->mYuv[1])){
+ CAMHAL_LOGEA("Error! One of the YUV Pointer is NULL");
+ goto exit;
+ }
+ else{
+ copy2Dto1D(dest->mapped,
+ frame->mYuv,
+ mPreviewWidth,
+ mPreviewHeight,
+ mPreviewStride,
+ frame->mOffset,
+ 2,
+ frame->mLength,
+ mPreviewPixelFormat);
+ }
+ }
+ }
+ }
+
+ exit:
+ mFrameProvider->returnFrame(frame->mBuffer, (CameraFrame::FrameType) frame->mFrameType);
+
+ if((mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) &&
+ mCameraHal->msgTypeEnabled(msgType) &&
+ (dest != NULL) && (dest->mapped != NULL)) {
+ android::AutoMutex locker(mLock);
+ if ( mPreviewMemory )
+ mDataCb(msgType, mPreviewMemory, mPreviewBufCount, NULL, mCallbackCookie);
+ }
+
+ if (mExternalLocking) {
+ unlockBufferAndUpdatePtrs(frame);
+ }
+
+ // increment for next buffer
+ mPreviewBufCount = (mPreviewBufCount + 1) % AppCallbackNotifier::MAX_BUFFERS;
+}
+
+status_t AppCallbackNotifier::dummyRaw()
+{
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == mRequestMemory ) {
+ CAMHAL_LOGEA("Can't allocate memory for dummy raw callback!");
+ return NO_INIT;
+ }
+
+ if ( ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) &&
+ ( NULL != mNotifyCb ) ){
+
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) ) {
+ camera_memory_t *dummyRaw = mRequestMemory(-1, 1, 1, NULL);
+
+ if ( NULL == dummyRaw ) {
+ CAMHAL_LOGEA("Dummy raw buffer allocation failed!");
+ return NO_MEMORY;
+ }
+
+ mDataCb(CAMERA_MSG_RAW_IMAGE, dummyRaw, 0, NULL, mCallbackCookie);
+
+ dummyRaw->release(dummyRaw);
+ } else if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) {
+ mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+void AppCallbackNotifier::notifyFrame()
+{
+ ///Receive and send the frame notifications to app
+ Utils::Message msg;
+ CameraFrame *frame;
+ android::MemoryHeapBase *heap;
+ android::MemoryBase *buffer = NULL;
+ android::sp<android::MemoryBase> memBase;
+ void *buf = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ {
+ android::AutoMutex lock(mLock);
+ if(!mFrameQ.isEmpty()) {
+ mFrameQ.get(&msg);
+ } else {
+ return;
+ }
+ }
+
+ bool ret = true;
+
+ frame = NULL;
+ switch(msg.command)
+ {
+ case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME:
+
+ frame = (CameraFrame *) msg.arg1;
+ if(!frame)
+ {
+ break;
+ }
+
+ if ( (CameraFrame::RAW_FRAME == frame->mFrameType )&&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) &&
+ ( NULL != mNotifyCb ) )
+ {
+
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) )
+ {
+#ifdef COPY_IMAGE_BUFFER
+ copyAndSendPictureFrame(frame, CAMERA_MSG_RAW_IMAGE);
+#else
+ //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
+#endif
+ }
+ else {
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) {
+ mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
+ }
+ mFrameProvider->returnFrame(frame->mBuffer,
+ (CameraFrame::FrameType) frame->mFrameType);
+ }
+
+ mRawAvailable = true;
+
+ }
+ else if ( (CameraFrame::IMAGE_FRAME == frame->mFrameType) &&
+ (NULL != mCameraHal) &&
+ (NULL != mDataCb) &&
+ (CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG & frame->mQuirks) )
+ {
+
+ int encode_quality = 100, tn_quality = 100;
+ int tn_width, tn_height;
+ unsigned int current_snapshot = 0;
+ Encoder_libjpeg::params *main_jpeg = NULL, *tn_jpeg = NULL;
+ void* exif_data = NULL;
+ const char *previewFormat = NULL;
+ camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL);
+
+ if(raw_picture) {
+ buf = raw_picture->data;
+ }
+
+ android::CameraParameters parameters;
+ char *params = mCameraHal->getParameters();
+ const android::String8 strParams(params);
+ parameters.unflatten(strParams);
+
+ encode_quality = parameters.getInt(android::CameraParameters::KEY_JPEG_QUALITY);
+ if (encode_quality < 0 || encode_quality > 100) {
+ encode_quality = 100;
+ }
+
+ tn_quality = parameters.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ if (tn_quality < 0 || tn_quality > 100) {
+ tn_quality = 100;
+ }
+
+ if (CameraFrame::HAS_EXIF_DATA & frame->mQuirks) {
+ exif_data = frame->mCookie2;
+ }
+
+ main_jpeg = (Encoder_libjpeg::params*)
+ malloc(sizeof(Encoder_libjpeg::params));
+
+ // Video snapshot with LDCNSF on adds a few bytes start offset
+ // and a few bytes on every line. They must be skipped.
+ int rightCrop = frame->mAlignment/2 - frame->mWidth;
+
+ CAMHAL_LOGDB("Video snapshot right crop = %d", rightCrop);
+ CAMHAL_LOGDB("Video snapshot offset = %d", frame->mOffset);
+
+ if (main_jpeg) {
+ main_jpeg->src = (uint8_t *)frame->mBuffer->mapped;
+ main_jpeg->src_size = frame->mLength;
+ main_jpeg->dst = (uint8_t*) buf;
+ main_jpeg->dst_size = frame->mLength;
+ main_jpeg->quality = encode_quality;
+ main_jpeg->in_width = frame->mAlignment/2; // use stride here
+ main_jpeg->in_height = frame->mHeight;
+ main_jpeg->out_width = frame->mAlignment/2;
+ main_jpeg->out_height = frame->mHeight;
+ main_jpeg->right_crop = rightCrop;
+ main_jpeg->start_offset = frame->mOffset;
+ if ( CameraFrame::FORMAT_YUV422I_UYVY & frame->mQuirks) {
+ main_jpeg->format = TICameraParameters::PIXEL_FORMAT_YUV422I_UYVY;
+ }
+ else { //if ( CameraFrame::FORMAT_YUV422I_YUYV & frame->mQuirks)
+ main_jpeg->format = android::CameraParameters::PIXEL_FORMAT_YUV422I;
+ }
+ }
+
+ tn_width = parameters.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ tn_height = parameters.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ previewFormat = parameters.getPreviewFormat();
+
+ if ((tn_width > 0) && (tn_height > 0) && ( NULL != previewFormat )) {
+ tn_jpeg = (Encoder_libjpeg::params*)
+ malloc(sizeof(Encoder_libjpeg::params));
+ // if malloc fails just keep going and encode main jpeg
+ if (!tn_jpeg) {
+ tn_jpeg = NULL;
+ }
+ }
+
+ if (tn_jpeg) {
+ int width, height;
+ parameters.getPreviewSize(&width,&height);
+ current_snapshot = (mPreviewBufCount + MAX_BUFFERS - 1) % MAX_BUFFERS;
+ tn_jpeg->src = (uint8_t *)mPreviewBuffers[current_snapshot].mapped;
+ tn_jpeg->src_size = mPreviewMemory->size / MAX_BUFFERS;
+ tn_jpeg->dst_size = CameraHal::calculateBufferSize(previewFormat,
+ tn_width,
+ tn_height);
+ tn_jpeg->dst = (uint8_t*) malloc(tn_jpeg->dst_size);
+ tn_jpeg->quality = tn_quality;
+ tn_jpeg->in_width = width;
+ tn_jpeg->in_height = height;
+ tn_jpeg->out_width = tn_width;
+ tn_jpeg->out_height = tn_height;
+ tn_jpeg->right_crop = 0;
+ tn_jpeg->start_offset = 0;
+ tn_jpeg->format = android::CameraParameters::PIXEL_FORMAT_YUV420SP;;
+ }
+
+ android::sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg,
+ tn_jpeg,
+ AppCallbackNotifierEncoderCallback,
+ (CameraFrame::FrameType)frame->mFrameType,
+ this,
+ raw_picture,
+ exif_data, frame->mBuffer);
+ gEncoderQueue.add(frame->mBuffer->mapped, encoder);
+ encoder->run();
+ encoder.clear();
+ if (params != NULL)
+ {
+ mCameraHal->putParameters(params);
+ }
+ }
+ else if ( ( CameraFrame::IMAGE_FRAME == frame->mFrameType ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) )
+ {
+
+ // CTS, MTS requirements: Every 'takePicture()' call
+ // who registers a raw callback should receive one
+ // as well. This is not always the case with
+ // CameraAdapters though.
+ if (!mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE)) {
+ dummyRaw();
+ } else {
+ mRawAvailable = false;
+ }
+
+#ifdef COPY_IMAGE_BUFFER
+ {
+ android::AutoMutex lock(mBurstLock);
+#ifdef OMAP_ENHANCEMENT_BURST_CAPTURE
+ if ( mBurst )
+ {
+ copyAndSendPictureFrame(frame, CAMERA_MSG_COMPRESSED_BURST_IMAGE);
+ }
+ else
+#endif
+ {
+ copyAndSendPictureFrame(frame, CAMERA_MSG_COMPRESSED_IMAGE);
+ }
+ }
+#else
+ //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
+#endif
+ }
+ else if ( ( CameraFrame::VIDEO_FRAME_SYNC == frame->mFrameType ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME) ) )
+ {
+ android::AutoMutex locker(mRecordingLock);
+ if(mRecording)
+ {
+ if(mUseMetaDataBufferMode)
+ {
+ camera_memory_t *videoMedatadaBufferMemory =
+ mVideoMetadataBufferMemoryMap.valueFor(frame->mBuffer->opaque);
+ video_metadata_t *videoMetadataBuffer = (video_metadata_t *) videoMedatadaBufferMemory->data;
+
+ if( (NULL == videoMedatadaBufferMemory) || (NULL == videoMetadataBuffer) || (NULL == frame->mBuffer) )
+ {
+ CAMHAL_LOGEA("Error! One of the video buffers is NULL");
+ break;
+ }
+
+ if ( mUseVideoBuffers )
+ {
+ CameraBuffer *vBuf = mVideoMap.valueFor(frame->mBuffer->opaque);
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ android::Rect bounds;
+ bounds.left = 0;
+ bounds.top = 0;
+ bounds.right = mVideoWidth;
+ bounds.bottom = mVideoHeight;
+ if (mExternalLocking) {
+ lockBufferAndUpdatePtrs(frame);
+ }
+ void *y_uv[2];
+ mapper.lock((buffer_handle_t)vBuf, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+ y_uv[1] = y_uv[0] + mVideoHeight*4096;
+
+ structConvImage input = {frame->mWidth,
+ frame->mHeight,
+ 4096,
+ IC_FORMAT_YCbCr420_lp,
+ (mmByte *)frame->mYuv[0],
+ (mmByte *)frame->mYuv[1],
+ frame->mOffset};
+
+ structConvImage output = {mVideoWidth,
+ mVideoHeight,
+ 4096,
+ IC_FORMAT_YCbCr420_lp,
+ (mmByte *)y_uv[0],
+ (mmByte *)y_uv[1],
+ 0};
+
+ VT_resizeFrame_Video_opt2_lp(&input, &output, NULL, 0);
+ mapper.unlock((buffer_handle_t)vBuf->opaque);
+ if (mExternalLocking) {
+ unlockBufferAndUpdatePtrs(frame);
+ }
+ videoMetadataBuffer->metadataBufferType = (int) android::kMetadataBufferTypeCameraSource;
+ /* FIXME remove cast */
+ videoMetadataBuffer->handle = (void *)vBuf->opaque;
+ videoMetadataBuffer->offset = 0;
+ }
+ else
+ {
+ videoMetadataBuffer->metadataBufferType = (int) android::kMetadataBufferTypeCameraSource;
+ videoMetadataBuffer->handle = camera_buffer_get_omx_ptr(frame->mBuffer);
+ videoMetadataBuffer->offset = frame->mOffset;
+ }
+
+ CAMHAL_LOGVB("mDataCbTimestamp : frame->mBuffer=0x%x, videoMetadataBuffer=0x%x, videoMedatadaBufferMemory=0x%x",
+ frame->mBuffer->opaque, videoMetadataBuffer, videoMedatadaBufferMemory);
+
+ mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME,
+ videoMedatadaBufferMemory, 0, mCallbackCookie);
+ }
+ else
+ {
+ //TODO: Need to revisit this, should ideally be mapping the TILER buffer using mRequestMemory
+ camera_memory_t* fakebuf = mRequestMemory(-1, sizeof(buffer_handle_t), 1, NULL);
+ if( (NULL == fakebuf) || ( NULL == fakebuf->data) || ( NULL == frame->mBuffer))
+ {
+ CAMHAL_LOGEA("Error! One of the video buffers is NULL");
+ break;
+ }
+ if (mExternalLocking) {
+ lockBufferAndUpdatePtrs(frame);
+ }
+ *reinterpret_cast<buffer_handle_t*>(fakebuf->data) = reinterpret_cast<buffer_handle_t>(frame->mBuffer->mapped);
+ mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME, fakebuf, 0, mCallbackCookie);
+ fakebuf->release(fakebuf);
+ if (mExternalLocking) {
+ unlockBufferAndUpdatePtrs(frame);
+ }
+ }
+ }
+ }
+ else if(( CameraFrame::SNAPSHOT_FRAME == frame->mFrameType ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) &&
+ ( NULL != mNotifyCb)) {
+ //When enabled, measurement data is sent instead of video data
+ if ( !mMeasurementEnabled ) {
+ copyAndSendPreviewFrame(frame, CAMERA_MSG_POSTVIEW_FRAME);
+ } else {
+ mFrameProvider->returnFrame(frame->mBuffer,
+ (CameraFrame::FrameType) frame->mFrameType);
+ }
+ }
+ else if ( ( CameraFrame::PREVIEW_FRAME_SYNC== frame->mFrameType ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) {
+ //When enabled, measurement data is sent instead of video data
+ if ( !mMeasurementEnabled ) {
+ copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME);
+ } else {
+ mFrameProvider->returnFrame(frame->mBuffer,
+ (CameraFrame::FrameType) frame->mFrameType);
+ }
+ }
+ else if ( ( CameraFrame::FRAME_DATA_SYNC == frame->mFrameType ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) {
+ copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME);
+ } else {
+ mFrameProvider->returnFrame(frame->mBuffer,
+ ( CameraFrame::FrameType ) frame->mFrameType);
+ CAMHAL_LOGDB("Frame type 0x%x is still unsupported!", frame->mFrameType);
+ }
+
+ break;
+
+ default:
+
+ break;
+
+ };
+
+exit:
+
+ if ( NULL != frame )
+ {
+ delete frame;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::frameCallbackRelay(CameraFrame* caFrame)
+{
+ LOG_FUNCTION_NAME;
+ AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (caFrame->mCookie);
+ appcbn->frameCallback(caFrame);
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::frameCallback(CameraFrame* caFrame)
+{
+ ///Post the event to the event queue of AppCallbackNotifier
+ Utils::Message msg;
+ CameraFrame *frame;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL != caFrame )
+ {
+
+ frame = new CameraFrame(*caFrame);
+ if ( NULL != frame )
+ {
+ msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME;
+ msg.arg1 = frame;
+ mFrameQ.put(&msg);
+ }
+ else
+ {
+ CAMHAL_LOGEA("Not enough resources to allocate CameraFrame");
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::flushAndReturnFrames()
+{
+ LOG_FUNCTION_NAME;
+
+ Utils::Message msg;
+ CameraFrame *frame;
+
+ android::AutoMutex lock(mLock);
+ while (!mFrameQ.isEmpty()) {
+ mFrameQ.get(&msg);
+ frame = (CameraFrame*) msg.arg1;
+ if (frame) {
+ mFrameProvider->returnFrame(frame->mBuffer,
+ (CameraFrame::FrameType) frame->mFrameType);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::eventCallbackRelay(CameraHalEvent* chEvt)
+{
+ LOG_FUNCTION_NAME;
+ AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (chEvt->mCookie);
+ appcbn->eventCallback(chEvt);
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::eventCallback(CameraHalEvent* chEvt)
+{
+
+ ///Post the event to the event queue of AppCallbackNotifier
+ Utils::Message msg;
+ CameraHalEvent *event;
+
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL != chEvt )
+ {
+
+ event = new CameraHalEvent(*chEvt);
+ if ( NULL != event )
+ {
+ msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_EVENT;
+ msg.arg1 = event;
+ {
+ android::AutoMutex lock(mLock);
+ mEventQ.put(&msg);
+ }
+ }
+ else
+ {
+ CAMHAL_LOGEA("Not enough resources to allocate CameraHalEvent");
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+void AppCallbackNotifier::flushEventQueue()
+{
+
+ {
+ android::AutoMutex lock(mLock);
+ mEventQ.clear();
+ }
+}
+
+
+bool AppCallbackNotifier::processMessage()
+{
+ ///Retrieve the command from the command queue and process it
+ Utils::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ CAMHAL_LOGDA("+Msg get...");
+ mNotificationThread->msgQ().get(&msg);
+ CAMHAL_LOGDA("-Msg get...");
+ bool ret = true;
+
+ switch(msg.command)
+ {
+ case NotificationThread::NOTIFIER_EXIT:
+ {
+ CAMHAL_LOGD("Received NOTIFIER_EXIT command from Camera HAL");
+ mNotifierState = AppCallbackNotifier::NOTIFIER_EXITED;
+ ret = false;
+ break;
+ }
+ default:
+ {
+ CAMHAL_LOGEA("Error: ProcessMsg() command from Camera HAL");
+ break;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+
+
+}
+
+AppCallbackNotifier::~AppCallbackNotifier()
+{
+ LOG_FUNCTION_NAME;
+
+ ///Stop app callback notifier if not already stopped
+ stop();
+
+ ///Unregister with the frame provider
+ if ( NULL != mFrameProvider )
+ {
+ mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
+ }
+
+ //unregister with the event provider
+ if ( NULL != mEventProvider )
+ {
+ mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS);
+ }
+
+ Utils::Message msg = {0,0,0,0,0,0};
+ msg.command = NotificationThread::NOTIFIER_EXIT;
+
+ ///Post the message to display thread
+ mNotificationThread->msgQ().put(&msg);
+
+ //Exit and cleanup the thread
+ mNotificationThread->requestExit();
+ mNotificationThread->join();
+
+ //Delete the display thread
+ mNotificationThread.clear();
+
+
+ ///Free the event and frame providers
+ if ( NULL != mEventProvider )
+ {
+ ///Deleting the event provider
+ CAMHAL_LOGDA("Stopping Event Provider");
+ delete mEventProvider;
+ mEventProvider = NULL;
+ }
+
+ if ( NULL != mFrameProvider )
+ {
+ ///Deleting the frame provider
+ CAMHAL_LOGDA("Stopping Frame Provider");
+ delete mFrameProvider;
+ mFrameProvider = NULL;
+ }
+
+ releaseSharedVideoBuffers();
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+//Free all video heaps and buffers
+void AppCallbackNotifier::releaseSharedVideoBuffers()
+{
+ LOG_FUNCTION_NAME;
+
+ if(mUseMetaDataBufferMode)
+ {
+ camera_memory_t* videoMedatadaBufferMemory;
+ for (unsigned int i = 0; i < mVideoMetadataBufferMemoryMap.size(); i++)
+ {
+ videoMedatadaBufferMemory = mVideoMetadataBufferMemoryMap.valueAt(i);
+ if(NULL != videoMedatadaBufferMemory)
+ {
+ videoMedatadaBufferMemory->release(videoMedatadaBufferMemory);
+ CAMHAL_LOGDB("Released videoMedatadaBufferMemory=%p", videoMedatadaBufferMemory);
+ }
+ }
+
+ mVideoMetadataBufferMemoryMap.clear();
+ mVideoMetadataBufferReverseMap.clear();
+ if (mUseVideoBuffers)
+ {
+ mVideoMap.clear();
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier)
+{
+
+ LOG_FUNCTION_NAME;
+ ///@remarks There is no NULL check here. We will check
+ ///for NULL when we get start command from CameraHal
+ ///@Remarks Currently only one event provider (CameraAdapter) is supported
+ ///@todo Have an array of event providers for each event bitmask
+ mEventProvider = new EventProvider(eventNotifier, this, eventCallbackRelay);
+ if ( NULL == mEventProvider )
+ {
+ CAMHAL_LOGEA("Error in creating EventProvider");
+ }
+ else
+ {
+ mEventProvider->enableEventNotification(eventMask);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier)
+{
+ LOG_FUNCTION_NAME;
+ ///@remarks There is no NULL check here. We will check
+ ///for NULL when we get the start command from CameraAdapter
+ mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay);
+ if ( NULL == mFrameProvider )
+ {
+ CAMHAL_LOGEA("Error in creating FrameProvider");
+ }
+ else
+ {
+ //Register only for captured images and RAW for now
+ //TODO: Register for and handle all types of frames
+ mFrameProvider->enableFrameNotification(CameraFrame::IMAGE_FRAME);
+ mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t AppCallbackNotifier::startPreviewCallbacks(android::CameraParameters &params, CameraBuffer *buffers, uint32_t *offsets, int fd, size_t length, size_t count)
+{
+ unsigned int *bufArr;
+ int size = 0;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if ( NULL == mFrameProvider )
+ {
+ CAMHAL_LOGEA("Trying to start video recording without FrameProvider");
+ return -EINVAL;
+ }
+
+ if ( mPreviewing )
+ {
+ CAMHAL_LOGDA("+Already previewing");
+ return NO_INIT;
+ }
+
+ int w,h;
+ ///Get preview size
+ params.getPreviewSize(&w, &h);
+
+ // save preview pixel format, size and stride
+ mPreviewWidth = w;
+ mPreviewHeight = h;
+ mPreviewStride = 4096;
+ mPreviewPixelFormat = CameraHal::getPixelFormatConstant(params.getPreviewFormat());
+ size = CameraHal::calculateBufferSize(mPreviewPixelFormat, w, h);
+
+ mPreviewMemory = mRequestMemory(-1, size, AppCallbackNotifier::MAX_BUFFERS, NULL);
+ if (!mPreviewMemory) {
+ return NO_MEMORY;
+ }
+
+ for (int i=0; i < AppCallbackNotifier::MAX_BUFFERS; i++) {
+ mPreviewBuffers[i].type = CAMERA_BUFFER_MEMORY;
+ mPreviewBuffers[i].opaque = (unsigned char*) mPreviewMemory->data + (i*size);
+ mPreviewBuffers[i].mapped = mPreviewBuffers[i].opaque;
+ }
+
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME ) ) {
+ mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_POSTVIEW_FRAME) ) {
+ mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
+ }
+
+ mPreviewBufCount = 0;
+
+ mPreviewing = true;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+void AppCallbackNotifier::setBurst(bool burst)
+{
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mBurstLock);
+
+ mBurst = burst;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::useVideoBuffers(bool useVideoBuffers)
+{
+ LOG_FUNCTION_NAME;
+
+ mUseVideoBuffers = useVideoBuffers;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+bool AppCallbackNotifier::getUesVideoBuffers()
+{
+ return mUseVideoBuffers;
+}
+
+void AppCallbackNotifier::setVideoRes(int width, int height)
+{
+ LOG_FUNCTION_NAME;
+
+ mVideoWidth = width;
+ mVideoHeight = height;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t AppCallbackNotifier::stopPreviewCallbacks()
+{
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == mFrameProvider )
+ {
+ CAMHAL_LOGEA("Trying to stop preview callbacks without FrameProvider");
+ return -EINVAL;
+ }
+
+ if ( !mPreviewing )
+ {
+ return NO_INIT;
+ }
+
+ mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ mFrameProvider->disableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
+
+ {
+ android::AutoMutex lock(mLock);
+ mPreviewMemory->release(mPreviewMemory);
+ mPreviewMemory = 0;
+ }
+
+ mPreviewing = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+
+}
+
+status_t AppCallbackNotifier::useMetaDataBufferMode(bool enable)
+{
+ mUseMetaDataBufferMode = enable;
+
+ return NO_ERROR;
+}
+
+
+status_t AppCallbackNotifier::startRecording()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mRecordingLock);
+
+ if ( NULL == mFrameProvider )
+ {
+ CAMHAL_LOGEA("Trying to start video recording without FrameProvider");
+ ret = -1;
+ }
+
+ if(mRecording)
+ {
+ return NO_INIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mFrameProvider->enableFrameNotification(CameraFrame::VIDEO_FRAME_SYNC);
+ }
+
+ mRecording = true;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+//Allocate metadata buffers for video recording
+status_t AppCallbackNotifier::initSharedVideoBuffers(CameraBuffer *buffers, uint32_t *offsets, int fd, size_t length, size_t count, CameraBuffer *vidBufs)
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ if(mUseMetaDataBufferMode)
+ {
+ camera_memory_t* videoMedatadaBufferMemory = NULL;
+
+ if(NULL == buffers)
+ {
+ CAMHAL_LOGEA("Error! Video buffers are NULL");
+ return BAD_VALUE;
+ }
+
+ for (uint32_t i = 0; i < count; i++)
+ {
+ videoMedatadaBufferMemory = mRequestMemory(-1, sizeof(video_metadata_t), 1, NULL);
+ if((NULL == videoMedatadaBufferMemory) || (NULL == videoMedatadaBufferMemory->data))
+ {
+ CAMHAL_LOGEA("Error! Could not allocate memory for Video Metadata Buffers");
+ return NO_MEMORY;
+ }
+
+ // FIXME remove cast
+ mVideoMetadataBufferMemoryMap.add((void *)buffers[i].opaque, videoMedatadaBufferMemory);
+ mVideoMetadataBufferReverseMap.add(videoMedatadaBufferMemory->data, &buffers[i]);
+ CAMHAL_LOGDB("buffers[%d]=%p, videoMedatadaBufferMemory=%p, videoMedatadaBufferMemory->data=%p",
+ i, &buffers[i], videoMedatadaBufferMemory, videoMedatadaBufferMemory->data);
+
+ if (vidBufs != NULL)
+ {
+ //ASSERT(buffers[i].type == CAMERA_BUFFER_GRALLOC);
+ // FIXME remove cast
+ mVideoMap.add((void *)buffers[i].opaque, &vidBufs[i]);
+ CAMHAL_LOGVB("buffers[%d]=%p, vBuffArr[%d]=%p", i, &buffers[i], i, &vidBufs[i]);
+ }
+ }
+ }
+
+exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t AppCallbackNotifier::stopRecording()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mRecordingLock);
+
+ if ( NULL == mFrameProvider )
+ {
+ CAMHAL_LOGEA("Trying to stop video recording without FrameProvider");
+ ret = -1;
+ }
+
+ if(!mRecording)
+ {
+ return NO_INIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mFrameProvider->disableFrameNotification(CameraFrame::VIDEO_FRAME_SYNC);
+ }
+
+ ///Release the shared video buffers
+ releaseSharedVideoBuffers();
+
+ mRecording = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t AppCallbackNotifier::releaseRecordingFrame(const void* mem)
+{
+ status_t ret = NO_ERROR;
+ CameraBuffer *frame = NULL;
+
+ LOG_FUNCTION_NAME;
+ if ( NULL == mFrameProvider )
+ {
+ CAMHAL_LOGEA("Trying to stop video recording without FrameProvider");
+ ret = -1;
+ }
+
+ if ( NULL == mem )
+ {
+ CAMHAL_LOGEA("Video Frame released is invalid");
+ ret = -1;
+ }
+
+ if( NO_ERROR != ret )
+ {
+ return ret;
+ }
+
+ if(mUseMetaDataBufferMode)
+ {
+ video_metadata_t *videoMetadataBuffer = (video_metadata_t *) mem ;
+ /* FIXME remove cast */
+ frame = mVideoMetadataBufferReverseMap.valueFor(videoMetadataBuffer);
+ CAMHAL_LOGVB("Releasing frame with videoMetadataBuffer=0x%x, videoMetadataBuffer->handle=0x%x & frame handle=0x%x\n",
+ videoMetadataBuffer, videoMetadataBuffer->handle, frame);
+ }
+ else
+ {
+ /* FIXME this won't work */
+ frame = (CameraBuffer *)(void*)(*((uint32_t *)mem));
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = mFrameProvider->returnFrame(frame, CameraFrame::VIDEO_FRAME_SYNC);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t AppCallbackNotifier::enableMsgType(int32_t msgType)
+{
+ if( msgType & CAMERA_MSG_PREVIEW_FRAME ) {
+ mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+
+ if( msgType & CAMERA_MSG_POSTVIEW_FRAME ) {
+ mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
+ }
+
+ if(msgType & CAMERA_MSG_RAW_IMAGE) {
+ mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME);
+ }
+
+ return NO_ERROR;
+}
+
+status_t AppCallbackNotifier::disableMsgType(int32_t msgType)
+{
+ if( msgType & CAMERA_MSG_PREVIEW_FRAME ) {
+ mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+
+ if( msgType & CAMERA_MSG_POSTVIEW_FRAME ) {
+ mFrameProvider->disableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
+ }
+
+ if(msgType & CAMERA_MSG_RAW_IMAGE) {
+ mFrameProvider->disableFrameNotification(CameraFrame::RAW_FRAME);
+ }
+
+ return NO_ERROR;
+
+}
+
+status_t AppCallbackNotifier::start()
+{
+ LOG_FUNCTION_NAME;
+ if(mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED)
+ {
+ CAMHAL_LOGDA("AppCallbackNotifier already running");
+ LOG_FUNCTION_NAME_EXIT;
+ return ALREADY_EXISTS;
+ }
+
+ ///Check whether initial conditions are met for us to start
+ ///A frame provider should be available, if not return error
+ if(!mFrameProvider)
+ {
+ ///AppCallbackNotifier not properly initialized
+ CAMHAL_LOGEA("AppCallbackNotifier not properly initialized - Frame provider is NULL");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ ///At least one event notifier should be available, if not return error
+ ///@todo Modify here when there is an array of event providers
+ if(!mEventProvider)
+ {
+ CAMHAL_LOGEA("AppCallbackNotifier not properly initialized - Event provider is NULL");
+ LOG_FUNCTION_NAME_EXIT;
+ ///AppCallbackNotifier not properly initialized
+ return NO_INIT;
+ }
+
+ mNotifierState = AppCallbackNotifier::NOTIFIER_STARTED;
+ CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STARTED \n");
+
+ gEncoderQueue.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+
+}
+
+status_t AppCallbackNotifier::stop()
+{
+ LOG_FUNCTION_NAME;
+
+ if(mNotifierState!=AppCallbackNotifier::NOTIFIER_STARTED)
+ {
+ CAMHAL_LOGDA("AppCallbackNotifier already in stopped state");
+ LOG_FUNCTION_NAME_EXIT;
+ return ALREADY_EXISTS;
+ }
+ {
+ android::AutoMutex lock(mLock);
+
+ mNotifierState = AppCallbackNotifier::NOTIFIER_STOPPED;
+ CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STOPPED \n");
+ }
+
+ while(!gEncoderQueue.isEmpty()) {
+ android::sp<Encoder_libjpeg> encoder = gEncoderQueue.valueAt(0);
+ camera_memory_t* encoded_mem = NULL;
+ ExifElementsTable* exif = NULL;
+
+ if(encoder.get()) {
+ encoder->cancel();
+
+ encoder->getCookies(NULL, (void**) &encoded_mem, (void**) &exif);
+ if (encoded_mem) {
+ encoded_mem->release(encoded_mem);
+ }
+ if (exif) {
+ delete exif;
+ }
+
+ encoder.clear();
+ }
+ gEncoderQueue.removeItemsAt(0);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+}
+
+
+/*--------------------NotificationHandler Class ENDS here-----------------------------*/
+
+
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/BaseCameraAdapter.cpp b/camera/BaseCameraAdapter.cpp
new file mode 100644
index 0000000..dafefb0
--- /dev/null
+++ b/camera/BaseCameraAdapter.cpp
@@ -0,0 +1,2744 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BaseCameraAdapter.h"
+
+const int EVENT_MASK = 0xffff;
+
+namespace Ti {
+namespace Camera {
+
+const LUT cameraCommandsUserToHAL[] = {
+ { "CAMERA_START_PREVIEW", CameraAdapter::CAMERA_START_PREVIEW },
+ { "CAMERA_STOP_PREVIEW", CameraAdapter::CAMERA_STOP_PREVIEW },
+ { "CAMERA_START_VIDEO", CameraAdapter::CAMERA_START_VIDEO },
+ { "CAMERA_STOP_VIDEO", CameraAdapter::CAMERA_STOP_VIDEO },
+ { "CAMERA_START_IMAGE_CAPTURE", CameraAdapter::CAMERA_START_IMAGE_CAPTURE },
+ { "CAMERA_STOP_IMAGE_CAPTURE", CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE },
+ { "CAMERA_PERFORM_AUTOFOCUS", CameraAdapter::CAMERA_PERFORM_AUTOFOCUS },
+ { "CAMERA_CANCEL_AUTOFOCUS", CameraAdapter::CAMERA_CANCEL_AUTOFOCUS },
+ { "CAMERA_PREVIEW_FLUSH_BUFFERS", CameraAdapter::CAMERA_PREVIEW_FLUSH_BUFFERS },
+ { "CAMERA_START_SMOOTH_ZOOM", CameraAdapter::CAMERA_START_SMOOTH_ZOOM },
+ { "CAMERA_STOP_SMOOTH_ZOOM", CameraAdapter::CAMERA_STOP_SMOOTH_ZOOM },
+ { "CAMERA_USE_BUFFERS_PREVIEW", CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW },
+ { "CAMERA_SET_TIMEOUT", CameraAdapter::CAMERA_SET_TIMEOUT },
+ { "CAMERA_CANCEL_TIMEOUT", CameraAdapter::CAMERA_CANCEL_TIMEOUT },
+ { "CAMERA_START_BRACKET_CAPTURE", CameraAdapter::CAMERA_START_BRACKET_CAPTURE },
+ { "CAMERA_STOP_BRACKET_CAPTURE", CameraAdapter::CAMERA_STOP_BRACKET_CAPTURE },
+ { "CAMERA_QUERY_RESOLUTION_PREVIEW", CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW },
+ { "CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE", CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE },
+ { "CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA", CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA },
+ { "CAMERA_USE_BUFFERS_IMAGE_CAPTURE", CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE },
+ { "CAMERA_USE_BUFFERS_PREVIEW_DATA", CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA },
+ { "CAMERA_TIMEOUT_EXPIRED", CameraAdapter::CAMERA_TIMEOUT_EXPIRED },
+ { "CAMERA_START_FD", CameraAdapter::CAMERA_START_FD },
+ { "CAMERA_STOP_FD", CameraAdapter::CAMERA_STOP_FD },
+ { "CAMERA_SWITCH_TO_EXECUTING", CameraAdapter::CAMERA_SWITCH_TO_EXECUTING },
+ { "CAMERA_USE_BUFFERS_VIDEO_CAPTURE", CameraAdapter::CAMERA_USE_BUFFERS_VIDEO_CAPTURE },
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ { "CAMERA_USE_BUFFERS_REPROCESS", CameraAdapter::CAMERA_USE_BUFFERS_REPROCESS },
+ { "CAMERA_START_REPROCESS", CameraAdapter::CAMERA_START_REPROCESS },
+#endif
+};
+
+const LUTtypeHAL CamCommandsLUT = {
+ sizeof(cameraCommandsUserToHAL)/sizeof(cameraCommandsUserToHAL[0]),
+ cameraCommandsUserToHAL
+};
+
+/*--------------------Camera Adapter Class STARTS here-----------------------------*/
+
+BaseCameraAdapter::BaseCameraAdapter()
+{
+ mReleaseImageBuffersCallback = NULL;
+ mEndImageCaptureCallback = NULL;
+ mErrorNotifier = NULL;
+ mEndCaptureData = NULL;
+ mReleaseData = NULL;
+ mRecording = false;
+
+ mPreviewBuffers = NULL;
+ mPreviewBufferCount = 0;
+ mPreviewBuffersLength = 0;
+
+ mVideoBuffers = NULL;
+ mVideoBuffersCount = 0;
+ mVideoBuffersLength = 0;
+
+ mCaptureBuffers = NULL;
+ mCaptureBuffersCount = 0;
+ mCaptureBuffersLength = 0;
+
+ mPreviewDataBuffers = NULL;
+ mPreviewDataBuffersCount = 0;
+ mPreviewDataBuffersLength = 0;
+
+ mAdapterState = INTIALIZED_STATE;
+
+ mSharedAllocator = NULL;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ mStartFocus.tv_sec = 0;
+ mStartFocus.tv_usec = 0;
+ mStartCapture.tv_sec = 0;
+ mStartCapture.tv_usec = 0;
+#endif
+
+}
+
+BaseCameraAdapter::~BaseCameraAdapter()
+{
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mSubscriberLock);
+
+ mFrameSubscribers.clear();
+ mImageSubscribers.clear();
+ mRawSubscribers.clear();
+ mVideoSubscribers.clear();
+ mVideoInSubscribers.clear();
+ mFocusSubscribers.clear();
+ mShutterSubscribers.clear();
+ mZoomSubscribers.clear();
+ mSnapshotSubscribers.clear();
+ mMetadataSubscribers.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t BaseCameraAdapter::registerImageReleaseCallback(release_image_buffers_callback callback, void *user_data)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ mReleaseImageBuffersCallback = callback;
+ mReleaseData = user_data;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::registerEndCaptureCallback(end_image_capture_callback callback, void *user_data)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ mEndImageCaptureCallback= callback;
+ mEndCaptureData = user_data;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::setErrorHandler(ErrorNotifier *errorNotifier)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == errorNotifier )
+ {
+ CAMHAL_LOGEA("Invalid Error Notifier reference");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mErrorNotifier = errorNotifier;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+void BaseCameraAdapter::enableMsgType(int32_t msgs, frame_callback callback, event_callback eventCb, void* cookie)
+{
+ android::AutoMutex lock(mSubscriberLock);
+
+ LOG_FUNCTION_NAME;
+
+ int32_t frameMsg = ((msgs >> MessageNotifier::FRAME_BIT_FIELD_POSITION) & EVENT_MASK);
+ int32_t eventMsg = ((msgs >> MessageNotifier::EVENT_BIT_FIELD_POSITION) & EVENT_MASK);
+
+ if ( frameMsg != 0 )
+ {
+ CAMHAL_LOGVB("Frame message type id=0x%x subscription request", frameMsg);
+ switch ( frameMsg )
+ {
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ mFrameSubscribers.add((int) cookie, callback);
+ break;
+ case CameraFrame::FRAME_DATA_SYNC:
+ mFrameDataSubscribers.add((int) cookie, callback);
+ break;
+ case CameraFrame::SNAPSHOT_FRAME:
+ mSnapshotSubscribers.add((int) cookie, callback);
+ break;
+ case CameraFrame::IMAGE_FRAME:
+ mImageSubscribers.add((int) cookie, callback);
+ break;
+ case CameraFrame::RAW_FRAME:
+ mRawSubscribers.add((int) cookie, callback);
+ break;
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ mVideoSubscribers.add((int) cookie, callback);
+ break;
+ case CameraFrame::REPROCESS_INPUT_FRAME:
+ mVideoInSubscribers.add((int) cookie, callback);
+ break;
+ default:
+ CAMHAL_LOGEA("Frame message type id=0x%x subscription no supported yet!", frameMsg);
+ break;
+ }
+ }
+
+ if ( eventMsg != 0)
+ {
+ CAMHAL_LOGVB("Event message type id=0x%x subscription request", eventMsg);
+ if ( CameraHalEvent::ALL_EVENTS == eventMsg )
+ {
+ mFocusSubscribers.add((int) cookie, eventCb);
+ mShutterSubscribers.add((int) cookie, eventCb);
+ mZoomSubscribers.add((int) cookie, eventCb);
+ mMetadataSubscribers.add((int) cookie, eventCb);
+ }
+ else
+ {
+ CAMHAL_LOGEA("Event message type id=0x%x subscription no supported yet!", eventMsg);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void BaseCameraAdapter::disableMsgType(int32_t msgs, void* cookie)
+{
+ android::AutoMutex lock(mSubscriberLock);
+
+ LOG_FUNCTION_NAME;
+
+ int32_t frameMsg = ((msgs >> MessageNotifier::FRAME_BIT_FIELD_POSITION) & EVENT_MASK);
+ int32_t eventMsg = ((msgs >> MessageNotifier::EVENT_BIT_FIELD_POSITION) & EVENT_MASK);
+
+ if ( frameMsg != 0 )
+ {
+ CAMHAL_LOGVB("Frame message type id=0x%x remove subscription request", frameMsg);
+ switch ( frameMsg )
+ {
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ mFrameSubscribers.removeItem((int) cookie);
+ break;
+ case CameraFrame::FRAME_DATA_SYNC:
+ mFrameDataSubscribers.removeItem((int) cookie);
+ break;
+ case CameraFrame::SNAPSHOT_FRAME:
+ mSnapshotSubscribers.removeItem((int) cookie);
+ break;
+ case CameraFrame::IMAGE_FRAME:
+ mImageSubscribers.removeItem((int) cookie);
+ break;
+ case CameraFrame::RAW_FRAME:
+ mRawSubscribers.removeItem((int) cookie);
+ break;
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ mVideoSubscribers.removeItem((int) cookie);
+ break;
+ case CameraFrame::REPROCESS_INPUT_FRAME:
+ mVideoInSubscribers.removeItem((int) cookie);
+ break;
+ case CameraFrame::ALL_FRAMES:
+ mFrameSubscribers.removeItem((int) cookie);
+ mFrameDataSubscribers.removeItem((int) cookie);
+ mSnapshotSubscribers.removeItem((int) cookie);
+ mImageSubscribers.removeItem((int) cookie);
+ mRawSubscribers.removeItem((int) cookie);
+ mVideoSubscribers.removeItem((int) cookie);
+ mVideoInSubscribers.removeItem((int) cookie);
+ break;
+ default:
+ CAMHAL_LOGEA("Frame message type id=0x%x subscription remove not supported yet!", frameMsg);
+ break;
+ }
+ }
+
+ if ( eventMsg != 0 )
+ {
+ CAMHAL_LOGVB("Event message type id=0x%x remove subscription request", eventMsg);
+ if ( CameraHalEvent::ALL_EVENTS == eventMsg)
+ {
+ //TODO: Process case by case
+ mFocusSubscribers.removeItem((int) cookie);
+ mShutterSubscribers.removeItem((int) cookie);
+ mZoomSubscribers.removeItem((int) cookie);
+ mMetadataSubscribers.removeItem((int) cookie);
+ }
+ else
+ {
+ CAMHAL_LOGEA("Event message type id=0x%x subscription remove not supported yet!", eventMsg);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void BaseCameraAdapter::addFramePointers(CameraBuffer *frameBuf, void *buf)
+{
+ unsigned int *pBuf = (unsigned int *)buf;
+ android::AutoMutex lock(mSubscriberLock);
+
+ if ((frameBuf != NULL) && ( pBuf != NULL) )
+ {
+ CameraFrame *frame = new CameraFrame;
+ frame->mBuffer = frameBuf;
+ frame->mYuv[0] = pBuf[0];
+ frame->mYuv[1] = pBuf[1];
+ mFrameQueue.add(frameBuf, frame);
+
+ CAMHAL_LOGVB("Adding Frame=0x%x Y=0x%x UV=0x%x", frame->mBuffer, frame->mYuv[0], frame->mYuv[1]);
+ }
+}
+
+void BaseCameraAdapter::removeFramePointers()
+{
+ android::AutoMutex lock(mSubscriberLock);
+
+ int size = mFrameQueue.size();
+ CAMHAL_LOGVB("Removing %d Frames = ", size);
+ for (int i = 0; i < size; i++)
+ {
+ CameraFrame *frame = (CameraFrame *)mFrameQueue.valueAt(i);
+ CAMHAL_LOGVB("Free Frame=0x%x Y=0x%x UV=0x%x", frame->mBuffer, frame->mYuv[0], frame->mYuv[1]);
+ delete frame;
+ }
+ mFrameQueue.clear();
+}
+
+void BaseCameraAdapter::returnFrame(CameraBuffer * frameBuf, CameraFrame::FrameType frameType)
+{
+ status_t res = NO_ERROR;
+ size_t subscriberCount = 0;
+ int refCount = -1;
+
+ if ( NULL == frameBuf )
+ {
+ CAMHAL_LOGEA("Invalid frameBuf");
+ return;
+ }
+
+ if ( NO_ERROR == res)
+ {
+ android::AutoMutex lock(mReturnFrameLock);
+
+ refCount = getFrameRefCountByType(frameBuf, frameType);
+
+ if(frameType == CameraFrame::PREVIEW_FRAME_SYNC)
+ {
+ mFramesWithDisplay--;
+ }
+ else if(frameType == CameraFrame::VIDEO_FRAME_SYNC)
+ {
+ mFramesWithEncoder--;
+ }
+
+ if ( 0 < refCount )
+ {
+
+ refCount--;
+ setFrameRefCountByType(frameBuf, frameType, refCount);
+
+ if (mRecording) {
+ refCount += getFrameRefCount(frameBuf);
+ }
+
+ }
+ else
+ {
+ CAMHAL_LOGDA("Frame returned when ref count is already zero!!");
+ return;
+ }
+ }
+
+ CAMHAL_LOGVB("REFCOUNT 0x%x %d", frameBuf, refCount);
+
+ if ( NO_ERROR == res )
+ {
+ //check if someone is holding this buffer
+ if ( 0 == refCount )
+ {
+#ifdef CAMERAHAL_DEBUG
+ {
+ android::AutoMutex locker(mBuffersWithDucatiLock);
+ if((mBuffersWithDucati.indexOfKey((int)camera_buffer_get_omx_ptr(frameBuf)) >= 0) &&
+ ((CameraFrame::PREVIEW_FRAME_SYNC == frameType) ||
+ (CameraFrame::SNAPSHOT_FRAME == frameType)))
+ {
+ CAMHAL_LOGE("Buffer already with Ducati!! 0x%x", frameBuf);
+ for(int i=0;i<mBuffersWithDucati.size();i++) CAMHAL_LOGE("0x%x", mBuffersWithDucati.keyAt(i));
+ }
+ mBuffersWithDucati.add((int)camera_buffer_get_omx_ptr(frameBuf),1);
+ }
+#endif
+ res = fillThisBuffer(frameBuf, frameType);
+ }
+ }
+
+}
+
+status_t BaseCameraAdapter::sendCommand(CameraCommands operation, int value1, int value2, int value3, int value4) {
+ status_t ret = NO_ERROR;
+ struct timeval *refTimestamp;
+ BuffersDescriptor *desc = NULL;
+ CameraFrame *frame = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ switch ( operation ) {
+ case CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW:
+ CAMHAL_LOGDA("Use buffers for preview");
+ desc = ( BuffersDescriptor * ) value1;
+
+ if ( NULL == desc )
+ {
+ CAMHAL_LOGEA("Invalid preview buffers!");
+ return -EINVAL;
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ android::AutoMutex lock(mPreviewBufferLock);
+ mPreviewBuffers = desc->mBuffers;
+ mPreviewBuffersLength = desc->mLength;
+ mPreviewBuffersAvailable.clear();
+ mSnapshotBuffersAvailable.clear();
+ for ( uint32_t i = 0 ; i < desc->mMaxQueueable ; i++ )
+ {
+ mPreviewBuffersAvailable.add(&mPreviewBuffers[i], 0);
+ }
+ // initial ref count for undeqeueued buffers is 1 since buffer provider
+ // is still holding on to it
+ for ( uint32_t i = desc->mMaxQueueable ; i < desc->mCount ; i++ )
+ {
+ mPreviewBuffersAvailable.add(&mPreviewBuffers[i], 1);
+ }
+ }
+
+ if ( NULL != desc )
+ {
+ ret = useBuffers(CameraAdapter::CAMERA_PREVIEW,
+ desc->mBuffers,
+ desc->mCount,
+ desc->mLength,
+ desc->mMaxQueueable);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ case CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA:
+ CAMHAL_LOGDA("Use buffers for preview data");
+ desc = ( BuffersDescriptor * ) value1;
+
+ if ( NULL == desc )
+ {
+ CAMHAL_LOGEA("Invalid preview data buffers!");
+ return -EINVAL;
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ android::AutoMutex lock(mPreviewDataBufferLock);
+ mPreviewDataBuffers = desc->mBuffers;
+ mPreviewDataBuffersLength = desc->mLength;
+ mPreviewDataBuffersAvailable.clear();
+ for ( uint32_t i = 0 ; i < desc->mMaxQueueable ; i++ )
+ {
+ mPreviewDataBuffersAvailable.add(&mPreviewDataBuffers[i], 0);
+ }
+ // initial ref count for undeqeueued buffers is 1 since buffer provider
+ // is still holding on to it
+ for ( uint32_t i = desc->mMaxQueueable ; i < desc->mCount ; i++ )
+ {
+ mPreviewDataBuffersAvailable.add(&mPreviewDataBuffers[i], 1);
+ }
+ }
+
+ if ( NULL != desc )
+ {
+ ret = useBuffers(CameraAdapter::CAMERA_MEASUREMENT,
+ desc->mBuffers,
+ desc->mCount,
+ desc->mLength,
+ desc->mMaxQueueable);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ case CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE:
+ CAMHAL_LOGDA("Use buffers for image capture");
+ desc = ( BuffersDescriptor * ) value1;
+
+ if ( NULL == desc )
+ {
+ CAMHAL_LOGEA("Invalid capture buffers!");
+ return -EINVAL;
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ android::AutoMutex lock(mCaptureBufferLock);
+ mCaptureBuffers = desc->mBuffers;
+ mCaptureBuffersLength = desc->mLength;
+ }
+
+ if ( NULL != desc )
+ {
+ ret = useBuffers(CameraAdapter::CAMERA_IMAGE_CAPTURE,
+ desc->mBuffers,
+ desc->mCount,
+ desc->mLength,
+ desc->mMaxQueueable);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ case CameraAdapter::CAMERA_USE_BUFFERS_REPROCESS:
+ CAMHAL_LOGDA("Use buffers for reprocessing");
+ desc = (BuffersDescriptor *) value1;
+
+ if (NULL == desc) {
+ CAMHAL_LOGEA("Invalid capture buffers!");
+ return -EINVAL;
+ }
+
+ if (ret == NO_ERROR) {
+ ret = setState(operation);
+ }
+
+ if (ret == NO_ERROR) {
+ android::AutoMutex lock(mVideoInBufferLock);
+ mVideoInBuffers = desc->mBuffers;
+ mVideoInBuffersAvailable.clear();
+ for (uint32_t i = 0 ; i < desc->mMaxQueueable ; i++) {
+ mVideoInBuffersAvailable.add(&mVideoInBuffers[i], 0);
+ }
+ // initial ref count for undeqeueued buffers is 1 since buffer provider
+ // is still holding on to it
+ for ( uint32_t i = desc->mMaxQueueable ; i < desc->mCount ; i++ ) {
+ mVideoInBuffersAvailable.add(&mVideoInBuffers[i], 1);
+ }
+ ret = useBuffers(CameraAdapter::CAMERA_REPROCESS,
+ desc->mBuffers,
+ desc->mCount,
+ desc->mLength,
+ desc->mMaxQueueable);
+ }
+
+ if ( ret == NO_ERROR ) {
+ ret = commitState();
+ } else {
+ ret |= rollbackState();
+ }
+
+ break;
+#endif
+
+ case CameraAdapter::CAMERA_START_SMOOTH_ZOOM:
+ {
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = startSmoothZoom(value1);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_STOP_SMOOTH_ZOOM:
+ {
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = stopSmoothZoom();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_START_PREVIEW:
+ {
+
+ CAMHAL_LOGDA("Start Preview");
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = startPreview();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_STOP_PREVIEW:
+ {
+
+ CAMHAL_LOGDA("Stop Preview");
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = stopPreview();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_START_VIDEO:
+ {
+
+ CAMHAL_LOGDA("Start video recording");
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = startVideoCapture();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_STOP_VIDEO:
+ {
+
+ CAMHAL_LOGDA("Stop video recording");
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = stopVideoCapture();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_START_IMAGE_CAPTURE:
+ {
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ refTimestamp = ( struct timeval * ) value1;
+ if ( NULL != refTimestamp )
+ {
+ memcpy( &mStartCapture, refTimestamp, sizeof( struct timeval ));
+ }
+
+#endif
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = takePicture();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE:
+ {
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = stopImageCapture();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_START_BRACKET_CAPTURE:
+ {
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ refTimestamp = ( struct timeval * ) value2;
+ if ( NULL != refTimestamp )
+ {
+ memcpy( &mStartCapture, refTimestamp, sizeof( struct timeval ));
+ }
+
+#endif
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = startBracketing(value1);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_STOP_BRACKET_CAPTURE:
+ {
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = stopBracketing();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ }
+
+ case CameraAdapter::CAMERA_PERFORM_AUTOFOCUS:
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ refTimestamp = ( struct timeval * ) value1;
+ if ( NULL != refTimestamp )
+ {
+ memcpy( &mStartFocus, refTimestamp, sizeof( struct timeval ));
+ }
+
+#endif
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = autoFocus();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ case CameraAdapter::CAMERA_CANCEL_AUTOFOCUS:
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = cancelAutoFocus();
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ case CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW:
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ frame = ( CameraFrame * ) value1;
+
+ if ( NULL != frame )
+ {
+ ret = getFrameSize(frame->mWidth, frame->mHeight);
+ }
+ else
+ {
+ ret = -EINVAL;
+ }
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ case CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ frame = ( CameraFrame * ) value1;
+
+ if ( NULL != frame )
+ {
+ ret = getPictureBufferSize(*frame, value2);
+ }
+ else
+ {
+ ret = -EINVAL;
+ }
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ case CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA:
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ frame = ( CameraFrame * ) value1;
+
+ if ( NULL != frame )
+ {
+ ret = getFrameDataSize(frame->mLength, value2);
+ }
+ else
+ {
+ ret = -EINVAL;
+ }
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = commitState();
+ }
+ else
+ {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ case CameraAdapter::CAMERA_START_FD:
+
+ ret = startFaceDetection();
+
+ break;
+
+ case CameraAdapter::CAMERA_STOP_FD:
+
+ ret = stopFaceDetection();
+
+ break;
+
+ case CameraAdapter::CAMERA_USE_BUFFERS_VIDEO_CAPTURE:
+
+ CAMHAL_LOGDA("Use buffers for video (RAW + JPEG) capture");
+ desc = ( BuffersDescriptor * ) value1;
+
+ if ( NULL == desc ) {
+ CAMHAL_LOGEA("Invalid capture buffers!");
+ return -EINVAL;
+ }
+
+ if ( ret == NO_ERROR ) {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR ) {
+ android::AutoMutex lock(mVideoBufferLock);
+ mVideoBuffers = desc->mBuffers;
+ mVideoBuffersLength = desc->mLength;
+ mVideoBuffersAvailable.clear();
+ for ( uint32_t i = 0 ; i < desc->mMaxQueueable ; i++ ) {
+ mVideoBuffersAvailable.add(&mVideoBuffers[i], 1);
+ }
+ // initial ref count for undeqeueued buffers is 1 since buffer provider
+ // is still holding on to it
+ for ( uint32_t i = desc->mMaxQueueable ; i < desc->mCount ; i++ ) {
+ mVideoBuffersAvailable.add(&mVideoBuffers[i], 1);
+ }
+ }
+
+ if ( NULL != desc ) {
+ ret = useBuffers(CameraAdapter::CAMERA_VIDEO,
+ desc->mBuffers,
+ desc->mCount,
+ desc->mLength,
+ desc->mMaxQueueable);
+ }
+
+ if ( ret == NO_ERROR ) {
+ ret = commitState();
+ } else {
+ ret |= rollbackState();
+ }
+
+ break;
+
+ case CameraAdapter::CAMERA_SWITCH_TO_EXECUTING:
+ ret = switchToExecuting();
+ break;
+
+#ifdef OMAP_ENHANCEMENT_VTC
+ case CameraAdapter::CAMERA_SETUP_TUNNEL:
+ ret = setupTunnel(value1, value2, value3, value4);
+ break;
+
+ case CameraAdapter::CAMERA_DESTROY_TUNNEL:
+ ret = destroyTunnel();
+ break;
+#endif
+
+ case CameraAdapter::CAMERA_PREVIEW_INITIALIZATION:
+ ret = cameraPreviewInitialization();
+ break;
+
+ default:
+ CAMHAL_LOGEB("Command 0x%x unsupported!", operation);
+ break;
+ };
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t BaseCameraAdapter::notifyFocusSubscribers(CameraHalEvent::FocusStatus status)
+{
+ event_callback eventCb;
+ CameraHalEvent focusEvent;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( mFocusSubscribers.size() == 0 ) {
+ CAMHAL_LOGDA("No Focus Subscribers!");
+ return NO_INIT;
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ if (status == CameraHalEvent::FOCUS_STATUS_PENDING) {
+ gettimeofday(&mStartFocus, NULL);
+ } else {
+ //dump the AF latency
+ CameraHal::PPM("Focus finished in: ", &mStartFocus);
+ }
+#endif
+
+ focusEvent.mEventData = new CameraHalEvent::CameraHalEventData();
+ if ( NULL == focusEvent.mEventData.get() ) {
+ return -ENOMEM;
+ }
+
+ focusEvent.mEventType = CameraHalEvent::EVENT_FOCUS_LOCKED;
+ focusEvent.mEventData->focusEvent.focusStatus = status;
+
+ for (unsigned int i = 0 ; i < mFocusSubscribers.size(); i++ )
+ {
+ focusEvent.mCookie = (void *) mFocusSubscribers.keyAt(i);
+ eventCb = (event_callback) mFocusSubscribers.valueAt(i);
+ eventCb ( &focusEvent );
+ }
+
+ focusEvent.mEventData.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::notifyShutterSubscribers()
+{
+ CameraHalEvent shutterEvent;
+ event_callback eventCb;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( mShutterSubscribers.size() == 0 )
+ {
+ CAMHAL_LOGEA("No shutter Subscribers!");
+ return NO_INIT;
+ }
+
+ shutterEvent.mEventData = new CameraHalEvent::CameraHalEventData();
+ if ( NULL == shutterEvent.mEventData.get() ) {
+ return -ENOMEM;
+ }
+
+ shutterEvent.mEventType = CameraHalEvent::EVENT_SHUTTER;
+ shutterEvent.mEventData->shutterEvent.shutterClosed = true;
+
+ for (unsigned int i = 0 ; i < mShutterSubscribers.size() ; i++ ) {
+ shutterEvent.mCookie = ( void * ) mShutterSubscribers.keyAt(i);
+ eventCb = ( event_callback ) mShutterSubscribers.valueAt(i);
+
+ CAMHAL_LOGD("Sending shutter callback");
+
+ eventCb ( &shutterEvent );
+ }
+
+ shutterEvent.mEventData.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::notifyZoomSubscribers(int zoomIdx, bool targetReached)
+{
+ event_callback eventCb;
+ CameraHalEvent zoomEvent;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( mZoomSubscribers.size() == 0 ) {
+ CAMHAL_LOGDA("No zoom Subscribers!");
+ return NO_INIT;
+ }
+
+ zoomEvent.mEventData = new CameraHalEvent::CameraHalEventData();
+ if ( NULL == zoomEvent.mEventData.get() ) {
+ return -ENOMEM;
+ }
+
+ zoomEvent.mEventType = CameraHalEvent::EVENT_ZOOM_INDEX_REACHED;
+ zoomEvent.mEventData->zoomEvent.currentZoomIndex = zoomIdx;
+ zoomEvent.mEventData->zoomEvent.targetZoomIndexReached = targetReached;
+
+ for (unsigned int i = 0 ; i < mZoomSubscribers.size(); i++ ) {
+ zoomEvent.mCookie = (void *) mZoomSubscribers.keyAt(i);
+ eventCb = (event_callback) mZoomSubscribers.valueAt(i);
+
+ eventCb ( &zoomEvent );
+ }
+
+ zoomEvent.mEventData.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::notifyMetadataSubscribers(android::sp<CameraMetadataResult> &meta)
+{
+ event_callback eventCb;
+ CameraHalEvent metaEvent;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( mMetadataSubscribers.size() == 0 ) {
+ CAMHAL_LOGDA("No preview metadata subscribers!");
+ return NO_INIT;
+ }
+
+ metaEvent.mEventData = new CameraHalEvent::CameraHalEventData();
+ if ( NULL == metaEvent.mEventData.get() ) {
+ return -ENOMEM;
+ }
+
+ metaEvent.mEventType = CameraHalEvent::EVENT_METADATA;
+ metaEvent.mEventData->metadataEvent = meta;
+
+ for (unsigned int i = 0 ; i < mMetadataSubscribers.size(); i++ ) {
+ metaEvent.mCookie = (void *) mMetadataSubscribers.keyAt(i);
+ eventCb = (event_callback) mMetadataSubscribers.valueAt(i);
+
+ eventCb ( &metaEvent );
+ }
+
+ metaEvent.mEventData.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame)
+{
+ status_t ret = NO_ERROR;
+ unsigned int mask;
+
+ if ( NULL == frame )
+ {
+ CAMHAL_LOGEA("Invalid CameraFrame");
+ return -EINVAL;
+ }
+
+ for( mask = 1; mask < CameraFrame::ALL_FRAMES; mask <<= 1){
+ if( mask & frame->mFrameMask ){
+ switch( mask ){
+
+ case CameraFrame::IMAGE_FRAME:
+ {
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ CameraHal::PPM("Shot to Jpeg: ", &mStartCapture);
+#endif
+ ret = __sendFrameToSubscribers(frame, &mImageSubscribers, CameraFrame::IMAGE_FRAME);
+ }
+ break;
+ case CameraFrame::RAW_FRAME:
+ {
+ ret = __sendFrameToSubscribers(frame, &mRawSubscribers, CameraFrame::RAW_FRAME);
+ }
+ break;
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ {
+ ret = __sendFrameToSubscribers(frame, &mFrameSubscribers, CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+ break;
+ case CameraFrame::SNAPSHOT_FRAME:
+ {
+ ret = __sendFrameToSubscribers(frame, &mSnapshotSubscribers, CameraFrame::SNAPSHOT_FRAME);
+ }
+ break;
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ {
+ ret = __sendFrameToSubscribers(frame, &mVideoSubscribers, CameraFrame::VIDEO_FRAME_SYNC);
+ }
+ break;
+ case CameraFrame::FRAME_DATA_SYNC:
+ {
+ ret = __sendFrameToSubscribers(frame, &mFrameDataSubscribers, CameraFrame::FRAME_DATA_SYNC);
+ }
+ break;
+ case CameraFrame::REPROCESS_INPUT_FRAME:
+ {
+ ret = __sendFrameToSubscribers(frame, &mVideoInSubscribers, CameraFrame::REPROCESS_INPUT_FRAME);
+ }
+ break;
+ default:
+ CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", mask);
+ break;
+ }//SWITCH
+ frame->mFrameMask &= ~mask;
+
+ if (ret != NO_ERROR) {
+ goto EXIT;
+ }
+ }//IF
+ }//FOR
+
+ EXIT:
+ return ret;
+}
+
+status_t BaseCameraAdapter::__sendFrameToSubscribers(CameraFrame* frame,
+ android::KeyedVector<int, frame_callback> *subscribers,
+ CameraFrame::FrameType frameType)
+{
+ size_t refCount = 0;
+ status_t ret = NO_ERROR;
+ frame_callback callback = NULL;
+
+ frame->mFrameType = frameType;
+
+ if ( (frameType == CameraFrame::PREVIEW_FRAME_SYNC) ||
+ (frameType == CameraFrame::VIDEO_FRAME_SYNC) ||
+ (frameType == CameraFrame::SNAPSHOT_FRAME) ){
+ if (mFrameQueue.size() > 0){
+ CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(frame->mBuffer);
+ frame->mYuv[0] = lframe->mYuv[0];
+ frame->mYuv[1] = frame->mYuv[0] + (frame->mLength + frame->mOffset)*2/3;
+ }
+ else{
+ CAMHAL_LOGDA("Empty Frame Queue");
+ return -EINVAL;
+ }
+ }
+
+ if (NULL != subscribers) {
+ refCount = getFrameRefCountByType(frame->mBuffer, frameType);
+
+ if (refCount == 0) {
+ CAMHAL_LOGDA("Invalid ref count of 0");
+ return -EINVAL;
+ }
+
+ if (refCount > subscribers->size()) {
+ CAMHAL_LOGEB("Invalid ref count for frame type: 0x%x", frameType);
+ return -EINVAL;
+ }
+
+ CAMHAL_LOGVB("Type of Frame: 0x%x address: 0x%x refCount start %d",
+ frame->mFrameType,
+ ( uint32_t ) frame->mBuffer,
+ refCount);
+
+ for ( unsigned int i = 0 ; i < refCount; i++ ) {
+ frame->mCookie = ( void * ) subscribers->keyAt(i);
+ callback = (frame_callback) subscribers->valueAt(i);
+
+ if (!callback) {
+ CAMHAL_LOGEB("callback not set for frame type: 0x%x", frameType);
+ return -EINVAL;
+ }
+
+ callback(frame);
+ }
+ } else {
+ CAMHAL_LOGEA("Subscribers is null??");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+int BaseCameraAdapter::setInitFrameRefCount(CameraBuffer * buf, unsigned int mask)
+{
+ int ret = NO_ERROR;
+ unsigned int lmask;
+
+ LOG_FUNCTION_NAME;
+
+ if (buf == NULL)
+ {
+ return -EINVAL;
+ }
+
+ for( lmask = 1; lmask < CameraFrame::ALL_FRAMES; lmask <<= 1){
+ if( lmask & mask ){
+ switch( lmask ){
+
+ case CameraFrame::IMAGE_FRAME:
+ {
+ setFrameRefCountByType(buf, CameraFrame::IMAGE_FRAME, (int) mImageSubscribers.size());
+ }
+ break;
+ case CameraFrame::RAW_FRAME:
+ {
+ setFrameRefCountByType(buf, CameraFrame::RAW_FRAME, mRawSubscribers.size());
+ }
+ break;
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ {
+ setFrameRefCountByType(buf, CameraFrame::PREVIEW_FRAME_SYNC, mFrameSubscribers.size());
+ }
+ break;
+ case CameraFrame::SNAPSHOT_FRAME:
+ {
+ setFrameRefCountByType(buf, CameraFrame::SNAPSHOT_FRAME, mSnapshotSubscribers.size());
+ }
+ break;
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ {
+ setFrameRefCountByType(buf,CameraFrame::VIDEO_FRAME_SYNC, mVideoSubscribers.size());
+ }
+ break;
+ case CameraFrame::FRAME_DATA_SYNC:
+ {
+ setFrameRefCountByType(buf, CameraFrame::FRAME_DATA_SYNC, mFrameDataSubscribers.size());
+ }
+ break;
+ case CameraFrame::REPROCESS_INPUT_FRAME:
+ {
+ setFrameRefCountByType(buf,CameraFrame::REPROCESS_INPUT_FRAME, mVideoInSubscribers.size());
+ }
+ break;
+ default:
+ CAMHAL_LOGEB("FRAMETYPE NOT SUPPORTED 0x%x", lmask);
+ break;
+ }//SWITCH
+ mask &= ~lmask;
+ }//IF
+ }//FOR
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+int BaseCameraAdapter::getFrameRefCount(CameraBuffer * frameBuf)
+{
+ int res = 0, refCnt = 0;
+
+ for (unsigned int frameType = 1; frameType < CameraFrame::ALL_FRAMES; frameType <<= 1) {
+ refCnt = getFrameRefCountByType(frameBuf, static_cast<CameraFrame::FrameType>(frameType));
+ if (refCnt > 0) res += refCnt;
+ }
+ return res;
+}
+
+int BaseCameraAdapter::getFrameRefCountByType(CameraBuffer * frameBuf, CameraFrame::FrameType frameType)
+{
+ int res = -1;
+ ssize_t index = NAME_NOT_FOUND;
+
+ LOG_FUNCTION_NAME;
+
+ switch (frameType) {
+ case CameraFrame::IMAGE_FRAME:
+ case CameraFrame::RAW_FRAME:
+ {
+ android::AutoMutex lock(mCaptureBufferLock);
+ index = mCaptureBuffersAvailable.indexOfKey(frameBuf);
+ if (index != NAME_NOT_FOUND) {
+ res = mCaptureBuffersAvailable[index];
+ }
+ break;
+ }
+ case CameraFrame::SNAPSHOT_FRAME:
+ {
+ android::AutoMutex lock(mSnapshotBufferLock);
+ index = mSnapshotBuffersAvailable.indexOfKey(frameBuf);
+ if (index != NAME_NOT_FOUND) {
+ res = mSnapshotBuffersAvailable[index];
+ }
+ break;
+ }
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ {
+ android::AutoMutex lock(mPreviewBufferLock);
+ index = mPreviewBuffersAvailable.indexOfKey(frameBuf);
+ if (index != NAME_NOT_FOUND) {
+ res = mPreviewBuffersAvailable[index];
+ }
+ break;
+ }
+ case CameraFrame::FRAME_DATA_SYNC:
+ {
+ android::AutoMutex lock(mPreviewDataBufferLock);
+ index = mPreviewDataBuffersAvailable.indexOfKey(frameBuf);
+ if (index != NAME_NOT_FOUND) {
+ res = mPreviewDataBuffersAvailable[index];
+ }
+ break;
+ }
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ {
+ android::AutoMutex lock(mVideoBufferLock);
+ index = mVideoBuffersAvailable.indexOfKey(frameBuf);
+ if (index != NAME_NOT_FOUND) {
+ res = mVideoBuffersAvailable[index];
+ }
+ break;
+ }
+ case CameraFrame::REPROCESS_INPUT_FRAME:
+ {
+ android::AutoMutex lock(mVideoInBufferLock);
+ index = mVideoInBuffersAvailable.indexOfKey(frameBuf);
+ if (index != NAME_NOT_FOUND) {
+ res = mVideoInBuffersAvailable[index];
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return res;
+}
+
+void BaseCameraAdapter::setFrameRefCountByType(CameraBuffer * frameBuf, CameraFrame::FrameType frameType, int refCount)
+{
+
+ LOG_FUNCTION_NAME;
+
+ switch ( frameType )
+ {
+ case CameraFrame::IMAGE_FRAME:
+ case CameraFrame::RAW_FRAME:
+ {
+ android::AutoMutex lock(mCaptureBufferLock);
+ mCaptureBuffersAvailable.replaceValueFor(frameBuf, refCount);
+ }
+ break;
+ case CameraFrame::SNAPSHOT_FRAME:
+ {
+ android::AutoMutex lock(mSnapshotBufferLock);
+ mSnapshotBuffersAvailable.replaceValueFor(frameBuf, refCount);
+ }
+ break;
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ {
+ android::AutoMutex lock(mPreviewBufferLock);
+ mPreviewBuffersAvailable.replaceValueFor(frameBuf, refCount);
+ }
+ break;
+ case CameraFrame::FRAME_DATA_SYNC:
+ {
+ android::AutoMutex lock(mPreviewDataBufferLock);
+ mPreviewDataBuffersAvailable.replaceValueFor(frameBuf, refCount);
+ }
+ break;
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ {
+ android::AutoMutex lock(mVideoBufferLock);
+ mVideoBuffersAvailable.replaceValueFor(frameBuf, refCount);
+ }
+ break;
+ case CameraFrame::REPROCESS_INPUT_FRAME: {
+ android::AutoMutex lock(mVideoInBufferLock);
+ mVideoInBuffersAvailable.replaceValueFor(frameBuf, refCount);
+ }
+ break;
+ default:
+ break;
+ };
+
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+status_t BaseCameraAdapter::startVideoCapture()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mVideoBufferLock);
+
+ //If the capture is already ongoing, return from here.
+ if ( mRecording )
+ {
+ ret = NO_INIT;
+ }
+
+
+ if ( NO_ERROR == ret )
+ {
+
+ mVideoBuffersAvailable.clear();
+
+ for ( unsigned int i = 0 ; i < mPreviewBuffersAvailable.size() ; i++ )
+ {
+ mVideoBuffersAvailable.add(mPreviewBuffersAvailable.keyAt(i), 0);
+ }
+
+ mRecording = true;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::stopVideoCapture()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( !mRecording )
+ {
+ ret = NO_INIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ for ( unsigned int i = 0 ; i < mVideoBuffersAvailable.size() ; i++ )
+ {
+ CameraBuffer *frameBuf = mVideoBuffersAvailable.keyAt(i);
+ if( getFrameRefCountByType(frameBuf, CameraFrame::VIDEO_FRAME_SYNC) > 0)
+ {
+ returnFrame(frameBuf, CameraFrame::VIDEO_FRAME_SYNC);
+ }
+ }
+
+ mRecording = false;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+//-----------------Stub implementation of the interface ------------------------------
+
+status_t BaseCameraAdapter::takePicture()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::stopImageCapture()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::startBracketing(int range)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::stopBracketing()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::autoFocus()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ notifyFocusSubscribers(CameraHalEvent::FOCUS_STATUS_FAIL);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::cancelAutoFocus()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::startSmoothZoom(int targetIdx)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::stopSmoothZoom()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::startPreview()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::stopPreview()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::useBuffers(CameraMode mode, CameraBuffer* bufArr, int num, size_t length, unsigned int queueable)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::fillThisBuffer(CameraBuffer * frameBuf, CameraFrame::FrameType frameType)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::getFrameSize(size_t &width, size_t &height)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::getFrameDataSize(size_t &dataFrameSize, size_t bufferCount)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::getPictureBufferSize(CameraFrame &frame, size_t bufferCount)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::startFaceDetection()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::stopFaceDetection()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::switchToExecuting()
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+const char* BaseCameraAdapter::getLUTvalue_translateHAL(int Value, LUTtypeHAL LUT) {
+ int LUTsize = LUT.size;
+ for(int i = 0; i < LUTsize; i++)
+ if( LUT.Table[i].halDefinition == Value )
+ return LUT.Table[i].userDefinition;
+
+ return NULL;
+}
+
+status_t BaseCameraAdapter::setupTunnel(uint32_t SliceHeight, uint32_t EncoderHandle, uint32_t width, uint32_t height) {
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t BaseCameraAdapter::destroyTunnel() {
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t BaseCameraAdapter::cameraPreviewInitialization() {
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t BaseCameraAdapter::setState(CameraCommands operation)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ const char *printState = getLUTvalue_translateHAL(operation, CamCommandsLUT);
+
+ mLock.lock();
+
+ switch ( mAdapterState )
+ {
+
+ case INTIALIZED_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_USE_BUFFERS_PREVIEW:
+ CAMHAL_LOGDB("Adapter state switch INTIALIZED_STATE->LOADED_PREVIEW_STATE event = %s",
+ printState);
+ mNextState = LOADED_PREVIEW_STATE;
+ break;
+
+ //These events don't change the current state
+ case CAMERA_QUERY_RESOLUTION_PREVIEW:
+ case CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA:
+ CAMHAL_LOGDB("Adapter state switch INTIALIZED_STATE->INTIALIZED_STATE event = %s",
+ printState);
+ mNextState = INTIALIZED_STATE;
+ break;
+ case CAMERA_STOP_BRACKET_CAPTURE:
+ case CAMERA_STOP_IMAGE_CAPTURE:
+ ret = INVALID_OPERATION;
+ break;
+ case CAMERA_CANCEL_AUTOFOCUS:
+ ret = INVALID_OPERATION;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch INTIALIZED_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case LOADED_PREVIEW_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_START_PREVIEW:
+ CAMHAL_LOGDB("Adapter state switch LOADED_PREVIEW_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_STOP_PREVIEW:
+ CAMHAL_LOGDB("Adapter state switch LOADED_PREVIEW_STATE->INTIALIZED_STATE event = 0x%x",
+ operation);
+ mNextState = INTIALIZED_STATE;
+ break;
+
+ //These events don't change the current state
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ case CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA:
+ case CAMERA_USE_BUFFERS_PREVIEW_DATA:
+ CAMHAL_LOGDB("Adapter state switch LOADED_PREVIEW_STATE->LOADED_PREVIEW_STATE event = %s",
+ printState);
+ mNextState = LOADED_PREVIEW_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGDB("Adapter state switch LOADED_PREVIEW Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case PREVIEW_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_PREVIEW:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->INTIALIZED_STATE event = %s",
+ printState);
+ mNextState = INTIALIZED_STATE;
+ break;
+
+ case CAMERA_PERFORM_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->AF_STATE event = %s",
+ printState);
+ mNextState = AF_STATE;
+ break;
+
+ case CAMERA_START_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->ZOOM_STATE event = %s",
+ printState);
+ mNextState = ZOOM_STATE;
+ break;
+
+ case CAMERA_USE_BUFFERS_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->LOADED_CAPTURE_STATE event = %s",
+ printState);
+ mNextState = LOADED_CAPTURE_STATE;
+ break;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ case CAMERA_USE_BUFFERS_REPROCESS:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->LOADED_REPROCESS_STATE event = %s",
+ printState);
+ mNextState = LOADED_REPROCESS_STATE;
+ break;
+#endif
+
+ case CAMERA_START_VIDEO:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->VIDEO_STATE event = %s",
+ printState);
+ mNextState = VIDEO_STATE;
+ break;
+
+ case CAMERA_CANCEL_AUTOFOCUS:
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ case CAMERA_STOP_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_ACTIVE->PREVIEW_ACTIVE event = %s",
+ printState);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_STOP_IMAGE_CAPTURE:
+ case CAMERA_STOP_BRACKET_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_ACTIVE->PREVIEW_ACTIVE event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch PREVIEW_ACTIVE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ case LOADED_REPROCESS_STATE:
+ switch (operation) {
+ case CAMERA_USE_BUFFERS_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch LOADED_REPROCESS_STATE->LOADED_REPROCESS_CAPTURE_STATE event = %s",
+ printState);
+ mNextState = LOADED_REPROCESS_CAPTURE_STATE;
+ break;
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch LOADED_REPROCESS_STATE->LOADED_REPROCESS_STATE event = %s",
+ printState);
+ mNextState = LOADED_REPROCESS_STATE;
+ break;
+ default:
+ CAMHAL_LOGEB("Adapter state switch LOADED_REPROCESS_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+ }
+
+ break;
+
+ case LOADED_REPROCESS_CAPTURE_STATE:
+ switch (operation) {
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch LOADED_REPROCESS_CAPTURE_STATE->REPROCESS_STATE event = %s",
+ printState);
+ mNextState = REPROCESS_STATE;
+ break;
+ default:
+ CAMHAL_LOGEB("Adapter state switch LOADED_REPROCESS_CAPTURE_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+ }
+ break;
+#endif
+
+ case LOADED_CAPTURE_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch LOADED_CAPTURE_STATE->CAPTURE_STATE event = %s",
+ printState);
+ mNextState = CAPTURE_STATE;
+ break;
+
+ case CAMERA_START_BRACKET_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch LOADED_CAPTURE_STATE->BRACKETING_STATE event = %s",
+ printState);
+ mNextState = BRACKETING_STATE;
+ break;
+
+ case CAMERA_USE_BUFFERS_VIDEO_CAPTURE:
+ //Hadnle this state for raw capture path.
+ //Just need to keep the same state.
+ //The next CAMERA_START_IMAGE_CAPTURE command will assign the mNextState.
+ CAMHAL_LOGDB("Adapter state switch LOADED_CAPTURE_STATE->LOADED_CAPTURE_STATE event = %s",
+ printState);
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch LOADED_CAPTURE_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case CAPTURE_STATE:
+
+ switch ( operation )
+ {
+ case CAMERA_STOP_IMAGE_CAPTURE:
+ case CAMERA_STOP_BRACKET_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch CAPTURE_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch CAPTURE_STATE->CAPTURE_STATE event = %s",
+ printState);
+ mNextState = CAPTURE_STATE;
+ break;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ case CAMERA_USE_BUFFERS_REPROCESS:
+ CAMHAL_LOGDB("Adapter state switch CAPTURE_STATE->->LOADED_REPROCESS_STATE event = %s",
+ printState);
+ mNextState = LOADED_REPROCESS_STATE;
+ break;
+#endif
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch CAPTURE_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case BRACKETING_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_IMAGE_CAPTURE:
+ case CAMERA_STOP_BRACKET_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch BRACKETING_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch BRACKETING_STATE->CAPTURE_STATE event = %s",
+ printState);
+ mNextState = CAPTURE_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch BRACKETING_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case AF_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_CANCEL_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch AF_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch AF_STATE->CAPTURE_STATE event = 0x%x",
+ operation);
+ mNextState = CAPTURE_STATE;
+ break;
+
+ case CAMERA_START_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch AF_STATE->AF_ZOOM_STATE event = %s",
+ printState);
+ mNextState = AF_ZOOM_STATE;
+ break;
+
+ case CAMERA_START_VIDEO:
+ CAMHAL_LOGDB("Adapter state switch AF_STATE->VIDEO_STATE event = %s",
+ printState);
+ mNextState = VIDEO_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch AF_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case ZOOM_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_CANCEL_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch AF_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = ZOOM_STATE;
+ break;
+
+ case CAMERA_STOP_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch ZOOM_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_PERFORM_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch ZOOM_STATE->AF_ZOOM_STATE event = %s",
+ printState);
+ mNextState = AF_ZOOM_STATE;
+ break;
+
+ case CAMERA_START_VIDEO:
+ CAMHAL_LOGDB("Adapter state switch ZOOM_STATE->VIDEO_ZOOM_STATE event = %s",
+ printState);
+ mNextState = VIDEO_ZOOM_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch ZOOM_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case VIDEO_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_VIDEO:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_PERFORM_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_STATE->VIDEO_AF_STATE event = %s",
+ printState);
+ mNextState = VIDEO_AF_STATE;
+ break;
+
+ case CAMERA_START_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_STATE->VIDEO_ZOOM_STATE event = %s",
+ printState);
+ mNextState = VIDEO_ZOOM_STATE;
+ break;
+
+ case CAMERA_USE_BUFFERS_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_STATE->VIDEO_LOADED_CAPTURE_STATE event = %s",
+ printState);
+ mNextState = VIDEO_LOADED_CAPTURE_STATE;
+ break;
+
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_STATE->VIDEO_STATE event = %s",
+ printState);
+ mNextState = VIDEO_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch VIDEO_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case VIDEO_AF_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_CANCEL_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_AF_STATE->VIDEO_STATE event = %s",
+ printState);
+ mNextState = VIDEO_STATE;
+ break;
+
+ case CAMERA_USE_BUFFERS_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_AF_STATE->VIDEO_LOADED_CAPTURE_STATE event = %s",
+ printState);
+ mNextState = VIDEO_LOADED_CAPTURE_STATE;
+ break;
+
+ //This event doesn't change the current state
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_AF_STATE->VIDEO_AF_STATE event = %s",
+ printState);
+ mNextState = VIDEO_AF_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch VIDEO_AF_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case VIDEO_LOADED_CAPTURE_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch LOADED_CAPTURE_STATE->CAPTURE_STATE event = %s",
+ printState);
+ mNextState = VIDEO_CAPTURE_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch LOADED_CAPTURE_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case VIDEO_CAPTURE_STATE:
+
+ switch ( operation )
+ {
+ case CAMERA_STOP_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch CAPTURE_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = VIDEO_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch CAPTURE_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case AF_ZOOM_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch AF_ZOOM_STATE->AF_STATE event = %s",
+ printState);
+ mNextState = AF_STATE;
+ break;
+
+ case CAMERA_CANCEL_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch AF_ZOOM_STATE->ZOOM_STATE event = %s",
+ printState);
+ mNextState = ZOOM_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch AF_ZOOM_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case VIDEO_ZOOM_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_ZOOM_STATE->VIDEO_STATE event = %s",
+ printState);
+ mNextState = VIDEO_STATE;
+ break;
+
+ case CAMERA_STOP_VIDEO:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_ZOOM_STATE->ZOOM_STATE event = %s",
+ printState);
+ mNextState = ZOOM_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch VIDEO_ZOOM_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case BRACKETING_ZOOM_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch BRACKETING_ZOOM_STATE->BRACKETING_STATE event = %s",
+ printState);
+ mNextState = BRACKETING_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch BRACKETING_ZOOM_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ case REPROCESS_STATE:
+ switch (operation) {
+ case CAMERA_STOP_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch REPROCESS_STATE->PREVIEW_STATE event = %s",
+ printState);
+ mNextState = PREVIEW_STATE;
+ break;
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch REPROCESS_STATE->REPROCESS_STATE event = %s",
+ printState);
+ mNextState = REPROCESS_STATE;
+ break;
+ case CAMERA_USE_BUFFERS_REPROCESS:
+ CAMHAL_LOGDB("Adapter state switch REPROCESS_STATE->REPROCESS_STATE event = %s",
+ printState);
+ mNextState = LOADED_REPROCESS_STATE;
+ break;
+
+ case CAMERA_USE_BUFFERS_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch REPROCESS_STATE->LOADED_CAPTURE_STATE event = %s",
+ printState);
+ mNextState = LOADED_CAPTURE_STATE;
+ break;
+ default:
+ CAMHAL_LOGEB("Adapter state switch REPROCESS_STATE Invalid Op! event = %s",
+ printState);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+#endif
+
+
+ default:
+ CAMHAL_LOGEA("Invalid Adapter state!");
+ ret = INVALID_OPERATION;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::rollbackToInitializedState()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ while ((getState() != INTIALIZED_STATE) && (ret == NO_ERROR)) {
+ ret = rollbackToPreviousState();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::rollbackToPreviousState()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ CameraAdapter::AdapterState currentState = getState();
+
+ switch (currentState) {
+ case INTIALIZED_STATE:
+ return NO_ERROR;
+
+ case PREVIEW_STATE:
+ ret = sendCommand(CAMERA_STOP_PREVIEW);
+ break;
+
+ case CAPTURE_STATE:
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ case REPROCESS_STATE:
+#endif
+ ret = sendCommand(CAMERA_STOP_IMAGE_CAPTURE);
+ break;
+
+ case BRACKETING_STATE:
+ ret = sendCommand(CAMERA_STOP_BRACKET_CAPTURE);
+ break;
+
+ case AF_STATE:
+ ret = sendCommand(CAMERA_CANCEL_AUTOFOCUS);
+ break;
+
+ case ZOOM_STATE:
+ ret = sendCommand(CAMERA_STOP_SMOOTH_ZOOM);
+ break;
+
+ case VIDEO_STATE:
+ ret = sendCommand(CAMERA_STOP_VIDEO);
+ break;
+
+ case VIDEO_AF_STATE:
+ ret = sendCommand(CAMERA_CANCEL_AUTOFOCUS);
+ break;
+
+ case VIDEO_CAPTURE_STATE:
+ ret = sendCommand(CAMERA_STOP_IMAGE_CAPTURE);
+ break;
+
+ case AF_ZOOM_STATE:
+ ret = sendCommand(CAMERA_STOP_SMOOTH_ZOOM);
+ break;
+
+ case VIDEO_ZOOM_STATE:
+ ret = sendCommand(CAMERA_STOP_SMOOTH_ZOOM);
+ break;
+
+ case BRACKETING_ZOOM_STATE:
+ ret = sendCommand(CAMERA_STOP_SMOOTH_ZOOM);
+ break;
+
+ default:
+ CAMHAL_LOGEA("Invalid Adapter state!");
+ ret = INVALID_OPERATION;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+//State transition finished successfully.
+//Commit the state and unlock the adapter state.
+status_t BaseCameraAdapter::commitState()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ mAdapterState = mNextState;
+
+ mLock.unlock();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::rollbackState()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ mNextState = mAdapterState;
+
+ mLock.unlock();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+// getNextState() and getState()
+// publicly exposed functions to retrieve the adapter states
+// please notice that these functions are locked
+CameraAdapter::AdapterState BaseCameraAdapter::getState()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return mAdapterState;
+}
+
+CameraAdapter::AdapterState BaseCameraAdapter::getNextState()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return mNextState;
+}
+
+// getNextState() and getState()
+// internal protected functions to retrieve the adapter states
+// please notice that these functions are NOT locked to help
+// internal functions query state in the middle of state
+// transition
+status_t BaseCameraAdapter::getState(AdapterState &state)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ state = mAdapterState;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::getNextState(AdapterState &state)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ state = mNextState;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+void BaseCameraAdapter::onOrientationEvent(uint32_t orientation, uint32_t tilt)
+{
+ LOG_FUNCTION_NAME;
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+//-----------------------------------------------------------------------------
+
+extern "C" status_t OMXCameraAdapter_Capabilities(
+ CameraProperties::Properties * const properties_array,
+ const int starting_camera, const int max_camera, int & supportedCameras);
+extern "C" status_t V4LCameraAdapter_Capabilities(
+ CameraProperties::Properties * const properties_array,
+ const int starting_camera, const int max_camera, int & supportedCameras);
+
+extern "C" status_t CameraAdapter_Capabilities(
+ CameraProperties::Properties * const properties_array,
+ const int starting_camera, const int max_camera, int & supportedCameras)
+{
+
+ status_t ret = NO_ERROR;
+ status_t err = NO_ERROR;
+ int num_cameras_supported = 0;
+
+ LOG_FUNCTION_NAME;
+
+ supportedCameras = 0;
+#ifdef OMX_CAMERA_ADAPTER
+ //Query OMX cameras
+ err = OMXCameraAdapter_Capabilities( properties_array, starting_camera,
+ max_camera, supportedCameras);
+ if(err != NO_ERROR) {
+ CAMHAL_LOGEA("error while getting OMXCameraAdapter capabilities");
+ ret = UNKNOWN_ERROR;
+ }
+#endif
+#ifdef V4L_CAMERA_ADAPTER
+ //Query V4L cameras
+ err = V4LCameraAdapter_Capabilities( properties_array, (const int) supportedCameras,
+ max_camera, num_cameras_supported);
+ if(err != NO_ERROR) {
+ CAMHAL_LOGEA("error while getting V4LCameraAdapter capabilities");
+ ret = UNKNOWN_ERROR;
+ }
+#endif
+
+ supportedCameras += num_cameras_supported;
+ CAMHAL_LOGEB("supportedCameras= %d\n", supportedCameras);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+//-----------------------------------------------------------------------------
+
+} // namespace Camera
+} // namespace Ti
+
+/*--------------------Camera Adapter Class ENDS here-----------------------------*/
+
diff --git a/camera/BufferSourceAdapter.cpp b/camera/BufferSourceAdapter.cpp
new file mode 100644
index 0000000..3c4e698
--- /dev/null
+++ b/camera/BufferSourceAdapter.cpp
@@ -0,0 +1,1007 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+
+#include "BufferSourceAdapter.h"
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferMapper.h>
+#include <hal_public.h>
+
+namespace Ti {
+namespace Camera {
+
+static int getANWFormat(const char* parameters_format)
+{
+ int format = HAL_PIXEL_FORMAT_TI_NV12;
+
+ if (parameters_format != NULL) {
+ if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ CAMHAL_LOGDA("CbYCrY format selected");
+ format = HAL_PIXEL_FORMAT_TI_UYVY;
+ } else if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ format = HAL_PIXEL_FORMAT_TI_NV12;
+ } else if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
+ CAMHAL_LOGDA("RGB565 format selected");
+ // TODO(XXX): not defined yet
+ format = -1;
+ } else if (strcmp(parameters_format, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) {
+ format = HAL_PIXEL_FORMAT_TI_Y16;
+ } else {
+ CAMHAL_LOGDA("Invalid format, NV12 format selected as default");
+ format = HAL_PIXEL_FORMAT_TI_NV12;
+ }
+ }
+
+ return format;
+}
+
+static int getUsageFromANW(int format)
+{
+ int usage = GRALLOC_USAGE_SW_READ_RARELY |
+ GRALLOC_USAGE_SW_WRITE_NEVER;
+
+ switch (format) {
+ case HAL_PIXEL_FORMAT_TI_NV12:
+ case HAL_PIXEL_FORMAT_TI_Y16:
+ case HAL_PIXEL_FORMAT_TI_UYVY:
+ // This usage flag indicates to gralloc we want the
+ // buffers to come from system heap
+ usage |= GRALLOC_USAGE_PRIVATE_0;
+ break;
+ default:
+ // No special flags needed
+ break;
+ }
+ return usage;
+}
+
+static const char* getFormatFromANW(int format)
+{
+ switch (format) {
+ case HAL_PIXEL_FORMAT_TI_NV12:
+ // Assuming NV12 1D is RAW or Image frame
+ return android::CameraParameters::PIXEL_FORMAT_YUV420SP;
+ case HAL_PIXEL_FORMAT_TI_Y16:
+ return android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB;
+ case HAL_PIXEL_FORMAT_TI_UYVY:
+ return android::CameraParameters::PIXEL_FORMAT_YUV422I;
+ default:
+ break;
+ }
+ return android::CameraParameters::PIXEL_FORMAT_YUV420SP;
+}
+
+static CameraFrame::FrameType formatToOutputFrameType(const char* format) {
+ switch (getANWFormat(format)) {
+ case HAL_PIXEL_FORMAT_TI_NV12:
+ case HAL_PIXEL_FORMAT_TI_Y16:
+ case HAL_PIXEL_FORMAT_TI_UYVY:
+ // Assuming NV12 1D is RAW or Image frame
+ return CameraFrame::RAW_FRAME;
+ default:
+ break;
+ }
+ return CameraFrame::RAW_FRAME;
+}
+
+static int getHeightFromFormat(const char* format, int stride, int size) {
+ CAMHAL_ASSERT((NULL != format) && (0 <= stride) && (0 <= size));
+ switch (getANWFormat(format)) {
+ case HAL_PIXEL_FORMAT_TI_NV12:
+ return (size / (3 * stride)) * 2;
+ case HAL_PIXEL_FORMAT_TI_Y16:
+ case HAL_PIXEL_FORMAT_TI_UYVY:
+ return (size / stride) / 2;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*--------------------BufferSourceAdapter Class STARTS here-----------------------------*/
+
+
+///Constant definitions
+// TODO(XXX): Temporarily increase number of buffers we can allocate from ANW
+// until faux-NPA mode is implemented
+const int BufferSourceAdapter::NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP = 15;
+
+/**
+ * Display Adapter class STARTS here..
+ */
+BufferSourceAdapter::BufferSourceAdapter() : mBufferCount(0)
+{
+ LOG_FUNCTION_NAME;
+
+ mPixelFormat = NULL;
+ mBuffers = NULL;
+ mFrameProvider = NULL;
+ mBufferSource = NULL;
+
+ mFrameWidth = 0;
+ mFrameHeight = 0;
+ mPreviewWidth = 0;
+ mPreviewHeight = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+BufferSourceAdapter::~BufferSourceAdapter()
+{
+ LOG_FUNCTION_NAME;
+
+ freeBufferList(mBuffers);
+
+ android::AutoMutex lock(mLock);
+
+ destroy();
+
+ if (mFrameProvider) {
+ // Unregister with the frame provider
+ mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
+ delete mFrameProvider;
+ mFrameProvider = NULL;
+ }
+
+ if (mQueueFrame.get()) {
+ mQueueFrame->requestExit();
+ mQueueFrame.clear();
+ }
+
+ if (mReturnFrame.get()) {
+ mReturnFrame->requestExit();
+ mReturnFrame.clear();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t BufferSourceAdapter::initialize()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ mReturnFrame.clear();
+ mReturnFrame = new ReturnFrame(this);
+ mReturnFrame->run();
+
+ mQueueFrame.clear();
+ mQueueFrame = new QueueFrame(this);
+ mQueueFrame->run();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+int BufferSourceAdapter::setPreviewWindow(preview_stream_ops_t *source)
+{
+ LOG_FUNCTION_NAME;
+
+ if (!source) {
+ CAMHAL_LOGEA("NULL window object passed to DisplayAdapter");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ if (mBufferSource) {
+ char id1[OP_STR_SIZE], id2[OP_STR_SIZE];
+ status_t ret;
+
+ ret = extendedOps()->get_id(mBufferSource, id1, sizeof(id1));
+ if (ret != 0) {
+ CAMHAL_LOGE("Surface::getId returned error %d", ret);
+ return ret;
+ }
+
+ ret = extendedOps()->get_id(source, id2, sizeof(id2));
+ if (ret != 0) {
+ CAMHAL_LOGE("Surface::getId returned error %d", ret);
+ return ret;
+ }
+ if ((0 >= strlen(id1)) || (0 >= strlen(id2))) {
+ CAMHAL_LOGE("Cannot set ST without name: id1:\"%s\" id2:\"%s\"",
+ id1, id2);
+ return NOT_ENOUGH_DATA;
+ }
+ if (0 == strcmp(id1, id2)) {
+ return ALREADY_EXISTS;
+ }
+
+ // client has to unset mBufferSource before being able to set a new one
+ return BAD_VALUE;
+ }
+
+ // Move to new source obj
+ mBufferSource = source;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+bool BufferSourceAdapter::match(const char * str) {
+ char id1[OP_STR_SIZE];
+ status_t ret;
+
+ ret = extendedOps()->get_id(mBufferSource, id1, sizeof(id1));
+
+ if (ret != 0) {
+ CAMHAL_LOGE("Surface::getId returned error %d", ret);
+ }
+
+ return strcmp(id1, str) == 0;
+}
+
+int BufferSourceAdapter::setFrameProvider(FrameNotifier *frameProvider)
+{
+ LOG_FUNCTION_NAME;
+
+ if ( !frameProvider ) {
+ CAMHAL_LOGEA("NULL passed for frame provider");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ if ( NULL != mFrameProvider ) {
+ delete mFrameProvider;
+ }
+
+ mFrameProvider = new FrameProvider(frameProvider, this, frameCallback);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+int BufferSourceAdapter::setErrorHandler(ErrorNotifier *errorNotifier)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == errorNotifier ) {
+ CAMHAL_LOGEA("Invalid Error Notifier reference");
+ return -EINVAL;
+ }
+
+ mErrorNotifier = errorNotifier;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+int BufferSourceAdapter::enableDisplay(int width, int height,
+ struct timeval *refTime)
+{
+ LOG_FUNCTION_NAME;
+ CameraFrame::FrameType frameType;
+
+ if (mFrameProvider == NULL) {
+ // no-op frame provider not set yet
+ return NO_ERROR;
+ }
+
+ if (mBufferSourceDirection == BUFFER_SOURCE_TAP_IN) {
+ // only supporting one type of input frame
+ frameType = CameraFrame::REPROCESS_INPUT_FRAME;
+ } else {
+ frameType = formatToOutputFrameType(mPixelFormat);
+ }
+
+ mFrameProvider->enableFrameNotification(frameType);
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+int BufferSourceAdapter::disableDisplay(bool cancel_buffer)
+{
+ LOG_FUNCTION_NAME;
+
+ if (mFrameProvider) mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+status_t BufferSourceAdapter::pauseDisplay(bool pause)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ // no-op for BufferSourceAdapter
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+
+void BufferSourceAdapter::destroy()
+{
+ LOG_FUNCTION_NAME;
+
+ mBufferCount = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+CameraBuffer* BufferSourceAdapter::allocateBufferList(int width, int dummyHeight, const char* format,
+ int &bytes, int numBufs)
+{
+ LOG_FUNCTION_NAME;
+ status_t err;
+ int i = -1;
+ const int lnumBufs = numBufs;
+ int undequeued = 0;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+
+ mBuffers = new CameraBuffer [lnumBufs];
+ memset (mBuffers, 0, sizeof(CameraBuffer) * lnumBufs);
+
+ if ( NULL == mBufferSource ) {
+ return NULL;
+ }
+
+ int pixFormat = getANWFormat(format);
+ int usage = getUsageFromANW(pixFormat);
+ mPixelFormat = CameraHal::getPixelFormatConstant(format);
+
+ // Set gralloc usage bits for window.
+ err = mBufferSource->set_usage(mBufferSource, usage);
+ if (err != 0) {
+ CAMHAL_LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
+
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+
+ return NULL;
+ }
+
+ CAMHAL_LOGDB("Number of buffers set to BufferSourceAdapter %d", numBufs);
+ // Set the number of buffers needed for this buffer source
+ err = mBufferSource->set_buffer_count(mBufferSource, numBufs);
+ if (err != 0) {
+ CAMHAL_LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err);
+
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+
+ return NULL;
+ }
+
+ CAMHAL_LOGDB("Configuring %d buffers for ANativeWindow", numBufs);
+ mBufferCount = numBufs;
+
+ // re-calculate height depending on stride and size
+ int height = getHeightFromFormat(format, width, bytes);
+
+ // Set window geometry
+ err = mBufferSource->set_buffers_geometry(mBufferSource,
+ width, height,
+ pixFormat);
+
+ if (err != 0) {
+ CAMHAL_LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err);
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+ return NULL;
+ }
+
+ if ( mBuffers == NULL ) {
+ CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers");
+ LOG_FUNCTION_NAME_EXIT;
+ return NULL;
+ }
+
+ mBufferSource->get_min_undequeued_buffer_count(mBufferSource, &undequeued);
+
+ for (i = 0; i < mBufferCount; i++ ) {
+ buffer_handle_t *handle;
+ int stride; // dummy variable to get stride
+ // TODO(XXX): Do we need to keep stride information in camera hal?
+
+ err = mBufferSource->dequeue_buffer(mBufferSource, &handle, &stride);
+
+ if (err != 0) {
+ CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+ goto fail;
+ }
+
+ CAMHAL_LOGDB("got handle %p", handle);
+ mBuffers[i].opaque = (void *)handle;
+ mBuffers[i].type = CAMERA_BUFFER_ANW;
+ mBuffers[i].format = mPixelFormat;
+ mFramesWithCameraAdapterMap.add(handle, i);
+
+ bytes = CameraHal::calculateBufferSize(format, width, height);
+ }
+
+ for( i = 0; i < mBufferCount-undequeued; i++ ) {
+ void *y_uv[2];
+ android::Rect bounds(width, height);
+
+ buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
+ mBufferSource->lock_buffer(mBufferSource, handle);
+ mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+ mBuffers[i].mapped = y_uv[0];
+ }
+
+ // return the rest of the buffers back to ANativeWindow
+ for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++) {
+ buffer_handle_t *handle = (buffer_handle_t *) mBuffers[i].opaque;
+ void *y_uv[2];
+ android::Rect bounds(width, height);
+
+ mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+ mBuffers[i].mapped = y_uv[0];
+ mapper.unlock(*handle);
+
+ err = mBufferSource->cancel_buffer(mBufferSource, handle);
+ if (err != 0) {
+ CAMHAL_LOGEB("cancel_buffer failed: %s (%d)", strerror(-err), -err);
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+ goto fail;
+ }
+ mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) mBuffers[i].opaque);
+ }
+
+ mFrameWidth = width;
+ mFrameHeight = height;
+ mBufferSourceDirection = BUFFER_SOURCE_TAP_OUT;
+
+ return mBuffers;
+
+ fail:
+ // need to cancel buffers if any were dequeued
+ for (int start = 0; start < i && i > 0; start++) {
+ int err = mBufferSource->cancel_buffer(mBufferSource,
+ (buffer_handle_t *) mBuffers[start].opaque);
+ if (err != 0) {
+ CAMHAL_LOGEB("cancelBuffer failed w/ error 0x%08x", err);
+ break;
+ }
+ mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) mBuffers[start].opaque);
+ }
+
+ freeBufferList(mBuffers);
+
+ CAMHAL_LOGEA("Error occurred, performing cleanup");
+
+ if (NULL != mErrorNotifier.get()) {
+ mErrorNotifier->errorNotify(-ENOMEM);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NULL;
+
+}
+
+CameraBuffer *BufferSourceAdapter::getBuffers(bool reset) {
+ int undequeued = 0;
+ status_t err;
+ android::Mutex::Autolock lock(mLock);
+
+ if (!mBufferSource || !mBuffers) {
+ CAMHAL_LOGE("Adapter is not set up properly: "
+ "mBufferSource:%p mBuffers:%p",
+ mBufferSource, mBuffers);
+ goto fail;
+ }
+
+ // CameraHal is indicating to us that the state of the mBuffer
+ // might have changed. We might need to check the state of the
+ // buffer list and pass a new one depending on the state of our
+ // surface
+ if (reset) {
+ const int lnumBufs = mBufferCount;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ android::Rect bounds(mFrameWidth, mFrameHeight);
+ void *y_uv[2];
+ CameraBuffer * newBuffers = NULL;
+ unsigned int index = 0;
+ android::KeyedVector<void*, int> missingIndices;
+
+ newBuffers = new CameraBuffer [lnumBufs];
+ memset (newBuffers, 0, sizeof(CameraBuffer) * lnumBufs);
+
+ // Use this vector to figure out missing indices
+ for (int i = 0; i < mBufferCount; i++) {
+ missingIndices.add(mBuffers[i].opaque, i);
+ }
+
+ // assign buffers that we have already dequeued
+ for (index = 0; index < mFramesWithCameraAdapterMap.size(); index++) {
+ int value = mFramesWithCameraAdapterMap.valueAt(index);
+ newBuffers[index].opaque = mBuffers[value].opaque;
+ newBuffers[index].type = mBuffers[value].type;
+ newBuffers[index].format = mBuffers[value].format;
+ newBuffers[index].mapped = mBuffers[value].mapped;
+ mFramesWithCameraAdapterMap.replaceValueAt(index, index);
+ missingIndices.removeItem(newBuffers[index].opaque);
+ }
+
+ mBufferSource->get_min_undequeued_buffer_count(mBufferSource, &undequeued);
+
+ // dequeue the rest of the buffers
+ for (index; index < (unsigned int)(mBufferCount-undequeued); index++) {
+ buffer_handle_t *handle;
+ int stride; // dummy variable to get stride
+
+ err = mBufferSource->dequeue_buffer(mBufferSource, &handle, &stride);
+ if (err != 0) {
+ CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+ goto fail;
+ }
+ newBuffers[index].opaque = (void *)handle;
+ newBuffers[index].type = CAMERA_BUFFER_ANW;
+ newBuffers[index].format = mPixelFormat;
+ mFramesWithCameraAdapterMap.add(handle, index);
+
+ mBufferSource->lock_buffer(mBufferSource, handle);
+ mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+ newBuffers[index].mapped = y_uv[0];
+ CAMHAL_LOGDB("got handle %p", handle);
+
+ missingIndices.removeItem(newBuffers[index].opaque);
+ }
+
+ // now we need to figure out which buffers aren't dequeued
+ // which are in mBuffers but not newBuffers yet
+ if ((mBufferCount - index) != missingIndices.size()) {
+ CAMHAL_LOGD("Hrmm somethings gone awry. We are missing a different number"
+ " of buffers than we can fill");
+ }
+ for (unsigned int i = 0; i < missingIndices.size(); i++) {
+ int j = missingIndices.valueAt(i);
+
+ CAMHAL_LOGD("Filling at %d", j);
+ newBuffers[index].opaque = mBuffers[j].opaque;
+ newBuffers[index].type = mBuffers[j].type;
+ newBuffers[index].format = mBuffers[j].format;
+ newBuffers[index].mapped = mBuffers[j].mapped;
+ }
+
+ delete [] mBuffers;
+ mBuffers = newBuffers;
+ }
+
+ return mBuffers;
+
+ fail:
+ return NULL;
+}
+
+unsigned int BufferSourceAdapter::getSize() {
+ android::Mutex::Autolock lock(mLock);
+ return CameraHal::calculateBufferSize(mPixelFormat, mFrameWidth, mFrameHeight);
+}
+
+int BufferSourceAdapter::getBufferCount() {
+ int count = -1;
+
+ android::Mutex::Autolock lock(mLock);
+ if (mBufferSource) extendedOps()->get_buffer_count(mBufferSource, &count);
+ return count;
+}
+
+CameraBuffer* BufferSourceAdapter::getBufferList(int *num) {
+ LOG_FUNCTION_NAME;
+ status_t err;
+ const int lnumBufs = 1;
+ int formatSource;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ buffer_handle_t *handle;
+
+ // TODO(XXX): Only supporting one input buffer at a time right now
+ *num = 1;
+ mBufferCount = *num;
+ mBuffers = new CameraBuffer [lnumBufs];
+ memset (mBuffers, 0, sizeof(CameraBuffer) * lnumBufs);
+
+ if ( NULL == mBufferSource ) {
+ return NULL;
+ }
+
+ err = extendedOps()->update_and_get_buffer(mBufferSource,
+ &handle,
+ &mBuffers[0].stride,
+ &mBuffers[0].privateData);
+ if (err != 0) {
+ CAMHAL_LOGEB("update and get buffer failed: %s (%d)", strerror(-err), -err);
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+ goto fail;
+ }
+
+ CAMHAL_LOGD("got handle %p", handle);
+ mBuffers[0].opaque = (void *)handle;
+ mBuffers[0].type = CAMERA_BUFFER_ANW;
+ mFramesWithCameraAdapterMap.add(handle, 0);
+
+ err = extendedOps()->get_buffer_dimension(mBufferSource, &mBuffers[0].width, &mBuffers[0].height);
+ err = extendedOps()->get_buffer_format(mBufferSource, &formatSource);
+
+ int t, l, r, b, w, h;
+ err = extendedOps()->get_crop(mBufferSource, &l, &t, &r, &b);
+ err = extendedOps()->get_current_size(mBufferSource, &w, &h);
+
+ // lock buffer
+ {
+ void *y_uv[2];
+ android::Rect bounds(mBuffers[0].width, mBuffers[0].height);
+ mapper.lock(*handle, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+ mBuffers[0].mapped = y_uv[0];
+ }
+
+ mFrameWidth = mBuffers[0].width;
+ mFrameHeight = mBuffers[0].height;
+ mPixelFormat = getFormatFromANW(formatSource);
+
+ mBuffers[0].format = mPixelFormat;
+ mBuffers[0].actual_size = CameraHal::calculateBufferSize(mPixelFormat, w, h);
+ mBuffers[0].offset = t * w + l * CameraHal::getBPP(mPixelFormat);
+ mBufferSourceDirection = BUFFER_SOURCE_TAP_IN;
+
+ return mBuffers;
+
+ fail:
+ // need to cancel buffers if any were dequeued
+ freeBufferList(mBuffers);
+
+ if (NULL != mErrorNotifier.get()) {
+ mErrorNotifier->errorNotify(-ENOMEM);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NULL;
+}
+
+uint32_t * BufferSourceAdapter::getOffsets()
+{
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NULL;
+}
+
+int BufferSourceAdapter::minUndequeueableBuffers(int& undequeueable) {
+ LOG_FUNCTION_NAME;
+ int ret = NO_ERROR;
+
+ if(!mBufferSource)
+ {
+ ret = INVALID_OPERATION;
+ goto end;
+ }
+
+ ret = mBufferSource->get_min_undequeued_buffer_count(mBufferSource, &undequeueable);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("get_min_undequeued_buffer_count failed: %s (%d)", strerror(-ret), -ret);
+ if ( ENODEV == ret ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+ return -ret;
+ }
+
+ end:
+ return ret;
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+int BufferSourceAdapter::maxQueueableBuffers(unsigned int& queueable)
+{
+ LOG_FUNCTION_NAME;
+ int ret = NO_ERROR;
+ int undequeued = 0;
+
+ if(mBufferCount == 0) {
+ ret = INVALID_OPERATION;
+ goto end;
+ }
+
+ ret = minUndequeueableBuffers(undequeued);
+ if (ret != NO_ERROR) {
+ goto end;
+ }
+
+ queueable = mBufferCount - undequeued;
+
+ end:
+ return ret;
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+int BufferSourceAdapter::getFd()
+{
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return -1;
+
+}
+
+status_t BufferSourceAdapter::returnBuffersToWindow()
+{
+ status_t ret = NO_ERROR;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+
+ //Give the buffers back to display here - sort of free it
+ if (mBufferSource) {
+ for(unsigned int i = 0; i < mFramesWithCameraAdapterMap.size(); i++) {
+ int value = mFramesWithCameraAdapterMap.valueAt(i);
+ buffer_handle_t *handle = (buffer_handle_t *) mBuffers[value].opaque;
+
+ // if buffer index is out of bounds skip
+ if ((value < 0) || (value >= mBufferCount)) {
+ CAMHAL_LOGEA("Potential out bounds access to handle...skipping");
+ continue;
+ }
+
+ // unlock buffer before giving it up
+ mapper.unlock(*handle);
+
+ ret = mBufferSource->cancel_buffer(mBufferSource, handle);
+ if ( ENODEV == ret ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ return -ret;
+ } else if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("cancel_buffer() failed: %s (%d)",
+ strerror(-ret),
+ -ret);
+ return -ret;
+ }
+ }
+ } else {
+ CAMHAL_LOGE("mBufferSource is NULL");
+ }
+
+ ///Clear the frames with camera adapter map
+ mFramesWithCameraAdapterMap.clear();
+
+ return ret;
+
+}
+
+int BufferSourceAdapter::freeBufferList(CameraBuffer * buflist)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+
+ if ( mBuffers != buflist ) {
+ return BAD_VALUE;
+ }
+
+ android::AutoMutex lock(mLock);
+
+ if (mBufferSourceDirection == BUFFER_SOURCE_TAP_OUT) returnBuffersToWindow();
+
+ if( mBuffers != NULL)
+ {
+ delete [] mBuffers;
+ mBuffers = NULL;
+ }
+
+ return NO_ERROR;
+}
+
+
+bool BufferSourceAdapter::supportsExternalBuffering()
+{
+ return false;
+}
+
+void BufferSourceAdapter::addFrame(CameraFrame* frame)
+{
+ if (mQueueFrame.get()) {
+ mQueueFrame->addFrame(frame);
+ }
+}
+
+void BufferSourceAdapter::handleFrameCallback(CameraFrame* frame)
+{
+ status_t ret = NO_ERROR;
+ buffer_handle_t *handle = NULL;
+ int i;
+ uint32_t x, y;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+
+ android::AutoMutex lock(mLock);
+
+ if (!mBuffers || !frame->mBuffer) {
+ CAMHAL_LOGEA("Adapter sent BufferSourceAdapter a NULL frame?");
+ return;
+ }
+
+ for ( i = 0; i < mBufferCount; i++ ) {
+ if (frame->mBuffer == &mBuffers[i]) {
+ break;
+ }
+ }
+
+ if (i >= mBufferCount) {
+ CAMHAL_LOGD("Can't find frame in buffer list");
+ if (frame->mFrameType != CameraFrame::REPROCESS_INPUT_FRAME) {
+ mFrameProvider->returnFrame(frame->mBuffer,
+ static_cast<CameraFrame::FrameType>(frame->mFrameType));
+ }
+ return;
+ }
+
+ handle = (buffer_handle_t *) mBuffers[i].opaque;
+
+ // Handle input buffers
+ // TODO(XXX): Move handling of input buffers out of here if
+ // it becomes more complex
+ if (frame->mFrameType == CameraFrame::REPROCESS_INPUT_FRAME) {
+ CAMHAL_LOGD("Unlock %p (buffer #%d)", handle, i);
+ mapper.unlock(*handle);
+ extendedOps()->release_buffer(mBufferSource, mBuffers[i].privateData);
+ return;
+ }
+
+ CameraHal::getXYFromOffset(&x, &y, frame->mOffset, frame->mAlignment, mPixelFormat);
+ CAMHAL_LOGVB("offset = %u left = %d top = %d right = %d bottom = %d",
+ frame->mOffset, x, y, x + frame->mWidth, y + frame->mHeight);
+ ret = mBufferSource->set_crop(mBufferSource, x, y, x + frame->mWidth, y + frame->mHeight);
+ if (NO_ERROR != ret) {
+ CAMHAL_LOGE("mBufferSource->set_crop returned error %d", ret);
+ goto fail;
+ }
+
+ if ( NULL != frame->mMetaData.get() ) {
+ camera_memory_t *extMeta = frame->mMetaData->getExtendedMetadata();
+ if ( NULL != extMeta ) {
+ camera_metadata_t *metaData = static_cast<camera_metadata_t *> (extMeta->data);
+ metaData->timestamp = frame->mTimestamp;
+ ret = extendedOps()->set_metadata(mBufferSource, extMeta);
+ if (ret != 0) {
+ CAMHAL_LOGE("Surface::set_metadata returned error %d", ret);
+ goto fail;
+ }
+ }
+ }
+
+ // unlock buffer before enqueueing
+ mapper.unlock(*handle);
+
+ ret = mBufferSource->enqueue_buffer(mBufferSource, handle);
+ if (ret != 0) {
+ CAMHAL_LOGE("Surface::queueBuffer returned error %d", ret);
+ goto fail;
+ }
+
+ mFramesWithCameraAdapterMap.removeItem((buffer_handle_t *) frame->mBuffer->opaque);
+
+ return;
+
+fail:
+ mFramesWithCameraAdapterMap.clear();
+ mBufferSource = NULL;
+ mReturnFrame->requestExit();
+ mQueueFrame->requestExit();
+}
+
+
+bool BufferSourceAdapter::handleFrameReturn()
+{
+ status_t err;
+ buffer_handle_t *buf;
+ int i = 0;
+ int stride; // dummy variable to get stride
+ CameraFrame::FrameType type;
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+ void *y_uv[2];
+ android::Rect bounds(mFrameWidth, mFrameHeight);
+
+ android::AutoMutex lock(mLock);
+
+ if ( (NULL == mBufferSource) || (NULL == mBuffers) ) {
+ return false;
+ }
+
+ err = mBufferSource->dequeue_buffer(mBufferSource, &buf, &stride);
+ if (err != 0) {
+ CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+
+ return false;
+ }
+
+ err = mBufferSource->lock_buffer(mBufferSource, buf);
+ if (err != 0) {
+ CAMHAL_LOGEB("lockbuffer failed: %s (%d)", strerror(-err), -err);
+
+ if ( ENODEV == err ) {
+ CAMHAL_LOGEA("Preview surface abandoned!");
+ mBufferSource = NULL;
+ }
+
+ return false;
+ }
+
+ mapper.lock(*buf, CAMHAL_GRALLOC_USAGE, bounds, y_uv);
+
+ for(i = 0; i < mBufferCount; i++) {
+ if (mBuffers[i].opaque == buf)
+ break;
+ }
+
+ if (i >= mBufferCount) {
+ CAMHAL_LOGEB("Failed to find handle %p", buf);
+ }
+
+ mFramesWithCameraAdapterMap.add((buffer_handle_t *) mBuffers[i].opaque, i);
+
+ CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount - 1);
+
+ mFrameProvider->returnFrame(&mBuffers[i], formatToOutputFrameType(mPixelFormat));
+ return true;
+}
+
+void BufferSourceAdapter::frameCallback(CameraFrame* caFrame)
+{
+ if ((NULL != caFrame) && (NULL != caFrame->mCookie)) {
+ BufferSourceAdapter *da = (BufferSourceAdapter*) caFrame->mCookie;
+ da->addFrame(caFrame);
+ } else {
+ CAMHAL_LOGEB("Invalid Cookie in Camera Frame = %p, Cookie = %p",
+ caFrame, caFrame ? caFrame->mCookie : NULL);
+ }
+}
+
+/*--------------------BufferSourceAdapter Class ENDS here-----------------------------*/
+
+} // namespace Camera
+} // namespace Ti
+
+#endif
diff --git a/camera/CameraHal.cpp b/camera/CameraHal.cpp
new file mode 100644
index 0000000..7e7cf9d
--- /dev/null
+++ b/camera/CameraHal.cpp
@@ -0,0 +1,5012 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file CameraHal.cpp
+*
+* This file maps the Camera Hardware Interface to V4L2.
+*
+*/
+
+#include "CameraHal.h"
+#include "ANativeWindowDisplayAdapter.h"
+#include "BufferSourceAdapter.h"
+#include "TICameraParameters.h"
+#include "CameraProperties.h"
+#include <cutils/properties.h>
+
+#include <poll.h>
+#include <math.h>
+
+namespace Ti {
+namespace Camera {
+
+extern "C" CameraAdapter* OMXCameraAdapter_Factory(size_t);
+extern "C" CameraAdapter* V4LCameraAdapter_Factory(size_t, CameraHal*);
+
+/*****************************************************************************/
+
+////Constant definitions and declarations
+////@todo Have a CameraProperties class to store these parameters as constants for every camera
+//// Currently, they are hard-coded
+
+const int CameraHal::NO_BUFFERS_PREVIEW = MAX_CAMERA_BUFFERS;
+const int CameraHal::NO_BUFFERS_IMAGE_CAPTURE = 5;
+const int CameraHal::SW_SCALING_FPS_LIMIT = 15;
+
+const uint32_t MessageNotifier::EVENT_BIT_FIELD_POSITION = 16;
+
+const uint32_t MessageNotifier::FRAME_BIT_FIELD_POSITION = 0;
+
+// TODO(XXX): Temporarily increase number of buffers we can allocate from ANW
+// until faux-NPA mode is implemented
+const int CameraHal::NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP = 15;
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+// HACK: Default path to directory where RAW images coming from video port will be saved to.
+// If directory not exists the saving is skipped and video port frame is ignored.
+// The directory name is choosed in so weird way to enable RAW images saving only when
+// directory has been created explicitly by user.
+extern const char * const kRawImagesOutputDirPath = "/data/misc/camera/RaW_PiCtUrEs";
+extern const char * const kYuvImagesOutputDirPath = "/data/misc/camera/YuV_PiCtUrEs";
+#endif
+
+/******************************************************************************/
+
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+static int dummy_update_and_get_buffer(preview_stream_ops_t*, buffer_handle_t**, int*,int*) {
+ return INVALID_OPERATION;
+}
+
+static int dummy_release_buffer(preview_stream_ops_t*, int slot) {
+ return INVALID_OPERATION;
+}
+
+static int dummy_get_buffer_dimension(preview_stream_ops_t*, int*, int*) {
+ return INVALID_OPERATION;
+}
+
+static int dummy_get_buffer_format(preview_stream_ops_t*, int*) {
+ return INVALID_OPERATION;
+}
+
+static int dummy_set_metadata(preview_stream_ops_t*, const camera_memory_t*) {
+ return INVALID_OPERATION;
+}
+
+static int dummy_get_id(preview_stream_ops_t*, char *data, unsigned int dataSize) {
+ return INVALID_OPERATION;
+}
+
+static int dummy_get_buffer_count(preview_stream_ops_t*, int *count) {
+ return INVALID_OPERATION;
+}
+
+static int dummy_get_crop(preview_stream_ops_t*,
+ int *, int *, int *, int *) {
+ return INVALID_OPERATION;
+}
+
+static int dummy_get_current_size(preview_stream_ops_t*,
+ int *, int *) {
+ return INVALID_OPERATION;
+}
+#endif
+
+
+CameraHal::SocFamily CameraHal::getSocFamily() {
+ static const struct {
+ const char *name;
+ const CameraHal::SocFamily value;
+ } socFamilyArray[] = {
+ {"OMAP4430", SocFamily_Omap4430},
+ {"OMAP4460", SocFamily_Omap4460},
+ {"OMAP4470", SocFamily_Omap4470}
+ };
+ // lets get the soc family string from sysfs
+ static const char *sysfsNode = "/sys/board_properties/soc/family";
+ FILE *sysfsFd = fopen(sysfsNode, "r");
+ static const int bufSize = 128;
+ char buf[bufSize];
+ if (sysfsFd == NULL) {
+ CAMHAL_LOGEA("'%s' Not Available", sysfsNode);
+ return SocFamily_Undefined;
+ }
+ const char *res = fgets(buf, bufSize, sysfsFd);
+ fclose(sysfsFd);
+ if (res == NULL) {
+ CAMHAL_LOGEA("Error reading '%s'", sysfsNode);
+ return SocFamily_Undefined;
+ }
+ // translate it to CameraHal::SocFamily enum
+ for (int i = 0; i < SocFamily_ElementCount; ++i) {
+ if (strncmp(socFamilyArray[i].name, buf, strlen(socFamilyArray[i].name)) == 0) {
+ return socFamilyArray[i].value;
+ }
+ }
+ return SocFamily_Undefined;
+}
+
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+static preview_stream_extended_ops_t dummyPreviewStreamExtendedOps = {
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ dummy_update_and_get_buffer,
+ dummy_release_buffer,
+ dummy_get_buffer_dimension,
+ dummy_get_buffer_format,
+ dummy_set_metadata,
+ dummy_get_id,
+ dummy_get_buffer_count,
+ dummy_get_crop,
+ dummy_get_current_size,
+#endif
+};
+#endif
+
+
+DisplayAdapter::DisplayAdapter()
+{
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ mExtendedOps = &dummyPreviewStreamExtendedOps;
+#endif
+}
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+void DisplayAdapter::setExtendedOps(preview_stream_extended_ops_t * extendedOps) {
+ mExtendedOps = extendedOps ? extendedOps : &dummyPreviewStreamExtendedOps;
+}
+#endif
+
+
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+struct timeval CameraHal::mStartPreview;
+struct timeval CameraHal::mStartFocus;
+struct timeval CameraHal::mStartCapture;
+
+#endif
+
+static void orientation_cb(uint32_t orientation, uint32_t tilt, void* cookie) {
+ CameraHal *camera = NULL;
+
+ if (cookie) {
+ camera = (CameraHal*) cookie;
+ camera->onOrientationEvent(orientation, tilt);
+ }
+
+}
+
+/*-------------Camera Hal Interface Method definitions STARTS here--------------------*/
+
+/**
+ Callback function to receive orientation events from SensorListener
+ */
+void CameraHal::onOrientationEvent(uint32_t orientation, uint32_t tilt) {
+ LOG_FUNCTION_NAME;
+
+ if ( NULL != mCameraAdapter ) {
+ mCameraAdapter->onOrientationEvent(orientation, tilt);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Set the notification and data callbacks
+
+ @param[in] notify_cb Notify callback for notifying the app about events and errors
+ @param[in] data_cb Buffer callback for sending the preview/raw frames to the app
+ @param[in] data_cb_timestamp Buffer callback for sending the video frames w/ timestamp
+ @param[in] user Callback cookie
+ @return none
+
+ */
+void CameraHal::setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user)
+{
+ LOG_FUNCTION_NAME;
+
+ if ( NULL != mAppCallbackNotifier.get() )
+ {
+ mAppCallbackNotifier->setCallbacks(this,
+ notify_cb,
+ data_cb,
+ data_cb_timestamp,
+ get_memory,
+ user);
+ }
+
+ if ( NULL != mCameraAdapter ) {
+ mCameraAdapter->setSharedAllocator(get_memory);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Enable a message, or set of messages.
+
+ @param[in] msgtype Bitmask of the messages to enable (defined in include/ui/Camera.h)
+ @return none
+
+ */
+void CameraHal::enableMsgType(int32_t msgType)
+{
+ LOG_FUNCTION_NAME;
+
+ if ( ( msgType & CAMERA_MSG_SHUTTER ) && ( !mShutterEnabled ) )
+ {
+ msgType &= ~CAMERA_MSG_SHUTTER;
+ }
+
+ // ignoring enable focus message from camera service
+ // we will enable internally in autoFocus call
+ msgType &= ~CAMERA_MSG_FOCUS;
+#ifdef ANDROID_API_JB_OR_LATER
+ msgType &= ~CAMERA_MSG_FOCUS_MOVE;
+#endif
+
+ {
+ android::AutoMutex lock(mLock);
+ mMsgEnabled |= msgType;
+ }
+
+ if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+ {
+ if(mDisplayPaused)
+ {
+ CAMHAL_LOGDA("Preview currently paused...will enable preview callback when restarted");
+ msgType &= ~CAMERA_MSG_PREVIEW_FRAME;
+ }else
+ {
+ CAMHAL_LOGDA("Enabling Preview Callback");
+ }
+ }
+ else
+ {
+ CAMHAL_LOGDB("Preview callback not enabled %x", msgType);
+ }
+
+
+ ///Configure app callback notifier with the message callback required
+ mAppCallbackNotifier->enableMsgType (msgType);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Disable a message, or set of messages.
+
+ @param[in] msgtype Bitmask of the messages to disable (defined in include/ui/Camera.h)
+ @return none
+
+ */
+void CameraHal::disableMsgType(int32_t msgType)
+{
+ LOG_FUNCTION_NAME;
+
+ {
+ android::AutoMutex lock(mLock);
+ mMsgEnabled &= ~msgType;
+ }
+
+ if( msgType & CAMERA_MSG_PREVIEW_FRAME)
+ {
+ CAMHAL_LOGDA("Disabling Preview Callback");
+ }
+
+ ///Configure app callback notifier
+ mAppCallbackNotifier->disableMsgType (msgType);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief 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.
+
+ @param[in] msgtype Bitmask of the messages to query (defined in include/ui/Camera.h)
+ @return true If all message types are enabled
+ false If any message type
+
+ */
+int CameraHal::msgTypeEnabled(int32_t msgType)
+{
+ int32_t msgEnabled = 0;
+
+ LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mLock);
+
+ msgEnabled = mMsgEnabled;
+ if (!previewEnabled() && !mPreviewInitializationDone) {
+ msgEnabled &= ~(CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_PREVIEW_METADATA);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return (msgEnabled & msgType);
+}
+
+/**
+ @brief Set the camera parameters.
+
+ @param[in] params Camera parameters to configure the camera
+ @return NO_ERROR
+ @todo Define error codes
+
+ */
+int CameraHal::setParameters(const char* parameters)
+{
+
+ LOG_FUNCTION_NAME;
+
+ android::CameraParameters params;
+
+ android::String8 str_params(parameters);
+ params.unflatten(str_params);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return setParameters(params);
+}
+
+/**
+ @brief Set the camera parameters.
+
+ @param[in] params Camera parameters to configure the camera
+ @return NO_ERROR
+ @todo Define error codes
+
+ */
+int CameraHal::setParameters(const android::CameraParameters& params)
+{
+
+ LOG_FUNCTION_NAME;
+
+ int w, h;
+ int framerate;
+ const char *valstr = NULL;
+ int varint = 0;
+ status_t ret = NO_ERROR;
+ // Needed for KEY_RECORDING_HINT
+ bool restartPreviewRequired = false;
+ bool updateRequired = false;
+ android::CameraParameters oldParams = mParameters;
+#ifdef MOTOROLA_CAMERA
+ char value[PROPERTY_VALUE_MAX];
+#endif
+
+#ifdef V4L_CAMERA_ADAPTER
+ if (strcmp (V4L_CAMERA_NAME_USB, mCameraProperties->get(CameraProperties::CAMERA_NAME)) == 0 ) {
+ updateRequired = true;
+ }
+#endif
+
+ {
+ android::AutoMutex lock(mLock);
+
+ ///Ensure that preview is not enabled when the below parameters are changed.
+ if(!previewEnabled())
+ {
+ if ((valstr = params.getPreviewFormat()) != NULL) {
+ if ( isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS))) {
+ mParameters.setPreviewFormat(valstr);
+ CAMHAL_LOGDB("PreviewFormat set %s", valstr);
+ } else {
+ CAMHAL_LOGEB("Invalid preview format: %s. Supported: %s", valstr,
+ mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS));
+ return BAD_VALUE;
+ }
+ }
+
+ if ((valstr = params.get(TICameraParameters::KEY_VNF)) != NULL) {
+ if (strcmp(mCameraProperties->get(CameraProperties::VNF_SUPPORTED),
+ android::CameraParameters::TRUE) == 0) {
+ CAMHAL_LOGDB("VNF %s", valstr);
+ mParameters.set(TICameraParameters::KEY_VNF, valstr);
+ } else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
+ CAMHAL_LOGEB("ERROR: Invalid VNF: %s", valstr);
+ return BAD_VALUE;
+ } else {
+ mParameters.set(TICameraParameters::KEY_VNF,
+ android::CameraParameters::FALSE);
+ }
+ }
+
+ if ((valstr = params.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) != NULL) {
+ // make sure we support vstab...if we don't and application is trying to set
+ // vstab then return an error
+ if (strcmp(mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED),
+ android::CameraParameters::TRUE) != 0 &&
+ strcmp(valstr, android::CameraParameters::TRUE) == 0) {
+ CAMHAL_LOGEB("ERROR: Invalid VSTAB: %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_CAP_MODE)) != NULL) {
+
+ if (strcmp(TICameraParameters::VIDEO_MODE, valstr)) {
+ mCapModeBackup = valstr;
+ }
+
+ CAMHAL_LOGDB("Capture mode set %s", valstr);
+
+ const char *currentMode = mParameters.get(TICameraParameters::KEY_CAP_MODE);
+ if ( NULL != currentMode ) {
+ if ( strcmp(currentMode, valstr) != 0 ) {
+ updateRequired = true;
+ }
+ } else {
+ updateRequired = true;
+ }
+
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, valstr);
+ } else if (!mCapModeBackup.isEmpty()) {
+ // Restore previous capture mode after stopPreview()
+ mParameters.set(TICameraParameters::KEY_CAP_MODE,
+ mCapModeBackup.string());
+ updateRequired = true;
+ }
+
+#ifdef OMAP_ENHANCEMENT_VTC
+ if ((valstr = params.get(TICameraParameters::KEY_VTC_HINT)) != NULL ) {
+ mParameters.set(TICameraParameters::KEY_VTC_HINT, valstr);
+ if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
+ mVTCUseCase = true;
+ } else {
+ mVTCUseCase = false;
+ }
+ CAMHAL_LOGDB("VTC Hint = %d", mVTCUseCase);
+ }
+
+ if (mVTCUseCase) {
+ if ((valstr = params.get(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE)) != NULL ) {
+ mParameters.set(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE, valstr);
+ }
+
+ if ((valstr = params.get(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT)) != NULL ) {
+ mParameters.set(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT, valstr);
+ }
+ }
+#endif
+ }
+
+ if ((valstr = params.get(TICameraParameters::KEY_IPP)) != NULL) {
+ if (isParameterValid(valstr,mCameraProperties->get(CameraProperties::SUPPORTED_IPP_MODES))) {
+ if ((mParameters.get(TICameraParameters::KEY_IPP) == NULL) ||
+ (strcmp(valstr, mParameters.get(TICameraParameters::KEY_IPP)))) {
+ CAMHAL_LOGDB("IPP mode set %s", params.get(TICameraParameters::KEY_IPP));
+ mParameters.set(TICameraParameters::KEY_IPP, valstr);
+ restartPreviewRequired = true;
+ }
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid IPP mode: %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ if ( (valstr = params.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT)) != NULL )
+ {
+ if (strcmp(valstr, mParameters.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT)))
+ {
+ CAMHAL_LOGDB("Stereo 3D preview image layout is %s", valstr);
+ mParameters.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT, valstr);
+ restartPreviewRequired = true;
+ }
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ int orientation =0;
+ if((valstr = params.get(TICameraParameters::KEY_SENSOR_ORIENTATION)) != NULL)
+ {
+ doesSetParameterNeedUpdate(valstr,
+ mParameters.get(TICameraParameters::KEY_SENSOR_ORIENTATION),
+ updateRequired);
+
+ orientation = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION);
+ if ( orientation < 0 || orientation >= 360 || (orientation%90) != 0 ) {
+ CAMHAL_LOGE("Invalid sensor orientation: %s. Value must be one of: [0, 90, 180, 270]", valstr);
+ return BAD_VALUE;
+ }
+
+ CAMHAL_LOGD("Sensor Orientation is set to %d", orientation);
+ mParameters.set(TICameraParameters::KEY_SENSOR_ORIENTATION, valstr);
+ }
+#endif
+
+ params.getPreviewSize(&w, &h);
+ if (w == -1 && h == -1) {
+ CAMHAL_LOGEA("Unable to get preview size");
+ return BAD_VALUE;
+ }
+
+ mVideoWidth = w;
+ mVideoHeight = h;
+
+ // Handle RECORDING_HINT to Set/Reset Video Mode Parameters
+ valstr = params.get(android::CameraParameters::KEY_RECORDING_HINT);
+ if(valstr != NULL)
+ {
+ CAMHAL_LOGDB("Recording Hint is set to %s", valstr);
+ if(strcmp(valstr, android::CameraParameters::TRUE) == 0)
+ {
+ CAMHAL_LOGVB("Video Resolution: %d x %d", mVideoWidth, mVideoHeight);
+ mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, valstr);
+ restartPreviewRequired |= setVideoModeParameters(params);
+ }
+ else if(strcmp(valstr, android::CameraParameters::FALSE) == 0)
+ {
+ mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, valstr);
+ restartPreviewRequired |= resetVideoModeParameters();
+ }
+ else
+ {
+ CAMHAL_LOGEA("Invalid RECORDING_HINT");
+ return BAD_VALUE;
+ }
+ }
+ else
+ {
+ // This check is required in following case.
+ // If VideoRecording activity sets KEY_RECORDING_HINT to TRUE and
+ // ImageCapture activity doesnot set KEY_RECORDING_HINT to FALSE (i.e. simply NULL),
+ // then Video Mode parameters may remain present in ImageCapture activity as well.
+ CAMHAL_LOGDA("Recording Hint is set to NULL");
+ mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, "");
+ restartPreviewRequired |= resetVideoModeParameters();
+ }
+
+ if ( (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES)))
+ && (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES)))
+ && (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES)))
+ && (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES))) ) {
+ CAMHAL_LOGEB("Invalid preview resolution %d x %d", w, h);
+ return BAD_VALUE;
+ }
+
+ int oldWidth, oldHeight;
+ mParameters.getPreviewSize(&oldWidth, &oldHeight);
+ if ( ( oldWidth != w ) || ( oldHeight != h ) )
+ {
+ mParameters.setPreviewSize(w, h);
+ restartPreviewRequired = true;
+ }
+
+ CAMHAL_LOGDB("Preview Resolution: %d x %d", w, h);
+
+ if ((valstr = params.get(android::CameraParameters::KEY_FOCUS_MODE)) != NULL) {
+ if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES))) {
+ CAMHAL_LOGDB("Focus mode set %s", valstr);
+
+ // we need to take a decision on the capture mode based on whether CAF picture or
+ // video is chosen so the behavior of each is consistent to the application
+ if(strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) == 0){
+ restartPreviewRequired |= resetVideoModeParameters();
+ } else if (strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) == 0){
+ restartPreviewRequired |= setVideoModeParameters(params);
+ }
+
+ mParameters.set(android::CameraParameters::KEY_FOCUS_MODE, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid FOCUS mode = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ mRawCapture = false;
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ valstr = params.get(TICameraParameters::KEY_CAP_MODE);
+ if ( (!valstr || strcmp(valstr, TICameraParameters::HIGH_QUALITY_MODE) == 0) &&
+ access(kRawImagesOutputDirPath, F_OK) != -1 ) {
+ mRawCapture = true;
+ }
+#endif
+
+ if ( (valstr = params.get(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT)) != NULL )
+ {
+ CAMHAL_LOGDB("Stereo 3D capture image layout is %s", valstr);
+ mParameters.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT, valstr);
+ }
+
+ params.getPictureSize(&w, &h);
+ if ( (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES)))
+ || (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES)))
+ || (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES)))
+ || (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES))) ) {
+ mParameters.setPictureSize(w, h);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid picture resolution %d x %d", w, h);
+ return BAD_VALUE;
+ }
+
+ CAMHAL_LOGDB("Picture Size by App %d x %d", w, h);
+
+ if ( (valstr = params.getPictureFormat()) != NULL ) {
+ if (isParameterValid(valstr,mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS))) {
+ if ((strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) &&
+ mCameraProperties->get(CameraProperties::MAX_PICTURE_WIDTH) &&
+ mCameraProperties->get(CameraProperties::MAX_PICTURE_HEIGHT)) {
+ unsigned int width = 0, height = 0;
+ // Set picture size to full frame for raw bayer capture
+ width = atoi(mCameraProperties->get(CameraProperties::MAX_PICTURE_WIDTH));
+ height = atoi(mCameraProperties->get(CameraProperties::MAX_PICTURE_HEIGHT));
+ mParameters.setPictureSize(width,height);
+ }
+ mParameters.setPictureFormat(valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid picture format: %s",valstr);
+ ret = BAD_VALUE;
+ }
+ }
+
+#ifdef OMAP_ENHANCEMENT_BURST_CAPTURE
+ if ((valstr = params.get(TICameraParameters::KEY_BURST)) != NULL) {
+ if (params.getInt(TICameraParameters::KEY_BURST) >=0) {
+ CAMHAL_LOGDB("Burst set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_BURST, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Burst value: %s",valstr);
+ return BAD_VALUE;
+ }
+ }
+#endif
+
+ // Variable framerate ranges have higher priority over
+ // deprecated constant FPS.
+ // There is possible 3 situations :
+ // 1) User change FPS range and HAL use it for fps port value (don't care about
+ // changed or not const FPS).
+ // 2) User change single FPS and not change FPS range - will be applyed single FPS value
+ // to port.
+ // 3) Both FPS range and const FPS are unchanged - FPS range will be applied to port.
+
+ int curFramerate = 0;
+ bool frameRangeUpdated = false, fpsUpdated = false;
+ int curMaxFPS = 0, curMinFPS = 0, maxFPS = 0, minFPS = 0;
+
+ mParameters.getPreviewFpsRange(&curMinFPS, &curMaxFPS);
+ params.getPreviewFpsRange(&minFPS, &maxFPS);
+
+ curFramerate = mParameters.getPreviewFrameRate();
+ framerate = params.getPreviewFrameRate();
+
+ valstr = params.get(android::CameraParameters::KEY_PREVIEW_FPS_RANGE);
+ if (valstr != NULL && strlen(valstr) &&
+ ((curMaxFPS != maxFPS) || (curMinFPS != minFPS))) {
+ CAMHAL_LOGDB("## current minFPS = %d; maxFPS=%d", curMinFPS, curMaxFPS);
+ CAMHAL_LOGDB("## requested minFPS = %d; maxFPS=%d", minFPS, maxFPS);
+ if (!isFpsRangeValid(minFPS, maxFPS, params.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE)) &&
+ !isFpsRangeValid(minFPS, maxFPS, params.get(TICameraParameters::KEY_FRAMERATE_RANGES_EXT_SUPPORTED))) {
+ CAMHAL_LOGEA("Trying to set invalid FPS Range (%d,%d)", minFPS, maxFPS);
+ return BAD_VALUE;
+ }
+ mParameters.set(android::CameraParameters::KEY_PREVIEW_FPS_RANGE, valstr);
+ CAMHAL_LOGDB("FPS Range = %s", valstr);
+ if ( curMaxFPS == (FRAME_RATE_HIGH_HD * CameraHal::VFR_SCALE) &&
+ maxFPS < (FRAME_RATE_HIGH_HD * CameraHal::VFR_SCALE) ) {
+ restartPreviewRequired = true;
+ }
+ frameRangeUpdated = true;
+ }
+
+ valstr = params.get(android::CameraParameters::KEY_PREVIEW_FRAME_RATE);
+ if (valstr != NULL && strlen(valstr) && (framerate != curFramerate)) {
+ CAMHAL_LOGD("current framerate = %d reqested framerate = %d", curFramerate, framerate);
+ if (!isParameterValid(framerate, params.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES)) &&
+ !isParameterValid(framerate, params.get(TICameraParameters::KEY_FRAMERATES_EXT_SUPPORTED))) {
+ CAMHAL_LOGEA("Trying to set invalid frame rate %d", framerate);
+ return BAD_VALUE;
+ }
+ mParameters.setPreviewFrameRate(framerate);
+ CAMHAL_LOGDB("Set frame rate %d", framerate);
+ fpsUpdated = true;
+ }
+
+ if (frameRangeUpdated) {
+ mParameters.set(TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE,
+ mParameters.get(android::CameraParameters::KEY_PREVIEW_FPS_RANGE));
+ } else if (fpsUpdated) {
+ char tmpBuffer[MAX_PROP_VALUE_LENGTH];
+ sprintf(tmpBuffer, "%d,%d", framerate * CameraHal::VFR_SCALE, framerate * CameraHal::VFR_SCALE);
+ mParameters.set(TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE, tmpBuffer);
+ }
+
+ if ((valstr = params.get(TICameraParameters::KEY_GBCE)) != NULL) {
+ if (strcmp(mCameraProperties->get(CameraProperties::SUPPORTED_GBCE),
+ android::CameraParameters::TRUE) == 0) {
+ CAMHAL_LOGDB("GBCE %s", valstr);
+ mParameters.set(TICameraParameters::KEY_GBCE, valstr);
+ } else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
+ CAMHAL_LOGEB("ERROR: Invalid GBCE: %s", valstr);
+ return BAD_VALUE;
+ } else {
+ mParameters.set(TICameraParameters::KEY_GBCE, android::CameraParameters::FALSE);
+ }
+ } else {
+ mParameters.set(TICameraParameters::KEY_GBCE, android::CameraParameters::FALSE);
+ }
+
+ if ((valstr = params.get(TICameraParameters::KEY_GLBCE)) != NULL) {
+ if (strcmp(mCameraProperties->get(CameraProperties::SUPPORTED_GLBCE),
+ android::CameraParameters::TRUE) == 0) {
+ CAMHAL_LOGDB("GLBCE %s", valstr);
+ mParameters.set(TICameraParameters::KEY_GLBCE, valstr);
+ } else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
+ CAMHAL_LOGEB("ERROR: Invalid GLBCE: %s", valstr);
+ return BAD_VALUE;
+ } else {
+ mParameters.set(TICameraParameters::KEY_GLBCE, android::CameraParameters::FALSE);
+ }
+ } else {
+ mParameters.set(TICameraParameters::KEY_GLBCE, android::CameraParameters::FALSE);
+ }
+
+#ifdef OMAP_ENHANCEMENT_S3D
+ ///Update the current parameter set
+ if ( (valstr = params.get(TICameraParameters::KEY_AUTOCONVERGENCE_MODE)) != NULL ) {
+ CAMHAL_LOGDB("AutoConvergence mode set = %s", valstr);
+ mParameters.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, valstr);
+ }
+
+ if ( (valstr = params.get(TICameraParameters::KEY_MANUAL_CONVERGENCE)) != NULL ) {
+ int manualConvergence = (int)strtol(valstr, 0, 0);
+
+ if ( ( manualConvergence < strtol(mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MIN), 0, 0) ) ||
+ ( manualConvergence > strtol(mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MAX), 0, 0) ) ) {
+ CAMHAL_LOGEB("ERROR: Invalid Manual Convergence = %d", manualConvergence);
+ return BAD_VALUE;
+ } else {
+ CAMHAL_LOGDB("ManualConvergence Value = %d", manualConvergence);
+ mParameters.set(TICameraParameters::KEY_MANUAL_CONVERGENCE, valstr);
+ }
+ }
+
+ if((valstr = params.get(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION)) != NULL) {
+ if ( strcmp(mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED),
+ android::CameraParameters::TRUE) == 0 ) {
+ CAMHAL_LOGDB("Mechanical Mialignment Correction is %s", valstr);
+ mParameters.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION, valstr);
+ } else {
+ mParameters.remove(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION);
+ }
+ }
+
+ if ((valstr = params.get(TICameraParameters::KEY_EXPOSURE_MODE)) != NULL) {
+ if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES))) {
+ CAMHAL_LOGDB("Exposure mode set = %s", valstr);
+ mParameters.set(TICameraParameters::KEY_EXPOSURE_MODE, valstr);
+ if (!strcmp(valstr, TICameraParameters::EXPOSURE_MODE_MANUAL)) {
+ int manualVal;
+ if ((valstr = params.get(TICameraParameters::KEY_MANUAL_EXPOSURE)) != NULL) {
+ manualVal = params.getInt(TICameraParameters::KEY_MANUAL_EXPOSURE);
+ if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN) ||
+ manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX)) {
+ CAMHAL_LOGEB("ERROR: Manual Exposure = %s is out of range - "
+ "setting minimum supported value", valstr);
+ valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN);
+ }
+ CAMHAL_LOGDB("Manual Exposure = %s", valstr);
+ mParameters.set(TICameraParameters::KEY_MANUAL_EXPOSURE, valstr);
+ }
+ if ((valstr = params.get(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT)) != NULL) {
+ manualVal = params.getInt(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT);
+ if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN) ||
+ manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX)) {
+ CAMHAL_LOGEB("ERROR: Manual Exposure right = %s is out of range - "
+ "setting minimum supported value", valstr);
+ valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN);
+ }
+ CAMHAL_LOGDB("Manual Exposure right = %s", valstr);
+ mParameters.set(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT, valstr);
+ }
+ if ((valstr = params.get(TICameraParameters::KEY_MANUAL_GAIN_ISO)) != NULL) {
+ manualVal = params.getInt(TICameraParameters::KEY_MANUAL_GAIN_ISO);
+ if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN) ||
+ manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX)) {
+ CAMHAL_LOGEB("ERROR: Manual Gain = %s is out of range - "
+ "setting minimum supported value", valstr);
+ valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN);
+ }
+ CAMHAL_LOGDB("Manual Gain = %s", valstr);
+ mParameters.set(TICameraParameters::KEY_MANUAL_GAIN_ISO, valstr);
+ }
+ if ((valstr = params.get(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT)) != NULL) {
+ manualVal = params.getInt(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT);
+ if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN) ||
+ manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX)) {
+ CAMHAL_LOGEB("ERROR: Manual Gain right = %s is out of range - "
+ "setting minimum supported value", valstr);
+ valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN);
+ }
+ CAMHAL_LOGDB("Manual Gain right = %s", valstr);
+ mParameters.set(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT, valstr);
+ }
+ }
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Exposure mode = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+#endif
+
+ if ((valstr = params.get(android::CameraParameters::KEY_WHITE_BALANCE)) != NULL) {
+ if ( isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE))) {
+ CAMHAL_LOGDB("White balance set %s", valstr);
+ mParameters.set(android::CameraParameters::KEY_WHITE_BALANCE, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid white balance = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ if ((valstr = params.get(TICameraParameters::KEY_CONTRAST)) != NULL) {
+ if (params.getInt(TICameraParameters::KEY_CONTRAST) >= 0 ) {
+ CAMHAL_LOGDB("Contrast set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_CONTRAST, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Contrast = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ if ((valstr =params.get(TICameraParameters::KEY_SHARPNESS)) != NULL) {
+ if (params.getInt(TICameraParameters::KEY_SHARPNESS) >= 0 ) {
+ CAMHAL_LOGDB("Sharpness set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_SHARPNESS, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Sharpness = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ if ((valstr = params.get(TICameraParameters::KEY_SATURATION)) != NULL) {
+ if (params.getInt(TICameraParameters::KEY_SATURATION) >= 0 ) {
+ CAMHAL_LOGDB("Saturation set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_SATURATION, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Saturation = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ if ((valstr = params.get(TICameraParameters::KEY_BRIGHTNESS)) != NULL) {
+ if (params.getInt(TICameraParameters::KEY_BRIGHTNESS) >= 0 ) {
+ CAMHAL_LOGDB("Brightness set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_BRIGHTNESS, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Brightness = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+#endif
+
+ if ((valstr = params.get(android::CameraParameters::KEY_ANTIBANDING)) != NULL) {
+ if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING))) {
+ CAMHAL_LOGDB("Antibanding set %s", valstr);
+ mParameters.set(android::CameraParameters::KEY_ANTIBANDING, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Antibanding = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ if ((valstr = params.get(TICameraParameters::KEY_ISO)) != NULL) {
+ if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES))) {
+ CAMHAL_LOGDB("ISO set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_ISO, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid ISO = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+#endif
+
+ if( (valstr = params.get(android::CameraParameters::KEY_FOCUS_AREAS)) != NULL )
+ {
+ CAMHAL_LOGDB("Focus areas position set %s", params.get(android::CameraParameters::KEY_FOCUS_AREAS));
+ mParameters.set(android::CameraParameters::KEY_FOCUS_AREAS, valstr);
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ if( (valstr = params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE)) != NULL )
+ {
+ CAMHAL_LOGDB("Measurements set to %s", valstr);
+ mParameters.set(TICameraParameters::KEY_MEASUREMENT_ENABLE, valstr);
+
+ if (strcmp(valstr, android::CameraParameters::TRUE) == 0)
+ {
+ mMeasurementEnabled = true;
+ }
+ else if (strcmp(valstr, android::CameraParameters::FALSE) == 0)
+ {
+ mMeasurementEnabled = false;
+ }
+ else
+ {
+ mMeasurementEnabled = false;
+ }
+
+ }
+#endif
+
+ if( (valstr = params.get(android::CameraParameters::KEY_EXPOSURE_COMPENSATION)) != NULL)
+ {
+ CAMHAL_LOGDB("Exposure compensation set %s", params.get(android::CameraParameters::KEY_EXPOSURE_COMPENSATION));
+ mParameters.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION, valstr);
+ }
+
+ if ((valstr = params.get(android::CameraParameters::KEY_SCENE_MODE)) != NULL) {
+ if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES))) {
+ CAMHAL_LOGDB("Scene mode set %s", valstr);
+ doesSetParameterNeedUpdate(valstr,
+ mParameters.get(android::CameraParameters::KEY_SCENE_MODE),
+ updateRequired);
+ mParameters.set(android::CameraParameters::KEY_SCENE_MODE, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Scene mode = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ if ((valstr = params.get(android::CameraParameters::KEY_FLASH_MODE)) != NULL) {
+ if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES))) {
+ CAMHAL_LOGDB("Flash mode set %s", valstr);
+ mParameters.set(android::CameraParameters::KEY_FLASH_MODE, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Flash mode = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ if ((valstr = params.get(android::CameraParameters::KEY_EFFECT)) != NULL) {
+ if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS))) {
+ CAMHAL_LOGDB("Effect set %s", valstr);
+ mParameters.set(android::CameraParameters::KEY_EFFECT, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Effect = %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ varint = params.getInt(android::CameraParameters::KEY_ROTATION);
+ if ( varint >= 0 ) {
+ CAMHAL_LOGDB("Rotation set %d", varint);
+ mParameters.set(android::CameraParameters::KEY_ROTATION, varint);
+ }
+
+ varint = params.getInt(android::CameraParameters::KEY_JPEG_QUALITY);
+ if ( varint >= 0 ) {
+ CAMHAL_LOGDB("Jpeg quality set %d", varint);
+ mParameters.set(android::CameraParameters::KEY_JPEG_QUALITY, varint);
+ }
+
+ varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ if ( varint >= 0 ) {
+ CAMHAL_LOGDB("Thumbnail width set %d", varint);
+ mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, varint);
+ }
+
+ varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ if ( varint >= 0 ) {
+ CAMHAL_LOGDB("Thumbnail width set %d", varint);
+ mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, varint);
+ }
+
+ varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ if ( varint >= 0 ) {
+ CAMHAL_LOGDB("Thumbnail quality set %d", varint);
+ mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, varint);
+ }
+
+ if( (valstr = params.get(android::CameraParameters::KEY_GPS_LATITUDE)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS latitude set %s", params.get(android::CameraParameters::KEY_GPS_LATITUDE));
+ mParameters.set(android::CameraParameters::KEY_GPS_LATITUDE, valstr);
+ }else{
+ mParameters.remove(android::CameraParameters::KEY_GPS_LATITUDE);
+ }
+
+ if( (valstr = params.get(android::CameraParameters::KEY_GPS_LONGITUDE)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS longitude set %s", params.get(android::CameraParameters::KEY_GPS_LONGITUDE));
+ mParameters.set(android::CameraParameters::KEY_GPS_LONGITUDE, valstr);
+ }else{
+ mParameters.remove(android::CameraParameters::KEY_GPS_LONGITUDE);
+ }
+
+ if( (valstr = params.get(android::CameraParameters::KEY_GPS_ALTITUDE)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS altitude set %s", params.get(android::CameraParameters::KEY_GPS_ALTITUDE));
+ mParameters.set(android::CameraParameters::KEY_GPS_ALTITUDE, valstr);
+ }else{
+ mParameters.remove(android::CameraParameters::KEY_GPS_ALTITUDE);
+ }
+
+ if( (valstr = params.get(android::CameraParameters::KEY_GPS_TIMESTAMP)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS timestamp set %s", params.get(android::CameraParameters::KEY_GPS_TIMESTAMP));
+ mParameters.set(android::CameraParameters::KEY_GPS_TIMESTAMP, valstr);
+ }else{
+ mParameters.remove(android::CameraParameters::KEY_GPS_TIMESTAMP);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_GPS_DATESTAMP)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS datestamp set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_GPS_DATESTAMP, valstr);
+ }else{
+ mParameters.remove(TICameraParameters::KEY_GPS_DATESTAMP);
+ }
+
+ if( (valstr = params.get(android::CameraParameters::KEY_GPS_PROCESSING_METHOD)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS processing method set %s", params.get(android::CameraParameters::KEY_GPS_PROCESSING_METHOD));
+ mParameters.set(android::CameraParameters::KEY_GPS_PROCESSING_METHOD, valstr);
+ }else{
+ mParameters.remove(android::CameraParameters::KEY_GPS_PROCESSING_METHOD);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_GPS_MAPDATUM )) != NULL )
+ {
+ CAMHAL_LOGDB("GPS MAPDATUM set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_GPS_MAPDATUM, valstr);
+ }else{
+ mParameters.remove(TICameraParameters::KEY_GPS_MAPDATUM);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_GPS_VERSION)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS MAPDATUM set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_GPS_VERSION, valstr);
+ }else{
+ mParameters.remove(TICameraParameters::KEY_GPS_VERSION);
+ }
+
+#ifndef MOTOROLA_CAMERA
+ if( (valstr = params.get(TICameraParameters::KEY_EXIF_MODEL)) != NULL )
+ {
+ CAMHAL_LOGDB("EXIF Model set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_EXIF_MODEL, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_EXIF_MAKE)) != NULL )
+ {
+ CAMHAL_LOGDB("EXIF Make set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_EXIF_MAKE, valstr);
+ }
+#else
+ if( (property_get("ro.product.model",value,0) > 0))
+ {
+ CAMHAL_LOGDB("EXIF Model set %s",value);
+ mParameters.set(TICameraParameters::KEY_EXIF_MODEL, value);
+ }
+
+ if( (property_get("ro.product.manufacturer",value,0) > 0) )
+ {
+ CAMHAL_LOGDB("EXIF Make set %s",value);
+ mParameters.set(TICameraParameters::KEY_EXIF_MAKE, value);
+ }
+
+ // enabled/disabled similar parameters:
+ // KEY_MOT_LEDFLASH // int: 0..100 percent
+ if((params.get(TICameraParameters::KEY_MOT_LEDFLASH) != NULL)
+ && (params.getInt(TICameraParameters::KEY_MOT_LEDFLASH) >=0)
+ && (params.getInt(TICameraParameters::KEY_MOT_LEDFLASH) <=100))
+ {
+ CAMHAL_LOGDB("Led Flash : %s",params.get(TICameraParameters::KEY_MOT_LEDFLASH));
+ mParameters.set(TICameraParameters::KEY_MOT_LEDFLASH,
+ params.get(TICameraParameters::KEY_MOT_LEDFLASH));
+ }
+
+ // KEY_MOT_LEDTORCH // int: 0..100 percent
+ if((params.get(TICameraParameters::KEY_MOT_LEDTORCH) != NULL)
+ && (params.getInt(TICameraParameters::KEY_MOT_LEDTORCH) >=0)
+ && (params.getInt(TICameraParameters::KEY_MOT_LEDTORCH) <=100))
+ {
+ CAMHAL_LOGDB("Led Torch : %s",params.get(TICameraParameters::KEY_MOT_LEDTORCH));
+ mParameters.set(TICameraParameters::KEY_MOT_LEDTORCH,
+ params.get(TICameraParameters::KEY_MOT_LEDTORCH));
+ }
+#endif
+
+#ifdef OMAP_ENHANCEMENT
+ if( (valstr = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE)) != NULL )
+ {
+ CAMHAL_LOGDB("Exposure Bracketing set %s", params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE));
+ mParameters.set(TICameraParameters::KEY_EXP_BRACKETING_RANGE, valstr);
+ mParameters.remove(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE);
+ }
+ else if ((valstr = params.get(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE)) != NULL) {
+ CAMHAL_LOGDB("ABS Exposure+Gain Bracketing set %s", params.get(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE));
+ mParameters.set(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE, valstr);
+ mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
+ } else
+ {
+ mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE)) != NULL ) {
+ CAMHAL_LOGDB("Zoom Bracketing range %s", valstr);
+ mParameters.set(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE, valstr);
+ } else {
+ mParameters.remove(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE);
+ }
+#endif
+
+ if ((valstr = params.get(android::CameraParameters::KEY_ZOOM)) != NULL ) {
+ varint = atoi(valstr);
+ if ( varint >= 0 && varint <= mMaxZoomSupported ) {
+ CAMHAL_LOGDB("Zoom set %d", varint);
+ doesSetParameterNeedUpdate(valstr,
+ mParameters.get(android::CameraParameters::KEY_ZOOM),
+ updateRequired);
+ mParameters.set(android::CameraParameters::KEY_ZOOM, valstr);
+ } else {
+ CAMHAL_LOGEB("ERROR: Invalid Zoom: %s", valstr);
+ return BAD_VALUE;
+ }
+ }
+
+ if( (valstr = params.get(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK)) != NULL )
+ {
+ CAMHAL_LOGDB("Auto Exposure Lock set %s", valstr);
+ doesSetParameterNeedUpdate(valstr,
+ mParameters.get(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK),
+ updateRequired);
+ mParameters.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK, valstr);
+ }
+
+ if( (valstr = params.get(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK)) != NULL )
+ {
+ CAMHAL_LOGDB("Auto WhiteBalance Lock set %s", valstr);
+ doesSetParameterNeedUpdate(valstr,
+ mParameters.get(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK),
+ updateRequired);
+ mParameters.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, valstr);
+ }
+ if( (valstr = params.get(android::CameraParameters::KEY_METERING_AREAS)) != NULL )
+ {
+ CAMHAL_LOGDB("Metering areas position set %s", params.get(android::CameraParameters::KEY_METERING_AREAS));
+ mParameters.set(android::CameraParameters::KEY_METERING_AREAS, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::RAW_WIDTH)) != NULL ) {
+ CAMHAL_LOGDB("Raw image width set %s", params.get(TICameraParameters::RAW_WIDTH));
+ mParameters.set(TICameraParameters::RAW_WIDTH, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::RAW_HEIGHT)) != NULL ) {
+ CAMHAL_LOGDB("Raw image height set %s", params.get(TICameraParameters::RAW_HEIGHT));
+ mParameters.set(TICameraParameters::RAW_HEIGHT, valstr);
+ }
+
+ //TI extensions for enable/disable algos
+ if( (valstr = params.get(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA)) != NULL )
+ {
+ CAMHAL_LOGDB("External Gamma set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_ALGO_NSF1)) != NULL )
+ {
+ CAMHAL_LOGDB("NSF1 set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_ALGO_NSF1, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_ALGO_NSF2)) != NULL )
+ {
+ CAMHAL_LOGDB("NSF2 set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_ALGO_NSF2, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_ALGO_SHARPENING)) != NULL )
+ {
+ CAMHAL_LOGDB("Sharpening set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_ALGO_SHARPENING, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_ALGO_THREELINCOLORMAP)) != NULL )
+ {
+ CAMHAL_LOGDB("Color Conversion set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_ALGO_THREELINCOLORMAP, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_ALGO_GIC)) != NULL )
+ {
+ CAMHAL_LOGDB("Green Inballance Correction set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_ALGO_GIC, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_GAMMA_TABLE)) != NULL )
+ {
+ CAMHAL_LOGDB("Manual gamma table set %s", valstr);
+ mParameters.set(TICameraParameters::KEY_GAMMA_TABLE, valstr);
+ }
+
+ android::CameraParameters adapterParams = mParameters;
+
+#ifdef OMAP_ENHANCEMENT
+ if( NULL != params.get(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_POS) )
+ {
+ int posBracketRange = params.getInt(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_POS);
+ if ( 0 < posBracketRange )
+ {
+ mBracketRangePositive = posBracketRange;
+ }
+ }
+ CAMHAL_LOGDB("Positive bracketing range %d", mBracketRangePositive);
+
+
+ if( NULL != params.get(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_NEG) )
+ {
+ int negBracketRange = params.getInt(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_NEG);
+ if ( 0 < negBracketRange )
+ {
+ mBracketRangeNegative = negBracketRange;
+ }
+ }
+ CAMHAL_LOGDB("Negative bracketing range %d", mBracketRangeNegative);
+
+ if( ( (valstr = params.get(TICameraParameters::KEY_TEMP_BRACKETING)) != NULL) &&
+ ( strcmp(valstr, android::CameraParameters::TRUE) == 0 )) {
+ if ( !mBracketingEnabled ) {
+ CAMHAL_LOGDA("Enabling bracketing");
+ mBracketingEnabled = true;
+ } else {
+ CAMHAL_LOGDA("Bracketing already enabled");
+ }
+ adapterParams.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr);
+ mParameters.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr);
+ } else if ( ( (valstr = params.get(TICameraParameters::KEY_TEMP_BRACKETING)) != NULL ) &&
+ ( strcmp(valstr, android::CameraParameters::FALSE) == 0 )) {
+ CAMHAL_LOGDA("Disabling bracketing");
+
+ adapterParams.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr);
+ mParameters.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr);
+ mBracketingEnabled = false;
+ if ( mBracketingRunning ) {
+ stopImageBracketing();
+ }
+
+ } else {
+ adapterParams.remove(TICameraParameters::KEY_TEMP_BRACKETING);
+ mParameters.remove(TICameraParameters::KEY_TEMP_BRACKETING);
+ }
+#endif
+
+#ifdef OMAP_ENHANCEMENT_VTC
+ if (mVTCUseCase && !mTunnelSetup && (mCameraAdapter != NULL) &&
+ ((mParameters.get(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE)) != NULL )&&
+ ((mParameters.get(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT)) != NULL )) {
+
+ uint32_t sliceHeight = mParameters.getInt(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT);
+ uint32_t encoderHandle = mParameters.getInt(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE);
+ int w, h;
+ mParameters.getPreviewSize(&w, &h);
+ status_t done = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SETUP_TUNNEL, sliceHeight, encoderHandle, w, h);
+ if (done == NO_ERROR) mTunnelSetup = true;
+ ret |= done;
+ }
+#endif
+
+ // Only send parameters to adapter if preview is already
+ // enabled or doesSetParameterNeedUpdate says so. Initial setParameters to camera adapter,
+ // will be called in startPreview()
+ // TODO(XXX): Need to identify other parameters that need update from camera adapter
+ if ( (NULL != mCameraAdapter) &&
+ (mPreviewEnabled || updateRequired) &&
+ (!(mPreviewEnabled && restartPreviewRequired)) ) {
+ ret |= mCameraAdapter->setParameters(adapterParams);
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ if( ( (valstr = params.get(TICameraParameters::KEY_SHUTTER_ENABLE)) != NULL ) &&
+ ( strcmp(valstr, android::CameraParameters::TRUE) == 0 ))
+ {
+ CAMHAL_LOGDA("Enabling shutter sound");
+
+ mShutterEnabled = true;
+ mMsgEnabled |= CAMERA_MSG_SHUTTER;
+ mParameters.set(TICameraParameters::KEY_SHUTTER_ENABLE, valstr);
+ }
+ else if ( ( (valstr = params.get(TICameraParameters::KEY_SHUTTER_ENABLE)) != NULL ) &&
+ ( strcmp(valstr, android::CameraParameters::FALSE) == 0 ))
+ {
+ CAMHAL_LOGDA("Disabling shutter sound");
+
+ mShutterEnabled = false;
+ mMsgEnabled &= ~CAMERA_MSG_SHUTTER;
+ mParameters.set(TICameraParameters::KEY_SHUTTER_ENABLE, valstr);
+ }
+#endif
+ }
+
+ //On fail restore old parameters
+ if ( NO_ERROR != ret ) {
+ mParameters = oldParams;
+ }
+
+ // Restart Preview if needed by KEY_RECODING_HINT only if preview is already running.
+ // If preview is not started yet, Video Mode parameters will take effect on next startPreview()
+ if (restartPreviewRequired && previewEnabled() && !mRecordingEnabled) {
+ CAMHAL_LOGDA("Restarting Preview");
+ ret = restartPreview();
+ } else if (restartPreviewRequired && !previewEnabled() &&
+ mDisplayPaused && !mRecordingEnabled) {
+ CAMHAL_LOGDA("Restarting preview in paused mode");
+ ret = restartPreview();
+
+ // TODO(XXX): If there is some delay between the restartPreview call and the code
+ // below, then the user could see some preview frames and callbacks. Let's find
+ // a better place to put this later...
+ if (ret == NO_ERROR) {
+ mDisplayPaused = true;
+ mPreviewEnabled = false;
+ ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);
+ }
+ }
+
+ if ( !mBracketingRunning && mBracketingEnabled ) {
+ startImageBracketing();
+ }
+
+ if (ret != NO_ERROR)
+ {
+ CAMHAL_LOGEA("Failed to restart Preview");
+ return ret;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::allocPreviewBufs(int width, int height, const char* previewFormat,
+ unsigned int buffercount, unsigned int &max_queueable)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if(mDisplayAdapter.get() == NULL)
+ {
+ // Memory allocation of preview buffers is now placed in gralloc
+ // CameraHal should not allocate preview buffers without DisplayAdapter
+ return NO_MEMORY;
+ }
+
+ if(!mPreviewBuffers)
+ {
+ mPreviewLength = 0;
+ mPreviewBuffers = mDisplayAdapter->allocateBufferList(width, height,
+ previewFormat,
+ mPreviewLength,
+ buffercount);
+ if (NULL == mPreviewBuffers ) {
+ CAMHAL_LOGEA("Couldn't allocate preview buffers");
+ return NO_MEMORY;
+ }
+
+ mPreviewOffsets = (uint32_t *) mDisplayAdapter->getOffsets();
+ if ( NULL == mPreviewOffsets ) {
+ CAMHAL_LOGEA("Buffer mapping failed");
+ return BAD_VALUE;
+ }
+
+ mBufProvider = (BufferProvider*) mDisplayAdapter.get();
+
+ ret = mDisplayAdapter->maxQueueableBuffers(max_queueable);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::freePreviewBufs()
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ CAMHAL_LOGDB("mPreviewBuffers = %p", mPreviewBuffers);
+ if(mPreviewBuffers)
+ {
+ ret = mBufProvider->freeBufferList(mPreviewBuffers);
+ mPreviewBuffers = NULL;
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+
+status_t CameraHal::allocPreviewDataBufs(size_t size, size_t bufferCount)
+{
+ status_t ret = NO_ERROR;
+ int bytes;
+
+ LOG_FUNCTION_NAME;
+
+ bytes = size;
+
+ if ( NO_ERROR == ret )
+ {
+ if( NULL != mPreviewDataBuffers )
+ {
+ ret = freePreviewDataBufs();
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ bytes = ((bytes+4095)/4096)*4096;
+ mPreviewDataBuffers = mMemoryManager->allocateBufferList(0, 0, NULL, bytes, bufferCount);
+
+ CAMHAL_LOGDB("Size of Preview data buffer = %d", bytes);
+ if( NULL == mPreviewDataBuffers )
+ {
+ CAMHAL_LOGEA("Couldn't allocate image buffers using memory manager");
+ ret = -NO_MEMORY;
+ }
+ else
+ {
+ bytes = size;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mPreviewDataFd = mMemoryManager->getFd();
+ mPreviewDataLength = bytes;
+ mPreviewDataOffsets = mMemoryManager->getOffsets();
+ }
+ else
+ {
+ mPreviewDataFd = -1;
+ mPreviewDataLength = 0;
+ mPreviewDataOffsets = NULL;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::freePreviewDataBufs()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+
+ if( NULL != mPreviewDataBuffers )
+ {
+
+ ret = mMemoryManager->freeBufferList(mPreviewDataBuffers);
+ mPreviewDataBuffers = NULL;
+
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::allocImageBufs(unsigned int width, unsigned int height, size_t size,
+ const char* previewFormat, unsigned int bufferCount)
+{
+ status_t ret = NO_ERROR;
+ int bytes = size;
+
+ LOG_FUNCTION_NAME;
+
+ // allocate image buffers only if not already allocated
+ if(NULL != mImageBuffers) {
+ return NO_ERROR;
+ }
+
+ if ( NO_ERROR == ret ) {
+ bytes = ((bytes+4095)/4096)*4096;
+ mImageBuffers = mMemoryManager->allocateBufferList(0, 0, previewFormat, bytes, bufferCount);
+ CAMHAL_LOGDB("Size of Image cap buffer = %d", bytes);
+ if( NULL == mImageBuffers ) {
+ CAMHAL_LOGEA("Couldn't allocate image buffers using memory manager");
+ ret = -NO_MEMORY;
+ } else {
+ bytes = size;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ mImageFd = mMemoryManager->getFd();
+ mImageLength = bytes;
+ mImageOffsets = mMemoryManager->getOffsets();
+ mImageCount = bufferCount;
+ } else {
+ mImageFd = -1;
+ mImageLength = 0;
+ mImageOffsets = NULL;
+ mImageCount = 0;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::allocVideoBufs(uint32_t width, uint32_t height, uint32_t bufferCount)
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ if( NULL != mVideoBuffers ){
+ ret = freeVideoBufs(mVideoBuffers);
+ mVideoBuffers = NULL;
+ }
+
+ if ( NO_ERROR == ret ){
+ int32_t stride;
+ CameraBuffer *buffers = new CameraBuffer [bufferCount];
+
+ memset (buffers, 0, sizeof(CameraBuffer) * bufferCount);
+
+ if (buffers != NULL){
+ for (unsigned int i = 0; i< bufferCount; i++){
+ android::GraphicBufferAllocator &GrallocAlloc = android::GraphicBufferAllocator::get();
+ buffer_handle_t handle;
+ ret = GrallocAlloc.alloc(width, height, HAL_PIXEL_FORMAT_NV12, CAMHAL_GRALLOC_USAGE, &handle, &stride);
+ if (ret != NO_ERROR){
+ CAMHAL_LOGEA("Couldn't allocate video buffers using Gralloc");
+ ret = -NO_MEMORY;
+ for (unsigned int j=0; j< i; j++){
+ CAMHAL_LOGEB("Freeing Gralloc Buffer %p", buffers[i].opaque);
+ GrallocAlloc.free((buffer_handle_t)buffers[i].opaque);
+ }
+ delete [] buffers;
+ goto exit;
+ }
+ buffers[i].type = CAMERA_BUFFER_GRALLOC;
+ buffers[i].opaque = (void *)handle;
+ CAMHAL_LOGVB("*** Gralloc Handle =0x%x ***", handle);
+ }
+
+ mVideoBuffers = buffers;
+ }
+ else{
+ CAMHAL_LOGEA("Couldn't allocate video buffers ");
+ ret = -NO_MEMORY;
+ }
+ }
+
+ exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::allocRawBufs(int width, int height, const char* previewFormat, int bufferCount)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME
+
+
+ ///@todo Enhance this method allocImageBufs() to take in a flag for burst capture
+ ///Always allocate the buffers for image capture using MemoryManager
+ if (NO_ERROR == ret) {
+ if(( NULL != mVideoBuffers )) {
+ // Re-use the buffer for raw capture.
+ return ret;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ mVideoLength = 0;
+ mVideoLength = (((width * height * 2) + 4095)/4096)*4096;
+ mVideoBuffers = mMemoryManager->allocateBufferList(width, height, previewFormat,
+ mVideoLength, bufferCount);
+
+ CAMHAL_LOGDB("Size of Video cap buffer (used for RAW capture) %d", mVideoLength);
+ if( NULL == mVideoBuffers ) {
+ CAMHAL_LOGEA("Couldn't allocate Video buffers using memory manager");
+ ret = -NO_MEMORY;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ mVideoFd = mMemoryManager->getFd();
+ mVideoOffsets = mMemoryManager->getOffsets();
+ } else {
+ mVideoFd = -1;
+ mVideoOffsets = NULL;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+void endImageCapture( void *userData)
+{
+ LOG_FUNCTION_NAME;
+
+ if ( NULL != userData )
+ {
+ CameraHal *c = reinterpret_cast<CameraHal *>(userData);
+ c->signalEndImageCapture();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void releaseImageBuffers(void *userData)
+{
+ LOG_FUNCTION_NAME;
+
+ if (NULL != userData) {
+ CameraHal *c = reinterpret_cast<CameraHal *>(userData);
+ c->freeImageBufs();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t CameraHal::signalEndImageCapture()
+{
+ status_t ret = NO_ERROR;
+ int w,h;
+ android::AutoMutex lock(mLock);
+
+ LOG_FUNCTION_NAME;
+
+ if (mBufferSourceAdapter_Out.get()) {
+ mBufferSourceAdapter_Out->disableDisplay();
+ }
+
+ if (mBufferSourceAdapter_In.get()) {
+ mBufferSourceAdapter_In->disableDisplay();
+ }
+
+ if ( mBracketingRunning ) {
+ stopImageBracketing();
+ } else {
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::freeImageBufs()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if (NULL == mImageBuffers) {
+ return -EINVAL;
+ }
+
+ if (mBufferSourceAdapter_Out.get()) {
+ mBufferSourceAdapter_Out = 0;
+ } else {
+ ret = mMemoryManager->freeBufferList(mImageBuffers);
+ }
+
+ mImageBuffers = NULL;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::freeVideoBufs(CameraBuffer *bufs)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ int count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
+ if(bufs == NULL)
+ {
+ CAMHAL_LOGEA("NULL pointer passed to freeVideoBuffer");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ android::GraphicBufferAllocator &GrallocAlloc = android::GraphicBufferAllocator::get();
+
+ for(int i = 0; i < count; i++){
+ CAMHAL_LOGVB("Free Video Gralloc Handle 0x%x", bufs[i].opaque);
+ GrallocAlloc.free((buffer_handle_t)bufs[i].opaque);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::freeRawBufs()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME
+
+ if ( NO_ERROR == ret ) {
+ if( NULL != mVideoBuffers ) {
+ ///@todo Pluralise the name of this method to freeBuffers
+ ret = mMemoryManager->freeBufferList(mVideoBuffers);
+ mVideoBuffers = NULL;
+ } else {
+ ret = -EINVAL;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return ret;
+}
+
+/**
+ @brief Start preview mode.
+
+ @param none
+ @return NO_ERROR Camera switched to VF mode
+ @todo Update function header with the different errors that are possible
+
+ */
+status_t CameraHal::startPreview() {
+ LOG_FUNCTION_NAME;
+
+ // When tunneling is enabled during VTC, startPreview happens in 2 steps:
+ // When the application sends the command CAMERA_CMD_PREVIEW_INITIALIZATION,
+ // cameraPreviewInitialization() is called, which in turn causes the CameraAdapter
+ // to move from loaded to idle state. And when the application calls startPreview,
+ // the CameraAdapter moves from idle to executing state.
+ //
+ // If the application calls startPreview() without sending the command
+ // CAMERA_CMD_PREVIEW_INITIALIZATION, then the function cameraPreviewInitialization()
+ // AND startPreview() are executed. In other words, if the application calls
+ // startPreview() without sending the command CAMERA_CMD_PREVIEW_INITIALIZATION,
+ // then the CameraAdapter moves from loaded to idle to executing state in one shot.
+ status_t ret = cameraPreviewInitialization();
+
+ // The flag mPreviewInitializationDone is set to true at the end of the function
+ // cameraPreviewInitialization(). Therefore, if everything goes alright, then the
+ // flag will be set. Sometimes, the function cameraPreviewInitialization() may
+ // return prematurely if all the resources are not available for starting preview.
+ // For example, if the preview window is not set, then it would return NO_ERROR.
+ // Under such circumstances, one should return from startPreview as well and should
+ // not continue execution. That is why, we check the flag and not the return value.
+ if (!mPreviewInitializationDone) return ret;
+
+ // Once startPreview is called, there is no need to continue to remember whether
+ // the function cameraPreviewInitialization() was called earlier or not. And so
+ // the flag mPreviewInitializationDone is reset here. Plus, this preserves the
+ // current behavior of startPreview under the circumstances where the application
+ // calls startPreview twice or more.
+ mPreviewInitializationDone = false;
+
+ ///Enable the display adapter if present, actual overlay enable happens when we post the buffer
+ if(mDisplayAdapter.get() != NULL) {
+ CAMHAL_LOGDA("Enabling display");
+ int width, height;
+ mParameters.getPreviewSize(&width, &height);
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview);
+#else
+ ret = mDisplayAdapter->enableDisplay(width, height, NULL);
+#endif
+
+ if ( ret != NO_ERROR ) {
+ CAMHAL_LOGEA("Couldn't enable display");
+
+ // FIXME: At this stage mStateSwitchLock is locked and unlock is supposed to be called
+ // only from mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW)
+ // below. But this will never happen because of goto error. Thus at next
+ // startPreview() call CameraHAL will be deadlocked.
+ // Need to revisit mStateSwitch lock, for now just abort the process.
+ CAMHAL_ASSERT_X(false,
+ "At this stage mCameraAdapter->mStateSwitchLock is still locked, "
+ "deadlock is guaranteed");
+
+ goto error;
+ }
+
+ }
+
+ ///Send START_PREVIEW command to adapter
+ CAMHAL_LOGDA("Starting CameraAdapter preview mode");
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW);
+
+ if(ret!=NO_ERROR) {
+ CAMHAL_LOGEA("Couldn't start preview w/ CameraAdapter");
+ goto error;
+ }
+ CAMHAL_LOGDA("Started preview");
+
+ mPreviewEnabled = true;
+ mPreviewStartInProgress = false;
+ return ret;
+
+ error:
+
+ CAMHAL_LOGEA("Performing cleanup after error");
+
+ //Do all the cleanup
+ freePreviewBufs();
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
+ if(mDisplayAdapter.get() != NULL) {
+ mDisplayAdapter->disableDisplay(false);
+ }
+ mAppCallbackNotifier->stop();
+ mPreviewStartInProgress = false;
+ mPreviewEnabled = false;
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+////////////
+/**
+ @brief Set preview mode related initialization
+ -> Camera Adapter set params
+ -> Allocate buffers
+ -> Set use buffers for preview
+ @param none
+ @return NO_ERROR
+ @todo Update function header with the different errors that are possible
+
+ */
+status_t CameraHal::cameraPreviewInitialization()
+{
+
+ status_t ret = NO_ERROR;
+ CameraAdapter::BuffersDescriptor desc;
+ CameraFrame frame;
+ unsigned int required_buffer_count;
+ unsigned int max_queueble_buffers;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ gettimeofday(&mStartPreview, NULL);
+#endif
+
+ LOG_FUNCTION_NAME;
+
+ if (mPreviewInitializationDone) {
+ return NO_ERROR;
+ }
+
+ if ( mPreviewEnabled ){
+ CAMHAL_LOGDA("Preview already running");
+ LOG_FUNCTION_NAME_EXIT;
+ return ALREADY_EXISTS;
+ }
+
+ if ( NULL != mCameraAdapter ) {
+ ret = mCameraAdapter->setParameters(mParameters);
+ }
+
+ if ((mPreviewStartInProgress == false) && (mDisplayPaused == false)){
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,( int ) &frame);
+ if ( NO_ERROR != ret ){
+ CAMHAL_LOGEB("Error: CAMERA_QUERY_RESOLUTION_PREVIEW %d", ret);
+ return ret;
+ }
+
+ ///Update the current preview width and height
+ mPreviewWidth = frame.mWidth;
+ mPreviewHeight = frame.mHeight;
+ }
+
+ ///If we don't have the preview callback enabled and display adapter,
+ if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL)){
+ CAMHAL_LOGD("Preview not started. Preview in progress flag set");
+ mPreviewStartInProgress = true;
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING);
+ if ( NO_ERROR != ret ){
+ CAMHAL_LOGEB("Error: CAMERA_SWITCH_TO_EXECUTING %d", ret);
+ return ret;
+ }
+ return NO_ERROR;
+ }
+
+ if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) )
+ {
+ CAMHAL_LOGDA("Preview is in paused state");
+
+ mDisplayPaused = false;
+ mPreviewEnabled = true;
+ if ( NO_ERROR == ret )
+ {
+ ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Display adapter resume failed %x", ret);
+ }
+ }
+ //restart preview callbacks
+ if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+ {
+ mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);
+ }
+
+ signalEndImageCapture();
+ return ret;
+ }
+
+ required_buffer_count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
+
+ ///Allocate the preview buffers
+ ret = allocPreviewBufs(mPreviewWidth, mPreviewHeight, mParameters.getPreviewFormat(), required_buffer_count, max_queueble_buffers);
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEA("Couldn't allocate buffers for Preview");
+ goto error;
+ }
+
+ if ( mMeasurementEnabled )
+ {
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA,
+ ( int ) &frame,
+ required_buffer_count);
+ if ( NO_ERROR != ret )
+ {
+ return ret;
+ }
+
+ ///Allocate the preview data buffers
+ ret = allocPreviewDataBufs(frame.mLength, required_buffer_count);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEA("Couldn't allocate preview data buffers");
+ goto error;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ desc.mBuffers = mPreviewDataBuffers;
+ desc.mOffsets = mPreviewDataOffsets;
+ desc.mFd = mPreviewDataFd;
+ desc.mLength = mPreviewDataLength;
+ desc.mCount = ( size_t ) required_buffer_count;
+ desc.mMaxQueueable = (size_t) required_buffer_count;
+
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA,
+ ( int ) &desc);
+ }
+
+ }
+
+ ///Pass the buffers to Camera Adapter
+ desc.mBuffers = mPreviewBuffers;
+ desc.mOffsets = mPreviewOffsets;
+ desc.mFd = mPreviewFd;
+ desc.mLength = mPreviewLength;
+ desc.mCount = ( size_t ) required_buffer_count;
+ desc.mMaxQueueable = (size_t) max_queueble_buffers;
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW,
+ ( int ) &desc);
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Failed to register preview buffers: 0x%x", ret);
+ freePreviewBufs();
+ return ret;
+ }
+
+ ///Start the callback notifier
+ ret = mAppCallbackNotifier->start();
+
+ if( ALREADY_EXISTS == ret )
+ {
+ //Already running, do nothing
+ CAMHAL_LOGDA("AppCallbackNotifier already running");
+ ret = NO_ERROR;
+ }
+ else if ( NO_ERROR == ret ) {
+ CAMHAL_LOGDA("Started AppCallbackNotifier..");
+ mAppCallbackNotifier->setMeasurements(mMeasurementEnabled);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Couldn't start AppCallbackNotifier");
+ goto error;
+ }
+
+ if (ret == NO_ERROR) mPreviewInitializationDone = true;
+
+ mAppCallbackNotifier->startPreviewCallbacks(mParameters, mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, required_buffer_count);
+
+ return ret;
+
+ error:
+
+ CAMHAL_LOGEA("Performing cleanup after error");
+
+ //Do all the cleanup
+ freePreviewBufs();
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
+ if(mDisplayAdapter.get() != NULL)
+ {
+ mDisplayAdapter->disableDisplay(false);
+ }
+ mAppCallbackNotifier->stop();
+ mPreviewStartInProgress = false;
+ mPreviewEnabled = false;
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/**
+ @brief Sets ANativeWindow object.
+
+ Preview buffers provided to CameraHal via this object. DisplayAdapter will be interfacing with it
+ to render buffers to display.
+
+ @param[in] window The ANativeWindow object created by Surface flinger
+ @return NO_ERROR If the ANativeWindow object passes validation criteria
+ @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
+
+ */
+status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window)
+{
+ status_t ret = NO_ERROR;
+ CameraAdapter::BuffersDescriptor desc;
+
+ LOG_FUNCTION_NAME;
+ mSetPreviewWindowCalled = true;
+
+ ///If the Camera service passes a null window, we destroy existing window and free the DisplayAdapter
+ if(!window)
+ {
+ if(mDisplayAdapter.get() != NULL)
+ {
+ ///NULL window passed, destroy the display adapter if present
+ CAMHAL_LOGD("NULL window passed, destroying display adapter");
+ mDisplayAdapter.clear();
+ ///@remarks If there was a window previously existing, we usually expect another valid window to be passed by the client
+ ///@remarks so, we will wait until it passes a valid window to begin the preview again
+ mSetPreviewWindowCalled = false;
+ }
+ CAMHAL_LOGD("NULL ANativeWindow passed to setPreviewWindow");
+ return NO_ERROR;
+ }else if(mDisplayAdapter.get() == NULL)
+ {
+ // Need to create the display adapter since it has not been created
+ // Create display adapter
+ ANativeWindowDisplayAdapter* displayAdapter = new ANativeWindowDisplayAdapter();
+ displayAdapter->setExternalLocking(mExternalLocking);
+ if (NULL != mAppCallbackNotifier.get()) {
+ mAppCallbackNotifier->setExternalLocking(mExternalLocking);
+ } else {
+ CAMHAL_LOGE("Can't apply locking policy on AppCallbackNotifier");
+ CAMHAL_ASSERT(0);
+ }
+ mDisplayAdapter = displayAdapter;
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ mDisplayAdapter->setExtendedOps(mExtendedPreviewStreamOps);
+#endif
+ ret = NO_ERROR;
+ if(!mDisplayAdapter.get() || ((ret=mDisplayAdapter->initialize())!=NO_ERROR))
+ {
+ if(ret!=NO_ERROR)
+ {
+ mDisplayAdapter.clear();
+ CAMHAL_LOGEA("DisplayAdapter initialize failed");
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+ else
+ {
+ CAMHAL_LOGEA("Couldn't create DisplayAdapter");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_MEMORY;
+ }
+ }
+
+ // DisplayAdapter needs to know where to get the CameraFrames from inorder to display
+ // Since CameraAdapter is the one that provides the frames, set it as the frame provider for DisplayAdapter
+ mDisplayAdapter->setFrameProvider(mCameraAdapter);
+
+ // Any dynamic errors that happen during the camera use case has to be propagated back to the application
+ // via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application
+ // Set it as the error handler for the DisplayAdapter
+ mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get());
+
+ // Update the display adapter with the new window that is passed from CameraService
+ ret = mDisplayAdapter->setPreviewWindow(window);
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret);
+ }
+
+ if(mPreviewStartInProgress)
+ {
+ CAMHAL_LOGDA("setPreviewWindow called when preview running");
+ // Start the preview since the window is now available
+ ret = startPreview();
+ }
+ } else {
+ // Update the display adapter with the new window that is passed from CameraService
+ ret = mDisplayAdapter->setPreviewWindow(window);
+ if ( (NO_ERROR == ret) && previewEnabled() ) {
+ restartPreview();
+ } else if (ret == ALREADY_EXISTS) {
+ // ALREADY_EXISTS should be treated as a noop in this case
+ ret = NO_ERROR;
+ }
+ }
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+
+}
+
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+void CameraHal::setExtendedPreviewStreamOps(preview_stream_extended_ops_t *ops)
+{
+ mExtendedPreviewStreamOps = ops;
+}
+
+/**
+ @brief Sets Tapout Surfaces.
+
+ Buffers provided to CameraHal via this object for tap-out
+ functionality.
+
+ @param[in] window The ANativeWindow object created by Surface flinger
+ @return NO_ERROR If the ANativeWindow object passes validation criteria
+ @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
+
+ */
+status_t CameraHal::setTapoutLocked(struct preview_stream_ops *tapout)
+{
+ status_t ret = NO_ERROR;
+ int index = -1;
+
+ LOG_FUNCTION_NAME;
+
+ if (!tapout) {
+ CAMHAL_LOGD("Missing argument");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+ }
+
+ // Set tapout point
+ // 1. Check name of tap-out
+ // 2. If not already set, then create a new one
+ // 3. Allocate buffers. If user is re-setting the surface, free buffers first and re-allocate
+ // in case dimensions have changed
+
+ for (unsigned int i = 0; i < mOutAdapters.size(); i++) {
+ android::sp<DisplayAdapter> out;
+ out = mOutAdapters.itemAt(i);
+ ret = out->setPreviewWindow(tapout);
+ if (ret == ALREADY_EXISTS) {
+ CAMHAL_LOGD("Tap Out already set at index = %d", i);
+ index = i;
+ ret = NO_ERROR;
+ }
+ }
+
+ if (index < 0) {
+ android::sp<DisplayAdapter> out = new BufferSourceAdapter();
+
+ ret = out->initialize();
+ if (ret != NO_ERROR) {
+ out.clear();
+ CAMHAL_LOGEA("DisplayAdapter initialize failed");
+ goto exit;
+ }
+
+ // BufferSourceAdapter will be handler of the extended OPS
+ out->setExtendedOps(mExtendedPreviewStreamOps);
+
+ // CameraAdapter will be the frame provider for BufferSourceAdapter
+ out->setFrameProvider(mCameraAdapter);
+
+ // BufferSourceAdapter will use ErrorHandler to send errors back to
+ // the application
+ out->setErrorHandler(mAppCallbackNotifier.get());
+
+ // Update the display adapter with the new window that is passed from CameraService
+ ret = out->setPreviewWindow(tapout);
+ if(ret != NO_ERROR) {
+ CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret);
+ goto exit;
+ }
+
+ if (NULL != mCameraAdapter) {
+ unsigned int bufferCount, max_queueable;
+ CameraFrame frame;
+
+ bufferCount = out->getBufferCount();
+ if (bufferCount < 1) bufferCount = NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP;
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE,
+ ( int ) &frame,
+ bufferCount);
+ if (NO_ERROR != ret) {
+ CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret);
+ }
+ if (NO_ERROR == ret) {
+ CameraBuffer *bufs = NULL;
+ unsigned int stride;
+ unsigned int height = frame.mHeight;
+ int size = frame.mLength;
+
+ stride = frame.mAlignment / getBPP(mParameters.getPictureFormat());
+ bufs = out->allocateBufferList(stride,
+ height,
+ mParameters.getPictureFormat(),
+ size,
+ bufferCount);
+ if (bufs == NULL){
+ CAMHAL_LOGEB("error allocating buffer list");
+ goto exit;
+ }
+ }
+ }
+ mOutAdapters.add(out);
+ }
+
+exit:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/**
+ @brief Releases Tapout Surfaces.
+
+ @param[in] window The ANativeWindow object created by Surface flinger
+ @return NO_ERROR If the ANativeWindow object passes validation criteria
+ @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
+
+ */
+status_t CameraHal::releaseTapoutLocked(struct preview_stream_ops *tapout)
+{
+ status_t ret = NO_ERROR;
+ char id[OP_STR_SIZE];
+
+ LOG_FUNCTION_NAME;
+
+ if (!tapout) {
+ CAMHAL_LOGD("Missing argument");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+ }
+
+ // Get the name of tapout
+ ret = mExtendedPreviewStreamOps->get_id(tapout, id, sizeof(id));
+ if (NO_ERROR != ret) {
+ CAMHAL_LOGEB("get_id OPS returned error %d", ret);
+ return ret;
+ }
+
+ // 1. Check name of tap-out
+ // 2. If exist, then free buffers and then remove it
+ if (mBufferSourceAdapter_Out.get() && mBufferSourceAdapter_Out->match(id)) {
+ CAMHAL_LOGD("REMOVE tap out %p previously set as current", tapout);
+ mBufferSourceAdapter_Out.clear();
+ }
+ for (unsigned int i = 0; i < mOutAdapters.size(); i++) {
+ android::sp<DisplayAdapter> out;
+ out = mOutAdapters.itemAt(i);
+ if (out->match(id)) {
+ CAMHAL_LOGD("REMOVE tap out %p \"%s\" at position %d", tapout, id, i);
+ mOutAdapters.removeAt(i);
+ break;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/**
+ @brief Sets Tapin Surfaces.
+
+ Buffers provided to CameraHal via this object for tap-in
+ functionality.
+
+ @param[in] window The ANativeWindow object created by Surface flinger
+ @return NO_ERROR If the ANativeWindow object passes validation criteria
+ @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
+
+ */
+status_t CameraHal::setTapinLocked(struct preview_stream_ops *tapin)
+{
+ status_t ret = NO_ERROR;
+ int index = -1;
+
+ LOG_FUNCTION_NAME;
+
+ if (!tapin) {
+ CAMHAL_LOGD("Missing argument");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+ }
+
+ // 1. Set tapin point
+ // 1. Check name of tap-in
+ // 2. If not already set, then create a new one
+ // 3. Allocate buffers. If user is re-setting the surface, free buffers first and re-allocate
+ // in case dimensions have changed
+ for (unsigned int i = 0; i < mInAdapters.size(); i++) {
+ android::sp<DisplayAdapter> in;
+ in = mInAdapters.itemAt(i);
+ ret = in->setPreviewWindow(tapin);
+ if (ret == ALREADY_EXISTS) {
+ CAMHAL_LOGD("Tap In already set at index = %d", i);
+ index = i;
+ ret = NO_ERROR;
+ }
+ }
+
+ if (index < 0) {
+ android::sp<DisplayAdapter> in = new BufferSourceAdapter();
+
+ ret = in->initialize();
+ if (ret != NO_ERROR) {
+ in.clear();
+ CAMHAL_LOGEA("DisplayAdapter initialize failed");
+ goto exit;
+ }
+
+ // BufferSourceAdapter will be handler of the extended OPS
+ in->setExtendedOps(mExtendedPreviewStreamOps);
+
+ // CameraAdapter will be the frame provider for BufferSourceAdapter
+ in->setFrameProvider(mCameraAdapter);
+
+ // BufferSourceAdapter will use ErrorHandler to send errors back to
+ // the application
+ in->setErrorHandler(mAppCallbackNotifier.get());
+
+ // Update the display adapter with the new window that is passed from CameraService
+ ret = in->setPreviewWindow(tapin);
+ if(ret != NO_ERROR) {
+ CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret);
+ goto exit;
+ }
+
+ mInAdapters.add(in);
+ }
+
+exit:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+
+/**
+ @brief Releases Tapin Surfaces.
+
+ @param[in] window The ANativeWindow object created by Surface flinger
+ @return NO_ERROR If the ANativeWindow object passes validation criteria
+ @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
+
+ */
+status_t CameraHal::releaseTapinLocked(struct preview_stream_ops *tapin)
+{
+ status_t ret = NO_ERROR;
+ char id[OP_STR_SIZE];
+
+ LOG_FUNCTION_NAME;
+
+ if (!tapin) {
+ CAMHAL_LOGD("Missing argument");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+ }
+
+ // Get the name of tapin
+ ret = mExtendedPreviewStreamOps->get_id(tapin, id, sizeof(id));
+ if (NO_ERROR != ret) {
+ CAMHAL_LOGEB("get_id OPS returned error %d", ret);
+ return ret;
+ }
+
+ // 1. Check name of tap-in
+ // 2. If exist, then free buffers and then remove it
+ if (mBufferSourceAdapter_In.get() && mBufferSourceAdapter_In->match(id)) {
+ CAMHAL_LOGD("REMOVE tap in %p previously set as current", tapin);
+ mBufferSourceAdapter_In.clear();
+ }
+ for (unsigned int i = 0; i < mInAdapters.size(); i++) {
+ android::sp<DisplayAdapter> in;
+ in = mInAdapters.itemAt(i);
+ if (in->match(id)) {
+ CAMHAL_LOGD("REMOVE tap in %p \"%s\" at position %d", tapin, id, i);
+ mInAdapters.removeAt(i);
+ break;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+
+/**
+ @brief Sets ANativeWindow object.
+
+ Buffers provided to CameraHal via this object for tap-in/tap-out
+ functionality.
+
+ TODO(XXX): this is just going to use preview_stream_ops for now, but we
+ most likely need to extend it when we want more functionality
+
+ @param[in] window The ANativeWindow object created by Surface flinger
+ @return NO_ERROR If the ANativeWindow object passes validation criteria
+ @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
+
+ */
+status_t CameraHal::setBufferSource(struct preview_stream_ops *tapin, struct preview_stream_ops *tapout)
+{
+ status_t ret = NO_ERROR;
+ int index = -1;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ CAMHAL_LOGD ("setBufferSource(%p, %p)", tapin, tapout);
+
+ ret = setTapoutLocked(tapout);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("setTapoutLocked returned error 0x%x", ret);
+ goto exit;
+ }
+
+ ret = setTapinLocked(tapin);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("setTapinLocked returned error 0x%x", ret);
+ goto exit;
+ }
+
+exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+
+/**
+ @brief Releases ANativeWindow object.
+
+ Release Buffers previously released with setBufferSource()
+
+ TODO(XXX): this is just going to use preview_stream_ops for now, but we
+ most likely need to extend it when we want more functionality
+
+ @param[in] window The ANativeWindow object created by Surface flinger
+ @return NO_ERROR If the ANativeWindow object passes validation criteria
+ @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
+
+ */
+status_t CameraHal::releaseBufferSource(struct preview_stream_ops *tapin, struct preview_stream_ops *tapout)
+{
+ status_t ret = NO_ERROR;
+ int index = -1;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+ CAMHAL_LOGD ("releaseBufferSource(%p, %p)", tapin, tapout);
+ if (tapout) {
+ ret |= releaseTapoutLocked(tapout);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Error %d to release tap out", ret);
+ }
+ }
+
+ if (tapin) {
+ ret |= releaseTapinLocked(tapin);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Error %d to release tap in", ret);
+ }
+ }
+
+exit:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+#endif
+
+
+/**
+ @brief Stop a previously started preview.
+
+ @param none
+ @return none
+
+ */
+void CameraHal::stopPreview()
+{
+ LOG_FUNCTION_NAME;
+
+ if( (!previewEnabled() && !mDisplayPaused) || mRecordingEnabled)
+ {
+ LOG_FUNCTION_NAME_EXIT;
+ return;
+ }
+
+ bool imageCaptureRunning = (mCameraAdapter->getState() & CameraAdapter::CAPTURE_STATE) &&
+ (mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE);
+ if(mDisplayPaused && !imageCaptureRunning)
+ {
+ // Display is paused, which essentially means there is no preview active.
+ // Note: this is done so that when stopPreview is called by client after
+ // an image capture, we do not de-initialize the camera adapter and
+ // restart over again.
+
+ return;
+ }
+
+ forceStopPreview();
+
+ // Reset Capture-Mode to default, so that when we switch from VideoRecording
+ // to ImageCapture, CAPTURE_MODE is not left to VIDEO_MODE.
+ CAMHAL_LOGDA("Resetting Capture-Mode to default");
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, "");
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Returns true if preview is enabled
+
+ @param none
+ @return true If preview is running currently
+ false If preview has been stopped
+
+ */
+bool CameraHal::previewEnabled()
+{
+ LOG_FUNCTION_NAME;
+
+ return (mPreviewEnabled || mPreviewStartInProgress);
+}
+
+/**
+ @brief 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 calling
+ releaseRecordingFrame().
+
+ @param none
+ @return NO_ERROR If recording could be started without any issues
+ @todo Update the header with possible error values in failure scenarios
+
+ */
+status_t CameraHal::startRecording( )
+{
+ int w, h;
+ const char *valstr = NULL;
+ bool restartPreviewRequired = false;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ gettimeofday(&mStartPreview, NULL);
+
+#endif
+
+ if(!previewEnabled())
+ {
+ return NO_INIT;
+ }
+
+ // set internal recording hint in case camera adapter needs to make some
+ // decisions....(will only be sent to camera adapter if camera restart is required)
+ mParameters.set(TICameraParameters::KEY_RECORDING_HINT, android::CameraParameters::TRUE);
+
+ // if application starts recording in continuous focus picture mode...
+ // then we need to force default capture mode (as opposed to video mode)
+ if ( ((valstr = mParameters.get(android::CameraParameters::KEY_FOCUS_MODE)) != NULL) &&
+ (strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) == 0) ){
+ restartPreviewRequired = resetVideoModeParameters();
+ }
+
+ // only need to check recording hint if preview restart is not already needed
+ valstr = mParameters.get(android::CameraParameters::KEY_RECORDING_HINT);
+ if ( !restartPreviewRequired &&
+ (!valstr || (valstr && (strcmp(valstr, android::CameraParameters::TRUE) != 0))) ) {
+ restartPreviewRequired = setVideoModeParameters(mParameters);
+ }
+
+ if (restartPreviewRequired) {
+ {
+ android::AutoMutex lock(mLock);
+ mCapModeBackup = mParameters.get(TICameraParameters::KEY_CAP_MODE);
+ }
+ ret = restartPreview();
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ int count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
+ mParameters.getPreviewSize(&w, &h);
+ CAMHAL_LOGDB("%s Video Width=%d Height=%d", __FUNCTION__, mVideoWidth, mVideoHeight);
+
+ if ((w != mVideoWidth) && (h != mVideoHeight))
+ {
+ ret = allocVideoBufs(mVideoWidth, mVideoHeight, count);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret);
+ mParameters.remove(TICameraParameters::KEY_RECORDING_HINT);
+ return ret;
+ }
+
+ mAppCallbackNotifier->useVideoBuffers(true);
+ mAppCallbackNotifier->setVideoRes(mVideoWidth, mVideoHeight);
+ ret = mAppCallbackNotifier->initSharedVideoBuffers(mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, count, mVideoBuffers);
+ }
+ else
+ {
+ mAppCallbackNotifier->useVideoBuffers(false);
+ mAppCallbackNotifier->setVideoRes(mPreviewWidth, mPreviewHeight);
+ ret = mAppCallbackNotifier->initSharedVideoBuffers(mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, count, NULL);
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = mAppCallbackNotifier->startRecording();
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ///Buffers for video capture (if different from preview) are expected to be allocated within CameraAdapter
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_VIDEO);
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mRecordingEnabled = true;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/**
+ @brief Set the camera parameters specific to Video Recording.
+
+ This function checks for the camera parameters which have to be set for recording.
+ Video Recording needs CAPTURE_MODE to be VIDEO_MODE. This function sets it.
+ This function also enables Video Recording specific functions like VSTAB & VNF.
+
+ @param none
+ @return true if preview needs to be restarted for VIDEO_MODE parameters to take effect.
+ @todo Modify the policies for enabling VSTAB & VNF usecase based later.
+
+ */
+bool CameraHal::setVideoModeParameters(const android::CameraParameters& params)
+{
+ const char *valstr = NULL;
+ const char *valstrRemote = NULL;
+ bool restartPreviewRequired = false;
+
+ LOG_FUNCTION_NAME;
+
+ // Set CAPTURE_MODE to VIDEO_MODE, if not set already and Restart Preview
+ valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
+ if ( (valstr == NULL) ||
+ ( (valstr != NULL) && ( (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE) != 0) &&
+ (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE_HQ ) != 0) ) ) ) {
+ CAMHAL_LOGDA("Set CAPTURE_MODE to VIDEO_MODE");
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, (const char *) TICameraParameters::VIDEO_MODE);
+ restartPreviewRequired = true;
+ }
+
+ // set VSTAB, restart is required if VSTAB value has changed
+ int prevWidth, prevHeight;
+ params.getPreviewSize(&prevWidth, &prevHeight);
+ valstr = mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION);
+ if (prevWidth == 1920 &&
+ (mSocFamily == SocFamily_Omap4430 || mSocFamily == SocFamily_Omap4460)) {
+ // forcibly set to false because of not enough memory for needed buffer size in this case
+ CAMHAL_LOGDA("Forcing VSTAB off");
+ if (strcmp(valstr, android::CameraParameters::FALSE) != 0) {
+ restartPreviewRequired = true;
+ }
+ mParameters.set(android::CameraParameters::KEY_VIDEO_STABILIZATION,
+ android::CameraParameters::FALSE);
+ } else {
+ if ((valstrRemote = params.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) != NULL) {
+ // make sure we support vstab
+ if (strcmp(mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED),
+ android::CameraParameters::TRUE) == 0) {
+ if (strcmp(valstr, valstrRemote) != 0) {
+ restartPreviewRequired = true;
+ }
+ mParameters.set(android::CameraParameters::KEY_VIDEO_STABILIZATION,
+ valstrRemote);
+ }
+ } else if (mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) {
+ // vstab was configured but now unset
+ restartPreviewRequired = true;
+ mParameters.remove(android::CameraParameters::KEY_VIDEO_STABILIZATION);
+ }
+ }
+
+ // Set VNF
+ if ((valstrRemote = params.get(TICameraParameters::KEY_VNF)) == NULL) {
+ CAMHAL_LOGDA("Enable VNF");
+ mParameters.set(TICameraParameters::KEY_VNF, android::CameraParameters::TRUE);
+ restartPreviewRequired = true;
+ } else {
+ valstr = mParameters.get(TICameraParameters::KEY_VNF);
+ if (valstr && strcmp(valstr, valstrRemote) != 0) {
+ restartPreviewRequired = true;
+ }
+ mParameters.set(TICameraParameters::KEY_VNF, valstrRemote);
+ }
+
+#if !defined(OMAP_ENHANCEMENT) && !defined(ENHANCED_DOMX)
+ // For VSTAB alone for 1080p resolution, padded width goes > 2048, which cannot be rendered by GPU.
+ // In such case, there is support in Ducati for combination of VSTAB & VNF requiring padded width < 2048.
+ // So we are forcefully enabling VNF, if VSTAB is enabled for 1080p resolution.
+ int w, h;
+ params.getPreviewSize(&w, &h);
+ valstr = mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION);
+ if (valstr && (strcmp(valstr, android::CameraParameters::TRUE) == 0) && (w == 1920)) {
+ CAMHAL_LOGDA("Force Enable VNF for 1080p");
+ const char *valKeyVnf = mParameters.get(TICameraParameters::KEY_VNF);
+ if(!valKeyVnf || (strcmp(valKeyVnf, android::CameraParameters::TRUE) != 0)) {
+ mParameters.set(TICameraParameters::KEY_VNF, android::CameraParameters::TRUE);
+ restartPreviewRequired = true;
+ }
+ }
+#endif
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return restartPreviewRequired;
+}
+
+/**
+ @brief Reset the camera parameters specific to Video Recording.
+
+ This function resets CAPTURE_MODE and disables Recording specific functions like VSTAB & VNF.
+
+ @param none
+ @return true if preview needs to be restarted for VIDEO_MODE parameters to take effect.
+
+ */
+bool CameraHal::resetVideoModeParameters()
+{
+ const char *valstr = NULL;
+ bool restartPreviewRequired = false;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ // ignore this if we are already recording
+ if (mRecordingEnabled) {
+ return false;
+ }
+
+ // Set CAPTURE_MODE to VIDEO_MODE, if not set already and Restart Preview
+ valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
+ if ((valstr != NULL) && (strcmp(valstr, TICameraParameters::VIDEO_MODE) == 0)) {
+ CAMHAL_LOGDA("Reset Capture-Mode to default");
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, "");
+ restartPreviewRequired = true;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return restartPreviewRequired;
+}
+
+/**
+ @brief Restart the preview with setParameter.
+
+ This function restarts preview, for some VIDEO_MODE parameters to take effect.
+
+ @param none
+ @return NO_ERROR If recording parameters could be set without any issues
+
+ */
+status_t CameraHal::restartPreview()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ // Retain CAPTURE_MODE before calling stopPreview(), since it is reset in stopPreview().
+
+ forceStopPreview();
+
+ {
+ android::AutoMutex lock(mLock);
+ if (!mCapModeBackup.isEmpty()) {
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, mCapModeBackup.string());
+ } else {
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, "");
+ }
+ mCameraAdapter->setParameters(mParameters);
+ }
+
+ ret = startPreview();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/**
+ @brief Stop a previously started recording.
+
+ @param none
+ @return none
+
+ */
+void CameraHal::stopRecording()
+{
+ CameraAdapter::AdapterState currentState;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if (!mRecordingEnabled )
+ {
+ return;
+ }
+
+ currentState = mCameraAdapter->getState();
+ if (currentState == CameraAdapter::VIDEO_CAPTURE_STATE) {
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE);
+ }
+
+ mAppCallbackNotifier->stopRecording();
+
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_VIDEO);
+
+ mRecordingEnabled = false;
+
+ if ( mAppCallbackNotifier->getUesVideoBuffers() ){
+ freeVideoBufs(mVideoBuffers);
+ if (mVideoBuffers){
+ CAMHAL_LOGVB(" FREEING mVideoBuffers %p", mVideoBuffers);
+ delete [] mVideoBuffers;
+ }
+ mVideoBuffers = NULL;
+ }
+
+ // reset internal recording hint in case camera adapter needs to make some
+ // decisions....(will only be sent to camera adapter if camera restart is required)
+ mParameters.remove(TICameraParameters::KEY_RECORDING_HINT);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Returns true if recording is enabled.
+
+ @param none
+ @return true If recording is currently running
+ false If recording has been stopped
+
+ */
+int CameraHal::recordingEnabled()
+{
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return mRecordingEnabled;
+}
+
+/**
+ @brief Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+
+ @param[in] mem MemoryBase pointer to the frame being released. Must be one of the buffers
+ previously given by CameraHal
+ @return none
+
+ */
+void CameraHal::releaseRecordingFrame(const void* mem)
+{
+ LOG_FUNCTION_NAME;
+
+ //CAMHAL_LOGDB(" 0x%x", mem->pointer());
+
+ if ( ( mRecordingEnabled ) && mem != NULL)
+ {
+ mAppCallbackNotifier->releaseRecordingFrame(mem);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return;
+}
+
+/**
+ @brief Start auto focus
+
+ This call asynchronous.
+ 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.
+
+ @param none
+ @return NO_ERROR
+ @todo Define the error codes if the focus is not locked
+
+ */
+status_t CameraHal::autoFocus()
+{
+ status_t ret = NO_ERROR;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ gettimeofday(&mStartFocus, NULL);
+
+#endif
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ mMsgEnabled |= CAMERA_MSG_FOCUS;
+
+ if ( NULL == mCameraAdapter )
+ {
+ ret = -1;
+ goto EXIT;
+ }
+
+ CameraAdapter::AdapterState state;
+ ret = mCameraAdapter->getState(state);
+ if (ret != NO_ERROR)
+ {
+ goto EXIT;
+ }
+
+ if ((state == CameraAdapter::AF_STATE) || (state == CameraAdapter::VIDEO_AF_STATE))
+ {
+ CAMHAL_LOGI("Ignoring start-AF (already in progress)");
+ goto EXIT;
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ //pass the autoFocus timestamp along with the command to camera adapter
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_PERFORM_AUTOFOCUS, ( int ) &mStartFocus);
+
+#else
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_PERFORM_AUTOFOCUS);
+
+#endif
+
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/**
+ @brief 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.
+
+
+ @param none
+ @return NO_ERROR If the cancel succeeded
+ @todo Define error codes if cancel didnt succeed
+
+ */
+status_t CameraHal::cancelAutoFocus()
+{
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+ android::CameraParameters adapterParams = mParameters;
+ mMsgEnabled &= ~CAMERA_MSG_FOCUS;
+
+ if( NULL != mCameraAdapter )
+ {
+ adapterParams.set(TICameraParameters::KEY_AUTO_FOCUS_LOCK, android::CameraParameters::FALSE);
+ mCameraAdapter->setParameters(adapterParams);
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_CANCEL_AUTOFOCUS);
+ mAppCallbackNotifier->flushEventQueue();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+}
+
+void CameraHal::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier)
+{
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL != mEventProvider )
+ {
+ mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS);
+ delete mEventProvider;
+ mEventProvider = NULL;
+ }
+
+ mEventProvider = new EventProvider(eventNotifier, this, eventCallbackRelay);
+ if ( NULL == mEventProvider )
+ {
+ CAMHAL_LOGEA("Error in creating EventProvider");
+ }
+ else
+ {
+ mEventProvider->enableEventNotification(eventMask);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void CameraHal::eventCallbackRelay(CameraHalEvent* event)
+{
+ LOG_FUNCTION_NAME;
+
+ CameraHal *appcbn = ( CameraHal * ) (event->mCookie);
+ appcbn->eventCallback(event );
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void CameraHal::eventCallback(CameraHalEvent* event)
+{
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t CameraHal::startImageBracketing()
+{
+ status_t ret = NO_ERROR;
+ CameraFrame frame;
+ CameraAdapter::BuffersDescriptor desc;
+ unsigned int max_queueable = 0;
+
+
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ gettimeofday(&mStartCapture, NULL);
+
+#endif
+
+ LOG_FUNCTION_NAME;
+
+ if(!previewEnabled() && !mDisplayPaused)
+ {
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ if ( !mBracketingEnabled )
+ {
+ return ret;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mBracketingRunning = true;
+ }
+
+ if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
+ {
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE,
+ ( int ) &frame,
+ ( mBracketRangeNegative + 1 ));
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret);
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ if ( NULL != mAppCallbackNotifier.get() )
+ {
+ mAppCallbackNotifier->setBurst(true);
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mParameters.getPictureSize(( int * ) &frame.mWidth,
+ ( int * ) &frame.mHeight);
+
+ ret = allocImageBufs(frame.mWidth,
+ frame.mHeight,
+ frame.mLength,
+ mParameters.getPictureFormat(),
+ ( mBracketRangeNegative + 1 ));
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret);
+ }
+ }
+
+ if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
+ {
+
+ desc.mBuffers = mImageBuffers;
+ desc.mOffsets = mImageOffsets;
+ desc.mFd = mImageFd;
+ desc.mLength = mImageLength;
+ desc.mCount = ( size_t ) ( mBracketRangeNegative + 1 );
+ desc.mMaxQueueable = ( size_t ) ( mBracketRangeNegative + 1 );
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE,
+ ( int ) &desc);
+
+ if ( NO_ERROR == ret )
+ {
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ //pass capture timestamp along with the camera adapter command
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_BRACKET_CAPTURE, ( mBracketRangePositive + 1 ), (int) &mStartCapture);
+
+#else
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_BRACKET_CAPTURE, ( mBracketRangePositive + 1 ));
+
+#endif
+
+ }
+ }
+
+ return ret;
+}
+
+status_t CameraHal::stopImageBracketing()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if( !previewEnabled() )
+ {
+ return NO_INIT;
+ }
+
+ mBracketingRunning = false;
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_BRACKET_CAPTURE);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/**
+ @brief Take a picture.
+
+ @param none
+ @return NO_ERROR If able to switch to image capture
+ @todo Define error codes if unable to switch to image capture
+
+ */
+status_t CameraHal::takePicture(const char *params)
+{
+ // cancel AF state if needed (before any operation and mutex lock)
+ if ((mCameraAdapter->getState() == CameraAdapter::AF_STATE) ||
+ (mCameraAdapter->getState() == CameraAdapter::VIDEO_AF_STATE)) {
+ cancelAutoFocus();
+ }
+
+ android::AutoMutex lock(mLock);
+ return __takePicture(params);
+}
+
+/**
+ @brief Internal function for getting a captured image.
+ shared by takePicture and reprocess.
+ @param none
+ @return NO_ERROR If able to switch to image capture
+ @todo Define error codes if unable to switch to image capture
+
+ */
+status_t CameraHal::__takePicture(const char *params, struct timeval *captureStart)
+{
+ status_t ret = NO_ERROR;
+ CameraFrame frame;
+ CameraAdapter::BuffersDescriptor desc;
+ int burst = -1;
+ const char *valstr = NULL;
+ unsigned int bufferCount = 1;
+ unsigned int max_queueable = 0;
+ unsigned int rawBufferCount = 1;
+ bool isCPCamMode = false;
+ android::sp<DisplayAdapter> outAdapter = 0;
+ bool reuseTapout = false;
+#ifdef MOTOROLA_CAMERA
+ unsigned int intensity = DEFAULT_INTENSITY;
+#endif
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ if ( NULL == captureStart ) {
+ gettimeofday(&mStartCapture, NULL);
+ } else {
+ memcpy(&mStartCapture, captureStart, sizeof(struct timeval));
+ }
+
+#endif
+
+ LOG_FUNCTION_NAME;
+
+ if(!previewEnabled() && !mDisplayPaused)
+ {
+ LOG_FUNCTION_NAME_EXIT;
+ CAMHAL_LOGEA("Preview not started...");
+ return NO_INIT;
+ }
+
+ valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
+
+ isCPCamMode = valstr && !strcmp(valstr, TICameraParameters::CP_CAM_MODE);
+
+ // return error if we are already capturing
+ // however, we can queue a capture when in cpcam mode
+ if ( ((mCameraAdapter->getState() == CameraAdapter::CAPTURE_STATE &&
+ mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) ||
+ (mCameraAdapter->getState() == CameraAdapter::VIDEO_CAPTURE_STATE &&
+ mCameraAdapter->getNextState() != CameraAdapter::VIDEO_STATE)) &&
+ !isCPCamMode) {
+ CAMHAL_LOGEA("Already capturing an image...");
+ return NO_INIT;
+ }
+
+ // we only support video snapshot if we are in video mode (recording hint is set)
+ if ( (mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE) &&
+ (valstr && ( strcmp(valstr, TICameraParameters::VIDEO_MODE) &&
+ strcmp(valstr, TICameraParameters::VIDEO_MODE_HQ ) ) ) ) {
+ CAMHAL_LOGEA("Trying to capture while recording without recording hint set...");
+ return INVALID_OPERATION;
+ }
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ // check if camera application is using shots parameters
+ // api. parameters set here override anything set using setParameters
+ // TODO(XXX): Just going to use legacy TI parameters for now. Need
+ // add new APIs in CameraHal to utilize android::ShotParameters later, so
+ // we don't have to parse through the whole set of parameters
+ // in camera adapter
+ if (strlen(params) > 0) {
+ android::ShotParameters shotParams;
+ const char *valStr;
+ const char *valExpComp, *valExpGain;
+ int valNum;
+
+ android::String8 shotParams8(params);
+
+ shotParams.unflatten(shotParams8);
+ mParameters.remove(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE);
+ mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
+
+ valExpGain = shotParams.get(android::ShotParameters::KEY_EXP_GAIN_PAIRS);
+ valExpComp = shotParams.get(android::ShotParameters::KEY_EXP_COMPENSATION);
+ if (NULL != valExpComp) {
+ mParameters.set(TICameraParameters::KEY_EXP_BRACKETING_RANGE, valExpComp);
+ } else if (NULL != valExpGain) {
+ mParameters.set(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE, valExpGain);
+ }
+
+ valNum = shotParams.getInt(android::ShotParameters::KEY_BURST);
+ if (valNum >= 0) {
+ mParameters.set(TICameraParameters::KEY_BURST, valNum);
+ burst = valNum;
+ }
+
+ valStr = shotParams.get(android::ShotParameters::KEY_FLUSH_CONFIG);
+ if (valStr!= NULL) {
+ if ( 0 == strcmp(valStr, android::ShotParameters::TRUE) ) {
+ mParameters.set(TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE,
+ android::CameraParameters::TRUE);
+ } else if ( 0 == strcmp(valStr, android::ShotParameters::FALSE) ) {
+ mParameters.set(TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE,
+ android::CameraParameters::FALSE);
+ }
+ }
+
+ valStr = shotParams.get(android::ShotParameters::KEY_CURRENT_TAP_OUT);
+ if (valStr != NULL) {
+ int index = -1;
+ for (unsigned int i = 0; i < mOutAdapters.size(); i++) {
+ if(mOutAdapters.itemAt(i)->match(valStr)) {
+ index = i;
+ break;
+ }
+ }
+ if (index < 0) {
+ CAMHAL_LOGE("Invalid tap out surface passed to camerahal");
+ return BAD_VALUE;
+ }
+ CAMHAL_LOGD("Found matching out adapter at %d", index);
+ outAdapter = mOutAdapters.itemAt(index);
+ if ( outAdapter == mBufferSourceAdapter_Out ) {
+ reuseTapout = true;
+ }
+ }
+
+ mCameraAdapter->setParameters(mParameters);
+ } else
+#endif
+ {
+ // TODO(XXX): Should probably reset burst and bracketing params
+ // when we remove legacy TI parameters implementation
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Takepicture parameters set: ", &mStartCapture);
+
+#endif
+
+ // if we are already in the middle of a capture and using the same
+ // tapout ST...then we just need setParameters and start image
+ // capture to queue more shots
+ if (((mCameraAdapter->getState() & CameraAdapter::CAPTURE_STATE) ==
+ CameraAdapter::CAPTURE_STATE) &&
+ (mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) &&
+ (reuseTapout) ) {
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ //pass capture timestamp along with the camera adapter command
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE,
+ (int) &mStartCapture);
+#else
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE);
+#endif
+ return ret;
+ }
+
+ if ( !mBracketingRunning )
+ {
+ // if application didn't set burst through android::ShotParameters
+ // then query from TICameraParameters
+ if ((burst == -1) && (NO_ERROR == ret)) {
+ burst = mParameters.getInt(TICameraParameters::KEY_BURST);
+ }
+
+ //Allocate all buffers only in burst capture case
+ if ( burst > 0 ) {
+ // For CPCam mode...allocate for worst case burst
+ bufferCount = isCPCamMode || (burst > CameraHal::NO_BUFFERS_IMAGE_CAPTURE) ?
+ CameraHal::NO_BUFFERS_IMAGE_CAPTURE : burst;
+
+ if (outAdapter.get()) {
+ if ( reuseTapout ) {
+ bufferCount = mImageCount;
+ } else {
+ bufferCount = outAdapter->getBufferCount();
+ if (bufferCount < 1) {
+ bufferCount = NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP;
+ }
+ }
+ }
+
+ if ( NULL != mAppCallbackNotifier.get() ) {
+ mAppCallbackNotifier->setBurst(true);
+ }
+ } else if ( mBracketingEnabled ) {
+ bufferCount = mBracketRangeNegative + 1;
+ if ( NULL != mAppCallbackNotifier.get() ) {
+ mAppCallbackNotifier->setBurst(false);
+ }
+ } else {
+ if ( NULL != mAppCallbackNotifier.get() ) {
+ mAppCallbackNotifier->setBurst(false);
+ }
+ }
+
+ // pause preview during normal image capture
+ // do not pause preview if recording (video state)
+ if ( (NO_ERROR == ret) && (NULL != mDisplayAdapter.get()) ) {
+ if ((mCameraAdapter->getState() != CameraAdapter::VIDEO_STATE) &&
+ (mCameraAdapter->getState() != CameraAdapter::VIDEO_AF_STATE)) {
+ mDisplayPaused = true;
+ mPreviewEnabled = false;
+ ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);
+ // since preview is paused we should stop sending preview frames too
+ if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
+ mAppCallbackNotifier->disableMsgType (CAMERA_MSG_PREVIEW_FRAME);
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ mDisplayAdapter->setSnapshotTimeRef(&mStartCapture);
+#endif
+ }
+
+ // if we taking video snapshot...
+ if ((NO_ERROR == ret) && ((mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE) ||
+ (mCameraAdapter->getState() == CameraAdapter::VIDEO_AF_STATE))) {
+ // enable post view frames if not already enabled so we can internally
+ // save snapshot frames for generating thumbnail
+ if((mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME) == 0) {
+ mAppCallbackNotifier->enableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+ }
+ }
+
+ if ( (NO_ERROR == ret) && (NULL != mCameraAdapter) )
+ {
+#ifdef MOTOROLA_CAMERA
+ intensity = getFlashIntensity();
+
+ if (intensity == 0)
+ {
+ //notification callback can be triggered with this to inform user
+ mParameters.set(android::CameraParameters::KEY_FLASH_MODE, android::CameraParameters::FLASH_MODE_OFF);
+ }
+ else if (intensity <= DEFAULT_INTENSITY)
+ {
+ mParameters.set(TICameraParameters::KEY_MOT_LEDFLASH, (int) intensity);
+ mParameters.set(TICameraParameters::KEY_MOT_LEDTORCH, (int) intensity);
+ }
+#endif
+
+ if ( NO_ERROR == ret )
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE,
+ ( int ) &frame,
+ bufferCount);
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret);
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Takepicture buffer size queried: ", &mStartCapture);
+
+#endif
+
+ if (outAdapter.get()) {
+ // Avoid locking the tapout again when reusing it
+ if (!reuseTapout) {
+ // Need to reset buffers if we are switching adapters since we don't know
+ // the state of the new buffer list
+ ret = outAdapter->maxQueueableBuffers(max_queueable);
+ if (NO_ERROR != ret) {
+ CAMHAL_LOGE("Couldn't get max queuable");
+ return ret;
+ }
+ mImageBuffers = outAdapter->getBuffers(true);
+ mImageOffsets = outAdapter->getOffsets();
+ mImageFd = outAdapter->getFd();
+ mImageLength = outAdapter->getSize();
+ mImageCount = bufferCount;
+ mBufferSourceAdapter_Out = outAdapter;
+ }
+ } else {
+ mBufferSourceAdapter_Out.clear();
+ // allocImageBufs will only allocate new buffers if mImageBuffers is NULL
+ if ( NO_ERROR == ret ) {
+ max_queueable = bufferCount;
+ ret = allocImageBufs(frame.mAlignment / getBPP(mParameters.getPictureFormat()),
+ frame.mHeight,
+ frame.mLength,
+ mParameters.getPictureFormat(),
+ bufferCount);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret);
+ }
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Takepicture buffers allocated: ", &mStartCapture);
+ memcpy(&mImageBuffers->ppmStamp, &mStartCapture, sizeof(struct timeval));
+
+#endif
+
+ if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
+ {
+ desc.mBuffers = mImageBuffers;
+ desc.mOffsets = mImageOffsets;
+ desc.mFd = mImageFd;
+ desc.mLength = mImageLength;
+ desc.mCount = ( size_t ) bufferCount;
+ desc.mMaxQueueable = ( size_t ) max_queueable;
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE,
+ ( int ) &desc);
+ }
+ if (mRawCapture) {
+ if ( NO_ERROR == ret ) {
+ CAMHAL_LOGDB("Raw capture buffers setup - %s", mParameters.getPictureFormat());
+ ret = allocRawBufs(mParameters.getInt(TICameraParameters::RAW_WIDTH),
+ mParameters.getInt(TICameraParameters::RAW_HEIGHT),
+ android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB,
+ rawBufferCount);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("allocRawBufs (for RAW capture) returned error 0x%x", ret);
+ }
+ }
+
+ if ((NO_ERROR == ret) && ( NULL != mCameraAdapter )) {
+ desc.mBuffers = mVideoBuffers;
+ desc.mOffsets = mVideoOffsets;
+ desc.mFd = mVideoFd;
+ desc.mLength = mVideoLength;
+ desc.mCount = ( size_t ) rawBufferCount;
+ desc.mMaxQueueable = ( size_t ) rawBufferCount;
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_VIDEO_CAPTURE,
+ ( int ) &desc);
+ }
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Takepicture buffers registered: ", &mStartCapture);
+
+#endif
+
+ if ((ret == NO_ERROR) && mBufferSourceAdapter_Out.get()) {
+ mBufferSourceAdapter_Out->enableDisplay(0, 0, NULL);
+ }
+
+ if ((NO_ERROR == ret) && (NULL != mCameraAdapter)) {
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ //pass capture timestamp along with the camera adapter command
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE, (int) &mStartCapture);
+
+ CameraHal::PPM("Takepicture capture started: ", &mStartCapture);
+
+#else
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE);
+
+#endif
+
+ }
+
+ return ret;
+}
+
+/**
+ @brief Cancel a picture that was started with takePicture.
+
+ Calling this method when no picture is being taken is a no-op.
+
+ @param none
+ @return NO_ERROR If cancel succeeded. Cancel can succeed if image callback is not sent
+ @todo Define error codes
+
+ */
+status_t CameraHal::cancelPicture( )
+{
+ LOG_FUNCTION_NAME;
+ status_t ret = NO_ERROR;
+
+ ret = signalEndImageCapture();
+ return NO_ERROR;
+}
+
+/**
+ @brief Return the camera parameters.
+
+ @param none
+ @return Currently configured camera parameters
+
+ */
+char* CameraHal::getParameters()
+{
+ android::String8 params_str8;
+ char* params_string;
+ const char * valstr = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if( NULL != mCameraAdapter )
+ {
+ mCameraAdapter->getParameters(mParameters);
+ }
+
+ if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT)) != NULL ) {
+ if (!strcmp(TICameraParameters::S3D_TB_FULL, valstr)) {
+ mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_TOPBOTTOM_SIZES));
+ } else if (!strcmp(TICameraParameters::S3D_SS_FULL, valstr)) {
+ mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_SIDEBYSIDE_SIZES));
+ } else if ((!strcmp(TICameraParameters::S3D_TB_SUBSAMPLED, valstr))
+ || (!strcmp(TICameraParameters::S3D_SS_SUBSAMPLED, valstr))) {
+ mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_SUBSAMPLED_SIZES));
+ }
+ }
+
+ if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT)) != NULL ) {
+ if (!strcmp(TICameraParameters::S3D_TB_FULL, valstr)) {
+ mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_TOPBOTTOM_SIZES));
+ } else if (!strcmp(TICameraParameters::S3D_SS_FULL, valstr)) {
+ mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES));
+ } else if ((!strcmp(TICameraParameters::S3D_TB_SUBSAMPLED, valstr))
+ || (!strcmp(TICameraParameters::S3D_SS_SUBSAMPLED, valstr))) {
+ mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_SUBSAMPLED_SIZES));
+ }
+ }
+
+ android::CameraParameters mParams = mParameters;
+
+ // Handle RECORDING_HINT to Set/Reset Video Mode Parameters
+ valstr = mParameters.get(android::CameraParameters::KEY_RECORDING_HINT);
+ if(valstr != NULL)
+ {
+ if(strcmp(valstr, android::CameraParameters::TRUE) == 0)
+ {
+ //HACK FOR MMS MODE
+ resetPreviewRes(&mParams);
+ }
+ }
+
+ // do not send internal parameters to upper layers
+ mParams.remove(TICameraParameters::KEY_RECORDING_HINT);
+ mParams.remove(TICameraParameters::KEY_AUTO_FOCUS_LOCK);
+
+ params_str8 = mParams.flatten();
+
+ // camera service frees this string...
+ params_string = (char*) malloc(sizeof(char) * (params_str8.length()+1));
+ strcpy(params_string, params_str8.string());
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ ///Return the current set of parameters
+
+ return params_string;
+}
+
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+/**
+ @brief Starts reprocessing operation.
+ */
+status_t CameraHal::reprocess(const char *params)
+{
+ status_t ret = NO_ERROR;
+ int bufferCount = 0;
+ CameraAdapter::BuffersDescriptor desc;
+ CameraBuffer *reprocBuffers = NULL;
+ android::ShotParameters shotParams;
+ const char *valStr = NULL;
+ struct timeval startReprocess;
+
+ android::AutoMutex lock(mLock);
+
+ LOG_FUNCTION_NAME;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ gettimeofday(&startReprocess, NULL);
+
+#endif
+
+ // 0. Get tap in surface
+ if (strlen(params) > 0) {
+ android::String8 shotParams8(params);
+ shotParams.unflatten(shotParams8);
+ }
+
+ valStr = shotParams.get(android::ShotParameters::KEY_CURRENT_TAP_IN);
+ if (valStr != NULL) {
+ int index = -1;
+ for (unsigned int i = 0; i < mInAdapters.size(); i++) {
+ if(mInAdapters.itemAt(i)->match(valStr)) {
+ index = i;
+ break;
+ }
+ }
+ if (index < 0) {
+ CAMHAL_LOGE("Invalid tap in surface passed to camerahal");
+ return BAD_VALUE;
+ }
+ CAMHAL_LOGD("Found matching in adapter at %d", index);
+ mBufferSourceAdapter_In = mInAdapters.itemAt(index);
+ } else {
+ CAMHAL_LOGE("No tap in surface sent with shot config!");
+ return BAD_VALUE;
+ }
+
+ // 1. Get buffers
+ if (mBufferSourceAdapter_In.get()) {
+ reprocBuffers = mBufferSourceAdapter_In->getBufferList(&bufferCount);
+ }
+
+ if (!reprocBuffers) {
+ CAMHAL_LOGE("Error: couldn't get input buffers for reprocess()");
+ goto exit;
+ }
+
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Got reprocess buffers: ", &startReprocess);
+
+#endif
+
+ // 2. Get buffer information and parse parameters
+ {
+ shotParams.setBurst(bufferCount);
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ memcpy(&reprocBuffers->ppmStamp, &startReprocess, sizeof(struct timeval));
+
+#endif
+
+ // 3. Give buffer to camera adapter
+ desc.mBuffers = reprocBuffers;
+ desc.mOffsets = 0;
+ desc.mFd = 0;
+ desc.mLength = 0;
+ desc.mCount = (size_t) bufferCount;
+ desc.mMaxQueueable = (size_t) bufferCount;
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_REPROCESS, (int) &desc);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Error calling camera use buffers");
+ goto exit;
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Reprocess buffers registered: ", &startReprocess);
+
+#endif
+
+ // 4. Start reprocessing
+ ret = mBufferSourceAdapter_In->enableDisplay(0, 0, NULL);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Error enabling tap in point");
+ goto exit;
+ }
+
+ // 4.5. cancel AF state if needed (before any operation and mutex lock)
+ if ((mCameraAdapter->getState() == CameraAdapter::AF_STATE) ||
+ (mCameraAdapter->getState() == CameraAdapter::VIDEO_AF_STATE)) {
+ cancelAutoFocus();
+ }
+
+ // 5. Start capturing
+ ret = __takePicture(shotParams.flatten().string(), &startReprocess);
+
+exit:
+ return ret;
+}
+
+/**
+ @brief Cancels current reprocessing operation
+
+ */
+status_t CameraHal::cancel_reprocess( )
+{
+ LOG_FUNCTION_NAME;
+ status_t ret = NO_ERROR;
+
+ ret = signalEndImageCapture();
+ return NO_ERROR;
+}
+#endif
+
+
+void CameraHal::putParameters(char *parms)
+{
+ free(parms);
+}
+
+/**
+ @brief Send command to camera driver.
+
+ @param none
+ @return NO_ERROR If the command succeeds
+ @todo Define the error codes that this function can return
+
+ */
+status_t CameraHal::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( ( NO_ERROR == ret ) && ( NULL == mCameraAdapter ) )
+ {
+ CAMHAL_LOGEA("No CameraAdapter instance");
+ return -EINVAL;
+ }
+
+ ///////////////////////////////////////////////////////
+ // Following commands NEED preview to be started
+ ///////////////////////////////////////////////////////
+
+ if ((!previewEnabled()) && ((cmd == CAMERA_CMD_START_SMOOTH_ZOOM)
+ || (cmd == CAMERA_CMD_STOP_SMOOTH_ZOOM)
+ || (cmd == CAMERA_CMD_START_FACE_DETECTION)
+#ifdef OMAP_ENHANCEMENT_VTC
+ || (cmd == CAMERA_CMD_PREVIEW_DEINITIALIZATION)
+#endif
+ ))
+ {
+ CAMHAL_LOGEA("sendCommand with cmd = 0x%x need preview to be started", cmd);
+ return BAD_VALUE;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ switch(cmd)
+ {
+ case CAMERA_CMD_START_SMOOTH_ZOOM:
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_SMOOTH_ZOOM, arg1);
+
+ break;
+
+ case CAMERA_CMD_STOP_SMOOTH_ZOOM:
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_SMOOTH_ZOOM);
+
+ break;
+
+ case CAMERA_CMD_START_FACE_DETECTION:
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_FD);
+
+ break;
+
+ case CAMERA_CMD_STOP_FACE_DETECTION:
+ if (previewEnabled()) {
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_FD);
+ }
+
+ break;
+
+#ifdef OMAP_ENHANCEMENT_VTC
+ case CAMERA_CMD_PREVIEW_DEINITIALIZATION:
+ if(mDisplayAdapter.get() != NULL) {
+ ///Stop the buffer display first
+ mDisplayAdapter->disableDisplay();
+ }
+
+ if(mAppCallbackNotifier.get() != NULL) {
+ //Stop the callback sending
+ mAppCallbackNotifier->stop();
+ mAppCallbackNotifier->flushAndReturnFrames();
+ mAppCallbackNotifier->stopPreviewCallbacks();
+ }
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_DESTROY_TUNNEL);
+ mTunnelSetup = false;
+
+ break;
+
+ case CAMERA_CMD_PREVIEW_INITIALIZATION:
+ ret = cameraPreviewInitialization();
+
+ break;
+#endif
+
+#ifdef ANDROID_API_JB_OR_LATER
+ case CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG:
+ {
+ const bool enable = static_cast<bool>(arg1);
+ android::AutoMutex lock(mLock);
+ if ( enable ) {
+ mMsgEnabled |= CAMERA_MSG_FOCUS_MOVE;
+ } else {
+ mMsgEnabled &= ~CAMERA_MSG_FOCUS_MOVE;
+ }
+ break;
+ }
+#endif
+
+ default:
+ break;
+ };
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/**
+ @brief Release the hardware resources owned by this object.
+
+ Note that this is *not* done in the destructor.
+
+ @param none
+ @return none
+
+ */
+void CameraHal::release()
+{
+ LOG_FUNCTION_NAME;
+ ///@todo Investigate on how release is used by CameraService. Vaguely remember that this is called
+ ///just before CameraHal object destruction
+ deinitialize();
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+/**
+ @brief Dump state of the camera hardware
+
+ @param[in] fd File descriptor
+ @param[in] args Arguments
+ @return NO_ERROR Dump succeeded
+ @todo Error codes for dump fail
+
+ */
+status_t CameraHal::dump(int fd) const
+{
+ LOG_FUNCTION_NAME;
+ ///Implement this method when the h/w dump function is supported on Ducati side
+ return NO_ERROR;
+}
+
+/*-------------Camera Hal Interface Method definitions ENDS here--------------------*/
+
+
+
+
+/*-------------Camera Hal Internal Method definitions STARTS here--------------------*/
+
+/**
+ @brief Constructor of CameraHal
+
+ Member variables are initialized here. No allocations should be done here as we
+ don't use c++ exceptions in the code.
+
+ */
+CameraHal::CameraHal(int cameraId)
+ : mSocFamily(getSocFamily())
+{
+ LOG_FUNCTION_NAME;
+
+ ///Initialize all the member variables to their defaults
+ mPreviewEnabled = false;
+ mPreviewBuffers = NULL;
+ mImageBuffers = NULL;
+ mBufProvider = NULL;
+ mPreviewStartInProgress = false;
+ mVideoBuffers = NULL;
+ mVideoBufProvider = NULL;
+ mRecordingEnabled = false;
+ mDisplayPaused = false;
+ mSetPreviewWindowCalled = false;
+ mMsgEnabled = 0;
+ mAppCallbackNotifier = NULL;
+ mMemoryManager = NULL;
+ mCameraAdapter = NULL;
+ mBracketingEnabled = false;
+ mBracketingRunning = false;
+ mEventProvider = NULL;
+ mBracketRangePositive = 1;
+ mBracketRangeNegative = 1;
+ mMaxZoomSupported = 0;
+ mShutterEnabled = true;
+ mMeasurementEnabled = false;
+ mPreviewDataBuffers = NULL;
+ mCameraProperties = NULL;
+ mCurrentTime = 0;
+ mFalsePreview = 0;
+ mImageOffsets = NULL;
+ mImageLength = 0;
+ mImageFd = 0;
+ mImageCount = 0;
+ mVideoOffsets = NULL;
+ mVideoFd = 0;
+ mVideoLength = 0;
+ mPreviewDataOffsets = NULL;
+ mPreviewDataFd = 0;
+ mPreviewDataLength = 0;
+ mPreviewFd = 0;
+ mPreviewWidth = 0;
+ mPreviewHeight = 0;
+ mPreviewLength = 0;
+ mPreviewOffsets = NULL;
+ mPreviewRunning = 0;
+ mPreviewStateOld = 0;
+ mRecordingEnabled = 0;
+ mRecordEnabled = 0;
+ mSensorListener = NULL;
+ mVideoWidth = 0;
+ mVideoHeight = 0;
+#ifdef OMAP_ENHANCEMENT_VTC
+ mVTCUseCase = false;
+ mTunnelSetup = false;
+#endif
+ mPreviewInitializationDone = false;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ mExtendedPreviewStreamOps = 0;
+#endif
+
+ //These values depends on the sensor characteristics
+
+ mRawCapture = false;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ //Initialize the CameraHAL constructor timestamp, which is used in the
+ // PPM() method as time reference if the user does not supply one.
+ gettimeofday(&ppm_start, NULL);
+
+#endif
+
+ mCameraIndex = cameraId;
+
+ mExternalLocking = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Destructor of CameraHal
+
+ This function simply calls deinitialize() to free up memory allocate during construct
+ phase
+ */
+CameraHal::~CameraHal()
+{
+ LOG_FUNCTION_NAME;
+
+ ///Call de-initialize here once more - it is the last chance for us to relinquish all the h/w and s/w resources
+ deinitialize();
+
+ if ( NULL != mEventProvider )
+ {
+ mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS);
+ delete mEventProvider;
+ mEventProvider = NULL;
+ }
+
+ /// Free the callback notifier
+ mAppCallbackNotifier.clear();
+
+ /// Free the display adapter
+ mDisplayAdapter.clear();
+
+ if ( NULL != mCameraAdapter ) {
+ int strongCount = mCameraAdapter->getStrongCount();
+
+ mCameraAdapter->decStrong(mCameraAdapter);
+
+ mCameraAdapter = NULL;
+ }
+
+ freeImageBufs();
+ freeRawBufs();
+
+ /// Free the memory manager
+ mMemoryManager.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Initialize the Camera HAL
+
+ Creates CameraAdapter, AppCallbackNotifier, DisplayAdapter and MemoryManager
+
+ @param None
+ @return NO_ERROR - On success
+ NO_MEMORY - On failure to allocate memory for any of the objects
+ @remarks Camera Hal internal function
+
+ */
+
+status_t CameraHal::initialize(CameraProperties::Properties* properties)
+{
+ LOG_FUNCTION_NAME;
+
+ int sensor_index = 0;
+ const char* sensor_name = NULL;
+
+ ///Initialize the event mask used for registering an event provider for AppCallbackNotifier
+ ///Currently, registering all events as to be coming from CameraAdapter
+ int32_t eventMask = CameraHalEvent::ALL_EVENTS;
+
+ // Get my camera properties
+ mCameraProperties = properties;
+
+ if(!mCameraProperties)
+ {
+ goto fail_loop;
+ }
+
+ // Dump the properties of this Camera
+ // will only print if DEBUG macro is defined
+ mCameraProperties->dump();
+
+ if (strcmp(CameraProperties::DEFAULT_VALUE, mCameraProperties->get(CameraProperties::CAMERA_SENSOR_INDEX)) != 0 )
+ {
+ sensor_index = atoi(mCameraProperties->get(CameraProperties::CAMERA_SENSOR_INDEX));
+ }
+
+ if (strcmp(CameraProperties::DEFAULT_VALUE, mCameraProperties->get(CameraProperties::CAMERA_NAME)) != 0 ) {
+ sensor_name = mCameraProperties->get(CameraProperties::CAMERA_NAME);
+ }
+ CAMHAL_LOGDB("Sensor index= %d; Sensor name= %s", sensor_index, sensor_name);
+
+ if (strcmp(sensor_name, V4L_CAMERA_NAME_USB) == 0) {
+#ifdef V4L_CAMERA_ADAPTER
+ mCameraAdapter = V4LCameraAdapter_Factory(sensor_index, this);
+#endif
+ }
+ else {
+#ifdef OMX_CAMERA_ADAPTER
+ mCameraAdapter = OMXCameraAdapter_Factory(sensor_index);
+#endif
+ }
+
+ if ( ( NULL == mCameraAdapter ) || (mCameraAdapter->initialize(properties)!=NO_ERROR))
+ {
+ CAMHAL_LOGEA("Unable to create or initialize CameraAdapter");
+ mCameraAdapter = NULL;
+ goto fail_loop;
+ }
+
+ mCameraAdapter->incStrong(mCameraAdapter);
+ mCameraAdapter->registerImageReleaseCallback(releaseImageBuffers, (void *) this);
+ mCameraAdapter->registerEndCaptureCallback(endImageCapture, (void *)this);
+
+ if(!mAppCallbackNotifier.get())
+ {
+ /// Create the callback notifier
+ mAppCallbackNotifier = new AppCallbackNotifier();
+ if( ( NULL == mAppCallbackNotifier.get() ) || ( mAppCallbackNotifier->initialize() != NO_ERROR))
+ {
+ CAMHAL_LOGEA("Unable to create or initialize AppCallbackNotifier");
+ goto fail_loop;
+ }
+ }
+
+ if(!mMemoryManager.get())
+ {
+ /// Create Memory Manager
+ mMemoryManager = new MemoryManager();
+ if( ( NULL == mMemoryManager.get() ) || ( mMemoryManager->initialize() != NO_ERROR))
+ {
+ CAMHAL_LOGEA("Unable to create or initialize MemoryManager");
+ goto fail_loop;
+ }
+ }
+
+ ///Setup the class dependencies...
+
+ ///AppCallbackNotifier has to know where to get the Camera frames and the events like auto focus lock etc from.
+ ///CameraAdapter is the one which provides those events
+ ///Set it as the frame and event providers for AppCallbackNotifier
+ ///@remarks setEventProvider API takes in a bit mask of events for registering a provider for the different events
+ /// That way, if events can come from DisplayAdapter in future, we will be able to add it as provider
+ /// for any event
+ mAppCallbackNotifier->setEventProvider(eventMask, mCameraAdapter);
+ mAppCallbackNotifier->setFrameProvider(mCameraAdapter);
+
+ ///Any dynamic errors that happen during the camera use case has to be propagated back to the application
+ ///via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application
+ ///Set it as the error handler for CameraAdapter
+ mCameraAdapter->setErrorHandler(mAppCallbackNotifier.get());
+
+ ///Start the callback notifier
+ if(mAppCallbackNotifier->start() != NO_ERROR)
+ {
+ CAMHAL_LOGEA("Couldn't start AppCallbackNotifier");
+ goto fail_loop;
+ }
+
+ CAMHAL_LOGDA("Started AppCallbackNotifier..");
+ mAppCallbackNotifier->setMeasurements(mMeasurementEnabled);
+
+ ///Initialize default parameters
+ initDefaultParameters();
+
+
+ if ( setParameters(mParameters) != NO_ERROR )
+ {
+ CAMHAL_LOGEA("Failed to set default parameters?!");
+ }
+
+ // register for sensor events
+ mSensorListener = new SensorListener();
+ if (mSensorListener.get()) {
+ if (mSensorListener->initialize() == NO_ERROR) {
+ mSensorListener->setCallbacks(orientation_cb, this);
+ mSensorListener->enableSensor(SensorListener::SENSOR_ORIENTATION);
+ } else {
+ CAMHAL_LOGEA("Error initializing SensorListener. not fatal, continuing");
+ mSensorListener.clear();
+ mSensorListener = NULL;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+
+ fail_loop:
+
+ ///Free up the resources because we failed somewhere up
+ deinitialize();
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_MEMORY;
+
+}
+
+bool CameraHal::isResolutionValid(unsigned int width, unsigned int height, const char *supportedResolutions)
+{
+ bool ret = false;
+ status_t status = NO_ERROR;
+ char tmpBuffer[MAX_PROP_VALUE_LENGTH];
+ char *pos = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if (NULL == supportedResolutions) {
+ CAMHAL_LOGEA("Invalid supported resolutions string");
+ goto exit;
+ }
+
+ status = snprintf(tmpBuffer, MAX_PROP_VALUE_LENGTH - 1, "%dx%d", width, height);
+ if (0 > status) {
+ CAMHAL_LOGEA("Error encountered while generating validation string");
+ goto exit;
+ }
+
+ ret = isParameterValid(tmpBuffer, supportedResolutions);
+
+exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+bool CameraHal::isFpsRangeValid(int fpsMin, int fpsMax, const char *supportedFpsRanges)
+{
+ bool ret = false;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ char *pos;
+ int suppFpsRangeArray[2];
+ int i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == supportedFpsRanges ) {
+ CAMHAL_LOGEA("Invalid supported FPS ranges string");
+ return false;
+ }
+
+ if (fpsMin <= 0 || fpsMax <= 0 || fpsMin > fpsMax) {
+ return false;
+ }
+
+ strncpy(supported, supportedFpsRanges, MAX_PROP_VALUE_LENGTH);
+ pos = strtok(supported, " (,)");
+ while (pos != NULL) {
+ suppFpsRangeArray[i] = atoi(pos);
+ if (i++) {
+ if (fpsMin >= suppFpsRangeArray[0] && fpsMax <= suppFpsRangeArray[1]) {
+ ret = true;
+ break;
+ }
+ i = 0;
+ }
+ pos = strtok(NULL, " (,)");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+bool CameraHal::isParameterValid(const char *param, const char *supportedParams)
+{
+ bool ret = false;
+ char *pos;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ if (NULL == supportedParams) {
+ CAMHAL_LOGEA("Invalid supported parameters string");
+ goto exit;
+ }
+
+ if (NULL == param) {
+ CAMHAL_LOGEA("Invalid parameter string");
+ goto exit;
+ }
+
+ strncpy(supported, supportedParams, MAX_PROP_VALUE_LENGTH - 1);
+
+ pos = strtok(supported, ",");
+ while (pos != NULL) {
+ if (!strcmp(pos, param)) {
+ ret = true;
+ break;
+ }
+ pos = strtok(NULL, ",");
+ }
+
+exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+bool CameraHal::isParameterValid(int param, const char *supportedParams)
+{
+ bool ret = false;
+ status_t status;
+ char tmpBuffer[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ if (NULL == supportedParams) {
+ CAMHAL_LOGEA("Invalid supported parameters string");
+ goto exit;
+ }
+
+ status = snprintf(tmpBuffer, MAX_PROP_VALUE_LENGTH - 1, "%d", param);
+ if (0 > status) {
+ CAMHAL_LOGEA("Error encountered while generating validation string");
+ goto exit;
+ }
+
+ ret = isParameterValid(tmpBuffer, supportedParams);
+
+exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::doesSetParameterNeedUpdate(const char* new_param, const char* old_param, bool& update) {
+ if (!new_param || !old_param) {
+ return -EINVAL;
+ }
+
+ // if params mismatch we should update parameters for camera adapter
+ if ((strcmp(new_param, old_param) != 0)) {
+ update = true;
+ }
+
+ return NO_ERROR;
+}
+
+status_t CameraHal::parseResolution(const char *resStr, int &width, int &height)
+{
+ status_t ret = NO_ERROR;
+ char *ctx, *pWidth, *pHeight;
+ const char *sep = "x";
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == resStr )
+ {
+ return -EINVAL;
+ }
+
+ //This fixes "Invalid input resolution"
+ char *resStr_copy = (char *)malloc(strlen(resStr) + 1);
+ if ( NULL != resStr_copy )
+ {
+ strcpy(resStr_copy, resStr);
+ pWidth = strtok_r(resStr_copy, sep, &ctx);
+
+ if ( NULL != pWidth )
+ {
+ width = atoi(pWidth);
+ }
+ else
+ {
+ CAMHAL_LOGEB("Invalid input resolution %s", resStr);
+ ret = -EINVAL;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ pHeight = strtok_r(NULL, sep, &ctx);
+
+ if ( NULL != pHeight )
+ {
+ height = atoi(pHeight);
+ }
+ else
+ {
+ CAMHAL_LOGEB("Invalid input resolution %s", resStr);
+ ret = -EINVAL;
+ }
+ }
+
+ free(resStr_copy);
+ resStr_copy = NULL;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+void CameraHal::insertSupportedParams()
+{
+ LOG_FUNCTION_NAME;
+
+ android::CameraParameters &p = mParameters;
+
+ ///Set the name of the camera
+ p.set(TICameraParameters::KEY_CAMERA_NAME, mCameraProperties->get(CameraProperties::CAMERA_NAME));
+
+ mMaxZoomSupported = atoi(mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_STAGES));
+
+ p.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES));
+ p.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS));
+ p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES));
+ p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS));
+ p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_SUBSAMPLED_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES));
+ p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_SIDEBYSIDE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES));
+ p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_TOPBOTTOM_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES));
+ p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_SUBSAMPLED_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES));
+ p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES));
+ p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_TOPBOTTOM_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES));
+ p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES));
+ p.set(TICameraParameters::KEY_FRAMERATES_EXT_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES_EXT));
+ p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED));
+ p.set(TICameraParameters::KEY_FRAMERATE_RANGES_EXT_SUPPORTED, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_EXT_SUPPORTED));
+ p.set(android::CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_THUMBNAIL_SIZES));
+ p.set(android::CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE));
+ p.set(android::CameraParameters::KEY_SUPPORTED_EFFECTS, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS));
+ p.set(android::CameraParameters::KEY_SUPPORTED_SCENE_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES));
+ p.set(android::CameraParameters::KEY_SUPPORTED_FLASH_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES));
+ p.set(android::CameraParameters::KEY_SUPPORTED_FOCUS_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES));
+ p.set(android::CameraParameters::KEY_SUPPORTED_ANTIBANDING, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING));
+ p.set(android::CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MAX));
+ p.set(android::CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MIN));
+ p.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_EV_STEP));
+ p.set(TICameraParameters::KEY_SUPPORTED_EXPOSURE, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MAX));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_STEP));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MAX));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_STEP));
+ p.set(TICameraParameters::KEY_SUPPORTED_ISO_VALUES, mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES));
+ p.set(android::CameraParameters::KEY_ZOOM_RATIOS, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_RATIOS));
+ p.set(android::CameraParameters::KEY_MAX_ZOOM, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_STAGES));
+ p.set(android::CameraParameters::KEY_ZOOM_SUPPORTED, mCameraProperties->get(CameraProperties::ZOOM_SUPPORTED));
+ p.set(android::CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED, mCameraProperties->get(CameraProperties::SMOOTH_ZOOM_SUPPORTED));
+ p.set(TICameraParameters::KEY_SUPPORTED_IPP, mCameraProperties->get(CameraProperties::SUPPORTED_IPP_MODES));
+ p.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT_VALUES, mCameraProperties->get(CameraProperties::S3D_PRV_FRAME_LAYOUT_VALUES));
+ p.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT_VALUES, mCameraProperties->get(CameraProperties::S3D_CAP_FRAME_LAYOUT_VALUES));
+ p.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE_VALUES, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE_MODE_VALUES));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MIN));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MAX));
+ p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_STEP));
+ p.set(android::CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED, mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED));
+ p.set(TICameraParameters::KEY_VNF_SUPPORTED, mCameraProperties->get(CameraProperties::VNF_SUPPORTED));
+ p.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED));
+ p.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED));
+ p.set(android::CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED, mCameraProperties->get(CameraProperties::VIDEO_SNAPSHOT_SUPPORTED));
+ p.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED, mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED));
+ p.set(TICameraParameters::KEY_CAP_MODE_VALUES, mCameraProperties->get(CameraProperties::CAP_MODE_VALUES));
+
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+void CameraHal::initDefaultParameters()
+{
+ //Purpose of this function is to initialize the default current and supported parameters for the currently
+ //selected camera.
+
+ android::CameraParameters &p = mParameters;
+ int currentRevision, adapterRevision;
+ status_t ret = NO_ERROR;
+ int width, height;
+ const char *valstr;
+
+ LOG_FUNCTION_NAME;
+
+ insertSupportedParams();
+
+ ret = parseResolution(mCameraProperties->get(CameraProperties::PREVIEW_SIZE), width, height);
+
+ if ( NO_ERROR == ret )
+ {
+ p.setPreviewSize(width, height);
+ }
+ else
+ {
+ p.setPreviewSize(MIN_WIDTH, MIN_HEIGHT);
+ }
+
+ ret = parseResolution(mCameraProperties->get(CameraProperties::PICTURE_SIZE), width, height);
+
+ if ( NO_ERROR == ret )
+ {
+ p.setPictureSize(width, height);
+ }
+ else
+ {
+ p.setPictureSize(PICTURE_WIDTH, PICTURE_HEIGHT);
+ }
+
+ ret = parseResolution(mCameraProperties->get(CameraProperties::JPEG_THUMBNAIL_SIZE), width, height);
+
+ if ( NO_ERROR == ret )
+ {
+ p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
+ p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
+ }
+ else
+ {
+ p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, MIN_WIDTH);
+ p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, MIN_HEIGHT);
+ }
+
+ //Insert default values
+ p.setPreviewFrameRate(atoi(mCameraProperties->get(CameraProperties::PREVIEW_FRAME_RATE)));
+ p.set(android::CameraParameters::KEY_PREVIEW_FPS_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE));
+ p.set(TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE));
+ p.setPreviewFormat(mCameraProperties->get(CameraProperties::PREVIEW_FORMAT));
+ p.setPictureFormat(mCameraProperties->get(CameraProperties::PICTURE_FORMAT));
+ p.set(android::CameraParameters::KEY_JPEG_QUALITY, mCameraProperties->get(CameraProperties::JPEG_QUALITY));
+ p.set(android::CameraParameters::KEY_WHITE_BALANCE, mCameraProperties->get(CameraProperties::WHITEBALANCE));
+ p.set(android::CameraParameters::KEY_EFFECT, mCameraProperties->get(CameraProperties::EFFECT));
+ p.set(android::CameraParameters::KEY_ANTIBANDING, mCameraProperties->get(CameraProperties::ANTIBANDING));
+ p.set(android::CameraParameters::KEY_FLASH_MODE, mCameraProperties->get(CameraProperties::FLASH_MODE));
+ p.set(android::CameraParameters::KEY_FOCUS_MODE, mCameraProperties->get(CameraProperties::FOCUS_MODE));
+ p.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::EV_COMPENSATION));
+ p.set(android::CameraParameters::KEY_SCENE_MODE, mCameraProperties->get(CameraProperties::SCENE_MODE));
+ p.set(android::CameraParameters::KEY_ZOOM, mCameraProperties->get(CameraProperties::ZOOM));
+ p.set(TICameraParameters::KEY_CONTRAST, mCameraProperties->get(CameraProperties::CONTRAST));
+ p.set(TICameraParameters::KEY_SATURATION, mCameraProperties->get(CameraProperties::SATURATION));
+ p.set(TICameraParameters::KEY_BRIGHTNESS, mCameraProperties->get(CameraProperties::BRIGHTNESS));
+ p.set(TICameraParameters::KEY_SHARPNESS, mCameraProperties->get(CameraProperties::SHARPNESS));
+ p.set(TICameraParameters::KEY_EXPOSURE_MODE, mCameraProperties->get(CameraProperties::EXPOSURE_MODE));
+ p.set(TICameraParameters::KEY_MANUAL_EXPOSURE, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN));
+ p.set(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN));
+ p.set(TICameraParameters::KEY_MANUAL_GAIN_ISO, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN));
+ p.set(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN));
+ p.set(TICameraParameters::KEY_ISO, mCameraProperties->get(CameraProperties::ISO_MODE));
+ p.set(TICameraParameters::KEY_IPP, mCameraProperties->get(CameraProperties::IPP));
+ p.set(TICameraParameters::KEY_GBCE, mCameraProperties->get(CameraProperties::GBCE));
+ p.set(TICameraParameters::KEY_GBCE_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_GBCE));
+ p.set(TICameraParameters::KEY_GLBCE, mCameraProperties->get(CameraProperties::GLBCE));
+ p.set(TICameraParameters::KEY_GLBCE_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_GLBCE));
+ p.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT, mCameraProperties->get(CameraProperties::S3D_PRV_FRAME_LAYOUT));
+ p.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT, mCameraProperties->get(CameraProperties::S3D_CAP_FRAME_LAYOUT));
+ p.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE_MODE));
+ p.set(TICameraParameters::KEY_MANUAL_CONVERGENCE, mCameraProperties->get(CameraProperties::MANUAL_CONVERGENCE));
+ p.set(android::CameraParameters::KEY_VIDEO_STABILIZATION, mCameraProperties->get(CameraProperties::VSTAB));
+ p.set(TICameraParameters::KEY_VNF, mCameraProperties->get(CameraProperties::VNF));
+ p.set(android::CameraParameters::KEY_FOCAL_LENGTH, mCameraProperties->get(CameraProperties::FOCAL_LENGTH));
+ p.set(android::CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::HOR_ANGLE));
+ p.set(android::CameraParameters::KEY_VERTICAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::VER_ANGLE));
+ p.set(TICameraParameters::KEY_SENSOR_ORIENTATION, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION));
+ p.set(TICameraParameters::KEY_EXIF_MAKE, mCameraProperties->get(CameraProperties::EXIF_MAKE));
+ p.set(TICameraParameters::KEY_EXIF_MODEL, mCameraProperties->get(CameraProperties::EXIF_MODEL));
+ p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, mCameraProperties->get(CameraProperties::JPEG_THUMBNAIL_QUALITY));
+ p.set(android::CameraParameters::KEY_VIDEO_FRAME_FORMAT, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar");
+ p.set(android::CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, mCameraProperties->get(CameraProperties::MAX_FD_HW_FACES));
+ p.set(android::CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW, mCameraProperties->get(CameraProperties::MAX_FD_SW_FACES));
+ p.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION, mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION));
+ // Only one area a.k.a Touch AF for now.
+ // TODO: Add support for multiple focus areas.
+ p.set(android::CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, mCameraProperties->get(CameraProperties::MAX_FOCUS_AREAS));
+ p.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK));
+ p.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK));
+ p.set(android::CameraParameters::KEY_MAX_NUM_METERING_AREAS, mCameraProperties->get(CameraProperties::MAX_NUM_METERING_AREAS));
+ p.set(TICameraParameters::RAW_WIDTH, mCameraProperties->get(CameraProperties::RAW_WIDTH));
+ p.set(TICameraParameters::RAW_HEIGHT,mCameraProperties->get(CameraProperties::RAW_HEIGHT));
+
+ // TI extensions for enable/disable algos
+ // Hadcoded for now
+ p.set(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA, android::CameraParameters::FALSE);
+ p.set(TICameraParameters::KEY_ALGO_NSF1, android::CameraParameters::TRUE);
+ p.set(TICameraParameters::KEY_ALGO_NSF2, android::CameraParameters::TRUE);
+ p.set(TICameraParameters::KEY_ALGO_SHARPENING, android::CameraParameters::TRUE);
+ p.set(TICameraParameters::KEY_ALGO_THREELINCOLORMAP, android::CameraParameters::TRUE);
+ p.set(TICameraParameters::KEY_ALGO_GIC, android::CameraParameters::TRUE);
+
+#ifdef MOTOROLA_CAMERA
+ p.set(TICameraParameters::KEY_MOT_LEDFLASH, DEFAULT_INTENSITY);
+ p.set(TICameraParameters::KEY_MOT_LEDTORCH, DEFAULT_INTENSITY);
+#endif
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Stop a previously started preview.
+ @param none
+ @return none
+
+ */
+void CameraHal::forceStopPreview()
+{
+ LOG_FUNCTION_NAME;
+
+ // stop bracketing if it is running
+ if ( mBracketingRunning ) {
+ stopImageBracketing();
+ }
+
+ if(mDisplayAdapter.get() != NULL) {
+ ///Stop the buffer display first
+ mDisplayAdapter->disableDisplay();
+ }
+
+ if(mAppCallbackNotifier.get() != NULL) {
+ //Stop the callback sending
+ mAppCallbackNotifier->stop();
+ mAppCallbackNotifier->flushAndReturnFrames();
+ mAppCallbackNotifier->stopPreviewCallbacks();
+ }
+
+ if ( NULL != mCameraAdapter ) {
+ // only need to send these control commands to state machine if we are
+ // passed the LOADED_PREVIEW_STATE
+ if (mCameraAdapter->getState() > CameraAdapter::LOADED_PREVIEW_STATE) {
+ // according to javadoc...FD should be stopped in stopPreview
+ // and application needs to call startFaceDection again
+ // to restart FD
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_FD);
+ }
+
+ mCameraAdapter->rollbackToInitializedState();
+
+ }
+
+ freePreviewBufs();
+ freePreviewDataBufs();
+
+ mPreviewEnabled = false;
+ mDisplayPaused = false;
+ mPreviewStartInProgress = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Deallocates memory for all the resources held by Camera HAL.
+
+ Frees the following objects- CameraAdapter, AppCallbackNotifier, DisplayAdapter,
+ and Memory Manager
+
+ @param none
+ @return none
+
+ */
+void CameraHal::deinitialize()
+{
+ LOG_FUNCTION_NAME;
+
+ if ( mPreviewEnabled || mDisplayPaused ) {
+ forceStopPreview();
+ }
+
+ mSetPreviewWindowCalled = false;
+
+ if (mSensorListener.get()) {
+ mSensorListener->disableSensor(SensorListener::SENSOR_ORIENTATION);
+ mSensorListener.clear();
+ mSensorListener = NULL;
+ }
+
+ mBufferSourceAdapter_Out.clear();
+ mBufferSourceAdapter_In.clear();
+ mOutAdapters.clear();
+ mInAdapters.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+status_t CameraHal::storeMetaDataInBuffers(bool enable)
+{
+ LOG_FUNCTION_NAME;
+
+ return mAppCallbackNotifier->useMetaDataBufferMode(enable);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void CameraHal::setExternalLocking(bool extBuffLocking)
+{
+ mExternalLocking = extBuffLocking;
+}
+
+void CameraHal::resetPreviewRes(android::CameraParameters *params)
+{
+ LOG_FUNCTION_NAME;
+
+ if ( (mVideoWidth <= 320) && (mVideoHeight <= 240)){
+ params->setPreviewSize(mVideoWidth, mVideoHeight);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+#ifdef MOTOROLA_CAMERA
+#include <cutils/properties.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#define EXT_MODULE_VENDOR_STRING "SHARP,OV8820"
+#define INT_MODULE_VENDOR_STRING "SEMCO,OV7739"
+
+#define DCM_CAM_CONFIG_FILE "/data/system/dcm_camera.config"
+#define CAMERA_ENABLED 0x73
+#define CAMERA_DISABLED 0x45
+
+#define MOT_BURST_COUNT "mot-burst-picture-count"
+#define MOT_BURST_COUNT_VALUES "mot-burst-picture-count-values"
+#define MOT_MAX_BURST_SIZE "mot-max-burst-size"
+//Wide screen aspect ratio (16:9)
+#define WIDE_AR 1.7
+
+// TI supports arbitrary burst limits, so we
+// go with what we've used on other platforms
+#define SUPPORTED_BURSTS "0,1,3,6,9"
+
+#define TORCH_DRIVER_DEVICE "/dev/i2c-3"
+#define TORCH_DEVICE_SLAVE_ADDR 0x53
+#define TORCH_DEVICE_CONTROL_REG 0x10
+#define TORCH_BRIGHTNESS_CONTROL_REG 0xA0
+#define TORCH_DEFAULT_BRIGHTNESS 0x02
+#define TORCH_ENABLE 0x0A
+#define TORCH_DISABLE 0x0
+#define MAX_EXPOSURE_COMPENSATION 30
+
+bool CameraHal::i2cRW(int read_size, int write_size, unsigned char *read_data, unsigned char *write_data)
+{
+
+ int i2cfd = -1;
+ int i,j;
+ int ioctl_ret;
+ struct i2c_msg msgs[2];
+ struct i2c_rdwr_ioctl_data i2c_trans;
+ bool retL = 0;
+
+ enum { I2C_WRITE, I2C_READ };
+ enum { ARG_BUS = 1, ARG_ADDR, ARG_READCNT, ARG_DATA };
+
+ msgs[0].addr = TORCH_DEVICE_SLAVE_ADDR;
+ msgs[0].flags = 0;
+ msgs[0].len = write_size;
+ msgs[0].buf = write_data;
+
+ msgs[1].addr = TORCH_DEVICE_SLAVE_ADDR;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].len = read_size;
+ msgs[1].buf = read_data;
+
+ i2c_trans.msgs = NULL;
+ i2c_trans.nmsgs = 0;
+
+ if ((i2cfd = open(TORCH_DRIVER_DEVICE, O_RDWR)) < 0) {
+ CAMHAL_LOGD("failed to open %s", TORCH_DRIVER_DEVICE);
+ return 1;
+ }
+
+ if ( write_size && read_size ) {
+ i2c_trans.msgs = &msgs[0];
+ i2c_trans.nmsgs = 2;
+ }
+ else if (write_size) {
+ i2c_trans.msgs = &msgs[0];
+ i2c_trans.nmsgs = 1;
+ }
+ else if (read_size) {
+ i2c_trans.msgs = &msgs[1];
+ i2c_trans.nmsgs = 1;
+ }
+ else {
+ goto done;
+ }
+
+ if ( write_size > 0 ) {
+ CAMHAL_LOGD("I2C_WRITE");
+ for( i = 0; i < write_size; i++ )
+ {
+ CAMHAL_LOGD( "%02X ", write_data[i] );
+ }
+ }
+
+ if( (ioctl_ret = ioctl( i2cfd, I2C_RDWR, &(i2c_trans))) < 0 )
+ {
+ CAMHAL_LOGD("* failed driver call: ioctl returned %d", ioctl_ret);
+ retL = 1;
+ goto done;
+ }
+
+
+ if ( read_size > 0 ) {
+ CAMHAL_LOGD("I2C_READ");
+ for( i = 0; i < read_size; i++ )
+ {
+ CAMHAL_LOGD( "%02X ", read_data[i] );
+ }
+ }
+
+done:
+ /* close the hardware */
+ close(i2cfd);
+
+ return retL;
+
+}
+
+unsigned int CameraHal::getFlashIntensity()
+{
+ unsigned int flashIntensity = DEFAULT_INTENSITY;
+ char value[PROPERTY_VALUE_MAX];
+ unsigned long minFlashThreshold;
+
+ if (property_get("ro.media.capture.flashIntensity", value, 0) > 0)
+ {
+ flashIntensity = atoi(value);
+ }
+ if (property_get("ro.media.capture.flashMinV", value, 0) > 0)
+ {
+ minFlashThreshold = atoi(value);
+ }
+ else
+ {
+ minFlashThreshold = FLASH_VOLTAGE_THRESHOLD2;
+ }
+ if ( minFlashThreshold != 0)
+ {
+ int fd = open("/sys/class/power_supply/battery/voltage_now", O_RDONLY);
+ if (fd < 0)
+ {
+ CAMHAL_LOGE("Battery status is unavailable, defaulting Flash intensity to MAX");
+ }
+ else
+ {
+ char buf[8];
+ if ( read(fd, buf, 8) < 0 )
+ {
+ CAMHAL_LOGE("Unable to read battery status, defaulting flash intensity to MAX\n");
+ }
+ else
+ {
+ unsigned long batteryLevel;
+ buf[7] = '\0';
+ batteryLevel = atol(buf);
+ CAMHAL_LOGE("Current battery Level, %d uv", batteryLevel);
+ if (batteryLevel < minFlashThreshold)
+ {
+ CAMHAL_LOGE("Disabling flash due to low Battery");
+ flashIntensity = 0;
+ }
+ else if (batteryLevel < FLASH_VOLTAGE_THRESHOLD1)
+ {
+ flashIntensity = flashIntensity >> 1 ;
+ }
+ }
+ close(fd);
+ }
+ }
+ CAMHAL_LOGE("flashIntensity = %d", flashIntensity);
+ return flashIntensity;
+}
+
+bool CameraHal::SetFlashLedTorch( unsigned intensity )
+{
+ android::CameraParameters params;
+ mCameraAdapter->getParameters(params);
+ CAMHAL_LOGE("CameraHalTI::SetFlashLedTorch %d", intensity);
+ unsigned char write_data[2];
+
+ if (intensity == 0)
+ {
+ write_data[0] = TORCH_DEVICE_CONTROL_REG;
+ write_data[1] = TORCH_DISABLE;
+ i2cRW(0, 2, NULL, write_data);
+ }
+ else
+ {
+ write_data[0] = TORCH_BRIGHTNESS_CONTROL_REG;
+ write_data[1] = TORCH_DEFAULT_BRIGHTNESS;
+ i2cRW(0, 2, NULL, write_data);
+
+ write_data[0] = TORCH_DEVICE_CONTROL_REG;
+ write_data[1] = TORCH_ENABLE;
+ i2cRW(0, 2, NULL, write_data);
+ }
+
+ return true;
+}
+
+#endif
+
+void *
+camera_buffer_get_omx_ptr (CameraBuffer *buffer)
+{
+ CAMHAL_LOGV("buffer_type %d opaque %p", buffer->type, buffer->opaque);
+
+ if (buffer->type == CAMERA_BUFFER_ANW) {
+ buffer_handle_t *handle = (buffer_handle_t *)buffer->opaque;
+ CAMHAL_LOGV("anw %08x", *handle);
+ return (void *)*handle;
+ } else if (buffer->type == CAMERA_BUFFER_ION) {
+ return (void *)buffer->fd;
+ } else {
+ CAMHAL_LOGV("other %08x", buffer->opaque);
+ return (void *)buffer->opaque;
+ }
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/CameraHalCommon.cpp b/camera/CameraHalCommon.cpp
new file mode 100644
index 0000000..ce01528
--- /dev/null
+++ b/camera/CameraHalCommon.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CameraHal.h"
+
+namespace Ti {
+namespace Camera {
+
+const char CameraHal::PARAMS_DELIMITER []= ",";
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+struct timeval CameraHal::ppm_start;
+
+#endif
+
+#if PPM_INSTRUMENTATION
+
+/**
+ @brief PPM instrumentation
+
+ Dumps the current time offset. The time reference point
+ lies within the CameraHAL constructor.
+
+ @param str - log message
+ @return none
+
+ */
+void CameraHal::PPM(const char* str){
+ struct timeval ppm;
+
+ gettimeofday(&ppm, NULL);
+ ppm.tv_sec = ppm.tv_sec - ppm_start.tv_sec;
+ ppm.tv_sec = ppm.tv_sec * 1000000;
+ ppm.tv_sec = ppm.tv_sec + ppm.tv_usec - ppm_start.tv_usec;
+
+ CAMHAL_LOGI("PPM: %s :%ld.%ld ms", str, ( ppm.tv_sec /1000 ), ( ppm.tv_sec % 1000 ));
+}
+
+#elif PPM_INSTRUMENTATION_ABS
+
+/**
+ @brief PPM instrumentation
+
+ Dumps the current time offset. The time reference point
+ lies within the CameraHAL constructor. This implemetation
+ will also dump the abosolute timestamp, which is useful when
+ post calculation is done with data coming from the upper
+ layers (Camera application etc.)
+
+ @param str - log message
+ @return none
+
+ */
+void CameraHal::PPM(const char* str){
+ struct timeval ppm;
+
+ unsigned long long elapsed, absolute;
+ gettimeofday(&ppm, NULL);
+ elapsed = ppm.tv_sec - ppm_start.tv_sec;
+ elapsed *= 1000000;
+ elapsed += ppm.tv_usec - ppm_start.tv_usec;
+ absolute = ppm.tv_sec;
+ absolute *= 1000;
+ absolute += ppm.tv_usec /1000;
+
+ CAMHAL_LOGI("PPM: %s :%llu.%llu ms : %llu ms", str, ( elapsed /1000 ), ( elapsed % 1000 ), absolute);
+}
+
+#endif
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+/**
+ @brief PPM instrumentation
+
+ Calculates and dumps the elapsed time using 'ppm_first' as
+ reference.
+
+ @param str - log message
+ @return none
+
+ */
+void CameraHal::PPM(const char* str, struct timeval* ppm_first, ...){
+ char temp_str[256];
+ struct timeval ppm;
+ unsigned long long absolute;
+ va_list args;
+
+ va_start(args, ppm_first);
+ vsprintf(temp_str, str, args);
+ gettimeofday(&ppm, NULL);
+ absolute = ppm.tv_sec;
+ absolute *= 1000;
+ absolute += ppm.tv_usec /1000;
+ ppm.tv_sec = ppm.tv_sec - ppm_first->tv_sec;
+ ppm.tv_sec = ppm.tv_sec * 1000000;
+ ppm.tv_sec = ppm.tv_sec + ppm.tv_usec - ppm_first->tv_usec;
+
+ CAMHAL_LOGI("PPM: %s :%ld.%ld ms : %llu ms", temp_str, ( ppm.tv_sec /1000 ), ( ppm.tv_sec % 1000 ), absolute);
+
+ va_end(args);
+}
+
+#endif
+
+
+/** Common utility function definitions used all over the HAL */
+
+unsigned int CameraHal::getBPP(const char* format) {
+ unsigned int bytesPerPixel;
+
+ // Calculate bytes per pixel based on the pixel format
+ if (strcmp(format, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ bytesPerPixel = 2;
+ } else if (strcmp(format, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0 ||
+ strcmp(format, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) {
+ bytesPerPixel = 2;
+ } else if (strcmp(format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ bytesPerPixel = 1;
+ } else {
+ bytesPerPixel = 1;
+ }
+
+ return bytesPerPixel;
+}
+
+void CameraHal::getXYFromOffset(unsigned int *x, unsigned int *y,
+ unsigned int offset, unsigned int stride,
+ const char* format)
+{
+ CAMHAL_ASSERT( x && y && format && (0U < stride) );
+
+ *x = (offset % stride) / getBPP(format);
+ *y = (offset / stride);
+}
+
+const char* CameraHal::getPixelFormatConstant(const char* parametersFormat)
+{
+ const char *pixelFormat = NULL;
+
+ if ( NULL != parametersFormat ) {
+ if ( 0 == strcmp(parametersFormat, (const char *) android::CameraParameters::PIXEL_FORMAT_YUV422I) ) {
+ CAMHAL_LOGVA("CbYCrY format selected");
+ pixelFormat = (const char *) android::CameraParameters::PIXEL_FORMAT_YUV422I;
+ } else if ( (0 == strcmp(parametersFormat, (const char *) android::CameraParameters::PIXEL_FORMAT_YUV420SP)) ||
+ (0 == strcmp(parametersFormat, (const char *) android::CameraParameters::PIXEL_FORMAT_YUV420P)) ) {
+ // TODO(XXX): We are treating YV12 the same as YUV420SP
+ CAMHAL_LOGVA("YUV420SP format selected");
+ pixelFormat = (const char *) android::CameraParameters::PIXEL_FORMAT_YUV420SP;
+ } else if ( 0 == strcmp(parametersFormat, (const char *) android::CameraParameters::PIXEL_FORMAT_RGB565) ) {
+ CAMHAL_LOGVA("RGB565 format selected");
+ pixelFormat = (const char *) android::CameraParameters::PIXEL_FORMAT_RGB565;
+ } else if ( 0 == strcmp(parametersFormat, (const char *) android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) ) {
+ CAMHAL_LOGVA("BAYER format selected");
+ pixelFormat = (const char *) android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB;
+ } else if ( 0 == strcmp(parametersFormat, android::CameraParameters::PIXEL_FORMAT_JPEG) ) {
+ CAMHAL_LOGVA("JPEG format selected");
+ pixelFormat = (const char *) android::CameraParameters::PIXEL_FORMAT_JPEG;
+ } else {
+ CAMHAL_LOGEA("Invalid format, NV12 format selected as default");
+ pixelFormat = (const char *) android::CameraParameters::PIXEL_FORMAT_YUV420SP;
+ }
+ } else {
+ CAMHAL_LOGEA("Preview format is NULL, defaulting to NV12");
+ pixelFormat = (const char *) android::CameraParameters::PIXEL_FORMAT_YUV420SP;
+ }
+
+ return pixelFormat;
+}
+
+size_t CameraHal::calculateBufferSize(const char* parametersFormat, int width, int height)
+{
+ int bufferSize = -1;
+
+ if ( NULL != parametersFormat ) {
+ if ( 0 == strcmp(parametersFormat, (const char *) android::CameraParameters::PIXEL_FORMAT_YUV422I) ) {
+ bufferSize = width * height * 2;
+ } else if ( (0 == strcmp(parametersFormat, android::CameraParameters::PIXEL_FORMAT_YUV420SP)) ||
+ (0 == strcmp(parametersFormat, android::CameraParameters::PIXEL_FORMAT_YUV420P)) ) {
+ bufferSize = width * height * 3 / 2;
+ } else if ( 0 == strcmp(parametersFormat, (const char *) android::CameraParameters::PIXEL_FORMAT_RGB565) ) {
+ bufferSize = width * height * 2;
+ } else if ( 0 == strcmp(parametersFormat, (const char *) android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) ) {
+ bufferSize = width * height * 2;
+ } else {
+ CAMHAL_LOGEA("Invalid format");
+ bufferSize = 0;
+ }
+ } else {
+ CAMHAL_LOGEA("Preview format is NULL");
+ bufferSize = 0;
+ }
+
+ return bufferSize;
+}
+
+
+bool CameraHal::parsePair(const char *str, int *first, int *second, char delim)
+{
+ // Find the first integer.
+ char *end;
+ int w = (int)strtol(str, &end, 10);
+ // If a delimeter does not immediately follow, give up.
+ if (*end != delim) {
+ CAMHAL_LOGE("Cannot find delimeter (%c) in str=%s", delim, str);
+ return false;
+ }
+
+ // Find the second integer, immediately after the delimeter.
+ int h = (int)strtol(end+1, &end, 10);
+
+ *first = w;
+ *second = h;
+
+ return true;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/CameraHalUtilClasses.cpp b/camera/CameraHalUtilClasses.cpp
new file mode 100644
index 0000000..53c9a55
--- /dev/null
+++ b/camera/CameraHalUtilClasses.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file CameraHalUtilClasses.cpp
+*
+* This file maps the CameraHardwareInterface to the Camera interfaces on OMAP4 (mainly OMX).
+*
+*/
+
+#include "CameraHal.h"
+
+namespace Ti {
+namespace Camera {
+
+/*--------------------FrameProvider Class STARTS here-----------------------------*/
+
+int FrameProvider::enableFrameNotification(int32_t frameTypes)
+{
+ LOG_FUNCTION_NAME;
+ status_t ret = NO_ERROR;
+
+ ///Enable the frame notification to CameraAdapter (which implements FrameNotifier interface)
+ mFrameNotifier->enableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION
+ , mFrameCallback
+ , NULL
+ , mCookie
+ );
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+int FrameProvider::disableFrameNotification(int32_t frameTypes)
+{
+ LOG_FUNCTION_NAME;
+ status_t ret = NO_ERROR;
+
+ mFrameNotifier->disableMsgType(frameTypes<<MessageNotifier::FRAME_BIT_FIELD_POSITION
+ , mCookie
+ );
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+int FrameProvider::returnFrame(CameraBuffer *frameBuf, CameraFrame::FrameType frameType)
+{
+ status_t ret = NO_ERROR;
+
+ mFrameNotifier->returnFrame(frameBuf, frameType);
+
+ return ret;
+}
+
+void FrameProvider::addFramePointers(CameraBuffer *frameBuf, void *buf)
+{
+ mFrameNotifier->addFramePointers(frameBuf, buf);
+ return;
+}
+
+void FrameProvider::removeFramePointers()
+{
+ mFrameNotifier->removeFramePointers();
+ return;
+}
+
+/*--------------------FrameProvider Class ENDS here-----------------------------*/
+
+/*--------------------EventProvider Class STARTS here-----------------------------*/
+
+int EventProvider::enableEventNotification(int32_t frameTypes)
+{
+ LOG_FUNCTION_NAME;
+ status_t ret = NO_ERROR;
+
+ ///Enable the frame notification to CameraAdapter (which implements FrameNotifier interface)
+ mEventNotifier->enableMsgType(frameTypes<<MessageNotifier::EVENT_BIT_FIELD_POSITION
+ , NULL
+ , mEventCallback
+ , mCookie
+ );
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+int EventProvider::disableEventNotification(int32_t frameTypes)
+{
+ LOG_FUNCTION_NAME;
+ status_t ret = NO_ERROR;
+
+ mEventNotifier->disableMsgType(frameTypes<<MessageNotifier::EVENT_BIT_FIELD_POSITION
+ , mCookie
+ );
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+/*--------------------EventProvider Class ENDS here-----------------------------*/
+
+/*--------------------CameraArea Class STARTS here-----------------------------*/
+
+status_t CameraArea::transfrom(size_t width,
+ size_t height,
+ size_t &top,
+ size_t &left,
+ size_t &areaWidth,
+ size_t &areaHeight)
+{
+ status_t ret = NO_ERROR;
+ size_t hRange, vRange;
+ double hScale, vScale;
+
+ LOG_FUNCTION_NAME
+
+ hRange = CameraArea::RIGHT - CameraArea::LEFT;
+ vRange = CameraArea::BOTTOM - CameraArea::TOP;
+ hScale = ( double ) width / ( double ) hRange;
+ vScale = ( double ) height / ( double ) vRange;
+
+ top = ( mTop + vRange / 2 ) * vScale;
+ left = ( mLeft + hRange / 2 ) * hScale;
+ areaHeight = ( mBottom + vRange / 2 ) * vScale;
+ areaHeight -= top;
+ areaWidth = ( mRight + hRange / 2) * hScale;
+ areaWidth -= left;
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return ret;
+}
+
+status_t CameraArea::checkArea(ssize_t top,
+ ssize_t left,
+ ssize_t bottom,
+ ssize_t right,
+ ssize_t weight)
+{
+
+ //Handles the invalid regin corner case.
+ if ( ( 0 == top ) && ( 0 == left ) && ( 0 == bottom ) && ( 0 == right ) && ( 0 == weight ) ) {
+ return NO_ERROR;
+ }
+
+ if ( ( CameraArea::WEIGHT_MIN > weight ) || ( CameraArea::WEIGHT_MAX < weight ) ) {
+ CAMHAL_LOGEB("Camera area weight is invalid %d", weight);
+ return -EINVAL;
+ }
+
+ if ( ( CameraArea::TOP > top ) || ( CameraArea::BOTTOM < top ) ) {
+ CAMHAL_LOGEB("Camera area top coordinate is invalid %d", top );
+ return -EINVAL;
+ }
+
+ if ( ( CameraArea::TOP > bottom ) || ( CameraArea::BOTTOM < bottom ) ) {
+ CAMHAL_LOGEB("Camera area bottom coordinate is invalid %d", bottom );
+ return -EINVAL;
+ }
+
+ if ( ( CameraArea::LEFT > left ) || ( CameraArea::RIGHT < left ) ) {
+ CAMHAL_LOGEB("Camera area left coordinate is invalid %d", left );
+ return -EINVAL;
+ }
+
+ if ( ( CameraArea::LEFT > right ) || ( CameraArea::RIGHT < right ) ) {
+ CAMHAL_LOGEB("Camera area right coordinate is invalid %d", right );
+ return -EINVAL;
+ }
+
+ if ( left >= right ) {
+ CAMHAL_LOGEA("Camera area left larger than right");
+ return -EINVAL;
+ }
+
+ if ( top >= bottom ) {
+ CAMHAL_LOGEA("Camera area top larger than bottom");
+ return -EINVAL;
+ }
+
+ return NO_ERROR;
+}
+
+status_t CameraArea::parseAreas(const char *area,
+ size_t areaLength,
+ android::Vector<android::sp<CameraArea> > &areas)
+{
+ status_t ret = NO_ERROR;
+ char *ctx;
+ char *pArea = NULL;
+ char *pStart = NULL;
+ char *pEnd = NULL;
+ const char *startToken = "(";
+ const char endToken = ')';
+ const char sep = ',';
+ ssize_t top, left, bottom, right, weight;
+ char *tmpBuffer = NULL;
+ android::sp<CameraArea> currentArea;
+
+ LOG_FUNCTION_NAME
+
+ if ( ( NULL == area ) ||
+ ( 0 >= areaLength ) )
+ {
+ return -EINVAL;
+ }
+
+ tmpBuffer = ( char * ) malloc(areaLength);
+ if ( NULL == tmpBuffer )
+ {
+ return -ENOMEM;
+ }
+
+ memcpy(tmpBuffer, area, areaLength);
+
+ pArea = strtok_r(tmpBuffer, startToken, &ctx);
+
+ do
+ {
+
+ pStart = pArea;
+ if ( NULL == pStart )
+ {
+ CAMHAL_LOGEA("Parsing of the left area coordinate failed!");
+ ret = -EINVAL;
+ break;
+ }
+ else
+ {
+ left = static_cast<ssize_t>(strtol(pStart, &pEnd, 10));
+ }
+
+ if ( sep != *pEnd )
+ {
+ CAMHAL_LOGEA("Parsing of the top area coordinate failed!");
+ ret = -EINVAL;
+ break;
+ }
+ else
+ {
+ top = static_cast<ssize_t>(strtol(pEnd+1, &pEnd, 10));
+ }
+
+ if ( sep != *pEnd )
+ {
+ CAMHAL_LOGEA("Parsing of the right area coordinate failed!");
+ ret = -EINVAL;
+ break;
+ }
+ else
+ {
+ right = static_cast<ssize_t>(strtol(pEnd+1, &pEnd, 10));
+ }
+
+ if ( sep != *pEnd )
+ {
+ CAMHAL_LOGEA("Parsing of the bottom area coordinate failed!");
+ ret = -EINVAL;
+ break;
+ }
+ else
+ {
+ bottom = static_cast<ssize_t>(strtol(pEnd+1, &pEnd, 10));
+ }
+
+ if ( sep != *pEnd )
+ {
+ CAMHAL_LOGEA("Parsing of the weight area coordinate failed!");
+ ret = -EINVAL;
+ break;
+ }
+ else
+ {
+ weight = static_cast<ssize_t>(strtol(pEnd+1, &pEnd, 10));
+ }
+
+ if ( endToken != *pEnd )
+ {
+ CAMHAL_LOGEA("Malformed area!");
+ ret = -EINVAL;
+ break;
+ }
+
+ ret = checkArea(top, left, bottom, right, weight);
+ if ( NO_ERROR != ret ) {
+ break;
+ }
+
+ currentArea = new CameraArea(top, left, bottom, right, weight);
+ CAMHAL_LOGDB("Area parsed [%dx%d, %dx%d] %d",
+ ( int ) top,
+ ( int ) left,
+ ( int ) bottom,
+ ( int ) right,
+ ( int ) weight);
+ if ( NULL != currentArea.get() )
+ {
+ areas.add(currentArea);
+ }
+ else
+ {
+ ret = -ENOMEM;
+ break;
+ }
+
+ pArea = strtok_r(NULL, startToken, &ctx);
+
+ }
+ while ( NULL != pArea );
+
+ if ( NULL != tmpBuffer )
+ {
+ free(tmpBuffer);
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return ret;
+}
+
+bool CameraArea::areAreasDifferent(android::Vector< android::sp<CameraArea> > &area1,
+ android::Vector< android::sp<CameraArea> > &area2) {
+ if (area1.size() != area2.size()) {
+ return true;
+ }
+
+ // not going to care about sorting order for now
+ for (int i = 0; i < area1.size(); i++) {
+ if (!area1.itemAt(i)->compare(area2.itemAt(i))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CameraArea::compare(const android::sp<CameraArea> &area) {
+ return ((mTop == area->mTop) && (mLeft == area->mLeft) &&
+ (mBottom == area->mBottom) && (mRight == area->mRight) &&
+ (mWeight == area->mWeight));
+}
+
+
+/*--------------------CameraArea Class ENDS here-----------------------------*/
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/CameraHal_Module.cpp b/camera/CameraHal_Module.cpp
new file mode 100644
index 0000000..ddddacd
--- /dev/null
+++ b/camera/CameraHal_Module.cpp
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file CameraHal.cpp
+*
+* This file maps the Camera Hardware Interface to V4L2.
+*
+*/
+
+#include <utils/threads.h>
+
+#include "CameraHal.h"
+#include "CameraProperties.h"
+#include "TICameraParameters.h"
+
+
+#ifdef CAMERAHAL_DEBUG_VERBOSE
+# define CAMHAL_LOG_MODULE_FUNCTION_NAME LOG_FUNCTION_NAME
+#else
+# define CAMHAL_LOG_MODULE_FUNCTION_NAME
+#endif
+
+
+namespace Ti {
+namespace Camera {
+
+static CameraProperties gCameraProperties;
+static CameraHal* gCameraHals[MAX_CAMERAS_SUPPORTED];
+static unsigned int gCamerasOpen = 0;
+static android::Mutex gCameraHalDeviceLock;
+
+static int camera_device_open(const hw_module_t* module, const char* name,
+ hw_device_t** device);
+static int camera_device_close(hw_device_t* device);
+static int camera_get_number_of_cameras(void);
+static int camera_get_camera_info(int camera_id, struct camera_info *info);
+
+static struct hw_module_methods_t camera_module_methods = {
+ open: camera_device_open
+};
+
+} // namespace Camera
+} // namespace Ti
+
+
+camera_module_t HAL_MODULE_INFO_SYM = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: CAMERA_HARDWARE_MODULE_ID,
+ name: "TI OMAP CameraHal Module",
+ author: "TI",
+ methods: &Ti::Camera::camera_module_methods,
+ dso: NULL, /* remove compilation warnings */
+ reserved: {0}, /* remove compilation warnings */
+ },
+ get_number_of_cameras: Ti::Camera::camera_get_number_of_cameras,
+ get_camera_info: Ti::Camera::camera_get_camera_info,
+};
+
+
+namespace Ti {
+namespace Camera {
+
+typedef struct ti_camera_device {
+ camera_device_t base;
+ /* TI specific "private" data can go here (base.priv) */
+ int cameraid;
+} ti_camera_device_t;
+
+
+/*******************************************************************
+ * implementation of camera_device_ops functions
+ *******************************************************************/
+
+int camera_set_preview_window(struct camera_device * device,
+ struct preview_stream_ops *window)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->setPreviewWindow(window);
+
+ return rv;
+}
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+int camera_set_extended_preview_ops(struct camera_device * device,
+ preview_stream_extended_ops_t * extendedOps)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ if (!device) {
+ return BAD_VALUE;
+ }
+
+ ti_camera_device_t * const tiDevice = reinterpret_cast<ti_camera_device_t*>(device);
+ gCameraHals[tiDevice->cameraid]->setExtendedPreviewStreamOps(extendedOps);
+
+ return OK;
+}
+
+int camera_set_buffer_source(struct camera_device * device,
+ struct preview_stream_ops *tapin,
+ struct preview_stream_ops *tapout)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->setBufferSource(tapin, tapout);
+
+ return rv;
+}
+
+int camera_release_buffer_source(struct camera_device * device,
+ struct preview_stream_ops *tapin,
+ struct preview_stream_ops *tapout)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->releaseBufferSource(tapin, tapout);
+
+ return rv;
+}
+#endif
+
+void camera_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)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->setCallbacks(notify_cb, data_cb, data_cb_timestamp, get_memory, user);
+}
+
+void camera_enable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->enableMsgType(msg_type);
+}
+
+void camera_disable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->disableMsgType(msg_type);
+}
+
+int camera_msg_type_enabled(struct camera_device * device, int32_t msg_type)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return 0;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ return gCameraHals[ti_dev->cameraid]->msgTypeEnabled(msg_type);
+}
+
+int camera_start_preview(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->startPreview();
+
+ return rv;
+}
+
+void camera_stop_preview(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->stopPreview();
+}
+
+int camera_preview_enabled(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->previewEnabled();
+ return rv;
+}
+
+int camera_store_meta_data_in_buffers(struct camera_device * device, int enable)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ // TODO: meta data buffer not current supported
+ rv = gCameraHals[ti_dev->cameraid]->storeMetaDataInBuffers(enable);
+ return rv;
+ //return enable ? android::INVALID_OPERATION: android::OK;
+}
+
+int camera_start_recording(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->startRecording();
+ return rv;
+}
+
+void camera_stop_recording(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->stopRecording();
+}
+
+int camera_recording_enabled(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->recordingEnabled();
+ return rv;
+}
+
+void camera_release_recording_frame(struct camera_device * device,
+ const void *opaque)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->releaseRecordingFrame(opaque);
+}
+
+int camera_auto_focus(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->autoFocus();
+ return rv;
+}
+
+int camera_cancel_auto_focus(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->cancelAutoFocus();
+ return rv;
+}
+
+int camera_take_picture(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->takePicture(0);
+ return rv;
+}
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+int camera_take_picture_with_parameters(struct camera_device * device, const char *params)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->takePicture(params);
+ return rv;
+}
+#endif
+
+int camera_cancel_picture(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->cancelPicture();
+ return rv;
+}
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+int camera_reprocess(struct camera_device * device, const char *params)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->reprocess(params);
+ return rv;
+}
+
+int camera_cancel_reprocess(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->cancel_reprocess();
+ return rv;
+}
+#endif
+
+int camera_set_parameters(struct camera_device * device, const char *params)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->setParameters(params);
+ return rv;
+}
+
+char* camera_get_parameters(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ char* param = NULL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return NULL;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ param = gCameraHals[ti_dev->cameraid]->getParameters();
+
+ return param;
+}
+
+static void camera_put_parameters(struct camera_device *device, char *parms)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->putParameters(parms);
+}
+
+int camera_send_command(struct camera_device * device,
+ int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ if ( cmd == CAMERA_CMD_SETUP_EXTENDED_OPERATIONS ) {
+ camera_device_extended_ops_t * const ops = static_cast<camera_device_extended_ops_t*>(
+ camera_cmd_send_command_args_to_pointer(arg1, arg2));
+
+ ops->set_extended_preview_ops = camera_set_extended_preview_ops;
+ ops->set_buffer_source = camera_set_buffer_source;
+ ops->release_buffer_source = camera_release_buffer_source;
+ ops->take_picture_with_parameters = camera_take_picture_with_parameters;
+ ops->reprocess = camera_reprocess;
+ ops->cancel_reprocess = camera_cancel_reprocess;
+ return OK;
+ }
+#endif
+
+ rv = gCameraHals[ti_dev->cameraid]->sendCommand(cmd, arg1, arg2);
+ return rv;
+}
+
+void camera_release(struct camera_device * device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->release();
+}
+
+int camera_dump(struct camera_device * device, int fd)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->dump(fd);
+ return rv;
+}
+
+extern "C" void heaptracker_free_leaked_memory(void);
+
+int camera_device_close(hw_device_t* device)
+{
+ CAMHAL_LOG_MODULE_FUNCTION_NAME;
+
+ int ret = 0;
+ ti_camera_device_t* ti_dev = NULL;
+
+ android::AutoMutex lock(gCameraHalDeviceLock);
+
+ if (!device) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ if (ti_dev) {
+ if (gCameraHals[ti_dev->cameraid]) {
+ delete gCameraHals[ti_dev->cameraid];
+ gCameraHals[ti_dev->cameraid] = NULL;
+ gCamerasOpen--;
+ }
+
+ if (ti_dev->base.ops) {
+ free(ti_dev->base.ops);
+ }
+ free(ti_dev);
+ }
+done:
+#ifdef HEAPTRACKER
+ heaptracker_free_leaked_memory();
+#endif
+ return ret;
+}
+
+/*******************************************************************
+ * implementation of camera_module functions
+ *******************************************************************/
+
+/* open device handle to one of the cameras
+ *
+ * assume camera service will keep singleton of each camera
+ * so this function will always only be called once per camera instance
+ */
+
+int camera_device_open(const hw_module_t* module, const char* name,
+ hw_device_t** device)
+{
+ int rv = 0;
+ int num_cameras = 0;
+ int cameraid;
+ ti_camera_device_t* camera_device = NULL;
+ camera_device_ops_t* camera_ops = NULL;
+ CameraHal* camera = NULL;
+ CameraProperties::Properties* properties = NULL;
+
+ android::AutoMutex lock(gCameraHalDeviceLock);
+
+ CAMHAL_LOGI("camera_device open");
+
+ if (name != NULL) {
+ cameraid = atoi(name);
+ num_cameras = gCameraProperties.camerasSupported();
+
+ if(cameraid > num_cameras)
+ {
+ CAMHAL_LOGE("camera service provided cameraid out of bounds, "
+ "cameraid = %d, num supported = %d",
+ cameraid, num_cameras);
+ rv = -EINVAL;
+ goto fail;
+ }
+
+ if(gCamerasOpen >= MAX_SIMUL_CAMERAS_SUPPORTED)
+ {
+ CAMHAL_LOGE("maximum number of cameras already open");
+ rv = -ENOMEM;
+ goto fail;
+ }
+
+ camera_device = (ti_camera_device_t*)malloc(sizeof(*camera_device));
+ if(!camera_device)
+ {
+ CAMHAL_LOGE("camera_device allocation fail");
+ rv = -ENOMEM;
+ goto fail;
+ }
+
+ camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));
+ if(!camera_ops)
+ {
+ CAMHAL_LOGE("camera_ops allocation fail");
+ rv = -ENOMEM;
+ goto fail;
+ }
+
+ memset(camera_device, 0, sizeof(*camera_device));
+ memset(camera_ops, 0, sizeof(*camera_ops));
+
+ camera_device->base.common.tag = HARDWARE_DEVICE_TAG;
+ camera_device->base.common.version = 0;
+ camera_device->base.common.module = (hw_module_t *)(module);
+ camera_device->base.common.close = camera_device_close;
+ camera_device->base.ops = camera_ops;
+
+ camera_ops->set_preview_window = camera_set_preview_window;
+ camera_ops->set_callbacks = camera_set_callbacks;
+ camera_ops->enable_msg_type = camera_enable_msg_type;
+ camera_ops->disable_msg_type = camera_disable_msg_type;
+ camera_ops->msg_type_enabled = camera_msg_type_enabled;
+ camera_ops->start_preview = camera_start_preview;
+ camera_ops->stop_preview = camera_stop_preview;
+ camera_ops->preview_enabled = camera_preview_enabled;
+ camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers;
+ camera_ops->start_recording = camera_start_recording;
+ camera_ops->stop_recording = camera_stop_recording;
+ camera_ops->recording_enabled = camera_recording_enabled;
+ camera_ops->release_recording_frame = camera_release_recording_frame;
+ camera_ops->auto_focus = camera_auto_focus;
+ camera_ops->cancel_auto_focus = camera_cancel_auto_focus;
+ camera_ops->take_picture = camera_take_picture;
+ camera_ops->cancel_picture = camera_cancel_picture;
+ camera_ops->set_parameters = camera_set_parameters;
+ camera_ops->get_parameters = camera_get_parameters;
+ camera_ops->put_parameters = camera_put_parameters;
+ camera_ops->send_command = camera_send_command;
+ camera_ops->release = camera_release;
+ camera_ops->dump = camera_dump;
+
+ *device = &camera_device->base.common;
+
+ // -------- TI specific stuff --------
+
+ camera_device->cameraid = cameraid;
+
+ if(gCameraProperties.getProperties(cameraid, &properties) < 0)
+ {
+ CAMHAL_LOGE("Couldn't get camera properties");
+ rv = -ENOMEM;
+ goto fail;
+ }
+
+ camera = new CameraHal(cameraid);
+
+ if(!camera)
+ {
+ CAMHAL_LOGE("Couldn't create instance of CameraHal class");
+ rv = -ENOMEM;
+ goto fail;
+ }
+
+ if(properties && (camera->initialize(properties) != NO_ERROR))
+ {
+ CAMHAL_LOGE("Couldn't initialize camera instance");
+ rv = -ENODEV;
+ goto fail;
+ }
+
+ gCameraHals[cameraid] = camera;
+ gCamerasOpen++;
+ }
+
+ return rv;
+
+fail:
+ if(camera_device) {
+ free(camera_device);
+ camera_device = NULL;
+ }
+ if(camera_ops) {
+ free(camera_ops);
+ camera_ops = NULL;
+ }
+ if(camera) {
+ delete camera;
+ camera = NULL;
+ }
+ *device = NULL;
+ return rv;
+}
+
+int camera_get_number_of_cameras(void)
+{
+ int num_cameras = MAX_CAMERAS_SUPPORTED;
+
+ // this going to be the first call from camera service
+ // initialize camera properties here...
+ if(gCameraProperties.initialize() != NO_ERROR)
+ {
+ CAMHAL_LOGEA("Unable to create or initialize CameraProperties");
+ return NULL;
+ }
+
+ num_cameras = gCameraProperties.camerasSupported();
+
+ return num_cameras;
+}
+
+int camera_get_camera_info(int camera_id, struct camera_info *info)
+{
+ int rv = 0;
+ int face_value = CAMERA_FACING_BACK;
+ int orientation = 0;
+ const char *valstr = NULL;
+ CameraProperties::Properties* properties = NULL;
+
+ // this going to be the first call from camera service
+ // initialize camera properties here...
+ if(gCameraProperties.initialize() != NO_ERROR)
+ {
+ CAMHAL_LOGEA("Unable to create or initialize CameraProperties");
+ rv = -EINVAL;
+ goto end;
+ }
+
+ //Get camera properties for camera index
+ if(gCameraProperties.getProperties(camera_id, &properties) < 0)
+ {
+ CAMHAL_LOGE("Couldn't get camera properties");
+ rv = -EINVAL;
+ goto end;
+ }
+
+ if(properties)
+ {
+ valstr = properties->get(CameraProperties::FACING_INDEX);
+ if(valstr != NULL)
+ {
+ if (strcmp(valstr, TICameraParameters::FACING_FRONT) == 0)
+ {
+#ifndef TREAT_FRONT_AS_BACK
+ face_value = CAMERA_FACING_FRONT;
+#else
+ face_value = CAMERA_FACING_BACK;
+#endif
+ }
+ else if (strcmp(valstr, TICameraParameters::FACING_BACK) == 0)
+ {
+ face_value = CAMERA_FACING_BACK;
+ }
+ }
+
+ valstr = properties->get(CameraProperties::ORIENTATION_INDEX);
+ if(valstr != NULL)
+ {
+ orientation = atoi(valstr);
+ }
+ }
+ else
+ {
+ CAMHAL_LOGEB("getProperties() returned a NULL property set for Camera id %d", camera_id);
+ }
+
+ info->facing = face_value;
+ info->orientation = orientation;
+
+end:
+ return rv;
+}
+
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
new file mode 100644
index 0000000..82b1da4
--- /dev/null
+++ b/camera/CameraParameters.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file CameraProperties.cpp
+*
+* This file maps the CameraHardwareInterface to the Camera interfaces on OMAP4 (mainly OMX).
+*
+*/
+
+#include "CameraProperties.h"
+
+namespace Ti {
+namespace Camera {
+
+const char CameraProperties::INVALID[]="prop-invalid-key";
+const char CameraProperties::CAMERA_NAME[]="prop-camera-name";
+const char CameraProperties::CAMERA_SENSOR_INDEX[]="prop-sensor-index";
+const char CameraProperties::CAMERA_SENSOR_ID[] = "prop-sensor-id";
+const char CameraProperties::ORIENTATION_INDEX[]="prop-orientation";
+const char CameraProperties::FACING_INDEX[]="prop-facing";
+const char CameraProperties::SUPPORTED_PREVIEW_SIZES[] = "prop-preview-size-values";
+const char CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES[] = "prop-preview-subsampled-size-values";
+const char CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES[] = "prop-preview-topbottom-size-values";
+const char CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES[] = "prop-preview-sidebyside-size-values";
+const char CameraProperties::SUPPORTED_PREVIEW_FORMATS[] = "prop-preview-format-values";
+const char CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES[] = "prop-preview-frame-rate-values";
+const char CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES_EXT[] = "prop-preview-frame-rate-ext-values";
+const char CameraProperties::SUPPORTED_PICTURE_SIZES[] = "prop-picture-size-values";
+const char CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES[] = "prop-picture-subsampled-size-values";
+const char CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES[] = "prop-picture-topbottom-size-values";
+const char CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES[] = "prop-picture-sidebyside-size-values";
+const char CameraProperties::SUPPORTED_PICTURE_FORMATS[] = "prop-picture-format-values";
+const char CameraProperties::SUPPORTED_THUMBNAIL_SIZES[] = "prop-jpeg-thumbnail-size-values";
+const char CameraProperties::SUPPORTED_WHITE_BALANCE[] = "prop-whitebalance-values";
+const char CameraProperties::SUPPORTED_EFFECTS[] = "prop-effect-values";
+const char CameraProperties::SUPPORTED_ANTIBANDING[] = "prop-antibanding-values";
+const char CameraProperties::SUPPORTED_EXPOSURE_MODES[] = "prop-exposure-mode-values";
+const char CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN[] = "prop-manual-exposure-min";
+const char CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MAX[] = "prop-manual-exposure-max";
+const char CameraProperties::SUPPORTED_MANUAL_EXPOSURE_STEP[] = "prop-manual-exposure-step";
+const char CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN[] = "prop-manual-gain-iso-min";
+const char CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MAX[] = "prop-manual-gain-iso-max";
+const char CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_STEP[] = "prop-manual-gain-iso-step";
+const char CameraProperties::SUPPORTED_EV_MAX[] = "prop-ev-compensation-max";
+const char CameraProperties::SUPPORTED_EV_MIN[] = "prop-ev-compensation-min";
+const char CameraProperties::SUPPORTED_EV_STEP[] = "prop-ev-compensation-step";
+const char CameraProperties::SUPPORTED_ISO_VALUES[] = "prop-iso-mode-values";
+const char CameraProperties::SUPPORTED_SCENE_MODES[] = "prop-scene-mode-values";
+const char CameraProperties::SUPPORTED_FLASH_MODES[] = "prop-flash-mode-values";
+const char CameraProperties::SUPPORTED_FOCUS_MODES[] = "prop-focus-mode-values";
+const char CameraProperties::REQUIRED_PREVIEW_BUFS[] = "prop-required-preview-bufs";
+const char CameraProperties::REQUIRED_IMAGE_BUFS[] = "prop-required-image-bufs";
+const char CameraProperties::SUPPORTED_ZOOM_RATIOS[] = "prop-zoom-ratios";
+const char CameraProperties::SUPPORTED_ZOOM_STAGES[] = "prop-zoom-stages";
+const char CameraProperties::SUPPORTED_IPP_MODES[] = "prop-ipp-values";
+const char CameraProperties::SMOOTH_ZOOM_SUPPORTED[] = "prop-smooth-zoom-supported";
+const char CameraProperties::ZOOM_SUPPORTED[] = "prop-zoom-supported";
+const char CameraProperties::PREVIEW_SIZE[] = "prop-preview-size-default";
+const char CameraProperties::PREVIEW_FORMAT[] = "prop-preview-format-default";
+const char CameraProperties::PREVIEW_FRAME_RATE[] = "prop-preview-frame-rate-default";
+const char CameraProperties::ZOOM[] = "prop-zoom-default";
+const char CameraProperties::PICTURE_SIZE[] = "prop-picture-size-default";
+const char CameraProperties::PICTURE_FORMAT[] = "prop-picture-format-default";
+const char CameraProperties::JPEG_THUMBNAIL_SIZE[] = "prop-jpeg-thumbnail-size-default";
+const char CameraProperties::WHITEBALANCE[] = "prop-whitebalance-default";
+const char CameraProperties::EFFECT[] = "prop-effect-default";
+const char CameraProperties::ANTIBANDING[] = "prop-antibanding-default";
+const char CameraProperties::EXPOSURE_MODE[] = "prop-exposure-mode-default";
+const char CameraProperties::EV_COMPENSATION[] = "prop-ev-compensation-default";
+const char CameraProperties::ISO_MODE[] = "prop-iso-mode-default";
+const char CameraProperties::FOCUS_MODE[] = "prop-focus-mode-default";
+const char CameraProperties::SCENE_MODE[] = "prop-scene-mode-default";
+const char CameraProperties::FLASH_MODE[] = "prop-flash-mode-default";
+const char CameraProperties::JPEG_QUALITY[] = "prop-jpeg-quality-default";
+const char CameraProperties::CONTRAST[] = "prop-contrast-default";
+const char CameraProperties::BRIGHTNESS[] = "prop-brightness-default";
+const char CameraProperties::SATURATION[] = "prop-saturation-default";
+const char CameraProperties::SHARPNESS[] = "prop-sharpness-default";
+const char CameraProperties::IPP[] = "prop-ipp-default";
+const char CameraProperties::GBCE[] = "prop-gbce-default";
+const char CameraProperties::SUPPORTED_GBCE[] = "prop-gbce-supported";
+const char CameraProperties::GLBCE[] = "prop-glbce-default";
+const char CameraProperties::SUPPORTED_GLBCE[] = "prop-glbce-supported";
+const char CameraProperties::S3D_PRV_FRAME_LAYOUT[] = "prop-s3d-prv-frame-layout";
+const char CameraProperties::S3D_PRV_FRAME_LAYOUT_VALUES[] = "prop-s3d-prv-frame-layout-values";
+const char CameraProperties::S3D_CAP_FRAME_LAYOUT[] = "prop-s3d-cap-frame-layout";
+const char CameraProperties::S3D_CAP_FRAME_LAYOUT_VALUES[] = "prop-s3d-cap-frame-layout-values";
+const char CameraProperties::AUTOCONVERGENCE_MODE[] = "prop-auto-convergence-mode";
+const char CameraProperties::AUTOCONVERGENCE_MODE_VALUES[] = "prop-auto-convergence-mode-values";
+const char CameraProperties::MANUAL_CONVERGENCE[] = "prop-manual-convergence";
+const char CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MIN[] = "prop-supported-manual-convergence-min";
+const char CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MAX[] = "prop-supported-manual-convergence-max";
+const char CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_STEP[] = "prop-supported-manual-convergence-step";
+const char CameraProperties::VSTAB[] = "prop-vstab-default";
+const char CameraProperties::VSTAB_SUPPORTED[] = "prop-vstab-supported";
+const char CameraProperties::VNF[] = "prop-vnf-default";
+const char CameraProperties::VNF_SUPPORTED[] = "prop-vnf-supported";
+const char CameraProperties::REVISION[] = "prop-revision";
+const char CameraProperties::FOCAL_LENGTH[] = "prop-focal-length";
+const char CameraProperties::HOR_ANGLE[] = "prop-horizontal-angle";
+const char CameraProperties::VER_ANGLE[] = "prop-vertical-angle";
+const char CameraProperties::FRAMERATE_RANGE[] = "prop-framerate-range-default";
+const char CameraProperties::FRAMERATE_RANGE_SUPPORTED[]="prop-framerate-range-values";
+const char CameraProperties::FRAMERATE_RANGE_EXT_SUPPORTED[]="prop-framerate-range-ext-values";
+const char CameraProperties::SENSOR_ORIENTATION[]= "sensor-orientation";
+const char CameraProperties::SENSOR_ORIENTATION_VALUES[]= "sensor-orientation-values";
+const char CameraProperties::EXIF_MAKE[] = "prop-exif-make";
+const char CameraProperties::EXIF_MODEL[] = "prop-exif-model";
+const char CameraProperties::JPEG_THUMBNAIL_QUALITY[] = "prop-jpeg-thumbnail-quality-default";
+const char CameraProperties::MAX_FOCUS_AREAS[] = "prop-max-focus-areas";
+const char CameraProperties::MAX_FD_HW_FACES[] = "prop-max-fd-hw-faces";
+const char CameraProperties::MAX_FD_SW_FACES[] = "prop-max-fd-sw-faces";
+const char CameraProperties::AUTO_EXPOSURE_LOCK[] = "prop-auto-exposure-lock";
+const char CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED[] = "prop-auto-exposure-lock-supported";
+const char CameraProperties::AUTO_WHITEBALANCE_LOCK[] = "prop-auto-whitebalance-lock";
+const char CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED[] = "prop-auto-whitebalance-lock-supported";
+const char CameraProperties::MAX_NUM_METERING_AREAS[] = "prop-max-num-metering-areas";
+const char CameraProperties::METERING_AREAS[] = "prop-metering-areas";
+const char CameraProperties::VIDEO_SNAPSHOT_SUPPORTED[] = "prop-video-snapshot-supported";
+const char CameraProperties::VIDEO_SIZE[] = "video-size";
+const char CameraProperties::SUPPORTED_VIDEO_SIZES[] = "video-size-values";
+const char CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED[] = "prop-mechanical-misalignment-correction-supported";
+const char CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION[] = "prop-mechanical-misalignment-correction";
+const char CameraProperties::CAP_MODE_VALUES[] = "prop-mode-values";
+const char CameraProperties::RAW_WIDTH[] = "prop-raw-width-values";
+const char CameraProperties::RAW_HEIGHT[] = "prop-raw-height-values";
+const char CameraProperties::MAX_PICTURE_WIDTH[] = "prop-max-picture-width";
+const char CameraProperties::MAX_PICTURE_HEIGHT[] = "prop-max-picture-height";
+
+const char CameraProperties::DEFAULT_VALUE[] = "";
+
+const char CameraProperties::PARAMS_DELIMITER []= ",";
+
+// Returns the properties class for a specific Camera
+// Each value is indexed by the CameraProperties::CameraPropertyIndex enum
+int CameraProperties::getProperties(int cameraIndex, CameraProperties::Properties** properties)
+{
+ LOG_FUNCTION_NAME;
+
+ if(cameraIndex >= mCamerasSupported)
+ {
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ *properties = mCameraProps+cameraIndex;
+
+ LOG_FUNCTION_NAME_EXIT;
+ return 0;
+}
+
+void CameraProperties::Properties::set(const char * const prop, const char * const value) {
+ CAMHAL_ASSERT(prop);
+
+ if ( !value ) {
+ mProperties[mCurrentMode].removeItem(android::String8(prop));
+ } else {
+ mProperties[mCurrentMode].replaceValueFor(android::String8(prop), android::String8(value));
+ }
+}
+
+void CameraProperties::Properties::set(const char * const prop, const int value) {
+ char s_val[30];
+ sprintf(s_val, "%d", value);
+ set(prop, s_val);
+}
+
+const char* CameraProperties::Properties::get(const char * prop) const {
+ return mProperties[mCurrentMode].valueFor(android::String8(prop)).string();
+}
+
+int CameraProperties::Properties::getInt(const char * prop) const {
+ android::String8 value = mProperties[mCurrentMode].valueFor(android::String8(prop));
+ if (value.isEmpty()) {
+ return -1;
+ }
+ return strtol(value, 0, 0);
+}
+
+void CameraProperties::Properties::setSensorIndex(int idx) {
+ OperatingMode originalMode = getMode();
+ for ( int i = 0 ; i < MODE_MAX ; i++ ) {
+ setMode(static_cast<OperatingMode>(i));
+ set(CAMERA_SENSOR_INDEX, idx);
+ }
+ setMode(originalMode);
+}
+
+void CameraProperties::Properties::setMode(OperatingMode mode) {
+ CAMHAL_ASSERT(mode >= 0 && mode < MODE_MAX);
+ mCurrentMode = mode;
+}
+
+OperatingMode CameraProperties::Properties::getMode() const {
+ return mCurrentMode;
+}
+
+void CameraProperties::Properties::dump() {
+ CAMHAL_LOGD("================================");
+ CAMHAL_LOGD("Dumping properties for camera: %d", getInt("prop-sensor-index"));
+
+ for (size_t i = 0; i < mProperties[mCurrentMode].size(); i++) {
+ CAMHAL_LOGD("%s = %s",
+ mProperties[mCurrentMode].keyAt(i).string(),
+ mProperties[mCurrentMode].valueAt(i).string());
+ }
+
+ CAMHAL_LOGD("--------------------------------");
+}
+
+const char* CameraProperties::Properties::keyAt(const unsigned int index) const {
+ if (index < mProperties[mCurrentMode].size()) {
+ return mProperties[mCurrentMode].keyAt(index).string();
+ }
+ return NULL;
+}
+
+const char* CameraProperties::Properties::valueAt(const unsigned int index) const {
+ if (index < mProperties[mCurrentMode].size()) {
+ return mProperties[mCurrentMode].valueAt(index).string();
+ }
+ return NULL;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/CameraProperties.cpp b/camera/CameraProperties.cpp
new file mode 100644
index 0000000..93bc953
--- /dev/null
+++ b/camera/CameraProperties.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file CameraProperties.cpp
+*
+* This file maps the CameraHardwareInterface to the Camera interfaces on OMAP4 (mainly OMX).
+*
+*/
+
+#include "CameraProperties.h"
+
+#define CAMERA_ROOT "CameraRoot"
+#define CAMERA_INSTANCE "CameraInstance"
+
+namespace Ti {
+namespace Camera {
+
+// lower entries have higher priority
+static const char* g_camera_adapters[] = {
+#ifdef OMAP4_SUPPORT_OMX_CAMERA_ADAPTER
+ "libomxcameraadapter.so",
+#endif
+#ifdef OMAP4_SUPPORT_USB_CAMERA_ADAPTER
+ "libusbcameraadapter.so"
+#endif
+};
+
+/*********************************************************
+ CameraProperties - public function implemetation
+**********************************************************/
+
+CameraProperties::CameraProperties() : mCamerasSupported(0)
+{
+ LOG_FUNCTION_NAME;
+
+ mCamerasSupported = 0;
+ mInitialized = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+CameraProperties::~CameraProperties()
+{
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+// Initializes the CameraProperties class
+status_t CameraProperties::initialize()
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret;
+
+ android::AutoMutex lock(mLock);
+
+ if(mInitialized)
+ return NO_ERROR;
+
+ ret = loadProperties();
+
+ if (ret == NO_ERROR) {
+ mInitialized = 1;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+extern "C" status_t CameraAdapter_Capabilities(CameraProperties::Properties* properties_array,
+ int starting_camera, int max_camera, int & supported_cameras);
+
+///Loads all the Camera related properties
+status_t CameraProperties::loadProperties()
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+
+ //Must be re-initialized here, since loadProperties() could potentially be called more than once.
+ mCamerasSupported = 0;
+
+ // adapter updates capabilities and we update camera count
+ const status_t err = CameraAdapter_Capabilities(mCameraProps, mCamerasSupported,
+ MAX_CAMERAS_SUPPORTED, mCamerasSupported);
+
+ if(err != NO_ERROR) {
+ CAMHAL_LOGE("error while getting capabilities");
+ ret = UNKNOWN_ERROR;
+ } else if (mCamerasSupported == 0) {
+ CAMHAL_LOGE("camera busy. properties not loaded. num_cameras = %d", mCamerasSupported);
+ ret = UNKNOWN_ERROR;
+ } else if (mCamerasSupported > MAX_CAMERAS_SUPPORTED) {
+ CAMHAL_LOGE("returned too many adapaters");
+ ret = UNKNOWN_ERROR;
+ } else {
+ CAMHAL_LOGI("num_cameras = %d", mCamerasSupported);
+
+ for (int i = 0; i < mCamerasSupported; i++) {
+ mCameraProps[i].setSensorIndex(i);
+ mCameraProps[i].dump();
+ }
+ }
+
+ CAMHAL_LOGV("mCamerasSupported = %d", mCamerasSupported);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+// Returns the number of Cameras found
+int CameraProperties::camerasSupported()
+{
+ LOG_FUNCTION_NAME;
+ return mCamerasSupported;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/DecoderFactory.cpp b/camera/DecoderFactory.cpp
new file mode 100644
index 0000000..846fda4
--- /dev/null
+++ b/camera/DecoderFactory.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FrameDecoder.h"
+#include "SwFrameDecoder.h"
+#include "OmxFrameDecoder.h"
+#include "CameraHal.h"
+#include "DecoderFactory.h"
+
+namespace Ti {
+namespace Camera {
+
+
+FrameDecoder* DecoderFactory::createDecoderByType(DecoderType type, bool forceSwDecoder) {
+ FrameDecoder* decoder = NULL;
+ switch (type) {
+ case DecoderType_MJPEG: {
+
+ if (!forceSwDecoder) {
+ decoder = new OmxFrameDecoder(DecoderType_MJPEG);
+ CAMHAL_LOGD("Using HW Decoder for MJPEG");
+ } else {
+ decoder = new SwFrameDecoder();
+ CAMHAL_LOGD("Using SW Decoder for MJPEG");
+ }
+
+ //TODO add logic that handle verification is HW Decoder is available ?
+ // And if no - create SW decoder.
+ break;
+ }
+ case DecoderType_H264: {
+ decoder = new OmxFrameDecoder(DecoderType_H264);
+ CAMHAL_LOGD("Using HW Decoder for H264");
+ break;
+ }
+ default: {
+ CAMHAL_LOGE("Unrecognized decoder type %d", type);
+ }
+ }
+
+ return decoder;
+}
+
+} // namespace Camera
+} // namespace Ti
+
diff --git a/camera/Decoder_libjpeg.cpp b/camera/Decoder_libjpeg.cpp
new file mode 100644
index 0000000..35c343f
--- /dev/null
+++ b/camera/Decoder_libjpeg.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Decoder_libjpeg.h"
+
+extern "C" {
+ #include "jpeglib.h"
+ #include "jerror.h"
+}
+
+#define NUM_COMPONENTS_IN_YUV 3
+
+namespace Ti {
+namespace Camera {
+
+/* JPEG DHT Segment omitted from MJPEG data */
+static unsigned char jpeg_odml_dht[0x1a6] = {
+ 0xff, 0xd8, /* Start of Image */
+ 0xff, 0xc4, 0x01, 0xa2, /* Define Huffman Table */
+
+ 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+
+ 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+
+ 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa,
+
+ 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+struct libjpeg_source_mgr : jpeg_source_mgr {
+ libjpeg_source_mgr(unsigned char *buffer_ptr, int len);
+ ~libjpeg_source_mgr();
+
+ unsigned char *mBufferPtr;
+ int mFilledLen;
+};
+
+static void libjpeg_init_source(j_decompress_ptr cinfo) {
+ libjpeg_source_mgr* src = (libjpeg_source_mgr*)cinfo->src;
+ src->next_input_byte = (const JOCTET*)src->mBufferPtr;
+ src->bytes_in_buffer = 0;
+ src->current_offset = 0;
+}
+
+static boolean libjpeg_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
+ libjpeg_source_mgr* src = (libjpeg_source_mgr*)cinfo->src;
+ src->current_offset = byte_offset;
+ src->next_input_byte = (const JOCTET*)src->mBufferPtr + byte_offset;
+ src->bytes_in_buffer = 0;
+ return TRUE;
+}
+
+static boolean libjpeg_fill_input_buffer(j_decompress_ptr cinfo) {
+ libjpeg_source_mgr* src = (libjpeg_source_mgr*)cinfo->src;
+ src->current_offset += src->mFilledLen;
+ src->next_input_byte = src->mBufferPtr;
+ src->bytes_in_buffer = src->mFilledLen;
+ return TRUE;
+}
+
+static void libjpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
+ libjpeg_source_mgr* src = (libjpeg_source_mgr*)cinfo->src;
+
+ if (num_bytes > (long)src->bytes_in_buffer) {
+ CAMHAL_LOGEA("\n\n\n libjpeg_skip_input_data - num_bytes > (long)src->bytes_in_buffer \n\n\n");
+ } else {
+ src->next_input_byte += num_bytes;
+ src->bytes_in_buffer -= num_bytes;
+ }
+}
+
+static boolean libjpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
+ libjpeg_source_mgr* src = (libjpeg_source_mgr*)cinfo->src;
+ src->next_input_byte = (const JOCTET*)src->mBufferPtr;
+ src->bytes_in_buffer = 0;
+ return TRUE;
+}
+
+static void libjpeg_term_source(j_decompress_ptr /*cinfo*/) {}
+
+libjpeg_source_mgr::libjpeg_source_mgr(unsigned char *buffer_ptr, int len) : mBufferPtr(buffer_ptr), mFilledLen(len) {
+ init_source = libjpeg_init_source;
+ fill_input_buffer = libjpeg_fill_input_buffer;
+ skip_input_data = libjpeg_skip_input_data;
+ resync_to_restart = libjpeg_resync_to_restart;
+ term_source = libjpeg_term_source;
+ seek_input_data = libjpeg_seek_input_data;
+}
+
+libjpeg_source_mgr::~libjpeg_source_mgr() {}
+
+Decoder_libjpeg::Decoder_libjpeg()
+{
+ mWidth = 0;
+ mHeight = 0;
+ Y_Plane = NULL;
+ U_Plane = NULL;
+ V_Plane = NULL;
+ UV_Plane = NULL;
+}
+
+Decoder_libjpeg::~Decoder_libjpeg()
+{
+ release();
+}
+
+void Decoder_libjpeg::release()
+{
+ if (Y_Plane) {
+ free(Y_Plane);
+ Y_Plane = NULL;
+ }
+ if (U_Plane) {
+ free(U_Plane);
+ U_Plane = NULL;
+ }
+ if (V_Plane) {
+ free(V_Plane);
+ V_Plane = NULL;
+ }
+ if (UV_Plane) {
+ free(UV_Plane);
+ UV_Plane = NULL;
+ }
+}
+
+int Decoder_libjpeg::readDHTSize()
+{
+ return sizeof(jpeg_odml_dht);
+}
+
+// 0xFF 0xC4 - DHT (Define Huffman Table) marker
+// 0xFF 0xD9 - SOI (Start Of Image) marker
+// 0xFF 0xD9 - EOI (End Of Image) marker
+// This function return true if if found DHT
+bool Decoder_libjpeg::isDhtExist(unsigned char *jpeg_src, int filled_len) {
+ if (filled_len <= 0) {
+ return false;
+ }
+
+ for (int i = 1; i < filled_len; i++) {
+ if((jpeg_src[i - 1] == 0xFF) && (jpeg_src[i] == 0xC4)) {
+ CAMHAL_LOGD("Found DHT (Define Huffman Table) marker");
+ return true;
+ }
+ }
+ return false;
+}
+
+int Decoder_libjpeg::appendDHT(unsigned char *jpeg_src, int filled_len, unsigned char *jpeg_with_dht_buffer, int buff_size)
+{
+ /* Appending DHT to JPEG */
+
+ int len = filled_len + sizeof(jpeg_odml_dht) - 2; // final length of jpeg data
+ if (len > buff_size) {
+ CAMHAL_LOGEA("\n\n\n Buffer size too small. filled_len=%d, buff_size=%d, sizeof(jpeg_odml_dht)=%d\n\n\n", filled_len, buff_size, sizeof(jpeg_odml_dht));
+ return 0;
+ }
+
+ memcpy(jpeg_with_dht_buffer, jpeg_odml_dht, sizeof(jpeg_odml_dht));
+ memcpy((jpeg_with_dht_buffer + sizeof(jpeg_odml_dht)), jpeg_src + 2, (filled_len - 2));
+ return len;
+}
+
+
+bool Decoder_libjpeg::decode(unsigned char *jpeg_src, int filled_len, unsigned char *nv12_buffer, int stride)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ struct libjpeg_source_mgr s_mgr(jpeg_src, filled_len);
+
+ if (filled_len == 0)
+ return false;
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+
+ cinfo.src = &s_mgr;
+ int status = jpeg_read_header(&cinfo, true);
+ if (status != JPEG_HEADER_OK) {
+ CAMHAL_LOGEA("jpeg header corrupted");
+ return false;
+ }
+
+ cinfo.out_color_space = JCS_YCbCr;
+ cinfo.raw_data_out = true;
+ status = jpeg_start_decompress(&cinfo);
+ if (!status){
+ CAMHAL_LOGEA("jpeg_start_decompress failed");
+ return false;
+ }
+
+ if (mWidth == 0){
+ mWidth = cinfo.output_width;
+ mHeight = cinfo.output_height;
+ CAMHAL_LOGEA("w x h = %d x %d. stride=%d", cinfo.output_width, cinfo.output_height, stride);
+ }
+ else if ((cinfo.output_width > mWidth) || (cinfo.output_height > mHeight)) {
+ CAMHAL_LOGEA(" Free the existing buffers so that they are reallocated for new w x h. Old WxH = %dx%d. New WxH = %dx%d",
+ mWidth, mHeight, cinfo.output_width, cinfo.output_height);
+ release();
+ mWidth = cinfo.output_width;
+ mHeight = cinfo.output_height;
+ }
+
+ unsigned int decoded_uv_buffer_size = cinfo.output_width * cinfo.output_height / 2;
+ if (Y_Plane == NULL)Y_Plane = (unsigned char **)malloc(cinfo.output_height * sizeof(unsigned char *));
+ if (U_Plane == NULL)U_Plane = (unsigned char **)malloc(cinfo.output_height * sizeof(unsigned char *));
+ if (V_Plane == NULL)V_Plane = (unsigned char **)malloc(cinfo.output_height * sizeof(unsigned char *));
+ if (UV_Plane == NULL) UV_Plane = (unsigned char *)malloc(decoded_uv_buffer_size);
+
+ unsigned char **YUV_Planes[NUM_COMPONENTS_IN_YUV];
+ YUV_Planes[0] = Y_Plane;
+ YUV_Planes[1] = U_Plane;
+ YUV_Planes[2] = V_Plane;
+
+ unsigned char *row = &nv12_buffer[0];
+
+ // Y Component
+ for (unsigned int j = 0; j < cinfo.output_height; j++, row += stride)
+ YUV_Planes[0][j] = row;
+
+ row = &UV_Plane[0];
+
+ // U Component
+ for (unsigned int j = 0; j < cinfo.output_height; j+=2, row += cinfo.output_width / 2){
+ YUV_Planes[1][j+0] = row;
+ YUV_Planes[1][j+1] = row;
+ }
+
+ // V Component
+ for (unsigned int j = 0; j < cinfo.output_height; j+=2, row += cinfo.output_width / 2){
+ YUV_Planes[2][j+0] = row;
+ YUV_Planes[2][j+1] = row;
+ }
+
+ // Interleaving U and V
+ for (unsigned int i = 0; i < cinfo.output_height; i += 8) {
+ jpeg_read_raw_data(&cinfo, YUV_Planes, 8);
+ YUV_Planes[0] += 8;
+ YUV_Planes[1] += 8;
+ YUV_Planes[2] += 8;
+ }
+
+ unsigned char *uv_ptr = nv12_buffer + (stride * cinfo.output_height);
+ unsigned char *u_ptr = UV_Plane;
+ unsigned char *v_ptr = UV_Plane + (decoded_uv_buffer_size / 2);
+ for(unsigned int i = 0; i < cinfo.output_height / 2; i++){
+ for(unsigned int j = 0; j < cinfo.output_width; j+=2){
+ *(uv_ptr + j) = *u_ptr; u_ptr++;
+ *(uv_ptr + j + 1) = *v_ptr; v_ptr++;
+ }
+ uv_ptr = uv_ptr + stride;
+ }
+
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+
+ return true;
+}
+
+} // namespace Camera
+} // namespace Ti
+
diff --git a/camera/Encoder_libjpeg.cpp b/camera/Encoder_libjpeg.cpp
new file mode 100644
index 0000000..1cd09d3
--- /dev/null
+++ b/camera/Encoder_libjpeg.cpp
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file Encoder_libjpeg.cpp
+*
+* This file encodes a YUV422I buffer to a jpeg
+* TODO(XXX): Need to support formats other than yuv422i
+* Change interface to pre/post-proc algo framework
+*
+*/
+
+#include "Encoder_libjpeg.h"
+#include "NV12_resize.h"
+#include "TICameraParameters.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <math.h>
+
+extern "C" {
+ #include "jpeglib.h"
+ #include "jerror.h"
+}
+
+#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
+#define MIN(x,y) ((x < y) ? x : y)
+
+namespace Ti {
+namespace Camera {
+
+struct integer_string_pair {
+ unsigned int integer;
+ const char* string;
+};
+
+static integer_string_pair degress_to_exif_lut [] = {
+ // degrees, exif_orientation
+ {0, "1"},
+ {90, "6"},
+ {180, "3"},
+ {270, "8"},
+};
+struct libjpeg_destination_mgr : jpeg_destination_mgr {
+ libjpeg_destination_mgr(uint8_t* input, int size);
+
+ uint8_t* buf;
+ int bufsize;
+ size_t jpegsize;
+};
+
+static void libjpeg_init_destination (j_compress_ptr cinfo) {
+ libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
+
+ dest->next_output_byte = dest->buf;
+ dest->free_in_buffer = dest->bufsize;
+ dest->jpegsize = 0;
+}
+
+static boolean libjpeg_empty_output_buffer(j_compress_ptr cinfo) {
+ libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
+
+ dest->next_output_byte = dest->buf;
+ dest->free_in_buffer = dest->bufsize;
+ return TRUE; // ?
+}
+
+static void libjpeg_term_destination (j_compress_ptr cinfo) {
+ libjpeg_destination_mgr* dest = (libjpeg_destination_mgr*)cinfo->dest;
+ dest->jpegsize = dest->bufsize - dest->free_in_buffer;
+}
+
+libjpeg_destination_mgr::libjpeg_destination_mgr(uint8_t* input, int size) {
+ this->init_destination = libjpeg_init_destination;
+ this->empty_output_buffer = libjpeg_empty_output_buffer;
+ this->term_destination = libjpeg_term_destination;
+
+ this->buf = input;
+ this->bufsize = size;
+
+ jpegsize = 0;
+}
+
+/* private static functions */
+static void nv21_to_yuv(uint8_t* dst, uint8_t* y, uint8_t* uv, int width) {
+ if (!dst || !y || !uv) {
+ return;
+ }
+
+ while ((width--) > 0) {
+ uint8_t y0 = y[0];
+ uint8_t v0 = uv[0];
+ uint8_t u0 = *(uv+1);
+ dst[0] = y0;
+ dst[1] = u0;
+ dst[2] = v0;
+ dst += 3;
+ y++;
+ if(!(width % 2)) uv+=2;
+ }
+}
+
+static void uyvy_to_yuv(uint8_t* dst, uint32_t* src, int width) {
+ if (!dst || !src) {
+ return;
+ }
+
+ if (width % 2) {
+ return; // not supporting odd widths
+ }
+
+#ifdef ARCH_ARM_HAVE_NEON
+ // currently, neon routine only supports multiple of 16 width
+ if ((width % 16) == 0) {
+ int n = width;
+ asm volatile (
+ " pld [%[src], %[src_stride], lsl #2] \n\t"
+ " cmp %[n], #16 \n\t"
+ " blt 5f \n\t"
+ "0: @ 16 pixel swap \n\t"
+ " vld2.8 {q0, q1} , [%[src]]! @ q0 = uv q1 = y \n\t"
+ " vuzp.8 q0, q2 @ d0 = u d4 = v \n\t"
+ " vmov d1, d0 @ q0 = u0u1u2..u0u1u2... \n\t"
+ " vmov d5, d4 @ q2 = v0v1v2..v0v1v2... \n\t"
+ " vzip.8 d0, d1 @ q0 = u0u0u1u1u2u2... \n\t"
+ " vzip.8 d4, d5 @ q2 = v0v0v1v1v2v2... \n\t"
+ " vswp q0, q1 @ now q0 = y q1 = u q2 = v \n\t"
+ " vst3.8 {d0,d2,d4},[%[dst]]! \n\t"
+ " vst3.8 {d1,d3,d5},[%[dst]]! \n\t"
+ " sub %[n], %[n], #16 \n\t"
+ " cmp %[n], #16 \n\t"
+ " bge 0b \n\t"
+ "5: @ end \n\t"
+#ifdef NEEDS_ARM_ERRATA_754319_754320
+ " vmov s0,s0 @ add noop for errata item \n\t"
+#endif
+ : [dst] "+r" (dst), [src] "+r" (src), [n] "+r" (n)
+ : [src_stride] "r" (width)
+ : "cc", "memory", "q0", "q1", "q2"
+ );
+ } else
+#endif
+ {
+ while ((width-=2) >= 0) {
+ uint8_t u0 = (src[0] >> 0) & 0xFF;
+ uint8_t y0 = (src[0] >> 8) & 0xFF;
+ uint8_t v0 = (src[0] >> 16) & 0xFF;
+ uint8_t y1 = (src[0] >> 24) & 0xFF;
+ dst[0] = y0;
+ dst[1] = u0;
+ dst[2] = v0;
+ dst[3] = y1;
+ dst[4] = u0;
+ dst[5] = v0;
+ dst += 6;
+ src++;
+ }
+ }
+}
+
+static void yuyv_to_yuv(uint8_t* dst, uint32_t* src, int width) {
+ if (!dst || !src) {
+ return;
+ }
+
+ if (width % 2) {
+ return; // not supporting odd widths
+ }
+
+#ifdef ARCH_ARM_HAVE_NEON
+ // currently, neon routine only supports multiple of 16 width
+ if ((width % 16) == 0) {
+ int n = width;
+ asm volatile (
+ " pld [%[src], %[src_stride], lsl #2] \n\t"
+ " cmp %[n], #16 \n\t"
+ " blt 5f \n\t"
+ "0: @ 16 pixel swap \n\t"
+ " vld2.8 {q0, q1} , [%[src]]! @ q0 = yyyy.. q1 = uvuv.. \n\t"
+ " vuzp.8 q1, q2 @ d2 = u d4 = v \n\t"
+ " vmov d3, d2 @ q1 = u0u1u2..u0u1u2... \n\t"
+ " vmov d5, d4 @ q2 = v0v1v2..v0v1v2... \n\t"
+ " vzip.8 d2, d3 @ q1 = u0u0u1u1u2u2... \n\t"
+ " vzip.8 d4, d5 @ q2 = v0v0v1v1v2v2... \n\t"
+ " @ now q0 = y q1 = u q2 = v \n\t"
+ " vst3.8 {d0,d2,d4},[%[dst]]! \n\t"
+ " vst3.8 {d1,d3,d5},[%[dst]]! \n\t"
+ " sub %[n], %[n], #16 \n\t"
+ " cmp %[n], #16 \n\t"
+ " bge 0b \n\t"
+ "5: @ end \n\t"
+#ifdef NEEDS_ARM_ERRATA_754319_754320
+ " vmov s0,s0 @ add noop for errata item \n\t"
+#endif
+ : [dst] "+r" (dst), [src] "+r" (src), [n] "+r" (n)
+ : [src_stride] "r" (width)
+ : "cc", "memory", "q0", "q1", "q2"
+ );
+ } else
+#endif
+ {
+ while ((width-=2) >= 0) {
+ uint8_t y0 = (src[0] >> 0) & 0xFF;
+ uint8_t u0 = (src[0] >> 8) & 0xFF;
+ uint8_t y1 = (src[0] >> 16) & 0xFF;
+ uint8_t v0 = (src[0] >> 24) & 0xFF;
+ dst[0] = y0;
+ dst[1] = u0;
+ dst[2] = v0;
+ dst[3] = y1;
+ dst[4] = u0;
+ dst[5] = v0;
+ dst += 6;
+ src++;
+ }
+ }
+}
+
+static void resize_nv12(Encoder_libjpeg::params* params, uint8_t* dst_buffer) {
+ structConvImage o_img_ptr, i_img_ptr;
+
+ if (!params || !dst_buffer) {
+ return;
+ }
+
+ //input
+ i_img_ptr.uWidth = params->in_width;
+ i_img_ptr.uStride = i_img_ptr.uWidth;
+ i_img_ptr.uHeight = params->in_height;
+ i_img_ptr.eFormat = IC_FORMAT_YCbCr420_lp;
+ i_img_ptr.imgPtr = (uint8_t*) params->src;
+ i_img_ptr.clrPtr = i_img_ptr.imgPtr + (i_img_ptr.uWidth * i_img_ptr.uHeight);
+ i_img_ptr.uOffset = 0;
+
+ //ouput
+ o_img_ptr.uWidth = params->out_width;
+ o_img_ptr.uStride = o_img_ptr.uWidth;
+ o_img_ptr.uHeight = params->out_height;
+ o_img_ptr.eFormat = IC_FORMAT_YCbCr420_lp;
+ o_img_ptr.imgPtr = dst_buffer;
+ o_img_ptr.clrPtr = o_img_ptr.imgPtr + (o_img_ptr.uWidth * o_img_ptr.uHeight);
+ o_img_ptr.uOffset = 0;
+
+ VT_resizeFrame_Video_opt2_lp(&i_img_ptr, &o_img_ptr, NULL, 0);
+}
+
+/* public static functions */
+const char* ExifElementsTable::degreesToExifOrientation(unsigned int degrees) {
+ for (unsigned int i = 0; i < ARRAY_SIZE(degress_to_exif_lut); i++) {
+ if (degrees == degress_to_exif_lut[i].integer) {
+ return degress_to_exif_lut[i].string;
+ }
+ }
+ return NULL;
+}
+
+void ExifElementsTable::stringToRational(const char* str, unsigned int* num, unsigned int* den) {
+ int len;
+ char * tempVal = NULL;
+
+ if (str != NULL) {
+ len = strlen(str);
+ tempVal = (char*) malloc( sizeof(char) * (len + 1));
+ }
+
+ if (tempVal != NULL) {
+ // convert the decimal string into a rational
+ size_t den_len;
+ char *ctx;
+ unsigned int numerator = 0;
+ unsigned int denominator = 0;
+ char* temp = NULL;
+
+ memset(tempVal, '\0', len + 1);
+ strncpy(tempVal, str, len);
+ temp = strtok_r(tempVal, ".", &ctx);
+
+ if (temp != NULL)
+ numerator = atoi(temp);
+
+ if (!numerator)
+ numerator = 1;
+
+ temp = strtok_r(NULL, ".", &ctx);
+ if (temp != NULL) {
+ den_len = strlen(temp);
+ if(HUGE_VAL == den_len ) {
+ den_len = 0;
+ }
+
+ denominator = static_cast<unsigned int>(pow(10, den_len));
+ numerator = numerator * denominator + atoi(temp);
+ } else {
+ denominator = 1;
+ }
+
+ free(tempVal);
+
+ *num = numerator;
+ *den = denominator;
+ }
+}
+
+bool ExifElementsTable::isAsciiTag(const char* tag) {
+ // TODO(XXX): Add tags as necessary
+ return (strcmp(tag, TAG_GPS_PROCESSING_METHOD) == 0);
+}
+
+void ExifElementsTable::insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size) {
+ ReadMode_t read_mode = (ReadMode_t)(READ_METADATA | READ_IMAGE);
+
+ ResetJpgfile();
+ if (ReadJpegSectionsFromBuffer(jpeg, jpeg_size, read_mode)) {
+ jpeg_opened = true;
+#ifdef ANDROID_API_JB_OR_LATER
+ create_EXIF(table, exif_tag_count, gps_tag_count, has_datetime_tag);
+#else
+ create_EXIF(table, exif_tag_count, gps_tag_count);
+#endif
+ }
+}
+
+status_t ExifElementsTable::insertExifThumbnailImage(const char* thumb, int len) {
+ status_t ret = NO_ERROR;
+
+ if ((len > 0) && jpeg_opened) {
+ ret = ReplaceThumbnailFromBuffer(thumb, len) ? NO_ERROR : UNKNOWN_ERROR;
+ CAMHAL_LOGDB("insertExifThumbnailImage. ReplaceThumbnail(). ret=%d", ret);
+ }
+
+ return ret;
+}
+
+void ExifElementsTable::saveJpeg(unsigned char* jpeg, size_t jpeg_size) {
+ if (jpeg_opened) {
+ WriteJpegToBuffer(jpeg, jpeg_size);
+ DiscardData();
+ jpeg_opened = false;
+ }
+}
+
+/* public functions */
+ExifElementsTable::~ExifElementsTable() {
+ int num_elements = gps_tag_count + exif_tag_count;
+
+ for (int i = 0; i < num_elements; i++) {
+ if (table[i].Value) {
+ free(table[i].Value);
+ }
+ }
+
+ if (jpeg_opened) {
+ DiscardData();
+ }
+}
+
+status_t ExifElementsTable::insertElement(const char* tag, const char* value) {
+ unsigned int value_length = 0;
+ status_t ret = NO_ERROR;
+
+ if (!value || !tag) {
+ return -EINVAL;
+ }
+
+ if (position >= MAX_EXIF_TAGS_SUPPORTED) {
+ CAMHAL_LOGEA("Max number of EXIF elements already inserted");
+ return NO_MEMORY;
+ }
+
+ if (isAsciiTag(tag)) {
+ value_length = sizeof(ExifAsciiPrefix) + strlen(value + sizeof(ExifAsciiPrefix));
+ } else {
+ value_length = strlen(value);
+ }
+
+ if (IsGpsTag(tag)) {
+ table[position].GpsTag = TRUE;
+ table[position].Tag = GpsTagNameToValue(tag);
+ gps_tag_count++;
+ } else {
+ table[position].GpsTag = FALSE;
+ table[position].Tag = TagNameToValue(tag);
+ exif_tag_count++;
+
+ if (strcmp(tag, TAG_DATETIME) == 0) {
+#ifdef ANDROID_API_JB_OR_LATER
+ has_datetime_tag = true;
+#else
+ // jhead isn't taking datetime tag...this is a WA
+ ImageInfo.numDateTimeTags = 1;
+ memcpy(ImageInfo.DateTime, value,
+ MIN(ARRAY_SIZE(ImageInfo.DateTime), value_length + 1));
+#endif
+ }
+ }
+
+ table[position].DataLength = 0;
+ table[position].Value = (char*) malloc(sizeof(char) * (value_length + 1));
+
+ if (table[position].Value) {
+ memcpy(table[position].Value, value, value_length + 1);
+ table[position].DataLength = value_length + 1;
+ }
+
+ position++;
+ return ret;
+}
+
+/* private member functions */
+size_t Encoder_libjpeg::encode(params* input) {
+ jpeg_compress_struct cinfo;
+ jpeg_error_mgr jerr;
+ jpeg_destination_mgr jdest;
+ uint8_t* src = NULL, *resize_src = NULL;
+ uint8_t* row_tmp = NULL;
+ uint8_t* row_src = NULL;
+ uint8_t* row_uv = NULL; // used only for NV12
+ int out_width = 0, in_width = 0;
+ int out_height = 0, in_height = 0;
+ int bpp = 2; // for uyvy
+ int right_crop = 0, start_offset = 0;
+
+ if (!input) {
+ return 0;
+ }
+
+ out_width = input->out_width;
+ in_width = input->in_width;
+ out_height = input->out_height;
+ in_height = input->in_height;
+ right_crop = input->right_crop;
+ start_offset = input->start_offset;
+ src = input->src;
+ input->jpeg_size = 0;
+
+ libjpeg_destination_mgr dest_mgr(input->dst, input->dst_size);
+
+ // param check...
+ if ((in_width < 2) || (out_width < 2) || (in_height < 2) || (out_height < 2) ||
+ (src == NULL) || (input->dst == NULL) || (input->quality < 1) || (input->src_size < 1) ||
+ (input->dst_size < 1) || (input->format == NULL)) {
+ goto exit;
+ }
+
+ if (strcmp(input->format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ bpp = 1;
+ if ((in_width != out_width) || (in_height != out_height)) {
+ resize_src = (uint8_t*) malloc(input->dst_size);
+ resize_nv12(input, resize_src);
+ if (resize_src) src = resize_src;
+ }
+ } else if (strcmp(input->format, android::CameraParameters::PIXEL_FORMAT_YUV422I) &&
+ strcmp(input->format, TICameraParameters::PIXEL_FORMAT_YUV422I_UYVY)) {
+ // we currently only support yuv422i and yuv420sp
+ CAMHAL_LOGEB("Encoder: format not supported: %s", input->format);
+ goto exit;
+ } else if ((in_width != out_width) || (in_height != out_height)) {
+ CAMHAL_LOGEB("Encoder: resizing is not supported for this format: %s", input->format);
+ goto exit;
+ }
+
+ cinfo.err = jpeg_std_error(&jerr);
+
+ jpeg_create_compress(&cinfo);
+
+ CAMHAL_LOGDB("encoding... \n\t"
+ "width: %d \n\t"
+ "height:%d \n\t"
+ "dest %p \n\t"
+ "dest size:%d \n\t"
+ "mSrc %p \n\t"
+ "format: %s",
+ out_width, out_height, input->dst,
+ input->dst_size, src, input->format);
+
+ cinfo.dest = &dest_mgr;
+ cinfo.image_width = out_width - right_crop;
+ cinfo.image_height = out_height;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_YCbCr;
+ cinfo.input_gamma = 1;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, input->quality, TRUE);
+ cinfo.dct_method = JDCT_IFAST;
+
+ jpeg_start_compress(&cinfo, TRUE);
+
+ row_tmp = (uint8_t*)malloc((out_width - right_crop) * 3);
+ row_src = src + start_offset;
+ row_uv = src + out_width * out_height * bpp;
+
+ while ((cinfo.next_scanline < cinfo.image_height) && !mCancelEncoding) {
+ JSAMPROW row[1]; /* pointer to JSAMPLE row[s] */
+
+ // convert input yuv format to yuv444
+ if (strcmp(input->format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ nv21_to_yuv(row_tmp, row_src, row_uv, out_width - right_crop);
+ } else if (strcmp(input->format, TICameraParameters::PIXEL_FORMAT_YUV422I_UYVY) == 0) {
+ uyvy_to_yuv(row_tmp, (uint32_t*)row_src, out_width - right_crop);
+ } else if (strcmp(input->format, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ yuyv_to_yuv(row_tmp, (uint32_t*)row_src, out_width - right_crop);
+ }
+
+ row[0] = row_tmp;
+ jpeg_write_scanlines(&cinfo, row, 1);
+ row_src = row_src + out_width*bpp;
+
+ // move uv row if input format needs it
+ if (strcmp(input->format, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ if (!(cinfo.next_scanline % 2))
+ row_uv = row_uv + out_width * bpp;
+ }
+ }
+
+ // no need to finish encoding routine if we are prematurely stopping
+ // we will end up crashing in dest_mgr since data is incomplete
+ if (!mCancelEncoding)
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+
+ if (resize_src) free(resize_src);
+ if (row_tmp) free(row_tmp);
+
+ exit:
+ input->jpeg_size = dest_mgr.jpegsize;
+ return dest_mgr.jpegsize;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/FrameDecoder.cpp b/camera/FrameDecoder.cpp
new file mode 100644
index 0000000..80b4946
--- /dev/null
+++ b/camera/FrameDecoder.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Common.h"
+#include "FrameDecoder.h"
+
+
+namespace Ti {
+namespace Camera {
+
+FrameDecoder::FrameDecoder()
+: mCameraHal(NULL), mState(DecoderState_Uninitialized) {
+}
+
+FrameDecoder::~FrameDecoder() {
+}
+
+status_t FrameDecoder::start() {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+ status_t ret;
+ if (mState == DecoderState_Running) {
+ return NO_INIT;
+ }
+ ret = doStart();
+ if (ret == NO_ERROR) {
+ mState = DecoderState_Running;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+void FrameDecoder::stop() {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+ if (mState >= DecoderState_Requested_Stop) {
+ return;
+ }
+ mState = DecoderState_Requested_Stop;
+ doStop();
+ mState = DecoderState_Stoppped;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void FrameDecoder::release() {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+ if (mState <= DecoderState_Requested_Stop) {
+ return;
+ }
+ doRelease();
+ mState = DecoderState_Uninitialized;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void FrameDecoder::flush() {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+ if (mState <= DecoderState_Requested_Stop) {
+ return;
+ }
+ doFlush();
+ mInQueue.clear();
+ mOutQueue.clear();
+
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void FrameDecoder::configure(const DecoderParameters& params) {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+ if (mState == DecoderState_Running) {
+ return;
+ }
+ mParams = params;
+ mInQueue.reserve(mParams.inputBufferCount);
+ mOutQueue.reserve(mParams.outputBufferCount);
+ doConfigure(params);
+ mState = DecoderState_Initialized;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t FrameDecoder::dequeueInputBuffer(int &id) {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if (mState != DecoderState_Running) {
+ CAMHAL_LOGE("Try to use Decoder not in RUNNING state");
+ return INVALID_OPERATION;
+ }
+
+ for (size_t i = 0; i < mInQueue.size(); i++) {
+ int index = mInQueue[i];
+ android::sp<MediaBuffer>& in = mInBuffers->editItemAt(index);
+ android::AutoMutex bufferLock(in->getLock());
+ if (in->getStatus() == BufferStatus_InDecoded) {
+ id = index;
+ in->setStatus(BufferStatus_Unknown);
+ mInQueue.removeAt(i);
+ return NO_ERROR;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return INVALID_OPERATION;
+}
+
+status_t FrameDecoder::dequeueOutputBuffer(int &id) {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if (mState != DecoderState_Running) {
+ CAMHAL_LOGE("Try to use Decoder not in RUNNING state");
+ return INVALID_OPERATION;
+ }
+
+ for (size_t i = 0; i < mOutQueue.size(); i++) {
+ int index = mOutQueue[i];
+ android::sp<MediaBuffer>& out = mOutBuffers->editItemAt(index);
+ android::AutoMutex bufferLock(out->getLock());
+ if (out->getStatus() == BufferStatus_OutFilled) {
+ id = index;
+ out->setStatus(BufferStatus_Unknown);
+ mOutQueue.removeAt(i);
+ return NO_ERROR;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return INVALID_OPERATION;
+}
+
+status_t FrameDecoder::queueOutputBuffer(int index) {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ //We queue all available buffers to Decoder not in recording mode - before start
+ if (mState > DecoderState_Running) {
+ CAMHAL_LOGE("Try to use Decoder not in RUNNING state");
+ return INVALID_OPERATION;
+ }
+
+ android::sp<MediaBuffer>& out = mOutBuffers->editItemAt(index);
+ android::AutoMutex bufferLock(out->getLock());
+ out->setStatus(BufferStatus_OutQueued);
+ mOutQueue.push_back(index);
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+}
+
+status_t FrameDecoder::queueInputBuffer(int id) {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if (mState != DecoderState_Running) {
+ CAMHAL_LOGE("Try to use Decoder not in RUNNING state");
+ return INVALID_OPERATION;
+ }
+
+ {
+ android::sp<MediaBuffer>& in = mInBuffers->editItemAt(id);
+ android::AutoMutex bufferLock(in->getLock());
+ in->setStatus(BufferStatus_InQueued);
+ mInQueue.push_back(id);
+ }
+
+ // Since we got queued buffer - we can process it
+ doProcessInputBuffer();
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+}
+
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/MemoryManager.cpp b/camera/MemoryManager.cpp
new file mode 100644
index 0000000..b684203
--- /dev/null
+++ b/camera/MemoryManager.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CameraHal.h"
+#include "TICameraParameters.h"
+
+extern "C" {
+
+//#include <timm_osal_interfaces.h>
+//#include <timm_osal_trace.h>
+
+
+};
+
+namespace Ti {
+namespace Camera {
+
+///@todo Move these constants to a common header file, preferably in tiler.h
+#define STRIDE_8BIT (4 * 1024)
+#define STRIDE_16BIT (4 * 1024)
+
+#define ALLOCATION_2D 2
+
+///Utility Macro Declarations
+
+/*--------------------MemoryManager Class STARTS here-----------------------------*/
+MemoryManager::MemoryManager() {
+ mIonFd = -1;
+}
+
+MemoryManager::~MemoryManager() {
+ if ( mIonFd >= 0 ) {
+ ion_close(mIonFd);
+ mIonFd = -1;
+ }
+}
+
+status_t MemoryManager::initialize() {
+ if ( mIonFd == -1 ) {
+ mIonFd = ion_open();
+ if ( mIonFd < 0 ) {
+ CAMHAL_LOGE("ion_open() failed, error: %d", mIonFd);
+ mIonFd = -1;
+ return NO_INIT;
+ }
+ }
+
+ return OK;
+}
+
+CameraBuffer* MemoryManager::allocateBufferList(int width, int height, const char* format, int &size, int numBufs)
+{
+ LOG_FUNCTION_NAME;
+
+ CAMHAL_ASSERT(mIonFd != -1);
+
+ ///We allocate numBufs+1 because the last entry will be marked NULL to indicate end of array, which is used when freeing
+ ///the buffers
+ const uint numArrayEntriesC = (uint)(numBufs+1);
+
+ ///Allocate a buffer array
+ CameraBuffer *buffers = new CameraBuffer [numArrayEntriesC];
+ if(!buffers) {
+ CAMHAL_LOGEB("Allocation failed when creating buffers array of %d CameraBuffer elements", numArrayEntriesC);
+ goto error;
+ }
+
+ ///Initialize the array with zeros - this will help us while freeing the array in case of error
+ ///If a value of an array element is NULL, it means we didnt allocate it
+ memset(buffers, 0, sizeof(CameraBuffer) * numArrayEntriesC);
+
+ //2D Allocations are not supported currently
+ if(size != 0) {
+ struct ion_handle *handle;
+ int mmap_fd;
+ size_t stride;
+
+ ///1D buffers
+ for (int i = 0; i < numBufs; i++) {
+ unsigned char *data;
+#ifdef USE_LIBION_TI
+ int ret = ion_alloc(mIonFd, size, 0, 1 << ION_HEAP_TYPE_CARVEOUT,
+ &handle);
+#else
+ int ret = ion_alloc(mIonFd, size, 0, 1 << ION_HEAP_TYPE_CARVEOUT, 0,
+ &handle);
+#endif
+ if((ret < 0) || ((int)handle == -ENOMEM)) {
+ ret = ion_alloc_tiler(mIonFd, (size_t)size, 1, TILER_PIXEL_FMT_PAGE,
+ OMAP_ION_HEAP_TILER_MASK, &handle, &stride);
+ }
+
+ if((ret < 0) || ((int)handle == -ENOMEM)) {
+ CAMHAL_LOGEB("FAILED to allocate ion buffer of size=%d. ret=%d(0x%x)", size, ret, ret);
+ goto error;
+ }
+
+ CAMHAL_LOGDB("Before mapping, handle = %p, nSize = %d", handle, size);
+ if ((ret = ion_map(mIonFd, handle, size, PROT_READ | PROT_WRITE, MAP_SHARED, 0,
+ &data, &mmap_fd)) < 0) {
+ CAMHAL_LOGEB("Userspace mapping of ION buffers returned error %d", ret);
+ ion_free(mIonFd, handle);
+ goto error;
+ }
+
+ buffers[i].type = CAMERA_BUFFER_ION;
+ buffers[i].opaque = data;
+ buffers[i].mapped = data;
+ buffers[i].ion_handle = handle;
+ buffers[i].ion_fd = mIonFd;
+ buffers[i].fd = mmap_fd;
+ buffers[i].size = size;
+ buffers[i].format = CameraHal::getPixelFormatConstant(format);
+
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return buffers;
+
+error:
+
+ CAMHAL_LOGE("Freeing buffers already allocated after error occurred");
+ if(buffers)
+ freeBufferList(buffers);
+
+ if ( NULL != mErrorNotifier.get() )
+ mErrorNotifier->errorNotify(-ENOMEM);
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NULL;
+}
+
+CameraBuffer* MemoryManager::getBufferList(int *numBufs) {
+ LOG_FUNCTION_NAME;
+ if (numBufs) *numBufs = -1;
+
+ return NULL;
+}
+
+//TODO: Get needed data to map tiler buffers
+//Return dummy data for now
+uint32_t * MemoryManager::getOffsets()
+{
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NULL;
+}
+
+int MemoryManager::getFd()
+{
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return -1;
+}
+
+int MemoryManager::freeBufferList(CameraBuffer *buffers)
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ int i;
+
+ if(!buffers)
+ {
+ CAMHAL_LOGEA("NULL pointer passed to freebuffer");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ i = 0;
+ while(buffers[i].type == CAMERA_BUFFER_ION)
+ {
+ if(buffers[i].size)
+ {
+ munmap(buffers[i].opaque, buffers[i].size);
+ close(buffers[i].fd);
+ ion_free(mIonFd, buffers[i].ion_handle);
+ }
+ else
+ {
+ CAMHAL_LOGEA("Not a valid Memory Manager buffer");
+ }
+ i++;
+ }
+
+ delete [] buffers;
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t MemoryManager::setErrorHandler(ErrorNotifier *errorNotifier)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == errorNotifier )
+ {
+ CAMHAL_LOGEA("Invalid Error Notifier reference");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mErrorNotifier = errorNotifier;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
+
+
+/*--------------------MemoryManager Class ENDS here-----------------------------*/
diff --git a/camera/NV12_resize.cpp b/camera/NV12_resize.cpp
new file mode 100644
index 0000000..971ee38
--- /dev/null
+++ b/camera/NV12_resize.cpp
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NV12_resize.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "NV12_resize"
+
+#define STRIDE 4096
+
+/*==========================================================================
+* Function Name : VT_resizeFrame_Video_opt2_lp
+*
+* Description : Resize a yuv frame.
+*
+* Input(s) : input_img_ptr -> Input Image Structure
+* : output_img_ptr -> Output Image Structure
+* : cropout -> crop structure
+*
+* Value Returned : mmBool -> FALSE on error TRUE on success
+* NOTE:
+* Not tested for crop funtionallity.
+* faster version.
+============================================================================*/
+mmBool
+VT_resizeFrame_Video_opt2_lp(
+ structConvImage* i_img_ptr, /* Points to the input image */
+ structConvImage* o_img_ptr, /* Points to the output image */
+ IC_rect_type* cropout, /* how much to resize to in final image */
+ mmUint16 dummy /* Transparent pixel value */
+ ) {
+ LOG_FUNCTION_NAME;
+
+ mmUint16 row,col;
+ mmUint32 resizeFactorX;
+ mmUint32 resizeFactorY;
+
+ mmUint16 x, y;
+
+ mmUchar* ptr8;
+ mmUchar *ptr8Cb, *ptr8Cr;
+
+ mmUint16 xf, yf;
+ mmUchar* inImgPtrY;
+ mmUchar* inImgPtrU;
+ mmUchar* inImgPtrV;
+ mmUint32 cox, coy, codx, cody;
+ mmUint16 idx,idy, idxC;
+
+ if ( i_img_ptr->uWidth == o_img_ptr->uWidth ) {
+ if ( i_img_ptr->uHeight == o_img_ptr->uHeight ) {
+ CAMHAL_LOGV("************************f(i_img_ptr->uHeight == o_img_ptr->uHeight) are same *********************\n");
+ CAMHAL_LOGV("************************(i_img_ptr->width == %d" , i_img_ptr->uWidth );
+ CAMHAL_LOGV("************************(i_img_ptr->uHeight == %d" , i_img_ptr->uHeight );
+ CAMHAL_LOGV("************************(o_img_ptr->width == %d" ,o_img_ptr->uWidth );
+ CAMHAL_LOGV("************************(o_img_ptr->uHeight == %d" , o_img_ptr->uHeight );
+ }
+ }
+
+ if ( !i_img_ptr || !i_img_ptr->imgPtr || !o_img_ptr || !o_img_ptr->imgPtr ) {
+ CAMHAL_LOGE("Image Point NULL");
+ return false;
+ }
+
+ inImgPtrY = (mmUchar *) i_img_ptr->imgPtr + i_img_ptr->uOffset;
+ inImgPtrU = (mmUchar *) i_img_ptr->clrPtr + i_img_ptr->uOffset/2;
+ inImgPtrV = (mmUchar*)inImgPtrU + 1;
+
+ if ( !cropout ) {
+ cox = 0;
+ coy = 0;
+ codx = o_img_ptr->uWidth;
+ cody = o_img_ptr->uHeight;
+ } else {
+ cox = cropout->x;
+ coy = cropout->y;
+ codx = cropout->uWidth;
+ cody = cropout->uHeight;
+ }
+ idx = i_img_ptr->uWidth;
+ idy = i_img_ptr->uHeight;
+
+ /* make sure valid input size */
+ if ( idx < 1 || idy < 1 || i_img_ptr->uStride < 1 ) {
+ CAMHAL_LOGE("idx or idy less then 1 idx = %d idy = %d stride = %d", idx, idy, i_img_ptr->uStride);
+ return false;
+ }
+
+ resizeFactorX = ((idx-1)<<9) / codx;
+ resizeFactorY = ((idy-1)<<9) / cody;
+
+ if( i_img_ptr->eFormat != IC_FORMAT_YCbCr420_lp ||
+ o_img_ptr->eFormat != IC_FORMAT_YCbCr420_lp ) {
+ CAMHAL_LOGE("eFormat not supported");
+ return false;
+ }
+
+ ptr8 = (mmUchar*)o_img_ptr->imgPtr + cox + coy*o_img_ptr->uWidth;
+
+ ////////////////////////////for Y//////////////////////////
+ for ( row = 0; row < cody; row++ ) {
+ mmUchar *pu8Yrow1 = NULL;
+ mmUchar *pu8Yrow2 = NULL;
+ y = (mmUint16) ((mmUint32) (row*resizeFactorY) >> 9);
+ yf = (mmUchar) ((mmUint32)((row*resizeFactorY) >> 6) & 0x7);
+ pu8Yrow1 = inImgPtrY + (y) * i_img_ptr->uStride;
+ pu8Yrow2 = pu8Yrow1 + i_img_ptr->uStride;
+
+ for ( col = 0; col < codx; col++ ) {
+ mmUchar in11, in12, in21, in22;
+ mmUchar *pu8ptr1 = NULL;
+ mmUchar *pu8ptr2 = NULL;
+ mmUchar w;
+ mmUint16 accum_1;
+ //mmUint32 accum_W;
+
+ x = (mmUint16) ((mmUint32) (col*resizeFactorX) >> 9);
+ xf = (mmUchar) ((mmUint32) ((col*resizeFactorX) >> 6) & 0x7);
+
+ //accum_W = 0;
+ accum_1 = 0;
+
+ pu8ptr1 = pu8Yrow1 + (x);
+ pu8ptr2 = pu8Yrow2 + (x);
+
+ /* A pixel */
+ //in = *(inImgPtrY + (y)*idx + (x));
+ in11 = *(pu8ptr1);
+
+ w = bWeights[xf][yf][0];
+ accum_1 = (w * in11);
+ //accum_W += (w);
+
+ /* B pixel */
+ //in = *(inImgPtrY + (y)*idx + (x+1));
+ in12 = *(pu8ptr1+1);
+ w = bWeights[xf][yf][1];
+ accum_1 += (w * in12);
+ //accum_W += (w);
+
+ /* C pixel */
+ //in = *(inImgPtrY + (y+1)*idx + (x));
+ in21 = *(pu8ptr2);
+ w = bWeights[xf][yf][3];
+ accum_1 += (w * in21);
+ //accum_W += (w);
+
+ /* D pixel */
+ //in = *(inImgPtrY + (y+1)*idx + (x+1));
+ in22 = *(pu8ptr2+1);
+ w = bWeights[xf][yf][2];
+ accum_1 += (w * in22);
+ //accum_W += (w);
+
+ /* divide by sum of the weights */
+ //accum_1 /= (accum_W);
+ //accum_1 = (accum_1/64);
+ accum_1 = (accum_1>>6);
+ *ptr8 = (mmUchar)accum_1 ;
+
+ ptr8++;
+ }
+ ptr8 = ptr8 + (o_img_ptr->uStride - codx);
+ }
+ ////////////////////////////for Y//////////////////////////
+
+ ///////////////////////////////for Cb-Cr//////////////////////
+
+ ptr8Cb = (mmUchar*)o_img_ptr->clrPtr + cox + coy*o_img_ptr->uWidth;
+
+ ptr8Cr = (mmUchar*)(ptr8Cb+1);
+
+ idxC = (idx>>1);
+ for ( row = 0; row < (((cody)>>1)); row++ ) {
+ mmUchar *pu8Cbr1 = NULL;
+ mmUchar *pu8Cbr2 = NULL;
+ mmUchar *pu8Crr1 = NULL;
+ mmUchar *pu8Crr2 = NULL;
+
+ y = (mmUint16) ((mmUint32) (row*resizeFactorY) >> 9);
+ yf = (mmUchar) ((mmUint32)((row*resizeFactorY) >> 6) & 0x7);
+
+ pu8Cbr1 = inImgPtrU + (y) * i_img_ptr->uStride;
+ pu8Cbr2 = pu8Cbr1 + i_img_ptr->uStride;
+ pu8Crr1 = inImgPtrV + (y) * i_img_ptr->uStride;
+ pu8Crr2 = pu8Crr1 + i_img_ptr->uStride;
+
+ for ( col = 0; col < (((codx)>>1)); col++ ) {
+ mmUchar in11, in12, in21, in22;
+ mmUchar *pu8Cbc1 = NULL;
+ mmUchar *pu8Cbc2 = NULL;
+ mmUchar *pu8Crc1 = NULL;
+ mmUchar *pu8Crc2 = NULL;
+
+ mmUchar w;
+ mmUint16 accum_1Cb, accum_1Cr;
+ //mmUint32 accum_WCb, accum_WCr;
+
+ x = (mmUint16) ((mmUint32) (col*resizeFactorX) >> 9);
+ xf = (mmUchar) ((mmUint32) ((col*resizeFactorX) >> 6) & 0x7);
+
+ //accum_WCb = accum_WCr = 0;
+ accum_1Cb = accum_1Cr = 0;
+
+ pu8Cbc1 = pu8Cbr1 + (x*2);
+ pu8Cbc2 = pu8Cbr2 + (x*2);
+ pu8Crc1 = pu8Crr1 + (x*2);
+ pu8Crc2 = pu8Crr2 + (x*2);
+
+ /* A pixel */
+ w = bWeights[xf][yf][0];
+
+ in11 = *(pu8Cbc1);
+ accum_1Cb = (w * in11);
+ // accum_WCb += (w);
+
+ in11 = *(pu8Crc1);
+ accum_1Cr = (w * in11);
+ //accum_WCr += (w);
+
+ /* B pixel */
+ w = bWeights[xf][yf][1];
+
+ in12 = *(pu8Cbc1+2);
+ accum_1Cb += (w * in12);
+ //accum_WCb += (w);
+
+ in12 = *(pu8Crc1+2);
+ accum_1Cr += (w * in12);
+ //accum_WCr += (w);
+
+ /* C pixel */
+ w = bWeights[xf][yf][3];
+
+ in21 = *(pu8Cbc2);
+ accum_1Cb += (w * in21);
+ //accum_WCb += (w);
+
+ in21 = *(pu8Crc2);
+ accum_1Cr += (w * in21);
+ //accum_WCr += (w);
+
+ /* D pixel */
+ w = bWeights[xf][yf][2];
+
+ in22 = *(pu8Cbc2+2);
+ accum_1Cb += (w * in22);
+ //accum_WCb += (w);
+
+ in22 = *(pu8Crc2+2);
+ accum_1Cr += (w * in22);
+ //accum_WCr += (w);
+
+ /* divide by sum of the weights */
+ //accum_1Cb /= (accum_WCb);
+ accum_1Cb = (accum_1Cb>>6);
+ *ptr8Cb = (mmUchar)accum_1Cb ;
+
+ accum_1Cr = (accum_1Cr >> 6);
+ *ptr8Cr = (mmUchar)accum_1Cr ;
+
+ ptr8Cb++;
+ ptr8Cr++;
+
+ ptr8Cb++;
+ ptr8Cr++;
+ }
+ ptr8Cb = ptr8Cb + (o_img_ptr->uStride-codx);
+ ptr8Cr = ptr8Cr + (o_img_ptr->uStride-codx);
+ }
+ ///////////////////For Cb- Cr////////////////////////////////////////
+
+ CAMHAL_LOGV("success");
+ return true;
+}
diff --git a/camera/OMXCameraAdapter/OMX3A.cpp b/camera/OMXCameraAdapter/OMX3A.cpp
new file mode 100644
index 0000000..8e6437a
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMX3A.cpp
@@ -0,0 +1,2161 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMX3A.cpp
+*
+* This file contains functionality for handling 3A configurations.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+
+#include <cutils/properties.h>
+
+#define METERING_AREAS_RANGE 0xFF
+
+static const char PARAM_SEP[] = ",";
+
+namespace Ti {
+namespace Camera {
+
+const SceneModesEntry* OMXCameraAdapter::getSceneModeEntry(const char* name,
+ OMX_SCENEMODETYPE scene) {
+ const SceneModesEntry* cameraLUT = NULL;
+ const SceneModesEntry* entry = NULL;
+ unsigned int numEntries = 0;
+
+ // 1. Find camera's scene mode LUT
+ for (unsigned int i = 0; i < ARRAY_SIZE(CameraToSensorModesLUT); i++) {
+ if (strcmp(CameraToSensorModesLUT[i].name, name) == 0) {
+ cameraLUT = CameraToSensorModesLUT[i].Table;
+ numEntries = CameraToSensorModesLUT[i].size;
+ break;
+ }
+ }
+
+ // 2. Find scene mode entry in table
+ if (!cameraLUT) {
+ goto EXIT;
+ }
+
+ for (unsigned int i = 0; i < numEntries; i++) {
+ if(cameraLUT[i].scene == scene) {
+ entry = cameraLUT + i;
+ break;
+ }
+ }
+ EXIT:
+ return entry;
+}
+
+status_t OMXCameraAdapter::setParameters3A(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ int mode = 0;
+ const char *str = NULL;
+ int varint = 0;
+ BaseCameraAdapter::AdapterState nextState;
+ BaseCameraAdapter::getNextState(nextState);
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(m3ASettingsUpdateLock);
+
+ str = params.get(android::CameraParameters::KEY_SCENE_MODE);
+ mode = getLUTvalue_HALtoOMX( str, SceneLUT);
+ if ( mFirstTimeInit || ((str != NULL) && ( mParameters3A.SceneMode != mode )) ) {
+ if ( 0 <= mode ) {
+ mParameters3A.SceneMode = mode;
+ if ((mode == OMX_Manual) && (mFirstTimeInit == false)){//Auto mode
+ mFirstTimeInit = true;
+ }
+ if ((mode != OMX_Manual) &&
+ (state & PREVIEW_ACTIVE) && !(nextState & CAPTURE_ACTIVE)) {
+ // if setting preset scene mode, previewing, and not in the middle of capture
+ // set preset scene mode immediately instead of in next FBD
+ // for feedback params to work properly since they need to be read
+ // by application in subsequent getParameters()
+ ret |= setScene(mParameters3A);
+ // re-apply EV compensation after setting scene mode since it probably reset it
+ if(mParameters3A.EVCompensation) {
+ setEVCompensation(mParameters3A);
+ }
+ return ret;
+ } else {
+ mPending3Asettings |= SetSceneMode;
+ }
+ } else {
+ mParameters3A.SceneMode = OMX_Manual;
+ }
+ CAMHAL_LOGVB("SceneMode %d", mParameters3A.SceneMode);
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ if ( (str = params.get(TICameraParameters::KEY_EXPOSURE_MODE)) != NULL ) {
+ mode = getLUTvalue_HALtoOMX(str, ExpLUT);
+ if ( mParameters3A.Exposure != mode ) {
+ // If either the new or the old exposure mode is manual set also
+ // the SetManualExposure flag to call setManualExposureVal where
+ // the auto gain and exposure flags are configured
+ if ( mParameters3A.Exposure == OMX_ExposureControlOff ||
+ mode == OMX_ExposureControlOff ) {
+ mPending3Asettings |= SetManualExposure;
+ }
+ mParameters3A.Exposure = mode;
+ CAMHAL_LOGDB("Exposure mode %d", mode);
+ if ( 0 <= mParameters3A.Exposure ) {
+ mPending3Asettings |= SetExpMode;
+ }
+ }
+ if ( mode == OMX_ExposureControlOff ) {
+ mode = params.getInt(TICameraParameters::KEY_MANUAL_EXPOSURE);
+ if ( mParameters3A.ManualExposure != mode ) {
+ mParameters3A.ManualExposure = mode;
+ CAMHAL_LOGDB("Manual Exposure = %d", mode);
+ mPending3Asettings |= SetManualExposure;
+ }
+ mode = params.getInt(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT);
+ if ( mParameters3A.ManualExposureRight != mode ) {
+ mParameters3A.ManualExposureRight = mode;
+ CAMHAL_LOGDB("Manual Exposure right = %d", mode);
+ mPending3Asettings |= SetManualExposure;
+ }
+ mode = params.getInt(TICameraParameters::KEY_MANUAL_GAIN_ISO);
+ if ( mParameters3A.ManualGain != mode ) {
+ mParameters3A.ManualGain = mode;
+ CAMHAL_LOGDB("Manual Gain = %d", mode);
+ mPending3Asettings |= SetManualExposure;
+ }
+ mode = params.getInt(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT);
+ if ( mParameters3A.ManualGainRight != mode ) {
+ mParameters3A.ManualGainRight = mode;
+ CAMHAL_LOGDB("Manual Gain right = %d", mode);
+ mPending3Asettings |= SetManualExposure;
+ }
+ }
+ }
+#endif
+
+ str = params.get(android::CameraParameters::KEY_WHITE_BALANCE);
+ mode = getLUTvalue_HALtoOMX( str, WBalLUT);
+ if (mFirstTimeInit || ((str != NULL) && (mode != mParameters3A.WhiteBallance)))
+ {
+ mParameters3A.WhiteBallance = mode;
+ CAMHAL_LOGDB("Whitebalance mode %d", mode);
+ if ( 0 <= mParameters3A.WhiteBallance )
+ {
+ mPending3Asettings |= SetWhiteBallance;
+ }
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ varint = params.getInt(TICameraParameters::KEY_CONTRAST);
+ if ( 0 <= varint )
+ {
+ if ( mFirstTimeInit ||
+ ( (mParameters3A.Contrast + CONTRAST_OFFSET) != varint ) )
+ {
+ mParameters3A.Contrast = varint - CONTRAST_OFFSET;
+ CAMHAL_LOGDB("Contrast %d", mParameters3A.Contrast);
+ mPending3Asettings |= SetContrast;
+ }
+ }
+
+ varint = params.getInt(TICameraParameters::KEY_SHARPNESS);
+ if ( 0 <= varint )
+ {
+ if ( mFirstTimeInit ||
+ ((mParameters3A.Sharpness + SHARPNESS_OFFSET) != varint ))
+ {
+ mParameters3A.Sharpness = varint - SHARPNESS_OFFSET;
+ CAMHAL_LOGDB("Sharpness %d", mParameters3A.Sharpness);
+ mPending3Asettings |= SetSharpness;
+ }
+ }
+
+ varint = params.getInt(TICameraParameters::KEY_SATURATION);
+ if ( 0 <= varint )
+ {
+ if ( mFirstTimeInit ||
+ ((mParameters3A.Saturation + SATURATION_OFFSET) != varint ) )
+ {
+ mParameters3A.Saturation = varint - SATURATION_OFFSET;
+ CAMHAL_LOGDB("Saturation %d", mParameters3A.Saturation);
+ mPending3Asettings |= SetSaturation;
+ }
+ }
+
+ varint = params.getInt(TICameraParameters::KEY_BRIGHTNESS);
+ if ( 0 <= varint )
+ {
+ if ( mFirstTimeInit ||
+ (( mParameters3A.Brightness != varint )) )
+ {
+ mParameters3A.Brightness = (unsigned) varint;
+ CAMHAL_LOGDB("Brightness %d", mParameters3A.Brightness);
+ mPending3Asettings |= SetBrightness;
+ }
+ }
+#endif
+
+ str = params.get(android::CameraParameters::KEY_ANTIBANDING);
+ mode = getLUTvalue_HALtoOMX(str,FlickerLUT);
+ if ( mFirstTimeInit || ( ( str != NULL ) && ( mParameters3A.Flicker != mode ) ))
+ {
+ mParameters3A.Flicker = mode;
+ CAMHAL_LOGDB("Flicker %d", mParameters3A.Flicker);
+ if ( 0 <= mParameters3A.Flicker )
+ {
+ mPending3Asettings |= SetFlicker;
+ }
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ str = params.get(TICameraParameters::KEY_ISO);
+ mode = getLUTvalue_HALtoOMX(str, IsoLUT);
+ CAMHAL_LOGVB("ISO mode arrived in HAL : %s", str);
+ if ( mFirstTimeInit || ( ( str != NULL ) && ( mParameters3A.ISO != mode )) )
+ {
+ mParameters3A.ISO = mode;
+ CAMHAL_LOGDB("ISO %d", mParameters3A.ISO);
+ if ( 0 <= mParameters3A.ISO )
+ {
+ mPending3Asettings |= SetISO;
+ }
+ }
+#endif
+
+ str = params.get(android::CameraParameters::KEY_FOCUS_MODE);
+ mode = getLUTvalue_HALtoOMX(str, FocusLUT);
+ if ( (mFirstTimeInit || ((str != NULL) && (mParameters3A.Focus != mode))))
+ {
+ mPending3Asettings |= SetFocus;
+
+ mParameters3A.Focus = mode;
+
+ // if focus mode is set to infinity...update focus distance immediately
+ if (mode == OMX_IMAGE_FocusControlAutoInfinity) {
+ updateFocusDistances(mParameters);
+ }
+
+ CAMHAL_LOGDB("Focus %x", mParameters3A.Focus);
+ }
+
+ str = params.get(android::CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ varint = params.getInt(android::CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ if ( mFirstTimeInit || (str && (mParameters3A.EVCompensation != varint))) {
+ CAMHAL_LOGDB("Setting EV Compensation to %d", varint);
+ mParameters3A.EVCompensation = varint;
+ mPending3Asettings |= SetEVCompensation;
+ }
+
+ str = params.get(android::CameraParameters::KEY_FLASH_MODE);
+ mode = getLUTvalue_HALtoOMX( str, FlashLUT);
+ if ( mFirstTimeInit || (( str != NULL ) && ( mParameters3A.FlashMode != mode )) )
+ {
+ if ( 0 <= mode )
+ {
+ mParameters3A.FlashMode = mode;
+ mPending3Asettings |= SetFlash;
+ }
+ else
+ {
+ mParameters3A.FlashMode = OMX_IMAGE_FlashControlAuto;
+ }
+ }
+
+ CAMHAL_LOGVB("Flash Setting %s", str);
+ CAMHAL_LOGVB("FlashMode %d", mParameters3A.FlashMode);
+
+ str = params.get(android::CameraParameters::KEY_EFFECT);
+ mode = getLUTvalue_HALtoOMX( str, EffLUT);
+ if ( mFirstTimeInit || (( str != NULL ) && ( mParameters3A.Effect != mode )) )
+ {
+ mParameters3A.Effect = mode;
+ CAMHAL_LOGDB("Effect %d", mParameters3A.Effect);
+ if ( 0 <= mParameters3A.Effect )
+ {
+ mPending3Asettings |= SetEffect;
+ }
+ }
+
+ str = params.get(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED);
+ if ( (str != NULL) && (!strcmp(str, android::CameraParameters::TRUE)) )
+ {
+ OMX_BOOL lock = OMX_FALSE;
+ mUserSetExpLock = OMX_FALSE;
+ str = params.get(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK);
+ if (str && ((strcmp(str, android::CameraParameters::TRUE)) == 0))
+ {
+ CAMHAL_LOGVA("Locking Exposure");
+ lock = OMX_TRUE;
+ mUserSetExpLock = OMX_TRUE;
+ }
+ else
+ {
+ CAMHAL_LOGVA("UnLocking Exposure");
+ }
+
+ if (mParameters3A.ExposureLock != lock)
+ {
+ mParameters3A.ExposureLock = lock;
+ CAMHAL_LOGDB("ExposureLock %d", lock);
+ mPending3Asettings |= SetExpLock;
+ }
+ }
+
+ str = params.get(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED);
+ if ( (str != NULL) && (!strcmp(str, android::CameraParameters::TRUE)) )
+ {
+ OMX_BOOL lock = OMX_FALSE;
+ mUserSetWbLock = OMX_FALSE;
+ str = params.get(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK);
+ if (str && ((strcmp(str, android::CameraParameters::TRUE)) == 0))
+ {
+ CAMHAL_LOGVA("Locking WhiteBalance");
+ lock = OMX_TRUE;
+ mUserSetWbLock = OMX_TRUE;
+ }
+ else
+ {
+ CAMHAL_LOGVA("UnLocking WhiteBalance");
+ }
+ if (mParameters3A.WhiteBalanceLock != lock)
+ {
+ mParameters3A.WhiteBalanceLock = lock;
+ CAMHAL_LOGDB("WhiteBalanceLock %d", lock);
+ mPending3Asettings |= SetWBLock;
+ }
+ }
+
+ str = params.get(TICameraParameters::KEY_AUTO_FOCUS_LOCK);
+ if (str && (strcmp(str, android::CameraParameters::TRUE) == 0) && (mParameters3A.FocusLock != OMX_TRUE)) {
+ CAMHAL_LOGVA("Locking Focus");
+ mParameters3A.FocusLock = OMX_TRUE;
+ setFocusLock(mParameters3A);
+ } else if (str && (strcmp(str, android::CameraParameters::FALSE) == 0) && (mParameters3A.FocusLock != OMX_FALSE)) {
+ CAMHAL_LOGVA("UnLocking Focus");
+ mParameters3A.FocusLock = OMX_FALSE;
+ setFocusLock(mParameters3A);
+ }
+
+ str = params.get(android::CameraParameters::KEY_METERING_AREAS);
+ if ( (str != NULL) ) {
+ size_t MAX_METERING_AREAS;
+ android::Vector<android::sp<CameraArea> > tempAreas;
+
+ MAX_METERING_AREAS = atoi(params.get(android::CameraParameters::KEY_MAX_NUM_METERING_AREAS));
+
+ android::AutoMutex lock(mMeteringAreasLock);
+
+ ret = CameraArea::parseAreas(str, ( strlen(str) + 1 ), tempAreas);
+
+ CAMHAL_LOGVB("areAreasDifferent? = %d",
+ CameraArea::areAreasDifferent(mMeteringAreas, tempAreas));
+
+ if ( (NO_ERROR == ret) && CameraArea::areAreasDifferent(mMeteringAreas, tempAreas) ) {
+ mMeteringAreas.clear();
+ mMeteringAreas = tempAreas;
+
+ if ( MAX_METERING_AREAS >= mMeteringAreas.size() ) {
+ CAMHAL_LOGDB("Setting Metering Areas %s",
+ params.get(android::CameraParameters::KEY_METERING_AREAS));
+
+ mPending3Asettings |= SetMeteringAreas;
+ } else {
+ CAMHAL_LOGEB("Metering areas supported %d, metering areas set %d",
+ MAX_METERING_AREAS, mMeteringAreas.size());
+ ret = -EINVAL;
+ }
+ }
+ }
+
+#ifndef MOTOROLA_CAMERA
+// TI extensions for enable/disable algos
+ declareParameter3ABool(params, TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA,
+ mParameters3A.AlgoExternalGamma, SetAlgoExternalGamma, "External Gamma");
+ declareParameter3ABool(params, TICameraParameters::KEY_ALGO_NSF1,
+ mParameters3A.AlgoNSF1, SetAlgoNSF1, "NSF1");
+ declareParameter3ABool(params, TICameraParameters::KEY_ALGO_NSF2,
+ mParameters3A.AlgoNSF2, SetAlgoNSF2, "NSF2");
+ declareParameter3ABool(params, TICameraParameters::KEY_ALGO_SHARPENING,
+ mParameters3A.AlgoSharpening, SetAlgoSharpening, "Sharpening");
+ declareParameter3ABool(params, TICameraParameters::KEY_ALGO_THREELINCOLORMAP,
+ mParameters3A.AlgoThreeLinColorMap, SetAlgoThreeLinColorMap, "ThreeLinColorMap");
+ declareParameter3ABool(params, TICameraParameters::KEY_ALGO_GIC, mParameters3A.AlgoGIC, SetAlgoGIC, "GIC");
+
+ // Gamma table
+ str = params.get(TICameraParameters::KEY_GAMMA_TABLE);
+ updateGammaTable(str);
+#endif
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+#ifndef MOTOROLA_CAMERA
+void OMXCameraAdapter::updateGammaTable(const char* gamma)
+{
+ unsigned int plane = 0;
+ unsigned int i = 0;
+ bool gamma_changed = false;
+ const char *a = gamma;
+ OMX_TI_GAMMATABLE_ELEM_TYPE *elem[3] = { mParameters3A.mGammaTable.pR,
+ mParameters3A.mGammaTable.pG,
+ mParameters3A.mGammaTable.pB};
+
+ if (!gamma) return;
+
+ mPending3Asettings &= ~SetGammaTable;
+ memset(&mParameters3A.mGammaTable, 0, sizeof(mParameters3A.mGammaTable));
+ for (plane = 0; plane < 3; plane++) {
+ a = strchr(a, '(');
+ if (NULL != a) {
+ a++;
+ for (i = 0; i < OMX_TI_GAMMATABLE_SIZE; i++) {
+ char *b;
+ int newVal;
+ newVal = strtod(a, &b);
+ if (newVal != elem[plane][i].nOffset) {
+ elem[plane][i].nOffset = newVal;
+ gamma_changed = true;
+ }
+ a = strpbrk(b, ",:)");
+ if ((NULL != a) && (':' == *a)) {
+ a++;
+ } else if ((NULL != a) && (',' == *a)){
+ a++;
+ break;
+ } else if ((NULL != a) && (')' == *a)){
+ a++;
+ break;
+ } else {
+ CAMHAL_LOGE("Error while parsing values");
+ gamma_changed = false;
+ break;
+ }
+ newVal = strtod(a, &b);
+ if (newVal != elem[plane][i].nSlope) {
+ elem[plane][i].nSlope = newVal;
+ gamma_changed = true;
+ }
+ a = strpbrk(b, ",:)");
+ if ((NULL != a) && (',' == *a)) {
+ a++;
+ } else if ((NULL != a) && (':' == *a)){
+ a++;
+ break;
+ } else if ((NULL != a) && (')' == *a)){
+ a++;
+ break;
+ } else {
+ CAMHAL_LOGE("Error while parsing values");
+ gamma_changed = false;
+ break;
+ }
+ }
+ if ((OMX_TI_GAMMATABLE_SIZE - 1) != i) {
+ CAMHAL_LOGE("Error while parsing values (incorrect count %u)", i);
+ gamma_changed = false;
+ break;
+ }
+ } else {
+ CAMHAL_LOGE("Error while parsing planes (%u)", plane);
+ gamma_changed = false;
+ break;
+ }
+ }
+
+ if (gamma_changed) {
+ mPending3Asettings |= SetGammaTable;
+ }
+}
+#endif
+
+void OMXCameraAdapter::declareParameter3ABool(const android::CameraParameters &params, const char *key,
+ OMX_BOOL &current_setting, E3ASettingsFlags pending,
+ const char *msg)
+{
+ OMX_BOOL val = OMX_TRUE;
+ const char *str = params.get(key);
+
+ if (str && ((strcmp(str, android::CameraParameters::FALSE)) == 0))
+ {
+ CAMHAL_LOGVB("Disabling %s", msg);
+ val = OMX_FALSE;
+ }
+ else
+ {
+ CAMHAL_LOGVB("Enabling %s", msg);
+ }
+ if (current_setting != val)
+ {
+ current_setting = val;
+ CAMHAL_LOGDB("%s %s", msg, current_setting ? "enabled" : "disabled");
+ mPending3Asettings |= pending;
+ }
+}
+
+int OMXCameraAdapter::getLUTvalue_HALtoOMX(const char * HalValue, LUTtype LUT)
+{
+ int LUTsize = LUT.size;
+ if( HalValue )
+ for(int i = 0; i < LUTsize; i++)
+ if( 0 == strcmp(LUT.Table[i].userDefinition, HalValue) )
+ return LUT.Table[i].omxDefinition;
+
+ return -ENOENT;
+}
+
+const char* OMXCameraAdapter::getLUTvalue_OMXtoHAL(int OMXValue, LUTtype LUT)
+{
+ int LUTsize = LUT.size;
+ for(int i = 0; i < LUTsize; i++)
+ if( LUT.Table[i].omxDefinition == OMXValue )
+ return LUT.Table[i].userDefinition;
+
+ return NULL;
+}
+
+int OMXCameraAdapter::getMultipleLUTvalue_OMXtoHAL(int OMXValue, LUTtype LUT, char * supported)
+{
+ int num = 0;
+ int remaining_size;
+ int LUTsize = LUT.size;
+ for(int i = 0; i < LUTsize; i++)
+ if( LUT.Table[i].omxDefinition == OMXValue )
+ {
+ num++;
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ remaining_size = ((((int)MAX_PROP_VALUE_LENGTH - 1 - (int)strlen(supported)) < 0) ? 0 : (MAX_PROP_VALUE_LENGTH - 1 - strlen(supported)));
+ strncat(supported, LUT.Table[i].userDefinition, remaining_size);
+ }
+
+ return num;
+}
+
+status_t OMXCameraAdapter::setExposureMode(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXPOSURECONTROLTYPE exp;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&exp, OMX_CONFIG_EXPOSURECONTROLTYPE);
+ exp.nPortIndex = OMX_ALL;
+ exp.eExposureControl = (OMX_EXPOSURECONTROLTYPE)Gen3A.Exposure;
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposure,
+ &exp);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring exposure mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera exposure mode configured successfully");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+static bool isFlashDisabled() {
+#if (PROPERTY_VALUE_MAX < 5)
+#error "PROPERTY_VALUE_MAX must be at least 5"
+#endif
+
+ // Ignore flash_off system property for user build.
+ char buildType[PROPERTY_VALUE_MAX];
+ if (property_get("ro.build.type", buildType, NULL) &&
+ !strcasecmp(buildType, "user")) {
+ return false;
+ }
+
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("camera.flash_off", value, NULL) &&
+ (!strcasecmp(value, android::CameraParameters::TRUE) || !strcasecmp(value, "1"))) {
+ CAMHAL_LOGW("flash is disabled for testing purpose");
+ return true;
+ }
+
+ return false;
+}
+
+status_t OMXCameraAdapter::setManualExposureVal(Gen3A_settings& Gen3A) {
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXPOSUREVALUETYPE expVal;
+ OMX_TI_CONFIG_EXPOSUREVALUERIGHTTYPE expValRight;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&expVal, OMX_CONFIG_EXPOSUREVALUETYPE);
+ OMX_INIT_STRUCT_PTR (&expValRight, OMX_TI_CONFIG_EXPOSUREVALUERIGHTTYPE);
+ expVal.nPortIndex = OMX_ALL;
+ expValRight.nPortIndex = OMX_ALL;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expVal);
+ if ( OMX_ErrorNone == eError ) {
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigRightExposureValue,
+ &expValRight);
+ }
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("OMX_GetConfig error 0x%x (manual exposure values)", eError);
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+
+ if ( Gen3A.Exposure != OMX_ExposureControlOff ) {
+ expVal.bAutoShutterSpeed = OMX_TRUE;
+ expVal.bAutoSensitivity = OMX_TRUE;
+ } else {
+ expVal.bAutoShutterSpeed = OMX_FALSE;
+ expVal.nShutterSpeedMsec = Gen3A.ManualExposure;
+ expValRight.nShutterSpeedMsec = Gen3A.ManualExposureRight;
+ if ( Gen3A.ManualGain <= 0 || Gen3A.ManualGainRight <= 0 ) {
+ expVal.bAutoSensitivity = OMX_TRUE;
+ } else {
+ expVal.bAutoSensitivity = OMX_FALSE;
+ expVal.nSensitivity = Gen3A.ManualGain;
+ expValRight.nSensitivity = Gen3A.ManualGainRight;
+ }
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expVal);
+ if ( OMX_ErrorNone == eError ) {
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigRightExposureValue,
+ &expValRight);
+ }
+
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error 0x%x while configuring manual exposure values", eError);
+ } else {
+ CAMHAL_LOGDA("Camera manual exposure values configured successfully");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setFlashMode(Gen3A_settings& Gen3A)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_PARAM_FLASHCONTROLTYPE flash;
+ OMX_CONFIG_FOCUSASSISTTYPE focusAssist;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&flash, OMX_IMAGE_PARAM_FLASHCONTROLTYPE);
+ flash.nPortIndex = OMX_ALL;
+
+ if (isFlashDisabled()) {
+ flash.eFlashControl = ( OMX_IMAGE_FLASHCONTROLTYPE ) OMX_IMAGE_FlashControlOff;
+ } else {
+ flash.eFlashControl = ( OMX_IMAGE_FLASHCONTROLTYPE ) Gen3A.FlashMode;
+ }
+
+ CAMHAL_LOGDB("Configuring flash mode 0x%x", flash.eFlashControl);
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_IndexConfigFlashControl,
+ &flash);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring flash mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera flash mode configured successfully");
+ }
+
+ if ( OMX_ErrorNone == eError )
+ {
+ OMX_INIT_STRUCT_PTR (&focusAssist, OMX_CONFIG_FOCUSASSISTTYPE);
+ focusAssist.nPortIndex = OMX_ALL;
+ if ( flash.eFlashControl == OMX_IMAGE_FlashControlOff )
+ {
+ focusAssist.bFocusAssist = OMX_FALSE;
+ }
+ else
+ {
+ focusAssist.bFocusAssist = OMX_TRUE;
+ }
+
+ CAMHAL_LOGDB("Configuring AF Assist mode 0x%x", focusAssist.bFocusAssist);
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_IndexConfigFocusAssist,
+ &focusAssist);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring AF Assist mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera AF Assist mode configured successfully");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::getFlashMode(Gen3A_settings& Gen3A)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_PARAM_FLASHCONTROLTYPE flash;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&flash, OMX_IMAGE_PARAM_FLASHCONTROLTYPE);
+ flash.nPortIndex = OMX_ALL;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_IndexConfigFlashControl,
+ &flash);
+
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while getting flash mode 0x%x", eError);
+ } else {
+ Gen3A.FlashMode = flash.eFlashControl;
+ CAMHAL_LOGDB("Gen3A.FlashMode 0x%x", Gen3A.FlashMode);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setFocusMode(Gen3A_settings& Gen3A)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus;
+ size_t top, left, width, height, weight;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+
+ LOG_FUNCTION_NAME;
+
+ BaseCameraAdapter::AdapterState state;
+ BaseCameraAdapter::getState(state);
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+
+ ///Face detection takes precedence over touch AF
+ if ( mFaceDetectionRunning )
+ {
+ //Disable region priority first
+ setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, false);
+
+ //Enable face algorithm priority for focus
+ setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO , true);
+
+ //Do normal focus afterwards
+ ////FIXME: Check if the extended focus control is needed? this overrides caf
+ //focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) OMX_IMAGE_FocusControlExtended;
+ }
+ else if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea()) )
+ {
+
+ //Disable face priority first
+ setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
+
+ //Enable region algorithm priority
+ setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
+
+
+ //Do normal focus afterwards
+ //FIXME: Check if the extended focus control is needed? this overrides caf
+ //focus.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) OMX_IMAGE_FocusControlExtended;
+
+ }
+ else
+ {
+
+ //Disable both region and face priority
+ setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, false);
+
+ setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
+
+ }
+
+ if ( NO_ERROR == ret && ((state & AF_ACTIVE) == 0) )
+ {
+ OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
+
+ if ( Gen3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
+ {
+ // Don't lock at infinity, otherwise the AF cannot drive
+ // the lens at infinity position
+ if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR)
+ {
+ CAMHAL_LOGEA("Error Applying 3A locks");
+ } else {
+ CAMHAL_LOGDA("Focus locked. Applied focus locks successfully");
+ }
+ }
+ if ( Gen3A.Focus == OMX_IMAGE_FocusControlAuto ||
+ Gen3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
+ {
+ // Run focus scanning if switching to continuous infinity focus mode
+ bOMX.bEnabled = OMX_TRUE;
+ }
+ else
+ {
+ bOMX.bEnabled = OMX_FALSE;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable,
+ &bOMX);
+
+ OMX_INIT_STRUCT_PTR (&focus, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
+ focus.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ focus.eFocusControl = (OMX_IMAGE_FOCUSCONTROLTYPE)Gen3A.Focus;
+
+ CAMHAL_LOGDB("Configuring focus mode 0x%x", focus.eFocusControl);
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp, OMX_IndexConfigFocusControl, &focus);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring focus mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera focus mode configured successfully");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::getFocusMode(Gen3A_settings& Gen3A)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus;
+ size_t top, left, width, height, weight;
+
+ LOG_FUNCTION_NAME;
+
+ if (OMX_StateInvalid == mComponentState) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&focus, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
+ focus.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigFocusControl, &focus);
+
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while configuring focus mode 0x%x", eError);
+ } else {
+ Gen3A.Focus = focus.eFocusControl;
+ CAMHAL_LOGDB("Gen3A.Focus 0x%x", Gen3A.Focus);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setScene(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_SCENEMODETYPE scene;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&scene, OMX_CONFIG_SCENEMODETYPE);
+ scene.nPortIndex = OMX_ALL;
+ scene.eSceneMode = ( OMX_SCENEMODETYPE ) Gen3A.SceneMode;
+
+ CAMHAL_LOGDB("Configuring scene mode 0x%x", scene.eSceneMode);
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigSceneMode,
+ &scene);
+
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while configuring scene mode 0x%x", eError);
+ } else {
+ CAMHAL_LOGDA("Camera scene configured successfully");
+ if (Gen3A.SceneMode != OMX_Manual) {
+ // Get preset scene mode feedback
+ getFocusMode(Gen3A);
+ getFlashMode(Gen3A);
+ getWBMode(Gen3A);
+
+ // TODO(XXX): Re-enable these for mainline
+ // getSharpness(Gen3A);
+ // getSaturation(Gen3A);
+ // getISO(Gen3A);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setEVCompensation(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXPOSUREVALUETYPE expValues;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&expValues, OMX_CONFIG_EXPOSUREVALUETYPE);
+ expValues.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expValues);
+ CAMHAL_LOGDB("old EV Compensation for OMX = 0x%x", (int)expValues.xEVCompensation);
+ CAMHAL_LOGDB("EV Compensation for HAL = %d", Gen3A.EVCompensation);
+
+ expValues.xEVCompensation = ( Gen3A.EVCompensation * ( 1 << Q16_OFFSET ) ) / 10;
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expValues);
+ CAMHAL_LOGDB("new EV Compensation for OMX = 0x%x", (int)expValues.xEVCompensation);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring EV Compensation 0x%x error = 0x%x",
+ ( unsigned int ) expValues.xEVCompensation,
+ eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("EV Compensation 0x%x configured successfully",
+ ( unsigned int ) expValues.xEVCompensation);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::getEVCompensation(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXPOSUREVALUETYPE expValues;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&expValues, OMX_CONFIG_EXPOSUREVALUETYPE);
+ expValues.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expValues);
+
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while getting EV Compensation error = 0x%x", eError);
+ } else {
+ Gen3A.EVCompensation = (10 * expValues.xEVCompensation) / (1 << Q16_OFFSET);
+ CAMHAL_LOGDB("Gen3A.EVCompensation 0x%x", Gen3A.EVCompensation);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setWBMode(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_WHITEBALCONTROLTYPE wb;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&wb, OMX_CONFIG_WHITEBALCONTROLTYPE);
+ wb.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ wb.eWhiteBalControl = ( OMX_WHITEBALCONTROLTYPE ) Gen3A.WhiteBallance;
+
+ // disable face and region priorities
+ setAlgoPriority(FACE_PRIORITY, WHITE_BALANCE_ALGO, false);
+ setAlgoPriority(REGION_PRIORITY, WHITE_BALANCE_ALGO, false);
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonWhiteBalance,
+ &wb);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring Whitebalance mode 0x%x error = 0x%x",
+ ( unsigned int ) wb.eWhiteBalControl,
+ eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("Whitebalance mode 0x%x configured successfully",
+ ( unsigned int ) wb.eWhiteBalControl);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return eError;
+}
+
+status_t OMXCameraAdapter::getWBMode(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_WHITEBALCONTROLTYPE wb;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&wb, OMX_CONFIG_WHITEBALCONTROLTYPE);
+ wb.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonWhiteBalance,
+ &wb);
+
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while getting Whitebalance mode error = 0x%x", eError);
+ } else {
+ Gen3A.WhiteBallance = wb.eWhiteBalControl;
+ CAMHAL_LOGDB("Gen3A.WhiteBallance 0x%x", Gen3A.WhiteBallance);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return eError;
+}
+
+status_t OMXCameraAdapter::setFlicker(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_FLICKERCANCELTYPE flicker;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&flicker, OMX_CONFIG_FLICKERCANCELTYPE);
+ flicker.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ flicker.eFlickerCancel = (OMX_COMMONFLICKERCANCELTYPE)Gen3A.Flicker;
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigFlickerCancel,
+ &flicker );
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring Flicker mode 0x%x error = 0x%x",
+ ( unsigned int ) flicker.eFlickerCancel,
+ eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("Flicker mode 0x%x configured successfully",
+ ( unsigned int ) flicker.eFlickerCancel);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setBrightness(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_BRIGHTNESSTYPE brightness;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&brightness, OMX_CONFIG_BRIGHTNESSTYPE);
+ brightness.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ brightness.nBrightness = Gen3A.Brightness;
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonBrightness,
+ &brightness);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring Brightness 0x%x error = 0x%x",
+ ( unsigned int ) brightness.nBrightness,
+ eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("Brightness 0x%x configured successfully",
+ ( unsigned int ) brightness.nBrightness);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setContrast(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CONTRASTTYPE contrast;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&contrast, OMX_CONFIG_CONTRASTTYPE);
+ contrast.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ contrast.nContrast = Gen3A.Contrast;
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonContrast,
+ &contrast);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring Contrast 0x%x error = 0x%x",
+ ( unsigned int ) contrast.nContrast,
+ eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("Contrast 0x%x configured successfully",
+ ( unsigned int ) contrast.nContrast);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return eError;
+}
+
+status_t OMXCameraAdapter::setSharpness(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE procSharpness;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&procSharpness, OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE);
+ procSharpness.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ procSharpness.nLevel = Gen3A.Sharpness;
+
+ if( procSharpness.nLevel == 0 )
+ {
+ procSharpness.bAuto = OMX_TRUE;
+ }
+ else
+ {
+ procSharpness.bAuto = OMX_FALSE;
+ }
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigSharpeningLevel,
+ &procSharpness);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring Sharpness 0x%x error = 0x%x",
+ ( unsigned int ) procSharpness.nLevel,
+ eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("Sharpness 0x%x configured successfully",
+ ( unsigned int ) procSharpness.nLevel);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::getSharpness(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE procSharpness;
+
+ LOG_FUNCTION_NAME;
+
+ if (OMX_StateInvalid == mComponentState) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&procSharpness, OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE);
+ procSharpness.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigSharpeningLevel,
+ &procSharpness);
+
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while configuring Sharpness error = 0x%x", eError);
+ } else {
+ Gen3A.Sharpness = procSharpness.nLevel;
+ CAMHAL_LOGDB("Gen3A.Sharpness 0x%x", Gen3A.Sharpness);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setSaturation(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_SATURATIONTYPE saturation;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&saturation, OMX_CONFIG_SATURATIONTYPE);
+ saturation.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ saturation.nSaturation = Gen3A.Saturation;
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonSaturation,
+ &saturation);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring Saturation 0x%x error = 0x%x",
+ ( unsigned int ) saturation.nSaturation,
+ eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("Saturation 0x%x configured successfully",
+ ( unsigned int ) saturation.nSaturation);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::getSaturation(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_SATURATIONTYPE saturation;
+
+ LOG_FUNCTION_NAME;
+
+ if (OMX_StateInvalid == mComponentState) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&saturation, OMX_CONFIG_SATURATIONTYPE);
+ saturation.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ eError = OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonSaturation,
+ &saturation);
+
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while getting Saturation error = 0x%x", eError);
+ } else {
+ Gen3A.Saturation = saturation.nSaturation;
+ CAMHAL_LOGDB("Gen3A.Saturation 0x%x", Gen3A.Saturation);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setISO(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXPOSUREVALUETYPE expValues;
+ OMX_TI_CONFIG_EXPOSUREVALUERIGHTTYPE expValRight;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ // In case of manual exposure Gain is applied from setManualExposureVal
+ if ( Gen3A.Exposure == OMX_ExposureControlOff ) {
+ return NO_ERROR;
+ }
+
+ OMX_INIT_STRUCT_PTR (&expValues, OMX_CONFIG_EXPOSUREVALUETYPE);
+ OMX_INIT_STRUCT_PTR (&expValRight, OMX_TI_CONFIG_EXPOSUREVALUERIGHTTYPE);
+ expValues.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ expValRight.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ eError = OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expValues);
+
+ if ( OMX_ErrorNone == eError ) {
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigRightExposureValue,
+ &expValRight);
+ }
+
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("OMX_GetConfig error 0x%x (manual exposure values)", eError);
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+
+ if( 0 == Gen3A.ISO ) {
+ expValues.bAutoSensitivity = OMX_TRUE;
+ } else {
+ expValues.bAutoSensitivity = OMX_FALSE;
+ expValues.nSensitivity = Gen3A.ISO;
+ expValRight.nSensitivity = expValues.nSensitivity;
+ }
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expValues);
+
+ if ( OMX_ErrorNone == eError ) {
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigRightExposureValue,
+ &expValRight);
+ }
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring ISO 0x%x error = 0x%x",
+ ( unsigned int ) expValues.nSensitivity,
+ eError);
+ } else {
+ CAMHAL_LOGDB("ISO 0x%x configured successfully",
+ ( unsigned int ) expValues.nSensitivity);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::getISO(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXPOSUREVALUETYPE expValues;
+
+ LOG_FUNCTION_NAME;
+
+ if (OMX_StateInvalid == mComponentState) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&expValues, OMX_CONFIG_EXPOSUREVALUETYPE);
+ expValues.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expValues);
+
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while getting ISO error = 0x%x", eError);
+ } else {
+ Gen3A.ISO = expValues.nSensitivity;
+ CAMHAL_LOGDB("Gen3A.ISO %d", Gen3A.ISO);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setEffect(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_IMAGEFILTERTYPE effect;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&effect, OMX_CONFIG_IMAGEFILTERTYPE);
+ effect.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ effect.eImageFilter = (OMX_IMAGEFILTERTYPE ) Gen3A.Effect;
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonImageFilter,
+ &effect);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring Effect 0x%x error = 0x%x",
+ ( unsigned int ) effect.eImageFilter,
+ eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("Effect 0x%x configured successfully",
+ ( unsigned int ) effect.eImageFilter);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setWhiteBalanceLock(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_LOCKTYPE lock;
+
+ LOG_FUNCTION_NAME
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&lock, OMX_IMAGE_CONFIG_LOCKTYPE);
+ lock.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ lock.bLock = Gen3A.WhiteBalanceLock;
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigImageWhiteBalanceLock,
+ &lock);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring WhiteBalance Lock error = 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("WhiteBalance Lock configured successfully %d ", lock.bLock);
+ }
+ LOG_FUNCTION_NAME_EXIT
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setExposureLock(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_LOCKTYPE lock;
+
+ LOG_FUNCTION_NAME
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&lock, OMX_IMAGE_CONFIG_LOCKTYPE);
+ lock.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ lock.bLock = Gen3A.ExposureLock;
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigImageExposureLock,
+ &lock);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring Exposure Lock error = 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("Exposure Lock configured successfully %d ", lock.bLock);
+ }
+ LOG_FUNCTION_NAME_EXIT
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setFocusLock(Gen3A_settings& Gen3A)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_LOCKTYPE lock;
+
+ LOG_FUNCTION_NAME
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&lock, OMX_IMAGE_CONFIG_LOCKTYPE);
+ lock.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ lock.bLock = Gen3A.FocusLock;
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigImageFocusLock,
+ &lock);
+
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring Focus Lock error = 0x%x", eError);
+ } else {
+ CAMHAL_LOGDB("Focus Lock configured successfully %d ", lock.bLock);
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::set3ALock(OMX_BOOL toggleExp, OMX_BOOL toggleWb, OMX_BOOL toggleFocus)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_LOCKTYPE lock;
+
+ LOG_FUNCTION_NAME
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&lock, OMX_IMAGE_CONFIG_LOCKTYPE);
+ lock.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ mParameters3A.ExposureLock = toggleExp;
+ mParameters3A.FocusLock = toggleFocus;
+ mParameters3A.WhiteBalanceLock = toggleWb;
+
+ eError = OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigImageExposureLock,
+ &lock);
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error GetConfig Exposure Lock error = 0x%x", eError);
+ goto EXIT;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Exposure Lock GetConfig successfull");
+
+ /* Apply locks only when not applied already */
+ if ( lock.bLock != toggleExp )
+ {
+ setExposureLock(mParameters3A);
+ }
+
+ }
+
+ OMX_INIT_STRUCT_PTR (&lock, OMX_IMAGE_CONFIG_LOCKTYPE);
+ lock.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ eError = OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigImageFocusLock,
+ &lock);
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error GetConfig Focus Lock error = 0x%x", eError);
+ goto EXIT;
+ }
+ else
+ {
+ CAMHAL_LOGDB("Focus Lock GetConfig successfull bLock(%d)", lock.bLock);
+
+ /* Apply locks only when not applied already */
+ if ( lock.bLock != toggleFocus )
+ {
+ setFocusLock(mParameters3A);
+ }
+ }
+
+ OMX_INIT_STRUCT_PTR (&lock, OMX_IMAGE_CONFIG_LOCKTYPE);
+ lock.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ eError = OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigImageWhiteBalanceLock,
+ &lock);
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error GetConfig WhiteBalance Lock error = 0x%x", eError);
+ goto EXIT;
+ }
+ else
+ {
+ CAMHAL_LOGDA("WhiteBalance Lock GetConfig successfull");
+
+ /* Apply locks only when not applied already */
+ if ( lock.bLock != toggleWb )
+ {
+ setWhiteBalanceLock(mParameters3A);
+ }
+
+ }
+ EXIT:
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setMeteringAreas(Gen3A_settings& Gen3A)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ CameraBuffer *bufferlist;
+ OMX_ALGOAREASTYPE *meteringAreas;
+ OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
+ int areasSize = 0;
+
+ LOG_FUNCTION_NAME
+
+ android::AutoMutex lock(mMeteringAreasLock);
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096;
+ bufferlist = mMemMgr.allocateBufferList(0, 0, NULL, areasSize, 1);
+ meteringAreas = (OMX_ALGOAREASTYPE *)bufferlist[0].opaque;
+
+ OMXCameraPortParameters * mPreviewData = NULL;
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ if (!meteringAreas)
+ {
+ CAMHAL_LOGEB("Error allocating buffer for metering areas %d", eError);
+ return -ENOMEM;
+ }
+
+ OMX_INIT_STRUCT_PTR (meteringAreas, OMX_ALGOAREASTYPE);
+
+ meteringAreas->nPortIndex = OMX_ALL;
+ meteringAreas->nNumAreas = mMeteringAreas.size();
+ meteringAreas->nAlgoAreaPurpose = OMX_AlgoAreaExposure;
+
+ for ( unsigned int n = 0; n < mMeteringAreas.size(); n++)
+ {
+ int widthDivisor = 1;
+ int heightDivisor = 1;
+
+ if (mPreviewData->mFrameLayoutType == OMX_TI_StereoFrameLayoutTopBottom) {
+ heightDivisor = 2;
+ }
+ if (mPreviewData->mFrameLayoutType == OMX_TI_StereoFrameLayoutLeftRight) {
+ widthDivisor = 2;
+ }
+
+ // transform the coordinates to 3A-type coordinates
+ mMeteringAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth/widthDivisor,
+ (size_t)mPreviewData->mHeight/heightDivisor,
+ (size_t&)meteringAreas->tAlgoAreas[n].nTop,
+ (size_t&)meteringAreas->tAlgoAreas[n].nLeft,
+ (size_t&)meteringAreas->tAlgoAreas[n].nWidth,
+ (size_t&)meteringAreas->tAlgoAreas[n].nHeight);
+
+ meteringAreas->tAlgoAreas[n].nLeft =
+ ( meteringAreas->tAlgoAreas[n].nLeft * METERING_AREAS_RANGE ) / mPreviewData->mWidth;
+ meteringAreas->tAlgoAreas[n].nTop =
+ ( meteringAreas->tAlgoAreas[n].nTop* METERING_AREAS_RANGE ) / mPreviewData->mHeight;
+ meteringAreas->tAlgoAreas[n].nWidth =
+ ( meteringAreas->tAlgoAreas[n].nWidth * METERING_AREAS_RANGE ) / mPreviewData->mWidth;
+ meteringAreas->tAlgoAreas[n].nHeight =
+ ( meteringAreas->tAlgoAreas[n].nHeight * METERING_AREAS_RANGE ) / mPreviewData->mHeight;
+
+ meteringAreas->tAlgoAreas[n].nPriority = mMeteringAreas.itemAt(n)->getWeight();
+
+ CAMHAL_LOGDB("Metering area %d : top = %d left = %d width = %d height = %d prio = %d",
+ n, (int)meteringAreas->tAlgoAreas[n].nTop, (int)meteringAreas->tAlgoAreas[n].nLeft,
+ (int)meteringAreas->tAlgoAreas[n].nWidth, (int)meteringAreas->tAlgoAreas[n].nHeight,
+ (int)meteringAreas->tAlgoAreas[n].nPriority);
+
+ }
+
+ OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
+
+ sharedBuffer.nPortIndex = OMX_ALL;
+ sharedBuffer.nSharedBuffSize = areasSize;
+ sharedBuffer.pSharedBuff = (OMX_U8 *)camera_buffer_get_omx_ptr (&bufferlist[0]);
+
+ if ( NULL == sharedBuffer.pSharedBuff )
+ {
+ CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
+ ret = -ENOMEM;
+ goto EXIT;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer);
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError);
+ ret = -EINVAL;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Metering Areas SetConfig successfull.");
+ }
+
+ EXIT:
+ if (NULL != bufferlist)
+ {
+ mMemMgr.freeBufferList(bufferlist);
+ }
+
+ return ret;
+}
+
+//TI extensions for enable/disable algos
+status_t OMXCameraAdapter::setParameter3ABoolInvert(const OMX_INDEXTYPE omx_idx,
+ const OMX_BOOL data, const char *msg)
+{
+ OMX_BOOL inv_data;
+
+ if (OMX_TRUE == data)
+ {
+ inv_data = OMX_FALSE;
+ }
+ else if (OMX_FALSE == data)
+ {
+ inv_data = OMX_TRUE;
+ }
+ else
+ {
+ return BAD_VALUE;
+ }
+ return setParameter3ABool(omx_idx, inv_data, msg);
+}
+
+status_t OMXCameraAdapter::setParameter3ABool(const OMX_INDEXTYPE omx_idx,
+ const OMX_BOOL data, const char *msg)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_BOOLEANTYPE cfgdata;
+
+ LOG_FUNCTION_NAME
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&cfgdata, OMX_CONFIG_BOOLEANTYPE);
+ cfgdata.bEnabled = data;
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ omx_idx,
+ &cfgdata);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring %s error = 0x%x", msg, eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("%s configured successfully %d ", msg, cfgdata.bEnabled);
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+#ifndef MOTOROLA_CAMERA
+status_t OMXCameraAdapter::setAlgoExternalGamma(Gen3A_settings& Gen3A)
+{
+ return setParameter3ABool((OMX_INDEXTYPE) OMX_TI_IndexConfigExternalGamma, Gen3A.AlgoExternalGamma, "External Gamma");
+}
+
+status_t OMXCameraAdapter::setAlgoNSF1(Gen3A_settings& Gen3A)
+{
+ return setParameter3ABoolInvert((OMX_INDEXTYPE) OMX_TI_IndexConfigDisableNSF1, Gen3A.AlgoNSF1, "NSF1");
+}
+
+status_t OMXCameraAdapter::setAlgoNSF2(Gen3A_settings& Gen3A)
+{
+ return setParameter3ABoolInvert((OMX_INDEXTYPE) OMX_TI_IndexConfigDisableNSF2, Gen3A.AlgoNSF2, "NSF2");
+}
+
+status_t OMXCameraAdapter::setAlgoSharpening(Gen3A_settings& Gen3A)
+{
+ return setParameter3ABoolInvert((OMX_INDEXTYPE) OMX_TI_IndexConfigDisableSharpening, Gen3A.AlgoSharpening, "Sharpening");
+}
+
+status_t OMXCameraAdapter::setAlgoThreeLinColorMap(Gen3A_settings& Gen3A)
+{
+ return setParameter3ABoolInvert((OMX_INDEXTYPE) OMX_TI_IndexConfigDisableThreeLinColorMap, Gen3A.AlgoThreeLinColorMap, "Color Conversion");
+}
+
+status_t OMXCameraAdapter::setAlgoGIC(Gen3A_settings& Gen3A)
+{
+ return setParameter3ABoolInvert((OMX_INDEXTYPE) OMX_TI_IndexConfigDisableGIC, Gen3A.AlgoGIC, "Green Inballance Correction");
+}
+
+status_t OMXCameraAdapter::setGammaTable(Gen3A_settings& Gen3A)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ CameraBuffer *bufferlist = NULL;
+ OMX_TI_CONFIG_GAMMATABLE_TYPE *gammaTable = NULL;
+ OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
+ int tblSize = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = NO_INIT;
+ goto EXIT;
+ }
+
+ tblSize = ((sizeof(OMX_TI_CONFIG_GAMMATABLE_TYPE)+4095)/4096)*4096;
+ bufferlist = mMemMgr.allocateBufferList(0, 0, NULL, tblSize, 1);
+ if (NULL == bufferlist) {
+ CAMHAL_LOGEB("Error allocating buffer for gamma table");
+ ret = NO_MEMORY;
+ goto EXIT;
+ }
+ gammaTable = (OMX_TI_CONFIG_GAMMATABLE_TYPE *)bufferlist[0].mapped;
+ if (NULL == gammaTable) {
+ CAMHAL_LOGEB("Error allocating buffer for gamma table (wrong data pointer)");
+ ret = NO_MEMORY;
+ goto EXIT;
+ }
+
+ memcpy(gammaTable, &mParameters3A.mGammaTable, sizeof(OMX_TI_CONFIG_GAMMATABLE_TYPE));
+
+#ifdef CAMERAHAL_DEBUG
+ {
+ android::String8 DmpR;
+ android::String8 DmpG;
+ android::String8 DmpB;
+ for (unsigned int i=0; i<OMX_TI_GAMMATABLE_SIZE;i++) {
+ DmpR.appendFormat(" %d:%d;", (int)gammaTable->pR[i].nOffset, (int)(int)gammaTable->pR[i].nSlope);
+ DmpG.appendFormat(" %d:%d;", (int)gammaTable->pG[i].nOffset, (int)(int)gammaTable->pG[i].nSlope);
+ DmpB.appendFormat(" %d:%d;", (int)gammaTable->pB[i].nOffset, (int)(int)gammaTable->pB[i].nSlope);
+ }
+ CAMHAL_LOGE("Gamma table R:%s", DmpR.string());
+ CAMHAL_LOGE("Gamma table G:%s", DmpG.string());
+ CAMHAL_LOGE("Gamma table B:%s", DmpB.string());
+ }
+#endif
+
+ OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
+ sharedBuffer.nPortIndex = OMX_ALL;
+ sharedBuffer.nSharedBuffSize = sizeof(OMX_TI_CONFIG_GAMMATABLE_TYPE);
+ sharedBuffer.pSharedBuff = (OMX_U8 *)camera_buffer_get_omx_ptr (&bufferlist[0]);
+ if ( NULL == sharedBuffer.pSharedBuff ) {
+ CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
+ ret = NO_MEMORY;
+ goto EXIT;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigGammaTable, &sharedBuffer);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while setting Gamma Table configuration 0x%x", eError);
+ ret = BAD_VALUE;
+ goto EXIT;
+ } else {
+ CAMHAL_LOGDA("Gamma Table SetConfig successfull.");
+ }
+
+EXIT:
+
+ if (NULL != bufferlist) {
+ mMemMgr.freeBufferList(bufferlist);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+#endif
+
+status_t OMXCameraAdapter::apply3Asettings( Gen3A_settings& Gen3A )
+{
+ status_t ret = NO_ERROR;
+ unsigned int currSett; // 32 bit
+ int portIndex;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(m3ASettingsUpdateLock);
+
+ /*
+ * Scenes have a priority during the process
+ * of applying 3A related parameters.
+ * They can override pretty much all other 3A
+ * settings and similarly get overridden when
+ * for instance the focus mode gets switched.
+ * There is only one exception to this rule,
+ * the manual a.k.a. auto scene.
+ */
+ if (SetSceneMode & mPending3Asettings) {
+ mPending3Asettings &= ~SetSceneMode;
+ ret |= setScene(Gen3A);
+ // re-apply EV compensation after setting scene mode since it probably reset it
+ if(Gen3A.EVCompensation) {
+ setEVCompensation(Gen3A);
+ }
+ return ret;
+ } else if (OMX_Manual != Gen3A.SceneMode) {
+ // only certain settings are allowed when scene mode is set
+ mPending3Asettings &= (SetEVCompensation | SetFocus | SetWBLock |
+ SetExpLock | SetWhiteBallance | SetFlash);
+ if ( mPending3Asettings == 0 ) return NO_ERROR;
+ }
+
+ for( currSett = 1; currSett < E3aSettingMax; currSett <<= 1)
+ {
+ if( currSett & mPending3Asettings )
+ {
+ switch( currSett )
+ {
+ case SetEVCompensation:
+ {
+ ret |= setEVCompensation(Gen3A);
+ break;
+ }
+
+ case SetWhiteBallance:
+ {
+ ret |= setWBMode(Gen3A);
+ break;
+ }
+
+ case SetFlicker:
+ {
+ ret |= setFlicker(Gen3A);
+ break;
+ }
+
+ case SetBrightness:
+ {
+ ret |= setBrightness(Gen3A);
+ break;
+ }
+
+ case SetContrast:
+ {
+ ret |= setContrast(Gen3A);
+ break;
+ }
+
+ case SetSharpness:
+ {
+ ret |= setSharpness(Gen3A);
+ break;
+ }
+
+ case SetSaturation:
+ {
+ ret |= setSaturation(Gen3A);
+ break;
+ }
+
+ case SetISO:
+ {
+ ret |= setISO(Gen3A);
+ break;
+ }
+
+ case SetEffect:
+ {
+ ret |= setEffect(Gen3A);
+ break;
+ }
+
+ case SetFocus:
+ {
+ ret |= setFocusMode(Gen3A);
+ break;
+ }
+
+ case SetExpMode:
+ {
+ ret |= setExposureMode(Gen3A);
+ break;
+ }
+
+ case SetManualExposure: {
+ ret |= setManualExposureVal(Gen3A);
+ break;
+ }
+
+ case SetFlash:
+ {
+ ret |= setFlashMode(Gen3A);
+ break;
+ }
+
+ case SetExpLock:
+ {
+ ret |= setExposureLock(Gen3A);
+ break;
+ }
+
+ case SetWBLock:
+ {
+ ret |= setWhiteBalanceLock(Gen3A);
+ break;
+ }
+ case SetMeteringAreas:
+ {
+ ret |= setMeteringAreas(Gen3A);
+ }
+ break;
+
+#ifndef MOTOROLA_CAMERA
+ //TI extensions for enable/disable algos
+ case SetAlgoExternalGamma:
+ {
+ ret |= setAlgoExternalGamma(Gen3A);
+ }
+ break;
+
+ case SetAlgoNSF1:
+ {
+ ret |= setAlgoNSF1(Gen3A);
+ }
+ break;
+
+ case SetAlgoNSF2:
+ {
+ ret |= setAlgoNSF2(Gen3A);
+ }
+ break;
+
+ case SetAlgoSharpening:
+ {
+ ret |= setAlgoSharpening(Gen3A);
+ }
+ break;
+
+ case SetAlgoThreeLinColorMap:
+ {
+ ret |= setAlgoThreeLinColorMap(Gen3A);
+ }
+ break;
+
+ case SetAlgoGIC:
+ {
+ ret |= setAlgoGIC(Gen3A);
+ }
+ break;
+
+ case SetGammaTable:
+ {
+ ret |= setGammaTable(Gen3A);
+ }
+ break;
+#endif
+
+ default:
+ CAMHAL_LOGEB("this setting (0x%x) is still not supported in CameraAdapter ",
+ currSett);
+ break;
+ }
+ mPending3Asettings &= ~currSett;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXAlgo.cpp b/camera/OMXCameraAdapter/OMXAlgo.cpp
new file mode 100644
index 0000000..72ce1f6
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXAlgo.cpp
@@ -0,0 +1,1355 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXAlgo.cpp
+*
+* This file contains functionality for handling algorithm configurations.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+
+#undef TRUE
+
+namespace Ti {
+namespace Camera {
+
+status_t OMXCameraAdapter::setParametersAlgo(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *valstr = NULL;
+ const char *valManualStr = NULL;
+ const char *oldstr = NULL;
+ OMXCameraPortParameters *cap;
+ BrightnessMode gbce = BRIGHTNESS_OFF;
+ BrightnessMode glbce = BRIGHTNESS_OFF;
+
+ LOG_FUNCTION_NAME;
+
+ CaptureMode capMode;
+ CAMHAL_LOGDB("Capture mode %s", params.get(TICameraParameters::KEY_CAP_MODE));
+ if ( (valstr = params.get(TICameraParameters::KEY_CAP_MODE)) != NULL ) {
+ if (strcmp(valstr, (const char *) TICameraParameters::HIGH_PERFORMANCE_MODE) == 0) {
+ capMode = OMXCameraAdapter::HIGH_SPEED;
+ mCapabilitiesOpMode = MODE_HIGH_SPEED;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::EXPOSURE_BRACKETING) == 0) {
+ capMode = OMXCameraAdapter::HIGH_SPEED;
+ mCapabilitiesOpMode = MODE_HIGH_SPEED;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::ZOOM_BRACKETING) == 0) {
+ capMode = OMXCameraAdapter::HIGH_SPEED;
+ mCapabilitiesOpMode = MODE_HIGH_SPEED;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::HIGH_QUALITY_MODE) == 0) {
+ capMode = OMXCameraAdapter::HIGH_QUALITY;
+ mCapabilitiesOpMode = MODE_HIGH_QUALITY;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::HIGH_QUALITY_ZSL_MODE) == 0) {
+ capMode = OMXCameraAdapter::HIGH_QUALITY_ZSL;
+ mCapabilitiesOpMode = MODE_ZEROSHUTTERLAG;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE) == 0) {
+ capMode = OMXCameraAdapter::VIDEO_MODE;
+ mCapabilitiesOpMode = MODE_VIDEO;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE_HQ) == 0) {
+ capMode = OMXCameraAdapter::VIDEO_MODE_HQ;
+ mCapabilitiesOpMode = MODE_VIDEO_HIGH_QUALITY;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::CP_CAM_MODE) == 0) {
+ capMode = OMXCameraAdapter::CP_CAM;
+ mCapabilitiesOpMode = MODE_CPCAM;
+ } else if (strcmp(valstr, (const char *) TICameraParameters::TEMP_BRACKETING) == 0) {
+ capMode = OMXCameraAdapter::HIGH_SPEED;
+ mCapabilitiesOpMode = MODE_HIGH_SPEED;
+ } else {
+ capMode = OMXCameraAdapter::HIGH_QUALITY;
+ mCapabilitiesOpMode = MODE_HIGH_QUALITY;
+ }
+
+ } else {
+ capMode = OMXCameraAdapter::HIGH_QUALITY;
+ mCapabilitiesOpMode = MODE_HIGH_QUALITY;
+ }
+
+ if ( mSensorIndex == 2 ) {
+ mCapabilitiesOpMode = MODE_STEREO;
+ }
+
+ if ( mCapMode != capMode ) {
+ mCapMode = capMode;
+ mOMXStateSwitch = true;
+ mPendingPreviewSettings |= SetCapMode;
+ }
+
+ CAMHAL_LOGDB("Capture Mode set %d", mCapMode);
+
+ /// Configure IPP, LDCNSF, GBCE and GLBCE only in HQ mode
+ IPPMode ipp;
+ if((mCapMode == OMXCameraAdapter::HIGH_QUALITY) || (mCapMode == OMXCameraAdapter::HIGH_QUALITY_ZSL)
+ || (mCapMode == OMXCameraAdapter::VIDEO_MODE)
+ || (mCapMode == OMXCameraAdapter::CP_CAM))
+ {
+ if ( (valstr = params.get(TICameraParameters::KEY_IPP)) != NULL )
+ {
+ if (strcmp(valstr, (const char *) TICameraParameters::IPP_LDCNSF) == 0)
+ {
+ ipp = OMXCameraAdapter::IPP_LDCNSF;
+ }
+ else if (strcmp(valstr, (const char *) TICameraParameters::IPP_LDC) == 0)
+ {
+ ipp = OMXCameraAdapter::IPP_LDC;
+ }
+ else if (strcmp(valstr, (const char *) TICameraParameters::IPP_NSF) == 0)
+ {
+ ipp = OMXCameraAdapter::IPP_NSF;
+ }
+ else if (strcmp(valstr, (const char *) TICameraParameters::IPP_NONE) == 0)
+ {
+ ipp = OMXCameraAdapter::IPP_NONE;
+ }
+ else
+ {
+ ipp = OMXCameraAdapter::IPP_NONE;
+ }
+ }
+ else
+ {
+ ipp = OMXCameraAdapter::IPP_NONE;
+ }
+
+ CAMHAL_LOGVB("IPP Mode set %d", ipp);
+
+ if (((valstr = params.get(TICameraParameters::KEY_GBCE)) != NULL) ) {
+ if (strcmp(valstr, android::CameraParameters::TRUE ) == 0) {
+ gbce = BRIGHTNESS_ON;
+ } else {
+ gbce = BRIGHTNESS_OFF;
+ }
+
+ if ( gbce != mGBCE ) {
+ mGBCE = gbce;
+ setGBCE(mGBCE);
+ }
+
+ } else if(mFirstTimeInit) {
+ //Disable GBCE by default
+ setGBCE(OMXCameraAdapter::BRIGHTNESS_OFF);
+ }
+
+ if ( ( valstr = params.get(TICameraParameters::KEY_GLBCE) ) != NULL ) {
+
+ if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
+ glbce = BRIGHTNESS_ON;
+ } else {
+ glbce = BRIGHTNESS_OFF;
+ }
+
+ if ( glbce != mGLBCE ) {
+ mGLBCE = glbce;
+ setGLBCE(mGLBCE);
+ }
+
+ } else if(mFirstTimeInit) {
+ //Disable GLBCE by default
+ setGLBCE(OMXCameraAdapter::BRIGHTNESS_OFF);
+ }
+
+ } else {
+ ipp = OMXCameraAdapter::IPP_NONE;
+ }
+
+ if ( mIPP != ipp )
+ {
+ mIPP = ipp;
+ mOMXStateSwitch = true;
+ mPendingPreviewSettings |= SetLDC;
+ mPendingPreviewSettings |= SetNSF;
+ }
+
+ ///Set VNF Configuration
+ bool vnfEnabled = false;
+ valstr = params.get(TICameraParameters::KEY_VNF);
+ if (valstr && strcmp(valstr, android::CameraParameters::TRUE) == 0)
+ {
+ CAMHAL_LOGDA("VNF Enabled");
+ vnfEnabled = true;
+ }
+ else
+ {
+ CAMHAL_LOGDA("VNF Disabled");
+ vnfEnabled = false;
+ }
+
+ if ( mVnfEnabled != vnfEnabled )
+ {
+ mVnfEnabled = vnfEnabled;
+ mOMXStateSwitch = true;
+ mPendingPreviewSettings |= SetVNF;
+ }
+
+ ///Set VSTAB Configuration
+ bool vstabEnabled = false;
+ valstr = params.get(android::CameraParameters::KEY_VIDEO_STABILIZATION);
+ if (valstr && strcmp(valstr, android::CameraParameters::TRUE) == 0) {
+ CAMHAL_LOGDA("VSTAB Enabled");
+ vstabEnabled = true;
+ }
+ else
+ {
+ CAMHAL_LOGDA("VSTAB Disabled");
+ vstabEnabled = false;
+ }
+
+ if ( mVstabEnabled != vstabEnabled )
+ {
+ mVstabEnabled = vstabEnabled;
+ mOMXStateSwitch = true;
+ mPendingPreviewSettings |= SetVSTAB;
+ }
+
+ //A work-around for a failing call to OMX flush buffers
+ if ( ( capMode = OMXCameraAdapter::VIDEO_MODE ) &&
+ ( mVstabEnabled ) )
+ {
+ mOMXStateSwitch = true;
+ }
+
+#ifdef OMAP_ENHANCEMENT
+
+ //Set Auto Convergence Mode
+ valstr = params.get((const char *) TICameraParameters::KEY_AUTOCONVERGENCE_MODE);
+ valManualStr = params.get(TICameraParameters::KEY_MANUAL_CONVERGENCE);
+
+ cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ if (cap->mFrameLayoutType != OMX_TI_StereoFrameLayout2D) {
+ if ((valstr != NULL) || (valManualStr != NULL)) {
+ setAutoConvergence(valstr, valManualStr, params);
+ if (valstr != NULL) {
+ CAMHAL_LOGDB("AutoConvergenceMode %s", valstr);
+ }
+ if (valManualStr != NULL) {
+ CAMHAL_LOGDB("Manual Convergence %s", valManualStr);
+ }
+ }
+
+ //Set Mechanical Misalignment Correction
+ valstr = params.get(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION);
+ if ( valstr != NULL ) {
+ setMechanicalMisalignmentCorrection(strcmp(valstr, android::CameraParameters::TRUE) == 0);
+ CAMHAL_LOGDB("Mechanical Misalignment Correction %s", valstr);
+ }
+ }
+
+#endif
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+// Set AutoConvergence
+status_t OMXCameraAdapter::setAutoConvergence(const char *pValstr, const char *pValManualstr, const android::CameraParameters &params)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_CONVERGENCETYPE ACParams;
+ const char *str = NULL;
+ android::Vector<android::sp<CameraArea> > tempAreas;
+ int mode;
+ int changed = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( pValManualstr != NULL ) {
+ OMX_S32 manualConvergence = (OMX_S32)strtol(pValManualstr ,0 ,0);
+
+ if (mManualConv != manualConvergence) {
+ mManualConv = manualConvergence;
+ changed = 1;
+ }
+ }
+
+ if ( pValstr != NULL ) {
+ mode = getLUTvalue_HALtoOMX(pValstr, mAutoConvergenceLUT);
+
+ if ( NAME_NOT_FOUND == mode ) {
+ CAMHAL_LOGEB("Wrong convergence mode: %s", pValstr);
+ LOG_FUNCTION_NAME_EXIT;
+ return mode;
+ }
+
+ if ( mAutoConv != static_cast<OMX_TI_AUTOCONVERGENCEMODETYPE> (mode) ) {
+ mAutoConv = static_cast<OMX_TI_AUTOCONVERGENCEMODETYPE> (mode);
+ changed = 1;
+ }
+ }
+
+ if ( OMX_TI_AutoConvergenceModeFocusFaceTouch == mAutoConv ) {
+ android::AutoMutex lock(mTouchAreasLock);
+
+ str = params.get(android::CameraParameters::KEY_METERING_AREAS);
+
+ if ( NULL != str ) {
+ ret = CameraArea::parseAreas(str, ( strlen(str) + 1 ), tempAreas);
+ } else {
+ CAMHAL_LOGEB("Touch areas not received in %s",
+ android::CameraParameters::KEY_METERING_AREAS);
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ if ( CameraArea::areAreasDifferent(mTouchAreas, tempAreas) ) {
+ mTouchAreas.clear();
+ mTouchAreas = tempAreas;
+ changed = 1;
+ }
+ }
+
+ if (!changed) {
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+ }
+
+ OMXCameraPortParameters * mPreviewData;
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ ACParams.nSize = (OMX_U32)sizeof(OMX_TI_CONFIG_CONVERGENCETYPE);
+ ACParams.nVersion = mLocalVersionParam;
+ ACParams.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoConvergence,
+ &ACParams);
+
+ ACParams.eACMode = mAutoConv;
+ ACParams.nManualConverence = mManualConv;
+
+ if (1 == mTouchAreas.size()) {
+ int widthDivisor = 1;
+ int heightDivisor = 1;
+
+ if (mPreviewData->mFrameLayoutType == OMX_TI_StereoFrameLayoutTopBottom) {
+ heightDivisor = 2;
+ }
+ if (mPreviewData->mFrameLayoutType == OMX_TI_StereoFrameLayoutLeftRight) {
+ widthDivisor = 2;
+ }
+
+ // transform the coordinates to 3A-type coordinates
+ mTouchAreas.itemAt(0)->transfrom((size_t)mPreviewData->mWidth/widthDivisor,
+ (size_t)mPreviewData->mHeight/heightDivisor,
+ (size_t&) ACParams.nACProcWinStartY,
+ (size_t&) ACParams.nACProcWinStartX,
+ (size_t&) ACParams.nACProcWinWidth,
+ (size_t&) ACParams.nACProcWinHeight);
+ }
+
+ CAMHAL_LOGDB("nSize %d", (int)ACParams.nSize);
+ CAMHAL_LOGDB("nPortIndex %d", (int)ACParams.nPortIndex);
+ CAMHAL_LOGDB("nManualConverence %d", (int)ACParams.nManualConverence);
+ CAMHAL_LOGDB("eACMode %d", (int)ACParams.eACMode);
+ CAMHAL_LOGDB("nACProcWinStartX %d", (int)ACParams.nACProcWinStartX);
+ CAMHAL_LOGDB("nACProcWinStartY %d", (int)ACParams.nACProcWinStartY);
+ CAMHAL_LOGDB("nACProcWinWidth %d", (int)ACParams.nACProcWinWidth);
+ CAMHAL_LOGDB("nACProcWinHeight %d", (int)ACParams.nACProcWinHeight);
+ CAMHAL_LOGDB("bACStatus %d", (int)ACParams.bACStatus);
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoConvergence,
+ &ACParams);
+
+ if ( eError != OMX_ErrorNone ) {
+ CAMHAL_LOGEB("Error while setting AutoConvergence 0x%x", eError);
+ ret = BAD_VALUE;
+ } else {
+ CAMHAL_LOGDA("AutoConvergence applied successfully");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::enableVideoNoiseFilter(bool enable)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_PARAM_VIDEONOISEFILTERTYPE vnfCfg;
+
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&vnfCfg, OMX_PARAM_VIDEONOISEFILTERTYPE);
+
+ if ( enable )
+ {
+ CAMHAL_LOGDA("VNF is enabled");
+ vnfCfg.eMode = OMX_VideoNoiseFilterModeOn;
+ }
+ else
+ {
+ CAMHAL_LOGDA("VNF is disabled");
+ vnfCfg.eMode = OMX_VideoNoiseFilterModeOff;
+ }
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexParamVideoNoiseFilter,
+ &vnfCfg);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring video noise filter 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Video noise filter is configured successfully");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::enableVideoStabilization(bool enable)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_FRAMESTABTYPE frameStabCfg;
+
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_CONFIG_BOOLEANTYPE vstabp;
+ OMX_INIT_STRUCT_PTR (&vstabp, OMX_CONFIG_BOOLEANTYPE);
+ if(enable)
+ {
+ vstabp.bEnabled = OMX_TRUE;
+ }
+ else
+ {
+ vstabp.bEnabled = OMX_FALSE;
+ }
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexParamFrameStabilisation,
+ &vstabp);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring video stabilization param 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Video stabilization param configured successfully");
+ }
+
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ OMX_INIT_STRUCT_PTR (&frameStabCfg, OMX_CONFIG_FRAMESTABTYPE);
+
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigCommonFrameStabilisation,
+ &frameStabCfg);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while getting video stabilization mode 0x%x",
+ (unsigned int)eError);
+ ret = -1;
+ }
+
+ CAMHAL_LOGDB("VSTAB Port Index = %d", (int)frameStabCfg.nPortIndex);
+
+ frameStabCfg.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ if ( enable )
+ {
+ CAMHAL_LOGDA("VSTAB is enabled");
+ frameStabCfg.bStab = OMX_TRUE;
+ }
+ else
+ {
+ CAMHAL_LOGDA("VSTAB is disabled");
+ frameStabCfg.bStab = OMX_FALSE;
+
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigCommonFrameStabilisation,
+ &frameStabCfg);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring video stabilization mode 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Video stabilization mode configured successfully");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setGBCE(OMXCameraAdapter::BrightnessMode mode)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_LOCAL_AND_GLOBAL_BRIGHTNESSCONTRASTTYPE bControl;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&bControl, OMX_TI_CONFIG_LOCAL_AND_GLOBAL_BRIGHTNESSCONTRASTTYPE);
+
+ bControl.nPortIndex = OMX_ALL;
+
+ switch ( mode )
+ {
+ case OMXCameraAdapter::BRIGHTNESS_ON:
+ {
+ bControl.eControl = OMX_TI_BceModeOn;
+ break;
+ }
+ case OMXCameraAdapter::BRIGHTNESS_AUTO:
+ {
+ bControl.eControl = OMX_TI_BceModeAuto;
+ break;
+ }
+ case OMXCameraAdapter::BRIGHTNESS_OFF:
+ default:
+ {
+ bControl.eControl = OMX_TI_BceModeOff;
+ break;
+ }
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigGlobalBrightnessContrastEnhance,
+ &bControl);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while setting GBCE 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDB("GBCE configured successfully 0x%x", mode);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setGLBCE(OMXCameraAdapter::BrightnessMode mode)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_LOCAL_AND_GLOBAL_BRIGHTNESSCONTRASTTYPE bControl;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&bControl, OMX_TI_CONFIG_LOCAL_AND_GLOBAL_BRIGHTNESSCONTRASTTYPE);
+ bControl.nPortIndex = OMX_ALL;
+
+ switch ( mode )
+ {
+ case OMXCameraAdapter::BRIGHTNESS_ON:
+ {
+ bControl.eControl = OMX_TI_BceModeOn;
+ break;
+ }
+ case OMXCameraAdapter::BRIGHTNESS_AUTO:
+ {
+ bControl.eControl = OMX_TI_BceModeAuto;
+ break;
+ }
+ case OMXCameraAdapter::BRIGHTNESS_OFF:
+ default:
+ {
+ bControl.eControl = OMX_TI_BceModeOff;
+ break;
+ }
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigLocalBrightnessContrastEnhance,
+ &bControl);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configure GLBCE 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("GLBCE configured successfully");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setCaptureMode(OMXCameraAdapter::CaptureMode mode)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CAMOPERATINGMODETYPE camMode;
+ OMX_CONFIG_BOOLEANTYPE bCAC;
+ OMX_TI_CONFIG_SINGLEPREVIEWMODETYPE singlePrevMode;
+
+ LOG_FUNCTION_NAME;
+
+ //CAC is disabled by default
+ OMX_INIT_STRUCT_PTR (&bCAC, OMX_CONFIG_BOOLEANTYPE);
+ OMX_INIT_STRUCT_PTR (&singlePrevMode, OMX_TI_CONFIG_SINGLEPREVIEWMODETYPE);
+ bCAC.bEnabled = OMX_FALSE;
+
+ if ( NO_ERROR == ret )
+ {
+
+ OMX_INIT_STRUCT_PTR (&camMode, OMX_CONFIG_CAMOPERATINGMODETYPE);
+ if ( mSensorIndex == OMX_TI_StereoSensor ) {
+ if ( OMXCameraAdapter::VIDEO_MODE == mode ) {
+ CAMHAL_LOGDA("Camera mode: STEREO VIDEO");
+ camMode.eCamOperatingMode = OMX_TI_StereoVideo;
+ } else {
+ CAMHAL_LOGDA("Camera mode: STEREO");
+ camMode.eCamOperatingMode = OMX_CaptureStereoImageCapture;
+ }
+ } else if ( OMXCameraAdapter::HIGH_SPEED == mode ) {
+ CAMHAL_LOGDA("Camera mode: HIGH SPEED");
+ camMode.eCamOperatingMode = OMX_CaptureImageHighSpeedTemporalBracketing;
+ } else if ( OMXCameraAdapter::CP_CAM == mode ) {
+ CAMHAL_LOGDA("Camera mode: CP CAM");
+ camMode.eCamOperatingMode = OMX_TI_CPCam;
+ // TODO(XXX): Hardcode for now until we implement re-proc pipe
+ singlePrevMode.eMode = OMX_TI_SinglePreviewMode_ImageCaptureHighSpeed;
+ } else if( OMXCameraAdapter::HIGH_QUALITY == mode ) {
+ CAMHAL_LOGDA("Camera mode: HIGH QUALITY");
+ camMode.eCamOperatingMode = OMX_CaptureImageProfileBase;
+ } else if( OMXCameraAdapter::HIGH_QUALITY_ZSL== mode ) {
+ const char* valstr = NULL;
+ CAMHAL_LOGDA("Camera mode: HIGH QUALITY_ZSL");
+ camMode.eCamOperatingMode = OMX_TI_CaptureImageProfileZeroShutterLag;
+
+#ifdef CAMERAHAL_TUNA
+ if ( !mIternalRecordingHint ) {
+ zslHistoryLen.nHistoryLen = 5;
+ }
+#endif
+
+ } else if( OMXCameraAdapter::VIDEO_MODE == mode ) {
+ CAMHAL_LOGDA("Camera mode: VIDEO MODE");
+ camMode.eCamOperatingMode = OMX_CaptureVideo;
+ } else if( OMXCameraAdapter::VIDEO_MODE_HQ == mode ) {
+ CAMHAL_LOGDA("Camera mode: VIDEO MODE HQ");
+ camMode.eCamOperatingMode = OMX_CaptureHighQualityVideo;
+ } else {
+ CAMHAL_LOGEA("Camera mode: INVALID mode passed!");
+ return BAD_VALUE;
+ }
+
+ if( NO_ERROR == ret )
+ {
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexCameraOperatingMode,
+ &camMode);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring camera mode 0x%x", eError);
+ ret = Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera mode configured successfully");
+ }
+ }
+
+ if((NO_ERROR == ret) && (OMXCameraAdapter::CP_CAM == mode)) {
+ //Configure Single Preview Mode
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigSinglePreviewMode,
+ &singlePrevMode);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring single preview mode 0x%x", eError);
+ ret = Utils::ErrorUtils::omxToAndroidError(eError);
+ } else {
+ CAMHAL_LOGDA("single preview mode configured successfully");
+ }
+ }
+
+
+ if( NO_ERROR == ret )
+ {
+ //Configure CAC
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigChromaticAberrationCorrection,
+ &bCAC);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring CAC 0x%x", eError);
+ ret = Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("CAC configured successfully");
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setLDC(OMXCameraAdapter::IPPMode mode)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateLoaded != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is not in loaded state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
+
+ switch ( mode )
+ {
+ case OMXCameraAdapter::IPP_LDCNSF:
+ case OMXCameraAdapter::IPP_LDC:
+ {
+ bOMX.bEnabled = OMX_TRUE;
+ break;
+ }
+ case OMXCameraAdapter::IPP_NONE:
+ case OMXCameraAdapter::IPP_NSF:
+ default:
+ {
+ bOMX.bEnabled = OMX_FALSE;
+ break;
+ }
+ }
+
+ CAMHAL_LOGVB("Configuring LDC mode 0x%x", bOMX.bEnabled);
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexParamLensDistortionCorrection,
+ &bOMX);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEA("Error while setting LDC");
+ ret = -1;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setNSF(OMXCameraAdapter::IPPMode mode)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_PARAM_ISONOISEFILTERTYPE nsf;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateLoaded != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is not in loaded state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&nsf, OMX_PARAM_ISONOISEFILTERTYPE);
+ nsf.nPortIndex = OMX_ALL;
+
+ switch ( mode )
+ {
+ case OMXCameraAdapter::IPP_LDCNSF:
+ case OMXCameraAdapter::IPP_NSF:
+ {
+ nsf.eMode = OMX_ISONoiseFilterModeOn;
+ break;
+ }
+ case OMXCameraAdapter::IPP_LDC:
+ case OMXCameraAdapter::IPP_NONE:
+ default:
+ {
+ nsf.eMode = OMX_ISONoiseFilterModeOff;
+ break;
+ }
+ }
+
+ CAMHAL_LOGVB("Configuring NSF mode 0x%x", nsf.eMode);
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexParamHighISONoiseFiler,
+ &nsf);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEA("Error while setting NSF");
+ ret = -1;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setImageQuality(unsigned int quality)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_PARAM_QFACTORTYPE jpegQualityConf;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT(jpegQualityConf, OMX_IMAGE_PARAM_QFACTORTYPE);
+ jpegQualityConf.nQFactor = quality;
+ jpegQualityConf.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexParamQFactor,
+ &jpegQualityConf);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring jpeg Quality 0x%x", eError);
+ ret = -1;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setThumbnailParams(unsigned int width,
+ unsigned int height,
+ unsigned int quality)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_PARAM_THUMBNAILTYPE thumbConf;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT(thumbConf, OMX_PARAM_THUMBNAILTYPE);
+ thumbConf.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ eError = OMX_GetParameter(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexParamThumbnail,
+ &thumbConf);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while retrieving thumbnail size 0x%x", eError);
+ ret = -1;
+ }
+
+ //CTS Requirement: width or height equal to zero should
+ //result in absent EXIF thumbnail
+ if ( ( 0 == width ) || ( 0 == height ) )
+ {
+ thumbConf.nWidth = mThumbRes[0].width;
+ thumbConf.nHeight = mThumbRes[0].height;
+ thumbConf.eCompressionFormat = OMX_IMAGE_CodingUnused;
+ }
+ else
+ {
+ thumbConf.nWidth = width;
+ thumbConf.nHeight = height;
+ thumbConf.nQuality = quality;
+ thumbConf.eCompressionFormat = OMX_IMAGE_CodingJPEG;
+ }
+
+ CAMHAL_LOGDB("Thumbnail width = %d, Thumbnail Height = %d", width, height);
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexParamThumbnail,
+ &thumbConf);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring thumbnail size 0x%x", eError);
+ ret = -1;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setAlgoPriority(AlgoPriority priority,
+ Algorithm3A algo,
+ bool enable)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ if ( FACE_PRIORITY == priority ) {
+
+ if ( algo & WHITE_BALANCE_ALGO ) {
+ if ( enable ) {
+ mFacePriority.bAwbFaceEnable = OMX_TRUE;
+ } else {
+ mFacePriority.bAwbFaceEnable = OMX_FALSE;
+ }
+ }
+
+ if ( algo & EXPOSURE_ALGO ) {
+ if ( enable ) {
+ mFacePriority.bAeFaceEnable = OMX_TRUE;
+ } else {
+ mFacePriority.bAeFaceEnable = OMX_FALSE;
+ }
+ }
+
+ if ( algo & FOCUS_ALGO ) {
+ if ( enable ) {
+ mFacePriority.bAfFaceEnable = OMX_TRUE;
+ } else {
+ mFacePriority.bAfFaceEnable = OMX_FALSE;
+ }
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFacePriority3a,
+ &mFacePriority);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring face priority 0x%x", eError);
+ } else {
+ CAMHAL_LOGDB("Face priority for algorithms set successfully 0x%x, 0x%x, 0x%x",
+ mFacePriority.bAfFaceEnable,
+ mFacePriority.bAeFaceEnable,
+ mFacePriority.bAwbFaceEnable);
+ }
+
+ } else if ( REGION_PRIORITY == priority ) {
+
+ if ( algo & WHITE_BALANCE_ALGO ) {
+ if ( enable ) {
+ mRegionPriority.bAwbRegionEnable= OMX_TRUE;
+ } else {
+ mRegionPriority.bAwbRegionEnable = OMX_FALSE;
+ }
+ }
+
+ if ( algo & EXPOSURE_ALGO ) {
+ if ( enable ) {
+ mRegionPriority.bAeRegionEnable = OMX_TRUE;
+ } else {
+ mRegionPriority.bAeRegionEnable = OMX_FALSE;
+ }
+ }
+
+ if ( algo & FOCUS_ALGO ) {
+ if ( enable ) {
+ mRegionPriority.bAfRegionEnable = OMX_TRUE;
+ } else {
+ mRegionPriority.bAfRegionEnable = OMX_FALSE;
+ }
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigRegionPriority3a,
+ &mRegionPriority);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring region priority 0x%x", eError);
+ } else {
+ CAMHAL_LOGDB("Region priority for algorithms set successfully 0x%x, 0x%x, 0x%x",
+ mRegionPriority.bAfRegionEnable,
+ mRegionPriority.bAeRegionEnable,
+ mRegionPriority.bAwbRegionEnable);
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setPictureRotation(unsigned int degree)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_ROTATIONTYPE rotation;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT(rotation, OMX_CONFIG_ROTATIONTYPE);
+ rotation.nRotation = degree;
+ rotation.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonRotate,
+ &rotation);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring rotation 0x%x", eError);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setSensorOrientation(unsigned int degree)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_ROTATIONTYPE sensorOrientation;
+ int tmpHeight, tmpWidth;
+ OMXCameraPortParameters *mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ LOG_FUNCTION_NAME;
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -1;
+ }
+
+ /* Set Temproary Port resolution.
+ * For resolution with height >= 720,
+ * resolution cannot be set without configuring orientation.
+ * So we first set a temp resolution. We have used VGA
+ */
+ if ( mPreviewData->mHeight >= 720 ) {
+ tmpHeight = mPreviewData->mHeight;
+ tmpWidth = mPreviewData->mWidth;
+ mPreviewData->mWidth = 640;
+ mPreviewData->mHeight = 480;
+
+ ret = setFormat(OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW, *mPreviewData);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error while configuring format 0x%x", ret);
+ return ret;
+ }
+
+ mPreviewData->mWidth = tmpWidth;
+ mPreviewData->mHeight = tmpHeight;
+ mPreviewPortInitialized = true;
+ }
+ else if (!mPreviewPortInitialized) {
+ ret = setFormat(OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW, *mPreviewData);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error while configuring format 0x%x", ret);
+ return ret;
+ }
+ mPreviewPortInitialized = true;
+ }
+
+ /* Now set Required Orientation*/
+ if ( NO_ERROR == ret ) {
+ OMX_INIT_STRUCT(sensorOrientation, OMX_CONFIG_ROTATIONTYPE);
+ sensorOrientation.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ sensorOrientation.nRotation = degree;
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonRotate,
+ &sensorOrientation);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring rotation 0x%x", eError);
+ }
+ CAMHAL_LOGVB(" Currently Sensor Orientation is set to : %d",
+ ( unsigned int ) sensorOrientation.nRotation);
+ CAMHAL_LOGVB(" Sensor Configured for Port : %d",
+ ( unsigned int ) sensorOrientation.nPortIndex);
+ }
+
+ /* Now set the required resolution as requested */
+ if ( NO_ERROR == ret ) {
+ bool portConfigured = false;
+ ret = setSensorQuirks(degree,
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex],
+ portConfigured);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error while configuring setSensorQuirks 0x%x", ret);
+ return ret;
+ }
+
+ if ( !portConfigured ) {
+ ret = setFormat (mCameraAdapterParameters.mPrevPortIndex,
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex]);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error while configuring format 0x%x", ret);
+ return ret;
+ }
+
+ // Another WA: Setting the port definition will reset the VFR
+ // configuration.
+ setVFramerate(mPreviewData->mMinFrameRate,
+ mPreviewData->mMaxFrameRate);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setVFramerate(OMX_U32 minFrameRate, OMX_U32 maxFrameRate)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_VARFRMRANGETYPE vfr;
+ OMXCameraPortParameters * mPreviewData =
+ &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( !mSetFormatDone ) {
+ return NO_INIT;
+ }
+
+ if ( NO_ERROR == ret ) {
+ OMX_INIT_STRUCT_PTR (&vfr, OMX_TI_CONFIG_VARFRMRANGETYPE);
+
+ vfr.xMin = minFrameRate<<16;
+ vfr.xMax = maxFrameRate<<16;
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexConfigVarFrmRange,
+ &vfr);
+ if(OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while setting VFR min = %d, max = %d, error = 0x%x",
+ ( unsigned int ) minFrameRate,
+ ( unsigned int ) maxFrameRate,
+ eError);
+ ret = -1;
+ } else {
+ CAMHAL_LOGDB("VFR Configured Successfully [%d:%d]",
+ ( unsigned int ) minFrameRate,
+ ( unsigned int ) maxFrameRate);
+ }
+ }
+
+ return ret;
+ }
+
+status_t OMXCameraAdapter::setMechanicalMisalignmentCorrection(const bool enable)
+{
+ status_t ret = NO_ERROR;
+#ifndef MOTOROLA_CAMERA
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_MM mm;
+
+ LOG_FUNCTION_NAME;
+
+ mm.nVersion = mLocalVersionParam;
+ mm.nSize = sizeof(OMX_TI_CONFIG_MM);
+ mm.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ mm.bMM = enable ? OMX_TRUE : OMX_FALSE;
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexConfigMechanicalMisalignment,
+ &mm);
+
+ if(OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while enabling mechanical misalignment correction. error = 0x%x", eError);
+ ret = -1;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+#endif
+
+ return ret;
+}
+
+#ifdef MOTOROLA_CAMERA
+// This function is used when setting LedFlash Intensity
+status_t OMXCameraAdapter::setLedFlash(int nLedFlashIntensP)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_LEDINTESITY LedIntensity;
+
+ LOG_FUNCTION_NAME
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&LedIntensity, OMX_CONFIG_LEDINTESITY);
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE) OMX_IndexConfigLedIntensity, &LedIntensity);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("OMXGetConfig() returned error 0x%x on index==%08x", eError, OMX_IndexConfigLedIntensity);
+ ret = -1;
+ }
+ if (NO_ERROR == ret)
+ {
+ CAMHAL_LOGEB("old LedIntensity.nLedFlashIntens is: %d ", LedIntensity.nLedFlashIntens);
+
+ LedIntensity.nLedFlashIntens = (OMX_U32)nLedFlashIntensP;
+ CAMHAL_LOGDB("new LedIntensity.nLedFlashIntens is: %d ", LedIntensity.nLedFlashIntens);
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE) OMX_IndexConfigLedIntensity, &LedIntensity);
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring LedFlash Intensity. "
+ "OMXSetConfig() returned error 0x%x", eError);
+ ret = -1;
+ }
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return ret;
+}
+
+// This function is used when setting LedTorch Intensity
+status_t OMXCameraAdapter::setLedTorch(int nLedTorchIntensP)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_LEDINTESITY LedIntensity;
+ char value[PROPERTY_VALUE_MAX];
+ unsigned int torchIntensity = DEFAULT_INTENSITY;
+
+ LOG_FUNCTION_NAME
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&LedIntensity, OMX_CONFIG_LEDINTESITY);
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE) OMX_IndexConfigLedIntensity, &LedIntensity);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("OMXGetConfig() returned error 0x%x", eError);
+ ret = -1;
+ }
+ if (NO_ERROR == ret)
+ {
+ CAMHAL_LOGEB("old LedIntensity.nLedTorchIntens is: %d ", LedIntensity.nLedTorchIntens);
+
+ // read product specific torvh value
+ if (property_get("ro.media.capture.torchIntensity", value, 0) > 0)
+ {
+ torchIntensity = atoi(value);
+ if ((torchIntensity < 0) || (torchIntensity > DEFAULT_INTENSITY))
+ {
+ torchIntensity = DEFAULT_INTENSITY;
+ }
+ }
+ else
+ {
+ torchIntensity = nLedTorchIntensP;
+ }
+
+ LedIntensity.nLedTorchIntens = (OMX_U32)torchIntensity;
+ CAMHAL_LOGEB("new LedIntensity.nLedTorchIntens is: %d ", LedIntensity.nLedTorchIntens);
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE) OMX_IndexConfigLedIntensity, &LedIntensity);
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring LedTorch Intensity. "
+ "OMXSetConfig() returned error 0x%x", eError);
+ ret = -1;
+ }
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return ret;
+}
+#endif
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXCameraAdapter.cpp b/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
new file mode 100644
index 0000000..a52654a
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
@@ -0,0 +1,4534 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXCameraAdapter.cpp
+*
+* This file maps the Camera Hardware Interface to OMX.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#ifndef USES_LEGACY_DOMX_DCC
+#include "OMXDCC.h"
+#endif
+#include "ErrorUtils.h"
+#include "TICameraParameters.h"
+#include <signal.h>
+#include <math.h>
+
+#include <cutils/properties.h>
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+static int mDebugFps = 0;
+static int mDebugFcs = 0;
+
+#define HERE(Msg) {CAMHAL_LOGEB("--===line %d, %s===--\n", __LINE__, Msg);}
+
+namespace Ti {
+namespace Camera {
+
+#ifdef CAMERAHAL_OMX_PROFILING
+
+const char OMXCameraAdapter::DEFAULT_PROFILE_PATH[] = "/data/dbg/profile_data.bin";
+
+#endif
+
+//frames skipped before recalculating the framerate
+#define FPS_PERIOD 30
+
+android::Mutex gAdapterLock;
+/*--------------------Camera Adapter Class STARTS here-----------------------------*/
+
+status_t OMXCameraAdapter::initialize(CameraProperties::Properties* caps)
+{
+ LOG_FUNCTION_NAME;
+
+ char value[PROPERTY_VALUE_MAX];
+ const char *mountOrientationString = NULL;
+
+ property_get("debug.camera.showfps", value, "0");
+ mDebugFps = atoi(value);
+ property_get("debug.camera.framecounts", value, "0");
+ mDebugFcs = atoi(value);
+
+#ifdef CAMERAHAL_OMX_PROFILING
+
+ property_get("debug.camera.profile", value, "0");
+ mDebugProfile = atoi(value);
+
+#endif
+
+ TIMM_OSAL_ERRORTYPE osalError = OMX_ErrorNone;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ status_t ret = NO_ERROR;
+
+ mLocalVersionParam.s.nVersionMajor = 0x1;
+ mLocalVersionParam.s.nVersionMinor = 0x1;
+ mLocalVersionParam.s.nRevision = 0x0 ;
+ mLocalVersionParam.s.nStep = 0x0;
+
+ mPending3Asettings = 0;//E3AsettingsAll;
+ mPendingCaptureSettings = 0;
+ mPendingPreviewSettings = 0;
+ mPendingReprocessSettings = 0;
+
+ ret = mMemMgr.initialize();
+ if ( ret != OK ) {
+ CAMHAL_LOGE("MemoryManager initialization failed, error: %d", ret);
+ return ret;
+ }
+
+ if ( 0 != mInitSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mInitSem semaphore count %d", mInitSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ ///Update the preview and image capture port indexes
+ mCameraAdapterParameters.mPrevPortIndex = OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW;
+ // temp changed in order to build OMX_CAMERA_PORT_VIDEO_OUT_IMAGE;
+ mCameraAdapterParameters.mImagePortIndex = OMX_CAMERA_PORT_IMAGE_OUT_IMAGE;
+ mCameraAdapterParameters.mMeasurementPortIndex = OMX_CAMERA_PORT_VIDEO_OUT_MEASUREMENT;
+ //currently not supported use preview port instead
+ mCameraAdapterParameters.mVideoPortIndex = OMX_CAMERA_PORT_VIDEO_OUT_VIDEO;
+ mCameraAdapterParameters.mVideoInPortIndex = OMX_CAMERA_PORT_VIDEO_IN_VIDEO;
+
+ eError = OMX_Init();
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_Init() failed, error: 0x%x", eError);
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+ mOmxInitialized = true;
+
+ // Initialize the callback handles
+ OMX_CALLBACKTYPE callbacks;
+ callbacks.EventHandler = Camera::OMXCameraAdapterEventHandler;
+ callbacks.EmptyBufferDone = Camera::OMXCameraAdapterEmptyBufferDone;
+ callbacks.FillBufferDone = Camera::OMXCameraAdapterFillBufferDone;
+
+ ///Get the handle to the OMX Component
+ eError = OMXCameraAdapter::OMXCameraGetHandle(&mCameraAdapterParameters.mHandleComp, this, callbacks);
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_GetHandle -0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError != OMX_ErrorNone), eError);
+
+ mComponentState = OMX_StateLoaded;
+
+ CAMHAL_LOGVB("OMX_GetHandle -0x%x sensor_index = %lu", eError, mSensorIndex);
+ initDccFileDataSave(&mCameraAdapterParameters.mHandleComp, mCameraAdapterParameters.mPrevPortIndex);
+
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortDisable,
+ OMX_ALL,
+ NULL);
+
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SendCommand(OMX_CommandPortDisable) -0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError != OMX_ErrorNone), eError);
+
+ // Register for port enable event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ mInitSem);
+ if(ret != NO_ERROR) {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+
+ // Enable PREVIEW Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SendCommand(OMX_CommandPortEnable) -0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ // Wait for the port enable event to occur
+ ret = mInitSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if ( NO_ERROR == ret ) {
+ CAMHAL_LOGDA("-Port enable event arrived");
+ } else {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ CAMHAL_LOGEA("Timeout for enabling preview port expired!");
+ goto EXIT;
+ }
+
+ // Select the sensor
+ OMX_CONFIG_SENSORSELECTTYPE sensorSelect;
+ OMX_INIT_STRUCT_PTR (&sensorSelect, OMX_CONFIG_SENSORSELECTTYPE);
+ sensorSelect.eSensor = (OMX_SENSORSELECT) mSensorIndex;
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, ( OMX_INDEXTYPE ) OMX_TI_IndexConfigSensorSelect, &sensorSelect);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while selecting the sensor index as %d - 0x%x", mSensorIndex, eError);
+ return BAD_VALUE;
+ } else {
+ CAMHAL_LOGDB("Sensor %d selected successfully", mSensorIndex);
+ }
+
+#ifdef CAMERAHAL_DEBUG
+
+ printComponentVersion(mCameraAdapterParameters.mHandleComp);
+
+#endif
+
+ mBracketingEnabled = false;
+ mZoomBracketingEnabled = false;
+ mBracketingBuffersQueuedCount = 0;
+ mBracketingRange = 1;
+ mLastBracetingBufferIdx = 0;
+ mBracketingBuffersQueued = NULL;
+ mOMXStateSwitch = false;
+ mBracketingSet = false;
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ mRawCapture = false;
+ mYuvCapture = false;
+#endif
+
+ mCaptureSignalled = false;
+ mCaptureConfigured = false;
+ mReprocConfigured = false;
+ mRecording = false;
+ mWaitingForSnapshot = false;
+ mPictureFormatFromClient = NULL;
+
+ mCapabilitiesOpMode = MODE_MAX;
+ mCapMode = INITIAL_MODE;
+ mIPP = IPP_NULL;
+ mVstabEnabled = false;
+ mVnfEnabled = false;
+ mBurstFrames = 1;
+ mFlushShotConfigQueue = false;
+ mPictureQuality = 100;
+ mCurrentZoomIdx = 0;
+ mTargetZoomIdx = 0;
+ mPreviousZoomIndx = 0;
+ mReturnZoomStatus = false;
+ mZoomInc = 1;
+ mZoomParameterIdx = 0;
+ mExposureBracketingValidEntries = 0;
+ mZoomBracketingValidEntries = 0;
+ mSensorOverclock = false;
+ mAutoConv = OMX_TI_AutoConvergenceModeMax;
+ mManualConv = 0;
+
+#ifdef CAMERAHAL_TUNA
+ mIternalRecordingHint = false;
+#endif
+
+ mDeviceOrientation = 0;
+ mFaceOrientation = 0;
+ mCapabilities = caps;
+ mZoomUpdating = false;
+ mZoomUpdate = false;
+ mGBCE = BRIGHTNESS_OFF;
+ mGLBCE = BRIGHTNESS_OFF;
+ mParameters3A.ExposureLock = OMX_FALSE;
+ mParameters3A.WhiteBalanceLock = OMX_FALSE;
+
+ mEXIFData.mGPSData.mAltitudeValid = false;
+ mEXIFData.mGPSData.mDatestampValid = false;
+ mEXIFData.mGPSData.mLatValid = false;
+ mEXIFData.mGPSData.mLongValid = false;
+ mEXIFData.mGPSData.mMapDatumValid = false;
+ mEXIFData.mGPSData.mProcMethodValid = false;
+ mEXIFData.mGPSData.mVersionIdValid = false;
+ mEXIFData.mGPSData.mTimeStampValid = false;
+ mEXIFData.mModelValid = false;
+ mEXIFData.mMakeValid = false;
+
+ mCapturedFrames = 0;
+ mBurstFramesAccum = 0;
+ mBurstFramesQueued = 0;
+
+ //update the mDeviceOrientation with the sensor mount orientation.
+ //So that the face detect will work before onOrientationEvent()
+ //get triggered.
+ CAMHAL_ASSERT(mCapabilities);
+ mountOrientationString = mCapabilities->get(CameraProperties::ORIENTATION_INDEX);
+ CAMHAL_ASSERT(mountOrientationString);
+ mDeviceOrientation = atoi(mountOrientationString);
+ mFaceOrientation = atoi(mountOrientationString);
+
+ if (mSensorIndex != 2) {
+ mCapabilities->setMode(MODE_HIGH_SPEED);
+ }
+
+ if (mCapabilities->get(CameraProperties::SUPPORTED_ZOOM_STAGES) != NULL) {
+ mMaxZoomSupported = mCapabilities->getInt(CameraProperties::SUPPORTED_ZOOM_STAGES) + 1;
+ } else {
+ mMaxZoomSupported = 1;
+ }
+
+ // initialize command handling thread
+ if(mCommandHandler.get() == NULL)
+ mCommandHandler = new CommandHandler(this);
+
+ if ( NULL == mCommandHandler.get() )
+ {
+ CAMHAL_LOGEA("Couldn't create command handler");
+ return NO_MEMORY;
+ }
+
+ ret = mCommandHandler->run("CallbackThread", android::PRIORITY_URGENT_DISPLAY);
+ if ( ret != NO_ERROR )
+ {
+ if( ret == INVALID_OPERATION){
+ CAMHAL_LOGDA("command handler thread already runnning!!");
+ ret = NO_ERROR;
+ } else {
+ CAMHAL_LOGEA("Couldn't run command handlerthread");
+ return ret;
+ }
+ }
+
+ // initialize omx callback handling thread
+ if(mOMXCallbackHandler.get() == NULL)
+ mOMXCallbackHandler = new OMXCallbackHandler(this);
+
+ if ( NULL == mOMXCallbackHandler.get() )
+ {
+ CAMHAL_LOGEA("Couldn't create omx callback handler");
+ return NO_MEMORY;
+ }
+
+ ret = mOMXCallbackHandler->run("OMXCallbackThread", android::PRIORITY_URGENT_DISPLAY);
+ if ( ret != NO_ERROR )
+ {
+ if( ret == INVALID_OPERATION){
+ CAMHAL_LOGDA("omx callback handler thread already runnning!!");
+ ret = NO_ERROR;
+ } else {
+ CAMHAL_LOGEA("Couldn't run omx callback handler thread");
+ return ret;
+ }
+ }
+
+ OMX_INIT_STRUCT_PTR (&mRegionPriority, OMX_TI_CONFIG_3A_REGION_PRIORITY);
+ OMX_INIT_STRUCT_PTR (&mFacePriority, OMX_TI_CONFIG_3A_FACE_PRIORITY);
+ mRegionPriority.nPortIndex = OMX_ALL;
+ mFacePriority.nPortIndex = OMX_ALL;
+
+ //Setting this flag will that the first setParameter call will apply all 3A settings
+ //and will not conditionally apply based on current values.
+ mFirstTimeInit = true;
+
+ //Flag to avoid calling setVFramerate() before OMX_SetParameter(OMX_IndexParamPortDefinition)
+ //Ducati will return an error otherwise.
+ mSetFormatDone = false;
+
+ memset(mExposureBracketingValues, 0, EXP_BRACKET_RANGE*sizeof(int));
+ memset(mZoomBracketingValues, 0, ZOOM_BRACKET_RANGE*sizeof(int));
+ mMeasurementEnabled = false;
+ mFaceDetectionRunning = false;
+ mFaceDetectionPaused = false;
+ mFDSwitchAlgoPriority = false;
+
+ metadataLastAnalogGain = -1;
+ metadataLastExposureTime = -1;
+
+ memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex], 0, sizeof(OMXCameraPortParameters));
+ memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex], 0, sizeof(OMXCameraPortParameters));
+ memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex], 0, sizeof(OMXCameraPortParameters));
+ memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex], 0, sizeof(OMXCameraPortParameters));
+
+ // initialize 3A defaults
+ mParameters3A.Effect = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_EFFECT, EffLUT);
+ mParameters3A.FlashMode = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_FLASH_MODE, FlashLUT);
+ mParameters3A.SceneMode = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_SCENE_MODE, SceneLUT);
+ mParameters3A.EVCompensation = atoi(OMXCameraAdapter::DEFAULT_EV_COMPENSATION);
+ mParameters3A.Focus = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_FOCUS_MODE, FocusLUT);
+ mParameters3A.ISO = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_ISO_MODE, IsoLUT);
+ mParameters3A.Flicker = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_ANTIBANDING, FlickerLUT);
+ mParameters3A.Brightness = atoi(OMXCameraAdapter::DEFAULT_BRIGHTNESS);
+ mParameters3A.Saturation = atoi(OMXCameraAdapter::DEFAULT_SATURATION) - SATURATION_OFFSET;
+ mParameters3A.Sharpness = atoi(OMXCameraAdapter::DEFAULT_SHARPNESS) - SHARPNESS_OFFSET;
+ mParameters3A.Contrast = atoi(OMXCameraAdapter::DEFAULT_CONTRAST) - CONTRAST_OFFSET;
+ mParameters3A.WhiteBallance = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_WB, WBalLUT);
+ mParameters3A.Exposure = getLUTvalue_HALtoOMX(OMXCameraAdapter::DEFAULT_EXPOSURE_MODE, ExpLUT);
+ mParameters3A.ExposureLock = OMX_FALSE;
+ mParameters3A.FocusLock = OMX_FALSE;
+ mParameters3A.WhiteBalanceLock = OMX_FALSE;
+
+ mParameters3A.ManualExposure = 0;
+ mParameters3A.ManualExposureRight = 0;
+ mParameters3A.ManualGain = 0;
+ mParameters3A.ManualGainRight = 0;
+
+ mParameters3A.AlgoExternalGamma = OMX_FALSE;
+ mParameters3A.AlgoNSF1 = OMX_TRUE;
+ mParameters3A.AlgoNSF2 = OMX_TRUE;
+ mParameters3A.AlgoSharpening = OMX_TRUE;
+ mParameters3A.AlgoThreeLinColorMap = OMX_TRUE;
+ mParameters3A.AlgoGIC = OMX_TRUE;
+ memset(&mParameters3A.mGammaTable, 0, sizeof(mParameters3A.mGammaTable));
+
+ LOG_FUNCTION_NAME_EXIT;
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+
+ EXIT:
+
+ CAMHAL_LOGDB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+void OMXCameraAdapter::performCleanupAfterError()
+{
+ if(mCameraAdapterParameters.mHandleComp)
+ {
+ ///Free the OMX component handle in case of error
+ OMX_FreeHandle(mCameraAdapterParameters.mHandleComp);
+ mCameraAdapterParameters.mHandleComp = NULL;
+ }
+
+ ///De-init the OMX
+ OMX_Deinit();
+ mComponentState = OMX_StateInvalid;
+ mOmxInitialized = false;
+}
+
+OMXCameraAdapter::OMXCameraPortParameters *OMXCameraAdapter::getPortParams(CameraFrame::FrameType frameType)
+{
+ OMXCameraAdapter::OMXCameraPortParameters *ret = NULL;
+
+ switch ( frameType )
+ {
+ case CameraFrame::IMAGE_FRAME:
+ ret = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+ break;
+ case CameraFrame::RAW_FRAME:
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ if (mRawCapture) {
+ ret = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex];
+ } else {
+#endif
+ ret = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ }
+#endif
+ break;
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ case CameraFrame::SNAPSHOT_FRAME:
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ ret = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+ break;
+ case CameraFrame::FRAME_DATA_SYNC:
+ ret = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex];
+ break;
+ default:
+ break;
+ };
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::fillThisBuffer(CameraBuffer * frameBuf, CameraFrame::FrameType frameType)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ OMXCameraPortParameters *port = NULL;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ BaseCameraAdapter::AdapterState state;
+ BaseCameraAdapter::getState(state);
+ bool isCaptureFrame = false;
+
+ if ( ( PREVIEW_ACTIVE & state ) != PREVIEW_ACTIVE )
+ {
+ return NO_INIT;
+ }
+
+ if ( NULL == frameBuf )
+ {
+ return -EINVAL;
+ }
+
+ isCaptureFrame = (CameraFrame::IMAGE_FRAME == frameType) ||
+ (CameraFrame::RAW_FRAME == frameType);
+
+ if ( NO_ERROR == ret )
+ {
+ port = getPortParams(frameType);
+ if ( NULL == port )
+ {
+ CAMHAL_LOGEB("Invalid frameType 0x%x", frameType);
+ ret = -EINVAL;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ for ( int i = 0 ; i < port->mNumBufs ; i++) {
+ if ((CameraBuffer *) port->mBufferHeader[i]->pAppPrivate == frameBuf) {
+ if ( isCaptureFrame && !mBracketingEnabled ) {
+ android::AutoMutex lock(mBurstLock);
+ if ((1 > mCapturedFrames) && !mBracketingEnabled && (mCapMode != CP_CAM)) {
+ // Signal end of image capture
+ if ( NULL != mEndImageCaptureCallback) {
+ mEndImageCaptureCallback(mEndCaptureData);
+ }
+ port->mStatus[i] = OMXCameraPortParameters::IDLE;
+ return NO_ERROR;
+ } else if (mBurstFramesQueued >= mBurstFramesAccum) {
+ port->mStatus[i] = OMXCameraPortParameters::IDLE;
+ return NO_ERROR;
+ }
+ mBurstFramesQueued++;
+ }
+ port->mStatus[i] = OMXCameraPortParameters::FILL;
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp, port->mBufferHeader[i]);
+ if ( eError != OMX_ErrorNone )
+ {
+ CAMHAL_LOGEB("OMX_FillThisBuffer 0x%x", eError);
+ goto EXIT;
+ }
+ mFramesWithDucati++;
+ break;
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ //Since fillthisbuffer is called asynchronously, make sure to signal error to the app
+ mErrorNotifier->errorNotify(CAMERA_ERROR_HARD);
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+void OMXCameraAdapter::setParamS3D(OMX_U32 port, const char *valstr)
+{
+ OMXCameraPortParameters *cap;
+
+ LOG_FUNCTION_NAME;
+
+ cap = &mCameraAdapterParameters.mCameraPortParams[port];
+ if (valstr != NULL)
+ {
+ if (strcmp(valstr, TICameraParameters::S3D_TB_FULL) == 0)
+ {
+ cap->mFrameLayoutType = OMX_TI_StereoFrameLayoutTopBottom;
+ }
+ else if (strcmp(valstr, TICameraParameters::S3D_SS_FULL) == 0)
+ {
+ cap->mFrameLayoutType = OMX_TI_StereoFrameLayoutLeftRight;
+ }
+ else if (strcmp(valstr, TICameraParameters::S3D_TB_SUBSAMPLED) == 0)
+ {
+ cap->mFrameLayoutType = OMX_TI_StereoFrameLayoutTopBottomSubsample;
+ }
+ else if (strcmp(valstr, TICameraParameters::S3D_SS_SUBSAMPLED) == 0)
+ {
+ cap->mFrameLayoutType = OMX_TI_StereoFrameLayoutLeftRightSubsample;
+ }
+ else
+ {
+ cap->mFrameLayoutType = OMX_TI_StereoFrameLayout2D;
+ }
+ }
+ else
+ {
+ cap->mFrameLayoutType = OMX_TI_StereoFrameLayout2D;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t OMXCameraAdapter::setParameters(const android::CameraParameters &params)
+{
+ LOG_FUNCTION_NAME;
+
+ int mode = 0;
+ status_t ret = NO_ERROR;
+ bool updateImagePortParams = false;
+ int minFramerate, maxFramerate, frameRate;
+ const char *valstr = NULL;
+ int w, h;
+ OMX_COLOR_FORMATTYPE pixFormat;
+ BaseCameraAdapter::AdapterState state;
+ BaseCameraAdapter::getState(state);
+
+ ///@todo Include more camera parameters
+ if ( (valstr = params.getPreviewFormat()) != NULL ) {
+ if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
+ strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV420P) == 0 ||
+ strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ pixFormat = OMX_COLOR_FormatYUV420PackedSemiPlanar;
+ } else if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
+ CAMHAL_LOGDA("RGB565 format selected");
+ pixFormat = OMX_COLOR_Format16bitRGB565;
+ } else {
+ CAMHAL_LOGDA("Invalid format, CbYCrY format selected as default");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ }
+ } else {
+ CAMHAL_LOGEA("Preview format is NULL, defaulting to CbYCrY");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ }
+
+ OMXCameraPortParameters *cap;
+ cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ params.getPreviewSize(&w, &h);
+ frameRate = params.getPreviewFrameRate();
+
+ const char *frameRateRange = params.get(TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE);
+ bool fpsRangeParsed = CameraHal::parsePair(frameRateRange, &minFramerate, &maxFramerate, ',');
+ CAMHAL_ASSERT(fpsRangeParsed);
+
+ minFramerate /= CameraHal::VFR_SCALE;
+ maxFramerate /= CameraHal::VFR_SCALE;
+
+ frameRate = maxFramerate;
+
+ if ( ( cap->mMinFrameRate != (OMX_U32) minFramerate ) ||
+ ( cap->mMaxFrameRate != (OMX_U32) maxFramerate ) ) {
+ cap->mMinFrameRate = minFramerate;
+ cap->mMaxFrameRate = maxFramerate;
+ setVFramerate(cap->mMinFrameRate, cap->mMaxFrameRate);
+ }
+
+ cap->mColorFormat = pixFormat;
+ cap->mWidth = w;
+ cap->mHeight = h;
+ cap->mFrameRate = frameRate;
+
+ CAMHAL_LOGVB("Prev: cap.mColorFormat = %d", (int)cap->mColorFormat);
+ CAMHAL_LOGVB("Prev: cap.mWidth = %d", (int)cap->mWidth);
+ CAMHAL_LOGVB("Prev: cap.mHeight = %d", (int)cap->mHeight);
+ CAMHAL_LOGVB("Prev: cap.mFrameRate = %d", (int)cap->mFrameRate);
+
+ ///mStride is set from setBufs() while passing the APIs
+ cap->mStride = 4096;
+ cap->mBufSize = cap->mStride * cap->mHeight;
+
+
+ if ( ( cap->mWidth >= 1920 ) &&
+ ( cap->mHeight >= 1080 ) &&
+ ( cap->mFrameRate >= FRAME_RATE_FULL_HD ) &&
+ ( !mSensorOverclock ) )
+ {
+ mOMXStateSwitch = true;
+ }
+ else if ( ( ( cap->mWidth < 1920 ) ||
+ ( cap->mHeight < 1080 ) ||
+ ( cap->mFrameRate < FRAME_RATE_FULL_HD ) ) &&
+ ( mSensorOverclock ) )
+ {
+ mOMXStateSwitch = true;
+ }
+
+#ifdef CAMERAHAL_TUNA
+ valstr = params.get(TICameraParameters::KEY_RECORDING_HINT);
+ if (!valstr || (valstr && (strcmp(valstr, android::CameraParameters::FALSE)))) {
+ mIternalRecordingHint = false;
+ } else {
+ mIternalRecordingHint = true;
+ }
+#endif
+
+#ifdef OMAP_ENHANCEMENT
+ if ( (valstr = params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE)) != NULL )
+ {
+ if (strcmp(valstr, android::CameraParameters::TRUE) == 0)
+ {
+ mMeasurementEnabled = true;
+ }
+ else if (strcmp(valstr, android::CameraParameters::FALSE) == 0)
+ {
+ mMeasurementEnabled = false;
+ }
+ else
+ {
+ mMeasurementEnabled = false;
+ }
+ }
+ else
+ {
+ //Disable measurement data by default
+ mMeasurementEnabled = false;
+ }
+#endif
+
+#ifdef OMAP_ENHANCEMENT_S3D
+ setParamS3D(mCameraAdapterParameters.mPrevPortIndex,
+ params.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT));
+#endif
+
+ ret |= setParametersCapture(params, state);
+
+ ret |= setParameters3A(params, state);
+
+ ret |= setParametersAlgo(params, state);
+
+ ret |= setParametersFocus(params, state);
+
+ ret |= setParametersFD(params, state);
+
+ ret |= setParametersZoom(params, state);
+
+ ret |= setParametersEXIF(params, state);
+
+#ifdef MOTOROLA_CAMERA
+ CAMHAL_LOGDA("Start setting of Motorola specific parameters");
+ if (NULL != params.get(TICameraParameters::KEY_MOT_LEDFLASH)) {
+ setLedFlash((unsigned int) (params.getInt(TICameraParameters::KEY_MOT_LEDFLASH)));
+ }
+ if (NULL != params.get(TICameraParameters::KEY_MOT_LEDTORCH)) {
+ setLedTorch((unsigned int) (params.getInt(TICameraParameters::KEY_MOT_LEDTORCH)));
+ }
+#endif
+
+ mParams = params;
+ mFirstTimeInit = false;
+
+ if ( MODE_MAX != mCapabilitiesOpMode ) {
+ mCapabilities->setMode(mCapabilitiesOpMode);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+void saveFile(unsigned char *buff, int width, int height, int format) {
+ static int counter = 1;
+ int fd = -1;
+ char fn[256];
+
+ LOG_FUNCTION_NAME;
+
+ fn[0] = 0;
+ sprintf(fn, "/preview%03d.yuv", counter);
+ fd = open(fn, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
+ if(fd < 0) {
+ CAMHAL_LOGE("Unable to open file %s: %s", fn, strerror(fd));
+ return;
+ }
+
+ CAMHAL_LOGVB("Copying from 0x%x, size=%d x %d", buff, width, height);
+
+ //method currently supports only nv12 dumping
+ int stride = width;
+ uint8_t *bf = (uint8_t*) buff;
+ for(int i=0;i<height;i++)
+ {
+ write(fd, bf, width);
+ bf += 4096;
+ }
+
+ for(int i=0;i<height/2;i++)
+ {
+ write(fd, bf, stride);
+ bf += 4096;
+ }
+
+ close(fd);
+
+
+ counter++;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+static status_t saveBufferToFile(const void *buf, int size, const char *filename)
+{
+ if (size < 0) {
+ CAMHAL_LOGE("Wrong buffer size: %d", size);
+ return BAD_VALUE;
+ }
+
+ const int fd = open(filename, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0644);
+ if (fd < 0) {
+ CAMHAL_LOGE("ERROR: %s, Unable to save raw file", strerror(fd));
+ return BAD_VALUE;
+ }
+
+ if (write(fd, buf, size) != (signed)size) {
+ CAMHAL_LOGE("ERROR: Unable to write to raw file: %s ", strerror(errno));
+ close(fd);
+ return NO_MEMORY;
+ }
+
+ CAMHAL_LOGD("buffer=%p, size=%d stored at %s", buf, size, filename);
+
+ close(fd);
+ return OK;
+}
+#endif
+
+
+void OMXCameraAdapter::getParameters(android::CameraParameters& params)
+{
+ status_t ret = NO_ERROR;
+ OMX_CONFIG_EXPOSUREVALUETYPE exp;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ BaseCameraAdapter::AdapterState state;
+ BaseCameraAdapter::getState(state);
+ const char *valstr = NULL;
+ LOG_FUNCTION_NAME;
+
+ if( mParameters3A.SceneMode != OMX_Manual ) {
+ const char *valstr_supported = NULL;
+
+ if (mCapabilities) {
+ const SceneModesEntry* entry = NULL;
+ entry = getSceneModeEntry(mCapabilities->get(CameraProperties::CAMERA_NAME),
+ (OMX_SCENEMODETYPE) mParameters3A.SceneMode);
+ if(entry) {
+ mParameters3A.Focus = entry->focus;
+ mParameters3A.FlashMode = entry->flash;
+ mParameters3A.WhiteBallance = entry->wb;
+ }
+ }
+
+ valstr = getLUTvalue_OMXtoHAL(mParameters3A.WhiteBallance, WBalLUT);
+ valstr_supported = mParams.get(android::CameraParameters::KEY_SUPPORTED_WHITE_BALANCE);
+ if (valstr && valstr_supported && strstr(valstr_supported, valstr))
+ params.set(android::CameraParameters::KEY_WHITE_BALANCE , valstr);
+
+ valstr = getLUTvalue_OMXtoHAL(mParameters3A.FlashMode, FlashLUT);
+ valstr_supported = mParams.get(android::CameraParameters::KEY_SUPPORTED_FLASH_MODES);
+ if (valstr && valstr_supported && strstr(valstr_supported, valstr))
+ params.set(android::CameraParameters::KEY_FLASH_MODE, valstr);
+
+ if ((mParameters3A.Focus == OMX_IMAGE_FocusControlAuto) &&
+ ( (mCapMode != OMXCameraAdapter::VIDEO_MODE) &&
+ (mCapMode != OMXCameraAdapter::VIDEO_MODE_HQ) ) ) {
+ valstr = android::CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE;
+ } else {
+ valstr = getLUTvalue_OMXtoHAL(mParameters3A.Focus, FocusLUT);
+ }
+ valstr_supported = mParams.get(android::CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
+ if (valstr && valstr_supported && strstr(valstr_supported, valstr))
+ params.set(android::CameraParameters::KEY_FOCUS_MODE, valstr);
+ }
+
+ //Query focus distances only when focus is running
+ if ( ( AF_ACTIVE & state ) ||
+ ( NULL == mParameters.get(android::CameraParameters::KEY_FOCUS_DISTANCES) ) )
+ {
+ updateFocusDistances(params);
+ }
+ else
+ {
+ params.set(android::CameraParameters::KEY_FOCUS_DISTANCES,
+ mParameters.get(android::CameraParameters::KEY_FOCUS_DISTANCES));
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ OMX_INIT_STRUCT_PTR (&exp, OMX_CONFIG_EXPOSUREVALUETYPE);
+ exp.nPortIndex = OMX_ALL;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &exp);
+ if ( OMX_ErrorNone == eError )
+ {
+ params.set(TICameraParameters::KEY_CURRENT_ISO, exp.nSensitivity);
+ }
+ else
+ {
+ CAMHAL_LOGEB("OMX error 0x%x, while retrieving current ISO value", eError);
+ }
+#endif
+
+ {
+ android::AutoMutex lock(mZoomLock);
+ //Immediate zoom should not be avaialable while smooth zoom is running
+ if ( ZOOM_ACTIVE & state )
+ {
+ if ( mZoomParameterIdx != mCurrentZoomIdx )
+ {
+ mZoomParameterIdx += mZoomInc;
+ }
+ params.set(android::CameraParameters::KEY_ZOOM, mZoomParameterIdx);
+ if ( ( mCurrentZoomIdx == mTargetZoomIdx ) &&
+ ( mZoomParameterIdx == mCurrentZoomIdx ) )
+ {
+
+ if ( NO_ERROR == ret )
+ {
+
+ ret = BaseCameraAdapter::setState(CAMERA_STOP_SMOOTH_ZOOM);
+
+ if ( NO_ERROR == ret )
+ {
+ ret = BaseCameraAdapter::commitState();
+ }
+ else
+ {
+ ret |= BaseCameraAdapter::rollbackState();
+ }
+
+ }
+
+ }
+
+ CAMHAL_LOGDB("CameraParameters Zoom = %d", mCurrentZoomIdx);
+ }
+ else
+ {
+ params.set(android::CameraParameters::KEY_ZOOM, mCurrentZoomIdx);
+ }
+ }
+
+ //Populate current lock status
+ if ( mUserSetExpLock || mParameters3A.ExposureLock ) {
+ params.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK,
+ android::CameraParameters::TRUE);
+ } else {
+ params.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK,
+ android::CameraParameters::FALSE);
+ }
+
+ if ( mUserSetWbLock || mParameters3A.WhiteBalanceLock ) {
+ params.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK,
+ android::CameraParameters::TRUE);
+ } else {
+ params.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK,
+ android::CameraParameters::FALSE);
+ }
+
+ // Update Picture size capabilities dynamically
+ params.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ mCapabilities->get(CameraProperties::SUPPORTED_PICTURE_SIZES));
+
+ // Update framerate capabilities dynamically
+ params.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
+ mCapabilities->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES));
+
+ params.set(TICameraParameters::KEY_FRAMERATES_EXT_SUPPORTED,
+ mCapabilities->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES_EXT));
+
+ params.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
+ mCapabilities->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED));
+
+ params.set(TICameraParameters::KEY_FRAMERATE_RANGES_EXT_SUPPORTED,
+ mCapabilities->get(CameraProperties::FRAMERATE_RANGE_EXT_SUPPORTED));
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t OMXCameraAdapter::setupTunnel(uint32_t SliceHeight, uint32_t EncoderHandle, uint32_t width, uint32_t height) {
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_HANDLETYPE *encoderHandle = (OMX_HANDLETYPE *)EncoderHandle;
+
+ CAMHAL_LOGDB("\n %s: SliceHeight:%d, EncoderHandle:%d width:%d height:%d \n", __FUNCTION__, SliceHeight, EncoderHandle, width, height);
+
+ if (SliceHeight == 0){
+ CAMHAL_LOGEA("\n\n #### Encoder Slice Height Not received, Dont Setup Tunnel $$$$\n\n");
+ return BAD_VALUE;
+ }
+
+ if (encoderHandle == NULL) {
+ CAMHAL_LOGEA("Encoder Handle not set \n\n");
+ return BAD_VALUE;
+ }
+
+ if ( 0 != mInitSem.Count() ) {
+ CAMHAL_LOGEB("Error mInitSem semaphore count %d", mInitSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ // Register for port enable event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ mInitSem);
+ if(ret != NO_ERROR) {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ return UNKNOWN_ERROR;
+ }
+
+ // Enable VIDEO Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ NULL);
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SendCommand(OMX_CommandPortEnable) -0x%x", eError);
+ return BAD_VALUE;
+ }
+
+ // Wait for the port enable event to occur
+ ret = mInitSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if ( NO_ERROR == ret ) {
+ CAMHAL_LOGDA("-Port enable event arrived");
+ } else {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ NULL);
+ CAMHAL_LOGEA("Timeout for enabling preview port expired!");
+ return UNKNOWN_ERROR;
+ }
+
+ //Set the Video Port Params
+ OMX_PARAM_PORTDEFINITIONTYPE portCheck;
+ OMX_INIT_STRUCT_PTR (&portCheck, OMX_PARAM_PORTDEFINITIONTYPE);
+ portCheck.nPortIndex = OMX_CAMERA_PORT_VIDEO_OUT_VIDEO;
+ eError = OMX_GetParameter(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexParamPortDefinition, &portCheck);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_GetParameter OMX_IndexParamPortDefinition Error - %x", eError);
+ }
+
+ portCheck.format.video.nFrameWidth = width;
+ portCheck.format.video.nFrameHeight = height;
+ portCheck.format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedSemiPlanar;
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexParamPortDefinition, &portCheck);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SetParameter OMX_IndexParamPortDefinition Error- %x", eError);
+ }
+
+#ifndef MOTOROLA_CAMERA
+ //Slice Configuration
+ OMX_TI_PARAM_VTCSLICE VTCSlice;
+ OMX_INIT_STRUCT_PTR(&VTCSlice, OMX_TI_PARAM_VTCSLICE);
+ eError = OMX_GetParameter(mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexParamVtcSlice, &VTCSlice);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_GetParameter OMX_TI_IndexParamVtcSlice Error - %x", eError);
+ }
+
+ VTCSlice.nSliceHeight = SliceHeight;
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexParamVtcSlice, &VTCSlice);
+ if (OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("OMX_SetParameter on OMX_TI_IndexParamVtcSlice returned error: 0x%x", eError);
+ return BAD_VALUE;
+ }
+
+ eError = OMX_SetupTunnel(mCameraAdapterParameters.mHandleComp,
+ mCameraAdapterParameters.mVideoPortIndex, encoderHandle, 0);
+ if (OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("OMX_SetupTunnel returned error: 0x%x", eError);
+ return BAD_VALUE;
+ }
+#endif
+
+ return NO_ERROR;
+}
+
+status_t OMXCameraAdapter::setSensorQuirks(int orientation,
+ OMXCameraPortParameters &portParams,
+ bool &portConfigured)
+{
+ status_t overclockStatus = NO_ERROR;
+ int sensorID = -1;
+ size_t overclockWidth;
+ size_t overclockHeight;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_PARAM_PORTDEFINITIONTYPE portCheck;
+
+ LOG_FUNCTION_NAME;
+
+ portConfigured = false;
+ OMX_INIT_STRUCT_PTR (&portCheck, OMX_PARAM_PORTDEFINITIONTYPE);
+
+ portCheck.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ eError = OMX_GetParameter (mCameraAdapterParameters.mHandleComp,
+ OMX_IndexParamPortDefinition,
+ &portCheck);
+
+ if ( eError != OMX_ErrorNone ) {
+ CAMHAL_LOGEB("OMX_GetParameter - %x", eError);
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+
+ if ( ( orientation == 90 ) || ( orientation == 270 ) ) {
+ overclockWidth = 1080;
+ overclockHeight = 1920;
+ } else {
+ overclockWidth = 1920;
+ overclockHeight = 1080;
+ }
+
+ sensorID = mCapabilities->getInt(CameraProperties::CAMERA_SENSOR_ID);
+ if( ( ( sensorID == SENSORID_IMX060 ) &&
+ ( portParams.mWidth >= overclockWidth ) &&
+ ( portParams.mHeight >= overclockHeight ) &&
+ ( portParams.mFrameRate >= FRAME_RATE_FULL_HD ) ) ||
+ (( sensorID == SENSORID_OV14825) &&
+ ( portParams.mFrameRate >= FRAME_RATE_HIGH_HD ))||
+ ( ( sensorID == SENSORID_OV5640 ) &&
+ ( portParams.mWidth >= overclockWidth ) &&
+ ( portParams.mHeight >= overclockHeight ) ) ) {
+ overclockStatus = setSensorOverclock(true);
+ } else {
+
+ //WA: If the next port resolution doesn't require
+ // sensor overclocking, but the previous resolution
+ // needed it, then we have to first set new port
+ // resolution and then disable sensor overclocking.
+ if( ( ( sensorID == SENSORID_IMX060 ) &&
+ ( portCheck.format.video.nFrameWidth >= overclockWidth ) &&
+ ( portCheck.format.video.nFrameHeight >= overclockHeight ) &&
+ ( ( portCheck.format.video.xFramerate >> 16 ) >= FRAME_RATE_FULL_HD ) ) ||
+ (( sensorID == SENSORID_OV14825) &&
+ (( portCheck.format.video.xFramerate >> 16) >= FRAME_RATE_HIGH_HD ))||
+ ( ( sensorID == SENSORID_OV5640 ) &&
+ ( portCheck.format.video.nFrameWidth >= overclockWidth ) &&
+ ( portCheck.format.video.nFrameHeight >= overclockHeight ) ) ) {
+ status_t ret = setFormat(mCameraAdapterParameters.mPrevPortIndex,
+ portParams);
+ if ( NO_ERROR != ret ) {
+ return ret;
+ }
+
+ // Another WA: Setting the port definition will reset the VFR
+ // configuration.
+ setVFramerate(portParams.mMinFrameRate, portParams.mMaxFrameRate);
+
+ portConfigured = true;
+ }
+
+ overclockStatus = setSensorOverclock(false);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return overclockStatus;
+}
+status_t OMXCameraAdapter::setFormat(OMX_U32 port, OMXCameraPortParameters &portParams)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ size_t bufferCount;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_PARAM_PORTDEFINITIONTYPE portCheck;
+
+ OMX_INIT_STRUCT_PTR (&portCheck, OMX_PARAM_PORTDEFINITIONTYPE);
+
+ portCheck.nPortIndex = port;
+
+ eError = OMX_GetParameter (mCameraAdapterParameters.mHandleComp,
+ OMX_IndexParamPortDefinition, &portCheck);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_GetParameter - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ if (OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW == port) {
+ portCheck.format.video.nFrameWidth = portParams.mWidth;
+ portCheck.format.video.nFrameHeight = portParams.mHeight;
+ portCheck.format.video.eColorFormat = portParams.mColorFormat;
+ portCheck.format.video.nStride = portParams.mStride;
+
+ portCheck.format.video.xFramerate = portParams.mFrameRate<<16;
+ portCheck.nBufferSize = portParams.mStride * portParams.mHeight;
+ portCheck.nBufferCountActual = portParams.mNumBufs;
+ mFocusThreshold = FOCUS_THRESHOLD * portParams.mFrameRate;
+ // Used for RAW capture
+ } else if (OMX_CAMERA_PORT_VIDEO_OUT_VIDEO == port) {
+ portCheck.format.video.nFrameWidth = portParams.mWidth;
+ portCheck.format.video.nFrameHeight = portParams.mHeight;
+ portCheck.format.video.eColorFormat = OMX_COLOR_FormatRawBayer10bit; // portParams.mColorFormat;
+ portCheck.nBufferCountActual = 1; // portParams.mNumBufs;
+ } else if (OMX_CAMERA_PORT_IMAGE_OUT_IMAGE == port) {
+ portCheck.format.image.nFrameWidth = portParams.mWidth;
+ portCheck.format.image.nFrameHeight = portParams.mHeight;
+ if (OMX_COLOR_FormatUnused == portParams.mColorFormat) {
+ portCheck.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY;
+ if (mCodingMode == CodingJPEG) {
+ portCheck.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG;
+ } else if (mCodingMode == CodingJPS) {
+ portCheck.format.image.eCompressionFormat = (OMX_IMAGE_CODINGTYPE) OMX_TI_IMAGE_CodingJPS;
+ } else if (mCodingMode == CodingMPO) {
+ portCheck.format.image.eCompressionFormat = (OMX_IMAGE_CODINGTYPE) OMX_TI_IMAGE_CodingMPO;
+ } else {
+ portCheck.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
+ }
+ } else {
+ portCheck.format.image.eColorFormat = portParams.mColorFormat;
+ portCheck.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
+ }
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ // RAW + YUV Capture
+ if (mYuvCapture) {
+ portCheck.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY;
+ portCheck.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
+ }
+#endif
+ //Stride for 1D tiler buffer is zero
+ portCheck.format.image.nStride = 0;
+ portCheck.nBufferCountActual = portParams.mNumBufs;
+ } else if (OMX_CAMERA_PORT_VIDEO_IN_VIDEO == port) {
+ portCheck.format.video.nFrameWidth = portParams.mWidth;
+ portCheck.format.video.nStride = portParams.mStride;
+ portCheck.format.video.nFrameHeight = portParams.mHeight;
+ portCheck.format.video.eColorFormat = portParams.mColorFormat;
+ portCheck.format.video.xFramerate = 30 << 16;
+ portCheck.nBufferCountActual = portParams.mNumBufs;
+ } else {
+ CAMHAL_LOGEB("Unsupported port index (%lu)", port);
+ }
+
+ if (( mSensorIndex == OMX_TI_StereoSensor ) && (OMX_CAMERA_PORT_VIDEO_OUT_VIDEO != port)) {
+ ret = setS3DFrameLayout(port);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEA("Error configuring stereo 3D frame layout");
+ return ret;
+ }
+ }
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexParamPortDefinition, &portCheck);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SetParameter - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ /* check if parameters are set correctly by calling GetParameter() */
+ eError = OMX_GetParameter(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexParamPortDefinition, &portCheck);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_GetParameter - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ portParams.mBufSize = portCheck.nBufferSize;
+ portParams.mStride = portCheck.format.image.nStride;
+
+ if (OMX_CAMERA_PORT_IMAGE_OUT_IMAGE == port) {
+ CAMHAL_LOGDB("\n *** IMG Width = %ld", portCheck.format.image.nFrameWidth);
+ CAMHAL_LOGDB("\n *** IMG Height = %ld", portCheck.format.image.nFrameHeight);
+
+ CAMHAL_LOGDB("\n *** IMG IMG FMT = %x", portCheck.format.image.eColorFormat);
+ CAMHAL_LOGDB("\n *** IMG portCheck.nBufferSize = %ld\n",portCheck.nBufferSize);
+ CAMHAL_LOGDB("\n *** IMG portCheck.nBufferCountMin = %ld\n",
+ portCheck.nBufferCountMin);
+ CAMHAL_LOGDB("\n *** IMG portCheck.nBufferCountActual = %ld\n",
+ portCheck.nBufferCountActual);
+ CAMHAL_LOGDB("\n *** IMG portCheck.format.image.nStride = %ld\n",
+ portCheck.format.image.nStride);
+ } else if (OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW == port) {
+ CAMHAL_LOGDB("\n *** PRV Width = %ld", portCheck.format.video.nFrameWidth);
+ CAMHAL_LOGDB("\n *** PRV Height = %ld", portCheck.format.video.nFrameHeight);
+
+ CAMHAL_LOGDB("\n *** PRV IMG FMT = %x", portCheck.format.video.eColorFormat);
+ CAMHAL_LOGDB("\n *** PRV portCheck.nBufferSize = %ld\n",portCheck.nBufferSize);
+ CAMHAL_LOGDB("\n *** PRV portCheck.nBufferCountMin = %ld\n",
+ portCheck.nBufferCountMin);
+ CAMHAL_LOGDB("\n *** PRV portCheck.nBufferCountActual = %ld\n",
+ portCheck.nBufferCountActual);
+ CAMHAL_LOGDB("\n ***PRV portCheck.format.video.nStride = %ld\n",
+ portCheck.format.video.nStride);
+ } else {
+ CAMHAL_LOGDB("\n *** VID Width = %ld", portCheck.format.video.nFrameWidth);
+ CAMHAL_LOGDB("\n *** VID Height = %ld", portCheck.format.video.nFrameHeight);
+
+ CAMHAL_LOGDB("\n *** VID IMG FMT = %x", portCheck.format.video.eColorFormat);
+ CAMHAL_LOGDB("\n *** VID portCheck.nBufferSize = %ld\n",portCheck.nBufferSize);
+ CAMHAL_LOGDB("\n *** VID portCheck.nBufferCountMin = %ld\n",
+ portCheck.nBufferCountMin);
+ CAMHAL_LOGDB("\n *** VID portCheck.nBufferCountActual = %ld\n",
+ portCheck.nBufferCountActual);
+ CAMHAL_LOGDB("\n *** VID portCheck.format.video.nStride = %ld\n",
+ portCheck.format.video.nStride);
+ }
+
+ mSetFormatDone = true;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+
+ EXIT:
+
+ CAMHAL_LOGEB("Exiting function %s because of eError = 0x%x", __FUNCTION__, eError);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::flushBuffers(OMX_U32 nPort)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ if ( 0 != mFlushSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mFlushSem semaphore count %d", mFlushSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ OMXCameraPortParameters * mPreviewData = NULL;
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[nPort];
+
+ ///Register for the FLUSH event
+ ///This method just inserts a message in Event Q, which is checked in the callback
+ ///The sempahore passed is signalled by the callback
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandFlush,
+ nPort,
+ mFlushSem);
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+
+ ///Send FLUSH command to preview port
+ eError = OMX_SendCommand (mCameraAdapterParameters.mHandleComp,
+ OMX_CommandFlush,
+ nPort,
+ NULL);
+
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_SendCommand(OMX_CommandFlush)-0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ CAMHAL_LOGDA("Waiting for flush event");
+
+ ///Wait for the FLUSH event to occur
+ ret = mFlushSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after Flush Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Flush event received");
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandFlush,
+ nPort,
+ NULL);
+ CAMHAL_LOGDA("Flush event timeout expired");
+ goto EXIT;
+ }
+
+ mOMXCallbackHandler->flush();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+ EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+///API to give the buffers to Adapter
+status_t OMXCameraAdapter::useBuffers(CameraMode mode, CameraBuffer * bufArr, int num, size_t length, unsigned int queueable)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ switch(mode)
+ {
+ case CAMERA_PREVIEW:
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex].mNumBufs = num;
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex].mMaxQueueable = queueable;
+ ret = UseBuffersPreview(bufArr, num);
+ break;
+
+ case CAMERA_IMAGE_CAPTURE:
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex].mMaxQueueable = queueable;
+ ret = UseBuffersCapture(bufArr, num);
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex].mNumBufs = num;
+ break;
+
+ case CAMERA_VIDEO:
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex].mNumBufs = num;
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex].mMaxQueueable = queueable;
+ ret = UseBuffersRawCapture(bufArr, num);
+ break;
+
+ case CAMERA_MEASUREMENT:
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex].mNumBufs = num;
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex].mMaxQueueable = queueable;
+ ret = UseBuffersPreviewData(bufArr, num);
+ break;
+
+ case CAMERA_REPROCESS:
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex].mNumBufs = num;
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex].mMaxQueueable = queueable;
+ ret = UseBuffersReprocess(bufArr, num);
+ break;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::UseBuffersPreviewData(CameraBuffer * bufArr, int num)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters * measurementData = NULL;
+ android::AutoMutex lock(mPreviewDataBufferLock);
+
+ LOG_FUNCTION_NAME;
+
+ if ( mComponentState != OMX_StateLoaded )
+ {
+ CAMHAL_LOGEA("Calling UseBuffersPreviewData() when not in LOADED state");
+ return BAD_VALUE;
+ }
+
+ if ( NULL == bufArr )
+ {
+ CAMHAL_LOGEA("NULL pointer passed for buffArr");
+ return BAD_VALUE;
+ }
+
+ if ( 0 != mUsePreviewDataSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mUsePreviewDataSem semaphore count %d", mUsePreviewDataSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ measurementData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex];
+ measurementData->mNumBufs = num ;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ///Register for port enable event on measurement port
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mMeasurementPortIndex,
+ mUsePreviewDataSem);
+
+ if ( ret == NO_ERROR )
+ {
+ CAMHAL_LOGDB("Registering for event %d", ret);
+ }
+ else
+ {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ///Enable MEASUREMENT Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mMeasurementPortIndex,
+ NULL);
+
+ if ( eError == OMX_ErrorNone )
+ {
+ CAMHAL_LOGDB("OMX_SendCommand(OMX_CommandPortEnable) -0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGEB("OMX_SendCommand(OMX_CommandPortEnable) -0x%x", eError);
+ goto EXIT;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = mUsePreviewDataSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after measurement port enable Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Port enable event arrived on measurement port");
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mMeasurementPortIndex,
+ NULL);
+ CAMHAL_LOGEA("Timeout expoired during port enable on measurement port");
+ goto EXIT;
+ }
+
+ CAMHAL_LOGDA("Port enable event arrived on measurement port");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::switchToExecuting()
+{
+ status_t ret = NO_ERROR;
+ Utils::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ mStateSwitchLock.lock();
+ msg.command = CommandHandler::CAMERA_SWITCH_TO_EXECUTING;
+ msg.arg1 = mErrorNotifier;
+ ret = mCommandHandler->put(&msg);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::doSwitchToExecuting()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ LOG_FUNCTION_NAME;
+
+ if ( (mComponentState == OMX_StateExecuting) || (mComponentState == OMX_StateInvalid) ){
+ CAMHAL_LOGDA("Already in OMX_Executing state or OMX_StateInvalid state");
+ mStateSwitchLock.unlock();
+ return NO_ERROR;
+ }
+
+ if ( 0 != mSwitchToExecSem.Count() ){
+ CAMHAL_LOGEB("Error mSwitchToExecSem semaphore count %d", mSwitchToExecSem.Count());
+ goto EXIT;
+ }
+
+ ///Register for Preview port DISABLE event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ mSwitchToExecSem);
+ if ( NO_ERROR != ret ){
+ CAMHAL_LOGEB("Error in registering Port Disable for event %d", ret);
+ goto EXIT;
+ }
+ ///Disable Preview Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ ret = mSwitchToExecSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if (ret != NO_ERROR){
+ CAMHAL_LOGEB("Timeout PREVIEW PORT DISABLE %d", ret);
+ }
+
+ CAMHAL_LOGVB("PREV PORT DISABLED %d", ret);
+
+ ///Register for IDLE state switch event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ mSwitchToExecSem);
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error in IDLE STATE SWITCH %d", ret);
+ goto EXIT;
+ }
+ eError = OMX_SendCommand (mCameraAdapterParameters.mHandleComp ,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ NULL);
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ ret = mSwitchToExecSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if (ret != NO_ERROR){
+ CAMHAL_LOGEB("Timeout IDLE STATE SWITCH %d", ret);
+ goto EXIT;
+ }
+ mComponentState = OMX_StateIdle;
+ CAMHAL_LOGVB("OMX_SendCommand(OMX_StateIdle) 0x%x", eError);
+
+ ///Register for EXECUTING state switch event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateExecuting,
+ mSwitchToExecSem);
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error in EXECUTING STATE SWITCH %d", ret);
+ goto EXIT;
+ }
+ eError = OMX_SendCommand (mCameraAdapterParameters.mHandleComp ,
+ OMX_CommandStateSet,
+ OMX_StateExecuting,
+ NULL);
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ ret = mSwitchToExecSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if (ret != NO_ERROR){
+ CAMHAL_LOGEB("Timeout EXEC STATE SWITCH %d", ret);
+ goto EXIT;
+ }
+ mComponentState = OMX_StateExecuting;
+ CAMHAL_LOGVB("OMX_SendCommand(OMX_StateExecuting) 0x%x", eError);
+
+ mStateSwitchLock.unlock();
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+
+ EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ mStateSwitchLock.unlock();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::switchToIdle() {
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mIdleStateSwitchLock);
+
+ if ( mComponentState == OMX_StateIdle || mComponentState == OMX_StateLoaded || mComponentState == OMX_StateInvalid) {
+ CAMHAL_LOGDA("Already in OMX_StateIdle, OMX_Loaded state or OMX_StateInvalid state");
+ return NO_ERROR;
+ }
+
+ if ( 0 != mSwitchToLoadedSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mSwitchToLoadedSem semaphore count %d", mSwitchToLoadedSem.Count());
+ goto EXIT;
+ }
+
+ ///Register for EXECUTING state transition.
+ ///This method just inserts a message in Event Q, which is checked in the callback
+ ///The sempahore passed is signalled by the callback
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ mSwitchToLoadedSem);
+
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+
+ eError = OMX_SendCommand (mCameraAdapterParameters.mHandleComp,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ NULL);
+
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_SendCommand(OMX_StateIdle) - %x", eError);
+ }
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ ///Wait for the EXECUTING ->IDLE transition to arrive
+
+ CAMHAL_LOGDA("EXECUTING->IDLE state changed");
+ ret = mSwitchToLoadedSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after EXECUTING->IDLE Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("EXECUTING->IDLE state changed");
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on EXECUTING->IDLE state change");
+ goto EXIT;
+ }
+
+ mComponentState = OMX_StateIdle;
+
+ return NO_ERROR;
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+
+
+status_t OMXCameraAdapter::prevPortEnable() {
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ ///Register for Preview port ENABLE event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ mSwitchToLoadedSem);
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+
+ ///Enable Preview Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+
+
+ CAMHAL_LOGDB("OMX_SendCommand(OMX_CommandStateSet) 0x%x", eError);
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ CAMHAL_LOGDA("Enabling Preview port");
+ ///Wait for state to switch to idle
+ ret = mSwitchToLoadedSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after Enabling Preview port Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Preview port enabled!");
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ CAMHAL_LOGEA("Preview enable timedout");
+
+ goto EXIT;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::switchToLoaded(bool bPortEnableRequired) {
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mStateSwitchLock);
+ if ( mComponentState == OMX_StateLoaded || mComponentState == OMX_StateInvalid) {
+ CAMHAL_LOGDA("Already in OMX_Loaded state or OMX_StateInvalid state");
+ return NO_ERROR;
+ }
+
+ if ( mComponentState != OMX_StateIdle) {
+ ret = switchToIdle();
+ if (ret != NO_ERROR) return ret;
+ }
+
+ if ( 0 != mSwitchToLoadedSem.Count() ) {
+ CAMHAL_LOGEB("Error mSwitchToLoadedSem semaphore count %d", mSwitchToLoadedSem.Count());
+ goto EXIT;
+ }
+
+ ///Register for LOADED state transition.
+ ///This method just inserts a message in Event Q, which is checked in the callback
+ ///The sempahore passed is signalled by the callback
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateLoaded,
+ mSwitchToLoadedSem);
+
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+
+ eError = OMX_SendCommand (mCameraAdapterParameters.mHandleComp,
+ OMX_CommandStateSet,
+ OMX_StateLoaded,
+ NULL);
+
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_SendCommand(OMX_StateLoaded) - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ if ( !bPortEnableRequired ) {
+ OMXCameraPortParameters *mCaptureData , *mPreviewData, *measurementData;
+ mCaptureData = mPreviewData = measurementData = NULL;
+
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+ mCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+ measurementData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex];
+
+ ///Free the OMX Buffers
+ for ( int i = 0 ; i < mPreviewData->mNumBufs ; i++ ) {
+ eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
+ mCameraAdapterParameters.mPrevPortIndex,
+ mPreviewData->mBufferHeader[i]);
+
+ if(eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_FreeBuffer - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+
+ if ( mMeasurementEnabled ) {
+
+ for ( int i = 0 ; i < measurementData->mNumBufs ; i++ ) {
+ eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
+ mCameraAdapterParameters.mMeasurementPortIndex,
+ measurementData->mBufferHeader[i]);
+ if(eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_FreeBuffer - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+
+ {
+ android::AutoMutex lock(mPreviewDataBufferLock);
+ mPreviewDataBuffersAvailable.clear();
+ }
+
+ }
+ }
+
+ CAMHAL_LOGDA("Switching IDLE->LOADED state");
+ ret = mSwitchToLoadedSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after IDLE->LOADED Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("IDLE->LOADED state changed");
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateLoaded,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on IDLE->LOADED state change");
+ goto EXIT;
+ }
+
+ mComponentState = OMX_StateLoaded;
+ if (bPortEnableRequired == true) {
+ prevPortEnable();
+ }
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ {
+ android::AutoMutex lock(mPreviewBufferLock);
+ ///Clear all the available preview buffers
+ mPreviewBuffersAvailable.clear();
+ }
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::UseBuffersPreview(CameraBuffer * bufArr, int num)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ int tmpHeight, tmpWidth;
+
+ LOG_FUNCTION_NAME;
+
+ if(!bufArr)
+ {
+ CAMHAL_LOGEA("NULL pointer passed for buffArr");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ OMXCameraPortParameters * mPreviewData = NULL;
+ OMXCameraPortParameters *measurementData = NULL;
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+ measurementData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex];
+ mPreviewData->mNumBufs = num ;
+
+ if ( 0 != mUsePreviewSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mUsePreviewSem semaphore count %d", mUsePreviewSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ if(mPreviewData->mNumBufs != num)
+ {
+ CAMHAL_LOGEA("Current number of buffers doesnt equal new num of buffers passed!");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ mStateSwitchLock.lock();
+
+ if ( mComponentState == OMX_StateLoaded ) {
+
+ if (mPendingPreviewSettings & SetLDC) {
+ mPendingPreviewSettings &= ~SetLDC;
+ ret = setLDC(mIPP);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("setLDC() failed %d", ret);
+ }
+ }
+
+ if (mPendingPreviewSettings & SetNSF) {
+ mPendingPreviewSettings &= ~SetNSF;
+ ret = setNSF(mIPP);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("setNSF() failed %d", ret);
+ }
+ }
+
+ if (mPendingPreviewSettings & SetCapMode) {
+ mPendingPreviewSettings &= ~SetCapMode;
+ ret = setCaptureMode(mCapMode);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("setCaptureMode() failed %d", ret);
+ }
+ }
+
+ if( (mCapMode == OMXCameraAdapter::VIDEO_MODE) ||
+ (mCapMode == OMXCameraAdapter::VIDEO_MODE_HQ) ) {
+
+ if (mPendingPreviewSettings & SetVNF) {
+ mPendingPreviewSettings &= ~SetVNF;
+ ret = enableVideoNoiseFilter(mVnfEnabled);
+ if ( NO_ERROR != ret){
+ CAMHAL_LOGEB("Error configuring VNF %x", ret);
+ }
+ }
+
+ if (mPendingPreviewSettings & SetVSTAB) {
+ mPendingPreviewSettings &= ~SetVSTAB;
+ ret = enableVideoStabilization(mVstabEnabled);
+ if ( NO_ERROR != ret) {
+ CAMHAL_LOGEB("Error configuring VSTAB %x", ret);
+ }
+ }
+
+ }
+ }
+
+ ret = setSensorOrientation(mSensorOrientation);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error configuring Sensor Orientation %x", ret);
+ mSensorOrientation = 0;
+ }
+
+ if ( mComponentState == OMX_StateLoaded )
+ {
+ ///Register for IDLE state switch event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ mUsePreviewSem);
+
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+
+ ///Once we get the buffers, move component state to idle state and pass the buffers to OMX comp using UseBuffer
+ eError = OMX_SendCommand (mCameraAdapterParameters.mHandleComp ,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ NULL);
+
+ CAMHAL_LOGDB("OMX_SendCommand(OMX_CommandStateSet) 0x%x", eError);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ mComponentState = OMX_StateIdle;
+ }
+ else
+ {
+ ///Register for Preview port ENABLE event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ mUsePreviewSem);
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+
+ ///Enable Preview Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ }
+
+
+ ///Configure DOMX to use either gralloc handles or vptrs
+ OMX_TI_PARAMUSENATIVEBUFFER domxUseGrallocHandles;
+ OMX_INIT_STRUCT_PTR (&domxUseGrallocHandles, OMX_TI_PARAMUSENATIVEBUFFER);
+
+ domxUseGrallocHandles.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ domxUseGrallocHandles.bEnable = OMX_TRUE;
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexUseNativeBuffers, &domxUseGrallocHandles);
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_SetParameter - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ OMX_BUFFERHEADERTYPE *pBufferHdr;
+ for(int index=0;index<num;index++) {
+ OMX_U8 *ptr;
+
+ ptr = (OMX_U8 *)camera_buffer_get_omx_ptr (&bufArr[index]);
+ eError = OMX_UseBuffer( mCameraAdapterParameters.mHandleComp,
+ &pBufferHdr,
+ mCameraAdapterParameters.mPrevPortIndex,
+ 0,
+ mPreviewData->mBufSize,
+ ptr);
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_UseBuffer-0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ pBufferHdr->pAppPrivate = (OMX_PTR)&bufArr[index];
+ pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ pBufferHdr->nVersion.s.nVersionMajor = 1 ;
+ pBufferHdr->nVersion.s.nVersionMinor = 1 ;
+ pBufferHdr->nVersion.s.nRevision = 0 ;
+ pBufferHdr->nVersion.s.nStep = 0;
+ mPreviewData->mBufferHeader[index] = pBufferHdr;
+ }
+
+ if ( mMeasurementEnabled )
+ {
+
+ for( int i = 0; i < num; i++ )
+ {
+ OMX_BUFFERHEADERTYPE *pBufHdr;
+ OMX_U8 *ptr;
+
+ ptr = (OMX_U8 *)camera_buffer_get_omx_ptr (&mPreviewDataBuffers[i]);
+ eError = OMX_UseBuffer( mCameraAdapterParameters.mHandleComp,
+ &pBufHdr,
+ mCameraAdapterParameters.mMeasurementPortIndex,
+ 0,
+ measurementData->mBufSize,
+ ptr);
+
+ if ( eError == OMX_ErrorNone )
+ {
+ pBufHdr->pAppPrivate = (OMX_PTR *)&mPreviewDataBuffers[i];
+ pBufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ pBufHdr->nVersion.s.nVersionMajor = 1 ;
+ pBufHdr->nVersion.s.nVersionMinor = 1 ;
+ pBufHdr->nVersion.s.nRevision = 0 ;
+ pBufHdr->nVersion.s.nStep = 0;
+ measurementData->mBufferHeader[i] = pBufHdr;
+ }
+ else
+ {
+ CAMHAL_LOGEB("OMX_UseBuffer -0x%x", eError);
+ ret = BAD_VALUE;
+ break;
+ }
+ }
+
+ }
+
+ CAMHAL_LOGDA("Registering preview buffers");
+
+ ret = mUsePreviewSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after Registering preview buffers Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Preview buffer registration successfull");
+ }
+ else
+ {
+ if ( mComponentState == OMX_StateLoaded )
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ NULL);
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ }
+ CAMHAL_LOGEA("Timeout expired on preview buffer registration");
+ goto EXIT;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+ ///If there is any failure, we reach here.
+ ///Here, we do any resource freeing and convert from OMX error code to Camera Hal error code
+EXIT:
+ mStateSwitchLock.unlock();
+
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::startPreview()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters *mPreviewData = NULL;
+ OMXCameraPortParameters *measurementData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if( 0 != mStartPreviewSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mStartPreviewSem semaphore count %d", mStartPreviewSem.Count());
+ ret = NO_INIT;
+ goto EXIT;
+ }
+
+ // Enable all preview mode extra data.
+ if ( OMX_ErrorNone == eError) {
+ ret |= setExtraData(true, mCameraAdapterParameters.mPrevPortIndex, OMX_AncillaryData);
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ ret |= setExtraData(true, OMX_ALL, OMX_TI_VectShotInfo);
+#endif
+#ifdef CAMERAHAL_OMX_PROFILING
+ if ( UNLIKELY( mDebugProfile ) ) {
+ ret |= setExtraData(true, OMX_ALL, OMX_TI_ProfilerData);
+ }
+#endif
+ }
+
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+ measurementData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex];
+
+ if( OMX_StateIdle == mComponentState )
+ {
+ ///Register for EXECUTING state transition.
+ ///This method just inserts a message in Event Q, which is checked in the callback
+ ///The sempahore passed is signalled by the callback
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateExecuting,
+ mStartPreviewSem);
+
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error in registering for event %d", ret);
+ goto EXIT;
+ }
+
+ ///Switch to EXECUTING state
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandStateSet,
+ OMX_StateExecuting,
+ NULL);
+
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_SendCommand(OMX_StateExecuting)-0x%x", eError);
+ }
+
+ CAMHAL_LOGDA("+Waiting for component to go into EXECUTING state");
+ ret = mStartPreviewSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after IDLE_EXECUTING Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("+Great. Component went into executing state!!");
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateExecuting,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on executing state switch!");
+ goto EXIT;
+ }
+
+ mComponentState = OMX_StateExecuting;
+
+ }
+
+ mStateSwitchLock.unlock();
+
+ //Queue all the buffers on preview port
+ for(int index=0;index< mPreviewData->mMaxQueueable;index++)
+ {
+ CAMHAL_LOGDB("Queuing buffer on Preview port - 0x%x", (uint32_t)mPreviewData->mBufferHeader[index]->pBuffer);
+ mPreviewData->mStatus[index] = OMXCameraPortParameters::FILL;
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp,
+ (OMX_BUFFERHEADERTYPE*)mPreviewData->mBufferHeader[index]);
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_FillThisBuffer-0x%x", eError);
+ }
+ mFramesWithDucati++;
+#ifdef CAMERAHAL_DEBUG
+ {
+ android::AutoMutex locker(mBuffersWithDucatiLock);
+ mBuffersWithDucati.add((int)mPreviewData->mBufferHeader[index]->pBuffer,1);
+ }
+#endif
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+
+ if ( mMeasurementEnabled )
+ {
+
+ for(int index=0;index< mPreviewData->mNumBufs;index++)
+ {
+ CAMHAL_LOGDB("Queuing buffer on Measurement port - 0x%x", (uint32_t) measurementData->mBufferHeader[index]->pBuffer);
+ measurementData->mStatus[index] = OMXCameraPortParameters::FILL;
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp,
+ (OMX_BUFFERHEADERTYPE*) measurementData->mBufferHeader[index]);
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_FillThisBuffer-0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+
+ }
+
+ setFocusCallback(true);
+
+ //reset frame rate estimates
+ mFPS = 0.0f;
+ mLastFPS = 0.0f;
+ // start frame count from 0. i.e first frame after
+ // startPreview will be the 0th reference frame
+ // this way we will wait for second frame until
+ // takePicture/autoFocus is allowed to run. we
+ // are seeing SetConfig/GetConfig fail after
+ // calling after the first frame and not failing
+ // after the second frame
+ mFrameCount = -1;
+ mLastFrameCount = 0;
+ mIter = 1;
+ mLastFPSTime = systemTime();
+ mTunnelDestroyed = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+ EXIT:
+
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ mStateSwitchLock.unlock();
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+}
+
+status_t OMXCameraAdapter::destroyTunnel()
+{
+ LOG_FUNCTION_NAME;
+
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ status_t ret = NO_ERROR;
+
+ OMXCameraPortParameters *mCaptureData , *mPreviewData, *measurementData;
+ mCaptureData = mPreviewData = measurementData = NULL;
+
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+ mCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+ measurementData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex];
+
+ if (mAdapterState == LOADED_PREVIEW_STATE) {
+ // Something happened in CameraHal between UseBuffers and startPreview
+ // this means that state switch is still locked..so we need to unlock else
+ // deadlock will occur on the next start preview
+ mStateSwitchLock.unlock();
+ return ALREADY_EXISTS;
+ }
+
+ if ( mComponentState != OMX_StateExecuting )
+ {
+ CAMHAL_LOGEA("Calling StopPreview() when not in EXECUTING state");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ {
+ android::AutoMutex lock(mFrameCountMutex);
+ // we should wait for the first frame to come before trying to stopPreview...if not
+ // we might put OMXCamera in a bad state (IDLE->LOADED timeout). Seeing this a lot
+ // after a capture
+ if (mFrameCount < 1) {
+ // I want to wait for at least two frames....
+ mFrameCount = -1;
+
+ // first frame may time some time to come...so wait for an adequate amount of time
+ // which 2 * OMX_CAPTURE_TIMEOUT * 1000 will cover.
+ ret = mFirstFrameCondition.waitRelative(mFrameCountMutex,
+ (nsecs_t) 2 * OMX_CAPTURE_TIMEOUT * 1000);
+ }
+ // even if we timeout waiting for the first frame...go ahead with trying to stop preview
+ // signal anybody that might be waiting
+ mFrameCount = 0;
+ mFirstFrameCondition.broadcast();
+ }
+
+ {
+ android::AutoMutex lock(mDoAFMutex);
+ mDoAFCond.broadcast();
+ }
+
+ OMX_CONFIG_FOCUSASSISTTYPE focusAssist;
+ OMX_INIT_STRUCT_PTR (&focusAssist, OMX_CONFIG_FOCUSASSISTTYPE);
+ focusAssist.nPortIndex = OMX_ALL;
+ focusAssist.bFocusAssist = OMX_FALSE;
+ CAMHAL_LOGDB("Configuring AF Assist mode 0x%x", focusAssist.bFocusAssist);
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_IndexConfigFocusAssist,
+ &focusAssist);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring AF Assist mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera AF Assist mode configured successfully");
+ }
+
+ if ( 0 != mStopPreviewSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mStopPreviewSem semaphore count %d", mStopPreviewSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ ret = disableImagePort();
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("disable image port failed 0x%x", ret);
+ goto EXIT;
+ }
+
+ CAMHAL_LOGDB("Average framerate: %f", mFPS);
+
+ //Avoid state switching of the OMX Component
+ ret = flushBuffers();
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Flush Buffers failed 0x%x", ret);
+ goto EXIT;
+ }
+
+ switchToIdle();
+
+ mTunnelDestroyed = true;
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ {
+ android::AutoMutex lock(mPreviewBufferLock);
+ ///Clear all the available preview buffers
+ mPreviewBuffersAvailable.clear();
+ }
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+}
+
+status_t OMXCameraAdapter::stopPreview() {
+ LOG_FUNCTION_NAME;
+
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ status_t ret = NO_ERROR;
+
+#ifdef CAMERAHAL_OMX_PROFILING
+ ret |= setExtraData(false, OMX_ALL, OMX_TI_ProfilerData);
+#endif
+ if (mTunnelDestroyed == false){
+ ret = destroyTunnel();
+ if (ret == ALREADY_EXISTS) {
+ // Special case to handle invalid stopping preview in LOADED_PREVIEW_STATE
+ return NO_ERROR;
+ }
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGEB(" destroyTunnel returned error ");
+ return ret;
+ }
+ }
+
+ mTunnelDestroyed = false;
+
+ {
+ android::AutoMutex lock(mPreviewBufferLock);
+ ///Clear all the available preview buffers
+ mPreviewBuffersAvailable.clear();
+ }
+
+ switchToLoaded();
+
+ mFirstTimeInit = true;
+ mPendingCaptureSettings = 0;
+ mPendingReprocessSettings = 0;
+ mFramesWithDucati = 0;
+ mFramesWithDisplay = 0;
+ mFramesWithEncoder = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::setSensorOverclock(bool enable)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateLoaded != mComponentState )
+ {
+ CAMHAL_LOGDA("OMX component is not in loaded state");
+ return ret;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
+
+ if ( enable )
+ {
+ bOMX.bEnabled = OMX_TRUE;
+ }
+ else
+ {
+ bOMX.bEnabled = OMX_FALSE;
+ }
+
+ CAMHAL_LOGDB("Configuring Sensor overclock mode 0x%x", bOMX.bEnabled);
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp, ( OMX_INDEXTYPE ) OMX_TI_IndexParamSensorOverClockMode, &bOMX);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while setting Sensor overclock 0x%x", eError);
+ }
+ else
+ {
+ mSensorOverclock = enable;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::printComponentVersion(OMX_HANDLETYPE handle)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_VERSIONTYPE compVersion;
+ char compName[OMX_MAX_STRINGNAME_SIZE];
+ char *currentUUID = NULL;
+ size_t offset = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == handle )
+ {
+ CAMHAL_LOGEB("Invalid OMX Handle =0x%x", ( unsigned int ) handle);
+ ret = -EINVAL;
+ }
+
+ mCompUUID[0] = 0;
+
+ if ( NO_ERROR == ret )
+ {
+ eError = OMX_GetComponentVersion(handle,
+ compName,
+ &compVersion,
+ &mCompRevision,
+ &mCompUUID
+ );
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("OMX_GetComponentVersion returned 0x%x", eError);
+ ret = BAD_VALUE;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGVB("OMX Component name: [%s]", compName);
+ CAMHAL_LOGVB("OMX Component version: [%u]", ( unsigned int ) compVersion.nVersion);
+ CAMHAL_LOGVB("Spec version: [%u]", ( unsigned int ) mCompRevision.nVersion);
+ CAMHAL_LOGVB("Git Commit ID: [%s]", mCompUUID);
+ currentUUID = ( char * ) mCompUUID;
+ }
+
+ if ( NULL != currentUUID )
+ {
+ offset = strlen( ( const char * ) mCompUUID) + 1;
+ if ( (int)currentUUID + (int)offset - (int)mCompUUID < OMX_MAX_STRINGNAME_SIZE )
+ {
+ currentUUID += offset;
+ CAMHAL_LOGVB("Git Branch: [%s]", currentUUID);
+ }
+ else
+ {
+ ret = BAD_VALUE;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ offset = strlen( ( const char * ) currentUUID) + 1;
+
+ if ( (int)currentUUID + (int)offset - (int)mCompUUID < OMX_MAX_STRINGNAME_SIZE )
+ {
+ currentUUID += offset;
+ CAMHAL_LOGVB("Build date and time: [%s]", currentUUID);
+ }
+ else
+ {
+ ret = BAD_VALUE;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ offset = strlen( ( const char * ) currentUUID) + 1;
+
+ if ( (int)currentUUID + (int)offset - (int)mCompUUID < OMX_MAX_STRINGNAME_SIZE )
+ {
+ currentUUID += offset;
+ CAMHAL_LOGVB("Build description: [%s]", currentUUID);
+ }
+ else
+ {
+ ret = BAD_VALUE;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setS3DFrameLayout(OMX_U32 port) const
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_FRAMELAYOUTTYPE frameLayout;
+ const OMXCameraPortParameters *cap =
+ &mCameraAdapterParameters.mCameraPortParams[port];
+
+ LOG_FUNCTION_NAME;
+
+ OMX_INIT_STRUCT_PTR (&frameLayout, OMX_TI_FRAMELAYOUTTYPE);
+ frameLayout.nPortIndex = port;
+ eError = OMX_GetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexParamStereoFrmLayout, &frameLayout);
+ if (eError != OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("Error while getting S3D frame layout: 0x%x", eError);
+ return -EINVAL;
+ }
+
+ if (cap->mFrameLayoutType == OMX_TI_StereoFrameLayoutTopBottomSubsample)
+ {
+ frameLayout.eFrameLayout = OMX_TI_StereoFrameLayoutTopBottom;
+ frameLayout.nSubsampleRatio = 2;
+ }
+ else if (cap->mFrameLayoutType ==
+ OMX_TI_StereoFrameLayoutLeftRightSubsample)
+ {
+ frameLayout.eFrameLayout = OMX_TI_StereoFrameLayoutLeftRight;
+ frameLayout.nSubsampleRatio = 2;
+ }
+ else
+ {
+ frameLayout.eFrameLayout = cap->mFrameLayoutType;
+ frameLayout.nSubsampleRatio = 1;
+ }
+ frameLayout.nSubsampleRatio = frameLayout.nSubsampleRatio << 7;
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexParamStereoFrmLayout, &frameLayout);
+ if (eError != OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("Error while setting S3D frame layout: 0x%x", eError);
+ return -EINVAL;
+ }
+ else
+ {
+ CAMHAL_LOGDB("S3D frame layout %d applied successfully on port %lu",
+ frameLayout.eFrameLayout, port);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+status_t OMXCameraAdapter::autoFocus()
+{
+ status_t ret = NO_ERROR;
+ Utils::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ {
+ android::AutoMutex lock(mFrameCountMutex);
+ if (mFrameCount < 1) {
+ // first frame may time some time to come...so wait for an adequate amount of time
+ // which 2 * OMX_CAPTURE_TIMEOUT * 1000 will cover.
+ ret = mFirstFrameCondition.waitRelative(mFrameCountMutex,
+ (nsecs_t) 2 * OMX_CAPTURE_TIMEOUT * 1000);
+ if ((NO_ERROR != ret) || (mFrameCount == 0)) {
+ goto EXIT;
+ }
+ }
+ }
+
+ msg.command = CommandHandler::CAMERA_PERFORM_AUTOFOCUS;
+ msg.arg1 = mErrorNotifier;
+ ret = mCommandHandler->put(&msg);
+
+ EXIT:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::takePicture()
+{
+ status_t ret = NO_ERROR;
+ Utils::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ if (mNextState != REPROCESS_STATE) {
+ android::AutoMutex lock(mFrameCountMutex);
+ if (mFrameCount < 1) {
+ // first frame may time some time to come...so wait for an adequate amount of time
+ // which 2 * OMX_CAPTURE_TIMEOUT * 1000 will cover.
+ ret = mFirstFrameCondition.waitRelative(mFrameCountMutex,
+ (nsecs_t) 2 * OMX_CAPTURE_TIMEOUT * 1000);
+ if ((NO_ERROR != ret) || (mFrameCount == 0)) {
+ goto EXIT;
+ }
+ }
+ }
+
+ // TODO(XXX): re-using take picture to kick off reprocessing pipe
+ // Need to rethink this approach during reimplementation
+ if (mNextState == REPROCESS_STATE) {
+ msg.command = CommandHandler::CAMERA_START_REPROCESS;
+ } else {
+ msg.command = CommandHandler::CAMERA_START_IMAGE_CAPTURE;
+ }
+
+ msg.arg1 = mErrorNotifier;
+ msg.arg2 = cacheCaptureParameters();
+ ret = mCommandHandler->put(&msg);
+
+ EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startVideoCapture()
+{
+ return BaseCameraAdapter::startVideoCapture();
+}
+
+status_t OMXCameraAdapter::stopVideoCapture()
+{
+ return BaseCameraAdapter::stopVideoCapture();
+}
+
+//API to get the frame size required to be allocated. This size is used to override the size passed
+//by camera service when VSTAB/VNF is turned ON for example
+status_t OMXCameraAdapter::getFrameSize(size_t &width, size_t &height)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_RECTTYPE tFrameDim;
+
+ LOG_FUNCTION_NAME;
+
+ OMX_INIT_STRUCT_PTR (&tFrameDim, OMX_CONFIG_RECTTYPE);
+ tFrameDim.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ if ( mOMXStateSwitch )
+ {
+ ret = switchToLoaded(true);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("switchToLoaded() failed 0x%x", ret);
+ goto exit;
+ }
+
+ mOMXStateSwitch = false;
+ }
+
+ if ( OMX_StateLoaded == mComponentState )
+ {
+
+ if (mPendingPreviewSettings & SetLDC) {
+ mPendingPreviewSettings &= ~SetLDC;
+ ret = setLDC(mIPP);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("setLDC() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ goto exit;
+ }
+ }
+
+ if (mPendingPreviewSettings & SetNSF) {
+ mPendingPreviewSettings &= ~SetNSF;
+ ret = setNSF(mIPP);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("setNSF() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ goto exit;
+ }
+ }
+
+ if (mPendingPreviewSettings & SetCapMode) {
+ mPendingPreviewSettings &= ~SetCapMode;
+ ret = setCaptureMode(mCapMode);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("setCaptureMode() failed %d", ret);
+ }
+ }
+
+ if((mCapMode == OMXCameraAdapter::VIDEO_MODE) ||
+ (mCapMode == OMXCameraAdapter::VIDEO_MODE_HQ) ) {
+
+ if (mPendingPreviewSettings & SetVNF) {
+ mPendingPreviewSettings &= ~SetVNF;
+ ret = enableVideoNoiseFilter(mVnfEnabled);
+ if ( NO_ERROR != ret){
+ CAMHAL_LOGEB("Error configuring VNF %x", ret);
+ }
+ }
+
+ if (mPendingPreviewSettings & SetVSTAB) {
+ mPendingPreviewSettings &= ~SetVSTAB;
+ ret = enableVideoStabilization(mVstabEnabled);
+ if ( NO_ERROR != ret) {
+ CAMHAL_LOGEB("Error configuring VSTAB %x", ret);
+ }
+ }
+
+ }
+ }
+
+ ret = setSensorOrientation(mSensorOrientation);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error configuring Sensor Orientation %x", ret);
+ mSensorOrientation = 0;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ eError = OMX_GetParameter(mCameraAdapterParameters.mHandleComp, ( OMX_INDEXTYPE ) OMX_TI_IndexParam2DBufferAllocDimension, &tFrameDim);
+ if ( OMX_ErrorNone == eError)
+ {
+ width = tFrameDim.nWidth;
+ height = tFrameDim.nHeight;
+ }
+ }
+
+exit:
+
+ CAMHAL_LOGDB("Required frame size %dx%d", width, height);
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::getFrameDataSize(size_t &dataFrameSize, size_t bufferCount)
+{
+ status_t ret = NO_ERROR;
+ OMX_PARAM_PORTDEFINITIONTYPE portCheck;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateLoaded != mComponentState )
+ {
+ CAMHAL_LOGEA("Calling getFrameDataSize() when not in LOADED state");
+ dataFrameSize = 0;
+ ret = BAD_VALUE;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR(&portCheck, OMX_PARAM_PORTDEFINITIONTYPE);
+ portCheck.nPortIndex = mCameraAdapterParameters.mMeasurementPortIndex;
+
+ eError = OMX_GetParameter(mCameraAdapterParameters.mHandleComp, OMX_IndexParamPortDefinition, &portCheck);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("OMX_GetParameter on OMX_IndexParamPortDefinition returned: 0x%x", eError);
+ dataFrameSize = 0;
+ ret = BAD_VALUE;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ portCheck.nBufferCountActual = bufferCount;
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp, OMX_IndexParamPortDefinition, &portCheck);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("OMX_SetParameter on OMX_IndexParamPortDefinition returned: 0x%x", eError);
+ dataFrameSize = 0;
+ ret = BAD_VALUE;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ eError = OMX_GetParameter(mCameraAdapterParameters.mHandleComp, OMX_IndexParamPortDefinition, &portCheck);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("OMX_GetParameter on OMX_IndexParamPortDefinition returned: 0x%x", eError);
+ ret = BAD_VALUE;
+ }
+ else
+ {
+ mCameraAdapterParameters.mCameraPortParams[portCheck.nPortIndex].mBufSize = portCheck.nBufferSize;
+ dataFrameSize = portCheck.nBufferSize;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+void OMXCameraAdapter::onOrientationEvent(uint32_t orientation, uint32_t tilt)
+{
+ LOG_FUNCTION_NAME;
+
+ static const unsigned int DEGREES_TILT_IGNORE = 45;
+
+ // if tilt angle is greater than DEGREES_TILT_IGNORE
+ // we are going to ignore the orientation returned from
+ // sensor. the orientation returned from sensor is not
+ // reliable. Value of DEGREES_TILT_IGNORE may need adjusting
+ if (tilt > DEGREES_TILT_IGNORE) {
+ return;
+ }
+
+ int mountOrientation = 0;
+ bool isFront = false;
+ if (mCapabilities) {
+ const char * const mountOrientationString =
+ mCapabilities->get(CameraProperties::ORIENTATION_INDEX);
+ if (mountOrientationString) {
+ mountOrientation = atoi(mountOrientationString);
+ }
+
+ const char * const facingString = mCapabilities->get(CameraProperties::FACING_INDEX);
+ if (facingString) {
+ isFront = strcmp(facingString, TICameraParameters::FACING_FRONT) == 0;
+ }
+ }
+
+ // direction is a constant sign for facing, meaning the rotation direction relative to device
+ // +1 (clockwise) for back sensor and -1 (counter-clockwise) for front sensor
+ const int direction = isFront ? -1 : 1;
+
+ int rotation = mountOrientation + direction*orientation;
+
+ // crop the calculated value to [0..360) range
+ while ( rotation < 0 ) rotation += 360;
+ rotation %= 360;
+
+ if (rotation != mDeviceOrientation) {
+ mDeviceOrientation = rotation;
+
+ // restart face detection with new rotation
+ setFaceDetectionOrientation(mDeviceOrientation);
+ }
+ CAMHAL_LOGVB("orientation = %d tilt = %d device_orientation = %d", orientation, tilt, mDeviceOrientation);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/* Application callback Functions */
+/*========================================================*/
+/* @ fn SampleTest_EventHandler :: Application callback */
+/*========================================================*/
+OMX_ERRORTYPE OMXCameraAdapterEventHandler(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+{
+ LOG_FUNCTION_NAME;
+
+ CAMHAL_LOGDB("Event %d", eEvent);
+
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ OMXCameraAdapter *oca = (OMXCameraAdapter*)pAppData;
+ ret = oca->OMXCameraAdapterEventHandler(hComponent, eEvent, nData1, nData2, pEventData);
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+/* Application callback Functions */
+/*========================================================*/
+/* @ fn SampleTest_EventHandler :: Application callback */
+/*========================================================*/
+OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterEventHandler(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+{
+
+ LOG_FUNCTION_NAME;
+
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ CAMHAL_LOGDB("+OMX_Event %x, %d %d", eEvent, (int)nData1, (int)nData2);
+
+ switch (eEvent) {
+ case OMX_EventCmdComplete:
+ CAMHAL_LOGDB("+OMX_EventCmdComplete %d %d", (int)nData1, (int)nData2);
+
+ if (OMX_CommandStateSet == nData1) {
+ mCameraAdapterParameters.mState = (OMX_STATETYPE) nData2;
+
+ } else if (OMX_CommandFlush == nData1) {
+ CAMHAL_LOGDB("OMX_CommandFlush received for port %d", (int)nData2);
+
+ } else if (OMX_CommandPortDisable == nData1) {
+ CAMHAL_LOGDB("OMX_CommandPortDisable received for port %d", (int)nData2);
+
+ } else if (OMX_CommandPortEnable == nData1) {
+ CAMHAL_LOGDB("OMX_CommandPortEnable received for port %d", (int)nData2);
+
+ } else if (OMX_CommandMarkBuffer == nData1) {
+ ///This is not used currently
+ }
+
+ CAMHAL_LOGDA("-OMX_EventCmdComplete");
+ break;
+
+ case OMX_EventIndexSettingChanged:
+ CAMHAL_LOGDB("OMX_EventIndexSettingChanged event received data1 0x%x, data2 0x%x",
+ ( unsigned int ) nData1, ( unsigned int ) nData2);
+ break;
+
+ case OMX_EventError:
+ CAMHAL_LOGDB("OMX interface failed to execute OMX command %d", (int)nData1);
+ CAMHAL_LOGDA("See OMX_INDEXTYPE for reference");
+ if ( NULL != mErrorNotifier && ( ( OMX_U32 ) OMX_ErrorHardware == nData1 ) && mComponentState != OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("***Got Fatal Error Notification***\n");
+ mComponentState = OMX_StateInvalid;
+ /*
+ Remove any unhandled events and
+ unblock any waiting semaphores
+ */
+ if ( !mEventSignalQ.isEmpty() )
+ {
+ for (unsigned int i = 0 ; i < mEventSignalQ.size(); i++ )
+ {
+ CAMHAL_LOGEB("***Removing %d EVENTS***** \n", mEventSignalQ.size());
+ //remove from queue and free msg
+ Utils::Message *msg = mEventSignalQ.itemAt(i);
+ if ( NULL != msg )
+ {
+ Utils::Semaphore *sem = (Utils::Semaphore*) msg->arg3;
+ if ( sem )
+ {
+ sem->Signal();
+ }
+ free(msg);
+ }
+ }
+ mEventSignalQ.clear();
+ }
+ ///Report Error to App
+ mErrorNotifier->errorNotify(CAMERA_ERROR_FATAL);
+ }
+ break;
+
+ case OMX_EventMark:
+ break;
+
+ case OMX_EventPortSettingsChanged:
+ break;
+
+ case OMX_EventBufferFlag:
+ break;
+
+ case OMX_EventResourcesAcquired:
+ break;
+
+ case OMX_EventComponentResumed:
+ break;
+
+ case OMX_EventDynamicResourcesAvailable:
+ break;
+
+ case OMX_EventPortFormatDetected:
+ break;
+
+ default:
+ break;
+ }
+
+ ///Signal to the thread(s) waiting that the event has occured
+ SignalEvent(hComponent, eEvent, nData1, nData2, pEventData);
+
+ LOG_FUNCTION_NAME_EXIT;
+ return eError;
+
+ EXIT:
+
+ CAMHAL_LOGEB("Exiting function %s because of eError=%x", __FUNCTION__, eError);
+ LOG_FUNCTION_NAME_EXIT;
+ return eError;
+}
+
+OMX_ERRORTYPE OMXCameraAdapter::SignalEvent(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+{
+ android::AutoMutex lock(mEventLock);
+ Utils::Message *msg;
+ bool eventSignalled = false;
+
+ LOG_FUNCTION_NAME;
+
+ if ( !mEventSignalQ.isEmpty() )
+ {
+ CAMHAL_LOGDA("Event queue not empty");
+
+ for ( unsigned int i = 0 ; i < mEventSignalQ.size() ; i++ )
+ {
+ msg = mEventSignalQ.itemAt(i);
+ if ( NULL != msg )
+ {
+ if( ( msg->command != 0 || msg->command == ( unsigned int ) ( eEvent ) )
+ && ( !msg->arg1 || ( OMX_U32 ) msg->arg1 == nData1 )
+ && ( !msg->arg2 || ( OMX_U32 ) msg->arg2 == nData2 )
+ && msg->arg3)
+ {
+ Utils::Semaphore *sem = (Utils::Semaphore*) msg->arg3;
+ CAMHAL_LOGDA("Event matched, signalling sem");
+ mEventSignalQ.removeAt(i);
+ //Signal the semaphore provided
+ sem->Signal();
+ free(msg);
+ eventSignalled = true;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ CAMHAL_LOGDA("Event queue empty!!!");
+ }
+
+ // Special handling for any unregistered events
+ if (!eventSignalled) {
+ // Handling for focus callback
+ if ((nData2 == OMX_IndexConfigCommonFocusStatus) &&
+ (eEvent == (OMX_EVENTTYPE) OMX_EventIndexSettingChanged)) {
+ Utils::Message msg;
+ msg.command = OMXCallbackHandler::CAMERA_FOCUS_STATUS;
+ msg.arg1 = NULL;
+ msg.arg2 = NULL;
+ mOMXCallbackHandler->put(&msg);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXCameraAdapter::RemoveEvent(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData)
+{
+ android::AutoMutex lock(mEventLock);
+ Utils::Message *msg;
+ LOG_FUNCTION_NAME;
+
+ if ( !mEventSignalQ.isEmpty() )
+ {
+ CAMHAL_LOGDA("Event queue not empty");
+
+ for ( unsigned int i = 0 ; i < mEventSignalQ.size() ; i++ )
+ {
+ msg = mEventSignalQ.itemAt(i);
+ if ( NULL != msg )
+ {
+ if( ( msg->command != 0 || msg->command == ( unsigned int ) ( eEvent ) )
+ && ( !msg->arg1 || ( OMX_U32 ) msg->arg1 == nData1 )
+ && ( !msg->arg2 || ( OMX_U32 ) msg->arg2 == nData2 )
+ && msg->arg3)
+ {
+ Utils::Semaphore *sem = (Utils::Semaphore*) msg->arg3;
+ CAMHAL_LOGDA("Event matched, signalling sem");
+ mEventSignalQ.removeAt(i);
+ free(msg);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ CAMHAL_LOGEA("Event queue empty!!!");
+ }
+ LOG_FUNCTION_NAME_EXIT;
+
+ return OMX_ErrorNone;
+}
+
+
+status_t OMXCameraAdapter::RegisterForEvent(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN Utils::Semaphore &semaphore)
+{
+ status_t ret = NO_ERROR;
+ ssize_t res;
+ android::AutoMutex lock(mEventLock);
+
+ LOG_FUNCTION_NAME;
+ Utils::Message * msg = ( struct Utils::Message * ) malloc(sizeof(struct Utils::Message));
+ if ( NULL != msg )
+ {
+ msg->command = ( unsigned int ) eEvent;
+ msg->arg1 = ( void * ) nData1;
+ msg->arg2 = ( void * ) nData2;
+ msg->arg3 = ( void * ) &semaphore;
+ msg->arg4 = ( void * ) hComponent;
+ res = mEventSignalQ.add(msg);
+ if ( NO_MEMORY == res )
+ {
+ CAMHAL_LOGEA("No ressources for inserting OMX events");
+ free(msg);
+ ret = -ENOMEM;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/*========================================================*/
+/* @ fn SampleTest_EmptyBufferDone :: Application callback*/
+/*========================================================*/
+OMX_ERRORTYPE OMXCameraAdapterEmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader)
+{
+ LOG_FUNCTION_NAME;
+
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ OMXCameraAdapter *oca = (OMXCameraAdapter*)pAppData;
+ eError = oca->OMXCameraAdapterEmptyBufferDone(hComponent, pBuffHeader);
+
+ LOG_FUNCTION_NAME_EXIT;
+ return eError;
+}
+
+
+/*========================================================*/
+/* @ fn SampleTest_EmptyBufferDone :: Application callback*/
+/*========================================================*/
+OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterEmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader)
+{
+
+ LOG_FUNCTION_NAME;
+ status_t stat = NO_ERROR;
+ status_t res1, res2;
+ OMXCameraPortParameters *pPortParam;
+ CameraFrame::FrameType typeOfFrame = CameraFrame::ALL_FRAMES;
+ unsigned int refCount = 0;
+ unsigned int mask = 0xFFFF;
+ CameraFrame cameraFrame;
+ OMX_TI_PLATFORMPRIVATE *platformPrivate;
+
+ res1 = res2 = NO_ERROR;
+
+ if (!pBuffHeader || !pBuffHeader->pBuffer) {
+ CAMHAL_LOGE("NULL Buffer from OMX");
+ return OMX_ErrorNone;
+ }
+
+ pPortParam = &(mCameraAdapterParameters.mCameraPortParams[pBuffHeader->nInputPortIndex]);
+ platformPrivate = (OMX_TI_PLATFORMPRIVATE*) pBuffHeader->pPlatformPrivate;
+
+ if (pBuffHeader->nInputPortIndex == OMX_CAMERA_PORT_VIDEO_IN_VIDEO) {
+ typeOfFrame = CameraFrame::REPROCESS_INPUT_FRAME;
+ mask = (unsigned int)CameraFrame::REPROCESS_INPUT_FRAME;
+
+ stat = sendCallBacks(cameraFrame, pBuffHeader, mask, pPortParam);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return OMX_ErrorNone;
+}
+
+static void debugShowFPS()
+{
+ static int mFrameCount = 0;
+ static int mLastFrameCount = 0;
+ static nsecs_t mLastFpsTime = 0;
+ static float mFps = 0;
+ mFrameCount++;
+ if (!(mFrameCount & 0x1F)) {
+ nsecs_t now = systemTime();
+ nsecs_t diff = now - mLastFpsTime;
+ mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
+ mLastFpsTime = now;
+ mLastFrameCount = mFrameCount;
+ CAMHAL_LOGI("Camera %d Frames, %f FPS", mFrameCount, mFps);
+ }
+ // XXX: mFPS has the value we want
+}
+
+/*========================================================*/
+/* @ fn SampleTest_FillBufferDone :: Application callback*/
+/*========================================================*/
+OMX_ERRORTYPE OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader)
+{
+ Utils::Message msg;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ if (UNLIKELY(mDebugFps)) {
+ debugShowFPS();
+ }
+
+ OMXCameraAdapter *adapter = ( OMXCameraAdapter * ) pAppData;
+ if ( NULL != adapter )
+ {
+ msg.command = OMXCameraAdapter::OMXCallbackHandler::CAMERA_FILL_BUFFER_DONE;
+ msg.arg1 = ( void * ) hComponent;
+ msg.arg2 = ( void * ) pBuffHeader;
+ adapter->mOMXCallbackHandler->put(&msg);
+ }
+
+ return eError;
+}
+
+#ifdef CAMERAHAL_OMX_PROFILING
+
+status_t OMXCameraAdapter::storeProfilingData(OMX_BUFFERHEADERTYPE* pBuffHeader) {
+ OMX_TI_PLATFORMPRIVATE *platformPrivate = NULL;
+ OMX_OTHER_EXTRADATATYPE *extraData = NULL;
+ FILE *fd = NULL;
+
+ LOG_FUNCTION_NAME
+
+ if ( UNLIKELY( mDebugProfile ) ) {
+
+ platformPrivate = static_cast<OMX_TI_PLATFORMPRIVATE *> (pBuffHeader->pPlatformPrivate);
+ extraData = getExtradata(platformPrivate,
+ static_cast<OMX_EXTRADATATYPE> (OMX_TI_ProfilerData));
+
+ if ( NULL != extraData ) {
+ if( extraData->eType == static_cast<OMX_EXTRADATATYPE> (OMX_TI_ProfilerData) ) {
+
+ fd = fopen(DEFAULT_PROFILE_PATH, "ab");
+ if ( NULL != fd ) {
+ fwrite(extraData->data, 1, extraData->nDataSize, fd);
+ fclose(fd);
+ } else {
+ return -errno;
+ }
+
+ } else {
+ return NOT_ENOUGH_DATA;
+ }
+ } else {
+ return NOT_ENOUGH_DATA;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return NO_ERROR;
+}
+
+#endif
+
+/*========================================================*/
+/* @ fn SampleTest_FillBufferDone :: Application callback*/
+/*========================================================*/
+OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader)
+{
+
+ status_t stat = NO_ERROR;
+ status_t res1, res2;
+ OMXCameraPortParameters *pPortParam;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ CameraFrame::FrameType typeOfFrame = CameraFrame::ALL_FRAMES;
+ unsigned int refCount = 0;
+ BaseCameraAdapter::AdapterState state, nextState;
+ BaseCameraAdapter::getState(state);
+ BaseCameraAdapter::getNextState(nextState);
+ android::sp<CameraMetadataResult> metadataResult = NULL;
+ unsigned int mask = 0xFFFF;
+ CameraFrame cameraFrame;
+ OMX_OTHER_EXTRADATATYPE *extraData;
+ OMX_TI_ANCILLARYDATATYPE *ancillaryData = NULL;
+ bool snapshotFrame = false;
+
+ if ( NULL == pBuffHeader ) {
+ return OMX_ErrorBadParameter;
+ }
+
+#ifdef CAMERAHAL_OMX_PROFILING
+
+ storeProfilingData(pBuffHeader);
+
+#endif
+
+ res1 = res2 = NO_ERROR;
+
+ if ( !pBuffHeader || !pBuffHeader->pBuffer ) {
+ CAMHAL_LOGEA("NULL Buffer from OMX");
+ return OMX_ErrorNone;
+ }
+
+ pPortParam = &(mCameraAdapterParameters.mCameraPortParams[pBuffHeader->nOutputPortIndex]);
+
+ // Find buffer and mark it as filled
+ for (int i = 0; i < pPortParam->mNumBufs; i++) {
+ if (pPortParam->mBufferHeader[i] == pBuffHeader) {
+ pPortParam->mStatus[i] = OMXCameraPortParameters::DONE;
+ }
+ }
+
+ if (pBuffHeader->nOutputPortIndex == OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW)
+ {
+
+ if ( ( PREVIEW_ACTIVE & state ) != PREVIEW_ACTIVE )
+ {
+ return OMX_ErrorNone;
+ }
+
+ if ( mWaitingForSnapshot ) {
+ extraData = getExtradata(pBuffHeader->pPlatformPrivate,
+ (OMX_EXTRADATATYPE) OMX_AncillaryData);
+
+ if ( NULL != extraData ) {
+ ancillaryData = (OMX_TI_ANCILLARYDATATYPE*) extraData->data;
+ if ((OMX_2D_Snap == ancillaryData->eCameraView)
+ || (OMX_3D_Left_Snap == ancillaryData->eCameraView)
+ || (OMX_3D_Right_Snap == ancillaryData->eCameraView)) {
+ snapshotFrame = OMX_TRUE;
+ } else {
+ snapshotFrame = OMX_FALSE;
+ }
+ mPending3Asettings |= SetFocus;
+ }
+ }
+
+ ///Prepare the frames to be sent - initialize CameraFrame object and reference count
+ // TODO(XXX): ancillary data for snapshot frame is not being sent for video snapshot
+ // if we are waiting for a snapshot and in video mode...go ahead and send
+ // this frame as a snapshot
+ if( mWaitingForSnapshot && (mCapturedFrames > 0) &&
+ (snapshotFrame || (mCapMode == VIDEO_MODE) || (mCapMode == VIDEO_MODE_HQ ) ))
+ {
+ typeOfFrame = CameraFrame::SNAPSHOT_FRAME;
+ mask = (unsigned int)CameraFrame::SNAPSHOT_FRAME;
+
+ // video snapshot gets ancillary data and wb info from last snapshot frame
+ mCaptureAncillaryData = ancillaryData;
+ mWhiteBalanceData = NULL;
+ extraData = getExtradata(pBuffHeader->pPlatformPrivate,
+ (OMX_EXTRADATATYPE) OMX_WhiteBalance);
+ if ( NULL != extraData )
+ {
+ mWhiteBalanceData = (OMX_TI_WHITEBALANCERESULTTYPE*) extraData->data;
+ }
+ }
+ else
+ {
+ typeOfFrame = CameraFrame::PREVIEW_FRAME_SYNC;
+ mask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC;
+ }
+
+ if (mRecording)
+ {
+ mask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC;
+ mFramesWithEncoder++;
+ }
+
+ //CAMHAL_LOGV("FBD pBuffer = 0x%x", pBuffHeader->pBuffer);
+
+ if( mWaitingForSnapshot )
+ {
+ if ( !mBracketingEnabled &&
+ ((HIGH_SPEED == mCapMode) ||
+ (VIDEO_MODE == mCapMode) ||
+ (VIDEO_MODE_HQ == mCapMode)) )
+ {
+ notifyShutterSubscribers();
+ }
+ }
+
+ stat = sendCallBacks(cameraFrame, pBuffHeader, mask, pPortParam);
+ mFramesWithDisplay++;
+
+ mFramesWithDucati--;
+
+#ifdef CAMERAHAL_DEBUG
+ {
+ android::AutoMutex locker(mBuffersWithDucatiLock);
+ if(mBuffersWithDucati.indexOfKey((uint32_t)pBuffHeader->pBuffer)<0)
+ {
+ CAMHAL_LOGE("Buffer was never with Ducati!! %p", pBuffHeader->pBuffer);
+ for(unsigned int i=0;i<mBuffersWithDucati.size();i++) CAMHAL_LOGE("0x%x", mBuffersWithDucati.keyAt(i));
+ }
+ mBuffersWithDucati.removeItem((int)pBuffHeader->pBuffer);
+ }
+#endif
+
+ if(mDebugFcs)
+ CAMHAL_LOGEB("C[%d] D[%d] E[%d]", mFramesWithDucati, mFramesWithDisplay, mFramesWithEncoder);
+
+ recalculateFPS();
+
+ createPreviewMetadata(pBuffHeader, metadataResult, pPortParam->mWidth, pPortParam->mHeight);
+ if ( NULL != metadataResult.get() ) {
+ notifyMetadataSubscribers(metadataResult);
+ metadataResult.clear();
+ }
+
+ {
+ android::AutoMutex lock(mFaceDetectionLock);
+ if ( mFDSwitchAlgoPriority ) {
+
+ //Disable region priority and enable face priority for AF
+ setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, false);
+ setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO , true);
+
+ //Disable Region priority and enable Face priority
+ setAlgoPriority(REGION_PRIORITY, EXPOSURE_ALGO, false);
+ setAlgoPriority(FACE_PRIORITY, EXPOSURE_ALGO, true);
+ mFDSwitchAlgoPriority = false;
+ }
+ }
+
+ sniffDccFileDataSave(pBuffHeader);
+
+ stat |= advanceZoom();
+
+ // On the fly update to 3A settings not working
+ // Do not update 3A here if we are in the middle of a capture
+ // or in the middle of transitioning to it
+ if( mPending3Asettings &&
+ ( (nextState & CAPTURE_ACTIVE) == 0 ) &&
+ ( (state & CAPTURE_ACTIVE) == 0 ) ) {
+ apply3Asettings(mParameters3A);
+ }
+
+ }
+ else if( pBuffHeader->nOutputPortIndex == OMX_CAMERA_PORT_VIDEO_OUT_MEASUREMENT )
+ {
+ typeOfFrame = CameraFrame::FRAME_DATA_SYNC;
+ mask = (unsigned int)CameraFrame::FRAME_DATA_SYNC;
+
+ stat = sendCallBacks(cameraFrame, pBuffHeader, mask, pPortParam);
+ }
+ else if( pBuffHeader->nOutputPortIndex == OMX_CAMERA_PORT_IMAGE_OUT_IMAGE )
+ {
+ OMX_COLOR_FORMATTYPE pixFormat;
+ const char *valstr = NULL;
+
+ pixFormat = pPortParam->mColorFormat;
+
+ if ( OMX_COLOR_FormatUnused == pixFormat )
+ {
+ typeOfFrame = CameraFrame::IMAGE_FRAME;
+ mask = (unsigned int) CameraFrame::IMAGE_FRAME;
+ } else if ( pixFormat == OMX_COLOR_FormatCbYCrY &&
+ ((mPictureFormatFromClient &&
+ !strcmp(mPictureFormatFromClient,
+ android::CameraParameters::PIXEL_FORMAT_JPEG)) ||
+ !mPictureFormatFromClient) ) {
+ // signals to callbacks that this needs to be coverted to jpeg
+ // before returning to framework
+ typeOfFrame = CameraFrame::IMAGE_FRAME;
+ mask = (unsigned int) CameraFrame::IMAGE_FRAME;
+ cameraFrame.mQuirks |= CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG;
+ cameraFrame.mQuirks |= CameraFrame::FORMAT_YUV422I_UYVY;
+
+ // populate exif data and pass to subscribers via quirk
+ // subscriber is in charge of freeing exif data
+ ExifElementsTable* exif = new ExifElementsTable();
+ setupEXIF_libjpeg(exif, mCaptureAncillaryData, mWhiteBalanceData);
+ cameraFrame.mQuirks |= CameraFrame::HAS_EXIF_DATA;
+ cameraFrame.mCookie2 = (void*) exif;
+ } else {
+ typeOfFrame = CameraFrame::RAW_FRAME;
+ mask = (unsigned int) CameraFrame::RAW_FRAME;
+ }
+
+ pPortParam->mImageType = typeOfFrame;
+
+ if((mCapturedFrames>0) && !mCaptureSignalled)
+ {
+ mCaptureSignalled = true;
+ mCaptureSem.Signal();
+ }
+
+ if( ( CAPTURE_ACTIVE & state ) != CAPTURE_ACTIVE )
+ {
+ goto EXIT;
+ }
+
+ {
+ android::AutoMutex lock(mBracketingLock);
+ if ( mBracketingEnabled )
+ {
+ doBracketing(pBuffHeader, typeOfFrame);
+ return eError;
+ }
+ }
+
+ if (mZoomBracketingEnabled) {
+ doZoom(mZoomBracketingValues[mCurrentZoomBracketing]);
+ CAMHAL_LOGDB("Current Zoom Bracketing: %d", mZoomBracketingValues[mCurrentZoomBracketing]);
+ mCurrentZoomBracketing++;
+ if (mCurrentZoomBracketing == ARRAY_SIZE(mZoomBracketingValues)) {
+ mZoomBracketingEnabled = false;
+ }
+ }
+
+ if ( 1 > mCapturedFrames )
+ {
+ goto EXIT;
+ }
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ if ( NULL != mSharedAllocator ) {
+ cameraFrame.mMetaData = new CameraMetadataResult(getMetaData(pBuffHeader->pPlatformPrivate, mSharedAllocator));
+ }
+#endif
+
+ CAMHAL_LOGDB("Captured Frames: %d", mCapturedFrames);
+
+ mCapturedFrames--;
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ if (mYuvCapture) {
+ struct timeval timeStampUsec;
+ gettimeofday(&timeStampUsec, NULL);
+
+ time_t saveTime;
+ time(&saveTime);
+ const struct tm * const timeStamp = gmtime(&saveTime);
+
+ char filename[256];
+ snprintf(filename,256, "%s/yuv_%d_%d_%d_%lu.yuv",
+ kYuvImagesOutputDirPath,
+ timeStamp->tm_hour,
+ timeStamp->tm_min,
+ timeStamp->tm_sec,
+ timeStampUsec.tv_usec);
+
+ const status_t saveBufferStatus = saveBufferToFile(((CameraBuffer*)pBuffHeader->pAppPrivate)->mapped,
+ pBuffHeader->nFilledLen, filename);
+
+ if (saveBufferStatus != OK) {
+ CAMHAL_LOGE("ERROR: %d, while saving yuv!", saveBufferStatus);
+ } else {
+ CAMHAL_LOGD("yuv_%d_%d_%d_%lu.yuv successfully saved in %s",
+ timeStamp->tm_hour,
+ timeStamp->tm_min,
+ timeStamp->tm_sec,
+ timeStampUsec.tv_usec,
+ kYuvImagesOutputDirPath);
+ }
+ }
+#endif
+
+ stat = sendCallBacks(cameraFrame, pBuffHeader, mask, pPortParam);
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ if ( NULL != cameraFrame.mMetaData.get() ) {
+ cameraFrame.mMetaData.clear();
+ }
+#endif
+
+ }
+ else if (pBuffHeader->nOutputPortIndex == OMX_CAMERA_PORT_VIDEO_OUT_VIDEO) {
+ typeOfFrame = CameraFrame::RAW_FRAME;
+ pPortParam->mImageType = typeOfFrame;
+ {
+ android::AutoMutex lock(mLock);
+ if( ( CAPTURE_ACTIVE & state ) != CAPTURE_ACTIVE ) {
+ goto EXIT;
+ }
+ }
+
+ CAMHAL_LOGD("RAW buffer done on video port, length = %d", pBuffHeader->nFilledLen);
+
+ mask = (unsigned int) CameraFrame::RAW_FRAME;
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ if ( mRawCapture ) {
+ struct timeval timeStampUsec;
+ gettimeofday(&timeStampUsec, NULL);
+
+ time_t saveTime;
+ time(&saveTime);
+ const struct tm * const timeStamp = gmtime(&saveTime);
+
+ char filename[256];
+ snprintf(filename,256, "%s/raw_%d_%d_%d_%lu.raw",
+ kRawImagesOutputDirPath,
+ timeStamp->tm_hour,
+ timeStamp->tm_min,
+ timeStamp->tm_sec,
+ timeStampUsec.tv_usec);
+
+ const status_t saveBufferStatus = saveBufferToFile( ((CameraBuffer*)pBuffHeader->pAppPrivate)->mapped,
+ pBuffHeader->nFilledLen, filename);
+
+ if (saveBufferStatus != OK) {
+ CAMHAL_LOGE("ERROR: %d , while saving raw!", saveBufferStatus);
+ } else {
+ CAMHAL_LOGD("raw_%d_%d_%d_%lu.raw successfully saved in %s",
+ timeStamp->tm_hour,
+ timeStamp->tm_min,
+ timeStamp->tm_sec,
+ timeStampUsec.tv_usec,
+ kRawImagesOutputDirPath);
+ stat = sendCallBacks(cameraFrame, pBuffHeader, mask, pPortParam);
+ }
+ }
+#endif
+ } else {
+ CAMHAL_LOGEA("Frame received for non-(preview/capture/measure) port. This is yet to be supported");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR != stat )
+ {
+ CameraBuffer *camera_buffer;
+
+ camera_buffer = (CameraBuffer *)pBuffHeader->pAppPrivate;
+
+ CAMHAL_LOGDB("sendFrameToSubscribers error: %d", stat);
+ returnFrame(camera_buffer, typeOfFrame);
+ }
+
+ return eError;
+
+ EXIT:
+
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, stat, eError);
+
+ if ( NO_ERROR != stat )
+ {
+ if ( NULL != mErrorNotifier )
+ {
+ mErrorNotifier->errorNotify(CAMERA_ERROR_UNKNOWN);
+ }
+ }
+
+ return eError;
+}
+
+status_t OMXCameraAdapter::recalculateFPS()
+{
+ float currentFPS;
+
+ {
+ android::AutoMutex lock(mFrameCountMutex);
+ mFrameCount++;
+ if (mFrameCount == 1) {
+ mFirstFrameCondition.broadcast();
+ }
+ }
+
+ if ( ( mFrameCount % FPS_PERIOD ) == 0 )
+ {
+ nsecs_t now = systemTime();
+ nsecs_t diff = now - mLastFPSTime;
+ currentFPS = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
+ mLastFPSTime = now;
+ mLastFrameCount = mFrameCount;
+
+ if ( 1 == mIter )
+ {
+ mFPS = currentFPS;
+ }
+ else
+ {
+ //cumulative moving average
+ mFPS = mLastFPS + (currentFPS - mLastFPS)/mIter;
+ }
+
+ mLastFPS = mFPS;
+ mIter++;
+ }
+
+ return NO_ERROR;
+}
+
+status_t OMXCameraAdapter::sendCallBacks(CameraFrame frame, OMX_IN OMX_BUFFERHEADERTYPE *pBuffHeader, unsigned int mask, OMXCameraPortParameters *port)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == port)
+ {
+ CAMHAL_LOGEA("Invalid portParam");
+ return -EINVAL;
+ }
+
+ if ( NULL == pBuffHeader )
+ {
+ CAMHAL_LOGEA("Invalid Buffer header");
+ return -EINVAL;
+ }
+
+ android::AutoMutex lock(mSubscriberLock);
+
+ //frame.mFrameType = typeOfFrame;
+ frame.mFrameMask = mask;
+ frame.mBuffer = (CameraBuffer *)pBuffHeader->pAppPrivate;
+ frame.mLength = pBuffHeader->nFilledLen;
+ frame.mAlignment = port->mStride;
+ frame.mOffset = pBuffHeader->nOffset;
+ frame.mWidth = port->mWidth;
+ frame.mHeight = port->mHeight;
+ frame.mYuv[0] = NULL;
+ frame.mYuv[1] = NULL;
+
+ if ( onlyOnce && mRecording )
+ {
+ mTimeSourceDelta = (pBuffHeader->nTimeStamp * 1000) - systemTime(SYSTEM_TIME_MONOTONIC);
+ onlyOnce = false;
+ }
+
+ frame.mTimestamp = (pBuffHeader->nTimeStamp * 1000) - mTimeSourceDelta;
+
+ ret = setInitFrameRefCount(frame.mBuffer, mask);
+
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
+ } else {
+ ret = sendFrameToSubscribers(&frame);
+ }
+
+ CAMHAL_LOGVB("B 0x%x T %llu", frame.mBuffer, pBuffHeader->nTimeStamp);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+bool OMXCameraAdapter::CommandHandler::Handler()
+{
+ Utils::Message msg;
+ volatile int forever = 1;
+ status_t stat;
+ ErrorNotifier *errorNotify = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ while ( forever )
+ {
+ stat = NO_ERROR;
+ CAMHAL_LOGDA("Handler: waiting for messsage...");
+ Utils::MessageQueue::waitForMsg(&mCommandMsgQ, NULL, NULL, -1);
+ {
+ android::AutoMutex lock(mLock);
+ mCommandMsgQ.get(&msg);
+ }
+ CAMHAL_LOGDB("msg.command = %d", msg.command);
+ switch ( msg.command ) {
+ case CommandHandler::CAMERA_START_IMAGE_CAPTURE:
+ {
+ OMXCameraAdapter::CachedCaptureParameters* cap_params =
+ static_cast<OMXCameraAdapter::CachedCaptureParameters*>(msg.arg2);
+ stat = mCameraAdapter->startImageCapture(false, cap_params);
+ delete cap_params;
+ break;
+ }
+ case CommandHandler::CAMERA_PERFORM_AUTOFOCUS:
+ {
+ stat = mCameraAdapter->doAutoFocus();
+ break;
+ }
+ case CommandHandler::COMMAND_EXIT:
+ {
+ CAMHAL_LOGDA("Exiting command handler");
+ forever = 0;
+ break;
+ }
+ case CommandHandler::CAMERA_SWITCH_TO_EXECUTING:
+ {
+ stat = mCameraAdapter->doSwitchToExecuting();
+ break;
+ }
+ case CommandHandler::CAMERA_START_REPROCESS:
+ {
+ OMXCameraAdapter::CachedCaptureParameters* cap_params =
+ static_cast<OMXCameraAdapter::CachedCaptureParameters*>(msg.arg2);
+ stat = mCameraAdapter->startReprocess();
+ stat = mCameraAdapter->startImageCapture(false, cap_params);
+ delete cap_params;
+ break;
+ }
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return false;
+}
+
+bool OMXCameraAdapter::OMXCallbackHandler::Handler()
+{
+ Utils::Message msg;
+ volatile int forever = 1;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ while(forever){
+ Utils::MessageQueue::waitForMsg(&mCommandMsgQ, NULL, NULL, -1);
+ {
+ android::AutoMutex lock(mLock);
+ mCommandMsgQ.get(&msg);
+ mIsProcessed = false;
+ }
+
+ switch ( msg.command ) {
+ case OMXCallbackHandler::CAMERA_FILL_BUFFER_DONE:
+ {
+ ret = mCameraAdapter->OMXCameraAdapterFillBufferDone(( OMX_HANDLETYPE ) msg.arg1,
+ ( OMX_BUFFERHEADERTYPE *) msg.arg2);
+ break;
+ }
+ case OMXCallbackHandler::CAMERA_FOCUS_STATUS:
+ {
+ mCameraAdapter->handleFocusCallback();
+ break;
+ }
+ case CommandHandler::COMMAND_EXIT:
+ {
+ CAMHAL_LOGDA("Exiting OMX callback handler");
+ forever = 0;
+ break;
+ }
+ }
+
+ {
+ android::AutoMutex locker(mLock);
+ CAMHAL_UNUSED(locker);
+
+ mIsProcessed = mCommandMsgQ.isEmpty();
+ if ( mIsProcessed )
+ mCondition.signal();
+ }
+ }
+
+ // force the condition to wake
+ {
+ android::AutoMutex locker(mLock);
+ CAMHAL_UNUSED(locker);
+
+ mIsProcessed = true;
+ mCondition.signal();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return false;
+}
+
+void OMXCameraAdapter::OMXCallbackHandler::flush()
+{
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex locker(mLock);
+ CAMHAL_UNUSED(locker);
+
+ if ( mIsProcessed )
+ return;
+
+ mCondition.wait(mLock);
+}
+
+status_t OMXCameraAdapter::setExtraData(bool enable, OMX_U32 nPortIndex, OMX_EXT_EXTRADATATYPE eType) {
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXTRADATATYPE extraDataControl;
+
+ LOG_FUNCTION_NAME;
+
+ if ( ( OMX_StateInvalid == mComponentState ) ||
+ ( NULL == mCameraAdapterParameters.mHandleComp ) ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return -EINVAL;
+ }
+
+ OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE);
+
+ extraDataControl.nPortIndex = nPortIndex;
+ extraDataControl.eExtraDataType = eType;
+#ifdef CAMERAHAL_TUNA
+ extraDataControl.eCameraView = OMX_2D;
+#endif
+
+ if (enable) {
+ extraDataControl.bEnable = OMX_TRUE;
+ } else {
+ extraDataControl.bEnable = OMX_FALSE;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_IndexConfigOtherExtraDataControl,
+ &extraDataControl);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+OMX_OTHER_EXTRADATATYPE *OMXCameraAdapter::getExtradata(const OMX_PTR ptrPrivate, OMX_EXTRADATATYPE type) const
+{
+ if ( NULL != ptrPrivate ) {
+ const OMX_TI_PLATFORMPRIVATE *platformPrivate = (const OMX_TI_PLATFORMPRIVATE *) ptrPrivate;
+
+ CAMHAL_LOGVB("Size = %d, sizeof = %d, pAuxBuf = 0x%x, pAuxBufSize= %d, pMetaDataBufer = 0x%x, nMetaDataSize = %d",
+ platformPrivate->nSize,
+ sizeof(OMX_TI_PLATFORMPRIVATE),
+ platformPrivate->pAuxBuf1,
+ platformPrivate->pAuxBufSize1,
+ platformPrivate->pMetaDataBuffer,
+ platformPrivate->nMetaDataSize);
+ if ( sizeof(OMX_TI_PLATFORMPRIVATE) == platformPrivate->nSize ) {
+ if ( 0 < platformPrivate->nMetaDataSize ) {
+ OMX_U32 remainingSize = platformPrivate->nMetaDataSize;
+ OMX_OTHER_EXTRADATATYPE *extraData = (OMX_OTHER_EXTRADATATYPE *) platformPrivate->pMetaDataBuffer;
+ if ( NULL != extraData ) {
+ while ( extraData->eType && extraData->nDataSize && extraData->data &&
+ (remainingSize >= extraData->nSize)) {
+ if ( type == extraData->eType ) {
+ return extraData;
+ }
+ remainingSize -= extraData->nSize;
+ extraData = (OMX_OTHER_EXTRADATATYPE*) ((char*)extraData + extraData->nSize);
+ }
+ } else {
+ CAMHAL_LOGEB("OMX_TI_PLATFORMPRIVATE pMetaDataBuffer is NULL");
+ }
+ } else {
+ CAMHAL_LOGEB("OMX_TI_PLATFORMPRIVATE nMetaDataSize is size is %d",
+ ( unsigned int ) platformPrivate->nMetaDataSize);
+ }
+ } else {
+ CAMHAL_LOGEB("OMX_TI_PLATFORMPRIVATE size mismatch: expected = %d, received = %d",
+ ( unsigned int ) sizeof(OMX_TI_PLATFORMPRIVATE),
+ ( unsigned int ) platformPrivate->nSize);
+ }
+ } else {
+ CAMHAL_LOGEA("Invalid OMX_TI_PLATFORMPRIVATE");
+ }
+
+ // Required extradata type wasn't found
+ return NULL;
+}
+
+OMXCameraAdapter::CachedCaptureParameters* OMXCameraAdapter::cacheCaptureParameters() {
+ CachedCaptureParameters* params = new CachedCaptureParameters();
+
+ params->mPendingCaptureSettings = mPendingCaptureSettings;
+ params->mPictureRotation = mPictureRotation;
+ memcpy(params->mExposureBracketingValues,
+ mExposureBracketingValues,
+ sizeof(mExposureBracketingValues));
+ memcpy(params->mExposureGainBracketingValues,
+ mExposureGainBracketingValues,
+ sizeof(mExposureGainBracketingValues));
+ memcpy(params->mExposureGainBracketingModes,
+ mExposureGainBracketingModes,
+ sizeof(mExposureGainBracketingModes));
+ params->mExposureBracketingValidEntries = mExposureBracketingValidEntries;
+ params->mExposureBracketMode = mExposureBracketMode;
+ params->mBurstFrames = mBurstFrames;
+ params->mFlushShotConfigQueue = mFlushShotConfigQueue;
+
+ return params;
+}
+
+OMXCameraAdapter::OMXCameraAdapter(size_t sensor_index)
+{
+ LOG_FUNCTION_NAME;
+
+ mOmxInitialized = false;
+ mComponentState = OMX_StateInvalid;
+ mSensorIndex = sensor_index;
+ mPictureRotation = 0;
+ // Initial values
+ mTimeSourceDelta = 0;
+ onlyOnce = true;
+ mDccData.pData = NULL;
+
+ mInitSem.Create(0);
+ mFlushSem.Create(0);
+ mUsePreviewDataSem.Create(0);
+ mUsePreviewSem.Create(0);
+ mUseCaptureSem.Create(0);
+ mUseReprocessSem.Create(0);
+ mStartPreviewSem.Create(0);
+ mStopPreviewSem.Create(0);
+ mStartCaptureSem.Create(0);
+ mStopCaptureSem.Create(0);
+ mStopReprocSem.Create(0);
+ mSwitchToLoadedSem.Create(0);
+ mCaptureSem.Create(0);
+
+ mSwitchToExecSem.Create(0);
+
+ mCameraAdapterParameters.mHandleComp = 0;
+
+ mUserSetExpLock = OMX_FALSE;
+ mUserSetWbLock = OMX_FALSE;
+
+ mFramesWithDucati = 0;
+ mFramesWithDisplay = 0;
+ mFramesWithEncoder = 0;
+
+#ifdef CAMERAHAL_OMX_PROFILING
+
+ mDebugProfile = 0;
+
+#endif
+
+ mPreviewPortInitialized = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+OMXCameraAdapter::~OMXCameraAdapter()
+{
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(gAdapterLock);
+
+ // return to OMX Loaded state
+ switchToLoaded();
+
+ if ( mOmxInitialized ) {
+ saveDccFileDataSave();
+
+ closeDccFileDataSave();
+ // deinit the OMX
+ if ( mComponentState == OMX_StateLoaded || mComponentState == OMX_StateInvalid ) {
+ // free the handle for the Camera component
+ if ( mCameraAdapterParameters.mHandleComp ) {
+ OMX_FreeHandle(mCameraAdapterParameters.mHandleComp);
+ mCameraAdapterParameters.mHandleComp = NULL;
+ }
+ }
+
+ OMX_Deinit();
+ mOmxInitialized = false;
+ }
+
+ //Remove any unhandled events
+ if ( !mEventSignalQ.isEmpty() )
+ {
+ for (unsigned int i = 0 ; i < mEventSignalQ.size() ; i++ )
+ {
+ Utils::Message *msg = mEventSignalQ.itemAt(i);
+ //remove from queue and free msg
+ if ( NULL != msg )
+ {
+ Utils::Semaphore *sem = (Utils::Semaphore*) msg->arg3;
+ sem->Signal();
+ free(msg);
+
+ }
+ }
+ mEventSignalQ.clear();
+ }
+
+ //Exit and free ref to command handling thread
+ if ( NULL != mCommandHandler.get() )
+ {
+ Utils::Message msg;
+ msg.command = CommandHandler::COMMAND_EXIT;
+ msg.arg1 = mErrorNotifier;
+ mCommandHandler->clearCommandQ();
+ mCommandHandler->put(&msg);
+ mCommandHandler->requestExitAndWait();
+ mCommandHandler.clear();
+ }
+
+ //Exit and free ref to callback handling thread
+ if ( NULL != mOMXCallbackHandler.get() )
+ {
+ Utils::Message msg;
+ msg.command = OMXCallbackHandler::COMMAND_EXIT;
+ //Clear all messages pending first
+ mOMXCallbackHandler->clearCommandQ();
+ mOMXCallbackHandler->put(&msg);
+ mOMXCallbackHandler->requestExitAndWait();
+ mOMXCallbackHandler.clear();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+extern "C" CameraAdapter* OMXCameraAdapter_Factory(size_t sensor_index)
+{
+ CameraAdapter *adapter = NULL;
+ android::AutoMutex lock(gAdapterLock);
+
+ LOG_FUNCTION_NAME;
+
+ adapter = new OMXCameraAdapter(sensor_index);
+ if ( adapter ) {
+ CAMHAL_LOGDB("New OMX Camera adapter instance created for sensor %d",sensor_index);
+ } else {
+ CAMHAL_LOGEA("OMX Camera adapter create failed for sensor index = %d!",sensor_index);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return adapter;
+}
+
+OMX_ERRORTYPE OMXCameraAdapter::OMXCameraGetHandle(OMX_HANDLETYPE *handle, OMX_PTR pAppData,
+ const OMX_CALLBACKTYPE & callbacks)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorUndefined;
+
+ for ( int i = 0; i < 5; ++i ) {
+ if ( i > 0 ) {
+ // sleep for 100 ms before next attempt
+ usleep(100000);
+ }
+
+ // setup key parameters to send to Ducati during init
+ OMX_CALLBACKTYPE oCallbacks = callbacks;
+
+ // get handle
+ eError = OMX_GetHandle(handle, (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA", pAppData, &oCallbacks);
+ if ( eError == OMX_ErrorNone ) {
+ return OMX_ErrorNone;
+ }
+
+ CAMHAL_LOGEB("OMX_GetHandle() failed, error: 0x%x", eError);
+ }
+
+ *handle = 0;
+ return eError;
+}
+
+
+class CapabilitiesHandler
+{
+public:
+ CapabilitiesHandler()
+ {
+ mComponent = 0;
+ }
+
+ const OMX_HANDLETYPE & component() const
+ {
+ return mComponent;
+ }
+
+ OMX_HANDLETYPE & componentRef()
+ {
+ return mComponent;
+ }
+
+ status_t fetchCapabiltiesForMode(OMX_CAMOPERATINGMODETYPE mode,
+ int sensorId,
+ CameraProperties::Properties * properties)
+ {
+ OMX_CONFIG_CAMOPERATINGMODETYPE camMode;
+
+ OMX_INIT_STRUCT_PTR (&camMode, OMX_CONFIG_CAMOPERATINGMODETYPE);
+ camMode.eCamOperatingMode = mode;
+
+ OMX_ERRORTYPE eError = OMX_SetParameter(component(),
+ ( OMX_INDEXTYPE ) OMX_IndexCameraOperatingMode,
+ &camMode);
+
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGE("Error while configuring camera mode in CameraAdapter_Capabilities 0x%x", eError);
+ return BAD_VALUE;
+ }
+
+ // get and fill capabilities
+ OMXCameraAdapter::getCaps(sensorId, properties, component());
+
+ return NO_ERROR;
+ }
+
+ status_t fetchCapabilitiesForSensor(int sensorId,
+ CameraProperties::Properties * properties)
+ {
+ // sensor select
+ OMX_CONFIG_SENSORSELECTTYPE sensorSelect;
+ OMX_INIT_STRUCT_PTR (&sensorSelect, OMX_CONFIG_SENSORSELECTTYPE);
+ sensorSelect.eSensor = (OMX_SENSORSELECT)sensorId;
+
+ CAMHAL_LOGD("Selecting sensor %d...", sensorId);
+ const OMX_ERRORTYPE sensorSelectError = OMX_SetConfig(component(),
+ (OMX_INDEXTYPE)OMX_TI_IndexConfigSensorSelect, &sensorSelect);
+ CAMHAL_LOGD("Selecting sensor %d... DONE", sensorId);
+
+ if ( sensorSelectError != OMX_ErrorNone ) {
+ CAMHAL_LOGD("Max supported sensor number reached: %d", sensorId);
+ return BAD_VALUE;
+ }
+
+ status_t err = NO_ERROR;
+ if ( sensorId == 2 ) {
+ CAMHAL_LOGD("Camera mode: STEREO");
+ properties->setMode(MODE_STEREO);
+ err = fetchCapabiltiesForMode(OMX_CaptureStereoImageCapture,
+ sensorId,
+ properties);
+ } else {
+ CAMHAL_LOGD("Camera MONO");
+
+ CAMHAL_LOGD("Camera mode: HQ ");
+ properties->setMode(MODE_HIGH_QUALITY);
+ err = fetchCapabiltiesForMode(OMX_CaptureImageProfileBase,
+ sensorId,
+ properties);
+ if ( NO_ERROR != err ) {
+ return err;
+ }
+
+ CAMHAL_LOGD("Camera mode: VIDEO ");
+ properties->setMode(MODE_VIDEO);
+ err = fetchCapabiltiesForMode(OMX_CaptureVideo,
+ sensorId,
+ properties);
+ if ( NO_ERROR != err ) {
+ return err;
+ }
+
+ CAMHAL_LOGD("Camera mode: ZSL ");
+ properties->setMode(MODE_ZEROSHUTTERLAG);
+ err = fetchCapabiltiesForMode(OMX_TI_CaptureImageProfileZeroShutterLag,
+ sensorId,
+ properties);
+ if ( NO_ERROR != err ) {
+ return err;
+ }
+
+ CAMHAL_LOGD("Camera mode: HS ");
+ properties->setMode(MODE_HIGH_SPEED);
+ err = fetchCapabiltiesForMode(OMX_CaptureImageHighSpeedTemporalBracketing,
+ sensorId,
+ properties);
+ if ( NO_ERROR != err ) {
+ return err;
+ }
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ CAMHAL_LOGD("Camera mode: CPCAM ");
+ properties->setMode(MODE_CPCAM);
+ err = fetchCapabiltiesForMode(OMX_TI_CPCam,
+ sensorId,
+ properties);
+ if ( NO_ERROR != err ) {
+ return err;
+ }
+#endif
+
+#ifdef CAMERAHAL_OMAP5_CAPTURE_MODES
+
+ CAMHAL_LOGD("Camera mode: VIDEO HQ ");
+ properties->setMode(MODE_VIDEO_HIGH_QUALITY);
+ err = fetchCapabiltiesForMode(OMX_CaptureHighQualityVideo,
+ sensorId,
+ properties);
+ if ( NO_ERROR != err ) {
+ return err;
+ }
+
+#endif
+
+ }
+
+ return err;
+ }
+
+private:
+ OMX_HANDLETYPE mComponent;
+ OMX_STATETYPE mState;
+};
+
+extern "C" status_t OMXCameraAdapter_Capabilities(
+ CameraProperties::Properties * const properties_array,
+ const int starting_camera, const int max_camera, int & supportedCameras)
+{
+ LOG_FUNCTION_NAME;
+
+ supportedCameras = 0;
+
+ int num_cameras_supported = 0;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ android::AutoMutex lock(gAdapterLock);
+
+ if (!properties_array) {
+ CAMHAL_LOGEB("invalid param: properties = 0x%p", properties_array);
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ eError = OMX_Init();
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("Error OMX_Init -0x%x", eError);
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+
+ CapabilitiesHandler handler;
+ OMX_CALLBACKTYPE callbacks;
+ callbacks.EventHandler = 0;
+ callbacks.EmptyBufferDone = 0;
+ callbacks.FillBufferDone = 0;
+
+ eError = OMXCameraAdapter::OMXCameraGetHandle(&handler.componentRef(), &handler, callbacks);
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_GetHandle -0x%x", eError);
+ goto EXIT;
+ }
+
+#ifndef USES_LEGACY_DOMX_DCC
+ DCCHandler dcc_handler;
+ dcc_handler.loadDCC(handler.componentRef());
+#endif
+
+ // Continue selecting sensor and then querying OMX Camera for it's capabilities
+ // When sensor select returns an error, we know to break and stop
+ while (eError == OMX_ErrorNone &&
+ (starting_camera + num_cameras_supported) < max_camera) {
+
+ const int sensorId = num_cameras_supported;
+ CameraProperties::Properties * properties = properties_array + starting_camera + sensorId;
+ const status_t err = handler.fetchCapabilitiesForSensor(sensorId, properties);
+
+ if ( err != NO_ERROR )
+ break;
+
+ num_cameras_supported++;
+ CAMHAL_LOGEB("Number of OMX Cameras detected = %d \n",num_cameras_supported);
+ }
+
+ // clean up
+ if(handler.component()) {
+ CAMHAL_LOGD("Freeing the component...");
+ OMX_FreeHandle(handler.component());
+ CAMHAL_LOGD("Freeing the component... DONE");
+ handler.componentRef() = NULL;
+ }
+
+ EXIT:
+ CAMHAL_LOGD("Deinit...");
+ OMX_Deinit();
+ CAMHAL_LOGD("Deinit... DONE");
+
+ if ( eError != OMX_ErrorNone )
+ {
+ CAMHAL_LOGE("Error: 0x%x", eError);
+ LOG_FUNCTION_NAME_EXIT;
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+
+ supportedCameras = num_cameras_supported;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+} // namespace Camera
+} // namespace Ti
+
+
+/*--------------------Camera Adapter Class ENDS here-----------------------------*/
+
diff --git a/camera/OMXCameraAdapter/OMXCapabilities.cpp b/camera/OMXCameraAdapter/OMXCapabilities.cpp
new file mode 100644
index 0000000..72a2380
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXCapabilities.cpp
@@ -0,0 +1,2513 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXCap.cpp
+*
+* This file implements the OMX Capabilities feature.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+#include "TICameraParameters.h"
+
+namespace Ti {
+namespace Camera {
+
+/************************************
+ * global constants and variables
+ *************************************/
+
+#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
+
+static const char PARAM_SEP[] = ",";
+static const uint32_t VFR_OFFSET = 8;
+static const char FPS_STR_MAX_LEN = 10;
+
+static const unsigned int MANUAL_EXPOSURE_STEP = 1;
+static const unsigned int MANUAL_GAIN_ISO_MIN = 100;
+static const unsigned int MANUAL_GAIN_ISO_STEP = 100;
+
+const int OMXCameraAdapter::SENSORID_IMX060 = 300;
+const int OMXCameraAdapter::SENSORID_OV5650 = 301;
+const int OMXCameraAdapter::SENSORID_OV5640 = 302;
+const int OMXCameraAdapter::SENSORID_OV14825 = 304;
+const int OMXCameraAdapter::SENSORID_S5K4E1GA = 305;
+const int OMXCameraAdapter::SENSORID_S5K6A1GX03 = 306;
+const int OMXCameraAdapter::SENSORID_OV8830 = 310;
+const int OMXCameraAdapter::SENSORID_OV2722 = 311;
+const int OMXCameraAdapter::SENSORID_OV9726 = 312;
+
+
+const int OMXCameraAdapter::FPS_MIN = 5;
+const int OMXCameraAdapter::FPS_MAX = 30;
+const int OMXCameraAdapter::FPS_MAX_EXTENDED = 60;
+
+inline static int androidFromDucatiFrameRate(OMX_U32 frameRate) {
+ return (frameRate >> VFR_OFFSET) * CameraHal::VFR_SCALE;
+}
+
+/**** look up tables to translate OMX Caps to Parameter ****/
+
+const CapResolution OMXCameraAdapter::mImageCapRes [] = {
+ { 4416, 3312, "4416x3312" },
+ { 4032, 3024, "4032x3024" },
+ { 4000, 3000, "4000x3000" },
+ { 3648, 2736, "3648x2736" },
+ { 3264, 2448, "3264x2448" },
+ { 2608, 1960, "2608x1960" },
+ { 2592, 1944, "2592x1944" },
+ { 2592, 1728, "2592x1728" },
+ { 2592, 1458, "2592x1458" },
+ { 2400, 1350, "2400x1350" },
+ { 2304, 1296, "2304x1296" },
+ { 2240, 1344, "2240x1344" },
+ { 2160, 1440, "2160x1440" },
+ { 2112, 1728, "2112x1728" },
+ { 2112, 1188, "2112x1188" },
+ { 2048, 1536, "2048x1536" },
+ { 2016, 1512, "2016x1512" },
+ { 2016, 1134, "2016x1134" },
+ { 2000, 1600, "2000x1600" },
+ { 1920, 1080, "1920x1080" },
+ { 1600, 1200, "1600x1200" },
+ { 1600, 900, "1600x900" },
+ { 1536, 864, "1536x864" },
+ { 1408, 792, "1408x792" },
+ { 1344, 756, "1344x756" },
+ { 1280, 1024, "1280x1024" },
+ { 1280, 720, "1280x720" },
+ { 1152, 864, "1152x864" },
+ { 1280, 960, "1280x960" },
+ { 1024, 768, "1024x768" },
+ { 640, 480, "640x480" },
+ { 320, 240, "320x240" },
+};
+
+const CapResolution OMXCameraAdapter::mImageCapResSS [] = {
+ { 4032*2, 3024, "8064x3024" },
+ { 3648*2, 2736, "7296x2736" },
+ { 3264*2, 2448, "6528x2448" },
+ { 2592*2, 1944, "5184x1944" },
+ { 2048*2, 1536, "4096x1536" },
+ { 1600*2, 1200, "3200x1200" },
+ { 1280*2, 960, "2560x960" },
+ { 1280*2, 720, "2560x720" },
+ { 1024*2, 768, "2048x768" },
+ { 640*2, 480, "1280x480" },
+ { 320*2, 240, "640x240" },
+};
+
+const CapResolution OMXCameraAdapter::mImageCapResTB [] = {
+ { 4032, 3024*2, "4032x6048" },
+ { 3648, 2736*2, "3648x5472" },
+ { 3264, 2448*2, "3264x4896" },
+ { 2592, 1944*2, "2592x3888" },
+ { 2048, 1536*2, "2048x3072" },
+ { 1600, 1200*2, "1600x2400" },
+ { 1280, 960*2, "1280x1920" },
+ { 1280, 720*2, "1280x1440" },
+ { 1024, 768*2, "1024x1536" },
+ { 640, 480*2, "640x960" },
+ { 320, 240*2, "320x480" },
+};
+
+const CapResolution OMXCameraAdapter::mPreviewRes [] = {
+ { 1920, 1080, "1920x1080" },
+ { 1280, 720, "1280x720" },
+ { 960, 720, "960x720" },
+ { 800, 480, "800x480" },
+ { 720, 576, "720x576" },
+ { 720, 480, "720x480" },
+ { 768, 576, "768x576" },
+ { 640, 480, "640x480" },
+ { 320, 240, "320x240" },
+ { 352, 288, "352x288" },
+ { 240, 160, "240x160" },
+ { 176, 144, "176x144" },
+ { 160, 120, "160x120" },
+ { 128, 96, "128x96" },
+};
+
+const CapResolution OMXCameraAdapter::mPreviewPortraitRes [] = {
+ //Portrait resolutions
+ { 1088, 1920, "1088x1920" },
+ { 720, 1280, "720x1280" },
+ { 480, 800, "480x800" },
+ { 576, 720, "576x720" },
+ { 576, 768, "576x768" },
+ { 480, 720, "480x720" },
+ { 480, 640, "480x640" },
+ { 288, 352, "288x352" },
+ { 240, 320, "240x320" },
+ { 160, 240, "160x240" },
+ { 144, 176, "144x176" },
+ { 120, 160, "120x160"},
+ { 96, 128, "96x128" }
+};
+
+const CapResolution OMXCameraAdapter::mPreviewResSS [] = {
+ { 1920*2, 1080, "3840x1080" },
+ { 1280*2, 720, "2560x720" },
+ { 800*2, 480, "1600x480" },
+ { 720*2, 576, "1440x576" },
+ { 720*2, 480, "1440x480" },
+ { 768*2, 576, "1536x576" },
+ { 640*2, 480, "1280x480" },
+ { 320*2, 240, "640x240" },
+ { 352*2, 288, "704x288" },
+ { 240*2, 160, "480x160" },
+ { 176*2, 144, "352x144" },
+ { 128*2, 96, "256x96" }
+};
+
+const CapResolution OMXCameraAdapter::mPreviewResTB [] = {
+ { 1920, 1080*2, "1920x2160" },
+ { 1280, 720*2, "1280x1440" },
+ { 800, 480*2, "800x960" },
+ { 720, 576*2, "720x1152" },
+ { 720, 480*2, "720x960" },
+ { 768, 576*2, "768x1152" },
+ { 640, 480*2, "640x960" },
+ { 320, 240*2, "320x480" },
+ { 352, 288*2, "352x576" },
+ { 240, 160*2, "240x320" },
+ { 176, 144*2, "176x288" },
+ { 128, 96*2, "128x192" },
+};
+
+const CapResolution OMXCameraAdapter::mThumbRes [] = {
+ { 640, 480, "640x480" },
+ { 160, 120, "160x120" },
+ { 200, 120, "200x120" },
+ { 320, 240, "320x240" },
+ { 512, 384, "512x384" },
+ { 352, 144, "352x144" },
+ { 176, 144, "176x144" },
+ { 96, 96, "96x96" },
+};
+
+const CapPixelformat OMXCameraAdapter::mPixelformats [] = {
+ { OMX_COLOR_FormatCbYCrY, android::CameraParameters::PIXEL_FORMAT_YUV422I },
+ { OMX_COLOR_FormatYUV420SemiPlanar, android::CameraParameters::PIXEL_FORMAT_YUV420SP },
+ { OMX_COLOR_Format16bitRGB565, android::CameraParameters::PIXEL_FORMAT_RGB565 },
+ { OMX_COLOR_FormatYUV420SemiPlanar, android::CameraParameters::PIXEL_FORMAT_YUV420P },
+ { OMX_COLOR_FormatUnused, TICameraParameters::PIXEL_FORMAT_UNUSED },
+ { OMX_COLOR_FormatRawBayer10bit, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB },
+};
+
+const userToOMX_LUT OMXCameraAdapter::mFrameLayout [] = {
+ { TICameraParameters::S3D_NONE, OMX_TI_StereoFrameLayout2D },
+ { TICameraParameters::S3D_TB_FULL, OMX_TI_StereoFrameLayoutTopBottom },
+ { TICameraParameters::S3D_SS_FULL, OMX_TI_StereoFrameLayoutLeftRight },
+ { TICameraParameters::S3D_TB_SUBSAMPLED, OMX_TI_StereoFrameLayoutTopBottomSubsample },
+ { TICameraParameters::S3D_SS_SUBSAMPLED, OMX_TI_StereoFrameLayoutLeftRightSubsample },
+};
+
+const LUTtype OMXCameraAdapter::mLayoutLUT = {
+ ARRAY_SIZE(mFrameLayout),
+ mFrameLayout
+};
+
+const CapCodingFormat OMXCameraAdapter::mImageCodingFormat [] = {
+ { OMX_IMAGE_CodingJPEG, android::CameraParameters::PIXEL_FORMAT_JPEG },
+ { (OMX_IMAGE_CODINGTYPE)OMX_TI_IMAGE_CodingJPS, TICameraParameters::PIXEL_FORMAT_JPS },
+ { (OMX_IMAGE_CODINGTYPE)OMX_TI_IMAGE_CodingMPO, TICameraParameters::PIXEL_FORMAT_MPO },
+};
+
+const CapFramerate OMXCameraAdapter::mFramerates [] = {
+ { 60, "60" },
+ { 30, "30" },
+ { 24, "24" },
+ { 20, "20" },
+ { 15, "15" },
+ { 10, "10" },
+};
+
+const CapZoom OMXCameraAdapter::mZoomStages [] = {
+ { 65536, "100" },
+ { 68157, "104" },
+ { 70124, "107" },
+ { 72745, "111" },
+ { 75366, "115" },
+ { 77988, "119" },
+ { 80609, "123" },
+ { 83231, "127" },
+ { 86508, "132" },
+ { 89784, "137" },
+ { 92406, "141" },
+ { 95683, "146" },
+ { 99615, "152" },
+ { 102892, "157" },
+ { 106168, "162" },
+ { 110100, "168" },
+ { 114033, "174" },
+ { 117965, "180" },
+ { 122552, "187" },
+ { 126484, "193" },
+ { 131072, "200" },
+ { 135660, "207" },
+ { 140247, "214" },
+ { 145490, "222" },
+ { 150733, "230" },
+ { 155976, "238" },
+ { 161219, "246" },
+ { 167117, "255" },
+ { 173015, "264" },
+ { 178913, "273" },
+ { 185467, "283" },
+ { 192020, "293" },
+ { 198574, "303" },
+ { 205783, "314" },
+ { 212992, "325" },
+ { 220201, "336" },
+ { 228065, "348" },
+ { 236585, "361" },
+ { 244449, "373" },
+ { 252969, "386" },
+ { 262144, "400" },
+ { 271319, "414" },
+ { 281149, "429" },
+ { 290980, "444" },
+ { 300810, "459" },
+ { 311951, "476" },
+ { 322437, "492" },
+ { 334234, "510" },
+ { 346030, "528" },
+ { 357827, "546" },
+ { 370934, "566" },
+ { 384041, "586" },
+ { 397148, "606" },
+ { 411566, "628" },
+ { 425984, "650" },
+ { 441057, "673" },
+ { 456131, "696" },
+ { 472515, "721" },
+ { 488899, "746" },
+ { 506593, "773" },
+ { 524288, "800" },
+};
+
+const CapISO OMXCameraAdapter::mISOStages [] = {
+ { 0, "auto" },
+ { 100, "100" },
+ { 200, "200"},
+ { 400, "400" },
+ { 800, "800" },
+ { 1000, "1000" },
+ { 1200, "1200" },
+ { 1600, "1600" },
+};
+
+// mapped values have to match with new_sensor_MSP.h
+const CapU32 OMXCameraAdapter::mSensorNames [] = {
+ { SENSORID_IMX060, "IMX060" },
+ { SENSORID_OV5650, "OV5650" },
+ { SENSORID_OV5640, "OV5640" },
+ { SENSORID_OV14825, "OV14825"},
+ { SENSORID_S5K4E1GA, "S5K4E1GA"},
+ { SENSORID_S5K6A1GX03, "S5K6A1GX03" },
+ { SENSORID_OV8830, "OV8830" },
+ { SENSORID_OV2722, "OV2722" },
+ { SENSORID_OV9726, "OV9726" }
+ // TODO(XXX): need to account for S3D camera later
+};
+
+const userToOMX_LUT OMXCameraAdapter::mAutoConvergence [] = {
+ { TICameraParameters::AUTOCONVERGENCE_MODE_DISABLE, OMX_TI_AutoConvergenceModeDisable },
+ { TICameraParameters::AUTOCONVERGENCE_MODE_FRAME, OMX_TI_AutoConvergenceModeFrame },
+ { TICameraParameters::AUTOCONVERGENCE_MODE_CENTER, OMX_TI_AutoConvergenceModeCenter },
+ { TICameraParameters::AUTOCONVERGENCE_MODE_TOUCH, OMX_TI_AutoConvergenceModeFocusFaceTouch },
+ { TICameraParameters::AUTOCONVERGENCE_MODE_MANUAL, OMX_TI_AutoConvergenceModeManual }
+};
+
+const LUTtype OMXCameraAdapter::mAutoConvergenceLUT = {
+ ARRAY_SIZE(mAutoConvergence),
+ mAutoConvergence
+};
+
+const userToOMX_LUT OMXCameraAdapter::mBracketingModes [] = {
+ { TICameraParameters::TEMP_BRACKETING , OMX_BracketTemporal },
+ { TICameraParameters::EXPOSURE_BRACKETING , OMX_BracketExposureRelativeInEV }
+};
+
+const LUTtype OMXCameraAdapter::mBracketingModesLUT = {
+ ARRAY_SIZE(mBracketingModes),
+ mBracketingModes
+};
+
+// values for supported camera facing direction
+const CapU32 OMXCameraAdapter::mFacing [] = {
+ { OMX_TI_SENFACING_BACK , TICameraParameters::FACING_BACK },
+ { OMX_TI_SENFACING_FRONT, TICameraParameters::FACING_FRONT},
+};
+
+/*****************************************
+ * internal static function declarations
+ *****************************************/
+
+/**** Utility functions to help translate OMX Caps to Parameter ****/
+
+status_t OMXCameraAdapter::encodeImageCodingFormatCap(OMX_IMAGE_CODINGTYPE format,
+ const CapCodingFormat *cap,
+ size_t capCount,
+ char * buffer) {
+
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( ( NULL == buffer ) || ( NULL == cap ) ) {
+ CAMHAL_LOGEA("Invalid input arguments");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret ) {
+ for ( unsigned int i = 0 ; i < capCount ; i++ ) {
+ if ( format == cap[i].imageCodingFormat ) {
+ if (buffer[0] != '\0') {
+ strncat(buffer, PARAM_SEP, ((((int)MAX_PROP_VALUE_LENGTH - 1 - (int)strlen(buffer)) < 0) ? 0 : (MAX_PROP_VALUE_LENGTH - 1 - strlen(buffer))));
+ }
+ strncat(buffer, cap[i].param, ((((int)MAX_PROP_VALUE_LENGTH - 1 - (int)strlen(buffer)) < 0) ? 0 : (MAX_PROP_VALUE_LENGTH - 1 - strlen(buffer))));
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodePixelformatCap(OMX_COLOR_FORMATTYPE format,
+ const CapPixelformat *cap,
+ size_t capCount,
+ char * buffer,
+ size_t bufferSize)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( ( NULL == buffer ) || ( NULL == cap ) ) {
+ CAMHAL_LOGEA("Invalid input arguments");
+ return -EINVAL;
+ }
+
+
+ for ( unsigned int i = 0 ; i < capCount ; i++ )
+ {
+ if ( format == cap[i].pixelformat )
+ {
+ if (buffer[0] != '\0') {
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+ strncat(buffer, cap[i].param, bufferSize - 1);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+void OMXCameraAdapter::encodeFrameRates(const int minFrameRate, const int maxFrameRate,
+ const OMX_TI_CAPTYPE & caps, const CapFramerate * const fixedFrameRates,
+ const int frameRateCount, android::Vector<FpsRange> & fpsRanges) {
+ LOG_FUNCTION_NAME;
+
+ if ( minFrameRate == maxFrameRate ) {
+ // single fixed frame rate supported
+ fpsRanges.add(FpsRange(minFrameRate, maxFrameRate));
+ return;
+ }
+
+ // insert min and max frame rates
+ fpsRanges.add(FpsRange(minFrameRate, minFrameRate));
+ fpsRanges.add(FpsRange(maxFrameRate, maxFrameRate));
+
+ // insert variable frame rates
+ for ( int i = 0; i < static_cast<int>(caps.ulPrvVarFPSModesCount); ++i ) {
+ const FpsRange fpsRange = FpsRange(
+ max(androidFromDucatiFrameRate(caps.tPrvVarFPSModes[i].nVarFPSMin), minFrameRate),
+ min(androidFromDucatiFrameRate(caps.tPrvVarFPSModes[i].nVarFPSMax), maxFrameRate));
+
+ if ( fpsRange.isFixed() ) {
+ // this range is either min or max fixed frame rate, already added above
+ continue;
+ }
+
+ fpsRanges.add(fpsRange);
+ }
+
+ // insert fixed frame rates
+ for ( int i = 0; i < frameRateCount; ++i ) {
+ const int fixedFrameRate = fixedFrameRates[i].num * CameraHal::VFR_SCALE;
+
+ if ( fixedFrameRate < minFrameRate || fixedFrameRate > maxFrameRate ) {
+ // not supported by hardware
+ continue;
+ }
+
+ const FpsRange fpsRange = FpsRange(fixedFrameRate, fixedFrameRate);
+ fpsRanges.add(fpsRange);
+ }
+
+ // sort first by max, then by min, according to Android API requirements
+ fpsRanges.sort(FpsRange::compare);
+
+ // remove duplicated frame rates
+ for ( int i = 0; i < static_cast<int>(fpsRanges.size()) - 1; ) {
+ const FpsRange & current = fpsRanges.itemAt(i);
+ const FpsRange & next = fpsRanges.itemAt(i + 1);
+ if ( current == next ) {
+ fpsRanges.removeAt(i + 1);
+ } else {
+ i++;
+ }
+ }
+}
+
+size_t OMXCameraAdapter::encodeZoomCap(OMX_S32 maxZoom,
+ const CapZoom *cap,
+ size_t capCount,
+ char * buffer,
+ size_t bufferSize)
+{
+ status_t res = NO_ERROR;
+ size_t ret = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( (NULL == buffer) || (NULL == cap) ) {
+ CAMHAL_LOGEA("Invalid input arguments");
+ return -EINVAL;
+ }
+
+
+ for ( unsigned int i = 0; i < capCount; i++ ) {
+ if ( cap[i].num <= maxZoom ) {
+ if (buffer[0] != '\0') {
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+ strncat(buffer, cap[i].param, bufferSize - 1);
+ ret++;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodeISOCap(OMX_U32 maxISO,
+ const CapISO *cap,
+ size_t capCount,
+ char * buffer,
+ size_t bufferSize)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( (NULL == buffer) || (NULL == cap) ) {
+ CAMHAL_LOGEA("Invalid input arguments");
+ return -EINVAL;
+ }
+
+ for ( unsigned int i = 0; i < capCount; i++ ) {
+ if ( cap[i].num <= maxISO) {
+ if (buffer[0] != '\0') {
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+ strncat(buffer, cap[i].param, bufferSize - 1);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodeSizeCap(OMX_TI_CAPRESTYPE &res,
+ const CapResolution *cap,
+ size_t capCount,
+ char * buffer,
+ size_t bufferSize)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( (NULL == buffer) || (NULL == cap) ) {
+ CAMHAL_LOGEA("Invalid input arguments");
+ return -EINVAL;
+ }
+
+ for ( unsigned int i = 0 ; i < capCount ; i++ ) {
+ if ( (cap[i].width <= res.nWidthMax) &&
+ (cap[i].height <= res.nHeightMax) &&
+ (cap[i].width >= res.nWidthMin) &&
+ (cap[i].height >= res.nHeightMin) ) {
+ if (buffer[0] != '\0') {
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+ strncat(buffer, cap[i].param, bufferSize -1);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodeSizeCap3D(OMX_TI_CAPRESTYPE &res,
+ const CapResolution *cap,
+ size_t capCount,
+ char * buffer,
+ size_t bufferSize)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( (NULL == buffer) || (NULL == cap) ) {
+ CAMHAL_LOGEA("Invalid input arguments");
+ return -EINVAL;
+ }
+
+ for ( unsigned int i = 0 ; i < capCount ; i++ ) {
+ if ( (cap[i].width <= res.nWidthMax) &&
+ (cap[i].height <= res.nHeightMax) &&
+ (cap[i].width >= res.nWidthMin) &&
+ (cap[i].height >= res.nHeightMin) &&
+ (cap[i].width * cap[i].height <= res.nMaxResInPixels)) {
+ if (buffer[0] != '\0') {
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+ strncat(buffer, cap[i].param, bufferSize -1);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertImageSizes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ int s3d_detected = 0;
+ int s3d_ss_detected = 0;
+ int s3d_tb_detected = 0;
+
+ LOG_FUNCTION_NAME;
+
+ for ( unsigned int i = 0 ; i < caps.ulCapFrameLayoutCount; i++ ) {
+ if (caps.eCapFrameLayout[i] == OMX_TI_StereoFrameLayoutTopBottom)
+ {
+ s3d_tb_detected = 1;
+ }
+ else if (caps.eCapFrameLayout[i] == OMX_TI_StereoFrameLayoutLeftRight)
+ {
+ s3d_ss_detected = 1;
+ }
+ else if ( (caps.eCapFrameLayout[i] == OMX_TI_StereoFrameLayoutTopBottomSubsample)
+ || (caps.eCapFrameLayout[i] == OMX_TI_StereoFrameLayoutLeftRightSubsample) )
+ {
+ s3d_detected = 1;
+ }
+ }
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ // Check if we are in 2d mode
+ if (!s3d_ss_detected && !s3d_tb_detected && !s3d_detected)
+ {
+ ret = encodeSizeCap(caps.tImageResRange,
+ mImageCapRes,
+ ARRAY_SIZE(mImageCapRes),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported picture sizes 0x%x", ret);
+ } else {
+ params->set(CameraProperties::SUPPORTED_PICTURE_SIZES, supported);
+ }
+ params->set(CameraProperties::MAX_PICTURE_WIDTH, caps.tImageResRange.nWidthMax);
+ params->set(CameraProperties::MAX_PICTURE_HEIGHT, caps.tImageResRange.nHeightMax);
+ }
+ else // 3d mode
+ {
+ if (s3d_tb_detected)
+ {
+ ret = encodeSizeCap3D(caps.tImageResRange,
+ mImageCapResTB,
+ ARRAY_SIZE(mImageCapResTB),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported picture sizes 0x%x", ret);
+ } else {
+ params->set(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES, supported);
+ }
+ }
+ else
+ {
+ params->set(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES, supported);
+ }
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ if (s3d_ss_detected)
+ {
+ ret = encodeSizeCap3D(caps.tImageResRange,
+ mImageCapResSS,
+ ARRAY_SIZE(mImageCapResSS),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported picture sizes 0x%x", ret);
+ } else {
+ params->set(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES, supported);
+ }
+ }
+ else
+ {
+ params->set(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES, supported);
+ }
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ if (s3d_detected)
+ {
+ ret = encodeSizeCap3D(caps.tImageResRange,
+ mImageCapRes,
+ ARRAY_SIZE(mImageCapRes),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported picture sizes 0x%x", ret);
+ } else {
+ params->set(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES, supported);
+ }
+ } else {
+ params->set(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES, supported);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertPreviewSizes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ int s3d_detected = 0;
+ int s3d_ss_detected = 0;
+ int s3d_tb_detected = 0;
+
+ LOG_FUNCTION_NAME;
+
+ for ( unsigned int i = 0 ; i < caps.ulPrvFrameLayoutCount; i++ ) {
+ if (caps.ePrvFrameLayout[i] == OMX_TI_StereoFrameLayoutTopBottom)
+ {
+ s3d_tb_detected = 1;
+ }
+ else if (caps.ePrvFrameLayout[i] == OMX_TI_StereoFrameLayoutLeftRight)
+ {
+ s3d_ss_detected = 1;
+ }
+ else if ( (caps.ePrvFrameLayout[i] == OMX_TI_StereoFrameLayoutTopBottomSubsample)
+ || (caps.ePrvFrameLayout[i] == OMX_TI_StereoFrameLayoutLeftRightSubsample) )
+ {
+ s3d_detected = 1;
+ }
+ }
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ // Check if we are in 2d mode
+ if (!s3d_ss_detected && !s3d_tb_detected && !s3d_detected)
+ {
+ ret = encodeSizeCap(caps.tPreviewResRange,
+ mPreviewRes,
+ ARRAY_SIZE(mPreviewRes),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported Landscape preview sizes 0x%x", ret);
+ return ret;
+ }
+
+ /* Insert Portait Resolutions by verifying Potrait Capability Support */
+ ret = encodeSizeCap(caps.tRotatedPreviewResRange,
+ mPreviewPortraitRes,
+ ARRAY_SIZE(mPreviewPortraitRes),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported Potrait preview sizes 0x%x", ret);
+ } else {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, supported);
+ }
+ }
+ else // 3d mode
+ {
+ if (s3d_tb_detected)
+ {
+ ret = encodeSizeCap3D(caps.tPreviewResRange,
+ mPreviewResTB,
+ ARRAY_SIZE(mPreviewResTB),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported 3D TB preview sizes 0x%x", ret);
+ return ret;
+ } else {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES, supported);
+ }
+ }
+ else
+ {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES, supported);
+ }
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ if (s3d_ss_detected)
+ {
+ ret = encodeSizeCap3D(caps.tPreviewResRange,
+ mPreviewResSS,
+ ARRAY_SIZE(mPreviewResSS),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported 3D SS preview sizes 0x%x", ret);
+ return ret;
+ } else {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES, supported);
+ }
+ }
+ else
+ {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES, supported);
+ }
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ if (s3d_detected)
+ {
+ ret = encodeSizeCap3D(caps.tPreviewResRange,
+ mPreviewRes,
+ ARRAY_SIZE(mPreviewRes),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported preview sizes 0x%x", ret);
+ return ret;
+ } else {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES, supported);
+ }
+ }
+ else
+ {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES, supported);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertVideoSizes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ ret = encodeSizeCap(caps.tPreviewResRange,
+ mPreviewRes,
+ ARRAY_SIZE(mPreviewRes),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported video sizes 0x%x", ret);
+ } else {
+ params->set(CameraProperties::SUPPORTED_VIDEO_SIZES, supported);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertThumbSizes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ ret = encodeSizeCap(caps.tThumbResRange,
+ mThumbRes,
+ ARRAY_SIZE(mThumbRes),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported thumbnail sizes 0x%x", ret);
+ } else {
+ //CTS Requirement: 0x0 should always be supported
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, "0x0", MAX_PROP_NAME_LENGTH);
+ params->set(CameraProperties::SUPPORTED_THUMBNAIL_SIZES, supported);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertZoomStages(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ size_t zoomStageCount = 0;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ zoomStageCount = encodeZoomCap(caps.xMaxWidthZoom,
+ mZoomStages,
+ ARRAY_SIZE(mZoomStages),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ params->set(CameraProperties::SUPPORTED_ZOOM_RATIOS, supported);
+ params->set(CameraProperties::SUPPORTED_ZOOM_STAGES, zoomStageCount - 1); //As per CTS requirement
+
+ if ( 0 == zoomStageCount ) {
+ params->set(CameraProperties::ZOOM_SUPPORTED, android::CameraParameters::FALSE);
+ params->set(CameraProperties::SMOOTH_ZOOM_SUPPORTED, android::CameraParameters::FALSE);
+ } else {
+ params->set(CameraProperties::ZOOM_SUPPORTED, android::CameraParameters::TRUE);
+ params->set(CameraProperties::SMOOTH_ZOOM_SUPPORTED, android::CameraParameters::TRUE);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertImageFormats(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', sizeof(supported));
+
+ for ( int i = 0 ; i < caps.ulImageFormatCount ; i++ ) {
+ ret = encodePixelformatCap(caps.eImageFormats[i],
+ mPixelformats,
+ ARRAY_SIZE(mPixelformats),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported picture formats 0x%x", ret);
+ break;
+ }
+ }
+
+ for (int i = 0; i < caps.ulImageCodingFormatCount ; i++) {
+ ret = encodeImageCodingFormatCap(caps.eImageCodingFormat[i],
+ mImageCodingFormat,
+ ARRAY_SIZE(mImageCodingFormat),
+ supported);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported picture formats 0x%x", ret);
+ break;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ params->set(CameraProperties::SUPPORTED_PICTURE_FORMATS, supported);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertPreviewFormats(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ for ( int i = 0 ; i < caps.ulPreviewFormatCount; i++ ) {
+ ret = encodePixelformatCap(caps.ePreviewFormats[i],
+ mPixelformats,
+ ARRAY_SIZE(mPixelformats),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported preview formats 0x%x", ret);
+ break;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ // need to advertise we support YV12 format
+ // We will program preview port with NV21 when we see application set YV12
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, android::CameraParameters::PIXEL_FORMAT_YUV420P, MAX_PROP_VALUE_LENGTH - 1);
+ params->set(CameraProperties::SUPPORTED_PREVIEW_FORMATS, supported);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertFramerates(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ // collect supported normal frame rates
+ {
+ android::Vector<FpsRange> fpsRanges;
+
+ // HASH: Fix JEM Amazon Ducati xFramerates which are [1 .. 30] vs [256 .. 7680]
+ int minFrameRate = -1;
+ if (caps.xFramerateMin >= 50)
+ minFrameRate = max<int>(FPS_MIN * CameraHal::VFR_SCALE, androidFromDucatiFrameRate(caps.xFramerateMin));
+ else
+ minFrameRate = max<int>(FPS_MIN * CameraHal::VFR_SCALE, androidFromDucatiFrameRate(caps.xFramerateMin << 8));
+ int maxFrameRate = -1;
+ if (caps.xFramerateMax >= 50)
+ maxFrameRate = min<int>(FPS_MAX * CameraHal::VFR_SCALE, androidFromDucatiFrameRate(caps.xFramerateMax));
+ else
+ maxFrameRate = min<int>(FPS_MAX * CameraHal::VFR_SCALE, androidFromDucatiFrameRate(caps.xFramerateMax << 8));
+
+ if ( minFrameRate > maxFrameRate ) {
+ CAMHAL_LOGE("Invalid frame rate range: [%d .. %d]", caps.xFramerateMin, caps.xFramerateMax);
+ return BAD_VALUE;
+ }
+
+ encodeFrameRates(minFrameRate, maxFrameRate, caps, mFramerates, ARRAY_SIZE(mFramerates), fpsRanges);
+
+ // populate variable frame rates
+ char supported[MAX_PROP_VALUE_LENGTH];
+ char defaultRange[MAX_PROP_VALUE_LENGTH];
+
+ memset(supported, 0, sizeof(supported));
+ memset(defaultRange, 0, sizeof(defaultRange));
+
+ for ( int i = 0; i < static_cast<int>(fpsRanges.size()); ++i ) {
+ const FpsRange & fpsRange = fpsRanges.itemAt(i);
+ if ( supported[0] ) strncat(supported, PARAM_SEP, 1);
+ char tmp[MAX_PROP_VALUE_LENGTH];
+ snprintf(tmp, sizeof(tmp) - 1, "(%d,%d)", fpsRange.min(), fpsRange.max());
+ strcat(supported, tmp);
+ }
+
+ const FpsRange & defaultFpsRange = fpsRanges.itemAt(fpsRanges.size() - 1);
+ snprintf(defaultRange, sizeof(defaultRange) - 1, "%d,%d", defaultFpsRange.min(), defaultFpsRange.max());
+
+ CAMHAL_LOGD("Supported framerate ranges: %s", supported);
+ CAMHAL_LOGD("Default framerate range: [%s]", defaultRange);
+
+ params->set(CameraProperties::FRAMERATE_RANGE_SUPPORTED, supported);
+ params->set(CameraProperties::FRAMERATE_RANGE, defaultRange);
+
+ // populate fixed frame rates
+ memset(supported, 0, sizeof(supported));
+ memset(defaultRange, 0, sizeof(defaultRange));
+
+ for ( int i = 0; i < static_cast<int>(fpsRanges.size()); ++i ) {
+ const FpsRange & fpsRange = fpsRanges.itemAt(i);
+ if ( fpsRange.isFixed() && (fpsRange.min()%CameraHal::VFR_SCALE) == 0 ) {
+ if ( supported[0] ) strncat(supported, PARAM_SEP, 1);
+ char tmp[MAX_PROP_VALUE_LENGTH];
+ snprintf(tmp, sizeof(tmp) - 1, "%d", fpsRange.min()/CameraHal::VFR_SCALE);
+ strcat(supported, tmp);
+ }
+ }
+
+ CAMHAL_LOGD("Supported preview framerates: %s", supported);
+ params->set(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES, supported);
+
+ // insert default frame rate only if it is fixed
+ if ( defaultFpsRange.isFixed() && (defaultFpsRange.min()%CameraHal::VFR_SCALE) == 0 ) {
+ snprintf(defaultRange, sizeof(defaultRange) - 1, "%d", defaultFpsRange.min()/CameraHal::VFR_SCALE);
+ params->set(CameraProperties::PREVIEW_FRAME_RATE, defaultRange);
+ }
+ }
+
+ // collect supported extended frame rates
+ {
+ android::Vector<FpsRange> fpsRanges;
+
+ // HASH: Fix JEM Amazon Ducati xFramerates which are [1 .. 30] vs [256 .. 7680]
+ int minFrameRate = -1;
+ if (caps.xFramerateMin >= 50)
+ minFrameRate = max<int>(FPS_MIN * CameraHal::VFR_SCALE, androidFromDucatiFrameRate(caps.xFramerateMin));
+ else
+ minFrameRate = max<int>(FPS_MIN * CameraHal::VFR_SCALE, androidFromDucatiFrameRate(caps.xFramerateMin << 8));
+ int maxFrameRate = -1;
+ if (caps.xFramerateMax >= 50)
+ maxFrameRate = min<int>(FPS_MAX_EXTENDED * CameraHal::VFR_SCALE, androidFromDucatiFrameRate(caps.xFramerateMax));
+ else
+ maxFrameRate = min<int>(FPS_MAX_EXTENDED * CameraHal::VFR_SCALE, androidFromDucatiFrameRate(caps.xFramerateMax << 8));
+
+ encodeFrameRates(minFrameRate, maxFrameRate, caps, mFramerates, ARRAY_SIZE(mFramerates), fpsRanges);
+
+ // populate variable frame rates
+ char supported[MAX_PROP_VALUE_LENGTH];
+ memset(supported, 0, sizeof(supported) - 1);
+
+ for ( int i = 0; i < static_cast<int>(fpsRanges.size()); ++i ) {
+ const FpsRange & fpsRange = fpsRanges.itemAt(i);
+ if ( supported[0] ) strncat(supported, PARAM_SEP, 1);
+ char tmp[MAX_PROP_VALUE_LENGTH];
+ snprintf(tmp, sizeof(tmp) - 1, "(%d,%d)", fpsRange.min(), fpsRange.max());
+ strcat(supported, tmp);
+ }
+
+ CAMHAL_LOGD("Supported framerate ranges extended: %s", supported);
+ params->set(CameraProperties::FRAMERATE_RANGE_EXT_SUPPORTED, supported);
+
+ // populate fixed frame rates
+ memset(supported, 0, sizeof(supported) - 1);
+
+ for ( int i = 0; i < static_cast<int>(fpsRanges.size()); ++i ) {
+ const FpsRange & fpsRange = fpsRanges.itemAt(i);
+ if ( fpsRange.isFixed() && (fpsRange.min()%CameraHal::VFR_SCALE) == 0 ) {
+ if ( supported[0] ) strncat(supported, PARAM_SEP, 1);
+ char tmp[MAX_PROP_VALUE_LENGTH];
+ snprintf(tmp, sizeof(tmp) - 1, "%d", fpsRange.min()/CameraHal::VFR_SCALE);
+ strcat(supported, tmp);
+ }
+ }
+
+ CAMHAL_LOGD("Supported extended preview framerates: %s", supported);
+ params->set(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES_EXT, supported);
+ }
+
+ return OK;
+}
+
+status_t OMXCameraAdapter::insertEVs(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", ( int ) ( caps.xEVCompensationMin * 10 ));
+ params->set(CameraProperties::SUPPORTED_EV_MIN, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", ( int ) ( caps.xEVCompensationMax * 10 ));
+ params->set(CameraProperties::SUPPORTED_EV_MAX, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertISOModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ ret = encodeISOCap(caps.nSensitivityMax,
+ mISOStages,
+ ARRAY_SIZE(mISOStages),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported ISO modes 0x%x", ret);
+ } else {
+ params->set(CameraProperties::SUPPORTED_ISO_VALUES, supported);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertIPPModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ //Off is always supported
+ strncat(supported, TICameraParameters::IPP_NONE, MAX_PROP_NAME_LENGTH);
+
+ if ( caps.bLensDistortionCorrectionSupported ) {
+ strncat(supported, PARAM_SEP, 1);
+ strncat(supported, TICameraParameters::IPP_LDC, MAX_PROP_NAME_LENGTH);
+ }
+
+ if ( caps.bISONoiseFilterSupported ) {
+ strncat(supported, PARAM_SEP, 1);
+ strncat(supported, TICameraParameters::IPP_NSF, MAX_PROP_NAME_LENGTH);
+ }
+
+ if ( caps.bISONoiseFilterSupported && caps.bLensDistortionCorrectionSupported ) {
+ strncat(supported, PARAM_SEP, 1);
+ strncat(supported, TICameraParameters::IPP_LDCNSF, MAX_PROP_NAME_LENGTH);
+ }
+
+ params->set(CameraProperties::SUPPORTED_IPP_MODES, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertWBModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ for ( unsigned int i = 0 ; i < caps.ulWhiteBalanceCount ; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eWhiteBalanceModes[i], WBalLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ }
+ }
+
+ params->set(CameraProperties::SUPPORTED_WHITE_BALANCE, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertEffects(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ for ( unsigned int i = 0 ; i < caps.ulColorEffectCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eColorEffects[i], EffLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ }
+ }
+
+ params->set(CameraProperties::SUPPORTED_EFFECTS, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertExpModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ for ( unsigned int i = 0 ; i < caps.ulExposureModeCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eExposureModes[i], ExpLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ }
+ }
+
+ params->set(CameraProperties::SUPPORTED_EXPOSURE_MODES, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertManualExpRanges(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps) {
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ if (caps.nManualExpMin > caps.nManualExpMax) {
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) 0);
+ params->set(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) 0);
+ params->set(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MAX, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) 0);
+ params->set(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_STEP, supported);
+ } else {
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) caps.nManualExpMin);
+ params->set(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) caps.nManualExpMax);
+ params->set(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MAX, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) MANUAL_EXPOSURE_STEP);
+ params->set(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_STEP, supported);
+ }
+
+ if (MANUAL_GAIN_ISO_MIN > caps.nSensitivityMax) {
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) 0);
+ params->set(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) 0);
+ params->set(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MAX, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) 0);
+ params->set(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_STEP, supported); }
+ else {
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) MANUAL_GAIN_ISO_MIN);
+ params->set(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) caps.nSensitivityMax);
+ params->set(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MAX, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", (int) MANUAL_GAIN_ISO_STEP);
+ params->set(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_STEP, supported);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertFlashModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ for ( unsigned int i = 0 ; i < caps.ulFlashCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eFlashModes[i], FlashLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ }
+ }
+
+ if ( strlen(supported) == 0 ) {
+ strncpy(supported, DEFAULT_FLASH_MODE, MAX_PROP_NAME_LENGTH);
+ }
+
+ params->set(CameraProperties::SUPPORTED_FLASH_MODES, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertSceneModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ for ( unsigned int i = 0 ; i < caps.ulSceneCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eSceneModes[i], SceneLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ }
+ }
+
+ params->set(CameraProperties::SUPPORTED_SCENE_MODES, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertFocusModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ for ( unsigned int i = 0 ; i < caps.ulFocusModeCount; i++ ) {
+ getMultipleLUTvalue_OMXtoHAL(caps.eFocusModes[i], FocusLUT, supported);
+ }
+
+ // Check if focus is supported by camera
+ if (caps.ulFocusModeCount == 1 &&
+ caps.eFocusModes[0] == OMX_IMAGE_FocusControlOff) {
+ // Focus is not supported by camera
+ // Advertise this to app as infinitiy focus mode
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, android::CameraParameters::FOCUS_MODE_INFINITY, MAX_PROP_NAME_LENGTH);
+ }
+
+ params->set(CameraProperties::SUPPORTED_FOCUS_MODES, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertFlickerModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ for ( unsigned int i = 0 ; i < caps.ulFlickerCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eFlicker[i], FlickerLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ }
+ }
+
+ params->set(CameraProperties::SUPPORTED_ANTIBANDING, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertAreas(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ sprintf(supported, "%d", caps.ulAlgoAreasFocusCount);
+ params->set(CameraProperties::MAX_FOCUS_AREAS, supported);
+ CAMHAL_LOGDB("Maximum supported focus areas %s", supported);
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+ sprintf(supported, "%d", caps.ulAlgoAreasExposureCount);
+ params->set(CameraProperties::MAX_NUM_METERING_AREAS, supported);
+ CAMHAL_LOGDB("Maximum supported exposure areas %s", supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertVNFSupported(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps) {
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_TRUE == caps.bVideoNoiseFilterSupported ) {
+ params->set(CameraProperties::VNF_SUPPORTED, android::CameraParameters::TRUE);
+ } else {
+ params->set(CameraProperties::VNF_SUPPORTED, android::CameraParameters::FALSE);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertVSTABSupported(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps) {
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_TRUE == caps.bVideoStabilizationSupported ) {
+ params->set(CameraProperties::VSTAB_SUPPORTED, android::CameraParameters::TRUE);
+ } else {
+ params->set(CameraProperties::VSTAB_SUPPORTED, android::CameraParameters::FALSE);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertLocks(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME
+
+ if ( caps.bAELockSupported ) {
+ params->set(CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED, android::CameraParameters::TRUE);
+ } else {
+ params->set(CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED, android::CameraParameters::FALSE);
+ }
+
+ if ( caps.bAWBLockSupported ) {
+ params->set(CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED, android::CameraParameters::TRUE);
+ } else {
+ params->set(CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED, android::CameraParameters::FALSE);
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertSenMount(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+ unsigned int i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', sizeof(supported));
+
+ // 1) Look up and assign sensor name
+ for (i = 0; i < ARRAY_SIZE(mSensorNames); i++) {
+ if(mSensorNames[i].num == caps.tSenMounting.nSenId) {
+ // sensor found
+ break;
+ }
+ }
+ if ( i == ARRAY_SIZE(mSensorNames) ) {
+ p = "UNKNOWN_SENSOR";
+ } else {
+ p = mSensorNames[i].param;
+ }
+ strncat(supported, p, REMAINING_BYTES(supported));
+ params->set(CameraProperties::CAMERA_NAME, supported);
+ params->set(CameraProperties::CAMERA_SENSOR_ID, caps.tSenMounting.nSenId);
+
+ // 2) Assign mounting rotation
+ params->set(CameraProperties::ORIENTATION_INDEX, caps.tSenMounting.nRotation);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertRaw(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps) {
+
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ unsigned int i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', sizeof(supported));
+ sprintf(supported,"%d",int(caps.uSenNativeResWidth));
+ params->set(CameraProperties::RAW_WIDTH, supported);
+
+ memset(supported, '\0', sizeof(supported));
+ if (caps.bMechanicalMisalignmentSupported) {
+ sprintf(supported,"%d",int(caps.uSenNativeResHeight) * 2);
+ } else {
+ sprintf(supported,"%d",int(caps.uSenNativeResHeight));
+ }
+ params->set(CameraProperties::RAW_HEIGHT, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertFacing(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+ unsigned int i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', sizeof(supported));
+
+ for (i = 0; i < ARRAY_SIZE(mFacing); i++) {
+ if((OMX_TI_SENFACING_TYPE)mFacing[i].num == caps.tSenMounting.eFacing) {
+ break;
+ }
+ }
+ if ( i == ARRAY_SIZE(mFacing) ) {
+ p = "UNKNOWN_FACING";
+ } else {
+ p = mFacing[i].param;
+ }
+ strncat(supported, p, REMAINING_BYTES(supported));
+ params->set(CameraProperties::FACING_INDEX, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertFocalLength(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', sizeof(supported));
+
+ sprintf(supported, "%d", caps.nFocalLength / 100);
+ strncat(supported, ".", REMAINING_BYTES(supported));
+ sprintf(supported+(strlen(supported)*sizeof(char)), "%d", caps.nFocalLength % 100);
+
+ params->set(CameraProperties::FOCAL_LENGTH, supported);
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertAutoConvergenceModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+ unsigned int i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', sizeof(supported));
+
+ for ( unsigned int i = 0 ; i < caps.ulAutoConvModesCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eAutoConvModes[i], mAutoConvergenceLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ }
+ strncat(supported, p, REMAINING_BYTES(supported));
+ }
+ }
+ params->set(CameraProperties::AUTOCONVERGENCE_MODE_VALUES, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertManualConvergenceRange(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", ( int ) ( caps.nManualConvMin ));
+ params->set(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MIN, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", ( int ) ( caps.nManualConvMax ));
+ params->set(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MAX, supported);
+
+ snprintf(supported, MAX_PROP_VALUE_LENGTH, "%d", ( int ) ( caps.nManualConvMax != caps.nManualConvMin ));
+ params->set(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_STEP, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertMechanicalMisalignmentCorrection(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ LOG_FUNCTION_NAME;
+
+ params->set(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED,
+ caps.bMechanicalMisalignmentSupported == OMX_TRUE ?
+ android::CameraParameters::TRUE : android::CameraParameters::FALSE);
+
+ return OK;
+}
+
+status_t OMXCameraAdapter::insertCaptureModes(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', sizeof(supported));
+
+ // 3D mode detect: Misalignment is present only in 3d mode
+ if (caps.bMechanicalMisalignmentSupported)
+ {
+ strncat(supported, TICameraParameters::HIGH_QUALITY_MODE, REMAINING_BYTES(supported));
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ strncat(supported, TICameraParameters::VIDEO_MODE, REMAINING_BYTES(supported));
+ }
+ else // 2D mode detect: Misalignment is present only in 3d mode
+ {
+ strncat(supported, TICameraParameters::HIGH_QUALITY_MODE, REMAINING_BYTES(supported));
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ strncat(supported, TICameraParameters::VIDEO_MODE, REMAINING_BYTES(supported));
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ strncat(supported, TICameraParameters::HIGH_PERFORMANCE_MODE, REMAINING_BYTES(supported));
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ strncat(supported, TICameraParameters::HIGH_QUALITY_ZSL_MODE, REMAINING_BYTES(supported));
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ strncat(supported, TICameraParameters::CP_CAM_MODE, REMAINING_BYTES(supported));
+#endif
+#ifdef CAMERAHAL_OMAP5_CAPTURE_MODES
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ strncat(supported, TICameraParameters::VIDEO_MODE_HQ, REMAINING_BYTES(supported));
+#endif
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ strncat(supported, TICameraParameters::ZOOM_BRACKETING, REMAINING_BYTES(supported));
+ }
+
+ for ( unsigned int i = 0 ; i < caps.ulBracketingModesCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eBracketingModes[i], mBracketingModesLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, REMAINING_BYTES(supported));
+ }
+ strncat(supported, p, REMAINING_BYTES(supported));
+ }
+ }
+
+ params->set(CameraProperties::CAP_MODE_VALUES, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertLayout(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+ unsigned int i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+ for ( unsigned int i = 0 ; i < caps.ulPrvFrameLayoutCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.ePrvFrameLayout[i], mLayoutLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ }
+ }
+ params->set(CameraProperties::S3D_PRV_FRAME_LAYOUT_VALUES, supported);
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+ for ( unsigned int i = 0 ; i < caps.ulCapFrameLayoutCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eCapFrameLayout[i], mLayoutLUT);
+ if ( NULL != p ) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ }
+ }
+ params->set(CameraProperties::S3D_CAP_FRAME_LAYOUT_VALUES, supported);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertVideoSnapshotSupported(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if (caps.bStillCapDuringVideoSupported)
+ {
+ params->set(CameraProperties::VIDEO_SNAPSHOT_SUPPORTED, android::CameraParameters::TRUE);
+ }
+ else
+ {
+ params->set(CameraProperties::VIDEO_SNAPSHOT_SUPPORTED, android::CameraParameters::FALSE);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertGBCESupported(CameraProperties::Properties* params,
+ const OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if (caps.bGbceSupported) {
+ params->set(CameraProperties::SUPPORTED_GBCE,
+ android::CameraParameters::TRUE);
+ } else {
+ params->set(CameraProperties::SUPPORTED_GBCE,
+ android::CameraParameters::FALSE);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertGLBCESupported(CameraProperties::Properties* params,
+ const OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if (caps.bGlbceSupported) {
+ params->set(CameraProperties::SUPPORTED_GLBCE,
+ android::CameraParameters::TRUE);
+ } else {
+ params->set(CameraProperties::SUPPORTED_GLBCE,
+ android::CameraParameters::FALSE);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertDefaults(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ char *pos, *str, *def;
+ char temp[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ /* If default is supported - set it, else - set first supported */
+ if (strstr(params->get(CameraProperties::S3D_PRV_FRAME_LAYOUT_VALUES), DEFAULT_S3D_PREVIEW_LAYOUT)) {
+ strncpy(temp, DEFAULT_S3D_PREVIEW_LAYOUT, MAX_PROP_VALUE_LENGTH - 1);
+ } else {
+ strncpy(temp, params->get(CameraProperties::S3D_PRV_FRAME_LAYOUT_VALUES),
+ MAX_PROP_VALUE_LENGTH - 1);
+ if ((pos = strstr(temp, PARAM_SEP))) {
+ *pos = '\0';
+ }
+ }
+ params->set(CameraProperties::S3D_PRV_FRAME_LAYOUT, temp);
+
+ if (!strcmp(TICameraParameters::S3D_TB_FULL, temp)) {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, params->get(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES));
+ } else if (!strcmp(TICameraParameters::S3D_SS_FULL, temp)) {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, params->get(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES));
+ } else if ((!strcmp(TICameraParameters::S3D_TB_SUBSAMPLED, temp))
+ || (!strcmp(TICameraParameters::S3D_SS_SUBSAMPLED, temp))) {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, params->get(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES));
+ }
+
+ /* If default is supported - set it, else - set first supported */
+ if (strstr(params->get(CameraProperties::S3D_CAP_FRAME_LAYOUT_VALUES), DEFAULT_S3D_PICTURE_LAYOUT)) {
+ strncpy(temp, DEFAULT_S3D_PICTURE_LAYOUT, MAX_PROP_VALUE_LENGTH - 1);
+ } else {
+ strncpy(temp, params->get(CameraProperties::S3D_CAP_FRAME_LAYOUT_VALUES),
+ MAX_PROP_VALUE_LENGTH - 1);
+ if ((pos = strstr(temp, PARAM_SEP))) {
+ *pos = '\0';
+ }
+ }
+ params->set(CameraProperties::S3D_CAP_FRAME_LAYOUT, temp);
+
+ if (!strcmp(TICameraParameters::S3D_TB_FULL, temp)) {
+ params->set(CameraProperties::SUPPORTED_PICTURE_SIZES, params->get(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES));
+ } else if (!strcmp(TICameraParameters::S3D_SS_FULL, temp)) {
+ params->set(CameraProperties::SUPPORTED_PICTURE_SIZES, params->get(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES));
+ } else if ((!strcmp(TICameraParameters::S3D_TB_SUBSAMPLED, temp))
+ || (!strcmp(TICameraParameters::S3D_SS_SUBSAMPLED, temp))) {
+ params->set(CameraProperties::SUPPORTED_PICTURE_SIZES, params->get(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES));
+ }
+
+ params->set(CameraProperties::ANTIBANDING, DEFAULT_ANTIBANDING);
+ params->set(CameraProperties::BRIGHTNESS, DEFAULT_BRIGHTNESS);
+ params->set(CameraProperties::CONTRAST, DEFAULT_CONTRAST);
+ params->set(CameraProperties::EFFECT, DEFAULT_EFFECT);
+ params->set(CameraProperties::EV_COMPENSATION, DEFAULT_EV_COMPENSATION);
+ params->set(CameraProperties::SUPPORTED_EV_STEP, DEFAULT_EV_STEP);
+ params->set(CameraProperties::EXPOSURE_MODE, DEFAULT_EXPOSURE_MODE);
+ params->set(CameraProperties::FLASH_MODE, DEFAULT_FLASH_MODE);
+ pos = strstr(params->get(CameraProperties::SUPPORTED_FOCUS_MODES), DEFAULT_FOCUS_MODE_PREFERRED);
+ if ( NULL != pos )
+ {
+ params->set(CameraProperties::FOCUS_MODE, DEFAULT_FOCUS_MODE_PREFERRED);
+ }
+ else
+ {
+ params->set(CameraProperties::FOCUS_MODE, DEFAULT_FOCUS_MODE);
+ }
+ params->set(CameraProperties::IPP, DEFAULT_IPP);
+ params->set(CameraProperties::GBCE, android::CameraParameters::FALSE);
+ params->set(CameraProperties::GLBCE, android::CameraParameters::FALSE);
+ params->set(CameraProperties::ISO_MODE, DEFAULT_ISO_MODE);
+ params->set(CameraProperties::JPEG_QUALITY, DEFAULT_JPEG_QUALITY);
+ params->set(CameraProperties::JPEG_THUMBNAIL_QUALITY, DEFAULT_THUMBNAIL_QUALITY);
+ params->set(CameraProperties::JPEG_THUMBNAIL_SIZE, DEFAULT_THUMBNAIL_SIZE);
+ params->set(CameraProperties::PICTURE_FORMAT, DEFAULT_PICTURE_FORMAT);
+
+ if (!strcmp(params->get(CameraProperties::S3D_CAP_FRAME_LAYOUT),
+ TICameraParameters::S3D_TB_FULL)) {
+ params->set(CameraProperties::PICTURE_SIZE, DEFAULT_PICTURE_TB_SIZE);
+ } else if (!strcmp(params->get(CameraProperties::S3D_CAP_FRAME_LAYOUT),
+ TICameraParameters::S3D_SS_FULL)) {
+ params->set(CameraProperties::PICTURE_SIZE, DEFAULT_PICTURE_SS_SIZE);
+ } else {
+ params->set(CameraProperties::PICTURE_SIZE, DEFAULT_PICTURE_SIZE);
+ }
+
+ if (!strcmp(params->get(CameraProperties::S3D_PRV_FRAME_LAYOUT),
+ TICameraParameters::S3D_TB_FULL)) {
+ params->set(CameraProperties::PREVIEW_SIZE, DEFAULT_PREVIEW_TB_SIZE);
+ } else if (!strcmp(params->get(CameraProperties::S3D_PRV_FRAME_LAYOUT),
+ TICameraParameters::S3D_SS_FULL)) {
+ params->set(CameraProperties::PREVIEW_SIZE, DEFAULT_PREVIEW_SS_SIZE);
+ } else {
+ params->set(CameraProperties::PREVIEW_SIZE, DEFAULT_PREVIEW_SIZE);
+ }
+
+ params->set(CameraProperties::PREVIEW_FORMAT, DEFAULT_PREVIEW_FORMAT);
+
+ /* Set default value if supported, otherwise set max supported value */
+ strncpy(temp, params->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES),
+ MAX_PROP_VALUE_LENGTH - 1);
+ def = str = temp;
+ while (1) {
+ if ((pos = strstr(str, PARAM_SEP))) {
+ *pos = '\0';
+ }
+ if (!strcmp(str, DEFAULT_FRAMERATE)) {
+ def = str;
+ break;
+ }
+ if (atoi(str) > atoi(def)) {
+ def = str;
+ }
+ if (pos == NULL) {
+ break;
+ }
+ str = pos + strlen(PARAM_SEP);
+ }
+ params->set(CameraProperties::PREVIEW_FRAME_RATE, def);
+
+ params->set(CameraProperties::REQUIRED_PREVIEW_BUFS, DEFAULT_NUM_PREV_BUFS);
+ params->set(CameraProperties::REQUIRED_IMAGE_BUFS, DEFAULT_NUM_PIC_BUFS);
+ params->set(CameraProperties::SATURATION, DEFAULT_SATURATION);
+ params->set(CameraProperties::SCENE_MODE, DEFAULT_SCENE_MODE);
+ params->set(CameraProperties::SHARPNESS, DEFAULT_SHARPNESS);
+ params->set(CameraProperties::VSTAB, DEFAULT_VSTAB);
+ params->set(CameraProperties::VNF, DEFAULT_VNF);
+ params->set(CameraProperties::WHITEBALANCE, DEFAULT_WB);
+ params->set(CameraProperties::ZOOM, DEFAULT_ZOOM);
+ params->set(CameraProperties::MAX_FD_HW_FACES, DEFAULT_MAX_FD_HW_FACES);
+ params->set(CameraProperties::MAX_FD_SW_FACES, DEFAULT_MAX_FD_SW_FACES);
+ params->set(CameraProperties::AUTO_EXPOSURE_LOCK, DEFAULT_AE_LOCK);
+ params->set(CameraProperties::AUTO_WHITEBALANCE_LOCK, DEFAULT_AWB_LOCK);
+ params->set(CameraProperties::HOR_ANGLE, DEFAULT_HOR_ANGLE);
+ params->set(CameraProperties::VER_ANGLE, DEFAULT_VER_ANGLE);
+ params->set(CameraProperties::VIDEO_SIZE, DEFAULT_VIDEO_SIZE);
+ params->set(CameraProperties::SENSOR_ORIENTATION, DEFAULT_SENSOR_ORIENTATION);
+ params->set(CameraProperties::AUTOCONVERGENCE_MODE, DEFAULT_AUTOCONVERGENCE_MODE);
+ params->set(CameraProperties::MANUAL_CONVERGENCE, DEFAULT_MANUAL_CONVERGENCE);
+ params->set(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION, DEFAULT_MECHANICAL_MISALIGNMENT_CORRECTION_MODE);
+
+ char property[PROPERTY_VALUE_MAX];
+ property_get("ro.product.manufacturer",
+ property,
+ DEFAULT_EXIF_MAKE);
+ property[0] = toupper(property[0]);
+ params->set(CameraProperties::EXIF_MAKE, property);
+ property_get("ro.product.model",
+ property,
+ DEFAULT_EXIF_MODEL);
+ property[0] = toupper(property[0]);
+ params->set(CameraProperties::EXIF_MODEL, property);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertCapabilities(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret ) {
+ ret = insertImageSizes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertPreviewSizes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertThumbSizes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertZoomStages(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertImageFormats(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertPreviewFormats(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertFramerates(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertEVs(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertISOModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertIPPModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertWBModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertEffects(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertExpModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertManualExpRanges(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertFlashModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertSceneModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertFocusModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertFlickerModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertSenMount(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertLocks(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertAreas(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertFacing(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertFocalLength(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertAutoConvergenceModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertManualConvergenceRange(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertMechanicalMisalignmentCorrection(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertRaw(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertCaptureModes(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertLayout(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertVideoSnapshotSupported(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertVSTABSupported(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertVNFSupported(params, caps);
+ }
+
+ //NOTE: Ensure that we always call insertDefaults after inserting the supported capabilities
+ //as there are checks inside insertDefaults to make sure a certain default is supported
+ // or not
+ if ( NO_ERROR == ret ) {
+ ret = insertVideoSizes(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertGBCESupported(params, caps);
+ }
+
+ if ( NO_ERROR == ret) {
+ ret = insertGLBCESupported(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertDefaults(params, caps);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+
+bool OMXCameraAdapter::_checkOmxTiCap(const OMX_TI_CAPTYPE & caps)
+{
+#define CAMHAL_CHECK_OMX_TI_CAP(countVar, arrayVar) \
+ do { \
+ const int count = static_cast<int>(caps.countVar); \
+ const int maxSize = CAMHAL_SIZE_OF_ARRAY(caps.arrayVar); \
+ if ( count < 0 || count > maxSize ) \
+ { \
+ CAMHAL_LOGE("OMX_TI_CAPTYPE verification failed"); \
+ CAMHAL_LOGE(" variable: OMX_TI_CAPTYPE::" #countVar \
+ ", value: %d, max allowed: %d", \
+ count, maxSize); \
+ return false; \
+ } \
+ } while (0)
+
+ CAMHAL_CHECK_OMX_TI_CAP(ulPreviewFormatCount, ePreviewFormats);
+ CAMHAL_CHECK_OMX_TI_CAP(ulImageFormatCount, eImageFormats);
+ CAMHAL_CHECK_OMX_TI_CAP(ulWhiteBalanceCount, eWhiteBalanceModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulColorEffectCount, eColorEffects);
+ CAMHAL_CHECK_OMX_TI_CAP(ulFlickerCount, eFlicker);
+ CAMHAL_CHECK_OMX_TI_CAP(ulExposureModeCount, eExposureModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulFocusModeCount, eFocusModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulSceneCount, eSceneModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulFlashCount, eFlashModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulPrvVarFPSModesCount, tPrvVarFPSModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulCapVarFPSModesCount, tCapVarFPSModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulAutoConvModesCount, eAutoConvModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulBracketingModesCount, eBracketingModes);
+ CAMHAL_CHECK_OMX_TI_CAP(ulImageCodingFormatCount, eImageCodingFormat);
+ CAMHAL_CHECK_OMX_TI_CAP(ulPrvFrameLayoutCount, ePrvFrameLayout);
+ CAMHAL_CHECK_OMX_TI_CAP(ulCapFrameLayoutCount, eCapFrameLayout);
+
+#undef CAMHAL_CHECK_OMX_TI_CAP
+
+ return true;
+}
+
+
+bool OMXCameraAdapter::_dumpOmxTiCap(const int sensorId, const OMX_TI_CAPTYPE & caps)
+{
+ if ( !_checkOmxTiCap(caps) )
+ {
+ CAMHAL_LOGE("OMX_TI_CAPTYPE structure is invalid");
+ return false;
+ }
+
+ CAMHAL_LOGD("===================================================");
+ CAMHAL_LOGD("---- Dumping OMX capabilities for sensor id: %d ----", sensorId);
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulPreviewFormatCount = %d", int(caps.ulPreviewFormatCount));
+ for ( int i = 0; i < int(caps.ulPreviewFormatCount); ++i )
+ CAMHAL_LOGD(" ePreviewFormats[%2d] = %d", i, int(caps.ePreviewFormats[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulImageFormatCount = %d", int(caps.ulImageFormatCount));
+ for ( int i = 0; i < int(caps.ulImageFormatCount); ++i )
+ CAMHAL_LOGD(" eImageFormats[%2d] = %d", i, int(caps.eImageFormats[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("tPreviewResRange.nWidthMin = %d", int(caps.tPreviewResRange.nWidthMin));
+ CAMHAL_LOGD("tPreviewResRange.nHeightMin = %d", int(caps.tPreviewResRange.nHeightMin));
+ CAMHAL_LOGD("tPreviewResRange.nWidthMax = %d", int(caps.tPreviewResRange.nWidthMax));
+ CAMHAL_LOGD("tPreviewResRange.nHeightMax = %d", int(caps.tPreviewResRange.nHeightMax));
+ CAMHAL_LOGD("tPreviewResRange.nMaxResInPixels = %d", int(caps.tPreviewResRange.nMaxResInPixels));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("tRotatedPreviewResRange.nWidthMin = %d", int(caps.tRotatedPreviewResRange.nWidthMin));
+ CAMHAL_LOGD("tRotatedPreviewResRange.nHeightMin = %d", int(caps.tRotatedPreviewResRange.nHeightMin));
+ CAMHAL_LOGD("tRotatedPreviewResRange.nWidthMax = %d", int(caps.tRotatedPreviewResRange.nWidthMax));
+ CAMHAL_LOGD("tRotatedPreviewResRange.nHeightMax = %d", int(caps.tRotatedPreviewResRange.nHeightMax));
+ CAMHAL_LOGD("tRotatedPreviewResRange.nMaxResInPixels = %d", int(caps.tRotatedPreviewResRange.nMaxResInPixels));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("tImageResRange.nWidthMin = %d", int(caps.tImageResRange.nWidthMin));
+ CAMHAL_LOGD("tImageResRange.nHeightMin = %d", int(caps.tImageResRange.nHeightMin));
+ CAMHAL_LOGD("tImageResRange.nWidthMax = %d", int(caps.tImageResRange.nWidthMax));
+ CAMHAL_LOGD("tImageResRange.nHeightMax = %d", int(caps.tImageResRange.nHeightMax));
+ CAMHAL_LOGD("tImageResRange.nMaxResInPixels = %d", int(caps.tImageResRange.nMaxResInPixels));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("tThumbResRange.nWidthMin = %d", int(caps.tThumbResRange.nWidthMin));
+ CAMHAL_LOGD("tThumbResRange.nHeightMin = %d", int(caps.tThumbResRange.nHeightMin));
+ CAMHAL_LOGD("tThumbResRange.nWidthMax = %d", int(caps.tThumbResRange.nWidthMax));
+ CAMHAL_LOGD("tThumbResRange.nHeightMax = %d", int(caps.tThumbResRange.nHeightMax));
+ CAMHAL_LOGD("tThumbResRange.nMaxResInPixels = %d", int(caps.tThumbResRange.nMaxResInPixels));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulWhiteBalanceCount = %d", int(caps.ulWhiteBalanceCount));
+ for ( int i = 0; i < int(caps.ulWhiteBalanceCount); ++i )
+ CAMHAL_LOGD(" eWhiteBalanceModes[%2d] = 0x%08x", i, int(caps.eWhiteBalanceModes[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulColorEffectCount = %d", int(caps.ulColorEffectCount));
+ for ( int i = 0; i < int(caps.ulColorEffectCount); ++i )
+ CAMHAL_LOGD(" eColorEffects[%2d] = 0x%08x", i, int(caps.eColorEffects[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("xMaxWidthZoom = %d", int(caps.xMaxWidthZoom));
+ CAMHAL_LOGD("xMaxHeightZoom = %d", int(caps.xMaxHeightZoom));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulFlickerCount = %d", int(caps.ulFlickerCount));
+ for ( int i = 0; i < int(caps.ulFlickerCount); ++i )
+ CAMHAL_LOGD(" eFlicker[%2d] = %d", i, int(caps.eFlicker[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulExposureModeCount = %d", int(caps.ulExposureModeCount));
+ for ( int i = 0; i < int(caps.ulExposureModeCount); ++i )
+ CAMHAL_LOGD(" eExposureModes[%2d] = 0x%08x", i, int(caps.eExposureModes[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("bLensDistortionCorrectionSupported = %d", int(caps.bLensDistortionCorrectionSupported));
+ CAMHAL_LOGD("bISONoiseFilterSupported = %d", int(caps.bISONoiseFilterSupported));
+ CAMHAL_LOGD("xEVCompensationMin = %d", int(caps.xEVCompensationMin));
+ CAMHAL_LOGD("xEVCompensationMax = %d", int(caps.xEVCompensationMax));
+ CAMHAL_LOGD("nSensitivityMax = %d", int(caps.nSensitivityMax));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulFocusModeCount = %d", int(caps.ulFocusModeCount));
+ for ( int i = 0; i < int(caps.ulFocusModeCount); ++i )
+ CAMHAL_LOGD(" eFocusModes[%2d] = 0x%08x", i, int(caps.eFocusModes[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulSceneCount = %d", int(caps.ulSceneCount));
+ for ( int i = 0; i < int(caps.ulSceneCount); ++i )
+ CAMHAL_LOGD(" eSceneModes[%2d] = %d", i, int(caps.eSceneModes[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulFlashCount = %d", int(caps.ulFlashCount));
+ for ( int i = 0; i < int(caps.ulFlashCount); ++i )
+ CAMHAL_LOGD(" eFlashModes[%2d] = %d", i, int(caps.eFlashModes[i]));
+
+ CAMHAL_LOGD("xFramerateMin = %d", int(caps.xFramerateMin));
+ CAMHAL_LOGD("xFramerateMax = %d", int(caps.xFramerateMax));
+ CAMHAL_LOGD("bContrastSupported = %d", int(caps.bContrastSupported));
+ CAMHAL_LOGD("bSaturationSupported = %d", int(caps.bSaturationSupported));
+ CAMHAL_LOGD("bBrightnessSupported = %d", int(caps.bBrightnessSupported));
+ CAMHAL_LOGD("bProcessingLevelSupported = %d", int(caps.bProcessingLevelSupported));
+ CAMHAL_LOGD("bQFactorSupported = %d", int(caps.bQFactorSupported));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulPrvVarFPSModesCount = %d", int(caps.ulPrvVarFPSModesCount));
+ for ( int i = 0; i < int(caps.ulPrvVarFPSModesCount); ++i )
+ {
+ CAMHAL_LOGD(" tPrvVarFPSModes[%d].nVarFPSMin = %d", i, int(caps.tPrvVarFPSModes[i].nVarFPSMin));
+ CAMHAL_LOGD(" tPrvVarFPSModes[%d].nVarFPSMax = %d", i, int(caps.tPrvVarFPSModes[i].nVarFPSMax));
+ }
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulCapVarFPSModesCount = %d", int(caps.ulCapVarFPSModesCount));
+ for ( int i = 0; i < int(caps.ulCapVarFPSModesCount); ++i )
+ {
+ CAMHAL_LOGD(" tCapVarFPSModes[%d].nVarFPSMin = %d", i, int(caps.tCapVarFPSModes[i].nVarFPSMin));
+ CAMHAL_LOGD(" tCapVarFPSModes[%d].nVarFPSMax = %d", i, int(caps.tCapVarFPSModes[i].nVarFPSMax));
+ }
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("tSenMounting.nSenId = %d", int(caps.tSenMounting.nSenId));
+ CAMHAL_LOGD("tSenMounting.nRotation = %d", int(caps.tSenMounting.nRotation));
+ CAMHAL_LOGD("tSenMounting.bMirror = %d", int(caps.tSenMounting.bMirror));
+ CAMHAL_LOGD("tSenMounting.bFlip = %d", int(caps.tSenMounting.bFlip));
+ CAMHAL_LOGD("tSenMounting.eFacing = %d", int(caps.tSenMounting.eFacing));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulAutoConvModesCount = %d", int(caps.ulAutoConvModesCount));
+ for ( int i = 0; i < int(caps.ulAutoConvModesCount); ++i )
+ CAMHAL_LOGD(" eAutoConvModes[%2d] = %d", i, int(caps.eAutoConvModes[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulBracketingModesCount = %d", int(caps.ulBracketingModesCount));
+ for ( int i = 0; i < int(caps.ulBracketingModesCount); ++i )
+ CAMHAL_LOGD(" eBracketingModes[%2d] = %d", i, int(caps.eBracketingModes[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("bGbceSupported = %d", int(caps.bGbceSupported));
+ CAMHAL_LOGD("bRawJpegSupported = %d", int(caps.bRawJpegSupported));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulImageCodingFormatCount = %d", int(caps.ulImageCodingFormatCount));
+ for ( int i = 0; i < int(caps.ulImageCodingFormatCount); ++i )
+ CAMHAL_LOGD(" eImageCodingFormat[%2d] = %d", i, int(caps.eImageCodingFormat[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("uSenNativeResWidth = %d", int(caps.uSenNativeResWidth));
+ CAMHAL_LOGD("uSenNativeResHeight = %d", int(caps.uSenNativeResHeight));
+ CAMHAL_LOGD("ulAlgoAreasFocusCount = %d", int(caps.ulAlgoAreasFocusCount));
+ CAMHAL_LOGD("ulAlgoAreasExposureCount = %d", int(caps.ulAlgoAreasExposureCount));
+ CAMHAL_LOGD("bAELockSupported = %d", int(caps.bAELockSupported));
+ CAMHAL_LOGD("bAWBLockSupported = %d", int(caps.bAWBLockSupported));
+ CAMHAL_LOGD("bAFLockSupported = %d", int(caps.bAFLockSupported));
+ CAMHAL_LOGD("nFocalLength = %d", int(caps.nFocalLength));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulPrvFrameLayoutCount = %d", int(caps.ulPrvFrameLayoutCount));
+ for ( int i = 0; i < int(caps.ulPrvFrameLayoutCount); ++i )
+ CAMHAL_LOGD(" ePrvFrameLayout[%2d] = %d", i, int(caps.ePrvFrameLayout[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("ulCapFrameLayoutCount = %d", int(caps.ulCapFrameLayoutCount));
+ for ( int i = 0; i < int(caps.ulCapFrameLayoutCount); ++i )
+ CAMHAL_LOGD(" eCapFrameLayout[%2d] = %d", i, int(caps.eCapFrameLayout[i]));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("bVideoNoiseFilterSupported = %d", int(caps.bVideoNoiseFilterSupported ));
+ CAMHAL_LOGD("bVideoStabilizationSupported = %d", int(caps.bVideoStabilizationSupported ));
+ CAMHAL_LOGD("bStillCapDuringVideoSupported = %d", int(caps.bStillCapDuringVideoSupported ));
+ CAMHAL_LOGD("bMechanicalMisalignmentSupported = %d", int(caps.bMechanicalMisalignmentSupported));
+ CAMHAL_LOGD("bFacePrioritySupported = %d", int(caps.bFacePrioritySupported ));
+ CAMHAL_LOGD("bRegionPrioritySupported = %d", int(caps.bRegionPrioritySupported ));
+ CAMHAL_LOGD("bGlbceSupported = %d", int(caps.bGlbceSupported));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("nManualConvMin = %d", int(caps.nManualConvMin ));
+ CAMHAL_LOGD("nManualConvMax = %d", int(caps.nManualConvMax ));
+ CAMHAL_LOGD("nManualExpMin = %d", int(caps.nManualExpMin ));
+ CAMHAL_LOGD("nManualExpMax = %d", int(caps.nManualExpMax ));
+ CAMHAL_LOGD("nBrightnessMin = %d", int(caps.nBrightnessMin ));
+ CAMHAL_LOGD("nBrightnessMax = %d", int(caps.nBrightnessMax ));
+ CAMHAL_LOGD("nContrastMin = %d", int(caps.nContrastMin ));
+ CAMHAL_LOGD("nContrastMax = %d", int(caps.nContrastMax ));
+ CAMHAL_LOGD("nSharpnessMin = %d", int(caps.nSharpnessMin ));
+ CAMHAL_LOGD("nSharpnessMax = %d", int(caps.nSharpnessMax ));
+ CAMHAL_LOGD("nSaturationMin = %d", int(caps.nSaturationMin ));
+ CAMHAL_LOGD("nSaturationMax = %d", int(caps.nSaturationMax ));
+
+ CAMHAL_LOGD("");
+ CAMHAL_LOGD("------------------- end of dump -------------------");
+ CAMHAL_LOGD("===================================================");
+
+ return true;
+}
+
+/*****************************************
+ * public exposed function declarations
+ *****************************************/
+
+status_t OMXCameraAdapter::getCaps(const int sensorId, CameraProperties::Properties* params, OMX_HANDLETYPE handle)
+{
+ status_t ret = NO_ERROR;
+ int caps_size = 0;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ CameraBuffer *bufferlist;
+ OMX_TI_CAPTYPE* caps;
+ OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
+ MemoryManager memMgr;
+
+ LOG_FUNCTION_NAME;
+
+ ret = memMgr.initialize();
+ if ( ret != OK ) {
+ CAMHAL_LOGE("MemoryManager initialization failed, error: %d", ret);
+ return ret;
+ }
+
+ // allocate tiler (or ion) buffer for caps (size is always a multiple of 4K)
+ caps_size = ((sizeof(OMX_TI_CAPTYPE)+4095)/4096)*4096;
+ bufferlist = memMgr.allocateBufferList(0, 0, NULL, caps_size, 1);
+ caps = (OMX_TI_CAPTYPE*) bufferlist[0].opaque;
+
+ if (!caps) {
+ CAMHAL_LOGEB("Error allocating buffer for caps %d", eError);
+ ret = -ENOMEM;
+ goto EXIT;
+ }
+
+ // initialize structures to be passed to OMX Camera
+ OMX_INIT_STRUCT_PTR (caps, OMX_TI_CAPTYPE);
+ caps->nPortIndex = OMX_ALL;
+
+ OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
+ sharedBuffer.nPortIndex = OMX_ALL;
+ sharedBuffer.nSharedBuffSize = caps_size;
+ sharedBuffer.pSharedBuff = (OMX_U8 *) camera_buffer_get_omx_ptr (&bufferlist[0]);
+
+ // Get capabilities from OMX Camera
+ eError = OMX_GetConfig(handle, (OMX_INDEXTYPE) OMX_TI_IndexConfigCamCapabilities, &sharedBuffer);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error during capabilities query 0x%x", eError);
+ ret = UNKNOWN_ERROR;
+ goto EXIT;
+ } else {
+ CAMHAL_LOGDA("OMX capability query success");
+ }
+
+#ifdef CAMERAHAL_PIRANHA
+ char hwrotation[PROPERTY_VALUE_MAX];
+ if (property_get("ro.sf.hwrotation", hwrotation, 0) > 0) {
+ if (caps->tSenMounting.nSenId == 306) { // front camera
+ caps->tSenMounting.nRotation = atoi(hwrotation);
+ } else { // back camera
+ caps->tSenMounting.nRotation = 360 - atoi(hwrotation);
+ }
+ }
+ // missing camera caps
+ if (caps->tSenMounting.nSenId == 306) {
+ caps->tPreviewResRange.nWidthMax = 640;
+ caps->tPreviewResRange.nHeightMax = 480;
+ caps->nFocalLength = 130;
+ } else {
+ caps->nFocalLength = 279;
+ }
+#endif
+
+#ifdef CAMERAHAL_DEBUG
+ _dumpOmxTiCap(sensorId, *caps);
+#endif
+
+ // Translate and insert Ducati capabilities to CameraProperties
+ if ( NO_ERROR == ret ) {
+ ret = insertCapabilities(params, *caps);
+ }
+
+ CAMHAL_LOGDB("sen mount id=%u", (unsigned int)caps->tSenMounting.nSenId);
+ CAMHAL_LOGDB("facing id=%u", (unsigned int)caps->tSenMounting.eFacing);
+
+ EXIT:
+ if (bufferlist) {
+ memMgr.freeBufferList(bufferlist);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXCapture.cpp b/camera/OMXCameraAdapter/OMXCapture.cpp
new file mode 100644
index 0000000..afc335e
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXCapture.cpp
@@ -0,0 +1,2098 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXCapture.cpp
+*
+* This file contains functionality for handling image capture.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+
+
+namespace Ti {
+namespace Camera {
+
+status_t OMXCameraAdapter::setParametersCapture(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *str = NULL;
+ int w, h;
+ OMX_COLOR_FORMATTYPE pixFormat;
+ CodingMode codingMode = mCodingMode;
+ const char *valstr = NULL;
+ int varint = 0;
+ OMX_TI_STEREOFRAMELAYOUTTYPE capFrmLayout;
+ bool inCaptureState = false;
+
+ LOG_FUNCTION_NAME;
+
+ OMXCameraPortParameters *cap;
+ cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ capFrmLayout = cap->mFrameLayoutType;
+ setParamS3D(mCameraAdapterParameters.mImagePortIndex,
+ params.get(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT));
+ if (capFrmLayout != cap->mFrameLayoutType) {
+ mPendingCaptureSettings |= SetFormat;
+ }
+
+ params.getPictureSize(&w, &h);
+
+ if ( ( w != ( int ) cap->mWidth ) ||
+ ( h != ( int ) cap->mHeight ) )
+ {
+ mPendingCaptureSettings |= SetFormat;
+ }
+
+ cap->mWidth = w;
+ cap->mHeight = h;
+ //TODO: Support more pixelformats
+ //cap->mStride = 2;
+
+ CAMHAL_LOGVB("Image: cap.mWidth = %d", (int)cap->mWidth);
+ CAMHAL_LOGVB("Image: cap.mHeight = %d", (int)cap->mHeight);
+
+ if ((valstr = params.getPictureFormat()) != NULL) {
+ if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ CAMHAL_LOGDA("CbYCrY format selected");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_YUV422I;
+ } else if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_YUV420SP;
+ } else if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
+ CAMHAL_LOGDA("RGB565 format selected");
+ pixFormat = OMX_COLOR_Format16bitRGB565;
+ mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_RGB565;
+ } else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_JPEG) == 0) {
+ CAMHAL_LOGDA("JPEG format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ codingMode = CodingJPEG;
+ mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_JPEG;
+ } else if (strcmp(valstr, TICameraParameters::PIXEL_FORMAT_JPS) == 0) {
+ CAMHAL_LOGDA("JPS format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ codingMode = CodingJPS;
+ mPictureFormatFromClient = TICameraParameters::PIXEL_FORMAT_JPS;
+ } else if (strcmp(valstr, TICameraParameters::PIXEL_FORMAT_MPO) == 0) {
+ CAMHAL_LOGDA("MPO format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ codingMode = CodingMPO;
+ mPictureFormatFromClient = TICameraParameters::PIXEL_FORMAT_MPO;
+ } else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) {
+ CAMHAL_LOGDA("RAW Picture format selected");
+ pixFormat = OMX_COLOR_FormatRawBayer10bit;
+ mPictureFormatFromClient = android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB;
+ } else {
+ CAMHAL_LOGEA("Invalid format, JPEG format selected as default");
+ pixFormat = OMX_COLOR_FormatUnused;
+ codingMode = CodingJPEG;
+ mPictureFormatFromClient = NULL;
+ }
+ } else {
+ CAMHAL_LOGEA("Picture format is NULL, defaulting to JPEG");
+ pixFormat = OMX_COLOR_FormatUnused;
+ codingMode = CodingJPEG;
+ mPictureFormatFromClient = NULL;
+ }
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ mRawCapture = false;
+ mYuvCapture = false;
+
+ valstr = params.get(TICameraParameters::KEY_CAP_MODE);
+ if ( (!valstr || strcmp(valstr, TICameraParameters::HIGH_QUALITY_MODE) == 0) &&
+ access(kRawImagesOutputDirPath, F_OK) != -1 ) {
+ mRawCapture = true;
+ }
+
+ if (mRawCapture && (access(kYuvImagesOutputDirPath, F_OK) != -1)) {
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ mYuvCapture = true;
+ }
+#endif
+ // JPEG capture is not supported in video mode by OMX Camera
+ // Set capture format to yuv422i...jpeg encode will
+ // be done on A9
+ valstr = params.get(TICameraParameters::KEY_CAP_MODE);
+ if ( (valstr && ( strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE) == 0 ||
+ strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE_HQ) == 0 ) ) &&
+ (pixFormat == OMX_COLOR_FormatUnused) ) {
+ CAMHAL_LOGDA("Capturing in video mode...selecting yuv422i");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ }
+
+ if (pixFormat != cap->mColorFormat || codingMode != mCodingMode) {
+ mPendingCaptureSettings |= SetFormat;
+ cap->mColorFormat = pixFormat;
+ mCodingMode = codingMode;
+ }
+
+#ifdef OMAP_ENHANCEMENT
+ str = params.get(TICameraParameters::KEY_TEMP_BRACKETING);
+ if ( ( str != NULL ) &&
+ ( strcmp(str, android::CameraParameters::TRUE) == 0 ) ) {
+
+ if ( !mBracketingSet ) {
+ mPendingCaptureSettings |= SetBurstExpBracket;
+ }
+
+ mBracketingSet = true;
+ } else {
+
+ if ( mBracketingSet ) {
+ mPendingCaptureSettings |= SetBurstExpBracket;
+ }
+
+ mBracketingSet = false;
+ }
+
+ if ( (str = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE)) != NULL ) {
+ parseExpRange(str, mExposureBracketingValues, NULL,
+ mExposureGainBracketingModes,
+ EXP_BRACKET_RANGE, mExposureBracketingValidEntries);
+ if (mCapMode == OMXCameraAdapter::CP_CAM) {
+ mExposureBracketMode = OMX_BracketVectorShot;
+ } else {
+ mExposureBracketMode = OMX_BracketExposureRelativeInEV;
+ }
+ mPendingCaptureSettings |= SetBurstExpBracket;
+ } else if ( (str = params.get(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE)) != NULL) {
+ parseExpRange(str, mExposureBracketingValues, mExposureGainBracketingValues,
+ mExposureGainBracketingModes,
+ EXP_BRACKET_RANGE, mExposureBracketingValidEntries);
+ if (mCapMode == OMXCameraAdapter::CP_CAM) {
+ mExposureBracketMode = OMX_BracketVectorShot;
+ } else {
+ mExposureBracketMode = OMX_BracketExposureGainAbsolute;
+ }
+ mPendingCaptureSettings |= SetBurstExpBracket;
+ } else {
+ // always set queued shot config in CPCAM mode
+ if (mCapMode == OMXCameraAdapter::CP_CAM) {
+ mExposureBracketMode = OMX_BracketVectorShot;
+ mPendingCaptureSettings |= SetBurstExpBracket;
+ }
+ // if bracketing was previously set...we set again before capturing to clear
+ if (mExposureBracketingValidEntries) {
+ mPendingCaptureSettings |= SetBurstExpBracket;
+ mExposureBracketingValidEntries = 0;
+ }
+ }
+
+ str = params.get(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE);
+ if ( NULL != str ) {
+ parseExpRange(str, mZoomBracketingValues, NULL, NULL,
+ ZOOM_BRACKET_RANGE, mZoomBracketingValidEntries);
+ mCurrentZoomBracketing = 0;
+ mZoomBracketingEnabled = true;
+ } else {
+ if (mZoomBracketingValidEntries) {
+ mZoomBracketingValidEntries = 0;
+ }
+ mZoomBracketingEnabled = false;
+ }
+#endif
+
+ // Flush config queue
+ // If TRUE: Flush queue and abort processing before enqueing
+ valstr = params.get(TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE);
+ if ( NULL != valstr ) {
+ if ( 0 == strcmp(valstr, android::CameraParameters::TRUE) ) {
+ mFlushShotConfigQueue = true;
+ } else if ( 0 == strcmp(valstr, android::CameraParameters::FALSE) ) {
+ mFlushShotConfigQueue = false;
+ } else {
+ CAMHAL_LOGE("Missing flush shot config parameter. Will use current (%s)",
+ mFlushShotConfigQueue ? "true" : "false");
+ }
+ }
+
+ if ( params.getInt(android::CameraParameters::KEY_ROTATION) != -1 )
+ {
+ if (params.getInt(android::CameraParameters::KEY_ROTATION) != (int) mPictureRotation) {
+ mPendingCaptureSettings |= SetRotation;
+ }
+ if (cap->mFrameLayoutType == OMX_TI_StereoFrameLayout2D) {
+ mPictureRotation = params.getInt(android::CameraParameters::KEY_ROTATION);
+ } else {
+ mPictureRotation = 0;
+ }
+ }
+ else
+ {
+ if (mPictureRotation) mPendingCaptureSettings |= SetRotation;
+ mPictureRotation = 0;
+ }
+
+ CAMHAL_LOGVB("Picture Rotation set %d", mPictureRotation);
+
+#ifdef OMAP_ENHANCEMENT
+ // Read Sensor Orientation and set it based on perating mode
+ varint = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION);
+ if ( varint != -1 )
+ {
+ mSensorOrientation = varint;
+ if (mSensorOrientation == 270 ||mSensorOrientation==90)
+ {
+ CAMHAL_LOGEA(" Orientation is 270/90. So setting counter rotation to Ducati");
+ mSensorOrientation +=180;
+ mSensorOrientation%=360;
+ }
+ }
+ else
+ {
+ mSensorOrientation = 0;
+ }
+
+ CAMHAL_LOGVB("Sensor Orientation set : %d", mSensorOrientation);
+#endif
+
+#ifdef OMAP_ENHANCEMENT_BURST_CAPTURE
+ varint = params.getInt(TICameraParameters::KEY_BURST);
+ if ( varint >= 1 )
+ {
+ if (varint != (int) mBurstFrames) {
+ mPendingCaptureSettings |= SetBurstExpBracket;
+ }
+ mBurstFrames = varint;
+ }
+ else
+ {
+ if (mBurstFrames != 1) mPendingCaptureSettings |= SetBurstExpBracket;
+ mBurstFrames = 1;
+ }
+
+ CAMHAL_LOGVB("Burst Frames set %d", mBurstFrames);
+#endif
+
+ varint = params.getInt(android::CameraParameters::KEY_JPEG_QUALITY);
+ if ( varint >= MIN_JPEG_QUALITY && varint <= MAX_JPEG_QUALITY ) {
+ if (varint != mPictureQuality) {
+ mPendingCaptureSettings |= SetQuality;
+ mPictureQuality = varint;
+ }
+ } else {
+ if (mPictureQuality != MAX_JPEG_QUALITY) {
+ mPendingCaptureSettings |= SetQuality;
+ mPictureQuality = MAX_JPEG_QUALITY;
+ }
+ }
+
+ CAMHAL_LOGVB("Picture Quality set %d", mPictureQuality);
+
+ varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ if ( varint >= 0 ) {
+ if (varint != mThumbWidth) {
+ mPendingCaptureSettings |= SetThumb;
+ mThumbWidth = varint;
+ }
+ } else {
+ if (mThumbWidth != DEFAULT_THUMB_WIDTH) {
+ mPendingCaptureSettings |= SetThumb;
+ mThumbWidth = DEFAULT_THUMB_WIDTH;
+ }
+ }
+
+ CAMHAL_LOGVB("Picture Thumb width set %d", mThumbWidth);
+
+ varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ if ( varint >= 0 ) {
+ if (varint != mThumbHeight) {
+ mPendingCaptureSettings |= SetThumb;
+ mThumbHeight = varint;
+ }
+ } else {
+ if (mThumbHeight != DEFAULT_THUMB_HEIGHT) {
+ mPendingCaptureSettings |= SetThumb;
+ mThumbHeight = DEFAULT_THUMB_HEIGHT;
+ }
+ }
+
+ CAMHAL_LOGVB("Picture Thumb height set %d", mThumbHeight);
+
+ varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ if ( varint >= MIN_JPEG_QUALITY && varint <= MAX_JPEG_QUALITY ) {
+ if (varint != mThumbQuality) {
+ mPendingCaptureSettings |= SetThumb;
+ mThumbQuality = varint;
+ }
+ } else {
+ if (mThumbQuality != MAX_JPEG_QUALITY) {
+ mPendingCaptureSettings |= SetThumb;
+ mThumbQuality = MAX_JPEG_QUALITY;
+ }
+ }
+
+ CAMHAL_LOGDB("Thumbnail Quality set %d", mThumbQuality);
+
+ if (mFirstTimeInit) {
+ mPendingCaptureSettings = ECapturesettingsAll;
+ }
+
+ cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex];
+ cap->mWidth = params.getInt(TICameraParameters::RAW_WIDTH);
+ cap->mHeight = params.getInt(TICameraParameters::RAW_HEIGHT);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::getPictureBufferSize(CameraFrame &frame, size_t bufferCount)
+{
+ status_t ret = NO_ERROR;
+ OMXCameraPortParameters *imgCaptureData = NULL;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+
+ // If any settings have changed that need to be set with SetParam,
+ // we will need to disable the port to set them
+ if ((mPendingCaptureSettings & ECaptureParamSettings)) {
+ disableImagePort();
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+ }
+
+ if (mPendingCaptureSettings & SetFormat) {
+ ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ frame.mLength = imgCaptureData->mBufSize;
+ frame.mWidth = imgCaptureData->mWidth;
+ frame.mHeight = imgCaptureData->mHeight;
+ frame.mAlignment = imgCaptureData->mStride;
+ CAMHAL_LOGDB("getPictureBufferSize: width:%u height:%u alignment:%u length:%u",
+ frame.mWidth, frame.mHeight, frame.mAlignment, frame.mLength);
+ }
+ else
+ {
+ CAMHAL_LOGEB("setFormat() failed 0x%x", ret);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+int OMXCameraAdapter::getBracketingValueMode(const char *a, const char *b) const
+{
+ BracketingValueMode bvm = BracketingValueAbsolute;
+
+ if ( (NULL != b) &&
+ (NULL != a) &&
+ (a < b) &&
+ ( (NULL != memchr(a, '+', b - a)) ||
+ (NULL != memchr(a, '-', b - a)) ) ) {
+ bvm = BracketingValueRelative;
+ }
+ return bvm;
+}
+
+status_t OMXCameraAdapter::parseExpRange(const char *rangeStr,
+ int *expRange,
+ int *gainRange,
+ int *expGainModes,
+ size_t count,
+ size_t &validEntries)
+{
+ status_t ret = NO_ERROR;
+ char *end = NULL;
+ const char *startPtr = NULL;
+ size_t i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == rangeStr ){
+ return -EINVAL;
+ }
+
+ if ( NULL == expRange ){
+ return -EINVAL;
+ }
+
+ if ( NO_ERROR == ret ) {
+ startPtr = rangeStr;
+ do {
+ // Relative Exposure example: "-30,-10, 0, 10, 30"
+ // Absolute Gain ex. (exposure,gain) pairs: "(100,300),(200,300),(400,300),(800,300),(1600,300)"
+ // Relative Gain ex. (exposure,gain) pairs: "(-30,+0),(-10, +0),(+0,+0),(+10,+0),(+30,+0)"
+ // Forced relative Exposure example: "-30F,-10F, 0F, 10F, 30F"
+ // Forced absolute Gain ex. (exposure,gain) pairs: "(100,300)F,(200,300)F,(400,300)F,(800,300)F,(1600,300)F"
+ // Forced relative Gain ex. (exposure,gain) pairs: "(-30,+0)F,(-10, +0)F,(+0,+0)F,(+10,+0)F,(+30,+0)F"
+
+ // skip '(' and ','
+ while ((*startPtr == '(') || (*startPtr == ',')) startPtr++;
+
+ expRange[i] = (int)strtol(startPtr, &end, 10);
+
+ if (expGainModes) {
+ // if gainRange is given rangeStr should be (exposure, gain) pair
+ if (gainRange) {
+ int bvm_exp = getBracketingValueMode(startPtr, end);
+ startPtr = end + 1; // for the ','
+ gainRange[i] = (int)strtol(startPtr, &end, 10);
+
+ if (BracketingValueAbsolute == bvm_exp) {
+ expGainModes[i] = getBracketingValueMode(startPtr, end);
+ } else {
+ expGainModes[i] = bvm_exp;
+ }
+ } else {
+ expGainModes[i] = BracketingValueCompensation;
+ }
+ }
+ startPtr = end;
+
+ // skip ')'
+ while (*startPtr == ')') startPtr++;
+
+ // Check for "forced" key
+ if (expGainModes) {
+ while ((*startPtr == 'F') || (*startPtr == 'f')) {
+ if ( BracketingValueAbsolute == expGainModes[i] ) {
+ expGainModes[i] = BracketingValueAbsoluteForced;
+ } else if ( BracketingValueRelative == expGainModes[i] ) {
+ expGainModes[i] = BracketingValueRelativeForced;
+ } else if ( BracketingValueCompensation == expGainModes[i] ) {
+ expGainModes[i] = BracketingValueCompensationForced;
+ } else {
+ CAMHAL_LOGE("Unexpected old mode 0x%x", expGainModes[i]);
+ }
+ startPtr++;
+ }
+ }
+
+ i++;
+
+ } while ((startPtr[0] != '\0') && (i < count));
+ validEntries = i;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::doExposureBracketing(int *evValues,
+ int *evValues2,
+ int *evModes2,
+ size_t evCount,
+ size_t frameCount,
+ bool flush,
+ OMX_BRACKETMODETYPE bracketMode)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( NULL == evValues ) {
+ CAMHAL_LOGEA("Exposure compensation values pointer is invalid");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret ) {
+ if (bracketMode == OMX_BracketVectorShot) {
+ ret = setVectorShot(evValues, evValues2, evModes2, evCount, frameCount, flush, bracketMode);
+ } else {
+ ret = setExposureBracketing(evValues, evValues2, evCount, frameCount, bracketMode);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setVectorStop(bool toPreview)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_VECTSHOTSTOPMETHODTYPE vecShotStop;
+
+
+ LOG_FUNCTION_NAME;
+
+ OMX_INIT_STRUCT_PTR(&vecShotStop, OMX_TI_CONFIG_VECTSHOTSTOPMETHODTYPE);
+
+ vecShotStop.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+ if (toPreview) {
+ vecShotStop.eStopMethod = OMX_TI_VECTSHOTSTOPMETHOD_GOTO_PREVIEW;
+ } else {
+ vecShotStop.eStopMethod = OMX_TI_VECTSHOTSTOPMETHOD_WAIT_IN_CAPTURE;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigVectShotStopMethod,
+ &vecShotStop);
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while configuring bracket shot 0x%x", eError);
+ } else {
+ CAMHAL_LOGDA("Bracket shot configured successfully");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::initVectorShot()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CAPTUREMODETYPE expCapMode;
+ OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode;
+
+ LOG_FUNCTION_NAME;
+
+ if (NO_ERROR == ret) {
+ OMX_INIT_STRUCT_PTR (&expCapMode, OMX_CONFIG_CAPTUREMODETYPE);
+ expCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ expCapMode.bFrameLimited = OMX_FALSE;
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCaptureMode,
+ &expCapMode);
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGEB("Error while configuring capture mode 0x%x", eError);
+ goto exit;
+ } else {
+ CAMHAL_LOGDA("Camera capture mode configured successfully");
+ }
+ }
+
+ if (NO_ERROR == ret) {
+ OMX_INIT_STRUCT_PTR (&extExpCapMode, OMX_CONFIG_EXTCAPTUREMODETYPE);
+ extExpCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ extExpCapMode.bEnableBracketing = OMX_TRUE;
+ extExpCapMode.tBracketConfigType.eBracketMode = OMX_BracketVectorShot;
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigExtCaptureMode,
+ &extExpCapMode);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring extended capture mode 0x%x", eError);
+ goto exit;
+ } else {
+ CAMHAL_LOGDA("Extended camera capture mode configured successfully");
+ }
+ }
+
+
+ if (NO_ERROR == ret) {
+ // set vector stop method to stop in capture
+ ret = setVectorStop(false);
+ }
+
+ exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::setVectorShot(int *evValues,
+ int *evValues2,
+ int *evModes2,
+ size_t evCount,
+ size_t frameCount,
+ bool flush,
+ OMX_BRACKETMODETYPE bracketMode)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_ENQUEUESHOTCONFIGS enqueueShotConfigs;
+ OMX_TI_CONFIG_QUERYAVAILABLESHOTS queryAvailableShots;
+ bool doFlush = flush;
+
+ LOG_FUNCTION_NAME;
+
+ OMX_INIT_STRUCT_PTR(&enqueueShotConfigs, OMX_TI_CONFIG_ENQUEUESHOTCONFIGS);
+ OMX_INIT_STRUCT_PTR(&queryAvailableShots, OMX_TI_CONFIG_QUERYAVAILABLESHOTS);
+
+ queryAvailableShots.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigQueryAvailableShots,
+ &queryAvailableShots);
+ if (OMX_ErrorNone != eError) {
+ CAMHAL_LOGE("Error getting available shots 0x%x", eError);
+ goto exit;
+ } else {
+ CAMHAL_LOGD("AVAILABLE SHOTS: %d", queryAvailableShots.nAvailableShots);
+ if (queryAvailableShots.nAvailableShots < evCount) {
+ // TODO(XXX): Need to implement some logic to handle this error
+ CAMHAL_LOGE("Not enough available shots to fulfill this queue request");
+ ret = -ENOSPC;
+ goto exit;
+ }
+ }
+
+ for ( unsigned int confID = 0; confID < evCount; ) {
+ unsigned int i;
+ for ( i = 0 ; (i < ARRAY_SIZE(enqueueShotConfigs.nShotConfig)) && (confID < evCount); i++, confID++ ) {
+ CAMHAL_LOGD("%2u: (%7d,%4d) mode: %d", confID, evValues[confID], evValues2[confID], evModes2[confID]);
+ enqueueShotConfigs.nShotConfig[i].nConfigId = confID;
+ enqueueShotConfigs.nShotConfig[i].nFrames = 1;
+ if ( (BracketingValueCompensation == evModes2[confID]) ||
+ (BracketingValueCompensationForced == evModes2[confID]) ) {
+ // EV compensation
+ enqueueShotConfigs.nShotConfig[i].nEC = evValues[confID];
+ enqueueShotConfigs.nShotConfig[i].nExp = 0;
+ enqueueShotConfigs.nShotConfig[i].nGain = 0;
+ } else {
+ // exposure,gain pair
+ enqueueShotConfigs.nShotConfig[i].nEC = 0;
+ enqueueShotConfigs.nShotConfig[i].nExp = evValues[confID];
+ enqueueShotConfigs.nShotConfig[i].nGain = evValues2[confID];
+ }
+ enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_ABSOLUTE;
+ switch (evModes2[confID]) {
+ case BracketingValueAbsolute: // (exp,gain) pairs directly program sensor values
+ default :
+ enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_ABSOLUTE;
+ break;
+ case BracketingValueRelative: // (exp,gain) pairs relative to AE settings and constraints
+ case BracketingValueCompensation: // EV compensation relative to AE settings and constraints
+ enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_RELATIVE;
+ break;
+ case BracketingValueAbsoluteForced: // (exp,gain) pairs directly program sensor values
+ // are forced over constraints due to flicker, etc.
+ enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_FORCE_ABSOLUTE;
+ break;
+ case BracketingValueRelativeForced: // (exp, gain) pairs relative to AE settings AND settings
+ case BracketingValueCompensationForced: // EV compensation relative to AE settings and constraints
+ // are forced over constraints due to flicker, etc.
+ enqueueShotConfigs.nShotConfig[i].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_FORCE_RELATIVE;
+ break;
+ }
+ enqueueShotConfigs.nShotConfig[i].bNoSnapshot = OMX_FALSE; // TODO: Make this configurable
+ }
+
+ // Repeat last exposure and again
+ if ((confID == evCount) && (evCount > 0) && (frameCount > evCount) && (0 != i)) {
+ enqueueShotConfigs.nShotConfig[i-1].nFrames = frameCount - evCount;
+ }
+
+ enqueueShotConfigs.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+ enqueueShotConfigs.bFlushQueue = doFlush ? OMX_TRUE : OMX_FALSE;
+ enqueueShotConfigs.nNumConfigs = i;
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigEnqueueShotConfigs,
+ &enqueueShotConfigs);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring enqueue shot 0x%x", eError);
+ goto exit;
+ } else {
+ CAMHAL_LOGDA("Enqueue shot configured successfully");
+ }
+ // Flush only first time
+ doFlush = false;
+ }
+
+ // Handle burst capture (no any bracketing) case
+ if (0 == evCount) {
+ CAMHAL_LOGE("Handle burst capture (no any bracketing) case");
+ enqueueShotConfigs.nShotConfig[0].nConfigId = 0;
+ enqueueShotConfigs.nShotConfig[0].nFrames = frameCount;
+ enqueueShotConfigs.nShotConfig[0].nEC = 0;
+ enqueueShotConfigs.nShotConfig[0].nExp = 0;
+ enqueueShotConfigs.nShotConfig[0].nGain = 0;
+ enqueueShotConfigs.nShotConfig[0].eExpGainApplyMethod = OMX_TI_EXPGAINAPPLYMETHOD_RELATIVE;
+ enqueueShotConfigs.nShotConfig[0].bNoSnapshot = OMX_FALSE; // TODO: Make this configurable
+ enqueueShotConfigs.nNumConfigs = 1;
+ enqueueShotConfigs.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+ enqueueShotConfigs.bFlushQueue = doFlush ? OMX_TRUE : OMX_FALSE;
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigEnqueueShotConfigs,
+ &enqueueShotConfigs);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring enqueue shot 0x%x", eError);
+ goto exit;
+ } else {
+ CAMHAL_LOGDA("Enqueue shot configured successfully");
+ }
+ }
+
+ exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::setExposureBracketing(int *evValues,
+ int *evValues2,
+ size_t evCount,
+ size_t frameCount,
+ OMX_BRACKETMODETYPE bracketMode)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CAPTUREMODETYPE expCapMode;
+ OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&expCapMode, OMX_CONFIG_CAPTUREMODETYPE);
+ expCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ /// If frameCount>0 but evCount<=0, then this is the case of HQ burst.
+ //Otherwise, it is normal HQ capture
+ ///If frameCount>0 and evCount>0 then this is the cause of HQ Exposure bracketing.
+ if ( 0 == evCount && 0 == frameCount )
+ {
+ expCapMode.bFrameLimited = OMX_FALSE;
+ }
+ else
+ {
+ expCapMode.bFrameLimited = OMX_TRUE;
+ expCapMode.nFrameLimit = frameCount;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCaptureMode,
+ &expCapMode);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring capture mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera capture mode configured successfully");
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&extExpCapMode, OMX_CONFIG_EXTCAPTUREMODETYPE);
+ extExpCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ if ( 0 == evCount )
+ {
+ extExpCapMode.bEnableBracketing = OMX_FALSE;
+ }
+ else
+ {
+ extExpCapMode.bEnableBracketing = OMX_TRUE;
+ extExpCapMode.tBracketConfigType.eBracketMode = bracketMode;
+ extExpCapMode.tBracketConfigType.nNbrBracketingValues = evCount - 1;
+ }
+
+ for ( unsigned int i = 0 ; i < evCount ; i++ )
+ {
+ if (bracketMode == OMX_BracketExposureGainAbsolute) {
+ extExpCapMode.tBracketConfigType.nBracketValues[i] = evValues[i];
+ extExpCapMode.tBracketConfigType.nBracketValues2[i] = evValues2[i];
+ } else {
+ // assuming OMX_BracketExposureRelativeInEV
+ extExpCapMode.tBracketConfigType.nBracketValues[i] = ( evValues[i] * ( 1 << Q16_OFFSET ) ) / 10;
+ }
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigExtCaptureMode,
+ &extExpCapMode);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring extended capture mode 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Extended camera capture mode configured successfully");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setShutterCallback(bool enabled)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CALLBACKREQUESTTYPE shutterRequstCallback;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ OMX_INIT_STRUCT_PTR (&shutterRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
+ shutterRequstCallback.nPortIndex = OMX_ALL;
+
+ if ( enabled )
+ {
+ shutterRequstCallback.bEnable = OMX_TRUE;
+ shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback;
+ CAMHAL_LOGDA("Enabling shutter callback");
+ }
+ else
+ {
+ shutterRequstCallback.bEnable = OMX_FALSE;
+ shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback;
+ CAMHAL_LOGDA("Disabling shutter callback");
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigCallbackRequest,
+ &shutterRequstCallback);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error registering shutter callback 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDB("Shutter callback for index 0x%x registered successfully",
+ OMX_TI_IndexConfigShutterCallback);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::doBracketing(OMX_BUFFERHEADERTYPE *pBuffHeader,
+ CameraFrame::FrameType typeOfFrame)
+{
+ status_t ret = NO_ERROR;
+ int currentBufferIdx, nextBufferIdx;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is not in executing state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CameraBuffer *buffer = (CameraBuffer *)pBuffHeader->pAppPrivate;
+ currentBufferIdx = buffer->index;
+
+ if ( currentBufferIdx >= imgCaptureData->mNumBufs)
+ {
+ CAMHAL_LOGEB("Invalid bracketing buffer index 0x%x", currentBufferIdx);
+ ret = -EINVAL;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mBracketingBuffersQueued[currentBufferIdx] = false;
+ mBracketingBuffersQueuedCount--;
+
+ if ( 0 >= mBracketingBuffersQueuedCount )
+ {
+ nextBufferIdx = ( currentBufferIdx + 1 ) % imgCaptureData->mNumBufs;
+ mBracketingBuffersQueued[nextBufferIdx] = true;
+ mBracketingBuffersQueuedCount++;
+ mLastBracetingBufferIdx = nextBufferIdx;
+ setFrameRefCountByType((CameraBuffer *)imgCaptureData->mBufferHeader[nextBufferIdx]->pAppPrivate, typeOfFrame, 1);
+ returnFrame((CameraBuffer *)imgCaptureData->mBufferHeader[nextBufferIdx]->pAppPrivate, typeOfFrame);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::sendBracketFrames(size_t &framesSent)
+{
+ status_t ret = NO_ERROR;
+ int currentBufferIdx;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+ framesSent = 0;
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is not in executing state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ currentBufferIdx = mLastBracetingBufferIdx;
+ do
+ {
+ currentBufferIdx++;
+ currentBufferIdx %= imgCaptureData->mNumBufs;
+ if (!mBracketingBuffersQueued[currentBufferIdx] )
+ {
+ CameraFrame cameraFrame;
+ sendCallBacks(cameraFrame,
+ imgCaptureData->mBufferHeader[currentBufferIdx],
+ imgCaptureData->mImageType,
+ imgCaptureData);
+ framesSent++;
+ }
+ } while ( currentBufferIdx != mLastBracetingBufferIdx );
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startBracketing(int range)
+{
+ status_t ret = NO_ERROR;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is not in executing state");
+ ret = -EINVAL;
+ }
+
+ {
+ android::AutoMutex lock(mBracketingLock);
+
+ if ( mBracketingEnabled )
+ {
+ return ret;
+ }
+ }
+
+ if ( 0 == imgCaptureData->mNumBufs )
+ {
+ CAMHAL_LOGEB("Image capture buffers set to %d", imgCaptureData->mNumBufs);
+ ret = -EINVAL;
+ }
+
+ if ( mPending3Asettings )
+ apply3Asettings(mParameters3A);
+
+ if ( NO_ERROR == ret )
+ {
+ android::AutoMutex lock(mBracketingLock);
+
+ mBracketingRange = range;
+ mBracketingBuffersQueued = new bool[imgCaptureData->mNumBufs];
+ if ( NULL == mBracketingBuffersQueued )
+ {
+ CAMHAL_LOGEA("Unable to allocate bracketing management structures");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mBracketingBuffersQueuedCount = imgCaptureData->mNumBufs;
+ mBurstFramesAccum = imgCaptureData->mNumBufs;
+ mLastBracetingBufferIdx = mBracketingBuffersQueuedCount - 1;
+
+ for ( int i = 0 ; i < imgCaptureData->mNumBufs ; i++ )
+ {
+ mBracketingBuffersQueued[i] = true;
+ }
+
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CachedCaptureParameters* cap_params = cacheCaptureParameters();
+ ret = startImageCapture(true, cap_params);
+ delete cap_params;
+ {
+ android::AutoMutex lock(mBracketingLock);
+
+ if ( NO_ERROR == ret )
+ {
+ mBracketingEnabled = true;
+ }
+ else
+ {
+ mBracketingEnabled = false;
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::stopBracketing()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ ret = stopImageCapture();
+
+ android::AutoMutex lock(mBracketingLock);
+
+ if ( NULL != mBracketingBuffersQueued )
+ {
+ delete [] mBracketingBuffersQueued;
+ }
+
+ mBracketingBuffersQueued = NULL;
+ mBracketingEnabled = false;
+ mBracketingBuffersQueuedCount = 0;
+ mLastBracetingBufferIdx = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startImageCapture(bool bracketing, CachedCaptureParameters* capParams)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters * capData = NULL;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+ size_t bracketingSent = 0;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mImageCaptureLock);
+
+ if(!mCaptureConfigured)
+ {
+ ///Image capture was cancelled before we could start
+ return NO_ERROR;
+ }
+
+ if ( 0 != mStartCaptureSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mStartCaptureSem semaphore count %d", mStartCaptureSem.Count());
+ return NO_INIT;
+ }
+
+ if ( !bracketing ) {
+ if ((getNextState() & (CAPTURE_ACTIVE|BRACKETING_ACTIVE)) == 0) {
+ CAMHAL_LOGDA("trying starting capture when already canceled");
+ return NO_ERROR;
+ }
+ }
+
+ if (!capParams) {
+ CAMHAL_LOGE("Invalid cached parameters sent!");
+ return BAD_VALUE;
+ }
+
+ // Camera framework doesn't expect face callbacks once capture is triggered
+ pauseFaceDetection(true);
+
+ //During bracketing image capture is already active
+ {
+ android::AutoMutex lock(mBracketingLock);
+ if ( mBracketingEnabled )
+ {
+ //Stop bracketing, activate normal burst for the remaining images
+ mBracketingEnabled = false;
+ ret = sendBracketFrames(bracketingSent);
+
+ // Check if we accumulated enough buffers
+ if ( bracketingSent < ( mBracketingRange - 1 ) )
+ {
+ mCapturedFrames = mBracketingRange + ( ( mBracketingRange - 1 ) - bracketingSent );
+ }
+ else
+ {
+ mCapturedFrames = mBracketingRange;
+ }
+ mBurstFramesQueued = 0;
+ mBurstFramesAccum = mCapturedFrames;
+
+ if(ret != NO_ERROR)
+ goto EXIT;
+ else
+ return ret;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ if (capParams->mPendingCaptureSettings & SetRotation) {
+ mPendingCaptureSettings &= ~SetRotation;
+ ret = setPictureRotation(mPictureRotation);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error configuring image rotation %x", ret);
+ }
+ }
+
+ if (capParams->mPendingCaptureSettings & SetBurstExpBracket) {
+ mPendingCaptureSettings &= ~SetBurstExpBracket;
+ if ( mBracketingSet ) {
+ ret = doExposureBracketing(capParams->mExposureBracketingValues,
+ capParams->mExposureGainBracketingValues,
+ capParams->mExposureGainBracketingModes,
+ 0,
+ 0,
+ capParams->mFlushShotConfigQueue,
+ capParams->mExposureBracketMode);
+ } else {
+ ret = doExposureBracketing(capParams->mExposureBracketingValues,
+ capParams->mExposureGainBracketingValues,
+ capParams->mExposureGainBracketingModes,
+ capParams->mExposureBracketingValidEntries,
+ capParams->mBurstFrames,
+ capParams->mFlushShotConfigQueue,
+ capParams->mExposureBracketMode);
+ }
+
+ if ( ret != NO_ERROR ) {
+ CAMHAL_LOGEB("setExposureBracketing() failed %d", ret);
+ goto EXIT;
+ }
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ CameraHal::PPM("startImageCapture bracketing configs done: ", &mStartCapture);
+#endif
+
+ capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ //OMX shutter callback events are only available in hq mode
+ if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) {
+ if ( NO_ERROR == ret )
+ {
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_TI_IndexConfigShutterCallback,
+ mStartCaptureSem);
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setShutterCallback(true);
+ }
+
+ }
+
+ if (mPending3Asettings) {
+ apply3Asettings(mParameters3A);
+ }
+
+ if (ret == NO_ERROR) {
+ int index = 0;
+ int queued = 0;
+ android::AutoMutex lock(mBurstLock);
+
+ if (capParams->mFlushShotConfigQueue) {
+ // reset shot queue
+ mCapturedFrames = mBurstFrames;
+ mBurstFramesAccum = mBurstFrames;
+ mBurstFramesQueued = 0;
+ for ( int index = 0 ; index < capData->mNumBufs ; index++ ) {
+ if (OMXCameraPortParameters::FILL == capData->mStatus[index]) {
+ mBurstFramesQueued++;
+ }
+ }
+ } else {
+ mCapturedFrames += mBurstFrames;
+ mBurstFramesAccum += mBurstFrames;
+ }
+ CAMHAL_LOGD("mBurstFramesQueued = %d mBurstFramesAccum = %d index = %d "
+ "capData->mNumBufs = %d queued = %d capData->mMaxQueueable = %d",
+ mBurstFramesQueued,mBurstFramesAccum,index,
+ capData->mNumBufs,queued,capData->mMaxQueueable);
+ CAMHAL_LOGD("%d", (mBurstFramesQueued < mBurstFramesAccum)
+ && (index < capData->mNumBufs)
+ && (queued < capData->mMaxQueueable));
+ while ((mBurstFramesQueued < mBurstFramesAccum) &&
+ (index < capData->mNumBufs) &&
+ (queued < capData->mMaxQueueable)) {
+ if (capData->mStatus[index] == OMXCameraPortParameters::IDLE) {
+ CAMHAL_LOGDB("Queuing buffer on Capture port - %p",
+ capData->mBufferHeader[index]->pBuffer);
+ capData->mStatus[index] = OMXCameraPortParameters::FILL;
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp,
+ (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]);
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ mBurstFramesQueued++;
+ queued++;
+ } else if (OMXCameraPortParameters::FILL == capData->mStatus[index]) {
+ CAMHAL_LOGE("Not queueing index = %d", index);
+ queued++;
+ }
+ index++;
+ }
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ if (mRawCapture) {
+ capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex];
+
+ ///Queue all the buffers on capture port
+ for ( int index = 0 ; index < capData->mNumBufs ; index++ ) {
+ CAMHAL_LOGDB("Queuing buffer on Video port (for RAW capture) - 0x%x", ( unsigned int ) capData->mBufferHeader[index]->pBuffer);
+ capData->mStatus[index] = OMXCameraPortParameters::FILL;
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp,
+ (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+ }
+#endif
+
+ mWaitingForSnapshot = true;
+ mCaptureSignalled = false;
+
+ // Capturing command is not needed when capturing in video mode
+ // Only need to queue buffers on image ports
+ if ( ( mCapMode != VIDEO_MODE ) && ( mCapMode != VIDEO_MODE_HQ ) ) {
+ OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
+ bOMX.bEnabled = OMX_TRUE;
+
+ /// sending Capturing Command to the component
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCapturing,
+ &bOMX);
+
+ CAMHAL_LOGDB("Capture set - 0x%x", eError);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ CameraHal::PPM("startImageCapture image buffers queued and capture enabled: ", &mStartCapture);
+#endif
+
+ //OMX shutter callback events are only available in hq mode
+
+ if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode))
+ {
+ if ( NO_ERROR == ret )
+ {
+ ret = mStartCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT);
+ }
+
+ //If something bad happened while we wait
+ if (mComponentState != OMX_StateExecuting)
+ {
+ CAMHAL_LOGEA("Invalid State after Image Capture Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Shutter callback received");
+ notifyShutterSubscribers();
+ }
+ else
+ {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_TI_IndexConfigShutterCallback,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on shutter callback");
+ goto EXIT;
+ }
+
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ CameraHal::PPM("startImageCapture shutter event received: ", &mStartCapture);
+#endif
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ mWaitingForSnapshot = false;
+ mCaptureSignalled = false;
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::stopImageCapture()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+ OMXCameraPortParameters *imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mImageCaptureLock);
+
+ if (!mCaptureConfigured) {
+ //Capture is not ongoing, return from here
+ return NO_ERROR;
+ }
+
+ if ( 0 != mStopCaptureSem.Count() ) {
+ CAMHAL_LOGEB("Error mStopCaptureSem semaphore count %d", mStopCaptureSem.Count());
+ goto EXIT;
+ }
+
+ // TODO(XXX): Reprocessing is currently piggy-backing capture commands
+ if (mAdapterState == REPROCESS_STATE) {
+ ret = stopReprocess();
+ }
+
+ //Disable the callback first
+ mWaitingForSnapshot = false;
+
+ // OMX shutter callback events are only available in hq mode
+ if ((HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) {
+ //Disable the callback first
+ ret = setShutterCallback(false);
+
+ // if anybody is waiting on the shutter callback
+ // signal them and then recreate the semaphore
+ if ( 0 != mStartCaptureSem.Count() ) {
+
+ for (int i = mStartCaptureSem.Count(); i < 0; i++) {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_TI_IndexConfigShutterCallback,
+ NULL );
+ }
+ mStartCaptureSem.Create(0);
+ }
+ } else if (CP_CAM == mCapMode) {
+ // Reset shot config queue
+ OMX_TI_CONFIG_ENQUEUESHOTCONFIGS resetShotConfigs;
+ OMX_INIT_STRUCT_PTR(&resetShotConfigs, OMX_TI_CONFIG_ENQUEUESHOTCONFIGS);
+
+ resetShotConfigs.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+ resetShotConfigs.bFlushQueue = OMX_TRUE;
+ resetShotConfigs.nNumConfigs = 0;
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigEnqueueShotConfigs,
+ &resetShotConfigs);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while reset shot config 0x%x", eError);
+ goto EXIT;
+ } else {
+ CAMHAL_LOGDA("Shot config reset successfully");
+ }
+ }
+
+ //Wait here for the capture to be done, in worst case timeout and proceed with cleanup
+ mCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State Image Capture Stop Exitting!!!");
+ goto EXIT;
+ }
+
+ // Disable image capture
+ // Capturing command is not needed when capturing in video mode
+ if ( ( mCapMode != VIDEO_MODE ) && ( mCapMode != VIDEO_MODE_HQ ) ) {
+ OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
+ bOMX.bEnabled = OMX_FALSE;
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCapturing,
+ &bOMX);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGDB("Error during SetConfig- 0x%x", eError);
+ ret = -1;
+ goto EXIT;
+ }
+ }
+
+ CAMHAL_LOGDB("Capture set - 0x%x", eError);
+
+ mCaptureSignalled = true; //set this to true if we exited because of timeout
+
+ {
+ android::AutoMutex lock(mFrameCountMutex);
+ mFrameCount = 0;
+ mFirstFrameCondition.broadcast();
+ }
+
+ // Stop is always signalled externally in CPCAM mode
+ // We need to make sure we really stop
+ if ((mCapMode == CP_CAM)) {
+ disableReprocess();
+ disableImagePort();
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+ }
+
+ // Moving code for below commit here as an optimization for continuous capture,
+ // so focus settings don't have to reapplied after each capture
+ // c78fa2a CameraHAL: Always reset focus mode after capture
+ // Workaround when doing many consecutive shots, CAF wasn't getting restarted.
+ mPending3Asettings |= SetFocus;
+
+ mCapturedFrames = 0;
+ mBurstFramesAccum = 0;
+ mBurstFramesQueued = 0;
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ //Release image buffers
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+
+ {
+ android::AutoMutex lock(mFrameCountMutex);
+ mFrameCount = 0;
+ mFirstFrameCondition.broadcast();
+ }
+
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::disableImagePort(){
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters *imgCaptureData = NULL;
+ OMXCameraPortParameters *imgRawCaptureData = NULL;
+
+ if (!mCaptureConfigured) {
+ return NO_ERROR;
+ }
+
+ mCaptureConfigured = false;
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+ imgRawCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex]; // for RAW capture
+
+ ///Register for Image port Disable event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mImagePortIndex,
+ mStopCaptureSem);
+ ///Disable Capture Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+
+ ///Free all the buffers on capture port
+ if (imgCaptureData) {
+ CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgCaptureData->mNumBufs);
+ for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++) {
+ CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x",
+ ( unsigned int ) imgCaptureData->mBufferHeader[index]->pBuffer);
+ eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
+ mCameraAdapterParameters.mImagePortIndex,
+ (OMX_BUFFERHEADERTYPE*)imgCaptureData->mBufferHeader[index]);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+ }
+ CAMHAL_LOGDA("Waiting for port disable");
+ //Wait for the image port enable event
+ ret = mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid)
+ {
+ CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret ) {
+ CAMHAL_LOGDA("Port disabled");
+ } else {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on port disable");
+ goto EXIT;
+ }
+
+ deinitInternalBuffers(mCameraAdapterParameters.mImagePortIndex);
+
+ // since port settings are not persistent after port is disabled...
+ mPendingCaptureSettings |= SetFormat;
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+
+ if (mRawCapture) {
+ ///Register for Video port Disable event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ mStopCaptureSem);
+ ///Disable RawCapture Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ NULL);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ ///Free all the buffers on RawCapture port
+ if (imgRawCaptureData) {
+ CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgRawCaptureData->mNumBufs);
+ for ( int index = 0 ; index < imgRawCaptureData->mNumBufs ; index++) {
+ CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x", ( unsigned int ) imgRawCaptureData->mBufferHeader[index]->pBuffer);
+ eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
+ mCameraAdapterParameters.mVideoPortIndex,
+ (OMX_BUFFERHEADERTYPE*)imgRawCaptureData->mBufferHeader[index]);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+ }
+ CAMHAL_LOGDA("Waiting for Video port disable");
+ //Wait for the image port enable event
+ mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ CAMHAL_LOGDA("Video Port disabled");
+ }
+#endif
+
+EXIT:
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::initInternalBuffers(OMX_U32 portIndex)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ int index = 0;
+ OMX_TI_PARAM_USEBUFFERDESCRIPTOR bufferdesc;
+
+ /* Indicate to Ducati that we're planning to use dynamically-mapped buffers */
+ OMX_INIT_STRUCT_PTR (&bufferdesc, OMX_TI_PARAM_USEBUFFERDESCRIPTOR);
+ bufferdesc.nPortIndex = portIndex;
+ bufferdesc.bEnabled = OMX_FALSE;
+ bufferdesc.eBufferType = OMX_TI_BufferTypePhysicalPageList;
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexUseBufferDescriptor,
+ &bufferdesc);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SetParameter - %x", eError);
+ return -EINVAL;
+ }
+
+ CAMHAL_LOGDA("Initializing internal buffers");
+ do {
+ OMX_TI_PARAM_COMPONENTBUFALLOCTYPE bufferalloc;
+ OMX_TI_PARAM_COMPONENTBUFALLOCTYPE bufferallocset;
+ OMX_INIT_STRUCT_PTR (&bufferalloc, OMX_TI_PARAM_COMPONENTBUFALLOCTYPE);
+ bufferalloc.nPortIndex = portIndex;
+ bufferalloc.nIndex = index;
+
+ eError = OMX_GetParameter (mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexParamComponentBufferAllocation,
+ &bufferalloc);
+ if (eError == OMX_ErrorNoMore) {
+ return NO_ERROR;
+ }
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("GetParameter failed error = 0x%x", eError);
+ break;
+ }
+
+ CAMHAL_LOGDB("Requesting buftype %d of size %dx%d",
+ (int)bufferalloc.eBufType, (int)bufferalloc.nAllocWidth,
+ (int)bufferalloc.nAllocLines);
+
+ bufferalloc.eBufType = OMX_TI_BufferTypeHardwareReserved1D;
+
+ OMX_INIT_STRUCT_PTR (&bufferallocset, OMX_TI_PARAM_COMPONENTBUFALLOCTYPE);
+ bufferallocset.nPortIndex = portIndex;
+ bufferallocset.nIndex = index;
+ bufferallocset.eBufType = OMX_TI_BufferTypeHardwareReserved1D;
+ bufferallocset.nAllocWidth = bufferalloc.nAllocWidth;
+ bufferallocset.nAllocLines = bufferalloc.nAllocLines;
+
+ eError = OMX_SetParameter (mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexParamComponentBufferAllocation,
+ &bufferallocset);
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("SetParameter failed, error=%08x", eError);
+ if (eError == OMX_ErrorNoMore) return NO_ERROR;
+ break;
+ }
+
+ index++;
+
+ /* 1 is an arbitrary limit */
+ } while (index < 1);
+
+ CAMHAL_LOGV("Ducati requested too many (>1) internal buffers");
+
+ return -EINVAL;
+}
+
+status_t OMXCameraAdapter::deinitInternalBuffers(OMX_U32 portIndex)
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_PARAM_USEBUFFERDESCRIPTOR bufferdesc;
+
+ OMX_INIT_STRUCT_PTR (&bufferdesc, OMX_TI_PARAM_USEBUFFERDESCRIPTOR);
+ bufferdesc.nPortIndex = portIndex;
+ bufferdesc.bEnabled = OMX_FALSE;
+ bufferdesc.eBufferType = OMX_TI_BufferTypeDefault;
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexUseBufferDescriptor,
+ &bufferdesc);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SetParameter - %x", eError);
+ return -EINVAL;
+ }
+
+ OMX_TI_PARAM_COMPONENTBUFALLOCTYPE bufferalloc;
+ OMX_INIT_STRUCT_PTR (&bufferalloc, OMX_TI_PARAM_COMPONENTBUFALLOCTYPE);
+ bufferalloc.nPortIndex = portIndex;
+ bufferalloc.eBufType = OMX_TI_BufferTypeDefault;
+ bufferalloc.nAllocWidth = 1;
+ bufferalloc.nAllocLines = 1;
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexParamComponentBufferAllocation,
+ &bufferalloc);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SetParameter - %x", eError);
+ return -EINVAL;
+ }
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::UseBuffersCapture(CameraBuffer * bufArr, int num)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+ OMXCameraPortParameters cap;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( 0 != mUseCaptureSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count());
+ return BAD_VALUE;
+ }
+
+ CAMHAL_ASSERT(num > 0);
+
+ // if some setting that requires a SetParameter (including
+ // changing buffer types) then we need to disable the port
+ // before being allowed to apply the settings
+ if ((mPendingCaptureSettings & ECaptureParamSettings) ||
+ bufArr[0].type != imgCaptureData->mBufferType ||
+ imgCaptureData->mNumBufs != num) {
+ if (mCaptureConfigured) {
+ disableImagePort();
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+ }
+
+ imgCaptureData->mBufferType = bufArr[0].type;
+ imgCaptureData->mNumBufs = num;
+
+ CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth);
+ CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mHeight);
+
+ if (mPendingCaptureSettings & SetFormat) {
+ mPendingCaptureSettings &= ~SetFormat;
+ ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
+ if ( ret != NO_ERROR ) {
+ CAMHAL_LOGEB("setFormat() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+ }
+
+ if (mPendingCaptureSettings & SetThumb) {
+ mPendingCaptureSettings &= ~SetThumb;
+ ret = setThumbnailParams(mThumbWidth, mThumbHeight, mThumbQuality);
+ if ( NO_ERROR != ret) {
+ CAMHAL_LOGEB("Error configuring thumbnail size %x", ret);
+ return ret;
+ }
+ }
+
+ if (mPendingCaptureSettings & SetQuality) {
+ mPendingCaptureSettings &= ~SetQuality;
+ ret = setImageQuality(mPictureQuality);
+ if ( NO_ERROR != ret) {
+ CAMHAL_LOGEB("Error configuring image quality %x", ret);
+ goto EXIT;
+ }
+ }
+
+ // Configure DOMX to use either gralloc handles or vptrs
+ {
+ OMX_TI_PARAMUSENATIVEBUFFER domxUseGrallocHandles;
+ OMX_INIT_STRUCT_PTR (&domxUseGrallocHandles, OMX_TI_PARAMUSENATIVEBUFFER);
+
+ domxUseGrallocHandles.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+ if (bufArr[0].type == CAMERA_BUFFER_ANW) {
+ CAMHAL_LOGD ("Using ANW Buffers");
+ initInternalBuffers(mCameraAdapterParameters.mImagePortIndex);
+ domxUseGrallocHandles.bEnable = OMX_TRUE;
+ } else {
+ CAMHAL_LOGD ("Using ION Buffers");
+ domxUseGrallocHandles.bEnable = OMX_FALSE;
+ }
+
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexUseNativeBuffers, &domxUseGrallocHandles);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SetParameter - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Takepicture image port configuration: ", &bufArr->ppmStamp);
+
+#endif
+
+ // Register for Image port ENABLE event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mImagePortIndex,
+ mUseCaptureSem);
+
+ // Enable Capture Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+
+ CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
+ GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
+
+ for (int index = 0 ; index < imgCaptureData->mNumBufs ; index++) {
+ OMX_BUFFERHEADERTYPE *pBufferHdr;
+ CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d",
+ (unsigned int)bufArr[index].opaque,
+ (int)imgCaptureData->mBufSize);
+
+ eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp,
+ &pBufferHdr,
+ mCameraAdapterParameters.mImagePortIndex,
+ 0,
+ imgCaptureData->mBufSize,
+ (OMX_U8*)camera_buffer_get_omx_ptr(&bufArr[index]));
+
+ CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
+ GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
+
+ pBufferHdr->pAppPrivate = (OMX_PTR) &bufArr[index];
+ bufArr[index].index = index;
+ pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ pBufferHdr->nVersion.s.nVersionMajor = 1 ;
+ pBufferHdr->nVersion.s.nVersionMinor = 1 ;
+ pBufferHdr->nVersion.s.nRevision = 0;
+ pBufferHdr->nVersion.s.nStep = 0;
+ imgCaptureData->mBufferHeader[index] = pBufferHdr;
+ imgCaptureData->mStatus[index] = OMXCameraPortParameters::IDLE;
+ }
+
+ // Wait for the image port enable event
+ CAMHAL_LOGDA("Waiting for port enable");
+ ret = mUseCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ // If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid) {
+ CAMHAL_LOGEA("Invalid State after Enable Image Port Exitting!!!");
+ goto EXIT;
+ }
+
+ if (ret != NO_ERROR) {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on port enable");
+ goto EXIT;
+ }
+ CAMHAL_LOGDA("Port enabled");
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Takepicture image port enabled and buffers registered: ", &bufArr->ppmStamp);
+
+#endif
+
+ if (mNextState != LOADED_REPROCESS_CAPTURE_STATE) {
+ // Enable WB and vector shot extra data for metadata
+ setExtraData(true, mCameraAdapterParameters.mImagePortIndex, OMX_WhiteBalance);
+ setExtraData(true, mCameraAdapterParameters.mImagePortIndex, OMX_TI_LSCTable);
+ }
+
+ // CPCam mode only supports vector shot
+ // Regular capture is not supported
+ if ( (mCapMode == CP_CAM) && (mNextState != LOADED_REPROCESS_CAPTURE_STATE) ) {
+ initVectorShot();
+ }
+
+ mCaptureBuffersAvailable.clear();
+ for (unsigned int i = 0; i < imgCaptureData->mMaxQueueable; i++ ) {
+ mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 0);
+ }
+
+ // initial ref count for undeqeueued buffers is 1 since buffer provider
+ // is still holding on to it
+ for (unsigned int i = imgCaptureData->mMaxQueueable; i < imgCaptureData->mNumBufs; i++ ) {
+ mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 1);
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setupEXIF();
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
+ }
+ }
+
+ // Choose proper single preview mode for cp capture (reproc or hs)
+ if (( NO_ERROR == ret) && (OMXCameraAdapter::CP_CAM == mCapMode)) {
+ OMX_TI_CONFIG_SINGLEPREVIEWMODETYPE singlePrevMode;
+ OMX_INIT_STRUCT_PTR (&singlePrevMode, OMX_TI_CONFIG_SINGLEPREVIEWMODETYPE);
+ if (mNextState == LOADED_CAPTURE_STATE) {
+ singlePrevMode.eMode = OMX_TI_SinglePreviewMode_ImageCaptureHighSpeed;
+ } else if (mNextState == LOADED_REPROCESS_CAPTURE_STATE) {
+ singlePrevMode.eMode = OMX_TI_SinglePreviewMode_Reprocess;
+ } else {
+ CAMHAL_LOGE("Wrong state trying to start a capture in CPCAM mode?");
+ singlePrevMode.eMode = OMX_TI_SinglePreviewMode_ImageCaptureHighSpeed;
+ }
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigSinglePreviewMode,
+ &singlePrevMode);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while configuring single preview mode 0x%x", eError);
+ ret = Utils::ErrorUtils::omxToAndroidError(eError);
+ } else {
+ CAMHAL_LOGDA("single preview mode configured successfully");
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Takepicture extra configs on image port done: ", &bufArr->ppmStamp);
+
+#endif
+
+ mCaptureConfigured = true;
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ if (mRawCapture) {
+ mCaptureConfigured = false;
+ }
+#endif
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ setExtraData(false, mCameraAdapterParameters.mImagePortIndex, OMX_WhiteBalance);
+ // TODO: WA: if domx client disables VectShotInfo metadata on the image port, this causes
+ // VectShotInfo to be disabled internally on preview port also. Remove setting in OMXCapture
+ // setExtraData(false, mCameraAdapterParameters.mImagePortIndex, OMX_TI_VectShotInfo);
+ setExtraData(false, mCameraAdapterParameters.mImagePortIndex, OMX_TI_LSCTable);
+ //Release image buffers
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+}
+status_t OMXCameraAdapter::UseBuffersRawCapture(CameraBuffer *bufArr, int num)
+{
+ LOG_FUNCTION_NAME
+ status_t ret;
+ OMX_ERRORTYPE eError;
+ OMXCameraPortParameters * imgRawCaptureData = NULL;
+ Utils::Semaphore camSem;
+ OMXCameraPortParameters cap;
+
+ imgRawCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoPortIndex];
+
+ if (mCaptureConfigured) {
+ return NO_ERROR;
+ }
+
+ camSem.Create();
+
+ // mWaitingForSnapshot is true only when we're in the process of capturing
+ if (mWaitingForSnapshot) {
+ ///Register for Video port Disable event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ camSem);
+
+ ///Disable Capture Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ NULL);
+
+ CAMHAL_LOGDA("Waiting for port disable");
+ //Wait for the image port enable event
+ camSem.Wait();
+ CAMHAL_LOGDA("Port disabled");
+ }
+
+ imgRawCaptureData->mNumBufs = num;
+
+ CAMHAL_LOGDB("RAW Max sensor width = %d", (int)imgRawCaptureData->mWidth);
+ CAMHAL_LOGDB("RAW Max sensor height = %d", (int)imgRawCaptureData->mHeight);
+
+ ret = setFormat(OMX_CAMERA_PORT_VIDEO_OUT_VIDEO, *imgRawCaptureData);
+
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGEB("setFormat() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT
+ return ret;
+ }
+
+ ///Register for Video port ENABLE event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ camSem);
+
+ ///Enable Video Capture Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mVideoPortIndex,
+ NULL);
+
+ mCaptureBuffersLength = (int)imgRawCaptureData->mBufSize;
+ for ( int index = 0 ; index < imgRawCaptureData->mNumBufs ; index++ ) {
+ OMX_BUFFERHEADERTYPE *pBufferHdr;
+ CAMHAL_LOGDB("OMX_UseBuffer rawCapture address: 0x%x, size = %d ",
+ (unsigned int)bufArr[index].opaque,
+ (int)imgRawCaptureData->mBufSize );
+
+ eError = OMX_UseBuffer( mCameraAdapterParameters.mHandleComp,
+ &pBufferHdr,
+ mCameraAdapterParameters.mVideoPortIndex,
+ 0,
+ mCaptureBuffersLength,
+ (OMX_U8*)camera_buffer_get_omx_ptr(&bufArr[index]));
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_UseBuffer = 0x%x", eError);
+ }
+
+ GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
+
+ pBufferHdr->pAppPrivate = (OMX_PTR) &bufArr[index];
+ bufArr[index].index = index;
+ pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ pBufferHdr->nVersion.s.nVersionMajor = 1 ;
+ pBufferHdr->nVersion.s.nVersionMinor = 1 ;
+ pBufferHdr->nVersion.s.nRevision = 0;
+ pBufferHdr->nVersion.s.nStep = 0;
+ imgRawCaptureData->mBufferHeader[index] = pBufferHdr;
+
+ }
+
+ //Wait for the image port enable event
+ CAMHAL_LOGDA("Waiting for port enable");
+ camSem.Wait();
+ CAMHAL_LOGDA("Port enabled");
+
+ if (NO_ERROR == ret) {
+ ret = setupEXIF();
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
+ }
+ }
+
+ mCapturedFrames = mBurstFrames;
+ mBurstFramesQueued = 0;
+ mCaptureConfigured = true;
+
+ EXIT:
+
+ if (eError != OMX_ErrorNone) {
+ if ( NULL != mErrorNotifier )
+ {
+ mErrorNotifier->errorNotify(eError);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT
+
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXDCC.cpp b/camera/OMXCameraAdapter/OMXDCC.cpp
new file mode 100644
index 0000000..cbaf2ab
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXDCC.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXDCC.cpp
+*
+* This file contains functionality for loading the DCC binaries.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+#include "OMXDCC.h"
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+namespace Ti {
+namespace Camera {
+
+#ifndef MOTOROLA_CAMERA
+android::String8 DCCHandler::DCCPath("/data/misc/camera/");
+#else
+android::String8 DCCHandler::DCCPath("/system/etc/omapcam/");
+#endif
+bool DCCHandler::mDCCLoaded = false;
+
+status_t DCCHandler::loadDCC(OMX_HANDLETYPE hComponent)
+{
+ OMX_ERRORTYPE dccError = OMX_ErrorNone;
+
+ if (!mDCCLoaded) {
+ dccError = initDCC(hComponent);
+ if (dccError != OMX_ErrorNone) {
+ CAMHAL_LOGE(" Error in DCC Init");
+ }
+
+ mDCCLoaded = true;
+ }
+
+ return Utils::ErrorUtils::omxToAndroidError(dccError);
+}
+
+OMX_ERRORTYPE DCCHandler::initDCC(OMX_HANDLETYPE hComponent)
+{
+ OMX_TI_PARAM_DCCURIINFO param;
+ OMX_PTR ptempbuf;
+ OMX_U16 nIndex = 0;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ int ret;
+ OMX_S32 status = 0;
+ android::Vector<android::String8 *> dccDirs;
+ OMX_U16 i;
+ MemoryManager memMgr;
+ CameraBuffer *dccBuffer = NULL;
+ int dccbuf_size = 0;
+ OMX_INIT_STRUCT_PTR(&param, OMX_TI_PARAM_DCCURIINFO);
+
+ // Read the the DCC URI info
+ for (nIndex = 0; eError != OMX_ErrorNoMore; nIndex++) {
+ param.nIndex = nIndex;
+ eError = OMX_GetParameter(hComponent,
+ ( OMX_INDEXTYPE )OMX_TI_IndexParamDccUriInfo,
+ &param);
+
+ if (eError == OMX_ErrorNone) {
+ CAMHAL_LOGD("DCC URI's %s ", param.sDCCURI);
+ android::String8 *dccDir = new android::String8();
+ if ( NULL != dccDir ) {
+ dccDir->clear();
+ dccDir->append(DCCPath);
+ dccDir->append((const char *) param.sDCCURI);
+ dccDir->append("/");
+ dccDirs.add(dccDir);
+ } else {
+ CAMHAL_LOGE("DCC URI not allocated");
+ eError = OMX_ErrorInsufficientResources;
+ goto EXIT;
+ }
+ }
+ }
+
+ // setting back errortype OMX_ErrorNone
+ if (eError == OMX_ErrorNoMore) {
+ eError = OMX_ErrorNone;
+ }
+
+ dccbuf_size = readDCCdir(NULL, dccDirs);
+ if(dccbuf_size <= 0) {
+ CAMHAL_LOGE("No DCC files found, switching back to default DCC");
+ eError = OMX_ErrorInsufficientResources;
+ goto EXIT;
+ }
+ dccbuf_size = ((dccbuf_size + 4095 )/4096)*4096;
+
+ if ( memMgr.initialize() != NO_ERROR ) {
+ CAMHAL_LOGE("DCC memory manager initialization failed!!!");
+ eError = OMX_ErrorInsufficientResources;
+ goto EXIT;
+ }
+
+ dccBuffer = memMgr.allocateBufferList(0, 0, NULL, dccbuf_size, 1);
+ if ( NULL == dccBuffer ) {
+ CAMHAL_LOGE("DCC buffer allocation failed!!!");
+ eError = OMX_ErrorInsufficientResources;
+ goto EXIT;
+ }
+
+ dccbuf_size = readDCCdir(dccBuffer[0].mapped, dccDirs);
+ CAMHAL_ASSERT_X(dccbuf_size > 0,"ERROR in copy DCC files into buffer");
+
+ eError = sendDCCBufPtr(hComponent, dccBuffer);
+
+EXIT:
+
+ for (i = 0; i < dccDirs.size(); i++) {
+ android::String8 *dccDir = dccDirs.itemAt(0);
+ dccDirs.removeAt(0);
+ delete dccDir;
+ }
+
+ if ( NULL != dccBuffer ) {
+ memMgr.freeBufferList(dccBuffer);
+ }
+
+ return eError;
+}
+
+OMX_ERRORTYPE DCCHandler::sendDCCBufPtr(OMX_HANDLETYPE hComponent,
+ CameraBuffer *dccBuffer)
+{
+ OMX_TI_CONFIG_SHAREDBUFFER uribufparam;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_INIT_STRUCT_PTR(&uribufparam, OMX_TI_CONFIG_SHAREDBUFFER);
+
+ CAMHAL_ASSERT_X(dccBuffer != NULL,"ERROR invalid DCC buffer");
+
+ uribufparam.nPortIndex = OMX_ALL;
+ uribufparam.nSharedBuffSize = dccBuffer->size;
+ uribufparam.pSharedBuff = (OMX_U8 *) camera_buffer_get_omx_ptr(dccBuffer);
+
+ eError = OMX_SetParameter(hComponent,
+ ( OMX_INDEXTYPE )OMX_TI_IndexParamDccUriBuffer,
+ &uribufparam);
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB(" Error in SetParam for DCC Uri Buffer 0x%x", eError);
+ }
+
+ return eError;
+}
+
+size_t DCCHandler::readDCCdir(OMX_PTR buffer,
+ const android::Vector<android::String8 *> &dirPaths)
+{
+ FILE *pFile;
+ OMX_S32 lSize;
+ OMX_S32 dcc_buf_size = 0;
+ size_t result;
+ OMX_STRING filename;
+ android::String8 temp;
+ const char *dotdot = "..";
+ DIR *d;
+ struct dirent *dir;
+ OMX_U16 i = 0;
+ status_t stat = NO_ERROR;
+ size_t ret = 0;
+
+ for (i = 0; i < dirPaths.size(); i++) {
+ d = opendir(dirPaths.itemAt(i)->string());
+ if (d) {
+ // read each filename
+ while ((dir = readdir(d)) != NULL) {
+ filename = dir->d_name;
+ temp.clear();
+ temp.append(dirPaths.itemAt(i)->string());
+ temp.append(filename);
+ if ((*filename != *dotdot)) {
+ pFile = fopen(temp.string(), "rb");
+ if (pFile == NULL) {
+ stat = -errno;
+ } else {
+ fseek(pFile, 0, SEEK_END);
+ lSize = ftell(pFile);
+ rewind(pFile);
+ // buffer is not NULL then copy all the DCC profiles into buffer
+ // else return the size of the DCC directory.
+ if (buffer) {
+ // copy file into the buffer:
+ result = fread(buffer, 1, lSize, pFile);
+ if (result != (size_t) lSize) {
+ stat = INVALID_OPERATION;
+ }
+ buffer = buffer + lSize;
+ }
+ // getting the size of the total dcc files available in FS */
+ dcc_buf_size = dcc_buf_size + lSize;
+ // terminate
+ fclose(pFile);
+ }
+ }
+ }
+ closedir(d);
+ }
+ }
+
+ if (stat == NO_ERROR) {
+ ret = dcc_buf_size;
+ }
+
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXDccDataSave.cpp b/camera/OMXCameraAdapter/OMXDccDataSave.cpp
new file mode 100644
index 0000000..7547743
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXDccDataSave.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXDccDataSave.cpp
+*
+* This file contains functionality for handling DCC data save
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+
+namespace Ti {
+namespace Camera {
+
+status_t OMXCameraAdapter::initDccFileDataSave(OMX_HANDLETYPE* omxHandle, int portIndex)
+{
+ OMX_CONFIG_EXTRADATATYPE extraDataControl;
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE);
+ extraDataControl.nPortIndex = portIndex;
+ extraDataControl.eExtraDataType = OMX_TI_DccData;
+ extraDataControl.bEnable = OMX_TRUE;
+
+ eError = OMX_SetConfig(*omxHandle,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigOtherExtraDataControl,
+ &extraDataControl);
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring dcc data overwrite extra data 0x%x",
+ eError);
+
+ ret = NO_INIT;
+ }
+
+ if (mDccData.pData) {
+ free(mDccData.pData);
+ mDccData.pData = NULL;
+ }
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::sniffDccFileDataSave(OMX_BUFFERHEADERTYPE* pBuffHeader)
+{
+ OMX_OTHER_EXTRADATATYPE *extraData;
+ OMX_TI_DCCDATATYPE* dccData;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mDccDataLock);
+
+ if ( NULL == pBuffHeader ) {
+ CAMHAL_LOGEA("Invalid Buffer header");
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ extraData = getExtradata(pBuffHeader->pPlatformPrivate,
+ (OMX_EXTRADATATYPE)OMX_TI_DccData);
+
+ if ( NULL != extraData ) {
+ CAMHAL_LOGVB("Size = %d, sizeof = %d, eType = 0x%x, nDataSize= %d, nPortIndex = 0x%x, nVersion = 0x%x",
+ extraData->nSize,
+ sizeof(OMX_OTHER_EXTRADATATYPE),
+ extraData->eType,
+ extraData->nDataSize,
+ extraData->nPortIndex,
+ extraData->nVersion);
+ } else {
+ CAMHAL_LOGVA("Invalid OMX_TI_DCCDATATYPE");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+ }
+
+ dccData = ( OMX_TI_DCCDATATYPE * ) extraData->data;
+
+ if (NULL == dccData) {
+ CAMHAL_LOGVA("OMX_TI_DCCDATATYPE is not found in extra data");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+ }
+
+ if (mDccData.pData) {
+ free(mDccData.pData);
+ }
+
+ memcpy(&mDccData, dccData, sizeof(mDccData));
+
+ int dccDataSize = (int)dccData->nSize - (int)(&(((OMX_TI_DCCDATATYPE*)0)->pData));
+
+ mDccData.pData = (OMX_PTR)malloc(dccDataSize);
+
+ if (NULL == mDccData.pData) {
+ CAMHAL_LOGVA("not enough memory for DCC data");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+ }
+
+ memcpy(mDccData.pData, &(dccData->pData), dccDataSize);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+// Recursively searches given directory contents for the correct DCC file.
+// The directory must be opened and its stream pointer + path passed
+// as arguments. As this function is called recursively, to avoid excessive
+// stack usage the path param is reused -> this MUST be char array with
+// enough length!!! (260 should suffice). Path must end with "/".
+// The directory must also be closed in the caller function.
+// If the correct camera DCC file is found (based on the OMX measurement data)
+// its file stream pointer is returned. NULL is returned otherwise
+FILE * OMXCameraAdapter::parseDCCsubDir(DIR *pDir, char *path)
+{
+ FILE *pFile;
+ DIR *pSubDir;
+ struct dirent *dirEntry;
+ int initialPathLength = strlen(path);
+
+ LOG_FUNCTION_NAME;
+
+ /* check each directory entry */
+ while ((dirEntry = readdir(pDir)) != NULL)
+ {
+ if (dirEntry->d_name[0] == '.')
+ continue;
+
+ strcat(path, dirEntry->d_name);
+ // dirEntry might be sub directory -> check it
+ pSubDir = opendir(path);
+ if (pSubDir) {
+ // dirEntry is sub directory -> parse it
+ strcat(path, "/");
+ pFile = parseDCCsubDir(pSubDir, path);
+ closedir(pSubDir);
+ if (pFile) {
+ // the correct DCC file found!
+ LOG_FUNCTION_NAME_EXIT;
+ return pFile;
+ }
+ } else {
+ // dirEntry is file -> open it
+ pFile = fopen(path, "rb");
+ if (pFile) {
+ // now check if this is the correct DCC file for that camera
+ OMX_U32 dccFileIDword;
+ OMX_U32 *dccFileDesc = (OMX_U32 *) &mDccData.nCameraModuleId;
+ int i;
+
+ // DCC file ID is 3 4-byte words
+ for (i = 0; i < 3; i++) {
+ if (fread(&dccFileIDword, sizeof(OMX_U32), 1, pFile) != 1) {
+ // file too short
+ break;
+ }
+ if (dccFileIDword != dccFileDesc[i]) {
+ // DCC file ID word i does not match
+ break;
+ }
+ }
+
+ fclose(pFile);
+ if (i == 3) {
+ // the correct DCC file found!
+ CAMHAL_LOGDB("DCC file to be updated: %s", path);
+ // reopen it for modification
+ pFile = fopen(path, "rb+");
+ if (!pFile)
+ CAMHAL_LOGEB("ERROR: DCC file %s failed to open for modification", path);
+ LOG_FUNCTION_NAME_EXIT;
+ return pFile;
+ }
+ } else {
+ CAMHAL_LOGEB("ERROR: Failed to open file %s for reading", path);
+ }
+ }
+ // restore original path
+ path[initialPathLength] = '\0';
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ // DCC file not found in this directory tree
+ return NULL;
+}
+
+// Finds the DCC file corresponding to the current camera based on the
+// OMX measurement data, opens it and returns the file stream pointer
+// (NULL on error or if file not found).
+// The folder string dccFolderPath must end with "/"
+FILE * OMXCameraAdapter::fopenCameraDCC(const char *dccFolderPath)
+{
+ FILE *pFile;
+ DIR *pDir;
+ char dccPath[260];
+
+ LOG_FUNCTION_NAME;
+
+ strcpy(dccPath, dccFolderPath);
+
+ pDir = opendir(dccPath);
+ if (!pDir) {
+ CAMHAL_LOGEB("ERROR: Opening DCC directory %s failed", dccPath);
+ LOG_FUNCTION_NAME_EXIT;
+ return NULL;
+ }
+
+ pFile = parseDCCsubDir(pDir, dccPath);
+ closedir(pDir);
+ if (pFile) {
+ CAMHAL_LOGDB("DCC file %s opened for modification", dccPath);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return pFile;
+}
+
+// Positions the DCC file stream pointer to the correct offset within the
+// correct usecase based on the OMX mesurement data. Returns 0 on success
+status_t OMXCameraAdapter::fseekDCCuseCasePos(FILE *pFile)
+{
+ OMX_U32 dccNumUseCases = 0;
+ OMX_U32 dccUseCaseData[3];
+ OMX_U32 i;
+
+ LOG_FUNCTION_NAME;
+
+ // position the file pointer to the DCC use cases section
+ if (fseek(pFile, 80, SEEK_SET)) {
+ CAMHAL_LOGEA("ERROR: Unexpected end of DCC file");
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ if (fread(&dccNumUseCases, sizeof(OMX_U32), 1, pFile) != 1 ||
+ dccNumUseCases == 0) {
+ CAMHAL_LOGEA("ERROR: DCC file contains 0 use cases");
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ for (i = 0; i < dccNumUseCases; i++) {
+ if (fread(dccUseCaseData, sizeof(OMX_U32), 3, pFile) != 3) {
+ CAMHAL_LOGEA("ERROR: Unexpected end of DCC file");
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ if (dccUseCaseData[0] == mDccData.nUseCaseId) {
+ // DCC use case match!
+ break;
+ }
+ }
+
+ if (i == dccNumUseCases) {
+ CAMHAL_LOGEB("ERROR: Use case ID %lu not found in DCC file", mDccData.nUseCaseId);
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ // dccUseCaseData[1] is the offset to the beginning of the actual use case
+ // from the beginning of the file
+ // mDccData.nOffset is the offset within the actual use case (from the
+ // beginning of the use case to the data to be modified)
+
+ if (fseek(pFile,dccUseCaseData[1] + mDccData.nOffset, SEEK_SET ))
+ {
+ CAMHAL_LOGEA("ERROR: Error setting the correct offset");
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+status_t OMXCameraAdapter::saveDccFileDataSave()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mDccDataLock);
+
+ if (mDccData.pData)
+ {
+ FILE *fd = fopenCameraDCC(DCC_PATH);
+
+ if (fd)
+ {
+ if (!fseekDCCuseCasePos(fd))
+ {
+ int dccDataSize = (int)mDccData.nSize - (int)(&(((OMX_TI_DCCDATATYPE*)0)->pData));
+
+ if (fwrite(mDccData.pData, dccDataSize, 1, fd) != 1)
+ {
+ CAMHAL_LOGEA("ERROR: Writing to DCC file failed");
+ }
+ else
+ {
+ CAMHAL_LOGDA("DCC file successfully updated");
+ }
+ }
+ fclose(fd);
+ }
+ else
+ {
+ CAMHAL_LOGEA("ERROR: Correct DCC file not found or failed to open for modification");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::closeDccFileDataSave()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mDccDataLock);
+
+ if (mDccData.pData) {
+ free(mDccData.pData);
+ mDccData.pData = NULL;
+ }
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXDefaults.cpp b/camera/OMXCameraAdapter/OMXDefaults.cpp
new file mode 100644
index 0000000..80805b2
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXDefaults.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXDefaults.cpp
+*
+* This file contains definitions are OMX Camera defaults
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+namespace Ti {
+namespace Camera {
+
+#define __STRINGIFY(s) __STRING(s)
+
+// OMX Camera defaults
+const char OMXCameraAdapter::DEFAULT_ANTIBANDING[] = "auto";
+const char OMXCameraAdapter::DEFAULT_BRIGHTNESS[] = "50";
+const char OMXCameraAdapter::DEFAULT_CONTRAST[] = "100";
+const char OMXCameraAdapter::DEFAULT_EFFECT[] = "none";
+const char OMXCameraAdapter::DEFAULT_EV_COMPENSATION[] = "0";
+const char OMXCameraAdapter::DEFAULT_EV_STEP[] = "0.1";
+const char OMXCameraAdapter::DEFAULT_EXPOSURE_MODE[] = "auto";
+const char OMXCameraAdapter::DEFAULT_FLASH_MODE[] = "off";
+const char OMXCameraAdapter::DEFAULT_FOCUS_MODE_PREFERRED[] = "auto";
+const char OMXCameraAdapter::DEFAULT_FOCUS_MODE[] = "infinity";
+#ifndef MOTOROLA_CAMERA
+const char OMXCameraAdapter::DEFAULT_IPP[] = "ldc-nsf";
+#else
+const char OMXCameraAdapter::DEFAULT_IPP[] = "off";
+#endif
+const char OMXCameraAdapter::DEFAULT_ISO_MODE[] = "auto";
+const char OMXCameraAdapter::DEFAULT_JPEG_QUALITY[] = "95";
+const char OMXCameraAdapter::DEFAULT_THUMBNAIL_QUALITY[] = "60";
+const char OMXCameraAdapter::DEFAULT_THUMBNAIL_SIZE[] = "160x120";
+const char OMXCameraAdapter::DEFAULT_PICTURE_FORMAT[] = "jpeg";
+const char OMXCameraAdapter::DEFAULT_S3D_PICTURE_LAYOUT[] = "tb-full";
+const char OMXCameraAdapter::DEFAULT_PICTURE_SIZE[] = "320x240";
+const char OMXCameraAdapter::DEFAULT_PICTURE_SS_SIZE[] = "640x240";
+const char OMXCameraAdapter::DEFAULT_PICTURE_TB_SIZE[] = "320x480";
+const char OMXCameraAdapter::DEFAULT_PREVIEW_FORMAT[] = "yuv420sp";
+const char OMXCameraAdapter::DEFAULT_FRAMERATE[] = "30";
+const char OMXCameraAdapter::DEFAULT_S3D_PREVIEW_LAYOUT[] = "tb-subsampled";
+const char OMXCameraAdapter::DEFAULT_PREVIEW_SIZE[] = "640x480";
+const char OMXCameraAdapter::DEFAULT_PREVIEW_SS_SIZE[] = "1280x480";
+const char OMXCameraAdapter::DEFAULT_PREVIEW_TB_SIZE[] = "640x960";
+const char OMXCameraAdapter::DEFAULT_NUM_PREV_BUFS[] = "6";
+const char OMXCameraAdapter::DEFAULT_NUM_PIC_BUFS[] = "1";
+const char OMXCameraAdapter::DEFAULT_SATURATION[] = "100";
+const char OMXCameraAdapter::DEFAULT_SCENE_MODE[] = "auto";
+const char OMXCameraAdapter::DEFAULT_SHARPNESS[] = "100";
+const char * OMXCameraAdapter::DEFAULT_VSTAB = android::CameraParameters::FALSE;
+const char * OMXCameraAdapter::DEFAULT_VNF = android::CameraParameters::FALSE;
+const char OMXCameraAdapter::DEFAULT_WB[] = "auto";
+const char OMXCameraAdapter::DEFAULT_ZOOM[] = "0";
+const char OMXCameraAdapter::DEFAULT_MAX_FD_HW_FACES[] = __STRINGIFY(MAX_NUM_FACES_SUPPORTED);
+const char OMXCameraAdapter::DEFAULT_MAX_FD_SW_FACES[] = "0";
+const char OMXCameraAdapter::DEFAULT_HOR_ANGLE[] = "54.8";
+const char OMXCameraAdapter::DEFAULT_VER_ANGLE[] = "42.5";
+const char * OMXCameraAdapter::DEFAULT_AE_LOCK = android::CameraParameters::FALSE;
+const char * OMXCameraAdapter::DEFAULT_AWB_LOCK = android::CameraParameters::FALSE;
+const char OMXCameraAdapter::DEFAULT_VIDEO_SIZE[] = "1920x1080";
+const char OMXCameraAdapter::DEFAULT_SENSOR_ORIENTATION[] = "0";
+const char OMXCameraAdapter::DEFAULT_AUTOCONVERGENCE_MODE[] = "frame";
+const char OMXCameraAdapter::DEFAULT_MANUAL_CONVERGENCE[] = "0";
+const char * OMXCameraAdapter::DEFAULT_MECHANICAL_MISALIGNMENT_CORRECTION_MODE = android::CameraParameters::TRUE;
+const char OMXCameraAdapter::DEFAULT_EXIF_MAKE[] = "default_make";
+const char OMXCameraAdapter::DEFAULT_EXIF_MODEL[] = "default_model";
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXExif.cpp b/camera/OMXCameraAdapter/OMXExif.cpp
new file mode 100644
index 0000000..b4fde5a
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXExif.cpp
@@ -0,0 +1,838 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXExif.cpp
+*
+* This file contains functionality for handling EXIF insertion.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include <math.h>
+
+namespace Ti {
+namespace Camera {
+
+status_t OMXCameraAdapter::setParametersEXIF(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *valstr = NULL;
+ double gpsPos;
+
+ LOG_FUNCTION_NAME;
+
+ if( ( valstr = params.get(android::CameraParameters::KEY_GPS_LATITUDE) ) != NULL )
+ {
+ gpsPos = strtod(valstr, NULL);
+
+ if ( convertGPSCoord(gpsPos,
+ mEXIFData.mGPSData.mLatDeg,
+ mEXIFData.mGPSData.mLatMin,
+ mEXIFData.mGPSData.mLatSec,
+ mEXIFData.mGPSData.mLatSecDiv ) == NO_ERROR )
+ {
+
+ if ( 0 < gpsPos )
+ {
+ strncpy(mEXIFData.mGPSData.mLatRef, GPS_NORTH_REF, GPS_REF_SIZE);
+ }
+ else
+ {
+ strncpy(mEXIFData.mGPSData.mLatRef, GPS_SOUTH_REF, GPS_REF_SIZE);
+ }
+
+ mEXIFData.mGPSData.mLatValid = true;
+ }
+ else
+ {
+ mEXIFData.mGPSData.mLatValid = false;
+ }
+ }
+ else
+ {
+ mEXIFData.mGPSData.mLatValid = false;
+ }
+
+ if( ( valstr = params.get(android::CameraParameters::KEY_GPS_LONGITUDE) ) != NULL )
+ {
+ gpsPos = strtod(valstr, NULL);
+
+ if ( convertGPSCoord(gpsPos,
+ mEXIFData.mGPSData.mLongDeg,
+ mEXIFData.mGPSData.mLongMin,
+ mEXIFData.mGPSData.mLongSec,
+ mEXIFData.mGPSData.mLongSecDiv) == NO_ERROR )
+ {
+
+ if ( 0 < gpsPos )
+ {
+ strncpy(mEXIFData.mGPSData.mLongRef, GPS_EAST_REF, GPS_REF_SIZE);
+ }
+ else
+ {
+ strncpy(mEXIFData.mGPSData.mLongRef, GPS_WEST_REF, GPS_REF_SIZE);
+ }
+
+ mEXIFData.mGPSData.mLongValid= true;
+ }
+ else
+ {
+ mEXIFData.mGPSData.mLongValid = false;
+ }
+ }
+ else
+ {
+ mEXIFData.mGPSData.mLongValid = false;
+ }
+
+ if( ( valstr = params.get(android::CameraParameters::KEY_GPS_ALTITUDE) ) != NULL )
+ {
+ gpsPos = strtod(valstr, NULL);
+ mEXIFData.mGPSData.mAltitude = floor(fabs(gpsPos));
+ if (gpsPos < 0) {
+ mEXIFData.mGPSData.mAltitudeRef = 1;
+ } else {
+ mEXIFData.mGPSData.mAltitudeRef = 0;
+ }
+ mEXIFData.mGPSData.mAltitudeValid = true;
+ }
+ else
+ {
+ mEXIFData.mGPSData.mAltitudeValid= false;
+ }
+
+ if( (valstr = params.get(android::CameraParameters::KEY_GPS_TIMESTAMP)) != NULL )
+ {
+ long gpsTimestamp = strtol(valstr, NULL, 10);
+ struct tm *timeinfo = gmtime( ( time_t * ) & (gpsTimestamp) );
+ if ( NULL != timeinfo )
+ {
+ mEXIFData.mGPSData.mTimeStampHour = timeinfo->tm_hour;
+ mEXIFData.mGPSData.mTimeStampMin = timeinfo->tm_min;
+ mEXIFData.mGPSData.mTimeStampSec = timeinfo->tm_sec;
+ mEXIFData.mGPSData.mTimeStampValid = true;
+ }
+ else
+ {
+ mEXIFData.mGPSData.mTimeStampValid = false;
+ }
+ }
+ else
+ {
+ mEXIFData.mGPSData.mTimeStampValid = false;
+ }
+
+ if( ( valstr = params.get(android::CameraParameters::KEY_GPS_TIMESTAMP) ) != NULL )
+ {
+ long gpsDatestamp = strtol(valstr, NULL, 10);
+ struct tm *timeinfo = gmtime( ( time_t * ) & (gpsDatestamp) );
+ if ( NULL != timeinfo )
+ {
+ strftime(mEXIFData.mGPSData.mDatestamp, GPS_DATESTAMP_SIZE, "%Y:%m:%d", timeinfo);
+ mEXIFData.mGPSData.mDatestampValid = true;
+ }
+ else
+ {
+ mEXIFData.mGPSData.mDatestampValid = false;
+ }
+ }
+ else
+ {
+ mEXIFData.mGPSData.mDatestampValid = false;
+ }
+
+ if( ( valstr = params.get(android::CameraParameters::KEY_GPS_PROCESSING_METHOD) ) != NULL )
+ {
+ strncpy(mEXIFData.mGPSData.mProcMethod, valstr, GPS_PROCESSING_SIZE-1);
+ mEXIFData.mGPSData.mProcMethodValid = true;
+ }
+ else
+ {
+ mEXIFData.mGPSData.mProcMethodValid = false;
+ }
+
+ if( ( valstr = params.get(TICameraParameters::KEY_GPS_MAPDATUM) ) != NULL )
+ {
+ strncpy(mEXIFData.mGPSData.mMapDatum, valstr, GPS_MAPDATUM_SIZE-1);
+ mEXIFData.mGPSData.mMapDatumValid = true;
+ }
+ else
+ {
+ mEXIFData.mGPSData.mMapDatumValid = false;
+ }
+
+ if( ( valstr = params.get(TICameraParameters::KEY_GPS_VERSION) ) != NULL )
+ {
+ strncpy(mEXIFData.mGPSData.mVersionId, valstr, GPS_VERSION_SIZE-1);
+ mEXIFData.mGPSData.mVersionIdValid = true;
+ }
+ else
+ {
+ mEXIFData.mGPSData.mVersionIdValid = false;
+ }
+
+ if( ( valstr = params.get(TICameraParameters::KEY_EXIF_MODEL ) ) != NULL )
+ {
+ CAMHAL_LOGVB("EXIF Model: %s", valstr);
+ strncpy(mEXIFData.mModel, valstr, EXIF_MODEL_SIZE - 1);
+ mEXIFData.mModelValid= true;
+ }
+ else
+ {
+ mEXIFData.mModelValid= false;
+ }
+
+ if( ( valstr = params.get(TICameraParameters::KEY_EXIF_MAKE ) ) != NULL )
+ {
+ CAMHAL_LOGVB("EXIF Make: %s", valstr);
+ strncpy(mEXIFData.mMake, valstr, EXIF_MAKE_SIZE - 1);
+ mEXIFData.mMakeValid = true;
+ }
+ else
+ {
+ mEXIFData.mMakeValid= false;
+ }
+
+
+ if( ( valstr = params.get(android::CameraParameters::KEY_FOCAL_LENGTH) ) != NULL ) {
+ CAMHAL_LOGVB("EXIF Focal length: %s", valstr);
+ ExifElementsTable::stringToRational(valstr,
+ &mEXIFData.mFocalNum,
+ &mEXIFData.mFocalDen);
+ } else {
+ mEXIFData.mFocalNum = 0;
+ mEXIFData.mFocalDen = 0;
+ }
+
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setupEXIF()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
+ OMX_TI_CONFIG_EXIF_TAGS *exifTags;
+ unsigned char *startPtr = NULL;
+ unsigned char *sharedPtr = NULL;
+ struct timeval sTv;
+ struct tm *pTime;
+ OMXCameraPortParameters * capData = NULL;
+ CameraBuffer *memmgr_buf_array;
+ int buf_size = 0;
+
+ LOG_FUNCTION_NAME;
+
+ sharedBuffer.pSharedBuff = NULL;
+ capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
+ sharedBuffer.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ //We allocate the shared buffer dynamically based on the
+ //requirements of the EXIF tags. The additional buffers will
+ //get stored after the EXIF configuration structure and the pointers
+ //will contain offsets within the shared buffer itself.
+ buf_size = sizeof(OMX_TI_CONFIG_EXIF_TAGS) +
+ ( EXIF_MODEL_SIZE ) +
+ ( EXIF_MAKE_SIZE ) +
+ ( EXIF_DATE_TIME_SIZE ) +
+ ( GPS_MAPDATUM_SIZE ) +
+ ( GPS_PROCESSING_SIZE );
+ buf_size = ((buf_size+4095)/4096)*4096;
+ sharedBuffer.nSharedBuffSize = buf_size;
+
+ memmgr_buf_array = mMemMgr.allocateBufferList(0, 0, NULL, buf_size, 1);
+ sharedBuffer.pSharedBuff = (OMX_U8*)camera_buffer_get_omx_ptr(&memmgr_buf_array[0]);
+ startPtr = ( OMX_U8 * ) memmgr_buf_array[0].opaque;
+
+ if ( NULL == startPtr)
+ {
+ CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
+ ret = -1;
+ }
+
+ //Extra data begins right after the EXIF configuration structure.
+ sharedPtr = startPtr + sizeof(OMX_TI_CONFIG_EXIF_TAGS);
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ exifTags = ( OMX_TI_CONFIG_EXIF_TAGS * ) startPtr;
+ OMX_INIT_STRUCT_PTR (exifTags, OMX_TI_CONFIG_EXIF_TAGS);
+ exifTags->nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigExifTags,
+ &sharedBuffer );
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while retrieving EXIF configuration structure 0x%x", eError);
+ ret = -1;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusModel ) &&
+ ( mEXIFData.mModelValid ) )
+ {
+ strncpy(( char * ) sharedPtr,
+ mEXIFData.mModel,
+ EXIF_MODEL_SIZE - 1);
+
+ exifTags->pModelBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
+ exifTags->ulModelBuffSizeBytes = strlen((char*)sharedPtr) + 1;
+ sharedPtr += EXIF_MODEL_SIZE;
+ exifTags->eStatusModel = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusMake) &&
+ ( mEXIFData.mMakeValid ) )
+ {
+ strncpy( ( char * ) sharedPtr,
+ mEXIFData.mMake,
+ EXIF_MAKE_SIZE - 1);
+
+ exifTags->pMakeBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
+ exifTags->ulMakeBuffSizeBytes = strlen((char*)sharedPtr) + 1;
+ sharedPtr += EXIF_MAKE_SIZE;
+ exifTags->eStatusMake = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusFocalLength ))
+ {
+ if (mEXIFData.mFocalNum || mEXIFData.mFocalDen ) {
+ exifTags->ulFocalLength[0] = (OMX_U32) mEXIFData.mFocalNum;
+ exifTags->ulFocalLength[1] = (OMX_U32) mEXIFData.mFocalDen;
+ CAMHAL_LOGVB("exifTags->ulFocalLength = [%u] [%u]",
+ (unsigned int)(exifTags->ulFocalLength[0]),
+ (unsigned int)(exifTags->ulFocalLength[1]));
+ exifTags->eStatusFocalLength = OMX_TI_TagUpdated;
+ }
+ }
+
+ if ( OMX_TI_TagReadWrite == exifTags->eStatusDateTime )
+ {
+ int status = gettimeofday (&sTv, NULL);
+ pTime = localtime (&sTv.tv_sec);
+ if ( ( 0 == status ) && ( NULL != pTime ) )
+ {
+ snprintf(( char * ) sharedPtr, EXIF_DATE_TIME_SIZE,
+ "%04d:%02d:%02d %02d:%02d:%02d",
+ pTime->tm_year + 1900,
+ pTime->tm_mon + 1,
+ pTime->tm_mday,
+ pTime->tm_hour,
+ pTime->tm_min,
+ pTime->tm_sec );
+ }
+
+ exifTags->pDateTimeBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
+ sharedPtr += EXIF_DATE_TIME_SIZE;
+ exifTags->ulDateTimeBuffSizeBytes = EXIF_DATE_TIME_SIZE;
+ exifTags->eStatusDateTime = OMX_TI_TagUpdated;
+ }
+
+ if ( OMX_TI_TagReadWrite == exifTags->eStatusImageWidth )
+ {
+ exifTags->ulImageWidth = capData->mWidth;
+ exifTags->eStatusImageWidth = OMX_TI_TagUpdated;
+ }
+
+ if ( OMX_TI_TagReadWrite == exifTags->eStatusImageHeight )
+ {
+ exifTags->ulImageHeight = capData->mHeight;
+ exifTags->eStatusImageHeight = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLatitude ) &&
+ ( mEXIFData.mGPSData.mLatValid ) )
+ {
+ exifTags->ulGpsLatitude[0] = abs(mEXIFData.mGPSData.mLatDeg);
+ exifTags->ulGpsLatitude[2] = abs(mEXIFData.mGPSData.mLatMin);
+ exifTags->ulGpsLatitude[4] = abs(mEXIFData.mGPSData.mLatSec);
+ exifTags->ulGpsLatitude[1] = 1;
+ exifTags->ulGpsLatitude[3] = 1;
+ exifTags->ulGpsLatitude[5] = abs(mEXIFData.mGPSData.mLatSecDiv);
+ exifTags->eStatusGpsLatitude = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpslatitudeRef ) &&
+ ( mEXIFData.mGPSData.mLatValid ) )
+ {
+ exifTags->cGpslatitudeRef[0] = ( OMX_S8 ) mEXIFData.mGPSData.mLatRef[0];
+ exifTags->cGpslatitudeRef[1] = '\0';
+ exifTags->eStatusGpslatitudeRef = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLongitude ) &&
+ ( mEXIFData.mGPSData.mLongValid ) )
+ {
+ exifTags->ulGpsLongitude[0] = abs(mEXIFData.mGPSData.mLongDeg);
+ exifTags->ulGpsLongitude[2] = abs(mEXIFData.mGPSData.mLongMin);
+ exifTags->ulGpsLongitude[4] = abs(mEXIFData.mGPSData.mLongSec);
+ exifTags->ulGpsLongitude[1] = 1;
+ exifTags->ulGpsLongitude[3] = 1;
+ exifTags->ulGpsLongitude[5] = abs(mEXIFData.mGPSData.mLongSecDiv);
+ exifTags->eStatusGpsLongitude = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLongitudeRef ) &&
+ ( mEXIFData.mGPSData.mLongValid ) )
+ {
+ exifTags->cGpsLongitudeRef[0] = ( OMX_S8 ) mEXIFData.mGPSData.mLongRef[0];
+ exifTags->cGpsLongitudeRef[1] = '\0';
+ exifTags->eStatusGpsLongitudeRef = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsAltitude ) &&
+ ( mEXIFData.mGPSData.mAltitudeValid) )
+ {
+ exifTags->ulGpsAltitude[0] = ( OMX_U32 ) mEXIFData.mGPSData.mAltitude;
+ exifTags->ulGpsAltitude[1] = 1;
+ exifTags->eStatusGpsAltitude = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsAltitudeRef ) &&
+ ( mEXIFData.mGPSData.mAltitudeValid) )
+ {
+ exifTags->ucGpsAltitudeRef = (OMX_U8) mEXIFData.mGPSData.mAltitudeRef;
+ exifTags->eStatusGpsAltitudeRef = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsMapDatum ) &&
+ ( mEXIFData.mGPSData.mMapDatumValid ) )
+ {
+ memcpy(sharedPtr, mEXIFData.mGPSData.mMapDatum, GPS_MAPDATUM_SIZE);
+
+ exifTags->pGpsMapDatumBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
+ exifTags->ulGpsMapDatumBuffSizeBytes = GPS_MAPDATUM_SIZE;
+ exifTags->eStatusGpsMapDatum = OMX_TI_TagUpdated;
+ sharedPtr += GPS_MAPDATUM_SIZE;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsProcessingMethod ) &&
+ ( mEXIFData.mGPSData.mProcMethodValid ) )
+ {
+ exifTags->pGpsProcessingMethodBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
+ memcpy(sharedPtr, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
+ sharedPtr += sizeof(ExifAsciiPrefix);
+
+ memcpy(sharedPtr,
+ mEXIFData.mGPSData.mProcMethod,
+ ( GPS_PROCESSING_SIZE - sizeof(ExifAsciiPrefix) ) );
+ exifTags->ulGpsProcessingMethodBuffSizeBytes = GPS_PROCESSING_SIZE;
+ exifTags->eStatusGpsProcessingMethod = OMX_TI_TagUpdated;
+ sharedPtr += GPS_PROCESSING_SIZE;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsVersionId ) &&
+ ( mEXIFData.mGPSData.mVersionIdValid ) )
+ {
+ exifTags->ucGpsVersionId[0] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[0];
+ exifTags->ucGpsVersionId[1] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[1];
+ exifTags->ucGpsVersionId[2] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[2];
+ exifTags->ucGpsVersionId[3] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[3];
+ exifTags->eStatusGpsVersionId = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsTimeStamp ) &&
+ ( mEXIFData.mGPSData.mTimeStampValid ) )
+ {
+ exifTags->ulGpsTimeStamp[0] = mEXIFData.mGPSData.mTimeStampHour;
+ exifTags->ulGpsTimeStamp[2] = mEXIFData.mGPSData.mTimeStampMin;
+ exifTags->ulGpsTimeStamp[4] = mEXIFData.mGPSData.mTimeStampSec;
+ exifTags->ulGpsTimeStamp[1] = 1;
+ exifTags->ulGpsTimeStamp[3] = 1;
+ exifTags->ulGpsTimeStamp[5] = 1;
+ exifTags->eStatusGpsTimeStamp = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsDateStamp ) &&
+ ( mEXIFData.mGPSData.mDatestampValid ) )
+ {
+ strncpy( ( char * ) exifTags->cGpsDateStamp,
+ ( char * ) mEXIFData.mGPSData.mDatestamp,
+ GPS_DATESTAMP_SIZE );
+ exifTags->eStatusGpsDateStamp = OMX_TI_TagUpdated;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigExifTags,
+ &sharedBuffer );
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while setting EXIF configuration 0x%x", eError);
+ ret = -1;
+ }
+ }
+
+ if ( NULL != memmgr_buf_array )
+ {
+ mMemMgr.freeBufferList(memmgr_buf_array);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable,
+ OMX_TI_ANCILLARYDATATYPE* pAncillaryData,
+ OMX_TI_WHITEBALANCERESULTTYPE* pWhiteBalanceData)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ struct timeval sTv;
+ struct tm *pTime;
+ OMXCameraPortParameters * capData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ((NO_ERROR == ret) && (mEXIFData.mModelValid)) {
+ ret = exifTable->insertElement(TAG_MODEL, mEXIFData.mModel);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mMakeValid)) {
+ ret = exifTable->insertElement(TAG_MAKE, mEXIFData.mMake);
+ }
+
+ if ((NO_ERROR == ret)) {
+ if (mEXIFData.mFocalNum || mEXIFData.mFocalDen) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u/%u",
+ mEXIFData.mFocalNum,
+ mEXIFData.mFocalDen);
+ ret = exifTable->insertElement(TAG_FOCALLENGTH, temp_value);
+
+ }
+ }
+
+ if ((NO_ERROR == ret)) {
+ int status = gettimeofday (&sTv, NULL);
+ pTime = localtime (&sTv.tv_sec);
+ char temp_value[EXIF_DATE_TIME_SIZE + 1];
+ if ((0 == status) && (NULL != pTime)) {
+ snprintf(temp_value, EXIF_DATE_TIME_SIZE,
+ "%04d:%02d:%02d %02d:%02d:%02d",
+ pTime->tm_year + 1900,
+ pTime->tm_mon + 1,
+ pTime->tm_mday,
+ pTime->tm_hour,
+ pTime->tm_min,
+ pTime->tm_sec );
+ ret = exifTable->insertElement(TAG_DATETIME, temp_value);
+ }
+ }
+
+ if ((NO_ERROR == ret)) {
+ char temp_value[5];
+ snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mWidth);
+ ret = exifTable->insertElement(TAG_IMAGE_WIDTH, temp_value);
+ }
+
+ if ((NO_ERROR == ret)) {
+ char temp_value[5];
+ snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mHeight);
+ ret = exifTable->insertElement(TAG_IMAGE_LENGTH, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d/%d,%d/%d,%d/%d",
+ abs(mEXIFData.mGPSData.mLatDeg), 1,
+ abs(mEXIFData.mGPSData.mLatMin), 1,
+ abs(mEXIFData.mGPSData.mLatSec), abs(mEXIFData.mGPSData.mLatSecDiv));
+ ret = exifTable->insertElement(TAG_GPS_LAT, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) {
+ ret = exifTable->insertElement(TAG_GPS_LAT_REF, mEXIFData.mGPSData.mLatRef);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d/%d,%d/%d,%d/%d",
+ abs(mEXIFData.mGPSData.mLongDeg), 1,
+ abs(mEXIFData.mGPSData.mLongMin), 1,
+ abs(mEXIFData.mGPSData.mLongSec), abs(mEXIFData.mGPSData.mLongSecDiv));
+ ret = exifTable->insertElement(TAG_GPS_LONG, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) {
+ ret = exifTable->insertElement(TAG_GPS_LONG_REF, mEXIFData.mGPSData.mLongRef);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d/%d",
+ abs( mEXIFData.mGPSData.mAltitude), 1);
+ ret = exifTable->insertElement(TAG_GPS_ALT, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) {
+ char temp_value[5];
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d", mEXIFData.mGPSData.mAltitudeRef);
+ ret = exifTable->insertElement(TAG_GPS_ALT_REF, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mMapDatumValid)) {
+ ret = exifTable->insertElement(TAG_GPS_MAP_DATUM, mEXIFData.mGPSData.mMapDatum);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mProcMethodValid)) {
+ char temp_value[GPS_PROCESSING_SIZE];
+
+ memcpy(temp_value, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
+ memcpy(temp_value + sizeof(ExifAsciiPrefix),
+ mEXIFData.mGPSData.mProcMethod,
+ (GPS_PROCESSING_SIZE - sizeof(ExifAsciiPrefix)));
+ ret = exifTable->insertElement(TAG_GPS_PROCESSING_METHOD, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mVersionIdValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d,%d,%d,%d",
+ mEXIFData.mGPSData.mVersionId[0],
+ mEXIFData.mGPSData.mVersionId[1],
+ mEXIFData.mGPSData.mVersionId[2],
+ mEXIFData.mGPSData.mVersionId[3]);
+ ret = exifTable->insertElement(TAG_GPS_VERSION_ID, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mTimeStampValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d/%d,%d/%d,%d/%d",
+ mEXIFData.mGPSData.mTimeStampHour, 1,
+ mEXIFData.mGPSData.mTimeStampMin, 1,
+ mEXIFData.mGPSData.mTimeStampSec, 1);
+ ret = exifTable->insertElement(TAG_GPS_TIMESTAMP, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mDatestampValid) ) {
+ ret = exifTable->insertElement(TAG_GPS_DATESTAMP, mEXIFData.mGPSData.mDatestamp);
+ }
+
+ if (NO_ERROR == ret) {
+ const char* exif_orient =
+ ExifElementsTable::degreesToExifOrientation(mPictureRotation);
+
+ if (exif_orient) {
+ ret = exifTable->insertElement(TAG_ORIENTATION, exif_orient);
+ }
+ }
+
+ // fill in short and ushort tags
+ if (NO_ERROR == ret) {
+ char temp_value[2];
+ temp_value[1] = '\0';
+
+ // AWB
+ if (mParameters3A.WhiteBallance == OMX_WhiteBalControlAuto) {
+ temp_value[0] = '0';
+ } else {
+ temp_value[0] = '1';
+ }
+ exifTable->insertElement(TAG_WHITEBALANCE, temp_value);
+
+ // MeteringMode
+ // TODO(XXX): only supporting this metering mode at the moment, may change in future
+ temp_value[0] = '2';
+ exifTable->insertElement(TAG_METERING_MODE, temp_value);
+
+ // ExposureProgram
+ // TODO(XXX): only supporting this exposure program at the moment, may change in future
+ temp_value[0] = '3';
+ exifTable->insertElement(TAG_EXPOSURE_PROGRAM, temp_value);
+
+ // ColorSpace
+ temp_value[0] = '1';
+ exifTable->insertElement(TAG_COLOR_SPACE, temp_value);
+
+ temp_value[0] = '2';
+ exifTable->insertElement(TAG_SENSING_METHOD, temp_value);
+
+ temp_value[0] = '1';
+ exifTable->insertElement(TAG_CUSTOM_RENDERED, temp_value);
+ }
+
+ if (pAncillaryData && (NO_ERROR == ret)) {
+ unsigned int numerator = 0, denominator = 0;
+ char temp_value[256];
+ unsigned int temp_num = 0;
+
+ // DigitalZoomRatio
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u/%u",
+ pAncillaryData->nDigitalZoomFactor, 1024);
+ exifTable->insertElement(TAG_DIGITALZOOMRATIO, temp_value);
+
+ // ExposureTime
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u/%u",
+ pAncillaryData->nExposureTime, 1000000);
+ exifTable->insertElement(TAG_EXPOSURETIME, temp_value);
+
+ // ApertureValue and FNumber
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u/%u",
+ pAncillaryData->nApertureValue, 100);
+ exifTable->insertElement(TAG_FNUMBER, temp_value);
+ exifTable->insertElement(TAG_APERTURE, temp_value);
+
+ // ISO
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u,0,0",
+ pAncillaryData->nCurrentISO);
+ exifTable->insertElement(TAG_ISO_EQUIVALENT, temp_value);
+
+ // ShutterSpeed
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%f",
+ log(pAncillaryData->nExposureTime) / log(2));
+ ExifElementsTable::stringToRational(temp_value, &numerator, &denominator);
+ snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%u/%u", numerator, denominator);
+ exifTable->insertElement(TAG_SHUTTERSPEED, temp_value);
+
+ // Flash
+ if (mParameters3A.FlashMode == OMX_IMAGE_FlashControlAuto) {
+ if(pAncillaryData->nFlashStatus) temp_num = 0x19; // Flash fired, auto mode
+ else temp_num = 0x18; // Flash did not fire, auto mode
+ } else if (mParameters3A.FlashMode == OMX_IMAGE_FlashControlOn) {
+ if(pAncillaryData->nFlashStatus) temp_num = 0x9; // Flash fired, compulsory flash mode
+ else temp_num = 0x10; // Flash did not fire, compulsory flash mode
+ } else if(pAncillaryData->nFlashStatus) {
+ temp_num = 0x1; // Flash fired
+ } else {
+ temp_num = 0x0; // Flash did not fire
+ }
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u", temp_num);
+ exifTable->insertElement(TAG_FLASH, temp_value);
+
+ if (pWhiteBalanceData) {
+ unsigned int lightsource = 0;
+ unsigned int colourtemp = pWhiteBalanceData->nColorTemperature;
+ bool flash_fired = (temp_num & 0x1); // value from flash above
+
+ // stole this from framework/tools_library/src/tools_sys_exif_tags.c
+ if( colourtemp <= 3200 ) {
+ lightsource = 3; // Tungsten
+ } else if( colourtemp > 3200 && colourtemp <= 4800 ) {
+ lightsource = 2; // Fluorescent
+ } else if( colourtemp > 4800 && colourtemp <= 5500 ) {
+ lightsource = 1; // Daylight
+ } else if( colourtemp > 5500 && colourtemp <= 6500 ) {
+ lightsource = 9; // Fine weather
+ } else if( colourtemp > 6500 ) {
+ lightsource = 10; // Cloudy weather
+ }
+
+ if(flash_fired) {
+ lightsource = 4; // Flash
+ }
+
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u", lightsource);
+ exifTable->insertElement(TAG_LIGHT_SOURCE, temp_value);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::convertGPSCoord(double coord,
+ int &deg,
+ int &min,
+ int &sec,
+ int &secDivisor)
+{
+ double tmp;
+
+ LOG_FUNCTION_NAME;
+
+ if ( coord == 0 ) {
+
+ CAMHAL_LOGE("Invalid GPS coordinate");
+
+ return -EINVAL;
+ }
+
+ deg = (int) floor(fabs(coord));
+ tmp = ( fabs(coord) - floor(fabs(coord)) ) * GPS_MIN_DIV;
+ min = (int) floor(tmp);
+ tmp = ( tmp - floor(tmp) ) * ( GPS_SEC_DIV * GPS_SEC_ACCURACY );
+ sec = (int) floor(tmp);
+ secDivisor = GPS_SEC_ACCURACY;
+
+ if( sec >= ( GPS_SEC_DIV * GPS_SEC_ACCURACY ) ) {
+ sec = 0;
+ min += 1;
+ }
+
+ if( min >= 60 ) {
+ min = 0;
+ deg += 1;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXFD.cpp b/camera/OMXCameraAdapter/OMXFD.cpp
new file mode 100644
index 0000000..1a482b2
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXFD.cpp
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXFD.cpp
+*
+* This file contains functionality for handling face detection.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+namespace Ti {
+namespace Camera {
+
+const uint32_t OMXCameraAdapter::FACE_DETECTION_THRESHOLD = 80;
+
+status_t OMXCameraAdapter::setParametersFD(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startFaceDetection()
+{
+ status_t ret = NO_ERROR;
+
+ android::AutoMutex lock(mFaceDetectionLock);
+
+ ret = setFaceDetection(true, mFaceOrientation);
+ if (ret != NO_ERROR) {
+ goto out;
+ }
+
+ if ( mFaceDetectionRunning ) {
+ mFDSwitchAlgoPriority = true;
+ }
+
+ // Note: White balance will not be face prioritized, since
+ // the algorithm needs full frame statistics, and not face
+ // regions alone.
+
+ faceDetectionNumFacesLastOutput = 0;
+ out:
+ return ret;
+}
+
+status_t OMXCameraAdapter::stopFaceDetection()
+{
+ status_t ret = NO_ERROR;
+ const char *str = NULL;
+ BaseCameraAdapter::AdapterState state;
+ BaseCameraAdapter::getState(state);
+
+ android::AutoMutex lock(mFaceDetectionLock);
+
+ ret = setFaceDetection(false, mFaceOrientation);
+ if (ret != NO_ERROR) {
+ goto out;
+ }
+
+ if ( mFaceDetectionRunning ) {
+ //Enable region priority and disable face priority for AF
+ setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
+ setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO , false);
+
+ //Enable Region priority and disable Face priority
+ setAlgoPriority(REGION_PRIORITY, EXPOSURE_ALGO, true);
+ setAlgoPriority(FACE_PRIORITY, EXPOSURE_ALGO, false);
+ }
+
+ if (mPending3Asettings) {
+ apply3Asettings(mParameters3A);
+ }
+
+ faceDetectionNumFacesLastOutput = 0;
+ out:
+ return ret;
+}
+
+void OMXCameraAdapter::pauseFaceDetection(bool pause)
+{
+ android::AutoMutex lock(mFaceDetectionLock);
+ // pausing will only take affect if fd is already running
+ if (mFaceDetectionRunning) {
+ mFaceDetectionPaused = pause;
+ faceDetectionNumFacesLastOutput = 0;
+ }
+}
+
+status_t OMXCameraAdapter::setFaceDetectionOrientation(OMX_U32 orientation)
+{
+ status_t ret = NO_ERROR;
+
+ android::AutoMutex lock(mFaceDetectionLock);
+
+ mFaceOrientation = orientation;
+
+ if (mFaceDetectionRunning) {
+ // restart face detection with new rotation
+ setFaceDetection(true, orientation);
+ }
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setFaceDetection(bool enable, OMX_U32 orientation)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_OBJDETECTIONTYPE objDetection;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ if ( orientation > 270 ) {
+ orientation = 0;
+ }
+
+ OMX_INIT_STRUCT_PTR (&objDetection, OMX_CONFIG_OBJDETECTIONTYPE);
+ objDetection.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ objDetection.nDeviceOrientation = orientation;
+ if ( enable )
+ {
+ objDetection.bEnable = OMX_TRUE;
+ }
+ else
+ {
+ objDetection.bEnable = OMX_FALSE;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigImageFaceDetection,
+ &objDetection);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring face detection 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Face detection configured successfully");
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ // TODO(XXX): Should enable/disable FD extra data separately
+ // on each port.
+ ret = setExtraData(enable, OMX_ALL, OMX_FaceDetection);
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEA("Error while configuring face detection extra data");
+ }
+ else
+ {
+ CAMHAL_LOGDA("Face detection extra data configured successfully");
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mFaceDetectionRunning = enable;
+ mFaceDetectionPaused = !enable;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::createPreviewMetadata(OMX_BUFFERHEADERTYPE* pBuffHeader,
+ android::sp<CameraMetadataResult> &result,
+ size_t previewWidth,
+ size_t previewHeight)
+{
+ status_t ret = NO_ERROR;
+ status_t faceRet = NO_ERROR;
+ status_t metaRet = NO_ERROR;
+ OMX_FACEDETECTIONTYPE *faceData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateExecuting != mComponentState ) {
+ CAMHAL_LOGEA("OMX component is not in executing state");
+ return NO_INIT;
+ }
+
+ if ( NULL == pBuffHeader ) {
+ CAMHAL_LOGEA("Invalid Buffer header");
+ return-EINVAL;
+ }
+
+ if ( mFaceDetectionRunning && !mFaceDetectionPaused ) {
+ OMX_OTHER_EXTRADATATYPE *extraData;
+
+ extraData = getExtradata(pBuffHeader->pPlatformPrivate,
+ (OMX_EXTRADATATYPE)OMX_FaceDetection);
+
+ if ( NULL != extraData ) {
+ CAMHAL_LOGVB("Size = %d, sizeof = %d, eType = 0x%x, nDataSize= %d, nPortIndex = 0x%x, nVersion = 0x%x",
+ extraData->nSize,
+ sizeof(OMX_OTHER_EXTRADATATYPE),
+ extraData->eType,
+ extraData->nDataSize,
+ extraData->nPortIndex,
+ extraData->nVersion);
+ } else {
+ CAMHAL_LOGD("FD extra data not found!");
+ return -EINVAL;
+ }
+
+ faceData = ( OMX_FACEDETECTIONTYPE * ) extraData->data;
+ if ( NULL != faceData ) {
+ if ( sizeof(OMX_FACEDETECTIONTYPE) == faceData->nSize ) {
+ CAMHAL_LOGVB("Faces detected %d",
+ faceData->ulFaceCount,
+ faceData->nSize,
+ sizeof(OMX_FACEDETECTIONTYPE),
+ faceData->eCameraView,
+ faceData->nPortIndex,
+ faceData->nVersion);
+ } else {
+ CAMHAL_LOGEB("OMX_FACEDETECTIONTYPE size mismatch: expected = %d, received = %d",
+ ( unsigned int ) sizeof(OMX_FACEDETECTIONTYPE),
+ ( unsigned int ) faceData->nSize);
+ return -EINVAL;
+ }
+ } else {
+ CAMHAL_LOGEA("Invalid OMX_FACEDETECTIONTYPE");
+ return -EINVAL;
+ }
+ }
+
+ result = new (std::nothrow) CameraMetadataResult;
+ if(NULL == result.get()) {
+ ret = NO_MEMORY;
+ return ret;
+ }
+
+ //Encode face coordinates
+ faceRet = encodeFaceCoordinates(faceData, result->getMetadataResult()
+ , previewWidth, previewHeight);
+ if ((NO_ERROR == faceRet) || (NOT_ENOUGH_DATA == faceRet)) {
+ // Ignore harmless errors (no error and no update) and go ahead and encode
+ // the preview meta data
+ metaRet = encodePreviewMetadata(result->getMetadataResult()
+ , pBuffHeader->pPlatformPrivate);
+ if ( (NO_ERROR != metaRet) && (NOT_ENOUGH_DATA != metaRet) ) {
+ // Some 'real' error occurred during preview meta data encod, clear metadata
+ // result and return correct error code
+ result.clear();
+ ret = metaRet;
+ }
+ } else {
+ //Some real error occurred during face encoding, clear metadata result
+ // and return correct error code
+ result.clear();
+ ret = faceRet;
+ }
+
+ if((NOT_ENOUGH_DATA == faceRet) && (NOT_ENOUGH_DATA == metaRet)) {
+ //No point sending the callback if nothing is changed
+ result.clear();
+ ret = faceRet;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodeFaceCoordinates(const OMX_FACEDETECTIONTYPE *faceData,
+ camera_frame_metadata_t *metadataResult,
+ size_t previewWidth,
+ size_t previewHeight)
+{
+ status_t ret = NO_ERROR;
+ camera_face_t *faces;
+ size_t hRange, vRange;
+ double tmp;
+ bool faceArrayChanged = false;
+
+ LOG_FUNCTION_NAME;
+
+ hRange = CameraMetadataResult::RIGHT - CameraMetadataResult::LEFT;
+ vRange = CameraMetadataResult::BOTTOM - CameraMetadataResult::TOP;
+
+ android::AutoMutex lock(mFaceDetectionLock);
+
+ // Avoid memory leak if called twice on same CameraMetadataResult
+ if ( (0 < metadataResult->number_of_faces) && (NULL != metadataResult->faces) ) {
+ free(metadataResult->faces);
+ metadataResult->number_of_faces = 0;
+ metadataResult->faces = NULL;
+ }
+
+ if ( (NULL != faceData) && (0 < faceData->ulFaceCount) ) {
+ int orient_mult;
+ int trans_left, trans_top, trans_right, trans_bot;
+
+ faces = ( camera_face_t * ) malloc(sizeof(camera_face_t)*faceData->ulFaceCount);
+ if ( NULL == faces ) {
+ ret = NO_MEMORY;
+ goto out;
+ }
+
+ /**
+ / * When device is 180 degrees oriented to the sensor, need to translate
+ / * the output from Ducati to what Android expects
+ / * Ducati always gives face coordinates in this form, irrespective of
+ / * rotation, i.e (l,t) always represents the point towards the left eye
+ / * and top of hair.
+ / * (l, t)
+ / * ---------------
+ / * - ,,,,,,, -
+ / * - | | -
+ / * - |<a <a| -
+ / * - (| ^ |) -
+ / * - | -=- | -
+ / * - \_____/ -
+ / * ---------------
+ / * (r, b)
+ / *
+ / * However, Android expects the coords to be in respect with what the
+ / * sensor is viewing, i.e Android expects sensor to see this with (l,t)
+ / * and (r,b) like so:
+ / * (l, t)
+ / * ---------------
+ / * - _____ -
+ / * - / \ -
+ / * - | -=- | -
+ / * - (| ^ |) -
+ / * - |a> a>| -
+ / * - | | -
+ / * - ,,,,,,, -
+ / * ---------------
+ / * (r, b)
+ */
+
+ if (mFaceOrientation == 180) {
+ orient_mult = -1;
+ trans_left = 2; // right is now left
+ trans_top = 3; // bottom is now top
+ trans_right = 0; // left is now right
+ trans_bot = 1; // top is not bottom
+ } else {
+ orient_mult = 1;
+ trans_left = 0; // left
+ trans_top = 1; // top
+ trans_right = 2; // right
+ trans_bot = 3; // bottom
+ }
+
+ int j = 0, i = 0;
+ for ( ; j < faceData->ulFaceCount ; j++)
+ {
+ OMX_S32 nLeft = 0;
+ OMX_S32 nTop = 0;
+ //Face filtering
+ //For real faces, it is seen that the h/w passes a score >=80
+ //For false faces, we seem to get even a score of 70 sometimes.
+ //In order to avoid any issue at application level, we filter
+ //<=70 score here.
+ if(faceData->tFacePosition[j].nScore <= FACE_DETECTION_THRESHOLD)
+ continue;
+
+ if (mFaceOrientation == 180) {
+ // from sensor pov, the left pos is the right corner of the face in pov of frame
+ nLeft = faceData->tFacePosition[j].nLeft + faceData->tFacePosition[j].nWidth;
+ nTop = faceData->tFacePosition[j].nTop + faceData->tFacePosition[j].nHeight;
+ } else {
+ nLeft = faceData->tFacePosition[j].nLeft;
+ nTop = faceData->tFacePosition[j].nTop;
+ }
+
+ tmp = ( double ) nLeft / ( double ) previewWidth;
+ tmp *= hRange;
+ tmp -= hRange/2;
+ faces[i].rect[trans_left] = tmp;
+
+ tmp = ( double ) nTop / ( double )previewHeight;
+ tmp *= vRange;
+ tmp -= vRange/2;
+ faces[i].rect[trans_top] = tmp;
+
+ tmp = ( double ) faceData->tFacePosition[j].nWidth / ( double ) previewWidth;
+ tmp *= hRange;
+ tmp *= orient_mult;
+ faces[i].rect[trans_right] = faces[i].rect[trans_left] + tmp;
+
+ tmp = ( double ) faceData->tFacePosition[j].nHeight / ( double ) previewHeight;
+ tmp *= vRange;
+ tmp *= orient_mult;
+ faces[i].rect[trans_bot] = faces[i].rect[trans_top] + tmp;
+
+ faces[i].score = faceData->tFacePosition[j].nScore;
+ faces[i].id = 0;
+ faces[i].left_eye[0] = CameraMetadataResult::INVALID_DATA;
+ faces[i].left_eye[1] = CameraMetadataResult::INVALID_DATA;
+ faces[i].right_eye[0] = CameraMetadataResult::INVALID_DATA;
+ faces[i].right_eye[1] = CameraMetadataResult::INVALID_DATA;
+ faces[i].mouth[0] = CameraMetadataResult::INVALID_DATA;
+ faces[i].mouth[1] = CameraMetadataResult::INVALID_DATA;
+ i++;
+ }
+
+ metadataResult->number_of_faces = i;
+ metadataResult->faces = faces;
+
+ for (int i = 0; i < metadataResult->number_of_faces; i++)
+ {
+ bool faceChanged = true;
+ int centerX = (faces[i].rect[trans_left] + faces[i].rect[trans_right] ) / 2;
+ int centerY = (faces[i].rect[trans_top] + faces[i].rect[trans_bot] ) / 2;
+
+ int sizeX = (faces[i].rect[trans_right] - faces[i].rect[trans_left] ) ;
+ int sizeY = (faces[i].rect[trans_bot] - faces[i].rect[trans_top] ) ;
+
+ for (int j = 0; j < faceDetectionNumFacesLastOutput; j++)
+ {
+ int tempCenterX = (faceDetectionLastOutput[j].rect[trans_left] +
+ faceDetectionLastOutput[j].rect[trans_right] ) / 2;
+ int tempCenterY = (faceDetectionLastOutput[j].rect[trans_top] +
+ faceDetectionLastOutput[j].rect[trans_bot] ) / 2;
+ int tempSizeX = (faceDetectionLastOutput[j].rect[trans_right] -
+ faceDetectionLastOutput[j].rect[trans_left] ) ;
+ int tempSizeY = (faceDetectionLastOutput[j].rect[trans_bot] -
+ faceDetectionLastOutput[j].rect[trans_top] ) ;
+
+ if ( ( tempCenterX == centerX) &&
+ ( tempCenterY == centerY) ) {
+ // Found Face.
+ // Now check size of rectangle
+ // compare to last output.
+ if ( ( tempSizeX == sizeX ) &&
+ ( tempSizeY == sizeY ) ) {
+ faceChanged = false;
+ }
+ }
+ }
+ // Send face detection data after some face coordinate changes
+ if (faceChanged) {
+ faceArrayChanged = true;
+ }
+ }
+
+ // Save this output for next iteration
+ for (int i = 0; i < metadataResult->number_of_faces; i++)
+ {
+ faceDetectionLastOutput[i] = faces[i];
+ }
+ } else {
+ metadataResult->number_of_faces = 0;
+ metadataResult->faces = NULL;
+ }
+
+ // Send face detection data after face count changes
+ if (faceDetectionNumFacesLastOutput != metadataResult->number_of_faces) {
+ faceArrayChanged = true;
+ }
+ faceDetectionNumFacesLastOutput = metadataResult->number_of_faces;
+
+ if ( !faceArrayChanged ) {
+ ret = NOT_ENOUGH_DATA;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+out:
+
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXFocus.cpp b/camera/OMXCameraAdapter/OMXFocus.cpp
new file mode 100644
index 0000000..d478035
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXFocus.cpp
@@ -0,0 +1,892 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+* @file OMXFocus.cpp
+*
+* This file contains functionality for handling focus configurations.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+
+#define TOUCH_FOCUS_RANGE 0xFF
+#define AF_IMAGE_CALLBACK_TIMEOUT 5000000 //5 seconds timeout
+#define AF_VIDEO_CALLBACK_TIMEOUT 2800000 //2.8 seconds timeout
+
+namespace Ti {
+namespace Camera {
+
+const nsecs_t OMXCameraAdapter::CANCEL_AF_TIMEOUT = seconds_to_nanoseconds(1);
+
+status_t OMXCameraAdapter::setParametersFocus(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *str = NULL;
+ android::Vector<android::sp<CameraArea> > tempAreas;
+ size_t MAX_FOCUS_AREAS;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mFocusAreasLock);
+
+ str = params.get(android::CameraParameters::KEY_FOCUS_AREAS);
+
+ MAX_FOCUS_AREAS = atoi(params.get(android::CameraParameters::KEY_MAX_NUM_FOCUS_AREAS));
+
+ if ( NULL != str ) {
+ ret = CameraArea::parseAreas(str, ( strlen(str) + 1 ), tempAreas);
+ }
+
+ if ( (NO_ERROR == ret) && CameraArea::areAreasDifferent(mFocusAreas, tempAreas) ) {
+ mFocusAreas.clear();
+ mFocusAreas = tempAreas;
+ if ( MAX_FOCUS_AREAS < mFocusAreas.size() ) {
+ CAMHAL_LOGEB("Focus areas supported %d, focus areas set %d",
+ MAX_FOCUS_AREAS,
+ mFocusAreas.size());
+ ret = -EINVAL;
+ }
+ else {
+ if ( !mFocusAreas.isEmpty() ) {
+ setTouchFocus();
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::doAutoFocus()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
+ OMX_PARAM_FOCUSSTATUSTYPE focusStatus;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+ CameraAdapter::AdapterState state;
+ nsecs_t timeout = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component in Invalid state");
+ returnFocusStatus(false);
+ return -EINVAL;
+ }
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ returnFocusStatus(false);
+ return NO_ERROR;
+ }
+
+ if( ((AF_ACTIVE & getState()) != AF_ACTIVE) && ((AF_ACTIVE & getNextState()) != AF_ACTIVE) ) {
+ CAMHAL_LOGDA("Auto focus got canceled before doAutoFocus could be called");
+ return NO_ERROR;
+ }
+
+ // AF when fixed focus modes are set should be a no-op.
+ if ( ( mParameters3A.Focus == OMX_IMAGE_FocusControlOff ) ||
+ ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) ||
+ ( mParameters3A.Focus == OMX_IMAGE_FocusControlHyperfocal ) ) {
+ returnFocusStatus(true);
+ return NO_ERROR;
+ }
+
+ OMX_INIT_STRUCT_PTR (&focusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
+
+ // If the app calls autoFocus, the camera will stop sending face callbacks.
+ pauseFaceDetection(true);
+
+ // This is needed for applying FOCUS_REGION correctly
+ if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea()))
+ {
+ //Disable face priority
+ setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
+
+ //Enable region algorithm priority
+ setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
+ }
+
+ OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
+ focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus;
+
+ if (mParameters3A.FocusLock) {
+ // this basically means user never called cancelAutoFocus after a scan...
+ // if this is the case we need to unlock AF to ensure we will do a scan
+ if (set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) {
+ CAMHAL_LOGEA("Error Unlocking 3A locks");
+ } else {
+ CAMHAL_LOGDA("AE/AWB unlocked successfully");
+ }
+
+ } else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) {
+ // In case we have CAF running we should first check the AF status.
+ // If it has managed to lock, then do as usual and return status
+ // immediately.
+ ret = checkFocus(&focusStatus);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Focus status check failed 0x%x!", ret);
+ return ret;
+ } else {
+ CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus);
+ }
+ }
+
+ if ( (focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto &&
+ ( focusStatus.eFocusStatus == OMX_FocusStatusRequest ||
+ focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach ||
+ focusStatus.eFocusStatus == OMX_FocusStatusLost ) ) ||
+ (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE)OMX_IMAGE_FocusControlAuto) ) {
+ OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
+ bOMX.bEnabled = OMX_TRUE;
+
+ //Enable focus scanning
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable,
+ &bOMX);
+ if ( OMX_ErrorNone != eError ) {
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+
+ {
+ android::AutoMutex lock(mDoAFMutex);
+
+ // force AF, Ducati will take care of whether CAF
+ // or AF will be performed, depending on light conditions
+ if ( focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto &&
+ ( focusStatus.eFocusStatus == OMX_FocusStatusRequest ||
+ focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach ||
+ focusStatus.eFocusStatus == OMX_FocusStatusLost ) ) {
+ focusControl.eFocusControl = OMX_IMAGE_FocusControlAutoLock;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigFocusControl,
+ &focusControl);
+
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
+ return INVALID_OPERATION;
+ } else {
+ CAMHAL_LOGDA("Autofocus started successfully");
+ }
+
+ // No need to wait if preview is about to stop
+ getNextState(state);
+ if ( ( PREVIEW_ACTIVE & state ) != PREVIEW_ACTIVE ) {
+ return NO_ERROR;
+ }
+
+ // configure focus timeout based on capture mode
+ timeout = (mCapMode == VIDEO_MODE) || (mCapMode == VIDEO_MODE_HQ) ?
+ ( ( nsecs_t ) AF_VIDEO_CALLBACK_TIMEOUT * 1000 ) :
+ ( ( nsecs_t ) AF_IMAGE_CALLBACK_TIMEOUT * 1000 );
+
+
+ ret = mDoAFCond.waitRelative(mDoAFMutex, timeout);
+ }
+
+ //If somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid) {
+ CAMHAL_LOGEA("Invalid State after Auto Focus Exitting!!!");
+ return -EINVAL;
+ }
+
+ if(ret != NO_ERROR) {
+ CAMHAL_LOGEA("Autofocus callback timeout expired");
+ ret = returnFocusStatus(true);
+ } else {
+ CAMHAL_LOGDA("Autofocus callback received");
+ ret = returnFocusStatus(false);
+ }
+ } else { // Focus mode in continuous
+ if ( NO_ERROR == ret ) {
+ ret = returnFocusStatus(true);
+ mPending3Asettings |= SetFocus;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::stopAutoFocus()
+{
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component in Invalid state");
+ returnFocusStatus(false);
+ return -EINVAL;
+ }
+
+ if ( OMX_StateExecuting != mComponentState ) {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ return NO_ERROR;
+ }
+
+ if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) {
+ // No need to stop focus if we are in infinity mode. Nothing to stop.
+ return NO_ERROR;
+ }
+
+ OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
+ focusControl.eFocusControl = OMX_IMAGE_FocusControlOff;
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigFocusControl,
+ &focusControl);
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while stopping focus 0x%x", eError);
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+#ifdef CAMERAHAL_TUNA
+ else {
+ // This is a WA. Usually the OMX Camera component should
+ // generate AF status change OMX event fairly quickly
+ // ( after one preview frame ) and this notification should
+ // actually come from 'handleFocusCallback()'.
+ android::AutoMutex lock(mDoAFMutex);
+ mDoAFCond.broadcast();
+ }
+#endif
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode)
+{;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState ) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
+ focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigFocusControl,
+ &focusMode);
+
+ if ( OMX_ErrorNone != eError ) {
+ CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::cancelAutoFocus()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode;
+
+ LOG_FUNCTION_NAME;
+
+ ret = getFocusMode(focusMode);
+ if ( NO_ERROR != ret ) {
+ return ret;
+ }
+
+ //Stop the AF only for modes other than CAF, Inifinity or Off
+ if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
+ ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
+ OMX_IMAGE_FocusControlAutoInfinity ) &&
+ ( focusMode.eFocusControl != OMX_IMAGE_FocusControlOff ) ) {
+ android::AutoMutex lock(mCancelAFMutex);
+ stopAutoFocus();
+ ret = mCancelAFCond.waitRelative(mCancelAFMutex, CANCEL_AF_TIMEOUT);
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGE("Cancel AF timeout!");
+ }
+ } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) {
+ // This re-enabling of CAF doesn't seem to
+ // be needed any more.
+ // re-apply CAF after unlocking and canceling
+ // mPending3Asettings |= SetFocus;
+ }
+
+ {
+ // Signal to 'doAutoFocus()'
+ android::AutoMutex lock(mDoAFMutex);
+ mDoAFCond.broadcast();
+ }
+
+ // If the apps call #cancelAutoFocus()}, the face callbacks will also resume.
+ pauseFaceDetection(false);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+
+}
+
+status_t OMXCameraAdapter::setFocusCallback(bool enabled)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component in Invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ return NO_ERROR;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
+ focusRequstCallback.nPortIndex = OMX_ALL;
+ focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus;
+
+ if ( enabled )
+ {
+ focusRequstCallback.bEnable = OMX_TRUE;
+ }
+ else
+ {
+ focusRequstCallback.bEnable = OMX_FALSE;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
+ &focusRequstCallback);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error registering focus callback 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully",
+ OMX_IndexConfigCommonFocusStatus);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached)
+{
+ status_t ret = NO_ERROR;
+ OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
+ CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
+ BaseCameraAdapter::AdapterState state, nextState;
+ BaseCameraAdapter::getState(state);
+ BaseCameraAdapter::getNextState(nextState);
+
+ LOG_FUNCTION_NAME;
+
+ OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
+
+ if( ((AF_ACTIVE & state ) != AF_ACTIVE) && ((AF_ACTIVE & nextState ) != AF_ACTIVE) )
+ {
+ /// We don't send focus callback if focus was not started
+ CAMHAL_LOGDA("Not sending focus callback because focus was not started");
+ return NO_ERROR;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ if ( !timeoutReached )
+ {
+ ret = checkFocus(&eFocusStatus);
+
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEA("Focus status check failed!");
+ }
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ if ( timeoutReached )
+ {
+ focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
+ }
+ else
+ {
+ switch (eFocusStatus.eFocusStatus)
+ {
+ case OMX_FocusStatusReached:
+ {
+ focusStatus = CameraHalEvent::FOCUS_STATUS_SUCCESS;
+ break;
+ }
+ case OMX_FocusStatusOff: // AF got canceled
+ return NO_ERROR;
+ case OMX_FocusStatusUnableToReach:
+ case OMX_FocusStatusRequest:
+ default:
+ {
+ focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
+ break;
+ }
+ }
+ // Lock CAF after AF call
+ if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_TRUE) != NO_ERROR) {
+ CAMHAL_LOGEA("Error Applying 3A locks");
+ } else {
+ CAMHAL_LOGDA("Focus locked. Applied focus locks successfully");
+ }
+
+ stopAutoFocus();
+ }
+ //Query current focus distance after AF is complete
+ updateFocusDistances(mParameters);
+ }
+
+ ret = BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS);
+ if ( NO_ERROR == ret )
+ {
+ ret = BaseCameraAdapter::commitState();
+ }
+ else
+ {
+ ret |= BaseCameraAdapter::rollbackState();
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ notifyFocusSubscribers(focusStatus);
+ }
+
+ // After focus, face detection will resume sending face callbacks
+ pauseFaceDetection(false);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == eFocusStatus )
+ {
+ CAMHAL_LOGEA("Invalid focus status");
+ ret = -EINVAL;
+ }
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component in Invalid state");
+ ret = -EINVAL;
+ }
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ ret = NO_ERROR;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonFocusStatus,
+ eFocusStatus);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError);
+ ret = -1;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::updateFocusDistances(android::CameraParameters &params)
+{
+ OMX_U32 focusNear, focusOptimal, focusFar;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ ret = getFocusDistances(focusNear, focusOptimal, focusFar);
+ if ( NO_ERROR == ret)
+ {
+ ret = addFocusDistances(focusNear, focusOptimal, focusFar, params);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret);
+ }
+ }
+ else
+ {
+ CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError;
+
+ OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = UNKNOWN_ERROR;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE);
+ focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance,
+ &focusDist);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError);
+ ret = UNKNOWN_ERROR;
+ }
+
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ near = focusDist.nFocusDistanceNear;
+ optimal = focusDist.nFocusDistanceOptimal;
+ far = focusDist.nFocusDistanceFar;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length)
+{
+ status_t ret = NO_ERROR;
+ uint32_t focusScale = 1000;
+ float distFinal;
+
+ LOG_FUNCTION_NAME;
+
+ if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
+ {
+ dist=0;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ if ( 0 == dist )
+ {
+ strncpy(buffer, android::CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 ));
+ }
+ else
+ {
+ distFinal = dist;
+ distFinal /= focusScale;
+ snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near,
+ OMX_U32 &optimal,
+ OMX_U32 &far,
+ android::CameraParameters& params)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+ ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear,
+ mFocusDistOptimal,
+ mFocusDistFar);
+
+ params.set(android::CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setTouchFocus()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ OMX_ALGOAREASTYPE *focusAreas;
+ OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
+ CameraBuffer *bufferlist;
+ int areasSize = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096;
+ bufferlist = mMemMgr.allocateBufferList(0, 0, NULL, areasSize, 1);
+ focusAreas = (OMX_ALGOAREASTYPE*) bufferlist[0].opaque;
+
+ OMXCameraPortParameters * mPreviewData = NULL;
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ if (!focusAreas)
+ {
+ CAMHAL_LOGEB("Error allocating buffer for focus areas %d", eError);
+ return -ENOMEM;
+ }
+
+ OMX_INIT_STRUCT_PTR (focusAreas, OMX_ALGOAREASTYPE);
+
+ focusAreas->nPortIndex = OMX_ALL;
+ focusAreas->nNumAreas = mFocusAreas.size();
+ focusAreas->nAlgoAreaPurpose = OMX_AlgoAreaFocus;
+
+ // If the area is the special case of (0, 0, 0, 0, 0), then
+ // the algorithm needs nNumAreas to be set to 0,
+ // in order to automatically choose the best fitting areas.
+ if ( mFocusAreas.itemAt(0)->isZeroArea() )
+ {
+ focusAreas->nNumAreas = 0;
+ }
+
+ for ( unsigned int n = 0; n < mFocusAreas.size(); n++) {
+ int widthDivisor = 1;
+ int heightDivisor = 1;
+
+ if (mPreviewData->mFrameLayoutType == OMX_TI_StereoFrameLayoutTopBottom) {
+ heightDivisor = 2;
+ }
+ if (mPreviewData->mFrameLayoutType == OMX_TI_StereoFrameLayoutLeftRight) {
+ widthDivisor = 2;
+ }
+
+ // transform the coordinates to 3A-type coordinates
+ mFocusAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth/widthDivisor,
+ (size_t)mPreviewData->mHeight/heightDivisor,
+ (size_t&)focusAreas->tAlgoAreas[n].nTop,
+ (size_t&)focusAreas->tAlgoAreas[n].nLeft,
+ (size_t&)focusAreas->tAlgoAreas[n].nWidth,
+ (size_t&)focusAreas->tAlgoAreas[n].nHeight);
+
+ focusAreas->tAlgoAreas[n].nLeft =
+ ( focusAreas->tAlgoAreas[n].nLeft * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
+ focusAreas->tAlgoAreas[n].nTop =
+ ( focusAreas->tAlgoAreas[n].nTop* TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
+ focusAreas->tAlgoAreas[n].nWidth =
+ ( focusAreas->tAlgoAreas[n].nWidth * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
+ focusAreas->tAlgoAreas[n].nHeight =
+ ( focusAreas->tAlgoAreas[n].nHeight * TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
+ focusAreas->tAlgoAreas[n].nPriority = mFocusAreas.itemAt(n)->getWeight();
+
+ CAMHAL_LOGDB("Focus area %d : top = %d left = %d width = %d height = %d prio = %d",
+ n, (int)focusAreas->tAlgoAreas[n].nTop, (int)focusAreas->tAlgoAreas[n].nLeft,
+ (int)focusAreas->tAlgoAreas[n].nWidth, (int)focusAreas->tAlgoAreas[n].nHeight,
+ (int)focusAreas->tAlgoAreas[n].nPriority);
+ }
+
+ OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
+
+ sharedBuffer.nPortIndex = OMX_ALL;
+ sharedBuffer.nSharedBuffSize = areasSize;
+ sharedBuffer.pSharedBuff = (OMX_U8 *) camera_buffer_get_omx_ptr (&bufferlist[0]);
+
+ if ( NULL == sharedBuffer.pSharedBuff )
+ {
+ CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
+ ret = -ENOMEM;
+ goto EXIT;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer);
+
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError);
+ ret = -EINVAL;
+ }
+
+ EXIT:
+ if (NULL != bufferlist)
+ {
+ mMemMgr.freeBufferList (bufferlist);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+void OMXCameraAdapter::handleFocusCallback() {
+ OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
+ CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
+ status_t ret = NO_ERROR;
+ BaseCameraAdapter::AdapterState nextState, currentState;
+ BaseCameraAdapter::getNextState(nextState);
+ BaseCameraAdapter::getState(currentState);
+
+ // Dropping AF callback if it triggered in non AF state
+ if ((currentState != AF_STATE) && (currentState != AF_ZOOM_STATE) &&
+ (currentState != VIDEO_AF_STATE) && (nextState != VIDEO_AF_STATE) &&
+ (nextState != AF_STATE) && (nextState != AF_ZOOM_STATE)) {
+ return;
+ }
+
+ OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
+
+ ret = checkFocus(&eFocusStatus);
+
+ if (NO_ERROR != ret) {
+ CAMHAL_LOGEA("Focus status check failed!");
+ // signal and unblock doAutoFocus
+ if (AF_ACTIVE & nextState) {
+ android::AutoMutex lock(mDoAFMutex);
+ mDoAFCond.broadcast();
+ }
+ return;
+ }
+
+ if ( eFocusStatus.eFocusStatus == OMX_FocusStatusOff ) {
+ android::AutoMutex lock(mCancelAFMutex);
+ mCancelAFCond.signal();
+ return;
+ }
+
+ if (eFocusStatus.eFocusStatus != OMX_FocusStatusRequest) {
+ // signal doAutoFocus when a end of scan message comes
+ // ignore start of scan
+ android::AutoMutex lock(mDoAFMutex);
+ mDoAFCond.broadcast();
+ }
+
+ if (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE) OMX_IMAGE_FocusControlAuto) {
+ CAMHAL_LOGDA("unregistered focus callback when not in CAF or doAutoFocus... not handling");
+ return;
+ }
+
+ // Handling for CAF Callbacks
+ switch (eFocusStatus.eFocusStatus) {
+ case OMX_FocusStatusRequest:
+ focusStatus = CameraHalEvent::FOCUS_STATUS_PENDING;
+ break;
+ case OMX_FocusStatusReached:
+ case OMX_FocusStatusOff:
+ case OMX_FocusStatusUnableToReach:
+ default:
+ focusStatus = CameraHalEvent::FOCUS_STATUS_DONE;
+ break;
+ }
+
+ notifyFocusSubscribers(focusStatus);
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXMetadata.cpp b/camera/OMXCameraAdapter/OMXMetadata.cpp
new file mode 100644
index 0000000..af8c49c
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXMetadata.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMX3A.cpp
+*
+* This file contains functionality for handling 3A configurations.
+*
+*/
+
+#undef LOG_TAG
+
+#define LOG_TAG "OMXMetaData"
+
+#include "OMXCameraAdapter.h"
+#include <camera/CameraMetadata.h>
+
+namespace Ti {
+namespace Camera {
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+camera_memory_t * OMXCameraAdapter::getMetaData(const OMX_PTR plat_pvt,
+ camera_request_memory allocator) const
+{
+ camera_memory_t * ret = NULL;
+
+ OMX_OTHER_EXTRADATATYPE *extraData;
+ OMX_FACEDETECTIONTYPE *faceData = NULL;
+ OMX_TI_WHITEBALANCERESULTTYPE * WBdata = NULL;
+ OMX_TI_VECTSHOTINFOTYPE *shotInfo = NULL;
+ OMX_TI_LSCTABLETYPE *lscTbl = NULL;
+ camera_metadata_t *metaData;
+ size_t offset = 0;
+
+ size_t metaDataSize = sizeof(camera_metadata_t);
+
+ extraData = getExtradata(plat_pvt, (OMX_EXTRADATATYPE) OMX_FaceDetection);
+ if ( NULL != extraData ) {
+ faceData = ( OMX_FACEDETECTIONTYPE * ) extraData->data;
+ metaDataSize += faceData->ulFaceCount * sizeof(camera_metadata_face_t);
+ }
+
+ extraData = getExtradata(plat_pvt, (OMX_EXTRADATATYPE) OMX_WhiteBalance);
+ if ( NULL != extraData ) {
+ WBdata = ( OMX_TI_WHITEBALANCERESULTTYPE * ) extraData->data;
+ }
+
+ extraData = getExtradata(plat_pvt, (OMX_EXTRADATATYPE) OMX_TI_VectShotInfo);
+ if ( NULL != extraData ) {
+ shotInfo = ( OMX_TI_VECTSHOTINFOTYPE * ) extraData->data;
+ }
+
+ extraData = getExtradata(plat_pvt, (OMX_EXTRADATATYPE) OMX_TI_LSCTable);
+ if ( NULL != extraData ) {
+ lscTbl = ( OMX_TI_LSCTABLETYPE * ) extraData->data;
+ metaDataSize += OMX_TI_LSC_GAIN_TABLE_SIZE;
+ }
+
+ ret = allocator(-1, metaDataSize, 1, NULL);
+ if ( NULL == ret ) {
+ return NULL;
+ } else {
+ metaData = static_cast<camera_metadata_t *> (ret->data);
+ offset += sizeof(camera_metadata_t);
+ }
+
+ if ( NULL != faceData ) {
+ metaData->number_of_faces = 0;
+ int idx = 0;
+ metaData->faces_offset = offset;
+ struct camera_metadata_face *faces = reinterpret_cast<struct camera_metadata_face *> (static_cast<char*>(ret->data) + offset);
+ for ( int j = 0; j < faceData->ulFaceCount ; j++ ) {
+ if(faceData->tFacePosition[j].nScore <= FACE_DETECTION_THRESHOLD) {
+ continue;
+ }
+ idx = metaData->number_of_faces;
+ metaData->number_of_faces++;
+ // TODO: Rework and re-use encodeFaceCoordinates()
+ faces[idx].left = faceData->tFacePosition[j].nLeft;
+ faces[idx].top = faceData->tFacePosition[j].nTop;
+ faces[idx].bottom = faceData->tFacePosition[j].nWidth;
+ faces[idx].right = faceData->tFacePosition[j].nHeight;
+ }
+ offset += sizeof(camera_metadata_face_t) * metaData->number_of_faces;
+ }
+
+ if ( NULL != WBdata ) {
+ metaData->awb_temp = WBdata->nColorTemperature;
+ metaData->gain_b = WBdata->nGainB;
+ metaData->gain_gb = WBdata->nGainGB;
+ metaData->gain_gr = WBdata->nGainGR;
+ metaData->gain_r = WBdata->nGainR;
+ metaData->offset_b = WBdata->nOffsetB;
+ metaData->offset_gb = WBdata->nOffsetGB;
+ metaData->offset_gr = WBdata->nOffsetGR;
+ metaData->offset_r = WBdata->nOffsetR;
+ }
+
+ if ( NULL != lscTbl ) {
+ metaData->lsc_table_applied = lscTbl->bApplied;
+ metaData->lsc_table_size = OMX_TI_LSC_GAIN_TABLE_SIZE;
+ metaData->lsc_table_offset = offset;
+ uint8_t *lsc_table = reinterpret_cast<uint8_t *> (static_cast<char*>(ret->data) + offset);
+ memcpy(lsc_table, lscTbl->pGainTable, OMX_TI_LSC_GAIN_TABLE_SIZE);
+ offset += metaData->lsc_table_size;
+ }
+
+ if ( NULL != shotInfo ) {
+ metaData->frame_number = shotInfo->nFrameNum;
+ metaData->shot_number = shotInfo->nConfigId;
+ metaData->analog_gain = shotInfo->nAGain;
+ metaData->analog_gain_req = shotInfo->nReqGain;
+ metaData->analog_gain_min = shotInfo->nGainMin;
+ metaData->analog_gain_max = shotInfo->nGainMax;
+ metaData->analog_gain_error = shotInfo->nSenAGainErr;
+ metaData->analog_gain_dev = shotInfo->nDevAGain;
+ metaData->exposure_time = shotInfo->nExpTime;
+ metaData->exposure_time_req = shotInfo->nReqExpTime;
+ metaData->exposure_time_min = shotInfo->nExpMin;
+ metaData->exposure_time_max = shotInfo->nExpMax;
+ metaData->exposure_time_dev = shotInfo->nDevExpTime;
+ metaData->exposure_time_error = shotInfo->nSenExpTimeErr;
+ metaData->exposure_compensation_req = shotInfo->nReqEC;
+ metaData->exposure_dev = shotInfo->nDevEV;
+ }
+
+ return ret;
+}
+#endif
+
+status_t OMXCameraAdapter::encodePreviewMetadata(camera_frame_metadata_t *meta, const OMX_PTR plat_pvt)
+{
+ status_t ret = NO_ERROR;
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ OMX_OTHER_EXTRADATATYPE *extraData = NULL;
+
+ extraData = getExtradata(plat_pvt, (OMX_EXTRADATATYPE) OMX_TI_VectShotInfo);
+
+ if ( (NULL != extraData) && (NULL != extraData->data) ) {
+ OMX_TI_VECTSHOTINFOTYPE *shotInfo;
+ shotInfo = (OMX_TI_VECTSHOTINFOTYPE*) extraData->data;
+
+ meta->analog_gain = shotInfo->nAGain;
+ meta->exposure_time = shotInfo->nExpTime;
+ } else {
+ meta->analog_gain = -1;
+ meta->exposure_time = -1;
+ }
+
+ // Send metadata event only after any value has been changed
+ if ((metadataLastAnalogGain == meta->analog_gain) &&
+ (metadataLastExposureTime == meta->exposure_time)) {
+ ret = NOT_ENOUGH_DATA;
+ } else {
+ metadataLastAnalogGain = meta->analog_gain;
+ metadataLastExposureTime = meta->exposure_time;
+ }
+#else
+ // no-op in non enhancement mode
+ CAMHAL_UNUSED(meta);
+ CAMHAL_UNUSED(plat_pvt);
+#endif
+
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXReprocess.cpp b/camera/OMXCameraAdapter/OMXReprocess.cpp
new file mode 100644
index 0000000..6fdbe7b
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXReprocess.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXReprocess.cpp
+*
+* This file contains functionality for handling reprocessing operations.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+
+
+namespace Ti {
+namespace Camera {
+
+status_t OMXCameraAdapter::setParametersReprocess(const android::CameraParameters &params,
+ CameraBuffer* buffers,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ int w, h, s;
+ OMX_COLOR_FORMATTYPE pixFormat;
+ OMXCameraPortParameters *portData;
+ const char* valstr;
+
+ LOG_FUNCTION_NAME;
+
+ if (!buffers) {
+ CAMHAL_LOGE("invalid buffer array");
+ return BAD_VALUE;
+ }
+
+ portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex];
+
+ w = buffers[0].width;
+ h = buffers[0].height;
+ s = buffers[0].stride;
+
+ valstr = buffers[0].format;
+ if (valstr != NULL) {
+ if(strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ } else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) {
+ CAMHAL_LOGDA("RAW Picture format selected");
+ pixFormat = OMX_COLOR_FormatRawBayer10bit;
+ } else if (strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ CAMHAL_LOGDA("YUV422i Picture format selected");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ } else {
+ CAMHAL_LOGDA("Format not supported, selecting YUV420SP by default");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+ } else {
+ CAMHAL_LOGDA("Format not supported, selecting YUV420SP by default");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+
+ if ( (w != (int)portData->mWidth) || (h != (int)portData->mHeight) ||
+ (s != (int) portData->mStride) || (pixFormat != portData->mColorFormat)) {
+ portData->mWidth = w;
+ portData->mHeight = h;
+
+ if ( ( OMX_COLOR_FormatRawBayer10bit == pixFormat ) ||
+ ( OMX_COLOR_FormatCbYCrY == pixFormat ) ) {
+ portData->mStride = w * 2;
+ } else {
+ portData->mStride = s;
+ }
+
+ portData->mColorFormat = pixFormat;
+
+ mPendingReprocessSettings |= SetFormat;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startReprocess()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters * portData = NULL;
+
+ LOG_FUNCTION_NAME;
+ CAMHAL_LOGD ("mReprocConfigured = %d", mReprocConfigured);
+ if (!mReprocConfigured) {
+ return NO_ERROR;
+ }
+
+ portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex];
+
+ CAMHAL_LOGD ("mReprocConfigured = %d", mBurstFramesQueued);
+ if (NO_ERROR == ret) {
+ android::AutoMutex lock(mBurstLock);
+
+ for ( int index = 0 ; index < portData->mMaxQueueable ; index++ ) {
+ CAMHAL_LOGDB("Queuing buffer on video input port - %p, offset: %d, length: %d",
+ portData->mBufferHeader[index]->pBuffer,
+ portData->mBufferHeader[index]->nOffset,
+ portData->mBufferHeader[index]->nFilledLen);
+ portData->mStatus[index] = OMXCameraPortParameters::FILL;
+ eError = OMX_EmptyThisBuffer(mCameraAdapterParameters.mHandleComp,
+ (OMX_BUFFERHEADERTYPE*)portData->mBufferHeader[index]);
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ CameraHal::PPM("startReprocess buffers queued on video port: ", &mStartCapture);
+#endif
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::stopReprocess()
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters *portData = NULL;
+
+ if (!mReprocConfigured) {
+ return NO_ERROR;
+ }
+
+ portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex];
+
+ // Disable port - send command and then free all buffers
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mVideoInPortIndex,
+ mStopReprocSem);
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mVideoInPortIndex,
+ NULL);
+ if (portData) {
+ CAMHAL_LOGDB("Freeing buffers on reproc port - num: %d", portData->mNumBufs);
+ for (int index = 0 ; index < portData->mNumBufs ; index++) {
+ CAMHAL_LOGDB("Freeing buffer on reproc port - 0x%x",
+ ( unsigned int ) portData->mBufferHeader[index]->pBuffer);
+ eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
+ mCameraAdapterParameters.mVideoInPortIndex,
+ (OMX_BUFFERHEADERTYPE*)portData->mBufferHeader[index]);
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+ }
+ CAMHAL_LOGDA("Waiting for port disable");
+ ret = mStopReprocSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if (mComponentState == OMX_StateInvalid) {
+ CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!");
+ goto EXIT;
+ }
+ if (NO_ERROR == ret) {
+ CAMHAL_LOGDA("Port disabled");
+ } else {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mVideoInPortIndex,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on port disable");
+ goto EXIT;
+ }
+
+ deinitInternalBuffers(mCameraAdapterParameters.mVideoInPortIndex);
+
+ mReprocConfigured = false;
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::disableReprocess(){
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ // no-op..for now
+
+EXIT:
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+}
+
+status_t OMXCameraAdapter::UseBuffersReprocess(CameraBuffer *bufArr, int num)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters *portData = NULL;
+
+ portData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mVideoInPortIndex];
+
+ if ( 0 != mUseReprocessSem.Count() ) {
+ CAMHAL_LOGEB("Error mUseReprocessSem semaphore count %d", mUseReprocessSem.Count());
+ return BAD_VALUE;
+ }
+
+ CAMHAL_ASSERT(num > 0);
+
+ if (mAdapterState == REPROCESS_STATE) {
+ stopReprocess();
+ } else if (mAdapterState == CAPTURE_STATE) {
+ stopImageCapture();
+ stopReprocess();
+ }
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Reprocess stopping image capture and disabling image port: ", &bufArr->ppmStamp);
+
+#endif
+
+ portData->mNumBufs = num;
+
+ // Configure
+ ret = setParametersReprocess(mParams, bufArr, mAdapterState);
+
+ if (mReprocConfigured) {
+ if (mPendingReprocessSettings & ECaptureParamSettings) {
+ stopReprocess();
+ } else {
+ // Tap in port has been already configured.
+ return NO_ERROR;
+ }
+ }
+
+ if (mPendingReprocessSettings & SetFormat) {
+ mPendingReprocessSettings &= ~SetFormat;
+ ret = setFormat(OMX_CAMERA_PORT_VIDEO_IN_VIDEO, *portData);
+ if ( ret != NO_ERROR ) {
+ CAMHAL_LOGEB("setFormat() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+ }
+
+ // Configure DOMX to use either gralloc handles or vptrs
+ OMX_TI_PARAMUSENATIVEBUFFER domxUseGrallocHandles;
+ OMX_INIT_STRUCT_PTR (&domxUseGrallocHandles, OMX_TI_PARAMUSENATIVEBUFFER);
+
+ domxUseGrallocHandles.nPortIndex = mCameraAdapterParameters.mVideoInPortIndex;
+ if (bufArr[0].type == CAMERA_BUFFER_ANW) {
+ CAMHAL_LOGD("Using ANW");
+ domxUseGrallocHandles.bEnable = OMX_TRUE;
+
+ // Need to allocate tiler reservation and state we are going to be using
+ // pagelist buffers. Assuming this happens when buffers if from anw
+ initInternalBuffers(mCameraAdapterParameters.mVideoInPortIndex);
+ } else {
+ CAMHAL_LOGD("Using ION");
+ domxUseGrallocHandles.bEnable = OMX_FALSE;
+ }
+ eError = OMX_SetParameter(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexUseNativeBuffers, &domxUseGrallocHandles);
+ if (eError!=OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_SetParameter - %x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Reprocess configuration done: ", &bufArr->ppmStamp);
+
+#endif
+
+ // Enable Port
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mVideoInPortIndex,
+ mUseReprocessSem);
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mVideoInPortIndex,
+ NULL);
+ GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
+
+ for (int index = 0 ; index < portData->mNumBufs ; index++)
+ {
+ OMX_BUFFERHEADERTYPE *pBufferHdr;
+ CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d",
+ (unsigned int)bufArr[index].opaque,
+ (int)portData->mBufSize);
+
+ eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp,
+ &pBufferHdr,
+ mCameraAdapterParameters.mVideoInPortIndex,
+ 0,
+ portData->mBufSize,
+ (OMX_U8*)camera_buffer_get_omx_ptr(&bufArr[index]));
+
+ CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
+ GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
+
+ pBufferHdr->pAppPrivate = (OMX_PTR) &bufArr[index];
+ bufArr[index].index = index;
+ pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ pBufferHdr->nVersion.s.nVersionMajor = 1 ;
+ pBufferHdr->nVersion.s.nVersionMinor = 1 ;
+ pBufferHdr->nVersion.s.nRevision = 0;
+ pBufferHdr->nVersion.s.nStep = 0;
+ pBufferHdr->nOffset = bufArr[index].offset;
+ pBufferHdr->nFilledLen = bufArr[index].actual_size;
+ portData->mBufferHeader[index] = pBufferHdr;
+ }
+
+ // Wait for port enable event
+ CAMHAL_LOGDA("Waiting for port enable");
+ ret = mUseReprocessSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ // Error out if somethiing bad happened while we wait
+ if (mComponentState == OMX_StateInvalid) {
+ CAMHAL_LOGEA("Invalid State while trying to enable port for reprocessing");
+ goto EXIT;
+ }
+
+ if (ret == NO_ERROR) {
+ CAMHAL_LOGDA("Port enabled");
+ } else {
+ ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mVideoInPortIndex,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on port enable");
+ goto EXIT;
+ }
+
+ mReprocConfigured = true;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Reprocess video port enabled and buffers registered: ", &bufArr->ppmStamp);
+
+#endif
+
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ // Release image buffers
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+ performCleanupAfterError();
+ LOG_FUNCTION_NAME_EXIT;
+ return (ret | Utils::ErrorUtils::omxToAndroidError(eError));
+
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OMXCameraAdapter/OMXZoom.cpp b/camera/OMXCameraAdapter/OMXZoom.cpp
new file mode 100644
index 0000000..e39a3b0
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXZoom.cpp
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXZoom.cpp
+*
+* This file contains functionality for handling zoom configurations.
+*
+*/
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+namespace Ti {
+namespace Camera {
+
+const int32_t OMXCameraAdapter::ZOOM_STEPS [ZOOM_STAGES] = {
+ 65536, 68157, 70124, 72745,
+ 75366, 77988, 80609, 83231,
+ 86508, 89784, 92406, 95683,
+ 99615, 102892, 106168, 110100,
+ 114033, 117965, 122552, 126484,
+ 131072, 135660, 140247, 145490,
+ 150733, 155976, 161219, 167117,
+ 173015, 178913, 185467, 192020,
+ 198574, 205783, 212992, 220201,
+ 228065, 236585, 244449, 252969,
+ 262144, 271319, 281149, 290980,
+ 300810, 311951, 322437, 334234,
+ 346030, 357827, 370934, 384041,
+ 397148, 411566, 425984, 441057,
+ 456131, 472515, 488899, 506593,
+ 524288 };
+
+
+status_t OMXCameraAdapter::setParametersZoom(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ android::AutoMutex lock(mZoomLock);
+
+ LOG_FUNCTION_NAME;
+
+ //Immediate zoom should not be avaialable while smooth zoom is running
+ if ( ( ZOOM_ACTIVE & state ) != ZOOM_ACTIVE )
+ {
+ int zoom = params.getInt(android::CameraParameters::KEY_ZOOM);
+ if (( zoom >= 0 ) && ( zoom < mMaxZoomSupported )) {
+ mTargetZoomIdx = zoom;
+
+ //Immediate zoom should be applied instantly ( CTS requirement )
+ mCurrentZoomIdx = mTargetZoomIdx;
+ if(!mZoomUpdating) {
+ doZoom(mCurrentZoomIdx);
+ mZoomUpdating = true;
+ } else {
+ mZoomUpdate = true;
+ }
+
+ CAMHAL_LOGDB("Zoom by App %d", zoom);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::doZoom(int index)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_SCALEFACTORTYPE zoomControl;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -1;
+ }
+
+ if (( 0 > index) || ((mMaxZoomSupported - 1 ) < index )) {
+ CAMHAL_LOGEB("Zoom index %d out of range", index);
+ ret = -EINVAL;
+ }
+
+ if (mPreviousZoomIndx == index )
+ {
+ return NO_ERROR;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT_PTR (&zoomControl, OMX_CONFIG_SCALEFACTORTYPE);
+ zoomControl.nPortIndex = OMX_ALL;
+ zoomControl.xHeight = ZOOM_STEPS[index];
+ zoomControl.xWidth = ZOOM_STEPS[index];
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonDigitalZoom,
+ &zoomControl);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while applying digital zoom 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Digital zoom applied successfully");
+ mPreviousZoomIndx = index;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::advanceZoom()
+{
+ status_t ret = NO_ERROR;
+ AdapterState state;
+ android::AutoMutex lock(mZoomLock);
+
+ BaseCameraAdapter::getState(state);
+
+ if ( mReturnZoomStatus )
+ {
+ mCurrentZoomIdx +=mZoomInc;
+ mTargetZoomIdx = mCurrentZoomIdx;
+ mReturnZoomStatus = false;
+ ret = doZoom(mCurrentZoomIdx);
+ notifyZoomSubscribers(mCurrentZoomIdx, true);
+ }
+ else if ( mCurrentZoomIdx != mTargetZoomIdx )
+ {
+ if ( ZOOM_ACTIVE & state )
+ {
+ if ( mCurrentZoomIdx < mTargetZoomIdx )
+ {
+ mZoomInc = 1;
+ }
+ else
+ {
+ mZoomInc = -1;
+ }
+
+ mCurrentZoomIdx += mZoomInc;
+ }
+ else
+ {
+ mCurrentZoomIdx = mTargetZoomIdx;
+ }
+
+ ret = doZoom(mCurrentZoomIdx);
+
+ if ( ZOOM_ACTIVE & state )
+ {
+ if ( mCurrentZoomIdx == mTargetZoomIdx )
+ {
+ CAMHAL_LOGDB("[Goal Reached] Smooth Zoom notify currentIdx = %d, targetIdx = %d",
+ mCurrentZoomIdx,
+ mTargetZoomIdx);
+
+ if ( NO_ERROR == ret )
+ {
+
+ ret = BaseCameraAdapter::setState(CAMERA_STOP_SMOOTH_ZOOM);
+
+ if ( NO_ERROR == ret )
+ {
+ ret = BaseCameraAdapter::commitState();
+ }
+ else
+ {
+ ret |= BaseCameraAdapter::rollbackState();
+ }
+
+ }
+ mReturnZoomStatus = false;
+ notifyZoomSubscribers(mCurrentZoomIdx, true);
+ }
+ else
+ {
+ CAMHAL_LOGDB("[Advancing] Smooth Zoom notify currentIdx = %d, targetIdx = %d",
+ mCurrentZoomIdx,
+ mTargetZoomIdx);
+ notifyZoomSubscribers(mCurrentZoomIdx, false);
+ }
+ }
+ }
+ else if ( (mCurrentZoomIdx == mTargetZoomIdx ) &&
+ ( ZOOM_ACTIVE & state ) )
+ {
+ ret = BaseCameraAdapter::setState(CameraAdapter::CAMERA_STOP_SMOOTH_ZOOM);
+
+ if ( NO_ERROR == ret )
+ {
+ ret = BaseCameraAdapter::commitState();
+ }
+ else
+ {
+ ret |= BaseCameraAdapter::rollbackState();
+ }
+
+ }
+
+ if(mZoomUpdate) {
+ doZoom(mTargetZoomIdx);
+ mZoomUpdate = false;
+ mZoomUpdating = true;
+ } else {
+ mZoomUpdating = false;
+ }
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startSmoothZoom(int targetIdx)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mZoomLock);
+
+ CAMHAL_LOGDB("Start smooth zoom target = %d, mCurrentIdx = %d",
+ targetIdx,
+ mCurrentZoomIdx);
+
+ if (( targetIdx >= 0 ) && ( targetIdx < mMaxZoomSupported )) {
+ mTargetZoomIdx = targetIdx;
+ mZoomParameterIdx = mCurrentZoomIdx;
+ mReturnZoomStatus = false;
+ } else {
+ CAMHAL_LOGEB("Smooth value out of range %d!", targetIdx);
+ ret = -EINVAL;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::stopSmoothZoom()
+{
+ status_t ret = NO_ERROR;
+ android::AutoMutex lock(mZoomLock);
+
+ LOG_FUNCTION_NAME;
+
+ if ( mTargetZoomIdx != mCurrentZoomIdx )
+ {
+ if ( mCurrentZoomIdx < mTargetZoomIdx )
+ {
+ mZoomInc = 1;
+ }
+ else
+ {
+ mZoomInc = -1;
+ }
+ mReturnZoomStatus = true;
+ mReturnZoomStatus = true;
+ CAMHAL_LOGDB("Stop smooth zoom mCurrentZoomIdx = %d, mTargetZoomIdx = %d",
+ mCurrentZoomIdx,
+ mTargetZoomIdx);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/OmxFrameDecoder.cpp b/camera/OmxFrameDecoder.cpp
new file mode 100644
index 0000000..be794e5
--- /dev/null
+++ b/camera/OmxFrameDecoder.cpp
@@ -0,0 +1,1077 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ErrorUtils.h"
+#include "OmxFrameDecoder.h"
+#include "OMX_TI_IVCommon.h"
+#include "OMX_TI_Index.h"
+#include "Decoder_libjpeg.h"
+
+
+namespace Ti {
+namespace Camera {
+
+const static uint32_t kMaxColorFormatSupported = 1000;
+const static int kMaxStateSwitchTimeOut = 1 * 1000 * 1000 * 1000; // 1 sec
+
+static const char* gDecoderRole[2] = {"video_decoder.mjpeg", "video_decoder.avc"};
+static const OMX_VIDEO_CODINGTYPE gCompressionFormat[2] = {OMX_VIDEO_CodingMJPEG, OMX_VIDEO_CodingAVC};
+
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+
+
+CallbackDispatcher::CallbackDispatcher()
+: mDone(false) {
+ mThread = new CallbackDispatcherThread(this);
+ mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
+}
+
+CallbackDispatcher::~CallbackDispatcher() {
+ {
+ android::Mutex::Autolock autoLock(mLock);
+
+ mDone = true;
+ mQueueChanged.signal();
+ }
+
+ status_t status = mThread->join();
+ if (status != WOULD_BLOCK) {
+ //CAMHAL_ASSERT(status, (status_t)NO_ERROR);
+ }
+}
+
+void CallbackDispatcher::post(const OmxMessage &msg) {
+ android::Mutex::Autolock autoLock(mLock);
+
+ mQueue.push_back(msg);
+ mQueueChanged.signal();
+}
+
+void CallbackDispatcher::dispatch(const OmxMessage &msg) {
+
+ switch(msg.type)
+ {
+ case OmxMessage::EVENT :
+ {
+ static_cast<OmxFrameDecoder*>(msg.u.eventData.appData)->eventHandler(msg.u.eventData.event, msg.u.eventData.data1, msg.u.eventData.data2, msg.u.eventData.pEventData);
+ break;
+ }
+
+ case OmxMessage::EMPTY_BUFFER_DONE:
+ {
+ static_cast<OmxFrameDecoder*>(msg.u.bufferData.appData)->emptyBufferDoneHandler(msg.u.bufferData.pBuffHead);
+ break;
+ }
+
+ case OmxMessage::FILL_BUFFER_DONE:
+ {
+ static_cast<OmxFrameDecoder*>(msg.u.bufferData.appData)->fillBufferDoneHandler(msg.u.bufferData.pBuffHead);
+ break;
+ }
+ };
+}
+
+bool CallbackDispatcher::loop() {
+ for (;;) {
+ OmxMessage msg;
+
+ {
+ android::Mutex::Autolock autoLock(mLock);
+ while (!mDone && mQueue.empty()) {
+ mQueueChanged.wait(mLock);
+ }
+
+ if (mDone) {
+ break;
+ }
+
+ msg = *mQueue.begin();
+ mQueue.erase(mQueue.begin());
+ }
+
+ dispatch(msg);
+ }
+
+ return false;
+}
+
+bool CallbackDispatcherThread::threadLoop() {
+ return mDispatcher->loop();
+}
+
+//Static
+OMX_ERRORTYPE OmxFrameDecoder::eventCallback(const OMX_HANDLETYPE component,
+ const OMX_PTR appData, const OMX_EVENTTYPE event, const OMX_U32 data1, const OMX_U32 data2,
+ const OMX_PTR pEventData) {
+ OmxMessage msg;
+ msg.type = OmxMessage::EVENT;
+ msg.u.eventData.appData = appData;
+ msg.u.eventData.event = event;
+ msg.u.eventData.data1 = data1;
+ msg.u.eventData.data2 = data2;
+ ((OmxFrameDecoder *)appData)->mDispatcher.post(msg);
+ return OMX_ErrorNone;
+}
+
+//Static
+OMX_ERRORTYPE OmxFrameDecoder::emptyBufferDoneCallback(OMX_HANDLETYPE hComponent,
+ OMX_PTR appData, OMX_BUFFERHEADERTYPE* pBuffHead) {
+ OmxMessage msg;
+ msg.type = OmxMessage::EMPTY_BUFFER_DONE;
+ msg.u.bufferData.appData = appData;
+ msg.u.bufferData.pBuffHead = pBuffHead;
+ ((OmxFrameDecoder *)appData)->mDispatcher.post(msg);
+ return OMX_ErrorNone;
+}
+
+//Static
+OMX_ERRORTYPE OmxFrameDecoder::fillBufferDoneCallback(OMX_HANDLETYPE hComponent,
+ OMX_PTR appData, OMX_BUFFERHEADERTYPE* pBuffHead) {
+ OmxMessage msg;
+ msg.type = OmxMessage::FILL_BUFFER_DONE;
+ msg.u.bufferData.appData = appData;
+ msg.u.bufferData.pBuffHead = pBuffHead;
+ ((OmxFrameDecoder *)appData)->mDispatcher.post(msg);
+ return OMX_ErrorNone;
+}
+
+OmxFrameDecoder::OmxFrameDecoder(DecoderType type)
+ : mOmxInialized(false), mCurrentState(OmxDecoderState_Unloaded), mPreviousState(OmxDecoderState_Unloaded),
+ mStopping(false), mDecoderType(type), mIsNeedCheckDHT(true), mAlwaysAppendDHT(false) {
+}
+
+OmxFrameDecoder::~OmxFrameDecoder() {
+}
+
+OMX_ERRORTYPE OmxFrameDecoder::emptyBufferDoneHandler(OMX_BUFFERHEADERTYPE* pBuffHead) {
+ LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mHwLock);
+
+ int bufferIndex = reinterpret_cast<int>(pBuffHead->pAppPrivate);
+ CAMHAL_LOGD("Got header %p id = %d", pBuffHead, bufferIndex);
+ android::sp<MediaBuffer>& in = mInBuffers->editItemAt(bufferIndex);
+
+ android::AutoMutex itemLock(in->getLock());
+ in->setStatus((getOmxState() == OmxDecoderState_Executing) ? BufferStatus_InDecoded : BufferStatus_InQueued);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OmxFrameDecoder::fillBufferDoneHandler(OMX_BUFFERHEADERTYPE* pBuffHead) {
+ LOG_FUNCTION_NAME;
+ android::AutoMutex lock(mHwLock);
+
+ int index = (int)pBuffHead->pAppPrivate;
+ android::sp<MediaBuffer>& out = mOutBuffers->editItemAt(index);
+
+ android::AutoMutex itemLock(out->getLock());
+ CameraBuffer* frame = static_cast<CameraBuffer*>(out->buffer);
+ out->setOffset(pBuffHead->nOffset);
+ out->setTimestamp(pBuffHead->nTimeStamp);
+ out->setStatus((getOmxState() == OmxDecoderState_Executing) ? BufferStatus_OutFilled : BufferStatus_OutQueued);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OmxFrameDecoder::eventHandler(const OMX_EVENTTYPE event, const OMX_U32 data1, const OMX_U32 data2,
+ const OMX_PTR pEventData) {
+
+ LOG_FUNCTION_NAME;
+
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ android::AutoMutex lock(mHwLock);
+
+ switch(event) {
+
+ case OMX_EventCmdComplete:
+ {
+ if ((data1 == OMX_CommandStateSet) && (data2 == OMX_StateIdle)) {
+ CAMHAL_LOGD("Component State Changed To OMX_StateIdle\n");
+ commitState(OmxDecoderState_Idle);
+ mStateCondition.signal();
+ }
+ else if ((data1 == OMX_CommandStateSet) && (data2 == OMX_StateExecuting)) {
+ CAMHAL_LOGD("Component State Changed To OMX_StateExecuting\n");
+ commitState(OmxDecoderState_Executing);
+ mStateCondition.signal();
+ }
+ else if ((data1 == OMX_CommandStateSet) && (data2 == OMX_StateLoaded)) {
+ CAMHAL_LOGD("Component State Changed To OMX_StateLoaded\n");
+ if(getOmxState() == OmxDecoderState_Executing)
+ commitState(OmxDecoderState_Loaded);
+ mStateCondition.signal();
+ }
+ else if (data1 == OMX_CommandFlush) {
+ CAMHAL_LOGD("OMX_CommandFlush done on %d port\n", data2);
+ mStateCondition.signal();
+ }
+ else if (data1 == OMX_CommandPortDisable) {
+ CAMHAL_LOGD("OMX_CommandPortDisable done on %d port\n", data2);
+ mStateCondition.signal();
+ }
+ else if (data1 == OMX_CommandPortEnable) {
+ CAMHAL_LOGD("OMX_CommandPortEnable done on %d port\n", data2);
+ mStateCondition.signal();
+ } else {
+ CAMHAL_LOGD("Event %d done on %d port\n", data1, data2);
+ }
+ break;
+ }
+ case OMX_EventError:
+ {
+ CAMHAL_LOGD("\n\n\nOMX Component reported an Error!!!! 0x%x 0x%x\n\n\n", data1, data2);
+ commitState(OmxDecoderState_Error);
+ omxSendCommand(OMX_CommandStateSet, OMX_StateInvalid);
+ mStateCondition.signal();
+ break;
+ }
+ case OMX_EventPortSettingsChanged:
+ {
+ CAMHAL_LOGD("\n\n\nOMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)\n\n\n",
+ data1, data2);
+ if (data2 == 0) {
+ // This means that some serious change to port happens
+ commitState(OmxDecoderState_Reconfigure);
+ } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
+#if 0
+ OMX_CONFIG_RECTTYPE rect;
+ InitOMXParams(&rect);
+ rect.nPortIndex = PortIndexOutput;
+ status_t ret = omxGetConfig(OMX_IndexConfigCommonOutputCrop, &rect);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Can't get new crop parameters 0x%x", ret);
+ break;
+ }
+
+ CAMHAL_LOGV("Crop should change to %d %d %d %d", rect.nLeft, rect.nTop, rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight);
+#endif
+ }
+ break;
+ }
+ default:
+ {
+ CAMHAL_LOGD("\n\n\nOMX Unhandelled event ID=0x%x!!!!\n\n\n", event);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+ }
+
+void OmxFrameDecoder::doConfigure(const DecoderParameters& config) {
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t OmxFrameDecoder::enableGrallockHandles() {
+ OMX_TI_PARAMUSENATIVEBUFFER domxUseGrallocHandles;
+ InitOMXParams(&domxUseGrallocHandles);
+
+ domxUseGrallocHandles.nPortIndex = PortIndexOutput;
+ domxUseGrallocHandles.bEnable = OMX_TRUE;
+
+ return omxSetParameter((OMX_INDEXTYPE)OMX_TI_IndexUseNativeBuffers, &domxUseGrallocHandles);
+}
+
+status_t OmxFrameDecoder::omxSwitchToExecutingSync() {
+ CAMHAL_LOGV("Try set OMX_StateExecuting");
+ android::AutoMutex lock(mHwLock);
+ omxSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+ status_t ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("State transition to EXECUTING ERROR 0x%x", ret);
+ return UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+}
+
+void OmxFrameDecoder::dumpPortSettings(PortType port) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = port;
+ omxGetParameter(OMX_IndexParamPortDefinition, &def);
+ omxDumpPortSettings(def);
+}
+
+status_t OmxFrameDecoder::disablePortSync(int port) {
+ OMX_ERRORTYPE eError;
+ android::AutoMutex lock(mHwLock);
+ eError = OMX_SendCommand(mHandleComp, OMX_CommandPortDisable, port, NULL);
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_CommandPortDisable OMX_ALL returned error 0x%x", eError);
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+ status_t ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("State transition to OMX_StateLoaded ERROR 0x%x", ret);
+ return UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+}
+
+status_t OmxFrameDecoder::enablePortSync(int port) {
+ android::AutoMutex lock(mHwLock);
+ OMX_ERRORTYPE eError = OMX_SendCommand(mHandleComp, OMX_CommandPortEnable, port, NULL);
+ status_t ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_SendCommand OMX_CommandPortEnable OUT returned error 0x%x", eError);
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+ return NO_ERROR;
+}
+
+
+status_t OmxFrameDecoder::doPortReconfigure() {
+ OMX_ERRORTYPE eError;
+ status_t ret = NO_ERROR;
+
+ CAMHAL_LOGD("Starting port reconfiguration !");
+ dumpPortSettings(PortIndexInput);
+ dumpPortSettings(PortIndexOutput);
+
+ android::AutoMutex lock(mHwLock);
+
+ omxSendCommand(OMX_CommandFlush, PortIndexOutput);
+ ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("State transition to OMX_CommandFlush ERROR 0x%x", ret);
+ return UNKNOWN_ERROR;
+ }
+
+ omxSendCommand(OMX_CommandFlush, PortIndexInput);
+ ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("State transition to OMX_CommandFlush ERROR 0x%x", ret);
+ return UNKNOWN_ERROR;
+ }
+
+ ret = omxSendCommand(OMX_CommandPortDisable, PortIndexOutput);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("OMX_CommandPortDisable PortIndexOutput returned error 0x%x", ret);
+ return ret;
+ }
+
+ freeBuffersOnOutput();
+
+ ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("State transition to OMX_StateLoaded ERROR 0x%x", ret);
+ return UNKNOWN_ERROR;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = PortIndexOutput;
+ omxGetParameter(OMX_IndexParamPortDefinition, &def);
+ def.nBufferCountActual = mParams.outputBufferCount;
+ CAMHAL_LOGD("Will set def.nBufferSize=%d stride=%d height=%d", def.nBufferSize , def.format.video.nStride, def.format.video.nFrameHeight);
+ omxSetParameter(OMX_IndexParamPortDefinition, &def);
+
+
+
+ ret = omxSendCommand(OMX_CommandPortEnable, PortIndexOutput);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("omxSendCommand OMX_CommandPortEnable returned error 0x%x", ret);
+ return ret;
+ }
+
+ allocateBuffersOutput();
+
+ ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("omxSendCommand OMX_CommandPortEnable timeout 0x%x", ret);
+ return UNKNOWN_ERROR;
+ }
+
+ CAMHAL_LOGD("Port reconfiguration DONE!");
+ //dumpPortSettings(PortIndexOutput);
+
+ return NO_ERROR;
+}
+
+void OmxFrameDecoder::queueOutputBuffers() {
+
+ LOG_FUNCTION_NAME;
+
+ android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
+
+ for (size_t i = 0; i < mOutQueue.size(); i++) {
+ int index = mOutQueue[i];
+ android::sp<MediaBuffer> &outBuffer = mOutBuffers->editItemAt(index);
+ android::AutoMutex bufferLock(outBuffer->getLock());
+ if (outBuffer->getStatus() == BufferStatus_OutQueued) {
+ outBuffer->setStatus(BufferStatus_OutWaitForFill);
+ CameraBuffer* frame = static_cast<CameraBuffer*>(outBuffer->buffer);
+ OMX_BUFFERHEADERTYPE *pOutBufHdr = mOutBufferHeaders[outBuffer->bufferId];
+ CAMHAL_LOGV("Fill this buffer cf=%p bh=%p id=%d", frame, pOutBufHdr, outBuffer->bufferId);
+ status_t status = omxFillThisBuffer(pOutBufHdr);
+ CAMHAL_ASSERT(status == NO_ERROR);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void OmxFrameDecoder::doProcessInputBuffer() {
+
+ LOG_FUNCTION_NAME;
+
+ if (getOmxState() == OmxDecoderState_Reconfigure) {
+ if (doPortReconfigure() == NO_ERROR) {
+ commitState(OmxDecoderState_Executing);
+ queueOutputBuffers();
+ } else {
+ commitState(OmxDecoderState_Error);
+ return;
+ }
+
+ }
+
+ if (getOmxState() == OmxDecoderState_Idle) {
+ CAMHAL_ASSERT(omxSwitchToExecutingSync() == NO_ERROR);
+ queueOutputBuffers();
+ }
+
+ if (getOmxState() == OmxDecoderState_Executing) {
+ for (size_t i = 0; i < mInQueue.size(); i++) {
+ int index = mInQueue[i];
+ CAMHAL_LOGD("Got in inqueue[%d] buffer id=%d", i, index);
+ android::sp<MediaBuffer> &inBuffer = mInBuffers->editItemAt(index);
+ android::AutoMutex bufferLock(inBuffer->getLock());
+ if (inBuffer->getStatus() == BufferStatus_InQueued) {
+ OMX_BUFFERHEADERTYPE *pInBufHdr = mInBufferHeaders[index];
+ inBuffer->setStatus(BufferStatus_InWaitForEmpty);
+ omxEmptyThisBuffer(inBuffer, pInBufHdr);
+ }
+ }
+ queueOutputBuffers();
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t OmxFrameDecoder::omxInit() {
+
+ LOG_FUNCTION_NAME;
+
+ OMX_ERRORTYPE eError = OMX_Init();
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_Init() failed, error: 0x%x", eError);
+ }
+ else mOmxInialized = true;
+
+ LOG_FUNCTION_NAME_EXIT;
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OmxFrameDecoder::omxFillThisBuffer(OMX_BUFFERHEADERTYPE *pOutBufHdr) {
+ OMX_ERRORTYPE eError = OMX_ErrorUndefined;
+
+ pOutBufHdr->nFilledLen = 0;
+ pOutBufHdr->nOffset = 0;
+ pOutBufHdr->nFlags = 0;
+
+ eError = OMX_FillThisBuffer(mHandleComp, pOutBufHdr);
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_FillThisBuffer ERROR 0x%x", eError);
+ }
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+
+status_t OmxFrameDecoder::omxGetHandle(OMX_HANDLETYPE *handle, OMX_PTR pAppData,
+ OMX_CALLBACKTYPE & callbacks) {
+ LOG_FUNCTION_NAME;
+
+ OMX_ERRORTYPE eError = OMX_ErrorUndefined;
+
+ eError = OMX_GetHandle(handle, (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.DECODER", pAppData, &callbacks);
+ if((eError != OMX_ErrorNone) || (handle == NULL)) {
+ handle = NULL;
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+ commitState(OmxDecoderState_Loaded);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OmxFrameDecoder::omxEmptyThisBuffer(android::sp<MediaBuffer>& inBuffer, OMX_BUFFERHEADERTYPE *pInBufHdr) {
+
+ LOG_FUNCTION_NAME;
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ InitOMXParams(&def);
+ def.nPortIndex = PortIndexInput;
+ omxGetParameter(OMX_IndexParamPortDefinition, &def);
+ CAMHAL_LOGD("Founded id for empty is %d ", inBuffer->bufferId);
+ if (inBuffer->filledLen > def.nBufferSize) {
+ CAMHAL_LOGE("Can't copy IN buffer due to it too small %d than needed %d", def.nBufferSize, inBuffer->filledLen);
+ return UNKNOWN_ERROR;
+ }
+
+ int filledLen = inBuffer->filledLen;
+ unsigned char* dataBuffer = reinterpret_cast<unsigned char*>(inBuffer->buffer);
+
+ //If decoder type MJPEG we check if append DHT forced and if true append it
+ //in other case we check mIsNeedCheckDHT and if true search for DHT in buffer
+ //if we don't found it - will do append
+ //once we find that buffer not contain DHT we will append it each time
+ if ((mDecoderType == DecoderType_MJPEG) && ((mAlwaysAppendDHT) || ((mIsNeedCheckDHT) &&
+ (mIsNeedCheckDHT = !Decoder_libjpeg::isDhtExist(dataBuffer, filledLen))))) {
+ CAMHAL_LOGV("Will append DHT to buffer");
+ Decoder_libjpeg::appendDHT(dataBuffer, filledLen, pInBufHdr->pBuffer, filledLen + Decoder_libjpeg::readDHTSize());
+ filledLen += Decoder_libjpeg::readDHTSize();
+ mIsNeedCheckDHT = false;
+ mAlwaysAppendDHT = true;
+ } else {
+ memcpy(pInBufHdr->pBuffer, dataBuffer, filledLen);
+ }
+
+ CAMHAL_LOGV("Copied %d bytes into In buffer with bh=%p", filledLen, pInBufHdr);
+ CAMHAL_LOGV("Empty this buffer id=%d timestamp %lld offset=%d", inBuffer->bufferId, pInBufHdr->nTimeStamp, pInBufHdr->nOffset);
+ pInBufHdr->nFilledLen = filledLen;
+ pInBufHdr->nTimeStamp = inBuffer->getTimestamp();
+ pInBufHdr->nFlags = 16;
+ pInBufHdr->nOffset = 0;
+ eError = OMX_EmptyThisBuffer(mHandleComp, pInBufHdr);
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_EmptyThisBuffer ERROR 0x%x", eError);
+ Utils::ErrorUtils::omxToAndroidError(eError);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+
+status_t OmxFrameDecoder::allocateBuffersOutput() {
+ LOG_FUNCTION_NAME;
+
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = PortIndexOutput;
+ omxGetParameter(OMX_IndexParamPortDefinition, &def);
+ def.nBufferCountActual = mParams.outputBufferCount;
+
+ CAMHAL_LOGD("Will set def.nBufferSize=%d stride=%d height=%d", def.nBufferSize , def.format.video.nStride, def.format.video.nFrameHeight);
+
+ OMX_BUFFERHEADERTYPE *pOutBufHdr;
+ mOutBufferHeaders.clear();
+ for (size_t i = 0; i < mOutBuffers->size(); i++) {
+ android::sp<MediaBuffer>& outBuffer = mOutBuffers->editItemAt(i);
+ android::AutoMutex lock(outBuffer->getLock());
+ CameraBuffer* cb = static_cast<CameraBuffer*>(outBuffer->buffer);
+ OMX_U8 * outPtr = static_cast<OMX_U8*>(camera_buffer_get_omx_ptr(cb));
+ CAMHAL_LOGV("Try to set OMX_UseBuffer [0x%x] for output port with length %d ", outPtr, def.nBufferSize);
+ eError = OMX_UseBuffer(mHandleComp, &pOutBufHdr, PortIndexOutput, (void*)i, def.nBufferSize, outPtr);
+
+ if (eError != OMX_ErrorNone) {
+ ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", eError, eError);
+ commitState(OmxDecoderState_Error);
+ return UNKNOWN_ERROR;
+ }
+
+ CAMHAL_LOGD("Got buffer header %p", pOutBufHdr);
+ mOutBufferHeaders.add(pOutBufHdr);
+ }
+
+ omxDumpPortSettings(def);
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+
+}
+
+status_t OmxFrameDecoder::allocateBuffersInput() {
+ LOG_FUNCTION_NAME;
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ OMX_BUFFERHEADERTYPE *pInBufHdr;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ InitOMXParams(&def);
+ def.nPortIndex = PortIndexInput;
+ omxGetParameter(OMX_IndexParamPortDefinition, &def);
+
+ // TODO: Will be changed since port reconfiguration will be handled
+ def.nBufferCountActual = mInBuffers->size();
+ def.bEnabled = OMX_TRUE;
+ omxSetParameter(OMX_IndexParamPortDefinition, &def);
+
+ mInBufferHeaders.clear();
+
+ for (size_t i = 0; i < mInBuffers->size(); i++) {
+ CAMHAL_LOGD("Will do OMX_AllocateBuffer for input port with size %d id=%d", def.nBufferSize, i);
+ eError = OMX_AllocateBuffer(mHandleComp, &pInBufHdr, PortIndexInput, (void*)i, def.nBufferSize);
+ if (eError != OMX_ErrorNone) {
+ ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", eError, eError);
+ commitState(OmxDecoderState_Error);
+ return UNKNOWN_ERROR;
+ }
+ CAMHAL_LOGD("Got new buffer header [%p] for IN port", pInBufHdr);
+ mInBufferHeaders.push_back(pInBufHdr);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+}
+
+status_t OmxFrameDecoder::getAndConfigureDecoder() {
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError;
+
+ ret = omxInit();
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("OMX_Init returned error 0x%x", ret);
+ return ret;
+ }
+ OMX_CALLBACKTYPE callbacks;
+ callbacks.EventHandler = OmxFrameDecoder::eventCallback;
+ callbacks.EmptyBufferDone = OmxFrameDecoder::emptyBufferDoneCallback;
+ callbacks.FillBufferDone = OmxFrameDecoder::fillBufferDoneCallback;
+ ret = omxGetHandle(&mHandleComp, this, callbacks);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("OMX_GetHandle returned error 0x%x", ret);
+ OMX_Deinit();
+ mOmxInialized = false;
+ return ret;
+ }
+ ret = setComponentRole();
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("setComponentRole returned error 0x%x", ret);
+ OMX_Deinit();
+ mOmxInialized = false;
+ return ret;
+ }
+ disablePortSync(PortIndexOutput);
+ ret = setVideoOutputFormat(mParams.width, mParams.height);
+ enablePortSync(PortIndexOutput);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Can't set output format error 0x%x", ret);
+ OMX_Deinit();
+ mOmxInialized = false;
+ return ret;
+ }
+ enableGrallockHandles();
+ return NO_ERROR;
+}
+
+status_t OmxFrameDecoder::switchToIdle() {
+ CAMHAL_ASSERT(getOmxState() == OmxDecoderState_Loaded);
+ CAMHAL_LOGD("Try set OMX_StateIdle");
+ android::AutoMutex lock(mHwLock);
+ status_t ret = omxSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Can't omxSendCommandt error 0x%x", ret);
+ OMX_Deinit();
+ mOmxInialized = false;
+ return ret;
+ }
+
+ allocateBuffersInput();
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = PortIndexOutput;
+ omxGetParameter(OMX_IndexParamPortDefinition, &def);
+ def.nBufferCountActual = mParams.outputBufferCount;
+ omxSetParameter(OMX_IndexParamPortDefinition, &def);
+
+ allocateBuffersOutput();
+
+ ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("State transition to IDLE ERROR 0x%x", ret);
+ return ret;
+ }
+ commitState(OmxDecoderState_Idle);
+ return NO_ERROR;
+}
+
+status_t OmxFrameDecoder::doStart() {
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ mStopping = false;
+ OMX_ERRORTYPE eError;
+
+ ret = getAndConfigureDecoder();
+
+#if 0
+ OMX_TI_PARAM_ENHANCEDPORTRECONFIG tParamStruct;
+ tParamStruct.nSize = sizeof(OMX_TI_PARAM_ENHANCEDPORTRECONFIG);
+ tParamStruct.nVersion.s.nVersionMajor = 0x1;
+ tParamStruct.nVersion.s.nVersionMinor = 0x1;
+ tParamStruct.nVersion.s.nRevision = 0x0;
+ tParamStruct.nVersion.s.nStep = 0x0;
+ tParamStruct.nPortIndex = PortIndexOutput;
+ tParamStruct.bUsePortReconfigForCrop = OMX_TRUE;
+ tParamStruct.bUsePortReconfigForPadding = OMX_FALSE;
+ omxSetParameter((OMX_INDEXTYPE)OMX_TI_IndexParamUseEnhancedPortReconfig, &tParamStruct);
+#endif
+
+ // Transition to IDLE
+ ret = switchToIdle();
+ dumpPortSettings(PortIndexInput);
+ dumpPortSettings(PortIndexOutput);
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t OmxFrameDecoder::omxGetParameter(OMX_INDEXTYPE index, OMX_PTR ptr) {
+ OMX_ERRORTYPE eError = OMX_GetParameter(mHandleComp, index, ptr);
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_GetParameter - error 0x%x", eError);
+ }
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OmxFrameDecoder::omxGetConfig(OMX_INDEXTYPE index, OMX_PTR ptr) {
+ OMX_ERRORTYPE eError = OMX_GetConfig(mHandleComp, index, ptr);
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_GetConfig - error 0x%x", eError);
+ }
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OmxFrameDecoder::omxSetParameter(OMX_INDEXTYPE index, OMX_PTR ptr) {
+ OMX_ERRORTYPE eError = OMX_SetParameter(mHandleComp, index, ptr);
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_SetParameter - error 0x%x", eError);
+ }
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OmxFrameDecoder::omxSetConfig(OMX_INDEXTYPE index, OMX_PTR ptr) {
+ OMX_ERRORTYPE eError = OMX_SetConfig(mHandleComp, index, ptr);
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_SetConfig - error 0x%x", eError);
+ }
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OmxFrameDecoder::omxSendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
+ OMX_ERRORTYPE eError = OMX_SendCommand(mHandleComp, cmd, param, NULL);
+ if(eError != OMX_ErrorNone) {
+ CAMHAL_LOGE("OMX_SendCommand - error 0x%x", eError);
+ }
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OmxFrameDecoder::setVideoOutputFormat(OMX_U32 width, OMX_U32 height) {
+ LOG_FUNCTION_NAME;
+
+ CAMHAL_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
+
+ OMX_VIDEO_CODINGTYPE compressionFormat = gCompressionFormat[mDecoderType];
+
+ status_t err = setVideoPortFormatType(
+ PortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
+
+ if (err != NO_ERROR) {
+ CAMHAL_LOGE("Error during setVideoPortFormatType 0x%x", err);
+ return err;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = PortIndexInput;
+
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ err = omxGetParameter(OMX_IndexParamPortDefinition, &def);
+
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ video_def->eCompressionFormat = compressionFormat;
+ video_def->eColorFormat = OMX_COLOR_FormatUnused;
+
+
+ err = omxSetParameter(OMX_IndexParamPortDefinition, &def);
+
+
+ if (err != OK) {
+ return err;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE odef;
+ OMX_VIDEO_PORTDEFINITIONTYPE *out_video_def = &odef.format.video;
+
+ InitOMXParams(&odef);
+ odef.nPortIndex = PortIndexOutput;
+
+ err = omxGetParameter(OMX_IndexParamPortDefinition, &odef);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ out_video_def->nFrameWidth = width;
+ out_video_def->nFrameHeight = height;
+ out_video_def->xFramerate = 30<< 16;//((width >= 720) ? 60 : 30) << 16;
+ out_video_def->nStride = 4096;
+
+ err = omxSetParameter(OMX_IndexParamPortDefinition, &odef);
+ CAMHAL_LOGD("OUT port is configured");
+ dumpPortSettings(PortIndexOutput);
+
+ LOG_FUNCTION_NAME_EXIT;
+ return err;
+}
+
+status_t OmxFrameDecoder::setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat) {
+
+ LOG_FUNCTION_NAME;
+
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ InitOMXParams(&format);
+ format.nPortIndex = portIndex;
+ format.nIndex = 0;
+ bool found = false;
+
+ OMX_U32 index = 0;
+ for (;;) {
+ CAMHAL_LOGV("Will check index = %d", index);
+ format.nIndex = index;
+ OMX_ERRORTYPE eError = OMX_GetParameter(
+ mHandleComp, OMX_IndexParamVideoPortFormat,
+ &format);
+
+ CAMHAL_LOGV("format.eCompressionFormat=0x%x format.eColorFormat=0x%x", format.eCompressionFormat, format.eColorFormat);
+
+ if (format.eCompressionFormat == compressionFormat
+ && format.eColorFormat == colorFormat) {
+ found = true;
+ break;
+ }
+
+ ++index;
+ if (index >= kMaxColorFormatSupported) {
+ CAMHAL_LOGE("color format %d or compression format %d is not supported",
+ colorFormat, compressionFormat);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ if (!found) {
+ return UNKNOWN_ERROR;
+ }
+
+ CAMHAL_LOGV("found a match.");
+ OMX_ERRORTYPE eError = OMX_SetParameter(
+ mHandleComp, OMX_IndexParamVideoPortFormat,
+ &format);
+
+ LOG_FUNCTION_NAME_EXIT;
+ return Utils::ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OmxFrameDecoder::setComponentRole() {
+ OMX_PARAM_COMPONENTROLETYPE roleParams;
+ const char *role = gDecoderRole[mDecoderType];
+ InitOMXParams(&roleParams);
+
+ strncpy((char *)roleParams.cRole,
+ role, OMX_MAX_STRINGNAME_SIZE - 1);
+ roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ return omxSetParameter(OMX_IndexParamStandardComponentRole, &roleParams);
+}
+
+void OmxFrameDecoder::freeBuffersOnOutput() {
+ LOG_FUNCTION_NAME;
+ for (size_t i = 0; i < mOutBufferHeaders.size(); i++) {
+ OMX_BUFFERHEADERTYPE* header = mOutBufferHeaders[i];
+ CAMHAL_LOGD("Freeing OUT buffer header %p", header);
+ OMX_FreeBuffer(mHandleComp, PortIndexOutput, header);
+ }
+ mOutBufferHeaders.clear();
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void OmxFrameDecoder::freeBuffersOnInput() {
+ LOG_FUNCTION_NAME;
+ for (size_t i = 0; i < mInBufferHeaders.size(); i++) {
+ OMX_BUFFERHEADERTYPE* header = mInBufferHeaders[i];
+ CAMHAL_LOGD("Freeing IN buffer header %p", header);
+ OMX_FreeBuffer(mHandleComp, PortIndexInput, header);
+ }
+ mInBufferHeaders.clear();
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void OmxFrameDecoder::doStop() {
+ LOG_FUNCTION_NAME;
+
+ mStopping = true;
+ android::AutoMutex lock(mHwLock);
+
+ CAMHAL_LOGD("HwFrameDecoder::doStop state id=%d", getOmxState());
+
+ if ((getOmxState() == OmxDecoderState_Executing) || (getOmxState() == OmxDecoderState_Reconfigure)) {
+
+ CAMHAL_LOGD("Try set OMX_StateIdle");
+ status_t ret = omxSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Can't omxSendCommandt error 0x%x", ret);
+ }
+
+ ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("State transition to IDLE ERROR 0x%x", ret);
+ }
+ commitState(OmxDecoderState_Idle);
+ }
+
+ if (getOmxState() == OmxDecoderState_Idle) {
+
+ CAMHAL_LOGD("Try set OMX_StateLoaded");
+ status_t ret = omxSendCommand(OMX_CommandStateSet, OMX_StateLoaded);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("Can't omxSendCommandt error 0x%x", ret);
+ return;
+ }
+ freeBuffersOnOutput();
+ freeBuffersOnInput();
+ ret = mStateCondition.waitRelative(mHwLock, kMaxStateSwitchTimeOut);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGE("State transition to OMX_StateLoaded ERROR 0x%x", ret);
+ }
+ commitState(OmxDecoderState_Loaded);
+
+ }
+
+ if (getOmxState() == OmxDecoderState_Error) {
+ CAMHAL_LOGD("In state ERROR will try to free buffers!");
+ freeBuffersOnOutput();
+ freeBuffersOnInput();
+ }
+
+ CAMHAL_LOGD("Before OMX_FreeHandle ....");
+ OMX_FreeHandle(mHandleComp);
+ CAMHAL_LOGD("After OMX_FreeHandle ....");
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void OmxFrameDecoder::doFlush() {
+ LOG_FUNCTION_NAME;
+ mIsNeedCheckDHT = true;
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void OmxFrameDecoder::doRelease() {
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void OmxFrameDecoder::omxDumpPortSettings(OMX_PARAM_PORTDEFINITIONTYPE& def) {
+ CAMHAL_LOGD("----------Port settings start--------------------");
+ CAMHAL_LOGD("nSize=%d nPortIndex=%d eDir=%d nBufferCountActual=%d", def.nSize, def.nPortIndex, def.eDir, def.nBufferCountActual);
+ CAMHAL_LOGD("nBufferCountMin=%d nBufferSize=%d bEnabled=%d bPopulated=%d bBuffersContiguous=%d nBufferAlignment=%d", def.nBufferCountMin, def.nBufferSize, def.bEnabled, def.bPopulated, def.bBuffersContiguous, def.nBufferAlignment);
+
+ CAMHAL_LOGD("eDomain = %d",def.eDomain);
+
+ if (def.eDomain == OMX_PortDomainVideo) {
+ CAMHAL_LOGD("===============Video Port===================");
+ CAMHAL_LOGD("cMIMEType=%s",def.format.video.cMIMEType);
+ CAMHAL_LOGD("nFrameWidth=%d nFrameHeight=%d", def.format.video.nFrameWidth, def.format.video.nFrameHeight);
+ CAMHAL_LOGD("nStride=%d nSliceHeight=%d", def.format.video.nStride, def.format.video.nSliceHeight);
+ CAMHAL_LOGD("nBitrate=%d xFramerate=%d", def.format.video.nBitrate, def.format.video.xFramerate>>16);
+ CAMHAL_LOGD("bFlagErrorConcealment=%d eCompressionFormat=%d", def.format.video.bFlagErrorConcealment, def.format.video.eCompressionFormat);
+ CAMHAL_LOGD("eColorFormat=0x%x pNativeWindow=%p", def.format.video.eColorFormat, def.format.video.pNativeWindow);
+ CAMHAL_LOGD("===============END Video Part===================");
+ }
+ else if (def.eDomain == OMX_PortDomainImage) {
+ CAMHAL_LOGD("===============Image Port===================");
+ CAMHAL_LOGD("cMIMEType=%s",def.format.image.cMIMEType);
+ CAMHAL_LOGD("nFrameWidth=%d nFrameHeight=%d", def.format.image.nFrameWidth, def.format.image.nFrameHeight);
+ CAMHAL_LOGD("nStride=%d nSliceHeight=%d", def.format.image.nStride, def.format.image.nSliceHeight);
+ CAMHAL_LOGD("bFlagErrorConcealment=%d eCompressionFormat=%d", def.format.image.bFlagErrorConcealment, def.format.image.eCompressionFormat);
+ CAMHAL_LOGD("eColorFormat=0x%x pNativeWindow=%p", def.format.image.eColorFormat, def.format.image.pNativeWindow);
+ CAMHAL_LOGD("===============END Image Part===================");
+ }
+ CAMHAL_LOGD("----------Port settings end--------------------");
+}
+
+void OmxFrameDecoder::omxDumpBufferHeader(OMX_BUFFERHEADERTYPE* bh) {
+ CAMHAL_LOGD("==============OMX_BUFFERHEADERTYPE start==============");
+ CAMHAL_LOGD("nAllocLen=%d nFilledLen=%d nOffset=%d nFlags=0x%x", bh->nAllocLen, bh->nFilledLen, bh->nOffset, bh->nFlags);
+ CAMHAL_LOGD("pBuffer=%p nOutputPortIndex=%d nInputPortIndex=%d nSize=0x%x", bh->pBuffer, bh->nOutputPortIndex, bh->nInputPortIndex, bh->nSize);
+ CAMHAL_LOGD("nVersion=0x%x", bh->nVersion);
+ CAMHAL_LOGD("==============OMX_BUFFERHEADERTYPE end==============");
+}
+
+bool OmxFrameDecoder::getPaddedDimensions(size_t &width, size_t &height) {
+
+ switch (height) {
+
+ case 480: {
+ height = 576;
+ if (width == 640) {
+ width = 768;
+ }
+ break;
+ }
+ case 720: {
+ height = 832;
+ if (width == 1280) {
+ width = 1408;
+ }
+ break;
+ }
+ case 1080: {
+ height = 1184;
+ if (width == 1920) {
+ width = 2048;
+ }
+ break;
+ }
+
+ }
+
+ CAMHAL_LOGD("WxH updated to padded values : %d x %d", width, height);
+ return true;
+}
+
+} // namespace Camera
+} // namespace Ti
+
diff --git a/camera/SensorListener.cpp b/camera/SensorListener.cpp
new file mode 100644
index 0000000..e53fa83
--- /dev/null
+++ b/camera/SensorListener.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file SensorListener.cpp
+*
+* This file listens and propogates sensor events to CameraHal.
+*
+*/
+
+#include "SensorListener.h"
+
+#include <stdint.h>
+#include <math.h>
+#include <sys/types.h>
+
+namespace Ti {
+namespace Camera {
+
+/*** static declarations ***/
+static const float RADIANS_2_DEG = (float) (180 / M_PI);
+// measured values on device...might need tuning
+static const int DEGREES_90_THRESH = 50;
+static const int DEGREES_180_THRESH = 170;
+static const int DEGREES_270_THRESH = 250;
+
+static int sensor_events_listener(int fd, int events, void* data)
+{
+ SensorListener* listener = (SensorListener*) data;
+ ssize_t num_sensors;
+ ASensorEvent sen_events[8];
+ while ((num_sensors = listener->mSensorEventQueue->read(sen_events, 8)) > 0) {
+ for (int i = 0; i < num_sensors; i++) {
+ if (sen_events[i].type == android::Sensor::TYPE_ACCELEROMETER) {
+ float x = sen_events[i].vector.azimuth;
+ float y = sen_events[i].vector.pitch;
+ float z = sen_events[i].vector.roll;
+ float radius = 0;
+ int tilt = 0, orient = 0;
+
+ CAMHAL_LOGVA("ACCELEROMETER EVENT");
+ CAMHAL_LOGVB(" azimuth = %f pitch = %f roll = %f",
+ sen_events[i].vector.azimuth,
+ sen_events[i].vector.pitch,
+ sen_events[i].vector.roll);
+ // see http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates
+ // about conversion from cartesian to spherical for orientation calculations
+ radius = (float) sqrt(x * x + y * y + z * z);
+ tilt = (int) asinf(z / radius) * RADIANS_2_DEG;
+ orient = (int) atan2f(-x, y) * RADIANS_2_DEG;
+
+ if (orient < 0) {
+ orient += 360;
+ }
+
+ if (orient >= DEGREES_270_THRESH) {
+ orient = 270;
+ } else if (orient >= DEGREES_180_THRESH) {
+ orient = 180;
+ } else if (orient >= DEGREES_90_THRESH) {
+ orient = 90;
+ } else {
+ orient = 0;
+ }
+ listener->handleOrientation(orient, tilt);
+ CAMHAL_LOGVB(" tilt = %d orientation = %d", tilt, orient);
+ } else if (sen_events[i].type == android::Sensor::TYPE_GYROSCOPE) {
+ CAMHAL_LOGVA("GYROSCOPE EVENT");
+ }
+ }
+ }
+
+ if (num_sensors < 0 && num_sensors != -EAGAIN) {
+ CAMHAL_LOGEB("reading events failed: %s", strerror(-num_sensors));
+ }
+
+ return 1;
+}
+
+/****** public - member functions ******/
+SensorListener::SensorListener() {
+ LOG_FUNCTION_NAME;
+
+ sensorsEnabled = 0;
+ mOrientationCb = NULL;
+ mSensorEventQueue = NULL;
+ mSensorLooperThread = NULL;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+SensorListener::~SensorListener() {
+ LOG_FUNCTION_NAME;
+
+ CAMHAL_LOGDA("Kill looper thread");
+ if (mSensorLooperThread.get()) {
+ // 1. Request exit
+ // 2. Wake up looper which should be polling for an event
+ // 3. Wait for exit
+ mSensorLooperThread->requestExit();
+ mSensorLooperThread->wake();
+ mSensorLooperThread->join();
+ mSensorLooperThread.clear();
+ mSensorLooperThread = NULL;
+ }
+
+ CAMHAL_LOGDA("Kill looper");
+ if (mLooper.get()) {
+ mLooper->removeFd(mSensorEventQueue->getFd());
+ mLooper.clear();
+ mLooper = NULL;
+ }
+ CAMHAL_LOGDA("SensorListener destroyed");
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t SensorListener::initialize() {
+ status_t ret = NO_ERROR;
+ android::SensorManager& mgr(android::SensorManager::getInstance());
+
+ LOG_FUNCTION_NAME;
+
+ android::sp<android::Looper> mLooper;
+
+ mSensorEventQueue = mgr.createEventQueue();
+ if (mSensorEventQueue == NULL) {
+ CAMHAL_LOGEA("createEventQueue returned NULL");
+ ret = NO_INIT;
+ goto out;
+ }
+
+ mLooper = new android::Looper(false);
+ mLooper->addFd(mSensorEventQueue->getFd(), 0, ALOOPER_EVENT_INPUT, sensor_events_listener, this);
+
+ if (mSensorLooperThread.get() == NULL)
+ mSensorLooperThread = new SensorLooperThread(mLooper.get());
+
+ if (mSensorLooperThread.get() == NULL) {
+ CAMHAL_LOGEA("Couldn't create sensor looper thread");
+ ret = NO_MEMORY;
+ goto out;
+ }
+
+ ret = mSensorLooperThread->run("sensor looper thread", android::PRIORITY_URGENT_DISPLAY);
+ if (ret == INVALID_OPERATION){
+ CAMHAL_LOGDA("thread already running ?!?");
+ } else if (ret != NO_ERROR) {
+ CAMHAL_LOGEA("couldn't run thread");
+ goto out;
+ }
+
+ out:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+void SensorListener::setCallbacks(orientation_callback_t orientation_cb, void *cookie) {
+ LOG_FUNCTION_NAME;
+
+ if (orientation_cb) {
+ mOrientationCb = orientation_cb;
+ }
+ mCbCookie = cookie;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void SensorListener::handleOrientation(uint32_t orientation, uint32_t tilt) {
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(&mLock);
+
+ if (mOrientationCb && (sensorsEnabled & SENSOR_ORIENTATION)) {
+ mOrientationCb(orientation, tilt, mCbCookie);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void SensorListener::enableSensor(sensor_type_t type) {
+ android::Sensor const* sensor;
+ android::SensorManager& mgr(android::SensorManager::getInstance());
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(&mLock);
+
+ if ((type & SENSOR_ORIENTATION) && !(sensorsEnabled & SENSOR_ORIENTATION)) {
+ sensor = mgr.getDefaultSensor(android::Sensor::TYPE_ACCELEROMETER);
+ if(sensor) {
+ CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string());
+ mSensorEventQueue->enableSensor(sensor);
+ mSensorEventQueue->setEventRate(sensor, ms2ns(100));
+ sensorsEnabled |= SENSOR_ORIENTATION;
+ } else {
+ CAMHAL_LOGDB("not enabling absent orientation sensor");
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void SensorListener::disableSensor(sensor_type_t type) {
+ android::Sensor const* sensor;
+ android::SensorManager& mgr(android::SensorManager::getInstance());
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(&mLock);
+
+ if ((type & SENSOR_ORIENTATION) && (sensorsEnabled & SENSOR_ORIENTATION)) {
+ sensor = mgr.getDefaultSensor(android::Sensor::TYPE_ACCELEROMETER);
+ CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string());
+ mSensorEventQueue->disableSensor(sensor);
+ sensorsEnabled &= ~SENSOR_ORIENTATION;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/SwFrameDecoder.cpp b/camera/SwFrameDecoder.cpp
new file mode 100644
index 0000000..2ce2c0f
--- /dev/null
+++ b/camera/SwFrameDecoder.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Common.h"
+#include "SwFrameDecoder.h"
+
+namespace Ti {
+namespace Camera {
+
+SwFrameDecoder::SwFrameDecoder()
+: mjpegWithHdrSize(0), mJpegWithHeaderBuffer(NULL) {
+}
+
+SwFrameDecoder::~SwFrameDecoder() {
+ delete [] mJpegWithHeaderBuffer;
+ mJpegWithHeaderBuffer = NULL;
+}
+
+
+void SwFrameDecoder::doConfigure(const DecoderParameters& params) {
+ LOG_FUNCTION_NAME;
+
+ mjpegWithHdrSize = (mParams.width * mParams.height / 2) +
+ mJpgdecoder.readDHTSize();
+ if (mJpegWithHeaderBuffer != NULL) {
+ delete [] mJpegWithHeaderBuffer;
+ mJpegWithHeaderBuffer = NULL;
+ }
+ mJpegWithHeaderBuffer = new unsigned char[mjpegWithHdrSize];
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+void SwFrameDecoder::doProcessInputBuffer() {
+ LOG_FUNCTION_NAME;
+ nsecs_t timestamp = 0;
+
+ CAMHAL_LOGV("Will add header to MJPEG");
+ int final_jpg_sz = 0;
+ {
+ int inIndex = mInQueue.itemAt(0);
+ android::sp<MediaBuffer>& inBuffer = mInBuffers->editItemAt(inIndex);
+ android::AutoMutex lock(inBuffer->getLock());
+ timestamp = inBuffer->getTimestamp();
+ final_jpg_sz = mJpgdecoder.appendDHT(
+ reinterpret_cast<unsigned char*>(inBuffer->buffer),
+ inBuffer->filledLen, mJpegWithHeaderBuffer, mjpegWithHdrSize);
+ inBuffer->setStatus(BufferStatus_InDecoded);
+ }
+ CAMHAL_LOGV("Added header to MJPEG");
+ {
+ int outIndex = mOutQueue.itemAt(0);
+ android::sp<MediaBuffer>& outBuffer = mOutBuffers->editItemAt(outIndex);
+ android::AutoMutex lock(outBuffer->getLock());
+ CameraBuffer* buffer = reinterpret_cast<CameraBuffer*>(outBuffer->buffer);
+ if (!mJpgdecoder.decode(mJpegWithHeaderBuffer, final_jpg_sz,
+ reinterpret_cast<unsigned char*>(buffer->mapped), 4096)) {
+ CAMHAL_LOGEA("Error while decoding JPEG");
+ return;
+ }
+ outBuffer->setTimestamp(timestamp);
+ outBuffer->setStatus(BufferStatus_OutFilled);
+ }
+ CAMHAL_LOGV("JPEG decoded!");
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/TICameraParameters.cpp b/camera/TICameraParameters.cpp
new file mode 100644
index 0000000..c8b8619
--- /dev/null
+++ b/camera/TICameraParameters.cpp
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Log.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <TICameraParameters.h>
+
+#define TI_KEY_ALGO_PREFIX "ti-algo-"
+
+namespace Ti {
+namespace Camera {
+
+//TI extensions to camera mode
+const char TICameraParameters::HIGH_PERFORMANCE_MODE[] = "high-performance";
+const char TICameraParameters::HIGH_QUALITY_MODE[] = "high-quality";
+const char TICameraParameters::HIGH_QUALITY_ZSL_MODE[] = "high-quality-zsl";
+const char TICameraParameters::CP_CAM_MODE[] = "cp-cam";
+const char TICameraParameters::VIDEO_MODE[] = "video-mode";
+const char TICameraParameters::VIDEO_MODE_HQ[] = "video-mode-hq";
+const char TICameraParameters::EXPOSURE_BRACKETING[] = "exposure-bracketing";
+const char TICameraParameters::ZOOM_BRACKETING[] = "zoom-bracketing";
+const char TICameraParameters::TEMP_BRACKETING[] = "temporal-bracketing";
+
+// TI extensions to standard android Parameters
+const char TICameraParameters::KEY_SUPPORTED_CAMERAS[] = "camera-indexes";
+const char TICameraParameters::KEY_CAMERA[] = "camera-index";
+const char TICameraParameters::KEY_SHUTTER_ENABLE[] = "shutter-enable";
+const char TICameraParameters::KEY_CAMERA_NAME[] = "camera-name";
+const char TICameraParameters::KEY_BURST[] = "burst-capture";
+const char TICameraParameters::KEY_CAP_MODE[] = "mode";
+const char TICameraParameters::KEY_CAP_MODE_VALUES[] = "mode-values";
+const char TICameraParameters::KEY_VNF[] = "vnf";
+const char TICameraParameters::KEY_VNF_SUPPORTED[] = "vnf-supported";
+const char TICameraParameters::KEY_SATURATION[] = "saturation";
+const char TICameraParameters::KEY_BRIGHTNESS[] = "brightness";
+const char TICameraParameters::KEY_SUPPORTED_EXPOSURE[] = "exposure-mode-values";
+const char TICameraParameters::KEY_EXPOSURE_MODE[] = "exposure";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN[] = "supported-manual-exposure-min";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX[] = "supported-manual-exposure-max";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_STEP[] = "supported-manual-exposure-step";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN[] = "supported-manual-gain-iso-min";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX[] = "supported-manual-gain-iso-max";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_STEP[] = "supported-manual-gain-iso-step";
+const char TICameraParameters::KEY_MANUAL_EXPOSURE[] = "manual-exposure";
+const char TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT[] = "manual-exposure-right";
+const char TICameraParameters::KEY_MANUAL_GAIN_ISO[] = "manual-gain-iso";
+const char TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT[] = "manual-gain-iso-right";
+const char TICameraParameters::KEY_CONTRAST[] = "contrast";
+const char TICameraParameters::KEY_SHARPNESS[] = "sharpness";
+const char TICameraParameters::KEY_ISO[] = "iso";
+const char TICameraParameters::KEY_SUPPORTED_ISO_VALUES[] = "iso-mode-values";
+const char TICameraParameters::KEY_SUPPORTED_IPP[] = "ipp-values";
+const char TICameraParameters::KEY_IPP[] = "ipp";
+const char TICameraParameters::KEY_METERING_MODE[] = "meter-mode";
+const char TICameraParameters::KEY_EXP_BRACKETING_RANGE[] = "exp-bracketing-range";
+const char TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE[] = "exp-gain-bracketing-range";
+const char TICameraParameters::KEY_ZOOM_BRACKETING_RANGE[] = "zoom-bracketing-range";
+const char TICameraParameters::KEY_TEMP_BRACKETING[] = "temporal-bracketing";
+const char TICameraParameters::KEY_TEMP_BRACKETING_RANGE_POS[] = "temporal-bracketing-range-positive";
+const char TICameraParameters::KEY_TEMP_BRACKETING_RANGE_NEG[] = "temporal-bracketing-range-negative";
+const char TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE[] = "flush-shot-config-queue";
+const char TICameraParameters::KEY_MEASUREMENT_ENABLE[] = "measurement";
+const char TICameraParameters::KEY_GBCE[] = "gbce";
+const char TICameraParameters::KEY_GBCE_SUPPORTED[] = "gbce-supported";
+const char TICameraParameters::KEY_GLBCE[] = "glbce";
+const char TICameraParameters::KEY_GLBCE_SUPPORTED[] = "glbce-supported";
+const char TICameraParameters::KEY_CURRENT_ISO[] = "current-iso";
+const char TICameraParameters::KEY_SENSOR_ORIENTATION[] = "sensor-orientation";
+const char TICameraParameters::KEY_RECORDING_HINT[] = "internal-recording-hint";
+const char TICameraParameters::KEY_AUTO_FOCUS_LOCK[] = "auto-focus-lock";
+const char TICameraParameters::KEY_FRAMERATE_RANGES_EXT_SUPPORTED[] = "preview-fps-range-ext-values";
+const char TICameraParameters::KEY_FRAMERATES_EXT_SUPPORTED[] = "preview-fps-ext-values";
+
+const char TICameraParameters::RAW_WIDTH[] = "raw-width";
+const char TICameraParameters::RAW_HEIGHT[] = "raw-height";
+
+// TI extensions for Stereo Mode
+const char TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT[] = "s3d-prv-frame-layout";
+const char TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT_VALUES[] = "s3d-prv-frame-layout-values";
+const char TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT[] = "s3d-cap-frame-layout";
+const char TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT_VALUES[] = "s3d-cap-frame-layout-values";
+
+//TI extentions fo 3D resolutions
+const char TICameraParameters::KEY_SUPPORTED_PICTURE_SUBSAMPLED_SIZES[] = "supported-picture-subsampled-size-values";
+const char TICameraParameters::KEY_SUPPORTED_PICTURE_TOPBOTTOM_SIZES[] = "supported-picture-topbottom-size-values";
+const char TICameraParameters::KEY_SUPPORTED_PICTURE_SIDEBYSIDE_SIZES[] = "supported-picture-sidebyside-size-values";
+const char TICameraParameters::KEY_SUPPORTED_PREVIEW_SUBSAMPLED_SIZES[] = "supported-preview-subsampled-size-values";
+const char TICameraParameters::KEY_SUPPORTED_PREVIEW_TOPBOTTOM_SIZES[] = "supported-preview-topbottom-size-values";
+const char TICameraParameters::KEY_SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES[] = "supported-preview-sidebyside-size-values";
+
+//TI extensions for SAC/SMC
+const char TICameraParameters::KEY_AUTOCONVERGENCE_MODE[] = "auto-convergence-mode";
+const char TICameraParameters::KEY_AUTOCONVERGENCE_MODE_VALUES[] = "auto-convergence-mode-values";
+const char TICameraParameters::KEY_MANUAL_CONVERGENCE[] = "manual-convergence";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_MIN[] = "supported-manual-convergence-min";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_MAX[] = "supported-manual-convergence-max";
+const char TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_STEP[] = "supported-manual-convergence-step";
+
+//TI extensions for setting EXIF tags
+const char TICameraParameters::KEY_EXIF_MODEL[] = "exif-model";
+const char TICameraParameters::KEY_EXIF_MAKE[] = "exif-make";
+
+//TI extensions for additiona GPS data
+const char TICameraParameters::KEY_GPS_MAPDATUM[] = "gps-mapdatum";
+const char TICameraParameters::KEY_GPS_VERSION[] = "gps-version";
+const char TICameraParameters::KEY_GPS_DATESTAMP[] = "gps-datestamp";
+
+// TI extensions for slice mode implementation for VTC
+const char TICameraParameters::KEY_VTC_HINT[] = "internal-vtc-hint";
+const char TICameraParameters::KEY_VIDEO_ENCODER_HANDLE[] = "encoder_handle";
+const char TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT[] = "encoder_slice_height";
+
+//TI extensions to Image post-processing
+const char TICameraParameters::IPP_LDCNSF[] = "ldc-nsf";
+const char TICameraParameters::IPP_LDC[] = "ldc";
+const char TICameraParameters::IPP_NSF[] = "nsf";
+const char TICameraParameters::IPP_NONE[] = "off";
+
+// TI extensions to standard android pixel formats
+const char TICameraParameters::PIXEL_FORMAT_UNUSED[] = "unused";
+const char TICameraParameters::PIXEL_FORMAT_JPS[] = "jps";
+const char TICameraParameters::PIXEL_FORMAT_MPO[] = "mpo";
+const char TICameraParameters::PIXEL_FORMAT_YUV422I_UYVY[] = "yuv422i-uyvy";
+
+// TI extensions to standard android scene mode settings
+const char TICameraParameters::SCENE_MODE_CLOSEUP[] = "closeup";
+const char TICameraParameters::SCENE_MODE_AQUA[] = "aqua";
+const char TICameraParameters::SCENE_MODE_SNOWBEACH[] = "snow-beach";
+const char TICameraParameters::SCENE_MODE_MOOD[] = "mood";
+const char TICameraParameters::SCENE_MODE_NIGHT_INDOOR[] = "night-indoor";
+const char TICameraParameters::SCENE_MODE_DOCUMENT[] = "document";
+const char TICameraParameters::SCENE_MODE_BARCODE[] = "barcode";
+const char TICameraParameters::SCENE_MODE_VIDEO_SUPER_NIGHT[] = "super-night";
+const char TICameraParameters::SCENE_MODE_VIDEO_CINE[] = "cine";
+const char TICameraParameters::SCENE_MODE_VIDEO_OLD_FILM[] = "old-film";
+
+// TI extensions to standard android white balance values.
+const char TICameraParameters::WHITE_BALANCE_TUNGSTEN[] = "tungsten";
+const char TICameraParameters::WHITE_BALANCE_HORIZON[] = "horizon";
+const char TICameraParameters::WHITE_BALANCE_SUNSET[] = "sunset";
+const char TICameraParameters::WHITE_BALANCE_FACE[] = "face-priority";
+
+// TI extensions to standard android focus modes.
+const char TICameraParameters::FOCUS_MODE_PORTRAIT[] = "portrait";
+const char TICameraParameters::FOCUS_MODE_EXTENDED[] = "extended";
+const char TICameraParameters::FOCUS_MODE_FACE[] = "face-priority";
+const char TICameraParameters::FOCUS_MODE_OFF[] = "off";
+
+// TI extensions to add values for effect settings.
+const char TICameraParameters::EFFECT_NATURAL[] = "natural";
+const char TICameraParameters::EFFECT_VIVID[] = "vivid";
+const char TICameraParameters::EFFECT_COLOR_SWAP[] = "color-swap";
+const char TICameraParameters::EFFECT_BLACKWHITE[] = "blackwhite";
+
+// TI extensions to add exposure preset modes
+const char TICameraParameters::EXPOSURE_MODE_MANUAL[] = "manual";
+const char TICameraParameters::EXPOSURE_MODE_AUTO[] = "auto";
+const char TICameraParameters::EXPOSURE_MODE_NIGHT[] = "night";
+const char TICameraParameters::EXPOSURE_MODE_BACKLIGHT[] = "backlighting";
+const char TICameraParameters::EXPOSURE_MODE_SPOTLIGHT[] = "spotlight";
+const char TICameraParameters::EXPOSURE_MODE_SPORTS[] = "sports";
+const char TICameraParameters::EXPOSURE_MODE_SNOW[] = "snow";
+const char TICameraParameters::EXPOSURE_MODE_BEACH[] = "beach";
+const char TICameraParameters::EXPOSURE_MODE_APERTURE[] = "aperture";
+const char TICameraParameters::EXPOSURE_MODE_SMALL_APERTURE[] = "small-aperture";
+const char TICameraParameters::EXPOSURE_MODE_FACE[] = "face-priority";
+
+// TI extensions to add iso values
+const char TICameraParameters::ISO_MODE_AUTO[] = "auto";
+const char TICameraParameters::ISO_MODE_100[] = "100";
+const char TICameraParameters::ISO_MODE_200[] = "200";
+const char TICameraParameters::ISO_MODE_400[] = "400";
+const char TICameraParameters::ISO_MODE_800[] = "800";
+const char TICameraParameters::ISO_MODE_1000[] = "1000";
+const char TICameraParameters::ISO_MODE_1200[] = "1200";
+const char TICameraParameters::ISO_MODE_1600[] = "1600";
+
+//TI extensions for stereo frame layouts
+const char TICameraParameters::S3D_NONE[] = "none";
+const char TICameraParameters::S3D_TB_FULL[] = "tb-full";
+const char TICameraParameters::S3D_SS_FULL[] = "ss-full";
+const char TICameraParameters::S3D_TB_SUBSAMPLED[] = "tb-subsampled";
+const char TICameraParameters::S3D_SS_SUBSAMPLED[] = "ss-subsampled";
+
+// TI extensions to add auto convergence values
+const char TICameraParameters::AUTOCONVERGENCE_MODE_DISABLE[] = "disable";
+const char TICameraParameters::AUTOCONVERGENCE_MODE_FRAME[] = "frame";
+const char TICameraParameters::AUTOCONVERGENCE_MODE_CENTER[] = "center";
+const char TICameraParameters::AUTOCONVERGENCE_MODE_TOUCH[] = "touch";
+const char TICameraParameters::AUTOCONVERGENCE_MODE_MANUAL[] = "manual";
+
+//TI values for camera direction
+const char TICameraParameters::FACING_FRONT[]="front";
+const char TICameraParameters::FACING_BACK[]="back";
+
+//TI extensions to flash settings
+const char TICameraParameters::FLASH_MODE_FILL_IN[] = "fill-in";
+
+//TI extensions to add sensor orientation parameters
+const char TICameraParameters::ORIENTATION_SENSOR_NONE[] = "0";
+const char TICameraParameters::ORIENTATION_SENSOR_90[] = "90";
+const char TICameraParameters::ORIENTATION_SENSOR_180[] = "180";
+const char TICameraParameters::ORIENTATION_SENSOR_270[] = "270";
+
+const char TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED[] = "mechanical-misalignment-correction-supported";
+const char TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION[] = "mechanical-misalignment-correction";
+
+//TI extensions for enable/disable algos
+const char TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA[] = TI_KEY_ALGO_PREFIX "external-gamma";
+const char TICameraParameters::KEY_ALGO_NSF1[] = TI_KEY_ALGO_PREFIX "nsf1";
+const char TICameraParameters::KEY_ALGO_NSF2[] = TI_KEY_ALGO_PREFIX "nsf2";
+const char TICameraParameters::KEY_ALGO_SHARPENING[] = TI_KEY_ALGO_PREFIX "sharpening";
+const char TICameraParameters::KEY_ALGO_THREELINCOLORMAP[] = TI_KEY_ALGO_PREFIX "threelinecolormap";
+const char TICameraParameters::KEY_ALGO_GIC[] = TI_KEY_ALGO_PREFIX "gic";
+
+const char TICameraParameters::KEY_GAMMA_TABLE[] = "gamma-table";
+
+const char TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE[] = "preview-frame-rate-range";
+
+#ifdef MOTOROLA_CAMERA
+const char TICameraParameters::KEY_MOT_LEDFLASH[] = "mot-led-flash"; // U32, default 100, percent
+const char TICameraParameters::KEY_MOT_LEDTORCH[] = "mot-led-torch"; // U32, default 100, percent
+#endif
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/V4LCameraAdapter/V4LCameraAdapter.cpp b/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
new file mode 100644
index 0000000..e2cc5f3
--- /dev/null
+++ b/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
@@ -0,0 +1,1684 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file V4LCameraAdapter.cpp
+*
+* This file maps the Camera Hardware Interface to V4L2.
+*
+*/
+
+
+#include "V4LCameraAdapter.h"
+#include "CameraHal.h"
+#include "TICameraParameters.h"
+#include "DebugUtils.h"
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <linux/videodev.h>
+#include <cutils/properties.h>
+#include "DecoderFactory.h"
+
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+static int mDebugFps = 0;
+
+#define Q16_OFFSET 16
+
+#define HERE(Msg) {CAMHAL_LOGEB("--=== %s===--\n", Msg);}
+
+namespace Ti {
+namespace Camera {
+
+//frames skipped before recalculating the framerate
+#define FPS_PERIOD 30
+
+//Proto Types
+static void convertYUV422i_yuyvTouyvy(uint8_t *src, uint8_t *dest, size_t size );
+static void convertYUV422ToNV12Tiler(unsigned char *src, unsigned char *dest, int width, int height );
+static void convertYUV422ToNV12(unsigned char *src, unsigned char *dest, int width, int height );
+
+android::Mutex gV4LAdapterLock;
+char device[15];
+
+static void debugShowFPS()
+{
+ static int mFrameCount = 0;
+ static int mLastFrameCount = 0;
+ static nsecs_t mLastFpsTime = 0;
+ static float mFps = 0;
+ if(mDebugFps) {
+ mFrameCount++;
+ if ((mFrameCount % 30 == 0)) {
+ nsecs_t now = systemTime();
+ nsecs_t diff = now - mLastFpsTime;
+ mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
+ mLastFpsTime = now;
+ mLastFrameCount = mFrameCount;
+ CAMHAL_LOGE("Camera %d Frames, %f FPS", mFrameCount, mFps);
+ }
+ }
+}
+
+
+/*--------------------Camera Adapter Class STARTS here-----------------------------*/
+
+/*--------------------V4L wrapper functions -------------------------------*/
+
+bool V4LCameraAdapter::isNeedToUseDecoder() const {
+ return mPixelFormat != V4L2_PIX_FMT_YUYV;
+}
+
+status_t V4LCameraAdapter::v4lIoctl (int fd, int req, void* argp) {
+ status_t ret = NO_ERROR;
+ errno = 0;
+
+ android::AutoMutex lock(mV4LLock);
+
+ do {
+ ret = ioctl (fd, req, argp);
+ }while (-1 == ret && EINTR == errno);
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::v4lInitMmap(int& count, int width, int height) {
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ //First allocate adapter internal buffers at V4L level for USB Cam
+ //These are the buffers from which we will copy the data into overlay buffers
+ /* Check if camera can handle NB_BUFFER buffers */
+ mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->rb.memory = V4L2_MEMORY_MMAP;
+ mVideoInfo->rb.count = count;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
+ if (ret < 0) {
+ CAMHAL_LOGEB("VIDIOC_REQBUFS failed: %s", strerror(errno));
+ return ret;
+ }
+
+ count = mVideoInfo->rb.count;
+
+ //Since we will do mapping of new In buffers - clear input MediaBuffer storage
+ mInBuffers.clear();
+
+ for (int i = 0; i < count; i++) {
+
+ memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer));
+
+ mVideoInfo->buf.index = i;
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = v4lIoctl (mCameraHandle, VIDIOC_QUERYBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ CAMHAL_LOGEB("Unable to query buffer (%s)", strerror(errno));
+ return ret;
+ }
+
+ mVideoInfo->mem[i] = mmap (NULL,
+ mVideoInfo->buf.length,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ mCameraHandle,
+ mVideoInfo->buf.m.offset);
+
+ CAMHAL_LOGVB(" mVideoInfo->mem[%d]=%p ; mVideoInfo->buf.length = %d", i, mVideoInfo->mem[i], mVideoInfo->buf.length);
+ if (mVideoInfo->mem[i] == MAP_FAILED) {
+ CAMHAL_LOGEB("Unable to map buffer [%d]. (%s)", i, strerror(errno));
+ return -1;
+ }
+
+ MediaBuffer* buffer = new MediaBuffer(i, mVideoInfo->mem[i], mVideoInfo->buf.length);
+ mInBuffers.push_back(buffer);
+ }
+
+ if (isNeedToUseDecoder()) {
+ mDecoder->registerInputBuffers(&mInBuffers);
+ DecoderParameters params;
+ params.width = width;
+ params.height = height;
+ params.inputBufferCount = count;
+ params.outputBufferCount = count;
+ mDecoder->configure(params);
+ }
+
+
+
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::v4lInitUsrPtr(int& count) {
+ status_t ret = NO_ERROR;
+
+ mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->rb.memory = V4L2_MEMORY_USERPTR;
+ mVideoInfo->rb.count = count;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
+ if (ret < 0) {
+ CAMHAL_LOGEB("VIDIOC_REQBUFS failed for USERPTR: %s", strerror(errno));
+ return ret;
+ }
+
+ count = mVideoInfo->rb.count;
+ return ret;
+}
+
+status_t V4LCameraAdapter::v4lStartStreaming () {
+ status_t ret = NO_ERROR;
+ enum v4l2_buf_type bufType;
+
+ LOG_FUNCTION_NAME;
+
+ if (!mVideoInfo->isStreaming) {
+ bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ ret = applyFpsValue();
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ ret = v4lIoctl (mCameraHandle, VIDIOC_STREAMON, &bufType);
+ if (ret < 0) {
+ CAMHAL_LOGEB("StartStreaming: Unable to start capture: %s", strerror(errno));
+ return ret;
+ }
+ mVideoInfo->isStreaming = true;
+ }
+
+ // This is WA for some cameras with incorrect driver behavior
+ // there is possibility that fist frame after VIDIOC_STREAMON
+ // will remain from previous resolution/will be distorted
+ // for such cameras can be dynamically set frame count that will be
+ // skipped after frame on.
+ for (int i = 0; i < mSkipFramesCount; i++) {
+ int id = 0, length = 0;
+ if (GetFrame(id, length) != NULL) {
+ returnBufferToV4L(id);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::v4lStopStreaming (int nBufferCount) {
+ status_t ret = NO_ERROR;
+ enum v4l2_buf_type bufType;
+
+ LOG_FUNCTION_NAME;
+
+ if (mVideoInfo->isStreaming) {
+ bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = v4lIoctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType);
+ if (ret != 0) {
+ CAMHAL_LOGEB("StopStreaming: Unable to stop capture: %s", strerror(errno));
+ return ret;
+ }
+ mVideoInfo->isStreaming = false;
+
+ /* Unmap buffers */
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+ for (int i = 0; i < nBufferCount; i++) {
+ if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0) {
+ CAMHAL_LOGEA("munmap() failed");
+ }
+ mVideoInfo->mem[i] = 0;
+ }
+
+ //free the memory allocated during REQBUFS, by setting the count=0
+ mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->rb.memory = V4L2_MEMORY_MMAP;
+ mVideoInfo->rb.count = 0;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
+ if (ret < 0) {
+ CAMHAL_LOGEB("VIDIOC_REQBUFS failed: %s", strerror(errno));
+ goto EXIT;
+ }
+ }
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::v4lSetFormat (int width, int height, uint32_t pix_format) {
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ ret = v4lIoctl(mCameraHandle, VIDIOC_G_FMT, &mVideoInfo->format);
+ if (ret < 0) {
+ CAMHAL_LOGEB("VIDIOC_G_FMT Failed: %s", strerror(errno));
+ }
+
+ mVideoInfo->width = width;
+ mVideoInfo->height = height;
+ mVideoInfo->framesizeIn = (width * height << 1);
+ mVideoInfo->formatIn = pix_format;
+
+ mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->format.fmt.pix.width = width;
+ mVideoInfo->format.fmt.pix.height = height;
+ mVideoInfo->format.fmt.pix.pixelformat = pix_format;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_S_FMT, &mVideoInfo->format);
+ if (ret < 0) {
+ CAMHAL_LOGEB("VIDIOC_S_FMT Failed: %s", strerror(errno));
+ return ret;
+ }
+ v4lIoctl(mCameraHandle, VIDIOC_G_FMT, &mVideoInfo->format);
+ CAMHAL_LOGDB("VIDIOC_G_FMT : WxH = %dx%d", mVideoInfo->format.fmt.pix.width, mVideoInfo->format.fmt.pix.height);
+ CAMHAL_LOGD("### Using: WxH = %dx%d pixelformat=0x%x ", mVideoInfo->format.fmt.pix.width, mVideoInfo->format.fmt.pix.height, mVideoInfo->format.fmt.pix.pixelformat);
+ CAMHAL_LOGD("### Using: bytesperline=%d sizeimage=%d colorspace=0x%x", mVideoInfo->format.fmt.pix.bytesperline, mVideoInfo->format.fmt.pix.sizeimage, mVideoInfo->format.fmt.pix.colorspace);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::restartPreview ()
+{
+ status_t ret = NO_ERROR;
+ int width = 0;
+ int height = 0;
+ struct v4l2_streamparm streamParams;
+
+ LOG_FUNCTION_NAME;
+
+ //configure for preview size and pixel format.
+ mParams.getPreviewSize(&width, &height);
+
+ ret = v4lSetFormat (width, height, mPixelFormat);
+ if (ret < 0) {
+ CAMHAL_LOGEB("v4lSetFormat Failed: %s", strerror(errno));
+ goto EXIT;
+ }
+
+ ret = v4lInitMmap(mPreviewBufferCount, width, height);
+ if (ret < 0) {
+ CAMHAL_LOGEB("v4lInitMmap Failed: %s", strerror(errno));
+ goto EXIT;
+ }
+
+ for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
+
+ v4l2_buffer buf;
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("VIDIOC_QBUF Failed");
+ goto EXIT;
+ }
+ nQueued++;
+ }
+
+ if (isNeedToUseDecoder()) {
+ for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
+ mDecoder->queueOutputBuffer(i);
+ CAMHAL_LOGV("Queued output buffer with id=%d ", i);
+ }
+ mDecoder->start();
+ }
+
+ ret = v4lStartStreaming();
+ CAMHAL_LOGDA("Ready for preview....");
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+/*--------------------Camera Adapter Functions-----------------------------*/
+status_t V4LCameraAdapter::initialize(CameraProperties::Properties* caps)
+{
+ char value[PROPERTY_VALUE_MAX];
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ property_get("debug.camera.showfps", value, "0");
+ mDebugFps = atoi(value);
+
+ int ret = NO_ERROR;
+
+ // Allocate memory for video info structure
+ mVideoInfo = (struct VideoInfo *) calloc (1, sizeof (struct VideoInfo));
+ if(!mVideoInfo) {
+ ret = NO_MEMORY;
+ goto EXIT;
+ }
+
+ if ((mCameraHandle = open(device, O_RDWR | O_NONBLOCK) ) == -1) {
+ CAMHAL_LOGEB("Error while opening handle to V4L2 Camera: %s", strerror(errno));
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+
+ ret = v4lIoctl (mCameraHandle, VIDIOC_QUERYCAP, &mVideoInfo->cap);
+ if (ret < 0) {
+ CAMHAL_LOGEA("Error when querying the capabilities of the V4L Camera");
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+
+ if ((mVideoInfo->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
+ CAMHAL_LOGEA("Error while adapter initialization: video capture not supported.");
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+
+ if (!(mVideoInfo->cap.capabilities & V4L2_CAP_STREAMING)) {
+ CAMHAL_LOGEA("Error while adapter initialization: Capture device does not support streaming i/o");
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+
+ // Initialize flags
+ mPreviewing = false;
+ mVideoInfo->isStreaming = false;
+ mRecording = false;
+ mCapturing = false;
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::fillThisBuffer(CameraBuffer *frameBuf, CameraFrame::FrameType frameType)
+{
+ status_t ret = NO_ERROR;
+ int idx = 0;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if ( frameType == CameraFrame::IMAGE_FRAME) { //(1 > mCapturedFrames)
+ // Signal end of image capture
+ if ( NULL != mEndImageCaptureCallback) {
+ CAMHAL_LOGDB("===========Signal End Image Capture==========");
+ mLock.unlock();
+ mEndImageCaptureCallback(mEndCaptureData);
+ mLock.lock();
+ }
+ return ret;
+ }
+
+ if ( !mVideoInfo->isStreaming ) {
+ return ret;
+ }
+
+ for (int xx = 0; xx < NB_BUFFER; xx++){
+ if (mPreviewBufs[xx] == frameBuf){
+ idx = xx;
+ break;
+ }
+ }
+ if (idx == NB_BUFFER){
+ CAMHAL_LOGEB("Wrong index = %d. What do i do? What do i do?",idx);
+ return ret;
+ }
+ if(idx < 0) {
+ CAMHAL_LOGEB("Wrong index = %d",idx);
+ return ret;
+ }
+ if (isNeedToUseDecoder()) {
+ for (int i = 0; i < mOutBuffers.size(); i++) {
+ android::sp<MediaBuffer>& outBuffer = mOutBuffers.editItemAt(i);
+ CameraBuffer* buffer = static_cast<CameraBuffer*>(outBuffer->buffer);
+ if (buffer == frameBuf) {
+ mDecoder->queueOutputBuffer(outBuffer->bufferId);
+ break;
+ }
+ }
+
+ int inIndex = -1;
+ ret = mDecoder->dequeueInputBuffer(inIndex);
+
+ if (ret == NO_ERROR) {
+ ret = returnBufferToV4L(inIndex);
+ }
+
+ } else {
+ v4l2_buffer buf;
+ buf.index = idx;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ CAMHAL_LOGD("Will return buffer to V4L with id=%d", idx);
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("VIDIOC_QBUF Failed");
+ goto EXIT;
+ }
+
+ nQueued++;
+ }
+
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+
+}
+
+status_t V4LCameraAdapter::applyFpsValue() {
+ struct v4l2_streamparm streamParams;
+ status_t ret = NO_ERROR;
+ streamParams.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ streamParams.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+ streamParams.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
+ streamParams.parm.capture.timeperframe.denominator = mFrameRate / CameraHal::VFR_SCALE;
+ streamParams.parm.capture.timeperframe.numerator= 1;
+ ret = v4lIoctl(mCameraHandle, VIDIOC_S_PARM, &streamParams);
+ if (ret < 0) {
+ CAMHAL_LOGEB(" VIDIOC_S_PARM Failed: %s", strerror(errno));
+ return ret;
+ }
+ int actualFps = streamParams.parm.capture.timeperframe.denominator / streamParams.parm.capture.timeperframe.numerator;
+ CAMHAL_LOGDB("Actual FPS set is : %d.", actualFps);
+ return NO_ERROR;
+}
+
+status_t V4LCameraAdapter::setParameters(const android::CameraParameters &params)
+{
+ status_t ret = NO_ERROR;
+ int width, height;
+ int minFps = 0, maxFps = 0;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if(!mPreviewing && !mCapturing) {
+ params.getPreviewSize(&width, &height);
+ CAMHAL_LOGDB("Width * Height %d x %d format 0x%x", width, height, mPixelFormat);
+ ret = v4lSetFormat( width, height, mPixelFormat);
+ if (ret < 0) {
+ CAMHAL_LOGEB(" VIDIOC_S_FMT Failed: %s", strerror(errno));
+ goto EXIT;
+ }
+ const char *frameRateRange = params.get(TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE);
+ bool fpsRangeParsed = CameraHal::parsePair(frameRateRange, &minFps, &maxFps, ',');
+ CAMHAL_ASSERT(fpsRangeParsed);
+ CAMHAL_LOGD("Current fps is %d new fps is (%d,%d)", mFrameRate, minFps, maxFps);
+ if (maxFps != mFrameRate) {
+ mFrameRate = maxFps;
+ }
+
+ }
+
+ // Udpate the current parameter set
+ mParams = params;
+
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+
+void V4LCameraAdapter::getParameters(android::CameraParameters& params)
+{
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+ // Return the current parameter set
+ params = mParams;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+///API to give the buffers to Adapter
+status_t V4LCameraAdapter::useBuffers(CameraMode mode, CameraBuffer *bufArr, int num, size_t length, unsigned int queueable)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ switch(mode)
+ {
+ case CAMERA_PREVIEW:
+ mPreviewBufferCountQueueable = queueable;
+ ret = UseBuffersPreview(bufArr, num);
+ break;
+
+ case CAMERA_IMAGE_CAPTURE:
+ mCaptureBufferCountQueueable = queueable;
+ ret = UseBuffersCapture(bufArr, num);
+ break;
+
+ case CAMERA_VIDEO:
+ //@warn Video capture is not fully supported yet
+ mPreviewBufferCountQueueable = queueable;
+ ret = UseBuffersPreview(bufArr, num);
+ break;
+
+ case CAMERA_MEASUREMENT:
+ break;
+
+ default:
+ break;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::UseBuffersCapture(CameraBuffer *bufArr, int num) {
+ int ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+ if(NULL == bufArr) {
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+
+ for (int i = 0; i < num; i++) {
+ //Associate each Camera internal buffer with the one from Overlay
+ mCaptureBufs.add(&bufArr[i], i);
+ CAMHAL_LOGDB("capture- buff [%d] = 0x%x ",i, mCaptureBufs.keyAt(i));
+ }
+
+ mCaptureBuffersAvailable.clear();
+ for (int i = 0; i < mCaptureBufferCountQueueable; i++ ) {
+ mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 0);
+ }
+
+ // initial ref count for undeqeueued buffers is 1 since buffer provider
+ // is still holding on to it
+ for (int i = mCaptureBufferCountQueueable; i < num; i++ ) {
+ mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 1);
+ }
+
+ // Update the preview buffer count
+ mCaptureBufferCount = num;
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+
+}
+
+status_t V4LCameraAdapter::UseBuffersPreview(CameraBuffer *bufArr, int num)
+{
+ int ret = NO_ERROR;
+ int width = 0, height = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if(NULL == bufArr) {
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+
+ mParams.getPreviewSize(&width, &height);
+ ret = v4lInitMmap(num, width, height);
+
+ mOutBuffers.clear();
+
+ if (ret == NO_ERROR) {
+ for (int i = 0; i < num; i++) {
+ //Associate each Camera internal buffer with the one from Overlay
+ mPreviewBufs[i] = &bufArr[i];
+ MediaBuffer* buffer = new MediaBuffer(i, mPreviewBufs[i]);
+ mOutBuffers.push_back(buffer);
+ CAMHAL_LOGDB("Preview- buff [%d] = 0x%x length=%d",i, mPreviewBufs[i], mFrameQueue.valueFor(mPreviewBufs[i])->mLength);
+ }
+ if (isNeedToUseDecoder()) {
+ mDecoder->registerOutputBuffers(&mOutBuffers);
+ }
+ // Update the preview buffer count
+ mPreviewBufferCount = num;
+ }
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::takePicture() {
+ status_t ret = NO_ERROR;
+ int width = 0;
+ int height = 0;
+ size_t yuv422i_buff_size = 0;
+ int index = 0;
+ char *fp = NULL;
+ CameraBuffer *buffer = NULL;
+ CameraFrame frame;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if (mCapturing) {
+ CAMHAL_LOGEA("Already Capture in Progress...");
+ return BAD_VALUE;
+ }
+
+ mPreviewing = false;
+ mLock.unlock();
+
+ {
+ android::AutoMutex stopLock(mStopLock);
+ CAMHAL_LOGW("Wait till preview stops");
+ ret = mStopCondition.waitRelative(mStopLock, 100000000);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGW("Timeout waiting for preview stop");
+ }
+ }
+
+ if (isNeedToUseDecoder()) {
+ mDecoder->stop();
+ mDecoder->flush();
+ }
+ mLock.lock();
+ mCapturing = true;
+ mPreviewing = false;
+
+ // Stop preview streaming
+ ret = v4lStopStreaming(mPreviewBufferCount);
+ if (ret < 0 ) {
+ CAMHAL_LOGEB("v4lStopStreaming Failed: %s", strerror(errno));
+ goto EXIT;
+ }
+
+ //configure for capture image size and pixel format.
+ mParams.getPictureSize(&width, &height);
+ CAMHAL_LOGDB("Image Capture Size WxH = %dx%d",width,height);
+ yuv422i_buff_size = width * height * 2;
+
+ ret = v4lSetFormat (width, height, DEFAULT_CAPTURE_FORMAT);
+ if (ret < 0) {
+ CAMHAL_LOGEB("v4lSetFormat Failed: %s", strerror(errno));
+ goto EXIT;
+ }
+
+ ret = v4lInitMmap(mCaptureBufferCount, width, height);
+ if (ret < 0) {
+ CAMHAL_LOGEB("v4lInitMmap Failed: %s", strerror(errno));
+ goto EXIT;
+ }
+
+ for (int i = 0; i < mCaptureBufferCountQueueable; i++) {
+
+ v4l2_buffer buf;
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("VIDIOC_QBUF Failed");
+ return BAD_VALUE;
+ }
+ nQueued++;
+ }
+
+ ret = v4lStartStreaming();
+ if (ret < 0) {
+ CAMHAL_LOGEB("v4lStartStreaming Failed: %s", strerror(errno));
+ goto EXIT;
+ }
+
+ CAMHAL_LOGDA("Streaming started for Image Capture");
+
+ //get the frame and send to encode as JPG
+ int filledLen;
+ CAMHAL_LOGD("*********Will dequeue frame for Image Capture***********");
+
+ fp = this->GetFrame(index, filledLen);
+ if (!fp) {
+ CAMHAL_LOGEA("!!! Captured frame is NULL !!!!");
+ return BAD_VALUE;
+ }
+
+
+
+ CAMHAL_LOGDA("::Capture Frame received from V4L::");
+ buffer = mCaptureBufs.keyAt(index);
+ CAMHAL_LOGVB("## captureBuf[%d] = 0x%x, yuv422i_buff_size=%d fill_length=%d", index, buffer->opaque, yuv422i_buff_size, filledLen);
+
+ //copy the yuv422i data to the image buffer.
+ memcpy(buffer->opaque, fp, filledLen);
+
+#ifdef DUMP_CAPTURE_FRAME
+ //dump the YUV422 buffer in to a file
+ //a folder should have been created at /data/misc/camera/raw/
+ {
+ int fd =-1;
+ fd = open("/data/misc/camera/raw/captured_yuv422i_dump.yuv", O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
+ if(fd < 0) {
+ CAMHAL_LOGEB("Unable to open file: %s", strerror(fd));
+ }
+ else {
+ write(fd, fp, yuv422i_buff_size );
+ close(fd);
+ CAMHAL_LOGDB("::Captured Frame dumped at /data/misc/camera/raw/captured_yuv422i_dump.yuv::");
+ }
+ }
+#endif
+
+ CAMHAL_LOGDA("::sending capture frame to encoder::");
+ frame.mFrameType = CameraFrame::IMAGE_FRAME;
+ frame.mBuffer = buffer;
+ frame.mLength = yuv422i_buff_size;
+ frame.mWidth = width;
+ frame.mHeight = height;
+ frame.mAlignment = width*2;
+ frame.mOffset = 0;
+ frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ frame.mFrameMask = (unsigned int)CameraFrame::IMAGE_FRAME;
+ frame.mQuirks |= CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG;
+ frame.mQuirks |= CameraFrame::FORMAT_YUV422I_YUYV;
+
+ ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
+ } else {
+ ret = sendFrameToSubscribers(&frame);
+ }
+
+ // Stop streaming after image capture
+ ret = v4lStopStreaming(mCaptureBufferCount);
+ if (ret < 0 ) {
+ CAMHAL_LOGEB("v4lStopStreaming Failed: %s", strerror(errno));
+ goto EXIT;
+ }
+ ret = restartPreview();
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::stopImageCapture()
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ //Release image buffers
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+ mCaptureBufs.clear();
+
+ mCapturing = false;
+ mPreviewing = true;
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::autoFocus()
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ //autoFocus is not implemented. Just return.
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::startPreview()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if(mPreviewing) {
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+
+ for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
+ v4l2_buffer buf;
+
+ memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer));
+
+ mVideoInfo->buf.index = i;
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = v4lIoctl (mCameraHandle, VIDIOC_QUERYBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ CAMHAL_LOGEB("Unable to query buffer (%s)", strerror(errno));
+ return ret;
+ }
+
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("VIDIOC_QBUF Failed");
+ goto EXIT;
+ }
+ nQueued++;
+ }
+
+ if (isNeedToUseDecoder()) {
+ for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
+ mDecoder->queueOutputBuffer(i);
+ CAMHAL_LOGV("Queued output buffer with id=%d ", i);
+ }
+ mDecoder->start();
+ }
+ ret = v4lStartStreaming();
+
+ // Create and start preview thread for receiving buffers from V4L Camera
+ if(!mCapturing) {
+ mPreviewThread = new PreviewThread(this);
+ CAMHAL_LOGDA("Created preview thread");
+ }
+
+ //Update the flag to indicate we are previewing
+ mPreviewing = true;
+ mCapturing = false;
+
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t V4LCameraAdapter::stopPreview()
+{
+ enum v4l2_buf_type bufType;
+ int ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ if(!mPreviewing) {
+ return NO_INIT;
+ }
+ mPreviewing = false;
+ if (isNeedToUseDecoder()) {
+ android::AutoMutex lock(mStopLock);
+ mStopCondition.waitRelative(mStopLock, 100000000);
+ mDecoder->stop();
+ mDecoder->flush();
+ }
+ ret = v4lStopStreaming(mPreviewBufferCount);
+ if (ret < 0) {
+ CAMHAL_LOGEB("StopStreaming: FAILED: %s", strerror(errno));
+ }
+
+ nQueued = 0;
+ nDequeued = 0;
+ mFramesWithEncoder = 0;
+
+ mLock.unlock();
+
+ mPreviewThread->requestExitAndWait();
+ mPreviewThread.clear();
+
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+
+void saveFile(unsigned char* buff, int buff_size) {
+ static int counter = 1;
+ int fd = -1;
+ char fn[256];
+
+ LOG_FUNCTION_NAME;
+ if (counter > 30) {
+ return;
+ }
+ //dump nv12 buffer
+ counter++;
+ sprintf(fn, "/data/tmp/dump_%03d.h264", counter);
+ CAMHAL_LOGEB("Dumping h264 frame to a file : %s.", fn);
+
+ fd = open(fn, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
+ if(fd < 0) {
+ CAMHAL_LOGE("Unable to open file %s: %s", fn, strerror(fd));
+ return;
+ }
+
+ write(fd, buff, buff_size );
+ close(fd);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+char * V4LCameraAdapter::GetFrame(int &index, int &filledLen)
+{
+ int ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ v4l2_buffer buf;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ /* DQ */
+ // Some V4L drivers, notably uvc, protect each incoming call with
+ // a driver-wide mutex. If we use poll() or blocking VIDIOC_DQBUF ioctl
+ // here then we sometimes would run into a deadlock on VIDIO_QBUF ioctl.
+ while(true) {
+ if(!mVideoInfo->isStreaming) {
+ return NULL;
+ }
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_DQBUF, &buf);
+ if((ret == 0) || (errno != EAGAIN)) {
+ break;
+ }
+ }
+
+ if (ret < 0) {
+ CAMHAL_LOGEA("GetFrame: VIDIOC_DQBUF Failed");
+ return NULL;
+ }
+
+ index = buf.index;
+ filledLen = buf.bytesused;
+
+ android::sp<MediaBuffer>& inBuffer = mInBuffers.editItemAt(index);
+ {
+ android::AutoMutex bufferLock(inBuffer->getLock());
+ inBuffer->setTimestamp(systemTime(SYSTEM_TIME_MONOTONIC));
+ inBuffer->filledLen = buf.bytesused;
+ }
+ debugShowFPS();
+ LOG_FUNCTION_NAME_EXIT;
+ return (char *)mVideoInfo->mem[index];
+}
+
+
+
+
+
+//API to get the frame size required to be allocated. This size is used to override the size passed
+//by camera service when VSTAB/VNF is turned ON for example
+status_t V4LCameraAdapter::getFrameSize(size_t &width, size_t &height)
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ // Just return the current preview size, nothing more to do here.
+ mParams.getPreviewSize(( int * ) &width,( int * ) &height);
+
+ // TODO: This will reside until correct port reconfiguration handling will done.
+ if (isNeedToUseDecoder()) {
+ mDecoder->getPaddedDimensions(width, height);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::getFrameDataSize(size_t &dataFrameSize, size_t bufferCount)
+{
+ android::AutoMutex lock(mLock);
+ // We don't support meta data, so simply return
+ return NO_ERROR;
+}
+
+status_t V4LCameraAdapter::getPictureBufferSize(CameraFrame &frame, size_t bufferCount)
+{
+ int width = 0;
+ int height = 0;
+ int bytesPerPixel = 2; // for YUV422i; default pixel format
+
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ mParams.getPictureSize( &width, &height );
+ frame.mLength = width * height * bytesPerPixel;
+ frame.mWidth = width;
+ frame.mHeight = height;
+ frame.mAlignment = width * bytesPerPixel;
+
+ CAMHAL_LOGDB("Picture size: W x H = %u x %u (size=%u bytes, alignment=%u bytes)",
+ frame.mWidth, frame.mHeight, frame.mLength, frame.mAlignment);
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+}
+
+status_t V4LCameraAdapter::recalculateFPS()
+{
+ float currentFPS;
+
+ mFrameCount++;
+
+ if ( ( mFrameCount % FPS_PERIOD ) == 0 )
+ {
+ nsecs_t now = systemTime();
+ nsecs_t diff = now - mLastFPSTime;
+ currentFPS = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
+ mLastFPSTime = now;
+ mLastFrameCount = mFrameCount;
+
+ if ( 1 == mIter )
+ {
+ mFPS = currentFPS;
+ }
+ else
+ {
+ //cumulative moving average
+ mFPS = mLastFPS + (currentFPS - mLastFPS)/mIter;
+ }
+
+ mLastFPS = mFPS;
+ mIter++;
+ }
+
+ return NO_ERROR;
+}
+
+void V4LCameraAdapter::onOrientationEvent(uint32_t orientation, uint32_t tilt)
+{
+ LOG_FUNCTION_NAME;
+
+ android::AutoMutex lock(mLock);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void V4LCameraAdapter::setupWorkingMode() {
+ char value[PROPERTY_VALUE_MAX];
+ int v4lMode = 0;
+
+ property_get("camera.v4l.mode", value, "3");
+ v4lMode = atoi(value);
+
+ if (mDecoder) {
+ delete mDecoder;
+ mDecoder = NULL;
+ }
+
+ switch (v4lMode) {
+ case 0 : {
+ mPixelFormat = V4L2_PIX_FMT_MJPEG;
+ mCameraHal->setExternalLocking(true);
+ mDecoder = DecoderFactory::createDecoderByType(DecoderType_MJPEG, false);
+ CAMHAL_LOGI("Using V4L preview format: V4L2_PIX_FMT_MJPEG with HW decoding");
+ break;
+ }
+
+ case 1 : {
+ mPixelFormat = V4L2_PIX_FMT_MJPEG;
+ mCameraHal->setExternalLocking(false);
+ mDecoder = DecoderFactory::createDecoderByType(DecoderType_MJPEG, true);
+ CAMHAL_LOGI("Using V4L preview format: V4L2_PIX_FMT_MJPEG with SW decoding");
+ break;
+ }
+
+ case 2 : {
+ mPixelFormat = V4L2_PIX_FMT_H264;
+ mCameraHal->setExternalLocking(true);
+ mDecoder = DecoderFactory::createDecoderByType(DecoderType_H264, false);
+ CAMHAL_LOGI("Using V4L preview format: V4L2_PIX_FMT_H264");
+ break;
+ }
+ default:
+ case 3 : {
+ mCameraHal->setExternalLocking(false);
+ mPixelFormat = V4L2_PIX_FMT_YUYV;
+ CAMHAL_LOGI("Using V4L preview format: V4L2_PIX_FMT_YUYV");
+ }
+
+ }
+}
+
+V4LCameraAdapter::V4LCameraAdapter(size_t sensor_index, CameraHal* hal)
+ :mPixelFormat(DEFAULT_PIXEL_FORMAT), mFrameRate(0), mCameraHal(hal),
+ mSkipFramesCount(0)
+{
+ LOG_FUNCTION_NAME;
+
+ char value[PROPERTY_VALUE_MAX];
+
+ // Nothing useful to do in the constructor
+ mFramesWithEncoder = 0;
+ mDecoder = 0;
+ nQueued = 0;
+ nDequeued = 0;
+
+ setupWorkingMode();
+
+ property_get("camera.v4l.skipframes", value, "1");
+ mSkipFramesCount = atoi(value);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+V4LCameraAdapter::~V4LCameraAdapter()
+{
+ LOG_FUNCTION_NAME;
+
+ // Close the camera handle and free the video info structure
+ close(mCameraHandle);
+
+ if (mVideoInfo)
+ {
+ free(mVideoInfo);
+ mVideoInfo = NULL;
+ }
+
+ delete mDecoder;
+
+ mInBuffers.clear();
+ mOutBuffers.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+static void convertYUV422i_yuyvTouyvy(uint8_t *src, uint8_t *dest, size_t size ) {
+ //convert YUV422I yuyv to uyvy format.
+ uint32_t *bf = (uint32_t*)src;
+ uint32_t *dst = (uint32_t*)dest;
+
+ LOG_FUNCTION_NAME;
+
+ if (!src || !dest) {
+ return;
+ }
+
+ for(size_t i = 0; i < size; i = i+4)
+ {
+ dst[0] = ((bf[0] & 0x00FF00FF) << 8) | ((bf[0] & 0xFF00FF00) >> 8);
+ bf++;
+ dst++;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+static void convertYUV422ToNV12Tiler(unsigned char *src, unsigned char *dest, int width, int height ) {
+ //convert YUV422I to YUV420 NV12 format and copies directly to preview buffers (Tiler memory).
+ int stride = 4096;
+ unsigned char *bf = src;
+ unsigned char *dst_y = dest;
+ unsigned char *dst_uv = dest + ( height * stride);
+#ifdef PPM_PER_FRAME_CONVERSION
+ static int frameCount = 0;
+ static nsecs_t ppm_diff = 0;
+ nsecs_t ppm_start = systemTime();
+#endif
+
+ LOG_FUNCTION_NAME;
+
+ if (width % 16 ) {
+ for(int i = 0; i < height; i++) {
+ for(int j = 0; j < width; j++) {
+ *dst_y = *bf;
+ dst_y++;
+ bf = bf + 2;
+ }
+ dst_y += (stride - width);
+ }
+
+ bf = src;
+ bf++; //UV sample
+ for(int i = 0; i < height/2; i++) {
+ for(int j=0; j<width; j++) {
+ *dst_uv = *bf;
+ dst_uv++;
+ bf = bf + 2;
+ }
+ bf = bf + width*2;
+ dst_uv = dst_uv + (stride - width);
+ }
+ } else {
+ //neon conversion
+ for(int i = 0; i < height; i++) {
+ int n = width;
+ int skip = i & 0x1; // skip uv elements for the odd rows
+ asm volatile (
+ " pld [%[src], %[src_stride], lsl #2] \n\t"
+ " cmp %[n], #16 \n\t"
+ " blt 5f \n\t"
+ "0: @ 16 pixel copy \n\t"
+ " vld2.8 {q0, q1} , [%[src]]! @ q0 = yyyy.. q1 = uvuv.. \n\t"
+ " @ now q0 = y q1 = uv \n\t"
+ " vst1.32 {d0,d1}, [%[dst_y]]! \n\t"
+ " cmp %[skip], #0 \n\t"
+ " bne 1f \n\t"
+ " vst1.32 {d2,d3},[%[dst_uv]]! \n\t"
+ "1: @ skip odd rows for UV \n\t"
+ " sub %[n], %[n], #16 \n\t"
+ " cmp %[n], #16 \n\t"
+ " bge 0b \n\t"
+ "5: @ end \n\t"
+#ifdef NEEDS_ARM_ERRATA_754319_754320
+ " vmov s0,s0 @ add noop for errata item \n\t"
+#endif
+ : [dst_y] "+r" (dst_y), [dst_uv] "+r" (dst_uv), [src] "+r" (src), [n] "+r" (n)
+ : [src_stride] "r" (width), [skip] "r" (skip)
+ : "cc", "memory", "q0", "q1", "q2", "d0", "d1", "d2", "d3"
+ );
+ dst_y = dst_y + (stride - width);
+ if (skip == 0) {
+ dst_uv = dst_uv + (stride - width);
+ }
+ } //end of for()
+ }
+
+#ifdef PPM_PER_FRAME_CONVERSION
+ ppm_diff += (systemTime() - ppm_start);
+ frameCount++;
+
+ if (frameCount >= 30) {
+ ppm_diff = ppm_diff / frameCount;
+ LOGD("PPM: YUV422i to NV12 Conversion(%d x %d): %llu us ( %llu ms )", width, height,
+ ns2us(ppm_diff), ns2ms(ppm_diff) );
+ ppm_diff = 0;
+ frameCount = 0;
+ }
+#endif
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+static void convertYUV422ToNV12(unsigned char *src, unsigned char *dest, int width, int height ) {
+ //convert YUV422I to YUV420 NV12 format.
+ unsigned char *bf = src;
+ unsigned char *dst_y = dest;
+ unsigned char *dst_uv = dest + (width * height);
+
+ LOG_FUNCTION_NAME;
+
+ if (width % 16 ) {
+ for(int i = 0; i < height; i++) {
+ for(int j = 0; j < width; j++) {
+ *dst_y = *bf;
+ dst_y++;
+ bf = bf + 2;
+ }
+ }
+
+ bf = src;
+ bf++; //UV sample
+ for(int i = 0; i < height/2; i++) {
+ for(int j=0; j<width; j++) {
+ *dst_uv = *bf;
+ dst_uv++;
+ bf = bf + 2;
+ }
+ bf = bf + width*2;
+ }
+ } else {
+ //neon conversion
+ for(int i = 0; i < height; i++) {
+ int n = width;
+ int skip = i & 0x1; // skip uv elements for the odd rows
+ asm volatile (
+ " pld [%[src], %[src_stride], lsl #2] \n\t"
+ " cmp %[n], #16 \n\t"
+ " blt 5f \n\t"
+ "0: @ 16 pixel copy \n\t"
+ " vld2.8 {q0, q1} , [%[src]]! @ q0 = yyyy.. q1 = uvuv.. \n\t"
+ " @ now q0 = y q1 = uv \n\t"
+ " vst1.32 {d0,d1}, [%[dst_y]]! \n\t"
+ " cmp %[skip], #0 \n\t"
+ " bne 1f \n\t"
+ " vst1.32 {d2,d3},[%[dst_uv]]! \n\t"
+ "1: @ skip odd rows for UV \n\t"
+ " sub %[n], %[n], #16 \n\t"
+ " cmp %[n], #16 \n\t"
+ " bge 0b \n\t"
+ "5: @ end \n\t"
+#ifdef NEEDS_ARM_ERRATA_754319_754320
+ " vmov s0,s0 @ add noop for errata item \n\t"
+#endif
+ : [dst_y] "+r" (dst_y), [dst_uv] "+r" (dst_uv), [src] "+r" (src), [n] "+r" (n)
+ : [src_stride] "r" (width), [skip] "r" (skip)
+ : "cc", "memory", "q0", "q1", "q2", "d0", "d1", "d2", "d3"
+ );
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+
+
+
+/* Preview Thread */
+// ---------------------------------------------------------------------------
+
+void V4LCameraAdapter::returnOutputBuffer(int index)
+{
+ LOG_FUNCTION_NAME;
+
+ size_t width, height;
+ int stride = 4096;
+ CameraFrame frame;
+
+ getFrameSize(width, height);
+
+ android::Mutex::Autolock slock(mSubscriberLock);
+
+ android::sp<MediaBuffer>& buffer = mOutBuffers.editItemAt(index);
+
+ CameraBuffer* cbuffer = static_cast<CameraBuffer*>(buffer->buffer);
+
+ frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
+ frame.mBuffer = cbuffer;
+ if (isNeedToUseDecoder()) {
+ //We always get NV12 on out, when using decoder.
+ frame.mLength = height * stride * 3 / 2;
+ } else {
+ frame.mLength = CameraHal::calculateBufferSize(mParams.getPreviewFormat(), width, height);
+ }
+ frame.mAlignment = stride;
+ frame.mOffset = buffer->getOffset();
+ frame.mTimestamp = buffer->getTimestamp();
+ frame.mFrameMask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC;
+
+ if (mRecording)
+ {
+ frame.mFrameMask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC;
+ mFramesWithEncoder++;
+ }
+
+ int ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
+ } else {
+ ret = sendFrameToSubscribers(&frame);
+ }
+ //debugShowFPS();
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t V4LCameraAdapter::returnBufferToV4L(int id) {
+ status_t ret = NO_ERROR;
+ v4l2_buffer buf;
+ buf.index = id;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("VIDIOC_QBUF Failed 0x%x", ret);
+ return FAILED_TRANSACTION;
+ }
+
+ return NO_ERROR;
+}
+
+int V4LCameraAdapter::previewThread()
+{
+ status_t ret = NO_ERROR;
+ int width, height;
+ CameraFrame frame;
+ void *y_uv[2];
+ int index = 0;
+ int filledLen = 0;
+ int stride = 4096;
+ char *fp = NULL;
+
+ mParams.getPreviewSize(&width, &height);
+
+ {
+ android::AutoMutex lock(mLock);
+ if (!mPreviewing) {
+ //If stop preview is called - it can now go on.
+ android::AutoMutex stopLock(mStopLock);
+ mStopCondition.signal();
+ return ret;
+ }
+ }
+
+ {
+ android::Mutex::Autolock lock(mSubscriberLock);
+ if ( mFrameSubscribers.size() == 0 ) {
+ return BAD_VALUE;
+ }
+ }
+
+ if (isNeedToUseDecoder()){
+
+ CAMHAL_LOGV("########### Decoder ###########");
+ int inIndex = -1, outIndex = -1;
+
+ if (GetFrame(index, filledLen) != NULL) {
+ CAMHAL_LOGD("Dequeued buffer from V4L with ID=%d", index);
+ mDecoder->queueInputBuffer(index);
+ }
+
+ while (NO_ERROR == mDecoder->dequeueInputBuffer(inIndex)) {
+ returnBufferToV4L(inIndex);
+ }
+
+ while (NO_ERROR == mDecoder->dequeueOutputBuffer(outIndex)) {
+ returnOutputBuffer(outIndex);
+ }
+
+ CAMHAL_LOGV("########### End Decode ###########");
+ goto EXIT;
+ }
+ else
+ {
+ fp = GetFrame(index, filledLen);
+
+ if(!fp) {
+ ret = BAD_VALUE;
+ goto EXIT;
+ }
+ CAMHAL_LOGD("GOT IN frame with ID=%d",index);
+
+ CameraBuffer *buffer = mPreviewBufs[index];
+ if (mPixelFormat == V4L2_PIX_FMT_YUYV) {
+ convertYUV422ToNV12Tiler(reinterpret_cast<unsigned char*>(fp), reinterpret_cast<unsigned char*>(buffer->mapped), width, height);
+ }
+ CAMHAL_LOGVB("##...index= %d.;camera buffer= 0x%x; mapped= 0x%x.",index, buffer, buffer->mapped);
+
+#ifdef SAVE_RAW_FRAMES
+ unsigned char* nv12_buff = (unsigned char*) malloc(width*height*3/2);
+ //Convert yuv422i to yuv420sp(NV12) & dump the frame to a file
+ convertYUV422ToNV12 ( (unsigned char*)fp, nv12_buff, width, height);
+ saveFile( nv12_buff, ((width*height)*3/2) );
+ free (nv12_buff);
+#endif
+
+ android::Mutex::Autolock lock(mSubscriberLock);
+
+ frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
+ frame.mBuffer = buffer;
+ frame.mLength = width*height*3/2;
+ frame.mAlignment = stride;
+ frame.mOffset = 0;
+ frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ frame.mFrameMask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC;
+
+ if (mRecording)
+ {
+ frame.mFrameMask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC;
+ mFramesWithEncoder++;
+ }
+
+ ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);
+ if (ret != NO_ERROR) {
+ CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
+ } else {
+ ret = sendFrameToSubscribers(&frame);
+ }
+ }
+
+EXIT:
+
+ return ret;
+}
+
+//scan for video devices
+void detectVideoDevice(char** video_device_list, int& num_device) {
+ char dir_path[20];
+ char* filename;
+ char** dev_list = video_device_list;
+ DIR *d;
+ struct dirent *dir;
+ int index = 0;
+
+ strcpy(dir_path, DEVICE_PATH);
+ d = opendir(dir_path);
+ if(d) {
+ //read each entry in the /dev/ and find if there is videox entry.
+ while ((dir = readdir(d)) != NULL) {
+ filename = dir->d_name;
+ if (strncmp(filename, DEVICE_NAME, 5) == 0) {
+ strcpy(dev_list[index],DEVICE_PATH);
+ strncat(dev_list[index],filename,sizeof(DEVICE_NAME));
+ index++;
+ }
+ } //end of while()
+ closedir(d);
+ num_device = index;
+
+ for(int i=0; i<index; i++){
+ CAMHAL_LOGDB("Video device list::dev_list[%d]= %s",i,dev_list[i]);
+ }
+ }
+}
+
+extern "C" CameraAdapter* V4LCameraAdapter_Factory(size_t sensor_index, CameraHal* hal)
+{
+ CameraAdapter *adapter = NULL;
+ android::AutoMutex lock(gV4LAdapterLock);
+
+ LOG_FUNCTION_NAME;
+
+ adapter = new V4LCameraAdapter(sensor_index, hal);
+ if ( adapter ) {
+ CAMHAL_LOGDB("New V4L Camera adapter instance created for sensor %d",sensor_index);
+ } else {
+ CAMHAL_LOGEA("V4L Camera adapter create failed for sensor index = %d!",sensor_index);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return adapter;
+}
+
+extern "C" status_t V4LCameraAdapter_Capabilities(
+ CameraProperties::Properties * const properties_array,
+ const int starting_camera, const int max_camera, int & supportedCameras)
+{
+ status_t ret = NO_ERROR;
+ struct v4l2_capability cap;
+ int tempHandle = NULL;
+ int num_cameras_supported = 0;
+ char device_list[5][15];
+ char* video_device_list[5];
+ int num_v4l_devices = 0;
+ int sensorId = 0;
+ CameraProperties::Properties* properties = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ supportedCameras = 0;
+ memset((void*)&cap, 0, sizeof(v4l2_capability));
+
+ if (!properties_array) {
+ CAMHAL_LOGEB("invalid param: properties = 0x%p", properties_array);
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ for (int i = 0; i < 5; i++) {
+ video_device_list[i] = device_list[i];
+ }
+ //look for the connected video devices
+ detectVideoDevice(video_device_list, num_v4l_devices);
+
+ for (int i = 0; i < num_v4l_devices; i++) {
+ if ( (starting_camera + num_cameras_supported) < max_camera) {
+ sensorId = starting_camera + num_cameras_supported;
+
+ CAMHAL_LOGDB("Opening device[%d] = %s..",i, video_device_list[i]);
+ if ((tempHandle = open(video_device_list[i], O_RDWR)) == -1) {
+ CAMHAL_LOGEB("Error while opening handle to V4L2 Camera(%s): %s",video_device_list[i], strerror(errno));
+ continue;
+ }
+
+ ret = ioctl (tempHandle, VIDIOC_QUERYCAP, &cap);
+ if (ret < 0) {
+ CAMHAL_LOGEA("Error when querying the capabilities of the V4L Camera");
+ close(tempHandle);
+ continue;
+ }
+
+ //check for video capture devices
+ if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
+ CAMHAL_LOGEA("Error while adapter initialization: video capture not supported.");
+ close(tempHandle);
+ continue;
+ }
+
+ strcpy(device, video_device_list[i]);
+ properties = properties_array + starting_camera + num_cameras_supported;
+
+ //fetch capabilities for this camera
+ ret = V4LCameraAdapter::getCaps( sensorId, properties, tempHandle );
+ if (ret < 0) {
+ CAMHAL_LOGEA("Error while getting capabilities.");
+ close(tempHandle);
+ continue;
+ }
+
+ num_cameras_supported++;
+
+ }
+ //For now exit this loop once a valid video capture device is found.
+ //TODO: find all V4L capture devices and it capabilities
+ break;
+ }//end of for() loop
+
+ supportedCameras = num_cameras_supported;
+ CAMHAL_LOGDB("Number of V4L cameras detected =%d", num_cameras_supported);
+
+EXIT:
+ LOG_FUNCTION_NAME_EXIT;
+ close(tempHandle);
+ return NO_ERROR;
+}
+
+} // namespace Camera
+} // namespace Ti
+
+
+/*--------------------Camera Adapter Class ENDS here-----------------------------*/
+
diff --git a/camera/V4LCameraAdapter/V4LCapabilities.cpp b/camera/V4LCameraAdapter/V4LCapabilities.cpp
new file mode 100644
index 0000000..f03ba9b
--- /dev/null
+++ b/camera/V4LCameraAdapter/V4LCapabilities.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file V4LCapabilities.cpp
+*
+* This file implements the V4L Capabilities feature.
+*
+*/
+
+#include "CameraHal.h"
+#include "V4LCameraAdapter.h"
+#include "ErrorUtils.h"
+#include "TICameraParameters.h"
+
+namespace Ti {
+namespace Camera {
+
+/************************************
+ * global constants and variables
+ *************************************/
+
+#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
+#define MAX_RES_STRING_LENGTH 10
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 480
+
+static const char PARAM_SEP[] = ",";
+
+//Camera defaults
+const char V4LCameraAdapter::DEFAULT_PICTURE_FORMAT[] = "jpeg";
+const char V4LCameraAdapter::DEFAULT_PICTURE_SIZE[] = "640x480";
+const char V4LCameraAdapter::DEFAULT_PREVIEW_FORMAT[] = "yuv420sp";
+const char V4LCameraAdapter::DEFAULT_PREVIEW_SIZE[] = "640x480";
+const char V4LCameraAdapter::DEFAULT_NUM_PREV_BUFS[] = "6";
+const char V4LCameraAdapter::DEFAULT_FRAMERATE[] = "30";
+const char V4LCameraAdapter::DEFAULT_FOCUS_MODE[] = "infinity";
+const char V4LCameraAdapter::DEFAULT_FRAMERATE_RANGE[] = "30000,30000";
+const char * V4LCameraAdapter::DEFAULT_VSTAB = android::CameraParameters::FALSE;
+const char * V4LCameraAdapter::DEFAULT_VNF = android::CameraParameters::FALSE;
+
+
+const CapPixelformat V4LCameraAdapter::mPixelformats [] = {
+ { V4L2_PIX_FMT_YUYV, android::CameraParameters::PIXEL_FORMAT_YUV422I },
+ { V4L2_PIX_FMT_JPEG, android::CameraParameters::PIXEL_FORMAT_JPEG },
+};
+
+/*****************************************
+ * internal static function declarations
+ *****************************************/
+
+/**** Utility functions to help translate V4L Caps to Parameter ****/
+
+status_t V4LCameraAdapter::insertDefaults(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ params->set(CameraProperties::PREVIEW_FORMAT, DEFAULT_PREVIEW_FORMAT);
+
+ params->set(CameraProperties::PICTURE_FORMAT, DEFAULT_PICTURE_FORMAT);
+ params->set(CameraProperties::PICTURE_SIZE, DEFAULT_PICTURE_SIZE);
+ params->set(CameraProperties::PREVIEW_SIZE, DEFAULT_PREVIEW_SIZE);
+ params->set(CameraProperties::PREVIEW_FRAME_RATE, DEFAULT_FRAMERATE);
+ params->set(CameraProperties::REQUIRED_PREVIEW_BUFS, DEFAULT_NUM_PREV_BUFS);
+ params->set(CameraProperties::FOCUS_MODE, DEFAULT_FOCUS_MODE);
+
+ params->set(CameraProperties::CAMERA_NAME, "USBCAMERA");
+ params->set(CameraProperties::JPEG_THUMBNAIL_SIZE, "320x240");
+ params->set(CameraProperties::JPEG_QUALITY, "90");
+ params->set(CameraProperties::JPEG_THUMBNAIL_QUALITY, "50");
+ params->set(CameraProperties::FRAMERATE_RANGE, DEFAULT_FRAMERATE_RANGE);
+ params->set(CameraProperties::S3D_PRV_FRAME_LAYOUT, "none");
+ params->set(CameraProperties::SUPPORTED_EXPOSURE_MODES, "auto");
+ params->set(CameraProperties::SUPPORTED_ISO_VALUES, "auto");
+ params->set(CameraProperties::SUPPORTED_ANTIBANDING, "auto");
+ params->set(CameraProperties::SUPPORTED_EFFECTS, "none");
+ params->set(CameraProperties::SUPPORTED_IPP_MODES, "ldc-nsf");
+ params->set(CameraProperties::FACING_INDEX, TICameraParameters::FACING_FRONT);
+ params->set(CameraProperties::ORIENTATION_INDEX, 0);
+ params->set(CameraProperties::SENSOR_ORIENTATION, "0");
+ params->set(CameraProperties::VSTAB, DEFAULT_VSTAB);
+ params->set(CameraProperties::VNF, DEFAULT_VNF);
+
+ //For compatibility
+ params->set(CameraProperties::SUPPORTED_ZOOM_RATIOS,"0");
+ params->set(CameraProperties::SUPPORTED_ZOOM_STAGES, "0");
+ params->set(CameraProperties::ZOOM, "0");
+ params->set(CameraProperties::ZOOM_SUPPORTED, "true");
+
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::insertPreviewFormats(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) {
+
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+ for (int i = 0; i < caps.ulPreviewFormatCount; i++) {
+ for (unsigned int j = 0; j < ARRAY_SIZE(mPixelformats); j++) {
+ if(caps.ePreviewFormats[i] == mPixelformats[j].pixelformat ) {
+ strncat (supported, mPixelformats[j].param, MAX_PROP_VALUE_LENGTH-1 );
+ strncat (supported, PARAM_SEP, 1 );
+ }
+ }
+ }
+ strncat(supported, android::CameraParameters::PIXEL_FORMAT_YUV420P, MAX_PROP_VALUE_LENGTH - 1);
+ strncat (supported, PARAM_SEP, 1 );
+ strncat(supported, android::CameraParameters::PIXEL_FORMAT_YUV420SP, MAX_PROP_VALUE_LENGTH - 1);
+ params->set(CameraProperties::SUPPORTED_PREVIEW_FORMATS, supported);
+ return NO_ERROR;
+}
+
+status_t V4LCameraAdapter::insertPreviewSizes(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) {
+
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+ for (int i = 0; i < caps.ulPreviewResCount; i++) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat (supported, caps.tPreviewRes[i].param, MAX_PROP_VALUE_LENGTH-1 );
+ }
+
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, supported);
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES, supported);
+ return NO_ERROR;
+}
+
+status_t V4LCameraAdapter::insertImageSizes(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) {
+
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+ for (int i = 0; i < caps.ulCaptureResCount; i++) {
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat (supported, caps.tCaptureRes[i].param, MAX_PROP_VALUE_LENGTH-1 );
+ }
+ params->set(CameraProperties::SUPPORTED_PICTURE_SIZES, supported);
+ return NO_ERROR;
+}
+
+status_t V4LCameraAdapter::insertFrameRates(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) {
+
+ char supported[MAX_PROP_VALUE_LENGTH];
+ char temp[MAX_PROP_VALUE_LENGTH];
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+ for (int i = 0; i < caps.ulFrameRateCount; i++) {
+ snprintf (temp, sizeof(temp) - 1, "%d", caps.ulFrameRates[i] );
+ if (supported[0] != '\0') {
+ strncat(supported, PARAM_SEP, 1);
+ }
+ strncat (supported, temp, MAX_PROP_VALUE_LENGTH-1 );
+ }
+
+ params->set(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES, supported);
+
+ memset(supported, 0, sizeof(supported));
+
+ for (int i = caps.ulFrameRateCount - 1; i >= 0 ; i--) {
+ if ( supported[0] ) strncat(supported, PARAM_SEP, 1);
+ snprintf(temp, sizeof(temp) - 1, "(%d,%d)", caps.ulFrameRates[i] * CameraHal::VFR_SCALE, caps.ulFrameRates[i] * CameraHal::VFR_SCALE);
+ strcat(supported, temp);
+ }
+
+ params->set(CameraProperties::FRAMERATE_RANGE_SUPPORTED, supported);
+
+ return NO_ERROR;
+}
+
+status_t V4LCameraAdapter::insertCapabilities(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret ) {
+ ret = insertPreviewFormats(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertImageSizes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertPreviewSizes(params, caps);
+ }
+
+ if ( NO_ERROR == ret ) {
+ ret = insertFrameRates(params, caps);
+ }
+
+ //Insert Supported Focus modes.
+ params->set(CameraProperties::SUPPORTED_FOCUS_MODES, "infinity");
+
+ params->set(CameraProperties::SUPPORTED_PICTURE_FORMATS, "jpeg");
+
+ if ( NO_ERROR == ret ) {
+ ret = insertDefaults(params, caps);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::sortAscend(V4L_TI_CAPTYPE &caps, uint16_t count) {
+ size_t tempRes;
+ size_t w, h, tmpW,tmpH;
+ for (int i=0; i<count; i++) {
+ w = caps.tPreviewRes[i].width;
+ h = caps.tPreviewRes[i].height;
+ tempRes = w*h;
+ for (int j=i+1; j<count; j++) {
+ tmpW = caps.tPreviewRes[j].width;
+ tmpH = caps.tPreviewRes[j].height;
+
+ if (tempRes > (tmpW * tmpH) ) {
+ caps.tPreviewRes[j].width = w;
+ caps.tPreviewRes[j].height = h;
+ w = tmpW;
+ h = tmpH;
+ }
+ }
+ caps.tPreviewRes[i].width = w;
+ caps.tPreviewRes[i].height = h;
+
+ }
+ return NO_ERROR;
+}
+
+/*****************************************
+ * public exposed function declarations
+ *****************************************/
+
+status_t V4LCameraAdapter::getCaps(const int sensorId, CameraProperties::Properties* params,
+ V4L_HANDLETYPE handle) {
+ status_t status = NO_ERROR;
+ V4L_TI_CAPTYPE caps;
+ int i = 0;
+ int j = 0;
+ struct v4l2_fmtdesc fmtDesc;
+ struct v4l2_frmsizeenum frmSizeEnum;
+ struct v4l2_frmivalenum frmIvalEnum;
+
+ //get supported pixel formats
+ for ( i = 0; status == NO_ERROR; i++) {
+ fmtDesc.index = i;
+ fmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ status = ioctl (handle, VIDIOC_ENUM_FMT, &fmtDesc);
+ if (status == NO_ERROR) {
+ CAMHAL_LOGDB("fmtDesc[%d].description::pixelformat::flags== (%s::%d::%d)",i, fmtDesc.description,fmtDesc.pixelformat,fmtDesc.flags);
+ caps.ePreviewFormats[i] = fmtDesc.pixelformat;
+ }
+ }
+ caps.ulPreviewFormatCount = i;
+
+ //get preview sizes & capture image sizes
+ status = NO_ERROR;
+ for ( i = 0; status == NO_ERROR; i++) {
+ frmSizeEnum.index = i;
+ //Check for frame sizes for default pixel format
+ //TODO: Check for frame sizes for all supported pixel formats
+ frmSizeEnum.pixel_format = DEFAULT_PIXEL_FORMAT;
+ status = ioctl (handle, VIDIOC_ENUM_FRAMESIZES, &frmSizeEnum);
+ if(frmSizeEnum.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
+ break;
+ }
+ if (status == NO_ERROR) {
+ CAMHAL_LOGDB("frmSizeEnum.index[%d].width x height == (%d x %d)", i, frmSizeEnum.discrete.width, frmSizeEnum.discrete.height);
+ caps.tPreviewRes[i].width = frmSizeEnum.discrete.width;
+ caps.tPreviewRes[i].height = frmSizeEnum.discrete.height;
+ snprintf(caps.tPreviewRes[i].param, MAX_RES_STRING_LENGTH,"%dx%d",frmSizeEnum.discrete.width,frmSizeEnum.discrete.height);
+
+ caps.tCaptureRes[i].width = frmSizeEnum.discrete.width;
+ caps.tCaptureRes[i].height = frmSizeEnum.discrete.height;
+ snprintf(caps.tCaptureRes[i].param, MAX_RES_STRING_LENGTH,"%dx%d",frmSizeEnum.discrete.width,frmSizeEnum.discrete.height);
+ }
+ else {
+ caps.ulCaptureResCount = i;
+ caps.ulPreviewResCount = i;
+ }
+ }
+ if(frmSizeEnum.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
+ CAMHAL_LOGDB("\nmin_width x height = %d x %d ",frmSizeEnum.stepwise.min_width, frmSizeEnum.stepwise.min_height);
+ CAMHAL_LOGDB("\nmax_width x height = %d x %d ",frmSizeEnum.stepwise.max_width, frmSizeEnum.stepwise.max_height);
+ CAMHAL_LOGDB("\nstep width x height = %d x %d ",frmSizeEnum.stepwise.step_width,frmSizeEnum.stepwise.step_height);
+ //TODO: populate the sizes when type = V4L2_FRMSIZE_TYPE_STEPWISE
+ }
+
+ //sort the preview sizes in ascending order
+ sortAscend(caps, caps.ulPreviewResCount);
+
+ //get supported frame rates
+ bool fps30 = false;
+ for ( j=caps.ulPreviewResCount-1; j >= 0; j--) {
+ CAMHAL_LOGDB(" W x H = %d x %d", caps.tPreviewRes[j].width, caps.tPreviewRes[j].height);
+ status = NO_ERROR;
+ for ( i = 0; status == NO_ERROR; i++) {
+ frmIvalEnum.index = i;
+ //Check for supported frame rates for the default pixel format.
+ frmIvalEnum.pixel_format = DEFAULT_PIXEL_FORMAT;
+ frmIvalEnum.width = caps.tPreviewRes[j].width;
+ frmIvalEnum.height = caps.tPreviewRes[j].height;
+
+ status = ioctl (handle, VIDIOC_ENUM_FRAMEINTERVALS, &frmIvalEnum);
+ if(frmIvalEnum.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
+ break;
+ }
+ if (status == NO_ERROR) {
+ CAMHAL_LOGDB("frmIvalEnum[%d].frame rate= %d)",i, (frmIvalEnum.discrete.denominator/frmIvalEnum.discrete.numerator));
+ caps.ulFrameRates[i] = (frmIvalEnum.discrete.denominator/frmIvalEnum.discrete.numerator);
+ if (caps.ulFrameRates[i] == 30) {
+ fps30 = true;
+ }
+ }
+ else {
+ caps.ulFrameRateCount = i;
+ }
+ }
+ if(fps30) {
+ break;
+ }
+ }
+
+ if(frmIvalEnum.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
+ //TODO: populate the frame rates when type = V4L2_FRMIVAL_TYPE_STEPWISE;
+ }
+
+ //update the preview resolution with the highest resolution which supports 30fps.
+/* // for video preview the application choose the resolution from the mediaprofiles.xml.
+ // so populating all supported preview resolution is required for video mode.
+ caps.tPreviewRes[0].width = caps.tPreviewRes[j].width;
+ caps.tPreviewRes[0].height = caps.tPreviewRes[j].height;
+ snprintf(caps.tPreviewRes[0].param, MAX_RES_STRING_LENGTH,"%dx%d",caps.tPreviewRes[j].width,caps.tPreviewRes[j].height);
+ caps.ulPreviewResCount = 1;
+*/
+ insertCapabilities (params, caps);
+ return NO_ERROR;
+}
+
+
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/android-api.mk b/camera/android-api.mk
new file mode 100644
index 0000000..da3f56e
--- /dev/null
+++ b/camera/android-api.mk
@@ -0,0 +1,39 @@
+
+# Makefile variables and C/C++ macros to recognize API level
+ANDROID_API_LP_OR_LATER :=
+ANDROID_API_KK_OR_LATER :=
+ANDROID_API_JB_MR1_OR_LATER :=
+ANDROID_API_JB_OR_LATER :=
+ANDROID_API_ICS_OR_LATER :=
+ANDROID_API_CFLAGS :=
+
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 20 || echo 1),)
+ ANDROID_API_LP_OR_LATER := true
+ ANDROID_API_CFLAGS += -DANDROID_API_LP_OR_LATER
+endif
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 19 || echo 1),)
+ ANDROID_API_KK_OR_LATER := true
+ ANDROID_API_CFLAGS += -DANDROID_API_KK_OR_LATER
+endif
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 17 || echo 1),)
+ ANDROID_API_JB_MR1_OR_LATER := true
+ ANDROID_API_CFLAGS += -DANDROID_API_JB_MR1_OR_LATER
+endif
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 16 || echo 1),)
+ ANDROID_API_JB_OR_LATER := true
+ ANDROID_API_CFLAGS += -DANDROID_API_JB_OR_LATER
+endif
+ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 14 || echo 1),)
+ ANDROID_API_ICS_OR_LATER := true
+ ANDROID_API_CFLAGS += -DANDROID_API_ICS_OR_LATER
+endif
+
+define clear-android-api-vars
+$(eval ANDROID_API_LP_OR_LATER:=) \
+$(eval ANDROID_API_KK_OR_LATER:=) \
+$(eval ANDROID_API_JB_MR1_OR_LATER:=) \
+$(eval ANDROID_API_JB_OR_LATER:=) \
+$(eval ANDROID_API_ICS_OR_LATER:=) \
+$(eval ANDROID_API_CFLAGS:=) \
+$(eval clear-android-api-vars:=)
+endef
diff --git a/camera/inc/ANativeWindowDisplayAdapter.h b/camera/inc/ANativeWindowDisplayAdapter.h
new file mode 100644
index 0000000..eba91bb
--- /dev/null
+++ b/camera/inc/ANativeWindowDisplayAdapter.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#include "CameraHal.h"
+#include <ui/GraphicBufferMapper.h>
+#include <hal_public.h>
+
+namespace Ti {
+namespace Camera {
+
+/**
+ * Display handler class - This class basically handles the buffer posting to display
+ */
+
+class ANativeWindowDisplayAdapter : public DisplayAdapter
+{
+public:
+
+ typedef struct
+ {
+ CameraBuffer *mBuffer;
+ void *mUser;
+ int mOffset;
+ int mWidth;
+ int mHeight;
+ int mWidthStride;
+ int mHeightStride;
+ int mLength;
+ CameraFrame::FrameType mType;
+ } DisplayFrame;
+
+ enum DisplayStates
+ {
+ DISPLAY_INIT = 0,
+ DISPLAY_STARTED,
+ DISPLAY_STOPPED,
+ DISPLAY_EXITED
+ };
+
+public:
+
+ ANativeWindowDisplayAdapter();
+ virtual ~ANativeWindowDisplayAdapter();
+
+ ///Initializes the display adapter creates any resources required
+ virtual status_t initialize();
+
+ virtual int setPreviewWindow(struct preview_stream_ops *window);
+ virtual int setFrameProvider(FrameNotifier *frameProvider);
+ virtual int setErrorHandler(ErrorNotifier *errorNotifier);
+ virtual int enableDisplay(int width, int height, struct timeval *refTime = NULL);
+ virtual int disableDisplay(bool cancel_buffer = true);
+ virtual status_t pauseDisplay(bool pause);
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ //Used for shot to snapshot measurement
+ virtual status_t setSnapshotTimeRef(struct timeval *refTime = NULL);
+
+#endif
+
+ virtual bool supportsExternalBuffering();
+
+ //Implementation of inherited interfaces
+ virtual CameraBuffer * allocateBufferList(int width, int height, const char* format, int &bytes, int numBufs);
+ virtual CameraBuffer *getBufferList(int *numBufs);
+ virtual uint32_t * getOffsets() ;
+ virtual int getFd() ;
+ virtual int freeBufferList(CameraBuffer * buflist);
+
+ virtual status_t maxQueueableBuffers(unsigned int& queueable);
+ virtual status_t minUndequeueableBuffers(int& unqueueable);
+
+ // If set to true ANativeWindowDisplayAdapter will not lock/unlock graphic buffers
+ void setExternalLocking(bool extBuffLocking);
+
+ ///Class specific functions
+ static void frameCallbackRelay(CameraFrame* caFrame);
+ void frameCallback(CameraFrame* caFrame);
+
+ void displayThread();
+
+ private:
+ void destroy();
+ bool processHalMsg();
+ status_t PostFrame(ANativeWindowDisplayAdapter::DisplayFrame &dispFrame);
+ bool handleFrameReturn();
+ status_t returnBuffersToWindow();
+
+public:
+
+ static const int DISPLAY_TIMEOUT;
+ static const int FAILED_DQS_TO_SUSPEND;
+
+ class DisplayThread : public android::Thread
+ {
+ ANativeWindowDisplayAdapter* mDisplayAdapter;
+ Utils::MessageQueue mDisplayThreadQ;
+
+ public:
+ DisplayThread(ANativeWindowDisplayAdapter* da)
+ : Thread(false), mDisplayAdapter(da) { }
+
+ ///Returns a reference to the display message Q for display adapter to post messages
+ Utils::MessageQueue& msgQ()
+ {
+ return mDisplayThreadQ;
+ }
+
+ virtual bool threadLoop()
+ {
+ mDisplayAdapter->displayThread();
+ return false;
+ }
+
+ enum DisplayThreadCommands
+ {
+ DISPLAY_START,
+ DISPLAY_STOP,
+ DISPLAY_FRAME,
+ DISPLAY_EXIT
+ };
+ };
+
+ //friend declarations
+friend class DisplayThread;
+
+private:
+ int postBuffer(void* displayBuf);
+
+private:
+ bool mFirstInit;
+ bool mSuspend;
+ int mFailedDQs;
+ bool mPaused; //Pause state
+ preview_stream_ops_t* mANativeWindow;
+ android::sp<DisplayThread> mDisplayThread;
+ FrameProvider *mFrameProvider; ///Pointer to the frame provider interface
+ Utils::MessageQueue mDisplayQ;
+ unsigned int mDisplayState;
+ ///@todo Have a common class for these members
+ mutable android::Mutex mLock;
+ bool mDisplayEnabled;
+ int mBufferCount;
+ CameraBuffer *mBuffers;
+ //buffer_handle_t** mBufferHandleMap; // -> frames[i].BufferHandle
+ //IMG_native_handle_t** mGrallocHandleMap; // -> frames[i].GrallocHandle
+ uint32_t* mOffsetsMap; // -> frames[i].Offset
+ int mFD;
+ android::KeyedVector<buffer_handle_t *, int> mFramesWithCameraAdapterMap;
+ android::KeyedVector<int, int> mFramesType;
+ android::sp<ErrorNotifier> mErrorNotifier;
+
+ uint32_t mFrameWidth;
+ uint32_t mFrameHeight;
+ uint32_t mPreviewWidth;
+ uint32_t mPreviewHeight;
+
+ uint32_t mXOff;
+ uint32_t mYOff;
+
+ const char *mPixelFormat;
+
+ //In case if we ,as example, using out buffers in Ducati Decoder
+ //DOMX will handle lock/unlock of graphic buffers
+ bool mUseExternalBufferLocking;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ //Used for calculating standby to first shot
+ struct timeval mStandbyToShot;
+ bool mMeasureStandby;
+ //Used for shot to snapshot/shot calculation
+ struct timeval mStartCapture;
+ bool mShotToShot;
+
+#endif
+
+};
+
+} // namespace Camera
+} // namespace Ti
diff --git a/camera/inc/BaseCameraAdapter.h b/camera/inc/BaseCameraAdapter.h
new file mode 100644
index 0000000..ffe0492
--- /dev/null
+++ b/camera/inc/BaseCameraAdapter.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#ifndef BASE_CAMERA_ADAPTER_H
+#define BASE_CAMERA_ADAPTER_H
+
+#include "CameraHal.h"
+
+namespace Ti {
+namespace Camera {
+
+struct LUT {
+ const char * userDefinition;
+ int halDefinition;
+};
+
+struct LUTtypeHAL{
+ int size;
+ const LUT *Table;
+};
+
+class BaseCameraAdapter : public CameraAdapter
+{
+
+public:
+
+ BaseCameraAdapter();
+ virtual ~BaseCameraAdapter();
+
+ ///Initialzes the camera adapter creates any resources required
+ virtual status_t initialize(CameraProperties::Properties*) = 0;
+
+ virtual int setErrorHandler(ErrorNotifier *errorNotifier);
+
+ //Message/Frame notification APIs
+ virtual void enableMsgType(int32_t msgs, frame_callback callback=NULL, event_callback eventCb=NULL, void* cookie=NULL);
+ virtual void disableMsgType(int32_t msgs, void* cookie);
+ virtual void returnFrame(CameraBuffer * frameBuf, CameraFrame::FrameType frameType);
+ virtual void addFramePointers(CameraBuffer *frameBuf, void *y_uv);
+ virtual void removeFramePointers();
+
+ //APIs to configure Camera adapter and get the current parameter set
+ virtual status_t setParameters(const android::CameraParameters& params) = 0;
+ virtual void getParameters(android::CameraParameters& params) = 0;
+
+ //API to send a command to the camera
+ virtual status_t sendCommand(CameraCommands operation, int value1 = 0, int value2 = 0, int value3 = 0, int value4 = 0 );
+
+ virtual status_t registerImageReleaseCallback(release_image_buffers_callback callback, void *user_data);
+
+ virtual status_t registerEndCaptureCallback(end_image_capture_callback callback, void *user_data);
+
+ //Retrieves the current Adapter state
+ virtual AdapterState getState();
+ //Retrieves the next Adapter state
+ virtual AdapterState getNextState();
+
+ virtual status_t setSharedAllocator(camera_request_memory shmem_alloc) { mSharedAllocator = shmem_alloc; return NO_ERROR; };
+
+ // Rolls the state machine back to INTIALIZED_STATE from the current state
+ virtual status_t rollbackToInitializedState();
+
+protected:
+ //The first two methods will try to switch the adapter state.
+ //Every call to setState() should be followed by a corresponding
+ //call to commitState(). If the state switch fails, then it will
+ //get reset to the previous state via rollbackState().
+ virtual status_t setState(CameraCommands operation);
+ virtual status_t commitState();
+ virtual status_t rollbackState();
+
+ // Retrieves the current Adapter state - for internal use (not locked)
+ virtual status_t getState(AdapterState &state);
+ // Retrieves the next Adapter state - for internal use (not locked)
+ virtual status_t getNextState(AdapterState &state);
+
+ //-----------Interface that needs to be implemented by deriving classes --------------------
+
+ //Should be implmented by deriving classes in order to start image capture
+ virtual status_t takePicture();
+
+ //Should be implmented by deriving classes in order to start image capture
+ virtual status_t stopImageCapture();
+
+ //Should be implmented by deriving classes in order to start temporal bracketing
+ virtual status_t startBracketing(int range);
+
+ //Should be implemented by deriving classes in order to stop temporal bracketing
+ virtual status_t stopBracketing();
+
+ //Should be implemented by deriving classes in oder to initiate autoFocus
+ virtual status_t autoFocus();
+
+ //Should be implemented by deriving classes in oder to initiate autoFocus
+ virtual status_t cancelAutoFocus();
+
+ //Should be called by deriving classes in order to do some bookkeeping
+ virtual status_t startVideoCapture();
+
+ //Should be called by deriving classes in order to do some bookkeeping
+ virtual status_t stopVideoCapture();
+
+ //Should be implemented by deriving classes in order to start camera preview
+ virtual status_t startPreview();
+
+ //Should be implemented by deriving classes in order to stop camera preview
+ virtual status_t stopPreview();
+
+ //Should be implemented by deriving classes in order to start smooth zoom
+ virtual status_t startSmoothZoom(int targetIdx);
+
+ //Should be implemented by deriving classes in order to stop smooth zoom
+ virtual status_t stopSmoothZoom();
+
+ //Should be implemented by deriving classes in order to stop smooth zoom
+ virtual status_t useBuffers(CameraMode mode, CameraBuffer* bufArr, int num, size_t length, unsigned int queueable);
+
+ //Should be implemented by deriving classes in order queue a released buffer in CameraAdapter
+ virtual status_t fillThisBuffer(CameraBuffer* frameBuf, CameraFrame::FrameType frameType);
+
+ //API to get the frame size required to be allocated. This size is used to override the size passed
+ //by camera service when VSTAB/VNF is turned ON for example
+ virtual status_t getFrameSize(size_t &width, size_t &height);
+
+ //API to get required data frame size
+ virtual status_t getFrameDataSize(size_t &dataFrameSize, size_t bufferCount);
+
+ //API to get required picture buffers size with the current configuration in CameraParameters
+ virtual status_t getPictureBufferSize(CameraFrame &frame, size_t bufferCount);
+
+ // Should be implemented by deriving classes in order to start face detection
+ // ( if supported )
+ virtual status_t startFaceDetection();
+
+ // Should be implemented by deriving classes in order to stop face detection
+ // ( if supported )
+ virtual status_t stopFaceDetection();
+
+ virtual status_t switchToExecuting();
+
+ virtual status_t setupTunnel(uint32_t SliceHeight, uint32_t EncoderHandle, uint32_t width, uint32_t height);
+
+ virtual status_t destroyTunnel();
+
+ virtual status_t cameraPreviewInitialization();
+
+ // Receive orientation events from CameraHal
+ virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt);
+
+ // ---------------------Interface ends-----------------------------------
+
+ status_t notifyFocusSubscribers(CameraHalEvent::FocusStatus status);
+ status_t notifyShutterSubscribers();
+ status_t notifyZoomSubscribers(int zoomIdx, bool targetReached);
+ status_t notifyMetadataSubscribers(android::sp<CameraMetadataResult> &meta);
+
+ //Send the frame to subscribers
+ status_t sendFrameToSubscribers(CameraFrame *frame);
+
+ //Resets the refCount for this particular frame
+ status_t resetFrameRefCount(CameraFrame &frame);
+
+ //A couple of helper functions
+ void setFrameRefCountByType(CameraBuffer* frameBuf, CameraFrame::FrameType frameType, int refCount);
+ int getFrameRefCount(CameraBuffer* frameBuf);
+ int getFrameRefCountByType(CameraBuffer* frameBuf, CameraFrame::FrameType frameType);
+ int setInitFrameRefCount(CameraBuffer* buf, unsigned int mask);
+ static const char* getLUTvalue_translateHAL(int Value, LUTtypeHAL LUT);
+
+// private member functions
+private:
+ status_t __sendFrameToSubscribers(CameraFrame* frame,
+ android::KeyedVector<int, frame_callback> *subscribers,
+ CameraFrame::FrameType frameType);
+ status_t rollbackToPreviousState();
+
+// protected data types and variables
+protected:
+ enum FrameState {
+ STOPPED = 0,
+ RUNNING
+ };
+
+ enum FrameCommands {
+ START_PREVIEW = 0,
+ START_RECORDING,
+ RETURN_FRAME,
+ STOP_PREVIEW,
+ STOP_RECORDING,
+ DO_AUTOFOCUS,
+ TAKE_PICTURE,
+ FRAME_EXIT
+ };
+
+ enum AdapterCommands {
+ ACK = 0,
+ ERROR
+ };
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ struct timeval mStartFocus;
+ struct timeval mStartCapture;
+
+#endif
+
+ mutable android::Mutex mReturnFrameLock;
+
+ //Lock protecting the Adapter state
+ mutable android::Mutex mLock;
+ AdapterState mAdapterState;
+ AdapterState mNextState;
+
+ //Different frame subscribers get stored using these
+ android::KeyedVector<int, frame_callback> mFrameSubscribers;
+ android::KeyedVector<int, frame_callback> mSnapshotSubscribers;
+ android::KeyedVector<int, frame_callback> mFrameDataSubscribers;
+ android::KeyedVector<int, frame_callback> mVideoSubscribers;
+ android::KeyedVector<int, frame_callback> mVideoInSubscribers;
+ android::KeyedVector<int, frame_callback> mImageSubscribers;
+ android::KeyedVector<int, frame_callback> mRawSubscribers;
+ android::KeyedVector<int, event_callback> mFocusSubscribers;
+ android::KeyedVector<int, event_callback> mZoomSubscribers;
+ android::KeyedVector<int, event_callback> mShutterSubscribers;
+ android::KeyedVector<int, event_callback> mMetadataSubscribers;
+
+ //Preview buffer management data
+ CameraBuffer *mPreviewBuffers;
+ int mPreviewBufferCount;
+ size_t mPreviewBuffersLength;
+ android::KeyedVector<CameraBuffer *, int> mPreviewBuffersAvailable;
+ mutable android::Mutex mPreviewBufferLock;
+
+ //Snapshot buffer management data
+ android::KeyedVector<CameraBuffer *, int> mSnapshotBuffersAvailable;
+ mutable android::Mutex mSnapshotBufferLock;
+
+ //Video buffer management data
+ CameraBuffer *mVideoBuffers;
+ android::KeyedVector<CameraBuffer *, int> mVideoBuffersAvailable;
+ int mVideoBuffersCount;
+ size_t mVideoBuffersLength;
+ mutable android::Mutex mVideoBufferLock;
+
+ //Image buffer management data
+ CameraBuffer *mCaptureBuffers;
+ android::KeyedVector<CameraBuffer *, int> mCaptureBuffersAvailable;
+ int mCaptureBuffersCount;
+ size_t mCaptureBuffersLength;
+ mutable android::Mutex mCaptureBufferLock;
+
+ //Metadata buffermanagement
+ CameraBuffer *mPreviewDataBuffers;
+ android::KeyedVector<CameraBuffer *, int> mPreviewDataBuffersAvailable;
+ int mPreviewDataBuffersCount;
+ size_t mPreviewDataBuffersLength;
+ mutable android::Mutex mPreviewDataBufferLock;
+
+ //Video input buffer management data (used for reproc pipe)
+ CameraBuffer *mVideoInBuffers;
+ android::KeyedVector<CameraBuffer *, int> mVideoInBuffersAvailable;
+ mutable android::Mutex mVideoInBufferLock;
+
+ Utils::MessageQueue mFrameQ;
+ Utils::MessageQueue mAdapterQ;
+ mutable android::Mutex mSubscriberLock;
+ ErrorNotifier *mErrorNotifier;
+ release_image_buffers_callback mReleaseImageBuffersCallback;
+ end_image_capture_callback mEndImageCaptureCallback;
+ void *mReleaseData;
+ void *mEndCaptureData;
+ bool mRecording;
+
+ camera_request_memory mSharedAllocator;
+
+ uint32_t mFramesWithDucati;
+ uint32_t mFramesWithDisplay;
+ uint32_t mFramesWithEncoder;
+
+#ifdef CAMERAHAL_DEBUG
+ android::Mutex mBuffersWithDucatiLock;
+ android::KeyedVector<int, bool> mBuffersWithDucati;
+#endif
+
+ android::KeyedVector<void *, CameraFrame *> mFrameQueue;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif //BASE_CAMERA_ADAPTER_H
+
+
diff --git a/camera/inc/BufferSourceAdapter.h b/camera/inc/BufferSourceAdapter.h
new file mode 100644
index 0000000..c006b9d
--- /dev/null
+++ b/camera/inc/BufferSourceAdapter.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BUFFER_SOURCE_ADAPTER_H
+#define BUFFER_SOURCE_ADAPTER_H
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+
+#include "CameraHal.h"
+#include <ui/GraphicBufferMapper.h>
+#include <hal_public.h>
+
+namespace Ti {
+namespace Camera {
+
+/**
+ * Handles enqueueing/dequeing buffers to tap-in/tap-out points
+ * TODO(XXX): this class implements DisplayAdapter for now
+ * but this will most likely change once tap-in/tap-out points
+ * are better defined
+ */
+
+class BufferSourceAdapter : public DisplayAdapter
+{
+// private types
+private:
+ ///Constant declarations
+ static const int NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP;
+
+
+ // helper class to return frame in different thread context
+ class ReturnFrame : public android::Thread {
+ public:
+ ReturnFrame(BufferSourceAdapter* __this) : mBufferSourceAdapter(__this) {
+ android::AutoMutex lock(mReturnFrameMutex);
+ mDestroying = false;
+ mFrameCount = 0;
+ }
+
+ ~ReturnFrame() {
+ android::AutoMutex lock(mReturnFrameMutex);
+ }
+
+ void signal() {
+ android::AutoMutex lock(mReturnFrameMutex);
+ mFrameCount++;
+ mReturnFrameCondition.signal();
+ }
+
+ virtual void requestExit() {
+ Thread::requestExit();
+
+ android::AutoMutex lock(mReturnFrameMutex);
+ mDestroying = true;
+ mReturnFrameCondition.signal();
+ }
+
+ virtual bool threadLoop() {
+ android::AutoMutex lock(mReturnFrameMutex);
+ if ( 0 >= mFrameCount ) {
+ mReturnFrameCondition.wait(mReturnFrameMutex);
+ }
+ if (!mDestroying) {
+ mBufferSourceAdapter->handleFrameReturn();
+ mFrameCount--;
+ }
+ return true;
+ }
+
+ private:
+ BufferSourceAdapter* mBufferSourceAdapter;
+ android::Condition mReturnFrameCondition;
+ android::Mutex mReturnFrameMutex;
+ int mFrameCount;
+ bool mDestroying;
+ };
+
+ // helper class to queue frame in different thread context
+ class QueueFrame : public android::Thread {
+ public:
+ QueueFrame(BufferSourceAdapter* __this) : mBufferSourceAdapter(__this) {
+ mDestroying = false;
+ }
+
+ ~QueueFrame() {
+ }
+
+ void addFrame(CameraFrame *frame) {
+ android::AutoMutex lock(mFramesMutex);
+ mFrames.add(new CameraFrame(*frame));
+ mFramesCondition.signal();
+ }
+
+ virtual void requestExit() {
+ Thread::requestExit();
+
+ mDestroying = true;
+
+ android::AutoMutex lock(mFramesMutex);
+ while (!mFrames.empty()) {
+ CameraFrame *frame = mFrames.itemAt(0);
+ mFrames.removeAt(0);
+ frame->mMetaData.clear();
+ delete frame;
+ }
+ mFramesCondition.signal();
+ }
+
+ virtual bool threadLoop() {
+ CameraFrame *frame = NULL;
+ {
+ android::AutoMutex lock(mFramesMutex);
+ while (mFrames.empty() && !mDestroying) mFramesCondition.wait(mFramesMutex);
+ if (!mDestroying) {
+ frame = mFrames.itemAt(0);
+ mFrames.removeAt(0);
+ }
+ }
+
+ if (frame) {
+ mBufferSourceAdapter->handleFrameCallback(frame);
+ frame->mMetaData.clear();
+
+ if (frame->mFrameType != CameraFrame::REPROCESS_INPUT_FRAME) {
+ // signal return frame thread that it can dequeue a buffer now
+ mBufferSourceAdapter->mReturnFrame->signal();
+ }
+
+ delete frame;
+ }
+
+ return true;
+ }
+
+ private:
+ BufferSourceAdapter* mBufferSourceAdapter;
+ android::Vector<CameraFrame *> mFrames;
+ android::Condition mFramesCondition;
+ android::Mutex mFramesMutex;
+ bool mDestroying;
+ };
+
+ enum {
+ BUFFER_SOURCE_TAP_IN,
+ BUFFER_SOURCE_TAP_OUT
+ };
+
+// public member functions
+public:
+ BufferSourceAdapter();
+ virtual ~BufferSourceAdapter();
+
+ virtual status_t initialize();
+ virtual int setPreviewWindow(struct preview_stream_ops *source);
+ virtual int setFrameProvider(FrameNotifier *frameProvider);
+ virtual int setErrorHandler(ErrorNotifier *errorNotifier);
+ virtual int enableDisplay(int width, int height, struct timeval *refTime = NULL);
+ virtual int disableDisplay(bool cancel_buffer = true);
+ virtual status_t pauseDisplay(bool pause);
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ // Not implemented in this class
+ virtual status_t setSnapshotTimeRef(struct timeval *refTime = NULL) { return NO_ERROR; }
+#endif
+ virtual bool supportsExternalBuffering();
+ virtual CameraBuffer * allocateBufferList(int width, int dummyHeight, const char* format, int &bytes, int numBufs);
+ virtual CameraBuffer *getBufferList(int *numBufs);
+ virtual uint32_t * getOffsets() ;
+ virtual int getFd() ;
+ virtual int freeBufferList(CameraBuffer * buflist);
+ virtual int maxQueueableBuffers(unsigned int& queueable);
+ virtual int minUndequeueableBuffers(int& unqueueable);
+ virtual bool match(const char * str);
+
+ virtual CameraBuffer * getBuffers(bool reset = false);
+ virtual unsigned int getSize();
+ virtual int getBufferCount();
+
+ static void frameCallback(CameraFrame* caFrame);
+ void addFrame(CameraFrame* caFrame);
+ void handleFrameCallback(CameraFrame* caFrame);
+ bool handleFrameReturn();
+
+private:
+ void destroy();
+ status_t returnBuffersToWindow();
+
+private:
+ preview_stream_ops_t* mBufferSource;
+ FrameProvider *mFrameProvider; // Pointer to the frame provider interface
+
+ mutable android::Mutex mLock;
+ int mBufferCount;
+ CameraBuffer *mBuffers;
+
+ android::KeyedVector<buffer_handle_t *, int> mFramesWithCameraAdapterMap;
+ android::sp<ErrorNotifier> mErrorNotifier;
+ android::sp<ReturnFrame> mReturnFrame;
+ android::sp<QueueFrame> mQueueFrame;
+
+ uint32_t mFrameWidth;
+ uint32_t mFrameHeight;
+ uint32_t mPreviewWidth;
+ uint32_t mPreviewHeight;
+
+ int mBufferSourceDirection;
+
+ const char *mPixelFormat;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif
+
+#endif
diff --git a/camera/inc/CameraHal.h b/camera/inc/CameraHal.h
new file mode 100644
index 0000000..b6d19b7
--- /dev/null
+++ b/camera/inc/CameraHal.h
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <hardware/camera.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/threads.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <camera/CameraParameters.h>
+#ifdef OMAP_ENHANCEMENT_CPCAM
+#include <camera/CameraMetadata.h>
+#include <camera/ShotParameters.h>
+#endif
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBuffer.h>
+
+/* For IMG_native_handle_t */
+#include <ui/GraphicBufferMapper.h>
+#include <hal_public.h>
+
+#ifdef USE_LIBION_TI
+#include <ion_ti/ion.h>
+#else
+#include <ion/ion.h>
+#endif
+
+#include "Common.h"
+#include "MessageQueue.h"
+#include "Semaphore.h"
+#include "CameraProperties.h"
+#include "SensorListener.h"
+
+//temporarily define format here
+#define HAL_PIXEL_FORMAT_TI_NV12 0x100
+#define HAL_PIXEL_FORMAT_TI_Y8 0x103
+#define HAL_PIXEL_FORMAT_TI_Y16 0x104
+#define HAL_PIXEL_FORMAT_TI_UYVY 0x105
+
+#define MIN_WIDTH 640
+#define MIN_HEIGHT 480
+#define PICTURE_WIDTH 3264 /* 5mp - 2560. 8mp - 3280 */ /* Make sure it is a multiple of 16. */
+#define PICTURE_HEIGHT 2448 /* 5mp - 2048. 8mp - 2464 */ /* Make sure it is a multiple of 16. */
+#define PREVIEW_WIDTH 176
+#define PREVIEW_HEIGHT 144
+#define PIXEL_FORMAT V4L2_PIX_FMT_UYVY
+
+#define VIDEO_FRAME_COUNT_MAX 8 //NUM_OVERLAY_BUFFERS_REQUESTED
+#define MAX_CAMERA_BUFFERS 8 //NUM_OVERLAY_BUFFERS_REQUESTED
+#define MAX_ZOOM 3
+#define THUMB_WIDTH 80
+#define THUMB_HEIGHT 60
+#define PIX_YUV422I 0
+#define PIX_YUV420P 1
+
+#define SATURATION_OFFSET 100
+#define SHARPNESS_OFFSET 100
+#define CONTRAST_OFFSET 100
+
+#ifdef MOTOROLA_CAMERA
+#define DEFAULT_INTENSITY 100
+#define FLASH_VOLTAGE_THRESHOLD1 3700000 // intensity will be reduced to 50% below threshold1
+#define FLASH_VOLTAGE_THRESHOLD2 3300000 // flash disabled below threshold2
+#endif
+
+#define FRAME_RATE_HIGH_HD 60
+
+#define CAMHAL_GRALLOC_USAGE GRALLOC_USAGE_HW_TEXTURE | \
+ GRALLOC_USAGE_HW_RENDER | \
+ GRALLOC_USAGE_SW_READ_RARELY | \
+ GRALLOC_USAGE_SW_WRITE_NEVER
+
+//Enables Absolute PPM measurements in logcat
+#define PPM_INSTRUMENTATION_ABS 1
+
+#define LOCK_BUFFER_TRIES 5
+#define HAL_PIXEL_FORMAT_NV12 0x100
+
+#define OP_STR_SIZE 100
+
+#define NONNEG_ASSIGN(x,y) \
+ if(x > -1) \
+ y = x
+
+#define CAMHAL_SIZE_OF_ARRAY(x) static_cast<int>(sizeof(x)/sizeof(x[0]))
+
+namespace Ti {
+namespace Camera {
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+extern const char * const kRawImagesOutputDirPath;
+extern const char * const kYuvImagesOutputDirPath;
+#endif
+#define V4L_CAMERA_NAME_USB "USBCAMERA"
+#define OMX_CAMERA_NAME_OV "OV5640"
+#define OMX_CAMERA_NAME_SONY "IMX060"
+#ifdef MOTOROLA_CAMERA
+#define OMX_CAMERA_NAME_OV8820 "OV8820"
+#define OMX_CAMERA_NAME_OV7739 "OV7739"
+#define OMX_CAMERA_NAME_MT9M114 "MT9M114"
+#endif
+
+
+///Forward declarations
+class CameraHal;
+class CameraFrame;
+class CameraHalEvent;
+class DisplayFrame;
+
+class FpsRange {
+public:
+ static int compare(const FpsRange * left, const FpsRange * right);
+
+ FpsRange(int min, int max);
+ FpsRange();
+
+ bool operator==(const FpsRange & fpsRange) const;
+
+ bool isNull() const;
+ bool isFixed() const;
+
+ int min() const;
+ int max() const;
+
+private:
+ int mMin;
+ int mMax;
+};
+
+
+inline int FpsRange::compare(const FpsRange * const left, const FpsRange * const right) {
+ if ( left->max() < right->max() ) {
+ return -1;
+ }
+
+ if ( left->max() > right->max() ) {
+ return 1;
+ }
+
+ if ( left->min() < right->min() ) {
+ return -1;
+ }
+
+ if ( left->min() > right->min() ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+inline FpsRange::FpsRange(const int min, const int max) : mMin(min), mMax(max) {}
+
+inline FpsRange::FpsRange() : mMin(-1), mMax(-1) {}
+
+inline bool FpsRange::operator==(const FpsRange & fpsRange) const {
+ return mMin == fpsRange.mMin && mMax == fpsRange.mMax;
+}
+
+inline bool FpsRange::isNull() const {
+ return mMin == -1 || mMax == -1;
+}
+
+inline bool FpsRange::isFixed() const {
+ return mMin == mMax;
+}
+
+inline int FpsRange::min() const { return mMin; }
+
+inline int FpsRange::max() const { return mMax; }
+
+class CameraArea : public android::RefBase
+{
+public:
+
+ CameraArea(ssize_t top,
+ ssize_t left,
+ ssize_t bottom,
+ ssize_t right,
+ size_t weight) : mTop(top),
+ mLeft(left),
+ mBottom(bottom),
+ mRight(right),
+ mWeight(weight) {}
+
+ status_t transfrom(size_t width,
+ size_t height,
+ size_t &top,
+ size_t &left,
+ size_t &areaWidth,
+ size_t &areaHeight);
+
+ bool isValid()
+ {
+ return ( ( 0 != mTop ) || ( 0 != mLeft ) || ( 0 != mBottom ) || ( 0 != mRight) );
+ }
+
+ bool isZeroArea()
+ {
+ return ( (0 == mTop ) && ( 0 == mLeft ) && ( 0 == mBottom )
+ && ( 0 == mRight ) && ( 0 == mWeight ));
+ }
+
+ size_t getWeight()
+ {
+ return mWeight;
+ }
+
+ bool compare(const android::sp<CameraArea> &area);
+
+ static status_t parseAreas(const char *area,
+ size_t areaLength,
+ android::Vector< android::sp<CameraArea> > &areas);
+
+ static status_t checkArea(ssize_t top,
+ ssize_t left,
+ ssize_t bottom,
+ ssize_t right,
+ ssize_t weight);
+
+ static bool areAreasDifferent(android::Vector< android::sp<CameraArea> > &, android::Vector< android::sp<CameraArea> > &);
+
+protected:
+ static const ssize_t TOP = -1000;
+ static const ssize_t LEFT = -1000;
+ static const ssize_t BOTTOM = 1000;
+ static const ssize_t RIGHT = 1000;
+ static const ssize_t WEIGHT_MIN = 1;
+ static const ssize_t WEIGHT_MAX = 1000;
+
+ ssize_t mTop;
+ ssize_t mLeft;
+ ssize_t mBottom;
+ ssize_t mRight;
+ size_t mWeight;
+};
+
+class CameraMetadataResult : public android::RefBase
+{
+public:
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ CameraMetadataResult(camera_memory_t * extMeta) : mExtendedMetadata(extMeta) {
+ mMetadata.faces = NULL;
+ mMetadata.number_of_faces = 0;
+#ifdef OMAP_ENHANCEMENT
+ mMetadata.analog_gain = 0;
+ mMetadata.exposure_time = 0;
+#endif
+ };
+#endif
+
+ CameraMetadataResult() {
+ mMetadata.faces = NULL;
+ mMetadata.number_of_faces = 0;
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ mMetadata.analog_gain = 0;
+ mMetadata.exposure_time = 0;
+#endif
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ mExtendedMetadata = NULL;
+#endif
+ }
+
+ virtual ~CameraMetadataResult() {
+ if ( NULL != mMetadata.faces ) {
+ free(mMetadata.faces);
+ }
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ if ( NULL != mExtendedMetadata ) {
+ mExtendedMetadata->release(mExtendedMetadata);
+ }
+#endif
+ }
+
+ camera_frame_metadata_t *getMetadataResult() { return &mMetadata; };
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ camera_memory_t *getExtendedMetadata() { return mExtendedMetadata; };
+#endif
+
+ static const ssize_t TOP = -1000;
+ static const ssize_t LEFT = -1000;
+ static const ssize_t BOTTOM = 1000;
+ static const ssize_t RIGHT = 1000;
+ static const ssize_t INVALID_DATA = -2000;
+
+private:
+
+ camera_frame_metadata_t mMetadata;
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ camera_memory_t *mExtendedMetadata;
+#endif
+};
+
+typedef enum {
+ CAMERA_BUFFER_NONE = 0,
+ CAMERA_BUFFER_GRALLOC,
+ CAMERA_BUFFER_ANW,
+ CAMERA_BUFFER_MEMORY,
+ CAMERA_BUFFER_ION
+} CameraBufferType;
+
+typedef struct _CameraBuffer {
+ CameraBufferType type;
+ /* opaque is the generic drop-in replacement for the pointers
+ * that were used previously */
+ void *opaque;
+
+ /* opaque has different meanings depending on the buffer type:
+ * GRALLOC - gralloc_handle_t
+ * ANW - a pointer to the buffer_handle_t (which corresponds to
+ * the ANativeWindowBuffer *)
+ * MEMORY - address of allocated memory
+ * ION - address of mapped ion allocation
+ *
+ * FIXME opaque should be split into several fields:
+ * - handle/pointer we got from the allocator
+ * - handle/value we pass to OMX
+ * - pointer to mapped memory (if the buffer is mapped)
+ */
+
+ /* mapped holds ptr to mapped memory in userspace */
+ void *mapped;
+
+ /* These are specific to ION buffers */
+ struct ion_handle * ion_handle;
+ int ion_fd;
+ int fd;
+ size_t size;
+ int index;
+
+ /* These describe the camera buffer */
+ int width;
+ int stride;
+ int height;
+ const char *format;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ struct timeval ppmStamp;
+
+#endif
+
+ /* These are for buffers which include borders */
+ int offset; // where valid data starts
+ int actual_size; // size of the entire buffer with borders
+ int privateData;
+} CameraBuffer;
+
+void * camera_buffer_get_omx_ptr (CameraBuffer *buffer);
+
+class CameraFrame
+{
+ public:
+
+ enum FrameType
+ {
+ PREVIEW_FRAME_SYNC = 0x1, ///SYNC implies that the frame needs to be explicitly returned after consuming in order to be filled by camera again
+ PREVIEW_FRAME = 0x2 , ///Preview frame includes viewfinder and snapshot frames
+ IMAGE_FRAME_SYNC = 0x4, ///Image Frame is the image capture output frame
+ IMAGE_FRAME = 0x8,
+ VIDEO_FRAME_SYNC = 0x10, ///Timestamp will be updated for these frames
+ VIDEO_FRAME = 0x20,
+ FRAME_DATA_SYNC = 0x40, ///Any extra data assosicated with the frame. Always synced with the frame
+ FRAME_DATA= 0x80,
+ RAW_FRAME = 0x100,
+ SNAPSHOT_FRAME = 0x200,
+ REPROCESS_INPUT_FRAME = 0x400,
+ ALL_FRAMES = 0xFFFF ///Maximum of 16 frame types supported
+ };
+
+ enum FrameQuirks
+ {
+ ENCODE_RAW_YUV422I_TO_JPEG = 0x1 << 0,
+ HAS_EXIF_DATA = 0x1 << 1,
+ FORMAT_YUV422I_YUYV = 0x1 << 2,
+ FORMAT_YUV422I_UYVY = 0x1 << 3,
+ };
+
+ //default contrustor
+ CameraFrame():
+ mCookie(NULL),
+ mCookie2(NULL),
+ mBuffer(NULL),
+ mFrameType(0),
+ mTimestamp(0),
+ mWidth(0),
+ mHeight(0),
+ mOffset(0),
+ mAlignment(0),
+ mFd(0),
+ mLength(0),
+ mFrameMask(0),
+ mQuirks(0)
+ {
+ mYuv[0] = 0; // NULL is meant for pointers
+ mYuv[1] = 0; // NULL is meant for pointers
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ mMetaData = 0;
+#endif
+ }
+
+ void *mCookie;
+ void *mCookie2;
+ CameraBuffer *mBuffer;
+ int mFrameType;
+ nsecs_t mTimestamp;
+ unsigned int mWidth, mHeight;
+ uint32_t mOffset;
+ unsigned int mAlignment;
+ int mFd;
+ size_t mLength;
+ unsigned mFrameMask;
+ unsigned int mQuirks;
+ unsigned int mYuv[2];
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ android::sp<CameraMetadataResult> mMetaData;
+#endif
+ ///@todo add other member vars like stride etc
+};
+
+enum CameraHalError
+{
+ CAMERA_ERROR_FATAL = 0x1, //Fatal errors can only be recovered by restarting media server
+ CAMERA_ERROR_HARD = 0x2, // Hard errors are hardware hangs that may be recoverable by resetting the hardware internally within the adapter
+ CAMERA_ERROR_SOFT = 0x4, // Soft errors are non fatal errors that can be recovered from without needing to stop use-case
+};
+
+///Common Camera Hal Event class which is visible to CameraAdapter,DisplayAdapter and AppCallbackNotifier
+///@todo Rename this class to CameraEvent
+class CameraHalEvent
+{
+public:
+ //Enums
+ enum CameraHalEventType {
+ NO_EVENTS = 0x0,
+ EVENT_FOCUS_LOCKED = 0x1,
+ EVENT_FOCUS_ERROR = 0x2,
+ EVENT_ZOOM_INDEX_REACHED = 0x4,
+ EVENT_SHUTTER = 0x8,
+ EVENT_METADATA = 0x10,
+ ///@remarks Future enum related to display, like frame displayed event, could be added here
+ ALL_EVENTS = 0xFFFF ///Maximum of 16 event types supported
+ };
+
+ enum FocusStatus {
+ FOCUS_STATUS_SUCCESS = 0x1,
+ FOCUS_STATUS_FAIL = 0x2,
+ FOCUS_STATUS_PENDING = 0x4,
+ FOCUS_STATUS_DONE = 0x8,
+ };
+
+ ///Class declarations
+ ///@remarks Add a new class for a new event type added above
+
+ //Shutter event specific data
+ typedef struct ShutterEventData_t {
+ bool shutterClosed;
+ }ShutterEventData;
+
+ ///Focus event specific data
+ typedef struct FocusEventData_t {
+ FocusStatus focusStatus;
+ int currentFocusValue;
+ } FocusEventData;
+
+ ///Zoom specific event data
+ typedef struct ZoomEventData_t {
+ int currentZoomIndex;
+ bool targetZoomIndexReached;
+ } ZoomEventData;
+
+ typedef struct FaceData_t {
+ ssize_t top;
+ ssize_t left;
+ ssize_t bottom;
+ ssize_t right;
+ size_t score;
+ } FaceData;
+
+ typedef android::sp<CameraMetadataResult> MetaEventData;
+
+ class CameraHalEventData : public android::RefBase{
+
+ public:
+
+ CameraHalEvent::FocusEventData focusEvent;
+ CameraHalEvent::ZoomEventData zoomEvent;
+ CameraHalEvent::ShutterEventData shutterEvent;
+ CameraHalEvent::MetaEventData metadataEvent;
+ };
+
+ //default contrustor
+ CameraHalEvent():
+ mCookie(NULL),
+ mEventType(NO_EVENTS) {}
+
+ //copy constructor
+ CameraHalEvent(const CameraHalEvent &event) :
+ mCookie(event.mCookie),
+ mEventType(event.mEventType),
+ mEventData(event.mEventData) {};
+
+ void* mCookie;
+ CameraHalEventType mEventType;
+ android::sp<CameraHalEventData> mEventData;
+
+};
+
+/// Have a generic callback class based on template - to adapt CameraFrame and Event
+typedef void (*frame_callback) (CameraFrame *cameraFrame);
+typedef void (*event_callback) (CameraHalEvent *event);
+
+//signals CameraHAL to relase image buffers
+typedef void (*release_image_buffers_callback) (void *userData);
+typedef void (*end_image_capture_callback) (void *userData);
+
+/**
+ * Interface class implemented by classes that have some events to communicate to dependendent classes
+ * Dependent classes use this interface for registering for events
+ */
+class MessageNotifier
+{
+public:
+ static const uint32_t EVENT_BIT_FIELD_POSITION;
+ static const uint32_t FRAME_BIT_FIELD_POSITION;
+
+ ///@remarks Msg type comes from CameraFrame and CameraHalEvent classes
+ /// MSB 16 bits is for events and LSB 16 bits is for frame notifications
+ /// FrameProvider and EventProvider classes act as helpers to event/frame
+ /// consumers to call this api
+ virtual void enableMsgType(int32_t msgs, frame_callback frameCb=NULL, event_callback eventCb=NULL, void* cookie=NULL) = 0;
+ virtual void disableMsgType(int32_t msgs, void* cookie) = 0;
+
+ virtual ~MessageNotifier() {};
+};
+
+class ErrorNotifier : public virtual android::RefBase
+{
+public:
+ virtual void errorNotify(int error) = 0;
+
+ virtual ~ErrorNotifier() {};
+};
+
+
+/**
+ * Interace class abstraction for Camera Adapter to act as a frame provider
+ * This interface is fully implemented by Camera Adapter
+ */
+class FrameNotifier : public MessageNotifier
+{
+public:
+ virtual void returnFrame(CameraBuffer* frameBuf, CameraFrame::FrameType frameType) = 0;
+ virtual void addFramePointers(CameraBuffer *frameBuf, void *buf) = 0;
+ virtual void removeFramePointers() = 0;
+
+ virtual ~FrameNotifier() {};
+};
+
+/** * Wrapper class around Frame Notifier, which is used by display and notification classes for interacting with Camera Adapter
+ */
+class FrameProvider
+{
+ FrameNotifier* mFrameNotifier;
+ void* mCookie;
+ frame_callback mFrameCallback;
+
+public:
+ FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback)
+ :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { }
+
+ int enableFrameNotification(int32_t frameTypes);
+ int disableFrameNotification(int32_t frameTypes);
+ int returnFrame(CameraBuffer *frameBuf, CameraFrame::FrameType frameType);
+ void addFramePointers(CameraBuffer *frameBuf, void *buf);
+ void removeFramePointers();
+};
+
+/** Wrapper class around MessageNotifier, which is used by display and notification classes for interacting with
+ * Camera Adapter
+ */
+class EventProvider
+{
+public:
+ MessageNotifier* mEventNotifier;
+ void* mCookie;
+ event_callback mEventCallback;
+
+public:
+ EventProvider(MessageNotifier *mn, void* cookie, event_callback eventCallback)
+ :mEventNotifier(mn), mCookie(cookie), mEventCallback(eventCallback) {}
+
+ int enableEventNotification(int32_t eventTypes);
+ int disableEventNotification(int32_t eventTypes);
+};
+
+/*
+ * Interface for providing buffers
+ */
+class BufferProvider
+{
+public:
+ virtual CameraBuffer * allocateBufferList(int width, int height, const char* format, int &bytes, int numBufs) = 0;
+
+ // gets a buffer list from BufferProvider when buffers are sent from external source and already pre-allocated
+ // only call this function for an input source into CameraHal. If buffers are not from a pre-allocated source
+ // this function will return NULL and numBufs of -1
+ virtual CameraBuffer *getBufferList(int *numBufs) = 0;
+
+ //additional methods used for memory mapping
+ virtual uint32_t * getOffsets() = 0;
+ virtual int getFd() = 0;
+ virtual CameraBuffer * getBuffers(bool reset = false) { return NULL; }
+ virtual unsigned int getSize() {return 0; }
+ virtual int getBufferCount() {return -1; }
+
+ virtual int freeBufferList(CameraBuffer * buf) = 0;
+
+ virtual ~BufferProvider() {}
+};
+
+/**
+ * Class for handling data and notify callbacks to application
+ */
+class AppCallbackNotifier: public ErrorNotifier , public virtual android::RefBase
+{
+
+public:
+
+ ///Constants
+ static const int NOTIFIER_TIMEOUT;
+ static const int32_t MAX_BUFFERS = 8;
+
+ enum NotifierCommands
+ {
+ NOTIFIER_CMD_PROCESS_EVENT,
+ NOTIFIER_CMD_PROCESS_FRAME,
+ NOTIFIER_CMD_PROCESS_ERROR
+ };
+
+ enum NotifierState
+ {
+ NOTIFIER_STOPPED,
+ NOTIFIER_STARTED,
+ NOTIFIER_EXITED
+ };
+
+public:
+
+ ~AppCallbackNotifier();
+
+ ///Initialzes the callback notifier, creates any resources required
+ status_t initialize();
+
+ ///Starts the callbacks to application
+ status_t start();
+
+ ///Stops the callbacks from going to application
+ status_t stop();
+
+ void setEventProvider(int32_t eventMask, MessageNotifier * eventProvider);
+ void setFrameProvider(FrameNotifier *frameProvider);
+
+ //All sub-components of Camera HAL call this whenever any error happens
+ virtual void errorNotify(int error);
+
+ status_t startPreviewCallbacks(android::CameraParameters &params, CameraBuffer *buffers, uint32_t *offsets, int fd, size_t length, size_t count);
+ status_t stopPreviewCallbacks();
+
+ status_t enableMsgType(int32_t msgType);
+ status_t disableMsgType(int32_t msgType);
+
+ //API for enabling/disabling measurement data
+ void setMeasurements(bool enable);
+
+ //thread loops
+ bool notificationThread();
+
+ ///Notification callback functions
+ static void frameCallbackRelay(CameraFrame* caFrame);
+ static void eventCallbackRelay(CameraHalEvent* chEvt);
+ void frameCallback(CameraFrame* caFrame);
+ void eventCallback(CameraHalEvent* chEvt);
+ void flushAndReturnFrames();
+
+ void setCallbacks(CameraHal *cameraHal,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user);
+
+ //Set Burst mode
+ void setBurst(bool burst);
+
+ //Notifications from CameraHal for video recording case
+ status_t startRecording();
+ status_t stopRecording();
+ status_t initSharedVideoBuffers(CameraBuffer *buffers, uint32_t *offsets, int fd, size_t length, size_t count, CameraBuffer *vidBufs);
+ status_t releaseRecordingFrame(const void *opaque);
+
+ status_t useMetaDataBufferMode(bool enable);
+
+ void EncoderDoneCb(void*, void*, CameraFrame::FrameType type, void* cookie1, void* cookie2, void *cookie3);
+
+ void useVideoBuffers(bool useVideoBuffers);
+
+ bool getUesVideoBuffers();
+ void setVideoRes(int width, int height);
+
+ void flushEventQueue();
+ void setExternalLocking(bool extBuffLocking);
+
+ //Internal class definitions
+ class NotificationThread : public android::Thread {
+ AppCallbackNotifier* mAppCallbackNotifier;
+ Utils::MessageQueue mNotificationThreadQ;
+ public:
+ enum NotificationThreadCommands
+ {
+ NOTIFIER_START,
+ NOTIFIER_STOP,
+ NOTIFIER_EXIT,
+ };
+ public:
+ NotificationThread(AppCallbackNotifier* nh)
+ : Thread(false), mAppCallbackNotifier(nh) { }
+ virtual bool threadLoop() {
+ return mAppCallbackNotifier->notificationThread();
+ }
+
+ Utils::MessageQueue &msgQ() { return mNotificationThreadQ;}
+ };
+
+ //Friend declarations
+ friend class NotificationThread;
+
+private:
+ void notifyEvent();
+ void notifyFrame();
+ bool processMessage();
+ void releaseSharedVideoBuffers();
+ status_t dummyRaw();
+ void copyAndSendPictureFrame(CameraFrame* frame, int32_t msgType);
+ void copyAndSendPreviewFrame(CameraFrame* frame, int32_t msgType);
+ size_t calculateBufferSize(size_t width, size_t height, const char *pixelFormat);
+ const char* getContstantForPixelFormat(const char *pixelFormat);
+ void lockBufferAndUpdatePtrs(CameraFrame* frame);
+ void unlockBufferAndUpdatePtrs(CameraFrame* frame);
+
+private:
+ mutable android::Mutex mLock;
+ mutable android::Mutex mBurstLock;
+ CameraHal* mCameraHal;
+ camera_notify_callback mNotifyCb;
+ camera_data_callback mDataCb;
+ camera_data_timestamp_callback mDataCbTimestamp;
+ camera_request_memory mRequestMemory;
+ void *mCallbackCookie;
+
+ //Keeps Video MemoryHeaps and Buffers within
+ //these objects
+ android::KeyedVector<unsigned int, unsigned int> mVideoHeaps;
+ android::KeyedVector<unsigned int, unsigned int> mVideoBuffers;
+ android::KeyedVector<void *, CameraBuffer *> mVideoMap;
+
+ //Keeps list of Gralloc handles and associated Video Metadata Buffers
+ android::KeyedVector<void *, camera_memory_t *> mVideoMetadataBufferMemoryMap;
+ android::KeyedVector<void *, CameraBuffer *> mVideoMetadataBufferReverseMap;
+
+ bool mBufferReleased;
+
+ android::sp< NotificationThread> mNotificationThread;
+ EventProvider *mEventProvider;
+ FrameProvider *mFrameProvider;
+ Utils::MessageQueue mEventQ;
+ Utils::MessageQueue mFrameQ;
+ NotifierState mNotifierState;
+
+ bool mPreviewing;
+ camera_memory_t* mPreviewMemory;
+ CameraBuffer mPreviewBuffers[MAX_BUFFERS];
+ int mPreviewBufCount;
+ int mPreviewWidth;
+ int mPreviewHeight;
+ int mPreviewStride;
+ const char *mPreviewPixelFormat;
+ android::KeyedVector<unsigned int, android::sp<android::MemoryHeapBase> > mSharedPreviewHeaps;
+ android::KeyedVector<unsigned int, android::sp<android::MemoryBase> > mSharedPreviewBuffers;
+
+ //Burst mode active
+ bool mBurst;
+ mutable android::Mutex mRecordingLock;
+ bool mRecording;
+ bool mMeasurementEnabled;
+
+ bool mUseMetaDataBufferMode;
+ bool mRawAvailable;
+
+ bool mUseVideoBuffers;
+
+ int mVideoWidth;
+ int mVideoHeight;
+
+ bool mExternalLocking;
+
+};
+
+
+/**
+ * Class used for allocating memory for JPEG bit stream buffers, output buffers of camera in no overlay case
+ */
+class MemoryManager : public BufferProvider, public virtual android::RefBase
+{
+public:
+ MemoryManager();
+ ~MemoryManager();
+
+ status_t initialize();
+
+ int setErrorHandler(ErrorNotifier *errorNotifier);
+ virtual CameraBuffer * allocateBufferList(int width, int height, const char* format, int &bytes, int numBufs);
+ virtual CameraBuffer *getBufferList(int *numBufs);
+ virtual uint32_t * getOffsets();
+ virtual int getFd() ;
+ virtual int freeBufferList(CameraBuffer * buflist);
+
+private:
+ android::sp<ErrorNotifier> mErrorNotifier;
+ int mIonFd;
+};
+
+
+
+
+/**
+ * CameraAdapter interface class
+ * Concrete classes derive from this class and provide implementations based on the specific camera h/w interface
+ */
+
+class CameraAdapter: public FrameNotifier, public virtual android::RefBase
+{
+protected:
+ enum AdapterActiveStates {
+ INTIALIZED_ACTIVE = 1 << 0,
+ LOADED_PREVIEW_ACTIVE = 1 << 1,
+ PREVIEW_ACTIVE = 1 << 2,
+ LOADED_CAPTURE_ACTIVE = 1 << 3,
+ CAPTURE_ACTIVE = 1 << 4,
+ BRACKETING_ACTIVE = 1 << 5,
+ AF_ACTIVE = 1 << 6,
+ ZOOM_ACTIVE = 1 << 7,
+ VIDEO_ACTIVE = 1 << 8,
+ LOADED_REPROCESS_ACTIVE = 1 << 9,
+ REPROCESS_ACTIVE = 1 << 10,
+ };
+public:
+ typedef struct
+ {
+ CameraBuffer *mBuffers;
+ uint32_t *mOffsets;
+ int mFd;
+ size_t mLength;
+ size_t mCount;
+ size_t mMaxQueueable;
+ } BuffersDescriptor;
+
+ enum CameraCommands
+ {
+ CAMERA_START_PREVIEW = 0,
+ CAMERA_STOP_PREVIEW = 1,
+ CAMERA_START_VIDEO = 2,
+ CAMERA_STOP_VIDEO = 3,
+ CAMERA_START_IMAGE_CAPTURE = 4,
+ CAMERA_STOP_IMAGE_CAPTURE = 5,
+ CAMERA_PERFORM_AUTOFOCUS = 6,
+ CAMERA_CANCEL_AUTOFOCUS = 7,
+ CAMERA_PREVIEW_FLUSH_BUFFERS = 8,
+ CAMERA_START_SMOOTH_ZOOM = 9,
+ CAMERA_STOP_SMOOTH_ZOOM = 10,
+ CAMERA_USE_BUFFERS_PREVIEW = 11,
+ CAMERA_SET_TIMEOUT = 12,
+ CAMERA_CANCEL_TIMEOUT = 13,
+ CAMERA_START_BRACKET_CAPTURE = 14,
+ CAMERA_STOP_BRACKET_CAPTURE = 15,
+ CAMERA_QUERY_RESOLUTION_PREVIEW = 16,
+ CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE = 17,
+ CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA = 18,
+ CAMERA_USE_BUFFERS_IMAGE_CAPTURE = 19,
+ CAMERA_USE_BUFFERS_PREVIEW_DATA = 20,
+ CAMERA_TIMEOUT_EXPIRED = 21,
+ CAMERA_START_FD = 22,
+ CAMERA_STOP_FD = 23,
+ CAMERA_SWITCH_TO_EXECUTING = 24,
+ CAMERA_USE_BUFFERS_VIDEO_CAPTURE = 25,
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ CAMERA_USE_BUFFERS_REPROCESS = 26,
+ CAMERA_START_REPROCESS = 27,
+#endif
+#ifdef OMAP_ENHANCEMENT_VTC
+ CAMERA_SETUP_TUNNEL = 28,
+ CAMERA_DESTROY_TUNNEL = 29,
+#endif
+ CAMERA_PREVIEW_INITIALIZATION = 30,
+ };
+
+ enum CameraMode
+ {
+ CAMERA_PREVIEW,
+ CAMERA_IMAGE_CAPTURE,
+ CAMERA_VIDEO,
+ CAMERA_MEASUREMENT,
+ CAMERA_REPROCESS,
+ };
+
+ enum AdapterState {
+ INTIALIZED_STATE = INTIALIZED_ACTIVE,
+ LOADED_PREVIEW_STATE = LOADED_PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ PREVIEW_STATE = PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ LOADED_CAPTURE_STATE = LOADED_CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ CAPTURE_STATE = CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ BRACKETING_STATE = BRACKETING_ACTIVE | CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE ,
+ AF_STATE = AF_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ ZOOM_STATE = ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ VIDEO_STATE = VIDEO_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ VIDEO_AF_STATE = VIDEO_ACTIVE | AF_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ VIDEO_ZOOM_STATE = VIDEO_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ VIDEO_LOADED_CAPTURE_STATE = VIDEO_ACTIVE | LOADED_CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ VIDEO_CAPTURE_STATE = VIDEO_ACTIVE | CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ AF_ZOOM_STATE = AF_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ BRACKETING_ZOOM_STATE = BRACKETING_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ LOADED_REPROCESS_STATE = LOADED_REPROCESS_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ LOADED_REPROCESS_CAPTURE_STATE = LOADED_REPROCESS_ACTIVE | LOADED_CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ REPROCESS_STATE = REPROCESS_ACTIVE | CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE,
+ };
+
+
+public:
+
+ ///Initialzes the camera adapter creates any resources required
+ virtual int initialize(CameraProperties::Properties*) = 0;
+
+ virtual int setErrorHandler(ErrorNotifier *errorNotifier) = 0;
+
+ //Message/Frame notification APIs
+ virtual void enableMsgType(int32_t msgs,
+ frame_callback callback = NULL,
+ event_callback eventCb = NULL,
+ void *cookie = NULL) = 0;
+ virtual void disableMsgType(int32_t msgs, void* cookie) = 0;
+ virtual void returnFrame(CameraBuffer* frameBuf, CameraFrame::FrameType frameType) = 0;
+ virtual void addFramePointers(CameraBuffer *frameBuf, void *buf) = 0;
+ virtual void removeFramePointers() = 0;
+
+ //APIs to configure Camera adapter and get the current parameter set
+ virtual int setParameters(const android::CameraParameters& params) = 0;
+ virtual void getParameters(android::CameraParameters& params) = 0;
+
+ //Registers callback for returning image buffers back to CameraHAL
+ virtual int registerImageReleaseCallback(release_image_buffers_callback callback, void *user_data) = 0;
+
+ //Registers callback, which signals a completed image capture
+ virtual int registerEndCaptureCallback(end_image_capture_callback callback, void *user_data) = 0;
+
+ //API to send a command to the camera
+ virtual status_t sendCommand(CameraCommands operation, int value1=0, int value2=0, int value3=0, int value4=0) = 0;
+
+ virtual ~CameraAdapter() {};
+
+ //Retrieves the current Adapter state
+ virtual AdapterState getState() = 0;
+
+ //Retrieves the next Adapter state
+ virtual AdapterState getNextState() = 0;
+
+ // Receive orientation events from CameraHal
+ virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt) = 0;
+
+ // Rolls the state machine back to INTIALIZED_STATE from the current state
+ virtual status_t rollbackToInitializedState() = 0;
+
+ // Retrieves the current Adapter state - for internal use (not locked)
+ virtual status_t getState(AdapterState &state) = 0;
+ // Retrieves the next Adapter state - for internal use (not locked)
+ virtual status_t getNextState(AdapterState &state) = 0;
+
+ virtual status_t setSharedAllocator(camera_request_memory shmem_alloc) = 0;
+
+protected:
+ //The first two methods will try to switch the adapter state.
+ //Every call to setState() should be followed by a corresponding
+ //call to commitState(). If the state switch fails, then it will
+ //get reset to the previous state via rollbackState().
+ virtual status_t setState(CameraCommands operation) = 0;
+ virtual status_t commitState() = 0;
+ virtual status_t rollbackState() = 0;
+};
+
+class DisplayAdapter : public BufferProvider, public virtual android::RefBase
+{
+public:
+ DisplayAdapter();
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ preview_stream_extended_ops_t * extendedOps() const {
+ return mExtendedOps;
+ }
+
+ void setExtendedOps(preview_stream_extended_ops_t * extendedOps);
+#endif
+
+ ///Initializes the display adapter creates any resources required
+ virtual int initialize() = 0;
+
+ virtual int setPreviewWindow(struct preview_stream_ops *window) = 0;
+ virtual int setFrameProvider(FrameNotifier *frameProvider) = 0;
+ virtual int setErrorHandler(ErrorNotifier *errorNotifier) = 0;
+ virtual int enableDisplay(int width, int height, struct timeval *refTime = NULL) = 0;
+ virtual int disableDisplay(bool cancel_buffer = true) = 0;
+ //Used for Snapshot review temp. pause
+ virtual int pauseDisplay(bool pause) = 0;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+ //Used for shot to snapshot measurement
+ virtual int setSnapshotTimeRef(struct timeval *refTime = NULL) = 0;
+#endif
+
+ virtual bool supportsExternalBuffering() = 0;
+
+ // Get max queueable buffers display supports
+ // This function should only be called after
+ // allocateBufferList
+ virtual status_t maxQueueableBuffers(unsigned int& queueable) = 0;
+
+ // Get min buffers display needs at any given time
+ virtual status_t minUndequeueableBuffers(int& unqueueable) = 0;
+
+ // Given a vector of DisplayAdapters find the one corresponding to str
+ virtual bool match(const char * str) { return false; }
+
+private:
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ preview_stream_extended_ops_t * mExtendedOps;
+#endif
+};
+
+static void releaseImageBuffers(void *userData);
+
+static void endImageCapture(void *userData);
+
+ /**
+ Implementation of the Android Camera hardware abstraction layer
+
+ This class implements the interface methods defined in CameraHardwareInterface
+ for the OMAP4 platform
+
+*/
+class CameraHal
+
+{
+
+public:
+ enum SocFamily {
+ SocFamily_Undefined = -1,
+ SocFamily_Omap4430 = 0,
+ SocFamily_Omap4460,
+ SocFamily_Omap4470,
+ SocFamily_ElementCount // element count of SocFamily
+ };
+
+ ///Constants
+ static const int NO_BUFFERS_PREVIEW;
+ static const int NO_BUFFERS_IMAGE_CAPTURE;
+ static const int NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP;
+ static const uint32_t VFR_SCALE = 1000;
+
+
+ /*--------------------Interface Methods---------------------------------*/
+
+ //@{
+public:
+
+#ifdef MOTOROLA_CAMERA
+ bool SetFlashLedTorch(unsigned intensity);
+#endif
+
+ /** Set the notification and data callbacks */
+ void setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user);
+
+ /** Receives orientation events from SensorListener **/
+ void onOrientationEvent(uint32_t orientation, uint32_t tilt);
+
+ /**
+ * The following three functions all take a msgtype,
+ * which is a bitmask of the messages defined in
+ * include/ui/Camera.h
+ */
+
+ /**
+ * Enable a message, or set of messages.
+ */
+ void enableMsgType(int32_t msgType);
+
+ /**
+ * Disable a message, or a set of messages.
+ */
+ void disableMsgType(int32_t msgType);
+
+ /**
+ * 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 msgTypeEnabled(int32_t msgType);
+
+ /**
+ * Start preview mode.
+ */
+ int startPreview();
+
+ /**
+ * Set preview mode related initialization.
+ * Only used when slice based processing is enabled.
+ */
+ int cameraPreviewInitialization();
+
+ /**
+ * Only used if overlays are used for camera preview.
+ */
+ int setPreviewWindow(struct preview_stream_ops *window);
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ void setExtendedPreviewStreamOps(preview_stream_extended_ops_t *ops);
+
+ /**
+ * Set a tap-in or tap-out point.
+ */
+ int setBufferSource(struct preview_stream_ops *tapin, struct preview_stream_ops *tapout);
+#endif
+
+ /**
+ * Release a tap-in or tap-out point.
+ */
+ int releaseBufferSource(struct preview_stream_ops *tapin, struct preview_stream_ops *tapout);
+
+ /**
+ * Stop a previously started preview.
+ */
+ void stopPreview();
+
+ /**
+ * Returns true if preview is enabled.
+ */
+ bool previewEnabled();
+
+ /**
+ * 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 calling releaseRecordingFrame().
+ */
+ int startRecording();
+
+ /**
+ * Stop a previously started recording.
+ */
+ void stopRecording();
+
+ /**
+ * Returns true if recording is enabled.
+ */
+ int recordingEnabled();
+
+ /**
+ * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+ */
+ void releaseRecordingFrame(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 autoFocus();
+
+ /**
+ * 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 cancelAutoFocus();
+
+ /**
+ * Take a picture.
+ */
+ int takePicture(const char* params);
+
+ /**
+ * Cancel a picture that was started with takePicture. Calling this
+ * method when no picture is being taken is a no-op.
+ */
+ int cancelPicture();
+
+ /** Set the camera parameters. */
+ int setParameters(const char* params);
+ int setParameters(const android::CameraParameters& params);
+
+ /** Return the camera parameters. */
+ char* getParameters();
+ void putParameters(char *);
+
+ /**
+ * Send command to camera driver.
+ */
+ int sendCommand(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 release();
+
+ /**
+ * Dump state of the camera hardware
+ */
+ int dump(int fd) const;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ /**
+ * start a reprocessing operation.
+ */
+ int reprocess(const char* params);
+
+ /**
+ * cancels current reprocessing operation
+ */
+ int cancel_reprocess();
+#endif
+
+ status_t storeMetaDataInBuffers(bool enable);
+
+ // Use external locking for graphic buffers
+ void setExternalLocking(bool extBuffLocking);
+
+ //@}
+
+/*--------------------Internal Member functions - Public---------------------------------*/
+
+public:
+ /** @name internalFunctionsPublic */
+ //@{
+
+ /** Constructor of CameraHal */
+ CameraHal(int cameraId);
+
+ // Destructor of CameraHal
+ ~CameraHal();
+
+ /** Initialize CameraHal */
+ status_t initialize(CameraProperties::Properties*);
+
+ /** Deinitialize CameraHal */
+ void deinitialize();
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ //Uses the constructor timestamp as a reference to calcluate the
+ // elapsed time
+ static void PPM(const char *);
+ //Uses a user provided timestamp as a reference to calcluate the
+ // elapsed time
+ static void PPM(const char *, struct timeval*, ...);
+
+#endif
+
+ /** Free image bufs */
+ status_t freeImageBufs();
+
+ //Signals the end of image capture
+ status_t signalEndImageCapture();
+
+ //Events
+ static void eventCallbackRelay(CameraHalEvent* event);
+ void eventCallback(CameraHalEvent* event);
+ void setEventProvider(int32_t eventMask, MessageNotifier * eventProvider);
+
+ static const char* getPixelFormatConstant(const char* parameters_format);
+ static size_t calculateBufferSize(const char* parameters_format, int width, int height);
+ static void getXYFromOffset(unsigned int *x, unsigned int *y,
+ unsigned int offset, unsigned int stride,
+ const char* format);
+ static unsigned int getBPP(const char* format);
+ static bool parsePair(const char *str, int *first, int *second, char delim);
+
+/*--------------------Internal Member functions - Private---------------------------------*/
+private:
+
+ /** @name internalFunctionsPrivate */
+ //@{
+
+ /** Set the camera parameters specific to Video Recording. */
+ bool setVideoModeParameters(const android::CameraParameters&);
+
+ /** Reset the camera parameters specific to Video Recording. */
+ bool resetVideoModeParameters();
+
+ /** Restart the preview with setParameter. */
+ status_t restartPreview();
+
+ status_t parseResolution(const char *resStr, int &width, int &height);
+
+ void insertSupportedParams();
+
+ /** Allocate preview data buffers */
+ status_t allocPreviewDataBufs(size_t size, size_t bufferCount);
+
+ /** Free preview data buffers */
+ status_t freePreviewDataBufs();
+
+ /** Allocate preview buffers */
+ status_t allocPreviewBufs(int width, int height, const char* previewFormat, unsigned int bufferCount, unsigned int &max_queueable);
+
+ /** Allocate video buffers */
+ status_t allocVideoBufs(uint32_t width, uint32_t height, uint32_t bufferCount);
+
+ /** Allocate image capture buffers */
+ status_t allocImageBufs(unsigned int width, unsigned int height, size_t length,
+ const char* previewFormat, unsigned int bufferCount);
+
+ /** Allocate Raw buffers */
+ status_t allocRawBufs(int width, int height, const char* previewFormat, int bufferCount);
+
+ /** Free preview buffers */
+ status_t freePreviewBufs();
+
+ /** Free video bufs */
+ status_t freeVideoBufs(CameraBuffer *bufs);
+
+ /** Free RAW bufs */
+ status_t freeRawBufs();
+
+ //Check if a given resolution is supported by the current camera
+ //instance
+ bool isResolutionValid(unsigned int width, unsigned int height, const char *supportedResolutions);
+
+ //Check if a given variable frame rate range is supported by the current camera
+ //instance
+ bool isFpsRangeValid(int fpsMin, int fpsMax, const char *supportedFpsRanges);
+
+ //Check if a given parameter is supported by the current camera
+ // instance
+ bool isParameterValid(const char *param, const char *supportedParams);
+ bool isParameterValid(int param, const char *supportedParams);
+ status_t doesSetParameterNeedUpdate(const char *new_param, const char *old_params, bool &update);
+
+ /** Initialize default parameters */
+ void initDefaultParameters();
+
+ void dumpProperties(CameraProperties::Properties& cameraProps);
+
+ status_t startImageBracketing();
+
+ status_t stopImageBracketing();
+
+ void setShutter(bool enable);
+
+ void forceStopPreview();
+
+ void resetPreviewRes(android::CameraParameters *params);
+
+ // Internal __takePicture function - used in public takePicture() and reprocess()
+ int __takePicture(const char* params, struct timeval *captureStart = NULL);
+ //@}
+
+ status_t setTapoutLocked(struct preview_stream_ops *out);
+ status_t releaseTapoutLocked(struct preview_stream_ops *out);
+ status_t setTapinLocked(struct preview_stream_ops *in);
+ status_t releaseTapinLocked(struct preview_stream_ops *in);
+
+ static SocFamily getSocFamily();
+
+#ifdef MOTOROLA_CAMERA
+ // I2C read write utility to support factory test commands
+ bool i2cRW(int read_size, int write_size, unsigned char *read_data, unsigned char *write_data);
+
+ // get best flash intensity level for the current battery level
+ unsigned int getFlashIntensity(void);
+#endif
+/*----------Member variables - Public ---------------------*/
+public:
+ int32_t mMsgEnabled;
+ bool mRecordEnabled;
+ nsecs_t mCurrentTime;
+ bool mFalsePreview;
+ bool mPreviewEnabled;
+ uint32_t mTakePictureQueue;
+ bool mBracketingEnabled;
+ bool mBracketingRunning;
+ //User shutter override
+ bool mShutterEnabled;
+ bool mMeasurementEnabled;
+ //Google's parameter delimiter
+ static const char PARAMS_DELIMITER[];
+
+ CameraAdapter *mCameraAdapter;
+ android::sp<AppCallbackNotifier> mAppCallbackNotifier;
+ android::sp<DisplayAdapter> mDisplayAdapter;
+ android::sp<MemoryManager> mMemoryManager;
+
+ android::Vector< android::sp<DisplayAdapter> > mOutAdapters;
+ android::Vector< android::sp<DisplayAdapter> > mInAdapters;
+
+ // TODO(XXX): Even though we support user setting multiple BufferSourceAdapters now
+ // only one tap in surface and one tap out surface is supported at a time.
+ android::sp<DisplayAdapter> mBufferSourceAdapter_In;
+ android::sp<DisplayAdapter> mBufferSourceAdapter_Out;
+
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ preview_stream_extended_ops_t * mExtendedPreviewStreamOps;
+#endif
+
+ android::sp<android::IMemoryHeap> mPictureHeap;
+
+ int* mGrallocHandles;
+ bool mFpsRangeChangedByApp;
+
+
+ int mRawWidth;
+ int mRawHeight;
+ bool mRawCapture;
+
+
+///static member vars
+
+ static const int SW_SCALING_FPS_LIMIT;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ //Timestamp from the CameraHal constructor
+ static struct timeval ppm_start;
+ //Timestamp of the autoFocus command
+ static struct timeval mStartFocus;
+ //Timestamp of the startPreview command
+ static struct timeval mStartPreview;
+ //Timestamp of the takePicture command
+ static struct timeval mStartCapture;
+
+#endif
+
+/*----------Member variables - Private ---------------------*/
+private:
+ bool mDynamicPreviewSwitch;
+ //keeps paused state of display
+ bool mDisplayPaused;
+
+#ifdef OMAP_ENHANCEMENT_VTC
+ bool mTunnelSetup;
+ bool mVTCUseCase;
+#endif
+
+ //Index of current camera adapter
+ int mCameraIndex;
+
+ mutable android::Mutex mLock;
+
+ android::sp<SensorListener> mSensorListener;
+
+ void* mCameraAdapterHandle;
+
+ android::CameraParameters mParameters;
+ bool mPreviewRunning;
+ bool mPreviewStateOld;
+ bool mRecordingEnabled;
+ EventProvider *mEventProvider;
+
+ CameraBuffer *mPreviewDataBuffers;
+ uint32_t *mPreviewDataOffsets;
+ int mPreviewDataFd;
+ int mPreviewDataLength;
+ CameraBuffer *mImageBuffers;
+ uint32_t *mImageOffsets;
+ int mImageFd;
+ int mImageLength;
+ unsigned int mImageCount;
+ CameraBuffer *mPreviewBuffers;
+ uint32_t *mPreviewOffsets;
+ int mPreviewLength;
+ int mPreviewFd;
+ CameraBuffer *mVideoBuffers;
+ uint32_t *mVideoOffsets;
+ int mVideoFd;
+ int mVideoLength;
+
+ int mBracketRangePositive;
+ int mBracketRangeNegative;
+
+ ///@todo Rename this as preview buffer provider
+ BufferProvider *mBufProvider;
+ BufferProvider *mVideoBufProvider;
+
+
+ CameraProperties::Properties* mCameraProperties;
+
+ bool mPreviewStartInProgress;
+ bool mPreviewInitializationDone;
+
+ bool mSetPreviewWindowCalled;
+
+ uint32_t mPreviewWidth;
+ uint32_t mPreviewHeight;
+ int32_t mMaxZoomSupported;
+
+ int mVideoWidth;
+ int mVideoHeight;
+
+ android::String8 mCapModeBackup;
+
+ bool mExternalLocking;
+
+ const SocFamily mSocFamily;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif
diff --git a/camera/inc/CameraProperties.h b/camera/inc/CameraProperties.h
new file mode 100644
index 0000000..0c003c3
--- /dev/null
+++ b/camera/inc/CameraProperties.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+
+#ifndef CAMERA_PROPERTIES_H
+#define CAMERA_PROPERTIES_H
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "cutils/properties.h"
+
+#include "Common.h"
+
+namespace Ti {
+namespace Camera {
+
+#ifndef MAX_CAMERAS_SUPPORTED
+#define MAX_CAMERAS_SUPPORTED 3
+#endif
+#define MAX_SIMUL_CAMERAS_SUPPORTED 1
+#define MAX_PROP_NAME_LENGTH 50
+#define MAX_PROP_VALUE_LENGTH 2048
+
+#define REMAINING_BYTES(buff) ((((int)sizeof(buff) - 1 - (int)strlen(buff)) < 0) ? 0 : (sizeof(buff) - 1 - strlen(buff)))
+
+enum OperatingMode {
+ MODE_HIGH_SPEED = 0,
+ MODE_HIGH_QUALITY,
+ MODE_ZEROSHUTTERLAG,
+ MODE_VIDEO,
+ MODE_STEREO,
+ MODE_CPCAM,
+ MODE_VIDEO_HIGH_QUALITY,
+ MODE_MAX
+};
+
+// Class that handles the Camera Properties
+class CameraProperties
+{
+public:
+ static const char INVALID[];
+ static const char CAMERA_NAME[];
+ static const char CAMERA_SENSOR_INDEX[];
+ static const char CAMERA_SENSOR_ID[];
+ static const char ORIENTATION_INDEX[];
+ static const char FACING_INDEX[];
+ static const char SUPPORTED_PREVIEW_SIZES[];
+ static const char SUPPORTED_PREVIEW_SUBSAMPLED_SIZES[];
+ static const char SUPPORTED_PREVIEW_TOPBOTTOM_SIZES[];
+ static const char SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES[];
+ static const char SUPPORTED_PREVIEW_FORMATS[];
+ static const char SUPPORTED_PREVIEW_FRAME_RATES[];
+ static const char SUPPORTED_PREVIEW_FRAME_RATES_EXT[];
+ static const char SUPPORTED_PICTURE_SIZES[];
+ static const char SUPPORTED_PICTURE_SUBSAMPLED_SIZES[];
+ static const char SUPPORTED_PICTURE_TOPBOTTOM_SIZES[];
+ static const char SUPPORTED_PICTURE_SIDEBYSIDE_SIZES[];
+ static const char SUPPORTED_PICTURE_FORMATS[];
+ static const char SUPPORTED_THUMBNAIL_SIZES[];
+ static const char SUPPORTED_WHITE_BALANCE[];
+ static const char SUPPORTED_EFFECTS[];
+ static const char SUPPORTED_ANTIBANDING[];
+ static const char SUPPORTED_EXPOSURE_MODES[];
+ static const char SUPPORTED_MANUAL_EXPOSURE_MIN[];
+ static const char SUPPORTED_MANUAL_EXPOSURE_MAX[];
+ static const char SUPPORTED_MANUAL_EXPOSURE_STEP[];
+ static const char SUPPORTED_MANUAL_GAIN_ISO_MIN[];
+ static const char SUPPORTED_MANUAL_GAIN_ISO_MAX[];
+ static const char SUPPORTED_MANUAL_GAIN_ISO_STEP[];
+ static const char SUPPORTED_EV_MIN[];
+ static const char SUPPORTED_EV_MAX[];
+ static const char SUPPORTED_EV_STEP[];
+ static const char SUPPORTED_ISO_VALUES[];
+ static const char SUPPORTED_SCENE_MODES[];
+ static const char SUPPORTED_FLASH_MODES[];
+ static const char SUPPORTED_FOCUS_MODES[];
+ static const char REQUIRED_PREVIEW_BUFS[];
+ static const char REQUIRED_IMAGE_BUFS[];
+ static const char SUPPORTED_ZOOM_RATIOS[];
+ static const char SUPPORTED_ZOOM_STAGES[];
+ static const char SUPPORTED_IPP_MODES[];
+ static const char SMOOTH_ZOOM_SUPPORTED[];
+ static const char ZOOM_SUPPORTED[];
+ static const char PREVIEW_SIZE[];
+ static const char PREVIEW_FORMAT[];
+ static const char PREVIEW_FRAME_RATE[];
+ static const char ZOOM[];
+ static const char PICTURE_SIZE[];
+ static const char PICTURE_FORMAT[];
+ static const char JPEG_THUMBNAIL_SIZE[];
+ static const char WHITEBALANCE[];
+ static const char EFFECT[];
+ static const char ANTIBANDING[];
+ static const char EXPOSURE_MODE[];
+ static const char EV_COMPENSATION[];
+ static const char ISO_MODE[];
+ static const char FOCUS_MODE[];
+ static const char SCENE_MODE[];
+ static const char FLASH_MODE[];
+ static const char JPEG_QUALITY[];
+ static const char BRIGHTNESS[];
+ static const char SATURATION[];
+ static const char SHARPNESS[];
+ static const char CONTRAST[];
+ static const char IPP[];
+ static const char GBCE[];
+ static const char SUPPORTED_GBCE[];
+ static const char GLBCE[];
+ static const char SUPPORTED_GLBCE[];
+ static const char AUTOCONVERGENCE_MODE[];
+ static const char AUTOCONVERGENCE_MODE_VALUES[];
+ static const char MANUAL_CONVERGENCE[];
+ static const char SUPPORTED_MANUAL_CONVERGENCE_MIN[];
+ static const char SUPPORTED_MANUAL_CONVERGENCE_MAX[];
+ static const char SUPPORTED_MANUAL_CONVERGENCE_STEP[];
+ static const char SENSOR_ORIENTATION[];
+ static const char SENSOR_ORIENTATION_VALUES[];
+ static const char REVISION[];
+ static const char FOCAL_LENGTH[];
+ static const char HOR_ANGLE[];
+ static const char VER_ANGLE[];
+ static const char EXIF_MAKE[];
+ static const char EXIF_MODEL[];
+ static const char JPEG_THUMBNAIL_QUALITY[];
+ static const char MAX_FOCUS_AREAS[];
+ static const char MAX_FD_HW_FACES[];
+ static const char MAX_FD_SW_FACES[];
+
+ static const char MAX_PICTURE_WIDTH[];
+ static const char MAX_PICTURE_HEIGHT[];
+
+ static const char PARAMS_DELIMITER [];
+
+ static const char S3D_PRV_FRAME_LAYOUT[];
+ static const char S3D_PRV_FRAME_LAYOUT_VALUES[];
+ static const char S3D_CAP_FRAME_LAYOUT[];
+ static const char S3D_CAP_FRAME_LAYOUT_VALUES[];
+ static const char VSTAB[];
+ static const char VSTAB_SUPPORTED[];
+ static const char VNF[];
+ static const char VNF_SUPPORTED[];
+ static const char FRAMERATE_RANGE[];
+ static const char FRAMERATE_RANGE_SUPPORTED[];
+ static const char FRAMERATE_RANGE_EXT_SUPPORTED[];
+
+ static const char DEFAULT_VALUE[];
+
+ static const char AUTO_EXPOSURE_LOCK[];
+ static const char AUTO_EXPOSURE_LOCK_SUPPORTED[];
+ static const char AUTO_WHITEBALANCE_LOCK[];
+ static const char AUTO_WHITEBALANCE_LOCK_SUPPORTED[];
+ static const char MAX_NUM_METERING_AREAS[];
+ static const char METERING_AREAS[];
+ static const char MAX_NUM_FOCUS_AREAS[];
+
+ static const char VIDEO_SNAPSHOT_SUPPORTED[];
+
+ static const char VIDEO_SIZE[];
+ static const char SUPPORTED_VIDEO_SIZES[];
+
+ static const char MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED[];
+ static const char MECHANICAL_MISALIGNMENT_CORRECTION[];
+
+ static const char RAW_WIDTH[];
+ static const char RAW_HEIGHT[];
+
+ static const char CAP_MODE_VALUES[];
+
+ CameraProperties();
+ ~CameraProperties();
+
+ // container class passed around for accessing properties
+ class Properties
+ {
+ public:
+
+ Properties()
+ {
+ }
+
+ ~Properties()
+ {
+ }
+
+ void set(const char *prop, const char *value);
+ void set(const char *prop, int value);
+ const char* get(const char * prop) const;
+ int getInt(const char * prop) const;
+ void setSensorIndex(int idx);
+ void setMode(OperatingMode mode);
+ OperatingMode getMode() const;
+ void dump();
+
+ protected:
+ const char* keyAt(const unsigned int) const;
+ const char* valueAt(const unsigned int) const;
+
+ private:
+ OperatingMode mCurrentMode;
+ android::DefaultKeyedVector<android::String8, android::String8> mProperties[MODE_MAX];
+
+ };
+
+ ///Initializes the CameraProperties class
+ status_t initialize();
+ status_t loadProperties();
+ int camerasSupported();
+ int getProperties(int cameraIndex, Properties** properties);
+
+private:
+
+ int mCamerasSupported;
+ int mInitialized;
+ mutable android::Mutex mLock;
+
+ Properties mCameraProps[MAX_CAMERAS_SUPPORTED];
+
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif //CAMERA_PROPERTIES_H
diff --git a/camera/inc/Common.h b/camera/inc/Common.h
new file mode 100644
index 0000000..b369e65
--- /dev/null
+++ b/camera/inc/Common.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CAMERAHAL_COMMON_H
+#define CAMERAHAL_COMMON_H
+
+#include "UtilsCommon.h"
+#include "DebugUtils.h"
+#include "Status.h"
+
+
+
+
+// logging functions
+#ifdef CAMERAHAL_DEBUG
+# define CAMHAL_LOGD DBGUTILS_LOGD
+# define CAMHAL_LOGDA DBGUTILS_LOGDA
+# define CAMHAL_LOGDB DBGUTILS_LOGDB
+# ifdef CAMERAHAL_DEBUG_VERBOSE
+# define CAMHAL_LOGV DBGUTILS_LOGV
+# define CAMHAL_LOGVA DBGUTILS_LOGVA
+# define CAMHAL_LOGVB DBGUTILS_LOGVB
+# else
+# define CAMHAL_LOGV(...)
+# define CAMHAL_LOGVA(str)
+# define CAMHAL_LOGVB(str, ...)
+# endif
+#else
+# define CAMHAL_LOGD(...)
+# define CAMHAL_LOGDA(str)
+# define CAMHAL_LOGDB(str, ...)
+# define CAMHAL_LOGV(...)
+# define CAMHAL_LOGVA(str)
+# define CAMHAL_LOGVB(str, ...)
+#endif
+
+#define CAMHAL_LOGI DBGUTILS_LOGI
+#define CAMHAL_LOGW DBGUTILS_LOGW
+#define CAMHAL_LOGE DBGUTILS_LOGE
+#define CAMHAL_LOGEA DBGUTILS_LOGEA
+#define CAMHAL_LOGEB DBGUTILS_LOGEB
+#define CAMHAL_LOGF DBGUTILS_LOGF
+
+#define CAMHAL_ASSERT DBGUTILS_ASSERT
+#define CAMHAL_ASSERT_X DBGUTILS_ASSERT_X
+
+#define CAMHAL_UNUSED(x) (void)x
+
+
+
+
+#endif // CAMERAHAL_COMMON_H
diff --git a/camera/inc/DecoderFactory.h b/camera/inc/DecoderFactory.h
new file mode 100644
index 0000000..d5e566f
--- /dev/null
+++ b/camera/inc/DecoderFactory.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DECODERFACTORY_H_
+#define DECODERFACTORY_H_
+
+#include "FrameDecoder.h"
+
+namespace Ti {
+namespace Camera {
+
+class DecoderFactory {
+ DecoderFactory();
+ ~DecoderFactory();
+public:
+ static FrameDecoder* createDecoderByType(DecoderType type, bool forceSwDecoder = false);
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif /* DECODERFACTORY_H_ */
diff --git a/camera/inc/Decoder_libjpeg.h b/camera/inc/Decoder_libjpeg.h
new file mode 100644
index 0000000..425ebf1
--- /dev/null
+++ b/camera/inc/Decoder_libjpeg.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_CAMERA_HARDWARE_DECODER_LIBJPEG_H
+#define ANDROID_CAMERA_HARDWARE_DECODER_LIBJPEG_H
+
+#include "CameraHal.h"
+
+extern "C" {
+#include "jhead.h"
+
+#undef TRUE
+#undef FALSE
+
+}
+
+
+namespace Ti {
+namespace Camera {
+
+class Decoder_libjpeg
+{
+
+public:
+ Decoder_libjpeg();
+ ~Decoder_libjpeg();
+ static int readDHTSize();
+ static bool isDhtExist(unsigned char *jpeg_src, int filled_len);
+ static int appendDHT(unsigned char *jpeg_src, int filled_len, unsigned char *jpeg_with_dht_buffer, int buff_size);
+ bool decode(unsigned char *jpeg_src, int filled_len, unsigned char *nv12_buffer, int stride);
+
+private:
+ void release();
+ unsigned char **Y_Plane;
+ unsigned char **U_Plane;
+ unsigned char **V_Plane;
+ unsigned char *UV_Plane;
+ unsigned int mWidth, mHeight;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif
+
diff --git a/camera/inc/Encoder_libjpeg.h b/camera/inc/Encoder_libjpeg.h
new file mode 100644
index 0000000..72feb08
--- /dev/null
+++ b/camera/inc/Encoder_libjpeg.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file Encoder_libjpeg.h
+*
+* This defines API for camerahal to encode YUV using libjpeg
+*
+*/
+
+#ifndef ANDROID_CAMERA_HARDWARE_ENCODER_LIBJPEG_H
+#define ANDROID_CAMERA_HARDWARE_ENCODER_LIBJPEG_H
+
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+
+extern "C" {
+#include "jhead.h"
+
+#undef TRUE
+#undef FALSE
+
+}
+
+#include "CameraHal.h"
+
+#define CANCEL_TIMEOUT 5000000 // 5 seconds
+
+namespace Ti {
+namespace Camera {
+
+/**
+ * libjpeg encoder class - uses libjpeg to encode yuv
+ */
+
+#define MAX_EXIF_TAGS_SUPPORTED 30
+typedef void (*encoder_libjpeg_callback_t) (void* main_jpeg,
+ void* thumb_jpeg,
+ CameraFrame::FrameType type,
+ void* cookie1,
+ void* cookie2,
+ void* cookie3,
+ void* cookie4,
+ bool canceled);
+
+// these have to match strings defined in external/jhead/exif.c
+static const char TAG_MODEL[] = "Model";
+static const char TAG_MAKE[] = "Make";
+static const char TAG_FOCALLENGTH[] = "FocalLength";
+static const char TAG_DATETIME[] = "DateTime";
+static const char TAG_IMAGE_WIDTH[] = "ImageWidth";
+static const char TAG_IMAGE_LENGTH[] = "ImageLength";
+static const char TAG_GPS_LAT[] = "GPSLatitude";
+static const char TAG_GPS_LAT_REF[] = "GPSLatitudeRef";
+static const char TAG_GPS_LONG[] = "GPSLongitude";
+static const char TAG_GPS_LONG_REF[] = "GPSLongitudeRef";
+static const char TAG_GPS_ALT[] = "GPSAltitude";
+static const char TAG_GPS_ALT_REF[] = "GPSAltitudeRef";
+static const char TAG_GPS_MAP_DATUM[] = "GPSMapDatum";
+static const char TAG_GPS_PROCESSING_METHOD[] = "GPSProcessingMethod";
+static const char TAG_GPS_VERSION_ID[] = "GPSVersionID";
+static const char TAG_GPS_TIMESTAMP[] = "GPSTimeStamp";
+static const char TAG_GPS_DATESTAMP[] = "GPSDateStamp";
+static const char TAG_ORIENTATION[] = "Orientation";
+static const char TAG_FLASH[] = "Flash";
+static const char TAG_DIGITALZOOMRATIO[] = "DigitalZoomRatio";
+static const char TAG_EXPOSURETIME[] = "ExposureTime";
+static const char TAG_APERTURE[] = "ApertureValue";
+static const char TAG_ISO_EQUIVALENT[] = "ISOSpeedRatings";
+static const char TAG_WHITEBALANCE[] = "WhiteBalance";
+static const char TAG_LIGHT_SOURCE[] = "LightSource";
+static const char TAG_METERING_MODE[] = "MeteringMode";
+static const char TAG_EXPOSURE_PROGRAM[] = "ExposureProgram";
+static const char TAG_COLOR_SPACE[] = "ColorSpace";
+static const char TAG_CPRS_BITS_PER_PIXEL[] = "CompressedBitsPerPixel";
+static const char TAG_FNUMBER[] = "FNumber";
+static const char TAG_SHUTTERSPEED[] = "ShutterSpeedValue";
+static const char TAG_SENSING_METHOD[] = "SensingMethod";
+static const char TAG_CUSTOM_RENDERED[] = "CustomRendered";
+
+class ExifElementsTable {
+ public:
+ ExifElementsTable() :
+ gps_tag_count(0), exif_tag_count(0), position(0),
+ jpeg_opened(false)
+ {
+#ifdef ANDROID_API_JB_OR_LATER
+ has_datetime_tag = false;
+#endif
+ }
+ ~ExifElementsTable();
+
+ status_t insertElement(const char* tag, const char* value);
+ void insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size);
+ status_t insertExifThumbnailImage(const char*, int);
+ void saveJpeg(unsigned char* picture, size_t jpeg_size);
+ static const char* degreesToExifOrientation(unsigned int);
+ static void stringToRational(const char*, unsigned int*, unsigned int*);
+ static bool isAsciiTag(const char* tag);
+ private:
+ ExifElement_t table[MAX_EXIF_TAGS_SUPPORTED];
+ unsigned int gps_tag_count;
+ unsigned int exif_tag_count;
+ unsigned int position;
+ bool jpeg_opened;
+#ifdef ANDROID_API_JB_OR_LATER
+ bool has_datetime_tag;
+#endif
+};
+
+class Encoder_libjpeg : public android::Thread {
+ /* public member types and variables */
+ public:
+ struct params {
+ uint8_t* src;
+ int src_size;
+ uint8_t* dst;
+ int dst_size;
+ int quality;
+ int in_width;
+ int in_height;
+ int out_width;
+ int out_height;
+ int right_crop;
+ int start_offset;
+ const char* format;
+ size_t jpeg_size;
+ };
+ /* public member functions */
+ public:
+ Encoder_libjpeg(params* main_jpeg,
+ params* tn_jpeg,
+ encoder_libjpeg_callback_t cb,
+ CameraFrame::FrameType type,
+ void* cookie1,
+ void* cookie2,
+ void* cookie3, void *cookie4)
+ : android::Thread(false), mMainInput(main_jpeg), mThumbnailInput(tn_jpeg), mCb(cb),
+ mCancelEncoding(false), mCookie1(cookie1), mCookie2(cookie2), mCookie3(cookie3), mCookie4(cookie4),
+ mType(type), mThumb(NULL) {
+ this->incStrong(this);
+ mCancelSem.Create(0);
+ }
+
+ ~Encoder_libjpeg() {
+ CAMHAL_LOGVB("~Encoder_libjpeg(%p)", this);
+ }
+
+ virtual bool threadLoop() {
+ size_t size = 0;
+ if (mThumbnailInput) {
+ // start thread to encode thumbnail
+ mThumb = new Encoder_libjpeg(mThumbnailInput, NULL, NULL, mType, NULL, NULL, NULL, NULL);
+ mThumb->run();
+ }
+
+ // encode our main image
+ size = encode(mMainInput);
+
+ // signal cancel semaphore incase somebody is waiting
+ mCancelSem.Signal();
+
+ // check if it is main jpeg thread
+ if(mThumb.get()) {
+ // wait until tn jpeg thread exits.
+ mThumb->join();
+ mThumb.clear();
+ mThumb = NULL;
+ }
+
+ if(mCb) {
+ mCb(mMainInput, mThumbnailInput, mType, mCookie1, mCookie2, mCookie3, mCookie4, mCancelEncoding);
+ }
+
+ // encoder thread runs, self-destructs, and then exits
+ this->decStrong(this);
+ return false;
+ }
+
+ void cancel() {
+ mCancelEncoding = true;
+ if (mThumb.get()) {
+ mThumb->cancel();
+ mCancelSem.WaitTimeout(CANCEL_TIMEOUT);
+ }
+ }
+
+ void getCookies(void **cookie1, void **cookie2, void **cookie3) {
+ if (cookie1) *cookie1 = mCookie1;
+ if (cookie2) *cookie2 = mCookie2;
+ if (cookie3) *cookie3 = mCookie3;
+ }
+
+ private:
+ params* mMainInput;
+ params* mThumbnailInput;
+ encoder_libjpeg_callback_t mCb;
+ bool mCancelEncoding;
+ void* mCookie1;
+ void* mCookie2;
+ void* mCookie3;
+ void* mCookie4;
+ CameraFrame::FrameType mType;
+ android::sp<Encoder_libjpeg> mThumb;
+ Utils::Semaphore mCancelSem;
+
+ size_t encode(params*);
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif
diff --git a/camera/inc/FrameDecoder.h b/camera/inc/FrameDecoder.h
new file mode 100644
index 0000000..fab0544
--- /dev/null
+++ b/camera/inc/FrameDecoder.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAMEDECODER_H_
+#define FRAMEDECODER_H_
+
+#include <utils/Vector.h>
+#include <utils/StrongPointer.h>
+#include "CameraHal.h"
+
+
+namespace Ti {
+namespace Camera {
+
+enum DecoderType {
+ DecoderType_MJPEG,
+ DecoderType_H264
+};
+
+enum BufferStatus {
+ BufferStatus_Unknown,
+ BufferStatus_InQueued,
+ BufferStatus_InWaitForEmpty,
+ BufferStatus_InDecoded,
+ BufferStatus_OutQueued,
+ BufferStatus_OutWaitForFill,
+ BufferStatus_OutFilled
+};
+
+enum DecoderState {
+ DecoderState_Uninitialized,
+ DecoderState_Initialized,
+ DecoderState_Running,
+ DecoderState_Requested_Stop,
+ DecoderState_Stoppped
+};
+
+class MediaBuffer: public virtual android::RefBase {
+
+public:
+ MediaBuffer()
+ : bufferId(-1), buffer(0), filledLen(0), size(0),
+ mOffset(0), mTimestamp(0), mStatus(BufferStatus_Unknown) {
+ }
+
+ MediaBuffer(int id, void* buffer, size_t buffSize = 0)
+ : bufferId(id), buffer(buffer), filledLen(0), size(buffSize),
+ mOffset(0), mTimestamp(0), mStatus(BufferStatus_Unknown) {
+ }
+
+ virtual ~MediaBuffer() {
+ }
+
+ int bufferId;
+ void* buffer;
+ int filledLen;
+ size_t size;
+
+ nsecs_t getTimestamp() const {
+ return mTimestamp;
+ }
+ void setTimestamp(nsecs_t ts) {
+ mTimestamp = ts;
+ }
+
+ BufferStatus getStatus() const {
+ return mStatus;
+ }
+
+ void setStatus(BufferStatus status) {
+ mStatus = status;
+ }
+
+ android::Mutex& getLock() const {
+ return mLock;
+ }
+
+ uint32_t getOffset() const {
+ return mOffset;
+ }
+
+ void setOffset(uint32_t offset) {
+ mOffset = offset;
+ }
+
+private:
+ uint32_t mOffset;
+ nsecs_t mTimestamp;
+ BufferStatus mStatus;
+ mutable android::Mutex mLock;
+};
+
+struct DecoderParameters {
+ int width;
+ int height;
+ int inputBufferCount;
+ int outputBufferCount;
+};
+
+class FrameDecoder {
+public:
+ FrameDecoder();
+ virtual ~FrameDecoder();
+ void configure(const DecoderParameters& config);
+ status_t start();
+ void stop();
+ void release();
+ void flush();
+ status_t queueInputBuffer(int id);
+ status_t dequeueInputBuffer(int &id);
+ status_t queueOutputBuffer(int id);
+ status_t dequeueOutputBuffer(int &id);
+
+ void registerOutputBuffers(android::Vector< android::sp<MediaBuffer> > *outBuffers) {
+ android::AutoMutex lock(mLock);
+ mOutQueue.clear();
+ mOutBuffers = outBuffers;
+ }
+
+ void registerInputBuffers(android::Vector< android::sp<MediaBuffer> > *inBuffers) {
+ android::AutoMutex lock(mLock);
+ mInQueue.clear();
+ mInBuffers = inBuffers;
+ }
+
+ virtual bool getPaddedDimensions(size_t &width, size_t &height) {
+ return false;
+ }
+
+ void setHal(CameraHal* hal) {
+ mCameraHal = hal;
+ }
+
+protected:
+ virtual void doConfigure(const DecoderParameters& config) = 0;
+ virtual void doProcessInputBuffer() = 0;
+ virtual status_t doStart() = 0;
+ virtual void doStop() = 0;
+ virtual void doFlush() = 0;
+ virtual void doRelease() = 0;
+
+ DecoderParameters mParams;
+
+ android::Vector<int> mInQueue;
+ android::Vector<int> mOutQueue;
+
+ android::Vector< android::sp<MediaBuffer> >* mInBuffers;
+ android::Vector< android::sp<MediaBuffer> >* mOutBuffers;
+
+ CameraHal* mCameraHal;
+
+private:
+ DecoderState mState;
+ android::Mutex mLock;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif /* FRAMEDECODER_H_ */
diff --git a/camera/inc/General3A_Settings.h b/camera/inc/General3A_Settings.h
new file mode 100644
index 0000000..c1e017c
--- /dev/null
+++ b/camera/inc/General3A_Settings.h
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file General3A_Settings.h
+*
+* This file maps the Camera Hardware Interface to OMX.
+*
+*/
+
+#include "OMX_TI_IVCommon.h"
+#include "OMX_TI_Common.h"
+#include "OMX_TI_Index.h"
+#include "TICameraParameters.h"
+
+#ifndef GENERAL_3A_SETTINGS_H
+#define GENERAL_3A_SETTINGS_H
+
+namespace Ti {
+namespace Camera {
+
+struct userToOMX_LUT{
+ const char * userDefinition;
+ int omxDefinition;
+};
+
+struct LUTtype{
+ int size;
+ const userToOMX_LUT *Table;
+};
+
+const userToOMX_LUT isoUserToOMX[] = {
+ { TICameraParameters::ISO_MODE_AUTO, 0 },
+ { TICameraParameters::ISO_MODE_100, 100 },
+ { TICameraParameters::ISO_MODE_200, 200 },
+ { TICameraParameters::ISO_MODE_400, 400 },
+ { TICameraParameters::ISO_MODE_800, 800 },
+ { TICameraParameters::ISO_MODE_1000, 1000 },
+ { TICameraParameters::ISO_MODE_1200, 1200 },
+ { TICameraParameters::ISO_MODE_1600, 1600 },
+};
+
+const userToOMX_LUT effects_UserToOMX [] = {
+ { android::CameraParameters::EFFECT_NONE, OMX_ImageFilterNone },
+ { android::CameraParameters::EFFECT_NEGATIVE, OMX_ImageFilterNegative },
+ { android::CameraParameters::EFFECT_SOLARIZE, OMX_ImageFilterSolarize },
+ { android::CameraParameters::EFFECT_SEPIA, OMX_ImageFilterSepia },
+ { android::CameraParameters::EFFECT_MONO, OMX_ImageFilterGrayScale },
+ { android::CameraParameters::EFFECT_BLACKBOARD, OMX_TI_ImageFilterBlackBoard },
+ { android::CameraParameters::EFFECT_WHITEBOARD, OMX_TI_ImageFilterWhiteBoard },
+ { android::CameraParameters::EFFECT_AQUA, OMX_TI_ImageFilterAqua },
+ { android::CameraParameters::EFFECT_POSTERIZE, OMX_TI_ImageFilterPosterize },
+#ifdef OMAP_ENHANCEMENT
+ { TICameraParameters::EFFECT_NATURAL, OMX_ImageFilterNatural },
+ { TICameraParameters::EFFECT_VIVID, OMX_ImageFilterVivid },
+ { TICameraParameters::EFFECT_COLOR_SWAP, OMX_ImageFilterColourSwap },
+ { TICameraParameters::EFFECT_BLACKWHITE, OMX_TI_ImageFilterBlackWhite }
+#endif
+};
+
+const userToOMX_LUT scene_UserToOMX [] = {
+ { android::CameraParameters::SCENE_MODE_AUTO, OMX_Manual },
+ { android::CameraParameters::SCENE_MODE_LANDSCAPE, OMX_Landscape },
+ { android::CameraParameters::SCENE_MODE_NIGHT_PORTRAIT, OMX_NightPortrait },
+ { android::CameraParameters::SCENE_MODE_FIREWORKS, OMX_Fireworks },
+ { android::CameraParameters::SCENE_MODE_ACTION, OMX_TI_Action },
+ { android::CameraParameters::SCENE_MODE_BEACH, OMX_TI_Beach },
+ { android::CameraParameters::SCENE_MODE_CANDLELIGHT, OMX_TI_Candlelight },
+ { android::CameraParameters::SCENE_MODE_NIGHT, OMX_TI_Night },
+ { android::CameraParameters::SCENE_MODE_PARTY, OMX_TI_Party },
+ { android::CameraParameters::SCENE_MODE_PORTRAIT, OMX_TI_Portrait },
+ { android::CameraParameters::SCENE_MODE_SNOW, OMX_TI_Snow },
+ { android::CameraParameters::SCENE_MODE_STEADYPHOTO, OMX_TI_Steadyphoto },
+ { android::CameraParameters::SCENE_MODE_SUNSET, OMX_TI_Sunset },
+ { android::CameraParameters::SCENE_MODE_THEATRE, OMX_TI_Theatre },
+ { android::CameraParameters::SCENE_MODE_SPORTS, OMX_Sport },
+#ifdef OMAP_ENHANCEMENT
+ { TICameraParameters::SCENE_MODE_CLOSEUP, OMX_Closeup },
+ { TICameraParameters::SCENE_MODE_AQUA, OMX_Underwater },
+ { TICameraParameters::SCENE_MODE_MOOD, OMX_Mood },
+ { TICameraParameters::SCENE_MODE_NIGHT_INDOOR, OMX_NightIndoor },
+ { TICameraParameters::SCENE_MODE_DOCUMENT, OMX_Document },
+ { TICameraParameters::SCENE_MODE_BARCODE, OMX_Barcode },
+ { TICameraParameters::SCENE_MODE_VIDEO_SUPER_NIGHT, OMX_SuperNight },
+ { TICameraParameters::SCENE_MODE_VIDEO_CINE, OMX_Cine },
+ { TICameraParameters::SCENE_MODE_VIDEO_OLD_FILM, OMX_OldFilm },
+#endif
+};
+
+const userToOMX_LUT whiteBal_UserToOMX [] = {
+ { android::CameraParameters::WHITE_BALANCE_AUTO, OMX_WhiteBalControlAuto },
+ { android::CameraParameters::WHITE_BALANCE_DAYLIGHT, OMX_WhiteBalControlSunLight },
+ { android::CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, OMX_WhiteBalControlCloudy },
+ { android::CameraParameters::WHITE_BALANCE_FLUORESCENT, OMX_WhiteBalControlFluorescent },
+ { android::CameraParameters::WHITE_BALANCE_INCANDESCENT, OMX_WhiteBalControlIncandescent },
+ { android::CameraParameters::WHITE_BALANCE_SHADE, OMX_TI_WhiteBalControlShade },
+ { android::CameraParameters::WHITE_BALANCE_TWILIGHT, OMX_TI_WhiteBalControlTwilight },
+ { android::CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT, OMX_TI_WhiteBalControlWarmFluorescent },
+#ifdef OMAP_ENHANCEMENT
+ { TICameraParameters::WHITE_BALANCE_TUNGSTEN, OMX_WhiteBalControlTungsten },
+ { TICameraParameters::WHITE_BALANCE_HORIZON, OMX_WhiteBalControlHorizon },
+ { TICameraParameters::WHITE_BALANCE_SUNSET, OMX_TI_WhiteBalControlSunset }
+#endif
+};
+
+const userToOMX_LUT antibanding_UserToOMX [] = {
+ { android::CameraParameters::ANTIBANDING_OFF, OMX_FlickerCancelOff },
+ { android::CameraParameters::ANTIBANDING_AUTO, OMX_FlickerCancelAuto },
+ { android::CameraParameters::ANTIBANDING_50HZ, OMX_FlickerCancel50 },
+ { android::CameraParameters::ANTIBANDING_60HZ, OMX_FlickerCancel60 }
+};
+
+const userToOMX_LUT focus_UserToOMX [] = {
+ { android::CameraParameters::FOCUS_MODE_AUTO, OMX_IMAGE_FocusControlAutoLock },
+ { android::CameraParameters::FOCUS_MODE_INFINITY, OMX_IMAGE_FocusControlAutoInfinity },
+ { android::CameraParameters::FOCUS_MODE_INFINITY, OMX_IMAGE_FocusControlHyperfocal },
+ { android::CameraParameters::FOCUS_MODE_MACRO, OMX_IMAGE_FocusControlAutoMacro },
+ { android::CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO, OMX_IMAGE_FocusControlAuto },
+ { android::CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE, OMX_IMAGE_FocusControlAuto },
+#ifdef OMAP_ENHANCEMENT
+ { TICameraParameters::FOCUS_MODE_FACE , OMX_IMAGE_FocusControlContinousFacePriority },
+ { TICameraParameters::FOCUS_MODE_PORTRAIT, OMX_IMAGE_FocusControlPortrait },
+ { TICameraParameters::FOCUS_MODE_EXTENDED, OMX_IMAGE_FocusControlExtended },
+#endif
+ { TICameraParameters::FOCUS_MODE_OFF , OMX_IMAGE_FocusControlOff }
+};
+
+const userToOMX_LUT exposure_UserToOMX [] = {
+ { TICameraParameters::EXPOSURE_MODE_MANUAL, OMX_ExposureControlOff },
+ { TICameraParameters::EXPOSURE_MODE_AUTO, OMX_ExposureControlAuto },
+ { TICameraParameters::EXPOSURE_MODE_NIGHT, OMX_ExposureControlNight },
+ { TICameraParameters::EXPOSURE_MODE_BACKLIGHT, OMX_ExposureControlBackLight },
+ { TICameraParameters::EXPOSURE_MODE_SPOTLIGHT, OMX_ExposureControlSpotLight},
+ { TICameraParameters::EXPOSURE_MODE_SPORTS, OMX_ExposureControlSports },
+ { TICameraParameters::EXPOSURE_MODE_SNOW, OMX_ExposureControlSnow },
+ { TICameraParameters::EXPOSURE_MODE_BEACH, OMX_ExposureControlBeach },
+ { TICameraParameters::EXPOSURE_MODE_APERTURE, OMX_ExposureControlLargeAperture },
+ { TICameraParameters::EXPOSURE_MODE_SMALL_APERTURE, OMX_ExposureControlSmallApperture },
+};
+
+const userToOMX_LUT flash_UserToOMX [] = {
+ { android::CameraParameters::FLASH_MODE_OFF ,OMX_IMAGE_FlashControlOff },
+ { android::CameraParameters::FLASH_MODE_ON ,OMX_IMAGE_FlashControlOn },
+ { android::CameraParameters::FLASH_MODE_AUTO ,OMX_IMAGE_FlashControlAuto },
+ { android::CameraParameters::FLASH_MODE_TORCH ,OMX_IMAGE_FlashControlTorch },
+ { android::CameraParameters::FLASH_MODE_RED_EYE ,OMX_IMAGE_FlashControlRedEyeReduction },
+#ifdef OMAP_ENHANCEMENT
+ { TICameraParameters::FLASH_MODE_FILL_IN ,OMX_IMAGE_FlashControlFillin }
+#endif
+};
+
+const LUTtype ExpLUT =
+ {
+ sizeof(exposure_UserToOMX)/sizeof(exposure_UserToOMX[0]),
+ exposure_UserToOMX
+ };
+
+const LUTtype WBalLUT =
+ {
+ sizeof(whiteBal_UserToOMX)/sizeof(whiteBal_UserToOMX[0]),
+ whiteBal_UserToOMX
+ };
+
+const LUTtype FlickerLUT =
+ {
+ sizeof(antibanding_UserToOMX)/sizeof(antibanding_UserToOMX[0]),
+ antibanding_UserToOMX
+ };
+
+const LUTtype SceneLUT =
+ {
+ sizeof(scene_UserToOMX)/sizeof(scene_UserToOMX[0]),
+ scene_UserToOMX
+ };
+
+const LUTtype FlashLUT =
+ {
+ sizeof(flash_UserToOMX)/sizeof(flash_UserToOMX[0]),
+ flash_UserToOMX
+ };
+
+const LUTtype EffLUT =
+ {
+ sizeof(effects_UserToOMX)/sizeof(effects_UserToOMX[0]),
+ effects_UserToOMX
+ };
+
+const LUTtype FocusLUT =
+ {
+ sizeof(focus_UserToOMX)/sizeof(focus_UserToOMX[0]),
+ focus_UserToOMX
+ };
+
+const LUTtype IsoLUT =
+ {
+ sizeof(isoUserToOMX)/sizeof(isoUserToOMX[0]),
+ isoUserToOMX
+ };
+
+/*
+* class Gen3A_settings
+* stores the 3A settings
+* also defines the look up tables
+* for mapping settings from Hal to OMX
+*/
+class Gen3A_settings{
+ public:
+
+ int Exposure;
+ int WhiteBallance;
+ int Flicker;
+ int SceneMode;
+ int Effect;
+ int Focus;
+ int EVCompensation;
+ int Contrast;
+ int Saturation;
+ int Sharpness;
+ int ISO;
+ int FlashMode;
+ int ManualExposure;
+ int ManualExposureRight;
+ int ManualGain;
+ int ManualGainRight;
+
+ unsigned int Brightness;
+ OMX_BOOL ExposureLock;
+ OMX_BOOL FocusLock;
+ OMX_BOOL WhiteBalanceLock;
+
+ OMX_BOOL AlgoExternalGamma;
+ OMX_BOOL AlgoNSF1;
+ OMX_BOOL AlgoNSF2;
+ OMX_BOOL AlgoSharpening;
+ OMX_BOOL AlgoThreeLinColorMap;
+ OMX_BOOL AlgoGIC;
+
+ OMX_TI_CONFIG_GAMMATABLE_TYPE mGammaTable;
+
+};
+
+/*
+* Flags raised when a setting is changed
+*/
+enum E3ASettingsFlags
+{
+ SetSceneMode = 1 << 0,
+ SetEVCompensation = 1 << 1,
+ SetWhiteBallance = 1 << 2,
+ SetFlicker = 1 << 3,
+ SetExposure = 1 << 4,
+ SetSharpness = 1 << 5,
+ SetBrightness = 1 << 6,
+ SetContrast = 1 << 7,
+ SetISO = 1 << 8,
+ SetSaturation = 1 << 9,
+ SetEffect = 1 << 10,
+ SetFocus = 1 << 11,
+ SetExpMode = 1 << 14,
+ SetFlash = 1 << 15,
+ SetExpLock = 1 << 16,
+ SetWBLock = 1 << 17,
+ SetMeteringAreas = 1 << 18,
+ SetManualExposure = 1 << 19,
+
+ SetAlgoExternalGamma = 1 << 20,
+ SetAlgoNSF1 = 1 << 21,
+ SetAlgoNSF2 = 1 << 22,
+ SetAlgoSharpening = 1 << 23,
+ SetAlgoThreeLinColorMap = 1 << 24,
+ SetAlgoGIC = 1 << 25,
+ SetGammaTable = 1 << 26,
+
+
+ E3aSettingMax,
+ E3AsettingsAll = ( ((E3aSettingMax -1 ) << 1) -1 ) /// all possible flags raised
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif //GENERAL_3A_SETTINGS_H
diff --git a/camera/inc/NV12_resize.h b/camera/inc/NV12_resize.h
new file mode 100644
index 0000000..4b05a4f
--- /dev/null
+++ b/camera/inc/NV12_resize.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NV12_RESIZE_H_
+#define NV12_RESIZE_H_
+
+#include "Common.h"
+
+typedef unsigned char mmBool;
+typedef unsigned char mmUchar;
+typedef unsigned char mmUint8;
+typedef unsigned char mmByte;
+typedef unsigned short mmUint16;
+typedef unsigned int mmUint32;
+typedef unsigned long mmUint64;
+typedef signed char mmInt8;
+typedef char mmChar;
+typedef signed short mmInt16;
+typedef signed int mmInt32;
+typedef signed long mmLong;
+typedef signed int mmHandle;
+typedef float mmFloat;
+typedef double mmDouble;
+typedef int HObj;
+typedef HObj HFile;
+typedef int HDir;
+typedef void* mmMutexHandle;
+typedef struct _fstat {
+ mmInt32 fileSize;
+} VE_FileAttribute;
+
+typedef struct {
+ mmInt32 second;
+ mmInt32 millisecond;
+} tsVE_Time;
+
+typedef struct {
+ mmInt32 year;
+ mmInt32 month;
+ mmInt32 day;
+ mmInt32 hour;
+ mmInt32 minute;
+ mmInt32 second;
+} TmDateTime;
+
+const mmUint8 bWeights[8][8][4] = {
+ {{64, 0, 0, 0}, {56, 0, 0, 8}, {48, 0, 0,16}, {40, 0, 0,24},
+ {32, 0, 0,32}, {24, 0, 0,40}, {16, 0, 0,48}, { 8, 0, 0,56}},
+
+ {{56, 8, 0, 0}, {49, 7, 1, 7}, {42, 6, 2,14}, {35, 5, 3,21},
+ {28, 4, 4,28}, {21, 3, 5,35}, {14, 2, 6,42}, { 7, 1, 7,49}},
+
+ {{48,16, 0, 0}, {42,14, 2, 6}, {36,12,4 ,12}, {30,10,6 ,18},
+ {24, 8, 8,24}, {18, 6,10,30}, {12,4 ,12,36}, { 6, 2,14,42}},
+
+ {{40,24,0 ,0 }, {35,21, 3, 5}, {30,18, 6,10}, {25,15, 9,15},
+ {20,12,12,20}, {15, 9,15,25}, {10, 6,18,30}, { 5, 3,21,35}},
+
+ {{32,32, 0,0 }, {28,28, 4, 4}, {24,24, 8, 8}, {20,20,12,12},
+ {16,16,16,16}, {12,12,20,20}, { 8, 8,24,24}, { 4, 4,28,28}},
+
+ {{24,40,0 ,0 }, {21,35, 5, 3}, {18,30,10, 6}, {15,25,15, 9},
+ {12,20,20,12}, { 9,15,25,15}, { 6,10,30,18}, { 3, 5,35,21}},
+
+ {{16,48, 0,0 }, {14,42, 6, 2}, {12,36,12, 4}, {10,30,18, 6},
+ {8 ,24,24,8 }, { 6,18,30,10}, { 4,12,36,12}, { 2, 6,42,14}},
+
+ {{ 8,56, 0,0 }, { 7,49, 7, 1}, { 6,42,14, 2}, { 5,35,21, 3},
+ { 4,28,28,4 }, { 3,21,35, 5}, { 2,14,42, 6}, { 1,7 ,49, 7}}
+};
+
+typedef enum {
+ IC_FORMAT_NONE,
+ IC_FORMAT_RGB565,
+ IC_FORMAT_RGB888,
+ IC_FORMAT_YCbCr420_lp,
+ IC_FORMAT_YCbCr,
+ IC_FORMAT_YCbCr420_FRAME_PK,
+ IC_FORMAT_MAX
+} enumImageFormat;
+
+/* This structure defines the format of an image */
+typedef struct {
+ mmInt32 uWidth;
+ mmInt32 uHeight;
+ mmInt32 uStride;
+ enumImageFormat eFormat;
+ mmByte *imgPtr;
+ mmByte *clrPtr;
+ mmInt32 uOffset;
+} structConvImage;
+
+typedef struct IC_crop_struct {
+ mmUint32 x; /* x pos of rectangle */
+ mmUint32 y; /* y pos of rectangle */
+ mmUint32 uWidth; /* dx of rectangle */
+ mmUint32 uHeight; /* dy of rectangle */
+} IC_rect_type;
+
+/*==========================================================================
+* Function Name : VT_resizeFrame_Video_opt2_lp
+*
+* Description : Resize a yuv frame.
+*
+* Input(s) : input_img_ptr -> Input Image Structure
+* : output_img_ptr -> Output Image Structure
+* : cropout -> crop structure
+*
+* Value Returned : mmBool -> FALSE on error TRUE on success
+* NOTE:
+* Not tested for crop funtionallity.
+* faster version.
+============================================================================*/
+mmBool
+VT_resizeFrame_Video_opt2_lp(
+ structConvImage* i_img_ptr, /* Points to the input image */
+ structConvImage* o_img_ptr, /* Points to the output image */
+ IC_rect_type* cropout, /* how much to resize to in final image */
+ mmUint16 dummy /* Transparent pixel value */
+ );
+
+#endif //#define NV12_RESIZE_H_
diff --git a/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
new file mode 100644
index 0000000..10590df
--- /dev/null
+++ b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
@@ -0,0 +1,1235 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#ifndef OMX_CAMERA_ADAPTER_H
+#define OMX_CAMERA_ADAPTER_H
+
+#include "CameraHal.h"
+#include "OMX_Types.h"
+#include "OMX_Core.h"
+#include "OMX_CoreExt.h"
+#include "OMX_IVCommon.h"
+#include "OMX_Component.h"
+#include "OMX_Index.h"
+#include "OMX_IndexExt.h"
+#include "OMX_TI_Index.h"
+#include "OMX_TI_IVCommon.h"
+#include "OMX_TI_Common.h"
+#include "OMX_TI_Image.h"
+#include "General3A_Settings.h"
+#include "OMXSceneModeTables.h"
+
+#include "BaseCameraAdapter.h"
+#include "Encoder_libjpeg.h"
+#include "DebugUtils.h"
+
+
+extern "C"
+{
+#include "timm_osal_error.h"
+#include "timm_osal_events.h"
+#include "timm_osal_trace.h"
+#include "timm_osal_semaphores.h"
+}
+
+
+namespace Ti {
+namespace Camera {
+
+#define Q16_OFFSET 16
+
+#define OMX_CMD_TIMEOUT 3000000 //3 sec.
+#define OMX_CAPTURE_TIMEOUT 5000000 //5 sec.
+
+#define FOCUS_THRESHOLD 5 //[s.]
+
+#define MIN_JPEG_QUALITY 1
+#define MAX_JPEG_QUALITY 100
+#define EXP_BRACKET_RANGE 10
+#define ZOOM_BRACKET_RANGE 10
+
+#define FOCUS_DIST_SIZE 100
+#define FOCUS_DIST_BUFFER_SIZE 500
+
+#define TOUCH_DATA_SIZE 200
+#define DEFAULT_THUMB_WIDTH 160
+#define DEFAULT_THUMB_HEIGHT 120
+#define FRAME_RATE_FULL_HD 27
+#define FRAME_RATE_HIGH_HD 60
+
+#define ZOOM_STAGES 61
+
+#define FACE_DETECTION_BUFFER_SIZE 0x1000
+#define MAX_NUM_FACES_SUPPORTED 35
+
+#define EXIF_MODEL_SIZE 100
+#define EXIF_MAKE_SIZE 100
+#define EXIF_DATE_TIME_SIZE 20
+
+#define GPS_MIN_DIV 60
+#define GPS_SEC_DIV 60
+#define GPS_SEC_ACCURACY 1000
+#define GPS_TIMESTAMP_SIZE 6
+#define GPS_DATESTAMP_SIZE 11
+#define GPS_REF_SIZE 2
+#define GPS_MAPDATUM_SIZE 100
+#define GPS_PROCESSING_SIZE 100
+#define GPS_VERSION_SIZE 4
+#define GPS_NORTH_REF "N"
+#define GPS_SOUTH_REF "S"
+#define GPS_EAST_REF "E"
+#define GPS_WEST_REF "W"
+
+/* Default portstartnumber of Camera component */
+#define OMX_CAMERA_DEFAULT_START_PORT_NUM 0
+
+/* Define number of ports for differt domains */
+#define OMX_CAMERA_PORT_OTHER_NUM 1
+#define OMX_CAMERA_PORT_VIDEO_NUM 4
+#define OMX_CAMERA_PORT_IMAGE_NUM 1
+#define OMX_CAMERA_PORT_AUDIO_NUM 0
+#define OMX_CAMERA_NUM_PORTS (OMX_CAMERA_PORT_OTHER_NUM + OMX_CAMERA_PORT_VIDEO_NUM + OMX_CAMERA_PORT_IMAGE_NUM + OMX_CAMERA_PORT_AUDIO_NUM)
+
+/* Define start port number for differt domains */
+#define OMX_CAMERA_PORT_OTHER_START OMX_CAMERA_DEFAULT_START_PORT_NUM
+#define OMX_CAMERA_PORT_VIDEO_START (OMX_CAMERA_PORT_OTHER_START + OMX_CAMERA_PORT_OTHER_NUM)
+#define OMX_CAMERA_PORT_IMAGE_START (OMX_CAMERA_PORT_VIDEO_START + OMX_CAMERA_PORT_VIDEO_NUM)
+#define OMX_CAMERA_PORT_AUDIO_START (OMX_CAMERA_PORT_IMAGE_START + OMX_CAMERA_PORT_IMAGE_NUM)
+
+/* Port index for camera component */
+#define OMX_CAMERA_PORT_OTHER_IN (OMX_CAMERA_PORT_OTHER_START + 0)
+#define OMX_CAMERA_PORT_VIDEO_IN_VIDEO (OMX_CAMERA_PORT_VIDEO_START + 0)
+#define OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW (OMX_CAMERA_PORT_VIDEO_START + 1)
+#define OMX_CAMERA_PORT_VIDEO_OUT_VIDEO (OMX_CAMERA_PORT_VIDEO_START + 2)
+#define OMX_CAMERA_PORT_VIDEO_OUT_MEASUREMENT (OMX_CAMERA_PORT_VIDEO_START + 3)
+#define OMX_CAMERA_PORT_IMAGE_OUT_IMAGE (OMX_CAMERA_PORT_IMAGE_START + 0)
+
+
+#define OMX_INIT_STRUCT(_s_, _name_) \
+ memset(&(_s_), 0x0, sizeof(_name_)); \
+ (_s_).nSize = sizeof(_name_); \
+ (_s_).nVersion.s.nVersionMajor = 0x1; \
+ (_s_).nVersion.s.nVersionMinor = 0x1; \
+ (_s_).nVersion.s.nRevision = 0x0; \
+ (_s_).nVersion.s.nStep = 0x0
+
+#define OMX_INIT_STRUCT_PTR(_s_, _name_) \
+ memset((_s_), 0x0, sizeof(_name_)); \
+ (_s_)->nSize = sizeof(_name_); \
+ (_s_)->nVersion.s.nVersionMajor = 0x1; \
+ (_s_)->nVersion.s.nVersionMinor = 0x1; \
+ (_s_)->nVersion.s.nRevision = 0x0; \
+ (_s_)->nVersion.s.nStep = 0x0
+
+#define GOTO_EXIT_IF(_CONDITION,_ERROR) { \
+ if ((_CONDITION)) { \
+ eError = (_ERROR); \
+ goto EXIT; \
+ } \
+}
+
+const int64_t kCameraBufferLatencyNs = 250000000LL; // 250 ms
+
+///OMX Specific Functions
+static OMX_ERRORTYPE OMXCameraAdapterEventHandler(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+
+static OMX_ERRORTYPE OMXCameraAdapterEmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+static OMX_ERRORTYPE OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader);
+
+struct CapResolution {
+ size_t width, height;
+ const char *param;
+};
+
+struct CapPixelformat {
+ OMX_COLOR_FORMATTYPE pixelformat;
+ const char *param;
+};
+
+struct CapCodingFormat {
+ OMX_IMAGE_CODINGTYPE imageCodingFormat;
+ const char *param;
+};
+
+struct CapU32 {
+ OMX_U32 num;
+ const char *param;
+};
+
+struct CapS32 {
+ OMX_S32 num;
+ const char *param;
+};
+
+typedef CapU32 CapFramerate;
+typedef CapU32 CapISO;
+typedef CapU32 CapSensorName;
+typedef CapS32 CapZoom;
+
+/**
+ * Class which completely abstracts the camera hardware interaction from camera hal
+ * TODO: Need to list down here, all the message types that will be supported by this class
+ Need to implement BufferProvider interface to use AllocateBuffer of OMX if needed
+ */
+class OMXCameraAdapter : public BaseCameraAdapter
+{
+public:
+
+ /*--------------------Constant declarations----------------------------------------*/
+ static const int32_t MAX_NO_BUFFERS = 20;
+
+ ///@remarks OMX Camera has six ports - buffer input, time input, preview, image, video, and meta data
+ static const int MAX_NO_PORTS = 6;
+
+ ///Five second timeout
+ static const int CAMERA_ADAPTER_TIMEOUT = 5000*1000;
+
+ enum CaptureMode
+ {
+ INITIAL_MODE = -1,
+ HIGH_SPEED = 1,
+ HIGH_QUALITY,
+ VIDEO_MODE,
+ HIGH_QUALITY_ZSL,
+ CP_CAM,
+ VIDEO_MODE_HQ,
+ };
+
+ enum IPPMode
+ {
+ IPP_NULL = -1,
+ IPP_NONE = 0,
+ IPP_NSF,
+ IPP_LDC,
+ IPP_LDCNSF,
+ };
+
+ enum CodingMode
+ {
+ CodingJPEG = 0,
+ CodingJPS,
+ CodingMPO,
+ };
+
+ enum Algorithm3A
+ {
+ WHITE_BALANCE_ALGO = 0x1,
+ EXPOSURE_ALGO = 0x2,
+ FOCUS_ALGO = 0x4,
+ };
+
+ enum AlgoPriority
+ {
+ FACE_PRIORITY = 0,
+ REGION_PRIORITY,
+ };
+
+ enum BrightnessMode
+ {
+ BRIGHTNESS_OFF = 0,
+ BRIGHTNESS_ON,
+ BRIGHTNESS_AUTO,
+ };
+
+ enum CaptureSettingsFlags {
+ SetFormat = 1 << 0,
+ SetThumb = 1 << 1,
+ SetBurstExpBracket = 1 << 2,
+ SetQuality = 1 << 3,
+ SetRotation = 1 << 4,
+ ECaptureSettingMax,
+ ECapturesettingsAll = ( ((ECaptureSettingMax -1 ) << 1) -1 ), /// all possible flags raised
+ ECaptureParamSettings = SetFormat | SetThumb | SetQuality | SetBurstExpBracket, // Settings set with SetParam
+ ECaptureConfigSettings = (ECapturesettingsAll & ~ECaptureParamSettings)
+ };
+
+ enum PreviewSettingsFlags {
+ SetLDC = 1 << 0,
+ SetNSF = 1 << 1,
+ SetCapMode = 1 << 2,
+ SetVNF = 1 << 3,
+ SetVSTAB = 1 << 4,
+ EPreviewSettingMax,
+ EPreviewSettingsAll = ( ((EPreviewSettingMax -1 ) << 1) -1 ) /// all possible flags raised
+ };
+
+ enum BracketingValueMode {
+ BracketingValueAbsolute,
+ BracketingValueRelative,
+ BracketingValueAbsoluteForced,
+ BracketingValueRelativeForced,
+ BracketingValueCompensation,
+ BracketingValueCompensationForced
+ };
+
+ class GPSData
+ {
+ public:
+ int mLongDeg, mLongMin, mLongSec, mLongSecDiv;
+ char mLongRef[GPS_REF_SIZE];
+ bool mLongValid;
+ int mLatDeg, mLatMin, mLatSec, mLatSecDiv;
+ char mLatRef[GPS_REF_SIZE];
+ bool mLatValid;
+ int mAltitude;
+ unsigned char mAltitudeRef;
+ bool mAltitudeValid;
+ char mMapDatum[GPS_MAPDATUM_SIZE];
+ bool mMapDatumValid;
+ char mVersionId[GPS_VERSION_SIZE];
+ bool mVersionIdValid;
+ char mProcMethod[GPS_PROCESSING_SIZE];
+ bool mProcMethodValid;
+ char mDatestamp[GPS_DATESTAMP_SIZE];
+ bool mDatestampValid;
+ uint32_t mTimeStampHour;
+ uint32_t mTimeStampMin;
+ uint32_t mTimeStampSec;
+ bool mTimeStampValid;
+ };
+
+ class EXIFData
+ {
+ public:
+ GPSData mGPSData;
+ char mMake[EXIF_MODEL_SIZE];
+ char mModel[EXIF_MAKE_SIZE];
+ unsigned int mFocalNum, mFocalDen;
+ bool mMakeValid;
+ bool mModelValid;
+ };
+
+ ///Parameters specific to any port of the OMX Camera component
+ class OMXCameraPortParameters
+ {
+ public:
+ //CameraBuffer * mHostBufaddr[MAX_NO_BUFFERS];
+ OMX_BUFFERHEADERTYPE *mBufferHeader[MAX_NO_BUFFERS];
+ OMX_U8 mStatus[MAX_NO_BUFFERS];
+ OMX_U32 mWidth;
+ OMX_U32 mHeight;
+ OMX_U32 mStride;
+ OMX_U8 mNumBufs;
+
+ // defines maximum number of buffers our of mNumBufs
+ // queueable at given moment
+ OMX_U8 mMaxQueueable;
+
+ OMX_U32 mBufSize;
+ OMX_COLOR_FORMATTYPE mColorFormat;
+ OMX_PARAM_VIDEONOISEFILTERTYPE mVNFMode;
+ OMX_PARAM_VIDEOYUVRANGETYPE mYUVRange;
+ OMX_CONFIG_BOOLEANTYPE mVidStabParam;
+ OMX_CONFIG_FRAMESTABTYPE mVidStabConfig;
+ OMX_U32 mCapFrame;
+ OMX_U32 mFrameRate;
+ OMX_U32 mMinFrameRate;
+ OMX_U32 mMaxFrameRate;
+ CameraFrame::FrameType mImageType;
+ OMX_TI_STEREOFRAMELAYOUTTYPE mFrameLayoutType;
+ CameraBufferType mBufferType;
+
+ CameraBuffer * lookup_omx_buffer (OMX_BUFFERHEADERTYPE *pBufHeader);
+ enum {
+ IDLE = 0, // buffer is neither with HAL or Ducati
+ FILL, // buffer is with Ducati
+ DONE, // buffer is filled and sent to HAL
+ };
+ };
+
+ ///Context of the OMX Camera component
+ class OMXCameraAdapterComponentContext
+ {
+ public:
+ OMX_HANDLETYPE mHandleComp;
+ OMX_U32 mNumPorts;
+ OMX_STATETYPE mState ;
+ OMX_U32 mVideoPortIndex;
+ OMX_U32 mPrevPortIndex;
+ OMX_U32 mImagePortIndex;
+ OMX_U32 mMeasurementPortIndex;
+ OMX_U32 mVideoInPortIndex;
+ OMXCameraPortParameters mCameraPortParams[MAX_NO_PORTS];
+ };
+
+ class CachedCaptureParameters
+ {
+ public:
+ unsigned int mPendingCaptureSettings;
+ unsigned int mPictureRotation;
+ int mExposureBracketingValues[EXP_BRACKET_RANGE];
+ int mExposureGainBracketingValues[EXP_BRACKET_RANGE];
+ int mExposureGainBracketingModes[EXP_BRACKET_RANGE];
+ size_t mExposureBracketingValidEntries;
+ OMX_BRACKETMODETYPE mExposureBracketMode;
+ unsigned int mBurstFrames;
+ bool mFlushShotConfigQueue;
+ };
+
+public:
+
+ OMXCameraAdapter(size_t sensor_index);
+ ~OMXCameraAdapter();
+
+ ///Initialzes the camera adapter creates any resources required
+ virtual status_t initialize(CameraProperties::Properties*);
+
+ //APIs to configure Camera adapter and get the current parameter set
+ virtual status_t setParameters(const android::CameraParameters& params);
+ virtual void getParameters(android::CameraParameters& params);
+
+ // API
+ status_t UseBuffersPreview(CameraBuffer *bufArr, int num);
+
+ //API to flush the buffers
+ status_t flushBuffers(OMX_U32 port = OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW);
+
+ // API
+ virtual status_t setFormat(OMX_U32 port, OMXCameraPortParameters &cap);
+
+ // Function to get and populate caps from handle
+ static status_t getCaps(int sensorId, CameraProperties::Properties* props, OMX_HANDLETYPE handle);
+ static const char* getLUTvalue_OMXtoHAL(int OMXValue, LUTtype LUT);
+ static int getMultipleLUTvalue_OMXtoHAL(int OMXValue, LUTtype LUT, char * supported);
+ static int getLUTvalue_HALtoOMX(const char * HalValue, LUTtype LUT);
+
+ OMX_ERRORTYPE OMXCameraAdapterEventHandler(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+
+ OMX_ERRORTYPE OMXCameraAdapterEmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ OMX_ERRORTYPE OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader);
+
+ static OMX_ERRORTYPE OMXCameraGetHandle(OMX_HANDLETYPE *handle, OMX_PTR pAppData,
+ const OMX_CALLBACKTYPE & callbacks);
+
+protected:
+
+ //Parent class method implementation
+ virtual status_t takePicture();
+ virtual status_t stopImageCapture();
+ virtual status_t startBracketing(int range);
+ virtual status_t stopBracketing();
+ virtual status_t autoFocus();
+ virtual status_t cancelAutoFocus();
+ virtual status_t startSmoothZoom(int targetIdx);
+ virtual status_t stopSmoothZoom();
+ virtual status_t startVideoCapture();
+ virtual status_t stopVideoCapture();
+ virtual status_t startPreview();
+ virtual status_t stopPreview();
+ virtual status_t useBuffers(CameraMode mode, CameraBuffer * bufArr, int num, size_t length, unsigned int queueable);
+ virtual status_t fillThisBuffer(CameraBuffer * frameBuf, CameraFrame::FrameType frameType);
+ virtual status_t getFrameSize(size_t &width, size_t &height);
+ virtual status_t getPictureBufferSize(CameraFrame &frame, size_t bufferCount);
+ virtual status_t getFrameDataSize(size_t &dataFrameSize, size_t bufferCount);
+ virtual status_t startFaceDetection();
+ virtual status_t stopFaceDetection();
+ virtual status_t switchToExecuting();
+ virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt);
+
+private:
+
+ // Caches and returns current set of parameters
+ CachedCaptureParameters* cacheCaptureParameters();
+
+ status_t doSwitchToExecuting();
+
+ void performCleanupAfterError();
+
+ status_t switchToIdle();
+
+ status_t switchToLoaded(bool bPortEnableRequired = false);
+ status_t prevPortEnable();
+
+ OMXCameraPortParameters *getPortParams(CameraFrame::FrameType frameType);
+
+ OMX_ERRORTYPE SignalEvent(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+ OMX_ERRORTYPE RemoveEvent(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+
+ status_t RegisterForEvent(OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN Utils::Semaphore &semaphore);
+
+ status_t setPictureRotation(unsigned int degree);
+ status_t setSensorOrientation(unsigned int degree);
+ status_t setImageQuality(unsigned int quality);
+ status_t setThumbnailParams(unsigned int width, unsigned int height, unsigned int quality);
+ status_t setSensorQuirks(int orientation,
+ OMXCameraPortParameters &portParams,
+ bool &portConfigured);
+
+ status_t setupTunnel(uint32_t SliceHeight, uint32_t EncoderHandle, uint32_t width, uint32_t height);
+ status_t destroyTunnel();
+
+ //EXIF
+ status_t setParametersEXIF(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t convertGPSCoord(double coord, int &deg, int &min, int &sec, int &secDivisor);
+ status_t setupEXIF();
+ status_t setupEXIF_libjpeg(ExifElementsTable*, OMX_TI_ANCILLARYDATATYPE*,
+ OMX_TI_WHITEBALANCERESULTTYPE*);
+
+ //Focus functionality
+ status_t doAutoFocus();
+ status_t stopAutoFocus();
+ status_t checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus);
+ status_t returnFocusStatus(bool timeoutReached);
+ status_t getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode);
+ void handleFocusCallback();
+
+
+ //Focus distances
+ status_t setParametersFocus(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t addFocusDistances(OMX_U32 &near,
+ OMX_U32 &optimal,
+ OMX_U32 &far,
+ android::CameraParameters& params);
+ status_t encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length);
+ status_t getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far);
+
+ //VSTAB and VNF Functionality
+ status_t enableVideoNoiseFilter(bool enable);
+ status_t enableVideoStabilization(bool enable);
+
+ //Digital zoom
+ status_t setParametersZoom(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t doZoom(int index);
+ status_t advanceZoom();
+
+ //3A related parameters
+ status_t setParameters3A(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ void declareParameter3ABool(const android::CameraParameters &params, const char *key,
+ OMX_BOOL &current_setting, E3ASettingsFlags pending,
+ const char *msg);
+
+ // scene modes
+ status_t setScene(Gen3A_settings& Gen3A);
+ // returns pointer to SceneModesEntry from the LUT for camera given 'name' and 'scene'
+ static const SceneModesEntry* getSceneModeEntry(const char* name, OMX_SCENEMODETYPE scene);
+
+
+ //Flash modes
+ status_t setFlashMode(Gen3A_settings& Gen3A);
+ status_t getFlashMode(Gen3A_settings& Gen3A);
+
+ // Focus modes
+ status_t setFocusMode(Gen3A_settings& Gen3A);
+ status_t getFocusMode(Gen3A_settings& Gen3A);
+
+ //Exposure Modes
+ status_t setExposureMode(Gen3A_settings& Gen3A);
+ status_t setManualExposureVal(Gen3A_settings& Gen3A);
+ status_t setEVCompensation(Gen3A_settings& Gen3A);
+ status_t setWBMode(Gen3A_settings& Gen3A);
+ status_t setFlicker(Gen3A_settings& Gen3A);
+ status_t setBrightness(Gen3A_settings& Gen3A);
+ status_t setContrast(Gen3A_settings& Gen3A);
+ status_t setSharpness(Gen3A_settings& Gen3A);
+ status_t setSaturation(Gen3A_settings& Gen3A);
+ status_t setISO(Gen3A_settings& Gen3A);
+ status_t setEffect(Gen3A_settings& Gen3A);
+ status_t setMeteringAreas(Gen3A_settings& Gen3A);
+
+ //TI extensions for enable/disable algos
+ status_t setParameter3ABool(const OMX_INDEXTYPE omx_idx,
+ const OMX_BOOL data, const char *msg);
+ status_t setParameter3ABoolInvert(const OMX_INDEXTYPE omx_idx,
+ const OMX_BOOL data, const char *msg);
+ status_t setAlgoExternalGamma(Gen3A_settings& Gen3A);
+#ifndef MOTOROLA_CAMERA
+ status_t setAlgoNSF1(Gen3A_settings& Gen3A);
+ status_t setAlgoNSF2(Gen3A_settings& Gen3A);
+ status_t setAlgoSharpening(Gen3A_settings& Gen3A);
+ status_t setAlgoThreeLinColorMap(Gen3A_settings& Gen3A);
+ status_t setAlgoGIC(Gen3A_settings& Gen3A);
+
+ //Gamma table
+ void updateGammaTable(const char* gamma);
+ status_t setGammaTable(Gen3A_settings& Gen3A);
+#endif
+
+ status_t getEVCompensation(Gen3A_settings& Gen3A);
+ status_t getWBMode(Gen3A_settings& Gen3A);
+ status_t getSharpness(Gen3A_settings& Gen3A);
+ status_t getSaturation(Gen3A_settings& Gen3A);
+ status_t getISO(Gen3A_settings& Gen3A);
+
+ // 3A locks
+ status_t setExposureLock(Gen3A_settings& Gen3A);
+ status_t setFocusLock(Gen3A_settings& Gen3A);
+ status_t setWhiteBalanceLock(Gen3A_settings& Gen3A);
+ status_t set3ALock(OMX_BOOL toggleExp, OMX_BOOL toggleWb, OMX_BOOL toggleFocus);
+
+ //Stereo 3D
+ void setParamS3D(OMX_U32 port, const char *valstr);
+ status_t setS3DFrameLayout(OMX_U32 port) const;
+
+ //API to set FrameRate using VFR interface
+ status_t setVFramerate(OMX_U32 minFrameRate,OMX_U32 maxFrameRate);
+
+ status_t setParametersAlgo(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+
+ //Noise filtering
+ status_t setNSF(OMXCameraAdapter::IPPMode mode);
+
+ //LDC
+ status_t setLDC(OMXCameraAdapter::IPPMode mode);
+
+ //GLBCE
+ status_t setGLBCE(OMXCameraAdapter::BrightnessMode mode);
+
+ //GBCE
+ status_t setGBCE(OMXCameraAdapter::BrightnessMode mode);
+
+ status_t printComponentVersion(OMX_HANDLETYPE handle);
+
+ //Touch AF
+ status_t setTouchFocus();
+
+ //Face detection
+ status_t setParametersFD(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t updateFocusDistances(android::CameraParameters &params);
+ status_t setFaceDetectionOrientation(OMX_U32 orientation);
+ status_t setFaceDetection(bool enable, OMX_U32 orientation);
+ status_t createPreviewMetadata(OMX_BUFFERHEADERTYPE* pBuffHeader,
+ android::sp<CameraMetadataResult> &result,
+ size_t previewWidth,
+ size_t previewHeight);
+ status_t encodeFaceCoordinates(const OMX_FACEDETECTIONTYPE *faceData,
+ camera_frame_metadata_t *metadataResult,
+ size_t previewWidth,
+ size_t previewHeight);
+ status_t encodePreviewMetadata(camera_frame_metadata_t *meta, const OMX_PTR plat_pvt);
+
+ void pauseFaceDetection(bool pause);
+
+ //3A Algorithms priority configuration
+ status_t setAlgoPriority(AlgoPriority priority, Algorithm3A algo, bool enable);
+
+ //Sensor overclocking
+ status_t setSensorOverclock(bool enable);
+
+ // Utility methods for OMX Capabilities
+ static bool _checkOmxTiCap(const OMX_TI_CAPTYPE & caps);
+ static bool _dumpOmxTiCap(int sensorId, const OMX_TI_CAPTYPE & caps);
+
+ static status_t insertCapabilities(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t encodeSizeCap(OMX_TI_CAPRESTYPE&, const CapResolution *, size_t, char *, size_t);
+ static status_t encodeISOCap(OMX_U32, const CapISO*, size_t, char*, size_t);
+ static size_t encodeZoomCap(OMX_S32, const CapZoom*, size_t, char*, size_t);
+ static void encodeFrameRates(int minFrameRate, int maxFrameRate, const OMX_TI_CAPTYPE & caps,
+ const CapFramerate * fixedFrameRates, int frameRateCount, android::Vector<FpsRange> & fpsRanges);
+ static status_t encodeImageCodingFormatCap(OMX_IMAGE_CODINGTYPE,
+ const CapCodingFormat *,
+ size_t,
+ char *);
+ static status_t encodePixelformatCap(OMX_COLOR_FORMATTYPE,
+ const CapPixelformat*,
+ size_t,
+ char*,
+ size_t);
+ static status_t encodeSizeCap3D(OMX_TI_CAPRESTYPE&,
+ const CapResolution*,
+ size_t ,
+ char * ,
+ size_t);
+ static status_t insertImageSizes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertPreviewSizes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertThumbSizes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertZoomStages(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertImageFormats(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertPreviewFormats(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertFramerates(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertEVs(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertISOModes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertIPPModes(CameraProperties::Properties*, OMX_TI_CAPTYPE &);
+ static status_t insertWBModes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertEffects(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertExpModes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertManualExpRanges(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertSceneModes(CameraProperties::Properties*, OMX_TI_CAPTYPE &);
+ static status_t insertFocusModes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertFlickerModes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertFlashModes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertSenMount(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertDefaults(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertLocks(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertAreas(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertMechanicalMisalignmentCorrection(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertCaptureModes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertVideoSizes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertFacing(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertFocalLength(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertAutoConvergenceModes(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertManualConvergenceRange(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertLayout(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertVideoSnapshotSupported(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+ static status_t insertVNFSupported(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps);
+ static status_t insertVSTABSupported(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps);
+ static status_t insertGBCESupported(CameraProperties::Properties* params,
+ const OMX_TI_CAPTYPE &caps);
+ static status_t insertGLBCESupported(CameraProperties::Properties* params,
+ const OMX_TI_CAPTYPE &caps);
+ static status_t insertRaw(CameraProperties::Properties*, OMX_TI_CAPTYPE&);
+
+ status_t setParametersCapture(const android::CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+
+ //Exposure Bracketing
+ status_t initVectorShot();
+ status_t setVectorShot(int *evValues, int *evValues2, int *evModes2,
+ size_t evCount, size_t frameCount,
+ bool flush, OMX_BRACKETMODETYPE bracketMode);
+ status_t setVectorStop(bool toPreview = false);
+ status_t setExposureBracketing(int *evValues, int *evValues2,
+ size_t evCount, size_t frameCount,
+ OMX_BRACKETMODETYPE bracketMode);
+ status_t doExposureBracketing(int *evValues, int *evValues2,
+ int *evModes2,
+ size_t evCount, size_t frameCount,
+ bool flush,
+ OMX_BRACKETMODETYPE bracketMode);
+ int getBracketingValueMode(const char *a, const char *b) const;
+ status_t parseExpRange(const char *rangeStr, int *expRange, int *gainRange,
+ int *expGainModes,
+ size_t count, size_t &validEntries);
+
+ //Temporal Bracketing
+ status_t doBracketing(OMX_BUFFERHEADERTYPE *pBuffHeader, CameraFrame::FrameType typeOfFrame);
+ status_t sendBracketFrames(size_t &framesSent);
+
+ // Image Capture Service
+ status_t startImageCapture(bool bracketing, CachedCaptureParameters*);
+ status_t disableImagePort();
+
+ //Shutter callback notifications
+ status_t setShutterCallback(bool enabled);
+
+ //Sets eithter HQ or HS mode and the frame count
+ status_t setCaptureMode(OMXCameraAdapter::CaptureMode mode);
+ status_t UseBuffersCapture(CameraBuffer *bufArr, int num);
+ status_t UseBuffersPreviewData(CameraBuffer *bufArr, int num);
+ status_t UseBuffersRawCapture(CameraBuffer *bufArr, int num);
+
+ //Used for calculation of the average frame rate during preview
+ status_t recalculateFPS();
+
+ //Sends the incoming OMX buffer header to subscribers
+ status_t sendCallBacks(CameraFrame frame, OMX_IN OMX_BUFFERHEADERTYPE *pBuffHeader, unsigned int mask, OMXCameraPortParameters *port);
+
+ status_t apply3Asettings( Gen3A_settings& Gen3A );
+
+ // AutoConvergence
+ status_t setAutoConvergence(const char *valstr, const char *pValManualstr, const android::CameraParameters &params);
+
+ status_t setExtraData(bool enable, OMX_U32, OMX_EXT_EXTRADATATYPE);
+ OMX_OTHER_EXTRADATATYPE *getExtradata(const OMX_PTR ptrPrivate, OMX_EXTRADATATYPE type) const;
+
+ // Meta data
+#ifdef OMAP_ENHANCEMENT_CPCAM
+ camera_memory_t * getMetaData(const OMX_PTR plat_pvt,
+ camera_request_memory allocator) const;
+#endif
+
+ // Mechanical Misalignment Correction
+ status_t setMechanicalMisalignmentCorrection(bool enable);
+
+ // DCC file data save
+ status_t initDccFileDataSave(OMX_HANDLETYPE* omxHandle, int portIndex);
+ status_t sniffDccFileDataSave(OMX_BUFFERHEADERTYPE* pBuffHeader);
+ status_t saveDccFileDataSave();
+ status_t closeDccFileDataSave();
+ status_t fseekDCCuseCasePos(FILE *pFile);
+ FILE * fopenCameraDCC(const char *dccFolderPath);
+ FILE * parseDCCsubDir(DIR *pDir, char *path);
+
+#ifdef CAMERAHAL_OMX_PROFILING
+ status_t storeProfilingData(OMX_BUFFERHEADERTYPE* pBuffHeader);
+#endif
+
+ // Internal buffers
+ status_t initInternalBuffers (OMX_U32);
+ status_t deinitInternalBuffers (OMX_U32);
+
+ // Reprocess Methods -- implementation in OMXReprocess.cpp
+ status_t setParametersReprocess(const android::CameraParameters &params, CameraBuffer* bufs,
+ BaseCameraAdapter::AdapterState state);
+ status_t startReprocess();
+ status_t disableReprocess();
+ status_t stopReprocess();
+ status_t UseBuffersReprocess(CameraBuffer *bufArr, int num);
+
+ class CommandHandler : public android::Thread {
+ public:
+ CommandHandler(OMXCameraAdapter* ca)
+ : android::Thread(false), mCameraAdapter(ca) { }
+
+ virtual bool threadLoop() {
+ bool ret;
+ ret = Handler();
+ return ret;
+ }
+
+ status_t put(Utils::Message* msg){
+ android::AutoMutex lock(mLock);
+ return mCommandMsgQ.put(msg);
+ }
+
+ void clearCommandQ()
+ {
+ android::AutoMutex lock(mLock);
+ mCommandMsgQ.clear();
+ }
+
+ enum {
+ COMMAND_EXIT = -1,
+ CAMERA_START_IMAGE_CAPTURE = 0,
+ CAMERA_PERFORM_AUTOFOCUS,
+ CAMERA_SWITCH_TO_EXECUTING,
+ CAMERA_START_REPROCESS
+ };
+
+ private:
+ bool Handler();
+ Utils::MessageQueue mCommandMsgQ;
+ OMXCameraAdapter* mCameraAdapter;
+ android::Mutex mLock;
+ };
+ android::sp<CommandHandler> mCommandHandler;
+
+#ifdef MOTOROLA_CAMERA
+ status_t setLedFlash(int nLedFlashIntensP);
+ status_t setLedTorch(int nLedTorchIntensP);
+#endif
+
+public:
+
+#ifdef MOTOROLA_CAMERA
+ status_t getOTPEeprom(unsigned char * pData, unsigned long nSize);
+#endif
+
+ class OMXCallbackHandler : public android::Thread {
+ public:
+ OMXCallbackHandler(OMXCameraAdapter* ca)
+ : Thread(false), mCameraAdapter(ca)
+ {
+ mIsProcessed = true;
+ }
+
+ virtual bool threadLoop() {
+ bool ret;
+ ret = Handler();
+ return ret;
+ }
+
+ status_t put(Utils::Message* msg){
+ android::AutoMutex lock(mLock);
+ mIsProcessed = false;
+ return mCommandMsgQ.put(msg);
+ }
+
+ void clearCommandQ()
+ {
+ android::AutoMutex lock(mLock);
+ mCommandMsgQ.clear();
+ }
+
+ void flush();
+
+ enum {
+ COMMAND_EXIT = -1,
+ CAMERA_FILL_BUFFER_DONE,
+ CAMERA_FOCUS_STATUS
+ };
+
+ private:
+ bool Handler();
+ Utils::MessageQueue mCommandMsgQ;
+ OMXCameraAdapter* mCameraAdapter;
+ android::Mutex mLock;
+ android::Condition mCondition;
+ bool mIsProcessed;
+ };
+
+ android::sp<OMXCallbackHandler> mOMXCallbackHandler;
+
+private:
+
+ //AF callback
+ status_t setFocusCallback(bool enabled);
+
+ //OMX Capabilities data
+ static const CapResolution mImageCapRes [];
+ static const CapResolution mImageCapResSS [];
+ static const CapResolution mImageCapResTB [];
+ static const CapResolution mPreviewRes [];
+ static const CapResolution mPreviewResSS [];
+ static const CapResolution mPreviewResTB [];
+ static const CapResolution mPreviewPortraitRes [];
+ static const CapResolution mThumbRes [];
+ static const CapPixelformat mPixelformats [];
+ static const userToOMX_LUT mFrameLayout [];
+ static const LUTtype mLayoutLUT;
+ static const CapCodingFormat mImageCodingFormat[];
+ static const CapFramerate mFramerates [];
+ static const CapU32 mSensorNames[] ;
+ static const CapZoom mZoomStages [];
+ static const CapISO mISOStages [];
+ static const int SENSORID_IMX060;
+ static const int SENSORID_OV5650;
+ static const int SENSORID_OV5640;
+ static const int SENSORID_OV14825;
+ static const int SENSORID_S5K4E1GA;
+ static const int SENSORID_S5K6A1GX03;
+ static const int SENSORID_OV8830;
+ static const int SENSORID_OV2722;
+ static const int SENSORID_OV9726;
+#ifdef MOTOROLA_CAMERA
+ static const int SENSORID_OV8820;
+ static const int SENSORID_MT9M114;
+#endif
+ static const CapU32 mFacing [];
+ static const userToOMX_LUT mAutoConvergence [];
+ static const LUTtype mAutoConvergenceLUT;
+ static const userToOMX_LUT mBracketingModes[];
+ static const LUTtype mBracketingModesLUT;
+
+ static const int FPS_MIN;
+ static const int FPS_MAX;
+ static const int FPS_MAX_EXTENDED;
+
+ // OMX Camera defaults
+ static const char DEFAULT_ANTIBANDING[];
+ static const char DEFAULT_BRIGHTNESS[];
+ static const char DEFAULT_CONTRAST[];
+ static const char DEFAULT_EFFECT[];
+ static const char DEFAULT_EV_COMPENSATION[];
+ static const char DEFAULT_EV_STEP[];
+ static const char DEFAULT_EXPOSURE_MODE[];
+ static const char DEFAULT_FLASH_MODE[];
+ static const char DEFAULT_FOCUS_MODE_PREFERRED[];
+ static const char DEFAULT_FOCUS_MODE[];
+ static const char DEFAULT_IPP[];
+ static const char DEFAULT_ISO_MODE[];
+ static const char DEFAULT_JPEG_QUALITY[];
+ static const char DEFAULT_THUMBNAIL_QUALITY[];
+ static const char DEFAULT_THUMBNAIL_SIZE[];
+ static const char DEFAULT_PICTURE_FORMAT[];
+ static const char DEFAULT_S3D_PICTURE_LAYOUT[];
+ static const char DEFAULT_PICTURE_SIZE[];
+ static const char DEFAULT_PICTURE_SS_SIZE[];
+ static const char DEFAULT_PICTURE_TB_SIZE[];
+ static const char DEFAULT_PREVIEW_FORMAT[];
+ static const char DEFAULT_FRAMERATE[];
+ static const char DEFAULT_S3D_PREVIEW_LAYOUT[];
+ static const char DEFAULT_PREVIEW_SIZE[];
+ static const char DEFAULT_PREVIEW_SS_SIZE[];
+ static const char DEFAULT_PREVIEW_TB_SIZE[];
+ static const char DEFAULT_NUM_PREV_BUFS[];
+ static const char DEFAULT_NUM_PIC_BUFS[];
+ static const char DEFAULT_SATURATION[];
+ static const char DEFAULT_SCENE_MODE[];
+ static const char DEFAULT_SHARPNESS[];
+ static const char * DEFAULT_VSTAB;
+ static const char * DEFAULT_VNF;
+ static const char DEFAULT_WB[];
+ static const char DEFAULT_ZOOM[];
+ static const char DEFAULT_MAX_FD_HW_FACES[];
+ static const char DEFAULT_MAX_FD_SW_FACES[];
+ static const char * DEFAULT_AE_LOCK;
+ static const char * DEFAULT_AWB_LOCK;
+ static const char DEFAULT_HOR_ANGLE[];
+ static const char DEFAULT_VER_ANGLE[];
+ static const char DEFAULT_VIDEO_SIZE[];
+ static const char DEFAULT_SENSOR_ORIENTATION[];
+ static const char DEFAULT_AUTOCONVERGENCE_MODE[];
+ static const char DEFAULT_MANUAL_CONVERGENCE[];
+ static const char * DEFAULT_MECHANICAL_MISALIGNMENT_CORRECTION_MODE;
+ static const char DEFAULT_EXIF_MODEL[];
+ static const char DEFAULT_EXIF_MAKE[];
+
+ static const size_t MAX_FOCUS_AREAS;
+
+#ifdef CAMERAHAL_OMX_PROFILING
+
+ static const char DEFAULT_PROFILE_PATH[];
+ int mDebugProfile;
+
+#endif
+
+ OMX_VERSIONTYPE mCompRevision;
+
+ //OMX Component UUID
+ OMX_UUIDTYPE mCompUUID;
+
+ //Current Focus distances
+ char mFocusDistNear[FOCUS_DIST_SIZE];
+ char mFocusDistOptimal[FOCUS_DIST_SIZE];
+ char mFocusDistFar[FOCUS_DIST_SIZE];
+ char mFocusDistBuffer[FOCUS_DIST_BUFFER_SIZE];
+
+ // Current Focus areas
+ android::Vector<android::sp<CameraArea> > mFocusAreas;
+ mutable android::Mutex mFocusAreasLock;
+
+ // Current Touch convergence areas
+ android::Vector<android::sp<CameraArea> > mTouchAreas;
+ mutable android::Mutex mTouchAreasLock;
+
+ // Current Metering areas
+ android::Vector<android::sp<CameraArea> > mMeteringAreas;
+ mutable android::Mutex mMeteringAreasLock;
+
+ OperatingMode mCapabilitiesOpMode;
+ CaptureMode mCapMode;
+ // TODO(XXX): Do we really need this lock? Let's
+ // try to merge temporal bracketing and burst
+ // capture later
+ mutable android::Mutex mBurstLock;
+ size_t mBurstFrames;
+ size_t mBurstFramesAccum;
+ size_t mBurstFramesQueued;
+ size_t mCapturedFrames;
+ bool mFlushShotConfigQueue;
+
+ bool mMeasurementEnabled;
+
+ //Exposure Bracketing
+ int mExposureBracketingValues[EXP_BRACKET_RANGE];
+ int mExposureGainBracketingValues[EXP_BRACKET_RANGE];
+ int mExposureGainBracketingModes[EXP_BRACKET_RANGE];
+ size_t mExposureBracketingValidEntries;
+ OMX_BRACKETMODETYPE mExposureBracketMode;
+
+ //Zoom Bracketing
+ int mZoomBracketingValues[ZOOM_BRACKET_RANGE];
+ size_t mZoomBracketingValidEntries;
+
+ static const uint32_t FACE_DETECTION_THRESHOLD;
+ mutable android::Mutex mFaceDetectionLock;
+ //Face detection status
+ bool mFaceDetectionRunning;
+ bool mFaceDetectionPaused;
+ bool mFDSwitchAlgoPriority;
+
+ camera_face_t faceDetectionLastOutput[MAX_NUM_FACES_SUPPORTED];
+ int faceDetectionNumFacesLastOutput;
+ int metadataLastAnalogGain;
+ int metadataLastExposureTime;
+
+ //Geo-tagging
+ EXIFData mEXIFData;
+
+ //Image post-processing
+ IPPMode mIPP;
+
+ //jpeg Picture Quality
+ unsigned int mPictureQuality;
+
+ //thumbnail resolution
+ unsigned int mThumbWidth, mThumbHeight;
+
+ //thumbnail quality
+ unsigned int mThumbQuality;
+
+ //variables holding the estimated framerate
+ float mFPS, mLastFPS;
+
+ //automatically disable AF after a given amount of frames
+ unsigned int mFocusThreshold;
+
+ //This is needed for the CTS tests. They falsely assume, that during
+ //smooth zoom the current zoom stage will not change within the
+ //zoom callback scope, which in a real world situation is not always the
+ //case. This variable will "simulate" the expected behavior
+ unsigned int mZoomParameterIdx;
+
+ //current zoom
+ android::Mutex mZoomLock;
+ unsigned int mCurrentZoomIdx, mTargetZoomIdx, mPreviousZoomIndx;
+ bool mZoomUpdating, mZoomUpdate;
+ int mZoomInc;
+ bool mReturnZoomStatus;
+ static const int32_t ZOOM_STEPS [];
+
+ //local copy
+ OMX_VERSIONTYPE mLocalVersionParam;
+
+ unsigned int mPending3Asettings;
+ android::Mutex m3ASettingsUpdateLock;
+ Gen3A_settings mParameters3A;
+ const char *mPictureFormatFromClient;
+
+ BrightnessMode mGBCE;
+ BrightnessMode mGLBCE;
+
+ OMX_TI_CONFIG_3A_FACE_PRIORITY mFacePriority;
+ OMX_TI_CONFIG_3A_REGION_PRIORITY mRegionPriority;
+
+ android::CameraParameters mParams;
+ CameraProperties::Properties* mCapabilities;
+ unsigned int mPictureRotation;
+ bool mWaitingForSnapshot;
+ bool mCaptureConfigured;
+ unsigned int mPendingCaptureSettings;
+ unsigned int mPendingPreviewSettings;
+ unsigned int mPendingReprocessSettings;
+ OMX_TI_ANCILLARYDATATYPE* mCaptureAncillaryData;
+ OMX_TI_WHITEBALANCERESULTTYPE* mWhiteBalanceData;
+ bool mReprocConfigured;
+
+ //Temporal bracketing management data
+ bool mBracketingSet;
+ mutable android::Mutex mBracketingLock;
+ bool *mBracketingBuffersQueued;
+ int mBracketingBuffersQueuedCount;
+ int mLastBracetingBufferIdx;
+ bool mBracketingEnabled;
+ bool mZoomBracketingEnabled;
+ size_t mBracketingRange;
+ int mCurrentZoomBracketing;
+ android::CameraParameters mParameters;
+
+#ifdef CAMERAHAL_TUNA
+ bool mIternalRecordingHint;
+#endif
+
+ bool mOmxInitialized;
+ OMXCameraAdapterComponentContext mCameraAdapterParameters;
+ bool mFirstTimeInit;
+
+ ///Semaphores used internally
+ Utils::Semaphore mInitSem;
+ Utils::Semaphore mFlushSem;
+ Utils::Semaphore mUsePreviewDataSem;
+ Utils::Semaphore mUsePreviewSem;
+ Utils::Semaphore mUseCaptureSem;
+ Utils::Semaphore mStartPreviewSem;
+ Utils::Semaphore mStopPreviewSem;
+ Utils::Semaphore mStartCaptureSem;
+ Utils::Semaphore mStopCaptureSem;
+ Utils::Semaphore mSwitchToLoadedSem;
+ Utils::Semaphore mSwitchToExecSem;
+ Utils::Semaphore mStopReprocSem;
+ Utils::Semaphore mUseReprocessSem;
+
+ mutable android::Mutex mStateSwitchLock;
+ mutable android::Mutex mIdleStateSwitchLock;
+
+ android::Vector<Utils::Message *> mEventSignalQ;
+ android::Mutex mEventLock;
+
+ OMX_STATETYPE mComponentState;
+
+ OMX_TI_AUTOCONVERGENCEMODETYPE mAutoConv;
+ OMX_S32 mManualConv;
+ bool mVnfEnabled;
+ bool mVstabEnabled;
+
+ int mSensorOrientation;
+ int mDeviceOrientation;
+ int mFaceOrientation;
+ bool mSensorOverclock;
+
+ //Indicates if we should leave
+ //OMX_Executing state during
+ //stop-/startPreview
+ bool mOMXStateSwitch;
+
+ int mFrameCount;
+ int mLastFrameCount;
+ unsigned int mIter;
+ nsecs_t mLastFPSTime;
+ android::Mutex mFrameCountMutex;
+ android::Condition mFirstFrameCondition;
+
+ static const nsecs_t CANCEL_AF_TIMEOUT;
+ android::Mutex mCancelAFMutex;
+ android::Condition mCancelAFCond;
+
+ android::Mutex mDoAFMutex;
+ android::Condition mDoAFCond;
+
+ size_t mSensorIndex;
+ CodingMode mCodingMode;
+
+ // Time source delta of ducati & system time
+ OMX_TICKS mTimeSourceDelta;
+ bool onlyOnce;
+
+ Utils::Semaphore mCaptureSem;
+ bool mCaptureSignalled;
+
+ OMX_BOOL mUserSetExpLock;
+ OMX_BOOL mUserSetWbLock;
+
+#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
+ bool mRawCapture;
+ bool mYuvCapture;
+#endif
+
+ bool mSetFormatDone;
+
+ OMX_TI_DCCDATATYPE mDccData;
+ android::Mutex mDccDataLock;
+
+ int mMaxZoomSupported;
+ android::Mutex mImageCaptureLock;
+
+ bool mTunnelDestroyed;
+ bool mPreviewPortInitialized;
+
+ // Used for allocations that need to be sent to Ducati
+ MemoryManager mMemMgr;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif //OMX_CAMERA_ADAPTER_H
diff --git a/camera/inc/OMXCameraAdapter/OMXDCC.h b/camera/inc/OMXCameraAdapter/OMXDCC.h
new file mode 100644
index 0000000..c75a24d
--- /dev/null
+++ b/camera/inc/OMXCameraAdapter/OMXDCC.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OMX_DCC_H
+#define OMX_DCC_H
+
+namespace Ti {
+namespace Camera {
+
+class DCCHandler
+{
+public:
+
+ status_t loadDCC(OMX_HANDLETYPE hComponent);
+
+private:
+
+ OMX_ERRORTYPE initDCC(OMX_HANDLETYPE hComponent);
+ OMX_ERRORTYPE sendDCCBufPtr(OMX_HANDLETYPE hComponent, CameraBuffer *dccBuffer);
+ size_t readDCCdir(OMX_PTR buffer, const android::Vector<android::String8 *> &dirPaths);
+
+private:
+
+ static android::String8 DCCPath;
+ static bool mDCCLoaded;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif // OMX_DCC_H
diff --git a/camera/inc/OMXCameraAdapter/OMXSceneModeTables.h b/camera/inc/OMXCameraAdapter/OMXSceneModeTables.h
new file mode 100644
index 0000000..6ac9f2b
--- /dev/null
+++ b/camera/inc/OMXCameraAdapter/OMXSceneModeTables.h
@@ -0,0 +1,759 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file OMXSceneModeTables.h
+*
+* This holds scene mode settings for different omx cameras.
+*
+*/
+
+#include "OMX_TI_IVCommon.h"
+#include "OMX_TI_Common.h"
+#include "OMX_TI_Index.h"
+
+#ifndef OMXCAMERAADAPTER_SCENEMODES_H
+#define OMXCAMERAADAPTER_SCENEMODES_H
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
+#endif
+
+namespace Ti {
+namespace Camera {
+
+struct SceneModesEntry {
+ OMX_SCENEMODETYPE scene;
+ OMX_IMAGE_FLASHCONTROLTYPE flash;
+ int focus;
+ OMX_WHITEBALCONTROLTYPE wb;
+};
+
+struct CameraToSensorModesLUTEntry {
+ const char* name;
+ const SceneModesEntry* Table;
+ const unsigned int size;
+};
+
+static const SceneModesEntry S5K4E1GA_SceneModesLUT [] = {
+ { OMX_Closeup,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoMacro,
+ OMX_WhiteBalControlAuto },
+ { OMX_Landscape,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Underwater,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoLock,
+ OMX_WhiteBalControlSunLight },
+ { OMX_Sport,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Mood,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoLock,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightPortrait,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlPortrait,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightIndoor,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Fireworks,
+ OMX_IMAGE_FlashControlOn,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Document,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlAutoMacro,
+ OMX_WhiteBalControlAuto },
+ { OMX_Barcode,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoMacro,
+ OMX_WhiteBalControlAuto },
+ { OMX_SuperNight,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Cine,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_OldFilm,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Action,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlAuto,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Beach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlAutoLock,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Candlelight,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlIncandescent },
+ { OMX_TI_Night,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlAuto,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Party,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAuto,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Portrait,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlPortrait,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Snow,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlAutoLock,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Steadyphoto,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Sunset,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlAuto,
+ OMX_WhiteBalControlSunLight },
+ { OMX_TI_Theatre,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+};
+
+static const SceneModesEntry S5K6A1GX03_SceneModesLUT [] = {
+ { OMX_Closeup,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Landscape,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Underwater,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlSunLight },
+ { OMX_Sport,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SnowBeach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Mood,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightPortrait,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightIndoor,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Fireworks,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Document,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Barcode,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SuperNight,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Cine,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_OldFilm,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Action,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Beach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Candlelight,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlIncandescent },
+ { OMX_TI_Night,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Party,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Portrait,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Snow,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Steadyphoto,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Sunset,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlSunLight },
+ { OMX_TI_Theatre,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+};
+
+static const SceneModesEntry IMX060_SceneModesLUT [] = {
+ { OMX_Closeup,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoMacro,
+ OMX_WhiteBalControlAuto },
+ { OMX_Landscape,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlSunLight },
+ { OMX_Underwater,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Sport,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SnowBeach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Mood,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightPortrait,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlPortrait,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightIndoor,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Fireworks,
+ OMX_IMAGE_FlashControlOn,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Document,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoMacro,
+ OMX_WhiteBalControlAuto },
+ { OMX_Barcode,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoMacro,
+ OMX_WhiteBalControlAuto },
+ { OMX_SuperNight,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoInfinity,
+ OMX_WhiteBalControlAuto },
+ { OMX_Cine,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_OldFilm,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Action,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Beach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Candlelight,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlIncandescent },
+ { OMX_TI_Night,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Party,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoLock,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Portrait,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Snow,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Steadyphoto,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Sunset,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ ( OMX_WHITEBALCONTROLTYPE ) OMX_TI_WhiteBalControlSunset },
+ { OMX_TI_Theatre,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+};
+
+static const SceneModesEntry OV5640_SceneModesLUT [] = {
+ { OMX_Closeup,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Landscape,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Underwater,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlSunLight },
+ { OMX_Sport,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlAutoInfinity,
+ OMX_WhiteBalControlAuto },
+ { OMX_SnowBeach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Mood,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightPortrait,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightIndoor,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Fireworks,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Document,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Barcode,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SuperNight,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Cine,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_OldFilm,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Action,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Beach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Candlelight,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlIncandescent },
+ { OMX_TI_Night,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Party,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Portrait,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Snow,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Steadyphoto,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Sunset,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Theatre,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+};
+
+static const SceneModesEntry OV5650_SceneModesLUT [] = {
+ { OMX_Closeup,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Landscape,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlSunLight },
+ { OMX_Underwater,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Sport,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SnowBeach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Mood,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightPortrait,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlPortrait,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightIndoor,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Fireworks,
+ OMX_IMAGE_FlashControlOn,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Document,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Barcode,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SuperNight,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoInfinity,
+ OMX_WhiteBalControlAuto },
+ { OMX_Cine,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_OldFilm,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Action,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Beach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Candlelight,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlIncandescent },
+ { OMX_TI_Night,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Party,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoLock,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Portrait,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Snow,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Steadyphoto,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Sunset,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ ( OMX_WHITEBALCONTROLTYPE ) OMX_TI_WhiteBalControlSunset },
+ { OMX_TI_Theatre,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+};
+
+static const SceneModesEntry OV8830_SceneModesLUT [] = {
+ { OMX_Closeup,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Landscape,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlSunLight },
+ { OMX_Underwater,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Sport,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SnowBeach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Mood,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightPortrait,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlPortrait,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightIndoor,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Fireworks,
+ OMX_IMAGE_FlashControlOn,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Document,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Barcode,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SuperNight,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoInfinity,
+ OMX_WhiteBalControlAuto },
+ { OMX_Cine,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_OldFilm,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Action,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Beach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Candlelight,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlIncandescent },
+ { OMX_TI_Night,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Party,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoLock,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Portrait,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Snow,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Steadyphoto,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Sunset,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ ( OMX_WHITEBALCONTROLTYPE ) OMX_TI_WhiteBalControlSunset },
+ { OMX_TI_Theatre,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+};
+
+static const SceneModesEntry OV2722_SceneModesLUT [] = {
+ { OMX_Closeup,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Landscape,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlSunLight },
+ { OMX_Underwater,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Sport,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SnowBeach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Mood,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightPortrait,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_NightIndoor,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Fireworks,
+ OMX_IMAGE_FlashControlOn,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Document,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_Barcode,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_SuperNight,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlAutoInfinity,
+ OMX_WhiteBalControlAuto },
+ { OMX_Cine,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_OldFilm,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Action,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Beach,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Candlelight,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlIncandescent },
+ { OMX_TI_Night,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Party,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Portrait,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Snow,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Steadyphoto,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+ { OMX_TI_Sunset,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FocusControlHyperfocal,
+ ( OMX_WHITEBALCONTROLTYPE ) OMX_TI_WhiteBalControlSunset },
+ { OMX_TI_Theatre,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FocusControlHyperfocal,
+ OMX_WhiteBalControlAuto },
+};
+
+static const CameraToSensorModesLUTEntry CameraToSensorModesLUT [] = {
+ { "S5K4E1GA", S5K4E1GA_SceneModesLUT, ARRAY_SIZE(S5K4E1GA_SceneModesLUT)},
+ { "S5K6A1GX03", S5K6A1GX03_SceneModesLUT, ARRAY_SIZE(S5K6A1GX03_SceneModesLUT)},
+ { "IMX060", IMX060_SceneModesLUT, ARRAY_SIZE(IMX060_SceneModesLUT)},
+ { "OV5640", OV5640_SceneModesLUT, ARRAY_SIZE(OV5640_SceneModesLUT)},
+ { "OV5650", OV5650_SceneModesLUT, ARRAY_SIZE(OV5650_SceneModesLUT)},
+ { "OV8830", OV8830_SceneModesLUT, ARRAY_SIZE(OV8830_SceneModesLUT)},
+ { "OV9726", OV2722_SceneModesLUT, ARRAY_SIZE(OV2722_SceneModesLUT)},
+ { "OV2722", OV2722_SceneModesLUT, ARRAY_SIZE(OV2722_SceneModesLUT)},
+#ifdef MOTOROLA_CAMERA
+ { "OV8820", OV8830_SceneModesLUT, ARRAY_SIZE(OV8830_SceneModesLUT)},
+ { "OV7739", OV2722_SceneModesLUT, ARRAY_SIZE(OV2722_SceneModesLUT)},
+ { "MT9M114", OV2722_SceneModesLUT, ARRAY_SIZE(OV2722_SceneModesLUT)},
+#endif
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif
diff --git a/camera/inc/OmxFrameDecoder.h b/camera/inc/OmxFrameDecoder.h
new file mode 100644
index 0000000..7cbbf2c
--- /dev/null
+++ b/camera/inc/OmxFrameDecoder.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OMXFRAMEDECODER_H_
+#define OMXFRAMEDECODER_H_
+
+
+#include <utils/threads.h>
+#include <utils/List.h>
+#include "FrameDecoder.h"
+#include "OMX_Types.h"
+#include "OMX_Core.h"
+#include "OMX_Component.h"
+#include "Decoder_libjpeg.h"
+
+namespace Ti {
+namespace Camera {
+
+enum OmxDecoderState {
+ OmxDecoderState_Unloaded = 0,
+ OmxDecoderState_Loaded,
+ OmxDecoderState_Idle,
+ OmxDecoderState_Executing,
+ OmxDecoderState_Error,
+ OmxDecoderState_Invalid,
+ OmxDecoderState_Reconfigure,
+ OmxDecoderState_Exit
+};
+
+enum PortType {
+ PortIndexInput = 0,
+ PortIndexOutput = 1
+};
+
+
+struct OmxMessage {
+ enum {
+ EVENT,
+ EMPTY_BUFFER_DONE,
+ FILL_BUFFER_DONE,
+ }type;
+
+ union {
+ // if type == EVENT
+ struct {
+ OMX_PTR appData;
+ OMX_EVENTTYPE event;
+ OMX_U32 data1;
+ OMX_U32 data2;
+ OMX_PTR pEventData;
+ } eventData;
+
+ // if type == (EMPTY_BUFFER_DONE || FILL_BUFFER_DONE)
+ struct {
+ OMX_PTR appData;
+ OMX_BUFFERHEADERTYPE* pBuffHead;
+ } bufferData;
+ } u;
+};
+
+class CallbackDispatcher;
+
+struct CallbackDispatcherThread : public android::Thread {
+ CallbackDispatcherThread(CallbackDispatcher *dispatcher)
+ : mDispatcher(dispatcher) {
+ }
+
+private:
+ CallbackDispatcher *mDispatcher;
+
+ bool threadLoop();
+
+ CallbackDispatcherThread(const CallbackDispatcherThread &);
+ CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
+};
+
+class CallbackDispatcher
+{
+
+public:
+ CallbackDispatcher();
+ ~CallbackDispatcher();
+
+ void post(const OmxMessage &msg);
+ bool loop();
+
+private:
+ void dispatch(const OmxMessage &msg);
+
+ CallbackDispatcher(const CallbackDispatcher &);
+ CallbackDispatcher &operator=(const CallbackDispatcher &);
+
+ android::Mutex mLock;
+ android::Condition mQueueChanged;
+ android::List<OmxMessage> mQueue;
+ android::sp<CallbackDispatcherThread> mThread;
+ bool mDone;
+};
+
+class OmxFrameDecoder : public FrameDecoder
+{
+
+public:
+ OmxFrameDecoder(DecoderType type = DecoderType_MJPEG);
+ virtual ~OmxFrameDecoder();
+
+ OMX_ERRORTYPE eventHandler(const OMX_EVENTTYPE event, const OMX_U32 data1, const OMX_U32 data2,
+ const OMX_PTR pEventData);
+ OMX_ERRORTYPE fillBufferDoneHandler(OMX_BUFFERHEADERTYPE* pBuffHead);
+ OMX_ERRORTYPE emptyBufferDoneHandler(OMX_BUFFERHEADERTYPE* pBuffHead);
+
+ static OMX_ERRORTYPE eventCallback(const OMX_HANDLETYPE component,
+ const OMX_PTR appData, const OMX_EVENTTYPE event, const OMX_U32 data1, const OMX_U32 data2,
+ const OMX_PTR pEventData);
+ static OMX_ERRORTYPE emptyBufferDoneCallback(OMX_HANDLETYPE hComponent, OMX_PTR appData, OMX_BUFFERHEADERTYPE* pBuffHead);
+ static OMX_ERRORTYPE fillBufferDoneCallback(OMX_HANDLETYPE hComponent, OMX_PTR appData, OMX_BUFFERHEADERTYPE* pBuffHead);
+
+ virtual bool getPaddedDimensions(size_t &width, size_t &height);
+
+protected:
+ virtual void doConfigure (const DecoderParameters& config);
+ virtual void doProcessInputBuffer();
+ virtual status_t doStart();
+ virtual void doStop();
+ virtual void doFlush();
+ virtual void doRelease();
+
+private:
+ status_t setComponentRole();
+ status_t enableGrallockHandles();
+ status_t allocateBuffersOutput();
+ void freeBuffersOnOutput();
+ void freeBuffersOnInput();
+ status_t doPortReconfigure();
+ void dumpPortSettings(PortType port);
+ status_t getAndConfigureDecoder();
+ status_t configureJpegPorts(int width, int height);
+ status_t switchToIdle();
+ status_t allocateBuffersInput();
+ status_t disablePortSync(int port);
+ status_t enablePortSync(int port);
+ void queueOutputBuffers();
+ status_t setVideoOutputFormat(OMX_U32 width, OMX_U32 height);
+
+
+ status_t omxInit();
+ status_t omxGetHandle(OMX_HANDLETYPE *handle, OMX_PTR pAppData, OMX_CALLBACKTYPE & callbacks);
+ OmxDecoderState getOmxState() { return mCurrentState; }
+ status_t commitState(OmxDecoderState state) { mPreviousState = mCurrentState; mCurrentState = state; return NO_ERROR; }
+ status_t setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat);
+ status_t omxGetParameter(OMX_INDEXTYPE index, OMX_PTR ptr);
+ status_t omxSetParameter(OMX_INDEXTYPE index, OMX_PTR ptr);
+ status_t omxSendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param);
+ status_t omxGetConfig(OMX_INDEXTYPE index, OMX_PTR ptr);
+ status_t omxSetConfig(OMX_INDEXTYPE index, OMX_PTR ptr);
+ status_t omxFillThisBuffer(OMX_BUFFERHEADERTYPE *pOutBufHdr);
+ status_t omxEmptyThisBuffer(android::sp<MediaBuffer>& inBuffer, OMX_BUFFERHEADERTYPE *pInBufHdr);
+ void omxDumpPortSettings(OMX_PARAM_PORTDEFINITIONTYPE& def);
+ void omxDumpBufferHeader (OMX_BUFFERHEADERTYPE* bh);
+ status_t omxSwitchToExecutingSync();
+
+ bool mOmxInialized;
+
+ OMX_HANDLETYPE mHandleComp;
+ OmxDecoderState mCurrentState;
+ OmxDecoderState mPreviousState;
+
+ // Condition and Mutex used during OpenMAX state transitions & command completion
+ android::Condition mStateCondition;
+ android::Mutex mHwLock;
+
+ android::Vector<OMX_BUFFERHEADERTYPE*> mOutBufferHeaders;
+ android::Vector<OMX_BUFFERHEADERTYPE*> mInBufferHeaders;
+
+ CallbackDispatcher mDispatcher;
+
+ bool mStopping;
+ DecoderType mDecoderType;
+
+ // If true we will search for DHT in JPEG buffer
+ bool mIsNeedCheckDHT;
+ // If true we always append DHT to JPEG buffer
+ bool mAlwaysAppendDHT;
+};
+
+} //namespace Camera
+} //namespace Ti
+#endif /* OMXFRAMEDECODER_H_ */
diff --git a/camera/inc/SensorListener.h b/camera/inc/SensorListener.h
new file mode 100644
index 0000000..44037b7
--- /dev/null
+++ b/camera/inc/SensorListener.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @file SensorListener.h
+*
+* This defines API for camerahal to get sensor events
+*
+*/
+
+#ifndef ANDROID_CAMERA_HARDWARE_SENSOR_LISTENER_H
+#define ANDROID_CAMERA_HARDWARE_SENSOR_LISTENER_H
+
+#include <android/sensor.h>
+#include <gui/Sensor.h>
+#include <gui/SensorManager.h>
+#include <gui/SensorEventQueue.h>
+#include <utils/Looper.h>
+
+#include "Common.h"
+
+namespace Ti {
+namespace Camera {
+
+/**
+ * SensorListner class - Registers with sensor manager to get sensor events
+ */
+
+typedef void (*orientation_callback_t) (uint32_t orientation, uint32_t tilt, void* cookie);
+
+class SensorLooperThread : public android::Thread {
+ public:
+ SensorLooperThread(android::Looper* looper)
+ : Thread(false) {
+ mLooper = android::sp<android::Looper>(looper);
+ }
+ ~SensorLooperThread() {
+ mLooper.clear();
+ }
+
+ virtual bool threadLoop() {
+ int32_t ret = mLooper->pollOnce(-1);
+ return true;
+ }
+
+ // force looper wake up
+ void wake() {
+ mLooper->wake();
+ }
+ private:
+ android::sp<android::Looper> mLooper;
+};
+
+
+class SensorListener : public android::RefBase
+{
+/* public - types */
+public:
+ typedef enum {
+ SENSOR_ACCELEROMETER = 1 << 0,
+ SENSOR_MAGNETIC_FIELD = 1 << 1,
+ SENSOR_GYROSCOPE = 1 << 2,
+ SENSOR_LIGHT = 1 << 3,
+ SENSOR_PROXIMITY = 1 << 4,
+ SENSOR_ORIENTATION = 1 << 5,
+ } sensor_type_t;
+/* public - functions */
+public:
+ SensorListener();
+ ~SensorListener();
+ status_t initialize();
+ void setCallbacks(orientation_callback_t orientation_cb, void *cookie);
+ void enableSensor(sensor_type_t type);
+ void disableSensor(sensor_type_t type);
+ void handleOrientation(uint32_t orientation, uint32_t tilt);
+/* public - member variables */
+public:
+ android::sp<android::SensorEventQueue> mSensorEventQueue;
+/* private - member variables */
+private:
+ int sensorsEnabled;
+ orientation_callback_t mOrientationCb;
+ void *mCbCookie;
+ android::sp<android::Looper> mLooper;
+ android::sp<SensorLooperThread> mSensorLooperThread;
+ android::Mutex mLock;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif
diff --git a/camera/inc/SwFrameDecoder.h b/camera/inc/SwFrameDecoder.h
new file mode 100644
index 0000000..f123940
--- /dev/null
+++ b/camera/inc/SwFrameDecoder.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SWFRAMEDECODER_H_
+#define SWFRAMEDECODER_H_
+
+#include "FrameDecoder.h"
+#include "Decoder_libjpeg.h"
+
+namespace Ti {
+namespace Camera {
+
+class SwFrameDecoder: public FrameDecoder {
+public:
+ SwFrameDecoder();
+ virtual ~SwFrameDecoder();
+
+protected:
+ virtual void doConfigure(const DecoderParameters& config);
+ virtual void doProcessInputBuffer();
+ virtual status_t doStart() { return NO_ERROR; }
+ virtual void doStop() { }
+ virtual void doFlush() { }
+ virtual void doRelease() { }
+
+private:
+ int mjpegWithHdrSize;
+ Decoder_libjpeg mJpgdecoder;
+ unsigned char* mJpegWithHeaderBuffer;
+};
+
+} // namespace Camera
+} // namespace Ti
+#endif /* SWFRAMEDECODER_H_ */
diff --git a/camera/inc/TICameraParameters.h b/camera/inc/TICameraParameters.h
new file mode 100644
index 0000000..8686456
--- /dev/null
+++ b/camera/inc/TICameraParameters.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TI_CAMERA_PARAMETERS_H
+#define TI_CAMERA_PARAMETERS_H
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace Ti {
+namespace Camera {
+
+///TI Specific Camera Parameters
+class TICameraParameters
+{
+public:
+
+// Supported Camera indexes
+// Example value: "0,1,2,3", where 0-primary, 1-secondary1, 2-secondary2, 3-sterocamera
+static const char KEY_SUPPORTED_CAMERAS[];
+// Select logical Camera index
+static const char KEY_CAMERA[];
+static const char KEY_CAMERA_NAME[];
+static const char KEY_BURST[];
+static const char KEY_CAP_MODE[];
+static const char KEY_CAP_MODE_VALUES[];
+static const char KEY_VNF[];
+static const char KEY_VNF_SUPPORTED[];
+static const char KEY_SATURATION[];
+static const char KEY_BRIGHTNESS[];
+static const char KEY_SUPPORTED_EXPOSURE[];
+static const char KEY_EXPOSURE_MODE[];
+static const char KEY_SUPPORTED_MANUAL_EXPOSURE_MIN[];
+static const char KEY_SUPPORTED_MANUAL_EXPOSURE_MAX[];
+static const char KEY_SUPPORTED_MANUAL_EXPOSURE_STEP[];
+static const char KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN[];
+static const char KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX[];
+static const char KEY_SUPPORTED_MANUAL_GAIN_ISO_STEP[];
+static const char KEY_MANUAL_EXPOSURE[];
+static const char KEY_MANUAL_EXPOSURE_RIGHT[];
+static const char KEY_MANUAL_GAIN_ISO[];
+static const char KEY_MANUAL_GAIN_ISO_RIGHT[];
+static const char KEY_CONTRAST[];
+static const char KEY_SHARPNESS[];
+static const char KEY_ISO[];
+static const char KEY_SUPPORTED_ISO_VALUES[];
+static const char KEY_SUPPORTED_IPP[];
+static const char KEY_IPP[];
+static const char KEY_METERING_MODE[];
+static const char KEY_EXP_BRACKETING_RANGE[];
+static const char KEY_EXP_GAIN_BRACKETING_RANGE[];
+static const char KEY_ZOOM_BRACKETING_RANGE[];
+static const char KEY_TEMP_BRACKETING[];
+static const char KEY_TEMP_BRACKETING_RANGE_POS[];
+static const char KEY_TEMP_BRACKETING_RANGE_NEG[];
+static const char KEY_FLUSH_SHOT_CONFIG_QUEUE[];
+static const char KEY_SHUTTER_ENABLE[];
+static const char KEY_MEASUREMENT_ENABLE[];
+static const char KEY_INITIAL_VALUES[];
+static const char KEY_GBCE[];
+static const char KEY_GBCE_SUPPORTED[];
+static const char KEY_GLBCE[];
+static const char KEY_GLBCE_SUPPORTED[];
+static const char KEY_FRAMERATE_RANGES_EXT_SUPPORTED[];
+static const char KEY_FRAMERATES_EXT_SUPPORTED[];
+
+// TI recording hint to notify camera adapters of possible recording
+static const char KEY_RECORDING_HINT[];
+static const char KEY_AUTO_FOCUS_LOCK[];
+static const char KEY_CURRENT_ISO[];
+
+static const char KEY_SENSOR_ORIENTATION[];
+
+//TI extensions for camera capabilies
+static const char INITIAL_VALUES_TRUE[];
+static const char INITIAL_VALUES_FALSE[];
+
+// TI extensions to add values for ManualConvergence and AutoConvergence mode
+static const char KEY_AUTOCONVERGENCE_MODE[];
+static const char KEY_AUTOCONVERGENCE_MODE_VALUES[];
+static const char KEY_MANUAL_CONVERGENCE[];
+static const char KEY_SUPPORTED_MANUAL_CONVERGENCE_MIN[];
+static const char KEY_SUPPORTED_MANUAL_CONVERGENCE_MAX[];
+static const char KEY_SUPPORTED_MANUAL_CONVERGENCE_STEP[];
+
+// TI extensions to add Min frame rate Values
+static const char VIDEO_MINFRAMERATE_5[];
+static const char VIDEO_MINFRAMERATE_10[];
+static const char VIDEO_MINFRAMERATE_15[];
+static const char VIDEO_MINFRAMERATE_20[];
+static const char VIDEO_MINFRAMERATE_24[];
+static const char VIDEO_MINFRAMERATE_25[];
+static const char VIDEO_MINFRAMERATE_30[];
+static const char VIDEO_MINFRAMERATE_33[];
+
+//TI extensions for setting EXIF tags
+static const char KEY_EXIF_MODEL[];
+static const char KEY_EXIF_MAKE[];
+
+//TI extensions for additional GPS data
+static const char KEY_GPS_MAPDATUM[];
+static const char KEY_GPS_VERSION[];
+static const char KEY_GPS_DATESTAMP[];
+
+// TI extensions for VTC
+static const char KEY_VTC_HINT[];
+static const char KEY_VIDEO_ENCODER_HANDLE[];
+static const char KEY_VIDEO_ENCODER_SLICE_HEIGHT[];
+
+static const char RAW_WIDTH[];
+static const char RAW_HEIGHT[];
+
+//TI extensions to Image post-processing
+static const char IPP_LDCNSF[];
+static const char IPP_LDC[];
+static const char IPP_NSF[];
+static const char IPP_NONE[];
+
+//TI extensions to camera mode
+static const char HIGH_PERFORMANCE_MODE[];
+static const char HIGH_QUALITY_MODE[];
+static const char HIGH_QUALITY_ZSL_MODE[];
+static const char CP_CAM_MODE[];
+static const char VIDEO_MODE[];
+static const char VIDEO_MODE_HQ[];
+static const char EXPOSURE_BRACKETING[];
+static const char ZOOM_BRACKETING[];
+static const char TEMP_BRACKETING[];
+
+// TI extensions to standard android pixel formats
+static const char PIXEL_FORMAT_UNUSED[];
+static const char PIXEL_FORMAT_JPS[];
+static const char PIXEL_FORMAT_MPO[];
+static const char PIXEL_FORMAT_YUV422I_UYVY[];
+
+// TI extensions to standard android scene mode settings
+static const char SCENE_MODE_CLOSEUP[];
+static const char SCENE_MODE_AQUA[];
+static const char SCENE_MODE_SNOWBEACH[];
+static const char SCENE_MODE_MOOD[];
+static const char SCENE_MODE_NIGHT_INDOOR[];
+static const char SCENE_MODE_DOCUMENT[];
+static const char SCENE_MODE_BARCODE[];
+static const char SCENE_MODE_VIDEO_SUPER_NIGHT[];
+static const char SCENE_MODE_VIDEO_CINE[];
+static const char SCENE_MODE_VIDEO_OLD_FILM[];
+
+// TI extensions to standard android white balance settings.
+static const char WHITE_BALANCE_TUNGSTEN[];
+static const char WHITE_BALANCE_HORIZON[];
+static const char WHITE_BALANCE_SUNSET[];
+static const char WHITE_BALANCE_FACE[];
+
+// TI extensions to add exposure preset modes to android api
+static const char EXPOSURE_MODE_MANUAL[];
+static const char EXPOSURE_MODE_AUTO[];
+static const char EXPOSURE_MODE_NIGHT[];
+static const char EXPOSURE_MODE_BACKLIGHT[];
+static const char EXPOSURE_MODE_SPOTLIGHT[];
+static const char EXPOSURE_MODE_SPORTS[];
+static const char EXPOSURE_MODE_SNOW[];
+static const char EXPOSURE_MODE_BEACH[];
+static const char EXPOSURE_MODE_APERTURE[];
+static const char EXPOSURE_MODE_SMALL_APERTURE[];
+static const char EXPOSURE_MODE_FACE[];
+
+// TI extensions to standard android focus presets.
+static const char FOCUS_MODE_PORTRAIT[];
+static const char FOCUS_MODE_EXTENDED[];
+static const char FOCUS_MODE_FACE[];
+static const char FOCUS_MODE_OFF[];
+
+// TI extensions to add iso values
+static const char ISO_MODE_AUTO[];
+static const char ISO_MODE_100[];
+static const char ISO_MODE_200[];
+static const char ISO_MODE_400[];
+static const char ISO_MODE_800[];
+static const char ISO_MODE_1000[];
+static const char ISO_MODE_1200[];
+static const char ISO_MODE_1600[];
+
+// TI extensions to add values for effect settings.
+static const char EFFECT_NATURAL[];
+static const char EFFECT_VIVID[];
+static const char EFFECT_COLOR_SWAP[];
+static const char EFFECT_BLACKWHITE[];
+
+//TI extensions for stereo frame layouts
+static const char KEY_S3D_PRV_FRAME_LAYOUT[];
+static const char KEY_S3D_PRV_FRAME_LAYOUT_VALUES[];
+static const char KEY_S3D_CAP_FRAME_LAYOUT[];
+static const char KEY_S3D_CAP_FRAME_LAYOUT_VALUES[];
+
+//TI extensions for stereo frame layouts
+static const char S3D_NONE[];
+static const char S3D_TB_FULL[];
+static const char S3D_SS_FULL[];
+static const char S3D_TB_SUBSAMPLED[];
+static const char S3D_SS_SUBSAMPLED[];
+
+//TI extentions fo 3D resolutions
+static const char KEY_SUPPORTED_PICTURE_SUBSAMPLED_SIZES[];
+static const char KEY_SUPPORTED_PICTURE_TOPBOTTOM_SIZES[];
+static const char KEY_SUPPORTED_PICTURE_SIDEBYSIDE_SIZES[];
+static const char KEY_SUPPORTED_PREVIEW_SUBSAMPLED_SIZES[];
+static const char KEY_SUPPORTED_PREVIEW_TOPBOTTOM_SIZES[];
+static const char KEY_SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES[];
+
+// TI extensions to add values for AutoConvergence settings.
+static const char AUTOCONVERGENCE_MODE_DISABLE[];
+static const char AUTOCONVERGENCE_MODE_FRAME[];
+static const char AUTOCONVERGENCE_MODE_CENTER[];
+static const char AUTOCONVERGENCE_MODE_TOUCH[];
+static const char AUTOCONVERGENCE_MODE_MANUAL[];
+
+//TI extensions for flash mode settings
+static const char FLASH_MODE_FILL_IN[];
+
+//TI extensions to add sensor orientation parameters
+static const char ORIENTATION_SENSOR_NONE[];
+static const char ORIENTATION_SENSOR_90[];
+static const char ORIENTATION_SENSOR_180[];
+static const char ORIENTATION_SENSOR_270[];
+
+
+//TI values for camera direction
+static const char FACING_FRONT[];
+static const char FACING_BACK[];
+
+static const char KEY_MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED[];
+static const char KEY_MECHANICAL_MISALIGNMENT_CORRECTION[];
+
+//TI extensions for enable/disable algos
+static const char KEY_ALGO_EXTERNAL_GAMMA[];
+static const char KEY_ALGO_NSF1[];
+static const char KEY_ALGO_NSF2[];
+static const char KEY_ALGO_SHARPENING[];
+static const char KEY_ALGO_THREELINCOLORMAP[];
+static const char KEY_ALGO_GIC[];
+
+//Gamma table
+static const char KEY_GAMMA_TABLE[];
+
+static const char KEY_PREVIEW_FRAME_RATE_RANGE[];
+
+#ifdef MOTOROLA_CAMERA
+static const char KEY_MOT_LEDFLASH[];
+static const char KEY_MOT_LEDTORCH[];
+#endif
+
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif
diff --git a/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h b/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h
new file mode 100644
index 0000000..e1e7cad
--- /dev/null
+++ b/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+
+#ifndef V4L_CAMERA_ADAPTER_H
+#define V4L_CAMERA_ADAPTER_H
+
+#include <linux/videodev2.h>
+
+#include "CameraHal.h"
+#include "BaseCameraAdapter.h"
+#include "DebugUtils.h"
+#include "Decoder_libjpeg.h"
+#include "FrameDecoder.h"
+
+
+namespace Ti {
+namespace Camera {
+
+#ifndef V4L2_PIX_FMT_H264
+#define V4L2_PIX_FMT_H264 0
+#endif
+
+#define DEFAULT_PIXEL_FORMAT V4L2_PIX_FMT_YUYV
+#define DEFAULT_CAPTURE_FORMAT V4L2_PIX_FMT_YUYV
+
+#define NB_BUFFER 10
+#define DEVICE "/dev/videoxx"
+#define DEVICE_PATH "/dev/"
+#define DEVICE_NAME "videoxx"
+
+typedef int V4L_HANDLETYPE;
+
+struct CapPixelformat {
+ uint32_t pixelformat;
+ const char *param;
+};
+
+struct CapResolution {
+ size_t width, height;
+ char param[10];
+};
+
+struct CapU32 {
+ uint32_t num;
+ const char *param;
+};
+
+typedef CapU32 CapFramerate;
+
+struct VideoInfo {
+ struct v4l2_capability cap;
+ struct v4l2_format format;
+ struct v4l2_buffer buf;
+ struct v4l2_requestbuffers rb;
+ void *mem[NB_BUFFER];
+ void *CaptureBuffers[NB_BUFFER];
+ bool isStreaming;
+ int width;
+ int height;
+ int formatIn;
+ int framesizeIn;
+};
+
+typedef struct V4L_TI_CAPTYPE {
+ uint16_t ulPreviewFormatCount; // supported preview pixelformat count
+ uint32_t ePreviewFormats[32];
+ uint16_t ulPreviewResCount; // supported preview resolution sizes
+ CapResolution tPreviewRes[32];
+ uint16_t ulCaptureResCount; // supported capture resolution sizes
+ CapResolution tCaptureRes[32];
+ uint16_t ulFrameRateCount; // supported frame rate
+ uint16_t ulFrameRates[32];
+}V4L_TI_CAPTYPE;
+
+/**
+ * Class which completely abstracts the camera hardware interaction from camera hal
+ * TODO: Need to list down here, all the message types that will be supported by this class
+ Need to implement BufferProvider interface to use AllocateBuffer of OMX if needed
+ */
+class V4LCameraAdapter : public BaseCameraAdapter
+{
+public:
+
+ /*--------------------Constant declarations----------------------------------------*/
+ static const int32_t MAX_NO_BUFFERS = 20;
+
+ ///@remarks OMX Camera has six ports - buffer input, time input, preview, image, video, and meta data
+ static const int MAX_NO_PORTS = 6;
+
+ ///Five second timeout
+ static const int CAMERA_ADAPTER_TIMEOUT = 5000*1000;
+
+public:
+
+ V4LCameraAdapter(size_t sensor_index, CameraHal* hal);
+ ~V4LCameraAdapter();
+
+
+ ///Initialzes the camera adapter creates any resources required
+ virtual status_t initialize(CameraProperties::Properties*);
+
+ //APIs to configure Camera adapter and get the current parameter set
+ virtual status_t setParameters(const android::CameraParameters& params);
+ virtual void getParameters(android::CameraParameters& params);
+
+ // API
+ virtual status_t UseBuffersPreview(CameraBuffer *bufArr, int num);
+ virtual status_t UseBuffersCapture(CameraBuffer *bufArr, int num);
+
+ static status_t getCaps(const int sensorId, CameraProperties::Properties* params, V4L_HANDLETYPE handle);
+
+ void setupWorkingMode();
+
+protected:
+
+//----------Parent class method implementation------------------------------------
+ virtual status_t startPreview();
+ virtual status_t stopPreview();
+ virtual status_t takePicture();
+ virtual status_t stopImageCapture();
+ virtual status_t autoFocus();
+ virtual status_t useBuffers(CameraMode mode, CameraBuffer *bufArr, int num, size_t length, unsigned int queueable);
+ virtual status_t fillThisBuffer(CameraBuffer *frameBuf, CameraFrame::FrameType frameType);
+ virtual status_t getFrameSize(size_t &width, size_t &height);
+ virtual status_t getPictureBufferSize(CameraFrame &frame, size_t bufferCount);
+ virtual status_t getFrameDataSize(size_t &dataFrameSize, size_t bufferCount);
+ virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt);
+//-----------------------------------------------------------------------------
+
+
+private:
+
+ class PreviewThread : public android::Thread {
+ V4LCameraAdapter* mAdapter;
+ public:
+ PreviewThread(V4LCameraAdapter* hw) :
+ Thread(false), mAdapter(hw) { }
+ virtual void onFirstRef() {
+ run("CameraPreviewThread", android::PRIORITY_URGENT_DISPLAY);
+ }
+ virtual bool threadLoop() {
+ mAdapter->previewThread();
+ // loop until we need to quit
+ return true;
+ }
+ };
+
+ //Used for calculation of the average frame rate during preview
+ status_t recalculateFPS();
+
+ char * GetFrame(int &index, int &filledLen);
+
+ int previewThread();
+
+private:
+ //capabilities data
+ static const CapPixelformat mPixelformats [];
+ static const CapResolution mPreviewRes [];
+ static const CapFramerate mFramerates [];
+ static const CapResolution mImageCapRes [];
+
+ //camera defaults
+ static const char DEFAULT_PREVIEW_FORMAT[];
+ static const char DEFAULT_PREVIEW_SIZE[];
+ static const char DEFAULT_FRAMERATE[];
+ static const char DEFAULT_NUM_PREV_BUFS[];
+
+ static const char DEFAULT_PICTURE_FORMAT[];
+ static const char DEFAULT_PICTURE_SIZE[];
+ static const char DEFAULT_FOCUS_MODE[];
+ static const char DEFAULT_FRAMERATE_RANGE[];
+ static const char * DEFAULT_VSTAB;
+ static const char * DEFAULT_VNF;
+
+ static status_t insertDefaults(CameraProperties::Properties*, V4L_TI_CAPTYPE&);
+ static status_t insertCapabilities(CameraProperties::Properties*, V4L_TI_CAPTYPE&);
+ static status_t insertPreviewFormats(CameraProperties::Properties* , V4L_TI_CAPTYPE&);
+ static status_t insertPreviewSizes(CameraProperties::Properties* , V4L_TI_CAPTYPE&);
+ static status_t insertImageSizes(CameraProperties::Properties* , V4L_TI_CAPTYPE&);
+ static status_t insertFrameRates(CameraProperties::Properties* , V4L_TI_CAPTYPE&);
+ static status_t sortAscend(V4L_TI_CAPTYPE&, uint16_t ) ;
+
+ status_t v4lIoctl(int, int, void*);
+ status_t v4lInitMmap(int& count, int width, int height);
+ status_t v4lInitUsrPtr(int&);
+ status_t v4lStartStreaming();
+ status_t v4lStopStreaming(int nBufferCount);
+ status_t v4lSetFormat(int, int, uint32_t);
+ status_t restartPreview();
+ status_t applyFpsValue();
+ status_t returnBufferToV4L(int id);
+ void returnOutputBuffer(int index);
+ bool isNeedToUseDecoder() const;
+
+ int mPreviewBufferCount;
+ int mPreviewBufferCountQueueable;
+ int mCaptureBufferCount;
+ int mCaptureBufferCountQueueable;
+ CameraBuffer *mPreviewBufs[NB_BUFFER];
+ android::KeyedVector<CameraBuffer *, int> mCaptureBufs;
+
+ android::CameraParameters mParams;
+
+ bool mPreviewing;
+ bool mCapturing;
+ mutable android::Mutex mLock;
+
+ int mFrameCount;
+ int mLastFrameCount;
+ unsigned int mIter;
+ nsecs_t mLastFPSTime;
+
+ //variables holding the estimated framerate
+ float mFPS, mLastFPS;
+
+ int mSensorIndex;
+
+ // protected by mLock
+ android::sp<PreviewThread> mPreviewThread;
+
+ struct VideoInfo *mVideoInfo;
+ int mCameraHandle;
+
+ int nQueued;
+ int nDequeued;
+ int mQueuedOutputBuffers;
+
+ FrameDecoder* mDecoder;
+ android::Vector< android::sp<MediaBuffer> > mInBuffers;
+ android::Vector< android::sp<MediaBuffer> > mOutBuffers;
+
+ android::Mutex mV4LLock;
+
+ int mPixelFormat;
+ int mFrameRate;
+
+ android::Mutex mStopLock;
+ android::Condition mStopCondition;
+
+ CameraHal* mCameraHal;
+ int mSkipFramesCount;
+};
+
+} // namespace Camera
+} // namespace Ti
+
+#endif //V4L_CAMERA_ADAPTER_H
diff --git a/camera/inc/VideoMetadata.h b/camera/inc/VideoMetadata.h
new file mode 100644
index 0000000..f05ee50
--- /dev/null
+++ b/camera/inc/VideoMetadata.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Texas Instruments - http://www.ti.com/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VIDEO_METADATA_H
+#define VIDEO_METADATA_H
+
+/* This structure is used to pass buffer offset from Camera-Hal to Encoder component
+ * for specific algorithms like VSTAB & VNF
+ */
+
+typedef struct
+{
+ int metadataBufferType;
+ void* handle;
+ int offset;
+}
+video_metadata_t;
+
+#endif