summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk34
-rw-r--r--CleanSpec.mk55
-rw-r--r--MODULE_LICENSE_APACHE20
-rwxr-xr-xcamera/ANativeWindowDisplayAdapter.cpp1096
-rw-r--r--camera/Android.mk131
-rw-r--r--camera/AppCallbackNotifier.cpp1399
-rw-r--r--camera/BaseCameraAdapter.cpp1969
-rwxr-xr-xcamera/CameraHal.cpp3030
-rw-r--r--camera/CameraHalCommon.cpp121
-rw-r--r--camera/CameraHalUtilClasses.cpp273
-rw-r--r--camera/CameraHal_Module.cpp676
-rw-r--r--camera/CameraParameters.cpp184
-rw-r--r--camera/CameraProperties.cpp125
-rw-r--r--camera/MemoryManager.cpp284
-rw-r--r--camera/OMXCameraAdapter/OMX3A.cpp1083
-rw-r--r--camera/OMXCameraAdapter/OMXAlgo.cpp1181
-rw-r--r--camera/OMXCameraAdapter/OMXCameraAdapter.cpp3160
-rw-r--r--camera/OMXCameraAdapter/OMXCapabilities.cpp1181
-rw-r--r--camera/OMXCameraAdapter/OMXCapture.cpp1066
-rw-r--r--camera/OMXCameraAdapter/OMXDefaults.cpp71
-rw-r--r--camera/OMXCameraAdapter/OMXExif.cpp567
-rw-r--r--camera/OMXCameraAdapter/OMXFD.cpp327
-rw-r--r--camera/OMXCameraAdapter/OMXFocus.cpp673
-rw-r--r--camera/OMXCameraAdapter/OMXZoom.cpp270
-rw-r--r--camera/SensorListener.cpp232
-rw-r--r--camera/TICameraParameters.cpp202
-rw-r--r--camera/V4LCameraAdapter/V4LCameraAdapter.cpp615
-rw-r--r--camera/inc/ANativeWindowDisplayAdapter.h188
-rw-r--r--camera/inc/BaseCameraAdapter.h245
-rw-r--r--camera/inc/CameraHal.h1144
-rw-r--r--camera/inc/CameraProperties.h180
-rw-r--r--camera/inc/General3A_Settings.h262
-rw-r--r--camera/inc/OMXCameraAdapter/OMXCameraAdapter.h834
-rw-r--r--camera/inc/SensorListener.h101
-rw-r--r--camera/inc/TICameraParameters.h241
-rw-r--r--camera/inc/V4LCameraAdapter/V4LCameraAdapter.h158
-rw-r--r--camera/inc/VideoMetadata.h32
-rw-r--r--heaptracked-executable.mk7
-rw-r--r--heaptracked-shared-library.mk7
-rw-r--r--heaptracker.c576
-rw-r--r--hwc/Android.mk19
-rw-r--r--hwc/hal_public.h162
-rw-r--r--hwc/hwc.c693
-rw-r--r--ion/Android.mk20
-rw-r--r--ion/ion.c156
-rw-r--r--ion/ion.h35
-rw-r--r--ion/ion_test.c321
-rw-r--r--libstagefrighthw/Android.mk23
-rw-r--r--libstagefrighthw/TIOMXPlugin.cpp152
-rw-r--r--libstagefrighthw/TIOMXPlugin.h76
-rwxr-xr-xlibtiutils/Android.mk35
-rw-r--r--libtiutils/DebugUtils.h36
-rw-r--r--libtiutils/ErrorUtils.cpp141
-rw-r--r--libtiutils/ErrorUtils.h52
-rwxr-xr-xlibtiutils/MessageQueue.cpp397
-rwxr-xr-xlibtiutils/MessageQueue.h105
-rw-r--r--libtiutils/Semaphore.cpp226
-rw-r--r--libtiutils/Semaphore.h59
-rw-r--r--libyv12colorconvert/Android.mk21
-rw-r--r--libyv12colorconvert/ColorConvert.cpp114
-rw-r--r--mapinfo.c106
-rw-r--r--mapinfo.h16
-rw-r--r--omap4.mk33
-rw-r--r--stacktrace.c75
-rw-r--r--test/CameraHal/Android.mk38
-rw-r--r--test/CameraHal/camera_test.h165
-rw-r--r--test/CameraHal/camera_test_menu.cpp2522
-rw-r--r--test/CameraHal/camera_test_script.cpp1373
-rw-r--r--tiler/.gitignore27
-rw-r--r--tiler/Android.mk33
-rw-r--r--tiler/Makefile.am80
-rw-r--r--tiler/README136
-rwxr-xr-xtiler/bootstrap.sh18
-rwxr-xr-xtiler/configure.ac75
-rw-r--r--tiler/debug_utils.h211
-rwxr-xr-xtiler/fill_utr.py92
-rw-r--r--tiler/libtimemmgr.pc.in13
-rw-r--r--tiler/list_utils.h511
-rw-r--r--tiler/mem_types.h101
-rw-r--r--tiler/memmgr.c1078
-rw-r--r--tiler/memmgr.h311
-rw-r--r--tiler/memmgr_test.c1693
-rw-r--r--tiler/testlib.c163
-rw-r--r--tiler/testlib.h101
-rw-r--r--tiler/tiler.h105
-rw-r--r--tiler/tiler_ptest.c729
-rw-r--r--tiler/tilermem.h79
-rw-r--r--tiler/tilermem_utils.h52
-rw-r--r--tiler/tilermgr.c203
-rw-r--r--tiler/tilermgr.h54
-rw-r--r--tiler/utils.h63
-rw-r--r--tiler/utils_test.c489
-rw-r--r--tm.c54
93 files changed, 37622 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..2729bab
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,34 @@
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+
+LOCAL_PATH:= $(call my-dir)
+HARDWARE_TI_OMAP4_BASE:= $(LOCAL_PATH)
+OMAP4_DEBUG_MEMLEAK:= false
+
+ifeq ($(OMAP4_DEBUG_MEMLEAK),true)
+
+OMAP4_DEBUG_CFLAGS:= -DHEAPTRACKER
+OMAP4_DEBUG_LDFLAGS:= $(foreach f, $(strip malloc realloc calloc free), -Wl,--wrap=$(f))
+OMAP4_DEBUG_SHARED_LIBRARIES:= liblog
+BUILD_HEAPTRACKED_SHARED_LIBRARY:= hardware/ti/omap4xxx/heaptracked-shared-library.mk
+BUILD_HEAPTRACKED_EXECUTABLE:= hardware/ti/omap4xxx/heaptracked-executable.mk
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= heaptracker.c stacktrace.c mapinfo.c
+LOCAL_MODULE:= libheaptracker
+LOCAL_MODULE_TAGS:= optional
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= tm.c
+LOCAL_MODULE:= tm
+LOCAL_MODULE_TAGS:= test
+include $(BUILD_HEAPTRACKED_EXECUTABLE)
+
+else
+BUILD_HEAPTRACKED_SHARED_LIBRARY:=$(BUILD_SHARED_LIBRARY)
+BUILD_HEAPTRACKED_EXECUTABLE:= $(BUILD_EXECUTABLE)
+endif
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..9450dc7
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,55 @@
+# Copyright (C) 2007 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/vendor/lib/hw/hwcomposer.omap4.so)
+$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "lib*cameraadapter*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libcamera.so" -print0 | xargs -0 rm -f)
+$(call add-clean-step, find $(PRODUCT_OUT) -type d -name "libcamera_intermediates" -print0 | xargs -0 rm -rf)
+$(call add-clean-step, find $(PRODUCT_OUT) -type d -name "lib*cameraadapter_intermediates" -print0 | xargs -0 rm -rf)
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/camera/ANativeWindowDisplayAdapter.cpp b/camera/ANativeWindowDisplayAdapter.cpp
new file mode 100755
index 0000000..38e641f
--- /dev/null
+++ b/camera/ANativeWindowDisplayAdapter.cpp
@@ -0,0 +1,1096 @@
+/*
+ * 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.
+ */
+
+
+
+
+#define LOG_TAG "CameraHAL"
+
+#include "ANativeWindowDisplayAdapter.h"
+#include <OMX_IVCommon.h>
+#include <ui/GraphicBufferMapper.h>
+#include <hal_public.h>
+
+namespace android {
+
+///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, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
+ {
+ CAMHAL_LOGDA("CbYCrY format selected");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ }
+ else if(strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
+ {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+ else if(strcmp(parameters_format, (const char *) 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;
+ }
+
+ return pixFormat;
+}
+
+const char* getPixFormatConstant(const char* parameters_format)
+{
+ const char* pixFormat;
+
+ if ( parameters_format != NULL )
+ {
+ if (strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
+ {
+ CAMHAL_LOGVA("CbYCrY format selected");
+ pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_YUV422I;
+ }
+ else if(strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
+ strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_YUV420P) == 0)
+ {
+ // TODO(XXX): We are treating YV12 the same as YUV420SP
+ CAMHAL_LOGVA("YUV420SP format selected");
+ pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP;
+ }
+ else if(strcmp(parameters_format, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
+ {
+ CAMHAL_LOGVA("RGB565 format selected");
+ pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_RGB565;
+ }
+ else
+ {
+ CAMHAL_LOGEA("Invalid format, CbYCrY format selected as default");
+ pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_YUV422I;
+ }
+ }
+ else
+ {
+ CAMHAL_LOGEA("Preview format is NULL, defaulting to CbYCrY");
+ pixFormat = (const char *) CameraParameters::PIXEL_FORMAT_YUV422I;
+ }
+
+ return pixFormat;
+}
+
+const size_t getBufSize(const char* parameters_format, int width, int height)
+{
+ int buf_size;
+
+ if ( parameters_format != NULL ) {
+ if (strcmp(parameters_format,
+ (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ buf_size = width * height * 2;
+ }
+ else if((strcmp(parameters_format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) ||
+ (strcmp(parameters_format, CameraParameters::PIXEL_FORMAT_YUV420P) == 0)) {
+ buf_size = width * height * 3 / 2;
+ }
+ else if(strcmp(parameters_format,
+ (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
+ buf_size = width * height * 2;
+ } else {
+ CAMHAL_LOGEA("Invalid format");
+ buf_size = 0;
+ }
+ } else {
+ CAMHAL_LOGEA("Preview format is NULL");
+ buf_size = 0;
+ }
+
+ return buf_size;
+}
+/*--------------------ANativeWindowDisplayAdapter Class STARTS here-----------------------------*/
+
+
+/**
+ * Display Adapter class STARTS here..
+ */
+ANativeWindowDisplayAdapter::ANativeWindowDisplayAdapter():mDisplayThread(NULL),
+ mDisplayState(ANativeWindowDisplayAdapter::DISPLAY_INIT),
+ mDisplayEnabled(false),
+ mBufferCount(0)
+
+
+
+{
+ 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;
+ mBufferHandleMap = NULL;
+ mGrallocHandleMap = NULL;
+ mOffsetsMap = NULL;
+ mFrameProvider = NULL;
+
+ mFrameWidth = 0;
+ mFrameHeight = 0;
+ mPreviewWidth = 0;
+ mPreviewHeight = 0;
+
+ mSuspend = false;
+ mFailedDQs = 0;
+
+ mPaused = false;
+ mXOff = 0;
+ mYOff = 0;
+ mFirstInit = false;
+
+ mFD = -1;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+ANativeWindowDisplayAdapter::~ANativeWindowDisplayAdapter()
+{
+ Semaphore sem;
+ TIUTILS::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ ///If Frame provider exists
+ if(mFrameProvider)
+ {
+ // Unregister with the frame provider
+ mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES);
+ }
+
+ ///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", 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;
+ }
+
+ ///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;
+ }
+
+ /** 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 = -EINVAL;
+ }
+
+ 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 )
+ {
+ Mutex::Autolock 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, S3DParameters *s3dParams)
+{
+ Semaphore sem;
+ TIUTILS::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ if ( mDisplayEnabled )
+ {
+ CAMHAL_LOGDA("Display is already enabled");
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+ }
+
+#if 0 //TODO: s3d is not part of bringup...will reenable
+ if (s3dParams)
+ mOverlay->set_s3d_params(s3dParams->mode, s3dParams->framePacking,
+ s3dParams->order, s3dParams->subSampling);
+#endif
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ if ( NULL != refTime )
+ {
+ Mutex::Autolock 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);
+
+ mDisplayEnabled = true;
+ mPreviewWidth = width;
+ mPreviewHeight = height;
+
+ CAMHAL_LOGVB("mPreviewWidth = %d mPreviewHeight = %d", mPreviewWidth, mPreviewHeight);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+int ANativeWindowDisplayAdapter::disableDisplay()
+{
+ 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);
+
+ if ( NULL != mDisplayThread.get() )
+ {
+ //Send STOP_DISPLAY COMMAND to display thread. Display thread will stop and dequeue all messages
+ // and then wait for message
+ Semaphore sem;
+ sem.Create();
+ TIUTILS::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();
+
+ }
+
+ Mutex::Autolock lock(mLock);
+ {
+ ///Reset the display enabled flag
+ mDisplayEnabled = false;
+
+ ///Reset the offset values
+ mXOff = 0;
+ mYOff = 0;
+
+ ///Reset the frame width and height values
+ mFrameWidth =0;
+ mFrameHeight = 0;
+ mPreviewWidth = 0;
+ mPreviewHeight = 0;
+
+
+ if (mANativeWindow)
+ for(unsigned int i = 0; i < mFramesWithCameraAdapterMap.size(); i++) {
+ int value = mFramesWithCameraAdapterMap.valueAt(i);
+ mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[value]);
+ }
+ else
+ LOGE("mANativeWindow is 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;
+
+ {
+ Mutex::Autolock 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();
+ }
+
+ mBufferCount = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+// Implementation of inherited interfaces
+void* ANativeWindowDisplayAdapter::allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs)
+{
+ LOG_FUNCTION_NAME;
+ status_t err;
+ int i = -1;
+ const int lnumBufs = numBufs;
+ int32_t *buffers = new int32_t[lnumBufs];
+ mBufferHandleMap = new buffer_handle_t*[lnumBufs];
+ mGrallocHandleMap = new IMG_native_handle_t*[lnumBufs];
+ int undequeued = 0;
+
+ // Set gralloc usage bits for window.
+ err = mANativeWindow->set_usage(mANativeWindow, GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
+ | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
+ if (err != 0) {
+ LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
+ return NULL;
+ }
+
+ CAMHAL_LOGDB("Number of buffers set to ANativeWindow %d", numBufs);
+ //if(mBufferCount != numBufs)
+ // {
+ ///Set the number of buffers needed for camera preview
+ err = mANativeWindow->set_buffer_count(mANativeWindow, numBufs);
+ if (err != 0) {
+ LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err);
+ 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_NV12); // Gralloc only supports NV12 alloc!
+
+ if (err != 0) {
+ LOGE("native_window_set_buffers_geometry failed: %s (%d)", strerror(-err), -err);
+ 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 ( (buffers == NULL) || (mBufferHandleMap == NULL) )
+ {
+ CAMHAL_LOGEA("Couldn't create array for ANativeWindow buffers");
+ LOG_FUNCTION_NAME_EXIT;
+ delete [] buffers;
+ return NULL;
+ }
+
+ mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued);
+
+ for ( i=0; i < mBufferCount; i++ )
+ {
+ IMG_native_handle_t** hndl2hndl;
+ IMG_native_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, (buffer_handle_t**) &hndl2hndl, &stride);
+
+ if (err != 0) {
+ CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+ goto fail;
+ }
+
+ handle = *hndl2hndl;
+
+ mBufferHandleMap[i] = (buffer_handle_t*) hndl2hndl;
+ mGrallocHandleMap[i] = handle;
+ mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i);
+
+ bytes = getBufSize(format, width, height);
+
+ CAMHAL_LOGDB("Adding buffer index=%d, address=0x%x", i, buffers[i]);
+ }
+
+
+ // lock the initial queueable buffers
+ for( i = 0; i < mBufferCount-undequeued; i++ )
+ {
+ mANativeWindow->lock_buffer(mANativeWindow, mBufferHandleMap[i]);
+ }
+
+ // return the rest of the buffers back to ANativeWindow
+ for(i = (mBufferCount-undequeued); i >= 0 && i < mBufferCount; i++)
+ {
+ mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]);
+ }
+
+ mFirstInit = true;
+ mPixelFormat = getPixFormatConstant(format);
+ mFrameWidth = width;
+ mFrameHeight = height;
+
+ return mGrallocHandleMap;
+
+ fail:
+ // need to cancel buffers if any were dequeued
+ for (int start = 0; start < i && i > 0; start++) {
+ int err = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[start]);
+ if (err != 0) {
+ CAMHAL_LOGEB("cancelBuffer failed w/ error 0x%08x", err);
+ }
+ }
+ CAMHAL_LOGEA("Error occurred, performing cleanup");
+ if ( buffers )
+ {
+ delete [] buffers;
+ }
+
+ if ( NULL != mErrorNotifier.get() )
+ {
+ mErrorNotifier->errorNotify(-ENOMEM);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ 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( mBufferHandleMap == NULL)
+ {
+ CAMHAL_LOGEA("Buffers not allocated yet!!");
+ goto fail;
+ }
+
+ if(mOffsetsMap == NULL)
+ {
+ mOffsetsMap = new uint32_t[lnumBufs];
+ for(int i = 0; i < mBufferCount; i++)
+ {
+ IMG_native_handle_t* handle = (IMG_native_handle_t*) *(mBufferHandleMap[i]);
+ mOffsetsMap[i] = 0;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return mOffsetsMap;
+
+ fail:
+
+ if ( NULL != mOffsetsMap )
+ {
+ delete [] mOffsetsMap;
+ mOffsetsMap = NULL;
+ }
+
+ if ( NULL != mErrorNotifier.get() )
+ {
+ mErrorNotifier->errorNotify(-ENOSYS);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NULL;
+}
+
+int ANativeWindowDisplayAdapter::maxQueueableBuffers(unsigned int& queueable)
+{
+ LOG_FUNCTION_NAME;
+ int ret = NO_ERROR;
+ int undequeued = 0;
+
+ if(mBufferCount == 0)
+ {
+ ret = -ENOSYS;
+ goto end;
+ }
+
+ if(!mANativeWindow)
+ {
+ ret = -ENOSYS;
+ goto end;
+ }
+
+ mANativeWindow->get_min_undequeued_buffer_count(mANativeWindow, &undequeued);
+
+ queueable = mBufferCount - undequeued;
+
+ end:
+ return ret;
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+int ANativeWindowDisplayAdapter::getFd()
+{
+ LOG_FUNCTION_NAME;
+
+ if(mFD == -1)
+ {
+ IMG_native_handle_t* handle = (IMG_native_handle_t*) *(mBufferHandleMap[0]);
+ // TODO: should we dup the fd? not really necessary and another thing for ANativeWindow
+ // to manage and close...
+ mFD = dup(handle->fd[0]);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return mFD;
+
+}
+
+int ANativeWindowDisplayAdapter::freeBuffer(void* buf)
+{
+ LOG_FUNCTION_NAME;
+
+ int *buffers = (int *) buf;
+ if((int *)mGrallocHandleMap != buffers)
+ {
+ CAMHAL_LOGEA("CameraHal passed wrong set of buffers to free!!!");
+ if (mGrallocHandleMap != NULL)
+ delete []mGrallocHandleMap;
+ mGrallocHandleMap = NULL;
+ }
+
+ if ( NULL != buf )
+ {
+ delete [] buffers;
+ }
+
+ if( mBufferHandleMap != NULL)
+ {
+ delete [] mBufferHandleMap;
+ mBufferHandleMap = NULL;
+ }
+
+ if ( NULL != mOffsetsMap )
+ {
+ delete [] mOffsetsMap;
+ mOffsetsMap = NULL;
+ }
+
+ if( mFD != -1)
+ {
+ close(mFD); // close duped handle
+ mFD = -1;
+ }
+
+ return NO_ERROR;
+}
+
+
+bool ANativeWindowDisplayAdapter::supportsExternalBuffering()
+{
+ return false;
+}
+
+int ANativeWindowDisplayAdapter::useBuffers(void *bufArr, int num)
+{
+ return NO_ERROR;
+}
+
+void ANativeWindowDisplayAdapter::displayThread()
+{
+ bool shouldLive = true;
+ int timeout = 0;
+ status_t ret;
+
+ LOG_FUNCTION_NAME;
+
+ while(shouldLive)
+ {
+ ret = TIUTILS::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
+ {
+ TIUTILS::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()
+{
+ TIUTILS::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;
+
+ 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");
+ Semaphore &sem = *((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;
+ 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
+ for ( i = 0; i < mBufferCount; i++ )
+ {
+ if ( ((int) dispFrame.mBuffer ) == (int)mGrallocHandleMap[i] )
+ {
+ break;
+ }
+ }
+
+ if ( mDisplayState == ANativeWindowDisplayAdapter::DISPLAY_STARTED &&
+ (!mPaused || CameraFrame::CameraFrame::SNAPSHOT_FRAME == dispFrame.mType) &&
+ !mSuspend)
+ {
+ Mutex::Autolock lock(mLock);
+ uint32_t xOff = (dispFrame.mOffset% PAGE_SIZE);
+ uint32_t yOff = (dispFrame.mOffset / PAGE_SIZE);
+
+ // Set crop only if current x and y offsets do not match with frame offsets
+ if((mXOff!=xOff) || (mYOff!=yOff))
+ {
+ CAMHAL_LOGDB("Offset %d xOff = %d, yOff = %d", dispFrame.mOffset, xOff, yOff);
+ uint8_t bytesPerPixel;
+ ///Calculate bytes per pixel based on the pixel format
+ if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
+ {
+ bytesPerPixel = 2;
+ }
+ else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
+ {
+ bytesPerPixel = 2;
+ }
+ else if(strcmp(mPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
+ {
+ bytesPerPixel = 1;
+ }
+ else
+ {
+ bytesPerPixel = 1;
+ }
+
+ CAMHAL_LOGVB(" crop.left = %d crop.top = %d crop.right = %d crop.bottom = %d",
+ xOff/bytesPerPixel, yOff , (xOff/bytesPerPixel)+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/bytesPerPixel, yOff,
+ (xOff/bytesPerPixel)+mPreviewWidth, yOff+mPreviewHeight);
+
+ ///Update the current x and y offsets
+ mXOff = xOff;
+ mYOff = yOff;
+ }
+
+ ret = mANativeWindow->enqueue_buffer(mANativeWindow, mBufferHandleMap[i]);
+ if (ret != 0) {
+ LOGE("Surface::queueBuffer returned error %d", ret);
+ }
+
+ mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer);
+
+
+ // HWComposer has not minimum buffer requirement. We should be able to dequeue
+ // the buffer immediately
+ TIUTILS::Message msg;
+ mDisplayQ.put(&msg);
+
+
+#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
+
+ }
+ else
+ {
+ Mutex::Autolock lock(mLock);
+ // cancel buffer and dequeue another one
+ ret = mANativeWindow->cancel_buffer(mANativeWindow, mBufferHandleMap[i]);
+ if (ret != 0) {
+ LOGE("Surface::queueBuffer returned error %d", ret);
+ }
+
+ mFramesWithCameraAdapterMap.removeItem((int) dispFrame.mBuffer);
+
+ TIUTILS::Message msg;
+ mDisplayQ.put(&msg);
+ ret = NO_ERROR;
+ }
+
+ return ret;
+}
+
+
+bool ANativeWindowDisplayAdapter::handleFrameReturn()
+{
+ status_t err;
+ buffer_handle_t* buf;
+ int i = 0;
+ int stride; // dummy variable to get stride
+ // TODO(XXX): Do we need to keep stride information in camera hal?
+
+ err = mANativeWindow->dequeue_buffer(mANativeWindow, &buf, &stride);
+ if (err != 0) {
+ CAMHAL_LOGEB("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+ }
+
+ err = mANativeWindow->lock_buffer(mANativeWindow, buf);
+ if (err != 0) {
+ CAMHAL_LOGEB("lockbuffer failed: %s (%d)", strerror(-err), -err);
+ }
+
+ for(i = 0; i < mBufferCount; i++)
+ {
+ if (mBufferHandleMap[i] == buf)
+ break;
+ }
+
+ mFramesWithCameraAdapterMap.add((int) mGrallocHandleMap[i], i);
+
+ CAMHAL_LOGVB("handleFrameReturn: found graphic buffer %d of %d", i, mBufferCount-1);
+ mFrameProvider->returnFrame( (void*)mGrallocHandleMap[i], CameraFrame::PREVIEW_FRAME_SYNC);
+ 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);
+}
+
+
+/*--------------------ANativeWindowDisplayAdapter Class ENDS here-----------------------------*/
+
+};
+
diff --git a/camera/Android.mk b/camera/Android.mk
new file mode 100644
index 0000000..0e2bb8c
--- /dev/null
+++ b/camera/Android.mk
@@ -0,0 +1,131 @@
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+
+LOCAL_PATH:= $(call my-dir)
+
+OMAP4_CAMERA_HAL_USES:= OMX
+# OMAP4_CAMERA_HAL_USES:= USB
+
+OMAP4_CAMERA_HAL_SRC := \
+ CameraHal_Module.cpp \
+ CameraHal.cpp \
+ CameraHalUtilClasses.cpp \
+ AppCallbackNotifier.cpp \
+ ANativeWindowDisplayAdapter.cpp \
+ CameraProperties.cpp \
+ MemoryManager.cpp \
+ SensorListener.cpp
+
+OMAP4_CAMERA_COMMON_SRC:= \
+ CameraParameters.cpp \
+ TICameraParameters.cpp \
+ CameraHalCommon.cpp
+
+OMAP4_CAMERA_OMX_SRC:= \
+ BaseCameraAdapter.cpp \
+ OMXCameraAdapter/OMX3A.cpp \
+ OMXCameraAdapter/OMXAlgo.cpp \
+ OMXCameraAdapter/OMXCameraAdapter.cpp \
+ OMXCameraAdapter/OMXCapabilities.cpp \
+ OMXCameraAdapter/OMXCapture.cpp \
+ OMXCameraAdapter/OMXDefaults.cpp \
+ OMXCameraAdapter/OMXExif.cpp \
+ OMXCameraAdapter/OMXFD.cpp \
+ OMXCameraAdapter/OMXFocus.cpp \
+ OMXCameraAdapter/OMXZoom.cpp \
+
+OMAP4_CAMERA_USB_SRC:= \
+ BaseCameraAdapter.cpp \
+ V4LCameraAdapter/V4LCameraAdapter.cpp
+
+#
+# OMX Camera HAL
+#
+
+ifeq ($(OMAP4_CAMERA_HAL_USES),OMX)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ $(OMAP4_CAMERA_HAL_SRC) \
+ $(OMAP4_CAMERA_OMX_SRC) \
+ $(OMAP4_CAMERA_COMMON_SRC)
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/inc/ \
+ $(LOCAL_PATH)/../hwc \
+ $(LOCAL_PATH)/../include \
+ $(LOCAL_PATH)/inc/OMXCameraAdapter \
+ $(LOCAL_PATH)/../libtiutils \
+ hardware/ti/omap4xxx/tiler \
+ frameworks/base/include/ui \
+ frameworks/base/include/utils \
+ hardware/ti/omap4xxx/domx/omx_core/inc \
+ hardware/ti/omap4xxx/domx/mm_osal/inc \
+ frameworks/base/include/media/stagefright \
+ frameworks/base/include/media/stagefright/openmax
+
+LOCAL_SHARED_LIBRARIES:= \
+ libui \
+ libbinder \
+ libutils \
+ libcutils \
+ libtiutils \
+ libmm_osal \
+ libOMX_Core \
+ libtimemmgr \
+ libcamera_client \
+ libgui \
+ libdomx
+
+LOCAL_CFLAGS := -fno-short-enums -DCOPY_IMAGE_BUFFER
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE:= camera.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS:= optional
+
+include $(BUILD_HEAPTRACKED_SHARED_LIBRARY)
+
+else
+ifeq ($(OMAP4_CAMERA_HAL_USES),USB)
+
+#
+# USB Camera Adapter
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ $(OMAP4_CAMERA_HAL_SRC) \
+ $(OMAP4_CAMERA_USB_SRC) \
+ $(OMAP4_CAMERA_COMMON_SRC)
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/inc/ \
+ $(LOCAL_PATH)/../hwc \
+ $(LOCAL_PATH)/../include \
+ $(LOCAL_PATH)/inc/V4LCameraAdapter \
+ $(LOCAL_PATH)/../libtiutils \
+ hardware/ti/omap4xxx/tiler \
+ frameworks/base/include/ui \
+ frameworks/base/include/utils \
+ frameworks/base/include/media/stagefright/openmax
+
+LOCAL_SHARED_LIBRARIES:= \
+ libui \
+ libbinder \
+ libutils \
+ libcutils \
+ libtiutils \
+ libtimemmgr \
+ libcamera_client
+
+LOCAL_CFLAGS := -fno-short-enums -DCOPY_IMAGE_BUFFER
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE:= camera.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS:= optional
+
+include $(BUILD_HEAPTRACKED_SHARED_LIBRARY)
+endif
+endif
+endif
diff --git a/camera/AppCallbackNotifier.cpp b/camera/AppCallbackNotifier.cpp
new file mode 100644
index 0000000..d266cc2
--- /dev/null
+++ b/camera/AppCallbackNotifier.cpp
@@ -0,0 +1,1399 @@
+/*
+ * 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.
+ */
+
+
+
+
+#define LOG_TAG "CameraHAL"
+
+
+#include "CameraHal.h"
+#include "VideoMetadata.h"
+#include <MetadataBufferType.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferMapper.h>
+
+
+namespace android {
+
+const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1;
+
+/*--------------------NotificationHandler Class STARTS here-----------------------------*/
+
+/**
+ * NotificationHandler class
+ */
+
+
+///Initialization function for AppCallbackNotifier
+status_t AppCallbackNotifier::initialize()
+{
+ LOG_FUNCTION_NAME;
+
+ mMeasurementEnabled = false;
+
+ ///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", PRIORITY_URGENT_DISPLAY);
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEA("Couldn't run NotificationThread");
+ mNotificationThread.clear();
+ return ret;
+ }
+
+ mUseMetaDataBufferMode = true;
+
+ 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)
+{
+ Mutex::Autolock 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)
+{
+ Mutex::Autolock 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);
+
+ ///Notify errors to application in callback thread. Post error event to event queue
+ TIUTILS::Message msg;
+ msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_ERROR;
+ msg.arg1 = (void*)error;
+
+ mEventQ.put(&msg);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void AppCallbackNotifier::notificationThread()
+{
+ bool shouldLive = true;
+ status_t ret;
+
+ LOG_FUNCTION_NAME;
+
+ while(shouldLive)
+ {
+ //CAMHAL_LOGDA("Notification Thread waiting for message");
+ ret = TIUTILS::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.");
+ }
+ }
+ 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();
+ }
+ }
+
+ CAMHAL_LOGDA("Notification Thread exited.");
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+void AppCallbackNotifier::notifyEvent()
+{
+ ///Receive and send the event notifications to app
+ TIUTILS::Message msg;
+ LOG_FUNCTION_NAME;
+ mEventQ.get(&msg);
+ bool ret = true;
+ CameraHalEvent *evt = NULL;
+ CameraHalEvent::FocusEventData *focusEvtData;
+ CameraHalEvent::ZoomEventData *zoomEvtData;
+ CameraHalEvent::FaceEventData faceEvtData;
+
+ 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);
+ }
+
+ break;
+
+ case CameraHalEvent::EVENT_FOCUS_LOCKED:
+ case CameraHalEvent::EVENT_FOCUS_ERROR:
+
+ focusEvtData = &evt->mEventData->focusEvent;
+ if ( ( focusEvtData->focusLocked ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mNotifyCb ) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) )
+ {
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ }
+ else if ( focusEvtData->focusError &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mNotifyCb ) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) )
+ {
+ mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
+ }
+
+ 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_FACE:
+
+ faceEvtData = evt->mEventData->faceEvent;
+
+ 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,
+ faceEvtData->getFaceResult(),
+ mCallbackCookie);
+
+ faceEvtData.clear();
+
+ if ( NULL != tmpBuffer ) {
+ tmpBuffer->release(tmpBuffer);
+ }
+
+ }
+
+ break;
+
+ case CameraHalEvent::ALL_EVENTS:
+ break;
+ default:
+ break;
+ }
+
+ break;
+
+ case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_ERROR:
+
+ if ( ( NULL != mCameraHal ) &&
+ ( NULL != mNotifyCb ) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ERROR) ) )
+ {
+ mNotifyCb(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, mCallbackCookie);
+ }
+
+ break;
+
+ }
+
+ if ( NULL != evt )
+ {
+ delete evt;
+ }
+
+
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+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;
+ void *y_uv[2]; //y_uv[0]=> y pointer; y_uv[1]=>uv pointer
+
+ GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+ Rect bounds;
+
+ bounds.left = offset % stride;
+ bounds.top = offset / stride;
+ bounds.right = width;
+ bounds.bottom = height;
+
+ // get the y & uv pointers from the gralloc handle;
+ mapper.lock((buffer_handle_t)src, GRALLOC_USAGE_SW_READ_OFTEN, bounds, y_uv);
+
+ CAMHAL_LOGDB("copy2Dto1D() y= %p ; uv=%p.",y_uv[0],y_uv[1]);
+ CAMHAL_LOGDB("pixelFormat,= %d; offset=%d",*pixelFormat,offset);
+
+ if (pixelFormat!=NULL) {
+ if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV422I) == 0) {
+ bytesPerPixel = 2;
+ } else if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
+ strcmp(pixelFormat, 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 * ) y_uv[1] + (stride/2)*yOff + xOff;
+
+ if (strcmp(pixelFormat, 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);
+
+ 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 if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
+ uint16_t *bufferDst_U;
+ uint16_t *bufferDst_V;
+
+ // 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
+
+ bufferDst_V = (uint16_t *) (((uint8_t*)dst)+row*height);
+ bufferDst_U = (uint16_t *) (((uint8_t*)dst)+row*height+row*height/4);
+
+ 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"
+ );
+ }
+ }
+ mapper.unlock((buffer_handle_t)src);
+ return ;
+
+ } else if(strcmp(pixelFormat, 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);
+ }
+ mapper.unlock((buffer_handle_t)src);
+}
+
+void AppCallbackNotifier::notifyFrame()
+{
+ ///Receive and send the frame notifications to app
+ TIUTILS::Message msg;
+ CameraFrame *frame;
+ MemoryHeapBase *heap;
+ MemoryBase *buffer = NULL;
+ sp<MemoryBase> memBase;
+ void *buf = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if(!mFrameQ.isEmpty())
+ {
+ mFrameQ.get(&msg);
+ }
+ else
+ {
+ return;
+ }
+
+ bool ret = true;
+
+ if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED)
+ {
+ return;
+ }
+
+ 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) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) ) )
+ {
+
+#ifdef COPY_IMAGE_BUFFER
+
+ camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL);
+
+ if ( NULL != raw_picture )
+ {
+ buf = raw_picture->data;
+ if ( NULL != buf )
+ {
+ memcpy(buf,
+ ( void * ) ( (unsigned int) frame->mBuffer + frame->mOffset),
+ frame->mLength);
+ }
+ mFrameProvider->returnFrame(frame->mBuffer,
+ ( CameraFrame::FrameType ) frame->mFrameType);
+ }
+
+ mDataCb(CAMERA_MSG_RAW_IMAGE, raw_picture, 0, NULL, mCallbackCookie);
+#else
+
+ //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
+
+#endif
+ if(raw_picture)
+ {
+ raw_picture->release(raw_picture);
+ }
+
+ }
+ else if ( ( CameraFrame::IMAGE_FRAME == frame->mFrameType ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) )
+ {
+ Mutex::Autolock lock(mLock);
+
+#ifdef COPY_IMAGE_BUFFER
+
+ camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL);
+
+ if(raw_picture)
+ {
+ buf = raw_picture->data;
+ }
+
+ if ( NULL != buf)
+ {
+ memcpy(buf,
+ ( void * ) ( (unsigned int) frame->mBuffer + frame->mOffset),
+ frame->mLength);
+ }
+
+ {
+ Mutex::Autolock lock(mBurstLock);
+#if 0 //TODO: enable burst mode later
+ if ( mBurst )
+ {
+ `(CAMERA_MSG_BURST_IMAGE, JPEGPictureMemBase, mCallbackCookie);
+ }
+ else
+#endif
+ {
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, raw_picture,
+ 0, NULL,
+ mCallbackCookie);
+ }
+ }
+#else
+
+ //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase
+
+#endif
+ if(raw_picture)
+ {
+ raw_picture->release(raw_picture);
+ }
+
+ mFrameProvider->returnFrame(frame->mBuffer,
+ ( CameraFrame::FrameType ) frame->mFrameType);
+
+ }
+ else if ( ( CameraFrame::VIDEO_FRAME_SYNC == frame->mFrameType ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) &&
+ ( mCameraHal->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME) ) )
+ {
+ mRecordingLock.lock();
+ if(mRecording)
+ {
+ if(mUseMetaDataBufferMode)
+ {
+ camera_memory_t *videoMedatadaBufferMemory =
+ (camera_memory_t *) mVideoMetadataBufferMemoryMap.valueFor((uint32_t) frame->mBuffer);
+ 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;
+ }
+
+ videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource;
+ videoMetadataBuffer->handle = frame->mBuffer;
+ videoMetadataBuffer->offset = frame->mOffset;
+
+ CAMHAL_LOGVB("mDataCbTimestamp : frame->mBuffer=0x%x, videoMetadataBuffer=0x%x, videoMedatadaBufferMemory=0x%x",
+ frame->mBuffer, 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, 4, 1, NULL);
+ if( (NULL == fakebuf) || ( NULL == fakebuf->data) || ( NULL == frame->mBuffer))
+ {
+ CAMHAL_LOGEA("Error! One of the video buffers is NULL");
+ break;
+ }
+
+ fakebuf->data = frame->mBuffer;
+ mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME, fakebuf, 0, mCallbackCookie);
+ fakebuf->release(fakebuf);
+ }
+ }
+ mRecordingLock.unlock();
+
+ }
+ else if(( CameraFrame::SNAPSHOT_FRAME == frame->mFrameType ) &&
+ ( NULL != mCameraHal ) &&
+ ( NULL != mDataCb) &&
+ ( NULL != mNotifyCb)) {
+ Mutex::Autolock lock(mLock);
+ //When enabled, measurement data is sent instead of video data
+ if ( !mMeasurementEnabled ) {
+ if (!mPreviewMemory || !frame->mBuffer) {
+ CAMHAL_LOGDA("Error! One of the buffer is NULL");
+ break;
+ }
+
+ buf = (void*) mPreviewBufs[mPreviewBufCount];
+
+ CAMHAL_LOGVB("%d:copy2Dto1D(%p, %p, %d, %d, %d, %d, %d,%s)",
+ __LINE__,
+ buf,
+ frame->mBuffer,
+ frame->mWidth,
+ frame->mHeight,
+ frame->mAlignment,
+ 2,
+ frame->mLength,
+ mPreviewPixelFormat);
+
+ if ( NULL != buf ) {
+ copy2Dto1D(buf,
+ frame->mBuffer,
+ frame->mWidth,
+ frame->mHeight,
+ frame->mAlignment,
+ frame->mOffset,
+ 2,
+ frame->mLength,
+ mPreviewPixelFormat);
+ }
+
+ if (mCameraHal->msgTypeEnabled(CAMERA_MSG_POSTVIEW_FRAME)) {
+ ///Give preview callback to app
+ mDataCb(CAMERA_MSG_POSTVIEW_FRAME, mPreviewMemory, mPreviewBufCount, NULL, mCallbackCookie);
+ }
+
+ // increment for next buffer
+ mPreviewBufCount = (mPreviewBufCount+1) % AppCallbackNotifier::MAX_BUFFERS;
+ }
+
+ 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)) ) {
+ Mutex::Autolock lock(mLock);
+ //When enabled, measurement data is sent instead of video data
+ if ( !mMeasurementEnabled ) {
+ if (!mPreviewMemory || !frame->mBuffer) {
+ CAMHAL_LOGDA("Error! One of the buffer is NULL");
+ break;
+ }
+
+ buf = (void*) mPreviewBufs[mPreviewBufCount];
+
+ CAMHAL_LOGVB("%d:copy2Dto1D(%p, %p, %d, %d, %d, %d, %d,%s)",
+ __LINE__,
+ buf,
+ frame->mBuffer,
+ frame->mWidth,
+ frame->mHeight,
+ frame->mAlignment,
+ 2,
+ frame->mLength,
+ mPreviewPixelFormat);
+
+ if ( NULL != buf ) {
+ copy2Dto1D(buf,
+ frame->mBuffer,
+ frame->mWidth,
+ frame->mHeight,
+ frame->mAlignment,
+ frame->mOffset,
+ 2,
+ frame->mLength,
+ mPreviewPixelFormat);
+ }
+
+ // Give preview callback to app
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewMemory, mPreviewBufCount, NULL, mCallbackCookie);
+
+ // increment for next buffer
+ mPreviewBufCount = (mPreviewBufCount+1) % AppCallbackNotifier::MAX_BUFFERS;
+ }
+ 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)) ) {
+ if (!mPreviewMemory || !frame->mBuffer) {
+ CAMHAL_LOGDA("Error! One of the buffer is NULL");
+ break;
+ }
+
+ buf = (void*) mPreviewBufs[mPreviewBufCount];
+ if (buf) {
+ if ( (mPreviewMemory->size / MAX_BUFFERS) >= frame->mLength ) {
+ memcpy(buf, ( void * ) frame->mBuffer, frame->mLength);
+ } else {
+ memset(buf, 0, (mPreviewMemory->size / MAX_BUFFERS));
+ }
+ }
+
+ // Give preview callback to app
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewMemory, mPreviewBufCount, NULL, mCallbackCookie);
+
+ //Increment the buffer count
+ mPreviewBufCount = (mPreviewBufCount+1) % AppCallbackNotifier::MAX_BUFFERS;
+
+ mFrameProvider->returnFrame(frame->mBuffer,
+ ( CameraFrame::FrameType ) frame->mFrameType);
+ } 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
+ TIUTILS::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::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
+ TIUTILS::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;
+ mEventQ.put(&msg);
+ }
+ else
+ {
+ CAMHAL_LOGEA("Not enough resources to allocate CameraHalEvent");
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+bool AppCallbackNotifier::processMessage()
+{
+ ///Retrieve the command from the command queue and process it
+ TIUTILS::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_LOGEA("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);
+ }
+
+ TIUTILS::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->requestExitAndWait();
+
+ //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 = (camera_memory_t*) mVideoMetadataBufferMemoryMap.valueAt(i);
+ if(NULL != videoMedatadaBufferMemory)
+ {
+ videoMedatadaBufferMemory->release(videoMedatadaBufferMemory);
+ CAMHAL_LOGDB("Released videoMedatadaBufferMemory=0x%x", videoMedatadaBufferMemory);
+ }
+ }
+
+ mVideoMetadataBufferMemoryMap.clear();
+ mVideoMetadataBufferReverseMap.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(CameraParameters &params, void *buffers, uint32_t *offsets, int fd, size_t length, size_t count)
+{
+ sp<MemoryHeapBase> heap;
+ sp<MemoryBase> buffer;
+ unsigned int *bufArr;
+ size_t size = 0;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock 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);
+
+ //Get the preview pixel format
+ mPreviewPixelFormat = params.getPreviewFormat();
+
+ if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
+ {
+ size = w*h*2;
+ mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV422I;
+ }
+ else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
+ strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420P) == 0)
+ {
+ size = (w*h*3)/2;
+ mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV420SP;
+ }
+ else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
+ {
+ size = w*h*2;
+ mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_RGB565;
+ }
+
+ mPreviewMemory = mRequestMemory(-1, size, AppCallbackNotifier::MAX_BUFFERS, NULL);
+ if (!mPreviewMemory) {
+ return NO_MEMORY;
+ }
+
+ for (int i=0; i < AppCallbackNotifier::MAX_BUFFERS; i++) {
+ mPreviewBufs[i] = (unsigned char*) mPreviewMemory->data + (i*size);
+ }
+
+ if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME ) ) {
+ mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+
+ mPreviewBufCount = 0;
+
+ mPreviewing = true;
+
+ LOG_FUNCTION_NAME;
+
+ return NO_ERROR;
+}
+
+void AppCallbackNotifier::setBurst(bool burst)
+{
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(mBurstLock);
+
+ mBurst = burst;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t AppCallbackNotifier::stopPreviewCallbacks()
+{
+ sp<MemoryHeapBase> heap;
+ sp<MemoryBase> buffer;
+
+ 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);
+
+ mPreviewMemory->release(mPreviewMemory);
+
+ 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;
+
+ Mutex::Autolock 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(void *buffers, uint32_t *offsets, int fd, size_t length, size_t count)
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ if(mUseMetaDataBufferMode)
+ {
+ uint32_t *bufArr = NULL;
+ camera_memory_t* videoMedatadaBufferMemory = NULL;
+
+ if(NULL == buffers)
+ {
+ CAMHAL_LOGEA("Error! Video buffers are NULL");
+ return BAD_VALUE;
+ }
+ bufArr = (uint32_t *) buffers;
+
+ 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;
+ }
+
+ mVideoMetadataBufferMemoryMap.add(bufArr[i], (uint32_t)(videoMedatadaBufferMemory));
+ mVideoMetadataBufferReverseMap.add((uint32_t)(videoMedatadaBufferMemory->data), bufArr[i]);
+ CAMHAL_LOGDB("bufArr[%d]=0x%x, videoMedatadaBufferMemory=0x%x, videoMedatadaBufferMemory->data=0x%x",
+ i, bufArr[i], videoMedatadaBufferMemory, videoMedatadaBufferMemory->data);
+ }
+ }
+
+exit:
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t AppCallbackNotifier::stopRecording()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock 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;
+ void *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 ;
+ frame = (void*) mVideoMetadataBufferReverseMap.valueFor((uint32_t) videoMetadataBuffer);
+ CAMHAL_LOGVB("Releasing frame with videoMetadataBuffer=0x%x, videoMetadataBuffer->handle=0x%x & frame handle=0x%x\n",
+ videoMetadataBuffer, videoMetadataBuffer->handle, frame);
+ }
+ else
+ {
+ frame = (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_POSTVIEW_FRAME)
+ {
+ mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
+ }
+
+ if(msgType & CAMERA_MSG_PREVIEW_FRAME)
+ {
+ mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+
+ return NO_ERROR;
+}
+
+status_t AppCallbackNotifier::disableMsgType(int32_t msgType)
+{
+ if(msgType & CAMERA_MSG_POSTVIEW_FRAME)
+ {
+ mFrameProvider->disableFrameNotification(CameraFrame::SNAPSHOT_FRAME);
+ }
+
+ if(msgType & CAMERA_MSG_PREVIEW_FRAME)
+ {
+ mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+
+ 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");
+
+ 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;
+ }
+
+ mNotifierState = AppCallbackNotifier::NOTIFIER_STOPPED;
+ CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STOPPED \n");
+
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_ERROR;
+}
+
+
+/*--------------------NotificationHandler Class ENDS here-----------------------------*/
+
+
+
+};
diff --git a/camera/BaseCameraAdapter.cpp b/camera/BaseCameraAdapter.cpp
new file mode 100644
index 0000000..fb90a79
--- /dev/null
+++ b/camera/BaseCameraAdapter.cpp
@@ -0,0 +1,1969 @@
+/*
+ * 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.
+ */
+
+
+
+#define LOG_TAG "CameraHAL"
+
+#include "BaseCameraAdapter.h"
+
+namespace android {
+
+/*--------------------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;
+
+#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;
+
+ Mutex::Autolock lock(mSubscriberLock);
+
+ mFrameSubscribers.clear();
+ mImageSubscribers.clear();
+ mRawSubscribers.clear();
+ mVideoSubscribers.clear();
+ mFocusSubscribers.clear();
+ mShutterSubscribers.clear();
+ mZoomSubscribers.clear();
+ mFaceSubscribers.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)
+{
+ Mutex::Autolock lock(mSubscriberLock);
+
+ LOG_FUNCTION_NAME;
+
+ if ( CameraFrame::PREVIEW_FRAME_SYNC == msgs )
+ {
+ mFrameSubscribers.add((int) cookie, callback);
+ }
+ else if ( CameraFrame::FRAME_DATA_SYNC == msgs )
+ {
+ mFrameDataSubscribers.add((int) cookie, callback);
+ }
+ else if ( CameraFrame::IMAGE_FRAME == msgs)
+ {
+ mImageSubscribers.add((int) cookie, callback);
+ }
+ else if ( CameraFrame::RAW_FRAME == msgs)
+ {
+ mRawSubscribers.add((int) cookie, callback);
+ }
+ else if ( CameraFrame::VIDEO_FRAME_SYNC == msgs)
+ {
+ mVideoSubscribers.add((int) cookie, callback);
+ }
+ else if ( CameraHalEvent::ALL_EVENTS == msgs)
+ {
+ mFocusSubscribers.add((int) cookie, eventCb);
+ mShutterSubscribers.add((int) cookie, eventCb);
+ mZoomSubscribers.add((int) cookie, eventCb);
+ mFaceSubscribers.add((int) cookie, eventCb);
+ }
+ else
+ {
+ CAMHAL_LOGEA("Message type subscription no supported yet!");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void BaseCameraAdapter::disableMsgType(int32_t msgs, void* cookie)
+{
+ Mutex::Autolock lock(mSubscriberLock);
+
+ LOG_FUNCTION_NAME;
+
+ if ( CameraFrame::PREVIEW_FRAME_SYNC == msgs )
+ {
+ mFrameSubscribers.removeItem((int) cookie);
+ }
+ else if ( CameraFrame::FRAME_DATA_SYNC == msgs )
+ {
+ mFrameDataSubscribers.removeItem((int) cookie);
+ }
+ else if ( CameraFrame::IMAGE_FRAME == msgs)
+ {
+ mImageSubscribers.removeItem((int) cookie);
+ }
+ else if ( CameraFrame::RAW_FRAME == msgs)
+ {
+ mRawSubscribers.removeItem((int) cookie);
+ }
+ else if ( CameraFrame::VIDEO_FRAME_SYNC == msgs)
+ {
+ mVideoSubscribers.removeItem((int) cookie);
+ }
+ else if ( CameraFrame::ALL_FRAMES == msgs )
+ {
+ mFrameSubscribers.removeItem((int) cookie);
+ mFrameDataSubscribers.removeItem((int) cookie);
+ mImageSubscribers.removeItem((int) cookie);
+ mRawSubscribers.removeItem((int) cookie);
+ mVideoSubscribers.removeItem((int) cookie);
+ }
+ else if ( CameraHalEvent::ALL_EVENTS == msgs)
+ {
+ //Subscribe only for focus
+ //TODO: Process case by case
+ mFocusSubscribers.removeItem((int) cookie);
+ mShutterSubscribers.removeItem((int) cookie);
+ mZoomSubscribers.removeItem((int) cookie);
+ mFaceSubscribers.removeItem((int) cookie);
+ }
+ else
+ {
+ CAMHAL_LOGEB("Message type 0x%x subscription no supported yet!", msgs);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void BaseCameraAdapter::returnFrame(void* frameBuf, CameraFrame::FrameType frameType)
+{
+ status_t res = NO_ERROR;
+ size_t subscriberCount = 0;
+ int refCount = -1;
+
+ Mutex::Autolock lock(mReturnFrameLock);
+
+ if ( NULL == frameBuf )
+ {
+ CAMHAL_LOGEA("Invalid frameBuf");
+ return;
+ }
+
+ if ( NO_ERROR == res)
+ {
+
+ refCount = getFrameRefCount(frameBuf, frameType);
+
+ if ( 0 < refCount )
+ {
+
+ refCount--;
+ setFrameRefCount(frameBuf, frameType, refCount);
+
+ if ( ( mRecording ) && ( CameraFrame::VIDEO_FRAME_SYNC == frameType ) )
+ {
+ refCount += getFrameRefCount(frameBuf, CameraFrame::PREVIEW_FRAME_SYNC);
+ }
+ else if ( ( mRecording ) && ( CameraFrame::PREVIEW_FRAME_SYNC == frameType ) )
+ {
+ refCount += getFrameRefCount(frameBuf, CameraFrame::VIDEO_FRAME_SYNC);
+ }
+
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ if ( NO_ERROR == res )
+ {
+ //check if someone is holding this buffer
+ if ( 0 == refCount )
+ {
+ res = fillThisBuffer(frameBuf, frameType);
+ }
+ }
+
+}
+
+status_t BaseCameraAdapter::sendCommand(CameraCommands operation, int value1, int value2, int value3)
+{
+ 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 )
+ {
+ Mutex::Autolock lock(mPreviewBufferLock);
+ mPreviewBuffers = (int *) desc->mBuffers;
+ mPreviewBuffersLength = desc->mLength;
+ mPreviewBuffersAvailable.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 )
+ {
+ Mutex::Autolock lock(mPreviewDataBufferLock);
+ mPreviewDataBuffers = (int *) desc->mBuffers;
+ mPreviewDataBuffersLength = desc->mLength;
+ mPreviewDataBuffersAvailable.clear();
+ for ( uint32_t i = 0 ; i < desc->mMaxQueueable ; i++ )
+ {
+ mPreviewDataBuffersAvailable.add(mPreviewDataBuffers[i], true);
+ }
+ // 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(mPreviewBuffers[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 )
+ {
+ Mutex::Autolock lock(mCaptureBufferLock);
+ mCaptureBuffers = (int *) desc->mBuffers;
+ mCaptureBuffersLength = desc->mLength;
+ mCaptureBuffersAvailable.clear();
+ for ( uint32_t i = 0 ; i < desc->mMaxQueueable ; i++ )
+ {
+ mCaptureBuffersAvailable.add(mCaptureBuffers[i], true);
+ }
+ // 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++ )
+ {
+ mCaptureBuffersAvailable.add(mPreviewBuffers[i], 1);
+ }
+ }
+
+ 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;
+
+ 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_PREVIEW_FLUSH_BUFFERS:
+ {
+
+ if ( ret == NO_ERROR )
+ {
+ ret = setState(operation);
+ }
+
+ if ( ret == NO_ERROR )
+ {
+ ret = flushBuffers();
+ }
+
+ 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->mLength, 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;
+
+ default:
+ CAMHAL_LOGEB("Command 0x%x unsupported!", operation);
+ break;
+ };
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+status_t BaseCameraAdapter::notifyFocusSubscribers(bool 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
+
+ //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.focusLocked = status;
+ focusEvent.mEventData->focusEvent.focusError = !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_LOGEA("Sending shutter callback");
+
+ eventCb ( &shutterEvent );
+ }
+
+ shutterEvent.mEventData.clear();
+
+ LOG_FUNCTION_NAME;
+
+ 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::notifyFaceSubscribers(sp<CameraFDResult> &faces)
+{
+ event_callback eventCb;
+ CameraHalEvent faceEvent;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( mFaceSubscribers.size() == 0 ) {
+ CAMHAL_LOGDA("No face detection subscribers!");
+ return NO_INIT;
+ }
+
+ faceEvent.mEventData = new CameraHalEvent::CameraHalEventData();
+ if ( NULL == faceEvent.mEventData.get() ) {
+ return -ENOMEM;
+ }
+
+ faceEvent.mEventType = CameraHalEvent::EVENT_FACE;
+ faceEvent.mEventData->faceEvent = faces;
+
+ for (unsigned int i = 0 ; i < mFaceSubscribers.size(); i++ ) {
+ faceEvent.mCookie = (void *) mFaceSubscribers.keyAt(i);
+ eventCb = (event_callback) mFaceSubscribers.valueAt(i);
+
+ eventCb ( &faceEvent );
+ }
+
+ faceEvent.mEventData.clear();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t BaseCameraAdapter::sendFrameToSubscribers(CameraFrame *frame)
+{
+ status_t ret = NO_ERROR;
+ frame_callback callback;
+ uint32_t i = 0;
+ KeyedVector<int, frame_callback> *subscribers = NULL;
+ size_t refCount = 0;
+
+ if ( NULL == frame )
+ {
+ CAMHAL_LOGEA("Invalid CameraFrame");
+ ret = -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ switch(frame->mFrameType)
+ {
+ case CameraFrame::IMAGE_FRAME:
+ {
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ CameraHal::PPM("Shot to Jpeg: ", &mStartCapture);
+
+#endif
+
+ subscribers = &mImageSubscribers;
+ break;
+ }
+ case CameraFrame::RAW_FRAME:
+ {
+ subscribers = &mRawSubscribers;
+ break;
+ }
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ {
+ subscribers = &mVideoSubscribers;
+ break;
+ }
+ case CameraFrame::FRAME_DATA_SYNC:
+ {
+ subscribers = &mFrameDataSubscribers;
+ break;
+ }
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ case CameraFrame::SNAPSHOT_FRAME:
+ {
+ subscribers = &mFrameSubscribers;
+ break;
+ }
+ default:
+ {
+ ret = -EINVAL;
+ break;
+ }
+ };
+
+ }
+
+ if ( ( NO_ERROR == ret ) &&
+ ( NULL != subscribers ) )
+ {
+ Mutex::Autolock lock(mSubscriberLock);
+
+ refCount = subscribers->size();
+ CAMHAL_LOGVB("Type of Frame: 0x%x address: 0x%x refCount start %d",
+ frame->mFrameType,
+ ( uint32_t ) frame->mBuffer,
+ refCount);
+
+ setFrameRefCount(frame->mBuffer,
+ ( CameraFrame::FrameType ) frame->mFrameType,
+ refCount);
+
+ for ( i = 0 ; i < subscribers->size(); i++ )
+ {
+ frame->mCookie = ( void * ) subscribers->keyAt(i);
+ callback = (frame_callback) subscribers->valueAt(i);
+ callback(frame);
+ }
+ }
+
+ if ( 0 == i )
+ {
+ //No subscribers for this frame
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int BaseCameraAdapter::getFrameRefCount(void* frameBuf, CameraFrame::FrameType frameType)
+{
+ int res = -1;
+
+ LOG_FUNCTION_NAME;
+
+ switch ( frameType )
+ {
+ case CameraFrame::IMAGE_FRAME:
+ case CameraFrame::RAW_FRAME:
+ {
+ Mutex::Autolock lock(mCaptureBufferLock);
+ res = mCaptureBuffersAvailable.valueFor( ( unsigned int ) frameBuf );
+ }
+ break;
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ case CameraFrame::SNAPSHOT_FRAME:
+ {
+ Mutex::Autolock lock(mPreviewBufferLock);
+ res = mPreviewBuffersAvailable.valueFor( ( unsigned int ) frameBuf );
+ }
+ break;
+ case CameraFrame::FRAME_DATA_SYNC:
+ {
+ Mutex::Autolock lock(mPreviewDataBufferLock);
+ res = mPreviewDataBuffersAvailable.valueFor( ( unsigned int ) frameBuf );
+ }
+ break;
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ {
+ Mutex::Autolock lock(mVideoBufferLock);
+ res = mVideoBuffersAvailable.valueFor( ( unsigned int ) frameBuf );
+ }
+ break;
+ default:
+ break;
+ };
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return res;
+}
+
+void BaseCameraAdapter::setFrameRefCount(void* frameBuf, CameraFrame::FrameType frameType, int refCount)
+{
+
+ LOG_FUNCTION_NAME;
+
+ switch ( frameType )
+ {
+ case CameraFrame::IMAGE_FRAME:
+ case CameraFrame::RAW_FRAME:
+ {
+ Mutex::Autolock lock(mCaptureBufferLock);
+ mCaptureBuffersAvailable.replaceValueFor( ( unsigned int ) frameBuf, refCount);
+ }
+ break;
+ case CameraFrame::PREVIEW_FRAME_SYNC:
+ case CameraFrame::SNAPSHOT_FRAME:
+ {
+ Mutex::Autolock lock(mPreviewBufferLock);
+ mPreviewBuffersAvailable.replaceValueFor( ( unsigned int ) frameBuf, refCount);
+ }
+ break;
+ case CameraFrame::FRAME_DATA_SYNC:
+ {
+ Mutex::Autolock lock(mPreviewDataBufferLock);
+ mPreviewDataBuffersAvailable.replaceValueFor( ( unsigned int ) frameBuf, refCount);
+ }
+ break;
+ case CameraFrame::VIDEO_FRAME_SYNC:
+ {
+ Mutex::Autolock lock(mVideoBufferLock);
+ mVideoBuffersAvailable.replaceValueFor( ( unsigned int ) frameBuf, refCount);
+ }
+ break;
+ default:
+ break;
+ };
+
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+status_t BaseCameraAdapter::startVideoCapture()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(mVideoBufferLock);
+
+ //If the capture is already ongoing, return from here.
+ if ( mRecording )
+ {
+ ret = NO_INIT;
+ }
+
+
+ if ( NO_ERROR == ret )
+ {
+
+ 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++ )
+ {
+ void *frameBuf = ( void * ) mVideoBuffersAvailable.keyAt(i);
+ if( getFrameRefCount(frameBuf, CameraFrame::VIDEO_FRAME_SYNC) > 0)
+ {
+ returnFrame(frameBuf, CameraFrame::VIDEO_FRAME_SYNC);
+ }
+ }
+
+ mVideoBuffersAvailable.clear();
+
+ 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(false);
+
+ 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, void* 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(void* 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(size_t &length, 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::setState(CameraCommands operation)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ 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 = 0x%x",
+ operation);
+ mNextState = LOADED_PREVIEW_STATE;
+ break;
+
+ //These events don't change the current state
+ case CAMERA_QUERY_RESOLUTION_PREVIEW:
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ case CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA:
+ CAMHAL_LOGDB("Adapter state switch INTIALIZED_STATE->INTIALIZED_STATE event = 0x%x",
+ operation);
+ mNextState = INTIALIZED_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch INTIALIZED_STATE Invalid Op! event = 0x%x",
+ operation);
+ 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 = 0x%x",
+ operation);
+ mNextState = PREVIEW_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 = 0x%x",
+ operation);
+ mNextState = LOADED_PREVIEW_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGDB("Adapter state switch LOADED_PREVIEW Invalid Op! event = 0x%x",
+ operation);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case PREVIEW_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_PREVIEW:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->INTIALIZED_STATE event = 0x%x",
+ operation);
+ mNextState = INTIALIZED_STATE;
+ break;
+
+ case CAMERA_PERFORM_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->AF_STATE event = 0x%x",
+ operation);
+ mNextState = AF_STATE;
+ break;
+
+ case CAMERA_START_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->ZOOM_STATE event = 0x%x",
+ operation);
+ mNextState = ZOOM_STATE;
+ break;
+
+ case CAMERA_USE_BUFFERS_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->LOADED_CAPTURE_STATE event = 0x%x",
+ operation);
+ mNextState = LOADED_CAPTURE_STATE;
+ break;
+
+ case CAMERA_START_VIDEO:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_STATE->VIDEO_STATE event = 0x%x",
+ operation);
+ mNextState = VIDEO_STATE;
+ break;
+
+ case CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE:
+ case CAMERA_STOP_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch PREVIEW_ACTIVE->PREVIEW_ACTIVE event = 0x%x",
+ operation);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch PREVIEW_ACTIVE Invalid Op! event = 0x%x",
+ operation);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case LOADED_CAPTURE_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch LOADED_CAPTURE_STATE->CAPTURE_STATE event = 0x%x",
+ operation);
+ mNextState = CAPTURE_STATE;
+ break;
+
+ case CAMERA_START_BRACKET_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch LOADED_CAPTURE_STATE->BRACKETING_STATE event = 0x%x",
+ operation);
+ mNextState = BRACKETING_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch LOADED_CAPTURE_STATE Invalid Op! event = 0x%x",
+ operation);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case CAPTURE_STATE:
+
+ switch ( operation )
+ {
+ case CAMERA_STOP_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch CAPTURE_STATE->PREVIEW_STATE event = 0x%x",
+ operation);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch CAPTURE_STATE Invalid Op! event = 0x%x",
+ operation);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case BRACKETING_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_BRACKET_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch BRACKETING_STATE->PREVIEW_STATE event = 0x%x",
+ operation);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_START_IMAGE_CAPTURE:
+ CAMHAL_LOGDB("Adapter state switch BRACKETING_STATE->CAPTURE_STATE event = 0x%x",
+ operation);
+ mNextState = CAPTURE_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch BRACKETING_STATE Invalid Op! event = 0x%x",
+ operation);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case AF_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_CANCEL_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch AF_STATE->PREVIEW_STATE event = 0x%x",
+ operation);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_START_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch AF_STATE->AF_ZOOM_STATE event = 0x%x",
+ operation);
+ mNextState = AF_ZOOM_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch AF_STATE Invalid Op! event = 0x%x",
+ operation);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case ZOOM_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_SMOOTH_ZOOM:
+ CAMHAL_LOGDB("Adapter state switch ZOOM_STATE->PREVIEW_STATE event = 0x%x",
+ operation);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ case CAMERA_PERFORM_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch ZOOM_STATE->AF_ZOOM_STATE event = 0x%x",
+ operation);
+ mNextState = AF_ZOOM_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch ZOOM_STATE Invalid Op! event = 0x%x",
+ operation);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ break;
+
+ case VIDEO_STATE:
+
+ switch ( operation )
+ {
+
+ case CAMERA_STOP_VIDEO:
+ CAMHAL_LOGDB("Adapter state switch VIDEO_STATE->PREVIEW_STATE event = 0x%x",
+ operation);
+ mNextState = PREVIEW_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch VIDEO_STATE Invalid Op! event = 0x%x",
+ operation);
+ 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 = 0x%x",
+ operation);
+ mNextState = AF_STATE;
+ break;
+
+ case CAMERA_CANCEL_AUTOFOCUS:
+ CAMHAL_LOGDB("Adapter state switch AF_ZOOM_STATE->ZOOM_STATE event = 0x%x",
+ operation);
+ mNextState = ZOOM_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch AF_ZOOM_STATE Invalid Op! event = 0x%x",
+ operation);
+ 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 = 0x%x",
+ operation);
+ mNextState = VIDEO_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch VIDEO_ZOOM_STATE Invalid Op! event = 0x%x",
+ operation);
+ 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 = 0x%x",
+ operation);
+ mNextState = BRACKETING_STATE;
+ break;
+
+ default:
+ CAMHAL_LOGEB("Adapter state switch BRACKETING_ZOOM_STATE Invalid Op! event = 0x%x",
+ operation);
+ ret = INVALID_OPERATION;
+ break;
+
+ }
+
+ 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;
+
+ Mutex::Autolock lock(mLock);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return mAdapterState;
+}
+
+CameraAdapter::AdapterState BaseCameraAdapter::getNextState()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock 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;
+}
+//-----------------------------------------------------------------------------
+
+
+
+};
+
+/*--------------------Camera Adapter Class ENDS here-----------------------------*/
+
diff --git a/camera/CameraHal.cpp b/camera/CameraHal.cpp
new file mode 100755
index 0000000..53bc377
--- /dev/null
+++ b/camera/CameraHal.cpp
@@ -0,0 +1,3030 @@
+/*
+ * 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.
+*
+*/
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "ANativeWindowDisplayAdapter.h"
+#include "TICameraParameters.h"
+#include "CameraProperties.h"
+#include <cutils/properties.h>
+
+#include <poll.h>
+#include <math.h>
+
+namespace android {
+
+extern "C" CameraAdapter* CameraAdapter_Factory();
+
+/*****************************************************************************/
+
+////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 = 2;
+
+const uint32_t MessageNotifier::EVENT_BIT_FIELD_POSITION = 0;
+const uint32_t MessageNotifier::FRAME_BIT_FIELD_POSITION = 0;
+
+/******************************************************************************/
+
+#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);
+ }
+
+ 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;
+ }
+
+ {
+ Mutex::Autolock 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;
+
+ {
+ Mutex::Autolock 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)
+{
+ LOG_FUNCTION_NAME;
+ Mutex::Autolock lock(mLock);
+ LOG_FUNCTION_NAME_EXIT;
+ return (mMsgEnabled & 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;
+
+ CameraParameters params;
+
+ 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 CameraParameters& params)
+{
+
+ LOG_FUNCTION_NAME;
+
+ int w, h;
+ int w_orig, h_orig;
+ int framerate,minframerate;
+ bool framerateUpdated = true;
+ int maxFPS, minFPS;
+ int error;
+ int base;
+ const char *valstr = NULL;
+ const char *prevFormat;
+ char *af_coord;
+ TIUTILS::Message msg;
+ status_t ret = NO_ERROR;
+
+ Mutex::Autolock lock(mLock);
+
+ ///Ensure that preview is not enabled when the below parameters are changed.
+ if(!previewEnabled())
+ {
+
+ CAMHAL_LOGDB("PreviewFormat %s", params.getPreviewFormat());
+
+ if ( !isParameterValid(params.getPreviewFormat(), mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS)))
+ {
+ CAMHAL_LOGEB("Invalid preview format %s", mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS));
+ return -EINVAL;
+ }
+ else
+ {
+ if ( (valstr = params.getPreviewFormat()) != NULL)
+ mParameters.setPreviewFormat(valstr);
+ }
+
+ params.getPreviewSize(&w, &h);
+ if (w == -1 && h == -1) {
+ CAMHAL_LOGEA("Unable to get preview size");
+ return ret;
+ }
+
+ int orientation =0;
+ if((valstr = params.get(TICameraParameters::KEY_SENSOR_ORIENTATION)) != NULL)
+ {
+ CAMHAL_LOGDB("Sensor Orientation is set to %s", params.get(TICameraParameters::KEY_SENSOR_ORIENTATION));
+ mParameters.set(TICameraParameters::KEY_SENSOR_ORIENTATION, valstr);
+ orientation = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION);
+ }
+
+ if(orientation ==90 || orientation ==270)
+ {
+ if ( !isResolutionValid(h,w, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES)))
+ {
+ CAMHAL_LOGEB("Invalid preview resolution %d x %d", w, h);
+ return -EINVAL;
+ }
+ else
+ {
+ mParameters.setPreviewSize(w, h);
+ }
+ }
+ else
+ {
+ if ( !isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES)))
+ {
+ CAMHAL_LOGEB("Invalid preview resolution %d x %d", w, h);
+ return -EINVAL;
+ }
+ else
+ {
+ mParameters.setPreviewSize(w, h);
+ }
+ }
+
+ CAMHAL_LOGDB("PreviewResolution by App %d x %d", w, h);
+
+ if(( (valstr = params.get(TICameraParameters::KEY_VNF)) != NULL)
+ && ((params.getInt(TICameraParameters::KEY_VNF)==0) || (params.getInt(TICameraParameters::KEY_VNF)==1)))
+ {
+ CAMHAL_LOGDB("VNF set %s", params.get(TICameraParameters::KEY_VNF));
+ mParameters.set(TICameraParameters::KEY_VNF, valstr);
+ }
+
+ if(( (valstr = params.get(TICameraParameters::KEY_VSTAB)) != NULL)
+ && ((params.getInt(TICameraParameters::KEY_VSTAB)==0) || (params.getInt(TICameraParameters::KEY_VSTAB)==1)))
+ {
+ CAMHAL_LOGDB("VSTAB set %s", params.get(TICameraParameters::KEY_VSTAB));
+ mParameters.set(TICameraParameters::KEY_VSTAB, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_CAP_MODE)) != NULL)
+ {
+ CAMHAL_LOGDB("Capture mode set %s", params.get(TICameraParameters::KEY_CAP_MODE));
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, valstr);
+ }
+
+ if((valstr = params.get(TICameraParameters::KEY_IPP)) != NULL)
+ {
+ CAMHAL_LOGDB("IPP mode set %s", params.get(TICameraParameters::KEY_IPP));
+ mParameters.set(TICameraParameters::KEY_IPP, valstr);
+ }
+
+ if((valstr = params.get(TICameraParameters::KEY_S3D2D_PREVIEW)) != NULL)
+ {
+ CAMHAL_LOGDB("Stereo 3D->2D Preview mode is %s", params.get(TICameraParameters::KEY_S3D2D_PREVIEW));
+ mParameters.set(TICameraParameters::KEY_S3D2D_PREVIEW, valstr);
+ }
+
+ if((valstr = params.get(TICameraParameters::KEY_AUTOCONVERGENCE)) != NULL)
+ {
+ CAMHAL_LOGDB("AutoConvergence mode is %s", params.get(TICameraParameters::KEY_AUTOCONVERGENCE));
+ mParameters.set(TICameraParameters::KEY_AUTOCONVERGENCE, valstr);
+ }
+ if((valstr = params.get(TICameraParameters::KEY_SENSOR_ORIENTATION)) != NULL)
+ {
+ CAMHAL_LOGDB("Sensor Orientation is set to %s", params.get(TICameraParameters::KEY_SENSOR_ORIENTATION));
+ mParameters.set(TICameraParameters::KEY_SENSOR_ORIENTATION, valstr);
+ }
+
+ }
+
+ ///Below parameters can be changed when the preview is running
+ if ( !isParameterValid(params.getPictureFormat(),
+ mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS)))
+ {
+ CAMHAL_LOGEA("Invalid picture format");
+ return -EINVAL;
+ }
+ else
+ {
+ valstr = params.getPictureFormat();
+ if (valstr)
+ mParameters.setPictureFormat(valstr);
+ }
+
+ params.getPictureSize(&w, &h);
+ if ( !isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES)))
+ {
+ CAMHAL_LOGEB("Invalid picture resolution %dx%d", w, h);
+ return -EINVAL;
+ }
+ else
+ {
+ mParameters.setPictureSize(w, h);
+ }
+
+ CAMHAL_LOGDB("Picture Size by App %d x %d", w, h);
+
+ if(( (valstr = params.get(TICameraParameters::KEY_BURST)) != NULL)
+ && (params.getInt(TICameraParameters::KEY_BURST) >=0))
+ {
+ CAMHAL_LOGDB("Burst set %s", params.get(TICameraParameters::KEY_BURST));
+ mParameters.set(TICameraParameters::KEY_BURST, valstr);
+ }
+
+ framerate = params.getPreviewFrameRate();
+ if ( isParameterValid(framerate, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES)))
+ {
+ if ( mLastPreviewFramerate != framerate )
+ {
+ mLastPreviewFramerate = framerate;
+ mParameters.setPreviewFrameRate(framerate);
+ framerateUpdated = true;
+ }
+ else
+ {
+ framerateUpdated = false;
+ }
+ }
+ else
+ {
+ framerateUpdated = false;
+ }
+
+ CAMHAL_LOGDB("FRAMERATE %d", framerate);
+
+ //If client uses fixed framerate than
+ //give it a higher piority than VFR.
+ if ( framerateUpdated )
+ {
+
+ minFPS = framerate;
+ maxFPS = framerate;
+
+ CAMHAL_LOGDB("FPS Range [%d, %d]", minFPS, maxFPS);
+ mParameters.set(TICameraParameters::KEY_MINFRAMERATE, minFPS);
+ mParameters.set(TICameraParameters::KEY_MAXFRAMERATE, maxFPS);
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, params.get(CameraParameters::KEY_PREVIEW_FPS_RANGE));
+ }
+ else if ( ( valstr = params.get(CameraParameters::KEY_PREVIEW_FPS_RANGE) ) != NULL )
+ {
+ CAMHAL_LOGDB("FPS Range = %s", valstr);
+ params.getPreviewFpsRange(&minFPS, &maxFPS);
+
+ if ( ( 0 > minFPS ) || ( 0 > maxFPS ) )
+ {
+ CAMHAL_LOGEA("FPS Range is negative!");
+ return -EINVAL;
+ }
+
+ minFPS /= CameraHal::VFR_SCALE;
+ maxFPS /= CameraHal::VFR_SCALE;
+
+ if ( ( 0 == minFPS ) || ( 0 == maxFPS ) )
+ {
+ CAMHAL_LOGEA("FPS Range is invalid!");
+ return -EINVAL;
+ }
+
+ if ( maxFPS < minFPS )
+ {
+ CAMHAL_LOGEA("Max FPS is smaller than Min FPS!");
+ return -EINVAL;
+ }
+
+ if ( maxFPS > framerate )
+ {
+ framerate = maxFPS;
+ mParameters.setPreviewFrameRate(framerate);
+ }
+
+ CAMHAL_LOGDB("FPS Range [%d, %d]", minFPS, maxFPS);
+ mParameters.set(TICameraParameters::KEY_MINFRAMERATE, minFPS);
+ mParameters.set(TICameraParameters::KEY_MAXFRAMERATE, maxFPS);
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, valstr);
+ }
+
+ if( ( valstr = params.get(TICameraParameters::KEY_GBCE) ) != NULL )
+ {
+ CAMHAL_LOGDB("GBCE Value = %s", valstr);
+ mParameters.set(TICameraParameters::KEY_GBCE, valstr);
+ }
+
+ if( ( valstr = params.get(TICameraParameters::KEY_GLBCE) ) != NULL )
+ {
+ CAMHAL_LOGDB("GLBCE Value = %s", valstr);
+ mParameters.set(TICameraParameters::KEY_GLBCE, valstr);
+ }
+
+ ///Update the current parameter set
+ if( (valstr = params.get(TICameraParameters::KEY_AUTOCONVERGENCE)) != NULL)
+ {
+ CAMHAL_LOGDB("AutoConvergence Mode is set = %s", params.get(TICameraParameters::KEY_AUTOCONVERGENCE));
+ mParameters.set(TICameraParameters::KEY_AUTOCONVERGENCE, valstr);
+ }
+
+// if(params.get(TICameraParameters::KEY_AUTOCONVERGENCE_MODE)!=NULL)
+// {
+// CAMHAL_LOGDB("AutoConvergence Mode is set = %s", params.get(TICameraParameters::KEY_AUTOCONVERGENCE_MODE));
+// mParameters.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, params.get(TICameraParameters::KEY_AUTOCONVERGENCE_MODE));
+// }
+
+ if( (valstr = params.get(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES)) !=NULL )
+ {
+ CAMHAL_LOGDB("ManualConvergence Value = %s", params.get(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES));
+ mParameters.set(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES, valstr);
+ }
+
+ if( ((valstr = params.get(TICameraParameters::KEY_EXPOSURE_MODE)) != NULL)
+ && isParameterValid(params.get(TICameraParameters::KEY_EXPOSURE_MODE),
+ mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES)))
+ {
+ CAMHAL_LOGDB("Exposure set = %s", params.get(TICameraParameters::KEY_EXPOSURE_MODE));
+ mParameters.set(TICameraParameters::KEY_EXPOSURE_MODE, valstr);
+ }
+
+ if( ((valstr = params.get(CameraParameters::KEY_WHITE_BALANCE)) != NULL)
+ && isParameterValid(params.get(CameraParameters::KEY_WHITE_BALANCE),
+ mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE)))
+ {
+ CAMHAL_LOGDB("White balance set %s", params.get(CameraParameters::KEY_WHITE_BALANCE));
+ mParameters.set(CameraParameters::KEY_WHITE_BALANCE, valstr);
+ }
+
+ if( ((valstr = params.get(TICameraParameters::KEY_CONTRAST)) != NULL)
+ && (params.getInt(TICameraParameters::KEY_CONTRAST) >= 0 ))
+ {
+ CAMHAL_LOGDB("Contrast set %s", params.get(TICameraParameters::KEY_CONTRAST));
+ mParameters.set(TICameraParameters::KEY_CONTRAST, valstr);
+ }
+
+ if( ((valstr =params.get(TICameraParameters::KEY_SHARPNESS)) != NULL) && params.getInt(TICameraParameters::KEY_SHARPNESS) >= 0 )
+ {
+ CAMHAL_LOGDB("Sharpness set %s", params.get(TICameraParameters::KEY_SHARPNESS));
+ mParameters.set(TICameraParameters::KEY_SHARPNESS, valstr);
+ }
+
+
+ if( ((valstr = params.get(TICameraParameters::KEY_SATURATION)) != NULL)
+ && (params.getInt(TICameraParameters::KEY_SATURATION) >= 0 ) )
+ {
+ CAMHAL_LOGDB("Saturation set %s", params.get(TICameraParameters::KEY_SATURATION));
+ mParameters.set(TICameraParameters::KEY_SATURATION, valstr);
+ }
+
+ if( ((valstr = params.get(TICameraParameters::KEY_BRIGHTNESS)) != NULL)
+ && (params.getInt(TICameraParameters::KEY_BRIGHTNESS) >= 0 ))
+ {
+ CAMHAL_LOGDB("Brightness set %s", params.get(TICameraParameters::KEY_BRIGHTNESS));
+ mParameters.set(TICameraParameters::KEY_BRIGHTNESS, valstr);
+ }
+
+
+ if( ((valstr = params.get(CameraParameters::KEY_ANTIBANDING)) != NULL)
+ && isParameterValid(params.get(CameraParameters::KEY_ANTIBANDING),
+ mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING)))
+ {
+ CAMHAL_LOGDB("Antibanding set %s", params.get(CameraParameters::KEY_ANTIBANDING));
+ mParameters.set(CameraParameters::KEY_ANTIBANDING, valstr);
+ }
+
+ if( ((valstr = params.get(TICameraParameters::KEY_ISO)) != NULL)
+ && isParameterValid(params.get(TICameraParameters::KEY_ISO),
+ mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES)))
+ {
+ CAMHAL_LOGDB("ISO set %s", params.get(TICameraParameters::KEY_ISO));
+ mParameters.set(TICameraParameters::KEY_ISO, valstr);
+ }
+
+ if( ((valstr = params.get(CameraParameters::KEY_FOCUS_MODE)) != NULL)
+ && isParameterValid(params.get(CameraParameters::KEY_FOCUS_MODE),
+ mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES)))
+ {
+ CAMHAL_LOGDB("Focus mode set %s", params.get(CameraParameters::KEY_FOCUS_MODE));
+ mParameters.set(CameraParameters::KEY_FOCUS_MODE, valstr);
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_FOCUS_AREAS)) != NULL )
+ {
+ CAMHAL_LOGEB("Focus areas position set %s", params.get(CameraParameters::KEY_FOCUS_AREAS));
+ mParameters.set(CameraParameters::KEY_FOCUS_AREAS, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE)) != NULL )
+ {
+ CAMHAL_LOGDB("Measurements set to %s", params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE));
+ mParameters.set(TICameraParameters::KEY_MEASUREMENT_ENABLE, valstr);
+
+ if (strcmp(valstr, (const char *) TICameraParameters::MEASUREMENT_ENABLE) == 0)
+ {
+ mMeasurementEnabled = true;
+ }
+ else if (strcmp(valstr, (const char *) TICameraParameters::MEASUREMENT_DISABLE) == 0)
+ {
+ mMeasurementEnabled = false;
+ }
+ else
+ {
+ mMeasurementEnabled = false;
+ }
+
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_EXPOSURE_COMPENSATION)) != NULL)
+ {
+ CAMHAL_LOGDB("Exposure compensation set %s", params.get(CameraParameters::KEY_EXPOSURE_COMPENSATION));
+ mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, valstr);
+ }
+
+ if(( (valstr = params.get(CameraParameters::KEY_SCENE_MODE)) != NULL)
+ && isParameterValid(params.get(CameraParameters::KEY_SCENE_MODE),
+ mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES)))
+ {
+ CAMHAL_LOGDB("Scene mode set %s", params.get(CameraParameters::KEY_SCENE_MODE));
+ mParameters.set(CameraParameters::KEY_SCENE_MODE, valstr);
+ }
+
+ if(( (valstr = params.get(CameraParameters::KEY_FLASH_MODE)) != NULL)
+ && isParameterValid(params.get(CameraParameters::KEY_FLASH_MODE),
+ mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES)))
+ {
+ CAMHAL_LOGDB("Flash mode set %s", params.get(CameraParameters::KEY_FLASH_MODE));
+ mParameters.set(CameraParameters::KEY_FLASH_MODE, valstr);
+ }
+
+ if(( (valstr = params.get(CameraParameters::KEY_EFFECT)) != NULL)
+ && isParameterValid(params.get(CameraParameters::KEY_EFFECT),
+ mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS)))
+ {
+ CAMHAL_LOGDB("Effect set %s", params.get(CameraParameters::KEY_EFFECT));
+ mParameters.set(CameraParameters::KEY_EFFECT, valstr);
+ }
+
+ if(( (valstr = params.get(CameraParameters::KEY_ROTATION)) != NULL)
+ && (params.getInt(CameraParameters::KEY_ROTATION) >=0))
+ {
+ CAMHAL_LOGDB("Rotation set %s", params.get(CameraParameters::KEY_ROTATION));
+ mParameters.set(CameraParameters::KEY_ROTATION, valstr);
+ }
+
+ if(( (valstr = params.get(CameraParameters::KEY_JPEG_QUALITY)) != NULL)
+ && (params.getInt(CameraParameters::KEY_JPEG_QUALITY) >=0))
+ {
+ CAMHAL_LOGDB("Jpeg quality set %s", params.get(CameraParameters::KEY_JPEG_QUALITY));
+ mParameters.set(CameraParameters::KEY_JPEG_QUALITY, valstr);
+ }
+
+ if(( (valstr = params.get(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH)) != NULL)
+ && (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH) >=0))
+ {
+ CAMHAL_LOGDB("Thumbnail width set %s", params.get(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH));
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, valstr);
+ }
+
+ if(( (valstr = params.get(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT)) != NULL)
+ && (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT) >=0))
+ {
+ CAMHAL_LOGDB("Thumbnail width set %s", params.get(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT));
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, valstr);
+ }
+
+ if(( (valstr = params.get(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY)) != NULL )
+ && (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY) >=0))
+ {
+ CAMHAL_LOGDB("Thumbnail quality set %s", params.get(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY));
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, valstr);
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_GPS_LATITUDE)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS latitude set %s", params.get(CameraParameters::KEY_GPS_LATITUDE));
+ mParameters.set(CameraParameters::KEY_GPS_LATITUDE, valstr);
+ }else{
+ mParameters.remove(CameraParameters::KEY_GPS_LATITUDE);
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_GPS_LONGITUDE)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS longitude set %s", params.get(CameraParameters::KEY_GPS_LONGITUDE));
+ mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, valstr);
+ }else{
+ mParameters.remove(CameraParameters::KEY_GPS_LONGITUDE);
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_GPS_ALTITUDE)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS altitude set %s", params.get(CameraParameters::KEY_GPS_ALTITUDE));
+ mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, valstr);
+ }else{
+ mParameters.remove(CameraParameters::KEY_GPS_ALTITUDE);
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_GPS_TIMESTAMP)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS timestamp set %s", params.get(CameraParameters::KEY_GPS_TIMESTAMP));
+ mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, valstr);
+ }else{
+ mParameters.remove(CameraParameters::KEY_GPS_TIMESTAMP);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_GPS_DATESTAMP)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS datestamp set %s", params.get(TICameraParameters::KEY_GPS_DATESTAMP));
+ mParameters.set(TICameraParameters::KEY_GPS_DATESTAMP, valstr);
+ }else{
+ mParameters.remove(TICameraParameters::KEY_GPS_DATESTAMP);
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD)) != NULL )
+ {
+ CAMHAL_LOGDB("GPS processing method set %s", params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD));
+ mParameters.set(CameraParameters::KEY_GPS_PROCESSING_METHOD, valstr);
+ }else{
+ mParameters.remove(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_GPS_MAPDATUM )) != NULL )
+ {
+ CAMHAL_LOGDB("GPS MAPDATUM set %s", params.get(TICameraParameters::KEY_GPS_MAPDATUM));
+ 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", params.get(TICameraParameters::KEY_GPS_VERSION));
+ mParameters.set(TICameraParameters::KEY_GPS_VERSION, valstr);
+ }else{
+ mParameters.remove(TICameraParameters::KEY_GPS_VERSION);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_EXIF_MODEL)) != NULL )
+ {
+ CAMHAL_LOGDB("EXIF Model set %s", params.get(TICameraParameters::KEY_EXIF_MODEL));
+ mParameters.set(TICameraParameters::KEY_EXIF_MODEL, valstr);
+ }
+
+ if( (valstr = params.get(TICameraParameters::KEY_EXIF_MAKE)) != NULL )
+ {
+ CAMHAL_LOGDB("EXIF Make set %s", params.get(TICameraParameters::KEY_EXIF_MAKE));
+ mParameters.set(TICameraParameters::KEY_EXIF_MAKE, valstr);
+ }
+
+ 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);
+ }
+ else
+ {
+ mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
+ }
+
+ if( ( (valstr = params.get(CameraParameters::KEY_ZOOM)) != NULL )
+ && (params.getInt(CameraParameters::KEY_ZOOM) >= 0 )
+ && (params.getInt(CameraParameters::KEY_ZOOM) <= mMaxZoomSupported ) )
+ {
+ CAMHAL_LOGDB("Zoom set %s", params.get(CameraParameters::KEY_ZOOM));
+ mParameters.set(CameraParameters::KEY_ZOOM, valstr);
+ }
+ else
+ {
+ //CTS requirement: Invalid zoom values should always return an error.
+ ret = -EINVAL;
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK)) != NULL )
+ {
+ CAMHAL_LOGDB("Auto Exposure Lock set %s", params.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK));
+ mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, valstr);
+ }
+
+ if( (valstr = params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK)) != NULL )
+ {
+ CAMHAL_LOGDB("Auto WhiteBalance Lock set %s", params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK));
+ mParameters.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, valstr);
+ }
+
+ CameraParameters adapterParams = mParameters;
+
+ //If the app has not set the capture mode, set the capture resolution as preview resolution
+ //so that black bars are not displayed in preview.
+ //Later in takePicture we will configure the correct picture size
+ if(params.get(TICameraParameters::KEY_CAP_MODE) == NULL)
+ {
+ CAMHAL_LOGDA("Capture mode not set by app, setting picture res to preview res");
+ mParameters.getPreviewSize(&w, &h);
+ adapterParams.setPictureSize(w,h);
+ }
+
+ // Only send parameters to adapter if preview is already
+ // enabled. Initial setParameters to camera adapter, will
+ // be called in startPreview()
+ if ( NULL != mCameraAdapter && mPreviewEnabled ) {
+ ret |= mCameraAdapter->setParameters(adapterParams);
+ }
+
+ 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, TICameraParameters::BRACKET_ENABLE) == 0 ))
+ {
+ if ( !mBracketingEnabled )
+ {
+ CAMHAL_LOGDA("Enabling bracketing");
+ mBracketingEnabled = true;
+
+ //Wait for AF events to enable bracketing
+ if ( NULL != mCameraAdapter )
+ {
+ setEventProvider( CameraHalEvent::ALL_EVENTS, mCameraAdapter );
+ }
+ }
+ else
+ {
+ CAMHAL_LOGDA("Bracketing already enabled");
+ }
+ }
+ else if ( ( (valstr = params.get(TICameraParameters::KEY_TEMP_BRACKETING)) != NULL ) &&
+ ( strcmp(valstr, TICameraParameters::BRACKET_DISABLE) == 0 ))
+ {
+ CAMHAL_LOGDA("Disabling bracketing");
+
+ mBracketingEnabled = false;
+ stopImageBracketing();
+
+ //Remove AF events subscription
+ if ( NULL != mEventProvider )
+ {
+ mEventProvider->disableEventNotification( CameraHalEvent::ALL_EVENTS );
+ delete mEventProvider;
+ mEventProvider = NULL;
+ }
+
+ }
+
+ if( ( (valstr = params.get(TICameraParameters::KEY_SHUTTER_ENABLE)) != NULL ) &&
+ ( strcmp(valstr, TICameraParameters::SHUTTER_ENABLE) == 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, TICameraParameters::SHUTTER_DISABLE) == 0 ))
+ {
+ CAMHAL_LOGDA("Disabling shutter sound");
+
+ mShutterEnabled = false;
+ mMsgEnabled &= ~CAMERA_MSG_SHUTTER;
+ mParameters.set(TICameraParameters::KEY_SHUTTER_ENABLE, valstr);
+ }
+
+ 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(!mPreviewBufs)
+ {
+ ///@todo Pluralise the name of this method to allocateBuffers
+ mPreviewLength = 0;
+ mPreviewBufs = (int32_t *) mDisplayAdapter->allocateBuffer(width, height,
+ previewFormat,
+ mPreviewLength,
+ buffercount);
+
+ if (NULL == mPreviewBufs ) {
+ 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;
+ }
+
+ mPreviewFd = mDisplayAdapter->getFd();
+ if ( -1 == mPreviewFd ) {
+ CAMHAL_LOGEA("Invalid handle");
+ 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("mPreviewBufs = 0x%x", (unsigned int)mPreviewBufs);
+ if(mPreviewBufs)
+ {
+ ///@todo Pluralise the name of this method to freeBuffers
+ ret = mBufProvider->freeBuffer(mPreviewBufs);
+ mPreviewBufs = 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 != mPreviewDataBufs )
+ {
+ ret = freePreviewDataBufs();
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mPreviewDataBufs = (int32_t *)mMemoryManager->allocateBuffer(0, 0, NULL, bytes, bufferCount);
+
+ CAMHAL_LOGDB("Size of Preview data buffer = %d", bytes);
+ if( NULL == mPreviewDataBufs )
+ {
+ 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;
+
+ return ret;
+}
+
+status_t CameraHal::freePreviewDataBufs()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+
+ if( NULL != mPreviewDataBufs )
+ {
+
+ ///@todo Pluralise the name of this method to freeBuffers
+ ret = mMemoryManager->freeBuffer(mPreviewDataBufs);
+ mPreviewDataBufs = NULL;
+
+ }
+ else
+ {
+ CAMHAL_LOGEA("Couldn't free PreviewDataBufs allocated by memory manager");
+ ret = -EINVAL;
+ }
+
+ }
+
+ 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;
+
+ LOG_FUNCTION_NAME;
+
+ bytes = size;
+
+ ///Always allocate the buffers for image capture using MemoryManager
+ if ( NO_ERROR == ret )
+ {
+ if( ( NULL != mImageBufs ) )
+ {
+ ret = freeImageBufs();
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mImageBufs = (int32_t *)mMemoryManager->allocateBuffer(0, 0, previewFormat, bytes, bufferCount);
+
+ CAMHAL_LOGDB("Size of Image cap buffer = %d", bytes);
+ if( NULL == mImageBufs )
+ {
+ 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();
+ }
+ else
+ {
+ mImageFd = -1;
+ mImageLength = 0;
+ mImageOffsets = NULL;
+ }
+
+ LOG_FUNCTION_NAME;
+
+ 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;
+ CameraParameters adapterParams = mParameters;
+ Mutex::Autolock lock(mLock);
+
+ LOG_FUNCTION_NAME;
+
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE);
+
+ //If the app has not set the capture mode, restore the capture resolution
+ //back to the preview resolution to get rid of the black bars issue
+ if (mParameters.get(TICameraParameters::KEY_CAP_MODE) == NULL) {
+ CAMHAL_LOGDA("Capture mode not set by app, setting picture res back to preview res");
+ mParameters.getPreviewSize(&w, &h);
+ adapterParams.setPictureSize(w,h);
+ ret = mCameraAdapter->setParameters(adapterParams);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::freeImageBufs()
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NO_ERROR == ret )
+ {
+
+ if( NULL != mImageBufs )
+ {
+
+ ///@todo Pluralise the name of this method to freeBuffers
+ ret = mMemoryManager->freeBuffer(mImageBufs);
+ mImageBufs = 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()
+{
+
+ status_t ret = NO_ERROR;
+ CameraAdapter::BuffersDescriptor desc;
+ CameraFrame frame;
+ const char *valstr = NULL;
+ unsigned int required_buffer_count;
+ unsigned int max_queueble_buffers;
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ gettimeofday(&mStartPreview, NULL);
+
+#endif
+
+ LOG_FUNCTION_NAME;
+
+ 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);
+ }
+ return ret;
+
+ }
+ else if ( mPreviewEnabled )
+ {
+ CAMHAL_LOGDA("Preview already running");
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ALREADY_EXISTS;
+ }
+
+ ///If we don't have the preview callback enabled and display adapter,
+ if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL))
+ {
+ CAMHAL_LOGEA("Preview not started. Preview in progress flag set");
+ mPreviewStartInProgress = true;
+ return NO_ERROR;
+ }
+
+ if ( NULL != mCameraAdapter ) {
+
+ CameraParameters adapterParams = mParameters;
+
+ //If the app has not set the capture mode, set the capture resolution as preview resolution
+ //so that black bars are not displayed in preview.
+ //Later in takePicture we will configure the correct picture size
+ if(mParameters.get(TICameraParameters::KEY_CAP_MODE) == NULL)
+ {
+ int w,h;
+ CAMHAL_LOGDA("Capture mode not set by app, setting picture res to preview res");
+ mParameters.getPreviewSize(&w, &h);
+ adapterParams.setPictureSize(w,h);
+ }
+
+ ret = mCameraAdapter->setParameters(adapterParams);
+ }
+
+ /// Ensure that buffers for preview are allocated before we start the camera
+ ///Get the updated size from Camera Adapter, to account for padding etc
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,
+ ( int ) &frame);
+ if ( NO_ERROR != ret )
+ {
+ return ret;
+ }
+
+ ///Update the current preview width and height
+ mPreviewWidth = frame.mWidth;
+ mPreviewHeight = frame.mHeight;
+
+ //Update the padded width and height - required for VNF and VSTAB
+ mParameters.set(TICameraParameters::KEY_PADDED_WIDTH, mPreviewWidth);
+ mParameters.set(TICameraParameters::KEY_PADDED_HEIGHT, mPreviewHeight);
+
+ required_buffer_count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
+
+ ///Allocate the preview buffers
+ ret = allocPreviewBufs(frame.mWidth, frame.mHeight, 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 = mPreviewDataBufs;
+ 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 = mPreviewBufs;
+ desc.mOffsets = mPreviewOffsets;
+ desc.mFd = mPreviewFd;
+ desc.mLength = mPreviewLength;
+ desc.mCount = ( size_t ) required_buffer_count;
+ desc.mMaxQueueable = (size_t) max_queueble_buffers;
+
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW,
+ ( int ) &desc);
+
+ mAppCallbackNotifier->startPreviewCallbacks(mParameters, mPreviewBufs, mPreviewOffsets, mPreviewFd, mPreviewLength, required_buffer_count);
+
+ ///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;
+ }
+
+ ///Enable the display adapter if present, actual overlay enable happens when we post the buffer
+ if(mDisplayAdapter.get() != NULL)
+ {
+ CAMHAL_LOGDA("Enabling display");
+ bool isS3d = false;
+ DisplayAdapter::S3DParameters s3dParams;
+ int width, height;
+ mParameters.getPreviewSize(&width, &height);
+#if 0 //TODO: s3d is not part of bringup...will reenable
+ if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D_SUPPORTED)) != NULL) {
+ isS3d = (strcmp(valstr, "true") == 0);
+ }
+ if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D2D_PREVIEW)) != NULL) {
+ if (strcmp(valstr, "off") == 0)
+ {
+ CAMHAL_LOGEA("STEREO 3D->2D PREVIEW MODE IS OFF");
+ //TODO: obtain the frame packing configuration from camera or user settings
+ //once side by side configuration is supported
+ s3dParams.mode = OVERLAY_S3D_MODE_ON;
+ s3dParams.framePacking = OVERLAY_S3D_FORMAT_OVERUNDER;
+ s3dParams.order = OVERLAY_S3D_ORDER_LF;
+ s3dParams.subSampling = OVERLAY_S3D_SS_NONE;
+ }
+ else
+ {
+ CAMHAL_LOGEA("STEREO 3D->2D PREVIEW MODE IS ON");
+ s3dParams.mode = OVERLAY_S3D_MODE_OFF;
+ s3dParams.framePacking = OVERLAY_S3D_FORMAT_OVERUNDER;
+ s3dParams.order = OVERLAY_S3D_ORDER_LF;
+ s3dParams.subSampling = OVERLAY_S3D_SS_NONE;
+ }
+ }
+#endif //if 0
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview, isS3d ? &s3dParams : NULL);
+
+#else
+
+ ret = mDisplayAdapter->enableDisplay(width, height, NULL, isS3d ? &s3dParams : NULL);
+
+#endif
+
+ if ( ret != NO_ERROR )
+ {
+ CAMHAL_LOGEA("Couldn't enable display");
+ 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();
+ }
+ 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_LOGEA("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_LOGEA("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
+ mDisplayAdapter = new ANativeWindowDisplayAdapter();
+ 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
+ {
+ /* If mDisplayAdpater is already created. No need to do anything.
+ * We get a surface handle directly now, so we can reconfigure surface
+ * itself in DisplayAdapter if dimensions have changed
+ */
+ }
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+
+}
+
+
+/**
+ @brief Stop a previously started preview.
+
+ @param none
+ @return none
+
+ */
+void CameraHal::stopPreview()
+{
+ LOG_FUNCTION_NAME;
+
+ if(!previewEnabled() && !mDisplayPaused)
+ {
+ LOG_FUNCTION_NAME_EXIT;
+ return;
+ }
+
+ if(mDisplayPaused)
+ {
+ // 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();
+
+ 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;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ gettimeofday(&mStartPreview, NULL);
+
+#endif
+
+ if(!previewEnabled())
+ {
+ return NO_INIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setVideoModeParameters();
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = mAppCallbackNotifier->initSharedVideoBuffers(mPreviewBufs, mPreviewOffsets, mPreviewFd, mPreviewLength, atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS)));
+ }
+
+ 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 NO_ERROR If recording parameters could be set without any issues
+ @todo Modify the policies for enabling VSTAB & VNF usecase based later.
+
+ */
+status_t CameraHal::setVideoModeParameters()
+{
+ const char *valstr = NULL;
+ bool restartPreviewRequired = false;
+ status_t ret = NO_ERROR;
+
+ 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) ) )
+ {
+ CAMHAL_LOGDA("Set CAPTURE_MODE to VIDEO_MODE");
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, (const char *) TICameraParameters::VIDEO_MODE);
+ restartPreviewRequired = true;
+ }
+
+ // FIXME: This check is put since currently VSTAB and VNF are functional only for Primary Camera.
+ // Remove this check once VSTAB and VNF are functional for Secondary Camera as well.
+ if(mCameraIndex == 0)
+ {
+ // Check if CAPTURE_MODE is VIDEO_MODE, since VSTAB & VNF work only in VIDEO_MODE.
+ valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
+ if (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE) == 0)
+ {
+ // Enable VSTAB, if not enabled already
+ valstr = mParameters.get(TICameraParameters::KEY_VSTAB);
+ if ( (valstr == NULL) ||
+ ( (valstr != NULL) && (strcmp(valstr, "1") != 0) ) )
+ {
+ CAMHAL_LOGDA("Enable VSTAB");
+ mParameters.set(TICameraParameters::KEY_VSTAB, "1");
+ restartPreviewRequired = true;
+ }
+
+ // Enable VNF, if not enabled already
+ valstr = mParameters.get(TICameraParameters::KEY_VNF);
+ if ( (valstr == NULL) ||
+ ( (valstr != NULL) && (strcmp(valstr, "1") != 0) ) )
+ {
+ CAMHAL_LOGDA("Enable VNF");
+ mParameters.set(TICameraParameters::KEY_VNF, "1");
+ restartPreviewRequired = true;
+ }
+
+ // 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.
+ valstr = mParameters.get(TICameraParameters::KEY_VSTAB);
+ if ((valstr != NULL) && (strcmp(valstr, "1") == 0) && (mPreviewWidth == 1920))
+ {
+ CAMHAL_LOGDA("Force Enable VNF for 1080p");
+ mParameters.set(TICameraParameters::KEY_VNF, "1");
+ restartPreviewRequired = true;
+ }
+ }
+ }
+
+ if (restartPreviewRequired)
+ {
+ CAMHAL_LOGDA("Restarting preview");
+ stopPreview();
+ // Setting CAPTURE_MODE to VIDEO_MODE again, since it is reset in stopPreview()
+ mParameters.set(TICameraParameters::KEY_CAP_MODE, (const char *) TICameraParameters::VIDEO_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()
+{
+ LOG_FUNCTION_NAME;
+
+ if (!mRecordingEnabled )
+ {
+ return;
+ }
+
+ mAppCallbackNotifier->stopRecording();
+
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_VIDEO);
+
+ mRecordingEnabled = false;
+
+ 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;
+
+ if ( NULL != mCameraAdapter )
+ {
+
+#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
+
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ 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;
+ if( NULL != mCameraAdapter )
+ {
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_CANCEL_AUTOFOCUS);
+ }
+ 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;
+
+ if ( NULL != event )
+ {
+ switch( event->mEventType )
+ {
+ case CameraHalEvent::EVENT_FOCUS_LOCKED:
+ case CameraHalEvent::EVENT_FOCUS_ERROR:
+ {
+ if ( mBracketingEnabled )
+ {
+ startImageBracketing();
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ };
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t CameraHal::startImageBracketing()
+{
+ status_t ret = NO_ERROR;
+ CameraFrame frame;
+ CameraAdapter::BuffersDescriptor desc;
+
+#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 = mImageBufs;
+ 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 ( !mBracketingRunning )
+ {
+ return ret;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mBracketingRunning = false;
+ }
+
+ if(!previewEnabled() && !mDisplayPaused)
+ {
+ return NO_INIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ 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( )
+{
+ status_t ret = NO_ERROR;
+ CameraFrame frame;
+ CameraAdapter::BuffersDescriptor desc;
+ int burst;
+ unsigned int bufferCount = 1;
+
+ Mutex::Autolock lock(mLock);
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ gettimeofday(&mStartCapture, NULL);
+
+#endif
+
+ LOG_FUNCTION_NAME;
+
+ if(!previewEnabled() && !mDisplayPaused)
+ {
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ //If capture has already started, then queue this call for later execution
+ if ( mCameraAdapter->getState() == CameraAdapter::CAPTURE_STATE &&
+ mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) {
+ return NO_INIT;
+ }
+
+ if ( !mBracketingRunning )
+ {
+
+ if ( NO_ERROR == ret )
+ {
+ burst = mParameters.getInt(TICameraParameters::KEY_BURST);
+ }
+
+ //Allocate all buffers only in burst capture case
+ if ( burst > 1 )
+ {
+ bufferCount = CameraHal::NO_BUFFERS_IMAGE_CAPTURE;
+ if ( NULL != mAppCallbackNotifier.get() )
+ {
+ mAppCallbackNotifier->setBurst(true);
+ }
+ }
+ else
+ {
+ if ( NULL != mAppCallbackNotifier.get() )
+ {
+ mAppCallbackNotifier->setBurst(false);
+ }
+ }
+
+ //Pause Preview during capture
+ if ( (NO_ERROR == ret) && ( NULL != mDisplayAdapter.get() ) && ( burst < 1 ) )
+ {
+ mDisplayPaused = true;
+ mPreviewEnabled = false;
+ ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);
+
+#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
+
+ mDisplayAdapter->setSnapshotTimeRef(&mStartCapture);
+
+#endif
+ // since preview is paused we should stop sending preview frames too
+ if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+ {
+ mAppCallbackNotifier->disableMsgType (CAMERA_MSG_PREVIEW_FRAME);
+ }
+ }
+
+ if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
+ {
+
+ //Configure the correct picture resolution now if the capture mode is not set
+ if(mParameters.get(TICameraParameters::KEY_CAP_MODE) == NULL)
+ {
+ ret = mCameraAdapter->setParameters(mParameters);
+ }
+
+ 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 ( NO_ERROR == ret )
+ {
+ mParameters.getPictureSize(( int * ) &frame.mWidth,
+ ( int * ) &frame.mHeight);
+
+ ret = allocImageBufs(frame.mWidth,
+ frame.mHeight,
+ frame.mLength,
+ mParameters.getPictureFormat(),
+ bufferCount);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret);
+ }
+ }
+
+ if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
+ {
+ desc.mBuffers = mImageBufs;
+ desc.mOffsets = mImageOffsets;
+ desc.mFd = mImageFd;
+ desc.mLength = mImageLength;
+ desc.mCount = ( size_t ) bufferCount;
+ desc.mMaxQueueable = ( size_t ) bufferCount;
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE,
+ ( int ) &desc);
+ }
+ }
+ else
+ {
+ mBracketingRunning = false;
+ }
+
+ 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);
+
+#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;
+
+ Mutex::Autolock lock(mLock);
+
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE);
+
+ return NO_ERROR;
+}
+
+/**
+ @brief Return the camera parameters.
+
+ @param none
+ @return Currently configured camera parameters
+
+ */
+char* CameraHal::getParameters()
+{
+ CameraParameters params;
+ String8 params_str8;
+ char* params_string;
+
+ LOG_FUNCTION_NAME;
+
+ params = mParameters;
+ if( NULL != mCameraAdapter )
+ {
+ mCameraAdapter->getParameters(params);
+ }
+
+ params_str8 = params.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;
+}
+
+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");
+ ret = -EINVAL;
+ }
+
+ if ( ( NO_ERROR == ret ) && ( !previewEnabled() ))
+ {
+ CAMHAL_LOGEA("Preview is not running");
+ ret = -EINVAL;
+ }
+
+ 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);
+
+ case CAMERA_CMD_START_FACE_DETECTION:
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_FD);
+
+ break;
+
+ case CAMERA_CMD_STOP_FACE_DETECTION:
+
+ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_FD);
+
+ break;
+
+ 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)
+{
+ LOG_FUNCTION_NAME;
+
+ ///Initialize all the member variables to their defaults
+ mPreviewEnabled = false;
+ mPreviewBufs = NULL;
+ mImageBufs = NULL;
+ mBufProvider = NULL;
+ mPreviewStartInProgress = false;
+ mVideoBufs = 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;
+ mPreviewDataBufs = NULL;
+ mCameraProperties = NULL;
+ mCurrentTime = 0;
+ mFalsePreview = 0;
+ mImageOffsets = NULL;
+ mImageLength = 0;
+ mImageFd = 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;
+
+#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;
+
+ 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 memory manager
+ mMemoryManager.clear();
+
+ /// Free the display adapter
+ mDisplayAdapter.clear();
+
+ if ( NULL != mCameraAdapter ) {
+ int strongCount = mCameraAdapter->getStrongCount();
+
+ mCameraAdapter->decStrong(mCameraAdapter);
+
+ mCameraAdapter = NULL;
+ }
+
+ 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;
+
+ mLastPreviewFramerate = 0;
+
+ ///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));
+ }
+
+ CAMHAL_LOGDB("Sensor index %d", sensor_index);
+
+ mCameraAdapter = CameraAdapter_Factory();
+ if ( ( NULL == mCameraAdapter ) || (mCameraAdapter->initialize(properties, sensor_index)!=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 = true;
+ status_t status = NO_ERROR;
+ char tmpBuffer[PARAM_BUFFER + 1];
+ char *pos = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == supportedResolutions )
+ {
+ CAMHAL_LOGEA("Invalid supported resolutions string");
+ ret = false;
+ goto exit;
+ }
+
+ status = snprintf(tmpBuffer, PARAM_BUFFER, "%dx%d", width, height);
+ if ( 0 > status )
+ {
+ CAMHAL_LOGEA("Error encountered while generating validation string");
+ ret = false;
+ goto exit;
+ }
+
+ pos = strstr(supportedResolutions, tmpBuffer);
+ if ( NULL == pos )
+ {
+ ret = false;
+ }
+ else
+ {
+ ret = true;
+ }
+
+exit:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+bool CameraHal::isParameterValid(const char *param, const char *supportedParams)
+{
+ bool ret = true;
+ char *pos = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == supportedParams )
+ {
+ CAMHAL_LOGEA("Invalid supported parameters string");
+ ret = false;
+ goto exit;
+ }
+
+ if ( NULL == param )
+ {
+ CAMHAL_LOGEA("Invalid parameter string");
+ ret = false;
+ goto exit;
+ }
+
+ pos = strstr(supportedParams, param);
+ if ( NULL == pos )
+ {
+ ret = false;
+ }
+ else
+ {
+ ret = true;
+ }
+
+exit:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+bool CameraHal::isParameterValid(int param, const char *supportedParams)
+{
+ bool ret = true;
+ char *pos = NULL;
+ status_t status;
+ char tmpBuffer[PARAM_BUFFER + 1];
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == supportedParams )
+ {
+ CAMHAL_LOGEA("Invalid supported parameters string");
+ ret = false;
+ goto exit;
+ }
+
+ status = snprintf(tmpBuffer, PARAM_BUFFER, "%d", param);
+ if ( 0 > status )
+ {
+ CAMHAL_LOGEA("Error encountered while generating validation string");
+ ret = false;
+ goto exit;
+ }
+
+ pos = strstr(supportedParams, tmpBuffer);
+ if ( NULL == pos )
+ {
+ ret = false;
+ }
+ else
+ {
+ ret = true;
+ }
+
+exit:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t CameraHal::parseResolution(const char *resStr, int &width, int &height)
+{
+ status_t ret = NO_ERROR;
+ char *ctx, *pWidth, *pHeight;
+ const char *sep = "x";
+ char *tmp = NULL;
+
+ 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 ) {
+ if ( NO_ERROR == ret )
+ {
+ strcpy(resStr_copy, resStr);
+ pWidth = strtok_r( (char *) 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()
+{
+ char tmpBuffer[PARAM_BUFFER + 1];
+
+ LOG_FUNCTION_NAME;
+
+ 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(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES));
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS));
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES));
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS));
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES));
+ p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_THUMBNAIL_SIZES));
+ p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE));
+ p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS));
+ p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES));
+ p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES));
+ p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES));
+ p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING));
+ p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MAX));
+ p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MIN));
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_EV_STEP));
+ p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES));
+ p.set(TICameraParameters::KEY_SUPPORTED_EXPOSURE, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES));
+ p.set(TICameraParameters::KEY_SUPPORTED_ISO_VALUES, mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES));
+ p.set(CameraParameters::KEY_ZOOM_RATIOS, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_RATIOS));
+ p.set(CameraParameters::KEY_MAX_ZOOM, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_STAGES));
+ p.set(CameraParameters::KEY_ZOOM_SUPPORTED, mCameraProperties->get(CameraProperties::ZOOM_SUPPORTED));
+ p.set(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_SUPPORTED,mCameraProperties->get(CameraProperties::S3D_SUPPORTED));
+ p.set(TICameraParameters::KEY_S3D2D_PREVIEW_MODE,mCameraProperties->get(CameraProperties::S3D2D_PREVIEW_MODES));
+ p.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE_MODE));
+ p.set(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES, mCameraProperties->get(CameraProperties::MANUALCONVERGENCE_VALUES));
+ p.set(TICameraParameters::KEY_VSTAB,mCameraProperties->get(CameraProperties::VSTAB));
+ p.set(TICameraParameters::KEY_VSTAB_VALUES,mCameraProperties->get(CameraProperties::VSTAB_VALUES));
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED));
+ p.set(TICameraParameters::KEY_SENSOR_ORIENTATION, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION));
+ p.set(TICameraParameters::KEY_SENSOR_ORIENTATION_VALUES, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION_VALUES));
+ p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED));
+ p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED));
+
+ 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.
+
+ CameraParameters &p = mParameters;
+ int currentRevision, adapterRevision;
+ status_t ret = NO_ERROR;
+ int width, height;
+
+ LOG_FUNCTION_NAME;
+
+ 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(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
+ }
+ else
+ {
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, MIN_WIDTH);
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, MIN_HEIGHT);
+ }
+
+ insertSupportedParams();
+
+ //Insert default values
+ p.setPreviewFrameRate(atoi(mCameraProperties->get(CameraProperties::PREVIEW_FRAME_RATE)));
+ p.setPreviewFormat(mCameraProperties->get(CameraProperties::PREVIEW_FORMAT));
+ p.setPictureFormat(mCameraProperties->get(CameraProperties::PICTURE_FORMAT));
+ p.set(CameraParameters::KEY_JPEG_QUALITY, mCameraProperties->get(CameraProperties::JPEG_QUALITY));
+ p.set(CameraParameters::KEY_WHITE_BALANCE, mCameraProperties->get(CameraProperties::WHITEBALANCE));
+ p.set(CameraParameters::KEY_EFFECT, mCameraProperties->get(CameraProperties::EFFECT));
+ p.set(CameraParameters::KEY_ANTIBANDING, mCameraProperties->get(CameraProperties::ANTIBANDING));
+ p.set(CameraParameters::KEY_FLASH_MODE, mCameraProperties->get(CameraProperties::FLASH_MODE));
+ p.set(CameraParameters::KEY_FOCUS_MODE, mCameraProperties->get(CameraProperties::FOCUS_MODE));
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::EV_COMPENSATION));
+ p.set(CameraParameters::KEY_SCENE_MODE, mCameraProperties->get(CameraProperties::SCENE_MODE));
+ p.set(CameraParameters::KEY_FLASH_MODE, mCameraProperties->get(CameraProperties::FLASH_MODE));
+ p.set(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_ISO, mCameraProperties->get(CameraProperties::ISO_MODE));
+ p.set(TICameraParameters::KEY_IPP, mCameraProperties->get(CameraProperties::IPP));
+ p.set(TICameraParameters::KEY_S3D2D_PREVIEW, mCameraProperties->get(CameraProperties::S3D2D_PREVIEW));
+ p.set(TICameraParameters::KEY_AUTOCONVERGENCE, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE));
+ p.set(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES, mCameraProperties->get(CameraProperties::MANUALCONVERGENCE_VALUES));
+ p.set(TICameraParameters::KEY_VSTAB,mCameraProperties->get(CameraProperties::VSTAB));
+ p.set(TICameraParameters::KEY_VSTAB_VALUES,mCameraProperties->get(CameraProperties::VSTAB_VALUES));
+ p.set(CameraParameters::KEY_FOCAL_LENGTH, mCameraProperties->get(CameraProperties::FOCAL_LENGTH));
+ p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::HOR_ANGLE));
+ p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::VER_ANGLE));
+ p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,mCameraProperties->get(CameraProperties::FRAMERATE_RANGE));
+ p.set(TICameraParameters::KEY_SENSOR_ORIENTATION, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION));
+ p.set(TICameraParameters::KEY_SENSOR_ORIENTATION_VALUES, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION_VALUES));
+ p.set(TICameraParameters::KEY_EXIF_MAKE, mCameraProperties->get(CameraProperties::EXIF_MAKE));
+ p.set(TICameraParameters::KEY_EXIF_MODEL, mCameraProperties->get(CameraProperties::EXIF_MODEL));
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, mCameraProperties->get(CameraProperties::JPEG_THUMBNAIL_QUALITY));
+ p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar");
+ p.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, mCameraProperties->get(CameraProperties::MAX_FD_HW_FACES));
+ p.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW, mCameraProperties->get(CameraProperties::MAX_FD_SW_FACES));
+
+ // Only one area a.k.a Touch AF for now.
+ // TODO: Add support for multiple focus areas.
+ p.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, mCameraProperties->get(CameraProperties::MAX_FOCUS_AREAS));
+ p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK));
+ p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK));
+ p.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS, mCameraProperties->get(CameraProperties::MAX_NUM_METERING_AREAS));
+
+ 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
+ stopImageBracketing();
+
+ if(mDisplayAdapter.get() != NULL) {
+ ///Stop the buffer display first
+ mDisplayAdapter->disableDisplay();
+ }
+
+ if(mAppCallbackNotifier.get() != NULL) {
+ //Stop the callback sending
+ mAppCallbackNotifier->stop();
+ mAppCallbackNotifier->stopPreviewCallbacks();
+ }
+
+ // since prerequisite for capturing is for camera system
+ // to be previewing...cancel all captures before stopping
+ // preview
+ if ( mCameraAdapter->getState() == CameraAdapter::CAPTURE_STATE &&
+ mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) {
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE);
+ }
+
+ if ( NULL != mCameraAdapter ) {
+ cancelAutoFocus();
+ //Stop the source of frames
+ mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
+ }
+
+ freePreviewBufs();
+ freePreviewDataBufs();
+
+ mPreviewEnabled = false;
+ mDisplayPaused = 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 ) {
+ forceStopPreview();
+ }
+
+ freeImageBufs();
+
+ mSetPreviewWindowCalled = false;
+
+ if (mSensorListener.get()) {
+ mSensorListener->disableSensor(SensorListener::SENSOR_ORIENTATION);
+ mSensorListener.clear();
+ mSensorListener = NULL;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+}
+
+status_t CameraHal::storeMetaDataInBuffers(bool enable)
+{
+ LOG_FUNCTION_NAME;
+
+ return mAppCallbackNotifier->useMetaDataBufferMode(enable);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+};
+
+
diff --git a/camera/CameraHalCommon.cpp b/camera/CameraHalCommon.cpp
new file mode 100644
index 0000000..6d4ea2c
--- /dev/null
+++ b/camera/CameraHalCommon.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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 android {
+
+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;
+
+ LOGD("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;
+
+ LOGD("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;
+
+ LOGD("PPM: %s :%ld.%ld ms : %llu ms", temp_str, ( ppm.tv_sec /1000 ), ( ppm.tv_sec % 1000 ), absolute);
+
+ va_end(args);
+}
+
+#endif
+
+};
+
+
diff --git a/camera/CameraHalUtilClasses.cpp b/camera/CameraHalUtilClasses.cpp
new file mode 100644
index 0000000..84eea38
--- /dev/null
+++ b/camera/CameraHalUtilClasses.cpp
@@ -0,0 +1,273 @@
+/*
+ * 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).
+*
+*/
+
+#define LOG_TAG "CameraHAL"
+
+
+#include "CameraHal.h"
+
+namespace android {
+
+/*--------------------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(void *frameBuf, CameraFrame::FrameType frameType)
+{
+ status_t ret = NO_ERROR;
+
+ mFrameNotifier->returnFrame(frameBuf, frameType);
+
+ return ret;
+}
+
+
+/*--------------------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::FRAME_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::parseFocusArea(const char *area,
+ size_t areaLength,
+ Vector< 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;
+ 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;
+ }
+
+ 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;
+}
+
+/*--------------------CameraArea Class ENDS here-----------------------------*/
+
+};
diff --git a/camera/CameraHal_Module.cpp b/camera/CameraHal_Module.cpp
new file mode 100644
index 0000000..cf3ec60
--- /dev/null
+++ b/camera/CameraHal_Module.cpp
@@ -0,0 +1,676 @@
+/*
+ * 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.
+*
+*/
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "CameraProperties.h"
+#include "TICameraParameters.h"
+
+
+static android::CameraProperties gCameraProperties;
+static android::CameraHal* gCameraHals[MAX_CAMERAS_SUPPORTED];
+
+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
+};
+
+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: &camera_module_methods,
+ dso: NULL, /* remove compilation warnings */
+ reserved: {0}, /* remove compilation warnings */
+ },
+ get_number_of_cameras: camera_get_number_of_cameras,
+ get_camera_info: camera_get_camera_info,
+};
+
+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)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->setPreviewWindow(window);
+
+ return rv;
+}
+
+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)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->stopPreview();
+}
+
+int camera_preview_enabled(struct camera_device * device)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->stopRecording();
+}
+
+int camera_recording_enabled(struct camera_device * device)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->releaseRecordingFrame(opaque);
+}
+
+int camera_auto_focus(struct camera_device * device)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->takePicture();
+ return rv;
+}
+
+int camera_cancel_picture(struct camera_device * device)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->cancelPicture();
+ return rv;
+}
+
+int camera_set_parameters(struct camera_device * device, const char *params)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ char* param = NULL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ 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)
+{
+ int rv = -EINVAL;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if(!device)
+ return rv;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ rv = gCameraHals[ti_dev->cameraid]->sendCommand(cmd, arg1, arg2);
+ return rv;
+}
+
+void camera_release(struct camera_device * device)
+{
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if(!device)
+ return;
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ gCameraHals[ti_dev->cameraid]->release();
+}
+
+int camera_dump(struct camera_device * device, int fd)
+{
+ 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)
+{
+ int ret = 0;
+ ti_camera_device_t* ti_dev = NULL;
+
+ LOGV("%s", __FUNCTION__);
+
+ if (!device) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ti_dev = (ti_camera_device_t*) device;
+
+ if (gCameraHals[ti_dev->cameraid]) {
+ delete gCameraHals[ti_dev->cameraid];
+ gCameraHals[ti_dev->cameraid] = NULL;
+ }
+
+ 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 = -EINVAL;
+ int num_cameras = 0;
+ int cameraid;
+ ti_camera_device_t* camera_device = NULL;
+ camera_device_ops_t* camera_ops = NULL;
+ android::CameraHal* camera = NULL;
+ android::CameraProperties::Properties* properties = NULL;
+
+ LOGI("camera_device open");
+
+ if (name != NULL) {
+ cameraid = atoi(name);
+ num_cameras = gCameraProperties.camerasSupported();
+
+ if(cameraid > num_cameras)
+ {
+ LOGE("camera service provided cameraid out of bounds, "
+ "cameraid = %d, num supported = %d",
+ cameraid, num_cameras);
+ goto fail;
+ }
+
+ camera_device = (ti_camera_device_t*)malloc(sizeof(*camera_device));
+ if(!camera_device)
+ {
+ LOGE("camera_device allocation fail");
+ rv = -ENOMEM;
+ goto fail;
+ }
+
+ camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));
+ if(!camera_ops)
+ {
+ 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)
+ {
+ LOGE("Couldn't get camera properties");
+ rv = -ENOMEM;
+ goto fail;
+ }
+
+ camera = new android::CameraHal(cameraid);
+
+ if(!camera)
+ {
+ LOGE("Couldn't create instance of CameraHal class");
+ rv = -ENOMEM;
+ goto fail;
+ }
+
+ if(properties && (camera->initialize(properties) != android::NO_ERROR))
+ {
+ LOGE("Couldn't initialize camera instance");
+ rv = -ENODEV;
+ goto fail;
+ }
+
+ gCameraHals[cameraid] = camera;
+ }
+
+ return rv;
+
+fail:
+
+ if(camera_device)
+ free(camera_device);
+ if(camera_ops)
+ free(camera_ops);
+ if(camera)
+ delete camera;
+
+ return rv;
+}
+
+int camera_get_number_of_cameras(void)
+{
+ int num_cameras = MAX_CAMERAS_SUPPORTED;
+
+ // TODO(XXX): Ducati is not loaded yet when camera service gets here
+ // Lets revisit this later to see if we can somehow get this working
+#if 0
+ // this going to be the first call from camera service
+ // initialize camera properties here...
+ if(gCameraProperties.initialize() != android::NO_ERROR)
+ {
+ CAMHAL_LOGEA("Unable to create or initialize CameraProperties");
+ return NULL;
+ }
+
+ num_cameras = gCameraProperties.camerasSupported();
+#endif
+
+ 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;
+ android::CameraProperties::Properties* properties = NULL;
+
+ // this going to be the first call from camera service
+ // initialize camera properties here...
+ if(gCameraProperties.initialize() != android::NO_ERROR)
+ {
+ CAMHAL_LOGEA("Unable to create or initialize CameraProperties");
+ return NULL;
+ }
+
+ //Get camera properties for camera index
+ if(gCameraProperties.getProperties(camera_id, &properties) < 0)
+ {
+ LOGE("Couldn't get camera properties");
+ rv = -EINVAL;
+ goto end;
+ }
+
+ if(properties)
+ {
+ valstr = properties->get(android::CameraProperties::FACING_INDEX);
+ if(valstr != NULL)
+ {
+ if (strcmp(valstr, (const char *) android::TICameraParameters::FACING_FRONT) == 0)
+ {
+ face_value = CAMERA_FACING_FRONT;
+ }
+ else if (strcmp(valstr, (const char *) android::TICameraParameters::FACING_BACK) == 0)
+ {
+ face_value = CAMERA_FACING_BACK;
+ }
+ }
+
+ valstr = properties->get(android::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;
+}
+
+
+
+
+
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
new file mode 100644
index 0000000..f19a0fe
--- /dev/null
+++ b/camera/CameraParameters.cpp
@@ -0,0 +1,184 @@
+/*
+ * 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 "CameraHal.h"
+#include "CameraProperties.h"
+
+namespace android {
+
+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::ORIENTATION_INDEX[]="prop-orientation";
+const char CameraProperties::FACING_INDEX[]="prop-facing";
+const char CameraProperties::S3D_SUPPORTED[]="prop-s3d-supported";
+const char CameraProperties::SUPPORTED_PREVIEW_SIZES[] = "prop-preview-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_PICTURE_SIZES[] = "prop-picture-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_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::S3D2D_PREVIEW[] = "prop-s3d2d-preview";
+const char CameraProperties::S3D2D_PREVIEW_MODES[] = "prop-s3d2d-preview-values";
+const char CameraProperties::AUTOCONVERGENCE[] = "prop-auto-convergence";
+const char CameraProperties::AUTOCONVERGENCE_MODE[] = "prop-auto-convergence-mode";
+const char CameraProperties::MANUALCONVERGENCE_VALUES[] = "prop-manual-convergence-values";
+const char CameraProperties::VSTAB[] = "prop-vstab-default";
+const char CameraProperties::VSTAB_VALUES[] = "prop-vstab-values";
+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::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::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((unsigned int)cameraIndex >= mCamerasSupported)
+ {
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ *properties = mCameraProps+cameraIndex;
+
+ LOG_FUNCTION_NAME_EXIT;
+ return 0;
+}
+
+ssize_t CameraProperties::Properties::set(const char *prop, const char *value)
+{
+ if(!prop)
+ return -EINVAL;
+ if(!value)
+ value = DEFAULT_VALUE;
+
+ return mProperties->replaceValueFor(String8(prop), String8(value));
+}
+
+ssize_t CameraProperties::Properties::set(const char *prop, int value)
+{
+ char s_val[30];
+
+ sprintf(s_val, "%d", value);
+
+ return set(prop, s_val);
+}
+
+const char* CameraProperties::Properties::get(const char * prop)
+{
+ String8 value = mProperties->valueFor(String8(prop));
+ return value.string();
+}
+
+void CameraProperties::Properties::dump()
+{
+ for (size_t i = 0; i < mProperties->size(); i++)
+ {
+ CAMHAL_LOGDB("%s = %s\n",
+ mProperties->keyAt(i).string(),
+ mProperties->valueAt(i).string());
+ }
+}
+
+const char* CameraProperties::Properties::keyAt(unsigned int index)
+{
+ if(index < mProperties->size())
+ {
+ return mProperties->keyAt(index).string();
+ }
+ return NULL;
+}
+
+const char* CameraProperties::Properties::valueAt(unsigned int index)
+{
+ if(index < mProperties->size())
+ {
+ return mProperties->valueAt(index).string();
+ }
+ return NULL;
+}
+
+};
diff --git a/camera/CameraProperties.cpp b/camera/CameraProperties.cpp
new file mode 100644
index 0000000..47b2177
--- /dev/null
+++ b/camera/CameraProperties.cpp
@@ -0,0 +1,125 @@
+/*
+ * 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 "CameraHal.h"
+#include "DebugUtils.h"
+#include "CameraProperties.h"
+
+#define CAMERA_ROOT "CameraRoot"
+#define CAMERA_INSTANCE "CameraInstance"
+
+namespace android {
+
+// 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;
+
+ if(mInitialized)
+ return NO_ERROR;
+
+ ret = loadProperties();
+
+ mInitialized = 1;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+extern "C" int CameraAdapter_Capabilities(CameraProperties::Properties* properties_array,
+ const unsigned int starting_camera,
+ const unsigned int max_camera);
+
+///Loads all the Camera related properties
+status_t CameraProperties::loadProperties()
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+
+ // adapter updates capabilities and we update camera count
+ mCamerasSupported = CameraAdapter_Capabilities(mCameraProps, mCamerasSupported, MAX_CAMERAS_SUPPORTED);
+
+ if((int)mCamerasSupported < 0) {
+ LOGE("error while getting capabilities");
+ ret = UNKNOWN_ERROR;
+ } else if (mCamerasSupported > MAX_CAMERAS_SUPPORTED) {
+ LOGE("returned too many adapaters");
+ ret = UNKNOWN_ERROR;
+ } else {
+ LOGE("num_cameras = %d", mCamerasSupported);
+
+ for (unsigned int i = 0; i < mCamerasSupported; i++) {
+ mCameraProps[i].set(CAMERA_SENSOR_INDEX, i);
+ mCameraProps[i].dump();
+ }
+ }
+
+ LOGV("mCamerasSupported = %d", mCamerasSupported);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+// Returns the number of Cameras found
+int CameraProperties::camerasSupported()
+{
+ LOG_FUNCTION_NAME;
+ return mCamerasSupported;
+}
+
+};
diff --git a/camera/MemoryManager.cpp b/camera/MemoryManager.cpp
new file mode 100644
index 0000000..f86b263
--- /dev/null
+++ b/camera/MemoryManager.cpp
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+
+
+#define LOG_TAG "CameraHAL"
+
+
+#include "CameraHal.h"
+#include "TICameraParameters.h"
+
+extern "C" {
+
+#include "memmgr.h"
+#include "tiler.h"
+//#include <timm_osal_interfaces.h>
+//#include <timm_osal_trace.h>
+
+
+};
+
+namespace android {
+
+///@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
+#define ZERO_OUT_ARR(a,b) { for(unsigned int i=0;i<b;i++) a[i]=NULL;}
+
+#define ZERO_OUT_STRUCT(a, b) memset(a, 0, sizeof(b));
+
+/*--------------------MemoryManager Class STARTS here-----------------------------*/
+void* MemoryManager::allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs)
+{
+ LOG_FUNCTION_NAME;
+ ///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);
+
+ MemAllocBlock *tMemBlock;
+
+
+ ///Allocate a buffer array
+ uint32_t *bufsArr = new uint32_t[numArrayEntriesC];
+ if(!bufsArr)
+ {
+ CAMHAL_LOGEB("Allocation failed when creating buffers array of %d uint32_t elements", numArrayEntriesC);
+ LOG_FUNCTION_NAME_EXIT;
+ return NULL;
+ }
+
+ ///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
+ ZERO_OUT_ARR(bufsArr, numArrayEntriesC);
+
+ ///If the bytes field is not zero, it means it is a 1-D tiler buffer request (possibly for image capture bit stream buffer)
+ if(bytes!=0)
+ {
+ ///MemAllocBlock is the structure that describes the buffer alloc request to MemMgr
+ tMemBlock = (MemAllocBlock*)malloc(sizeof(MemAllocBlock));
+
+ if(!tMemBlock)
+ {
+ delete [] bufsArr;
+ return NULL;
+ }
+
+ ZERO_OUT_STRUCT(tMemBlock, MemAllocBlock );
+
+ ///1D buffers
+ for (int i = 0; i < numBufs; i++)
+ {
+ tMemBlock->dim.len = bytes;
+ tMemBlock->pixelFormat = PIXEL_FMT_PAGE;
+ tMemBlock->stride = 0;
+ CAMHAL_LOGDB("requested bytes = %d", bytes);
+ CAMHAL_LOGDB("tMemBlock.dim.len = %d", tMemBlock->dim.len);
+ bufsArr[i] = (uint32_t)MemMgr_Alloc(tMemBlock, 1);
+ if(!bufsArr[i])
+ {
+ LOGE("Buffer allocation failed for iteration %d", i);
+ goto error;
+ }
+ else
+ {
+ CAMHAL_LOGDB("Allocated Tiler PAGED mode buffer address[%x]", bufsArr[i]);
+ }
+ }
+
+ }
+ else ///If bytes is not zero, then it is a 2-D tiler buffer request
+ {
+ ///2D buffers
+ ///MemAllocBlock is the structure that describes the buffer alloc request to MemMgr
+ tMemBlock = (MemAllocBlock*)malloc(sizeof(MemAllocBlock)*ALLOCATION_2D);
+
+ if(!tMemBlock)
+ {
+ delete [] bufsArr;
+ return NULL;
+ }
+
+ memset(tMemBlock, 0, sizeof(MemAllocBlock)*ALLOCATION_2D);
+
+ for (int i = 0; i < numBufs; i++)
+ {
+ int numAllocs = 1;
+ pixel_fmt_t pixelFormat[ALLOCATION_2D];
+ int stride[ALLOCATION_2D];
+
+ if(!strcmp(format,(const char *) CameraParameters::PIXEL_FORMAT_YUV422I))
+ {
+ ///YUV422I format
+ pixelFormat[0] = PIXEL_FMT_16BIT;
+ stride[0] = STRIDE_16BIT;
+ numAllocs = 1;
+ }
+ else if(!strcmp(format,(const char *) CameraParameters::PIXEL_FORMAT_YUV420SP))
+ {
+ ///YUV420 NV12 format
+ pixelFormat[0] = PIXEL_FMT_8BIT;
+ pixelFormat[1] = PIXEL_FMT_16BIT;
+ stride[0] = STRIDE_8BIT;
+ stride[1] = STRIDE_16BIT;
+ numAllocs = 2;
+ }
+ else if(!strcmp(format,(const char *) CameraParameters::PIXEL_FORMAT_RGB565))
+ {
+ ///RGB 565 format
+ pixelFormat[0] = PIXEL_FMT_16BIT;
+ stride[0] = STRIDE_16BIT;
+ numAllocs = 1;
+ }
+ else if(!strcmp(format,(const char *) TICameraParameters::PIXEL_FORMAT_RAW))
+ {
+ ///RAW format
+ pixelFormat[0] = PIXEL_FMT_16BIT;
+ stride[0] = STRIDE_16BIT;
+ numAllocs = 1;
+ }
+ else
+ {
+ ///By default assume YUV420 NV12 format
+ ///YUV420 NV12 format
+ pixelFormat[0] = PIXEL_FMT_8BIT;
+ pixelFormat[1] = PIXEL_FMT_16BIT;
+ stride[0] = STRIDE_8BIT;
+ stride[1] = STRIDE_16BIT;
+ numAllocs = 2;
+ }
+
+ for(int index=0;index<numAllocs;index++)
+ {
+ tMemBlock[index].pixelFormat = pixelFormat[index];
+ tMemBlock[index].stride = stride[index];
+ tMemBlock[index].dim.area.width= width;/*width*/
+ tMemBlock[index].dim.area.height= height;/*height*/
+ }
+
+ bufsArr[i] = (uint32_t)MemMgr_Alloc(tMemBlock, numAllocs);
+ if(!bufsArr[i])
+ {
+ CAMHAL_LOGEB("Buffer allocation failed for iteration %d", i);
+ goto error;
+ }
+ else
+ {
+ CAMHAL_LOGDB("Allocated Tiler PAGED mode buffer address[%x]", bufsArr[i]);
+ }
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+
+ ///Free the request structure before returning from the function
+ free(tMemBlock);
+
+ return (void*)bufsArr;
+
+ error:
+ LOGE("Freeing buffers already allocated after error occurred");
+ freeBuffer(bufsArr);
+ free(tMemBlock);
+
+ if ( NULL != mErrorNotifier.get() )
+ {
+ mErrorNotifier->errorNotify(-ENOMEM);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ 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::freeBuffer(void* buf)
+{
+ status_t ret = NO_ERROR;
+ LOG_FUNCTION_NAME;
+
+ uint32_t *bufEntry = (uint32_t*)buf;
+
+ if(!bufEntry)
+ {
+ CAMHAL_LOGEA("NULL pointer passed to freebuffer");
+ LOG_FUNCTION_NAME_EXIT;
+ return BAD_VALUE;
+ }
+
+ while(*bufEntry)
+ {
+ ret |= MemMgr_Free((void*)*bufEntry++);
+ }
+
+ ///@todo Check if this way of deleting array is correct, else use malloc/free
+ uint32_t * bufArr = (uint32_t*)buf;
+ delete [] bufArr;
+
+ 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;
+}
+
+};
+
+
+/*--------------------MemoryManager Class ENDS here-----------------------------*/
diff --git a/camera/OMXCameraAdapter/OMX3A.cpp b/camera/OMXCameraAdapter/OMX3A.cpp
new file mode 100644
index 0000000..1c347a2
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMX3A.cpp
@@ -0,0 +1,1083 @@
+/*
+ * 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 "CameraHAL"
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include "ErrorUtils.h"
+
+namespace android {
+
+status_t OMXCameraAdapter::setParameters3A(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ int mode = 0;
+ const char *str = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ str = params.get(TICameraParameters::KEY_EXPOSURE_MODE);
+ mode = getLUTvalue_HALtoOMX( str, ExpLUT);
+ if ( ( str != NULL ) && ( mParameters3A.Exposure != mode ) )
+ {
+ mParameters3A.Exposure = mode;
+ CAMHAL_LOGDB("Exposure mode %d", mode);
+ if ( 0 <= mParameters3A.Exposure )
+ {
+ mPending3Asettings |= SetExpMode;
+ }
+ }
+
+ str = params.get(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;
+ }
+ }
+
+ if ( 0 <= params.getInt(TICameraParameters::KEY_CONTRAST) )
+ {
+ if ( mFirstTimeInit ||
+ ( (mParameters3A.Contrast + CONTRAST_OFFSET) !=
+ params.getInt(TICameraParameters::KEY_CONTRAST)) )
+ {
+ mParameters3A.Contrast = params.getInt(TICameraParameters::KEY_CONTRAST) - CONTRAST_OFFSET;
+ CAMHAL_LOGDB("Contrast %d", mParameters3A.Contrast);
+ mPending3Asettings |= SetContrast;
+ }
+ }
+
+ if ( 0 <= params.getInt(TICameraParameters::KEY_SHARPNESS) )
+ {
+ if ( mFirstTimeInit ||
+ ((mParameters3A.Sharpness + SHARPNESS_OFFSET) !=
+ params.getInt(TICameraParameters::KEY_SHARPNESS)))
+ {
+ mParameters3A.Sharpness = params.getInt(TICameraParameters::KEY_SHARPNESS) - SHARPNESS_OFFSET;
+ CAMHAL_LOGDB("Sharpness %d", mParameters3A.Sharpness);
+ mPending3Asettings |= SetSharpness;
+ }
+ }
+
+ if ( 0 <= params.getInt(TICameraParameters::KEY_SATURATION) )
+ {
+ if ( mFirstTimeInit ||
+ ((mParameters3A.Saturation + SATURATION_OFFSET) !=
+ params.getInt(TICameraParameters::KEY_SATURATION)) )
+ {
+ mParameters3A.Saturation = params.getInt(TICameraParameters::KEY_SATURATION) - SATURATION_OFFSET;
+ CAMHAL_LOGDB("Saturation %d", mParameters3A.Saturation);
+ mPending3Asettings |= SetSaturation;
+ }
+ }
+
+ if ( 0 <= params.getInt(TICameraParameters::KEY_BRIGHTNESS) )
+ {
+ if ( mFirstTimeInit ||
+ (( mParameters3A.Brightness !=
+ ( unsigned int ) params.getInt(TICameraParameters::KEY_BRIGHTNESS))) )
+ {
+ mParameters3A.Brightness = (unsigned)params.getInt(TICameraParameters::KEY_BRIGHTNESS);
+ CAMHAL_LOGDB("Brightness %d", mParameters3A.Brightness);
+ mPending3Asettings |= SetBrightness;
+ }
+ }
+
+ str = params.get(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;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ str = params.get(CameraParameters::KEY_FOCUS_MODE);
+ mode = getLUTvalue_HALtoOMX(str, FocusLUT);
+ if ( mFirstTimeInit || ( ( str != NULL ) && ( mParameters3A.Focus != mode ) ) )
+ {
+ //Apply focus mode immediatly only if CAF or Inifinity are selected
+ if ( ( mode == OMX_IMAGE_FocusControlAuto ) ||
+ ( mode == OMX_IMAGE_FocusControlAutoInfinity ) )
+ {
+ mPending3Asettings |= SetFocus;
+ mParameters3A.Focus = mode;
+ }
+ else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto )
+ {
+ //If we switch from CAF to something else, then disable CAF
+ mPending3Asettings |= SetFocus;
+ mParameters3A.Focus = OMX_IMAGE_FocusControlOff;
+ }
+
+ mParameters3A.Focus = mode;
+ CAMHAL_LOGDB("Focus %x", mParameters3A.Focus);
+ }
+
+ str = params.get(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ if ( mFirstTimeInit ||
+ (( str != NULL ) &&
+ (mParameters3A.EVCompensation !=
+ params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION))))
+ {
+ CAMHAL_LOGDB("Setting EV Compensation to %d",
+ params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION));
+
+ mParameters3A.EVCompensation = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ mPending3Asettings |= SetEVCompensation;
+ }
+
+ str = params.get(CameraParameters::KEY_SCENE_MODE);
+ mode = getLUTvalue_HALtoOMX( str, SceneLUT);
+ if ( mFirstTimeInit || (( str != NULL ) && ( mParameters3A.SceneMode != mode )) )
+ {
+ if ( 0 <= mode )
+ {
+ mParameters3A.SceneMode = mode;
+ mPending3Asettings |= SetSceneMode;
+ }
+ else
+ {
+ mParameters3A.SceneMode = OMX_Manual;
+ }
+
+ CAMHAL_LOGDB("SceneMode %d", mParameters3A.SceneMode);
+ }
+
+ str = params.get(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_Manual;
+ }
+ }
+
+ CAMHAL_LOGVB("Flash Setting %s", str);
+ CAMHAL_LOGVB("FlashMode %d", mParameters3A.FlashMode);
+
+ str = params.get(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(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED);
+ if ( (str != NULL) && (!strcmp(str, "true")) )
+ {
+ OMX_BOOL lock = OMX_FALSE;
+ str = params.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK);
+ if ( (strcmp(str, "true")) == 0)
+ {
+ CAMHAL_LOGVA("Locking Exposure");
+ lock = OMX_TRUE;
+ }
+ else
+ {
+ CAMHAL_LOGVA("UnLocking Exposure");
+ }
+ if (mParameters3A.ExposureLock != lock)
+ {
+ mParameters3A.ExposureLock = lock;
+ CAMHAL_LOGDB("ExposureLock %d", lock);
+ mPending3Asettings |= SetExpLock;
+ }
+ }
+
+ str = params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED);
+ if ( (str != NULL) && (!strcmp(str, "true")) )
+ {
+ OMX_BOOL lock = OMX_FALSE;
+ str = params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK);
+ if ( (strcmp(str, "true")) == 0)
+ {
+ CAMHAL_LOGVA("Locking WhiteBalance");
+ lock = OMX_TRUE;
+ }
+ else
+ {
+ CAMHAL_LOGVA("UnLocking WhiteBalance");
+ }
+ if (mParameters3A.WhiteBalanceLock != lock)
+ {
+ mParameters3A.WhiteBalanceLock = lock;
+ CAMHAL_LOGDB("WhiteBalanceLock %d", lock);
+ mPending3Asettings |= SetWBLock;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+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;
+}
+
+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;
+ }
+
+ if ( EXPOSURE_FACE_PRIORITY == Gen3A.Exposure )
+ {
+ //Disable Region priority and enable Face priority
+ setAlgoPriority(REGION_PRIORITY, EXPOSURE_ALGO, false);
+ setAlgoPriority(FACE_PRIORITY, EXPOSURE_ALGO, true);
+
+ //Then set the mode to auto
+ Gen3A.WhiteBallance = OMX_ExposureControlAuto;
+ }
+ else
+ {
+ //Disable Face and Region priority
+ setAlgoPriority(FACE_PRIORITY, EXPOSURE_ALGO, false);
+ setAlgoPriority(REGION_PRIORITY, EXPOSURE_ALGO, false);
+ }
+
+ 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 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;
+
+ 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;
+ 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");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return 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;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return NO_INIT;
+ }
+
+ //First Disable Face and Region priority
+ ret |= setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
+ ret |= setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, false);
+
+ if ( NO_ERROR == ret )
+ {
+ 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 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");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return 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 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;
+
+ if ( WB_FACE_PRIORITY == Gen3A.WhiteBallance )
+ {
+ //Disable Region priority and enable Face priority
+ setAlgoPriority(REGION_PRIORITY, WHITE_BALANCE_ALGO, false);
+ setAlgoPriority(FACE_PRIORITY, WHITE_BALANCE_ALGO, true);
+
+ //Then set the mode to auto
+ Gen3A.WhiteBallance = OMX_WhiteBalControlAuto;
+ }
+ else
+ {
+ //Disable Face and Region priority
+ 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::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 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 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 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 ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::setISO(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( 0 == Gen3A.ISO )
+ {
+ expValues.bAutoSensitivity = OMX_TRUE;
+ }
+ else
+ {
+ expValues.bAutoSensitivity = OMX_FALSE;
+ expValues.nSensitivity = Gen3A.ISO;
+ }
+
+ eError = OMX_SetConfig( mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonExposureValue,
+ &expValues);
+ 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 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 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 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 ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::release3ALock()
+{
+ 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 = OMX_FALSE;
+ mParameters3A.WhiteBalanceLock = OMX_FALSE;
+
+ eError = OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigImageExposureLock,
+ &lock);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error GetConfig Exposure Lock error = 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Exposure Lock GetConfig successfull");
+ }
+
+ /*if locked then unlock */
+ if ( lock.bLock )
+ {
+ setExposureLock(mParameters3A);
+ }
+
+ eError = OMX_GetConfig( mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_IndexConfigImageWhiteBalanceLock,
+ &lock);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error GetConfig WhiteBalance Lock error = 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("WhiteBalance Lock GetConfig successfull");
+ }
+
+ /*if locked then unlock */
+ if ( lock.bLock )
+ {
+ setWhiteBalanceLock(mParameters3A);
+ }
+
+ return ErrorUtils::omxToAndroidError(eError);
+
+}
+
+status_t OMXCameraAdapter::apply3Asettings( Gen3A_settings& Gen3A )
+{
+ status_t ret = NO_ERROR;
+ unsigned int currSett; // 32 bit
+ int portIndex;
+
+ /*
+ * 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;
+ return setScene(Gen3A);
+ }
+ else if ( OMX_Manual != Gen3A.SceneMode )
+ {
+ 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 SetFlash:
+ {
+ ret |= setFlashMode(Gen3A);
+ break;
+ }
+
+ case SetExpLock:
+ {
+ ret |= setExposureLock(Gen3A);
+ break;
+ }
+
+ case SetWBLock:
+ {
+ ret |= setWhiteBalanceLock(Gen3A);
+ break;
+ }
+
+ default:
+ CAMHAL_LOGEB("this setting (0x%x) is still not supported in CameraAdapter ",
+ currSett);
+ break;
+ }
+ mPending3Asettings &= ~currSett;
+ }
+ }
+ return ret;
+}
+
+};
diff --git a/camera/OMXCameraAdapter/OMXAlgo.cpp b/camera/OMXCameraAdapter/OMXAlgo.cpp
new file mode 100644
index 0000000..ef9414e
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXAlgo.cpp
@@ -0,0 +1,1181 @@
+/*
+ * 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.
+*
+*/
+
+#undef LOG_TAG
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+namespace android {
+
+status_t OMXCameraAdapter::setParametersAlgo(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *valstr = NULL;
+ const char *oldstr = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ CaptureMode capMode;
+ CAMHAL_LOGEB("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;
+ }
+ else if (strcmp(valstr, (const char *) TICameraParameters::HIGH_QUALITY_MODE) == 0)
+ {
+ capMode = OMXCameraAdapter::HIGH_QUALITY;
+ }
+ else if (strcmp(valstr, (const char *) TICameraParameters::HIGH_QUALITY_ZSL_MODE) == 0)
+ {
+ capMode = OMXCameraAdapter::HIGH_QUALITY_ZSL;
+ }
+ else if (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE) == 0)
+ {
+ capMode = OMXCameraAdapter::VIDEO_MODE;
+ }
+ else
+ {
+ capMode = OMXCameraAdapter::HIGH_QUALITY;
+ }
+ }
+ else
+ {
+ capMode = OMXCameraAdapter::HIGH_QUALITY_ZSL;
+
+ }
+
+ if ( mCapMode != capMode )
+ {
+ mCapMode = capMode;
+ mOMXStateSwitch = true;
+ }
+
+ 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))
+ {
+ 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) )
+ {
+ // Configure GBCE only if the setting has changed since last time
+ oldstr = mParams.get(TICameraParameters::KEY_GBCE);
+ bool cmpRes = true;
+ if ( NULL != oldstr )
+ {
+ cmpRes = strcmp(valstr, oldstr) != 0;
+ }
+ else
+ {
+ cmpRes = true;
+ }
+
+
+ if( cmpRes )
+ {
+ if (strcmp(valstr, ( const char * ) TICameraParameters::GBCE_ENABLE ) == 0)
+ {
+ setGBCE(OMXCameraAdapter::BRIGHTNESS_ON);
+ }
+ else if (strcmp(valstr, ( const char * ) TICameraParameters::GBCE_DISABLE ) == 0)
+ {
+ setGBCE(OMXCameraAdapter::BRIGHTNESS_OFF);
+ }
+ else
+ {
+ setGBCE(OMXCameraAdapter::BRIGHTNESS_OFF);
+ }
+ }
+ }
+ else
+ {
+ //Disable GBCE by default
+ setGBCE(OMXCameraAdapter::BRIGHTNESS_OFF);
+ }
+
+ if ( ( valstr = params.get(TICameraParameters::KEY_GLBCE) ) != NULL )
+ {
+ // Configure GLBCE only if the setting has changed since last time
+
+ oldstr = mParams.get(TICameraParameters::KEY_GLBCE);
+ bool cmpRes = true;
+ if ( NULL != oldstr )
+ {
+ cmpRes = strcmp(valstr, oldstr) != 0;
+ }
+ else
+ {
+ cmpRes = true;
+ }
+
+
+ if( cmpRes )
+ {
+ if (strcmp(valstr, ( const char * ) TICameraParameters::GLBCE_ENABLE ) == 0)
+ {
+ setGLBCE(OMXCameraAdapter::BRIGHTNESS_ON);
+ }
+ else if (strcmp(valstr, ( const char * ) TICameraParameters::GLBCE_DISABLE ) == 0)
+ {
+ setGLBCE(OMXCameraAdapter::BRIGHTNESS_OFF);
+ }
+ else
+ {
+ setGLBCE(OMXCameraAdapter::BRIGHTNESS_OFF);
+ }
+ }
+ }
+ else
+ {
+ //Disable GLBCE by default
+ setGLBCE(OMXCameraAdapter::BRIGHTNESS_OFF);
+ }
+ }
+ else
+ {
+ ipp = OMXCameraAdapter::IPP_NONE;
+ }
+
+ if ( mIPP != ipp )
+ {
+ mIPP = ipp;
+ mOMXStateSwitch = true;
+ }
+
+ ///Set VNF Configuration
+ bool vnfEnabled = false;
+ if ( params.getInt(TICameraParameters::KEY_VNF) > 0 )
+ {
+ CAMHAL_LOGDA("VNF Enabled");
+ vnfEnabled = true;
+ }
+ else
+ {
+ CAMHAL_LOGDA("VNF Disabled");
+ vnfEnabled = false;
+ }
+
+ if ( mVnfEnabled != vnfEnabled )
+ {
+ mVnfEnabled = vnfEnabled;
+ mOMXStateSwitch = true;
+ }
+
+ ///Set VSTAB Configuration
+ bool vstabEnabled = false;
+ if ( params.getInt(TICameraParameters::KEY_VSTAB) > 0 )
+ {
+ CAMHAL_LOGDA("VSTAB Enabled");
+ vstabEnabled = true;
+ }
+ else
+ {
+ CAMHAL_LOGDA("VSTAB Disabled");
+ vstabEnabled = false;
+ }
+
+ if ( mVstabEnabled != vstabEnabled )
+ {
+ mVstabEnabled = vstabEnabled;
+ mOMXStateSwitch = true;
+ }
+
+ //A work-around for a failing call to OMX flush buffers
+ if ( ( capMode = OMXCameraAdapter::VIDEO_MODE ) &&
+ ( mVstabEnabled ) )
+ {
+ mOMXStateSwitch = true;
+ }
+
+ //Set Auto Convergence Mode
+ valstr = params.get((const char *) TICameraParameters::KEY_AUTOCONVERGENCE);
+ if ( valstr != NULL )
+ {
+ // Set ManualConvergence default value
+ OMX_S32 manualconvergence = -30;
+ if ( strcmp (valstr, (const char *) TICameraParameters::AUTOCONVERGENCE_MODE_DISABLE) == 0 )
+ {
+ setAutoConvergence(OMX_TI_AutoConvergenceModeDisable, manualconvergence);
+ }
+ else if ( strcmp (valstr, (const char *) TICameraParameters::AUTOCONVERGENCE_MODE_FRAME) == 0 )
+ {
+ setAutoConvergence(OMX_TI_AutoConvergenceModeFrame, manualconvergence);
+ }
+ else if ( strcmp (valstr, (const char *) TICameraParameters::AUTOCONVERGENCE_MODE_CENTER) == 0 )
+ {
+ setAutoConvergence(OMX_TI_AutoConvergenceModeCenter, manualconvergence);
+ }
+ else if ( strcmp (valstr, (const char *) TICameraParameters::AUTOCONVERGENCE_MODE_FFT) == 0 )
+ {
+ setAutoConvergence(OMX_TI_AutoConvergenceModeFocusFaceTouch, manualconvergence);
+ }
+ else if ( strcmp (valstr, (const char *) TICameraParameters::AUTOCONVERGENCE_MODE_MANUAL) == 0 )
+ {
+ manualconvergence = (OMX_S32)params.getInt(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES);
+ setAutoConvergence(OMX_TI_AutoConvergenceModeManual, manualconvergence);
+ }
+ CAMHAL_LOGVB("AutoConvergenceMode %s, value = %d", valstr, (int) manualconvergence);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+// Get AutoConvergence
+status_t OMXCameraAdapter::getAutoConvergence(OMX_TI_AUTOCONVERGENCEMODETYPE *pACMode,
+ OMX_S32 *pManualConverence)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_CONVERGENCETYPE ACParams;
+
+ ACParams.nSize = sizeof(OMX_TI_CONFIG_CONVERGENCETYPE);
+ ACParams.nVersion = mLocalVersionParam;
+ ACParams.nPortIndex = OMX_ALL;
+
+ LOG_FUNCTION_NAME;
+
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoConvergence,
+ &ACParams);
+ if ( eError != OMX_ErrorNone )
+ {
+ CAMHAL_LOGEB("Error while getting AutoConvergence 0x%x", eError);
+ ret = -EINVAL;
+ }
+ else
+ {
+ *pManualConverence = ACParams.nManualConverence;
+ *pACMode = ACParams.eACMode;
+ CAMHAL_LOGDA("AutoConvergence got successfully");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+// Set AutoConvergence
+status_t OMXCameraAdapter::setAutoConvergence(OMX_TI_AUTOCONVERGENCEMODETYPE pACMode,
+ OMX_S32 pManualConverence)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_CONVERGENCETYPE ACParams;
+
+ LOG_FUNCTION_NAME;
+
+ ACParams.nSize = sizeof(OMX_TI_CONFIG_CONVERGENCETYPE);
+ ACParams.nVersion = mLocalVersionParam;
+ ACParams.nPortIndex = OMX_ALL;
+ ACParams.nManualConverence = pManualConverence;
+ ACParams.eACMode = pACMode;
+ 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 = -EINVAL;
+ }
+ 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;
+
+ LOG_FUNCTION_NAME;
+
+ OMX_INIT_STRUCT_PTR (&bCAC, OMX_CONFIG_BOOLEANTYPE);
+ bCAC.bEnabled = OMX_FALSE;
+
+ if ( NO_ERROR == ret )
+ {
+
+ OMX_INIT_STRUCT_PTR (&camMode, OMX_CONFIG_CAMOPERATINGMODETYPE);
+ if ( mSensorIndex == OMX_TI_StereoSensor )
+ {
+ 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::HIGH_QUALITY == mode )
+ {
+ CAMHAL_LOGDA("Camera mode: HIGH QUALITY");
+ camMode.eCamOperatingMode = OMX_CaptureImageProfileBase;
+ bCAC.bEnabled = OMX_TRUE;
+ }
+ else if( OMXCameraAdapter::HIGH_QUALITY_ZSL== mode )
+ {
+ CAMHAL_LOGDA("Camera mode: HIGH QUALITY_ZSL");
+ camMode.eCamOperatingMode = OMX_TI_CaptureImageProfileZeroShutterLag;
+ bCAC.bEnabled = OMX_TRUE;
+ }
+ else if( OMXCameraAdapter::VIDEO_MODE == mode )
+ {
+ CAMHAL_LOGDA("Camera mode: VIDEO MODE");
+ camMode.eCamOperatingMode = OMX_CaptureVideo;
+ }
+ else
+ {
+ CAMHAL_LOGEA("Camera mode: INVALID mode passed!");
+ return BAD_VALUE;
+ }
+
+ if(ret != -1)
+ {
+ 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 = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Camera mode configured successfully");
+ }
+ }
+
+ if(ret != -1)
+ {
+ //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 = -1;
+ }
+ 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)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CONFIG_3A_REGION_PRIORITY regionPriority;
+ OMX_TI_CONFIG_3A_FACE_PRIORITY facePriority;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -1;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ if ( FACE_PRIORITY == priority )
+ {
+ OMX_INIT_STRUCT_PTR (&facePriority, OMX_TI_CONFIG_3A_FACE_PRIORITY);
+ facePriority.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ if ( algo & WHITE_BALANCE_ALGO )
+ {
+ if ( enable )
+ {
+ facePriority.bAwbFaceEnable = OMX_TRUE;
+ }
+ else
+ {
+ facePriority.bAwbFaceEnable = OMX_FALSE;
+ }
+ }
+
+ if ( algo & EXPOSURE_ALGO )
+ {
+ if ( enable )
+ {
+ facePriority.bAeFaceEnable = OMX_TRUE;
+ }
+ else
+ {
+ facePriority.bAeFaceEnable = OMX_FALSE;
+ }
+ }
+
+ if ( algo & FOCUS_ALGO )
+ {
+ if ( enable )
+ {
+ facePriority.bAfFaceEnable= OMX_TRUE;
+ }
+ else
+ {
+ facePriority.bAfFaceEnable = OMX_FALSE;
+ }
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFacePriority3a,
+ &facePriority);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring face priority 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Face priority for algorithms set successfully");
+ }
+
+ }
+ else if ( REGION_PRIORITY == priority )
+ {
+
+ OMX_INIT_STRUCT_PTR (&regionPriority, OMX_TI_CONFIG_3A_REGION_PRIORITY);
+ regionPriority.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
+
+ if ( algo & WHITE_BALANCE_ALGO )
+ {
+ if ( enable )
+ {
+ regionPriority.bAwbRegionEnable= OMX_TRUE;
+ }
+ else
+ {
+ regionPriority.bAwbRegionEnable = OMX_FALSE;
+ }
+ }
+
+ if ( algo & EXPOSURE_ALGO )
+ {
+ if ( enable )
+ {
+ regionPriority.bAeRegionEnable = OMX_TRUE;
+ }
+ else
+ {
+ regionPriority.bAeRegionEnable = OMX_FALSE;
+ }
+ }
+
+ if ( algo & FOCUS_ALGO )
+ {
+ if ( enable )
+ {
+ regionPriority.bAfRegionEnable = OMX_TRUE;
+ }
+ else
+ {
+ regionPriority.bAfRegionEnable = OMX_FALSE;
+ }
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_TI_IndexConfigRegionPriority3a,
+ &regionPriority);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring region priority 0x%x", eError);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Region priority for algorithms set successfully");
+ }
+
+ }
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+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 > 1008,resolution cannot be set without configuring orientation.
+ * So we first set a temp resolution. We have used VGA
+ */
+ tmpHeight = mPreviewData->mHeight;
+ tmpWidth = mPreviewData->mWidth;
+ mPreviewData->mWidth = 640;
+ mPreviewData->mHeight = 480;
+ ret = setFormat(OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW, *mPreviewData);
+ if ( ret != NO_ERROR )
+ {
+ CAMHAL_LOGEB("setFormat() failed %d", ret);
+ }
+
+ /* Now set Required Orientation*/
+ if ( NO_ERROR == ret )
+ {
+ OMX_INIT_STRUCT(sensorOrientation, OMX_CONFIG_ROTATIONTYPE);
+ sensorOrientation.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonRotate,
+ &sensorOrientation);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while Reading Sensor Orientation : 0x%x", eError);
+ }
+ CAMHAL_LOGVB(" Currently Sensor Orientation is set to : %d",
+ ( unsigned int ) sensorOrientation.nRotation);
+ 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_LOGVA(" Read the Parameters that are set");
+ eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
+ OMX_IndexConfigCommonRotate,
+ &sensorOrientation);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while Reading Sensor Orientation : 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 */
+
+ mPreviewData->mWidth = tmpWidth;
+ mPreviewData->mHeight = tmpHeight;
+ if ( NO_ERROR == ret )
+ {
+ ret = setFormat (mCameraAdapterParameters.mPrevPortIndex,
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex]);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("setFormat() failed %d", ret);
+ }
+ }
+
+ 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;
+
+ 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 (&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;
+ }
+
+};
diff --git a/camera/OMXCameraAdapter/OMXCameraAdapter.cpp b/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
new file mode 100644
index 0000000..899e3dc
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
@@ -0,0 +1,3160 @@
+/*
+ * 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"
+#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;
+
+#define HERE(Msg) {CAMHAL_LOGEB("--===line %d, %s===--\n", __LINE__, Msg);}
+
+namespace android {
+
+#undef LOG_TAG
+///Maintain a separate tag for OMXCameraAdapter logs to isolate issues OMX specific
+#define LOG_TAG "CameraHAL"
+
+//frames skipped before recalculating the framerate
+#define FPS_PERIOD 30
+
+static OMXCameraAdapter *gCameraAdapter = NULL;
+Mutex gAdapterLock;
+
+/*--------------------Camera Adapter Class STARTS here-----------------------------*/
+
+status_t OMXCameraAdapter::initialize(CameraProperties::Properties* caps, int sensor_index)
+{
+ LOG_FUNCTION_NAME;
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.camera.showfps", value, "0");
+ mDebugFps = atoi(value);
+
+ 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;
+
+ if ( 0 != mInitSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mInitSem semaphore count %d", mInitSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ if (mComponentState != OMX_StateLoaded && mComponentState != OMX_StateInvalid) {
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ if ( mComponentState != OMX_StateExecuting ){
+ ///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_PREVIEW;
+
+ if(!mCameraAdapterParameters.mHandleComp)
+ {
+ ///Initialize the OMX Core
+ eError = OMX_Init();
+
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_Init -0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ ///Setup key parameters to send to Ducati during init
+ OMX_CALLBACKTYPE oCallbacks;
+
+ /* Initialize the callback handles */
+ oCallbacks.EventHandler = android::OMXCameraAdapterEventHandler;
+ oCallbacks.EmptyBufferDone = android::OMXCameraAdapterEmptyBufferDone;
+ oCallbacks.FillBufferDone = android::OMXCameraAdapterFillBufferDone;
+
+ ///Get the handle to the OMX Component
+ mCameraAdapterParameters.mHandleComp = NULL;
+ eError = OMX_GetHandle(&(mCameraAdapterParameters.mHandleComp), // previously used: OMX_GetHandle
+ (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA" ///@todo Use constant instead of hardcoded name
+ , this
+ , &oCallbacks);
+
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_GetHandle -0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+
+ 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 |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ CAMHAL_LOGEA("Timeout for enabling preview port expired!");
+ goto EXIT;
+ }
+
+ }
+ else
+ {
+ OMXCameraPortParameters * mPreviewData =
+ &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ //Apply default configs before trying to swtich to a new sensor
+ if ( NO_ERROR != setFormat(OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW, *mPreviewData) )
+ {
+ CAMHAL_LOGEB("Error 0x%x while applying defaults", ret);
+ goto EXIT;
+ }
+ }
+ }
+ ///Select the sensor
+ OMX_CONFIG_SENSORSELECTTYPE sensorSelect;
+ OMX_INIT_STRUCT_PTR (&sensorSelect, OMX_CONFIG_SENSORSELECTTYPE);
+ sensorSelect.eSensor = (OMX_SENSORSELECT)sensor_index;
+ 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", sensor_index, eError);
+ return BAD_VALUE;
+ }
+ else
+ {
+ CAMHAL_LOGDB("Sensor %d selected successfully", sensor_index);
+ }
+
+ printComponentVersion(mCameraAdapterParameters.mHandleComp);
+
+ mSensorIndex = sensor_index;
+ mBracketingEnabled = false;
+ mBracketingBuffersQueuedCount = 0;
+ mBracketingRange = 1;
+ mLastBracetingBufferIdx = 0;
+ mOMXStateSwitch = false;
+
+ if ( mComponentState != OMX_StateExecuting ){
+ mCaptureSignalled = false;
+ mCaptureConfigured = false;
+ mRecording = false;
+ mWaitingForSnapshot = false;
+ mSnapshotCount = 0;
+ mComponentState = OMX_StateLoaded;
+
+ mCapMode = HIGH_QUALITY;
+ mBurstFrames = 1;
+ mCapturedFrames = 0;
+ mPictureQuality = 100;
+ mCurrentZoomIdx = 0;
+ mTargetZoomIdx = 0;
+ mReturnZoomStatus = false;
+ mZoomInc = 1;
+ mZoomParameterIdx = 0;
+ mExposureBracketingValidEntries = 0;
+ mSensorOverclock = false;
+
+ mDeviceOrientation = 0;
+ mCapabilities = caps;
+
+ 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;
+
+ // 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", PRIORITY_URGENT_DISPLAY);
+ if ( ret != NO_ERROR )
+ {
+ if( ret == INVALID_OPERATION){
+ CAMHAL_LOGDA("command handler thread already runnning!!");
+ }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", PRIORITY_URGENT_DISPLAY);
+ if ( ret != NO_ERROR )
+ {
+ if( ret == INVALID_OPERATION){
+ CAMHAL_LOGDA("omx callback handler thread already runnning!!");
+ }else
+ {
+ CAMHAL_LOGEA("Couldn't run omx callback handler thread");
+ return ret;
+ }
+ }
+
+ //Remove any unhandled events
+ if ( !mEventSignalQ.isEmpty() )
+ {
+ for (unsigned int i = 0 ; i < mEventSignalQ.size() ; i++ )
+ {
+ TIUTILS::Message *msg = mEventSignalQ.itemAt(i);
+ //remove from queue and free msg
+ mEventSignalQ.removeAt(i);
+ if ( NULL != msg )
+ {
+ free(msg);
+ }
+ }
+ }
+
+ //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;
+
+ memset(mExposureBracketingValues, 0, EXP_BRACKET_RANGE*sizeof(int));
+ mMeasurementEnabled = false;
+ mFaceDetectionRunning = false;
+
+ memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex], 0, sizeof(OMXCameraPortParameters));
+ memset(&mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex], 0, sizeof(OMXCameraPortParameters));
+ }
+ LOG_FUNCTION_NAME_EXIT;
+ return ErrorUtils::omxToAndroidError(eError);
+
+ EXIT:
+
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+
+ if(mCameraAdapterParameters.mHandleComp)
+ {
+ ///Free the OMX component handle in case of error
+ OMX_FreeHandle(mCameraAdapterParameters.mHandleComp);
+ }
+
+ ///De-init the OMX
+ OMX_Deinit();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ErrorUtils::omxToAndroidError(eError);
+}
+
+OMXCameraAdapter::OMXCameraPortParameters *OMXCameraAdapter::getPortParams(CameraFrame::FrameType frameType)
+{
+ OMXCameraAdapter::OMXCameraPortParameters *ret = NULL;
+
+ switch ( frameType )
+ {
+ case CameraFrame::IMAGE_FRAME:
+ case CameraFrame::RAW_FRAME:
+ ret = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+ 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(void* frameBuf, CameraFrame::FrameType frameType)
+{
+ status_t ret = NO_ERROR;
+ OMXCameraPortParameters *port = NULL;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ BaseCameraAdapter::AdapterState state;
+ BaseCameraAdapter::getState(state);
+
+ if ( ( PREVIEW_ACTIVE & state ) != PREVIEW_ACTIVE )
+ {
+ return NO_INIT;
+ }
+
+ if ( NULL == frameBuf )
+ {
+ return -EINVAL;
+ }
+
+ if ( (NO_ERROR == ret) &&
+ ((CameraFrame::IMAGE_FRAME == frameType) || (CameraFrame::RAW_FRAME == frameType)) &&
+ (1 > mCapturedFrames) &&
+ (!mBracketingEnabled)) {
+ // Signal end of image capture
+ if ( NULL != mEndImageCaptureCallback) {
+ mEndImageCaptureCallback(mEndCaptureData);
+ }
+ return NO_ERROR;
+ }
+
+ 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 ( port->mBufferHeader[i]->pBuffer == frameBuf )
+ {
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp, port->mBufferHeader[i]);
+ if ( eError != OMX_ErrorNone )
+ {
+ CAMHAL_LOGDB("OMX_FillThisBuffer 0x%x", eError);
+ ret = ErrorUtils::omxToAndroidError(eError);
+ }
+ break;
+ }
+ }
+
+ }
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setParameters(const CameraParameters &params)
+{
+ LOG_FUNCTION_NAME;
+
+ const char * str = NULL;
+ int mode = 0;
+ status_t ret = NO_ERROR;
+ bool updateImagePortParams = false;
+ int minFramerate, maxFramerate, frameRate;
+ const char *valstr = NULL;
+ const char *oldstr = 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, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
+ {
+ CAMHAL_LOGDA("CbYCrY format selected");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ }
+ else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ||
+ strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV420P) == 0)
+ {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+ else if(strcmp(valstr, (const char *) 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();
+ minFramerate = params.getInt(TICameraParameters::KEY_MINFRAMERATE);
+ maxFramerate = params.getInt(TICameraParameters::KEY_MAXFRAMERATE);
+ if ( ( 0 < minFramerate ) &&
+ ( 0 < maxFramerate ) )
+ {
+ if ( minFramerate > maxFramerate )
+ {
+ CAMHAL_LOGEA(" Min FPS set higher than MAX. So setting MIN and MAX to the higher value");
+ maxFramerate = minFramerate;
+ }
+
+ if ( 0 >= frameRate )
+ {
+ frameRate = maxFramerate;
+ }
+
+ if( ( cap->mMinFrameRate != minFramerate ) ||
+ ( cap->mMaxFrameRate != maxFramerate ) )
+ {
+ cap->mMinFrameRate = minFramerate;
+ cap->mMaxFrameRate = maxFramerate;
+ setVFramerate(cap->mMinFrameRate, cap->mMaxFrameRate);
+ }
+ }
+
+ if ( 0 < frameRate )
+ {
+ 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);
+
+ //TODO: Add an additional parameter for video resolution
+ //use preview resolution for now
+ cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+ cap->mColorFormat = pixFormat;
+ cap->mWidth = w;
+ cap->mHeight = h;
+ cap->mFrameRate = frameRate;
+
+ CAMHAL_LOGVB("Video: cap.mColorFormat = %d", (int)cap->mColorFormat);
+ CAMHAL_LOGVB("Video: cap.mWidth = %d", (int)cap->mWidth);
+ CAMHAL_LOGVB("Video: cap.mHeight = %d", (int)cap->mHeight);
+ CAMHAL_LOGVB("Video: 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;
+ }
+
+ if ( (valstr = params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE)) != NULL )
+ {
+ if (strcmp(valstr, (const char *) TICameraParameters::MEASUREMENT_ENABLE) == 0)
+ {
+ mMeasurementEnabled = true;
+ }
+ else if (strcmp(valstr, (const char *) TICameraParameters::MEASUREMENT_DISABLE) == 0)
+ {
+ mMeasurementEnabled = false;
+ }
+ else
+ {
+ mMeasurementEnabled = false;
+ }
+ }
+ else
+ {
+ //Disable measurement data by default
+ mMeasurementEnabled = false;
+ }
+
+ 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);
+
+ mParams = params;
+ mFirstTimeInit = false;
+
+ 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) {
+ 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;
+}
+
+void OMXCameraAdapter::getParameters(CameraParameters& params)
+{
+ status_t ret = NO_ERROR;
+ OMX_CONFIG_EXPOSUREVALUETYPE exp;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ BaseCameraAdapter::AdapterState state;
+ BaseCameraAdapter::getState(state);
+
+ LOG_FUNCTION_NAME;
+
+#ifdef PARAM_FEEDBACK
+
+ OMX_CONFIG_WHITEBALCONTROLTYPE wb;
+ OMX_CONFIG_FLICKERCANCELTYPE flicker;
+ OMX_CONFIG_SCENEMODETYPE scene;
+ OMX_IMAGE_PARAM_FLASHCONTROLTYPE flash;
+ OMX_CONFIG_BRIGHTNESSTYPE brightness;
+ OMX_CONFIG_CONTRASTTYPE contrast;
+ OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE procSharpness;
+ OMX_CONFIG_SATURATIONTYPE saturation;
+ OMX_CONFIG_IMAGEFILTERTYPE effect;
+ OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus;
+
+ exp.nSize = sizeof(OMX_CONFIG_EXPOSURECONTROLTYPE);
+ exp.nVersion = mLocalVersionParam;
+ exp.nPortIndex = OMX_ALL;
+
+ expValues.nSize = sizeof(OMX_CONFIG_EXPOSUREVALUETYPE);
+ expValues.nVersion = mLocalVersionParam;
+ expValues.nPortIndex = OMX_ALL;
+
+ wb.nSize = sizeof(OMX_CONFIG_WHITEBALCONTROLTYPE);
+ wb.nVersion = mLocalVersionParam;
+ wb.nPortIndex = OMX_ALL;
+
+ flicker.nSize = sizeof(OMX_CONFIG_FLICKERCANCELTYPE);
+ flicker.nVersion = mLocalVersionParam;
+ flicker.nPortIndex = OMX_ALL;
+
+ scene.nSize = sizeof(OMX_CONFIG_SCENEMODETYPE);
+ scene.nVersion = mLocalVersionParam;
+ scene.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+
+ flash.nSize = sizeof(OMX_IMAGE_PARAM_FLASHCONTROLTYPE);
+ flash.nVersion = mLocalVersionParam;
+ flash.nPortIndex = OMX_ALL;
+
+
+ brightness.nSize = sizeof(OMX_CONFIG_BRIGHTNESSTYPE);
+ brightness.nVersion = mLocalVersionParam;
+ brightness.nPortIndex = OMX_ALL;
+
+ contrast.nSize = sizeof(OMX_CONFIG_CONTRASTTYPE);
+ contrast.nVersion = mLocalVersionParam;
+ contrast.nPortIndex = OMX_ALL;
+
+ procSharpness.nSize = sizeof( OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE );
+ procSharpness.nVersion = mLocalVersionParam;
+ procSharpness.nPortIndex = OMX_ALL;
+
+ saturation.nSize = sizeof(OMX_CONFIG_SATURATIONTYPE);
+ saturation.nVersion = mLocalVersionParam;
+ saturation.nPortIndex = OMX_ALL;
+
+ effect.nSize = sizeof(OMX_CONFIG_IMAGEFILTERTYPE);
+ effect.nVersion = mLocalVersionParam;
+ effect.nPortIndex = OMX_ALL;
+
+ focus.nSize = sizeof(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
+ focus.nVersion = mLocalVersionParam;
+ focus.nPortIndex = OMX_ALL;
+
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp,OMX_IndexConfigCommonExposure, &exp);
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, OMX_IndexConfigCommonWhiteBalance, &wb);
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigFlickerCancel, &flicker );
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE)OMX_IndexParamSceneMode, &scene);
+ OMX_GetParameter( mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE)OMX_IndexParamFlashControl, &flash);
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, OMX_IndexConfigCommonBrightness, &brightness);
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, OMX_IndexConfigCommonContrast, &contrast);
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigSharpeningLevel, &procSharpness);
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, OMX_IndexConfigCommonSaturation, &saturation);
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, OMX_IndexConfigCommonImageFilter, &effect);
+ OMX_GetConfig( mCameraAdapterParameters.mHandleComp, OMX_IndexConfigFocusControl, &focus);
+
+ char * str = NULL;
+
+ for(int i = 0; i < ExpLUT.size; i++)
+ if( ExpLUT.Table[i].omxDefinition == exp.eExposureControl )
+ str = (char*)ExpLUT.Table[i].userDefinition;
+ params.set( TICameraParameters::KEY_EXPOSURE_MODE , str);
+
+ for(int i = 0; i < WBalLUT.size; i++)
+ if( WBalLUT.Table[i].omxDefinition == wb.eWhiteBalControl )
+ str = (char*)WBalLUT.Table[i].userDefinition;
+ params.set( CameraParameters::KEY_WHITE_BALANCE , str );
+
+ for(int i = 0; i < FlickerLUT.size; i++)
+ if( FlickerLUT.Table[i].omxDefinition == flicker.eFlickerCancel )
+ str = (char*)FlickerLUT.Table[i].userDefinition;
+ params.set( CameraParameters::KEY_ANTIBANDING , str );
+
+ for(int i = 0; i < SceneLUT.size; i++)
+ if( SceneLUT.Table[i].omxDefinition == scene.eSceneMode )
+ str = (char*)SceneLUT.Table[i].userDefinition;
+ params.set( CameraParameters::KEY_SCENE_MODE , str );
+
+ for(int i = 0; i < FlashLUT.size; i++)
+ if( FlashLUT.Table[i].omxDefinition == flash.eFlashControl )
+ str = (char*)FlashLUT.Table[i].userDefinition;
+ params.set( CameraParameters::KEY_FLASH_MODE, str );
+
+ for(int i = 0; i < EffLUT.size; i++)
+ if( EffLUT.Table[i].omxDefinition == effect.eImageFilter )
+ str = (char*)EffLUT.Table[i].userDefinition;
+ params.set( CameraParameters::KEY_EFFECT , str );
+
+ for(int i = 0; i < FocusLUT.size; i++)
+ if( FocusLUT.Table[i].omxDefinition == focus.eFocusControl )
+ str = (char*)FocusLUT.Table[i].userDefinition;
+
+ params.set( CameraParameters::KEY_FOCUS_MODE , str );
+
+ int comp = ((expValues.xEVCompensation * 10) >> Q16_OFFSET);
+
+ params.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, comp );
+ params.set( TICameraParameters::KEY_MAN_EXPOSURE, expValues.nShutterSpeedMsec);
+ params.set( TICameraParameters::KEY_BRIGHTNESS, brightness.nBrightness);
+ params.set( TICameraParameters::KEY_CONTRAST, contrast.nContrast );
+ params.set( TICameraParameters::KEY_SHARPNESS, procSharpness.nLevel);
+ params.set( TICameraParameters::KEY_SATURATION, saturation.nSaturation);
+
+#else
+
+ //Query focus distances only during CAF, Infinity
+ //or when focus is running
+ if ( ( AF_ACTIVE & state ) ||
+ ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) ||
+ ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) ||
+ ( NULL == mParameters.get(CameraParameters::KEY_FOCUS_DISTANCES) ) )
+ {
+ updateFocusDistances(params);
+ }
+ else
+ {
+ params.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ mParameters.get(CameraParameters::KEY_FOCUS_DISTANCES));
+ }
+
+ 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);
+ }
+
+ {
+ Mutex::Autolock lock(mZoomLock);
+ //Immediate zoom should not be avaialable while smooth zoom is running
+ if ( ZOOM_ACTIVE & state )
+ {
+ if ( mZoomParameterIdx != mCurrentZoomIdx )
+ {
+ mZoomParameterIdx += mZoomInc;
+ }
+ params.set( 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( CameraParameters::KEY_ZOOM, mCurrentZoomIdx);
+ }
+ }
+
+#endif
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+status_t OMXCameraAdapter::setFormat(OMX_U32 port, OMXCameraPortParameters &portParams)
+{
+ size_t bufferCount;
+
+ LOG_FUNCTION_NAME;
+
+ 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;
+ if( ( portCheck.format.video.nFrameWidth >= 1920 ) &&
+ ( portCheck.format.video.nFrameHeight >= 1080 ) &&
+ ( portParams.mFrameRate >= FRAME_RATE_FULL_HD ) )
+ {
+ setSensorOverclock(true);
+ }
+ else
+ {
+ setSensorOverclock(false);
+ }
+
+ portCheck.format.video.xFramerate = portParams.mFrameRate<<16;
+ portCheck.nBufferSize = portParams.mStride * portParams.mHeight;
+ portCheck.nBufferCountActual = portParams.mNumBufs;
+ mFocusThreshold = FOCUS_THRESHOLD * portParams.mFrameRate;
+ }
+ 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 && mCodingMode == CodingNone )
+ {
+ portCheck.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY;
+ portCheck.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG;
+ }
+ else if ( OMX_COLOR_FormatUnused == portParams.mColorFormat && mCodingMode == CodingJPS )
+ {
+ portCheck.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY;
+ portCheck.format.image.eCompressionFormat = (OMX_IMAGE_CODINGTYPE) OMX_TI_IMAGE_CodingJPS;
+ }
+ else if ( OMX_COLOR_FormatUnused == portParams.mColorFormat && mCodingMode == CodingMPO )
+ {
+ portCheck.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY;
+ portCheck.format.image.eCompressionFormat = (OMX_IMAGE_CODINGTYPE) OMX_TI_IMAGE_CodingMPO;
+ }
+ else if ( OMX_COLOR_FormatUnused == portParams.mColorFormat && mCodingMode == CodingRAWJPEG )
+ {
+ //TODO: OMX_IMAGE_CodingJPEG should be changed to OMX_IMAGE_CodingRAWJPEG when
+ // RAW format is supported
+ portCheck.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY;
+ portCheck.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG;
+ }
+ else if ( OMX_COLOR_FormatUnused == portParams.mColorFormat && mCodingMode == CodingRAWMPO )
+ {
+ //TODO: OMX_IMAGE_CodingJPEG should be changed to OMX_IMAGE_CodingRAWMPO when
+ // RAW format is supported
+ portCheck.format.image.eColorFormat = OMX_COLOR_FormatCbYCrY;
+ portCheck.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG;
+ }
+ else
+ {
+ portCheck.format.image.eColorFormat = portParams.mColorFormat;
+ portCheck.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
+ }
+
+ //Stride for 1D tiler buffer is zero
+ portCheck.format.image.nStride = 0;
+ portCheck.nBufferSize = portParams.mStride * portParams.mWidth * portParams.mHeight;
+ portCheck.nBufferCountActual = portParams.mNumBufs;
+ }
+ else
+ {
+ CAMHAL_LOGEB("Unsupported port index 0x%x", (unsigned int)port);
+ }
+
+ 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;
+
+ 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
+ {
+ 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);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ErrorUtils::omxToAndroidError(eError);
+
+ EXIT:
+
+ CAMHAL_LOGEB("Exiting function %s because of eError=%x", __FUNCTION__, eError);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ErrorUtils::omxToAndroidError(eError);
+}
+
+status_t OMXCameraAdapter::flushBuffers()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ TIMM_OSAL_ERRORTYPE err;
+ TIMM_OSAL_U32 uRequestedEvents = OMXCameraAdapter::CAMERA_PORT_FLUSH;
+ TIMM_OSAL_U32 pRetrievedEvents;
+
+ if ( 0 != mFlushSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mFlushSem semaphore count %d", mFlushSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ LOG_FUNCTION_NAME;
+
+ OMXCameraPortParameters * mPreviewData = NULL;
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+
+ ///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,
+ OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW,
+ 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,
+ mCameraAdapterParameters.mPrevPortIndex,
+ 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 ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Flush event received");
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandFlush,
+ OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW,
+ NULL);
+ CAMHAL_LOGDA("Flush event timeout expired");
+ goto EXIT;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+
+ EXIT:
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+}
+
+///API to give the buffers to Adapter
+status_t OMXCameraAdapter::useBuffers(CameraMode mode, void* 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].mNumBufs = num;
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex].mMaxQueueable = queueable;
+ ret = UseBuffersCapture(bufArr, num);
+ break;
+
+ case CAMERA_VIDEO:
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex].mNumBufs = num;
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex].mMaxQueueable = queueable;
+ ret = UseBuffersPreview(bufArr, num);
+ break;
+
+ case CAMERA_MEASUREMENT:
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex].mNumBufs = num;
+ mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mMeasurementPortIndex].mMaxQueueable = queueable;
+ ret = UseBuffersPreviewData(bufArr, num);
+ break;
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::UseBuffersPreviewData(void* bufArr, int num)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters * measurementData = NULL;
+ uint32_t *buffers;
+ Mutex::Autolock lock( mPreviewDataBufferLock);
+
+ LOG_FUNCTION_NAME;
+
+ if ( mComponentState != OMX_StateLoaded )
+ {
+ CAMHAL_LOGEA("Calling UseBuffersPreviewData() when not in LOADED state");
+ ret = BAD_VALUE;
+ }
+
+ if ( NULL == bufArr )
+ {
+ CAMHAL_LOGEA("NULL pointer passed for buffArr");
+ ret = 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 ;
+ buffers= (uint32_t*) bufArr;
+ }
+
+ 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);
+ ret = BAD_VALUE;
+ }
+ }
+
+ 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);
+ ret = BAD_VALUE;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = mUsePreviewDataSem.WaitTimeout(OMX_CMD_TIMEOUT);
+
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Port enable event arrived on measurement port");
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mMeasurementPortIndex,
+ NULL);
+ CAMHAL_LOGEA("Timeout expoired during port enable on measurement port");
+ }
+
+ CAMHAL_LOGDA("Port enable event arrived on measurement port");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::switchToLoaded()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ if ( mComponentState == OMX_StateLoaded )
+ {
+ CAMHAL_LOGDA("Already in OMX_Loaded state");
+ goto EXIT;
+ }
+
+ 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 ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("EXECUTING->IDLE state changed");
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateIdle,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on EXECUTING->IDLE state change");
+ 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);
+
+ CAMHAL_LOGDA("Switching IDLE->LOADED state");
+ ret = mSwitchToLoadedSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("IDLE->LOADED state changed");
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateLoaded,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on IDLE->LOADED state change");
+ goto EXIT;
+ }
+
+ mComponentState = OMX_StateLoaded;
+
+ ///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 ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Preview port enabled!");
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ CAMHAL_LOGEA("Preview enable timedout");
+ goto EXIT;
+ }
+
+ EXIT:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::UseBuffersPreview(void* bufArr, int num)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ int tmpHeight, tmpWidth;
+
+ LOG_FUNCTION_NAME;
+
+ ///Flag to determine whether it is 3D camera or not
+ bool isS3d = false;
+ const char *valstr = NULL;
+ if ( (valstr = mParams.get(TICameraParameters::KEY_S3D_SUPPORTED)) != NULL) {
+ isS3d = (strcmp(valstr, "true") == 0);
+ }
+
+ 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 ;
+ uint32_t *buffers = (uint32_t*)bufArr;
+
+ 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;
+ }
+
+ if ( mComponentState == OMX_StateLoaded )
+ {
+
+ ret = setLDC(mIPP);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("setLDC() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+
+ ret = setNSF(mIPP);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("setNSF() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+
+ ret = setCaptureMode(mCapMode);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("setCaptureMode() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+
+ CAMHAL_LOGDB("Camera Mode = %d", mCapMode);
+
+ if( ( mCapMode == OMXCameraAdapter::VIDEO_MODE ) ||
+ ( isS3d && (mCapMode == OMXCameraAdapter::HIGH_QUALITY)) )
+ {
+ ///Enable/Disable Video Noise Filter
+ ret = enableVideoNoiseFilter(mVnfEnabled);
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring VNF %x", ret);
+ return ret;
+ }
+
+ ///Enable/Disable Video Stabilization
+ ret = enableVideoStabilization(mVstabEnabled);
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring VSTAB %x", ret);
+ return ret;
+ }
+ }
+ else
+ {
+ ret = enableVideoNoiseFilter(false);
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring VNF %x", ret);
+ return ret;
+ }
+ ///Enable/Disable Video Stabilization
+ ret = enableVideoStabilization(false);
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring VSTAB %x", ret);
+ return ret;
+ }
+ }
+ }
+
+ ret = setSensorOrientation(mSensorOrientation);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error configuring Sensor Orientation %x", ret);
+ mSensorOrientation = 0;
+ }
+
+ ret = setVFramerate(mPreviewData->mMinFrameRate, mPreviewData->mMaxFrameRate);
+ if ( ret != NO_ERROR )
+ {
+ CAMHAL_LOGEB("VFR configuration failed 0x%x", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+
+ 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++) {
+
+ CAMHAL_LOGDB("OMX_UseBuffer(0x%x)", buffers[index]);
+ eError = OMX_UseBuffer( mCameraAdapterParameters.mHandleComp,
+ &pBufferHdr,
+ mCameraAdapterParameters.mPrevPortIndex,
+ 0,
+ mPreviewData->mBufSize,
+ (OMX_U8*)buffers[index]);
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_UseBuffer-0x%x", eError);
+ }
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+
+ //pBufferHdr->pAppPrivate = (OMX_PTR)pBufferHdr;
+ 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;
+ eError = OMX_UseBuffer( mCameraAdapterParameters.mHandleComp,
+ &pBufHdr,
+ mCameraAdapterParameters.mMeasurementPortIndex,
+ 0,
+ measurementData->mBufSize,
+ (OMX_U8*)(mPreviewDataBuffers[i]));
+
+ if ( eError == OMX_ErrorNone )
+ {
+ 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 ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Preview buffer registration successfull");
+ }
+ else
+ {
+ if ( mComponentState == OMX_StateLoaded )
+ {
+ ret |= SignalEvent(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 | 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:
+
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | 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());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ 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 ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("+Great. Component went into executing state!!");
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandStateSet,
+ OMX_StateExecuting,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on executing state switch!");
+ goto EXIT;
+ }
+
+ mComponentState = OMX_StateExecuting;
+
+ }
+
+ //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);
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp,
+ (OMX_BUFFERHEADERTYPE*)mPreviewData->mBufferHeader[index]);
+ if(eError!=OMX_ErrorNone)
+ {
+ CAMHAL_LOGEB("OMX_FillThisBuffer-0x%x", eError);
+ }
+ 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);
+ 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);
+ }
+
+ }
+
+ if ( mPending3Asettings )
+ apply3Asettings(mParameters3A);
+
+ //Query current focus distance after
+ //starting the preview
+ updateFocusDistances(mParameters);
+
+ //reset frame rate estimates
+ mFPS = 0.0f;
+ mLastFPS = 0.0f;
+ mFrameCount = 0;
+ mLastFrameCount = 0;
+ mIter = 1;
+ mLastFPSTime = systemTime();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+
+ EXIT:
+
+ CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+
+}
+
+status_t OMXCameraAdapter::stopPreview()
+{
+ 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 ( mComponentState != OMX_StateExecuting )
+ {
+ CAMHAL_LOGEA("Calling StopPreview() when not in EXECUTING state");
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ ret = cancelAutoFocus();
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error canceling autofocus %d", ret);
+ // Error, but we probably still want to continue to stop preview
+ }
+
+ ret = release3ALock();
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error Releaseing 3A locks%d", ret);
+ }
+
+ if ( 0 != mStopPreviewSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mStopPreviewSem semaphore count %d", mStopPreviewSem.Count());
+ LOG_FUNCTION_NAME_EXIT;
+ return NO_INIT;
+ }
+
+ 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;
+ }
+
+ ///Register for Preview port Disable event
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ mStopPreviewSem);
+
+ ///Disable Preview Port
+ eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+
+ ///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);
+ }
+
+ {
+ Mutex::Autolock lock(mPreviewDataBufferLock);
+ mPreviewDataBuffersAvailable.clear();
+ }
+
+ }
+
+ CAMHAL_LOGDA("Disabling preview port");
+ ret = mStopPreviewSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Preview port disabled");
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mPrevPortIndex,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on preview port disable");
+ goto EXIT;
+ }
+
+ {
+ Mutex::Autolock lock(mPreviewBufferLock);
+ ///Clear all the available preview buffers
+ mPreviewBuffersAvailable.clear();
+ }
+
+ switchToLoaded();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+
+ EXIT:
+
+ {
+ Mutex::Autolock lock(mPreviewBufferLock);
+ ///Clear all the available preview buffers
+ mPreviewBuffersAvailable.clear();
+ }
+
+ switchToLoaded();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | 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);
+ ret = BAD_VALUE;
+ }
+ else
+ {
+ mSensorOverclock = enable;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+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::autoFocus()
+{
+ status_t ret = NO_ERROR;
+ TIUTILS::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ msg.command = CommandHandler::CAMERA_PERFORM_AUTOFOCUS;
+ msg.arg1 = mErrorNotifier;
+ ret = mCommandHandler->put(&msg);
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::takePicture()
+{
+ status_t ret = NO_ERROR;
+ TIUTILS::Message msg;
+
+ LOG_FUNCTION_NAME;
+
+ msg.command = CommandHandler::CAMERA_START_IMAGE_CAPTURE;
+ msg.arg1 = mErrorNotifier;
+ ret = mCommandHandler->put(&msg);
+
+ 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();
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("switchToLoaded() failed 0x%x", ret);
+ goto exit;
+ }
+
+ mOMXStateSwitch = false;
+ }
+
+ if ( OMX_StateLoaded == mComponentState )
+ {
+
+ ret = setLDC(mIPP);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("setLDC() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ goto exit;
+ }
+
+ ret = setNSF(mIPP);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("setNSF() failed %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ goto exit;
+ }
+
+ ret = setCaptureMode(mCapMode);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("setCaptureMode() failed %d", ret);
+ }
+
+ if(mCapMode == OMXCameraAdapter::VIDEO_MODE)
+ {
+ if ( NO_ERROR == ret )
+ {
+ ///Enable/Disable Video Noise Filter
+ ret = enableVideoNoiseFilter(mVnfEnabled);
+ }
+
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring VNF %x", ret);
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ///Enable/Disable Video Stabilization
+ ret = enableVideoStabilization(mVstabEnabled);
+ }
+
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring VSTAB %x", ret);
+ }
+ }
+ else
+ {
+ if ( NO_ERROR == ret )
+ {
+ ///Enable/Disable Video Noise Filter
+ ret = enableVideoNoiseFilter(false);
+ }
+
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring VNF %x", ret);
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ///Enable/Disable Video Stabilization
+ ret = enableVideoStabilization(false);
+ }
+
+ 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 int DEGREES_TILT_IGNORE = 45;
+ int device_orientation = 0;
+ int mount_orientation = 0;
+ const char *facing_direction = NULL;
+
+ // 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;
+ }
+
+ if (mCapabilities) {
+ if (mCapabilities->get(CameraProperties::ORIENTATION_INDEX)) {
+ mount_orientation = atoi(mCapabilities->get(CameraProperties::ORIENTATION_INDEX));
+ }
+ facing_direction = mCapabilities->get(CameraProperties::FACING_INDEX);
+ }
+
+ // calculate device orientation relative to the sensor orientation
+ // front camera display is mirrored
+ if (facing_direction && !strcmp(facing_direction, TICameraParameters::FACING_FRONT)) {
+ device_orientation = (orientation - mount_orientation + 360) % 360;
+ } else { // back-facing camera
+ device_orientation = (orientation + mount_orientation) % 360;
+ }
+
+ if (device_orientation != mDeviceOrientation) {
+ mDeviceOrientation = device_orientation;
+
+ mFaceDetectionLock.lock();
+ if (mFaceDetectionRunning) {
+ // restart face detection with new rotation
+ setFaceDetection(true, mDeviceOrientation);
+ }
+ mFaceDetectionLock.unlock();
+ }
+ 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;
+ ///Report Error to App
+ mErrorNotifier->errorNotify(CAMERA_ERROR_UNKNOWN);
+ }
+ 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)
+{
+ Mutex::Autolock lock(mEventLock);
+ TIUTILS::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)
+ {
+ Semaphore *sem = (Semaphore*) msg->arg3;
+ CAMHAL_LOGDA("Event matched, signalling sem");
+ mEventSignalQ.removeAt(i);
+ //Signal the semaphore provided
+ sem->Signal();
+ 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 Semaphore &semaphore)
+{
+ status_t ret = NO_ERROR;
+ ssize_t res;
+ Mutex::Autolock lock(mEventLock);
+
+ LOG_FUNCTION_NAME;
+
+ TIUTILS::Message * msg = ( struct TIUTILS::Message * ) malloc(sizeof(struct TIUTILS::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");
+ 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;
+
+ 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;
+ LOGD("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)
+{
+ TIUTILS::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;
+}
+
+/*========================================================*/
+/* @ 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;
+ BaseCameraAdapter::getState(state);
+ sp<CameraFDResult> fdResult = NULL;
+
+ res1 = res2 = NO_ERROR;
+ pPortParam = &(mCameraAdapterParameters.mCameraPortParams[pBuffHeader->nOutputPortIndex]);
+ if (pBuffHeader->nOutputPortIndex == OMX_CAMERA_PORT_VIDEO_OUT_PREVIEW)
+ {
+
+ if ( ( PREVIEW_ACTIVE & state ) != PREVIEW_ACTIVE )
+ {
+ return OMX_ErrorNone;
+ }
+
+ recalculateFPS();
+
+ {
+ Mutex::Autolock lock(mFaceDetectionLock);
+ if ( mFaceDetectionRunning ) {
+ detectFaces(pBuffHeader, fdResult, pPortParam->mWidth, pPortParam->mHeight);
+ if ( NULL != fdResult.get() ) {
+ notifyFaceSubscribers(fdResult);
+ fdResult.clear();
+ }
+ }
+ }
+
+ stat |= advanceZoom();
+
+ ///On the fly update to 3A settings not working
+ if( mPending3Asettings )
+ {
+ apply3Asettings(mParameters3A);
+ }
+
+ ///Prepare the frames to be sent - initialize CameraFrame object and reference count
+ CameraFrame cameraFrameVideo, cameraFramePreview;
+ if ( mRecording )
+ {
+ res1 = initCameraFrame(cameraFrameVideo,
+ pBuffHeader,
+ CameraFrame::VIDEO_FRAME_SYNC,
+ pPortParam);
+ }
+
+ if( mWaitingForSnapshot )
+ {
+ typeOfFrame = CameraFrame::SNAPSHOT_FRAME;
+ }
+ else
+ {
+ typeOfFrame = CameraFrame::PREVIEW_FRAME_SYNC;
+ }
+
+ LOGV("FBD pBuffer = 0x%x", pBuffHeader->pBuffer);
+
+ res2 = initCameraFrame(cameraFramePreview,
+ pBuffHeader,
+ typeOfFrame,
+ pPortParam);
+
+ stat |= res1 | res2;
+
+ if ( mRecording )
+ {
+ res1 = sendFrame(cameraFrameVideo);
+ }
+
+ if( mWaitingForSnapshot )
+ {
+ mSnapshotCount++;
+
+ if ( ( mSnapshotCount == 1 ) &&
+ ( HIGH_SPEED == mCapMode ) )
+ {
+ notifyShutterSubscribers();
+ }
+ }
+
+ res2 = sendFrame(cameraFramePreview);
+
+ stat |= ( ( NO_ERROR == res1 ) || ( NO_ERROR == res2 ) ) ? ( ( int ) NO_ERROR ) : ( -1 );
+
+ }
+ else if( pBuffHeader->nOutputPortIndex == OMX_CAMERA_PORT_VIDEO_OUT_MEASUREMENT )
+ {
+ typeOfFrame = CameraFrame::FRAME_DATA_SYNC;
+ CameraFrame cameraFrame;
+ stat |= initCameraFrame(cameraFrame,
+ pBuffHeader,
+ typeOfFrame,
+ pPortParam);
+ stat |= sendFrame(cameraFrame);
+ }
+ else if( pBuffHeader->nOutputPortIndex == OMX_CAMERA_PORT_IMAGE_OUT_IMAGE )
+ {
+
+ if ( OMX_COLOR_FormatUnused == mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex].mColorFormat )
+ {
+ typeOfFrame = CameraFrame::IMAGE_FRAME;
+ }
+ else
+ {
+ typeOfFrame = CameraFrame::RAW_FRAME;
+ }
+
+ pPortParam->mImageType = typeOfFrame;
+
+ if((mCapturedFrames>0) && !mCaptureSignalled)
+ {
+ mCaptureSignalled = true;
+ mCaptureSem.Signal();
+ }
+
+ if( ( CAPTURE_ACTIVE & state ) != CAPTURE_ACTIVE )
+ {
+ goto EXIT;
+ }
+
+ {
+ Mutex::Autolock lock(mBracketingLock);
+ if ( mBracketingEnabled )
+ {
+ doBracketing(pBuffHeader, typeOfFrame);
+ return eError;
+ }
+ }
+
+ if ( 1 > mCapturedFrames )
+ {
+ goto EXIT;
+ }
+
+ CAMHAL_LOGDB("Captured Frames: %d", mCapturedFrames);
+
+ mCapturedFrames--;
+
+ CameraFrame cameraFrame;
+ stat |= initCameraFrame(cameraFrame,
+ pBuffHeader,
+ typeOfFrame,
+ pPortParam);
+ stat |= sendFrame(cameraFrame);
+ }
+ else
+ {
+ CAMHAL_LOGEA("Frame received for non-(preview/capture/measure) port. This is yet to be supported");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR != stat )
+ {
+ CAMHAL_LOGDB("sendFrameToSubscribers error: %d", stat);
+ returnFrame(pBuffHeader->pBuffer, 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;
+
+ 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;
+}
+
+status_t OMXCameraAdapter::sendFrame(CameraFrame &frame)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+
+ if ( NO_ERROR == ret )
+ {
+ ret = sendFrameToSubscribers(&frame);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::initCameraFrame( CameraFrame &frame,
+ OMX_IN OMX_BUFFERHEADERTYPE *pBuffHeader,
+ int typeOfFrame,
+ 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;
+ }
+
+ frame.mFrameType = typeOfFrame;
+ frame.mBuffer = pBuffHeader->pBuffer;
+ frame.mLength = pBuffHeader->nFilledLen;
+ frame.mAlignment = port->mStride;
+ frame.mOffset = pBuffHeader->nOffset;
+ frame.mWidth = port->mWidth;
+ frame.mHeight = port->mHeight;
+
+ // Calculating the time source delta of Ducati & system time only once at the start of camera.
+ // It's seen that there is a one-time constant diff between the ducati source clock &
+ // System monotonic timer, although both derived from the same 32KHz clock.
+ // This delta is offsetted to/from ducati timestamp to match with system time so that
+ // video timestamps are aligned with Audio with a periodic timestamp intervals.
+ if ( onlyOnce )
+ {
+ mTimeSourceDelta = (pBuffHeader->nTimeStamp * 1000) - systemTime(SYSTEM_TIME_MONOTONIC);
+ onlyOnce = false;
+ }
+
+ // Calculating the new video timestamp based on offset from ducati source.
+ frame.mTimestamp = (pBuffHeader->nTimeStamp * 1000) - mTimeSourceDelta;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+bool OMXCameraAdapter::CommandHandler::Handler()
+{
+ TIUTILS::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...");
+ TIUTILS::MessageQueue::waitForMsg(&mCommandMsgQ, NULL, NULL, -1);
+ mCommandMsgQ.get(&msg);
+ CAMHAL_LOGDB("msg.command = %d", msg.command);
+ switch ( msg.command ) {
+ case CommandHandler::CAMERA_START_IMAGE_CAPTURE:
+ {
+ stat = mCameraAdapter->startImageCapture();
+ break;
+ }
+ case CommandHandler::CAMERA_PERFORM_AUTOFOCUS:
+ {
+ stat = mCameraAdapter->doAutoFocus();
+ break;
+ }
+ case CommandHandler::COMMAND_EXIT:
+ {
+ CAMHAL_LOGEA("Exiting command handler");
+ forever = 0;
+ break;
+ }
+ }
+
+ if ( NO_ERROR != stat )
+ {
+ errorNotify = ( ErrorNotifier * ) msg.arg1;
+ if ( NULL != errorNotify )
+ {
+ errorNotify->errorNotify(CAMERA_ERROR_UNKNOWN);
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return false;
+}
+
+bool OMXCameraAdapter::OMXCallbackHandler::Handler()
+{
+ TIUTILS::Message msg;
+ volatile int forever = 1;
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ while(forever){
+ TIUTILS::MessageQueue::waitForMsg(&mCommandMsgQ, NULL, NULL, -1);
+ mCommandMsgQ.get(&msg);
+ switch ( msg.command ) {
+ case OMXCallbackHandler::CAMERA_FILL_BUFFER_DONE:
+ {
+ ret = mCameraAdapter->OMXCameraAdapterFillBufferDone(( OMX_HANDLETYPE ) msg.arg1,
+ ( OMX_BUFFERHEADERTYPE *) msg.arg2);
+ break;
+ }
+ case CommandHandler::COMMAND_EXIT:
+ {
+ CAMHAL_LOGEA("Exiting OMX callback handler");
+ forever = 0;
+ break;
+ }
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return false;
+}
+
+OMXCameraAdapter::OMXCameraAdapter():mComponentState (OMX_StateInvalid)
+{
+ LOG_FUNCTION_NAME;
+
+ mPictureRotation = 0;
+ // Initial values
+ mTimeSourceDelta = 0;
+ onlyOnce = true;
+
+ mDoAFSem.Create(0);
+ mInitSem.Create(0);
+ mFlushSem.Create(0);
+ mUsePreviewDataSem.Create(0);
+ mUsePreviewSem.Create(0);
+ mUseCaptureSem.Create(0);
+ mStartPreviewSem.Create(0);
+ mStopPreviewSem.Create(0);
+ mStartCaptureSem.Create(0);
+ mStopCaptureSem.Create(0);
+ mSwitchToLoadedSem.Create(0);
+ mCaptureSem.Create(0);
+
+ mCameraAdapterParameters.mHandleComp = 0;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+OMXCameraAdapter::~OMXCameraAdapter()
+{
+ LOG_FUNCTION_NAME;
+
+ //Return to OMX Loaded state
+ switchToLoaded();
+
+ ///Free the handle for the Camera component
+ if(mCameraAdapterParameters.mHandleComp)
+ {
+ OMX_FreeHandle(mCameraAdapterParameters.mHandleComp);
+ }
+
+ ///De-init the OMX
+ if( (mComponentState==OMX_StateLoaded) || (mComponentState==OMX_StateInvalid))
+ {
+ OMX_Deinit();
+ }
+
+ //Exit and free ref to command handling thread
+ if ( NULL != mCommandHandler.get() )
+ {
+ TIUTILS::Message msg;
+ msg.command = CommandHandler::COMMAND_EXIT;
+ msg.arg1 = mErrorNotifier;
+ mCommandHandler->put(&msg);
+ mCommandHandler->requestExitAndWait();
+ mCommandHandler.clear();
+ }
+
+ //Exit and free ref to callback handling thread
+ if ( NULL != mOMXCallbackHandler.get() )
+ {
+ TIUTILS::Message msg;
+ msg.command = OMXCallbackHandler::COMMAND_EXIT;
+ mOMXCallbackHandler->put(&msg);
+ mOMXCallbackHandler->requestExitAndWait();
+ mOMXCallbackHandler.clear();
+ }
+
+ gCameraAdapter = NULL;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+extern "C" CameraAdapter* CameraAdapter_Factory()
+{
+ Mutex::Autolock lock(gAdapterLock);
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == gCameraAdapter )
+ {
+ CAMHAL_LOGDA("Creating new Camera adapter instance");
+ gCameraAdapter= new OMXCameraAdapter();
+ }
+ else
+ {
+ CAMHAL_LOGDA("Reusing existing Camera adapter instance");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return gCameraAdapter;
+}
+
+extern "C" int CameraAdapter_Capabilities(CameraProperties::Properties* properties_array,
+ const unsigned int starting_camera,
+ const unsigned int max_camera) {
+ int num_cameras_supported = 0;
+ CameraProperties::Properties* properties = NULL;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_HANDLETYPE handle = NULL;
+ OMX_TI_CAPTYPE caps;
+
+ LOG_FUNCTION_NAME;
+
+ if (!properties_array) {
+ CAMHAL_LOGEB("invalid param: properties = 0x%p", properties_array);
+ LOG_FUNCTION_NAME_EXIT;
+ return -EINVAL;
+ }
+
+ // OMX_Init
+ eError = OMX_Init();
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_Init -0x%x", eError);
+ return 0; // no cameras supported
+ }
+
+ // Setup key parameters to send to Ducati during init
+ OMX_CALLBACKTYPE oCallbacks;
+
+ // Initialize the callback handles
+ oCallbacks.EventHandler = android::OMXCameraAdapterEventHandler;
+ oCallbacks.EmptyBufferDone = android::OMXCameraAdapterEmptyBufferDone;
+ oCallbacks.FillBufferDone = android::OMXCameraAdapterFillBufferDone;
+
+ // Get Handle
+ eError = OMX_GetHandle(&handle, (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA", NULL, &oCallbacks);
+ if (eError != OMX_ErrorNone) {
+ CAMHAL_LOGEB("OMX_GetHandle -0x%x", eError);
+ goto EXIT;
+ }
+
+ // 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) {
+ // sensor select
+ OMX_CONFIG_SENSORSELECTTYPE sensorSelect;
+ OMX_INIT_STRUCT_PTR (&sensorSelect, OMX_CONFIG_SENSORSELECTTYPE);
+ sensorSelect.eSensor = (OMX_SENSORSELECT) num_cameras_supported;
+ eError = OMX_SetConfig(handle, ( OMX_INDEXTYPE ) OMX_TI_IndexConfigSensorSelect, &sensorSelect);
+
+ if ( OMX_ErrorNone != eError ) {
+ break;
+ }
+
+ // get and fill capabilities
+ properties = properties_array + starting_camera + num_cameras_supported;
+ OMXCameraAdapter::getCaps(properties, handle);
+
+ // need to fill facing information
+ // assume that only sensor 0 is back facing
+ if (num_cameras_supported == 0) {
+ properties->set(CameraProperties::FACING_INDEX, TICameraParameters::FACING_BACK);
+ } else {
+ properties->set(CameraProperties::FACING_INDEX, TICameraParameters::FACING_FRONT);
+ }
+
+ num_cameras_supported++;
+ }
+
+ EXIT:
+ // clean up
+ if(handle) {
+ OMX_FreeHandle(handle);
+ }
+ OMX_Deinit();
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return num_cameras_supported;
+}
+
+};
+
+
+/*--------------------Camera Adapter Class ENDS here-----------------------------*/
+
diff --git a/camera/OMXCameraAdapter/OMXCapabilities.cpp b/camera/OMXCameraAdapter/OMXCapabilities.cpp
new file mode 100644
index 0000000..fc961fa
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXCapabilities.cpp
@@ -0,0 +1,1181 @@
+/*
+ * 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"
+
+extern "C" {
+#include "memmgr.h"
+}
+
+namespace android {
+
+#undef LOG_TAG
+
+// Maintain a separate tag for OMXCameraAdapter logs to isolate issues OMX specific
+#define LOG_TAG "CameraHAL"
+
+/************************************
+ * global constants and variables
+ *************************************/
+
+#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
+#define FPS_MIN 5
+#define FPS_STEP 5
+#define FPS_RANGE_STEP 10
+
+static const char PARAM_SEP[] = ",";
+static const int PARAM_SEP_CHAR = ',';
+static const uint32_t VFR_OFFSET = 8;
+static const char VFR_BACKET_START[] = "(";
+static const char VFR_BRACKET_END[] = ")";
+static const char FRAMERATE_COUNT = 10;
+
+/**** look up tables to translate OMX Caps to Parameter ****/
+
+const CapResolution OMXCameraAdapter::mImageCapRes [] = {
+ { 4032, 3024, "4032x3024" },
+ { 4000, 3000, "4000x3000" },
+ { 3648, 2736, "3648x2736" },
+ { 3264, 2448, "3264x2448" },
+ { 2592, 1944, "2592x1944" },
+ { 2048, 1536, "2048x1536" },
+ { 1600, 1200, "1600x1200" },
+ { 1280, 1024, "1280x1024" },
+ { 1152, 864, "1152x864" },
+ { 1280, 960, "1280x960" },
+ { 640, 480, "640x480" },
+ { 320, 240, "320x240" },
+};
+
+const CapResolution OMXCameraAdapter::mPreviewRes [] = {
+ { 1920, 1080, "1920x1080" },
+ { 1280, 720, "1280x720" },
+ { 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" },
+ { 128, 96, "128x96" },
+};
+
+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, CameraParameters::PIXEL_FORMAT_YUV422I },
+ { OMX_COLOR_FormatYUV420SemiPlanar, CameraParameters::PIXEL_FORMAT_YUV420SP },
+ { OMX_COLOR_Format16bitRGB565, CameraParameters::PIXEL_FORMAT_RGB565 },
+ { OMX_COLOR_FormatRawBayer10bit, TICameraParameters::PIXEL_FORMAT_RAW },
+};
+
+const CapFramerate OMXCameraAdapter::mFramerates [] = {
+ { 30, "30" },
+ { 25, "25" },
+ { 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 [] = {
+ { 300, "IMX060" },
+ { 301, "OV5650" },
+ { 305, "S5K4E1GA"},
+ { 306, "S5K6A1GX03" }
+ // TODO(XXX): need to account for S3D camera later
+};
+
+/************************************
+ * static helper functions
+ *************************************/
+
+// utility function to remove last seperator
+void remove_last_sep(char* buffer) {
+ char* last_sep = NULL;
+ last_sep = strrchr(buffer, PARAM_SEP_CHAR);
+ if (last_sep != NULL) {
+ last_sep[0] = '\0';
+ }
+}
+
+
+/*****************************************
+ * internal static function declarations
+ *****************************************/
+
+/**** Utility functions to help translate OMX Caps to Parameter ****/
+
+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 ) {
+ strncat(buffer, cap[i].param, bufferSize - 1);
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodeFramerateCap(OMX_U32 framerateMax,
+ OMX_U32 framerateMin,
+ const CapFramerate *cap,
+ size_t capCount,
+ char * buffer,
+ size_t bufferSize) {
+ status_t ret = NO_ERROR;
+ bool minInserted = false;
+ bool maxInserted = false;
+ char tmpBuffer[FRAMERATE_COUNT];
+
+ LOG_FUNCTION_NAME;
+
+ if ( ( NULL == buffer ) || ( NULL == cap ) ) {
+ CAMHAL_LOGEA("Invalid input arguments");
+ return -EINVAL;
+ }
+
+ for ( unsigned int i = 0; i < capCount; i++ ) {
+ if ( (framerateMax >= cap[i].num) && (framerateMin <= cap[i].num) ) {
+ strncat(buffer, cap[i].param, bufferSize - 1);
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+
+ if ( cap[i].num == framerateMin ) {
+ minInserted = true;
+ }
+ }
+ if ( cap[i].num == framerateMax ) {
+ maxInserted = true;
+ }
+ }
+
+ if ( !maxInserted ) {
+ memset(tmpBuffer, 0, FRAMERATE_COUNT);
+ snprintf(tmpBuffer, FRAMERATE_COUNT - 1, "%u,", ( unsigned int ) framerateMax);
+ strncat(buffer, tmpBuffer, bufferSize - 1);
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+
+ if ( !minInserted ) {
+ memset(tmpBuffer, 0, FRAMERATE_COUNT);
+ snprintf(tmpBuffer, FRAMERATE_COUNT - 1, "%u,", ( unsigned int ) framerateMin);
+ strncat(buffer, tmpBuffer, bufferSize - 1);
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+
+ remove_last_sep(buffer);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodeVFramerateCap(OMX_TI_CAPTYPE &caps,
+ char *buffer,
+ char *defaultRange,
+ size_t bufferSize) {
+ status_t ret = NO_ERROR;
+ uint32_t minVFR, maxVFR;
+ char tmpBuffer[MAX_PROP_VALUE_LENGTH];
+ bool skipLast = false;
+ uint32_t min, max;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == buffer ) {
+ CAMHAL_LOGEA("Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if(caps.ulPrvVarFPSModesCount < 1) {
+ return NO_ERROR;
+ }
+
+ // Assumption: last range in tPrvVarFPSModes will be for S30FPSHD mode
+ minVFR = caps.tPrvVarFPSModes[caps.ulPrvVarFPSModesCount-1].nVarFPSMin >> VFR_OFFSET;
+ maxVFR = caps.tPrvVarFPSModes[caps.ulPrvVarFPSModesCount-1].nVarFPSMax >> VFR_OFFSET;
+
+ if (minVFR < FPS_MIN) {
+ minVFR = FPS_MIN;
+ }
+
+ memset(tmpBuffer, '\0', MAX_PROP_VALUE_LENGTH);
+ min = max = 0;
+ for (unsigned int i = minVFR; i <= maxVFR; i += FPS_STEP) {
+
+ min = i * CameraHal::VFR_SCALE;
+ max = (i + FPS_RANGE_STEP) * CameraHal::VFR_SCALE;
+
+ snprintf(tmpBuffer, ( MAX_PROP_VALUE_LENGTH - 1 ), "(%d,%d)", min, min);
+ strncat(buffer, tmpBuffer, ( bufferSize - 1 ));
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+
+ if (max <= maxVFR * CameraHal::VFR_SCALE) {
+ snprintf(tmpBuffer, ( MAX_PROP_VALUE_LENGTH - 1 ), "(%d,%d)", min, max);
+ strncat(buffer, tmpBuffer, ( bufferSize - 1 ));
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+ }
+ remove_last_sep(buffer);
+
+ if ( 1 < strlen(tmpBuffer) ) {
+ snprintf(defaultRange, ( MAX_PROP_VALUE_LENGTH - 1 ), "%d,%d", min, min);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+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 ) {
+ strncat(buffer, cap[i].param, bufferSize - 1);
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ ret++;
+ }
+ }
+ remove_last_sep(buffer);
+
+ 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) {
+ strncat(buffer, cap[i].param, bufferSize - 1);
+ strncat(buffer, PARAM_SEP, bufferSize - 1);
+ }
+ }
+ remove_last_sep(buffer);
+
+ 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) ) {
+ strncat(buffer, cap[i].param, bufferSize -1);
+ strncat(buffer, PARAM_SEP, 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];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ 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 {
+ remove_last_sep(supported);
+ params->set(CameraProperties::SUPPORTED_PICTURE_SIZES, supported);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertPreviewSizes(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 preview sizes 0x%x", ret);
+ } else {
+ remove_last_sep(supported);
+ params->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, supported);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ 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
+ strncat(supported, "0x0", MAX_PROP_NAME_LENGTH);
+ params->set(CameraProperties::SUPPORTED_THUMBNAIL_SIZES, supported);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ 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, TICameraParameters::ZOOM_UNSUPPORTED);
+ params->set(CameraProperties::SMOOTH_ZOOM_SUPPORTED, TICameraParameters::ZOOM_UNSUPPORTED);
+ } else {
+ params->set(CameraProperties::ZOOM_SUPPORTED, TICameraParameters::ZOOM_SUPPORTED);
+ params->set(CameraProperties::SMOOTH_ZOOM_SUPPORTED, TICameraParameters::ZOOM_SUPPORTED);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ 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', MAX_PROP_VALUE_LENGTH);
+
+ 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;
+ }
+ }
+
+ if ( NO_ERROR == ret ) {
+ //jpeg is not supported in OMX capabilies yet
+ strncat(supported, CameraParameters::PIXEL_FORMAT_JPEG, MAX_PROP_VALUE_LENGTH - 1);
+ params->set(CameraProperties::SUPPORTED_PICTURE_FORMATS, supported);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ 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
+ strncat(supported, CameraParameters::PIXEL_FORMAT_YUV420P, MAX_PROP_VALUE_LENGTH - 1);
+ params->set(CameraProperties::SUPPORTED_PREVIEW_FORMATS, supported);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertFramerates(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 = encodeFramerateCap(caps.xFramerateMax >> VFR_OFFSET,
+ caps.xFramerateMin >> VFR_OFFSET,
+ mFramerates,
+ ARRAY_SIZE(mFramerates),
+ supported,
+ MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported preview framerates 0x%x", ret);
+ } else {
+ params->set(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES, supported);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertVFramerates(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps) {
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ char defaultRange[MAX_PROP_VALUE_LENGTH];
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ ret = encodeVFramerateCap(caps, supported, defaultRange, MAX_PROP_VALUE_LENGTH);
+
+ if ( NO_ERROR != ret ) {
+ CAMHAL_LOGEB("Error inserting supported preview framerate ranges 0x%x", ret);
+ } else {
+ params->set(CameraProperties::FRAMERATE_RANGE_SUPPORTED, supported);
+ CAMHAL_LOGDB("framerate ranges %s", supported);
+ params->set(CameraProperties::FRAMERATE_RANGE, defaultRange);
+ CAMHAL_LOGDB("Default framerate range: [%s]", defaultRange);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+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;
+
+ 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;
+
+ 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);
+ strncat(supported, PARAM_SEP, 1);
+
+ if ( caps.bLensDistortionCorrectionSupported ) {
+ strncat(supported, TICameraParameters::IPP_LDC, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+
+ if ( caps.bISONoiseFilterSupported ) {
+ strncat(supported, TICameraParameters::IPP_NSF, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+
+ if ( caps.bISONoiseFilterSupported && caps.bLensDistortionCorrectionSupported ) {
+ strncat(supported, TICameraParameters::IPP_LDCNSF, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+
+ remove_last_sep(supported);
+ params->set(CameraProperties::SUPPORTED_IPP_MODES, supported);
+
+ LOG_FUNCTION_NAME;
+
+ 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 ) {
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+ }
+
+ //These modes are not supported by the capability feature
+ strncat(supported, TICameraParameters::WHITE_BALANCE_FACE, MAX_PROP_NAME_LENGTH);
+
+ params->set(CameraProperties::SUPPORTED_WHITE_BALANCE, supported);
+
+ LOG_FUNCTION_NAME;
+
+ 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 ) {
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+ }
+ remove_last_sep(supported);
+ params->set(CameraProperties::SUPPORTED_EFFECTS, supported);
+
+ LOG_FUNCTION_NAME;
+
+ 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 ) {
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+ }
+
+ //These modes are not supported by the capability feature
+ strncat(supported, TICameraParameters::EXPOSURE_MODE_FACE, MAX_PROP_NAME_LENGTH);
+
+ params->set(CameraProperties::SUPPORTED_EXPOSURE_MODES, supported);
+
+ LOG_FUNCTION_NAME;
+
+ 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 ) {
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+ }
+
+ remove_last_sep(supported);
+ params->set(CameraProperties::SUPPORTED_FLASH_MODES, supported);
+
+ LOG_FUNCTION_NAME;
+
+ 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 ) {
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+ }
+
+ remove_last_sep(supported);
+ params->set(CameraProperties::SUPPORTED_SCENE_MODES, supported);
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertFocusModes(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.ulFocusModeCount; i++ ) {
+ p = getLUTvalue_OMXtoHAL(caps.eFocusModes[i], FocusLUT);
+ if ( NULL != p ) {
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+ }
+
+ // 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
+ strncat(supported, CameraParameters::FOCUS_MODE_INFINITY, MAX_PROP_NAME_LENGTH);
+ } else {
+ // Focus is supported but these modes are not supported by the
+ // capability feature. Apply manually
+ strncat(supported, TICameraParameters::FOCUS_MODE_FACE, MAX_PROP_NAME_LENGTH);
+ }
+
+ params->set(CameraProperties::SUPPORTED_FOCUS_MODES, supported);
+
+ LOG_FUNCTION_NAME;
+
+ 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 ) {
+ strncat(supported, p, MAX_PROP_NAME_LENGTH);
+ strncat(supported, PARAM_SEP, 1);
+ }
+ }
+ remove_last_sep(supported);
+ params->set(CameraProperties::SUPPORTED_ANTIBANDING, supported);
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertLocks(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps) {
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME
+
+ params->set(CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED, DEFAULT_LOCK_SUPPORTED);
+ params->set(CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED, DEFAULT_LOCK_SUPPORTED);
+
+ LOG_FUNCTION_NAME
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertDefaults(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps) {
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+ const char *p;
+
+ LOG_FUNCTION_NAME;
+
+ 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);
+ params->set(CameraProperties::FOCUS_MODE, DEFAULT_FOCUS_MODE);
+ params->set(CameraProperties::IPP, DEFAULT_IPP);
+ 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);
+ params->set(CameraProperties::PICTURE_SIZE, DEFAULT_PICTURE_SIZE);
+ params->set(CameraProperties::PREVIEW_FORMAT, DEFAULT_PREVIEW_FORMAT);
+ params->set(CameraProperties::PREVIEW_FRAME_RATE, DEFAULT_FRAMERATE);
+ params->set(CameraProperties::PREVIEW_SIZE, DEFAULT_PREVIEW_SIZE);
+ params->set(CameraProperties::REQUIRED_PREVIEW_BUFS, DEFAULT_NUM_PREV_BUFS);
+ params->set(CameraProperties::REQUIRED_IMAGE_BUFS, DEFAULT_NUM_PIC_BUFS);
+ params->set(CameraProperties::MAX_FOCUS_AREAS, DEFAULT_MAX_FOCUS_AREAS);
+ 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::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::MAX_NUM_METERING_AREAS, DEFAULT_MAX_NUM_METERING_AREAS);
+
+ LOG_FUNCTION_NAME;
+
+ 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;
+ int i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
+
+ // 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, MAX_PROP_NAME_LENGTH);
+ params->set(CameraProperties::CAMERA_NAME, supported);
+
+ // 2) Assign mounting rotation
+ params->set(CameraProperties::ORIENTATION_INDEX, caps.tSenMounting.nRotation);
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::insertCapabilities(CameraProperties::Properties* params, OMX_TI_CAPTYPE &caps) {
+ status_t ret = NO_ERROR;
+ char supported[MAX_PROP_VALUE_LENGTH];
+
+ 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 = insertVFramerates(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 = 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 = insertDefaults(params, caps);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+/*****************************************
+ * public exposed function declarations
+ *****************************************/
+
+status_t OMXCameraAdapter::getCaps(CameraProperties::Properties* params, OMX_HANDLETYPE handle) {
+ status_t ret = NO_ERROR;
+ int caps_size = 0;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_CAPTYPE** caps = NULL;;
+ OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
+ MemoryManager memMgr;
+
+ LOG_FUNCTION_NAME;
+
+ // allocate tiler (or ion) buffer for caps
+ caps_size = sizeof(OMX_TI_CAPTYPE);
+ caps = (OMX_TI_CAPTYPE**) memMgr.allocateBuffer(0, 0, NULL, caps_size, 1);
+
+ 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[0], OMX_TI_CAPTYPE);
+ caps[0]->nPortIndex = OMX_ALL;
+
+ OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
+ sharedBuffer.nPortIndex = OMX_ALL;
+ sharedBuffer.nSharedBuffSize = caps_size;
+ sharedBuffer.pSharedBuff = (OMX_U8 *) caps[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");
+ }
+
+ // Translate and insert Ducati capabilities to CameraProperties
+ if ( NO_ERROR == ret ) {
+ ret = insertCapabilities(params, *caps[0]);
+ }
+
+ CAMHAL_LOGDB("sen mount id=%u", (unsigned int)caps[0]->tSenMounting.nSenId);
+
+
+ EXIT:
+ if (caps) {
+ memMgr.freeBuffer((void*) caps);
+ caps = NULL;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+};
+
diff --git a/camera/OMXCameraAdapter/OMXCapture.cpp b/camera/OMXCameraAdapter/OMXCapture.cpp
new file mode 100644
index 0000000..42fb384
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXCapture.cpp
@@ -0,0 +1,1066 @@
+/*
+ * 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.
+*
+*/
+
+#undef LOG_TAG
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+namespace android {
+
+status_t OMXCameraAdapter::setParametersCapture(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *str = NULL;
+ int w, h;
+ OMX_COLOR_FORMATTYPE pixFormat;
+ const char *valstr = NULL;
+ bool updateImagePortParams = false;
+
+ LOG_FUNCTION_NAME;
+
+ OMXCameraPortParameters *cap;
+ cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ params.getPictureSize(&w, &h);
+
+ if ( ( w != ( int ) cap->mWidth ) ||
+ ( h != ( int ) cap->mHeight ) )
+ {
+ updateImagePortParams = true;
+ }
+
+ 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, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
+ {
+ CAMHAL_LOGDA("CbYCrY format selected");
+ pixFormat = OMX_COLOR_FormatCbYCrY;
+ }
+ else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
+ {
+ CAMHAL_LOGDA("YUV420SP format selected");
+ pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+ else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
+ {
+ CAMHAL_LOGDA("RGB565 format selected");
+ pixFormat = OMX_COLOR_Format16bitRGB565;
+ }
+ else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_JPEG) == 0)
+ {
+ CAMHAL_LOGDA("JPEG format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mCodingMode = CodingNone;
+ }
+ else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_JPS) == 0)
+ {
+ CAMHAL_LOGDA("JPS format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mCodingMode = CodingJPS;
+ }
+ else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_MPO) == 0)
+ {
+ CAMHAL_LOGDA("MPO format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mCodingMode = CodingMPO;
+ }
+ else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW_JPEG) == 0)
+ {
+ CAMHAL_LOGDA("RAW + JPEG format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mCodingMode = CodingRAWJPEG;
+ }
+ else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW_MPO) == 0)
+ {
+ CAMHAL_LOGDA("RAW + MPO format selected");
+ pixFormat = OMX_COLOR_FormatUnused;
+ mCodingMode = CodingRAWMPO;
+ }
+ else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW) == 0)
+ {
+ CAMHAL_LOGDA("RAW Picture format selected");
+ pixFormat = OMX_COLOR_FormatRawBayer10bit;
+ }
+ else
+ {
+ CAMHAL_LOGEA("Invalid format, JPEG format selected as default");
+ pixFormat = OMX_COLOR_FormatUnused;
+ }
+ }
+ else
+ {
+ CAMHAL_LOGEA("Picture format is NULL, defaulting to JPEG");
+ pixFormat = OMX_COLOR_FormatUnused;
+ }
+
+ if ( pixFormat != cap->mColorFormat )
+ {
+ updateImagePortParams = true;
+ cap->mColorFormat = pixFormat;
+ }
+
+ if ( updateImagePortParams )
+ {
+ if ( ( CAPTURE_ACTIVE & state ) != CAPTURE_ACTIVE )
+ {
+ setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *cap);
+ }
+ }
+
+ str = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
+ if ( NULL != str ) {
+ parseExpRange(str, mExposureBracketingValues, EXP_BRACKET_RANGE, mExposureBracketingValidEntries);
+ } else {
+ mExposureBracketingValidEntries = 0;
+ }
+
+ if ( params.getInt(CameraParameters::KEY_ROTATION) != -1 )
+ {
+ mPictureRotation = params.getInt(CameraParameters::KEY_ROTATION);
+ }
+ else
+ {
+ mPictureRotation = 0;
+ }
+
+ CAMHAL_LOGVB("Picture Rotation set %d", mPictureRotation);
+
+ // Read Sensor Orientation and set it based on perating mode
+
+ if (( params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION) != -1 ) && (mCapMode == OMXCameraAdapter::VIDEO_MODE))
+ {
+ mSensorOrientation = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION);
+ 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);
+
+ if ( params.getInt(TICameraParameters::KEY_BURST) >= 1 )
+ {
+ mBurstFrames = params.getInt(TICameraParameters::KEY_BURST);
+ }
+ else
+ {
+ mBurstFrames = 1;
+ }
+
+ CAMHAL_LOGVB("Burst Frames set %d", mBurstFrames);
+
+ if ( ( params.getInt(CameraParameters::KEY_JPEG_QUALITY) >= MIN_JPEG_QUALITY ) &&
+ ( params.getInt(CameraParameters::KEY_JPEG_QUALITY) <= MAX_JPEG_QUALITY ) )
+ {
+ mPictureQuality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
+ }
+ else
+ {
+ mPictureQuality = MAX_JPEG_QUALITY;
+ }
+
+ CAMHAL_LOGVB("Picture Quality set %d", mPictureQuality);
+
+ if ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH) >= 0 )
+ {
+ mThumbWidth = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ }
+ else
+ {
+ mThumbWidth = DEFAULT_THUMB_WIDTH;
+ }
+
+
+ CAMHAL_LOGVB("Picture Thumb width set %d", mThumbWidth);
+
+ if ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT) >= 0 )
+ {
+ mThumbHeight = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ }
+ else
+ {
+ mThumbHeight = DEFAULT_THUMB_HEIGHT;
+ }
+
+
+ CAMHAL_LOGVB("Picture Thumb height set %d", mThumbHeight);
+
+ if ( ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY) >= MIN_JPEG_QUALITY ) &&
+ ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY) <= MAX_JPEG_QUALITY ) )
+ {
+ mThumbQuality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ }
+ else
+ {
+ mThumbQuality = MAX_JPEG_QUALITY;
+ }
+
+ CAMHAL_LOGDB("Thumbnail Quality set %d", mThumbQuality);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::getPictureBufferSize(size_t &length, 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];
+
+ imgCaptureData->mNumBufs = bufferCount;
+ ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
+ if ( ret == NO_ERROR )
+ {
+ length = imgCaptureData->mBufSize;
+ }
+ else
+ {
+ CAMHAL_LOGEB("setFormat() failed 0x%x", ret);
+ length = 0;
+ }
+ }
+
+ CAMHAL_LOGDB("getPictureBufferSize %d", length);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::parseExpRange(const char *rangeStr,
+ int * expRange,
+ size_t count,
+ size_t &validEntries)
+{
+ status_t ret = NO_ERROR;
+ char *ctx, *expVal;
+ char *tmp = NULL;
+ size_t i = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == rangeStr )
+ {
+ return -EINVAL;
+ }
+
+ if ( NULL == expRange )
+ {
+ return -EINVAL;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ tmp = ( char * ) malloc( strlen(rangeStr) + 1 );
+
+ if ( NULL == tmp )
+ {
+ CAMHAL_LOGEA("No resources for temporary buffer");
+ return -1;
+ }
+ memset(tmp, '\0', strlen(rangeStr) + 1);
+
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ strncpy(tmp, rangeStr, strlen(rangeStr) );
+ expVal = strtok_r( (char *) tmp, CameraHal::PARAMS_DELIMITER, &ctx);
+
+ i = 0;
+ while ( ( NULL != expVal ) && ( i < count ) )
+ {
+ expRange[i] = atoi(expVal);
+ expVal = strtok_r(NULL, CameraHal::PARAMS_DELIMITER, &ctx);
+ i++;
+ }
+ validEntries = i;
+ }
+
+ if ( NULL != tmp )
+ {
+ free(tmp);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setExposureBracketing(int *evValues,
+ size_t evCount,
+ size_t frameCount)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_CAPTUREMODETYPE expCapMode;
+ OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode;
+
+ 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 )
+ {
+ 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 = OMX_BracketExposureRelativeInEV;
+ extExpCapMode.tBracketConfigType.nNbrBracketingValues = evCount - 1;
+ }
+
+ for ( unsigned int i = 0 ; i < evCount ; i++ )
+ {
+ 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 )
+ {
+ currentBufferIdx = ( unsigned int ) pBuffHeader->pAppPrivate;
+
+ 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;
+ setFrameRefCount(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame, 1);
+ returnFrame(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::sendBracketFrames()
+{
+ status_t ret = NO_ERROR;
+ int currentBufferIdx;
+ 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 )
+ {
+
+ currentBufferIdx = mLastBracetingBufferIdx;
+ do
+ {
+ currentBufferIdx++;
+ currentBufferIdx %= imgCaptureData->mNumBufs;
+ if (!mBracketingBuffersQueued[currentBufferIdx] )
+ {
+ CameraFrame cameraFrame;
+ initCameraFrame(cameraFrame,
+ imgCaptureData->mBufferHeader[currentBufferIdx],
+ imgCaptureData->mImageType,
+ imgCaptureData);
+ sendFrame(cameraFrame);
+ }
+ } 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;
+ }
+
+ {
+ Mutex::Autolock 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 )
+ {
+ Mutex::Autolock 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;
+ mLastBracetingBufferIdx = mBracketingBuffersQueuedCount - 1;
+
+ for ( int i = 0 ; i < imgCaptureData->mNumBufs ; i++ )
+ {
+ mBracketingBuffersQueued[i] = true;
+ }
+
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ ret = startImageCapture();
+ {
+ Mutex::Autolock 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;
+
+ Mutex::Autolock lock(mBracketingLock);
+
+ if ( mBracketingEnabled )
+ {
+
+ if ( NULL != mBracketingBuffersQueued )
+ {
+ delete [] mBracketingBuffersQueued;
+ }
+
+ ret = stopImageCapture();
+
+ mBracketingBuffersQueued = NULL;
+ mBracketingEnabled = false;
+ mBracketingBuffersQueuedCount = 0;
+ mLastBracetingBufferIdx = 0;
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startImageCapture()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMXCameraPortParameters * capData = NULL;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+
+ LOG_FUNCTION_NAME;
+
+ 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;
+ }
+
+ //During bracketing image capture is already active
+ {
+ Mutex::Autolock lock(mBracketingLock);
+ if ( mBracketingEnabled )
+ {
+ //Stop bracketing, activate normal burst for the remaining images
+ mBracketingEnabled = false;
+ mCapturedFrames = mBracketingRange;
+ ret = sendBracketFrames();
+ goto EXIT;
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setPictureRotation(mPictureRotation);
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error configuring image rotation %x", ret);
+ }
+ }
+
+ //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 ( NO_ERROR == ret )
+ {
+ capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ ///Queue all the buffers on capture port
+ for ( int index = 0 ; index < capData->mNumBufs ; index++ )
+ {
+ CAMHAL_LOGDB("Queuing buffer on Capture port - 0x%x",
+ ( unsigned int ) capData->mBufferHeader[index]->pBuffer);
+ eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp,
+ (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]);
+
+ GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ }
+
+ mWaitingForSnapshot = true;
+ mCaptureSignalled = false;
+
+ 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);
+
+ }
+
+ //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 ( NO_ERROR == ret )
+ {
+ CAMHAL_LOGDA("Shutter callback received");
+ notifyShutterSubscribers();
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_TI_IndexConfigShutterCallback,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on shutter callback");
+ goto EXIT;
+ }
+
+ }
+
+ EXIT:
+
+ if ( eError != OMX_ErrorNone )
+ {
+
+ mWaitingForSnapshot = false;
+ mCaptureSignalled = false;
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::stopImageCapture()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError;
+ OMX_CONFIG_BOOLEANTYPE bOMX;
+ OMXCameraPortParameters *imgCaptureData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ 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;
+ }
+
+ //Disable the callback first
+ mWaitingForSnapshot = false;
+ mSnapshotCount = 0;
+
+ //Disable the callback first
+ ret = setShutterCallback(false);
+
+ //release any 3A locks if locked
+ ret = release3ALock();
+ if(ret!=NO_ERROR)
+ {
+ CAMHAL_LOGEB("Error Releaseing 3A locks%d", ret);
+ }
+
+ //Wait here for the capture to be done, in worst case timeout and proceed with cleanup
+ ret = mCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT);
+ if ( NO_ERROR != ret ) {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_TI_IndexConfigShutterCallback,
+ NULL);
+ CAMHAL_LOGEA("Timeout expired on shutter callback");
+ }
+
+ //Disable image capture
+ 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;
+ }
+
+ CAMHAL_LOGDB("Capture set - 0x%x", eError);
+
+ mCaptureSignalled = true; //set this to true if we exited because of timeout
+
+ mCaptureConfigured = false;
+
+ ///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 ( NO_ERROR == ret ) {
+ CAMHAL_LOGDA("Port disabled");
+ } else {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortDisable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on port disable");
+ goto EXIT;
+ }
+
+ EXIT:
+
+ //Release image buffers
+ if ( NULL != mReleaseImageBuffersCallback ) {
+ mReleaseImageBuffersCallback(mReleaseData);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::UseBuffersCapture(void* bufArr, int num)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError;
+ OMXCameraPortParameters * imgCaptureData = NULL;
+ uint32_t *buffers = (uint32_t*)bufArr;
+ OMXCameraPortParameters cap;
+
+ imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ( 0 != mUseCaptureSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count());
+ goto EXIT;
+ }
+
+ imgCaptureData->mNumBufs = num;
+
+ //TODO: Support more pixelformats
+
+ CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth);
+ CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mWidth);
+
+ 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;
+ }
+
+ ret = setThumbnailParams(mThumbWidth, mThumbHeight, mThumbQuality);
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring thumbnail size %x", ret);
+ return ret;
+ }
+
+ ret = setExposureBracketing( mExposureBracketingValues,
+ mExposureBracketingValidEntries, mBurstFrames);
+ if ( ret != NO_ERROR )
+ {
+ CAMHAL_LOGEB("setExposureBracketing() failed %d", ret);
+ return ret;
+ }
+
+ ret = setImageQuality(mPictureQuality);
+ if ( NO_ERROR != ret)
+ {
+ CAMHAL_LOGEB("Error configuring image quality %x", ret);
+ return ret;
+ }
+
+ ///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);
+
+ for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++ )
+ {
+ OMX_BUFFERHEADERTYPE *pBufferHdr;
+ CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d",
+ (unsigned int)buffers[index],
+ (int)imgCaptureData->mBufSize);
+
+ eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp,
+ &pBufferHdr,
+ mCameraAdapterParameters.mImagePortIndex,
+ 0,
+ mCaptureBuffersLength,
+ (OMX_U8*)buffers[index]);
+
+ CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
+
+ GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
+
+ pBufferHdr->pAppPrivate = (OMX_PTR) 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;
+ }
+
+ //Wait for the image port enable event
+ CAMHAL_LOGDA("Waiting for port enable");
+ ret = mUseCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
+ if ( ret == NO_ERROR )
+ {
+ CAMHAL_LOGDA("Port enabled");
+ }
+ else
+ {
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ OMX_EventCmdComplete,
+ OMX_CommandPortEnable,
+ mCameraAdapterParameters.mImagePortIndex,
+ NULL);
+ CAMHAL_LOGDA("Timeout expired on port enable");
+ goto EXIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setupEXIF();
+ if ( NO_ERROR != ret )
+ {
+ CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
+ }
+ }
+
+ mCapturedFrames = mBurstFrames;
+ mCaptureConfigured = true;
+
+ EXIT:
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+};
diff --git a/camera/OMXCameraAdapter/OMXDefaults.cpp b/camera/OMXCameraAdapter/OMXDefaults.cpp
new file mode 100644
index 0000000..670f562
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXDefaults.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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 android {
+
+#undef LOG_TAG
+#define LOG_TAG "CameraHAL"
+
+// 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[] = "infinity";
+const char OMXCameraAdapter::DEFAULT_FRAMERATE_RANGE[] = "20000,30000";
+const char OMXCameraAdapter::DEFAULT_IPP[] = "off";
+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_PICTURE_SIZE[] = "320x240";
+const char OMXCameraAdapter::DEFAULT_PREVIEW_FORMAT[] = "yuv420sp";
+const char OMXCameraAdapter::DEFAULT_FRAMERATE[] = "30";
+const char OMXCameraAdapter::DEFAULT_PREVIEW_SIZE[] = "640x480";
+const char OMXCameraAdapter::DEFAULT_NUM_PREV_BUFS[] = "6";
+const char OMXCameraAdapter::DEFAULT_NUM_PIC_BUFS[] = "1";
+const char OMXCameraAdapter::DEFAULT_MAX_FOCUS_AREAS[] = "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[] = "0";
+const char OMXCameraAdapter::DEFAULT_WB[] = "auto";
+const char OMXCameraAdapter::DEFAULT_ZOOM[] = "0";
+const char OMXCameraAdapter::DEFAULT_MAX_FD_HW_FACES[] = "35";
+const char OMXCameraAdapter::DEFAULT_MAX_FD_SW_FACES[] = "0";
+
+const char OMXCameraAdapter::DEFAULT_AE_LOCK[] = "false";
+const char OMXCameraAdapter::DEFAULT_AWB_LOCK[] = "false";
+const char OMXCameraAdapter::DEFAULT_MAX_NUM_METERING_AREAS[] = "0";
+const char OMXCameraAdapter::DEFAULT_LOCK_SUPPORTED[] = "true";
+const char OMXCameraAdapter::DEFAULT_LOCK_UNSUPPORTED[] = "false";
+};
+
diff --git a/camera/OMXCameraAdapter/OMXExif.cpp b/camera/OMXCameraAdapter/OMXExif.cpp
new file mode 100644
index 0000000..56b1694
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXExif.cpp
@@ -0,0 +1,567 @@
+/*
+ * 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.
+*
+*/
+
+#undef LOG_TAG
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+#include <math.h>
+
+namespace android {
+
+const char OMXCameraAdapter::EXIFASCIIPrefix [] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
+
+status_t OMXCameraAdapter::setParametersEXIF(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *valstr = NULL;
+ double gpsPos;
+
+ LOG_FUNCTION_NAME;
+
+ if( ( valstr = params.get(CameraParameters::KEY_GPS_LATITUDE) ) != NULL )
+ {
+ gpsPos = strtod(valstr, NULL);
+
+ if ( convertGPSCoord( gpsPos, &mEXIFData.mGPSData.mLatDeg,
+ &mEXIFData.mGPSData.mLatMin,
+ &mEXIFData.mGPSData.mLatSec ) == 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(CameraParameters::KEY_GPS_LONGITUDE) ) != NULL )
+ {
+ gpsPos = strtod(valstr, NULL);
+
+ if ( convertGPSCoord( gpsPos, &mEXIFData.mGPSData.mLongDeg,
+ &mEXIFData.mGPSData.mLongMin,
+ &mEXIFData.mGPSData.mLongSec ) == 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(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(CameraParameters::KEY_GPS_TIMESTAMP)) != NULL )
+ {
+ long gpsTimestamp = strtol(valstr, NULL, 10);
+ struct tm *timeinfo = localtime( ( 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(CameraParameters::KEY_GPS_TIMESTAMP) ) != NULL )
+ {
+ long gpsDatestamp = strtol(valstr, NULL, 10);
+ struct tm *timeinfo = localtime( ( 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(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);
+ mEXIFData.mModelValid= true;
+ }
+ else
+ {
+ mEXIFData.mModelValid= false;
+ }
+
+ if( ( valstr = params.get(TICameraParameters::KEY_EXIF_MAKE ) ) != NULL )
+ {
+ CAMHAL_LOGVB("EXIF Make: %s", valstr);
+ mEXIFData.mMakeValid = true;
+ }
+ else
+ {
+ mEXIFData.mMakeValid= false;
+ }
+
+ 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 *sharedPtr = NULL;
+ struct timeval sTv;
+ struct tm *pTime;
+ OMXCameraPortParameters * capData = NULL;
+ MemoryManager memMgr;
+ OMX_U8** memmgr_buf_array = NULL;
+ 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 );
+ sharedBuffer.nSharedBuffSize = buf_size;
+
+ memmgr_buf_array = (OMX_U8 **)memMgr.allocateBuffer(0, 0, NULL, buf_size, 1);
+ sharedBuffer.pSharedBuff = ( OMX_U8 * ) memmgr_buf_array[0];
+
+ if ( NULL == sharedBuffer.pSharedBuff )
+ {
+ CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
+ ret = -1;
+ }
+
+ //Extra data begins right after the EXIF configuration structure.
+ sharedPtr = sharedBuffer.pSharedBuff + sizeof(OMX_TI_CONFIG_EXIF_TAGS);
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ exifTags = ( OMX_TI_CONFIG_EXIF_TAGS * ) sharedBuffer.pSharedBuff;
+ 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,
+ ( char * ) mParams.get(TICameraParameters::KEY_EXIF_MODEL ),
+ EXIF_MODEL_SIZE - 1);
+
+ exifTags->pModelBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff );
+ sharedPtr += EXIF_MODEL_SIZE;
+ exifTags->ulModelBuffSizeBytes = EXIF_MODEL_SIZE;
+ exifTags->eStatusModel = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusMake) &&
+ ( mEXIFData.mMakeValid ) )
+ {
+ strncpy( ( char * ) sharedPtr,
+ ( char * ) mParams.get(TICameraParameters::KEY_EXIF_MAKE ),
+ EXIF_MAKE_SIZE - 1);
+
+ exifTags->pMakeBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff );
+ sharedPtr += EXIF_MAKE_SIZE;
+ exifTags->ulMakeBuffSizeBytes = EXIF_MAKE_SIZE;
+ exifTags->eStatusMake = OMX_TI_TagUpdated;
+ }
+
+ if ( ( OMX_TI_TagReadWrite == exifTags->eStatusFocalLength ))
+ {
+ char *ctx;
+ int len;
+ char* temp = (char*) mParams.get(CameraParameters::KEY_FOCAL_LENGTH);
+ char * tempVal = NULL;
+ if(temp != NULL)
+ {
+ len = strlen(temp);
+ tempVal = (char*) malloc( sizeof(char) * (len + 1));
+ }
+ if(tempVal != NULL)
+ {
+ memset(tempVal, '\0', len + 1);
+ strncpy(tempVal, temp, len);
+ CAMHAL_LOGDB("KEY_FOCAL_LENGTH = %s", tempVal);
+
+ // convert the decimal string into a rational
+ size_t den_len;
+ OMX_U32 numerator = 0;
+ OMX_U32 denominator = 0;
+ char* temp = strtok_r(tempVal, ".", &ctx);
+
+ if(temp != NULL)
+ numerator = atoi(temp);
+
+ temp = strtok_r(NULL, ".", &ctx);
+ if(temp != NULL)
+ {
+ den_len = strlen(temp);
+ if(HUGE_VAL == den_len )
+ {
+ den_len = 0;
+ }
+ denominator = static_cast<OMX_U32>(pow(10, den_len));
+ numerator = numerator*denominator + atoi(temp);
+ }else{
+ denominator = 1;
+ }
+
+ free(tempVal);
+
+ exifTags->ulFocalLength[0] = numerator;
+ exifTags->ulFocalLength[1] = denominator;
+ 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 - sharedBuffer.pSharedBuff );
+ 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] = 1;
+ 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] = 1;
+ 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 - sharedBuffer.pSharedBuff );
+ 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 - sharedBuffer.pSharedBuff );
+ 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 )
+ {
+ memMgr.freeBuffer(memmgr_buf_array);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::convertGPSCoord(double coord, int *deg, int *min, int *sec)
+{
+ double tmp;
+
+ LOG_FUNCTION_NAME;
+
+ if ( coord == 0 ) {
+
+ LOGE("Invalid GPS coordinate");
+
+ return -EINVAL;
+ }
+
+ *deg = (int) floor(fabs(coord));
+ tmp = ( fabs(coord) - floor(fabs(coord)) )*60;
+ *min = (int) floor(tmp);
+ tmp = ( tmp - floor(tmp) )*60;
+ *sec = (int) floor(tmp);
+
+ if( *sec >= 60 ) {
+ *sec = 0;
+ *min += 1;
+ }
+
+ if( *min >= 60 ) {
+ *min = 0;
+ *deg += 1;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return NO_ERROR;
+}
+
+};
diff --git a/camera/OMXCameraAdapter/OMXFD.cpp b/camera/OMXCameraAdapter/OMXFD.cpp
new file mode 100644
index 0000000..c1617d7
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXFD.cpp
@@ -0,0 +1,327 @@
+/*
+ * 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.
+*
+*/
+
+#undef LOG_TAG
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+namespace android {
+
+status_t OMXCameraAdapter::setParametersFD(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startFaceDetection()
+{
+ Mutex::Autolock lock(mFaceDetectionLock);
+ return setFaceDetection(true, mDeviceOrientation);
+}
+
+status_t OMXCameraAdapter::stopFaceDetection()
+{
+ Mutex::Autolock lock(mFaceDetectionLock);
+ return setFaceDetection(false, mDeviceOrientation);
+}
+
+status_t OMXCameraAdapter::setFaceDetection(bool enable, OMX_U32 orientation)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXTRADATATYPE extraDataControl;
+ 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 < 0 || 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 )
+ {
+ OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE);
+ extraDataControl.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
+ extraDataControl.eExtraDataType = OMX_FaceDetection;
+ extraDataControl.eCameraView = OMX_2D;
+ if ( enable )
+ {
+ extraDataControl.bEnable = OMX_TRUE;
+ }
+ else
+ {
+ extraDataControl.bEnable = OMX_FALSE;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigOtherExtraDataControl,
+ &extraDataControl);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring face detection extra data 0x%x",
+ eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDA("Face detection extra data configured successfully");
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ mFaceDetectionRunning = enable;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::detectFaces(OMX_BUFFERHEADERTYPE* pBuffHeader,
+ sp<CameraFDResult> &result,
+ size_t previewWidth,
+ size_t previewHeight)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_TI_FACERESULT *faceResult;
+ OMX_OTHER_EXTRADATATYPE *extraData;
+ OMX_FACEDETECTIONTYPE *faceData;
+ OMX_TI_PLATFORMPRIVATE *platformPrivate;
+ camera_frame_metadata_t *faces;
+
+ 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;
+ }
+
+ platformPrivate = (OMX_TI_PLATFORMPRIVATE *) (pBuffHeader->pPlatformPrivate);
+ if ( NULL != platformPrivate ) {
+ if ( sizeof(OMX_TI_PLATFORMPRIVATE) == platformPrivate->nSize ) {
+ 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);
+ } else {
+ CAMHAL_LOGEB("OMX_TI_PLATFORMPRIVATE size mismatch: expected = %d, received = %d",
+ ( unsigned int ) sizeof(OMX_TI_PLATFORMPRIVATE),
+ ( unsigned int ) platformPrivate->nSize);
+ ret = -EINVAL;
+ }
+ } else {
+ CAMHAL_LOGEA("Invalid OMX_TI_PLATFORMPRIVATE");
+ return-EINVAL;
+ }
+
+
+ if ( 0 >= platformPrivate->nMetaDataSize ) {
+ CAMHAL_LOGEB("OMX_TI_PLATFORMPRIVATE nMetaDataSize is size is %d",
+ ( unsigned int ) platformPrivate->nMetaDataSize);
+ return -EINVAL;
+ }
+
+ extraData = (OMX_OTHER_EXTRADATATYPE *) (platformPrivate->pMetaDataBuffer);
+ 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_LOGEA("Invalid OMX_OTHER_EXTRADATATYPE");
+ 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;
+ }
+
+ ret = encodeFaceCoordinates(faceData, &faces, previewWidth, previewHeight);
+
+ if ( NO_ERROR == ret ) {
+ result = new CameraFDResult(faces);
+ } else {
+ result.clear();
+ result = NULL;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::encodeFaceCoordinates(const OMX_FACEDETECTIONTYPE *faceData,
+ camera_frame_metadata_t **pFaces,
+ size_t previewWidth,
+ size_t previewHeight)
+{
+ status_t ret = NO_ERROR;
+ camera_face_t *faces;
+ camera_frame_metadata_t *faceResult;
+ size_t hRange, vRange;
+ double tmp;
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == faceData ) {
+ CAMHAL_LOGEA("Invalid OMX_FACEDETECTIONTYPE parameter");
+ return EINVAL;
+ }
+
+ LOG_FUNCTION_NAME
+
+ hRange = CameraFDResult::RIGHT - CameraFDResult::LEFT;
+ vRange = CameraFDResult::BOTTOM - CameraFDResult::TOP;
+
+ faceResult = ( camera_frame_metadata_t * ) malloc(sizeof(camera_frame_metadata_t));
+ if ( NULL == faceResult ) {
+ return -ENOMEM;
+ }
+
+ if ( 0 < faceData->ulFaceCount ) {
+
+ faces = ( camera_face_t * ) malloc(sizeof(camera_face_t)*faceData->ulFaceCount);
+ if ( NULL == faces ) {
+ return -ENOMEM;
+ }
+
+ for ( int i = 0 ; i < faceData->ulFaceCount ; i++)
+ {
+
+ tmp = ( double ) faceData->tFacePosition[i].nLeft / ( double ) previewWidth;
+ tmp *= hRange;
+ tmp -= hRange/2;
+ faces[i].rect[0] = tmp;
+
+ tmp = ( double ) faceData->tFacePosition[i].nTop / ( double )previewHeight;
+ tmp *= vRange;
+ tmp -= vRange/2;
+ faces[i].rect[1] = tmp;
+
+ tmp = ( double ) faceData->tFacePosition[i].nWidth / ( double ) previewWidth;
+ tmp *= hRange;
+ faces[i].rect[2] = faces[i].rect[0] + tmp;
+
+ tmp = ( double ) faceData->tFacePosition[i].nHeight / ( double ) previewHeight;
+ tmp *= vRange;
+ faces[i].rect[3] = faces[i].rect[1] + tmp;
+
+ faces[i].score = faceData->tFacePosition[i].nScore;
+ faces[i].id = 0;
+ faces[i].left_eye[0] = CameraFDResult::INVALID_DATA;
+ faces[i].left_eye[1] = CameraFDResult::INVALID_DATA;
+ faces[i].right_eye[0] = CameraFDResult::INVALID_DATA;
+ faces[i].right_eye[1] = CameraFDResult::INVALID_DATA;
+ faces[i].mouth[0] = CameraFDResult::INVALID_DATA;
+ faces[i].mouth[1] = CameraFDResult::INVALID_DATA;
+ }
+
+ faceResult->number_of_faces = faceData->ulFaceCount;
+ faceResult->faces = faces;
+
+ } else {
+ faceResult->number_of_faces = 0;
+ faceResult->faces = NULL;
+ }
+
+ *pFaces = faceResult;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+};
diff --git a/camera/OMXCameraAdapter/OMXFocus.cpp b/camera/OMXCameraAdapter/OMXFocus.cpp
new file mode 100644
index 0000000..19286ea
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXFocus.cpp
@@ -0,0 +1,673 @@
+/*
+ * 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.
+*
+*/
+
+#undef LOG_TAG
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+#define TOUCH_FOCUS_RANGE 0xFF
+#define AF_CALLBACK_TIMEOUT 10000000 //10 seconds timeout
+
+namespace android {
+
+status_t OMXCameraAdapter::setParametersFocus(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ const char *str = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ str = params.get(CameraParameters::KEY_FOCUS_AREAS);
+ mFocusAreas.clear();
+ if ( NULL != str )
+ {
+ CameraArea::parseFocusArea(str, strlen(str), mFocusAreas);
+ }
+
+ LOG_FUNCTION_NAME;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::doAutoFocus()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
+ size_t top, left, width, height, weight;
+ sp<CameraArea> focusArea = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ returnFocusStatus(false);
+ return NO_INIT;
+ }
+
+ if ( 0 != mDoAFSem.Count() )
+ {
+ CAMHAL_LOGEB("Error mDoAFSem semaphore count %d", mDoAFSem.Count());
+ return NO_INIT;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ if ( !mFocusAreas.isEmpty() )
+ {
+ focusArea = mFocusAreas.itemAt(0);
+ }
+
+ OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
+ focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus;
+
+ //If touch AF is set, then necessary configuration first
+ if ( ( NULL != focusArea.get() ) && ( focusArea->isValid() ) )
+ {
+
+ //Disable face priority first
+ setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
+
+ //Enable region algorithm priority
+ setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
+
+ //Set position
+ OMXCameraPortParameters * mPreviewData = NULL;
+ mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
+ focusArea->transfrom(mPreviewData->mWidth,
+ mPreviewData->mHeight,
+ top,
+ left,
+ width,
+ height);
+ setTouchFocus(left,
+ top,
+ width,
+ height,
+ mPreviewData->mWidth,
+ mPreviewData->mHeight);
+
+ //Do normal focus afterwards
+ focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) OMX_IMAGE_FocusControlExtended;
+
+ }
+ else if ( FOCUS_FACE_PRIORITY == focusControl.eFocusControl )
+ {
+
+ //Disable region priority first
+ setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, false);
+
+ //Enable face algorithm priority
+ setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, true);
+
+ //Do normal focus afterwards
+ focusControl.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 ( ( mParameters3A.Focus != OMX_IMAGE_FocusControlAuto ) &&
+ ( mParameters3A.Focus != OMX_IMAGE_FocusControlAutoInfinity ) )
+ {
+
+ ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_IndexConfigCommonFocusStatus,
+ mDoAFSem);
+
+ if ( NO_ERROR == ret )
+ {
+ ret = setFocusCallback(true);
+ }
+ }
+
+ 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");
+ }
+ }
+
+ if ( ( mParameters3A.Focus != OMX_IMAGE_FocusControlAuto ) &&
+ ( mParameters3A.Focus != OMX_IMAGE_FocusControlAutoInfinity ) )
+ {
+
+ ret = mDoAFSem.WaitTimeout(AF_CALLBACK_TIMEOUT);
+ //Disable auto focus callback from Ducati
+ setFocusCallback(false);
+ //Signal a dummy AF event so that in case the callback from ducati
+ //does come then it doesnt crash after
+ //exiting this function since eventSem will go out of scope.
+ if(ret != NO_ERROR)
+ {
+ CAMHAL_LOGEA("Autofocus callback timeout expired");
+ SignalEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_IndexConfigCommonFocusStatus,
+ NULL );
+ returnFocusStatus(true);
+ }
+ else
+ {
+ CAMHAL_LOGDA("Autofocus callback received");
+ ret = returnFocusStatus(false);
+ }
+
+ }
+ else
+ {
+ if ( NO_ERROR == ret )
+ {
+ ret = returnFocusStatus(true);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::stopAutoFocus()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ return NO_INIT;
+ }
+
+ if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) {
+ // No need to stop focus if we are in infinity mode. Nothing to stop.
+ return NO_ERROR;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ //Disable the callback first
+ ret = setFocusCallback(false);
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ 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);
+ ret = -1;
+ }
+ else
+ {
+ mParameters3A.Focus = OMX_IMAGE_FocusControlOff;
+ CAMHAL_LOGDA("Autofocus stopped successfully");
+ }
+ }
+
+ //Query current focus distance after AF is complete
+ updateFocusDistances(mParameters);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::cancelAutoFocus()
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+
+ LOG_FUNCTION_NAME;
+
+ stopAutoFocus();
+ //Signal a dummy AF event so that in case the callback from ducati
+ //does come then it doesnt crash after
+ //exiting this function since eventSem will go out of scope.
+ ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
+ (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
+ OMX_ALL,
+ OMX_IndexConfigCommonFocusStatus,
+ NULL );
+
+ 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_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ ret = -1;
+ }
+
+ 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;
+ bool focusStatus = false;
+ BaseCameraAdapter::AdapterState state;
+ BaseCameraAdapter::getState(state);
+
+ LOG_FUNCTION_NAME;
+
+ OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
+
+ if( ( AF_ACTIVE & state ) != AF_ACTIVE )
+ {
+ /// We don't send focus callback if 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 = false;
+ }
+ else
+ {
+
+ switch (eFocusStatus.eFocusStatus)
+ {
+ case OMX_FocusStatusReached:
+ {
+ focusStatus = true;
+ break;
+ }
+ case OMX_FocusStatusOff:
+ case OMX_FocusStatusUnableToReach:
+ case OMX_FocusStatusRequest:
+ default:
+ {
+ focusStatus = false;
+ break;
+ }
+ }
+
+ stopAutoFocus();
+ }
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ ret = BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS);
+
+ if ( NO_ERROR == ret )
+ {
+ ret = BaseCameraAdapter::commitState();
+ }
+ else
+ {
+ ret |= BaseCameraAdapter::rollbackState();
+ }
+
+ }
+
+ if ( NO_ERROR == ret )
+ {
+ notifyFocusSubscribers(focusStatus);
+ }
+
+ 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_StateExecuting != mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component not in executing state");
+ ret = -EINVAL;
+ }
+
+ 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(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, 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,
+ 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(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::setTouchFocus(size_t posX,
+ size_t posY,
+ size_t posWidth,
+ size_t posHeight,
+ size_t previewWidth,
+ size_t previewHeight)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXTFOCUSREGIONTYPE touchControl;
+
+ 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 (&touchControl, OMX_CONFIG_EXTFOCUSREGIONTYPE);
+ touchControl.nLeft = ( posX * TOUCH_FOCUS_RANGE ) / previewWidth;
+ touchControl.nTop = ( posY * TOUCH_FOCUS_RANGE ) / previewHeight;
+ touchControl.nWidth = ( posWidth * TOUCH_FOCUS_RANGE ) / previewWidth;
+ touchControl.nHeight = ( posHeight * TOUCH_FOCUS_RANGE ) / previewHeight;
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ ( OMX_INDEXTYPE ) OMX_IndexConfigExtFocusRegion,
+ &touchControl);
+ if ( OMX_ErrorNone != eError )
+ {
+ CAMHAL_LOGEB("Error while configuring touch focus 0x%x", eError);
+ ret = -1;
+ }
+ else
+ {
+ CAMHAL_LOGDB("Touch focus %d,%d %d,%d configured successfuly",
+ ( int ) touchControl.nLeft,
+ ( int ) touchControl.nTop,
+ ( int ) touchControl.nWidth,
+ ( int ) touchControl.nHeight);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+};
diff --git a/camera/OMXCameraAdapter/OMXZoom.cpp b/camera/OMXCameraAdapter/OMXZoom.cpp
new file mode 100644
index 0000000..9e59f3d
--- /dev/null
+++ b/camera/OMXCameraAdapter/OMXZoom.cpp
@@ -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.
+ */
+
+/**
+* @file OMXZoom.cpp
+*
+* This file contains functionality for handling zoom configurations.
+*
+*/
+
+#undef LOG_TAG
+
+#define LOG_TAG "CameraHAL"
+
+#include "CameraHal.h"
+#include "OMXCameraAdapter.h"
+
+namespace android {
+
+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 CameraParameters &params,
+ BaseCameraAdapter::AdapterState state)
+{
+ status_t ret = NO_ERROR;
+ Mutex::Autolock 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(CameraParameters::KEY_ZOOM);
+ if( ( zoom >= 0 ) && ( zoom < ZOOM_STAGES ) )
+ {
+ mTargetZoomIdx = zoom;
+
+ //Immediate zoom should be applied instantly ( CTS requirement )
+ mCurrentZoomIdx = mTargetZoomIdx;
+ doZoom(mCurrentZoomIdx);
+
+ 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;
+ static int prevIndex = 0;
+
+ LOG_FUNCTION_NAME;
+
+ if ( OMX_StateInvalid == mComponentState )
+ {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ ret = -1;
+ }
+
+ if ( ( 0 > index) || ( ( ZOOM_STAGES - 1 ) < index ) )
+ {
+ CAMHAL_LOGEB("Zoom index %d out of range", index);
+ ret = -EINVAL;
+ }
+
+ if ( prevIndex == 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");
+ prevIndex = index;
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::advanceZoom()
+{
+ status_t ret = NO_ERROR;
+ AdapterState state;
+ BaseCameraAdapter::getState(state);
+
+ if ( mReturnZoomStatus )
+ {
+ 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);
+ notifyZoomSubscribers(mCurrentZoomIdx, true);
+
+ if ( NO_ERROR == ret )
+ {
+
+ ret = BaseCameraAdapter::setState(CAMERA_STOP_SMOOTH_ZOOM);
+
+ if ( NO_ERROR == ret )
+ {
+ ret = BaseCameraAdapter::commitState();
+ }
+ else
+ {
+ ret |= BaseCameraAdapter::rollbackState();
+ }
+
+ }
+ }
+ 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();
+ }
+ }
+
+ return ret;
+}
+
+status_t OMXCameraAdapter::startSmoothZoom(int targetIdx)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(mZoomLock);
+
+ CAMHAL_LOGDB("Start smooth zoom target = %d, mCurrentIdx = %d",
+ targetIdx,
+ mCurrentZoomIdx);
+
+ if ( ( targetIdx >= 0 ) && ( targetIdx < ZOOM_STAGES ) )
+ {
+ mTargetZoomIdx = targetIdx;
+ mZoomParameterIdx = mCurrentZoomIdx;
+ }
+ 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;
+ Mutex::Autolock lock(mZoomLock);
+
+ LOG_FUNCTION_NAME;
+
+ if ( mTargetZoomIdx != mCurrentZoomIdx )
+ {
+ mTargetZoomIdx = mCurrentZoomIdx;
+ mReturnZoomStatus = true;
+ CAMHAL_LOGDB("Stop smooth zoom mCurrentZoomIdx = %d, mTargetZoomIdx = %d",
+ mCurrentZoomIdx,
+ mTargetZoomIdx);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+};
diff --git a/camera/SensorListener.cpp b/camera/SensorListener.cpp
new file mode 100644
index 0000000..8b3e942
--- /dev/null
+++ b/camera/SensorListener.cpp
@@ -0,0 +1,232 @@
+/*
+ * 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.
+*
+*/
+
+#define LOG_TAG "CameraHAL"
+
+#include "SensorListener.h"
+#include "CameraHal.h"
+
+#include <stdint.h>
+#include <math.h>
+#include <sys/types.h>
+
+namespace android {
+
+/*** 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 == 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 == 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;
+ SensorManager& mgr(SensorManager::getInstance());
+ Sensor const* const* list;
+ ssize_t count = 0;
+ Sensor const* accelerometer;
+
+ LOG_FUNCTION_NAME;
+
+ count = mgr.getSensorList(&list);
+ CAMHAL_LOGDB("numSensors = %lu", count);
+
+ mSensorEventQueue = mgr.createEventQueue();
+
+ sp<Looper> mLooper = new 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", 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;
+
+ Mutex::Autolock lock(&mLock);
+
+ if (mOrientationCb && (sensorsEnabled & SENSOR_ORIENTATION)) {
+ mOrientationCb(orientation, tilt, mCbCookie);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void SensorListener::enableSensor(sensor_type_t type) {
+ Sensor const* sensor;
+ SensorManager& mgr(SensorManager::getInstance());
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(&mLock);
+
+ if ((type & SENSOR_ORIENTATION) && !(sensorsEnabled & SENSOR_ORIENTATION)) {
+ sensor = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
+ CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string());
+ mSensorEventQueue->enableSensor(sensor);
+ mSensorEventQueue->setEventRate(sensor, ms2ns(100));
+ sensorsEnabled |= SENSOR_ORIENTATION;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void SensorListener::disableSensor(sensor_type_t type) {
+ Sensor const* sensor;
+ SensorManager& mgr(SensorManager::getInstance());
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(&mLock);
+
+ if ((type & SENSOR_ORIENTATION) && (sensorsEnabled & SENSOR_ORIENTATION)) {
+ sensor = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
+ CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string());
+ mSensorEventQueue->disableSensor(sensor);
+ sensorsEnabled &= ~SENSOR_ORIENTATION;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+} // namespace android
diff --git a/camera/TICameraParameters.cpp b/camera/TICameraParameters.cpp
new file mode 100644
index 0000000..2980645
--- /dev/null
+++ b/camera/TICameraParameters.cpp
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+
+
+
+#define LOG_TAG "CameraHAL"
+#include <utils/Log.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <TICameraParameters.h>
+#include "CameraHal.h"
+
+namespace android {
+
+//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::VIDEO_MODE[] = "video-mode";
+
+// 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_VSTAB[] = "vstab";
+const char TICameraParameters::KEY_VSTAB_VALUES[] = "vstab-values";
+const char TICameraParameters::KEY_VNF[] = "vnf";
+const char TICameraParameters::KEY_SATURATION[] = "saturation";
+const char TICameraParameters::KEY_BRIGHTNESS[] = "brightness";
+const char TICameraParameters::KEY_EXPOSURE_MODE[] = "exposure";
+const char TICameraParameters::KEY_SUPPORTED_EXPOSURE[] = "exposure-mode-values";
+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_MAN_EXPOSURE[] = "manual-exposure";
+const char TICameraParameters::KEY_METERING_MODE[] = "meter-mode";
+const char TICameraParameters::KEY_PADDED_WIDTH[] = "padded-width";
+const char TICameraParameters::KEY_PADDED_HEIGHT[] = "padded-height";
+const char TICameraParameters::KEY_EXP_BRACKETING_RANGE[] = "exp-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_S3D_SUPPORTED[] = "s3d-supported";
+const char TICameraParameters::KEY_MEASUREMENT_ENABLE[] = "measurement";
+const char TICameraParameters::KEY_GBCE[] = "gbce";
+const char TICameraParameters::KEY_GLBCE[] = "glbce";
+const char TICameraParameters::KEY_CURRENT_ISO[] = "current-iso";
+const char TICameraParameters::KEY_SENSOR_ORIENTATION[] = "sensor-orientation";
+const char TICameraParameters::KEY_SENSOR_ORIENTATION_VALUES[] = "sensor-orientation-values";
+const char TICameraParameters::KEY_MINFRAMERATE[] = "min-framerate";
+const char TICameraParameters::KEY_MAXFRAMERATE[] = "max-framerate";
+
+//TI extensions for enabling/disabling GLBCE
+const char TICameraParameters::GLBCE_ENABLE[] = "enable";
+const char TICameraParameters::GLBCE_DISABLE[] = "disable";
+
+//TI extensions for enabling/disabling GBCE
+const char TICameraParameters::GBCE_ENABLE[] = "enable";
+const char TICameraParameters::GBCE_DISABLE[] = "disable";
+
+//TI extensions for enabling/disabling measurement
+const char TICameraParameters::MEASUREMENT_ENABLE[] = "enable";
+const char TICameraParameters::MEASUREMENT_DISABLE[] = "disable";
+
+//TI extensions for zoom
+const char TICameraParameters::ZOOM_SUPPORTED[] = "true";
+const char TICameraParameters::ZOOM_UNSUPPORTED[] = "false";
+
+// TI extensions for 2D Preview in Stereo Mode
+const char TICameraParameters::KEY_S3D2D_PREVIEW[] = "s3d2d-preview";
+const char TICameraParameters::KEY_S3D2D_PREVIEW_MODE[] = "s3d2d-preview-values";
+
+//TI extensions for SAC/SMC
+const char TICameraParameters::KEY_AUTOCONVERGENCE[] = "auto-convergence";
+const char TICameraParameters::KEY_AUTOCONVERGENCE_MODE[] = "auto-convergence-mode";
+const char TICameraParameters::KEY_MANUALCONVERGENCE_VALUES[] = "manual-convergence-values";
+
+//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 enabling/disabling shutter sound
+const char TICameraParameters::SHUTTER_ENABLE[] = "true";
+const char TICameraParameters::SHUTTER_DISABLE[] = "false";
+
+//TI extensions for Temporal Bracketing
+const char TICameraParameters::BRACKET_ENABLE[] = "enable";
+const char TICameraParameters::BRACKET_DISABLE[] = "disable";
+
+//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_RAW[] = "raw";
+const char TICameraParameters::PIXEL_FORMAT_JPS[] = "jps";
+const char TICameraParameters::PIXEL_FORMAT_MPO[] = "mpo";
+const char TICameraParameters::PIXEL_FORMAT_RAW_JPEG[] = "raw+jpeg";
+const char TICameraParameters::PIXEL_FORMAT_RAW_MPO[] = "raw+mpo";
+
+// TI extensions to standard android scene mode settings
+const char TICameraParameters::SCENE_MODE_SPORT[] = "sport";
+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";
+
+// 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_OFF[] = "off";
+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 to add auto convergence values
+const char TICameraParameters::AUTOCONVERGENCE_MODE_DISABLE[] = "mode-disable";
+const char TICameraParameters::AUTOCONVERGENCE_MODE_FRAME[] = "mode-frame";
+const char TICameraParameters::AUTOCONVERGENCE_MODE_CENTER[] = "mode-center";
+const char TICameraParameters::AUTOCONVERGENCE_MODE_FFT[] = "mode-fft";
+const char TICameraParameters::AUTOCONVERGENCE_MODE_MANUAL[] = "mode-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";
+};
+
diff --git a/camera/V4LCameraAdapter/V4LCameraAdapter.cpp b/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
new file mode 100644
index 0000000..446a809
--- /dev/null
+++ b/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
@@ -0,0 +1,615 @@
+/*
+ * 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 <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>
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+static int mDebugFps = 0;
+
+#define Q16_OFFSET 16
+
+#define HERE(Msg) {CAMHAL_LOGEB("--===line %d, %s===--\n", __LINE__, Msg);}
+
+namespace android {
+
+#undef LOG_TAG
+///Maintain a separate tag for V4LCameraAdapter logs to isolate issues OMX specific
+#define LOG_TAG "CameraHAL"
+
+//frames skipped before recalculating the framerate
+#define FPS_PERIOD 30
+
+static V4LCameraAdapter *gCameraAdapter = NULL;
+Mutex gAdapterLock;
+const char *device = DEVICE;
+
+
+/*--------------------Camera Adapter Class STARTS here-----------------------------*/
+
+status_t V4LCameraAdapter::initialize(CameraProperties::Properties* caps, int sensor_index)
+{
+ LOG_FUNCTION_NAME;
+
+ char value[PROPERTY_VALUE_MAX];
+ 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)
+ {
+ return NO_MEMORY;
+ }
+
+ if ((mCameraHandle = open(device, O_RDWR)) == -1)
+ {
+ CAMHAL_LOGEB("Error while opening handle to V4L2 Camera: %s", strerror(errno));
+ return -EINVAL;
+ }
+
+ ret = ioctl (mCameraHandle, VIDIOC_QUERYCAP, &mVideoInfo->cap);
+ if (ret < 0)
+ {
+ CAMHAL_LOGEA("Error when querying the capabilities of the V4L Camera");
+ return -EINVAL;
+ }
+
+ if ((mVideoInfo->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0)
+ {
+ CAMHAL_LOGEA("Error while adapter initialization: video capture not supported.");
+ return -EINVAL;
+ }
+
+ if (!(mVideoInfo->cap.capabilities & V4L2_CAP_STREAMING))
+ {
+ CAMHAL_LOGEA("Error while adapter initialization: Capture device does not support streaming i/o");
+ return -EINVAL;
+ }
+
+ // Initialize flags
+ mPreviewing = false;
+ mVideoInfo->isStreaming = false;
+ mRecording = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::fillThisBuffer(void* frameBuf, CameraFrame::FrameType frameType)
+{
+
+ status_t ret = NO_ERROR;
+
+ if ( !mVideoInfo->isStreaming )
+ {
+ return NO_ERROR;
+ }
+
+ int i = mPreviewBufs.valueFor(( unsigned int )frameBuf);
+ if(i<0)
+ {
+ return BAD_VALUE;
+ }
+
+ mVideoInfo->buf.index = i;
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("Init: VIDIOC_QBUF Failed");
+ return -1;
+ }
+
+ nQueued++;
+
+ return ret;
+
+}
+
+status_t V4LCameraAdapter::setParameters(const CameraParameters &params)
+{
+ LOG_FUNCTION_NAME;
+
+ status_t ret = NO_ERROR;
+
+ int width, height;
+
+ params.getPreviewSize(&width, &height);
+
+ CAMHAL_LOGDB("Width * Height %d x %d format 0x%x", width, height, DEFAULT_PIXEL_FORMAT);
+
+ mVideoInfo->width = width;
+ mVideoInfo->height = height;
+ mVideoInfo->framesizeIn = (width * height << 1);
+ mVideoInfo->formatIn = DEFAULT_PIXEL_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 = DEFAULT_PIXEL_FORMAT;
+
+ ret = ioctl(mCameraHandle, VIDIOC_S_FMT, &mVideoInfo->format);
+ if (ret < 0) {
+ CAMHAL_LOGEB("Open: VIDIOC_S_FMT Failed: %s", strerror(errno));
+ return ret;
+ }
+
+ // Udpate the current parameter set
+ mParams = params;
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+}
+
+
+void V4LCameraAdapter::getParameters(CameraParameters& params)
+{
+ LOG_FUNCTION_NAME;
+
+ // Return the current parameter set
+ params = mParams;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+///API to give the buffers to Adapter
+status_t V4LCameraAdapter::useBuffers(CameraMode mode, void* bufArr, int num, size_t length, unsigned int queueable)
+{
+ status_t ret = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ Mutex::Autolock lock(mLock);
+
+ switch(mode)
+ {
+ case CAMERA_PREVIEW:
+ ret = UseBuffersPreview(bufArr, num);
+ break;
+
+ //@todo Insert Image capture case here
+
+ case CAMERA_VIDEO:
+ //@warn Video capture is not fully supported yet
+ ret = UseBuffersPreview(bufArr, num);
+ break;
+
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::UseBuffersPreview(void* bufArr, int num)
+{
+ int ret = NO_ERROR;
+
+ if(NULL == bufArr)
+ {
+ return BAD_VALUE;
+ }
+
+ //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 = num;
+
+ ret = ioctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
+ if (ret < 0) {
+ CAMHAL_LOGEB("VIDIOC_REQBUFS failed: %s", strerror(errno));
+ return ret;
+ }
+
+ for (int i = 0; i < num; 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 = ioctl (mCameraHandle, VIDIOC_QUERYBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ CAMHAL_LOGEB("Unable to query buffer (%s)", strerror(errno));
+ return ret;
+ }
+
+ mVideoInfo->mem[i] = mmap (0,
+ mVideoInfo->buf.length,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ mCameraHandle,
+ mVideoInfo->buf.m.offset);
+
+ if (mVideoInfo->mem[i] == MAP_FAILED) {
+ CAMHAL_LOGEB("Unable to map buffer (%s)", strerror(errno));
+ return -1;
+ }
+
+ uint32_t *ptr = (uint32_t*) bufArr;
+
+ //Associate each Camera internal buffer with the one from Overlay
+ mPreviewBufs.add((int)ptr[i], i);
+
+ }
+
+ // Update the preview buffer count
+ mPreviewBufferCount = num;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::startPreview()
+{
+ status_t ret = NO_ERROR;
+
+ Mutex::Autolock lock(mPreviewBufsLock);
+
+ if(mPreviewing)
+ {
+ return BAD_VALUE;
+ }
+
+ for (int i = 0; i < mPreviewBufferCount; i++) {
+
+ mVideoInfo->buf.index = i;
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("VIDIOC_QBUF Failed");
+ return -EINVAL;
+ }
+
+ nQueued++;
+ }
+
+ enum v4l2_buf_type bufType;
+ if (!mVideoInfo->isStreaming) {
+ bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl (mCameraHandle, VIDIOC_STREAMON, &bufType);
+ if (ret < 0) {
+ CAMHAL_LOGEB("StartStreaming: Unable to start capture: %s", strerror(errno));
+ return ret;
+ }
+
+ mVideoInfo->isStreaming = true;
+ }
+
+ // Create and start preview thread for receiving buffers from V4L Camera
+ mPreviewThread = new PreviewThread(this);
+
+ CAMHAL_LOGDA("Created preview thread");
+
+
+ //Update the flag to indicate we are previewing
+ mPreviewing = true;
+
+ return ret;
+
+}
+
+status_t V4LCameraAdapter::stopPreview()
+{
+ enum v4l2_buf_type bufType;
+ int ret = NO_ERROR;
+
+ Mutex::Autolock lock(mPreviewBufsLock);
+
+ if(!mPreviewing)
+ {
+ return NO_INIT;
+ }
+
+ if (mVideoInfo->isStreaming) {
+ bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType);
+ if (ret < 0) {
+ CAMHAL_LOGEB("StopStreaming: Unable to stop capture: %s", strerror(errno));
+ return ret;
+ }
+
+ mVideoInfo->isStreaming = false;
+ }
+
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+
+ nQueued = 0;
+ nDequeued = 0;
+
+ /* Unmap buffers */
+ for (int i = 0; i < mPreviewBufferCount; i++)
+ if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0)
+ CAMHAL_LOGEA("Unmap failed");
+
+ mPreviewBufs.clear();
+
+ mPreviewThread->requestExitAndWait();
+ mPreviewThread.clear();
+
+ return ret;
+
+}
+
+char * V4LCameraAdapter::GetFrame(int &index)
+{
+ int ret;
+
+ mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
+
+ /* DQ */
+ ret = ioctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf);
+ if (ret < 0) {
+ CAMHAL_LOGEA("GetFrame: VIDIOC_DQBUF Failed");
+ return NULL;
+ }
+ nDequeued++;
+
+ index = mVideoInfo->buf.index;
+
+ return (char *)mVideoInfo->mem[mVideoInfo->buf.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;
+
+ // Just return the current preview size, nothing more to do here.
+ mParams.getPreviewSize(( int * ) &width,
+ ( int * ) &height);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
+status_t V4LCameraAdapter::getFrameDataSize(size_t &dataFrameSize, size_t bufferCount)
+{
+ // We don't support meta data, so simply return
+ return NO_ERROR;
+}
+
+status_t V4LCameraAdapter::getPictureBufferSize(size_t &length, size_t bufferCount)
+{
+ // We don't support image capture yet, safely return from here without messing up
+ return NO_ERROR;
+}
+
+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;
+ LOGD("Camera %d Frames, %f FPS", mFrameCount, mFps);
+ }
+ // XXX: mFPS has the value we want
+}
+
+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;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+V4LCameraAdapter::V4LCameraAdapter()
+{
+ LOG_FUNCTION_NAME;
+
+ // Nothing useful to do in the constructor
+
+ 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;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/* Preview Thread */
+// ---------------------------------------------------------------------------
+
+int V4LCameraAdapter::previewThread()
+{
+ status_t ret = NO_ERROR;
+ int width, height;
+ CameraFrame frame;
+
+ if (mPreviewing)
+ {
+ int index = 0;
+ char *fp = this->GetFrame(index);
+ if(!fp)
+ {
+ return BAD_VALUE;
+ }
+
+ uint8_t* ptr = (uint8_t*) mPreviewBufs.keyAt(index);
+
+ int width, height;
+ uint16_t* dest = (uint16_t*)ptr;
+ uint16_t* src = (uint16_t*) fp;
+ mParams.getPreviewSize(&width, &height);
+ for(int i=0;i<height;i++)
+ {
+ for(int j=0;j<width;j++)
+ {
+ //*dest = *src;
+ //convert from YUYV to UYVY supported in Camera service
+ *dest = (((*src & 0xFF000000)>>24)<<16)|(((*src & 0x00FF0000)>>16)<<24) |
+ (((*src & 0xFF00)>>8)<<0)|(((*src & 0x00FF)>>0)<<8);
+ src++;
+ dest++;
+ }
+ dest += 4096/2-width;
+ }
+
+ mParams.getPreviewSize(&width, &height);
+ frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
+ frame.mBuffer = ptr;
+ frame.mLength = width*height*2;
+ frame.mAlignment = width*2;
+ frame.mOffset = 0;
+ frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);;
+
+ ret = sendFrameToSubscribers(&frame);
+
+ }
+
+ return ret;
+}
+
+extern "C" CameraAdapter* CameraAdapter_Factory()
+{
+ Mutex::Autolock lock(gAdapterLock);
+
+ LOG_FUNCTION_NAME;
+
+ if ( NULL == gCameraAdapter )
+ {
+ CAMHAL_LOGDA("Creating new Camera adapter instance");
+ gCameraAdapter= new V4LCameraAdapter();
+ }
+ else
+ {
+ CAMHAL_LOGDA("Reusing existing Camera adapter instance");
+ }
+
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return gCameraAdapter;
+}
+
+extern "C" int CameraAdapter_Capabilities(CameraProperties::Properties* properties_array,
+ const unsigned int starting_camera,
+ const unsigned int max_camera) {
+ int num_cameras_supported = 0;
+ CameraProperties::Properties* properties = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ if(!properties_array)
+ {
+ return -EINVAL;
+ }
+
+ // TODO: Need to tell camera properties what other cameras we can support
+ if (starting_camera + num_cameras_supported < max_camera) {
+ num_cameras_supported++;
+ properties = properties_array + starting_camera;
+ properties->set(CameraProperties::CAMERA_NAME, "USBCamera");
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return num_cameras_supported;
+}
+
+};
+
+
+/*--------------------Camera Adapter Class ENDS here-----------------------------*/
+
diff --git a/camera/inc/ANativeWindowDisplayAdapter.h b/camera/inc/ANativeWindowDisplayAdapter.h
new file mode 100644
index 0000000..89c2cf1
--- /dev/null
+++ b/camera/inc/ANativeWindowDisplayAdapter.h
@@ -0,0 +1,188 @@
+/*
+ * 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/egl/android_natives.h>
+#include <ui/GraphicBufferMapper.h>
+#include <hal_public.h>
+
+//temporarily define format here
+#define HAL_PIXEL_FORMAT_NV12 0x100
+
+namespace android {
+
+/**
+ * Display handler class - This class basically handles the buffer posting to display
+ */
+
+class ANativeWindowDisplayAdapter : public DisplayAdapter
+{
+public:
+
+ typedef struct
+ {
+ void *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, S3DParameters *s3dParams = NULL);
+ virtual int disableDisplay();
+ 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 int useBuffers(void* bufArr, int num);
+ virtual bool supportsExternalBuffering();
+
+ //Implementation of inherited interfaces
+ virtual void* allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs);
+ virtual uint32_t * getOffsets() ;
+ virtual int getFd() ;
+ virtual int freeBuffer(void* buf);
+
+ virtual int maxQueueableBuffers(unsigned int& queueable);
+
+ ///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();
+
+public:
+
+ static const int DISPLAY_TIMEOUT;
+ static const int FAILED_DQS_TO_SUSPEND;
+
+ class DisplayThread : public Thread
+ {
+ ANativeWindowDisplayAdapter* mDisplayAdapter;
+ TIUTILS::MessageQueue mDisplayThreadQ;
+
+ public:
+ DisplayThread(ANativeWindowDisplayAdapter* da)
+ : Thread(false), mDisplayAdapter(da) { }
+
+ ///Returns a reference to the display message Q for display adapter to post messages
+ TIUTILS::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;
+ sp<DisplayThread> mDisplayThread;
+ FrameProvider *mFrameProvider; ///Pointer to the frame provider interface
+ TIUTILS::MessageQueue mDisplayQ;
+ unsigned int mDisplayState;
+ ///@todo Have a common class for these members
+ mutable Mutex mLock;
+ bool mDisplayEnabled;
+ int mBufferCount;
+ buffer_handle_t** mBufferHandleMap;
+ IMG_native_handle_t** mGrallocHandleMap;
+ uint32_t* mOffsetsMap;
+ int mFD;
+ KeyedVector<int, int> mFramesWithCameraAdapterMap;
+ sp<ErrorNotifier> mErrorNotifier;
+
+ uint32_t mFrameWidth;
+ uint32_t mFrameHeight;
+ uint32_t mPreviewWidth;
+ uint32_t mPreviewHeight;
+
+ uint32_t mXOff;
+ uint32_t mYOff;
+
+ const char *mPixelFormat;
+
+#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
+
+};
+
+};
+
diff --git a/camera/inc/BaseCameraAdapter.h b/camera/inc/BaseCameraAdapter.h
new file mode 100644
index 0000000..15fb73f
--- /dev/null
+++ b/camera/inc/BaseCameraAdapter.h
@@ -0,0 +1,245 @@
+/*
+ * 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 android {
+
+class BaseCameraAdapter : public CameraAdapter
+{
+
+public:
+
+ BaseCameraAdapter();
+ virtual ~BaseCameraAdapter();
+
+ ///Initialzes the camera adapter creates any resources required
+ virtual status_t initialize(CameraProperties::Properties*, int sensor_index = 0) = 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(void * frameBuf, CameraFrame::FrameType frameType);
+
+ //APIs to configure Camera adapter and get the current parameter set
+ virtual status_t setParameters(const CameraParameters& params) = 0;
+ virtual void getParameters(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 );
+
+ 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();
+
+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, void* 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(void* 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(size_t &length, 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();
+
+ // Receive orientation events from CameraHal
+ virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt);
+
+ // ---------------------Interface ends-----------------------------------
+
+ status_t notifyFocusSubscribers(bool status);
+ status_t notifyShutterSubscribers();
+ status_t notifyZoomSubscribers(int zoomIdx, bool targetReached);
+ status_t notifyFaceSubscribers(sp<CameraFDResult> &faces);
+
+ //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 setFrameRefCount(void* frameBuf, CameraFrame::FrameType frameType, int refCount);
+ int getFrameRefCount(void* frameBuf, CameraFrame::FrameType frameType);
+
+ 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 Mutex mReturnFrameLock;
+
+ //Lock protecting the Adapter state
+ mutable Mutex mLock;
+ AdapterState mAdapterState;
+ AdapterState mNextState;
+
+ //Different frame subscribers get stored using these
+ KeyedVector<int, frame_callback> mFrameSubscribers;
+ KeyedVector<int, frame_callback> mFrameDataSubscribers;
+ KeyedVector<int, frame_callback> mVideoSubscribers;
+ KeyedVector<int, frame_callback> mImageSubscribers;
+ KeyedVector<int, frame_callback> mRawSubscribers;
+ KeyedVector<int, event_callback> mFocusSubscribers;
+ KeyedVector<int, event_callback> mZoomSubscribers;
+ KeyedVector<int, event_callback> mShutterSubscribers;
+ KeyedVector<int, event_callback> mFaceSubscribers;
+
+ //Preview buffer management data
+ int *mPreviewBuffers;
+ int mPreviewBufferCount;
+ size_t mPreviewBuffersLength;
+ KeyedVector<int, int> mPreviewBuffersAvailable;
+ mutable Mutex mPreviewBufferLock;
+
+ //Video buffer management data
+ int *mVideoBuffers;
+ KeyedVector<int, int> mVideoBuffersAvailable;
+ int mVideoBuffersCount;
+ size_t mVideoBuffersLength;
+ mutable Mutex mVideoBufferLock;
+
+ //Image buffer management data
+ int *mCaptureBuffers;
+ KeyedVector<int, bool> mCaptureBuffersAvailable;
+ int mCaptureBuffersCount;
+ size_t mCaptureBuffersLength;
+ mutable Mutex mCaptureBufferLock;
+
+ //Metadata buffermanagement
+ int *mPreviewDataBuffers;
+ KeyedVector<int, bool> mPreviewDataBuffersAvailable;
+ int mPreviewDataBuffersCount;
+ size_t mPreviewDataBuffersLength;
+ mutable Mutex mPreviewDataBufferLock;
+
+ TIUTILS::MessageQueue mFrameQ;
+ TIUTILS::MessageQueue mAdapterQ;
+ mutable Mutex mSubscriberLock;
+ ErrorNotifier *mErrorNotifier;
+ release_image_buffers_callback mReleaseImageBuffersCallback;
+ end_image_capture_callback mEndImageCaptureCallback;
+ void *mReleaseData;
+ void *mEndCaptureData;
+ bool mRecording;
+};
+
+};
+
+#endif //BASE_CAMERA_ADAPTER_H
+
+
diff --git a/camera/inc/CameraHal.h b/camera/inc/CameraHal.h
new file mode 100644
index 0000000..94ed67d
--- /dev/null
+++ b/camera/inc/CameraHal.h
@@ -0,0 +1,1144 @@
+/*
+ * 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 <utils/Log.h>
+#include <utils/threads.h>
+#include <linux/videodev2.h>
+#include "binder/MemoryBase.h"
+#include "binder/MemoryHeapBase.h"
+#include <utils/threads.h>
+#include <camera/CameraParameters.h>
+#include <hardware/camera.h>
+#include "MessageQueue.h"
+#include "Semaphore.h"
+#include "CameraProperties.h"
+#include "DebugUtils.h"
+#include "SensorListener.h"
+
+#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
+
+//Enables Absolute PPM measurements in logcat
+#define PPM_INSTRUMENTATION_ABS 1
+
+//Uncomment to enable more verbose/debug logs
+//#define DEBUG_LOG
+
+///Camera HAL Logging Functions
+#ifndef DEBUG_LOG
+
+#define CAMHAL_LOGDA(str)
+#define CAMHAL_LOGDB(str, ...)
+#define CAMHAL_LOGVA(str)
+#define CAMHAL_LOGVB(str, ...)
+
+#define CAMHAL_LOGEA LOGE
+#define CAMHAL_LOGEB LOGE
+
+#undef LOG_FUNCTION_NAME
+#undef LOG_FUNCTION_NAME_EXIT
+#define LOG_FUNCTION_NAME
+#define LOG_FUNCTION_NAME_EXIT
+
+#else
+
+#define CAMHAL_LOGDA DBGUTILS_LOGDA
+#define CAMHAL_LOGDB DBGUTILS_LOGDB
+#define CAMHAL_LOGVA DBGUTILS_LOGVA
+#define CAMHAL_LOGVB DBGUTILS_LOGVB
+
+#define CAMHAL_LOGEA DBGUTILS_LOGEA
+#define CAMHAL_LOGEB DBGUTILS_LOGEB
+
+#endif
+
+
+
+#define NONNEG_ASSIGN(x,y) \
+ if(x > -1) \
+ y = x
+
+namespace android {
+
+#define PARAM_BUFFER 6000
+
+///Forward declarations
+class CameraHal;
+class CameraFrame;
+class CameraHalEvent;
+class DisplayFrame;
+
+class CameraArea : public 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) );
+ }
+
+ size_t getWeight()
+ {
+ return mWeight;
+ }
+
+ static status_t parseFocusArea(const char *area,
+ size_t areaLength,
+ Vector< sp<CameraArea> > &areas);
+
+private:
+
+ static const ssize_t TOP = -1000;
+ static const ssize_t LEFT = -1000;
+ static const ssize_t BOTTOM = 1000;
+ static const ssize_t RIGHT = 1000;
+
+ ssize_t mTop;
+ ssize_t mLeft;
+ ssize_t mBottom;
+ ssize_t mRight;
+ size_t mWeight;
+};
+
+class CameraFDResult : public RefBase
+{
+public:
+
+ CameraFDResult() : mFaceData(NULL) {};
+ CameraFDResult(camera_frame_metadata_t *faces) : mFaceData(faces) {};
+
+ virtual ~CameraFDResult() {
+ if ( ( NULL != mFaceData ) && ( NULL != mFaceData->faces ) ) {
+ free(mFaceData->faces);
+ free(mFaceData);
+ }
+ }
+
+ camera_frame_metadata_t *getFaceResult() { return mFaceData; };
+
+ 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 *mFaceData;
+};
+
+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,
+ ALL_FRAMES = 0xFFFF ///Maximum of 16 frame types supported
+ };
+
+ //default contrustor
+ CameraFrame():
+ mCookie(NULL),
+ mBuffer(NULL),
+ mFrameType(0),
+ mTimestamp(0),
+ mWidth(0),
+ mHeight(0),
+ mOffset(0),
+ mAlignment(0),
+ mFd(0),
+ mLength(0) {}
+
+ //copy constructor
+ CameraFrame(const CameraFrame &frame) :
+ mCookie(frame.mCookie),
+ mBuffer(frame.mBuffer),
+ mFrameType(frame.mFrameType),
+ mTimestamp(frame.mTimestamp),
+ mWidth(frame.mWidth),
+ mHeight(frame.mHeight),
+ mOffset(frame.mOffset),
+ mAlignment(frame.mAlignment),
+ mFd(frame.mFd),
+ mLength(frame.mLength) {}
+
+ void *mCookie;
+ void *mBuffer;
+ int mFrameType;
+ nsecs_t mTimestamp;
+ unsigned int mWidth, mHeight;
+ uint32_t mOffset;
+ unsigned int mAlignment;
+ int mFd;
+ size_t mLength;
+ ///@todo add other member vars like stride etc
+};
+
+///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_FACE = 0x10,
+ ///@remarks Future enum related to display, like frame displayed event, could be added here
+ ALL_EVENTS = 0xFFFF ///Maximum of 16 event types supported
+ };
+
+ ///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 {
+ bool focusLocked;
+ bool focusError;
+ 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 sp<CameraFDResult> FaceEventData;
+
+ class CameraHalEventData : public RefBase{
+
+ public:
+
+ CameraHalEvent::FocusEventData focusEvent;
+ CameraHalEvent::ZoomEventData zoomEvent;
+ CameraHalEvent::ShutterEventData shutterEvent;
+ CameraHalEvent::FaceEventData faceEvent;
+ };
+
+ //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;
+ 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 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(void* frameBuf, CameraFrame::FrameType frameType) = 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(void *frameBuf, CameraFrame::FrameType frameType);
+};
+
+/** 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 void* allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs) = 0;
+
+ //additional methods used for memory mapping
+ virtual uint32_t * getOffsets() = 0;
+ virtual int getFd() = 0;
+
+ virtual int freeBuffer(void* buf) = 0;
+
+ virtual ~BufferProvider() {}
+};
+
+/**
+ * Class for handling data and notify callbacks to application
+ */
+class AppCallbackNotifier: public ErrorNotifier , public virtual 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(CameraParameters &params, void *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
+ void notificationThread();
+
+ ///Notification callback functions
+ static void frameCallbackRelay(CameraFrame* caFrame);
+ static void eventCallbackRelay(CameraHalEvent* chEvt);
+ void frameCallback(CameraFrame* caFrame);
+ void eventCallback(CameraHalEvent* chEvt);
+
+ 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(void *buffers, uint32_t *offsets, int fd, size_t length, size_t count);
+ status_t releaseRecordingFrame(const void *opaque);
+
+ status_t useMetaDataBufferMode(bool enable);
+
+ //Internal class definitions
+ class NotificationThread : public Thread {
+ AppCallbackNotifier* mAppCallbackNotifier;
+ TIUTILS::MessageQueue mNotificationThreadQ;
+ public:
+ enum NotificationThreadCommands
+ {
+ NOTIFIER_START,
+ NOTIFIER_STOP,
+ NOTIFIER_EXIT,
+ };
+ public:
+ NotificationThread(AppCallbackNotifier* nh)
+ : Thread(false), mAppCallbackNotifier(nh) { }
+ virtual bool threadLoop() {
+ mAppCallbackNotifier->notificationThread();
+ return false;
+ }
+
+ TIUTILS::MessageQueue &msgQ() { return mNotificationThreadQ;}
+ };
+
+ //Friend declarations
+ friend class NotificationThread;
+
+private:
+ void notifyEvent();
+ void notifyFrame();
+ bool processMessage();
+ void releaseSharedVideoBuffers();
+
+private:
+ mutable Mutex mLock;
+ mutable 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
+ KeyedVector<unsigned int, unsigned int> mVideoHeaps;
+ KeyedVector<unsigned int, unsigned int> mVideoBuffers;
+ KeyedVector<unsigned int, unsigned int> mVideoMap;
+
+ //Keeps list of Gralloc handles and associated Video Metadata Buffers
+ KeyedVector<uint32_t, uint32_t> mVideoMetadataBufferMemoryMap;
+ KeyedVector<uint32_t, uint32_t> mVideoMetadataBufferReverseMap;
+
+ bool mBufferReleased;
+
+ sp< NotificationThread> mNotificationThread;
+ EventProvider *mEventProvider;
+ FrameProvider *mFrameProvider;
+ TIUTILS::MessageQueue mEventQ;
+ TIUTILS::MessageQueue mFrameQ;
+ NotifierState mNotifierState;
+
+ bool mPreviewing;
+ camera_memory_t* mPreviewMemory;
+ unsigned char* mPreviewBufs[MAX_BUFFERS];
+ int mPreviewBufCount;
+ const char *mPreviewPixelFormat;
+ KeyedVector<unsigned int, sp<MemoryHeapBase> > mSharedPreviewHeaps;
+ KeyedVector<unsigned int, sp<MemoryBase> > mSharedPreviewBuffers;
+
+ //Burst mode active
+ bool mBurst;
+ mutable Mutex mRecordingLock;
+ bool mRecording;
+ bool mMeasurementEnabled;
+
+ bool mUseMetaDataBufferMode;
+
+};
+
+
+/**
+ * Class used for allocating memory for JPEG bit stream buffers, output buffers of camera in no overlay case
+ */
+class MemoryManager : public BufferProvider, public virtual RefBase
+{
+public:
+ ///Initializes the display adapter creates any resources required
+ status_t initialize(){ return NO_ERROR; }
+
+ int setErrorHandler(ErrorNotifier *errorNotifier);
+ virtual void* allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs);
+ virtual uint32_t * getOffsets();
+ virtual int getFd() ;
+ virtual int freeBuffer(void* buf);
+
+private:
+
+ sp<ErrorNotifier> mErrorNotifier;
+};
+
+
+
+
+/**
+ * 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 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,
+ };
+public:
+ typedef struct
+ {
+ void *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,
+ };
+
+ enum CameraMode
+ {
+ CAMERA_PREVIEW,
+ CAMERA_IMAGE_CAPTURE,
+ CAMERA_VIDEO,
+ CAMERA_MEASUREMENT
+ };
+
+ 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_ZOOM_STATE = VIDEO_ACTIVE | ZOOM_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,
+ };
+
+public:
+
+ ///Initialzes the camera adapter creates any resources required
+ virtual int initialize(CameraProperties::Properties*, int sensor_index=0) = 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(void* frameBuf, CameraFrame::FrameType frameType) = 0;
+
+ //APIs to configure Camera adapter and get the current parameter set
+ virtual int setParameters(const CameraParameters& params) = 0;
+ virtual void getParameters(CameraParameters& params) = 0;
+
+ //API to flush the buffers from Camera
+ status_t flushBuffers()
+ {
+ return sendCommand(CameraAdapter::CAMERA_PREVIEW_FLUSH_BUFFERS);
+ }
+
+ //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) = 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;
+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;
+
+ // 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;
+};
+
+class DisplayAdapter : public BufferProvider, public virtual RefBase
+{
+public:
+ typedef struct S3DParameters_t
+ {
+ int mode;
+ int framePacking;
+ int order;
+ int subSampling;
+ } S3DParameters;
+
+ ///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, S3DParameters *s3dParams = NULL) = 0;
+ virtual int disableDisplay() = 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 int useBuffers(void *bufArr, int num) = 0;
+ virtual bool supportsExternalBuffering() = 0;
+
+ // Get max queueable buffers display supports
+ // This function should only be called after
+ // allocateBuffer
+ virtual int maxQueueableBuffers(unsigned int& queueable) = 0;
+};
+
+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:
+ ///Constants
+ static const int NO_BUFFERS_PREVIEW;
+ static const int NO_BUFFERS_IMAGE_CAPTURE;
+ static const uint32_t VFR_SCALE = 1000;
+
+
+ /*--------------------Interface Methods---------------------------------*/
+
+ //@{
+public:
+
+ /** 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();
+
+ /**
+ * Only used if overlays are used for camera preview.
+ */
+ int setPreviewWindow(struct preview_stream_ops *window);
+
+ /**
+ * 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);
+
+ /**
+ * Set the camera parameters specific to Video Recording.
+ */
+ status_t setVideoModeParameters();
+
+ /**
+ * 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();
+
+ /**
+ * 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 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;
+
+
+ status_t storeMetaDataInBuffers(bool enable);
+
+ //@}
+
+/*--------------------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);
+
+/*--------------------Internal Member functions - Private---------------------------------*/
+private:
+
+ /** @name internalFunctionsPrivate */
+ //@{
+
+ 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(int width, int height, const char* previewFormat);
+
+ /** Allocate image capture buffers */
+ status_t allocImageBufs(unsigned int width, unsigned int height, size_t length, const char* previewFormat, unsigned int bufferCount);
+
+ /** Free preview buffers */
+ status_t freePreviewBufs();
+
+ /** Free video bufs */
+ status_t freeVideoBufs();
+
+ //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 parameter is supported by the current camera
+ // instance
+ bool isParameterValid(const char *param, const char *supportedParams);
+ bool isParameterValid(int param, const char *supportedParams);
+
+ /** Initialize default parameters */
+ void initDefaultParameters();
+
+ void dumpProperties(CameraProperties::Properties& cameraProps);
+
+ status_t startImageBracketing();
+
+ status_t stopImageBracketing();
+
+ void setShutter(bool enable);
+
+ void forceStopPreview();
+
+ //@}
+
+
+/*----------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;
+ sp<AppCallbackNotifier> mAppCallbackNotifier;
+ sp<DisplayAdapter> mDisplayAdapter;
+ sp<MemoryManager> mMemoryManager;
+
+ sp<IMemoryHeap> mPictureHeap;
+
+ int* mGrallocHandles;
+
+
+
+///static member vars
+
+#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:
+ //keeps paused state of display
+ bool mDisplayPaused;
+ //Index of current camera adapter
+ int mCameraIndex;
+
+ mutable Mutex mLock;
+
+ sp<SensorListener> mSensorListener;
+
+ void* mCameraAdapterHandle;
+
+ CameraParameters mParameters;
+ bool mPreviewRunning;
+ bool mPreviewStateOld;
+ bool mRecordingEnabled;
+ EventProvider *mEventProvider;
+
+ int32_t *mPreviewDataBufs;
+ uint32_t *mPreviewDataOffsets;
+ int mPreviewDataFd;
+ int mPreviewDataLength;
+ int32_t *mImageBufs;
+ uint32_t *mImageOffsets;
+ int mImageFd;
+ int mImageLength;
+ int32_t *mPreviewBufs;
+ uint32_t *mPreviewOffsets;
+ int mPreviewLength;
+ int mPreviewFd;
+ int32_t *mVideoBufs;
+ uint32_t *mVideoOffsets;
+ int mVideoFd;
+ int mVideoLength;
+
+ int32_t mLastPreviewFramerate;
+
+ int mBracketRangePositive;
+ int mBracketRangeNegative;
+
+ ///@todo Rename this as preview buffer provider
+ BufferProvider *mBufProvider;
+ BufferProvider *mVideoBufProvider;
+
+
+ CameraProperties::Properties* mCameraProperties;
+
+ bool mPreviewStartInProgress;
+
+ bool mSetPreviewWindowCalled;
+
+ uint32_t mPreviewWidth;
+ uint32_t mPreviewHeight;
+ int32_t mMaxZoomSupported;
+};
+
+
+}; // namespace android
+
+#endif
diff --git a/camera/inc/CameraProperties.h b/camera/inc/CameraProperties.h
new file mode 100644
index 0000000..83d1b10
--- /dev/null
+++ b/camera/inc/CameraProperties.h
@@ -0,0 +1,180 @@
+/*
+ * 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>
+
+namespace android {
+
+#define MAX_CAMERAS_SUPPORTED 2
+#define MAX_PROP_NAME_LENGTH 50
+#define MAX_PROP_VALUE_LENGTH 2048
+
+#define EXIF_MAKE_DEFAULT "default_make"
+#define EXIF_MODEL_DEFAULT "default_model"
+
+// 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 ORIENTATION_INDEX[];
+ static const char FACING_INDEX[];
+ static const char S3D_SUPPORTED[];
+ static const char SUPPORTED_PREVIEW_SIZES[];
+ static const char SUPPORTED_PREVIEW_FORMATS[];
+ static const char SUPPORTED_PREVIEW_FRAME_RATES[];
+ static const char SUPPORTED_PICTURE_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_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 AUTOCONVERGENCE[];
+ static const char AUTOCONVERGENCE_MODE[];
+ static const char MANUALCONVERGENCE_VALUES[];
+ 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 PARAMS_DELIMITER [];
+
+ static const char S3D2D_PREVIEW[];
+ static const char S3D2D_PREVIEW_MODES[];
+ static const char VSTAB[];
+ static const char VSTAB_VALUES[];
+ static const char FRAMERATE_RANGE[];
+ static const char FRAMERATE_RANGE_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[];
+
+ CameraProperties();
+ ~CameraProperties();
+
+ // container class passed around for accessing properties
+ class Properties
+ {
+ public:
+ Properties()
+ {
+ mProperties = new DefaultKeyedVector<String8, String8>(String8(DEFAULT_VALUE));
+ // set properties that are same for all cameras
+ set(EXIF_MAKE, EXIF_MAKE_DEFAULT);
+ set(EXIF_MODEL, EXIF_MODEL_DEFAULT);
+ }
+ ~Properties()
+ {
+ delete mProperties;
+ }
+ ssize_t set(const char *prop, const char *value);
+ ssize_t set(const char *prop, int value);
+ const char* get(const char * prop);
+ void dump();
+
+ protected:
+ const char* keyAt(unsigned int);
+ const char* valueAt(unsigned int);
+
+ private:
+ DefaultKeyedVector<String8, String8>* mProperties;
+
+ };
+
+ ///Initializes the CameraProperties class
+ status_t initialize();
+ status_t loadProperties();
+ int camerasSupported();
+ int getProperties(int cameraIndex, Properties** properties);
+
+private:
+
+ uint32_t mCamerasSupported;
+ int mInitialized;
+
+ Properties mCameraProps[MAX_CAMERAS_SUPPORTED];
+
+};
+
+};
+
+#endif //CAMERA_PROPERTIES_H
+
diff --git a/camera/inc/General3A_Settings.h b/camera/inc/General3A_Settings.h
new file mode 100644
index 0000000..af33518
--- /dev/null
+++ b/camera/inc/General3A_Settings.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.
+ */
+
+/**
+* @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
+
+#define FOCUS_FACE_PRIORITY OMX_IMAGE_FocusControlMax -1
+#define FOCUS_REGION_PRIORITY OMX_IMAGE_FocusControlMax -2
+#define WB_FACE_PRIORITY OMX_WhiteBalControlMax -1
+#define EXPOSURE_FACE_PRIORITY OMX_ExposureControlMax - 1
+
+namespace android {
+
+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 [] = {
+ { CameraParameters::EFFECT_NONE, OMX_ImageFilterNone },
+ { CameraParameters::EFFECT_NEGATIVE, OMX_ImageFilterNegative },
+ { CameraParameters::EFFECT_SOLARIZE, OMX_ImageFilterSolarize },
+ { CameraParameters::EFFECT_SEPIA, OMX_ImageFilterSepia },
+ { CameraParameters::EFFECT_MONO, OMX_ImageFilterGrayScale },
+ { TICameraParameters::EFFECT_NATURAL, OMX_ImageFilterNatural },
+ { TICameraParameters::EFFECT_VIVID, OMX_ImageFilterVivid },
+ { TICameraParameters::EFFECT_COLOR_SWAP, OMX_ImageFilterColourSwap },
+ { CameraParameters::EFFECT_BLACKBOARD, OMX_TI_ImageFilterBlackBoard },
+ { CameraParameters::EFFECT_WHITEBOARD, OMX_TI_ImageFilterWhiteBoard },
+ { CameraParameters::EFFECT_AQUA, OMX_TI_ImageFilterAqua },
+ { CameraParameters::EFFECT_POSTERIZE, OMX_TI_ImageFilterPosterize },
+ { TICameraParameters::EFFECT_BLACKWHITE, OMX_TI_ImageFilterBlackWhite }
+};
+
+const userToOMX_LUT scene_UserToOMX [] = {
+ { CameraParameters::SCENE_MODE_AUTO, OMX_Manual },
+ { TICameraParameters::SCENE_MODE_CLOSEUP, OMX_Closeup },
+ { CameraParameters::SCENE_MODE_LANDSCAPE, OMX_Landscape },
+ { TICameraParameters::SCENE_MODE_AQUA, OMX_Underwater },
+ { TICameraParameters::SCENE_MODE_SPORT, OMX_Sport },
+ { TICameraParameters::SCENE_MODE_MOOD, OMX_Mood },
+ { CameraParameters::SCENE_MODE_NIGHT_PORTRAIT, OMX_NightPortrait },
+ { TICameraParameters::SCENE_MODE_NIGHT_INDOOR, OMX_NightIndoor },
+ { CameraParameters::SCENE_MODE_FIREWORKS, OMX_Fireworks },
+ { 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 },
+ { CameraParameters::SCENE_MODE_ACTION, OMX_TI_Action },
+ { CameraParameters::SCENE_MODE_BEACH, OMX_TI_Beach },
+ { CameraParameters::SCENE_MODE_CANDLELIGHT, OMX_TI_Candlelight },
+ { CameraParameters::SCENE_MODE_NIGHT, OMX_TI_Night },
+ { CameraParameters::SCENE_MODE_PARTY, OMX_TI_Party },
+ { CameraParameters::SCENE_MODE_PORTRAIT, OMX_TI_Portrait },
+ { CameraParameters::SCENE_MODE_SNOW, OMX_TI_Snow },
+ { CameraParameters::SCENE_MODE_STEADYPHOTO, OMX_TI_Steadyphoto },
+ { CameraParameters::SCENE_MODE_SUNSET, OMX_TI_Sunset },
+ { CameraParameters::SCENE_MODE_THEATRE, OMX_TI_Theatre }
+};
+
+const userToOMX_LUT whiteBal_UserToOMX [] = {
+ { CameraParameters::WHITE_BALANCE_AUTO, OMX_WhiteBalControlAuto },
+ { CameraParameters::WHITE_BALANCE_DAYLIGHT, OMX_WhiteBalControlSunLight },
+ { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, OMX_WhiteBalControlCloudy },
+ { TICameraParameters::WHITE_BALANCE_TUNGSTEN, OMX_WhiteBalControlTungsten },
+ { CameraParameters::WHITE_BALANCE_FLUORESCENT, OMX_WhiteBalControlFluorescent },
+ { CameraParameters::WHITE_BALANCE_INCANDESCENT, OMX_WhiteBalControlIncandescent },
+ { TICameraParameters::WHITE_BALANCE_HORIZON, OMX_WhiteBalControlHorizon },
+ { CameraParameters::WHITE_BALANCE_SHADE, OMX_TI_WhiteBalControlShade },
+ { CameraParameters::WHITE_BALANCE_TWILIGHT, OMX_TI_WhiteBalControlTwilight },
+ { CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT, OMX_TI_WhiteBalControlWarmFluorescent },
+ { TICameraParameters::WHITE_BALANCE_FACE, WB_FACE_PRIORITY },
+ { TICameraParameters::WHITE_BALANCE_SUNSET, OMX_TI_WhiteBalControlSunset }
+};
+
+const userToOMX_LUT antibanding_UserToOMX [] = {
+ { CameraParameters::ANTIBANDING_OFF, OMX_FlickerCancelOff },
+ { CameraParameters::ANTIBANDING_AUTO, OMX_FlickerCancelAuto },
+ { CameraParameters::ANTIBANDING_50HZ, OMX_FlickerCancel50 },
+ { CameraParameters::ANTIBANDING_60HZ, OMX_FlickerCancel60 }
+};
+
+const userToOMX_LUT focus_UserToOMX [] = {
+ { CameraParameters::FOCUS_MODE_AUTO, OMX_IMAGE_FocusControlAutoLock },
+ { CameraParameters::FOCUS_MODE_INFINITY, OMX_IMAGE_FocusControlAutoInfinity },
+ { CameraParameters::FOCUS_MODE_MACRO, OMX_IMAGE_FocusControlAutoMacro },
+ { TICameraParameters::FOCUS_MODE_PORTRAIT, OMX_IMAGE_FocusControlPortrait },
+ { TICameraParameters::FOCUS_MODE_EXTENDED, OMX_IMAGE_FocusControlExtended },
+ { CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO, OMX_IMAGE_FocusControlAuto },
+ { TICameraParameters::FOCUS_MODE_FACE , FOCUS_FACE_PRIORITY },
+
+};
+
+const userToOMX_LUT exposure_UserToOMX [] = {
+ { TICameraParameters::EXPOSURE_MODE_OFF, 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 },
+ { TICameraParameters::EXPOSURE_MODE_FACE, EXPOSURE_FACE_PRIORITY },
+};
+
+const userToOMX_LUT flash_UserToOMX [] = {
+ { CameraParameters::FLASH_MODE_OFF ,OMX_IMAGE_FlashControlOff },
+ { CameraParameters::FLASH_MODE_ON ,OMX_IMAGE_FlashControlOn },
+ { CameraParameters::FLASH_MODE_AUTO ,OMX_IMAGE_FlashControlAuto },
+ { CameraParameters::FLASH_MODE_TORCH ,OMX_IMAGE_FlashControlTorch },
+ { CameraParameters::FLASH_MODE_RED_EYE ,OMX_IMAGE_FlashControlRedEyeReduction },
+ { TICameraParameters::FLASH_MODE_FILL_IN ,OMX_IMAGE_FlashControlFillin }
+};
+
+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;
+
+ unsigned int Brightness;
+ OMX_BOOL ExposureLock;
+ OMX_BOOL WhiteBalanceLock;
+};
+
+/*
+* 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,
+
+ E3aSettingMax,
+ E3AsettingsAll = ( ((E3aSettingMax -1 ) << 1) -1 ) /// all possible flags raised
+};
+
+};
+
+#endif //GENERAL_3A_SETTINGS_H
diff --git a/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
new file mode 100644
index 0000000..2a41ba0
--- /dev/null
+++ b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
@@ -0,0 +1,834 @@
+/*
+ * 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 "BaseCameraAdapter.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 android {
+
+#define Q16_OFFSET 16
+
+#define OMX_CMD_TIMEOUT 3000000 //3 sec.
+#define AF_CALLBACK_TIMEOUT 10000000 //10 seconds timeout
+#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 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 ZOOM_STAGES 61
+
+#define FACE_DETECTION_BUFFER_SIZE 0x1000
+
+#define EXIF_MODEL_SIZE 100
+#define EXIF_MAKE_SIZE 100
+#define EXIF_DATE_TIME_SIZE 20
+
+#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; \
+ } \
+}
+
+///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 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;
+typedef CapS32 CapEVComp;
+
+/**
+ * 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;
+
+ //EXIF ASCII prefix
+ static const char EXIFASCIIPrefix[];
+
+ enum OMXCameraEvents
+ {
+ CAMERA_PORT_ENABLE = 0x1,
+ CAMERA_PORT_FLUSH = 0x2,
+ CAMERA_PORT_DISABLE = 0x4,
+ };
+
+ enum CaptureMode
+ {
+ HIGH_SPEED = 1,
+ HIGH_QUALITY = 2,
+ VIDEO_MODE = 3,
+ HIGH_QUALITY_ZSL = 4,
+ };
+
+ enum IPPMode
+ {
+ IPP_NONE = 0,
+ IPP_NSF,
+ IPP_LDC,
+ IPP_LDCNSF,
+ };
+
+ enum CodingMode
+ {
+ CodingNone = 0,
+ CodingJPS,
+ CodingMPO,
+ CodingRAWJPEG,
+ CodingRAWMPO,
+ };
+
+ 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,
+ };
+
+ class GPSData
+ {
+ public:
+ int mLongDeg, mLongMin, mLongSec;
+ char mLongRef[GPS_REF_SIZE];
+ bool mLongValid;
+ int mLatDeg, mLatMin, mLatSec;
+ 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;
+ bool mMakeValid;
+ bool mModelValid;
+ };
+
+ ///Parameters specific to any port of the OMX Camera component
+ class OMXCameraPortParameters
+ {
+ public:
+ OMX_U32 mHostBufaddr[MAX_NO_BUFFERS];
+ OMX_BUFFERHEADERTYPE *mBufferHeader[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_S32 mMinFrameRate;
+ OMX_S32 mMaxFrameRate;
+ CameraFrame::FrameType mImageType;
+ };
+
+ ///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;
+ OMXCameraPortParameters mCameraPortParams[MAX_NO_PORTS];
+ };
+
+public:
+
+ OMXCameraAdapter();
+ ~OMXCameraAdapter();
+
+ ///Initialzes the camera adapter creates any resources required
+ virtual status_t initialize(CameraProperties::Properties*, int sensor_index=0);
+
+ //APIs to configure Camera adapter and get the current parameter set
+ virtual status_t setParameters(const CameraParameters& params);
+ virtual void getParameters(CameraParameters& params);
+
+ // API
+ virtual status_t UseBuffersPreview(void* bufArr, int num);
+
+ //API to flush the buffers for preview
+ status_t flushBuffers();
+
+ // API
+ virtual status_t setFormat(OMX_U32 port, OMXCameraPortParameters &cap);
+
+ // Function to get and populate caps from handle
+ static status_t getCaps(CameraProperties::Properties* props, OMX_HANDLETYPE handle);
+ static const char* getLUTvalue_OMXtoHAL(int OMXValue, LUTtype LUT);
+ 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);
+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, void* bufArr, int num, size_t length, unsigned int queueable);
+ virtual status_t fillThisBuffer(void* frameBuf, CameraFrame::FrameType frameType);
+ virtual status_t getFrameSize(size_t &width, size_t &height);
+ virtual status_t getPictureBufferSize(size_t &length, size_t bufferCount);
+ virtual status_t getFrameDataSize(size_t &dataFrameSize, size_t bufferCount);
+ virtual status_t startFaceDetection();
+ virtual status_t stopFaceDetection();
+ virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt);
+
+private:
+
+ status_t switchToLoaded();
+
+ 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);
+
+ 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 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);
+
+ //EXIF
+ status_t setParametersEXIF(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t convertGPSCoord(double coord, int *deg, int *min, int *sec);
+ status_t setupEXIF();
+
+ //Focus functionality
+ status_t doAutoFocus();
+ status_t stopAutoFocus();
+ status_t checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus);
+ status_t returnFocusStatus(bool timeoutReached);
+
+ //Focus distances
+ status_t setParametersFocus(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t addFocusDistances(OMX_U32 &near,
+ OMX_U32 &optimal,
+ OMX_U32 &far,
+ 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 CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t doZoom(int index);
+ status_t advanceZoom();
+
+ //3A related parameters
+ status_t setParameters3A(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t setScene(Gen3A_settings& Gen3A);
+
+ //Flash modes
+ status_t setFlashMode(Gen3A_settings& Gen3A);
+ status_t setFocusMode(Gen3A_settings& Gen3A);
+
+ //Exposure Modes
+ status_t setExposureMode(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 setExposureLock(Gen3A_settings& Gen3A);
+ status_t setWhiteBalanceLock(Gen3A_settings& Gen3A);
+ status_t release3ALock();
+
+ //API to set FrameRate using VFR interface
+ status_t setVFramerate(OMX_U32 minFrameRate,OMX_U32 maxFrameRate);
+
+ status_t setParametersAlgo(const 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(size_t posX,
+ size_t posY,
+ size_t posWidth,
+ size_t posHeight,
+ size_t previewWidth,
+ size_t previewHeight);
+
+ //Face detection
+ status_t setParametersFD(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+ status_t updateFocusDistances(CameraParameters &params);
+ status_t setFaceDetection(bool enable, OMX_U32 orientation);
+ status_t detectFaces(OMX_BUFFERHEADERTYPE* pBuffHeader,
+ sp<CameraFDResult> &result,
+ size_t previewWidth,
+ size_t previewHeight);
+ status_t encodeFaceCoordinates(const OMX_FACEDETECTIONTYPE *faceData,
+ camera_frame_metadata_t **pFaces,
+ size_t previewWidth,
+ size_t previewHeight);
+
+ //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 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 status_t encodeFramerateCap(OMX_U32, OMX_U32, const CapFramerate*, size_t, char*, size_t);
+ static status_t encodeVFramerateCap(OMX_TI_CAPTYPE&, char*, char*, size_t);
+ static status_t encodePixelformatCap(OMX_COLOR_FORMATTYPE,
+ const CapPixelformat*,
+ 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 insertVFramerates(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 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&);
+
+ status_t setParametersCapture(const CameraParameters &params,
+ BaseCameraAdapter::AdapterState state);
+
+ //Exposure Bracketing
+ status_t setExposureBracketing(int *evValues, size_t evCount, size_t frameCount);
+ status_t parseExpRange(const char *rangeStr, int * expRange, size_t count, size_t &validEntries);
+
+ //Temporal Bracketing
+ status_t doBracketing(OMX_BUFFERHEADERTYPE *pBuffHeader, CameraFrame::FrameType typeOfFrame);
+ status_t sendBracketFrames();
+
+ // Image Capture Service
+ status_t startImageCapture();
+
+ //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(void* bufArr, int num);
+ status_t UseBuffersPreviewData(void* bufArr, int num);
+
+ //Used for calculation of the average frame rate during preview
+ status_t recalculateFPS();
+
+ //Helper method for initializing a CameFrame object
+ status_t initCameraFrame(CameraFrame &frame, OMX_IN OMX_BUFFERHEADERTYPE *pBuffHeader, int typeOfFrame, OMXCameraPortParameters *port);
+
+ //Sends the incoming OMX buffer header to subscribers
+ status_t sendFrame(CameraFrame &frame);
+
+ status_t apply3Asettings( Gen3A_settings& Gen3A );
+
+ // AutoConvergence
+ status_t setAutoConvergence(OMX_TI_AUTOCONVERGENCEMODETYPE pACMode, OMX_S32 pManualConverence);
+ status_t getAutoConvergence(OMX_TI_AUTOCONVERGENCEMODETYPE *pACMode, OMX_S32 *pManualConverence);
+
+ class CommandHandler : public Thread {
+ public:
+ CommandHandler(OMXCameraAdapter* ca)
+ : Thread(false), mCameraAdapter(ca) { }
+
+ virtual bool threadLoop() {
+ bool ret;
+ ret = Handler();
+ return ret;
+ }
+
+ status_t put(TIUTILS::Message* msg){
+ return mCommandMsgQ.put(msg);
+ }
+
+ enum {
+ COMMAND_EXIT = -1,
+ CAMERA_START_IMAGE_CAPTURE = 0,
+ CAMERA_PERFORM_AUTOFOCUS
+ };
+
+ private:
+ bool Handler();
+ TIUTILS::MessageQueue mCommandMsgQ;
+ OMXCameraAdapter* mCameraAdapter;
+ };
+ sp<CommandHandler> mCommandHandler;
+
+public:
+
+ class OMXCallbackHandler : public Thread {
+ public:
+ OMXCallbackHandler(OMXCameraAdapter* ca)
+ : Thread(false), mCameraAdapter(ca) { }
+
+ virtual bool threadLoop() {
+ bool ret;
+ ret = Handler();
+ return ret;
+ }
+
+ status_t put(TIUTILS::Message* msg){
+ return mCommandMsgQ.put(msg);
+ }
+
+ enum {
+ COMMAND_EXIT = -1,
+ CAMERA_FILL_BUFFER_DONE,
+ };
+
+ private:
+ bool Handler();
+ TIUTILS::MessageQueue mCommandMsgQ;
+ OMXCameraAdapter* mCameraAdapter;
+ };
+
+ sp<OMXCallbackHandler> mOMXCallbackHandler;
+
+private:
+
+ //AF callback
+ status_t setFocusCallback(bool enabled);
+
+ //OMX Capabilities data
+ static const CapResolution mImageCapRes [];
+ static const CapResolution mPreviewRes [];
+ static const CapResolution mThumbRes [];
+ static const CapPixelformat mPixelformats [];
+ static const CapFramerate mFramerates [];
+ static const CapU32 mSensorNames[] ;
+ static const CapZoom mZoomStages [];
+ static const CapEVComp mEVCompRanges [];
+ static const CapISO mISOStages [];
+
+ // 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[];
+ static const char DEFAULT_FRAMERATE_RANGE[];
+ 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_PICTURE_SIZE[];
+ static const char DEFAULT_PREVIEW_FORMAT[];
+ static const char DEFAULT_FRAMERATE[];
+ static const char DEFAULT_PREVIEW_SIZE[];
+ static const char DEFAULT_NUM_PREV_BUFS[];
+ static const char DEFAULT_NUM_PIC_BUFS[];
+ static const char DEFAULT_MAX_FOCUS_AREAS[];
+ 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_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_MAX_NUM_METERING_AREAS[];
+ static const char DEFAULT_LOCK_SUPPORTED[];
+ static const char DEFAULT_LOCK_UNSUPPORTED[];
+
+ 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
+ Vector< sp<CameraArea> > mFocusAreas;
+
+ CaptureMode mCapMode;
+ size_t mBurstFrames;
+ size_t mCapturedFrames;
+
+ bool mMeasurementEnabled;
+
+ //Exposure Bracketing
+ int mExposureBracketingValues[EXP_BRACKET_RANGE];
+ size_t mExposureBracketingValidEntries;
+
+ mutable Mutex mFaceDetectionLock;
+ //Face detection status
+ bool mFaceDetectionRunning;
+
+ //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
+ Mutex mZoomLock;
+ unsigned int mCurrentZoomIdx, mTargetZoomIdx;
+ int mZoomInc;
+ bool mReturnZoomStatus;
+ static const int32_t ZOOM_STEPS [];
+
+ //local copy
+ OMX_VERSIONTYPE mLocalVersionParam;
+
+ unsigned int mPending3Asettings;
+ Gen3A_settings mParameters3A;
+
+ CameraParameters mParams;
+ CameraProperties::Properties* mCapabilities;
+ unsigned int mPictureRotation;
+ bool mWaitingForSnapshot;
+ int mSnapshotCount;
+ bool mCaptureConfigured;
+
+ //Temporal bracketing management data
+ mutable Mutex mBracketingLock;
+ bool *mBracketingBuffersQueued;
+ int mBracketingBuffersQueuedCount;
+ int mLastBracetingBufferIdx;
+ bool mBracketingEnabled;
+ int mBracketingRange;
+
+ CameraParameters mParameters;
+ OMXCameraAdapterComponentContext mCameraAdapterParameters;
+ bool mFirstTimeInit;
+
+ ///Semaphores used internally
+ Semaphore mDoAFSem;
+ Semaphore mInitSem;
+ Semaphore mFlushSem;
+ Semaphore mUsePreviewDataSem;
+ Semaphore mUsePreviewSem;
+ Semaphore mUseCaptureSem;
+ Semaphore mStartPreviewSem;
+ Semaphore mStopPreviewSem;
+ Semaphore mStartCaptureSem;
+ Semaphore mStopCaptureSem;
+ Semaphore mSwitchToLoadedSem;
+
+ Vector<struct TIUTILS::Message *> mEventSignalQ;
+ Mutex mEventLock;
+
+ OMX_STATETYPE mComponentState;
+
+ bool mVnfEnabled;
+ bool mVstabEnabled;
+
+ int mSensorOrientation;
+ int mDeviceOrientation;
+ 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;
+
+ int mSensorIndex;
+ CodingMode mCodingMode;
+
+ // Time source delta of ducati & system time
+ OMX_TICKS mTimeSourceDelta;
+ bool onlyOnce;
+
+ Semaphore mCaptureSem;
+ bool mCaptureSignalled;
+
+};
+}; //// namespace
+#endif //OMX_CAMERA_ADAPTER_H
+
diff --git a/camera/inc/SensorListener.h b/camera/inc/SensorListener.h
new file mode 100644
index 0000000..913eb95
--- /dev/null
+++ b/camera/inc/SensorListener.h
@@ -0,0 +1,101 @@
+/*
+ * 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>
+
+namespace android {
+
+/**
+ * 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 Thread {
+ public:
+ SensorLooperThread(Looper* looper)
+ : Thread(false) {
+ mLooper = sp<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:
+ sp<Looper> mLooper;
+};
+
+
+class SensorListener : public 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:
+ sp<SensorEventQueue> mSensorEventQueue;
+/* private - member variables */
+private:
+ int sensorsEnabled;
+ orientation_callback_t mOrientationCb;
+ void *mCbCookie;
+ sp<Looper> mLooper;
+ sp<SensorLooperThread> mSensorLooperThread;
+ Mutex mLock;
+};
+
+}
+
+#endif
diff --git a/camera/inc/TICameraParameters.h b/camera/inc/TICameraParameters.h
new file mode 100644
index 0000000..1886d0c
--- /dev/null
+++ b/camera/inc/TICameraParameters.h
@@ -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.
+ */
+
+
+
+
+#ifndef TI_CAMERA_PARAMETERS_H
+#define TI_CAMERA_PARAMETERS_H
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+///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_S3D_SUPPORTED[];
+static const char KEY_BURST[];
+static const char KEY_CAP_MODE[];
+static const char KEY_VSTAB[];
+static const char KEY_VSTAB_VALUES[];
+static const char KEY_VNF[];
+static const char KEY_SATURATION[];
+static const char KEY_BRIGHTNESS[];
+static const char KEY_EXPOSURE_MODE[];
+static const char KEY_SUPPORTED_EXPOSURE[];
+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_MAN_EXPOSURE[];
+static const char KEY_METERING_MODE[];
+static const char KEY_PADDED_WIDTH[];
+static const char KEY_PADDED_HEIGHT[];
+static const char KEY_EXP_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_SHUTTER_ENABLE[];
+static const char KEY_MEASUREMENT_ENABLE[];
+static const char KEY_INITIAL_VALUES[];
+static const char KEY_GBCE[];
+static const char KEY_GLBCE[];
+static const char KEY_MINFRAMERATE[];
+static const char KEY_MAXFRAMERATE[];
+
+static const char KEY_CURRENT_ISO[];
+
+static const char KEY_SENSOR_ORIENTATION[];
+static const char KEY_SENSOR_ORIENTATION_VALUES[];
+
+//TI extensions for zoom
+static const char ZOOM_SUPPORTED[];
+static const char ZOOM_UNSUPPORTED[];
+
+//TI extensions for camera capabilies
+static const char INITIAL_VALUES_TRUE[];
+static const char INITIAL_VALUES_FALSE[];
+
+//TI extensions for enabling/disabling measurements
+static const char MEASUREMENT_ENABLE[];
+static const char MEASUREMENT_DISABLE[];
+
+// TI extensions to add values for ManualConvergence and AutoConvergence mode
+static const char KEY_AUTOCONVERGENCE[];
+static const char KEY_AUTOCONVERGENCE_MODE[];
+static const char KEY_MANUALCONVERGENCE_VALUES[];
+
+//TI extensions for enabling/disabling GLBCE
+static const char GLBCE_ENABLE[];
+static const char GLBCE_DISABLE[];
+
+//TI extensions for enabling/disabling GBCE
+static const char GBCE_ENABLE[];
+static const char GBCE_DISABLE[];
+
+// 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 Manual Gain and Manual Exposure
+static const char KEY_MANUAL_EXPOSURE_LEFT[];
+static const char KEY_MANUAL_EXPOSURE_RIGHT[];
+static const char KEY_MANUAL_EXPOSURE_MODES[];
+static const char KEY_MANUAL_GAIN_EV_RIGHT[];
+static const char KEY_MANUAL_GAIN_EV_LEFT[];
+static const char KEY_MANUAL_GAIN_ISO_RIGHT[];
+static const char KEY_MANUAL_GAIN_ISO_LEFT[];
+static const char KEY_MANUAL_GAIN_MODES[];
+
+//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 enabling/disabling shutter sound
+static const char SHUTTER_ENABLE[];
+static const char SHUTTER_DISABLE[];
+
+//TI extensions for Temporal bracketing
+static const char BRACKET_ENABLE[];
+static const char BRACKET_DISABLE[];
+
+//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 VIDEO_MODE[];
+
+
+// TI extensions to standard android pixel formats
+static const char PIXEL_FORMAT_RAW[];
+static const char PIXEL_FORMAT_JPS[];
+static const char PIXEL_FORMAT_MPO[];
+static const char PIXEL_FORMAT_RAW_JPEG[];
+static const char PIXEL_FORMAT_RAW_MPO[];
+
+// TI extensions to standard android scene mode settings
+static const char SCENE_MODE_SPORT[];
+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_OFF[];
+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[];
+
+// 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[];
+
+static const char KEY_S3D2D_PREVIEW[];
+static const char KEY_S3D2D_PREVIEW_MODE[];
+
+// 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_FFT[];
+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[];
+
+};
+
+};
+
+#endif
+
diff --git a/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h b/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h
new file mode 100644
index 0000000..b9d3952
--- /dev/null
+++ b/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h
@@ -0,0 +1,158 @@
+/*
+ * 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 "CameraHal.h"
+#include "BaseCameraAdapter.h"
+#include "DebugUtils.h"
+
+namespace android {
+
+#define DEFAULT_PIXEL_FORMAT V4L2_PIX_FMT_YUYV
+#define NB_BUFFER 10
+#define DEVICE "/dev/video4"
+
+
+struct VideoInfo {
+ struct v4l2_capability cap;
+ struct v4l2_format format;
+ struct v4l2_buffer buf;
+ struct v4l2_requestbuffers rb;
+ void *mem[NB_BUFFER];
+ bool isStreaming;
+ int width;
+ int height;
+ int formatIn;
+ int framesizeIn;
+};
+
+
+/**
+ * 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();
+ ~V4LCameraAdapter();
+
+
+ ///Initialzes the camera adapter creates any resources required
+ virtual status_t initialize(CameraProperties::Properties*, int sensor_index=0);
+
+ //APIs to configure Camera adapter and get the current parameter set
+ virtual status_t setParameters(const CameraParameters& params);
+ virtual void getParameters(CameraParameters& params);
+
+ // API
+ virtual status_t UseBuffersPreview(void* bufArr, int num);
+
+ //API to flush the buffers for preview
+ status_t flushBuffers();
+
+protected:
+
+//----------Parent class method implementation------------------------------------
+ virtual status_t startPreview();
+ virtual status_t stopPreview();
+ virtual status_t useBuffers(CameraMode mode, void* bufArr, int num, size_t length, unsigned int queueable);
+ virtual status_t fillThisBuffer(void* frameBuf, CameraFrame::FrameType frameType);
+ virtual status_t getFrameSize(size_t &width, size_t &height);
+ virtual status_t getPictureBufferSize(size_t &length, 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 Thread {
+ V4LCameraAdapter* mAdapter;
+ public:
+ PreviewThread(V4LCameraAdapter* hw) :
+ Thread(false), mAdapter(hw) { }
+ virtual void onFirstRef() {
+ run("CameraPreviewThread", 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 previewThread();
+
+public:
+
+private:
+ int mPreviewBufferCount;
+ KeyedVector<int, int> mPreviewBufs;
+ mutable Mutex mPreviewBufsLock;
+
+ CameraParameters mParams;
+
+ bool mPreviewing;
+ bool mCapturing;
+ 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
+ sp<PreviewThread> mPreviewThread;
+
+ struct VideoInfo *mVideoInfo;
+ int mCameraHandle;
+
+
+ int nQueued;
+ int nDequeued;
+
+};
+}; //// namespace
+#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
diff --git a/heaptracked-executable.mk b/heaptracked-executable.mk
new file mode 100644
index 0000000..f09f7cf
--- /dev/null
+++ b/heaptracked-executable.mk
@@ -0,0 +1,7 @@
+LOCAL_SRC_FILES += $(OMAP4_DEBUG_SRC)
+LOCAL_SHARED_LIBRARIES += $(OMAP4_DEBUG_SHARED_LIBRARIES)
+LOCAL_STATIC_LIBRARIES:= libheaptracker
+LOCAL_CFLAGS += $(OMAP4_DEBUG_CFLAGS)
+LOCAL_LDFLAGS += $(OMAP4_DEBUG_LDFLAGS)
+
+include $(BUILD_EXECUTABLE)
diff --git a/heaptracked-shared-library.mk b/heaptracked-shared-library.mk
new file mode 100644
index 0000000..7fddc10
--- /dev/null
+++ b/heaptracked-shared-library.mk
@@ -0,0 +1,7 @@
+LOCAL_SRC_FILES += $(OMAP4_DEBUG_SRC)
+LOCAL_SHARED_LIBRARIES += $(OMAP4_DEBUG_SHARED_LIBRARIES)
+LOCAL_WHOLE_STATIC_LIBRARIES:= libheaptracker
+LOCAL_CFLAGS += $(OMAP4_DEBUG_CFLAGS)
+LOCAL_LDFLAGS += $(OMAP4_DEBUG_LDFLAGS)
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/heaptracker.c b/heaptracker.c
new file mode 100644
index 0000000..6f2dcfe
--- /dev/null
+++ b/heaptracker.c
@@ -0,0 +1,576 @@
+/*
+**
+** Copyright (C) 2008-2011, 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 <android/log.h>
+#include <pthread.h>
+#include <time.h>
+#include <stdarg.h>
+
+#include "mapinfo.h"
+
+extern int heaptracker_stacktrace(intptr_t*, size_t);
+extern void *__real_malloc(size_t size);
+extern void *__real_realloc(void *ptr, size_t size);
+extern void *__real_calloc(int nmemb, int size);
+extern void __real_free(void *ptr);
+
+static mapinfo *milist;
+
+#define MAX_BACKTRACE_DEPTH 15
+#define ALLOCATION_TAG 0x1ee7d00d
+#define BACKLOG_TAG 0xbabecafe
+#define FREE_POISON 0xa5
+#define BACKLOG_MAX 50
+#define FRONT_GUARD 0xaa
+#define FRONT_GUARD_LEN (1<<4)
+#define REAR_GUARD 0xbb
+#define REAR_GUARD_LEN (1<<4)
+#define SCANNER_SLEEP_S 3
+
+struct hdr {
+ uint32_t tag;
+ struct hdr *prev;
+ struct hdr *next;
+ intptr_t bt[MAX_BACKTRACE_DEPTH];
+ int bt_depth;
+ intptr_t freed_bt[MAX_BACKTRACE_DEPTH];
+ int freed_bt_depth;
+ size_t size;
+ char front_guard[FRONT_GUARD_LEN];
+} __attribute__((packed));
+
+struct ftr {
+ char rear_guard[REAR_GUARD_LEN];
+} __attribute__((packed));
+
+static inline struct ftr * to_ftr(struct hdr *hdr)
+{
+ return (struct ftr *)(((char *)(hdr + 1)) + hdr->size);
+}
+
+static inline void *user(struct hdr *hdr)
+{
+ return hdr + 1;
+}
+
+static inline struct hdr *meta(void *user)
+{
+ return ((struct hdr *)user) - 1;
+}
+
+extern int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap);
+static void default_log(const char *fmt, ...)
+{
+ va_list lst;
+ va_start(lst, fmt);
+ __android_log_vprint(ANDROID_LOG_ERROR, "DEBUG", fmt, lst);
+ va_end(lst);
+}
+
+/* Override this for non-printf reporting */
+void (*malloc_log)(const char *fmt, ...) = default_log;
+/* Call this ad dlclose() to get leaked memory */
+void free_leaked_memory(void);
+
+static unsigned num;
+static struct hdr *first;
+static struct hdr *last;
+static pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
+
+static unsigned backlog_num;
+static struct hdr *backlog_first;
+static struct hdr *backlog_last;
+static pthread_rwlock_t backlog_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+static void print_backtrace(const intptr_t *bt, int depth)
+{
+ mapinfo *mi;
+ int cnt, rel_pc;
+ malloc_log("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
+ for (cnt = 0; cnt < depth && cnt < MAX_BACKTRACE_DEPTH; cnt++) {
+ mi = pc_to_mapinfo(milist, bt[cnt], &rel_pc);
+ malloc_log("\t#%02d pc %08x %s\n", cnt,
+ mi ? rel_pc : bt[cnt],
+ mi ? mi->name : "(unknown)");
+ }
+}
+
+static inline void init_front_guard(struct hdr *hdr)
+{
+ memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN);
+}
+
+static inline int is_front_guard_valid(struct hdr *hdr)
+{
+ unsigned i;
+ for (i = 0; i < FRONT_GUARD_LEN; i++)
+ if (hdr->front_guard[i] != FRONT_GUARD)
+ return 0;
+ return 1;
+}
+
+static inline void init_rear_guard(struct hdr *hdr)
+{
+ struct ftr *ftr = to_ftr(hdr);
+ memset(ftr->rear_guard, REAR_GUARD, REAR_GUARD_LEN);
+}
+
+static inline int is_rear_guard_valid(struct hdr *hdr)
+{
+ unsigned i;
+ int valid = 1;
+ int first_mismatch = -1;
+ struct ftr *ftr = to_ftr(hdr);
+ for (i = 0; i < REAR_GUARD_LEN; i++) {
+ if (ftr->rear_guard[i] != REAR_GUARD) {
+ if (first_mismatch < 0)
+ first_mismatch = i;
+ valid = 0;
+ }
+ else if (first_mismatch >= 0) {
+ malloc_log("+++ REAR GUARD MISMATCH [%d, %d)\n", first_mismatch, i);
+ first_mismatch = -1;
+ }
+ }
+
+ if (first_mismatch >= 0)
+ malloc_log("+++ REAR GUARD MISMATCH [%d, %d)\n", first_mismatch, i);
+ return valid;
+}
+
+static inline void __add(struct hdr *hdr, struct hdr **first, struct hdr **last)
+{
+ hdr->prev = 0;
+ hdr->next = *last;
+ if (*last)
+ (*last)->prev = hdr;
+ else
+ *first = hdr;
+ *last = hdr;
+}
+
+static inline int __del(struct hdr *hdr, struct hdr **first, struct hdr **last)
+{
+ if (hdr->prev)
+ hdr->prev->next = hdr->next;
+ else
+ *last = hdr->next;
+ if (hdr->next)
+ hdr->next->prev = hdr->prev;
+ else
+ *first = hdr->prev;
+ return 0;
+}
+
+static inline void add(struct hdr *hdr, size_t size)
+{
+ pthread_rwlock_wrlock(&lock);
+ hdr->tag = ALLOCATION_TAG;
+ hdr->size = size;
+ init_front_guard(hdr);
+ init_rear_guard(hdr);
+ num++;
+ __add(hdr, &first, &last);
+ pthread_rwlock_unlock(&lock);
+}
+
+static inline int del(struct hdr *hdr)
+{
+ if (hdr->tag != ALLOCATION_TAG)
+ return -1;
+
+ pthread_rwlock_wrlock(&lock);
+ __del(hdr, &first, &last);
+ num--;
+ pthread_rwlock_unlock(&lock);
+ return 0;
+}
+
+static inline void poison(struct hdr *hdr)
+{
+ memset(user(hdr), FREE_POISON, hdr->size);
+}
+
+static int was_used_after_free(struct hdr *hdr)
+{
+ unsigned i;
+ const char *data = (const char *)user(hdr);
+ for (i = 0; i < hdr->size; i++)
+ if (data[i] != FREE_POISON)
+ return 1;
+ return 0;
+}
+
+/* returns 1 if valid, *safe == 1 if safe to dump stack */
+static inline int check_guards(struct hdr *hdr, int *safe)
+{
+ *safe = 1;
+ if (!is_front_guard_valid(hdr)) {
+ if (hdr->front_guard[0] == FRONT_GUARD) {
+ malloc_log("+++ ALLOCATION %p SIZE %d HAS A CORRUPTED FRONT GUARD\n",
+ user(hdr), hdr->size);
+ } else {
+ malloc_log("+++ ALLOCATION %p HAS A CORRUPTED FRONT GUARD "\
+ "(NOT DUMPING STACKTRACE)\n", user(hdr));
+ /* Allocation header is probably corrupt, do not print stack trace */
+ *safe = 0;
+ }
+ return 0;
+ }
+
+ if (!is_rear_guard_valid(hdr)) {
+ malloc_log("+++ ALLOCATION %p SIZE %d HAS A CORRUPTED REAR GUARD\n",
+ user(hdr), hdr->size);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* returns 1 if valid, *safe == 1 if safe to dump stack */
+static inline int __check_allocation(struct hdr *hdr, int *safe)
+{
+ int valid = 1;
+ *safe = 1;
+
+ if (hdr->tag != ALLOCATION_TAG && hdr->tag != BACKLOG_TAG) {
+ malloc_log("+++ ALLOCATION %p HAS INVALID TAG %08x (NOT DUMPING STACKTRACE)\n",
+ user(hdr), hdr->tag);
+ /* Allocation header is probably corrupt, do not dequeue or dump stack
+ * trace.
+ */
+ *safe = 0;
+ return 0;
+ }
+
+ if (hdr->tag == BACKLOG_TAG && was_used_after_free(hdr)) {
+ malloc_log("+++ ALLOCATION %p SIZE %d WAS USED AFTER BEING FREED\n",
+ user(hdr), hdr->size);
+ valid = 0;
+ /* check the guards to see if it's safe to dump a stack trace */
+ (void)check_guards(hdr, safe);
+ }
+ else
+ valid = check_guards(hdr, safe);
+
+ if (!valid && *safe) {
+ malloc_log("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
+ user(hdr), hdr->size);
+ print_backtrace(hdr->bt, hdr->bt_depth);
+ if (hdr->tag == BACKLOG_TAG) {
+ malloc_log("+++ ALLOCATION %p SIZE %d FREED HERE:\n",
+ user(hdr), hdr->size);
+ print_backtrace(hdr->freed_bt, hdr->freed_bt_depth);
+ }
+ }
+
+ return valid;
+}
+
+static inline int __del_and_check(struct hdr *hdr,
+ struct hdr **first, struct hdr **last, unsigned *cnt,
+ int *safe)
+{
+ int valid;
+ valid = __check_allocation(hdr, safe);
+ if (safe) {
+ (*cnt)--;
+ __del(hdr, first, last);
+ }
+ return valid;
+}
+
+static inline void __del_from_backlog(struct hdr *hdr)
+{
+ int safe;
+ (void)__del_and_check(hdr,
+ &backlog_first, &backlog_last, &backlog_num,
+ &safe);
+ hdr->tag = 0; /* clear the tag */
+}
+
+static inline void del_from_backlog(struct hdr *hdr)
+{
+ pthread_rwlock_wrlock(&backlog_lock);
+ __del_from_backlog(hdr);
+ pthread_rwlock_unlock(&backlog_lock);
+}
+
+static inline int del_leak(struct hdr *hdr, int *safe)
+{
+ int valid;
+ pthread_rwlock_wrlock(&lock);
+ valid = __del_and_check(hdr,
+ &first, &last, &num,
+ safe);
+ pthread_rwlock_unlock(&lock);
+ return valid;
+}
+
+static inline void add_to_backlog(struct hdr *hdr)
+{
+ pthread_rwlock_wrlock(&backlog_lock);
+ hdr->tag = BACKLOG_TAG;
+ backlog_num++;
+ __add(hdr, &backlog_first, &backlog_last);
+ poison(hdr);
+ /* If we've exceeded the maximum backlog, clear it up */
+ while (backlog_num > BACKLOG_MAX) {
+ struct hdr *gone = backlog_first;
+ __del_from_backlog(gone);
+ __real_free(gone);
+ }
+ pthread_rwlock_unlock(&backlog_lock);
+}
+
+void* __wrap_malloc(size_t size)
+{
+// malloc_tracker_log("%s: %s\n", __FILE__, __FUNCTION__);
+ struct hdr *hdr = __real_malloc(sizeof(struct hdr) + size +
+ sizeof(struct ftr));
+ if (hdr) {
+ hdr->bt_depth = heaptracker_stacktrace(
+ hdr->bt, MAX_BACKTRACE_DEPTH);
+ add(hdr, size);
+ return hdr+1;
+ }
+ return NULL;
+}
+
+void __wrap_free(void *ptr)
+{
+ struct hdr *hdr;
+ if (!ptr) /* ignore free(NULL) */
+ return;
+
+ hdr = meta(ptr);
+
+ if (del(hdr) < 0) {
+ intptr_t bt[MAX_BACKTRACE_DEPTH];
+ int depth;
+ depth = heaptracker_stacktrace(bt, MAX_BACKTRACE_DEPTH);
+ if (hdr->tag == BACKLOG_TAG) {
+ malloc_log("+++ ALLOCATION %p SIZE %d BYTES MULTIPLY FREED!\n",
+ user(hdr), hdr->size);
+ malloc_log("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
+ user(hdr), hdr->size);
+ print_backtrace(hdr->bt, hdr->bt_depth);
+ /* hdr->freed_bt_depth should be nonzero here */
+ malloc_log("+++ ALLOCATION %p SIZE %d FIRST FREED HERE:\n",
+ user(hdr), hdr->size);
+ print_backtrace(hdr->freed_bt, hdr->freed_bt_depth);
+ malloc_log("+++ ALLOCATION %p SIZE %d NOW BEING FREED HERE:\n",
+ user(hdr), hdr->size);
+ print_backtrace(bt, depth);
+ }
+ else {
+ malloc_log("+++ ALLOCATION %p IS CORRUPTED OR NOT ALLOCATED VIA TRACKER!\n",
+ user(hdr));
+ print_backtrace(bt, depth);
+ /* Leak here so that we do not crash */
+ //__real_free(user(hdr));
+ }
+ }
+ else {
+ hdr->freed_bt_depth = heaptracker_stacktrace(hdr->freed_bt,
+ MAX_BACKTRACE_DEPTH);
+ add_to_backlog(hdr);
+ }
+}
+
+void *__wrap_realloc(void *ptr, size_t size)
+{
+ struct hdr *hdr;
+
+ if (!size) {
+ __wrap_free(ptr);
+ return NULL;
+ }
+
+ if (!ptr)
+ return __wrap_malloc(size);
+
+ hdr = meta(ptr);
+
+// malloc_log("%s: %s\n", __FILE__, __FUNCTION__);
+ if (del(hdr) < 0) {
+ intptr_t bt[MAX_BACKTRACE_DEPTH];
+ int depth;
+ depth = heaptracker_stacktrace(bt, MAX_BACKTRACE_DEPTH);
+ if (hdr->tag == BACKLOG_TAG) {
+ malloc_log("+++ REALLOCATION %p SIZE %d OF FREED MEMORY!\n",
+ user(hdr), size, hdr->size);
+ malloc_log("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
+ user(hdr), hdr->size);
+ print_backtrace(hdr->bt, hdr->bt_depth);
+ /* hdr->freed_bt_depth should be nonzero here */
+ malloc_log("+++ ALLOCATION %p SIZE %d FIRST FREED HERE:\n",
+ user(hdr), hdr->size);
+ print_backtrace(hdr->freed_bt, hdr->freed_bt_depth);
+ malloc_log("+++ ALLOCATION %p SIZE %d NOW BEING REALLOCATED HERE:\n",
+ user(hdr), hdr->size);
+ print_backtrace(bt, depth);
+
+ /* We take the memory out of the backlog and fall through so the
+ * reallocation below succeeds. Since we didn't really free it, we
+ * can default to this behavior.
+ */
+ del_from_backlog(hdr);
+ }
+ else {
+ malloc_log("+++ REALLOCATION %p SIZE %d IS CORRUPTED OR NOT ALLOCATED VIA TRACKER!\n",
+ user(hdr), size);
+ print_backtrace(bt, depth);
+ // just get a whole new allocation and leak the old one
+ return __real_realloc(0, size);
+ // return __real_realloc(user(hdr), size); // assuming it was allocated externally
+ }
+ }
+
+ hdr = __real_realloc(hdr, sizeof(struct hdr) + size);
+ if (hdr) {
+ hdr->bt_depth = heaptracker_stacktrace(hdr->bt, MAX_BACKTRACE_DEPTH);
+ add(hdr, size);
+ return user(hdr);
+ }
+
+ return NULL;
+}
+
+void *__wrap_calloc(int nmemb, size_t size)
+{
+// malloc_tracker_log("%s: %s\n", __FILE__, __FUNCTION__);
+ struct hdr *hdr;
+ size_t __size = nmemb * size;
+ hdr = __real_calloc(1, sizeof(struct hdr) + __size);
+ if (hdr) {
+ hdr->bt_depth = heaptracker_stacktrace(
+ hdr->bt, MAX_BACKTRACE_DEPTH);
+ add(hdr, __size);
+ return user(hdr);
+ }
+ return NULL;
+}
+
+void heaptracker_free_leaked_memory(void)
+{
+ struct hdr *del; int cnt;
+
+ if (num)
+ malloc_log("+++ THERE ARE %d LEAKED ALLOCATIONS\n", num);
+
+ while (last) {
+ int safe;
+ del = last;
+ malloc_log("+++ DELETING %d BYTES OF LEAKED MEMORY AT %p (%d REMAINING)\n",
+ del->size, user(del), num);
+ if (del_leak(del, &safe)) {
+ /* safe == 1, because the allocation is valid */
+ malloc_log("+++ ALLOCATION %p SIZE %d ALLOCATED HERE:\n",
+ user(del), del->size);
+ print_backtrace(del->bt, del->bt_depth);
+ }
+ __real_free(del);
+ }
+
+// malloc_log("+++ DELETING %d BACKLOGGED ALLOCATIONS\n", backlog_num);
+ while (backlog_last) {
+ del = backlog_first;
+ del_from_backlog(del);
+ __real_free(del);
+ }
+}
+
+static int check_list(struct hdr *list, pthread_rwlock_t *rwlock)
+{
+ struct hdr *hdr;
+ int safe, num_checked;
+
+ pthread_rwlock_rdlock(rwlock);
+ num_checked = 0;
+ hdr = list;
+ while (hdr) {
+ (void)__check_allocation(hdr, &safe);
+ hdr = hdr->next;
+ num_checked++;
+ }
+ pthread_rwlock_unlock(rwlock);
+
+ return num_checked;
+}
+
+static pthread_t scanner_thread;
+static pthread_cond_t scanner_cond = PTHREAD_COND_INITIALIZER;
+static int scanner_stop;
+static pthread_mutex_t scanner_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static void* scanner(void *data __attribute__((unused)))
+{
+ struct timespec ts;
+ int num_checked, num_checked_backlog;
+
+ while (1) {
+ num_checked = check_list(last, &lock);
+ num_checked_backlog = check_list(backlog_last, &backlog_lock);
+
+// malloc_log("@@@ scanned %d/%d allocs and %d/%d freed\n",
+// num_checked, num,
+// num_checked_backlog, backlog_num);
+
+ pthread_mutex_lock(&scanner_lock);
+ if (!scanner_stop) {
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += SCANNER_SLEEP_S;
+ pthread_cond_timedwait(&scanner_cond, &scanner_lock, &ts);
+ }
+ if (scanner_stop) {
+ pthread_mutex_unlock(&scanner_lock);
+ break;
+ }
+ pthread_mutex_unlock(&scanner_lock);
+ }
+
+// malloc_log("@@@ scanner thread exiting");
+ return NULL;
+}
+
+static void init(void) __attribute__((constructor));
+static void init(void)
+{
+// malloc_log("@@@ start scanner thread");
+ milist = init_mapinfo(getpid());
+ pthread_create(&scanner_thread,
+ NULL,
+ scanner,
+ NULL);
+}
+
+static void deinit(void) __attribute__((destructor));
+static void deinit(void)
+{
+// malloc_log("@@@ signal stop to scanner thread");
+ pthread_mutex_lock(&scanner_lock);
+ scanner_stop = 1;
+ pthread_cond_signal(&scanner_cond);
+ pthread_mutex_unlock(&scanner_lock);
+// malloc_log("@@@ wait for scanner thread to exit");
+ pthread_join(scanner_thread, NULL);
+// malloc_log("@@@ scanner thread stopped");
+
+ heaptracker_free_leaked_memory();
+ deinit_mapinfo(milist);
+}
diff --git a/hwc/Android.mk b/hwc/Android.mk
new file mode 100644
index 0000000..af72df2
--- /dev/null
+++ b/hwc/Android.mk
@@ -0,0 +1,19 @@
+# HWC under heavy development and should not be included in builds for now
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implementation, not prelinked and stored in
+# hw/<HWCOMPOSE_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/../vendor/lib/hw
+LOCAL_SHARED_LIBRARIES := liblog libEGL libcutils libutils libhardware
+LOCAL_SRC_FILES := hwc.c
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := hwcomposer.omap4
+LOCAL_CFLAGS := -DLOG_TAG=\"ti_hwc\"
+# LOG_NDEBUG=0 means verbose logging enabled
+# LOCAL_CFLAGS += -DLOG_NDEBUG=0
+include $(BUILD_SHARED_LIBRARY)
diff --git a/hwc/hal_public.h b/hwc/hal_public.h
new file mode 100644
index 0000000..62c7849
--- /dev/null
+++ b/hwc/hal_public.h
@@ -0,0 +1,162 @@
+/* Copyright (c) Imagination Technologies Ltd.
+ *
+ * The contents of this file are subject to the MIT license as set out below.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HAL_PUBLIC_H
+#define HAL_PUBLIC_H
+
+/* Authors of third party hardware composer (HWC) modules will need to include
+ * this header to access functionality in the gralloc and framebuffer HALs.
+ */
+
+#include <hardware/gralloc.h>
+
+#define ALIGN(x,a) (((x) + (a) - 1L) & ~((a) - 1L))
+#define HW_ALIGN 32
+
+/* This can be tuned down as appropriate for the SOC.
+ *
+ * IMG formats are usually a single sub-alloc.
+ * Some OEM video formats are two sub-allocs (Y, UV planes).
+ * Future OEM video formats might be three sub-allocs (Y, U, V planes).
+ */
+#define MAX_SUB_ALLOCS 3
+
+typedef struct
+{
+ native_handle_t base;
+
+ /* These fields can be sent cross process. They are also valid
+ * to duplicate within the same process.
+ *
+ * A table is stored within psPrivateData on gralloc_module_t (this
+ * is obviously per-process) which maps stamps to a mapped
+ * PVRSRV_CLIENT_MEM_INFO in that process. Each map entry has a lock
+ * count associated with it, satisfying the requirements of the
+ * Android API. This also prevents us from leaking maps/allocations.
+ *
+ * This table has entries inserted either by alloc()
+ * (alloc_device_t) or map() (gralloc_module_t). Entries are removed
+ * by free() (alloc_device_t) and unmap() (gralloc_module_t).
+ *
+ * As a special case for framebuffer_device_t, framebuffer_open()
+ * will add and framebuffer_close() will remove from this table.
+ */
+
+#define IMG_NATIVE_HANDLE_NUMFDS MAX_SUB_ALLOCS
+ /* The `fd' field is used to "export" a meminfo to another process.
+ * Therefore, it is allocated by alloc_device_t, and consumed by
+ * gralloc_module_t. The framebuffer_device_t does not need a handle,
+ * and the special value IMG_FRAMEBUFFER_FD is used instead.
+ */
+ int fd[MAX_SUB_ALLOCS];
+
+#define IMG_NATIVE_HANDLE_NUMINTS ((sizeof(unsigned long long) / sizeof(int)) + 5)
+ /* A KERNEL unique identifier for any exported kernel meminfo. Each
+ * exported kernel meminfo will have a unique stamp, but note that in
+ * userspace, several meminfos across multiple processes could have
+ * the same stamp. As the native_handle can be dup(2)'d, there could be
+ * multiple handles with the same stamp but different file descriptors.
+ */
+ unsigned long long ui64Stamp;
+
+ /* This is used for buffer usage validation when locking a buffer,
+ * and also in WSEGL (for the composition bypass feature).
+ */
+ int usage;
+
+ /* In order to do efficient cache flushes we need the buffer dimensions
+ * and format. These are available on the ANativeWindowBuffer,
+ * but the platform doesn't pass them down to the graphics HAL.
+ *
+ * These fields are also used in the composition bypass. In this
+ * capacity, these are the "real" values for the backing allocation.
+ */
+ int iWidth;
+ int iHeight;
+ int iFormat;
+ unsigned int uiBpp;
+}
+__attribute__((aligned(sizeof(int)),packed)) IMG_native_handle_t;
+
+typedef struct
+{
+ framebuffer_device_t base;
+
+ /* The HWC was loaded. post() is no longer responsible for presents */
+ int bBypassPost;
+
+ /* Custom-blit components in lieu of overlay hardware */
+ int (*Blit)(framebuffer_device_t *device, buffer_handle_t src,
+ buffer_handle_t dest, int w, int h, int x, int y);
+
+ /* HWC path for present posts */
+ int (*Post2)(framebuffer_device_t *fb, buffer_handle_t *buffers,
+ int num_buffers, void *data, int data_length);
+}
+IMG_framebuffer_device_public_t;
+
+typedef struct IMG_gralloc_module_public_t
+{
+ gralloc_module_t base;
+
+ /* If the framebuffer has been opened, this will point to the
+ * framebuffer device data required by the allocator, WSEGL
+ * modules and composerhal.
+ */
+ IMG_framebuffer_device_public_t *psFrameBufferDevice;
+
+ int (*GetPhyAddrs)(struct IMG_gralloc_module_public_t const* module,
+ buffer_handle_t handle,
+ unsigned int auiPhyAddr[MAX_SUB_ALLOCS]);
+}
+IMG_gralloc_module_public_t;
+
+typedef struct
+{
+ int l, t, w, h;
+}
+IMG_write_lock_rect_t;
+
+typedef struct IMG_buffer_format_public_t
+{
+ /* Buffer formats are returned as a linked list */
+ struct IMG_buffer_format_public_t *psNext;
+
+ /* HAL_PIXEL_FORMAT_... enumerant */
+ int iHalPixelFormat;
+
+ /* WSEGL_PIXELFORMAT_... enumerant */
+ int iWSEGLPixelFormat;
+
+ /* Friendly name for format */
+ const char *const szName;
+
+ /* Bits (not bytes) per pixel */
+ unsigned int uiBpp;
+
+ /* GPU output format (creates EGLConfig for format) */
+ int bGPURenderable;
+}
+IMG_buffer_format_public_t;
+
+#endif /* HAL_PUBLIC_H */
diff --git a/hwc/hwc.c b/hwc/hwc.c
new file mode 100644
index 0000000..5f33764
--- /dev/null
+++ b/hwc/hwc.c
@@ -0,0 +1,693 @@
+/*
+ * 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 <errno.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <cutils/properties.h>
+#include <cutils/log.h>
+#include <cutils/native_handle.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+#include <EGL/egl.h>
+#include <utils/Timers.h>
+
+#include <video/dsscomp.h>
+
+#include "hal_public.h"
+
+#define MAX_HW_OVERLAYS 4
+#define MAX_SCALING_OVERLAYS 3
+#define HAL_PIXEL_FORMAT_BGRX_8888 0x1FF
+#define HAL_PIXEL_FORMAT_TI_NV12 0x100
+#define HAL_PIXEL_FORMAT_TI_NV12_PADDED 0x101
+#define MAX_TILER_SLOT (4 << 20)
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x)))
+
+struct omap4_hwc_module {
+ hwc_module_t base;
+
+ IMG_framebuffer_device_public_t *fb_dev;
+};
+typedef struct omap4_hwc_module omap4_hwc_module_t;
+
+struct omap4_hwc_device {
+ hwc_composer_device_t base;
+
+ IMG_framebuffer_device_public_t *fb_dev;
+ struct dsscomp_setup_dispc_data dsscomp_data;
+
+ buffer_handle_t *buffers;
+ int use_sgx;
+
+ int flags_rgb_order;
+ int flags_nv12_only;
+};
+typedef struct omap4_hwc_device omap4_hwc_device_t;
+
+static int debug = 0;
+
+static void dump_layer(hwc_layer_t const* l)
+{
+ LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
+ l->compositionType, l->flags, l->handle, l->transform, l->blending,
+ l->sourceCrop.left,
+ l->sourceCrop.top,
+ l->sourceCrop.right,
+ l->sourceCrop.bottom,
+ l->displayFrame.left,
+ l->displayFrame.top,
+ l->displayFrame.right,
+ l->displayFrame.bottom);
+}
+
+static void dump_dsscomp(struct dsscomp_setup_dispc_data *d)
+{
+ struct dss2_mgr_info *mi = &d->mgr;
+
+ LOGE("[%08x] set: %c%c%c(dis%d alpha=%d col=%08x ilace=%d n=%d)\n",
+ d->sync_id,
+ (d->mode & DSSCOMP_SETUP_MODE_APPLY) ? 'A' : '-',
+ (d->mode & DSSCOMP_SETUP_MODE_DISPLAY) ? 'D' : '-',
+ (d->mode & DSSCOMP_SETUP_MODE_CAPTURE) ? 'C' : '-',
+ mi->ix,
+ mi->alpha_blending, mi->default_color,
+ mi->interlaced,
+ d->num_ovls);
+
+ unsigned i;
+ for (i = 0; i < d->num_ovls; i++) {
+ struct dss2_ovl_info *oi = d->ovls + i;
+ struct dss2_ovl_cfg *c = &oi->cfg;
+ if (c->zonly)
+ LOGE("ovl%d(%s z%d)\n",
+ c->ix, c->enabled ? "ON" : "off", c->zorder);
+ else
+ LOGE("ovl%d(%s z%d %x%s *%d%% %d*%d:%d,%d+%d,%d rot%d%s => %d,%d+%d,%d %p/%p|%d)\n",
+ c->ix, c->enabled ? "ON" : "off", c->zorder, c->color_mode,
+ c->pre_mult_alpha ? " premult" : "",
+ (c->global_alpha * 100 + 128) / 255,
+ c->width, c->height, c->crop.x, c->crop.y,
+ c->crop.w, c->crop.h,
+ c->rotation, c->mirror ? "+mir" : "",
+ c->win.x, c->win.y, c->win.w, c->win.h,
+ (void *) oi->ba, (void *) oi->uv, c->stride);
+ }
+}
+
+static int omap4_hwc_is_valid_format(int format)
+{
+ switch(format) {
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ case HAL_PIXEL_FORMAT_TI_NV12:
+ case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
+ return 1;
+
+ default:
+ LOGI("invalid format %d", format);
+ return 0;
+ }
+}
+
+static int scaled(hwc_layer_t *layer)
+{
+ int w = layer->sourceCrop.right - layer->sourceCrop.left;
+ int h = layer->sourceCrop.bottom - layer->sourceCrop.top;
+ /* TODO: skip w/h if rotated by 90 */
+ return (layer->displayFrame.right - layer->displayFrame.left != w ||
+ layer->displayFrame.bottom - layer->displayFrame.top != h);
+}
+
+static int sync_id = 0;
+
+#define is_ALPHA(format) ((format) == HAL_PIXEL_FORMAT_BGRA_8888 || (format) == HAL_PIXEL_FORMAT_RGBA_8888)
+#define is_RGB(format) ((format) == HAL_PIXEL_FORMAT_BGRA_8888 || (format) == HAL_PIXEL_FORMAT_RGB_565 || (format) == HAL_PIXEL_FORMAT_BGRX_8888)
+#define is_BGR(format) ((format) == HAL_PIXEL_FORMAT_RGBX_8888 || (format) == HAL_PIXEL_FORMAT_RGBA_8888)
+#define is_NV12(format) ((format) == HAL_PIXEL_FORMAT_TI_NV12 || (format) == HAL_PIXEL_FORMAT_TI_NV12_PADDED)
+
+static void
+omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int width, int height)
+{
+ unsigned int bits_per_pixel;
+
+ /* YUV2RGB conversion */
+ const struct omap_dss_cconv_coefs ctbl_bt601_5 = {
+ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
+ };
+
+ /* convert color format */
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ /* Should be XBGR32, but this isn't supported */
+ oc->color_mode = OMAP_DSS_COLOR_RGB24U;
+ bits_per_pixel = 32;
+ break;
+
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ /* Should be ABGR32, but this isn't supported */
+ oc->color_mode = OMAP_DSS_COLOR_ARGB32;
+ bits_per_pixel = 32;
+ break;
+
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ oc->color_mode = OMAP_DSS_COLOR_ARGB32;
+ bits_per_pixel = 32;
+ break;
+
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ oc->color_mode = OMAP_DSS_COLOR_RGB24U;
+ bits_per_pixel = 32;
+ break;
+
+ case HAL_PIXEL_FORMAT_RGB_565:
+ oc->color_mode = OMAP_DSS_COLOR_RGB16;
+ bits_per_pixel = 16;
+ break;
+
+ case HAL_PIXEL_FORMAT_TI_NV12:
+ case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
+ oc->color_mode = OMAP_DSS_COLOR_NV12;
+ bits_per_pixel = 8;
+ oc->cconv = ctbl_bt601_5;
+ break;
+
+ default:
+ /* Should have been filtered out */
+ LOGV("Unsupported pixel format");
+ return;
+ }
+
+ oc->width = width;
+ oc->height = height;
+ oc->stride = ALIGN(width, HW_ALIGN) * bits_per_pixel / 8;
+
+ oc->enabled = 1;
+ oc->global_alpha = 255;
+ oc->zorder = index;
+ oc->ix = 0;
+
+ /* defaults for SGX framebuffer renders */
+ oc->crop.w = oc->win.w = width;
+ oc->crop.h = oc->win.h = height;
+
+ /* for now interlacing and vc1 info is not supplied */
+ oc->ilace = OMAP_DSS_ILACE_NONE;
+ oc->vc1.enable = 0;
+}
+
+static void
+omap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl,
+ hwc_layer_t *layer, int index,
+ int format, int width, int height)
+{
+ struct dss2_ovl_cfg *oc = &ovl->cfg;
+
+ //dump_layer(layer);
+
+ omap4_hwc_setup_layer_base(oc, index, format, width, height);
+
+ /* convert transformation - assuming 0-set config */
+ if (layer->transform & HWC_TRANSFORM_FLIP_H)
+ oc->mirror = 1;
+ if (layer->transform & HWC_TRANSFORM_FLIP_V) {
+ oc->rotation = 2;
+ oc->mirror = !oc->mirror;
+ }
+ if (layer->transform & HWC_TRANSFORM_ROT_90) {
+ oc->rotation += oc->mirror ? -1 : 1;
+ oc->rotation &= 3;
+ }
+
+ oc->pre_mult_alpha = layer->blending == HWC_BLENDING_PREMULT;
+
+ /* display position */
+ oc->win.x = layer->displayFrame.left;
+ oc->win.y = layer->displayFrame.top;
+ oc->win.w = layer->displayFrame.right - layer->displayFrame.left;
+ oc->win.h = layer->displayFrame.bottom - layer->displayFrame.top;
+
+ /* crop */
+ oc->crop.x = layer->sourceCrop.left;
+ oc->crop.y = layer->sourceCrop.top;
+ oc->crop.w = layer->sourceCrop.right - layer->sourceCrop.left;
+ oc->crop.h = layer->sourceCrop.bottom - layer->sourceCrop.top;
+}
+
+static int omap4_hwc_is_valid_layer(hwc_layer_t *layer,
+ IMG_native_handle_t *handle)
+{
+ /* Skip layers are handled by SF */
+ if ((layer->flags & HWC_SKIP_LAYER) || !handle)
+ return 0;
+
+ if (!omap4_hwc_is_valid_format(handle->iFormat))
+ return 0;
+
+ /* 1D buffers: no transform, must fit in TILER slot */
+ if (!is_NV12(handle->iFormat)) {
+ if (layer->transform)
+ return 0;
+ int bpp = (handle->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4);
+ int stride = ALIGN(handle->iWidth, HW_ALIGN) * bpp;
+ if (stride * handle->iHeight > MAX_TILER_SLOT)
+ return 0;
+ }
+ return 1;
+}
+
+static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t* list)
+{
+ omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
+ struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
+ unsigned int num_possible_overlay_layers = 0;
+ unsigned int num_composited_layers = 0;
+ unsigned int num_scaled_layers = 0;
+ unsigned int i;
+ unsigned int num_RGB = 0;
+ unsigned int num_BGR = 0;
+
+ memset(dsscomp, 0x0, sizeof(*dsscomp));
+ dsscomp->sync_id = sync_id++;
+
+ /* Figure out how many layers we can support via DSS */
+ num_composited_layers = list->numHwLayers;
+
+ for (i = 0; i < list->numHwLayers; i++) {
+ hwc_layer_t *layer = &list->hwLayers[i];
+ IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
+
+ layer->compositionType = HWC_FRAMEBUFFER;
+
+ if (omap4_hwc_is_valid_layer(layer, handle)) {
+ num_possible_overlay_layers++;
+
+ if (scaled(layer))
+ num_scaled_layers++;
+
+ if (is_BGR(handle->iFormat))
+ num_BGR++;
+ else if (is_RGB(handle->iFormat))
+ num_RGB++;
+ }
+ }
+
+ /* phase 2 logic: all DSS rendering */
+ if (num_possible_overlay_layers <= MAX_HW_OVERLAYS &&
+ num_possible_overlay_layers == num_composited_layers &&
+ num_scaled_layers <= MAX_SCALING_OVERLAYS &&
+ (num_BGR == 0 || num_RGB == 0 || !hwc_dev->flags_rgb_order) &&
+ num_possible_overlay_layers) {
+ /* All layers can be handled by the DSS -- don't use SGX for composition */
+ hwc_dev->use_sgx = 0;
+ dsscomp->mgr.swap_rb = num_BGR != 0;
+ } else {
+ /* Use SGX for composition plus first 3 layers that are DSS renderable */
+ hwc_dev->use_sgx = 1;
+ dsscomp->mgr.swap_rb = is_BGR(hwc_dev->fb_dev->base.format);
+ }
+ if (debug) {
+ LOGD("prepare (%d) %d layers - %s (poss=%d/%d scaled, comp=%d, rgb=%d,bgr=%d)\n",
+ dsscomp->sync_id, list->numHwLayers,
+ hwc_dev->use_sgx ? "SGX+OVL" : "all-OVL",
+ num_possible_overlay_layers, num_scaled_layers, num_composited_layers, num_RGB, num_BGR);
+ }
+
+ /* setup pipes */
+ dsscomp->num_ovls = hwc_dev->use_sgx;
+ int z = 0;
+ int fb_z = -1, fb_zmax = 0;
+ int scaled_gfx = 0;
+
+ /* set up if DSS layers */
+ for (i = 0; i < list->numHwLayers && dsscomp->num_ovls < MAX_HW_OVERLAYS; i++) {
+ hwc_layer_t *layer = &list->hwLayers[i];
+ IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
+
+ if (handle &&
+ omap4_hwc_is_valid_layer(layer, handle) &&
+ /* can't have a transparent overlay in the middle of the framebuffer stack */
+ !(is_ALPHA(handle->iFormat) && fb_z >= 0) &&
+ /* skip non-NV12 layers if also using SGX (if nv12_only flag is set) */
+ (!hwc_dev->flags_nv12_only || (!hwc_dev->use_sgx || is_NV12(handle->iFormat))) &&
+ /* make sure RGB ordering is consistent (if rgb_order flag is set) */
+ (!(dsscomp->mgr.swap_rb ? is_RGB(handle->iFormat) : is_BGR(handle->iFormat)) ||
+ !hwc_dev->flags_rgb_order)) {
+ /* render via DSS overlay */
+ layer->compositionType = HWC_OVERLAY;
+ /* clear layers above DSS layer areas */
+ layer->hints |= HWC_HINT_CLEAR_FB;
+ hwc_dev->buffers[dsscomp->num_ovls] = layer->handle;
+
+ omap4_hwc_setup_layer(hwc_dev,
+ &dsscomp->ovls[dsscomp->num_ovls],
+ &list->hwLayers[i],
+ z,
+ handle->iFormat,
+ handle->iWidth,
+ handle->iHeight);
+ /* TODO: we need to use gfx for the a layer that is not scaled */
+ dsscomp->ovls[dsscomp->num_ovls].cfg.ix = dsscomp->num_ovls;
+ /* just marking dss layers */
+ dsscomp->ovls[dsscomp->num_ovls].address = (void *) (dsscomp->num_ovls * 4096 + 0xA0000000);
+ dsscomp->ovls[dsscomp->num_ovls].uv = (__u32) hwc_dev->buffers[dsscomp->num_ovls];
+
+ /* ensure GFX layer is never scaled */
+ if (dsscomp->num_ovls == 0) {
+ scaled_gfx = scaled(layer);
+ } else if (scaled_gfx && !scaled(layer)) {
+ /* swap GFX layer with this one */
+ dsscomp->ovls[dsscomp->num_ovls].cfg.ix = 0;
+ dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls;
+ scaled_gfx = 0;
+ }
+
+ dsscomp->num_ovls++;
+ z++;
+ } else if (hwc_dev->use_sgx) {
+ if (fb_z < 0) {
+ /* NOTE: we are not handling transparent cutout for now */
+ fb_z = fb_zmax = z;
+ z++;
+ } else {
+ /* move fb z-order up (by lowering dss layers) */
+ while (fb_zmax < z - 1)
+ dsscomp->ovls[1 + fb_zmax++].cfg.zorder--;
+ }
+ }
+ }
+
+ /* clear FB above DSS layers */
+ /* FIXME: for now assume full screen layers. later this can be optimized */
+ int obstructed = 0;
+ if (dsscomp->num_ovls > hwc_dev->use_sgx) {
+ for (i = list->numHwLayers; i > 0;) {
+ i--;
+ hwc_layer_t *layer = &list->hwLayers[i];
+ if ((layer->flags & HWC_SKIP_LAYER) || !layer->handle)
+ continue;
+ if (layer->compositionType != HWC_OVERLAY)
+ obstructed = 1;
+ else if (obstructed)
+ layer->hints |= HWC_HINT_CLEAR_FB;
+ }
+ }
+
+ /* if scaling GFX (e.g. only 1 scaled surface) use a VID pipe */
+ if (scaled_gfx)
+ dsscomp->ovls[0].cfg.ix = 1;
+
+ /* assign a z-layer for fb */
+ if (hwc_dev->use_sgx && fb_z < 0) {
+ fb_z = z;
+ z++;
+ }
+
+ if (z != dsscomp->num_ovls || dsscomp->num_ovls > MAX_HW_OVERLAYS)
+ LOGE("**** used %d z-layers for %d overlays\n", z, dsscomp->num_ovls);
+
+ if (hwc_dev->use_sgx) {
+ hwc_dev->buffers[0] = NULL;
+ omap4_hwc_setup_layer_base(&dsscomp->ovls[0].cfg, fb_z,
+ hwc_dev->fb_dev->base.format,
+ hwc_dev->fb_dev->base.width,
+ hwc_dev->fb_dev->base.height);
+ dsscomp->ovls[0].uv = (__u32) hwc_dev->buffers[0];
+ }
+
+ dsscomp->mode = DSSCOMP_SETUP_DISPLAY;
+ dsscomp->mgr.ix = 0;
+ dsscomp->mgr.alpha_blending = 1;
+
+ return 0;
+}
+
+static int omap4_hwc_set(struct hwc_composer_device *dev, hwc_display_t dpy,
+ hwc_surface_t sur, hwc_layer_list_t* list)
+{
+ omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
+ struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
+ int err;
+ unsigned int i;
+
+ if (!list) {
+ LOGE("list is NULL");
+ return 0;
+ }
+
+ char big_log[1024];
+ int e = sizeof(big_log);
+ char *end = big_log + e;
+ e -= snprintf(end - e, e, "set H{");
+ for (i = 0; i < list->numHwLayers; i++) {
+ if (i)
+ e -= snprintf(end - e, e, " ");
+ hwc_layer_t *layer = &list->hwLayers[i];
+ IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
+ e -= snprintf(end - e, e, "%p:%s,", handle, layer->compositionType == HWC_OVERLAY ? "DSS" : "SGX");
+ if ((layer->flags & HWC_SKIP_LAYER) || !handle) {
+ e -= snprintf(end - e, e, "SKIP");
+ continue;
+ }
+ if (layer->flags & HWC_HINT_CLEAR_FB)
+ e -= snprintf(end - e, e, "CLR,");
+#define FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \
+ (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \
+ (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \
+ (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \
+ (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \
+ (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??")
+ e -= snprintf(end - e, e, "%d*%d(%s)", handle->iWidth, handle->iHeight, FMT(handle->iFormat));
+ if (layer->transform)
+ e -= snprintf(end - e, e, "~%d", layer->transform);
+#undef FMT
+ }
+ e -= snprintf(end - e, e, "} D{");
+ for (i = 0; i < dsscomp->num_ovls; i++) {
+ if (i)
+ e -= snprintf(end - e, e, " ");
+ e -= snprintf(end - e, e, "%d=", dsscomp->ovls[i].cfg.ix);
+#define FMT(f) ((f) == OMAP_DSS_COLOR_NV12 ? "NV12" : \
+ (f) == OMAP_DSS_COLOR_RGB24U ? "xRGB32" : \
+ (f) == OMAP_DSS_COLOR_ARGB32 ? "ARGB32" : \
+ (f) == OMAP_DSS_COLOR_RGB16 ? "RGB565" : "??")
+ if (dsscomp->ovls[i].cfg.enabled)
+ e -= snprintf(end - e, e, "%08x:%d*%d,%s",
+ dsscomp->ovls[i].ba,
+ dsscomp->ovls[i].cfg.width,
+ dsscomp->ovls[i].cfg.height,
+ FMT(dsscomp->ovls[i].cfg.color_mode));
+#undef FMT
+ else
+ e -= snprintf(end - e, e, "-");
+ }
+ e -= snprintf(end - e, e, "} L{");
+ for (i = 0; i < dsscomp->num_ovls; i++) {
+ if (i)
+ e -= snprintf(end - e, e, " ");
+ e -= snprintf(end - e, e, "%p", hwc_dev->buffers[i]);
+ }
+ e -= snprintf(end - e, e, "}%s\n", hwc_dev->use_sgx ? " swap" : "");
+ if (debug) {
+ LOGD("%s", big_log);
+ }
+
+ // LOGD("set %d layers (sgx=%d)\n", dsscomp->num_ovls, hwc_dev->use_sgx);
+
+ if (hwc_dev->use_sgx) {
+ if (!eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur)) {
+ LOGE("eglSwapBuffers error");
+ err = HWC_EGL_ERROR;
+ goto err_out;
+ }
+ }
+
+ //dump_dsscomp(dsscomp);
+
+ err = hwc_dev->fb_dev->Post2((framebuffer_device_t *)hwc_dev->fb_dev,
+ hwc_dev->buffers,
+ dsscomp->num_ovls,
+ dsscomp, sizeof(*dsscomp));
+ if (err)
+ LOGE("Post2 error");
+
+err_out:
+ return err;
+}
+
+static int dump_printf(char *buff, int buff_len, int len, const char *fmt, ...)
+{
+ va_list ap;
+
+ int print_len;
+
+ va_start(ap, fmt);
+
+ print_len = vsnprintf(buff + len, buff_len - len, fmt, ap);
+
+ va_end(ap);
+
+ return len + print_len;
+}
+
+static void omap4_hwc_dump(struct hwc_composer_device *dev, char *buff, int buff_len)
+{
+ omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev;
+ struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->dsscomp_data;
+ int len = 0;
+ int i;
+
+ len = dump_printf(buff, buff_len, len, "omap4_hwc %d:\n", dsscomp->num_ovls);
+
+ for (i = 0; i < dsscomp->num_ovls; i++) {
+ struct dss2_ovl_cfg *cfg = &dsscomp->ovls[i].cfg;
+
+ len = dump_printf(buff, buff_len, len, " layer %d:\n", i);
+ len = dump_printf(buff, buff_len, len, " enabled: %s\n",
+ cfg->enabled ? "true" : "false");
+ len = dump_printf(buff, buff_len, len, " buff: %dx%d stride: %d:\n",
+ cfg->width, cfg->height, cfg->stride);
+ len = dump_printf(buff, buff_len, len, " src: (%d,%d) %dx%d\n",
+ cfg->crop.x, cfg->crop.y, cfg->crop.w, cfg->crop.h);
+ len = dump_printf(buff, buff_len, len, " dst: (%d,%d) %dx%d\n",
+ cfg->win.x, cfg->win.y, cfg->win.w, cfg->win.h);
+ len = dump_printf(buff, buff_len, len, " ix: %d\n", cfg->ix);
+ len = dump_printf(buff, buff_len, len, " zorder: %d\n\n", cfg->zorder);
+
+ }
+}
+
+
+static int omap4_hwc_device_close(hw_device_t* device)
+{
+ omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) device;;
+
+ if (hwc_dev)
+ free(hwc_dev);
+
+ return 0;
+}
+
+static int omap4_hwc_open_fb_hal(IMG_framebuffer_device_public_t **fb_dev)
+{
+ IMG_gralloc_module_public_t *psGrallocModule;
+ int err;
+
+ err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t**)&psGrallocModule);
+ if(err)
+ goto err_out;
+
+ if(strcmp(psGrallocModule->base.common.author,
+ "Imagination Technologies"))
+ {
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ *fb_dev = psGrallocModule->psFrameBufferDevice;
+
+ return 0;
+
+err_out:
+ LOGE("Composer HAL failed to load compatible Graphics HAL");
+ return err;
+}
+
+static int omap4_hwc_device_open(const hw_module_t* module, const char* name,
+ hw_device_t** device)
+{
+ omap4_hwc_module_t *hwc_mod = (omap4_hwc_module_t *)module;
+ omap4_hwc_device_t *hwc_dev;
+ int err;
+
+ if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
+ return -EINVAL;
+ }
+
+ if (!hwc_mod->fb_dev) {
+ err = omap4_hwc_open_fb_hal(&hwc_mod->fb_dev);
+ if (err)
+ return err;
+
+ if (!hwc_mod->fb_dev) {
+ LOGE("Framebuffer HAL not opened before HWC");
+ return -EFAULT;
+ }
+ hwc_mod->fb_dev->bBypassPost = 1;
+ }
+
+ hwc_dev = (omap4_hwc_device_t *)malloc(sizeof(*hwc_dev));
+ if (hwc_dev == NULL)
+ return -ENOMEM;
+
+ memset(hwc_dev, 0, sizeof(*hwc_dev));
+
+ hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG;
+ hwc_dev->base.common.version = HWC_API_VERSION;
+ hwc_dev->base.common.module = (hw_module_t *)module;
+ hwc_dev->base.common.close = omap4_hwc_device_close;
+ hwc_dev->base.prepare = omap4_hwc_prepare;
+ hwc_dev->base.set = omap4_hwc_set;
+ hwc_dev->base.dump = omap4_hwc_dump;
+ hwc_dev->fb_dev = hwc_mod->fb_dev;
+ *device = &hwc_dev->base.common;
+
+ hwc_dev->buffers = malloc(sizeof(buffer_handle_t) * MAX_HW_OVERLAYS);
+ if (!hwc_dev->buffers) {
+ free(hwc_dev);
+ return -ENOMEM;
+ }
+
+ /* get debug properties */
+
+ /* see if hwc is enabled at all */
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.hwc.rgb_order", value, "1");
+ hwc_dev->flags_rgb_order = atoi(value);
+ property_get("debug.hwc.nv12_only", value, "0");
+ hwc_dev->flags_nv12_only = atoi(value);
+ LOGE("omap4_hwc_device_open(rgb_order=%d nv12_only=%d)",
+ hwc_dev->flags_rgb_order, hwc_dev->flags_nv12_only);
+
+ return 0;
+}
+
+static struct hw_module_methods_t omap4_hwc_module_methods = {
+ .open = omap4_hwc_device_open,
+};
+
+omap4_hwc_module_t HAL_MODULE_INFO_SYM = {
+ .base = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = HWC_HARDWARE_MODULE_ID,
+ .name = "OMAP 44xx Hardware Composer HAL",
+ .author = "Texas Instruments",
+ .methods = &omap4_hwc_module_methods,
+ },
+ },
+};
diff --git a/ion/Android.mk b/ion/Android.mk
new file mode 100644
index 0000000..c9bf668
--- /dev/null
+++ b/ion/Android.mk
@@ -0,0 +1,20 @@
+# only include if running on an omap4 platform
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := ion.c
+LOCAL_MODULE := libion
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := liblog
+include $(BUILD_HEAPTRACKED_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := ion.c ion_test.c
+LOCAL_MODULE := iontest
+LOCAL_MODULE_TAGS := optional tests
+LOCAL_SHARED_LIBRARIES := liblog
+include $(BUILD_HEAPTRACKED_EXECUTABLE)
+
+endif
diff --git a/ion/ion.c b/ion/ion.c
new file mode 100644
index 0000000..08e4570
--- /dev/null
+++ b/ion/ion.c
@@ -0,0 +1,156 @@
+/*
+ * ion.c
+ *
+ * Memory Allocator functions for ion
+ *
+ * Copyright 2011 Google, Inc
+ *
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#define LOG_TAG "ion"
+#include <cutils/log.h>
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+#include "ion.h"
+
+int ion_open()
+{
+ int fd = open("/dev/ion", O_RDWR);
+ if (fd < 0)
+ LOGE("open /dev/ion failed!\n");
+ return fd;
+}
+
+int ion_close(int fd)
+{
+ return close(fd);
+}
+
+int ion_ioctl(int fd, int req, void *arg)
+{
+ int ret = ioctl(fd, req, arg);
+ if (ret < 0) {
+ LOGE("ioctl %d failed with code %d: %s\n", req,
+ ret, strerror(errno));
+ return -errno;
+ }
+ return ret;
+}
+
+int ion_alloc(int fd, size_t len, size_t align, unsigned int flags,
+ struct ion_handle **handle)
+{
+ int ret;
+ struct ion_allocation_data data = {
+ .len = len,
+ .align = align,
+ .flags = flags,
+ };
+
+ ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
+ if (ret < 0)
+ return ret;
+ *handle = data.handle;
+ return ret;
+}
+
+int ion_alloc_tiler(int fd, size_t w, size_t h, int fmt, unsigned int flags,
+ struct ion_handle **handle, size_t *stride)
+{
+ int ret;
+ struct omap_ion_tiler_alloc_data alloc_data = {
+ .w = w,
+ .h = h,
+ .fmt = fmt,
+ .flags = flags,
+ };
+
+ struct ion_custom_data custom_data = {
+ .cmd = OMAP_ION_TILER_ALLOC,
+ .arg = (unsigned long)(&alloc_data),
+ };
+
+ ret = ion_ioctl(fd, ION_IOC_CUSTOM, &custom_data);
+ if (ret < 0)
+ return ret;
+ *stride = alloc_data.stride;
+ *handle = alloc_data.handle;
+ return ret;
+}
+
+int ion_free(int fd, struct ion_handle *handle)
+{
+ struct ion_handle_data data = {
+ .handle = handle,
+ };
+ return ion_ioctl(fd, ION_IOC_FREE, &data);
+}
+
+int ion_map(int fd, struct ion_handle *handle, size_t length, int prot,
+ int flags, off_t offset, unsigned char **ptr, int *map_fd)
+{
+ struct ion_fd_data data = {
+ .handle = handle,
+ };
+ int ret = ion_ioctl(fd, ION_IOC_MAP, &data);
+ if (ret < 0)
+ return ret;
+ *map_fd = data.fd;
+ if (*map_fd < 0) {
+ LOGE("map ioctl returned negative fd\n");
+ return -EINVAL;
+ }
+ *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
+ if (*ptr == MAP_FAILED) {
+ LOGE("mmap failed: %s\n", strerror(errno));
+ return -errno;
+ }
+ return ret;
+}
+
+int ion_share(int fd, struct ion_handle *handle, int *share_fd)
+{
+ int map_fd;
+ struct ion_fd_data data = {
+ .handle = handle,
+ };
+ int ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
+ if (ret < 0)
+ return ret;
+ *share_fd = data.fd;
+ if (*share_fd < 0) {
+ LOGE("map ioctl returned negative fd\n");
+ return -EINVAL;
+ }
+ return ret;
+}
+
+int ion_import(int fd, int share_fd, struct ion_handle **handle)
+{
+ struct ion_fd_data data = {
+ .fd = share_fd,
+ };
+ int ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
+ if (ret < 0)
+ return ret;
+ *handle = data.handle;
+ return ret;
+}
diff --git a/ion/ion.h b/ion/ion.h
new file mode 100644
index 0000000..871b9bc
--- /dev/null
+++ b/ion/ion.h
@@ -0,0 +1,35 @@
+/*
+ * ion.c
+ *
+ * Memory Allocator functions for ion
+ *
+ * Copyright 2011 Google, Inc
+ *
+ * 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 <linux/ion.h>
+#include <linux/omap_ion.h>
+
+int ion_open();
+int ion_close(int fd);
+int ion_alloc(int fd, size_t len, size_t align, unsigned int flags,
+ struct ion_handle **handle);
+int ion_alloc_tiler(int fd, size_t w, size_t h, int fmt, unsigned int flags,
+ struct ion_handle **handle, size_t *stride);
+int ion_free(int fd, struct ion_handle *handle);
+int ion_map(int fd, struct ion_handle *handle, size_t length, int prot,
+ int flags, off_t offset, unsigned char **ptr, int *map_fd);
+int ion_share(int fd, struct ion_handle *handle, int *share_fd);
+int ion_import(int fd, int share_fd, struct ion_handle **handle);
+
diff --git a/ion/ion_test.c b/ion/ion_test.c
new file mode 100644
index 0000000..734caca
--- /dev/null
+++ b/ion/ion_test.c
@@ -0,0 +1,321 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "ion.h"
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+
+size_t len = 1024*1024, align = 0;
+int prot = PROT_READ | PROT_WRITE;
+int map_flags = MAP_SHARED;
+int alloc_flags = 0;
+int test = -1;
+size_t width = 1024*1024, height = 1024*1024;
+int fmt = TILER_PIXEL_FMT_32BIT;
+int tiler_test = 0;
+size_t stride;
+
+int _ion_alloc_test(int *fd, struct ion_handle **handle)
+{
+ int ret;
+
+ *fd = ion_open();
+ if (*fd < 0)
+ return *fd;
+
+ if (tiler_test)
+ ret = ion_alloc_tiler(*fd, width, height, fmt, alloc_flags,
+ handle, &stride);
+ else
+ ret = ion_alloc(*fd, len, align, alloc_flags, handle);
+
+ if (ret)
+ printf("%s failed: %s\n", __func__, strerror(ret));
+ return ret;
+}
+
+void ion_alloc_test()
+{
+ int fd, ret;
+ struct ion_handle *handle;
+
+ if(_ion_alloc_test(&fd, &handle))
+ return;
+
+ ret = ion_free(fd, handle);
+ if (ret) {
+ printf("%s failed: %s %p\n", __func__, strerror(ret), handle);
+ return;
+ }
+ ion_close(fd);
+ printf("ion alloc test: passed\n");
+}
+
+void _ion_tiler_map_test(unsigned char *ptr)
+{
+ size_t row, col;
+
+ for (row = 0; row < height; row++)
+ for (col = 0; col < width; col++) {
+ int i = (row * stride) + col;
+ ptr[i] = (unsigned char)i;
+ }
+ for (row = 0; row < height; row++)
+ for (col = 0; col < width; col++) {
+ int i = (row * stride) + col;
+ if (ptr[i] != (unsigned char)i)
+ printf("%s failed wrote %d read %d from mapped "
+ "memory\n", __func__, i, ptr[i]);
+ }
+}
+
+
+void ion_map_test()
+{
+ int fd, map_fd, ret;
+ size_t i;
+ struct ion_handle *handle;
+ unsigned char *ptr;
+
+ if(_ion_alloc_test(&fd, &handle))
+ return;
+
+ if (tiler_test)
+ len = height * stride;
+ ret = ion_map(fd, handle, len, prot, map_flags, 0, &ptr, &map_fd);
+ if (ret)
+ return;
+
+ if (tiler_test)
+ _ion_tiler_map_test(ptr);
+ else {
+ for (i = 0; i < len; i++) {
+ ptr[i] = (unsigned char)i;
+ }
+ for (i = 0; i < len; i++)
+ if (ptr[i] != (unsigned char)i)
+ printf("%s failed wrote %d read %d from mapped "
+ "memory\n", __func__, i, ptr[i]);
+ }
+ /* clean up properly */
+ ret = ion_free(fd, handle);
+ ion_close(fd);
+ munmap(ptr, len);
+ close(map_fd);
+
+ _ion_alloc_test(&fd, &handle);
+ close(fd);
+
+#if 0
+ munmap(ptr, len);
+ close(map_fd);
+ ion_close(fd);
+
+ _ion_alloc_test(len, align, flags, &fd, &handle);
+ close(map_fd);
+ ret = ion_map(fd, handle, len, prot, flags, 0, &ptr, &map_fd);
+ /* don't clean up */
+#endif
+}
+
+void ion_share_test()
+
+{
+ struct ion_handle *handle;
+ int sd[2];
+ int num_fd = 1;
+ struct iovec count_vec = {
+ .iov_base = &num_fd,
+ .iov_len = sizeof num_fd,
+ };
+ char buf[CMSG_SPACE(sizeof(int))];
+ socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
+ if (fork()) {
+ struct msghdr msg = {
+ .msg_control = buf,
+ .msg_controllen = sizeof buf,
+ .msg_iov = &count_vec,
+ .msg_iovlen = 1,
+ };
+
+ struct cmsghdr *cmsg;
+ int fd, share_fd, ret;
+ char *ptr;
+ /* parent */
+ if(_ion_alloc_test(&fd, &handle))
+ return;
+ ret = ion_share(fd, handle, &share_fd);
+ if (ret)
+ printf("share failed %s\n", strerror(errno));
+ ptr = mmap(NULL, len, prot, map_flags, share_fd, 0);
+ if (ptr == MAP_FAILED) {
+ return;
+ }
+ strcpy(ptr, "master");
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ *(int *)CMSG_DATA(cmsg) = share_fd;
+ /* send the fd */
+ printf("master? [%10s] should be [master]\n", ptr);
+ printf("master sending msg 1\n");
+ sendmsg(sd[0], &msg, 0);
+ if (recvmsg(sd[0], &msg, 0) < 0)
+ perror("master recv msg 2");
+ printf("master? [%10s] should be [child]\n", ptr);
+
+ /* send ping */
+ sendmsg(sd[0], &msg, 0);
+ printf("master->master? [%10s]\n", ptr);
+ if (recvmsg(sd[0], &msg, 0) < 0)
+ perror("master recv 1");
+ } else {
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ char* ptr;
+ int fd, recv_fd;
+ char* child_buf[100];
+ /* child */
+ struct iovec count_vec = {
+ .iov_base = child_buf,
+ .iov_len = sizeof child_buf,
+ };
+
+ struct msghdr child_msg = {
+ .msg_control = buf,
+ .msg_controllen = sizeof buf,
+ .msg_iov = &count_vec,
+ .msg_iovlen = 1,
+ };
+
+ if (recvmsg(sd[1], &child_msg, 0) < 0)
+ perror("child recv msg 1");
+ cmsg = CMSG_FIRSTHDR(&child_msg);
+ if (cmsg == NULL) {
+ printf("no cmsg rcvd in child");
+ return;
+ }
+ recv_fd = *(int*)CMSG_DATA(cmsg);
+ if (recv_fd < 0) {
+ printf("could not get recv_fd from socket");
+ return;
+ }
+ printf("child %d\n", recv_fd);
+ fd = ion_open();
+ ptr = mmap(NULL, len, prot, map_flags, recv_fd, 0);
+ if (ptr == MAP_FAILED) {
+ return;
+ }
+ printf("child? [%10s] should be [master]\n", ptr);
+ strcpy(ptr, "child");
+ printf("child sending msg 2\n");
+ sendmsg(sd[1], &child_msg, 0);
+ }
+}
+
+int main(int argc, char* argv[]) {
+ int c;
+ enum tests {
+ ALLOC_TEST = 0, MAP_TEST, SHARE_TEST,
+ };
+
+ while (1) {
+ static struct option opts[] = {
+ {"alloc", no_argument, 0, 'a'},
+ {"alloc_flags", required_argument, 0, 'f'},
+ {"map", no_argument, 0, 'm'},
+ {"share", no_argument, 0, 's'},
+ {"len", required_argument, 0, 'l'},
+ {"align", required_argument, 0, 'g'},
+ {"map_flags", required_argument, 0, 'z'},
+ {"prot", required_argument, 0, 'p'},
+ {"alloc_tiler", no_argument, 0, 't'},
+ {"width", required_argument, 0, 'w'},
+ {"height", required_argument, 0, 'h'},
+ {"fmt", required_argument, 0, 'r'},
+ };
+ int i = 0;
+ c = getopt_long(argc, argv, "af:h:l:mr:stw:", opts, &i);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'l':
+ len = atol(optarg);
+ break;
+ case 'g':
+ align = atol(optarg);
+ break;
+ case 'z':
+ map_flags = 0;
+ map_flags |= strstr(optarg, "PROT_EXEC") ?
+ PROT_EXEC : 0;
+ map_flags |= strstr(optarg, "PROT_READ") ?
+ PROT_READ: 0;
+ map_flags |= strstr(optarg, "PROT_WRITE") ?
+ PROT_WRITE: 0;
+ map_flags |= strstr(optarg, "PROT_NONE") ?
+ PROT_NONE: 0;
+ break;
+ case 'p':
+ prot = 0;
+ prot |= strstr(optarg, "MAP_PRIVATE") ?
+ MAP_PRIVATE : 0;
+ prot |= strstr(optarg, "MAP_SHARED") ?
+ MAP_PRIVATE : 0;
+ break;
+ case 'f':
+ alloc_flags = atol(optarg);
+ break;
+ case 'a':
+ test = ALLOC_TEST;
+ break;
+ case 'm':
+ test = MAP_TEST;
+ break;
+ case 'r':
+ fmt = atol(optarg);
+ break;
+ case 's':
+ test = SHARE_TEST;
+ break;
+ case 'w':
+ width = atol(optarg);
+ break;
+ case 'h':
+ height = atol(optarg);
+ break;
+ case 't':
+ tiler_test = 1;
+ break;
+ }
+ }
+ printf("test %d, len %u, width %u, height %u fmt %u align %u, "
+ "map_flags %d, prot %d, alloc_flags %d\n", test, len, width,
+ height, fmt, align, map_flags, prot, alloc_flags);
+ switch (test) {
+ case ALLOC_TEST:
+ ion_alloc_test();
+ break;
+ case MAP_TEST:
+ ion_map_test();
+ break;
+ case SHARE_TEST:
+ ion_share_test();
+ break;
+ default:
+ printf("must specify a test (alloc, map, share)\n");
+ }
+ return 0;
+}
diff --git a/libstagefrighthw/Android.mk b/libstagefrighthw/Android.mk
new file mode 100644
index 0000000..c1757f2
--- /dev/null
+++ b/libstagefrighthw/Android.mk
@@ -0,0 +1,23 @@
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ TIOMXPlugin.cpp
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/include/media/stagefright/openmax
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libutils \
+ libcutils \
+ libui \
+ libdl \
+
+LOCAL_MODULE := libstagefrighthw
+
+include $(BUILD_HEAPTRACKED_SHARED_LIBRARY)
+
+endif
diff --git a/libstagefrighthw/TIOMXPlugin.cpp b/libstagefrighthw/TIOMXPlugin.cpp
new file mode 100644
index 0000000..14c5e91
--- /dev/null
+++ b/libstagefrighthw/TIOMXPlugin.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2009 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 "TIOMXPlugin.h"
+
+#include <dlfcn.h>
+
+#include <media/stagefright/HardwareAPI.h>
+#include <media/stagefright/MediaDebug.h>
+
+namespace android {
+
+extern "C" OMXPluginBase *createOMXPlugin() {
+ return new TIOMXPlugin;
+}
+
+extern "C" void destroyOMXPlugin(OMXPluginBase *plugin) {
+ delete plugin;
+}
+
+#define LIBOMX "libOMX_Core.so"
+
+TIOMXPlugin::TIOMXPlugin()
+ : mLibHandle(dlopen(LIBOMX, RTLD_NOW)),
+ mInit(NULL),
+ mDeinit(NULL),
+ mComponentNameEnum(NULL),
+ mGetHandle(NULL),
+ mFreeHandle(NULL),
+ mGetRolesOfComponentHandle(NULL) {
+ if (mLibHandle != NULL) {
+ mInit = (InitFunc)dlsym(mLibHandle, "TIOMX_Init");
+ mDeinit = (DeinitFunc)dlsym(mLibHandle, "TIOMX_DeInit");
+
+ mComponentNameEnum =
+ (ComponentNameEnumFunc)dlsym(mLibHandle, "TIOMX_ComponentNameEnum");
+
+ mGetHandle = (GetHandleFunc)dlsym(mLibHandle, "TIOMX_GetHandle");
+ mFreeHandle = (FreeHandleFunc)dlsym(mLibHandle, "TIOMX_FreeHandle");
+
+ mGetRolesOfComponentHandle =
+ (GetRolesOfComponentFunc)dlsym(
+ mLibHandle, "TIOMX_GetRolesOfComponent");
+
+ (*mInit)();
+ }
+ else
+ LOGE("%s: failed to load %s", __func__, LIBOMX);
+}
+
+TIOMXPlugin::~TIOMXPlugin() {
+ if (mLibHandle != NULL) {
+ (*mDeinit)();
+
+ dlclose(mLibHandle);
+ mLibHandle = NULL;
+ }
+}
+
+OMX_ERRORTYPE TIOMXPlugin::makeComponentInstance(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component) {
+ if (mLibHandle == NULL) {
+ return OMX_ErrorUndefined;
+ }
+
+ return (*mGetHandle)(
+ reinterpret_cast<OMX_HANDLETYPE *>(component),
+ const_cast<char *>(name),
+ appData, const_cast<OMX_CALLBACKTYPE *>(callbacks));
+}
+
+OMX_ERRORTYPE TIOMXPlugin::destroyComponentInstance(
+ OMX_COMPONENTTYPE *component) {
+ if (mLibHandle == NULL) {
+ return OMX_ErrorUndefined;
+ }
+
+ return (*mFreeHandle)(reinterpret_cast<OMX_HANDLETYPE *>(component));
+}
+
+OMX_ERRORTYPE TIOMXPlugin::enumerateComponents(
+ OMX_STRING name,
+ size_t size,
+ OMX_U32 index) {
+ if (mLibHandle == NULL) {
+ LOGE("mLibHandle is NULL!");
+ return OMX_ErrorUndefined;
+ }
+
+ return (*mComponentNameEnum)(name, size, index);
+}
+
+OMX_ERRORTYPE TIOMXPlugin::getRolesOfComponent(
+ const char *name,
+ Vector<String8> *roles) {
+ roles->clear();
+
+ if (mLibHandle == NULL) {
+ return OMX_ErrorUndefined;
+ }
+
+ OMX_U32 numRoles;
+ OMX_ERRORTYPE err = (*mGetRolesOfComponentHandle)(
+ const_cast<OMX_STRING>(name), &numRoles, NULL);
+
+ if (err != OMX_ErrorNone) {
+ return err;
+ }
+
+ if (numRoles > 0) {
+ OMX_U8 **array = new OMX_U8 *[numRoles];
+ for (OMX_U32 i = 0; i < numRoles; ++i) {
+ array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE];
+ }
+
+ err = (*mGetRolesOfComponentHandle)(
+ const_cast<OMX_STRING>(name), &numRoles, array);
+
+ CHECK_EQ(err, OMX_ErrorNone);
+
+ for (OMX_U32 i = 0; i < numRoles; ++i) {
+ String8 s((const char *)array[i]);
+ roles->push(s);
+
+ delete[] array[i];
+ array[i] = NULL;
+ }
+
+ delete[] array;
+ array = NULL;
+ }
+
+ return OMX_ErrorNone;
+}
+
+} // namespace android
diff --git a/libstagefrighthw/TIOMXPlugin.h b/libstagefrighthw/TIOMXPlugin.h
new file mode 100644
index 0000000..668c5ef
--- /dev/null
+++ b/libstagefrighthw/TIOMXPlugin.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 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 TI_OMX_PLUGIN_H_
+
+#define TI_OMX_PLUGIN_H_
+
+#include <media/stagefright/OMXPluginBase.h>
+
+namespace android {
+
+struct TIOMXPlugin : public OMXPluginBase {
+ TIOMXPlugin();
+ virtual ~TIOMXPlugin();
+
+ virtual OMX_ERRORTYPE makeComponentInstance(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+ virtual OMX_ERRORTYPE destroyComponentInstance(
+ OMX_COMPONENTTYPE *component);
+
+ virtual OMX_ERRORTYPE enumerateComponents(
+ OMX_STRING name,
+ size_t size,
+ OMX_U32 index);
+
+ virtual OMX_ERRORTYPE getRolesOfComponent(
+ const char *name,
+ Vector<String8> *roles);
+
+private:
+ void *mLibHandle;
+
+ typedef OMX_ERRORTYPE (*InitFunc)();
+ typedef OMX_ERRORTYPE (*DeinitFunc)();
+ typedef OMX_ERRORTYPE (*ComponentNameEnumFunc)(
+ OMX_STRING, OMX_U32, OMX_U32);
+
+ typedef OMX_ERRORTYPE (*GetHandleFunc)(
+ OMX_HANDLETYPE *, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE *);
+
+ typedef OMX_ERRORTYPE (*FreeHandleFunc)(OMX_HANDLETYPE *);
+
+ typedef OMX_ERRORTYPE (*GetRolesOfComponentFunc)(
+ OMX_STRING, OMX_U32 *, OMX_U8 **);
+
+ InitFunc mInit;
+ DeinitFunc mDeinit;
+ ComponentNameEnumFunc mComponentNameEnum;
+ GetHandleFunc mGetHandle;
+ FreeHandleFunc mFreeHandle;
+ GetRolesOfComponentFunc mGetRolesOfComponentHandle;
+
+ TIOMXPlugin(const TIOMXPlugin &);
+ TIOMXPlugin &operator=(const TIOMXPlugin &);
+};
+
+} // namespace android
+
+#endif // TI_OMX_PLUGIN_H_
diff --git a/libtiutils/Android.mk b/libtiutils/Android.mk
new file mode 100755
index 0000000..7312222
--- /dev/null
+++ b/libtiutils/Android.mk
@@ -0,0 +1,35 @@
+################################################
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES:= \
+ MessageQueue.cpp \
+ Semaphore.cpp \
+ ErrorUtils.cpp
+
+LOCAL_SHARED_LIBRARIES:= \
+ libdl \
+ libui \
+ libbinder \
+ libutils \
+ libcutils
+
+LOCAL_C_INCLUDES += \
+ kernel/android-2.6.29/include \
+ frameworks/base/include/utils \
+ bionic/libc/include \
+ hardware/ti/omap4xxx/domx/omx_core/inc \
+ hardware/ti/omap4xxx/domx/mm_osal/inc
+
+LOCAL_CFLAGS += -fno-short-enums
+
+# LOCAL_CFLAGS +=
+
+LOCAL_MODULE:= libtiutils
+LOCAL_MODULE_TAGS:= optional
+
+include $(BUILD_HEAPTRACKED_SHARED_LIBRARY)
diff --git a/libtiutils/DebugUtils.h b/libtiutils/DebugUtils.h
new file mode 100644
index 0000000..54edfc7
--- /dev/null
+++ b/libtiutils/DebugUtils.h
@@ -0,0 +1,36 @@
+/*
+ * 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 DEBUG_UTILS_H
+#define DEBUG_UTILS_H
+
+///Defines for debug statements - Macro LOG_TAG needs to be defined in the respective files
+#define DBGUTILS_LOGVA(str) LOGV("%s:%d %s - " str,__FILE__, __LINE__,__FUNCTION__);
+#define DBGUTILS_LOGVB(str,...) LOGV("%s:%d %s - " str,__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);
+#define DBGUTILS_LOGDA(str) LOGD("%s:%d %s - " str,__FILE__, __LINE__,__FUNCTION__);
+#define DBGUTILS_LOGDB(str, ...) LOGD("%s:%d %s - " str,__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);
+#define DBGUTILS_LOGEA(str) LOGE("%s:%d %s - " str,__FILE__, __LINE__, __FUNCTION__);
+#define DBGUTILS_LOGEB(str, ...) LOGE("%s:%d %s - " str,__FILE__, __LINE__,__FUNCTION__, __VA_ARGS__);
+#define LOG_FUNCTION_NAME LOGV("%d: %s() ENTER", __LINE__, __FUNCTION__);
+#define LOG_FUNCTION_NAME_EXIT LOGV("%d: %s() EXIT", __LINE__, __FUNCTION__);
+
+
+
+
+#endif //DEBUG_UTILS_H
+
diff --git a/libtiutils/ErrorUtils.cpp b/libtiutils/ErrorUtils.cpp
new file mode 100644
index 0000000..df0e51c
--- /dev/null
+++ b/libtiutils/ErrorUtils.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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"
+
+namespace android {
+
+/**
+ @brief Method to convert from POSIX to Android errors
+
+ @param error Any of the standard POSIX error codes (defined in bionic/libc/kernel/common/asm-generic/errno.h)
+ @return Any of the standard Android error code (defined in frameworks/base/include/utils/Errors.h)
+ */
+status_t ErrorUtils::posixToAndroidError(int error)
+{
+ switch(error)
+ {
+ case 0:
+ return NO_ERROR;
+ case EINVAL:
+ case EFBIG:
+ case EMSGSIZE:
+ case E2BIG:
+ case EFAULT:
+ case EILSEQ:
+ return BAD_VALUE;
+ case ENOSYS:
+ return INVALID_OPERATION;
+ case EACCES:
+ case EPERM:
+ return PERMISSION_DENIED;
+ case EADDRINUSE:
+ case EAGAIN:
+ case EALREADY:
+ case EBUSY:
+ case EEXIST:
+ case EINPROGRESS:
+ return ALREADY_EXISTS;
+ case ENOMEM:
+ return NO_MEMORY;
+ default:
+ return UNKNOWN_ERROR;
+ };
+
+ return NO_ERROR;
+}
+
+
+/**
+ @brief Method to convert from TI OSAL to Android errors
+
+ @param error Any of the standard TI OSAL error codes (defined in
+ hardware/ti/omx/ducati/domx/system/mm_osal/inc/timm_osal_error.h)
+ @return Any of the standard Android error code (defined in frameworks/base/include/utils/Errors.h)
+ */
+status_t ErrorUtils::osalToAndroidError(TIMM_OSAL_ERRORTYPE error)
+{
+ switch(error)
+ {
+ case TIMM_OSAL_ERR_NONE:
+ return NO_ERROR;
+ case TIMM_OSAL_ERR_ALLOC:
+ return NO_MEMORY;
+ default:
+ return UNKNOWN_ERROR;
+ }
+
+ return NO_ERROR;
+}
+
+/**
+ @brief Method to convert from OMX to Android errors
+
+ @param error Any of the standard OMX error codes (defined in hardware/ti/omx/ducati/domx/system/omx_core/inc/OMX_Core.h)
+ @return Any of the standard Android error code (defined in frameworks/base/include/utils/Errors.h)
+ */
+status_t ErrorUtils::omxToAndroidError(OMX_ERRORTYPE error)
+{
+ switch(error)
+ {
+ case OMX_ErrorNone:
+ return NO_ERROR;
+ case OMX_ErrorBadParameter:
+ case OMX_ErrorInvalidComponentName:
+ case OMX_ErrorUndefined:
+ case OMX_ErrorInvalidState:
+ case OMX_ErrorStreamCorrupt:
+ case OMX_ErrorPortsNotCompatible:
+ case OMX_ErrorVersionMismatch:
+ case OMX_ErrorMbErrorsInFrame:
+ return BAD_VALUE;
+ case OMX_ErrorInsufficientResources:
+ return NO_MEMORY;
+ case OMX_ErrorComponentNotFound:
+ case OMX_ErrorNotImplemented:
+ case OMX_ErrorFormatNotDetected:
+ case OMX_ErrorUnsupportedSetting:
+ return NAME_NOT_FOUND;
+ case OMX_ErrorUnderflow:
+ case OMX_ErrorOverflow:
+ case OMX_ErrorUnsupportedIndex:
+ case OMX_ErrorBadPortIndex:
+ return BAD_INDEX;
+ case OMX_ErrorHardware:
+ case OMX_ErrorContentPipeCreationFailed:
+ case OMX_ErrorContentPipeOpenFailed:
+ return FAILED_TRANSACTION;
+ case OMX_ErrorTimeout:
+ return TIMED_OUT;
+ case OMX_ErrorSameState:
+ case OMX_ErrorIncorrectStateTransition:
+ case OMX_ErrorIncorrectStateOperation:
+ return PERMISSION_DENIED;
+ case OMX_ErrorTunnelingUnsupported:
+ return INVALID_OPERATION;
+ default:
+ return UNKNOWN_ERROR;
+ }
+
+ return NO_ERROR;
+}
+
+
+};
+
+
+
diff --git a/libtiutils/ErrorUtils.h b/libtiutils/ErrorUtils.h
new file mode 100644
index 0000000..24dd806
--- /dev/null
+++ b/libtiutils/ErrorUtils.h
@@ -0,0 +1,52 @@
+/*
+ * 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 ERROR_UTILS_H
+#define ERROR_UTILS_H
+
+///Header file where all the android error codes are defined
+#include <Errors.h>
+
+///Header file where all the OMX error codes are defined
+#include "OMX_Core.h"
+
+
+extern "C"
+{
+///Header file where all the TI OSAL error codes are defined
+#include "timm_osal_error.h"
+};
+
+namespace android {
+
+///Generic class with static methods to convert any standard error type to Android error type
+class ErrorUtils
+{
+public:
+ ///Method to convert from POSIX to Android errors
+ static status_t posixToAndroidError(int error);
+
+ ///Method to convert from TI OSAL to Android errors
+ static status_t osalToAndroidError(TIMM_OSAL_ERRORTYPE error);
+
+ ///Method to convert from OMX to Android errors
+ static status_t omxToAndroidError(OMX_ERRORTYPE error);
+
+};
+
+};
+
+#endif /// ERROR_UTILS_H
diff --git a/libtiutils/MessageQueue.cpp b/libtiutils/MessageQueue.cpp
new file mode 100755
index 0000000..1a5942a
--- /dev/null
+++ b/libtiutils/MessageQueue.cpp
@@ -0,0 +1,397 @@
+/*
+ * 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 <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <Errors.h>
+
+
+
+#define LOG_TAG "MessageQueue"
+#include <utils/Log.h>
+
+#include "MessageQueue.h"
+
+namespace TIUTILS {
+
+/**
+ @brief Constructor for the message queue class
+
+ @param none
+ @return none
+ */
+MessageQueue::MessageQueue()
+{
+ LOG_FUNCTION_NAME;
+
+ int fds[2] = {-1,-1};
+ android::status_t stat;
+
+ stat = pipe(fds);
+
+ if ( 0 > stat )
+ {
+ MSGQ_LOGEB("Error while openning pipe: %s", strerror(stat) );
+ this->fd_read = 0;
+ this->fd_write = 0;
+ mHasMsg = false;
+ }
+ else
+ {
+ this->fd_read = fds[0];
+ this->fd_write = fds[1];
+
+ mHasMsg = false;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Destructor for the semaphore class
+
+ @param none
+ @return none
+ */
+MessageQueue::~MessageQueue()
+{
+ LOG_FUNCTION_NAME;
+
+ if(this->fd_read)
+ {
+ close(this->fd_read);
+ }
+
+ if(this->fd_write)
+ {
+ close(this->fd_write);
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Get a message from the queue
+
+ @param msg Message structure to hold the message to be retrieved
+ @return android::NO_ERROR On success
+ @return android::BAD_VALUE if the message pointer is NULL
+ @return android::NO_INIT If the file read descriptor is not set
+ @return android::UNKNOWN_ERROR if the read operation fromthe file read descriptor fails
+ */
+android::status_t MessageQueue::get(Message* msg)
+{
+ LOG_FUNCTION_NAME;
+
+ if(!msg)
+ {
+ MSGQ_LOGEA("msg is NULL");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::BAD_VALUE;
+ }
+
+ if(!this->fd_read)
+ {
+ MSGQ_LOGEA("read descriptor not initialized for message queue");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::NO_INIT;
+ }
+
+ char* p = (char*) msg;
+ size_t read_bytes = 0;
+
+ while( read_bytes < sizeof(*msg) )
+ {
+ int err = read(this->fd_read, p, sizeof(*msg) - read_bytes);
+
+ if( err < 0 )
+ {
+ MSGQ_LOGEB("read() error: %s", strerror(errno));
+ return android::UNKNOWN_ERROR;
+ }
+ else
+ {
+ read_bytes += err;
+ }
+ }
+
+ MSGQ_LOGDB("MQ.get(%d,%p,%p,%p,%p)", msg->command, msg->arg1,msg->arg2,msg->arg3,msg->arg4);
+
+ mHasMsg = false;
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return 0;
+}
+
+/**
+ @brief Get the input file descriptor of the message queue
+
+ @param none
+ @return file read descriptor
+ */
+
+int MessageQueue::getInFd()
+{
+ return this->fd_read;
+}
+
+/**
+ @brief Constructor for the message queue class
+
+ @param fd file read descriptor
+ @return none
+ */
+
+void MessageQueue::setInFd(int fd)
+{
+ LOG_FUNCTION_NAME;
+
+ if ( -1 != this->fd_read )
+ {
+ close(this->fd_read);
+ }
+
+ this->fd_read = fd;
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+/**
+ @brief Queue a message
+
+ @param msg Message structure to hold the message to be retrieved
+ @return android::NO_ERROR On success
+ @return android::BAD_VALUE if the message pointer is NULL
+ @return android::NO_INIT If the file write descriptor is not set
+ @return android::UNKNOWN_ERROR if the write operation fromthe file write descriptor fails
+ */
+
+android::status_t MessageQueue::put(Message* msg)
+{
+ LOG_FUNCTION_NAME;
+
+ char* p = (char*) msg;
+ size_t bytes = 0;
+
+ if(!msg)
+ {
+ MSGQ_LOGEA("msg is NULL");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::BAD_VALUE;
+ }
+
+ if(!this->fd_write)
+ {
+ MSGQ_LOGEA("write descriptor not initialized for message queue");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::NO_INIT;
+ }
+
+
+ MSGQ_LOGDB("MQ.put(%d,%p,%p,%p,%p)", msg->command, msg->arg1,msg->arg2,msg->arg3,msg->arg4);
+
+ while( bytes < sizeof(msg) )
+ {
+ int err = write(this->fd_write, p, sizeof(*msg) - bytes);
+
+ if( err < 0 )
+ {
+ MSGQ_LOGEB("write() error: %s", strerror(errno));
+ LOG_FUNCTION_NAME_EXIT;
+ return android::UNKNOWN_ERROR;
+ }
+ else
+ {
+ bytes += err;
+ }
+ }
+
+ MSGQ_LOGDA("MessageQueue::put EXIT");
+
+ LOG_FUNCTION_NAME_EXIT;
+ return 0;
+}
+
+
+/**
+ @brief Returns if the message queue is empty or not
+
+ @param none
+ @return true If the queue is empty
+ @return false If the queue has at least one message
+ */
+bool MessageQueue::isEmpty()
+{
+ LOG_FUNCTION_NAME;
+
+ struct pollfd pfd;
+
+ pfd.fd = this->fd_read;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ if(!this->fd_read)
+ {
+ MSGQ_LOGEA("read descriptor not initialized for message queue");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::NO_INIT;
+ }
+
+
+ if( -1 == poll(&pfd,1,0) )
+ {
+ MSGQ_LOGEB("poll() error: %s", strerror(errno));
+ LOG_FUNCTION_NAME_EXIT;
+ return false;
+ }
+
+ if(pfd.revents & POLLIN)
+ {
+ mHasMsg = true;
+ }
+ else
+ {
+ mHasMsg = false;
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return !mHasMsg;
+}
+
+/**
+ @brief Force whether the message queue has message or not
+
+ @param hasMsg Whether the queue has a message or not
+ @return none
+ */
+void MessageQueue::setMsg(bool hasMsg)
+ {
+ mHasMsg = hasMsg;
+ }
+
+
+/**
+ @briefWait for message in maximum three different queues with a timeout
+
+ @param queue1 First queue. At least this should be set to a valid queue pointer
+ @param queue2 Second queue. Optional.
+ @param queue3 Third queue. Optional.
+ @param timeout The timeout value (in micro secs) to wait for a message in any of the queues
+ @return android::NO_ERROR On success
+ @return android::BAD_VALUE If queue1 is NULL
+ @return android::NO_INIT If the file read descriptor of any of the provided queues is not set
+ */
+android::status_t MessageQueue::waitForMsg(MessageQueue *queue1, MessageQueue *queue2, MessageQueue *queue3, int timeout)
+ {
+ LOG_FUNCTION_NAME;
+
+ int n =1;
+ struct pollfd pfd[3];
+
+ if(!queue1)
+ {
+ MSGQ_LOGEA("queue1 pointer is NULL");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::BAD_VALUE;
+ }
+
+ pfd[0].fd = queue1->getInFd();
+ if(!pfd[0].fd)
+ {
+ MSGQ_LOGEA("read descriptor not initialized for message queue1");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::NO_INIT;
+ }
+ pfd[0].events = POLLIN;
+ pfd[0].revents = 0;
+ if(queue2)
+ {
+ MSGQ_LOGDA("queue2 not-null");
+ pfd[1].fd = queue2->getInFd();
+ if(!pfd[1].fd)
+ {
+ MSGQ_LOGEA("read descriptor not initialized for message queue2");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::NO_INIT;
+ }
+
+ pfd[1].events = POLLIN;
+ pfd[1].revents = 0;
+ n++;
+ }
+
+ if(queue3)
+ {
+ MSGQ_LOGDA("queue3 not-null");
+ pfd[2].fd = queue3->getInFd();
+ if(!pfd[2].fd)
+ {
+ MSGQ_LOGEA("read descriptor not initialized for message queue3");
+ LOG_FUNCTION_NAME_EXIT;
+ return android::NO_INIT;
+ }
+
+ pfd[2].events = POLLIN;
+ pfd[2].revents = 0;
+ n++;
+ }
+
+
+ int ret = poll(pfd, n, timeout);
+ if(ret==0)
+ {
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+
+ if(ret<android::NO_ERROR)
+ {
+ MSGQ_LOGEB("Message queue returned error %d", ret);
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+
+ if (pfd[0].revents & POLLIN)
+ {
+ queue1->setMsg(true);
+ }
+
+ if(queue2)
+ {
+ if (pfd[1].revents & POLLIN)
+ {
+ queue2->setMsg(true);
+ }
+ }
+
+ if(queue3)
+ {
+ if (pfd[2].revents & POLLIN)
+ {
+ queue3->setMsg(true);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+ return ret;
+ }
+
+};
diff --git a/libtiutils/MessageQueue.h b/libtiutils/MessageQueue.h
new file mode 100755
index 0000000..97e11a7
--- /dev/null
+++ b/libtiutils/MessageQueue.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.
+ */
+
+
+
+#ifndef __MESSAGEQUEUE_H__
+#define __MESSAGEQUEUE_H__
+
+#include "DebugUtils.h"
+#include <stdint.h>
+
+///Uncomment this macro to debug the message queue implementation
+//#define DEBUG_LOG
+
+///Camera HAL Logging Functions
+#ifndef DEBUG_LOG
+
+#define MSGQ_LOGDA(str)
+#define MSGQ_LOGDB(str, ...)
+
+#undef LOG_FUNCTION_NAME
+#undef LOG_FUNCTION_NAME_EXIT
+#define LOG_FUNCTION_NAME
+#define LOG_FUNCTION_NAME_EXIT
+
+#else
+
+#define MSGQ_LOGDA DBGUTILS_LOGDA
+#define MSGQ_LOGDB DBGUTILS_LOGDB
+
+#endif
+
+#define MSGQ_LOGEA DBGUTILS_LOGEA
+#define MSGQ_LOGEB DBGUTILS_LOGEB
+
+
+namespace TIUTILS {
+
+///Message type
+struct Message
+{
+ unsigned int command;
+ void* arg1;
+ void* arg2;
+ void* arg3;
+ void* arg4;
+ int64_t id;
+};
+
+///Message queue implementation
+class MessageQueue
+{
+public:
+
+ MessageQueue();
+ ~MessageQueue();
+
+ ///Get a message from the queue
+ android::status_t get(Message*);
+
+ ///Get the input file descriptor of the message queue
+ int getInFd();
+
+ ///Set the input file descriptor for the message queue
+ void setInFd(int fd);
+
+ ///Queue a message
+ android::status_t put(Message*);
+
+ ///Returns if the message queue is empty or not
+ bool isEmpty();
+
+ ///Force whether the message queue has message or not
+ void setMsg(bool hasMsg=false);
+
+ ///Wait for message in maximum three different queues with a timeout
+ static int waitForMsg(MessageQueue *queue1, MessageQueue *queue2=0, MessageQueue *queue3=0, int timeout = 0);
+
+ bool hasMsg()
+ {
+ return mHasMsg;
+ }
+
+private:
+ int fd_read;
+ int fd_write;
+ bool mHasMsg;
+};
+
+};
+
+#endif
diff --git a/libtiutils/Semaphore.cpp b/libtiutils/Semaphore.cpp
new file mode 100644
index 0000000..1f46dca
--- /dev/null
+++ b/libtiutils/Semaphore.cpp
@@ -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.
+ */
+
+
+
+#include "Semaphore.h"
+#include "ErrorUtils.h"
+#include <utils/Log.h>
+#include <time.h>
+
+namespace android {
+
+/**
+ @brief Constructor for the semaphore class
+
+ @param none
+ @return none
+ */
+Semaphore::Semaphore()
+{
+ ///Initialize the semaphore to NULL
+ mSemaphore = NULL;
+}
+
+/**
+ @brief Destructor of the semaphore class
+
+ @param none
+ @return none
+
+ */
+Semaphore::~Semaphore()
+{
+ Release();
+}
+
+/**
+ @brief: Releases semaphore
+
+ @param count >=0
+ @return NO_ERROR On Success
+ @return One of the android error codes based on semaphore de-initialization
+ */
+
+status_t Semaphore::Release()
+{
+ int status = 0;
+
+ ///Destroy only if the semaphore has been created
+ if(mSemaphore)
+ {
+ status = sem_destroy(mSemaphore);
+
+ free(mSemaphore);
+
+ mSemaphore = NULL;
+ }
+
+ ///Initialize the semaphore and return the status
+ return ErrorUtils::posixToAndroidError(status);
+
+}
+
+/**
+ @brief Create the semaphore with initial count value
+
+ @param count >=0
+ @return NO_ERROR On Success
+ @return NO_MEMORY If unable to allocate memory for the semaphore
+ @return BAD_VALUE If an invalid count value is passed (<0)
+ @return One of the android error codes based on semaphore initialization
+ */
+
+status_t Semaphore::Create(int count)
+{
+ status_t ret = NO_ERROR;
+
+ ///count cannot be less than zero
+ if(count<0)
+ {
+ return BAD_VALUE;
+ }
+
+ ret = Release();
+ if ( NO_ERROR != ret )
+ {
+ return ret;
+ }
+
+ ///allocate memory for the semaphore
+ mSemaphore = (sem_t*)malloc(sizeof(sem_t)) ;
+
+ ///if memory is unavailable, return error
+ if(!mSemaphore)
+ {
+ return NO_MEMORY;
+ }
+
+ ///Initialize the semaphore and return the status
+ return ErrorUtils::posixToAndroidError(sem_init(mSemaphore, 0x00, count));
+
+}
+
+/**
+ @brief Wait operation
+
+ @param none
+ @return BAD_VALUE if the semaphore is not initialized
+ @return NO_ERROR On success
+ @return One of the android error codes based on semaphore wait operation
+ */
+status_t Semaphore::Wait()
+{
+ ///semaphore should have been created first
+ if(!mSemaphore)
+ {
+ return BAD_VALUE;
+ }
+
+ ///Wait and return the status after signalling
+ return ErrorUtils::posixToAndroidError(sem_wait(mSemaphore));
+
+
+}
+
+
+/**
+ @brief Signal operation
+
+ @param none
+ @return BAD_VALUE if the semaphore is not initialized
+ @return NO_ERROR On success
+ @return One of the android error codes based on semaphore signal operation
+ */
+
+status_t Semaphore::Signal()
+{
+ ///semaphore should have been created first
+ if(!mSemaphore)
+ {
+ return BAD_VALUE;
+ }
+
+ ///Post to the semaphore
+ return ErrorUtils::posixToAndroidError(sem_post(mSemaphore));
+
+}
+
+/**
+ @brief Current semaphore count
+
+ @param none
+ @return Current count value of the semaphore
+ */
+int Semaphore::Count()
+{
+ int val;
+
+ ///semaphore should have been created first
+ if(!mSemaphore)
+ {
+ return BAD_VALUE;
+ }
+
+ ///get the value of the semaphore
+ sem_getvalue(mSemaphore, &val);
+
+ return val;
+}
+
+/**
+ @brief Wait operation with a timeout
+
+ @param timeoutMicroSecs The timeout period in micro seconds
+ @return BAD_VALUE if the semaphore is not initialized
+ @return NO_ERROR On success
+ @return One of the android error codes based on semaphore wait operation
+ */
+
+status_t Semaphore::WaitTimeout(int timeoutMicroSecs)
+{
+ status_t ret = NO_ERROR;
+
+ struct timespec timeSpec;
+ struct timeval currentTime;
+
+ ///semaphore should have been created first
+ if( NULL == mSemaphore)
+ {
+ ret = BAD_VALUE;
+ }
+
+ if ( NO_ERROR == ret )
+ {
+
+ ///setup the timeout values - timeout is specified in seconds and nanoseconds
+ gettimeofday(&currentTime, NULL);
+ timeSpec.tv_sec = currentTime.tv_sec;
+ timeSpec.tv_nsec = currentTime.tv_usec * 1000;
+ timeSpec.tv_sec += ( timeoutMicroSecs / 1000000 );
+ timeSpec.tv_nsec += ( timeoutMicroSecs % 1000000) * 1000;
+
+ ///Wait for the timeout or signal and return the result based on whichever event occurred first
+ ret = sem_timedwait(mSemaphore, &timeSpec);
+ }
+
+ return ret;
+}
+
+
+};
+
+
diff --git a/libtiutils/Semaphore.h b/libtiutils/Semaphore.h
new file mode 100644
index 0000000..466e709
--- /dev/null
+++ b/libtiutils/Semaphore.h
@@ -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 <Errors.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+namespace android {
+
+class Semaphore
+{
+public:
+
+ Semaphore();
+ ~Semaphore();
+
+ //Release semaphore
+ status_t Release();
+
+ ///Create the semaphore with initial count value
+ status_t Create(int count=0);
+
+ ///Wait operation
+ status_t Wait();
+
+ ///Signal operation
+ status_t Signal();
+
+ ///Current semaphore count
+ int Count();
+
+ ///Wait operation with a timeout
+ status_t WaitTimeout(int timeoutMicroSecs);
+
+private:
+ sem_t *mSemaphore;
+
+};
+
+};
diff --git a/libyv12colorconvert/Android.mk b/libyv12colorconvert/Android.mk
new file mode 100644
index 0000000..6f781f4
--- /dev/null
+++ b/libyv12colorconvert/Android.mk
@@ -0,0 +1,21 @@
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ ColorConvert.cpp
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/include/media/stagefright/openmax \
+ $(TOP)/frameworks/media/libvideoeditor/include
+
+LOCAL_SHARED_LIBRARIES := \
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := libyv12colorconvert
+
+include $(BUILD_HEAPTRACKED_SHARED_LIBRARY)
+
+endif
diff --git a/libyv12colorconvert/ColorConvert.cpp b/libyv12colorconvert/ColorConvert.cpp
new file mode 100644
index 0000000..41dcbad
--- /dev/null
+++ b/libyv12colorconvert/ColorConvert.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2011 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 "IYV12ColorConverter.h"
+#include <OMX_IVCommon.h>
+#include <string.h>
+
+static int getDecoderOutputFormat() {
+ return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
+}
+
+static int convertDecoderOutputToYV12(
+ void* srcBits, int srcWidth, int srcHeight, ARect srcRect, void* dstBits) {
+
+ const uint8_t *pSrc_y = (const uint8_t *)srcBits +
+ srcWidth * srcRect.top + srcRect.left;
+ const uint8_t *pSrc_uv = (const uint8_t *)pSrc_y +
+ srcWidth * (srcHeight - srcRect.top / 2);
+
+ int dstWidth = srcRect.right - srcRect.left + 1;
+ int dstHeight = srcRect.bottom - srcRect.top + 1;
+ size_t dst_y_size = dstWidth * dstHeight;
+ size_t dst_uv_stride = dstWidth / 2;
+ size_t dst_uv_size = dstWidth / 2 * dstHeight / 2;
+ uint8_t *pDst_y = (uint8_t *)dstBits;
+ uint8_t *pDst_u = pDst_y + dst_y_size;
+ uint8_t *pDst_v = pDst_u + dst_uv_size;
+
+ for (int y = 0; y < dstHeight; ++y) {
+ memcpy(pDst_y, pSrc_y, dstWidth);
+ pSrc_y += srcWidth;
+ pDst_y += dstWidth;
+ }
+
+ size_t tmp = (dstWidth + 1) / 2;
+ for (int y = 0; y < (dstHeight + 1) / 2; ++y) {
+ for (size_t x = 0; x < tmp; ++x) {
+ pDst_u[x] = pSrc_uv[2 * x];
+ pDst_v[x] = pSrc_uv[2 * x + 1];
+ }
+ pSrc_uv += srcWidth;
+ pDst_u += dst_uv_stride;
+ pDst_v += dst_uv_stride;
+ }
+ return 0;
+}
+
+static int getEncoderInputFormat() {
+ return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
+}
+
+static int convertYV12ToEncoderInput(
+ void* srcBits, int srcWidth, int srcHeight,
+ int dstWidth, int dstHeight, ARect dstRect,
+ void* dstBits) {
+ uint8_t *pSrc_y = (uint8_t*) srcBits;
+ uint8_t *pDst_y = (uint8_t*) dstBits;
+ for(int i=0; i < srcHeight; i++) {
+ memcpy(pDst_y, pSrc_y, srcWidth);
+ pSrc_y += srcWidth;
+ pDst_y += dstWidth;
+ }
+ uint8_t* pSrc_u = (uint8_t*)srcBits + (srcWidth * srcHeight);
+ uint8_t* pSrc_v = (uint8_t*)pSrc_u + (srcWidth / 2) * (srcHeight / 2);
+ uint8_t* pDst_uv = (uint8_t*)dstBits + dstWidth * dstHeight;
+
+ for(int i=0; i < srcHeight / 2; i++) {
+ for(int j=0, k=0; j < srcWidth / 2; j++, k+=2) {
+ pDst_uv[k] = pSrc_u[j];
+ pDst_uv[k+1] = pSrc_v[j];
+ }
+ pDst_uv += dstWidth;
+ pSrc_u += srcWidth / 2;
+ pSrc_v += srcWidth / 2;
+ }
+ return 0;
+}
+
+static int getEncoderInputBufferInfo(
+ int actualWidth, int actualHeight,
+ int* encoderWidth, int* encoderHeight,
+ ARect* encoderRect, int* encoderBufferSize) {
+
+ *encoderWidth = actualWidth;
+ *encoderHeight = actualHeight;
+ encoderRect->left = 0;
+ encoderRect->top = 0;
+ encoderRect->right = actualWidth - 1;
+ encoderRect->bottom = actualHeight - 1;
+ *encoderBufferSize = (actualWidth * actualHeight * 3 / 2);
+
+ return 0;
+}
+
+extern "C" void getYV12ColorConverter(IYV12ColorConverter *converter) {
+ converter->getDecoderOutputFormat = getDecoderOutputFormat;
+ converter->convertDecoderOutputToYV12 = convertDecoderOutputToYV12;
+ converter->getEncoderInputFormat = getEncoderInputFormat;
+ converter->convertYV12ToEncoderInput = convertYV12ToEncoderInput;
+ converter->getEncoderInputBufferInfo = getEncoderInputBufferInfo;
+}
diff --git a/mapinfo.c b/mapinfo.c
new file mode 100644
index 0000000..7f4250f
--- /dev/null
+++ b/mapinfo.c
@@ -0,0 +1,106 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "mapinfo.h"
+
+extern void *__real_malloc(size_t size);
+extern void __real_free(void *ptr);
+
+#if 0
+ while (p <= end) {
+ data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
+ _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
+ " %08x %08x %s\n", p, data,
+ map_to_name(map, data, ""));
+ p += 4;
+ }
+#endif
+
+// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so
+// 012345678901234567890123456789012345678901234567890123456789
+// 0 1 2 3 4 5
+
+static mapinfo *parse_maps_line(char *line)
+{
+ mapinfo *mi;
+ int len = strlen(line);
+
+ if(len < 1) return 0;
+ line[--len] = 0;
+
+ if(len < 50) return 0;
+ if(line[20] != 'x') return 0;
+
+ mi = __real_malloc(sizeof(mapinfo) + (len - 47));
+ if(mi == 0) return 0;
+
+ mi->start = strtoul(line, 0, 16);
+ mi->end = strtoul(line + 9, 0, 16);
+ /* To be filled in parse_elf_info if the mapped section starts with
+ * elf_header
+ */
+ mi->next = 0;
+ strcpy(mi->name, line + 49);
+
+ return mi;
+}
+
+mapinfo *init_mapinfo(int pid)
+{
+ struct mapinfo *milist = NULL;
+ char data[1024];
+ sprintf(data, "/proc/%d/maps", pid);
+ FILE *fp = fopen(data, "r");
+ if(fp) {
+ while(fgets(data, sizeof(data), fp)) {
+ mapinfo *mi = parse_maps_line(data);
+ if(mi) {
+ mi->next = milist;
+ milist = mi;
+ }
+ }
+ fclose(fp);
+ }
+
+ return milist;
+}
+
+void deinit_mapinfo(mapinfo *mi)
+{
+ mapinfo *del;
+ while(mi) {
+ del = mi;
+ mi = mi->next;
+ __real_free(del);
+ }
+}
+
+/* Map a pc address to the name of the containing ELF file */
+const char *map_to_name(mapinfo *mi, unsigned pc, const char* def)
+{
+ while(mi) {
+ if((pc >= mi->start) && (pc < mi->end)){
+ return mi->name;
+ }
+ mi = mi->next;
+ }
+ return def;
+}
+
+/* Find the containing map info for the pc */
+const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc)
+{
+ *rel_pc = pc;
+ while(mi) {
+ if((pc >= mi->start) && (pc < mi->end)){
+ // Only calculate the relative offset for shared libraries
+ if (strstr(mi->name, ".so")) {
+ *rel_pc -= mi->start;
+ }
+ return mi;
+ }
+ mi = mi->next;
+ }
+ return NULL;
+}
diff --git a/mapinfo.h b/mapinfo.h
new file mode 100644
index 0000000..25adeb4
--- /dev/null
+++ b/mapinfo.h
@@ -0,0 +1,16 @@
+#ifndef MAPINFO_H
+#define MAPINFO_H
+
+typedef struct mapinfo {
+ struct mapinfo *next;
+ unsigned start;
+ unsigned end;
+ char name[];
+} mapinfo;
+
+mapinfo *init_mapinfo(int pid);
+void deinit_mapinfo(mapinfo *mi);
+const char *map_to_name(mapinfo *mi, unsigned pc, const char* def);
+const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc);
+
+#endif
diff --git a/omap4.mk b/omap4.mk
new file mode 100644
index 0000000..1d1a877
--- /dev/null
+++ b/omap4.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2011 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.
+
+# This file lists the modules that are specific to OMAP4 but are used by
+# all OMAP4 devices.
+
+PRODUCT_PACKAGES := \
+ libdomx \
+ libOMX_Core \
+ libOMX.TI.DUCATI1.VIDEO.H264E \
+ libOMX.TI.DUCATI1.VIDEO.DECODER \
+ libOMX.TI.DUCATI1.VIDEO.CAMERA \
+ libOMX.TI.DUCATI1.MISC.SAMPLE \
+ libstagefrighthw \
+ libyv12colorconvert \
+ libtimemmgr \
+ libtiutils \
+ libcamera \
+ libion \
+ camera.omap4 \
+ libomxcameraadapter \
+ hwcomposer.omap4
diff --git a/stacktrace.c b/stacktrace.c
new file mode 100644
index 0000000..1e79bfa
--- /dev/null
+++ b/stacktrace.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <unwind.h>
+#include <sys/types.h>
+
+// =============================================================================
+// stack trace functions
+// =============================================================================
+
+typedef struct
+{
+ size_t count;
+ intptr_t* addrs;
+} stack_crawl_state_t;
+
+
+/* depends how the system includes define this */
+#ifdef HAVE_UNWIND_CONTEXT_STRUCT
+typedef struct _Unwind_Context __unwind_context;
+#else
+typedef _Unwind_Context __unwind_context;
+#endif
+
+static _Unwind_Reason_Code trace_function(__unwind_context *context, void *arg)
+{
+ stack_crawl_state_t* state = (stack_crawl_state_t*)arg;
+ if (state->count) {
+ intptr_t ip = (intptr_t)_Unwind_GetIP(context);
+ if (ip) {
+ state->addrs[0] = ip;
+ state->addrs++;
+ state->count--;
+ return _URC_NO_REASON;
+ }
+ }
+ /*
+ * If we run out of space to record the address or 0 has been seen, stop
+ * unwinding the stack.
+ */
+ return _URC_END_OF_STACK;
+}
+
+int heaptracker_stacktrace(intptr_t* addrs, size_t max_entries)
+{
+ stack_crawl_state_t state;
+ state.count = max_entries;
+ state.addrs = (intptr_t*)addrs;
+ _Unwind_Backtrace(trace_function, (void*)&state);
+ return max_entries - state.count;
+}
diff --git a/test/CameraHal/Android.mk b/test/CameraHal/Android.mk
new file mode 100644
index 0000000..c7da48a
--- /dev/null
+++ b/test/CameraHal/Android.mk
@@ -0,0 +1,38 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ camera_test_menu.cpp \
+ camera_test_script.cpp
+
+LOCAL_SHARED_LIBRARIES:= \
+ libdl \
+ libui \
+ libutils \
+ libcutils \
+ libbinder \
+ libmedia \
+ libui \
+ libgui \
+ libcamera_client
+
+LOCAL_C_INCLUDES += \
+ frameworks/base/include/ui \
+ frameworks/base/include/surfaceflinger \
+ frameworks/base/include/camera \
+ frameworks/base/include/media \
+ $(PV_INCLUDES)
+
+LOCAL_MODULE:= camera_test
+LOCAL_MODULE_TAGS:= tests
+
+LOCAL_CFLAGS += -Wall -fno-short-enums -O0 -g -D___ANDROID___
+
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+ LOCAL_CFLAGS += -DTARGET_OMAP4
+endif
+
+include $(BUILD_HEAPTRACKED_EXECUTABLE)
+
+
diff --git a/test/CameraHal/camera_test.h b/test/CameraHal/camera_test.h
new file mode 100644
index 0000000..6ff8eb3
--- /dev/null
+++ b/test/CameraHal/camera_test.h
@@ -0,0 +1,165 @@
+#ifndef CAMERA_TEST_H
+#define CAMERA_TEST_H
+
+#define PRINTOVER(arg...) LOGD(#arg)
+#define LOG_FUNCTION_NAME LOGD("%d: %s() ENTER", __LINE__, __FUNCTION__);
+#define LOG_FUNCTION_NAME_EXIT LOGD("%d: %s() EXIT", __LINE__, __FUNCTION__);
+#define KEY_GBCE "gbce"
+#define KEY_CAMERA "camera-index"
+#define KEY_SATURATION "saturation"
+#define KEY_BRIGHTNESS "brightness"
+#define KEY_BURST "burst-capture"
+#define KEY_EXPOSURE "exposure"
+#define KEY_CONTRAST "contrast"
+#define KEY_SHARPNESS "sharpness"
+#define KEY_ISO "iso"
+#define KEY_CAF "caf"
+#define KEY_MODE "mode"
+#define KEY_VNF "vnf"
+#define KEY_VSTAB "vstab"
+#define KEY_COMPENSATION "exposure-compensation"
+
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+#define KEY_IPP "ippMode"
+#else
+#define KEY_IPP "ipp"
+#endif
+
+#define KEY_BUFF_STARV "buff-starvation"
+#define KEY_METERING_MODE "meter-mode"
+#define KEY_AUTOCONVERGENCE "auto-convergence"
+#define KEY_MANUALCONVERGENCE_VALUES "manual-convergence-values"
+#define AUTOCONVERGENCE_MODE_MANUAL "mode-manual"
+#define KEY_EXP_BRACKETING_RANGE "exp-bracketing-range"
+#define KEY_TEMP_BRACKETING "temporal-bracketing"
+#define KEY_TEMP_BRACKETING_POS "temporal-bracketing-range-positive"
+#define KEY_TEMP_BRACKETING_NEG "temporal-bracketing-range-negative"
+#define KEY_MEASUREMENT "measurement"
+#define KEY_S3D2D_PREVIEW_MODE "s3d2d-preview"
+#define KEY_STEREO_CAMERA "s3d-supported"
+#define KEY_EXIF_MODEL "exif-model"
+#define KEY_EXIF_MAKE "exif-make"
+
+#define KEY_AUTO_EXPOSURE_LOCK "auto-exposure-lock"
+#define KEY_AUTO_WHITEBALANCE_LOCK "auto-whitebalance-lock"
+
+#define SDCARD_PATH "/sdcard/"
+
+#define MAX_BURST 15
+#define BURST_INC 5
+#define TEMP_BRACKETING_MAX_RANGE 4
+
+#define MEDIASERVER_DUMP "procmem -w $(ps | grep mediaserver | grep -Eo '[0-9]+' | head -n 1) | grep \"\\(Name\\|libcamera.so\\|libOMX\\|libomxcameraadapter.so\\|librcm.so\\|libnotify.so\\|libipcutils.so\\|libipc.so\\|libsysmgr.so\\|TOTAL\\)\""
+#define MEMORY_DUMP "procrank -u"
+#define KEY_METERING_MODE "meter-mode"
+
+#define TEST_FOCUS_AREA "(0,0,1000,1000,300),(-1000,-1000,1000,1000,300),(0,0,0,0,0)"
+
+#define COMPENSATION_OFFSET 20
+#define DELIMITER "|"
+
+#define MAX_PREVIEW_SURFACE_WIDTH 800
+#define MAX_PREVIEW_SURFACE_HEIGHT 480
+
+#define MODEL "camera_test"
+#define MAKE "camera_test"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+namespace android {
+ class CameraHandler: public CameraListener {
+ public:
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
+ virtual void postData(int32_t msgType,
+ const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata);
+
+ virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
+ };
+
+};
+
+using namespace android;
+
+char * get_cycle_cmd(const char *aSrc);
+int execute_functional_script(char *script);
+status_t dump_mem_status();
+int openCamera();
+int closeCamera();
+void initDefaults();
+int startPreview();
+void stopPreview();
+int startRecording();
+int stopRecording();
+int closeRecorder();
+int openRecorder();
+int configureRecorder();
+void printSupportedParams();
+char *load_script(char *config);
+int start_logging(char *config, int &pid);
+int stop_logging(int &pid);
+int execute_error_script(char *script);
+
+typedef struct pixel_format_t {
+ int32_t pixelFormatDesc;
+ const char *pixformat;
+}pixel_format;
+
+typedef struct output_format_t {
+ output_format type;
+ const char *desc;
+} outformat;
+
+typedef struct preview_size_t {
+ int width, height;
+ const char *desc;
+} preview_size;
+
+typedef struct Vcapture_size_t {
+ int width, height;
+ const char *desc;
+} Vcapture_size;
+
+typedef struct capture_Size_t {
+ int width, height;
+ const char *name;
+} capture_Size;
+
+typedef struct video_Codecs_t {
+ video_encoder type;
+ const char *desc;
+} video_Codecs;
+
+typedef struct audio_Codecs_t {
+ audio_encoder type;
+ const char *desc;
+} audio_Codecs;
+
+typedef struct V_bitRate_t {
+ uint32_t bit_rate;
+ const char *desc;
+} V_bitRate;
+
+typedef struct zoom_t {
+ int idx;
+ const char *zoom_description;
+} Zoom;
+
+typedef struct fps_ranges_t {
+ const char *range;
+ const char *rangeDescription;
+} fps_ranges;
+
+typedef struct fpsConst_Ranges_t {
+ const char *range;
+ const char *rangeDescription;
+ int constFramerate;
+} fpsConst_Ranges;
+
+typedef struct fpsConst_RangesSec_t {
+ const char *range;
+ const char *rangeDescription;
+ int constFramerate;
+} fpsConst_RangesSec;
+
+#endif
diff --git a/test/CameraHal/camera_test_menu.cpp b/test/CameraHal/camera_test_menu.cpp
new file mode 100644
index 0000000..9bbf16a
--- /dev/null
+++ b/test/CameraHal/camera_test_menu.cpp
@@ -0,0 +1,2522 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <semaphore.h>
+#include <pthread.h>
+
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/ISurfaceComposerClient.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+
+#include <camera/Camera.h>
+#include <camera/ICamera.h>
+#include <media/mediarecorder.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+#include <camera/CameraParameters.h>
+#include <system/audio.h>
+#include <system/camera.h>
+
+#include <cutils/memory.h>
+#include <utils/Log.h>
+
+#include <sys/wait.h>
+
+#include "camera_test.h"
+
+using namespace android;
+
+int camera_index = 0;
+int print_menu;
+sp<Camera> camera;
+sp<MediaRecorder> recorder;
+sp<SurfaceComposerClient> client;
+sp<SurfaceControl> surfaceControl;
+sp<Surface> previewSurface;
+CameraParameters params;
+float compensation = 0.0;
+double latitude = 0.0;
+double longitude = 0.0;
+double degree_by_step = 17.5609756;//..0975609756097;
+double altitude = 0.0;
+int awb_mode = 0;
+int effects_mode = 0;
+int scene_mode = 0;
+int caf_mode = 0;
+int vnf_mode = 0;
+int vstab_mode = 0;
+
+int tempBracketRange = 1;
+int tempBracketIdx = 0;
+int measurementIdx = 0;
+int expBracketIdx = 0;
+int AutoConvergenceModeIDX = 0;
+int ManualConvergenceValuesIDX = 0;
+int ManualConvergenceDefaultValueIDX = 2;
+int gbceIDX = 0;
+int rotation = 0;
+bool reSizePreview = true;
+bool hardwareActive = false;
+bool recordingMode = false;
+bool previewRunning = false;
+int saturation = 0;
+int zoomIDX = 0;
+int videoCodecIDX = 0;
+int audioCodecIDX = 0;
+int outputFormatIDX = 0;
+int contrast = 0;
+int brightness = 0;
+unsigned int burst = 0;
+int sharpness = 0;
+int iso_mode = 0;
+int capture_mode = 0;
+int exposure_mode = 0;
+int ippIDX = 0;
+int ippIDX_old = 0;
+int previewFormat = 0;
+int jpegQuality = 85;
+int thumbQuality = 85;
+int flashIdx = 0;
+int fpsRangeIdx = 0;
+timeval autofocus_start, picture_start;
+char script_name[80];
+int prevcnt = 0;
+int videoFd = -1;
+int elockidx = 0;
+int wblockidx = 0;
+
+
+char dir_path[80] = SDCARD_PATH;
+
+const char *cameras[] = {"Primary Camera", "Secondary Camera 1", "Stereo Camera", "USB Camera", "Fake Camera"};
+const char *measurement[] = {"disable", "enable"};
+const char *expBracketing[] = {"disable", "enable"};
+const char *expBracketingRange[] = {"", "-30,0,30,0,-30"};
+const char *tempBracketing[] = {"disable", "enable"};
+const char *faceDetection[] = {"disable", "enable"};
+const char *lock[] = {"false", "true"};
+
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+const char *ipp_mode[] = { "off", "Chroma Suppression", "Edge Enhancement" };
+#else
+const char *ipp_mode[] = { "off", "ldc", "nsf", "ldc-nsf" };
+#endif
+
+const char *iso [] = { "auto", "100", "200", "400", "800", "1200", "1600"};
+
+const char *effects [] = {
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+ "none",
+ "mono",
+ "negative",
+ "solarize",
+ "sepia",
+ "whiteboard",
+ "blackboard",
+ "cool",
+ "emboss"
+#else
+ "none",
+ "mono",
+ "negative",
+ "solarize",
+ "sepia",
+ "vivid",
+ "whiteboard",
+ "blackboard",
+ "cool",
+ "emboss",
+ "blackwhite",
+ "aqua",
+ "posterize"
+#endif
+};
+
+const char CameraParameters::FLASH_MODE_OFF[] = "off";
+const char CameraParameters::FLASH_MODE_AUTO[] = "auto";
+const char CameraParameters::FLASH_MODE_ON[] = "on";
+const char CameraParameters::FLASH_MODE_RED_EYE[] = "red-eye";
+const char CameraParameters::FLASH_MODE_TORCH[] = "torch";
+
+const char *flashModes[] = {
+ "off",
+ "auto",
+ "on",
+ "red-eye",
+ "torch",
+ "fill-in",
+};
+
+const char *caf [] = { "Off", "On" };
+const char *vnf [] = { "Off", "On" };
+const char *vstab [] = { "Off", "On" };
+
+
+const char *scene [] = {
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+ "auto",
+ "portrait",
+ "landscape",
+ "night",
+ "night-portrait",
+ "fireworks",
+ "snow",
+ "action",
+#else
+ "auto",
+ "portrait",
+ "landscape",
+ "night",
+ "night-portrait",
+ "night-indoor",
+ "fireworks",
+ "sport",
+ "cine",
+ "beach",
+ "snow",
+ "mood",
+ "closeup",
+ "underwater",
+ "document",
+ "barcode",
+ "oldfilm",
+ "candlelight",
+ "party",
+ "steadyphoto",
+ "sunset",
+ "action",
+ "theatre"
+#endif
+};
+const char *strawb_mode[] = {
+ "auto",
+ "incandescent",
+ "fluorescent",
+ "daylight",
+ "horizon",
+ "shadow",
+ "tungsten",
+ "shade",
+ "twilight",
+ "warm-fluorescent",
+ "facepriority",
+ "sunset"
+};
+
+size_t length_cam = ARRAY_SIZE(cameras);
+
+
+preview_size previewSize [] = {
+ { 0, 0, "NULL"},
+ { 128, 96, "SQCIF" },
+ { 176, 144, "QCIF" },
+ { 352, 288, "CIF" },
+ { 320, 240, "QVGA" },
+ { 352, 288, "CIF" },
+ { 640, 480, "VGA" },
+ { 720, 480, "NTSC" },
+ { 720, 576, "PAL" },
+ { 800, 480, "WVGA" },
+ { 848, 480, "WVGA2"},
+ { 864, 480, "WVGA3"},
+ { 992, 560, "WVGA4"},
+ { 1280, 720, "HD" },
+ { 1920, 1080, "FULLHD"},
+};
+
+size_t length_previewSize = ARRAY_SIZE(previewSize);
+
+Vcapture_size VcaptureSize [] = {
+ { 128, 96, "SQCIF" },
+ { 176, 144, "QCIF" },
+ { 352, 288, "CIF" },
+ { 320, 240, "QVGA" },
+ { 640, 480, "VGA" },
+ { 704, 480, "TVNTSC" },
+ { 704, 576, "TVPAL" },
+ { 720, 480, "D1NTSC" },
+ { 720, 576, "D1PAL" },
+ { 800, 480, "WVGA" },
+ #if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+ { 848, 480, "WVGA2"},
+ { 864, 480, "WVGA3"},
+ { 992, 560, "WVGA4"},
+ #endif
+ { 1280, 720, "HD" },
+ { 1920, 1080, "FULLHD"},
+};
+
+size_t lenght_Vcapture_size = ARRAY_SIZE(VcaptureSize);
+
+capture_Size captureSize[] = {
+ { 320, 240, "QVGA" },
+ { 640, 480, "VGA" },
+ { 800, 600, "SVGA" },
+ { 1152, 864, "1MP" },
+ { 1280, 1024, "1.3MP" },
+ { 1600, 1200, "2MP" },
+ { 2048, 1536, "3MP" },
+ { 2592, 1944, "5MP" },
+ { 2608, 1960, "5MP" },
+ { 3264, 2448, "8MP" },
+ { 3648, 2736, "10MP"},
+ { 4032, 3024, "12MP"},
+};
+
+size_t length_capture_Size = ARRAY_SIZE(captureSize);
+
+
+outformat outputFormat[] = {
+ { OUTPUT_FORMAT_THREE_GPP, "3gp" },
+ { OUTPUT_FORMAT_MPEG_4, "mp4" },
+ };
+
+size_t length_outformat = ARRAY_SIZE(outputFormat);
+
+video_Codecs videoCodecs[] = {
+ { VIDEO_ENCODER_H263, "H263" },
+ { VIDEO_ENCODER_H264, "H264" },
+ { VIDEO_ENCODER_MPEG_4_SP, "MPEG4"}
+};
+
+size_t length_video_Codecs = ARRAY_SIZE(videoCodecs);
+
+audio_Codecs audioCodecs[] = {
+ { AUDIO_ENCODER_AMR_NB, "AMR_NB" },
+ { AUDIO_ENCODER_AMR_WB, "AMR_WB" },
+ { AUDIO_ENCODER_AAC, "AAC" },
+ { AUDIO_ENCODER_AAC_PLUS, "AAC+" },
+ { AUDIO_ENCODER_EAAC_PLUS, "EAAC+" }
+};
+
+size_t length_audio_Codecs = ARRAY_SIZE(audioCodecs);
+
+V_bitRate VbitRate[] = {
+ { 64000, "64K" },
+ { 128000, "128K" },
+ { 192000, "192K" },
+ { 240000, "240K" },
+ { 320000, "320K" },
+ { 360000, "360K" },
+ { 384000, "384K" },
+ { 420000, "420K" },
+ { 768000, "768K" },
+ { 1000000, "1M" },
+ { 1500000, "1.5M" },
+ { 2000000, "2M" },
+ { 4000000, "4M" },
+ { 6000000, "6M" },
+ { 8000000, "8M" },
+ { 10000000, "10M" },
+};
+
+size_t length_V_bitRate = ARRAY_SIZE(VbitRate);
+
+Zoom zoom[] = {
+ { 0, "1x" },
+ { 12, "1.5x"},
+ { 20, "2x" },
+ { 27, "2.5x"},
+ { 32, "3x" },
+ { 36, "3.5x"},
+ { 40, "4x" },
+ { 60, "8x" },
+};
+
+size_t length_Zoom = ARRAY_SIZE(zoom);
+
+fps_ranges fpsRanges[] = {
+ { "5000,30000", "[5:30]" },
+ { "5000,10000", "[5:10]" },
+ { "5000,15000", "[5:15]" },
+ { "5000,20000", "[5:20]" },
+};
+
+size_t length_fps_ranges = ARRAY_SIZE(fpsRanges);
+
+fpsConst_Ranges fpsConstRanges[] = {
+ { "5000,5000", "[5:5]", 5 },
+ { "10000,10000", "[10:10]", 10 },
+ { "15000,15000", "[15:15]", 15 },
+ { "20000,20000", "[20:20]", 20 },
+ { "25000,25000", "[25:25]", 25 },
+ { "30000,30000", "[30:30]", 30 },
+};
+
+size_t length_fpsConst_Ranges = ARRAY_SIZE(fpsConstRanges);
+
+fpsConst_RangesSec fpsConstRangesSec[] = {
+ { "5000,5000", "[5:5]", 5 },
+ { "10000,10000", "[10:10]", 10 },
+ { "15000,15000", "[15:15]", 15 },
+ { "20000,20000", "[20:20]", 20 },
+ { "25000,25000", "[25:25]", 25 },
+ { "27000,27000", "[27:27]", 27 },
+};
+
+size_t length_fpsConst_RangesSec = ARRAY_SIZE(fpsConstRangesSec);
+
+const char *antibanding[] = {
+ "off",
+ "auto",
+ "50hz",
+ "60hz",
+};
+int antibanding_mode = 0;
+const char *focus[] = {
+ "auto",
+ "infinity",
+ "macro",
+ "continuous-video",
+ "extended",
+ "portrait",
+};
+int focus_mode = 0;
+pixel_format pixelformat[] = {
+ { HAL_PIXEL_FORMAT_YCbCr_422_I, CameraParameters::PIXEL_FORMAT_YUV422I },
+ { HAL_PIXEL_FORMAT_YCrCb_420_SP, CameraParameters::PIXEL_FORMAT_YUV420SP },
+ { HAL_PIXEL_FORMAT_RGB_565, CameraParameters::PIXEL_FORMAT_RGB565 },
+ { -1, CameraParameters::PIXEL_FORMAT_JPEG },
+ { -1, "raw" },
+ };
+
+const char *codingformat[] = {"yuv422i-yuyv", "yuv420sp", "rgb565", "jpeg", "raw", "jps", "mpo", "raw+jpeg", "raw+mpo"};
+const char *gbce[] = {"disable", "enable"};
+int pictureFormat = 3; // jpeg
+const char *exposure[] = {"auto", "macro", "portrait", "landscape", "sports", "night", "night-portrait", "backlighting", "manual"};
+const char *capture[] = { "high-performance", "high-quality", "video-mode" };
+const char *autoconvergencemode[] = { "mode-disable", "mode-frame", "mode-center", "mode-fft", "mode-manual" };
+const char *manualconvergencevalues[] = { "-100", "-50", "-30", "-25", "0", "25", "50", "100" };
+
+const struct {
+ int fps;
+} frameRate[] = {
+ {0},
+ {5},
+ {10},
+ {15},
+ {20},
+ {25},
+ {30}
+};
+
+int thumbSizeIDX = 3;
+int previewSizeIDX = ARRAY_SIZE(previewSize) - 1;
+int captureSizeIDX = ARRAY_SIZE(captureSize) - 1;
+int frameRateIDX = ARRAY_SIZE(fpsConstRanges) - 1;
+int frameRateIDXSec = ARRAY_SIZE(fpsConstRangesSec) - 1;
+int VcaptureSizeIDX = ARRAY_SIZE(VcaptureSize) - 1;
+int VbitRateIDX = ARRAY_SIZE(VbitRate) - 1;
+
+static unsigned int recording_counter = 1;
+
+int dump_preview = 0;
+int bufferStarvationTest = 0;
+bool showfps = false;
+
+const char *metering[] = {
+ "center",
+ "average",
+};
+int meter_mode = 0;
+bool bLogSysLinkTrace = true;
+bool stressTest = false;
+bool stopScript = false;
+int restartCount = 0;
+
+/** Calculate delay from a reference time */
+unsigned long long timeval_delay(const timeval *ref) {
+ unsigned long long st, end, delay;
+ timeval current_time;
+
+ gettimeofday(&current_time, 0);
+
+ st = ref->tv_sec * 1000000 + ref->tv_usec;
+ end = current_time.tv_sec * 1000000 + current_time.tv_usec;
+ delay = end - st;
+
+ return delay;
+}
+
+/** Callback for takePicture() */
+void my_raw_callback(const sp<IMemory>& mem) {
+
+ static int counter = 1;
+ unsigned char *buff = NULL;
+ int size;
+ int fd = -1;
+ char fn[256];
+
+ LOG_FUNCTION_NAME;
+
+ if (mem == NULL)
+ goto out;
+
+ //Start preview after capture.
+ camera->startPreview();
+
+ fn[0] = 0;
+ sprintf(fn, "/sdcard/img%03d.raw", counter);
+ fd = open(fn, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
+
+ if (fd < 0)
+ goto out;
+
+ size = mem->size();
+
+ if (size <= 0)
+ goto out;
+
+ buff = (unsigned char *)mem->pointer();
+
+ if (!buff)
+ goto out;
+
+ if (size != write(fd, buff, size))
+ printf("Bad Write int a %s error (%d)%s\n", fn, errno, strerror(errno));
+
+ counter++;
+ printf("%s: buffer=%08X, size=%d stored at %s\n",
+ __FUNCTION__, (int)buff, size, fn);
+
+out:
+
+ if (fd >= 0)
+ close(fd);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void saveFile(const sp<IMemory>& mem) {
+ static int counter = 1;
+ unsigned char *buff = NULL;
+ int size;
+ int fd = -1;
+ char fn[256];
+
+ LOG_FUNCTION_NAME;
+
+ if (mem == NULL)
+ goto out;
+
+ fn[0] = 0;
+ sprintf(fn, "/sdcard/preview%03d.yuv", counter);
+ fd = open(fn, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
+ if(fd < 0) {
+ LOGE("Unable to open file %s: %s", fn, strerror(fd));
+ goto out;
+ }
+
+ size = mem->size();
+ if (size <= 0) {
+ LOGE("IMemory object is of zero size");
+ goto out;
+ }
+
+ buff = (unsigned char *)mem->pointer();
+ if (!buff) {
+ LOGE("Buffer pointer is invalid");
+ goto out;
+ }
+
+ if (size != write(fd, buff, size))
+ printf("Bad Write int a %s error (%d)%s\n", fn, errno, strerror(errno));
+
+ counter++;
+ printf("%s: buffer=%08X, size=%d\n",
+ __FUNCTION__, (int)buff, size);
+
+out:
+
+ if (fd >= 0)
+ close(fd);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+
+void debugShowFPS()
+{
+ static int mFrameCount = 0;
+ static int mLastFrameCount = 0;
+ static nsecs_t mLastFpsTime = 0;
+ static float mFps = 0;
+ 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;
+ printf("####### [%d] Frames, %f FPS", mFrameCount, mFps);
+ }
+}
+
+/** Callback for startPreview() */
+void my_preview_callback(const sp<IMemory>& mem) {
+
+ printf("PREVIEW Callback 0x%x", ( unsigned int ) mem->pointer());
+ if (dump_preview) {
+
+ if(prevcnt==50)
+ saveFile(mem);
+
+ prevcnt++;
+
+ uint8_t *ptr = (uint8_t*) mem->pointer();
+
+ printf("PRV_CB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9]);
+
+ }
+
+ debugShowFPS();
+}
+
+/** Callback for takePicture() */
+void my_jpeg_callback(const sp<IMemory>& mem) {
+ static int counter = 1;
+ unsigned char *buff = NULL;
+ int size;
+ int fd = -1;
+ char fn[256];
+
+ LOG_FUNCTION_NAME;
+
+ //Start preview after capture.
+ camera->startPreview();
+
+ if (mem == NULL)
+ goto out;
+
+ fn[0] = 0;
+ sprintf(fn, "%s/img%03d.jpg", dir_path,counter);
+ fd = open(fn, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
+
+ if(fd < 0) {
+ LOGE("Unable to open file %s: %s", fn, strerror(fd));
+ goto out;
+ }
+
+ size = mem->size();
+ if (size <= 0) {
+ LOGE("IMemory object is of zero size");
+ goto out;
+ }
+
+ buff = (unsigned char *)mem->pointer();
+ if (!buff) {
+ LOGE("Buffer pointer is invalid");
+ goto out;
+ }
+
+ if (size != write(fd, buff, size))
+ printf("Bad Write int a %s error (%d)%s\n", fn, errno, strerror(errno));
+
+ counter++;
+ printf("%s: buffer=%08X, size=%d stored at %s\n",
+ __FUNCTION__, (int)buff, size, fn);
+
+out:
+
+ if (fd >= 0)
+ close(fd);
+
+ LOG_FUNCTION_NAME_EXIT;
+}
+
+void my_face_callback(camera_frame_metadata_t *metadata) {
+ int idx;
+
+ if ( NULL == metadata ) {
+ return;
+ }
+
+ for ( idx = 0 ; idx < metadata->number_of_faces ; idx++ ) {
+ printf("Face %d at %d,%d %d,%d \n",
+ idx,
+ metadata->faces[idx].rect[0],
+ metadata->faces[idx].rect[1],
+ metadata->faces[idx].rect[2],
+ metadata->faces[idx].rect[3]);
+ }
+
+}
+
+void CameraHandler::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
+
+ printf("Notify cb: %d %d %d\n", msgType, ext1, ext2);
+
+ if ( msgType & CAMERA_MSG_FOCUS )
+ printf("AutoFocus %s in %llu us\n", (ext1) ? "OK" : "FAIL", timeval_delay(&autofocus_start));
+
+ if ( msgType & CAMERA_MSG_SHUTTER )
+ printf("Shutter done in %llu us\n", timeval_delay(&picture_start));
+
+ if ( msgType & CAMERA_MSG_ERROR && (ext1 == 1))
+ {
+ printf("Camera Test CAMERA_MSG_ERROR.....\n");
+ if (stressTest)
+ {
+ printf("Camera Test Notified of Error Restarting.....\n");
+ stopScript = true;
+ }
+ else
+ {
+ printf("Camera Test Notified of Error Stopping.....\n");
+ stopScript =false;
+ stopPreview();
+
+ if (recordingMode)
+ {
+ stopRecording();
+ closeRecorder();
+ recordingMode = false;
+ }
+ }
+ }
+}
+
+void CameraHandler::postData(int32_t msgType,
+ const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata) {
+ printf("Data cb: %d\n", msgType);
+
+ if ( msgType & CAMERA_MSG_PREVIEW_FRAME )
+ my_preview_callback(dataPtr);
+
+ if ( msgType & CAMERA_MSG_RAW_IMAGE ) {
+ printf("RAW done in %llu us\n", timeval_delay(&picture_start));
+ my_raw_callback(dataPtr);
+ }
+
+ if (msgType & CAMERA_MSG_POSTVIEW_FRAME) {
+ printf("Postview frame %llu us\n", timeval_delay(&picture_start));
+ }
+
+ if (msgType & CAMERA_MSG_COMPRESSED_IMAGE ) {
+ printf("JPEG done in %llu us\n", timeval_delay(&picture_start));
+ my_jpeg_callback(dataPtr);
+ }
+
+ if ( ( msgType & CAMERA_MSG_PREVIEW_METADATA ) &&
+ ( NULL != metadata ) ) {
+ printf("Face detected %d \n", metadata->number_of_faces);
+ my_face_callback(metadata);
+ }
+}
+
+void CameraHandler::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
+
+{
+ printf("Recording cb: %d %lld %p\n", msgType, timestamp, dataPtr.get());
+
+ static uint32_t count = 0;
+
+ //if(count==100)
+ //saveFile(dataPtr);
+
+ count++;
+
+ uint8_t *ptr = (uint8_t*) dataPtr->pointer();
+
+ printf("VID_CB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9]);
+
+ camera->releaseRecordingFrame(dataPtr);
+}
+
+int createPreviewSurface(unsigned int width, unsigned int height, int32_t pixFormat) {
+ unsigned int previewWidth, previewHeight;
+
+ if ( MAX_PREVIEW_SURFACE_WIDTH < width ) {
+ previewWidth = MAX_PREVIEW_SURFACE_WIDTH;
+ } else {
+ previewWidth = width;
+ }
+
+ if ( MAX_PREVIEW_SURFACE_HEIGHT < height ) {
+ previewHeight = MAX_PREVIEW_SURFACE_HEIGHT;
+ } else {
+ previewHeight = height;
+ }
+
+ client = new SurfaceComposerClient();
+
+ if ( NULL == client.get() ) {
+ printf("Unable to establish connection to Surface Composer \n");
+
+ return -1;
+ }
+
+ surfaceControl = client->createSurface(0,
+ previewWidth,
+ previewHeight,
+ pixFormat);
+
+ previewSurface = surfaceControl->getSurface();
+
+ client->openGlobalTransaction();
+ surfaceControl->setLayer(100000);
+ surfaceControl->setPosition(0, 0);
+ surfaceControl->setSize(previewWidth, previewHeight);
+ surfaceControl->show();
+ client->closeGlobalTransaction();
+
+ return 0;
+}
+
+void printSupportedParams()
+{
+ printf("\n\r\tSupported Cameras: %s", params.get("camera-indexes"));
+ printf("\n\r\tSupported Picture Sizes: %s", params.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES));
+ printf("\n\r\tSupported Picture Formats: %s", params.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
+ printf("\n\r\tSupported Preview Sizes: %s", params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES));
+ printf("\n\r\tSupported Preview Formats: %s", params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS));
+ printf("\n\r\tSupported Preview Frame Rates: %s", params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
+ printf("\n\r\tSupported Thumbnail Sizes: %s", params.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES));
+ printf("\n\r\tSupported Whitebalance Modes: %s", params.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE));
+ printf("\n\r\tSupported Effects: %s", params.get(CameraParameters::KEY_SUPPORTED_EFFECTS));
+ printf("\n\r\tSupported Scene Modes: %s", params.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES));
+ printf("\n\r\tSupported Focus Modes: %s", params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES));
+ printf("\n\r\tSupported Antibanding Options: %s", params.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING));
+ printf("\n\r\tSupported Flash Modes: %s", params.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES));
+ printf("\n\r\tSupported Focus Areas: %d", params.getInt(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS));
+
+ if ( NULL != params.get(CameraParameters::KEY_FOCUS_DISTANCES) ) {
+ printf("\n\r\tFocus Distances: %s \n", params.get(CameraParameters::KEY_FOCUS_DISTANCES));
+ }
+
+ return;
+}
+
+
+int destroyPreviewSurface() {
+
+ if ( NULL != previewSurface.get() ) {
+ previewSurface.clear();
+ }
+
+ if ( NULL != surfaceControl.get() ) {
+ surfaceControl->clear();
+ surfaceControl.clear();
+ }
+
+ if ( NULL != client.get() ) {
+ client->dispose();
+ client.clear();
+ }
+
+ return 0;
+}
+
+int openRecorder() {
+ recorder = new MediaRecorder();
+
+ if ( NULL == recorder.get() ) {
+ printf("Error while creating MediaRecorder\n");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int closeRecorder() {
+ if ( NULL == recorder.get() ) {
+ printf("invalid recorder reference\n");
+
+ return -1;
+ }
+
+ if ( recorder->init() < 0 ) {
+ printf("recorder failed to initialize\n");
+
+ return -1;
+ }
+
+ if ( recorder->close() < 0 ) {
+ printf("recorder failed to close\n");
+
+ return -1;
+ }
+
+ if ( recorder->release() < 0 ) {
+ printf("error while releasing recorder\n");
+
+ return -1;
+ }
+
+ recorder.clear();
+
+ return 0;
+}
+
+int configureRecorder() {
+
+ char videoFile[256],vbit_string[50];
+ videoFd = -1;
+
+ if ( ( NULL == recorder.get() ) || ( NULL == camera.get() ) ) {
+ printf("invalid recorder and/or camera references\n");
+
+ return -1;
+ }
+
+ camera->unlock();
+
+ sprintf(vbit_string,"video-param-encoding-bitrate=%u", VbitRate[VbitRateIDX].bit_rate);
+ String8 bit_rate(vbit_string);
+ if ( recorder->setParameters(bit_rate) < 0 ) {
+ printf("error while configuring bit rate\n");
+
+ return -1;
+ }
+
+ if ( recorder->setCamera(camera->remote(), camera->getRecordingProxy()) < 0 ) {
+ printf("error while setting the camera\n");
+
+ return -1;
+ }
+
+ if ( recorder->setVideoSource(VIDEO_SOURCE_CAMERA) < 0 ) {
+ printf("error while configuring camera video source\n");
+
+ return -1;
+ }
+
+
+ if ( recorder->setAudioSource(AUDIO_SOURCE_MIC) < 0 ) {
+ printf("error while configuring camera audio source\n");
+
+ return -1;
+ }
+
+ if ( recorder->setOutputFormat(outputFormat[outputFormatIDX].type) < 0 ) {
+ printf("error while configuring output format\n");
+
+ return -1;
+ }
+
+ if(mkdir("/mnt/sdcard/videos",0777) == -1)
+ printf("\n Directory --videos-- was not created \n");
+ sprintf(videoFile, "/mnt/sdcard/videos/video%d.%s", recording_counter,outputFormat[outputFormatIDX].desc);
+
+ videoFd = open(videoFile, O_CREAT | O_RDWR);
+
+ if(videoFd < 0){
+ printf("Error while creating video filename\n");
+
+ return -1;
+ }
+
+ if ( recorder->setOutputFile(videoFd, 0, 0) < 0 ) {
+ printf("error while configuring video filename\n");
+
+ return -1;
+ }
+
+ recording_counter++;
+
+ if (camera_index == 0) {
+ if ( recorder->setVideoFrameRate(fpsConstRanges[frameRateIDX].constFramerate) < 0 ) {
+ printf("error while configuring video framerate\n");
+ return -1;
+ }
+ }
+ else {
+ if ( recorder->setVideoFrameRate(fpsConstRangesSec[frameRateIDXSec].constFramerate) < 0 ) {
+ printf("error while configuring video framerate\n");
+ return -1;
+ }
+ }
+
+ if ( recorder->setVideoSize(VcaptureSize[VcaptureSizeIDX].width, VcaptureSize[VcaptureSizeIDX].height) < 0 ) {
+ printf("error while configuring video size\n");
+
+ return -1;
+ }
+
+ if ( recorder->setVideoEncoder(videoCodecs[videoCodecIDX].type) < 0 ) {
+ printf("error while configuring video codec\n");
+
+ return -1;
+ }
+
+ if ( recorder->setAudioEncoder(audioCodecs[audioCodecIDX].type) < 0 ) {
+ printf("error while configuring audio codec\n");
+
+ return -1;
+ }
+
+ if ( recorder->setPreviewSurface( surfaceControl->getSurface() ) < 0 ) {
+ printf("error while configuring preview surface\n");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int startRecording() {
+ if ( ( NULL == recorder.get() ) || ( NULL == camera.get() ) ) {
+ printf("invalid recorder and/or camera references\n");
+
+ return -1;
+ }
+
+ camera->unlock();
+
+ if ( recorder->prepare() < 0 ) {
+ printf("recorder prepare failed\n");
+
+ return -1;
+ }
+
+ if ( recorder->start() < 0 ) {
+ printf("recorder start failed\n");
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int stopRecording() {
+ if ( NULL == recorder.get() ) {
+ printf("invalid recorder reference\n");
+
+ return -1;
+ }
+
+ if ( recorder->stop() < 0 ) {
+ printf("recorder failed to stop\n");
+
+ return -1;
+ }
+
+ if ( 0 < videoFd ) {
+ close(videoFd);
+ }
+
+ return 0;
+}
+
+int openCamera() {
+ printf("openCamera(camera_index=%d)\n", camera_index);
+ camera = Camera::connect(camera_index);
+
+ if ( NULL == camera.get() ) {
+ printf("Unable to connect to CameraService\n");
+ printf("Retrying... \n");
+ sleep(1);
+ camera = Camera::connect(camera_index);
+
+ if ( NULL == camera.get() ) {
+ printf("Giving up!! \n");
+ return -1;
+ }
+ }
+
+ params = camera->getParameters();
+ camera->setParameters(params.flatten());
+
+ camera->setListener(new CameraHandler());
+
+ hardwareActive = true;
+
+ return 0;
+}
+
+int closeCamera() {
+ if ( NULL == camera.get() ) {
+ printf("invalid camera reference\n");
+
+ return -1;
+ }
+
+ camera->disconnect();
+ camera.clear();
+
+ hardwareActive = false;
+
+ return 0;
+}
+
+//Workaround for an issue seen with ICS SurfaceFlinger.
+//The last surface created is not getting rendered on screen,
+//in our case this is the preview surface. Here we artificially wait
+//for the preview to start and create a new temporary surface, which
+//gets destroyed immediately.
+int surfaceWorkaround(unsigned int width, unsigned int height, int32_t pixFormat) {
+ sleep(1);
+
+ if ( NULL == client.get() ) {
+ return NO_INIT;
+ }
+
+ sp<SurfaceControl> tmpSurface = client->createSurface(0,
+ width,
+ height,
+ pixFormat);
+
+ if ( NULL != tmpSurface.get() ) {
+ tmpSurface->clear();
+ tmpSurface.clear();
+ } else {
+ return -ENOMEM;
+ }
+
+ return NO_ERROR;
+}
+
+int startPreview() {
+ int previewWidth, previewHeight;
+ if (reSizePreview) {
+
+ if(recordingMode)
+ {
+ previewWidth = VcaptureSize[VcaptureSizeIDX].width;
+ previewHeight = VcaptureSize[VcaptureSizeIDX].height;
+ }else
+ {
+ previewWidth = previewSize[previewSizeIDX].width;
+ previewHeight = previewSize[previewSizeIDX].height;
+ }
+
+ if ( createPreviewSurface(previewWidth,
+ previewHeight,
+ pixelformat[previewFormat].pixelFormatDesc) < 0 ) {
+ printf("Error while creating preview surface\n");
+ return -1;
+ }
+
+ if ( !hardwareActive ) {
+ openCamera();
+ }
+
+ params.setPreviewSize(previewWidth, previewHeight);
+ params.setPictureSize(captureSize[captureSizeIDX].width, captureSize[captureSizeIDX].height);
+
+ camera->setParameters(params.flatten());
+ camera->setPreviewDisplay(previewSurface);
+
+ if(!hardwareActive) prevcnt = 0;
+
+ camera->startPreview();
+
+ previewRunning = true;
+ reSizePreview = false;
+
+ surfaceWorkaround( previewWidth, previewHeight, pixelformat[previewFormat].pixelFormatDesc);
+ }
+
+ return 0;
+}
+
+void stopPreview() {
+ if ( hardwareActive ) {
+ camera->stopPreview();
+
+ destroyPreviewSurface();
+
+ previewRunning = false;
+ reSizePreview = true;
+ closeCamera();
+ }
+}
+
+void initDefaults() {
+ camera_index = 0;
+ antibanding_mode = 0;
+ focus_mode = 0;
+ fpsRangeIdx = 0;
+ previewSizeIDX = 1; /* Default resolution set to WVGA */
+ captureSizeIDX = 3; /* Default capture resolution is 8MP */
+ frameRateIDX = ARRAY_SIZE(fpsConstRanges) - 1; /* Default frame rate is 30 FPS */
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+ VcaptureSizeIDX = ARRAY_SIZE(VcaptureSize) - 6;/* Default video record is WVGA */
+#else
+ VcaptureSizeIDX = ARRAY_SIZE(VcaptureSize) - 2;/* Default video record is WVGA */
+#endif
+ VbitRateIDX = ARRAY_SIZE(VbitRate) - 4; /*Default video bit rate is 4M */
+ thumbSizeIDX = 0;
+ compensation = 0.0;
+ awb_mode = 0;
+ effects_mode = 0;
+ scene_mode = 0;
+ caf_mode = 0;
+ vnf_mode = 0;
+ vstab_mode = 0;
+ expBracketIdx = 0;
+ flashIdx = 0;
+ rotation = 0;
+ zoomIDX = 0;
+ videoCodecIDX = 0;
+ gbceIDX = 0;
+#ifdef TARGET_OMAP4
+ ///Temporary fix until OMAP3 and OMAP4 3A values are synced
+ contrast = 90;
+ brightness = 50;
+ sharpness = 0;
+ saturation = 50;
+#else
+ contrast = 100;
+ brightness = 100;
+ sharpness = 0;
+ saturation = 100;
+#endif
+ iso_mode = 0;
+ capture_mode = 0;
+ exposure_mode = 0;
+ ippIDX = 0;//set the ipp to ldc-nsf as the capture mode is set to HQ by default
+ ippIDX_old = ippIDX;
+ jpegQuality = 85;
+ bufferStarvationTest = 0;
+ meter_mode = 0;
+ previewFormat = 1;
+ pictureFormat = 3; // jpeg
+ params.setPreviewSize(previewSize[previewSizeIDX].width, previewSize[previewSizeIDX].height);
+ params.setPictureSize(captureSize[captureSizeIDX].width, captureSize[captureSizeIDX].height);
+ params.set(CameraParameters::KEY_ROTATION, rotation);
+ params.set(KEY_COMPENSATION, (int) (compensation * 10));
+ params.set(params.KEY_WHITE_BALANCE, strawb_mode[awb_mode]);
+ params.set(KEY_MODE, (capture[capture_mode]));
+ params.set(params.KEY_SCENE_MODE, scene[scene_mode]);
+ params.set(KEY_CAF, caf_mode);
+ params.set(KEY_ISO, iso_mode);
+ params.set(KEY_GBCE, gbce[gbceIDX]);
+ params.set(KEY_SHARPNESS, sharpness);
+ params.set(KEY_CONTRAST, contrast);
+ params.set(CameraParameters::KEY_ZOOM, zoom[zoomIDX].idx);
+ params.set(KEY_EXPOSURE, exposure[exposure_mode]);
+ params.set(KEY_BRIGHTNESS, brightness);
+ params.set(KEY_SATURATION, saturation);
+ params.set(params.KEY_EFFECT, effects[effects_mode]);
+ params.setPreviewFrameRate(frameRate[ARRAY_SIZE(frameRate) - 1].fps);
+ params.set(params.KEY_ANTIBANDING, antibanding[antibanding_mode]);
+ params.set(params.KEY_FOCUS_MODE, focus[focus_mode]);
+ params.set(KEY_IPP, ippIDX);
+ params.set(CameraParameters::KEY_JPEG_QUALITY, jpegQuality);
+ params.setPreviewFormat(pixelformat[previewFormat].pixformat);
+ params.setPictureFormat(codingformat[pictureFormat]);
+ params.set(KEY_BUFF_STARV, bufferStarvationTest); //enable buffer starvation
+ params.set(KEY_METERING_MODE, metering[meter_mode]);
+ params.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, previewSize[thumbSizeIDX].width);
+ params.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, previewSize[thumbSizeIDX].height);
+ ManualConvergenceValuesIDX = ManualConvergenceDefaultValueIDX;
+ params.set(KEY_MANUALCONVERGENCE_VALUES, manualconvergencevalues[ManualConvergenceValuesIDX]);
+ params.set(KEY_S3D2D_PREVIEW_MODE, "off");
+ params.set(KEY_STEREO_CAMERA, "false");
+ params.set(KEY_EXIF_MODEL, MODEL);
+ params.set(KEY_EXIF_MAKE, MAKE);
+}
+
+int menu_gps() {
+ char ch;
+ char coord_str[100];
+
+ if (print_menu) {
+ printf("\n\n== GPS MENU ============================\n\n");
+ printf(" e. Latitude: %.7lf\n", latitude);
+ printf(" d. Longitude: %.7lf\n", longitude);
+ printf(" c. Altitude: %.7lf\n", altitude);
+ printf("\n");
+ printf(" q. Return to main menu\n");
+ printf("\n");
+ printf(" Choice: ");
+ }
+
+ ch = getchar();
+ printf("%c", ch);
+
+ print_menu = 1;
+
+ switch (ch) {
+
+ case 'e':
+ latitude += degree_by_step;
+
+ if (latitude > 90.0) {
+ latitude -= 180.0;
+ }
+
+ snprintf(coord_str, 7, "%.7lf", latitude);
+ params.set(params.KEY_GPS_LATITUDE, coord_str);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'd':
+ longitude += degree_by_step;
+
+ if (longitude > 180.0) {
+ longitude -= 360.0;
+ }
+
+ snprintf(coord_str, 7, "%.7lf", longitude);
+ params.set(params.KEY_GPS_LONGITUDE, coord_str);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'c':
+ altitude += 12345.67890123456789;
+
+ if (altitude > 100000.0) {
+ altitude -= 200000.0;
+ }
+
+ snprintf(coord_str, 100, "%.20lf", altitude);
+ params.set(params.KEY_GPS_ALTITUDE, coord_str);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'Q':
+ case 'q':
+ return -1;
+
+ default:
+ print_menu = 0;
+ break;
+ }
+
+ return 0;
+}
+
+int functional_menu() {
+ char ch;
+
+ if (print_menu) {
+
+ printf("\n\n=========== FUNCTIONAL TEST MENU ===================\n\n");
+
+ printf(" \n\nSTART / STOP / GENERAL SERVICES \n");
+ printf(" -----------------------------\n");
+ printf(" A Select Camera %s\n", cameras[camera_index]);
+ printf(" [. Resume Preview after capture\n");
+ printf(" 0. Reset to defaults\n");
+ printf(" q. Quit\n");
+ printf(" @. Disconnect and Reconnect to CameraService \n");
+ printf(" /. Enable/Disable showfps: %s\n", ((showfps)? "Enabled":"Disabled"));
+ printf(" a. GEO tagging settings menu\n");
+ printf(" E. Camera Capability Dump");
+
+
+ printf(" \n\n PREVIEW SUB MENU \n");
+ printf(" -----------------------------\n");
+ printf(" 1. Start Preview\n");
+ printf(" 2. Stop Preview\n");
+ printf(" ~. Preview format %s\n", pixelformat[previewFormat].pixformat);
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+ printf(" 4. Preview size: %4d x %4d - %s\n",previewSize[previewSizeIDX].width, previewSize[previewSizeIDX].height, previewSize[previewSizeIDX].desc);
+#else
+ printf(" 4. Preview size: %4d x %4d - %s\n",previewSize[previewSizeIDX].width, camera_index == 2 ? previewSize[previewSizeIDX].height*2 : previewSize[previewSizeIDX].height, previewSize[previewSizeIDX].desc);
+#endif
+ printf(" R. Preview framerate range: %s\n", fpsRanges[fpsRangeIdx].rangeDescription);
+ printf(" &. Dump a preview frame\n");
+ printf(" _. Auto Convergence mode: %s\n", autoconvergencemode[AutoConvergenceModeIDX]);
+ printf(" ^. Manual Convergence Value: %s\n", manualconvergencevalues[ManualConvergenceValuesIDX]);
+ printf(" {. 2D Preview in 3D Stereo Mode: %s\n", params.get(KEY_S3D2D_PREVIEW_MODE));
+
+ printf(" \n\n IMAGE CAPTURE SUB MENU \n");
+ printf(" -----------------------------\n");
+ printf(" p. Take picture/Full Press\n");
+ printf(" H. Exposure Bracketing: %s\n", expBracketing[expBracketIdx]);
+ printf(" U. Temporal Bracketing: %s\n", tempBracketing[tempBracketIdx]);
+ printf(" W. Temporal Bracketing Range: [-%d;+%d]\n", tempBracketRange, tempBracketRange);
+ printf(" $. Picture Format: %s\n", codingformat[pictureFormat]);
+ printf(" 3. Picture Rotation: %3d degree\n", rotation );
+ printf(" 5. Picture size: %4d x %4d - %s\n",captureSize[captureSizeIDX].width, captureSize[captureSizeIDX].height, captureSize[captureSizeIDX].name);
+ printf(" i. ISO mode: %s\n", iso[iso_mode]);
+ printf(" u. Capture Mode: %s\n", capture[capture_mode]);
+ printf(" k. IPP Mode: %s\n", ipp_mode[ippIDX]);
+ printf(" K. GBCE: %s\n", gbce[gbceIDX]);
+ printf(" o. Jpeg Quality: %d\n", jpegQuality);
+ printf(" #. Burst Images: %3d\n", burst);
+ printf(" :. Thumbnail Size: %4d x %4d - %s\n",previewSize[thumbSizeIDX].width, previewSize[thumbSizeIDX].height, previewSize[thumbSizeIDX].desc);
+ printf(" ': Thumbnail Quality %d\n", thumbQuality);
+
+ printf(" \n\n VIDEO CAPTURE SUB MENU \n");
+ printf(" -----------------------------\n");
+
+ printf(" 6. Start Video Recording\n");
+ printf(" 2. Stop Recording\n");
+ printf(" l. Video Capture resolution: %4d x %4d - %s\n",VcaptureSize[VcaptureSizeIDX].width,VcaptureSize[VcaptureSizeIDX].height, VcaptureSize[VcaptureSizeIDX].desc);
+ printf(" ]. Video Bit rate : %s\n", VbitRate[VbitRateIDX].desc);
+ printf(" 9. Video Codec: %s\n", videoCodecs[videoCodecIDX].desc);
+ printf(" D. Audio Codec: %s\n", audioCodecs[audioCodecIDX].desc);
+ printf(" v. Output Format: %s\n", outputFormat[outputFormatIDX].desc);
+
+ if (camera_index == 1) {
+ printf(" r. Framerate: %d\n", fpsConstRangesSec[frameRateIDXSec].constFramerate);
+ }
+ else {
+ printf(" r. Framerate: %d\n", fpsConstRanges[frameRateIDX].constFramerate);
+ }
+ printf(" *. Start Video Recording dump ( 1 raw frame ) \n");
+ printf(" B VNF %s \n", vnf[vnf_mode]);
+ printf(" C VSTAB %s", vstab[vstab_mode]);
+
+ printf(" \n\n 3A SETTING SUB MENU \n");
+ printf(" -----------------------------\n");
+
+ printf(" M. Measurement Data: %s\n", measurement[measurementIdx]);
+ printf(" F. Start face detection \n");
+ printf(" T. Stop face detection \n");
+ printf(" G. Touch/Focus area AF\n");
+ printf(" f. Auto Focus/Half Press\n");
+ printf(" J.Flash: %s\n", flashModes[flashIdx]);
+ printf(" 7. EV offset: %4.1f\n", compensation);
+ printf(" 8. AWB mode: %s\n", strawb_mode[awb_mode]);
+ printf(" z. Zoom %s\n", zoom[zoomIDX].zoom_description);
+ printf(" j. Exposure %s\n", exposure[exposure_mode]);
+ printf(" e. Effect: %s\n", effects[effects_mode]);
+ printf(" w. Scene: %s\n", scene[scene_mode]);
+ printf(" s. Saturation: %d\n", saturation);
+ printf(" c. Contrast: %d\n", contrast);
+ printf(" h. Sharpness: %d\n", sharpness);
+ printf(" b. Brightness: %d\n", brightness);
+ printf(" x. Antibanding: %s\n", antibanding[antibanding_mode]);
+ printf(" g. Focus mode: %s\n", focus[focus_mode]);
+ printf(" m. Metering mode: %s\n" , metering[meter_mode]);
+ printf(" <. Exposure Lock: %s\n", lock[elockidx]);
+ printf(" >. WhiteBalance Lock: %s\n",lock[wblockidx]);
+ printf("\n");
+ printf(" Choice: ");
+ }
+
+ ch = getchar();
+ printf("%c", ch);
+
+ print_menu = 1;
+
+ switch (ch) {
+
+ case '_':
+ AutoConvergenceModeIDX++;
+ AutoConvergenceModeIDX %= ARRAY_SIZE(autoconvergencemode);
+ params.set(KEY_AUTOCONVERGENCE, autoconvergencemode[AutoConvergenceModeIDX]);
+ if ( strcmp (autoconvergencemode[AutoConvergenceModeIDX], AUTOCONVERGENCE_MODE_MANUAL) == 0) {
+ params.set(KEY_MANUALCONVERGENCE_VALUES, manualconvergencevalues[ManualConvergenceValuesIDX]);
+ }
+ else {
+ params.set(KEY_MANUALCONVERGENCE_VALUES, manualconvergencevalues[ManualConvergenceDefaultValueIDX]);
+ ManualConvergenceValuesIDX = ManualConvergenceDefaultValueIDX;
+ }
+ camera->setParameters(params.flatten());
+
+ break;
+ case '^':
+ if ( strcmp (autoconvergencemode[AutoConvergenceModeIDX], AUTOCONVERGENCE_MODE_MANUAL) == 0) {
+ ManualConvergenceValuesIDX++;
+ ManualConvergenceValuesIDX %= ARRAY_SIZE(manualconvergencevalues);
+ params.set(KEY_MANUALCONVERGENCE_VALUES, manualconvergencevalues[ManualConvergenceValuesIDX]);
+ camera->setParameters(params.flatten());
+ }
+ break;
+ case 'A':
+ camera_index++;
+ camera_index %= ARRAY_SIZE(cameras);
+ if ( camera_index == 2) {
+ params.set(KEY_STEREO_CAMERA, "true");
+ } else {
+ params.set(KEY_STEREO_CAMERA, "false");
+ }
+ closeCamera();
+
+ openCamera();
+
+ if (camera_index == 0) {
+ params.setPreviewFrameRate(30);
+ } else {
+ params.setPreviewFrameRate(27);
+ }
+
+
+ break;
+ case '[':
+ if ( hardwareActive ) {
+ camera->setParameters(params.flatten());
+ camera->startPreview();
+ }
+ break;
+
+ case '0':
+ initDefaults();
+ break;
+
+ case '1':
+
+ if ( startPreview() < 0 ) {
+ printf("Error while starting preview\n");
+
+ return -1;
+ }
+
+ break;
+
+ case '2':
+ stopPreview();
+
+ if ( recordingMode ) {
+ camera->disconnect();
+ camera.clear();
+ stopRecording();
+ closeRecorder();
+
+ camera = Camera::connect(camera_index);
+ if ( NULL == camera.get() ) {
+ sleep(1);
+ camera = Camera::connect(camera_index);
+ if ( NULL == camera.get() ) {
+ return -1;
+ }
+ }
+ camera->setListener(new CameraHandler());
+ camera->setParameters(params.flatten());
+ recordingMode = false;
+ }
+
+ break;
+
+ case '3':
+ rotation += 90;
+ rotation %= 360;
+ params.set(CameraParameters::KEY_ROTATION, rotation);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '4':
+ previewSizeIDX += 1;
+ previewSizeIDX %= ARRAY_SIZE(previewSize);
+ if ( strcmp(params.get(KEY_STEREO_CAMERA), "false") == 0 ) {
+ params.setPreviewSize(previewSize[previewSizeIDX].width, previewSize[previewSizeIDX].height);
+ } else {
+ params.setPreviewSize(previewSize[previewSizeIDX].width, previewSize[previewSizeIDX].height*2);
+ }
+ reSizePreview = true;
+
+ if ( hardwareActive && previewRunning ) {
+ camera->stopPreview();
+ camera->setParameters(params.flatten());
+ camera->startPreview();
+ } else if ( hardwareActive ) {
+ camera->setParameters(params.flatten());
+ }
+
+ break;
+
+ case '5':
+ captureSizeIDX += 1;
+ captureSizeIDX %= ARRAY_SIZE(captureSize);
+ params.setPictureSize(captureSize[captureSizeIDX].width, captureSize[captureSizeIDX].height);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'l':
+ case 'L':
+ VcaptureSizeIDX++;
+ VcaptureSizeIDX %= ARRAY_SIZE(VcaptureSize);
+ break;
+
+ case ']':
+ VbitRateIDX++;
+ VbitRateIDX %= ARRAY_SIZE(VbitRate);
+ break;
+
+
+ case '6':
+
+ if ( !recordingMode ) {
+
+ recordingMode = true;
+
+ if ( startPreview() < 0 ) {
+ printf("Error while starting preview\n");
+
+ return -1;
+ }
+
+ if ( openRecorder() < 0 ) {
+ printf("Error while openning video recorder\n");
+
+ return -1;
+ }
+
+ if ( configureRecorder() < 0 ) {
+ printf("Error while configuring video recorder\n");
+
+ return -1;
+ }
+
+ if ( startRecording() < 0 ) {
+ printf("Error while starting video recording\n");
+
+ return -1;
+ }
+ }
+
+ break;
+
+ case '7':
+
+ if ( compensation > 2.0) {
+ compensation = -2.0;
+ } else {
+ compensation += 0.1;
+ }
+
+ params.set(KEY_COMPENSATION, (int) (compensation * 10));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '8':
+ awb_mode++;
+ awb_mode %= ARRAY_SIZE(strawb_mode);
+ params.set(params.KEY_WHITE_BALANCE, strawb_mode[awb_mode]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '9':
+ videoCodecIDX++;
+ videoCodecIDX %= ARRAY_SIZE(videoCodecs);
+ break;
+ case '~':
+ previewFormat += 1;
+ previewFormat %= ARRAY_SIZE(pixelformat) - 1;
+ params.setPreviewFormat(pixelformat[previewFormat].pixformat);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+ case '$':
+ pictureFormat += 1;
+ if ( strcmp(params.get(KEY_STEREO_CAMERA), "false") == 0 && pictureFormat > 4 )
+ pictureFormat = 0;
+ pictureFormat %= ARRAY_SIZE(codingformat);
+ params.setPictureFormat(codingformat[pictureFormat]);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '?' :
+ ///Set mode=3 to select video mode
+ params.set(KEY_MODE, 3);
+ params.set(KEY_VNF, 1);
+ params.set(KEY_VSTAB, 1);
+ break;
+
+ case ':':
+ thumbSizeIDX += 1;
+ thumbSizeIDX %= ARRAY_SIZE(previewSize);
+ params.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, previewSize[thumbSizeIDX].width);
+ params.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, previewSize[thumbSizeIDX].height);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '\'':
+ if ( thumbQuality >= 100) {
+ thumbQuality = 0;
+ } else {
+ thumbQuality += 5;
+ }
+
+ params.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, thumbQuality);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'B' :
+ vnf_mode++;
+ vnf_mode %= ARRAY_SIZE(vnf);
+ params.set(KEY_VNF, vnf_mode);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'C' :
+ vstab_mode++;
+ vstab_mode %= ARRAY_SIZE(vstab);
+ params.set(KEY_VSTAB, vstab_mode);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'E':
+ if(hardwareActive)
+ params.unflatten(camera->getParameters());
+ printSupportedParams();
+ break;
+
+ case '*':
+ if ( hardwareActive )
+ camera->startRecording();
+ break;
+
+ case 'o':
+ if ( jpegQuality >= 100) {
+ jpegQuality = 0;
+ } else {
+ jpegQuality += 5;
+ }
+
+ params.set(CameraParameters::KEY_JPEG_QUALITY, jpegQuality);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'M':
+ measurementIdx = (measurementIdx + 1)%ARRAY_SIZE(measurement);
+ params.set(KEY_MEASUREMENT, measurement[measurementIdx]);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+ case 'm':
+ {
+ meter_mode = (meter_mode + 1)%ARRAY_SIZE(metering);
+ params.set(KEY_METERING_MODE, metering[meter_mode]);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+ }
+
+ case 'k':
+ ippIDX += 1;
+ ippIDX %= ARRAY_SIZE(ipp_mode);
+ ippIDX_old = ippIDX;
+
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+ params.set(KEY_IPP, ipp_mode[ippIDX]);
+#else
+ params.set(KEY_IPP, ippIDX);
+#endif
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'K':
+ gbceIDX+= 1;
+ gbceIDX %= ARRAY_SIZE(gbce);
+ params.set(KEY_GBCE, gbce[gbceIDX]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'F':
+ if ( hardwareActive )
+ camera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, 0, 0);
+
+ break;
+
+ case 'T':
+
+ if ( hardwareActive )
+ camera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0);
+
+ break;
+
+ case '@':
+ if ( hardwareActive ) {
+
+ closeCamera();
+
+ if ( 0 >= openCamera() ) {
+ printf( "Reconnected to CameraService \n");
+ }
+ }
+
+ break;
+
+ case '#':
+
+ if ( burst >= MAX_BURST ) {
+ burst = 0;
+ } else {
+ burst += BURST_INC;
+ }
+ params.set(KEY_BURST, burst);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'J':
+ flashIdx++;
+ flashIdx %= ARRAY_SIZE(flashModes);
+ params.set(CameraParameters::KEY_FLASH_MODE, (flashModes[flashIdx]));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'u':
+ capture_mode++;
+ capture_mode %= ARRAY_SIZE(capture);
+
+ // HQ should always be in ldc-nsf
+ // if not HQ, then return the ipp to its previous state
+ if( !strcmp(capture[capture_mode], "high-quality") ) {
+ ippIDX_old = ippIDX;
+ ippIDX = 3;
+ params.set(KEY_IPP, ipp_mode[ippIDX]);
+ } else {
+ ippIDX = ippIDX_old;
+ }
+
+ params.set(KEY_MODE, (capture[capture_mode]));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'U':
+ tempBracketIdx++;
+ tempBracketIdx %= ARRAY_SIZE(tempBracketing);
+ params.set(KEY_TEMP_BRACKETING, tempBracketing[tempBracketIdx]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'H':
+ expBracketIdx++;
+ expBracketIdx %= ARRAY_SIZE(expBracketing);
+
+ params.set(KEY_EXP_BRACKETING_RANGE, expBracketingRange[expBracketIdx]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'W':
+ tempBracketRange++;
+ tempBracketRange %= TEMP_BRACKETING_MAX_RANGE;
+ if ( 0 == tempBracketRange ) {
+ tempBracketRange = 1;
+ }
+
+ params.set(KEY_TEMP_BRACKETING_NEG, tempBracketRange);
+ params.set(KEY_TEMP_BRACKETING_POS, tempBracketRange);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'w':
+ scene_mode++;
+ scene_mode %= ARRAY_SIZE(scene);
+ params.set(params.KEY_SCENE_MODE, scene[scene_mode]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'i':
+ iso_mode++;
+ iso_mode %= ARRAY_SIZE(iso);
+ params.set(KEY_ISO, iso[iso_mode]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'h':
+ if ( sharpness >= 100) {
+ sharpness = 0;
+ } else {
+ sharpness += 10;
+ }
+ params.set(KEY_SHARPNESS, sharpness);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'D':
+ {
+ audioCodecIDX++;
+ audioCodecIDX %= ARRAY_SIZE(audioCodecs);
+ break;
+ }
+
+ case 'v':
+ {
+ outputFormatIDX++;
+ outputFormatIDX %= ARRAY_SIZE(outputFormat);
+ break;
+ }
+
+ case 'z':
+ zoomIDX++;
+ zoomIDX %= ARRAY_SIZE(zoom);
+ params.set(CameraParameters::KEY_ZOOM, zoom[zoomIDX].idx);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'j':
+ exposure_mode++;
+ exposure_mode %= ARRAY_SIZE(exposure);
+ params.set(KEY_EXPOSURE, exposure[exposure_mode]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'c':
+ if( contrast >= 200){
+ contrast = 0;
+ } else {
+ contrast += 10;
+ }
+ params.set(KEY_CONTRAST, contrast);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+ case 'b':
+ if ( brightness >= 200) {
+ brightness = 0;
+ } else {
+ brightness += 10;
+ }
+
+ params.set(KEY_BRIGHTNESS, brightness);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 's':
+ case 'S':
+ if ( saturation >= 100) {
+ saturation = 0;
+ } else {
+ saturation += 10;
+ }
+
+ params.set(KEY_SATURATION, saturation);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'e':
+ effects_mode++;
+ effects_mode %= ARRAY_SIZE(effects);
+ params.set(params.KEY_EFFECT, effects[effects_mode]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'r':
+
+
+ if (camera_index == 0) {
+ frameRateIDX += 1;
+ frameRateIDX %= ARRAY_SIZE(fpsConstRanges);
+ params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, fpsConstRanges[frameRateIDX].range);
+ } else
+ {
+ frameRateIDXSec += 1;
+ frameRateIDXSec %= ARRAY_SIZE(fpsConstRangesSec);
+ params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, fpsConstRangesSec[frameRateIDXSec].range);
+
+
+ }
+
+ if ( hardwareActive ) {
+ camera->setParameters(params.flatten());
+ }
+
+ break;
+
+ case 'R':
+ fpsRangeIdx += 1;
+ fpsRangeIdx %= ARRAY_SIZE(fpsRanges);
+ params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, fpsRanges[fpsRangeIdx].range);
+
+ if ( hardwareActive ) {
+ camera->setParameters(params.flatten());
+ }
+
+ break;
+
+ case 'x':
+ antibanding_mode++;
+ antibanding_mode %= ARRAY_SIZE(antibanding);
+ params.set(params.KEY_ANTIBANDING, antibanding[antibanding_mode]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'g':
+ focus_mode++;
+ focus_mode %= ARRAY_SIZE(focus);
+ params.set(params.KEY_FOCUS_MODE, focus[focus_mode]);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'G':
+
+ params.set(CameraParameters::KEY_FOCUS_AREAS, TEST_FOCUS_AREA);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ params.remove(CameraParameters::KEY_FOCUS_AREAS);
+
+ case 'f':
+
+ gettimeofday(&autofocus_start, 0);
+
+ if ( hardwareActive )
+ camera->autoFocus();
+
+ break;
+
+ case 'p':
+
+ gettimeofday(&picture_start, 0);
+
+ if ( hardwareActive )
+ camera->takePicture(CAMERA_MSG_COMPRESSED_IMAGE|CAMERA_MSG_RAW_IMAGE);
+
+ break;
+
+ case '&':
+ printf("Enabling Preview Callback");
+ dump_preview = 1;
+ if ( hardwareActive )
+ camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ break;
+
+ case '{':
+ if ( strcmp(params.get(KEY_S3D2D_PREVIEW_MODE), "off") == 0 )
+ {
+ params.set(KEY_S3D2D_PREVIEW_MODE, "on");
+ }
+ else
+ {
+ params.set(KEY_S3D2D_PREVIEW_MODE, "off");
+ }
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'a':
+
+ while (1) {
+ if ( menu_gps() < 0)
+ break;
+ };
+
+ break;
+
+ case 'q':
+
+ stopPreview();
+
+ return -1;
+
+ case '/':
+ {
+ if (showfps)
+ {
+ property_set("debug.image.showfps", "0");
+ showfps = false;
+ }
+ else
+ {
+ property_set("debug.image.showfps", "1");
+ showfps = true;
+ }
+ break;
+ }
+
+ case '<':
+ elockidx += 1;
+ elockidx %= ARRAY_SIZE(lock);
+ params.set(KEY_AUTO_EXPOSURE_LOCK, lock[elockidx]);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case '>':
+ wblockidx += 1;
+ wblockidx %= ARRAY_SIZE(lock);
+ params.set(KEY_AUTO_WHITEBALANCE_LOCK, lock[wblockidx]);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ default:
+ print_menu = 0;
+
+ break;
+ }
+
+ return 0;
+}
+
+void print_usage() {
+ printf(" USAGE: camera_test <param> <script>\n");
+ printf(" <param>\n-----------\n\n");
+ printf(" F or f -> Functional tests \n");
+ printf(" A or a -> API tests \n");
+ printf(" E or e -> Error scenario tests \n");
+ printf(" S or s -> Stress tests; with syslink trace \n");
+ printf(" SN or sn -> Stress tests; No syslink trace \n\n");
+ printf(" <script>\n----------\n");
+ printf("Script name (Only for stress tests)\n\n");
+ return;
+}
+
+int error_scenario() {
+ char ch;
+ status_t stat = NO_ERROR;
+
+ if (print_menu) {
+ printf(" 0. Buffer need\n");
+ printf(" 1. Not enough memory\n");
+ printf(" 2. Media server crash\n");
+ printf(" 3. Overlay object request\n");
+ printf(" 4. Pass unsupported preview&picture format\n");
+ printf(" 5. Pass unsupported preview&picture resolution\n");
+ printf(" 6. Pass unsupported preview framerate\n");
+
+ printf(" q. Quit\n");
+ printf(" Choice: ");
+ }
+
+ print_menu = 1;
+ ch = getchar();
+ printf("%c\n", ch);
+
+ switch (ch) {
+ case '0': {
+ printf("Case0:Buffer need\n");
+ bufferStarvationTest = 1;
+ params.set(KEY_BUFF_STARV, bufferStarvationTest); //enable buffer starvation
+
+ if ( !recordingMode ) {
+ recordingMode = true;
+ if ( startPreview() < 0 ) {
+ printf("Error while starting preview\n");
+
+ return -1;
+ }
+
+ if ( openRecorder() < 0 ) {
+ printf("Error while openning video recorder\n");
+
+ return -1;
+ }
+
+ if ( configureRecorder() < 0 ) {
+ printf("Error while configuring video recorder\n");
+
+ return -1;
+ }
+
+ if ( startRecording() < 0 ) {
+ printf("Error while starting video recording\n");
+
+ return -1;
+ }
+
+ }
+
+ usleep(1000000);//1s
+
+ stopPreview();
+
+ if ( recordingMode ) {
+ stopRecording();
+ closeRecorder();
+
+ recordingMode = false;
+ }
+
+ break;
+ }
+
+ case '1': {
+ printf("Case1:Not enough memory\n");
+ int* tMemoryEater = new int[999999999];
+
+ if (!tMemoryEater) {
+ printf("Not enough memory\n");
+ return -1;
+ } else {
+ delete tMemoryEater;
+ }
+
+ break;
+ }
+
+ case '2': {
+ printf("Case2:Media server crash\n");
+ //camera = Camera::connect();
+
+ if ( NULL == camera.get() ) {
+ printf("Unable to connect to CameraService\n");
+ return -1;
+ }
+
+ break;
+ }
+
+ case '3': {
+ printf("Case3:Overlay object request\n");
+ int err = 0;
+
+ err = open("/dev/video5", O_RDWR);
+
+ if (err < 0) {
+ printf("Could not open the camera device5: %d\n", err );
+ return err;
+ }
+
+ if ( startPreview() < 0 ) {
+ printf("Error while starting preview\n");
+ return -1;
+ }
+
+ usleep(1000000);//1s
+
+ stopPreview();
+
+ close(err);
+ break;
+ }
+
+ case '4': {
+
+ if ( hardwareActive ) {
+
+ params.setPictureFormat("invalid-format");
+ params.setPreviewFormat("invalid-format");
+
+ stat = camera->setParameters(params.flatten());
+
+ if ( NO_ERROR != stat ) {
+ printf("Test passed!\n");
+ } else {
+ printf("Test failed!\n");
+ }
+
+ initDefaults();
+ }
+
+ break;
+ }
+
+ case '5': {
+
+ if ( hardwareActive ) {
+
+ params.setPictureSize(-1, -1);
+ params.setPreviewSize(-1, -1);
+
+ stat = camera->setParameters(params.flatten());
+
+ if ( NO_ERROR != stat ) {
+ printf("Test passed!\n");
+ } else {
+ printf("Test failed!\n");
+ }
+
+ initDefaults();
+ }
+
+ break;
+ }
+
+ case '6': {
+
+ if ( hardwareActive ) {
+
+ params.setPreviewFrameRate(-1);
+
+ stat = camera->setParameters(params.flatten());
+
+ if ( NO_ERROR != stat ) {
+ printf("Test passed!\n");
+ } else {
+ printf("Test failed!\n");
+ }
+
+ initDefaults();
+ }
+
+
+ break;
+ }
+
+ case 'q': {
+ return -1;
+ }
+
+ default: {
+ print_menu = 0;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int restartCamera() {
+
+ const char dir_path_name[80] = SDCARD_PATH;
+
+ printf("+++Restarting Camera After Error+++\n");
+ stopPreview();
+
+ if (recordingMode) {
+ stopRecording();
+ closeRecorder();
+
+ recordingMode = false;
+ }
+
+ sleep(3); //Wait a bit before restarting
+
+ restartCount++;
+
+ if (strcpy(dir_path, dir_path_name) == NULL)
+ {
+ printf("Error reseting dir name");
+ return -1;
+ }
+
+ if ( openCamera() < 0 )
+ {
+ printf("+++Camera Restarted Failed+++\n");
+ system("echo camerahal_test > /sys/power/wake_unlock");
+ return -1;
+ }
+
+ initDefaults();
+
+ stopScript = false;
+
+ printf("+++Camera Restarted Successfully+++\n");
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ char *cmd;
+ int pid;
+ sp<ProcessState> proc(ProcessState::self());
+
+ unsigned long long st, end, delay;
+ timeval current_time;
+
+ gettimeofday(&current_time, 0);
+
+ st = current_time.tv_sec * 1000000 + current_time.tv_usec;
+
+ cmd = NULL;
+
+ if ( argc < 2 ) {
+ printf(" Please enter atleast 1 argument\n");
+ print_usage();
+
+ return 0;
+ }
+ system("echo camerahal_test > /sys/power/wake_lock");
+ if ( argc < 3 ) {
+ switch (*argv[1]) {
+ case 'S':
+ case 's':
+ printf("This is stress / regression tests \n");
+ printf("Provide script file as 2nd argument\n");
+
+ break;
+
+ case 'F':
+ case 'f':
+ ProcessState::self()->startThreadPool();
+
+ if ( openCamera() < 0 ) {
+ printf("Camera initialization failed\n");
+ system("echo camerahal_test > /sys/power/wake_unlock");
+ return -1;
+ }
+
+ initDefaults();
+ print_menu = 1;
+
+ while ( 1 ) {
+ if ( functional_menu() < 0 )
+ break;
+ };
+
+ break;
+
+ case 'A':
+ case 'a':
+ printf("API level test cases coming soon ... \n");
+
+ break;
+
+ case 'E':
+ case 'e': {
+ ProcessState::self()->startThreadPool();
+
+ if ( openCamera() < 0 ) {
+ printf("Camera initialization failed\n");
+ system("echo camerahal_test > /sys/power/wake_unlock");
+ return -1;
+ }
+
+ initDefaults();
+ print_menu = 1;
+
+ while (1) {
+ if (error_scenario() < 0) {
+ break;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ printf("INVALID OPTION USED\n");
+ print_usage();
+
+ break;
+ }
+ } else if ( ( argc == 3) && ( ( *argv[1] == 'S' ) || ( *argv[1] == 's') ) ) {
+
+ if((argv[1][1] == 'N') || (argv[1][1] == 'n')) {
+ bLogSysLinkTrace = false;
+ }
+
+ ProcessState::self()->startThreadPool();
+
+ if ( openCamera() < 0 ) {
+ printf("Camera initialization failed\n");
+ system("echo camerahal_test > /sys/power/wake_unlock");
+ return -1;
+ }
+
+ initDefaults();
+
+ cmd = load_script(argv[2]);
+
+ if ( cmd != NULL) {
+ start_logging(argv[2], pid);
+ stressTest = true;
+
+ while (1)
+ {
+ if ( execute_functional_script(cmd) == 0 )
+ {
+ break;
+ }
+ else
+ {
+ printf("CameraTest Restarting Camera...\n");
+
+ free(cmd);
+ cmd = NULL;
+
+ if ( (restartCamera() != 0) || ((cmd = load_script(argv[2])) == NULL) )
+ {
+ printf("ERROR::CameraTest Restarting Camera...\n");
+ break;
+ }
+ }
+ }
+ free(cmd);
+ stop_logging(pid);
+ }
+ } else if ( ( argc == 3) && ( ( *argv[1] == 'E' ) || ( *argv[1] == 'e') ) ) {
+
+ ProcessState::self()->startThreadPool();
+
+ if ( openCamera() < 0 ) {
+ printf("Camera initialization failed\n");
+ system("echo camerahal_test > /sys/power/wake_unlock");
+ return -1;
+ }
+
+ initDefaults();
+
+ cmd = load_script(argv[2]);
+
+ if ( cmd != NULL) {
+ start_logging(argv[2], pid);
+ execute_error_script(cmd);
+ free(cmd);
+ stop_logging(pid);
+ }
+
+ } else {
+ printf("INVALID OPTION USED\n");
+ print_usage();
+ }
+
+ gettimeofday(&current_time, 0);
+ end = current_time.tv_sec * 1000000 + current_time.tv_usec;
+ delay = end - st;
+ printf("Application clossed after: %llu ms\n", delay);
+ system("echo camerahal_test > /sys/power/wake_unlock");
+ return 0;
+}
+
diff --git a/test/CameraHal/camera_test_script.cpp b/test/CameraHal/camera_test_script.cpp
new file mode 100644
index 0000000..15a403c
--- /dev/null
+++ b/test/CameraHal/camera_test_script.cpp
@@ -0,0 +1,1373 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <semaphore.h>
+#include <pthread.h>
+
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/ISurfaceComposerClient.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+
+#include <camera/Camera.h>
+#include <camera/ICamera.h>
+#include <media/mediarecorder.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+#include <camera/CameraParameters.h>
+
+#include <sys/wait.h>
+
+#include "camera_test.h"
+
+using namespace android;
+
+extern bool stopScript;
+extern bool hardwareActive;
+extern sp<Camera> camera;
+extern CameraParameters params;
+extern bool recordingMode;
+extern int camera_index;
+extern int rotation;
+extern const preview_size previewSize [];
+extern const Vcapture_size VcaptureSize [];
+extern const capture_Size captureSize[];
+extern const outformat outputFormat[];
+extern const video_Codecs videoCodecs[];
+extern const audio_Codecs audioCodecs[];
+extern const V_bitRate VbitRate[];
+extern const fps_ranges fpsRanges[];
+extern const fpsConst_Ranges fpsConstRanges[];
+extern const fpsConst_RangesSec fpsConstRangesSec[];
+extern const Zoom zoom [];
+extern int previewSizeIDX;
+extern bool reSizePreview;
+extern bool previewRunning;
+extern int captureSizeIDX;
+extern float compensation;
+extern int videoCodecIDX;
+extern int outputFormatIDX;
+extern int audioCodecIDX;
+extern int VcaptureSizeIDX;
+extern int VbitRateIDX;
+extern int thumbSizeIDX;
+extern int thumbQuality;
+extern int jpegQuality;
+extern int dump_preview;
+extern int ippIDX_old;
+extern const char *capture[];
+extern int capture_mode;
+extern int ippIDX;
+extern const char *ipp_mode[];
+extern int tempBracketRange;
+extern int iso_mode;
+extern int sharpness;
+extern int contrast;
+extern int zoomIDX;
+extern int brightness;
+extern int saturation;
+extern int fpsRangeIdx;
+extern timeval autofocus_start, picture_start;
+extern const char *cameras[];
+extern double latitude;
+extern double degree_by_step;
+extern double longitude;
+extern double altitude;
+extern char dir_path[80];
+extern int AutoConvergenceModeIDX;
+extern const char *autoconvergencemode[];
+extern const char *manualconvergencevalues[];
+extern const int ManualConvergenceDefaultValueIDX;
+extern size_t length_cam;
+extern char script_name[];
+extern int restartCount;
+extern bool bLogSysLinkTrace;
+extern int bufferStarvationTest;
+extern size_t length_previewSize;
+extern size_t lenght_Vcapture_size;
+extern size_t length_outformat;
+extern size_t length_capture_Size;
+extern size_t length_video_Codecs;
+extern size_t length_audio_Codecs;
+extern size_t length_V_bitRate;
+extern size_t length_Zoom;
+extern size_t length_fps_ranges;
+extern size_t length_fpsConst_Ranges;
+extern size_t length_fpsConst_RangesSec;
+
+
+int execute_functional_script(char *script) {
+ char *cmd, *ctx, *cycle_cmd, *temp_cmd;
+ char id;
+ unsigned int i;
+ int dly;
+ int cycleCounter = 1;
+ int tLen = 0;
+ unsigned int iteration = 0;
+ status_t ret = NO_ERROR;
+ int frameR = 20;
+ int frameRateIndex = 0;
+
+ LOG_FUNCTION_NAME;
+
+ dump_mem_status();
+
+ cmd = strtok_r((char *) script, DELIMITER, &ctx);
+
+ while ( NULL != cmd && (stopScript == false)) {
+ id = cmd[0];
+ printf("Full Command: %s \n", cmd);
+ printf("Command: %c \n", cmd[0]);
+
+ switch (id) {
+
+ // Case for Suspend-Resume Feature
+ case '!': {
+ // STEP 1: Mount Debugfs
+ system("mkdir /debug");
+ system("mount -t debugfs debugfs /debug");
+
+ // STEP 2: Set up wake up Timer - wake up happens after 5 seconds
+ system("echo 10 > /debug/pm_debug/wakeup_timer_seconds");
+
+ // STEP 3: Make system ready for Suspend
+ system("echo camerahal_test > /sys/power/wake_unlock");
+ // Release wake lock held by test app
+ printf(" Wake lock released ");
+ system("cat /sys/power/wake_lock");
+ system("sendevent /dev/input/event0 1 60 1");
+ system("sendevent /dev/input/event0 1 60 0");
+ // Simulate F2 key press to make display OFF
+ printf(" F2 event simulation complete ");
+
+ //STEP 4: Wait for system Resume and then simuate F1 key
+ sleep(50);//50s // This delay is not related to suspend resume timer
+ printf(" After 30 seconds of sleep");
+ system("sendevent /dev/input/event0 1 59 0");
+ system("sendevent /dev/input/event0 1 59 1");
+ // Simulate F1 key press to make display ON
+ system("echo camerahal_test > /sys/power/wake_lock");
+ // Acquire wake lock for test app
+
+ break;
+ }
+
+ case '[':
+ if ( hardwareActive )
+ {
+
+ camera->setParameters(params.flatten());
+
+ printf("starting camera preview..");
+ status_t ret = camera->startPreview();
+ if(ret !=NO_ERROR)
+ {
+ printf("startPreview failed %d..", ret);
+ }
+ }
+ break;
+ case '+': {
+ cycleCounter = atoi(cmd + 1);
+ cycle_cmd = get_cycle_cmd(ctx);
+ tLen = strlen(cycle_cmd);
+ temp_cmd = new char[tLen+1];
+
+ for (int ind = 0; ind < cycleCounter; ind++) {
+ strcpy(temp_cmd, cycle_cmd);
+ if ( execute_functional_script(temp_cmd) != 0 )
+ return -1;
+ temp_cmd[0] = '\0';
+
+ //patch for image capture
+ //[
+ if (ind < cycleCounter - 1) {
+ if (hardwareActive == false) {
+ if ( openCamera() < 0 ) {
+ printf("Camera initialization failed\n");
+
+ return -1;
+ }
+
+ initDefaults();
+ }
+ }
+
+ //]
+ }
+
+ ctx += tLen + 1;
+
+ if (temp_cmd) {
+ delete temp_cmd;
+ temp_cmd = NULL;
+ }
+
+ if (cycle_cmd) {
+ delete cycle_cmd;
+ cycle_cmd = NULL;
+ }
+
+ break;
+ }
+
+ case '0':
+ {
+ initDefaults();
+ break;
+ }
+
+ case '1':
+
+ if ( startPreview() < 0 ) {
+ printf("Error while starting preview\n");
+
+ return -1;
+ }
+
+ break;
+
+ case '2':
+ stopPreview();
+
+ if ( recordingMode ) {
+
+ camera->disconnect();
+ camera.clear();
+ stopRecording();
+ closeRecorder();
+
+ camera = Camera::connect(camera_index);
+ if ( NULL == camera.get() ) {
+ sleep(1);
+ camera = Camera::connect(camera_index);
+
+ if ( NULL == camera.get() ) {
+ return -1;
+ }
+ }
+ camera->setListener(new CameraHandler());
+ camera->setParameters(params.flatten());
+
+ recordingMode = false;
+ }
+
+ break;
+
+ case '3':
+ rotation = atoi(cmd + 1);
+ params.set(CameraParameters::KEY_ROTATION, rotation);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '4':
+ {
+ printf("Setting resolution...");
+ int width, height;
+ for(i = 0; i < length_previewSize ; i++)
+ {
+ if( strcmp((cmd + 1), previewSize[i].desc) == 0)
+ {
+ width = previewSize[i].width;
+ height = previewSize[i].height;
+ previewSizeIDX = i;
+ break;
+ }
+ }
+
+ if (i == length_previewSize ) //if the resolution is not in the supported ones
+ {
+ char *res = NULL;
+ res = strtok(cmd + 1, "x");
+ width = atoi(res);
+ res = strtok(NULL, "x");
+ height = atoi(res);
+ }
+
+ if ( strcmp(params.get(KEY_STEREO_CAMERA), "true") == 0 ) {
+ height *=2;
+ }
+ printf("Resolution: %d x %d\n", width, height);
+ params.setPreviewSize(width, height);
+ reSizePreview = true;
+
+ if ( hardwareActive && previewRunning ) {
+ camera->stopPreview();
+ camera->setParameters(params.flatten());
+ camera->startPreview();
+ } else if ( hardwareActive ) {
+ camera->setParameters(params.flatten());
+ }
+
+ break;
+ }
+ case '5':
+
+ for (i = 0; i < length_capture_Size; i++) {
+ if ( strcmp((cmd + 1), captureSize[i].name) == 0)
+ break;
+ }
+
+ if ( i < length_capture_Size ) {
+ params.setPictureSize(captureSize[i].width, captureSize[i].height);
+ captureSizeIDX = i;
+ }
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '6':
+
+ if ( !recordingMode ) {
+
+ recordingMode = true;
+
+ if ( startPreview() < 0 ) {
+ printf("Error while starting preview\n");
+
+ return -1;
+ }
+
+ if ( openRecorder() < 0 ) {
+ printf("Error while openning video recorder\n");
+
+ return -1;
+ }
+
+ if ( configureRecorder() < 0 ) {
+ printf("Error while configuring video recorder\n");
+
+ return -1;
+ }
+
+ if ( startRecording() < 0 ) {
+ printf("Error while starting video recording\n");
+
+ return -1;
+ }
+
+ }
+
+ break;
+
+ case '7':
+ compensation = atof(cmd + 1);
+ params.set(KEY_COMPENSATION, (int) (compensation * 10));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '8':
+ params.set(params.KEY_WHITE_BALANCE, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '9':
+ for(i = 0; i < length_video_Codecs; i++)
+ {
+ if( strcmp((cmd + 1), videoCodecs[i].desc) == 0)
+ {
+ videoCodecIDX = i;
+ printf("Video Codec Selected: %s\n",
+ videoCodecs[i].desc);
+ break;
+ }
+ }
+ break;
+
+ case 'v':
+ for(i = 0; i < length_outformat; i++)
+
+ {
+ if( strcmp((cmd + 1), outputFormat[i].desc) == 0)
+ {
+ outputFormatIDX = i;
+ printf("Video Codec Selected: %s\n",
+ videoCodecs[i].desc);
+ break;
+ }
+ }
+ break;
+
+ case '~':
+ params.setPreviewFormat(cmd + 1);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '$':
+ params.setPictureFormat(cmd + 1);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+ case '-':
+ for(i = 0; i < length_audio_Codecs; i++)
+ {
+ if( strcmp((cmd + 1), audioCodecs[i].desc) == 0)
+ {
+ audioCodecIDX = i;
+ printf("Selected Audio: %s\n", audioCodecs[i].desc);
+ break;
+ }
+ }
+ break;
+
+ case 'A':
+ camera_index=atoi(cmd+1);
+ // camera_index %= ARRAY_SIZE(cameras);
+ camera_index %= length_cam;
+ if ( camera_index == 2)
+ params.set(KEY_STEREO_CAMERA, "true");
+ else
+ params.set(KEY_STEREO_CAMERA, "false");
+
+ printf("%s selected.\n", cameras[camera_index]);
+
+ if ( hardwareActive ) {
+ stopPreview();
+ closeCamera();
+ openCamera();
+ } else {
+ closeCamera();
+ openCamera();
+ }
+
+ if (camera_index == 0) params.setPreviewFrameRate(30);
+ else params.setPreviewFrameRate(27);
+
+
+ break;
+
+ case 'a':
+ char * temp_str;
+
+ temp_str = strtok(cmd+1,"!");
+ printf("Latitude %s \n",temp_str);
+ params.set(params.KEY_GPS_LATITUDE, temp_str);
+ temp_str=strtok(NULL,"!");
+ printf("Longitude %s \n",temp_str);
+ params.set(params.KEY_GPS_LONGITUDE, temp_str);
+ temp_str=strtok(NULL,"!");
+ printf("Altitude %s \n",temp_str);
+ params.set(params.KEY_GPS_ALTITUDE, temp_str);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'l':
+ case 'L':
+ for(i = 0; i < lenght_Vcapture_size; i++)
+ {
+ if( strcmp((cmd + 1), VcaptureSize[i].desc) == 0)
+ {
+ VcaptureSizeIDX = i;
+ printf("Video Capture Size: %s\n", VcaptureSize[i].desc);
+ break;
+ }
+ }
+ break;
+ case ']':
+ for(i = 0; i < length_V_bitRate; i++)
+ {
+ if( strcmp((cmd + 1), VbitRate[i].desc) == 0)
+ {
+ VbitRateIDX = i;
+ printf("Video Bit Rate: %s\n", VbitRate[i].desc);
+ break;
+ }
+ }
+ break;
+ case ':':
+ int width, height;
+ for(i = 0; i < length_previewSize ; i++)
+ {
+ if( strcmp((cmd + 1), previewSize[i].desc) == 0)
+ {
+ width = previewSize[i].width;
+ height = previewSize[i].height;
+ thumbSizeIDX = i;
+ break;
+ }
+ }
+
+ if (i == length_previewSize ) //if the resolution is not in the supported ones
+ {
+ char *res = NULL;
+ res = strtok(cmd + 1, "x");
+ width = atoi(res);
+ res = strtok(NULL, "x");
+ height = atoi(res);
+ }
+
+ params.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
+ params.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '\'':
+ thumbQuality = atoi(cmd + 1);
+
+ params.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, thumbQuality);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case '*':
+ if ( hardwareActive )
+ camera->startRecording();
+ break;
+
+ case 't':
+ params.setPreviewFormat((cmd + 1));
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'o':
+ jpegQuality = atoi(cmd + 1);
+ params.set(CameraParameters::KEY_JPEG_QUALITY, jpegQuality);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+
+ case '&':
+ printf("Enabling Preview Callback");
+ dump_preview = 1;
+ camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ break;
+
+
+ case 'k':
+ ippIDX_old = atoi(cmd + 1);
+ params.set(KEY_IPP, atoi(cmd + 1));
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'K':
+ params.set(KEY_GBCE, (cmd+1));
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'u':
+ // HQ should always be in ldc-nsf
+ // if not HQ, then return the ipp to its previous state
+ if( !strcmp(capture[capture_mode], "high-quality") ) {
+ ippIDX_old = ippIDX;
+ ippIDX = 3;
+ params.set(KEY_IPP, ipp_mode[ippIDX]);
+ } else {
+ ippIDX = ippIDX_old;
+ }
+
+ params.set(KEY_MODE, (cmd + 1));
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'U':
+
+ params.set(KEY_TEMP_BRACKETING, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'W':
+
+ tempBracketRange = atoi(cmd + 1);
+ tempBracketRange %= TEMP_BRACKETING_MAX_RANGE;
+ if ( 0 == tempBracketRange ) {
+ tempBracketRange = 1;
+ }
+
+ params.set(KEY_TEMP_BRACKETING_NEG, tempBracketRange);
+ params.set(KEY_TEMP_BRACKETING_POS, tempBracketRange);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '#':
+
+ params.set(KEY_BURST, atoi(cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'J':
+ params.set(CameraParameters::KEY_FLASH_MODE, (cmd+1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'w':
+ params.set(params.KEY_SCENE_MODE, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'B' :
+ params.set(KEY_VNF, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+
+ case 'C' :
+ params.set(KEY_VSTAB, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'D':
+ if ( hardwareActive )
+ camera->stopRecording();
+ break;
+
+ case 'E':
+ if(hardwareActive)
+ params.unflatten(camera->getParameters());
+ printSupportedParams();
+ break;
+
+ case 'i':
+ iso_mode = atoi(cmd + 1);
+ params.set(KEY_ISO, iso_mode);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'h':
+ sharpness = atoi(cmd + 1);
+ params.set(KEY_SHARPNESS, sharpness);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case '@':
+ if ( hardwareActive ) {
+
+ closeCamera();
+
+ if ( 0 >= openCamera() ) {
+ printf( "Reconnected to CameraService \n");
+ }
+ }
+
+ break;
+
+ case 'c':
+ contrast = atoi(cmd + 1);
+ params.set(KEY_CONTRAST, contrast);
+
+ if ( hardwareActive ) {
+ camera->setParameters(params.flatten());
+ }
+
+ break;
+
+ case 'z':
+ case 'Z':
+
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+ params.set(CameraParameters::KEY_ZOOM, atoi(cmd + 1));
+#else
+
+ for(i = 0; i < length_Zoom; i++)
+ {
+ if( strcmp((cmd + 1), zoom[i].zoom_description) == 0)
+ {
+ zoomIDX = i;
+ break;
+ }
+ }
+
+ params.set(CameraParameters::KEY_ZOOM, zoom[zoomIDX].idx);
+#endif
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'j':
+ params.set(KEY_EXPOSURE, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'b':
+ brightness = atoi(cmd + 1);
+ params.set(KEY_BRIGHTNESS, brightness);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 's':
+ saturation = atoi(cmd + 1);
+ params.set(KEY_SATURATION, saturation);
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'e':
+ params.set(params.KEY_EFFECT, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'r':
+
+ frameR = atoi(cmd + 1);
+
+
+ if (camera_index == 0) {
+ for (i = 0; i < length_fpsConst_Ranges; i++) {
+ if (frameR == fpsConstRanges[i].constFramerate)
+ frameRateIndex = i;
+
+ }
+ } else {
+ for (i = 0; i < length_fpsConst_RangesSec; i++) {
+ if (frameR == fpsConstRangesSec[i].constFramerate)
+ frameRateIndex = i;
+ }
+ }
+
+
+ if (camera_index == 0)
+ params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, fpsConstRanges[frameRateIndex].range);
+ else
+ params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, fpsConstRangesSec[frameRateIndex].range);
+
+
+ if ( hardwareActive && previewRunning ) {
+ camera->stopPreview();
+ camera->setParameters(params.flatten());
+ camera->startPreview();
+ } else if ( hardwareActive ) {
+ camera->setParameters(params.flatten());
+ }
+
+ break;
+
+ case 'R':
+ for(i = 0; i < length_fps_ranges; i++)
+ {
+ if( strcmp((cmd + 1), fpsRanges[i].rangeDescription) == 0)
+ {
+ fpsRangeIdx = i;
+ printf("Selected Framerate range: %s\n", fpsRanges[i].rangeDescription);
+ if ( hardwareActive ) {
+ params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, fpsRanges[i].range);
+ params.remove(CameraParameters::KEY_PREVIEW_FRAME_RATE);
+ camera->setParameters(params.flatten());
+ }
+ break;
+ }
+ }
+ break;
+
+ case 'x':
+ params.set(params.KEY_ANTIBANDING, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'g':
+ params.set(params.KEY_FOCUS_MODE, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ break;
+
+ case 'G':
+
+ params.set(CameraParameters::KEY_FOCUS_AREAS, (cmd + 1));
+
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+
+ params.remove(CameraParameters::KEY_FOCUS_AREAS);
+
+ case 'f':
+ gettimeofday(&autofocus_start, 0);
+
+ if ( hardwareActive )
+ camera->autoFocus();
+
+ break;
+
+ case 'p':
+ gettimeofday(&picture_start, 0);
+
+ if ( hardwareActive )
+ ret = camera->takePicture(CAMERA_MSG_COMPRESSED_IMAGE|CAMERA_MSG_RAW_IMAGE);
+
+ if ( ret != NO_ERROR )
+ printf("Error returned while taking a picture");
+ break;
+
+ case 'd':
+ dly = atoi(cmd + 1);
+ sleep(dly);
+ break;
+
+ case 'q':
+ dump_mem_status();
+ stopPreview();
+
+ if ( recordingMode ) {
+ stopRecording();
+ closeRecorder();
+
+ recordingMode = false;
+ }
+ goto exit;
+
+ case '\n':
+ printf("Iteration: %d \n", iteration);
+ iteration++;
+ break;
+
+ case '{':
+ if ( atoi(cmd + 1) > 0 )
+ params.set(KEY_S3D2D_PREVIEW_MODE, "on");
+ else
+ params.set(KEY_S3D2D_PREVIEW_MODE, "off");
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+
+ case 'M':
+ params.set(KEY_MEASUREMENT, (cmd + 1));
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+ case 'm':
+ {
+ params.set(KEY_METERING_MODE, (cmd + 1));
+ if ( hardwareActive )
+ {
+ camera->setParameters(params.flatten());
+ }
+ break;
+ }
+ case '<':
+ {
+ char coord_str[8];
+ latitude += degree_by_step;
+ if (latitude > 90.0)
+ {
+ latitude -= 180.0;
+ }
+ snprintf(coord_str, 7, "%.7lf", latitude);
+ params.set(params.KEY_GPS_LATITUDE, coord_str);
+ if ( hardwareActive )
+ {
+ camera->setParameters(params.flatten());
+ }
+ break;
+ }
+
+ case '=':
+ {
+ char coord_str[8];
+ longitude += degree_by_step;
+ if (longitude > 180.0)
+ {
+ longitude -= 360.0;
+ }
+ snprintf(coord_str, 7, "%.7lf", longitude);
+ params.set(params.KEY_GPS_LONGITUDE, coord_str);
+ if ( hardwareActive )
+ {
+ camera->setParameters(params.flatten());
+ }
+ break;
+ }
+
+ case '>':
+ {
+ char coord_str[8];
+ altitude += 12345.67890123456789;
+ if (altitude > 100000.0)
+ {
+ altitude -= 200000.0;
+ }
+ snprintf(coord_str, 7, "%.7lf", altitude);
+ params.set(params.KEY_GPS_ALTITUDE, coord_str);
+ if ( hardwareActive )
+ {
+ camera->setParameters(params.flatten());
+ }
+ break;
+ }
+
+ case 'X':
+ {
+ char rem_str[50];
+ printf("Deleting images from %s \n", dir_path);
+ if(!sprintf(rem_str,"rm %s/*.jpg",dir_path))
+ printf("Sprintf Error");
+ if(system(rem_str))
+ printf("Images were not deleted\n");
+ break;
+ }
+
+ case '_':
+ {
+ AutoConvergenceModeIDX = atoi(cmd + 1);
+ if ( AutoConvergenceModeIDX < 0 || AutoConvergenceModeIDX > 4 )
+ AutoConvergenceModeIDX = 0;
+ params.set(KEY_AUTOCONVERGENCE, autoconvergencemode[AutoConvergenceModeIDX]);
+ if ( AutoConvergenceModeIDX != 4 )
+ params.set(KEY_MANUALCONVERGENCE_VALUES, manualconvergencevalues[ManualConvergenceDefaultValueIDX]);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ break;
+ }
+
+ case '^':
+ {
+ char strtmpval[7];
+ if ( strcmp (autoconvergencemode[AutoConvergenceModeIDX], AUTOCONVERGENCE_MODE_MANUAL) == 0) {
+ sprintf(strtmpval,"%d", atoi(cmd + 1));
+ params.set(KEY_MANUALCONVERGENCE_VALUES, strtmpval);
+ if ( hardwareActive )
+ camera->setParameters(params.flatten());
+ }
+ break;
+ }
+
+ default:
+ printf("Unrecognized command!\n");
+ break;
+ }
+
+ cmd = strtok_r(NULL, DELIMITER, &ctx);
+ }
+
+exit:
+ if (stopScript == true)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+char * get_cycle_cmd(const char *aSrc) {
+ unsigned ind = 0;
+ char *cycle_cmd = new char[256];
+
+ while ((*aSrc != '+') && (*aSrc != '\0')) {
+ cycle_cmd[ind++] = *aSrc++;
+ }
+ cycle_cmd[ind] = '\0';
+
+ return cycle_cmd;
+}
+
+status_t dump_mem_status() {
+ system(MEDIASERVER_DUMP);
+ return system(MEMORY_DUMP);
+}
+
+char *load_script(char *config) {
+ FILE *infile;
+ size_t fileSize;
+ char *script;
+ size_t nRead = 0;
+ char dir_name[40];
+ size_t count;
+ char rCount [5];
+
+ count = 0;
+
+ infile = fopen(config, "r");
+
+ strcpy(script_name,config);
+
+ // remove just the '.txt' part of the config
+ while((config[count] != '.') && (count < sizeof(dir_name)/sizeof(dir_name[0])))
+ count++;
+
+ printf("\n SCRIPT : <%s> is currently being executed \n",script_name);
+ if(strncpy(dir_name,config,count) == NULL)
+ printf("Strcpy error");
+
+ dir_name[count]=NULL;
+
+ if(strcat(dir_path,dir_name) == NULL)
+ printf("Strcat error");
+
+ if(restartCount)
+ {
+ sprintf(rCount,"_%d",restartCount);
+ if(strcat(dir_path, rCount) == NULL)
+ printf("Strcat error RestartCount");
+ }
+
+ printf("\n COMPLETE FOLDER PATH : %s \n",dir_path);
+ if(mkdir(dir_path,0777) == -1) {
+ printf("\n Directory %s was not created \n",dir_path);
+ } else {
+ printf("\n Directory %s was created \n",dir_path);
+ }
+ printf("\n DIRECTORY CREATED FOR TEST RESULT IMAGES IN MMC CARD : %s \n",dir_name);
+
+ if( (NULL == infile)){
+ printf("Error while opening script file %s!\n", config);
+ return NULL;
+ }
+
+ fseek(infile, 0, SEEK_END);
+ fileSize = ftell(infile);
+ fseek(infile, 0, SEEK_SET);
+
+ script = (char *) malloc(fileSize);
+
+ if ( NULL == script ) {
+ printf("Unable to allocate buffer for the script\n");
+
+ return NULL;
+ }
+
+ if ((nRead = fread(script, 1, fileSize, infile)) != fileSize) {
+ printf("Error while reading script file!\n");
+
+ free(script);
+ fclose(infile);
+ return NULL;
+ }
+
+ fclose(infile);
+
+ return script;
+}
+
+int start_logging(char *config, int &pid) {
+ char dir_name[40];
+ size_t count = 0;
+ int status = 0;
+
+ // remove just the '.txt' part of the config
+ while((config[count] != '.') && (count < sizeof(dir_name)/sizeof(dir_name[0])))
+ count++;
+
+ if(strncpy(dir_name,config,count) == NULL)
+ printf("Strcpy error");
+
+ dir_name[count]=NULL;
+
+ pid = fork();
+ if (pid == 0)
+ {
+ char *command_list[] = {"sh", "-c", NULL, NULL};
+ char log_cmd[120];
+ // child process to run logging
+
+ // set group id of this process to itself
+ // we will use this group id to kill the
+ // application logging
+ setpgid(getpid(), getpid());
+
+ /* Start logcat */
+ if(!sprintf(log_cmd,"logcat > /sdcard/%s/log.txt &",dir_name))
+ printf(" Sprintf Error");
+
+ /* Start Syslink Trace */
+ if(bLogSysLinkTrace) {
+ if(!sprintf(log_cmd,"%s /system/bin/syslink_trace_daemon.out -l /sdcard/%s/syslink_trace.txt -f &",log_cmd, dir_name))
+ printf(" Sprintf Error");
+ }
+
+ command_list[2] = (char *)log_cmd;
+ execvp("/system/bin/sh", command_list);
+ } if(pid < 0)
+ {
+ printf("failed to fork logcat\n");
+ return -1;
+ }
+
+ //wait for logging to start
+ if(waitpid(pid, &status, 0) != pid)
+ {
+ printf("waitpid failed in log fork\n");
+ return -1;
+ }else
+ printf("logging started... status=%d\n", status);
+
+ return 0;
+}
+
+int stop_logging(int &pid)
+{
+ if(pid > 0)
+ {
+ if(killpg(pid, SIGKILL))
+ {
+ printf("Exit command failed");
+ return -1;
+ } else {
+ printf("\nlogging for script %s is complete\n logcat saved @ location: %s\n",script_name,dir_path);
+ if (bLogSysLinkTrace)
+ printf(" syslink_trace is saved @ location: %s\n\n",dir_path);
+ }
+ }
+ return 0;
+}
+
+int execute_error_script(char *script) {
+ char *cmd, *ctx;
+ char id;
+ status_t stat = NO_ERROR;
+
+ LOG_FUNCTION_NAME;
+
+ cmd = strtok_r((char *) script, DELIMITER, &ctx);
+
+ while ( NULL != cmd ) {
+ id = cmd[0];
+
+ switch (id) {
+
+ case '0': {
+ bufferStarvationTest = 1;
+ params.set(KEY_BUFF_STARV, bufferStarvationTest); //enable buffer starvation
+
+ if ( !recordingMode ) {
+
+ recordingMode = true;
+
+ if ( startPreview() < 0 ) {
+ printf("Error while starting preview\n");
+
+ return -1;
+ }
+
+ if ( openRecorder() < 0 ) {
+ printf("Error while openning video recorder\n");
+
+ return -1;
+ }
+
+ if ( configureRecorder() < 0 ) {
+ printf("Error while configuring video recorder\n");
+
+ return -1;
+ }
+
+ if ( startRecording() < 0 ) {
+ printf("Error while starting video recording\n");
+
+ return -1;
+ }
+
+ }
+
+ usleep(1000000);//1s
+
+ stopPreview();
+
+ if ( recordingMode ) {
+ stopRecording();
+ closeRecorder();
+
+ recordingMode = false;
+ }
+
+ break;
+ }
+
+ case '1': {
+ int* tMemoryEater = new int[999999999];
+
+ if (!tMemoryEater) {
+ printf("Not enough memory\n");
+ return -1;
+ } else {
+ delete tMemoryEater;
+ }
+
+ break;
+ }
+
+ case '2': {
+ //camera = Camera::connect();
+
+ if ( NULL == camera.get() ) {
+ printf("Unable to connect to CameraService\n");
+ return -1;
+ }
+
+ break;
+ }
+
+ case '3': {
+ int err = 0;
+
+ err = open("/dev/video5", O_RDWR);
+
+ if (err < 0) {
+ printf("Could not open the camera device5: %d\n", err );
+ return err;
+ }
+
+ if ( startPreview() < 0 ) {
+ printf("Error while starting preview\n");
+ return -1;
+ }
+
+ usleep(1000000);//1s
+
+ stopPreview();
+
+ close(err);
+ break;
+ }
+
+ case '4': {
+
+ if ( hardwareActive ) {
+
+ params.setPictureFormat("invalid-format");
+ params.setPreviewFormat("invalid-format");
+
+ stat = camera->setParameters(params.flatten());
+
+ if ( NO_ERROR != stat ) {
+ printf("Test passed!\n");
+ } else {
+ printf("Test failed!\n");
+ }
+
+ initDefaults();
+ }
+
+ break;
+ }
+
+ case '5': {
+
+ if ( hardwareActive ) {
+
+ params.setPictureSize(-1, -1);
+ params.setPreviewSize(-1, -1);
+
+ stat = camera->setParameters(params.flatten());
+
+ if ( NO_ERROR != stat ) {
+ printf("Test passed!\n");
+ } else {
+ printf("Test failed!\n");
+ }
+
+ initDefaults();
+ }
+
+ break;
+ }
+
+ case '6': {
+
+ if ( hardwareActive ) {
+
+ params.setPreviewFrameRate(-1);
+
+ stat = camera->setParameters(params.flatten());
+
+ if ( NO_ERROR != stat ) {
+ printf("Test passed!\n");
+ } else {
+ printf("Test failed!\n");
+ }
+
+ initDefaults();
+ }
+
+
+ break;
+ }
+
+ case 'q': {
+ goto exit;
+
+ break;
+ }
+
+ default: {
+ printf("Unrecognized command!\n");
+
+ break;
+ }
+ }
+
+ cmd = strtok_r(NULL, DELIMITER, &ctx);
+ }
+
+exit:
+
+ return 0;
+}
+
+
+
diff --git a/tiler/.gitignore b/tiler/.gitignore
new file mode 100644
index 0000000..c23ec1a
--- /dev/null
+++ b/tiler/.gitignore
@@ -0,0 +1,27 @@
+aclocal.m4
+autom4te.cache
+Makefile.in
+Makefile
+ltmain.sh
+stamp-h1
+.deps
+.libs
+*.o
+*.lo
+*.la
+libtool
+*.pc
+config.log
+config.status
+config.guess
+config.h
+config.h.in
+config.sub
+config
+configure
+m4
+build
+*~
+tests/testlib.c
+*_test
+*_ptest \ No newline at end of file
diff --git a/tiler/Android.mk b/tiler/Android.mk
new file mode 100644
index 0000000..60c8699
--- /dev/null
+++ b/tiler/Android.mk
@@ -0,0 +1,33 @@
+# only include if running on an omap4 platform
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := memmgr.c tilermgr.c
+LOCAL_MODULE := libtimemmgr
+LOCAL_MODULE_TAGS := optional tests
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := memmgr_test.c testlib.c
+LOCAL_SHARED_LIBRARIES := libtimemmgr
+LOCAL_MODULE := memmgr_test
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_HEAPTRACKED_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := utils_test.c testlib.c
+LOCAL_SHARED_LIBRARIES := libtimemmgr
+LOCAL_MODULE := utils_test
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_HEAPTRCKED_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := tiler_ptest.c
+LOCAL_SHARED_LIBRARIES := libtimemmgr
+LOCAL_MODULE := tiler_ptest
+LOCAL_MODULE_TAGS:= tests
+include $(BUILD_HEAPTRACKED_EXECUTABLE)
+
+endif
diff --git a/tiler/Makefile.am b/tiler/Makefile.am
new file mode 100644
index 0000000..9f9e70b
--- /dev/null
+++ b/tiler/Makefile.am
@@ -0,0 +1,80 @@
+#
+# Makefile.am
+#
+# TI OMAP Processor Memory Allocator Interface functions makefile.
+#
+# Copyright (C) 2009-2011 Texas Instruments, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Texas Instruments Incorporated nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+AUTOMAKE_OPTIONS = foreign
+
+## sources
+
+h_sources = memmgr.h tilermem.h mem_types.h tiler.h tilermem_utils.h
+if STUB_TILER
+c_sources = memmgr.c
+else
+c_sources = memmgr.c tilermgr.c
+endif
+
+if TILERMGR
+library_include_HEADERS = $(h_sources) tilermgr.h
+else
+library_include_HEADERS = $(h_sources)
+noinst_HEADERS = tilermgr.h
+endif
+
+#Install the headers in library directory - e.g. examplelib-1.0:
+library_includedir=$(includedir)/timemmgr
+
+# library sources
+lib_LTLIBRARIES= libtimemmgr.la
+libtimemmgr_la_SOURCES = $(h_sources) $(c_sources)
+libtimemmgr_la_CFLAGS = $(MEMMGR_CFLAGS) -fpic -ansi
+libtimemmgr_la_LIBTOOLFLAGS = --tag=disable-static
+libtimemmgr_la_LDFLAGS = -version-info 2:0:0
+
+if UNIT_TESTS
+bin_PROGRAMS = utils_test memmgr_test tiler_ptest
+
+utils_testdir = .
+utils_test_SOURCES = utils_test.c testlib.c
+
+memmgr_testdir = .
+memmgr_test_SOURCES = memmgr_test.c testlib.c
+memmgr_test_LDADD = libtimemmgr.la
+
+tiler_ptest_SOURCES = tiler_ptest.c
+tiler_ptest_LDADD = libtimemmgr.la
+endif
+
+pkgconfig_DATA = libtimemmgr.pc
+pkgconfigdir = $(libdir)/pkgconfig
+
diff --git a/tiler/README b/tiler/README
new file mode 100644
index 0000000..e531b09
--- /dev/null
+++ b/tiler/README
@@ -0,0 +1,136 @@
+Validating MemMgr
+
+ MemMgr tests are not persistently enumerated, so the test # in
+ memmgr test may vary from release to release.
+
+ You need to run the test with the "list" argument to list all the test
+ descriptions and the corresponding test numbers.
+
+ E.g. "memmgr_test list"
+
+ If you have access to the official test report, the details column lists
+ the test description (in the last line). Match the test case description
+ to the last line of the cells in the Details column.
+
+ Negative MemMgr tests run multiple test cases, so they map to multiple rows
+ in the official test report. Some of the test cases may not be available,
+ or may succeed even if the whole test failed/succeeded.
+
+ To ease the generation of the test report, a python script is provided that
+ will populate most of the test report:
+
+ run memmgr_test and pipe the output of the tests into a
+ file, e.g.:
+
+ memmgr_test > test.log
+
+ open UTR and select Tiler User Space worksheet
+ run this script by piping the test logs into the script, e.g. (you may
+ have to copy the log file from the target to a location that you can
+ access from the machine that has the UTR open.)
+
+ python fill_utr.py < test.log
+
+Latest List of test cases
+
+memmgr_test
+
+TEST # 1 - alloc_1D_test(4096, 0)
+TEST # 2 - alloc_2D_test(64, 64, PIXEL_FMT_8BIT)
+TEST # 3 - alloc_2D_test(64, 64, PIXEL_FMT_16BIT)
+TEST # 4 - alloc_2D_test(64, 64, PIXEL_FMT_32BIT)
+TEST # 5 - alloc_NV12_test(64, 64)
+TEST # 6 - map_1D_test(4096, 0)
+TEST # 7 - alloc_1D_test(176 * 144 * 2, 512)
+TEST # 8 - alloc_2D_test(176, 144, PIXEL_FMT_8BIT)
+TEST # 9 - alloc_2D_test(176, 144, PIXEL_FMT_16BIT)
+TEST # 10 - alloc_2D_test(176, 144, PIXEL_FMT_32BIT)
+TEST # 11 - alloc_NV12_test(176, 144)
+TEST # 12 - map_1D_test(176 * 144 * 2, 2048)
+TEST # 13 - alloc_1D_test(640 * 480 * 2, 0)
+TEST # 14 - alloc_2D_test(640, 480, PIXEL_FMT_8BIT)
+TEST # 15 - alloc_2D_test(640, 480, PIXEL_FMT_16BIT)
+TEST # 16 - alloc_2D_test(640, 480, PIXEL_FMT_32BIT)
+TEST # 17 - alloc_NV12_test(640, 480)
+TEST # 18 - map_1D_test(640 * 480 * 2, 0)
+TEST # 19 - alloc_1D_test(848 * 480 * 2, 0)
+TEST # 20 - alloc_2D_test(848, 480, PIXEL_FMT_8BIT)
+TEST # 21 - alloc_2D_test(848, 480, PIXEL_FMT_16BIT)
+TEST # 22 - alloc_2D_test(848, 480, PIXEL_FMT_32BIT)
+TEST # 23 - alloc_NV12_test(848, 480)
+TEST # 24 - map_1D_test(848 * 480 * 2, 0)
+TEST # 25 - alloc_1D_test(1280 * 720 * 2, 0)
+TEST # 26 - alloc_2D_test(1280, 720, PIXEL_FMT_8BIT)
+TEST # 27 - alloc_2D_test(1280, 720, PIXEL_FMT_16BIT)
+TEST # 28 - alloc_2D_test(1280, 720, PIXEL_FMT_32BIT)
+TEST # 29 - alloc_NV12_test(1280, 720)
+TEST # 30 - map_1D_test(1280 * 720 * 2, 0)
+TEST # 31 - alloc_1D_test(1920 * 1080 * 2, 0)
+TEST # 32 - alloc_2D_test(1920, 1080, PIXEL_FMT_8BIT)
+TEST # 33 - alloc_2D_test(1920, 1080, PIXEL_FMT_16BIT)
+TEST # 34 - alloc_2D_test(1920, 1080, PIXEL_FMT_32BIT)
+TEST # 35 - alloc_NV12_test(1920, 1080)
+TEST # 36 - map_1D_test(1920 * 1080 * 2, 0)
+TEST # 37 - neg_alloc_tests()
+TEST # 38 - neg_free_tests()
+TEST # 39 - neg_map_tests()
+TEST # 40 - neg_unmap_tests()
+TEST # 41 - neg_check_tests()
+TEST # 42 - page_size_test()
+TEST # 43 - maxalloc_2D_test(2500, 32, PIXEL_FMT_8BIT, MAX_ALLOCS)
+TEST # 44 - maxalloc_2D_test(2500, 16, PIXEL_FMT_16BIT, MAX_ALLOCS)
+TEST # 45 - maxalloc_2D_test(1250, 16, PIXEL_FMT_32BIT, MAX_ALLOCS)
+TEST # 46 - maxalloc_2D_test(5000, 32, PIXEL_FMT_8BIT, MAX_ALLOCS)
+TEST # 47 - maxalloc_2D_test(5000, 16, PIXEL_FMT_16BIT, MAX_ALLOCS)
+TEST # 48 - maxalloc_2D_test(2500, 16, PIXEL_FMT_32BIT, MAX_ALLOCS)
+TEST # 49 - alloc_2D_test(8193, 16, PIXEL_FMT_8BIT)
+TEST # 50 - alloc_2D_test(8193, 16, PIXEL_FMT_16BIT)
+TEST # 51 - alloc_2D_test(4097, 16, PIXEL_FMT_32BIT)
+TEST # 52 - alloc_2D_test(16384, 16, PIXEL_FMT_8BIT)
+TEST # 53 - alloc_2D_test(16384, 16, PIXEL_FMT_16BIT)
+TEST # 54 - alloc_2D_test(8192, 16, PIXEL_FMT_32BIT)
+TEST # 55 - !alloc_2D_test(16385, 16, PIXEL_FMT_8BIT)
+TEST # 56 - !alloc_2D_test(16385, 16, PIXEL_FMT_16BIT)
+TEST # 57 - !alloc_2D_test(8193, 16, PIXEL_FMT_32BIT)
+TEST # 58 - maxalloc_1D_test(4096, MAX_ALLOCS)
+TEST # 59 - maxalloc_2D_test(64, 64, PIXEL_FMT_8BIT, MAX_ALLOCS)
+TEST # 60 - maxalloc_2D_test(64, 64, PIXEL_FMT_16BIT, MAX_ALLOCS)
+TEST # 61 - maxalloc_2D_test(64, 64, PIXEL_FMT_32BIT, MAX_ALLOCS)
+TEST # 62 - maxalloc_NV12_test(64, 64, MAX_ALLOCS)
+TEST # 63 - maxmap_1D_test(4096, MAX_ALLOCS)
+TEST # 64 - maxalloc_1D_test(176 * 144 * 2, MAX_ALLOCS)
+TEST # 65 - maxalloc_2D_test(176, 144, PIXEL_FMT_8BIT, MAX_ALLOCS)
+TEST # 66 - maxalloc_2D_test(176, 144, PIXEL_FMT_16BIT, MAX_ALLOCS)
+TEST # 67 - maxalloc_2D_test(176, 144, PIXEL_FMT_32BIT, MAX_ALLOCS)
+TEST # 68 - maxalloc_NV12_test(176, 144, MAX_ALLOCS)
+TEST # 69 - maxmap_1D_test(176 * 144 * 2, MAX_ALLOCS)
+TEST # 70 - maxalloc_1D_test(640 * 480 * 2, MAX_ALLOCS)
+TEST # 71 - maxalloc_2D_test(640, 480, PIXEL_FMT_8BIT, MAX_ALLOCS)
+TEST # 72 - maxalloc_2D_test(640, 480, PIXEL_FMT_16BIT, MAX_ALLOCS)
+TEST # 73 - maxalloc_2D_test(640, 480, PIXEL_FMT_32BIT, MAX_ALLOCS)
+TEST # 74 - maxalloc_NV12_test(640, 480, MAX_ALLOCS)
+TEST # 75 - maxmap_1D_test(640 * 480 * 2, MAX_ALLOCS)
+TEST # 76 - maxalloc_1D_test(848 * 480 * 2, MAX_ALLOCS)
+TEST # 77 - maxalloc_2D_test(848, 480, PIXEL_FMT_8BIT, MAX_ALLOCS)
+TEST # 78 - maxalloc_2D_test(848, 480, PIXEL_FMT_16BIT, MAX_ALLOCS)
+TEST # 79 - maxalloc_2D_test(848, 480, PIXEL_FMT_32BIT, MAX_ALLOCS)
+TEST # 80 - maxalloc_NV12_test(848, 480, MAX_ALLOCS)
+TEST # 81 - maxmap_1D_test(848 * 480 * 2, MAX_ALLOCS)
+TEST # 82 - maxalloc_1D_test(1280 * 720 * 2, MAX_ALLOCS)
+TEST # 83 - maxalloc_2D_test(1280, 720, PIXEL_FMT_8BIT, MAX_ALLOCS)
+TEST # 84 - maxalloc_2D_test(1280, 720, PIXEL_FMT_16BIT, MAX_ALLOCS)
+TEST # 85 - maxalloc_2D_test(1280, 720, PIXEL_FMT_32BIT, MAX_ALLOCS)
+TEST # 86 - maxalloc_NV12_test(1280, 720, MAX_ALLOCS)
+TEST # 87 - maxmap_1D_test(1280 * 720 * 2, MAX_ALLOCS)
+TEST # 88 - maxalloc_1D_test(1920 * 1080 * 2, MAX_ALLOCS)
+TEST # 89 - maxalloc_2D_test(1920, 1080, PIXEL_FMT_8BIT, MAX_ALLOCS)
+TEST # 90 - maxalloc_2D_test(1920, 1080, PIXEL_FMT_16BIT, MAX_ALLOCS)
+TEST # 91 - maxalloc_2D_test(1920, 1080, PIXEL_FMT_32BIT, MAX_ALLOCS)
+TEST # 92 - maxalloc_NV12_test(1920, 1080, 2)
+TEST # 93 - maxalloc_NV12_test(1920, 1080, MAX_ALLOCS)
+TEST # 94 - maxmap_1D_test(1920 * 1080 * 2, MAX_ALLOCS)
+TEST # 95 - star_tiler_test(1000, 10)
+TEST # 96 - star_tiler_test(1000, 30)
+TEST # 97 - star_test(100, 10)
+TEST # 98 - star_test(1000, 10)
+
diff --git a/tiler/bootstrap.sh b/tiler/bootstrap.sh
new file mode 100755
index 0000000..6170918
--- /dev/null
+++ b/tiler/bootstrap.sh
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+cd `dirname $0`
+
+# on some platforms, you have "g" versions of some of these tools instead,
+# ie glibtoolize instead of libtoolize..
+find_tool() {
+ which $1 2> /dev/null || which g$1 2> /dev/null
+}
+
+aclocal=`find_tool aclocal`
+libtoolize=`find_tool libtoolize`
+automake=`find_tool automake`
+autoconf=`find_tool autoconf`
+autoheader=`find_tool autoheader`
+
+mkdir -p config && $autoheader && $aclocal && $libtoolize --copy --force && $automake --copy --add-missing --foreign && $autoconf
+
diff --git a/tiler/configure.ac b/tiler/configure.ac
new file mode 100755
index 0000000..30d131c
--- /dev/null
+++ b/tiler/configure.ac
@@ -0,0 +1,75 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT(timemmgr, 2.00, http://www.ti.com)
+AC_CONFIG_SRCDIR([memmgr.c])
+AC_CONFIG_HEADER([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([config])
+AC_CANONICAL_SYSTEM
+AM_INIT_AUTOMAKE([timemmgr], [2.00])
+LT_INIT
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_LIBTOOL
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h sys/ioctl.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+
+# Checks for library functions.
+AC_PROG_GCC_TRADITIONAL
+#AC_FUNC_MALLOC
+#AC_FUNC_MMAP
+AC_CHECK_FUNCS([munmap strerror])
+
+AC_ARG_ENABLE(tilermgr,
+[ --enable-tilermgr Include TilerMgr headers],
+[case "${enableval}" in
+ yes) tilermgr=true ;;
+ no) tilermgr=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-tilermgr) ;;
+esac],[tilermgr=true])
+
+AC_ARG_ENABLE(tests,
+[ --enable-tests Build unit tests],
+[case "${enableval}" in
+ yes) tests=true ;;
+ no) tests=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-tests) ;;
+esac],[tests=false])
+
+AM_CONDITIONAL(UNIT_TESTS, test x$tests = xtrue)
+
+AM_CONDITIONAL(TILERMGR, test x$tilermgr != xfalse)
+
+AC_ARG_ENABLE(stub,
+[ --enable-stub Stubbing tiler and syslink on none-arm system],
+[case "${enableval}" in
+ yes) stub_tiler=true ;;
+ no) stub_tiler=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-stub) ;;
+esac],[stub_tiler=false])
+
+AM_CONDITIONAL(STUB_TILER, test x$stub_tiler = xtrue)
+
+if test x$stub_tiler = xtrue; then
+AC_DEFINE([STUB_TILER],[1],[Use tiler stub])
+fi
+
+# Project build flags
+MEMMGR_CFLAGS="-Werror -Wall -pipe -ansi"
+AC_SUBST(MEMMGR_CFLAGS)
+
+AC_CONFIG_FILES([libtimemmgr.pc Makefile])
+AC_OUTPUT
+
diff --git a/tiler/debug_utils.h b/tiler/debug_utils.h
new file mode 100644
index 0000000..316e80e
--- /dev/null
+++ b/tiler/debug_utils.h
@@ -0,0 +1,211 @@
+/*
+ * debug_utils.h
+ *
+ * Debug Utility definitions.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEBUG_UTILS_H_
+#define _DEBUG_UTILS_H_
+
+#include <stdio.h>
+
+/*#define __DEBUG__*/
+/*#define __DEBUG_ENTRY__*/
+/*#define __DEBUG_ASSERT__*/
+
+/* ---------- Generic Debug Print Macros ---------- */
+
+/**
+ * Use as:
+ * P("val is %d", 5);
+ * ==> val is 5
+ * DP("val is %d", 15);
+ * ==> val is 5 at test.c:56:main()
+ */
+/* debug print (fmt must be a literal); adds new-line. */
+#define __DEBUG_PRINT(fmt, ...) do { fprintf(stdout, fmt "\n", ##__VA_ARGS__); fflush(stdout); } while(0)
+
+/* debug print with context information (fmt must be a literal) */
+#define __DEBUG_DPRINT(fmt, ...) __DEBUG_PRINT(fmt " at %s(" __FILE__ ":%d)", ##__VA_ARGS__, __FUNCTION__, __LINE__)
+
+#ifdef __DEBUG__
+#define P(fmt, ...) __DEBUG_PRINT(fmt, ##__VA_ARGS__)
+#define DP(fmt, ...) __DEBUG_DPRINT(fmt, ##__VA_ARGS__)
+#else
+#define P(fmt, ...)
+#define DP(fmt, ...)
+#endif
+
+/* ---------- Program Flow Debug Macros ---------- */
+
+/**
+ * Use as:
+ * int get5() {
+ * IN;
+ * return R_I(5);
+ * }
+ * void check(int i) {
+ * IN;
+ * if (i == 5) { RET; return; }
+ * OUT;
+ * }
+ * void main() {
+ * IN;
+ * check(get5());
+ * check(2);
+ * OUT;
+ * }
+ * ==>
+ * in main(test.c:11)
+ * in get5(test.c:2)
+ * out(5) at get5(test.c:3)
+ * in check(test.c:6)
+ * out() at check(test.c:7)
+ * in check(test.c:6)
+ * out check(test.c:8)
+ * out main(test.c:14)
+ */
+
+#ifdef __DEBUG_ENTRY__
+/* function entry */
+#define IN __DEBUG_PRINT("in %s(" __FILE__ ":%d)", __FUNCTION__, __LINE__)
+/* function exit */
+#define OUT __DEBUG_PRINT("out %s(" __FILE__ ":%d)", __FUNCTION__, __LINE__)
+/* function abort (return;) Use as { RET; return; } */
+#define RET __DEBUG_DPRINT("out() ")
+/* generic function return */
+#define R(val,type,fmt) ({ type __val__ = (type) val; __DEBUG_DPRINT("out(" fmt ")", __val__); __val__; })
+#else
+#define IN
+#define OUT
+#define RET
+#define R(val,type,fmt) (val)
+#endif
+
+/* integer return */
+#define R_I(val) R(val,int,"%d")
+/* pointer return */
+#define R_P(val) R(val,void *,"%p")
+/* long return */
+#define R_UP(val) R(val,long,"0x%lx")
+
+/* ---------- Assertion Debug Macros ---------- */
+
+/**
+ * Use as:
+ * int i = 5;
+ * // int j = i * 5;
+ * int j = A_I(i,==,3) * 5;
+ * // if (i > 3) P("bad")
+ * if (NOT_I(i,<=,3)) P("bad")
+ * P("j is %d", j);
+ * ==> assert: i (=5) !== 3 at test.c:56:main()
+ * assert: i (=5) !<= 3 at test.c:58:main()
+ * j is 25
+ *
+ */
+/* generic assertion check, A returns the value of exp, CHK return void */
+#ifdef __DEBUG_ASSERT__
+#define A(exp,cmp,val,type,fmt) ({ \
+ type __exp__ = (type) (exp); type __val__ = (type) (val); \
+ if (!(__exp__ cmp __val__)) __DEBUG_DPRINT("assert: %s (=" fmt ") !" #cmp " " fmt, #exp, __exp__, __val__); \
+ __exp__; \
+})
+#define CHK(exp,cmp,val,type,fmt) do { \
+ type __exp__ = (type) (exp); type __val__ = (type) (val); \
+ if (!(__exp__ cmp __val__)) __DEBUG_DPRINT("assert: %s (=" fmt ") !" #cmp " " fmt, #exp, __exp__, __val__); \
+} while(0)
+#else
+#define A(exp,cmp,val,type,fmt) (exp)
+#define CHK(exp,cmp,val,type,fmt)
+#endif
+
+/* typed assertions */
+#define A_I(exp,cmp,val) A(exp,cmp,val,int,"%d")
+#define A_L(exp,cmp,val) A(exp,cmp,val,long,"%ld")
+#define A_P(exp,cmp,val) A(exp,cmp,val,void *,"%p")
+#define CHK_I(exp,cmp,val) CHK(exp,cmp,val,int,"%d")
+#define CHK_L(exp,cmp,val) CHK(exp,cmp,val,long,"%ld")
+#define CHK_P(exp,cmp,val) CHK(exp,cmp,val,void *,"%p")
+
+/* generic assertion check, returns true iff assertion fails */
+#ifdef __DEBUG_ASSERT__
+#define NOT(exp,cmp,val,type,fmt) ({ \
+ type __exp__ = (type) (exp); type __val__ = (type) (val); \
+ if (!(__exp__ cmp __val__)) __DEBUG_DPRINT("assert: %s (=" fmt ") !" #cmp " " fmt, #exp, __exp__, __val__); \
+ !(__exp__ cmp __val__); \
+})
+#else
+#define NOT(exp,cmp,val,type,fmt) (!((exp) cmp (val)))
+#endif
+
+/* typed assertion checks */
+#define NOT_I(exp,cmp,val) NOT(exp,cmp,val,int,"%d")
+#define NOT_L(exp,cmp,val) NOT(exp,cmp,val,long,"%ld")
+#define NOT_P(exp,cmp,val) NOT(exp,cmp,val,void *,"%p")
+
+
+/* system assertions - will use perror to give external error information */
+#ifdef __DEBUG_ASSERT__
+#define ERR_S(fmt, ...) do { fprintf(stderr, fmt " at %s(" __FILE__ ":%d", ##__VA_ARGS__, __FUNCTION__, __LINE__); perror(")"); fflush(stderr); } while(0)
+#define A_S(exp,cmp,val) ({ \
+ int __exp__ = (int) (exp); int __val__ = (int) (val); \
+ if (!(__exp__ cmp __val__)) ERR_S("assert: %s (=%d) !" #cmp " %d", #exp, __exp__, __val__); \
+ __exp__; \
+})
+#define CHK_S(exp,cmp,val) do { \
+ int __exp__ = (int) (exp); int __val__ = (int) (val); \
+ if (!(__exp__ cmp __val__)) ERR_S("assert: %s (=%d) !" #cmp " %d", #exp, __exp__, __val__); \
+} while(0)
+#define NOT_S(exp,cmp,val) ({ \
+ int __exp__ = (int) (exp); int __val__ = (int) (val); \
+ if (!(__exp__ cmp __val__)) ERR_S("assert: %s (=%d) !" #cmp " %d", #exp, __exp__, __val__); \
+ !(__exp__ cmp __val__); \
+})
+#else
+#define A_S(exp,cmp,val) (exp)
+#define CHK_S(exp,cmp,val)
+#define NOT_S(exp,cmp,val) (!((exp) cmp (val)))
+#endif
+
+/* error propagation macros - these macros ensure evaluation of the expression
+ even if there was a prior error */
+
+/* new error is accumulated into error */
+#define ERR_ADD(err, exp) do { int __error__ = A_I(exp,==,0); err = err ? err : __error__; } while(0)
+#define ERR_ADD_S(err, exp) do { int __error__ = A_S(exp,==,0); err = err ? err : __error__; } while(0)
+/* new error overwrites old error */
+#define ERR_OVW(err, exp) do { int __error__ = A_I(exp,==,0); err = __error__ ? __error__ : err; } while(0)
+#define ERR_OVW_S(err, exp) do { int __error__ = A_S(exp,==,0); err = __error__ ? __error__ : err; } while(0)
+
+#endif
+
diff --git a/tiler/fill_utr.py b/tiler/fill_utr.py
new file mode 100755
index 0000000..d006298
--- /dev/null
+++ b/tiler/fill_utr.py
@@ -0,0 +1,92 @@
+# Use this script to fill out the UTR for MemMgr/D2C tests. You can use
+# either Python 2.6 or 3.1
+#
+# Limitations:
+# - only basic tests run by memmgr_test and d2c_test are filled out
+# - negative memmgr_tests are performed in one step and this script will
+# not separate which part of the test failed. If your negative memmgr
+# tests fail, you want to manually check which test case failed.
+
+# Usage:
+# 1. run memmgr_test and d2c_test, and pipe the output of the tests into a
+# file.
+#
+# memmgr_test > test.log
+# d2c_test >> test.log
+#
+# 2. open UTR and select Tiler/D2C User Space worksheet
+# 3. run this script by piping the test logs into the script, e.g.
+# python fill_utr.py < test.log
+
+import sys, re, win32com.client
+
+TCs, results = [], {}
+
+# gather test results from the log
+for line in sys.stdin:
+ # check for test description
+ desc = re.search("TEST #... - (.*)", line.strip())
+ if desc:
+ TCs.append(desc.group(1))
+
+ # check for any test result
+ result = re.search("==> TEST (.*)", line.strip())
+ if result:
+ result = result.group(1)
+ if result == 'OK':
+ result = 'P', ''
+ elif result == 'NOT AVAILABLE':
+ result = 'D', ''
+ else:
+ result = 'F', 'failed with error #' + result[5:-1]
+
+ results[TCs.pop(0)] = result
+
+assert "test_d2c(1920, 1080, 2)" in results
+
+# populate test results
+excel = win32com.client.Dispatch('Excel.Application')
+if not excel:
+ print('Could not find Excel application. The UTR is probably not open in Excel.')
+ sys.exit(1)
+
+sheet = excel.ActiveSheet
+if sheet.Name != 'Tiler' or sheet.Cells(1,1).Text != 'Test Metrics':
+ print('Active worksheet does not seem to be the Tiler UTR')
+ sys.exit(1)
+
+# find Header
+for r in range(1, 100):
+ if sheet.Cells(r, 1).Text == 'Test Case\nID':
+ break
+else:
+ print('Could not find header row starting with "Test Case\\nID"')
+ sys.exit(1)
+
+# find Status, Details and Comments columns
+heads = t_status, t_details, t_comments, t_desc = 'Status', 'Details', 'Comments', 'Test Case\nDescription'
+heads = set(heads)
+cols = {}
+for c in range(1, 100):
+ if sheet.Cells(r, c).Text in heads:
+ cols[sheet.Cells(r, c).Text] = c
+ heads.remove(sheet.Cells(r, c).Text)
+if heads:
+ print('Could not find columns', heads)
+ sys.exit(1)
+
+# populate sheet, quit after 20 empty Details/Description cells
+empties = 0
+while empties < 20:
+ r += 1
+ details = sheet.Cells(r, cols[t_details]).Text
+ if details:
+ empties = 0
+ # get test case description
+ desc = details.split('\n')[-1]
+ if not desc in results:
+ results[desc] = 'U', ''
+ sheet.Cells(r, cols[t_status]).Value, sheet.Cells(r, cols[t_comments]).Value = results[desc]
+ elif not sheet.Cells(r, cols[t_desc]).Text:
+ empties += 1
+
diff --git a/tiler/libtimemmgr.pc.in b/tiler/libtimemmgr.pc.in
new file mode 100644
index 0000000..7ecd886
--- /dev/null
+++ b/tiler/libtimemmgr.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: timemmgr
+Description: TI memory manager
+Version: @VERSION@
+Requires:
+Libs: -L${libdir} -ltimemmgr
+Cflags: -I${includedir}/timemmgr
+
+
diff --git a/tiler/list_utils.h b/tiler/list_utils.h
new file mode 100644
index 0000000..1643cf0
--- /dev/null
+++ b/tiler/list_utils.h
@@ -0,0 +1,511 @@
+/*
+ * list_utils.h
+ *
+ * Utility definitions for the Memory Interface for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LIST_UTILS_H_
+#define _LIST_UTILS_H_
+
+/*
+
+ DLIST macros facilitate double-linked lists in a generic fashion.
+
+ - Double-linked lists simplify list manipulations, so they are preferred to
+ single-linked lists.
+
+ - Having a double-linked list with a separate header allow accessing the
+ last element of the list easily, so this is also preferred to a double
+ linked list that uses NULL pointers at its ends.
+
+ Therefore, the following is required: a list info structure (separate from
+ the element structure, although the info structure can be a member of the
+ element structure). The info structure must contain (at least) the
+ following 3 members:
+
+ *next, *last: as pointers to the info structure. These are the next and
+ previous elements in the list.
+ *me: as a pointer to the element structure. This is how we get to the
+ element itself, as next and last points to another info structure.
+
+ The list element structure __MAY__ contain the info structure as a member,
+ or a pointer to the info structure if it is desired to be kept separately.
+ In such cases macros are provided to add the elements directly to the list,
+ and automatically set up the info structure fields correctly. You can also
+ iterate through the elements of the list using a pointer to the elements
+ itself, as the list structure can be obtained for each element.
+
+ Otherwise, macros are provided to manipulate list info structures and
+ link them in any shape or form into double linked lists. This allows
+ having NULL values as members of such lists.
+
+ :NOTE: If you use a macro with a field argument, you must not have NULL
+ elements because the field of any element must be/point to the list
+ info structure
+
+ DZLIST macros
+
+ Having the list info structure separate from the element structure also
+ allows to link elements into many separate lists (with separate info
+ structure fields/pointers). However, for cases where only a single list
+ is desired, a set of easy macros are also provided.
+
+ These macros combine the element and list structures. These macros
+ require the following 2 members in each element structure:
+
+ *next, *last: as pointers to the element structure. These are the next and
+ previous elements in the list.
+
+ :NOTE: In case of the DZLIST-s, the head of the list must be an element
+ structure, where only the next and last members are used. */
+
+/*
+ Usage:
+
+ DLIST macros are designed for preallocating the list info structures, e.g. in
+ an array. This is why most macros take a list info structure, and not a
+ pointer to a list info structure.
+
+ Basic linked list consists of element structure and list info structure
+
+ struct elem {
+ int data;
+ } *elA, *elB;
+ struct list {
+ struct elem *me;
+ struct list *last, *next;
+ } head, *inA, *inB, *in;
+
+ DLIST_INIT(head); // initialization -> ()
+ DLIST_IS_EMPTY(head) == TRUE; // emptiness check
+
+ // add element at beginning of list -> (1)
+ elA = NEW(struct elem);
+ elA->data = 1;
+ inA = NEW(struct list);
+ DLIST_ADD_AFTER(head, elA, *inA);
+
+ // add before an element -> (2, 1)
+ elB = NEW(struct elem);
+ elB->data = 2;
+ inB = NEW(struct list);
+ DLIST_ADD_BEFORE(*inA, elB, *inB);
+
+ // move an element to another position or another list -> (1, 2)
+ DLIST_MOVE_BEFORE(head, *inB);
+
+ // works even if the position is the same -> (1, 2)
+ DLIST_MOVE_BEFORE(head, *inB);
+
+ // get first and last elements
+ DLIST_FIRST(head) == elA;
+ DLIST_LAST(head) == elB;
+
+ // loop through elements
+ DLIST_LOOP(head, in) {
+ P("%d", in->me->data);
+ }
+
+ // remove element -> (2)
+ DLIST_REMOVE(*inA);
+ FREE(elA);
+ FREE(inA);
+
+ // delete list
+ DLIST_SAFE_LOOP(head, in, inA) {
+ DLIST_REMOVE(*in);
+ FREE(in->me);
+ FREE(in);
+ }
+
+ You can combine the element and list info structures to create an easy list,
+ but you still need to specify both element and info structure while adding
+ elements.
+
+ struct elem {
+ int data;
+ struct elem *me, *last, *next;
+ } head, *el, *elA, *elB;
+
+ DLIST_INIT(head); // initialization -> ()
+ DLIST_IS_EMPTY(head) == TRUE; // emptiness check
+
+ // add element at beginning of list -> (1)
+ elA = NEW(struct elem);
+ elA->data = 1;
+ DLIST_ADD_AFTER(head, elA, *elA);
+
+ // add before an element -> (2, 1)
+ elB = NEW(struct elem);
+ elB->data = 2;
+ DLIST_ADD_BEFORE(*elA, elB, *elB);
+
+ // move an element to another position or another list -> (1, 2)
+ DLIST_MOVE_BEFORE(head, *elB);
+
+ // works even if the position is the same -> (1, 2)
+ DLIST_MOVE_BEFORE(head, *elB);
+
+ // get first and last elements
+ DLIST_FIRST(head) == elA;
+ DLIST_LAST(head) == elB;
+
+ // loop through elements
+ DLIST_LOOP(head, el) {
+ P("%d", el->data);
+ }
+
+ // remove element -> (2)
+ DLIST_REMOVE(*elA);
+ FREE(elA);
+
+ // delete list
+ DLIST_SAFE_LOOP(head, el, elA) {
+ DLIST_REMOVE(*el);
+ FREE(el);
+ }
+
+ Or, you can use a DZLIST.
+
+ struct elem {
+ int data;
+ struct elem *last, *next;
+ } head, *el, *elA, *elB;
+
+ DZLIST_INIT(head); // initialization -> ()
+ DZLIST_IS_EMPTY(head) == TRUE; // emptiness check
+
+ // add element at beginning of list -> (1)
+ elA = NEW(struct elem);
+ elA->data = 1;
+ DZLIST_ADD_AFTER(head, *elA);
+
+ // add before an element -> (2, 1)
+ elB = NEW(struct elem);
+ elB->data = 2;
+ DZLIST_ADD_BEFORE(*elA, *elB);
+
+ // move an element to another position or another list -> (1, 2)
+ DZLIST_MOVE_BEFORE(head, *elB);
+
+ // works even if the position is the same -> (1, 2)
+ DZLIST_MOVE_BEFORE(head, *elB);
+
+ // get first and last elements
+ DZLIST_FIRST(head) == elA;
+ DZLIST_LAST(head) == elB;
+
+ // loop through elements
+ DZLIST_LOOP(head, el) {
+ P("%d", el->data);
+ }
+
+ // remove element -> (2)
+ DZLIST_REMOVE(*elA);
+ FREE(elA);
+
+ // delete list
+ DZLIST_SAFE_LOOP(head, el, elA) {
+ DZLIST_REMOVE(*el);
+ FREE(el);
+ }
+
+ A better way to get to the list structure from the element structure is to
+ enclose a pointer the list structure in the element structure. This allows
+ getting to the next/previous element from the element itself.
+
+ struct elem;
+ struct list {
+ struct elem *me;
+ struct list *last, *next;
+ } head, *inA, *inB, *in;
+ struct elem {
+ int data;
+ struct list *list_data;
+ } *elA, *elB, *el;
+
+ // or
+
+ struct elem {
+ int data;
+ struct list {
+ struct elem *me;
+ struct list *last, *next;
+ } *list_data;
+ } *elA, *elB, *el;
+ struct list head, *inA, *inB, *in;
+
+ DLIST_INIT(head); // initialization -> ()
+ DLIST_IS_EMPTY(head) == TRUE; // emptiness check
+
+ // add element at beginning of list -> (1)
+ elA = NEW(struct elem);
+ elA->data = 1;
+ inA = NEW(struct list);
+ DLIST_PADD_AFTER(head, elA, inA, list_data);
+
+ // add before an element -> (2, 1)
+ elB = NEW(struct elem);
+ elB->data = 2;
+ inB = NEW(struct list);
+ DLIST_PADD_BEFORE(*elA, elB, inB, list_data);
+
+ // move an element to another position or another list -> (1, 2)
+ DLIST_MOVE_BEFORE(head, *inB);
+
+ // works even if the position is the same -> (1, 2)
+ DLIST_MOVE_BEFORE(head, *inB);
+
+ // get first and last elements
+ DLIST_FIRST(head) == elA;
+ DLIST_LAST(head) == elB;
+
+ // loop through elements
+ DLIST_LOOP(head, in) {
+ P("%d", in->me->data);
+ }
+ DLIST_PLOOP(head, el, list_data) {
+ P("%d", el->data);
+ }
+
+ // remove element
+ DLIST_REMOVE(*inA);
+ FREE(inA);
+ FREE(elA);
+
+ // delete list
+ DLIST_SAFE_PLOOP(head, el, elA, list_data) {
+ DLIST_REMOVE(*el->list_data);
+ FREE(el->list_data);
+ FREE(el);
+ }
+
+ Lastly, you can include the list data in the element structure itself.
+
+ struct elem {
+ int data;
+ struct list {
+ struct list *last, *next;
+ struct elem *me;
+ } list_data;
+ } *elA, *elB, *el;
+ struct list head, *in;
+
+ DLIST_INIT(head); // initialization -> ()
+ DLIST_IS_EMPTY(head) == TRUE; // emptiness check
+
+ // add element at beginning of list -> (1)
+ elA = NEW(struct elem);
+ elA->data = 1;
+ DLIST_MADD_AFTER(head, elA, list_data);
+
+ // add before an element -> (2, 1)
+ elB = NEW(struct elem);
+ elB->data = 2;
+ DLIST_PADD_BEFORE(elA->list_data, elB, list_data);
+
+ // move an element to another position or another list -> (1, 2)
+ DLIST_MOVE_BEFORE(head, elB->list_data);
+
+ // works even if the position is the same -> (1, 2)
+ DLIST_MOVE_BEFORE(head, elB->list_data);
+
+ // get first and last elements
+ DLIST_FIRST(head) == elA;
+ DLIST_LAST(head) == elB;
+
+ // loop through elements
+ DLIST_LOOP(head, in) {
+ P("%d", in->me->data);
+ }
+ DLIST_MLOOP(head, el, list_data) {
+ P("%d", el->data);
+ }
+
+ // remove element
+ DLIST_REMOVE(elA->list_data);
+ FREE(elA);
+
+ // delete list
+ DLIST_SAFE_MLOOP(head, el, elA, list_data) {
+ DLIST_REMOVE(el->list_data);
+ FREE(el);
+ }
+
+ */
+
+/* -- internal (generic direction) macros -- */
+#define DLIST_move__(base, info, next, last) \
+ ((info).last = &base)->next = ((info).next = (base).next)->last = &(info)
+#define DLIST_padd__(base, pInfo, pElem, pField, next, last) \
+ ((pInfo)->last = &base)->next = ((pInfo)->next = (base).next)->last = \
+ pElem->pField = pInfo
+#define DLIST_loop__(head, pInfo, next) \
+ for (pInfo=(head).next; pInfo != &(head); pInfo = (pInfo)->next)
+#define DLIST_ploop__(head, pElem, pField, next) \
+ for (pElem=(head).next->me; pElem; pElem = (pElem)->pField->next->me)
+#define DLIST_mloop__(head, pElem, mField, next) \
+ for (pElem=(head).next->me; pElem; pElem = (pElem)->mField.next->me)
+#define DLIST_safe_loop__(head, pInfo, pInfo_safe, next) \
+ for (pInfo=(head).next; pInfo != &(head); pInfo = pInfo_safe) \
+ if ((pInfo_safe = (pInfo)->next) || 1)
+#define DLIST_safe_ploop__(head, pElem, pElem_safe, pField, next) \
+ for (pElem=(head).next->me; pElem; pElem = pElem_safe) \
+ if ((pElem_safe = (pElem)->pField->next->me) || 1)
+#define DLIST_safe_mloop__(head, pElem, pElem_safe, mField, next) \
+ for (pElem=(head).next->me; pElem; pElem = pElem_safe) \
+ if ((pElem_safe = (pElem)->mField.next->me) || 1)
+
+#define DLIST_IS_EMPTY(head) ((head).next == &(head))
+
+/* Adds the element (referred to by the info structure) before/or after another
+ element (or list header) (base). */
+
+#define DLIST_ADD_AFTER(base, pElem, info) \
+ (DLIST_move__(base, info, next, last))->me = pElem
+#define DLIST_ADD_BEFORE(base, pElem, info) \
+ (DLIST_move__(base, info, last, next))->me = pElem
+
+/* Adds the element (referred to by pElem pointer) along with its info
+ structure (referred to by pInfo pointer) before/or after an element or
+ list header (base). It also sets up the list structure header to point to
+ the element as well as the element's field to point back to the list info
+ structure. */
+#define DLIST_PADD_BEFORE(base, pElem, pInfo, pField) \
+ (DLIST_padd__(base, pInfo, pElem, pField, last, next))->me = pElem
+#define DLIST_PADD_AFTER(base, pElem, pInfo, pField) \
+ (DLIST_padd__(base, pInfo, pElem, pField, next, last))->me = pElem
+
+/* Adds the element (referred to by pElem pointer) before/or after an element or
+ list header (base). It also sets up the list structure header (which is a
+ member of the element's structure) to point to the element. */
+#define DLIST_MADD_BEFORE(base, pElem, mField) \
+ (DLIST_move__(base, pElem->mField, last, next))->me = pElem
+#define DLIST_MADD_AFTER(base, pElem, mField) \
+ (DLIST_move__(base, pElem->mField, next, last))->me = pElem
+
+/* Removes the element (referred to by the info structure) from its current
+ list. This requires that the element is a part of a list.
+
+ :NOTE: the info structure will still think that it belongs to the list it
+ used to belong to. However, the old list will not contain this element any
+ longer. You want to discard the info/element after this call. Otherwise,
+ you can use one of the MOVE macros to also add the item to another list,
+ or another place in the same list. */
+#define DLIST_REMOVE(info) ((info).last->next = (info).next)->last = (info).last
+
+/* Initializes the list header (to an empty list) */
+#define DLIST_INIT(head) \
+ do { (head).me = NULL; (head).next = (head).last = &(head); } while(0)
+
+/* These functions move an element (referred to by the info structure) before
+ or after another element (or the list head).
+ :NOTE: This logic also works for moving an element after/before itself. */
+#define DLIST_MOVE_AFTER(base, info) \
+ do { DLIST_REMOVE(info); DLIST_move__(base, info, next, last); } while(0)
+#define DLIST_MOVE_BEFORE(base, info) \
+ do { DLIST_REMOVE(info); DLIST_move__(base, info, last, next); } while(0)
+
+/* Loops behave syntactically as a for() statement. They traverse the loop
+ variable from the 1st to the last element (or in the opposite direction in
+ case of RLOOP). There are 3 flavors of loops depending on the type of the
+ loop variable.
+
+ DLIST_LOOP's loop variable is a pointer to the list info structure. You can
+ get to the element by using the 'me' member. Nonetheless, this loop
+ construct allows having NULL elements in the list.
+
+ DLIST_MLOOP's loop variable is a pointer to a list element. mField is the
+ field of the element containing the list info structure. Naturally, this
+ list cannot have NULL elements.
+
+ DLIST_PLOOP's loop variable is also a pointer to a list element. Use this
+ construct if the element contains a pointer to the list info structure
+ instead of embedding it directly into the element structure.
+
+*/
+#define DLIST_LOOP(head, pInfo) DLIST_loop__(head, pInfo, next)
+#define DLIST_RLOOP(head, pInfo) DLIST_loop__(head, pInfo, last)
+#define DLIST_MLOOP(head, pElem, mField) \
+ DLIST_mloop__(head, pElem, mField, next)
+#define DLIST_RMLOOP(head, pElem, mField) \
+ DLIST_mloop__(head, pElem, mField, last)
+#define DLIST_PLOOP(head, pElem, pField) \
+ DLIST_ploop__(head, pElem, pField, next)
+#define DLIST_RPLOOP(head, pElem, pField) \
+ DLIST_ploop__(head, pElem, pField, last)
+
+/* Safe loops are like ordinary loops, but they allow removal of the current
+ element from the list. They require an extra loop variable that holds the
+ value of the next element in case the current element is moved/removed. */
+#define DLIST_SAFE_LOOP(head, pInfo, pInfo_safe) \
+ DLIST_safe_loop__(head, pInfo, pInfo_safe, next)
+#define DLIST_SAFE_RLOOP(head, pInfo, pInfo_safe) \
+ DLIST_safe_loop__(head, pInfo, pInfo_safe, last)
+#define DLIST_SAFE_MLOOP(head, pElem, pElem_safe, mField) \
+ DLIST_safe_mloop__(head, pElem, pElem_safe, mField, next)
+#define DLIST_SAFE_RMLOOP(head, pElem, pElem_safe, mField) \
+ DLIST_safe_mloop__(head, pElem, pElem_safe, mField, last)
+#define DLIST_SAFE_PLOOP(head, pElem, pElem_safe, pField) \
+ DLIST_safe_ploop__(head, pElem, pElem_safe, pField, next)
+#define DLIST_SAFE_RPLOOP(head, pElem, pElem_safe, pField) \
+ DLIST_safe_ploop__(head, pElem, pElem_safe, pField, last)
+
+/* returns the first element of a list */
+#define DLIST_FIRST(head) (head).next->me
+/* returns the last element of a list */
+#define DLIST_LAST(head) (head).last->me
+
+
+/* DZLIST equivalent API - provided so arguments are specified */
+#define DZLIST_INIT(head) do { (head).next = (head).last = &(head); } while(0)
+#define DZLIST_IS_EMPTY(head) DLIST_IS_EMPTY(head)
+#define DZLIST_FIRST(head) (head).next
+#define DZLIST_LAST(head) (head).last
+
+#define DZLIST_ADD_AFTER(base, elem) DLIST_move__(base, elem, next, last)
+#define DZLIST_ADD_BEFORE(base, elem) DLIST_move__(base, elem, last, next)
+
+#define DZLIST_REMOVE(elem) DLIST_REMOVE(elem)
+
+#define DZLIST_MOVE_AFTER(base, elem) DLIST_MOVE_AFTER(base, elem)
+#define DZLIST_MOVE_BEFORE(base, elem) DLIST_MOVE_BEFORE(base, elem)
+
+#define DZLIST_LOOP(head, pElem) DLIST_LOOP(head, pElem)
+#define DZLIST_RLOOP(head, pElem) DLIST_RLOOP(head, pElem)
+#define DZLIST_SAFE_LOOP(head, pElem, pElem_safe) \
+ DLIST_SAFE_LOOP(head, pElem, pElem_safe)
+#define DZLIST_SAFE_RLOOP(head, pElem, pElem_safe) \
+ DLIST_SAFE_RLOOP(head, pElem, pElem_safe)
+
+#endif
+
diff --git a/tiler/mem_types.h b/tiler/mem_types.h
new file mode 100644
index 0000000..18453bb
--- /dev/null
+++ b/tiler/mem_types.h
@@ -0,0 +1,101 @@
+/*
+ * types.h
+ *
+ * Type definitions for the Memory Interface for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MEM_TYPES_H_
+#define _MEM_TYPES_H_
+
+/* for bool definition */
+#include <stdbool.h>
+#include <stdint.h>
+
+/** ---------------------------------------------------------------------------
+ * Type definitions
+ */
+
+/**
+ * Buffer length in bytes
+ */
+typedef uint32_t bytes_t;
+
+/**
+ * Length in pixels
+ */
+typedef uint16_t pixels_t;
+
+
+/**
+ * Pixel format
+ *
+ * Page mode is encoded in the pixel format to handle different
+ * set of buffers uniformly
+ */
+enum pixel_fmt_t {
+ PIXEL_FMT_MIN = 0,
+ PIXEL_FMT_8BIT = 0,
+ PIXEL_FMT_16BIT = 1,
+ PIXEL_FMT_32BIT = 2,
+ PIXEL_FMT_PAGE = 3,
+ PIXEL_FMT_MAX = 3
+};
+
+typedef enum pixel_fmt_t pixel_fmt_t;
+
+/**
+ * Ducati Space Virtual Address Pointer
+ *
+ * This is handled as a unsigned long so that no dereferencing
+ * is allowed by user space components.
+ */
+typedef uint32_t DSPtr;
+
+/**
+ * System Space Pointer
+ *
+ * This is handled as a unsigned long so that no dereferencing
+ * is allowed by user space components.
+ */
+typedef uint32_t SSPtr;
+
+/**
+ * Error values
+ *
+ * Page mode is encoded in the pixel format to handle different
+ * set of buffers uniformly
+ */
+#define MEMMGR_ERR_NONE 0
+#define MEMMGR_ERR_GENERIC 1
+
+#endif
+
diff --git a/tiler/memmgr.c b/tiler/memmgr.c
new file mode 100644
index 0000000..1f780cc
--- /dev/null
+++ b/tiler/memmgr.c
@@ -0,0 +1,1078 @@
+/*
+ * memmgr.c
+ *
+ * Memory Allocator Interface functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <errno.h>
+
+#define BUF_ALLOCED 1
+#define BUF_MAPPED 2
+#define BUF_ANY ~0
+
+#include <tiler.h>
+
+typedef struct tiler_block_info tiler_block_info;
+
+#define __DEBUG__
+#undef __DEBUG_ENTRY__
+#define __DEBUG_ASSERT__
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+#include "utils.h"
+#include "list_utils.h"
+#include "debug_utils.h"
+#include "tilermem.h"
+#include "tilermem_utils.h"
+#include "memmgr.h"
+
+/* list of allocations */
+struct _AllocData {
+ struct tiler_buf_info buf;
+ int buf_type;
+ struct _AllocList {
+ struct _AllocList *next, *last;
+ struct _AllocData *me;
+ } link;
+};
+static struct _AllocList bufs = {0};
+static int bufs_inited = 0;
+
+typedef struct _AllocList _AllocList;
+typedef struct _AllocData _AllocData;
+
+static int refCnt = 0;
+static int td = -1;
+static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t che_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * Initializes the static structures
+ *
+ * @author a0194118 (9/8/2009)
+ */
+static void init()
+{
+ if (!bufs_inited)
+ {
+ DLIST_INIT(bufs);
+ bufs_inited = 1;
+ }
+}
+
+/**
+ * Increases the reference count. Initialized tiler if this was
+ * the first reference
+ *
+ * @author a0194118 (9/2/2009)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static int inc_ref()
+{
+ /* initialize tiler on first call */
+ pthread_mutex_lock(&ref_mutex);
+
+ int res = MEMMGR_ERR_NONE;
+
+ if (!refCnt++) {
+ /* initialize lists */
+ init();
+#ifndef STUB_TILER
+ td = open("/dev/tiler", O_RDWR | O_SYNC);
+ if (NOT_I(td,>=,0)) res = MEMMGR_ERR_GENERIC;
+#else
+ td = 2;
+ res = MEMMGR_ERR_NONE;
+#endif
+ }
+ if (res)
+ {
+ refCnt--;
+ }
+
+ pthread_mutex_unlock(&ref_mutex);
+ return res;
+}
+
+/**
+ * Decreases the reference count. Deinitialized tiler if this
+ * was the last reference
+ *
+ * @author a0194118 (9/2/2009)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static int dec_ref()
+{
+ pthread_mutex_lock(&ref_mutex);
+
+ int res = MEMMGR_ERR_NONE;;
+
+ if (refCnt <= 0) res = MEMMGR_ERR_GENERIC;
+ else if (!--refCnt) {
+#ifndef STUB_TILER
+ close(td);
+ td = -1;
+#endif
+ }
+
+ pthread_mutex_unlock(&ref_mutex);
+ return res;
+}
+
+/**
+ * Returns the default page stride for this block
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @param width Width of 2D container in bytes
+ *
+ * @return Stride
+ */
+static bytes_t def_stride(bytes_t width)
+{
+ return ROUND_UP_TO2POW(width, PAGE_SIZE);
+}
+
+/**
+ * Returns the bytes per pixel for the pixel format.
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @param pixelFormat Pixelformat
+ *
+ * @return Bytes per pixel
+ */
+static bytes_t def_bpp(pixel_fmt_t pixelFormat)
+{
+ return (pixelFormat == PIXEL_FMT_32BIT ? 4 :
+ pixelFormat == PIXEL_FMT_16BIT ? 2 : 1);
+}
+
+/**
+ * Returns the size of the supplied block
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @param blk Pointer to the tiler_block_info struct
+ *
+ * @return size of the block in bytes
+ */
+static bytes_t def_size(tiler_block_info *blk)
+{
+ return (blk->fmt == PIXEL_FMT_PAGE ?
+ def_stride(blk->dim.len) :
+ blk->dim.area.height * def_stride(blk->dim.area.width * def_bpp(blk->fmt)));
+}
+
+/**
+ * Returns the map size based on an offset and buffer size
+ *
+ * @author a0194118 (7/8/2010)
+ *
+ * @param size Size of buffer
+ * @param offs Buffer offset
+ *
+ * @return (page aligned) size for mapping
+ */
+static bytes_t map_size(bytes_t size, bytes_t offs)
+{
+ return def_stride(size + (offs & (PAGE_SIZE - 1)));
+}
+
+/**
+ * Records a buffer-pointer -- tiler-ID mapping for a specific
+ * buffer type.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param bufPtr Buffer pointer
+ * @param tiler_id Tiler ID
+ * @param buf_type Buffer type: BUF_ALLOCED or BUF_MAPPED
+ *
+ * @return 0 on success, -ENOMEM on memory allocation failure
+ */
+static int buf_cache_add(struct tiler_buf_info *buf, int buf_type)
+{
+ pthread_mutex_lock(&che_mutex);
+ _AllocData *ad = NEW(_AllocData);
+ if (ad)
+ {
+ memcpy(&ad->buf, buf, sizeof(ad->buf));
+ ad->buf_type = buf_type;
+ DLIST_MADD_BEFORE(bufs, ad, link);
+ }
+ pthread_mutex_unlock(&che_mutex);
+ return ad == NULL ? -ENOMEM : 0;
+}
+
+/**
+ * Retrieves the tiler ID for given pointer and buffer type from
+ * the records. If the pointer lies within a tracked buffer,
+ * the tiler ID is returned. Otherwise 0 is returned.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param bufPtr Buffer pointer
+ * @param buf_type Buffer type: BUF_ALLOCED or BUF_MAPPED
+ *
+ * @return Tiler ID on success, 0 on failure.
+ */
+static void buf_cache_query(void *ptr, struct tiler_buf_info *buf,
+ int buf_type_mask)
+{
+ IN;
+ if(0) DP("in(p=%p,t=%d,bp*=%p)", ptr, buf_type_mask, buf->blocks[0].ptr);
+ _AllocData *ad;
+ pthread_mutex_lock(&che_mutex);
+ DLIST_MLOOP(bufs, ad, link) {
+ if(0) {
+ DP("got(%p-%p,%d)", ad->buf.blocks->ptr, ad->buf.blocks->ptr + ad->buf.length, ad->buf_type);
+ CHK_P(ad->buf.blocks->ptr,<=,ptr);
+ CHK_P(ptr,<,ad->buf.blocks->ptr + ad->buf.length);
+ CHK_I(ad->buf_type & buf_type_mask,!=,0);
+ CHK_P(buf->blocks->ptr,!=,0);
+ }
+ if ((ad->buf_type & buf_type_mask) &&
+ ad->buf.blocks->ptr <= ptr && ptr < ad->buf.blocks->ptr + ad->buf.length) {
+ memcpy(buf, &ad->buf, sizeof(*buf));
+ pthread_mutex_unlock(&che_mutex);
+ return;
+ }
+ }
+ pthread_mutex_unlock(&che_mutex);
+ ZERO(*buf);
+ OUT;
+}
+
+/**
+ * Retrieves the tiler ID for given buffer pointer and buffer
+ * type from the records. If the tiler ID is found, it is
+ * removed from the records as well.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param bufPtr Buffer pointer
+ * @param buf_type Buffer type: BUF_ALLOCED or BUF_MAPPED
+ *
+ * @return Tiler ID on success, 0 on failure.
+ */
+static void buf_cache_del(void *bufPtr, struct tiler_buf_info *buf,
+ int buf_type)
+{
+ _AllocData *ad;
+ pthread_mutex_lock(&che_mutex);
+ DLIST_MLOOP(bufs, ad, link) {
+ if (ad->buf.blocks->ptr == bufPtr && ad->buf_type == buf_type) {
+ memcpy(buf, &ad->buf, sizeof(*buf));
+ DLIST_REMOVE(ad->link);
+ FREE(ad);
+ pthread_mutex_unlock(&che_mutex);
+ return;
+ }
+ }
+ pthread_mutex_unlock(&che_mutex);
+ OUT;
+ return;
+}
+
+/**
+ * Checks the consistency of the internal record cache. The
+ * number of elements in the cache should equal to the number of
+ * references.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static int cache_check()
+{
+ int num_bufs = 0;
+ pthread_mutex_lock(&che_mutex);
+
+ init();
+
+ _AllocData *ad;
+ DLIST_MLOOP(bufs, ad, link) { num_bufs++; }
+
+ pthread_mutex_unlock(&che_mutex);
+ return (num_bufs == refCnt) ? MEMMGR_ERR_NONE : MEMMGR_ERR_GENERIC;
+}
+
+static void dump_block(struct tiler_block_info *blk, char *prefix, char *suffix)
+{
+#if 0
+ switch (blk->fmt)
+ {
+ case TILFMT_PAGE:
+ P("%s [%d:(%d,%08x), p=%p(0x%x),l=0x%x,s=%d,%d+%d]%s", prefix, blk->group_id, blk->key, blk->id, blk->ptr, blk->ssptr,
+ blk->dim.len, blk->stride, blk->align, blk->offs, suffix);
+ break;
+ case TILFMT_8BIT:
+ case TILFMT_16BIT:
+ case TILFMT_32BIT:
+ P("%s [%d:(%d,%08x), p=%p(0x%x),%d*%d*%d,s=%d,%d+%d]%s", prefix, blk->group_id, blk->key, blk->id, blk->ptr, blk->ssptr,
+ blk->dim.area.width, blk->dim.area.height, def_bpp(blk->fmt) * 8,
+ blk->stride, blk->align, blk->offs, suffix);
+ break;
+ default:
+ P("%s*[%d:(%d,%08x), p=%p(0x%x),l=0x%x,s=%d,%d+%d,fmt=0x%x]%s", prefix, blk->group_id, blk->key, blk->id, blk->ptr,
+ blk->ssptr, blk->dim.len, blk->stride, blk->align, blk->offs, blk->fmt, suffix);
+ }
+#endif
+}
+
+static void dump_buf(struct tiler_buf_info* buf, char* prefix)
+{
+#if 0
+ P("%sbuf={n=%d,id=0x%x,len=0x%x", prefix, buf->num_blocks, buf->offset, buf->length);
+ int ix = 0;
+ for (ix = 0; ix < buf->num_blocks; ix++)
+ {
+ dump_block(buf->blocks + ix, "", ix + 1 == buf->num_blocks ? "}" : "");
+ }
+#endif
+}
+
+/**
+ * Returns the tiler format for an address
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param ssptr Address
+ *
+ * @return The tiler format
+ */
+static enum tiler_fmt tiler_get_fmt(SSPtr ssptr)
+{
+#ifndef STUB_TILER
+ return (ssptr == 0 ? TILFMT_INVALID :
+ ssptr < TILER_MEM_8BIT ? TILFMT_NONE :
+ ssptr < TILER_MEM_16BIT ? TILFMT_8BIT :
+ ssptr < TILER_MEM_32BIT ? TILFMT_16BIT :
+ ssptr < TILER_MEM_PAGED ? TILFMT_32BIT :
+ ssptr < TILER_MEM_END ? TILFMT_PAGE : TILFMT_NONE);
+#else
+ /* if emulating, we need to get through all allocated memory segments */
+ pthread_mutex_lock(&che_mutex);
+ init();
+ _AllocData *ad;
+ void *ptr = (void *) ssptr;
+ if (!ptr) return TILFMT_INVALID;
+ /* P("?%p", (void *)ssptr); */
+ DLIST_MLOOP(bufs, ad, link) {
+ int ix;
+ struct tiler_buf_info *buf = (struct tiler_buf_info *) ad->buf.offset;
+ /* P("buf[%d]", buf->num_blocks); */
+ for (ix = 0; ix < buf->num_blocks; ix++)
+ {
+ /* P("block[%p-%p]", buf->blocks[ix].ptr, buf->blocks[ix].ptr + def_size(buf->blocks + ix)); */
+ if (ptr >= buf->blocks[ix].ptr &&
+ ptr < buf->blocks[ix].ptr + def_size(buf->blocks + ix)) {
+ enum tiler_fmt fmt = buf->blocks[ix].fmt;
+ pthread_mutex_unlock(&che_mutex);
+ return fmt;
+ }
+ }
+ }
+ pthread_mutex_unlock(&che_mutex);
+ return TILFMT_NONE;
+#endif
+}
+
+
+/**
+ * Allocates a memory block using tiler
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param blk Pointer to the block info
+ *
+ * @return ssptr of block allocated, or 0 on error
+ */
+static int tiler_alloc(struct tiler_block_info *blk)
+{
+ dump_block(blk, "=(ta)=>", "");
+ blk->ptr = NULL;
+ int ret = A_S(ioctl(td, TILIOC_GBLK, blk),==,0);
+ dump_block(blk, "alloced: ", "");
+ return R_I(ret);
+}
+
+/**
+ * Frees a memory block using tiler
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param blk Pointer to the block info
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static int tiler_free(struct tiler_block_info *blk)
+{
+ return R_I(ioctl(td, TILIOC_FBLK, blk));
+}
+
+/**
+ * Maps a memory block into tiler using tiler
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param blk Pointer to the block info
+ *
+ * @return ssptr of block mapped, or 0 on error
+ */
+static int tiler_map(struct tiler_block_info *blk)
+{
+ dump_block(blk, "=(tm)=>", "");
+ int ret = A_S(ioctl(td, TILIOC_MBLK, blk),==,0);
+ dump_block(blk, "mapped: ", "");
+ return R_I(ret);
+}
+
+/**
+ * Unmaps a memory block from tiler using tiler
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param blk Pointer to the block info
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static int tiler_unmap(struct tiler_block_info *blk)
+{
+ return ioctl(td, TILIOC_UMBLK, blk);
+}
+
+/**
+ * Registers a buffer structure with tiler, and maps the buffer
+ * into memory using tiler. On success, it writes the tiler ID
+ * of the buffer into the area pointed by tiler ID.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param blks Pointer to array of block info structures
+ * @param num_blocks Number of blocks
+ * @param tiler_id Pointer to tiler ID.
+ *
+ * @return pointer to the mapped buffer.
+ */
+static void *tiler_mmap(struct tiler_block_info *blks, int num_blocks,
+ int buf_type)
+{
+ IN;
+
+ /* get size */
+ int ix;
+ bytes_t size;
+
+ /* register buffer with tiler */
+ struct tiler_buf_info buf;
+ buf.num_blocks = num_blocks;
+ /* work on copy in buf */
+ memcpy(buf.blocks, blks, sizeof(tiler_block_info) * num_blocks);
+#ifndef STUB_TILER
+ dump_buf(&buf, "==(RBUF)=>");
+ int ret = ioctl(td, TILIOC_RBUF, &buf);
+ dump_buf(&buf, "<=(RBUF)==");
+ if (NOT_I(ret,==,0)) return NULL;
+ size = buf.length;
+#else
+ /* save buffer in stub */
+ struct tiler_buf_info *buf_c = NEWN(struct tiler_buf_info,2);
+ buf.offset = (uint32_t) buf_c;
+#endif
+ if (NOT_P(buf.offset,!=,0)) return NULL;
+
+ /* map blocks to process space */
+#ifndef STUB_TILER
+ void *bufPtr = mmap(0, map_size(size, buf.offset),
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ td, buf.offset & ~(PAGE_SIZE - 1));
+ if (bufPtr == MAP_FAILED){
+ bufPtr = NULL;
+ } else {
+ bufPtr += buf.offset & (PAGE_SIZE - 1);
+ }
+ if(0) DP("ptr=%p", bufPtr);
+#else
+ void *bufPtr = malloc(size + PAGE_SIZE - 1);
+ buf_c[1].blocks[0].ptr = bufPtr;
+ bufPtr = ROUND_UP_TO2POW(bufPtr, PAGE_SIZE);
+ /* P("<= [0x%x]", size); */
+
+ /* fill out pointers - this is needed for caching 1D/2D type */
+ for (size = ix = 0; ix < num_blocks; ix++)
+ {
+ buf.blocks[ix].ptr = bufPtr ? bufPtr + size : bufPtr;
+ size += def_size(blks + ix);
+ }
+
+ memcpy(buf_c, &buf, sizeof(struct tiler_buf_info));
+#endif
+
+ if (bufPtr != NULL)
+ {
+ /* fill out pointers */
+ for (size = ix = 0; ix < num_blocks; ix++)
+ {
+ buf.blocks[ix].ptr = bufPtr + size;
+ /* P(" [0x%p]", buf.blocks[ix].ptr); */
+ size += def_size(blks + ix);
+#ifdef STUB_TILER
+ buf.blocks[ix].ssptr = (uint32_t) buf.blocks[ix].ptr;
+#else
+ CHK_I((buf.blocks[ix].ssptr & (PAGE_SIZE - 1)),==,((uint32_t) buf.blocks[ix].ptr & (PAGE_SIZE - 1)));
+#endif
+ }
+ }
+ /* if failed to map: unregister buffer */
+ if (NOT_P(bufPtr,!=,NULL) ||
+ /* or failed to cache tiler buffer */
+ NOT_I(buf_cache_add(&buf, buf_type),==,0))
+ {
+#ifndef STUB_TILER
+ A_I(ioctl(td, TILIOC_URBUF, &buf),==,0);
+#else
+ FREE(buf_c);
+ buf.offset = 0;
+#endif
+ } else {
+ /* update original from local copy */
+ memcpy(blks, buf.blocks, sizeof(tiler_block_info) * num_blocks);
+ }
+
+ return R_P(bufPtr);
+}
+
+/**
+ * Checks whether the tiler_block_info is filled in correctly.
+ * Verifies the pixel format, correct length, width and or
+ * height, the length/stride relationship for 1D buffers, and
+ * the correct stride for 2D buffers. Also verifies block size
+ * to be page sized if desired.
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @param blk Pointer to the tiler_block_info struct
+ * @param is_page_sized Whether the block needs to be page
+ * sized (fit on whole pages).
+ * @return 0 on success, non-0 error value on failure.
+ */
+static int check_block(tiler_block_info *blk, bool is_page_sized)
+{
+ /* check pixelformat */
+ if (NOT_I(blk->fmt,>=,PIXEL_FMT_MIN) ||
+ NOT_I(blk->fmt,<=,PIXEL_FMT_MAX)) return MEMMGR_ERR_GENERIC;
+
+
+ if (blk->fmt == PIXEL_FMT_PAGE)
+ { /* check 1D buffers */
+
+ /* length must be multiple of stride if stride > 0 */
+ if (NOT_I(blk->dim.len,>,0) ||
+ (blk->stride && NOT_I(blk->dim.len % blk->stride,==,0)))
+ return MEMMGR_ERR_GENERIC;
+ }
+ else
+ { /* check 2D buffers */
+
+ /* check width, height and stride (must be the default stride or 0) */
+ bytes_t stride = def_stride(blk->dim.area.width * def_bpp(blk->fmt));
+ if (NOT_I(blk->dim.area.width,>,0) ||
+ NOT_I(blk->dim.area.height,>,0) ||
+ (blk->stride && NOT_I(blk->stride,==,stride)))
+ return MEMMGR_ERR_GENERIC;
+ }
+
+ if (is_page_sized && NOT_I(def_size(blk) & (PAGE_SIZE - 1),==,0))
+ return MEMMGR_ERR_GENERIC;
+
+ return MEMMGR_ERR_NONE;
+}
+
+/**
+ * Checks whether the block information is correct for map and
+ * alloc operations. Checks the number of blocks, and validity
+ * of each block. Warns if reserved member is not 0. Also
+ * checks if the alignment/offset requirements are consistent
+ * across the buffer
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param blks Pointer to the block info array.
+ * @param num_blocks Number of blocks.
+ * @param num_pagesize_blocks Number of blocks that must be
+ * page sized (these must be in
+ * front)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+static int check_blocks(struct tiler_block_info *blks, int num_blocks,
+ int num_pagesize_blocks)
+{
+ /* check arguments */
+ if (NOT_I(num_blocks,>,0) ||
+ NOT_I(num_blocks,<=,TILER_MAX_NUM_BLOCKS)) return MEMMGR_ERR_GENERIC;
+
+ /* check block allocation params */
+ int ix;
+ for (ix = 0; ix < num_blocks; ix++)
+ {
+ struct tiler_block_info *blk = blks + ix;
+ CHK_I(blk->ssptr,==,0);
+ CHK_I(blk->id,==,0);
+ int ret = check_block(blk, ix < num_pagesize_blocks);
+
+ /* check alignment */
+ if (!ret)
+ {
+ }
+ if (ret)
+ {
+ DP("for block[%d]", ix);
+ return ret;
+ }
+
+
+ }
+
+ /* set alignment parameters */
+ return MEMMGR_ERR_NONE;
+}
+
+/**
+ * Resets the ptr and reserved fields of the block info
+ * structures.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param blks Pointer to the block info array.
+ * @param num_blocks Number of blocks.
+ */
+static void reset_blocks(struct tiler_block_info *blks, int num_blocks)
+{
+ int ix;
+ for (ix = 0; ix < num_blocks; ix++)
+ {
+ blks[ix].ssptr = 0;
+ blks[ix].id = 0;
+ blks[ix].ptr = NULL;
+ }
+
+}
+
+bytes_t MemMgr_PageSize()
+{
+ return PAGE_SIZE;
+}
+
+void *MemMgr_Alloc(MemAllocBlock blocks[], int num_blocks)
+{
+ IN;
+ void *bufPtr = NULL;
+
+ /* need to access ssptrs */
+ struct tiler_block_info *blks = (tiler_block_info *) blocks;
+
+ /* check block allocation params, and state */
+ if (NOT_I(check_blocks(blks, num_blocks, num_blocks - 1),==,0) ||
+ NOT_I(inc_ref(),==,0)) goto DONE;
+
+ /* ----- begin recoverable portion ----- */
+ int ix;
+
+ /* allocate each buffer using tiler driver and initialize block info */
+ for (ix = 0; ix < num_blocks; ix++)
+ {
+ if (ix)
+ {
+ /* continue offset between pages */
+ }
+ CHK_I(blks[ix].ptr,==,NULL);
+ if (NOT_I(tiler_alloc(blks + ix),==,0)) goto FAIL_ALLOC;
+ }
+
+ bufPtr = tiler_mmap(blks, num_blocks, BUF_ALLOCED);
+ if (A_P(bufPtr,!=,0)) goto DONE;
+
+ /* ------ error handling ------ */
+FAIL_ALLOC:
+ while (ix)
+ {
+ tiler_free(blks + --ix);
+ }
+
+ /* clear ssptr and ptr fields for all blocks */
+ reset_blocks(blks, num_blocks);
+
+ A_I(dec_ref(),==,0);
+DONE:
+ CHK_I(cache_check(),==,0);
+ return R_P(bufPtr);
+}
+
+int MemMgr_Free(void *bufPtr)
+{
+ IN;
+
+ int ret = MEMMGR_ERR_GENERIC;
+ struct tiler_buf_info buf;
+ ZERO(buf);
+
+ /* retrieve registered buffers from vsptr */
+ /* :NOTE: if this succeeds, Memory Allocator stops tracking this buffer */
+ buf_cache_del(bufPtr, &buf, BUF_ALLOCED);
+
+ if (A_L(buf.offset,!=,0))
+ {
+#ifndef STUB_TILER
+ dump_buf(&buf, "==(URBUF)=>");
+ ret = A_I(ioctl(td, TILIOC_URBUF, &buf),==,0);
+ dump_buf(&buf, "<=(URBUF)==");
+
+ /* free each block */
+ int ix;
+ for (ix = 0; ix < buf.num_blocks; ix++)
+ {
+ ERR_ADD(ret, tiler_free(buf.blocks + ix));
+ }
+
+ /* unmap buffer */
+ bufPtr = (void *)((uint32_t)bufPtr & ~(PAGE_SIZE - 1));
+ ERR_ADD(ret, munmap(bufPtr, map_size(buf.length, buf.offset)));
+#else
+ void *ptr = (void *) buf.offset;
+ FREE(ptr);
+ ret = MEMMGR_ERR_NONE;
+#endif
+ ERR_ADD(ret, dec_ref());
+ }
+
+ CHK_I(cache_check(),==,0);
+ return R_I(ret);
+}
+
+void *MemMgr_Map(MemAllocBlock blocks[], int num_blocks)
+{
+ IN;
+ void *bufPtr = NULL;
+
+ /* need to access ssptrs */
+ struct tiler_block_info *blks = (tiler_block_info *) blocks;
+
+ /* check block params, and state */
+ if (check_blocks(blks, num_blocks, num_blocks) ||
+ NOT_I(inc_ref(),==,0)) goto DONE;
+
+ /* we only map 1 page aligned 1D buffer for now */
+ if (NOT_I(num_blocks,==,1) ||
+ NOT_I(blocks[0].pixelFormat,==,PIXEL_FMT_PAGE) ||
+ NOT_I(blocks[0].dim.len & (PAGE_SIZE - 1),==,0) ||
+#ifdef STUB_TILER
+ NOT_I(MemMgr_IsMapped(blocks[0].ptr),==,0) ||
+#endif
+ NOT_I((uint32_t)blocks[0].ptr & (PAGE_SIZE - 1),==,0))
+ goto FAIL;
+
+ /* ----- begin recoverable portion ----- */
+ int ix;
+
+ /* allocate each buffer using tiler driver */
+ for (ix = 0; ix < num_blocks; ix++)
+ {
+ if (ix)
+ {
+ /* continue offset between pages */
+ }
+ if (NOT_I(blks[ix].ptr,!=,NULL) ||
+ NOT_I(tiler_map(blks + ix),==,0)) goto FAIL_MAP;
+ }
+
+ /* map bufer into tiler space and register with tiler manager */
+ bufPtr = tiler_mmap(blks, num_blocks, BUF_MAPPED);
+ if (A_P(bufPtr,!=,0)) goto DONE;
+
+ /* ------ error handling ------ */
+FAIL_MAP:
+ while (ix)
+ {
+ tiler_unmap(blks + --ix);
+ }
+
+FAIL:
+ /* clear ssptr and ptr fields for all blocks */
+ reset_blocks(blks, num_blocks);
+
+ A_I(dec_ref(),==,0);
+DONE:
+ CHK_I(cache_check(),==,0);
+ return R_P(bufPtr);
+}
+
+int MemMgr_UnMap(void *bufPtr)
+{
+ IN;
+
+ int ret = MEMMGR_ERR_GENERIC;
+ struct tiler_buf_info buf;
+ ZERO(buf);
+
+ /* retrieve registered buffers from vsptr */
+ /* :NOTE: if this succeeds, Memory Allocator stops tracking this buffer */
+ buf_cache_del(bufPtr, &buf, BUF_MAPPED);
+
+ if (A_L(buf.offset,!=,0))
+ {
+#ifndef STUB_TILER
+ dump_buf(&buf, "==(URBUF)=>");
+ ret = A_I(ioctl(td, TILIOC_URBUF, &buf),==,0);
+ dump_buf(&buf, "<=(URBUF)==");
+
+ /* unmap each block */
+ int ix;
+ for (ix = 0; ix < buf.num_blocks; ix++)
+ {
+ ERR_ADD(ret, tiler_unmap(buf.blocks + ix));
+ }
+
+ /* unmap buffer */
+ bufPtr = (void *)((uint32_t)bufPtr & ~(PAGE_SIZE - 1));
+ ERR_ADD(ret, munmap(bufPtr, map_size(buf.length, buf.offset)));
+#else
+ struct tiler_buf_info *ptr = (struct tiler_buf_info *) buf.offset;
+ FREE(ptr[1].blocks[0].ptr);
+ FREE(ptr);
+ ret = MEMMGR_ERR_NONE;
+#endif
+ ERR_ADD(ret, dec_ref());
+ }
+
+ CHK_I(cache_check(),==,0);
+ return R_I(ret);
+}
+
+bool MemMgr_Is1DBlock(void *ptr)
+{
+ IN;
+
+ SSPtr ssptr = TilerMem_VirtToPhys(ptr);
+ enum tiler_fmt fmt = tiler_get_fmt(ssptr);
+ return R_I(fmt == TILFMT_PAGE);
+}
+
+bool MemMgr_Is2DBlock(void *ptr)
+{
+ IN;
+
+ SSPtr ssptr = TilerMem_VirtToPhys(ptr);
+ enum tiler_fmt fmt = tiler_get_fmt(ssptr);
+ return R_I(fmt == TILFMT_8BIT || fmt == TILFMT_16BIT ||
+ fmt == TILFMT_32BIT);
+}
+
+bool MemMgr_IsMapped(void *ptr)
+{
+ IN;
+ SSPtr ssptr = TilerMem_VirtToPhys(ptr);
+ enum tiler_fmt fmt = tiler_get_fmt(ssptr);
+ return R_I(fmt == TILFMT_8BIT || fmt == TILFMT_16BIT ||
+ fmt == TILFMT_32BIT || fmt == TILFMT_PAGE);
+}
+
+bytes_t MemMgr_GetStride(void *ptr)
+{
+ IN;
+#ifndef STUB_TILER
+ struct tiler_buf_info buf;
+ ZERO(buf);
+
+ /* find block that this buffer belongs to */
+ buf_cache_query(ptr, &buf, BUF_ALLOCED | BUF_MAPPED);
+ void *bufPtr = buf.blocks[0].ptr;
+
+ A_I(inc_ref(),==,0);
+
+ /* for tiler mapped buffers, get saved stride information */
+ if (buf.offset)
+ {
+ /* walk through block to determine which stride we need */
+ int ix;
+ for (ix = 0; ix < buf.num_blocks; ix++)
+ {
+ bytes_t size = def_size(buf.blocks + ix);
+ if (bufPtr <= ptr && ptr < bufPtr + size) {
+ A_I(dec_ref(),==,0);
+ return R_UP(buf.blocks[ix].stride);
+ }
+ bufPtr += size;
+ }
+ A_I(dec_ref(),==,0);
+ DP("assert: should not ever get here");
+ return R_UP(0);
+ }
+ /* see if pointer is valid */
+ else if (TilerMem_VirtToPhys(ptr) == 0)
+ {
+ A_I(dec_ref(),==,0);
+ return R_UP(0);
+ }
+ A_I(dec_ref(),==,0);
+#else
+ /* if emulating, we need to get through all allocated memory segments */
+ pthread_mutex_lock(&che_mutex);
+ init();
+
+ _AllocData *ad;
+ if (!ptr) return R_UP(0);
+ DLIST_MLOOP(bufs, ad, link) {
+ int ix;
+ struct tiler_buf_info *buf = (struct tiler_buf_info *) ad->buf.offset;
+ for (ix = 0; ix < buf->num_blocks; ix++)
+ {
+ if (ptr >= buf->blocks[ix].ptr &&
+ ptr < buf->blocks[ix].ptr + def_size(buf->blocks + ix))
+ {
+ bytes_t stride = buf->blocks[ix].stride;
+ pthread_mutex_unlock(&che_mutex);
+ return R_UP(stride);
+ }
+ }
+ }
+ pthread_mutex_unlock(&che_mutex);
+#endif
+ return R_UP(PAGE_SIZE);
+}
+
+bytes_t TilerMem_GetStride(SSPtr ssptr)
+{
+ IN;
+ switch(tiler_get_fmt(ssptr))
+ {
+ case TILFMT_8BIT: return R_UP(TILER_STRIDE_8BIT);
+ case TILFMT_16BIT: return R_UP(TILER_STRIDE_16BIT);
+ case TILFMT_32BIT: return R_UP(TILER_STRIDE_32BIT);
+ case TILFMT_PAGE: return R_UP(PAGE_SIZE);
+ default: return R_UP(0);
+ }
+}
+
+SSPtr TilerMem_VirtToPhys(void *ptr)
+{
+#ifndef STUB_TILER
+ SSPtr ssptr = 0;
+ if(!NOT_I(inc_ref(),==,0))
+ {
+ ssptr = ioctl(td, TILIOC_GSSP, (unsigned long) ptr);
+ A_I(dec_ref(),==,0);
+ }
+ return (SSPtr)R_P(ssptr);
+#else
+ return (SSPtr)ptr;
+#endif
+}
+
+/**
+ * Internal Unit Test. Tests the static methods of this
+ * library. Assumes an unitialized state as well.
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @return 0 for success, non-0 error value for failure.
+ */
+int __test__MemMgr()
+{
+ int ret = 0;
+
+ /* state check */
+ ret |= NOT_I(TILER_PAGE_WIDTH * TILER_PAGE_HEIGHT,==,PAGE_SIZE);
+ ret |= NOT_I(refCnt,==,0);
+ ret |= NOT_I(inc_ref(),==,0);
+ ret |= NOT_I(refCnt,==,1);
+ ret |= NOT_I(dec_ref(),==,0);
+ ret |= NOT_I(refCnt,==,0);
+
+ /* enumeration check */
+ ret |= NOT_I(PIXEL_FMT_8BIT,==,TILFMT_8BIT);
+ ret |= NOT_I(PIXEL_FMT_16BIT,==,TILFMT_16BIT);
+ ret |= NOT_I(PIXEL_FMT_32BIT,==,TILFMT_32BIT);
+ ret |= NOT_I(PIXEL_FMT_PAGE,==,TILFMT_PAGE);
+ ret |= NOT_I(sizeof(MemAllocBlock),==,sizeof(struct tiler_block_info));
+
+ /* void * arithmetic */
+ void *a = (void *)1000, *b = a + 2000, *c = (void *)3000;
+ ret |= NOT_P(b,==,c);
+
+ /* def_stride */
+ ret |= NOT_I(def_stride(0),==,0);
+ ret |= NOT_I(def_stride(1),==,PAGE_SIZE);
+ ret |= NOT_I(def_stride(PAGE_SIZE),==,PAGE_SIZE);
+ ret |= NOT_I(def_stride(PAGE_SIZE + 1),==,2 * PAGE_SIZE);
+
+ /* def_bpp */
+ ret |= NOT_I(def_bpp(PIXEL_FMT_32BIT),==,4);
+ ret |= NOT_I(def_bpp(PIXEL_FMT_16BIT),==,2);
+ ret |= NOT_I(def_bpp(PIXEL_FMT_8BIT),==,1);
+
+ /* def_size */
+ tiler_block_info blk = {0};
+ blk.fmt = TILFMT_8BIT;
+ blk.dim.area.width = PAGE_SIZE * 8 / 10;
+ blk.dim.area.height = 10;
+ ret |= NOT_I(def_size(&blk),==,10 * PAGE_SIZE);
+
+ blk.fmt = TILFMT_16BIT;
+ blk.dim.area.width = PAGE_SIZE * 7 / 10;
+ ret |= NOT_I(def_size(&blk),==,20 * PAGE_SIZE);
+ blk.dim.area.width = PAGE_SIZE * 4 / 10;
+ ret |= NOT_I(def_size(&blk),==,10 * PAGE_SIZE);
+
+ blk.fmt = TILFMT_32BIT;
+ ret |= NOT_I(def_size(&blk),==,20 * PAGE_SIZE);
+ blk.dim.area.width = PAGE_SIZE * 6 / 10;
+ ret |= NOT_I(def_size(&blk),==,30 * PAGE_SIZE);
+
+ return ret;
+}
+
diff --git a/tiler/memmgr.h b/tiler/memmgr.h
new file mode 100644
index 0000000..8f99904
--- /dev/null
+++ b/tiler/memmgr.h
@@ -0,0 +1,311 @@
+/*
+ * memmgr.h
+ *
+ * Memory Allocator Interface functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MEMMGR_H_
+#define _MEMMGR_H_
+
+/* retrieve type definitions */
+#include "mem_types.h"
+
+/**
+ * Memory Allocator is responsible for:
+ * <ol>
+ * <li>Allocate 1D and 2D blocks and pack them into a buffer.
+ * <li>Free such allocated blocks
+ * <li>Map 1D buffers into tiler space
+ * <li>Unmap 1D buffers from tiler space
+ * <li>Verify if an address lies in 1D or 2D space, whether it
+ * is mapped (to tiler space)
+ * <li>Mapping Ducati memory blocks to host processor and vice
+ * versa.
+ * </ol>
+ *
+ * The allocator distinguishes between:
+ * <ul>
+ * <li>1D and 2D blocks
+ * <li>2D blocks allocated by MemAlloc are non-cacheable. All
+ * other blocks are cacheable (e.g. 1D blocks). Preallocated
+ * may or may not be cacheable, depending on how they've been
+ * allocated, but are assumed to be cacheable.
+ * <li>buffers (an ordered collection of one or more blocks
+ * mapped consecutively)
+ * </ul>
+ *
+ * The allocator tracks each buffer based on (addr, size).
+ *
+ * Also, via the tiler manager, it tracks each block. The tiler
+ * manager itself also tracks each buffer.
+ *
+ */
+
+/**
+ * Memory Allocator block specification
+ *
+ * Size of a 2D buffer is calculated as height * stride. stride
+ * is the smallest multiple of page size that is at least
+ * the width, and is set by MemMgr_Alloc.
+ *
+ * Size of a 1D buffer is calculated as length. stride is not
+ * set by MemMgr_Alloc, but it can be set by the user. length
+ * must be a multiple of stride unless stride is 0.
+ *
+ * @author a0194118 (9/1/2009)
+ */
+struct MemAllocBlock {
+ pixel_fmt_t pixelFormat; /* pixel format */
+ union {
+ struct {
+ pixels_t width; /* width of 2D buffer */
+ pixels_t height; /* height of 2D buffer */
+ } area;
+ bytes_t len; /* length of 1D buffer. Must be multiple of
+ stride if stride is not 0. */
+ } dim;
+ uint32_t stride; /* must be multiple of page size. Can be 0 only
+ if pixelFormat is PIXEL_FMT_PAGE. */
+ void *ptr; /* pointer to beginning of buffer */
+ uint32_t id; /* buffer ID - received at allocation */
+ uint32_t key; /* buffer key - given at allocation */
+ uint32_t group_id; /* group ID */
+ /* alignment requirements for ssptr: ssptr & (align - 1) == offs */
+ uint32_t reserved; /* system space address (used internally) */
+};
+
+typedef struct MemAllocBlock MemAllocBlock;
+
+/**
+ * Returns the page size. This is required for allocating 1D
+ * blocks that stack under any other blocks.
+ *
+ * @author a0194118 (9/3/2009)
+ *
+ * @return Page size.
+ */
+bytes_t MemMgr_PageSize();
+
+/**
+ * Allocates a buffer as a list of blocks (1D or 2D), and maps
+ * them so that they are packaged consecutively. Returns the
+ * pointer to the first block, or NULL on failure.
+ * <p>
+ * The size of each block other than the last must be a multiple
+ * of the page size. This ensures that the blocks stack
+ * correctly. Set stride to 0 to avoid stride/length alignment
+ * constraints. Stride of 2D blocks will be updated by this
+ * method.
+ * <p>
+ * 2D blocks will be non-cacheable, while 1D blocks will be
+ * cacheable.
+ * <p>
+ * On success, the buffer is registered with the memory
+ * allocator.
+ * <p>
+ * As a side effect, if the operation was successful, the ssptr
+ * fields of the block specification will be filled with the
+ * system-space addresses, while the ptr fields will be set to
+ * the individual blocks. The stride information is set for 2D
+ * blocks.
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param blocks Block specification information. This
+ * should be an array of at least num_blocks
+ * elements.
+ * @param num_blocks Number of blocks to be included in the
+ * allocated memory segment
+ *
+ * @return Pointer to the buffer, which is also the pointer to
+ * the first allocated block. NULL if allocation failed.
+ */
+void *MemMgr_Alloc(MemAllocBlock blocks[], int num_blocks);
+
+/**
+ * Frees a buffer allocated by MemMgr_Alloc(). It fails for
+ * any buffer not allocated by MemMgr_Alloc() or one that has
+ * been already freed.
+ * <p>
+ * It also unregisters the buffer with the memory allocator.
+ * <p>
+ * This function unmaps the processor's virtual address to the
+ * tiler address for all blocks allocated, unregisters the
+ * buffer, and frees all of its tiler blocks.
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param bufPtr Pointer to the buffer allocated (returned)
+ * by MemMgr_Alloc()
+ *
+ * @return 0 on success. Non-0 error value on failure.
+ */
+int MemMgr_Free(void *bufPtr);
+
+/**
+ * This function maps the user provided data buffer to the tiler
+ * space as blocks, and maps that area into the process space
+ * consecutively. You can map a data buffer multiple times,
+ * resulting in multiple mapping for the same buffer. However,
+ * you cannot map a buffer that is already mapped to tiler, e.g.
+ * a buffer pointer returned by this method.
+ *
+ * In phase 1 and 2, the supported configurations are:
+ * <ol>
+ * <li> Mapping exactly one 1D block to tiler space (e.g.
+ * MapIn1DMode).
+ * </ol>
+ *
+ * @author a0194118 (9/3/2009)
+ *
+ * @param blocks Block specification information. This
+ * should be an array of at least num_blocks
+ * elements. The ptr fields must contain the
+ * user allocated buffers for the block.
+ * These will be updated with the mapped
+ * addresses of these blocks on success.
+ *
+ * Each block must be page aligned. Length of
+ * each block also must be page aligned.
+ *
+ * @param num_blocks Number of blocks to be included in the
+ * mapped memory segment
+ *
+ * @return Pointer to the buffer, which is also the pointer to
+ * the first mapped block. NULL if allocation failed.
+ */
+void *MemMgr_Map(MemAllocBlock blocks[], int num_blocks);
+
+/**
+ * This function unmaps the user provided data buffer from tiler
+ * space that was mapped to the tiler space in paged mode using
+ * MemMgr_Map(). It also unmaps the buffer itself from the
+ * process space. Trying to unmap a previously unmapped buffer
+ * will fail.
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param bufPtr Pointer to the buffer as returned by a
+ * previous call to MemMgr_MapIn1DMode()
+ *
+ * @return 0 on success. Non-0 error value on failure.
+ */
+int MemMgr_UnMap(void *bufPtr);
+
+/**
+ * Checks if a given virtual address is mapped by tiler manager
+ * to tiler space.
+ * <p>
+ * This function is equivalent to MemMgr_Is1DBuffer(ptr) ||
+ * MemMgr_Is2DBuffer(ptr). It retrieves the system space
+ * address that the virtual address maps to. If this system
+ * space address lies within the tiler area, the function
+ * returns TRUE.
+ *
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param ptr Pointer to a virtual address
+ *
+ * @return TRUE (non-0) if the virtual address is within a
+ * buffer that was mapped into tiler space, e.g. by
+ * calling MemMgr_MapIn1DMode() or MemMgr_MapIn2DMode()
+ */
+bool MemMgr_IsMapped(void *ptr);
+
+/**
+ * Checks if a given virtual address lies in a tiler 1D buffer.
+ * <p>
+ * This function retrieves the system space address that the
+ * virtual address maps to. If this system space address is
+ * within the 1D tiler area, it is considered lying within a 1D
+ * buffer.
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param ptr Pointer to a virtual address
+ *
+ * @return TRUE (non-0) if the virtual address is within a
+ * mapped 1D tiler buffer. FALSE (0) if the virtual
+ * address is not mapped, invalid, or is mapped to an
+ * area other than a 1D tiler buffer. In phase 1,
+ * however, it is TRUE it the virtual address is mapped
+ * to the page-mode area of the tiler space.
+ */
+bool MemMgr_Is1DBlock(void *ptr);
+
+/**
+ * Checks if a given virtual address lies in a 2D buffer.
+ * <p>
+ * This function retrieves the system space address that the
+ * virtual address maps to. If this system space address is
+ * within the 2D tiler area, it is considered lying within a 2D
+ * buffer.
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param ptr Pointer to a virtual address
+ *
+ * @return TRUE (non-0) if the virtual address is within a
+ * mapped 2D buffer. FALSE (0) if the virtual address
+ * is not mapped, invalid, or is mapped to an area other
+ * than a 2D buffer. In phase 1, however, it is TRUE it
+ * the virtual address is mapped to any area of the
+ * tiler space other than page mode.
+ */
+bool MemMgr_Is2DBlock(void *ptr);
+
+/**
+ * Returns the stride corresponding to a virtual address. For
+ * 1D and 2D buffers it returns the stride supplied
+ * with/acquired during the allocation/mapping. For non-tiler
+ * buffers it returns the page size.
+ * <p>
+ * NOTE: on Ducati phase 1, stride should return 16K for 8-bit
+ * 2D buffers, 32K for 16-bit and 32-bit 2D buffers, the stride
+ * used for alloc/map for 1D buffers, and the page size for
+ * non-tiler buffers.
+ *
+ * For unmapped addresses it returns 0. However, this cannot be
+ * used to determine if an address is unmapped as 1D buffers
+ * could also have 0 stride (e.g. compressed buffers).
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param ptr pointer to a virtual address
+ *
+ * @return The virtual stride of the block that contains the
+ * address.
+ */
+bytes_t MemMgr_GetStride(void *ptr);
+
+#endif
diff --git a/tiler/memmgr_test.c b/tiler/memmgr_test.c
new file mode 100644
index 0000000..2bb76b6
--- /dev/null
+++ b/tiler/memmgr_test.c
@@ -0,0 +1,1693 @@
+/*
+ * memmgr_test.c
+ *
+ * Memory Allocator Interface tests.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* retrieve type definitions */
+#define __DEBUG__
+#undef __DEBUG_ENTRY__
+#define __DEBUG_ASSERT__
+
+#define __MAP_OK__
+#undef __WRITE_IN_STRIDE__
+#undef STAR_TRACE_MEM
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+#include <utils.h>
+#include <list_utils.h>
+#include <debug_utils.h>
+#include <memmgr.h>
+#include <tilermem.h>
+#include <tilermem_utils.h>
+#include <testlib.h>
+
+/* for star_tiler_test */
+#include <fcntl.h> /* open() */
+#include <unistd.h> /* close() */
+#include <sys/ioctl.h> /* ioctl() */
+
+#define FALSE 0
+#define TESTERR_NOTIMPLEMENTED -65378
+
+#define MAX_ALLOCS 512
+
+#define TESTS\
+ T(alloc_1D_test(4096, 0))\
+ T(alloc_2D_test(64, 64, PIXEL_FMT_8BIT))\
+ T(alloc_2D_test(64, 64, PIXEL_FMT_16BIT))\
+ T(alloc_2D_test(64, 64, PIXEL_FMT_32BIT))\
+ T(alloc_NV12_test(64, 64))\
+ T(map_1D_test(4096, 0))\
+ T(alloc_1D_test(176 * 144 * 2, 0))\
+ T(alloc_2D_test(176, 144, PIXEL_FMT_8BIT))\
+ T(alloc_2D_test(176, 144, PIXEL_FMT_16BIT))\
+ T(alloc_2D_test(176, 144, PIXEL_FMT_32BIT))\
+ T(alloc_NV12_test(176, 144))\
+ T(map_1D_test(176 * 144 * 2, 0))\
+ T(alloc_1D_test(640 * 480 * 2, 0))\
+ T(alloc_2D_test(640, 480, PIXEL_FMT_8BIT))\
+ T(alloc_2D_test(640, 480, PIXEL_FMT_16BIT))\
+ T(alloc_2D_test(640, 480, PIXEL_FMT_32BIT))\
+ T(alloc_NV12_test(640, 480))\
+ T(map_1D_test(640 * 480 * 2, 0))\
+ T(alloc_1D_test(848 * 480 * 2, 0))\
+ T(alloc_2D_test(848, 480, PIXEL_FMT_8BIT))\
+ T(alloc_2D_test(848, 480, PIXEL_FMT_16BIT))\
+ T(alloc_2D_test(848, 480, PIXEL_FMT_32BIT))\
+ T(alloc_NV12_test(848, 480))\
+ T(map_1D_test(848 * 480 * 2, 0))\
+ T(alloc_1D_test(1280 * 720 * 2, 0))\
+ T(alloc_2D_test(1280, 720, PIXEL_FMT_8BIT))\
+ T(alloc_2D_test(1280, 720, PIXEL_FMT_16BIT))\
+ T(alloc_2D_test(1280, 720, PIXEL_FMT_32BIT))\
+ T(alloc_NV12_test(1280, 720))\
+ T(map_1D_test(1280 * 720 * 2, 0))\
+ T(alloc_1D_test(1920 * 1080 * 2, 0))\
+ T(alloc_2D_test(1920, 1080, PIXEL_FMT_8BIT))\
+ T(alloc_2D_test(1920, 1080, PIXEL_FMT_16BIT))\
+ T(alloc_2D_test(1920, 1080, PIXEL_FMT_32BIT))\
+ T(alloc_NV12_test(1920, 1080))\
+ T(map_1D_test(1920 * 1080 * 2, 0))\
+ T(map_1D_test(4096, 0))\
+ T(map_1D_test(8192, 0))\
+ T(map_1D_test(16384, 0))\
+ T(map_1D_test(32768, 0))\
+ T(map_1D_test(65536, 0))\
+ T(neg_alloc_tests())\
+ T(neg_free_tests())\
+ T(neg_map_tests())\
+ T(neg_unmap_tests())\
+ T(neg_check_tests())\
+ T(page_size_test())\
+ T(maxalloc_2D_test(2500, 32, PIXEL_FMT_8BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(2500, 16, PIXEL_FMT_16BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(1250, 16, PIXEL_FMT_32BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(5000, 32, PIXEL_FMT_8BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(5000, 16, PIXEL_FMT_16BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(2500, 16, PIXEL_FMT_32BIT, MAX_ALLOCS))\
+ T(alloc_2D_test(8193, 16, PIXEL_FMT_8BIT))\
+ T(alloc_2D_test(8193, 16, PIXEL_FMT_16BIT))\
+ T(alloc_2D_test(4097, 16, PIXEL_FMT_32BIT))\
+ T(alloc_2D_test(16384, 16, PIXEL_FMT_8BIT))\
+ T(alloc_2D_test(16384, 16, PIXEL_FMT_16BIT))\
+ T(alloc_2D_test(8192, 16, PIXEL_FMT_32BIT))\
+ T(!alloc_2D_test(16385, 16, PIXEL_FMT_8BIT))\
+ T(!alloc_2D_test(16385, 16, PIXEL_FMT_16BIT))\
+ T(!alloc_2D_test(8193, 16, PIXEL_FMT_32BIT))\
+ T(maxalloc_1D_test(4096, MAX_ALLOCS))\
+ T(maxalloc_2D_test(64, 64, PIXEL_FMT_8BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(64, 64, PIXEL_FMT_16BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(64, 64, PIXEL_FMT_32BIT, MAX_ALLOCS))\
+ T(maxalloc_NV12_test(64, 64, MAX_ALLOCS))\
+ T(maxmap_1D_test(4096, MAX_ALLOCS))\
+ T(maxalloc_1D_test(176 * 144 * 2, MAX_ALLOCS))\
+ T(maxalloc_2D_test(176, 144, PIXEL_FMT_8BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(176, 144, PIXEL_FMT_16BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(176, 144, PIXEL_FMT_32BIT, MAX_ALLOCS))\
+ T(maxalloc_NV12_test(176, 144, MAX_ALLOCS))\
+ T(maxmap_1D_test(176 * 144 * 2, MAX_ALLOCS))\
+ T(maxalloc_1D_test(640 * 480 * 2, MAX_ALLOCS))\
+ T(maxalloc_2D_test(640, 480, PIXEL_FMT_8BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(640, 480, PIXEL_FMT_16BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(640, 480, PIXEL_FMT_32BIT, MAX_ALLOCS))\
+ T(maxalloc_NV12_test(640, 480, MAX_ALLOCS))\
+ T(maxmap_1D_test(640 * 480 * 2, MAX_ALLOCS))\
+ T(maxalloc_1D_test(848 * 480 * 2, MAX_ALLOCS))\
+ T(maxalloc_2D_test(848, 480, PIXEL_FMT_8BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(848, 480, PIXEL_FMT_16BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(848, 480, PIXEL_FMT_32BIT, MAX_ALLOCS))\
+ T(maxalloc_NV12_test(848, 480, MAX_ALLOCS))\
+ T(maxmap_1D_test(848 * 480 * 2, MAX_ALLOCS))\
+ T(maxalloc_1D_test(1280 * 720 * 2, MAX_ALLOCS))\
+ T(maxalloc_2D_test(1280, 720, PIXEL_FMT_8BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(1280, 720, PIXEL_FMT_16BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(1280, 720, PIXEL_FMT_32BIT, MAX_ALLOCS))\
+ T(maxalloc_NV12_test(1280, 720, MAX_ALLOCS))\
+ T(maxmap_1D_test(1280 * 720 * 2, MAX_ALLOCS))\
+ T(maxalloc_1D_test(1920 * 1080 * 2, MAX_ALLOCS))\
+ T(maxalloc_2D_test(1920, 1080, PIXEL_FMT_8BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(1920, 1080, PIXEL_FMT_16BIT, MAX_ALLOCS))\
+ T(maxalloc_2D_test(1920, 1080, PIXEL_FMT_32BIT, MAX_ALLOCS))\
+ T(maxalloc_NV12_test(1920, 1080, 2))\
+ T(maxalloc_NV12_test(1920, 1080, MAX_ALLOCS))\
+ T(maxmap_1D_test(1920 * 1080 * 2, MAX_ALLOCS))\
+ T(star_tiler_test(1000, 10))\
+ T(star_tiler_test(1000, 30))\
+ T(star_test(100, 10))\
+ T(star_test(1000, 10))\
+
+/* this is defined in memmgr.c, but not exported as it is for internal
+ use only */
+extern int __test__MemMgr();
+
+/**
+ * Returns the default page stride for this block
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @param width Width of 2D container
+ *
+ * @return Stride
+ */
+static bytes_t def_stride(bytes_t width)
+{
+ return ROUND_UP_TO2POW(width, PAGE_SIZE);
+}
+
+/**
+ * Returns the bytes per pixel for the pixel format.
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @param pixelFormat Pixelformat
+ *
+ * @return Bytes per pixel
+ */
+static bytes_t def_bpp(pixel_fmt_t pixelFormat)
+{
+ return (pixelFormat == PIXEL_FMT_32BIT ? 4 :
+ pixelFormat == PIXEL_FMT_16BIT ? 2 : 1);
+}
+
+/**
+ * This method fills up a range of memory using a start address
+ * and start value. The method of filling ensures that
+ * accidentally overlapping regions have minimal chances of
+ * matching, even if the same starting value is used. This is
+ * because the difference between successive values varies as
+ * such. This series only repeats after 704189 values, so the
+ * probability of a match for a range of at least 2 values is
+ * less than 2*10^-11.
+ *
+ * V(i + 1) - V(i) = { 1, 2, 3, ..., 65535, 2, 4, 6, 8 ...,
+ * 65534, 3, 6, 9, 12, ..., 4, 8, 12, 16, ... }
+ *
+ * @author a0194118 (9/6/2009)
+ *
+ * @param start start value
+ * @param block pointer to block info strucure
+ */
+void fill_mem(uint16_t start, MemAllocBlock *block)
+{
+ IN;
+ uint16_t *ptr = (uint16_t *)block->ptr, delta = 1, step = 1;
+ bytes_t height, width, stride, i;
+ if (block->pixelFormat == PIXEL_FMT_PAGE)
+ {
+ height = 1;
+ stride = width = block->dim.len;
+ }
+ else
+ {
+ height = block->dim.area.height;
+ width = block->dim.area.width;
+ stride = block->stride;
+ }
+ width *= def_bpp(block->pixelFormat);
+ bytes_t size = height * stride;
+
+ P("(%p,0x%x*0x%x,s=0x%x)=0x%x", block->ptr, width, height, stride, start);
+
+ CHK_I(width,<=,stride);
+ uint32_t *ptr32 = (uint32_t *)ptr;
+ while (height--)
+ {
+ if (block->pixelFormat == PIXEL_FMT_32BIT)
+ {
+ for (i = 0; i < width; i += sizeof(uint32_t))
+ {
+ uint32_t val = (start & 0xFFFF) | (((uint32_t)(start + delta) & 0xFFFF) << 16);
+ *ptr32++ = val;
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ }
+#ifdef __WRITE_IN_STRIDE__
+ while (i < stride && (height || ((PAGE_SIZE - 1) & (uint32_t)ptr32)))
+ {
+ *ptr32++ = 0;
+ i += sizeof(uint32_t);
+ }
+#else
+ ptr32 += (stride - i) / sizeof(uint32_t);
+#endif
+ }
+ else
+ {
+ for (i = 0; i < width; i += sizeof(uint16_t))
+ {
+ *ptr++ = start;
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ }
+#ifdef __WRITE_IN_STRIDE__
+ while (i < stride && (height || ((PAGE_SIZE - 1) & (uint32_t)ptr)))
+ {
+ *ptr++ = 0;
+ i += sizeof(uint16_t);
+ }
+#else
+ ptr += (stride - i) / sizeof(uint16_t);
+#endif
+
+ }
+ }
+ CHK_P((block->pixelFormat == PIXEL_FMT_32BIT ? (void *)ptr32 : (void *)ptr),==,
+ (block->ptr + size));
+ OUT;
+}
+
+/**
+ * This verifies if a range of memory at a given address was
+ * filled up using the start value.
+ *
+ * @author a0194118 (9/6/2009)
+ *
+ * @param start start value
+ * @param block pointer to block info strucure
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int check_mem(uint16_t start, MemAllocBlock *block)
+{
+ IN;
+ uint16_t *ptr = (uint16_t *)block->ptr, delta = 1, step = 1;
+ bytes_t height, width, stride, r, i;
+ if (block->pixelFormat == PIXEL_FMT_PAGE)
+ {
+ height = 1;
+ stride = width = block->dim.len;
+ }
+ else
+ {
+ height = block->dim.area.height;
+ width = block->dim.area.width;
+ stride = block->stride;
+ }
+ width *= def_bpp(block->pixelFormat);
+
+ CHK_I(width,<=,stride);
+ uint32_t *ptr32 = (uint32_t *)ptr;
+ for (r = 0; r < height; r++)
+ {
+ if (block->pixelFormat == PIXEL_FMT_32BIT)
+ {
+ for (i = 0; i < width; i += sizeof(uint32_t))
+ {
+ uint32_t val = (start & 0xFFFF) | (((uint32_t)(start + delta) & 0xFFFF) << 16);
+ if (*ptr32++ != val) {
+ DP("assert: val[%u,%u] (=0x%x) != 0x%x", r, i, *--ptr32, val);
+ return R_I(MEMMGR_ERR_GENERIC);
+ }
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ }
+#ifdef __WRITE_IN_STRIDE__
+ while (i < stride && ((r < height - 1) || ((PAGE_SIZE - 1) & (uint32_t)ptr32)))
+ {
+ if (*ptr32++) {
+ DP("assert: val[%u,%u] (=0x%x) != 0", r, i, *--ptr32);
+ return R_I(MEMMGR_ERR_GENERIC);
+ }
+ i += sizeof(uint32_t);
+ }
+#else
+ ptr32 += (stride - i) / sizeof(uint32_t);
+#endif
+ }
+ else
+ {
+ for (i = 0; i < width; i += sizeof(uint16_t))
+ {
+ if (*ptr++ != start) {
+ DP("assert: val[%u,%u] (=0x%x) != 0x%x", r, i, *--ptr, start);
+ return R_I(MEMMGR_ERR_GENERIC);
+ }
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ }
+#ifdef __WRITE_IN_STRIDE__
+ while (i < stride && ((r < height - 1) || ((PAGE_SIZE - 1) & (uint32_t)ptr)))
+ {
+ if (*ptr++) {
+ DP("assert: val[%u,%u] (=0x%x) != 0", r, i, *--ptr);
+ return R_I(MEMMGR_ERR_GENERIC);
+ }
+ i += sizeof(uint16_t);
+ }
+#else
+ ptr += (stride - i) / sizeof(uint16_t);
+#endif
+ }
+ }
+ return R_I(MEMMGR_ERR_NONE);
+}
+
+/**
+ * This method allocates a 1D tiled buffer of the given length
+ * and stride using MemMgr_Alloc. If successful, it checks
+ * that the block information was updated with the pointer to
+ * the block. Additionally, it verifies the correct return
+ * values for MemMgr_IsMapped, MemMgr_Is1DBlock,
+ * MemMgr_Is2DBlock, MemMgr_GetStride, TilerMem_GetStride. It
+ * also verifies TilerMem_VirtToPhys using an internally stored
+ * value of the ssptr. If any of these verifications fail, the
+ * buffer is freed. Otherwise, it is filled using the given
+ * start value.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param length Buffer length
+ * @param stride Buffer stride
+ * @param val Fill start value
+ *
+ * @return pointer to the allocated buffer, or NULL on failure
+ */
+void *alloc_1D(bytes_t length, bytes_t stride, uint16_t val)
+{
+ MemAllocBlock block;
+ memset(&block, 0, sizeof(block));
+
+ block.pixelFormat = PIXEL_FMT_PAGE;
+ block.dim.len = length;
+ block.stride = stride;
+
+ void *bufPtr = MemMgr_Alloc(&block, 1);
+ CHK_P(bufPtr,==,block.ptr);
+ if (bufPtr) {
+ if (NOT_I(MemMgr_IsMapped(bufPtr),!=,0) ||
+ NOT_I(MemMgr_Is1DBlock(bufPtr),!=,0) ||
+ NOT_I(MemMgr_Is2DBlock(bufPtr),==,0) ||
+ NOT_I(MemMgr_GetStride(bufPtr),==,block.stride) ||
+ NOT_P(TilerMem_VirtToPhys(bufPtr),==,block.reserved) ||
+ NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys(bufPtr)),==,PAGE_SIZE) ||
+ NOT_L((PAGE_SIZE - 1) & (long)bufPtr,==,(PAGE_SIZE - 1) & block.reserved))
+ {
+ MemMgr_Free(bufPtr);
+ return NULL;
+ }
+ fill_mem(val, &block);
+ }
+ return bufPtr;
+}
+
+/**
+ * This method frees a 1D tiled buffer. The given length,
+ * stride and start values are used to verify that the buffer is
+ * still correctly filled. In the event of any errors, the
+ * error value is returned.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param length Buffer length
+ * @param stride Buffer stride
+ * @param val Fill start value
+ * @param bufPtr Pointer to the allocated buffer
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int free_1D(bytes_t length, bytes_t stride, uint16_t val, void *bufPtr)
+{
+ MemAllocBlock block;
+ memset(&block, 0, sizeof(block));
+
+ block.pixelFormat = PIXEL_FMT_PAGE;
+ block.dim.len = length;
+ block.stride = stride;
+ block.ptr = bufPtr;
+
+ int ret = A_I(check_mem(val, &block),==,0);
+ ERR_ADD(ret, MemMgr_Free(bufPtr));
+ return ret;
+}
+
+/**
+ * This method allocates a 2D tiled buffer of the given width,
+ * height, stride and pixel format using
+ * MemMgr_Alloc. If successful, it checks that the block
+ * information was updated with the pointer to the block.
+ * Additionally, it verifies the correct return values for
+ * MemMgr_IsMapped, MemMgr_Is1DBlock, MemMgr_Is2DBlock,
+ * MemMgr_GetStride, TilerMem_GetStride. It also verifies
+ * TilerMem_VirtToPhys using an internally stored value of the
+ * ssptr. If any of these verifications fail, the buffer is
+ * freed. Otherwise, it is filled using the given start value.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param width Buffer width
+ * @param height Buffer height
+ * @param fmt Pixel format
+ * @param stride Buffer stride
+ * @param val Fill start value
+ *
+ * @return pointer to the allocated buffer, or NULL on failure
+ */
+void *alloc_2D(pixels_t width, pixels_t height, pixel_fmt_t fmt, bytes_t stride,
+ uint16_t val)
+{
+ MemAllocBlock block;
+ memset(&block, 0, sizeof(block));
+
+ block.pixelFormat = fmt;
+ block.dim.area.width = width;
+ block.dim.area.height = height;
+ block.stride = stride;
+
+ void *bufPtr = MemMgr_Alloc(&block, 1);
+ CHK_P(bufPtr,==,block.ptr);
+ if (bufPtr) {
+ bytes_t cstride = (fmt == PIXEL_FMT_8BIT ? TILER_STRIDE_8BIT :
+ fmt == PIXEL_FMT_16BIT ? TILER_STRIDE_16BIT :
+ TILER_STRIDE_32BIT);
+
+ if (NOT_I(MemMgr_IsMapped(bufPtr),!=,0) ||
+ NOT_I(MemMgr_Is1DBlock(bufPtr),==,0) ||
+ NOT_I(MemMgr_Is2DBlock(bufPtr),!=,0) ||
+ NOT_I(block.stride,!=,0) ||
+ NOT_I(MemMgr_GetStride(bufPtr),==,block.stride) ||
+ NOT_P(TilerMem_VirtToPhys(bufPtr),==,block.reserved) ||
+ NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys(bufPtr)),==,cstride) ||
+ NOT_L((PAGE_SIZE - 1) & (long)bufPtr,==,(PAGE_SIZE - 1) & block.reserved))
+ {
+ MemMgr_Free(bufPtr);
+ return NULL;
+ }
+ fill_mem(val, &block);
+ }
+ return bufPtr;
+}
+
+/**
+ * This method frees a 2D tiled buffer. The given width,
+ * height, pixel format, stride and start values are used to
+ * verify that the buffer is still correctly filled. In the
+ * event of any errors, the error value is returned.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param width Buffer width
+ * @param height Buffer height
+ * @param fmt Pixel format
+ * @param stride Buffer stride
+ * @param val Fill start value
+ * @param bufPtr Pointer to the allocated buffer
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int free_2D(pixels_t width, pixels_t height, pixel_fmt_t fmt, bytes_t stride,
+ uint16_t val, void *bufPtr)
+{
+ MemAllocBlock block;
+ memset(&block, 0, sizeof(block));
+
+ block.pixelFormat = fmt;
+ block.dim.area.width = width;
+ block.dim.area.height = height;
+ block.stride = def_stride(width * def_bpp(fmt));
+ block.ptr = bufPtr;
+
+ int ret = A_I(check_mem(val, &block),==,0);
+ ERR_ADD(ret, MemMgr_Free(bufPtr));
+ return ret;
+}
+
+/**
+ * This method allocates an NV12 tiled buffer of the given width
+ * and height using MemMgr_Alloc. If successful, it checks that
+ * the block informations were updated with the pointers to the
+ * individual blocks. Additionally, it verifies the correct
+ * return values for MemMgr_IsMapped, MemMgr_Is1DBlock,
+ * MemMgr_Is2DBlock, MemMgr_GetStride, TilerMem_GetStride for
+ * both blocks. It also verifies TilerMem_VirtToPhys using an
+ * internally stored values of the ssptr. If any of these
+ * verifications fail, the buffer is freed. Otherwise, it is
+ * filled using the given start value.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param width Buffer width
+ * @param height Buffer height
+ * @param val Fill start value
+ *
+ * @return pointer to the allocated buffer, or NULL on failure
+ */
+void *alloc_NV12(pixels_t width, pixels_t height, uint16_t val)
+{
+ MemAllocBlock blocks[2];
+ ZERO(blocks);
+
+ blocks[0].pixelFormat = PIXEL_FMT_8BIT;
+ blocks[0].dim.area.width = width;
+ blocks[0].dim.area.height = height;
+ blocks[1].pixelFormat = PIXEL_FMT_16BIT;
+ blocks[1].dim.area.width = width >> 1;
+ blocks[1].dim.area.height = height >> 1;
+
+ void *bufPtr = MemMgr_Alloc(blocks, 2);
+ CHK_P(blocks[0].ptr,==,bufPtr);
+ if (bufPtr) {
+ void *buf2 = bufPtr + blocks[0].stride * height;
+ if (NOT_P(blocks[1].ptr,==,buf2) ||
+ NOT_I(MemMgr_IsMapped(bufPtr),!=,0) ||
+ NOT_I(MemMgr_IsMapped(buf2),!=,0) ||
+ NOT_I(MemMgr_Is1DBlock(bufPtr),==,0) ||
+ NOT_I(MemMgr_Is1DBlock(buf2),==,0) ||
+ NOT_I(MemMgr_Is2DBlock(bufPtr),!=,0) ||
+ NOT_I(MemMgr_Is2DBlock(buf2),!=,0) ||
+ NOT_I(blocks[0].stride,!=,0) ||
+ NOT_I(blocks[1].stride,!=,0) ||
+ NOT_I(MemMgr_GetStride(bufPtr),==,blocks[0].stride) ||
+ NOT_I(MemMgr_GetStride(buf2),==,blocks[1].stride) ||
+ NOT_P(TilerMem_VirtToPhys(bufPtr),==,blocks[0].reserved) ||
+ NOT_P(TilerMem_VirtToPhys(buf2),==,blocks[1].reserved) ||
+ NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys(bufPtr)),==,TILER_STRIDE_8BIT) ||
+ NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys(buf2)),==,TILER_STRIDE_16BIT) ||
+ NOT_L((PAGE_SIZE - 1) & (long)blocks[0].ptr,==,(PAGE_SIZE - 1) & blocks[0].reserved) ||
+ NOT_L((PAGE_SIZE - 1) & (long)blocks[1].ptr,==,(PAGE_SIZE - 1) & blocks[1].reserved))
+ {
+ MemMgr_Free(bufPtr);
+ return NULL;
+ }
+
+ fill_mem(val, blocks);
+ fill_mem(val, blocks + 1);
+ } else {
+ CHK_P(blocks[1].ptr,==,NULL);
+ }
+
+ return bufPtr;
+}
+
+/**
+ * This method frees an NV12 tiled buffer. The given width,
+ * height and start values are used to verify that the buffer is
+ * still correctly filled. In the event of any errors, the
+ * error value is returned.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param width Buffer width
+ * @param height Buffer height
+ * @param val Fill start value
+ * @param bufPtr Pointer to the allocated buffer
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int free_NV12(pixels_t width, pixels_t height, uint16_t val, void *bufPtr)
+{
+ MemAllocBlock blocks[2];
+ memset(blocks, 0, sizeof(blocks));
+
+ blocks[0].pixelFormat = PIXEL_FMT_8BIT;
+ blocks[0].dim.area.width = width;
+ blocks[0].dim.area.height = height;
+ blocks[0].stride = def_stride(width);
+ blocks[0].ptr = bufPtr;
+ blocks[1].pixelFormat = PIXEL_FMT_16BIT;
+ blocks[1].dim.area.width = width >> 1;
+ blocks[1].dim.area.height = height >> 1;
+ blocks[1].stride = def_stride(width);
+ blocks[1].ptr = bufPtr + blocks[0].stride * height;
+
+ int ret = A_I(check_mem(val, blocks),==,0);
+ ERR_ADD(ret, check_mem(val, blocks + 1));
+ ERR_ADD(ret, MemMgr_Free(bufPtr));
+ return ret;
+}
+
+/**
+ * This method maps a preallocated 1D buffer of the given length
+ * and stride into tiler space using MemMgr_Map. The mapped
+ * address must differ from the supplied address is successful.
+ * Moreover, it checks that the block information was
+ * updated with the pointer to the block. Additionally, it
+ * verifies the correct return values for MemMgr_IsMapped,
+ * MemMgr_Is1DBlock, MemMgr_Is2DBlock, MemMgr_GetStride,
+ * TilerMem_GetStride. It also verifies TilerMem_VirtToPhys
+ * using an internally stored value of the ssptr. If any of
+ * these verifications fail, the buffer is unmapped. Otherwise,
+ * the original buffer is filled using the given start value.
+ *
+ * :TODO: how do we verify the mapping?
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param dataPtr Pointer to the allocated buffer
+ * @param length Buffer length
+ * @param stride Buffer stride
+ * @param val Fill start value
+ *
+ * @return pointer to the mapped buffer, or NULL on failure
+ */
+void *map_1D(void *dataPtr, bytes_t length, bytes_t stride, uint16_t val)
+{
+ MemAllocBlock block;
+ memset(&block, 0, sizeof(block));
+
+ block.pixelFormat = PIXEL_FMT_PAGE;
+ block.dim.len = length;
+ block.stride = stride;
+ block.ptr = dataPtr;
+
+ void *bufPtr = MemMgr_Map(&block, 1);
+ CHK_P(bufPtr,==,block.ptr);
+ if (bufPtr) {
+ if (NOT_P(bufPtr,!=,dataPtr) ||
+ NOT_I(MemMgr_IsMapped(bufPtr),!=,0) ||
+ NOT_I(MemMgr_Is1DBlock(bufPtr),!=,0) ||
+ NOT_I(MemMgr_Is2DBlock(bufPtr),==,0) ||
+ NOT_I(MemMgr_GetStride(bufPtr),==,block.stride) ||
+ NOT_P(TilerMem_VirtToPhys(bufPtr),==,block.reserved) ||
+ NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys(bufPtr)),==,PAGE_SIZE) ||
+ NOT_L((PAGE_SIZE - 1) & (long)bufPtr,==,0) ||
+ NOT_L((PAGE_SIZE - 1) & block.reserved,==,0))
+ {
+ MemMgr_UnMap(bufPtr);
+ return NULL;
+ }
+ block.ptr = dataPtr;
+ fill_mem(val, &block);
+ }
+ return bufPtr;
+}
+
+/**
+ * This method unmaps a 1D tiled buffer. The given data
+ * pointer, length, stride and start values are used to verify
+ * that the buffer is still correctly filled. In the event of
+ * any errors, the error value is returned.
+ *
+ * :TODO: how do we verify the mapping?
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param dataPtr Pointer to the preallocated buffer
+ * @param length Buffer length
+ * @param stride Buffer stride
+ * @param val Fill start value
+ * @param bufPtr Pointer to the mapped buffer
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int unmap_1D(void *dataPtr, bytes_t length, bytes_t stride, uint16_t val, void *bufPtr)
+{
+ MemAllocBlock block;
+ memset(&block, 0, sizeof(block));
+
+ block.pixelFormat = PIXEL_FMT_PAGE;
+ block.dim.len = length;
+ block.stride = stride;
+ block.ptr = dataPtr;
+ int ret = A_I(check_mem(val, &block),==,0);
+ ERR_ADD(ret, MemMgr_UnMap(bufPtr));
+ return ret;
+}
+
+/**
+ * Tests the MemMgr_PageSize method.
+ *
+ * @author a0194118 (9/15/2009)
+ *
+ * @return 0 on success, non-0 error value on failure.
+ */
+int page_size_test()
+{
+ return NOT_I(MemMgr_PageSize(),==,PAGE_SIZE);
+}
+
+/**
+ * This method tests the allocation and freeing of a 1D tiled
+ * buffer.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param length Buffer length
+ * @param stride Buffer stride
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int alloc_1D_test(bytes_t length, bytes_t stride)
+{
+ printf("Allocate & Free %ub 1D buffer\n", length);
+
+ uint16_t val = (uint16_t) rand();
+ void *ptr = alloc_1D(length, stride, val);
+ if (!ptr) return 1;
+ int res = free_1D(length, stride, val, ptr);
+ return res;
+}
+
+/**
+ * This method tests the allocation and freeing of a 2D tiled
+ * buffer.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param width Buffer width
+ * @param height Buffer height
+ * @param fmt Pixel format
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int alloc_2D_test(pixels_t width, pixels_t height, pixel_fmt_t fmt)
+{
+ printf("Allocate & Free %ux%ux%ub 1D buffer\n", width, height, def_bpp(fmt));
+
+ uint16_t val = (uint16_t) rand();
+ void *ptr = alloc_2D(width, height, fmt, 0, val);
+ if (!ptr) return 1;
+ int res = free_2D(width, height, fmt, 0, val, ptr);
+ return res;
+}
+
+/**
+ * This method tests the allocation and freeing of an NV12 tiled
+ * buffer.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param width Buffer width
+ * @param height Buffer height
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int alloc_NV12_test(pixels_t width, pixels_t height)
+{
+ printf("Allocate & Free %ux%u NV12 buffer\n", width, height);
+
+ uint16_t val = (uint16_t) rand();
+ void *ptr = alloc_NV12(width, height, val);
+ if (!ptr) return 1;
+ int res = free_NV12(width, height, val, ptr);
+ return res;
+}
+
+/**
+ * This method tests the mapping and unmapping of a 1D buffer.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param length Buffer length
+ * @param stride Buffer stride
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int map_1D_test(bytes_t length, bytes_t stride)
+{
+ length = (length + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1);
+ printf("Mapping and UnMapping 0x%xb 1D buffer\n", length);
+
+#ifdef __MAP_OK__
+ /* allocate aligned buffer */
+ void *buffer = malloc(length + PAGE_SIZE - 1);
+ void *dataPtr = (void *)(((uint32_t)buffer + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
+ uint16_t val = (uint16_t) rand();
+ void *ptr = map_1D(dataPtr, length, stride, val);
+ if (!ptr) return 1;
+ int res = unmap_1D(dataPtr, length, stride, val, ptr);
+ FREE(buffer);
+#else
+ int res = TESTERR_NOTIMPLEMENTED;
+#endif
+ return res;
+}
+
+/**
+ * This method tests the allocation and freeing of a number of
+ * 1D tiled buffers (up to MAX_ALLOCS)
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param length Buffer length
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int maxalloc_1D_test(bytes_t length, int max_allocs)
+{
+ printf("Allocate & Free max # of %ub 1D buffers\n", length);
+
+ struct data {
+ uint16_t val;
+ void *bufPtr;
+ } *mem;
+
+ /* allocate as many buffers as we can */
+ mem = NEWN(struct data, max_allocs);
+ void *ptr = (void *)mem;
+ int ix, res = 0;
+ for (ix = 0; ptr && ix < max_allocs;)
+ {
+ uint16_t val = (uint16_t) rand();
+ ptr = alloc_1D(length, 0, val);
+ if (ptr)
+ {
+ mem[ix].val = val;
+ mem[ix].bufPtr = ptr;
+ ix++;
+ }
+ }
+
+ P(":: Allocated %d buffers", ix);
+
+ while (ix--)
+ {
+ ERR_ADD(res, free_1D(length, 0, mem[ix].val, mem[ix].bufPtr));
+ }
+ FREE(mem);
+ return res;
+}
+
+/**
+ * This method tests the allocation and freeing of a number of
+ * 2D tiled buffers (up to MAX_ALLOCS)
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param width Buffer width
+ * @param height Buffer height
+ * @param fmt Pixel format
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int maxalloc_2D_test(pixels_t width, pixels_t height, pixel_fmt_t fmt, int max_allocs)
+{
+ printf("Allocate & Free max # of %ux%ux%ub 1D buffers\n", width, height, def_bpp(fmt));
+
+ struct data {
+ uint16_t val;
+ void *bufPtr;
+ } *mem;
+
+ /* allocate as many buffers as we can */
+ mem = NEWN(struct data, max_allocs);
+ void *ptr = (void *)mem;
+ int ix, res = 0;
+ for (ix = 0; ptr && ix < max_allocs;)
+ {
+ uint16_t val = (uint16_t) rand();
+ ptr = alloc_2D(width, height, fmt, 0, val);
+ if (ptr)
+ {
+ mem[ix].val = val;
+ mem[ix].bufPtr = ptr;
+ ix++;
+ }
+ }
+
+ P(":: Allocated %d buffers", ix);
+
+ while (ix--)
+ {
+ ERR_ADD(res, free_2D(width, height, fmt, 0, mem[ix].val, mem[ix].bufPtr));
+ }
+ FREE(mem);
+ return res;
+}
+
+/**
+ * This method tests the allocation and freeing of a number of
+ * NV12 tiled buffers (up to MAX_ALLOCS)
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param width Buffer width
+ * @param height Buffer height
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int maxalloc_NV12_test(pixels_t width, pixels_t height, int max_allocs)
+{
+ printf("Allocate & Free max # of %ux%u NV12 buffers\n", width, height);
+
+ struct data {
+ uint16_t val;
+ void *bufPtr;
+ } *mem;
+
+ /* allocate as many buffers as we can */
+ mem = NEWN(struct data, max_allocs);
+ void *ptr = (void *)mem;
+ int ix, res = 0;
+ for (ix = 0; ptr && ix < max_allocs;)
+ {
+ uint16_t val = (uint16_t) rand();
+ ptr = alloc_NV12(width, height, val);
+ if (ptr)
+ {
+ mem[ix].val = val;
+ mem[ix].bufPtr = ptr;
+ ix++;
+ }
+ }
+
+ P(":: Allocated %d buffers", ix);
+
+ while (ix--)
+ {
+ ERR_ADD(res, free_NV12(width, height, mem[ix].val, mem[ix].bufPtr));
+ }
+ FREE(mem);
+ return res;
+}
+
+/**
+ * This method tests the mapping and unnapping of a number of
+ * 1D buffers (up to MAX_ALLOCS)
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param length Buffer length
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int maxmap_1D_test(bytes_t length, int max_maps)
+{
+ length = (length + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1);
+ printf("Map & UnMap max # of %xb 1D buffers\n", length);
+
+#ifdef __MAP_OK__
+ struct data {
+ uint16_t val;
+ void *bufPtr, *buffer, *dataPtr;
+ } *mem;
+
+ /* map as many buffers as we can */
+ mem = NEWN(struct data, max_maps);
+ void *ptr = (void *)mem;
+ int ix, res = 0;
+ for (ix = 0; ptr && ix < max_maps;)
+ {
+ /* allocate aligned buffer */
+ ptr = malloc(length + PAGE_SIZE - 1);
+ if (ptr)
+ {
+ void *buffer = ptr;
+ void *dataPtr = (void *)(((uint32_t)buffer + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
+ uint16_t val = (uint16_t) rand();
+ ptr = map_1D(dataPtr, length, 0, val);
+ if (ptr)
+ {
+ mem[ix].val = val;
+ mem[ix].bufPtr = ptr;
+ mem[ix].buffer = buffer;
+ mem[ix].dataPtr = dataPtr;
+ ix++;
+ }
+ else
+ {
+ FREE(buffer);
+ break;
+ }
+ }
+ }
+
+ P(":: Mapped %d buffers", ix);
+
+ while (ix--)
+ {
+ ERR_ADD(res, unmap_1D(mem[ix].dataPtr, length, 0, mem[ix].val, mem[ix].bufPtr));
+ FREE(mem[ix].buffer);
+ }
+#else
+ int res = TESTERR_NOTIMPLEMENTED;
+#endif
+ return res;
+}
+
+/**
+ * This stress tests allocates/maps/frees/unmaps buffers at
+ * least num_ops times. The test maintains a set of slots that
+ * are initially NULL. For each operation, a slot is randomly
+ * selected. If the slot is not used, it is filled randomly
+ * with a 1D, 2D, NV12 or mapped buffer. If it is used, the
+ * slot is cleared by freeing/unmapping the buffer already
+ * there. The buffers are filled on alloc/map and this is
+ * checked on free/unmap to verify that there was no memory
+ * corruption. Failed allocation and maps are ignored as we may
+ * run out of memory. The return value is the first error code
+ * encountered, or 0 on success.
+ *
+ * This test sets the seed so that it produces reproducible
+ * results.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param num_ops Number of operations to perform
+ * @param num_slots Number of slots to maintain
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int star_test(uint32_t num_ops, uint16_t num_slots)
+{
+ printf("Random set of %d Allocs/Maps and Frees/UnMaps for %d slots\n", num_ops, num_slots);
+ srand(0x4B72316A);
+ struct data {
+ int op;
+ uint16_t val;
+ pixels_t width, height;
+ bytes_t length;
+ void *bufPtr;
+ void *buffer;
+ void *dataPtr;
+ } *mem;
+
+ /* allocate memory state */
+ mem = NEWN(struct data, num_slots);
+ if (!mem) return NOT_P(mem,!=,NULL);
+
+ /* perform alloc/free/unmaps */
+ int res = 0, ix;
+ while (!res && num_ops--)
+ {
+ ix = rand() % num_slots;
+ /* see if we need to free/unmap data */
+ if (mem[ix].bufPtr)
+ {
+ /* check memory fill */
+ switch (mem[ix].op)
+ {
+ case 0: res = unmap_1D(mem[ix].dataPtr, mem[ix].length, 0, mem[ix].val, mem[ix].bufPtr);
+ FREE(mem[ix].buffer);
+ break;
+ case 1: res = free_1D(mem[ix].length, 0, mem[ix].val, mem[ix].bufPtr); break;
+ case 2: res = free_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_8BIT, 0, mem[ix].val, mem[ix].bufPtr); break;
+ case 3: res = free_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_16BIT, 0, mem[ix].val, mem[ix].bufPtr); break;
+ case 4: res = free_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_32BIT, 0, mem[ix].val, mem[ix].bufPtr); break;
+ case 5: res = free_NV12(mem[ix].width, mem[ix].height, mem[ix].val, mem[ix].bufPtr); break;
+ }
+ P("%s[%p]", mem[ix].op ? "free" : "unmap", mem[ix].bufPtr);
+ ZERO(mem[ix]);
+ }
+ /* we need to allocate/map data */
+ else
+ {
+ int op = rand();
+ /* set width */
+ pixels_t width, height;
+ switch ("AAAABBBBCCCDDEEF"[op & 15]) {
+ case 'F': width = 1920; height = 1080; break;
+ case 'E': width = 1280; height = 720; break;
+ case 'D': width = 640; height = 480; break;
+ case 'C': width = 848; height = 480; break;
+ case 'B': width = 176; height = 144; break;
+ case 'A': width = height = 64; break;
+ }
+ mem[ix].length = (bytes_t)width * height;
+ mem[ix].width = width;
+ mem[ix].height = height;
+ mem[ix].val = ((uint16_t)rand());
+
+ /* perform operation */
+ mem[ix].op = "AAABBBBCCCCDDDDE"[(op >> 4) & 15] - 'A';
+ switch (mem[ix].op)
+ {
+ case 0: /* map 1D buffer */
+#ifdef __MAP_OK__
+ /* allocate aligned buffer */
+ mem[ix].length = (mem[ix].length + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1);
+ mem[ix].buffer = malloc(mem[ix].length + PAGE_SIZE - 1);
+ if (mem[ix].buffer)
+ {
+ mem[ix].dataPtr = (void *)(((uint32_t)mem[ix].buffer + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
+ mem[ix].bufPtr = map_1D(mem[ix].dataPtr, mem[ix].length, 0, mem[ix].val);
+ if (!mem[ix].bufPtr) FREE(mem[ix].buffer);
+ }
+ P("map[l=0x%x] = %p", mem[ix].length, mem[ix].bufPtr);
+ break;
+#else
+ mem[ix].op = 1;
+#endif
+ case 1:
+ mem[ix].bufPtr = alloc_1D(mem[ix].length, 0, mem[ix].val);
+ P("alloc[l=0x%x] = %p", mem[ix].length, mem[ix].bufPtr);
+ break;
+ case 2:
+ mem[ix].bufPtr = alloc_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_8BIT, 0, mem[ix].val);
+ P("alloc[%d*%d*8] = %p", mem[ix].width, mem[ix].height, mem[ix].bufPtr);
+ break;
+ case 3:
+ mem[ix].bufPtr = alloc_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_16BIT, 0, mem[ix].val);
+ P("alloc[%d*%d*16] = %p", mem[ix].width, mem[ix].height, mem[ix].bufPtr);
+ break;
+ case 4:
+ mem[ix].bufPtr = alloc_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_32BIT, 0, mem[ix].val);
+ P("alloc[%d*%d*32] = %p", mem[ix].width, mem[ix].height, mem[ix].bufPtr);
+ break;
+ case 5:
+ mem[ix].bufPtr = alloc_NV12(mem[ix].width, mem[ix].height, mem[ix].val);
+ P("alloc[%d*%d*NV12] = %p", mem[ix].width, mem[ix].height, mem[ix].bufPtr);
+ break;
+ }
+
+ /* check all previous buffers */
+#ifdef STAR_TRACE_MEM
+ for (ix = 0; ix < num_slots; ix++)
+ {
+ MemAllocBlock blk;
+ if (mem[ix].bufPtr)
+ {
+ if(0) P("ptr=%p, op=%d, w=%d, h=%d, l=%x, val=%x",
+ mem[ix].bufPtr, mem[ix].op, mem[ix].width, mem[ix].height,
+ mem[ix].length, mem[ix].val);
+ switch (mem[ix].op)
+ {
+ case 0: case 1:
+ blk.pixelFormat = PIXEL_FMT_PAGE;
+ blk.dim.len = mem[ix].length;
+ break;
+ case 5:
+ blk.pixelFormat = PIXEL_FMT_16BIT;
+ blk.dim.area.width = mem[ix].width >> 1;
+ blk.dim.area.height = mem[ix].height >> 1;
+ blk.stride = def_stride(mem[ix].width); /* same for Y and UV */
+ blk.ptr = mem[ix].bufPtr + mem[ix].height * blk.stride;
+ check_mem(mem[ix].val, &blk);
+ case 2:
+ blk.pixelFormat = PIXEL_FMT_8BIT;
+ blk.dim.area.width = mem[ix].width;
+ blk.dim.area.height = mem[ix].height;
+ blk.stride = def_stride(mem[ix].width);
+ break;
+ case 3:
+ blk.pixelFormat = PIXEL_FMT_16BIT;
+ blk.dim.area.width = mem[ix].width;
+ blk.dim.area.height = mem[ix].height;
+ blk.stride = def_stride(mem[ix].width * 2);
+ break;
+ case 4:
+ blk.pixelFormat = PIXEL_FMT_32BIT;
+ blk.dim.area.width = mem[ix].width;
+ blk.dim.area.height = mem[ix].height;
+ blk.stride = def_stride(mem[ix].width * 4);
+ break;
+ }
+ blk.ptr = mem[ix].bufPtr;
+ check_mem(mem[ix].val, &blk);
+ }
+ }
+#endif
+ }
+ }
+
+ /* unmap and free everything */
+ for (ix = 0; ix < num_slots; ix++)
+ {
+ if (mem[ix].bufPtr)
+ {
+ /* check memory fill */
+ switch (mem[ix].op)
+ {
+ case 0: ERR_ADD(res, unmap_1D(mem[ix].dataPtr, mem[ix].length, 0, mem[ix].val, mem[ix].bufPtr));
+ FREE(mem[ix].buffer);
+ break;
+ case 1: ERR_ADD(res, free_1D(mem[ix].length, 0, mem[ix].val, mem[ix].bufPtr)); break;
+ case 2: ERR_ADD(res, free_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_8BIT, 0, mem[ix].val, mem[ix].bufPtr)); break;
+ case 3: ERR_ADD(res, free_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_16BIT, 0, mem[ix].val, mem[ix].bufPtr)); break;
+ case 4: ERR_ADD(res, free_2D(mem[ix].width, mem[ix].height, PIXEL_FMT_32BIT, 0, mem[ix].val, mem[ix].bufPtr)); break;
+ case 5: ERR_ADD(res, free_NV12(mem[ix].width, mem[ix].height, mem[ix].val, mem[ix].bufPtr)); break;
+ }
+ }
+ }
+ FREE(mem);
+
+ return res;
+}
+
+/**
+ * This stress tests allocates/maps/frees/unmaps buffers at
+ * least num_ops times. The test maintains a set of slots that
+ * are initially NULL. For each operation, a slot is randomly
+ * selected. If the slot is not used, it is filled randomly
+ * with a 1D, 2D, NV12 or mapped buffer. If it is used, the
+ * slot is cleared by freeing/unmapping the buffer already
+ * there. The buffers are filled on alloc/map and this is
+ * checked on free/unmap to verify that there was no memory
+ * corruption. Failed allocation and maps are ignored as we may
+ * run out of memory. The return value is the first error code
+ * encountered, or 0 on success.
+ *
+ * This test sets the seed so that it produces reproducible
+ * results.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param num_ops Number of operations to perform
+ * @param num_slots Number of slots to maintain
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int star_tiler_test(uint32_t num_ops, uint16_t num_slots)
+{
+ printf("Random set of %d tiler Allocs/Maps and Frees/UnMaps for %d slots\n", num_ops, num_slots);
+ srand(0x4B72316A);
+ struct data {
+ int op;
+ struct tiler_block_info blk;
+ void *buffer;
+ } *mem;
+
+ /* allocate memory state */
+ mem = NEWN(struct data, num_slots);
+ if (!mem) return NOT_P(mem,!=,NULL);
+
+ /* perform alloc/free/unmaps */
+ int ix, td = A_S(open("/dev/tiler", O_RDWR),>=,0), res = td < 0 ? td : 0;
+ while (!res && num_ops--)
+ {
+ ix = rand() % num_slots;
+ /* see if we need to free/unmap data */
+ if (mem[ix].blk.id)
+ {
+ P("free [0x%x(0x%x)]", mem[ix].blk.id, mem[ix].blk.ssptr);
+ res = A_S(ioctl(td, TILIOC_FBLK, &mem[ix].blk),==,0);
+ FREE(mem[ix].buffer);
+ ZERO(mem[ix]);
+ }
+ /* we need to allocate/map data */
+ else
+ {
+ int op = rand();
+ /* set width */
+ pixels_t width, height;
+ switch ("AAAABBBBCCCDDEEF"[op & 15]) {
+ case 'F': width = 1920; height = 1080; break;
+ case 'E': width = 1280; height = 720; break;
+ case 'D': width = 640; height = 480; break;
+ case 'C': width = 848; height = 480; break;
+ case 'B': width = 176; height = 144; break;
+ case 'A': width = height = 64; break;
+ }
+ bytes_t length = (bytes_t)width * height;
+
+ /* perform operation */
+ mem[ix].op = "AAABBBBCCCCDDDDE"[(op >> 4) & 15] - 'A';
+ switch (mem[ix].op)
+ {
+ case 0: /* map 1D buffer */
+ /* allocate aligned buffer */
+ length = (length + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1);
+ mem[ix].buffer = malloc(length + PAGE_SIZE - 1);
+ if (mem[ix].buffer)
+ {
+ mem[ix].blk.dim.len = length;
+ mem[ix].blk.fmt = TILFMT_PAGE;
+ mem[ix].blk.ptr = (void *)(((uint32_t)mem[ix].buffer + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
+ res = A_S(ioctl(td, TILIOC_MBLK, &mem[ix].blk),==,0);
+ if (res)
+ FREE(mem[ix].buffer);
+ }
+ P("map[l=0x%x] = 0x%x(0x%x)", length, mem[ix].blk.id, mem[ix].blk.ssptr);
+ break;
+ case 1:
+ mem[ix].blk.dim.len = length;
+ mem[ix].blk.fmt = TILFMT_PAGE;
+ res = A_S(ioctl(td, TILIOC_GBLK, &mem[ix].blk),==,0);
+ P("alloc[l=0x%x] = 0x%x(0x%x)", length, mem[ix].blk.id, mem[ix].blk.ssptr);
+ break;
+ case 2: case 3: case 4:
+ mem[ix].blk.dim.area.width = width;
+ mem[ix].blk.dim.area.height = height;
+ mem[ix].blk.fmt = TILFMT_8BIT + mem[ix].op - 2;
+ res = A_S(ioctl(td, TILIOC_GBLK, &mem[ix].blk),==,0);
+ P("alloc[%d*%d*%d] = 0x%x(0x%x)", width, height, 8 << (mem[ix].op -2), mem[ix].blk.id, mem[ix].blk.ssptr);
+ break;
+ }
+ }
+ }
+
+ /* unmap and free everything */
+ for (ix = 0; ix < num_slots; ix++)
+ {
+ if (mem[ix].blk.id)
+ {
+ res = A_S(ioctl(td, TILIOC_FBLK, &mem[ix].blk),==,0);
+ FREE(mem[ix].buffer);
+ }
+ }
+ ERR_ADD_S(res, close(td));
+ FREE(mem);
+
+ return res;
+}
+
+#define NEGA(exp) ({ void *__ptr__ = A_P(exp,==,NULL); if (__ptr__) MemMgr_Free(__ptr__); __ptr__ != NULL; })
+
+/**
+ * Performs negative tests for MemMgr_Alloc.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int neg_alloc_tests()
+{
+ printf("Negative Alloc tests\n");
+
+ MemAllocBlock block[2], *blk;
+ memset(&block, 0, sizeof(block));
+
+ int ret = 0, num_blocks;
+
+ for (num_blocks = 1; num_blocks < 3; num_blocks++)
+ {
+ blk = block + num_blocks - 1;
+
+ P("/* bad pixel format */");
+ blk->pixelFormat = PIXEL_FMT_MIN - 1;
+ blk->dim.len = PAGE_SIZE;
+ ret |= NEGA(MemMgr_Alloc(block, num_blocks));
+ blk->pixelFormat = PIXEL_FMT_MAX + 1;
+ ret |= NEGA(MemMgr_Alloc(block, num_blocks));
+
+ P("/* bad 1D stride */");
+ blk->pixelFormat = PIXEL_FMT_PAGE;
+ blk->stride = PAGE_SIZE - 1;
+ ret |= NEGA(MemMgr_Alloc(block, num_blocks));
+
+ P("/* 0 1D length */");
+ blk->dim.len = blk->stride = 0;
+ ret |= NEGA(MemMgr_Alloc(block, num_blocks));
+
+ P("/* bad 2D stride */");
+ blk->pixelFormat = PIXEL_FMT_8BIT;
+ blk->dim.area.width = PAGE_SIZE - 1;
+ blk->stride = PAGE_SIZE - 1;
+ blk->dim.area.height = 16;
+ ret |= NEGA(MemMgr_Alloc(block, num_blocks));
+
+ P("/* bad 2D width */");
+ blk->stride = blk->dim.area.width = 0;
+ ret |= NEGA(MemMgr_Alloc(block, num_blocks));
+
+ P("/* bad 2D height */");
+ blk->dim.area.height = 0;
+ blk->dim.area.width = 16;
+ ret |= NEGA(MemMgr_Alloc(block, num_blocks));
+
+ /* good 2D block */
+ blk->dim.area.height = 16;
+ }
+
+ block[0].pixelFormat = block[1].pixelFormat = PIXEL_FMT_8BIT;
+ block[0].dim.area.width = 16384;
+ block[0].dim.area.height = block[1].dim.area.width = 16;
+ block[1].dim.area.height = 8192;
+ ret |= NEGA(MemMgr_Alloc(block, 2));
+
+ return ret;
+}
+
+/**
+ * Performs negative tests for MemMgr_Free.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int neg_free_tests()
+{
+ printf("Negative Free tests\n");
+
+ void *ptr = alloc_2D(2500, 10, PIXEL_FMT_16BIT, 2 * PAGE_SIZE, 0);
+ int ret = 0;
+
+ MemMgr_Free(ptr);
+
+ P("/* free something twice */");
+ ret |= NOT_I(MemMgr_Free(ptr),!=,0);
+
+ P("/* free NULL */");
+ ret |= NOT_I(MemMgr_Free(NULL),!=,0);
+
+ P("/* free arbitrary value */");
+ ret |= NOT_I(MemMgr_Free((void *)0x12345678),!=,0);
+
+ P("/* free mapped buffer */");
+ void *buffer = malloc(PAGE_SIZE * 2);
+ void *dataPtr = (void *)(((uint32_t)buffer + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
+ ptr = map_1D(dataPtr, PAGE_SIZE, 0, 0);
+ ret |= NOT_I(MemMgr_Free(ptr),!=,0);
+
+ MemMgr_UnMap(ptr);
+
+ return ret;
+}
+
+#define NEGM(exp) ({ void *__ptr__ = A_P(exp,==,NULL); if (__ptr__) MemMgr_UnMap(__ptr__); __ptr__ != NULL; })
+
+/**
+ * Performs negative tests for MemMgr_Map.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int neg_map_tests()
+{
+ printf("Negative Map tests\n");
+
+ MemAllocBlock block[2], *blk;
+ memset(&block, 0, sizeof(block));
+
+ int ret = 0, num_blocks;
+
+ for (num_blocks = 1; num_blocks < 3; num_blocks++)
+ {
+ blk = block + num_blocks - 1;
+
+ P("/* bad pixel format */");
+ blk->pixelFormat = PIXEL_FMT_MIN - 1;
+ blk->dim.len = PAGE_SIZE;
+ ret |= NEGM(MemMgr_Map(block, num_blocks));
+ blk->pixelFormat = PIXEL_FMT_MAX + 1;
+ ret |= NEGM(MemMgr_Map(block, num_blocks));
+
+ P("/* bad 1D stride */");
+ blk->pixelFormat = PIXEL_FMT_PAGE;
+ blk->stride = PAGE_SIZE - 1;
+ ret |= NEGM(MemMgr_Map(block, num_blocks));
+
+ P("/* 0 1D length */");
+ blk->dim.len = blk->stride = 0;
+ ret |= NEGM(MemMgr_Map(block, num_blocks));
+
+ P("/* bad 2D stride */");
+ blk->pixelFormat = PIXEL_FMT_8BIT;
+ blk->dim.area.width = PAGE_SIZE - 1;
+ blk->stride = PAGE_SIZE - 1;
+ blk->dim.area.height = 16;
+ ret |= NEGM(MemMgr_Map(block, num_blocks));
+
+ P("/* bad 2D width */");
+ blk->stride = blk->dim.area.width = 0;
+ ret |= NEGM(MemMgr_Map(block, num_blocks));
+
+ P("/* bad 2D height */");
+ blk->dim.area.height = 0;
+ blk->dim.area.width = 16;
+ ret |= NEGM(MemMgr_Map(block, num_blocks));
+
+ /* good 2D block */
+ blk->dim.area.height = 16;
+ }
+
+ P("/* 2 buffers */");
+ ret |= NEGM(MemMgr_Map(block, 2));
+
+ P("/* 1 2D buffer */");
+ ret |= NEGM(MemMgr_Map(block, 1));
+
+ P("/* 1 1D buffer with no address */");
+ block[0].pixelFormat = PIXEL_FMT_PAGE;
+ block[0].dim.len = 2 * PAGE_SIZE;
+ block[0].ptr = NULL;
+ ret |= NEGM(MemMgr_Map(block, 1));
+
+ P("/* 1 1D buffer with not aligned start address */");
+ void *buffer = malloc(3 * PAGE_SIZE);
+ void *dataPtr = (void *)(((uint32_t)buffer + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
+ block[0].ptr = dataPtr + 3;
+ ret |= NEGM(MemMgr_Map(block, 1));
+
+ P("/* 1 1D buffer with not aligned length */");
+ block[0].ptr = dataPtr;
+ block[0].dim.len -= 5;
+ ret |= NEGM(MemMgr_Map(block, 1));
+
+#if 0 /* TODO: it's possible that our va falls within the TILER addr range */
+ P("/* Mapping a tiled 1D buffer */");
+ void *ptr = alloc_1D(PAGE_SIZE * 2, 0, 0);
+ dataPtr = (void *)(((uint32_t)ptr + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
+ block[0].ptr = dataPtr;
+ block[0].dim.len = PAGE_SIZE;
+ ret |= NEGM(MemMgr_Map(block, 1));
+
+ MemMgr_Free(ptr);
+#endif
+
+ return ret;
+}
+
+/**
+ * Performs negative tests for MemMgr_UnMap.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int neg_unmap_tests()
+{
+ printf("Negative Unmap tests\n");
+
+ void *ptr = alloc_1D(PAGE_SIZE, 0, 0);
+ int ret = 0;
+
+ P("/* unmap alloced buffer */");
+ ret |= NOT_I(MemMgr_UnMap(ptr),!=,0);
+
+ MemMgr_Free(ptr);
+
+ void *buffer = malloc(PAGE_SIZE * 2);
+ void *dataPtr = (void *)(((uint32_t)buffer + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
+ ptr = map_1D(dataPtr, PAGE_SIZE, 0, 0);
+ MemMgr_UnMap(ptr);
+
+ P("/* unmap something twice */");
+ ret |= NOT_I(MemMgr_UnMap(ptr),!=,0);
+
+ P("/* unmap NULL */");
+ ret |= NOT_I(MemMgr_UnMap(NULL),!=,0);
+
+ P("/* unmap arbitrary value */");
+ ret |= NOT_I(MemMgr_UnMap((void *)0x12345678),!=,0);
+
+ return ret;
+}
+
+/**
+ * Performs negative tests for MemMgr_Is.. functions.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int neg_check_tests()
+{
+ printf("Negative Is... tests\n");
+ void *ptr = malloc(32);
+
+ int ret = 0;
+
+ ret |= NOT_I(MemMgr_Is1DBlock(NULL),==,FALSE);
+ ret |= NOT_I(MemMgr_Is1DBlock((void *)0x12345678),==,FALSE);
+ ret |= NOT_I(MemMgr_Is1DBlock(ptr),==,FALSE);
+ ret |= NOT_I(MemMgr_Is2DBlock(NULL),==,FALSE);
+ ret |= NOT_I(MemMgr_Is2DBlock((void *)0x12345678),==,FALSE);
+ ret |= NOT_I(MemMgr_Is2DBlock(ptr),==,FALSE);
+ ret |= NOT_I(MemMgr_IsMapped(NULL),==,FALSE);
+ ret |= NOT_I(MemMgr_IsMapped((void *)0x12345678),==,FALSE);
+ ret |= NOT_I(MemMgr_IsMapped(ptr),==,FALSE);
+
+ ret |= NOT_I(MemMgr_GetStride(NULL),==,0);
+ ret |= NOT_I(MemMgr_GetStride((void *)0x12345678),==,0);
+ ret |= NOT_I(MemMgr_GetStride(ptr),==,PAGE_SIZE);
+
+ ret |= NOT_P(TilerMem_VirtToPhys(NULL),==,0);
+ ret |= NOT_P(TilerMem_VirtToPhys((void *)0x12345678),==,0);
+ ret |= NOT_P(TilerMem_VirtToPhys(ptr),!=,0);
+
+ ret |= NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys(NULL)),==,0);
+ ret |= NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys((void *)0x12345678)),==,0);
+ ret |= NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys(ptr)),==,0);
+
+ FREE(ptr);
+
+ return ret;
+}
+
+DEFINE_TESTS(TESTS)
+
+/**
+ * We run the same identity check before and after running the
+ * tests.
+ *
+ * @author a0194118 (9/12/2009)
+ */
+void memmgr_identity_test(void *ptr)
+{
+ /* also execute internal unit tests - this also verifies that we did not
+ keep any references */
+ __test__MemMgr();
+}
+
+/**
+ * Main test function. Checks arguments for test case ranges,
+ * runs tests and prints usage or test list if required.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param argc Number of arguments
+ * @param argv Arguments
+ *
+ * @return -1 on usage or test list, otherwise # of failed
+ * tests.
+ */
+int main(int argc, char **argv)
+{
+ return TestLib_Run(argc, argv,
+ memmgr_identity_test, memmgr_identity_test, NULL);
+}
+
diff --git a/tiler/testlib.c b/tiler/testlib.c
new file mode 100644
index 0000000..63d1298
--- /dev/null
+++ b/tiler/testlib.c
@@ -0,0 +1,163 @@
+/*
+ * testlib.c
+ *
+ * Unit test interface.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* retrieve type definitions */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "testlib.h"
+
+#include <utils.h>
+#include <debug_utils.h>
+
+#define TESTLIB_OK 0
+#define TESTLIB_FAIL 1
+
+/** Returns TRUE iff str is a whole unsigned int */
+#define is_uint(str) \
+ ({ unsigned i; char c; sscanf(str, "%u%c", &i, &c) == 1; })
+
+extern int __internal__TestLib_DoList(int id);
+
+/**
+ * Prints test result and returns summary result
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param res Test result
+ *
+ * @return TEST_RESULT_OK on success, TEST_RESULT_FAIL on
+ * failure, TEST_RESULT_UNAVAILABLE if test is not
+ * available
+ */
+int __internal__TestLib_Report(int res)
+{
+ switch (res)
+ {
+ case TESTLIB_UNAVAILABLE:
+ printf("==> TEST NOT AVAILABLE\n");
+ fflush(stdout);
+ return TESTLIB_UNAVAILABLE;
+ case 0:
+ printf("==> TEST OK\n");
+ fflush(stdout);
+ return TESTLIB_OK;
+ default:
+ printf("==> TEST FAIL(%d)\n", res);
+ fflush(stdout);
+ return TESTLIB_FAIL;
+ }
+}
+
+void __internal__TestLib_NullFn(void *ptr)
+{
+}
+
+int TestLib_Run(int argc, char **argv, void(*init_fn)(void *),
+ void(*exit_fn)(void *), void *ptr)
+{
+ int start, end, res, failed = 0, succeeded = 0, unavailable = 0;
+
+ /* all tests */
+ if (argc == 1)
+ {
+ start = 1; end = -1;
+ }
+ /* test list */
+ else if (argc == 2 && !strcmp(argv[1], "list"))
+ {
+ __internal__TestLib_DoList(0);
+ return -1;
+ }
+ /* single test */
+ else if (argc == 2 && is_uint(argv[1]))
+ {
+ start = end = atoi(argv[1]);
+ }
+ /* open range .. b */
+ else if (argc == 3 && !strcmp(argv[1], "..") && is_uint(argv[2]))
+ {
+ start = 1;
+ end = atoi(argv[2]);
+ }
+ /* open range a .. */
+ else if (argc == 3 && !strcmp(argv[2], "..") && is_uint(argv[1]))
+ {
+ start = atoi(argv[1]);
+ end = -1;
+ }
+ else if (argc == 4 && !strcmp(argv[2], "..") && is_uint(argv[1]) && is_uint(argv[3]))
+ {
+ start = atoi(argv[1]);
+ end = atoi(argv[3]);
+ }
+ else
+ {
+ fprintf(stderr, "Usage: %s [<range>], where <range> is\n"
+ " empty: run all tests\n"
+ " list: list tests\n"
+ " ix: run test #ix\n"
+ " a ..: run tests #a, #a+1, ...\n"
+ " .. b: run tests #1, #2, .. #b\n"
+ " a .. b: run tests #a, #a+1, .. #b\n", argv[0]);
+ fflush(stderr);
+ return -1;
+ }
+
+ /* execute tests */
+ init_fn(ptr);
+
+ do
+ {
+ res = __internal__TestLib_DoList(start++);
+ if (res == TESTLIB_FAIL) failed++;
+ else if (res == TESTLIB_OK) succeeded++;
+ else if (res == TESTLIB_UNAVAILABLE) unavailable++;
+ printf("so far FAILED: %d, SUCCEEDED: %d, UNAVAILABLE: %d\n", failed, succeeded,
+ unavailable);
+ fflush(stdout);
+ } while (res != TESTLIB_INVALID && (end < 0 || start <= end));
+
+ printf("FAILED: %d, SUCCEEDED: %d, UNAVAILABLE: %d\n", failed, succeeded,
+ unavailable);
+ fflush(stdout);
+
+ /* also execute internal unit tests - this also verifies that we did not
+ keep any references */
+ exit_fn(ptr);
+
+ return failed;
+}
+
diff --git a/tiler/testlib.h b/tiler/testlib.h
new file mode 100644
index 0000000..bc1a799
--- /dev/null
+++ b/tiler/testlib.h
@@ -0,0 +1,101 @@
+/*
+ * testlib.h
+ *
+ * Unit test interface API.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TESTLIB_H_
+#define _TESTLIB_H_
+
+/* error type definitions */
+#define TESTLIB_UNAVAILABLE -65378
+#define TESTLIB_INVALID -1
+
+#define T(test) ++i; \
+ if (!id || i == id) printf("TEST #% 3d - %s\n", i, #test); \
+ if (i == id) { \
+ printf("TEST_DESC - "); \
+ fflush(stdout); \
+ return __internal__TestLib_Report(test); \
+ }
+
+/* test run function that must be defined from the test app */
+
+/**
+ * Runs a specified test by id, or lists all test cases. This
+ * function uses the TESTS macros, and defines each T(test) to
+ * run a test starting from id == 1, and then return the result.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param id Test case id, or 0 if only listing test cases
+ *
+ * @return Summary result: TEST_RESULT_OK, FAIL, INVALID or
+ * UNAVAILABLE.
+ */
+#define TESTS_ \
+ int __internal__TestLib_DoList(int id) { int i = 0;
+
+#define _TESTS \
+ return TESTLIB_INVALID; }
+
+#define DEFINE_TESTS(TESTS) TESTS_ TESTS _TESTS
+
+/* internal function prototypes and defines */
+extern int __internal__TestLib_Report(int res);
+extern void __internal__TestLib_NullFn(void *ptr);
+
+#define nullfn __internal__TestLib_NullFn
+
+/**
+ * Parses argument list, prints usage on error, lists test
+ * cases, runs tests and reports results.
+ *
+ * @author a0194118 (9/12/2009)
+ *
+ * @param argc Number of test arguments
+ * @param argv Test argument array
+ * @param init_fn Initialization function of void fn(void *).
+ * This is called before the testing.
+ * @param exit_fn Deinit function of void fn(void *). This is
+ * done after the testing concludes.
+ * @param ptr Custom pointer that is passed into the
+ * initialization functions.
+ *
+ * @return # of test cases failed, 0 on success, -1 if no tests
+ * were run because of an error or a list request.
+ */
+int TestLib_Run(int argc, char **argv, void(*init_fn)(void *),
+ void(*exit_fn)(void *), void *ptr);
+
+#endif
+
diff --git a/tiler/tiler.h b/tiler/tiler.h
new file mode 100644
index 0000000..8358f8d
--- /dev/null
+++ b/tiler/tiler.h
@@ -0,0 +1,105 @@
+/*
+ * tiler.h
+ *
+ * TILER driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TILER_H_
+#define _TILER_H_
+
+#define TILER_MEM_8BIT 0x60000000
+#define TILER_MEM_16BIT 0x68000000
+#define TILER_MEM_32BIT 0x70000000
+#define TILER_MEM_PAGED 0x78000000
+#define TILER_MEM_END 0x80000000
+
+#define TILER_PAGE 0x1000
+#define TILER_WIDTH 256
+#define TILER_HEIGHT 128
+#define TILER_BLOCK_WIDTH 64
+#define TILER_BLOCK_HEIGHT 64
+#define TILER_LENGTH (TILER_WIDTH * TILER_HEIGHT * TILER_PAGE)
+
+#define TILER_DEVICE_PATH "/dev/tiler"
+#define TILER_MAX_NUM_BLOCKS 16
+
+enum tiler_fmt {
+ TILFMT_MIN = -2,
+ TILFMT_INVALID = -2,
+ TILFMT_NONE = -1,
+ TILFMT_8BIT = 0,
+ TILFMT_16BIT = 1,
+ TILFMT_32BIT = 2,
+ TILFMT_PAGE = 3,
+ TILFMT_MAX = 3,
+ TILFMT_8AND16 = 4,
+};
+
+struct area {
+ uint16_t width;
+ uint16_t height;
+};
+
+struct tiler_block_info {
+ enum tiler_fmt fmt;
+ union {
+ struct area area;
+ uint32_t len;
+ } dim;
+ uint32_t stride;
+ void *ptr;
+ uint32_t id;
+ uint32_t key;
+ uint32_t group_id;
+ uint32_t ssptr;
+};
+
+struct tiler_buf_info {
+ uint32_t num_blocks;
+ struct tiler_block_info blocks[TILER_MAX_NUM_BLOCKS];
+ uint32_t offset;
+ uint32_t length;
+};
+
+#define TILIOC_GBLK _IOWR('z', 100, struct tiler_block_info)
+#define TILIOC_FBLK _IOW('z', 101, struct tiler_block_info)
+#define TILIOC_GSSP _IOWR('z', 102, uint32_t)
+#define TILIOC_MBLK _IOWR('z', 103, struct tiler_block_info)
+#define TILIOC_UMBLK _IOW('z', 104, struct tiler_block_info)
+#define TILIOC_QBUF _IOWR('z', 105, struct tiler_buf_info)
+#define TILIOC_RBUF _IOWR('z', 106, struct tiler_buf_info)
+#define TILIOC_URBUF _IOWR('z', 107, struct tiler_buf_info)
+#define TILIOC_QBLK _IOWR('z', 108, struct tiler_block_info)
+#define TILIOC_PRBLK _IOW('z', 109, struct tiler_block_info)
+#define TILIOC_URBLK _IOW('z', 110, uint32_t)
+
+#endif
diff --git a/tiler/tiler_ptest.c b/tiler/tiler_ptest.c
new file mode 100644
index 0000000..7f06940
--- /dev/null
+++ b/tiler/tiler_ptest.c
@@ -0,0 +1,729 @@
+/*
+ * tiler_ptest.c
+ *
+ * Memory Allocator Interface tests.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* retrieve type definitions */
+#define __DEBUG__
+#undef __DEBUG_ENTRY__
+#define __DEBUG_ASSERT__
+
+#undef __WRITE_IN_STRIDE__
+#undef STAR_TRACE_MEM
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+#include <utils.h>
+#include <list_utils.h>
+#include <debug_utils.h>
+#include <memmgr.h>
+#include <tilermem.h>
+#include <tilermem_utils.h>
+#include <testlib.h>
+
+#define FALSE 0
+
+/**
+ * Returns the default page stride for this block
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @param width Width of 2D container
+ *
+ * @return Stride
+ */
+static bytes_t def_stride(pixels_t width)
+{
+ return (PAGE_SIZE - 1 + (bytes_t)width) & ~(PAGE_SIZE - 1);
+}
+
+/**
+ * Returns the bytes per pixel for the pixel format.
+ *
+ * @author a0194118 (9/4/2009)
+ *
+ * @param pixelFormat Pixelformat
+ *
+ * @return Bytes per pixel
+ */
+static bytes_t def_bpp(pixel_fmt_t pixelFormat)
+{
+ return (pixelFormat == PIXEL_FMT_32BIT ? 4 :
+ pixelFormat == PIXEL_FMT_16BIT ? 2 : 1);
+}
+
+enum ptr_type {
+ ptr_empty = 0,
+ ptr_alloced,
+ ptr_tiler_alloced,
+};
+
+struct ptr_info {
+ int num_blocks;
+ struct tiler_block_info blocks[TILER_MAX_NUM_BLOCKS];
+ int ptr;
+ short type;
+ uint16_t val;
+};
+
+static void dump_block(struct tiler_block_info *blk, char *prefix, char *suffix)
+{
+ switch (blk->fmt)
+ {
+ case PIXEL_FMT_PAGE:
+ P("%s [p=%p(0x%x),l=0x%x,s=%d]%s", prefix, blk->ptr, blk->ssptr,
+ blk->dim.len, blk->stride, suffix);
+ break;
+ case PIXEL_FMT_8BIT:
+ case PIXEL_FMT_16BIT:
+ case PIXEL_FMT_32BIT:
+ P("%s [p=%p(0x%x),%d*%d*%d,s=%d]%s", prefix, blk->ptr, blk->ssptr,
+ blk->dim.area.width, blk->dim.area.height, def_bpp(blk->fmt) * 8,
+ blk->stride, suffix);
+ break;
+ default:
+ P("%s*[p=%p(0x%x),l=0x%x,s=%d,fmt=0x%x]%s", prefix, blk->ptr,
+ blk->ssptr, blk->dim.len, blk->stride, blk->fmt, suffix);
+ }
+}
+
+static void dump_slot(struct ptr_info* buf, char* prefix)
+{
+ P("%sbuf={n=%d,ptr=0x%x,type=%d,", prefix, buf->num_blocks, buf->ptr,
+ buf->type);
+ int ix = 0;
+ for (ix = 0; ix < buf->num_blocks; ix++)
+ {
+ dump_block(buf->blocks + ix, "", ix + 1 == buf->num_blocks ? "}" : "");
+ }
+}
+
+/**
+ * This method fills up a range of memory using a start address
+ * and start value. The method of filling ensures that
+ * accidentally overlapping regions have minimal chances of
+ * matching, even if the same starting value is used. This is
+ * because the difference between successive values varies as
+ * such. This series only repeats after 704189 values, so the
+ * probability of a match for a range of at least 2 values is
+ * less than 2*10^-11.
+ *
+ * V(i + 1) - V(i) = { 1, 2, 3, ..., 65535, 2, 4, 6, 8 ...,
+ * 65534, 3, 6, 9, 12, ..., 4, 8, 12, 16, ... }
+ *
+ * @author a0194118 (9/6/2009)
+ *
+ * @param start start value
+ * @param block pointer to block info strucure
+ */
+void fill_mem(uint16_t start, MemAllocBlock *block)
+{
+ IN;
+ uint16_t *ptr = (uint16_t *)block->ptr, delta = 1, step = 1;
+ bytes_t height, width, stride, i;
+ if (block->pixelFormat == PIXEL_FMT_PAGE)
+ {
+ height = 1;
+ stride = width = block->dim.len;
+ }
+ else
+ {
+ height = block->dim.area.height;
+ width = block->dim.area.width;
+ stride = block->stride;
+ }
+ width *= def_bpp(block->pixelFormat);
+ bytes_t size = height * stride;
+
+ P("(%p,0x%x*0x%x,s=0x%x)=0x%x", block->ptr, width, height, stride, start);
+
+ CHK_I(width,<=,stride);
+ uint32_t *ptr32 = (uint32_t *)ptr;
+ while (height--)
+ {
+ if (block->pixelFormat == PIXEL_FMT_32BIT)
+ {
+ for (i = 0; i < width; i += sizeof(uint32_t))
+ {
+ uint32_t val = (start & 0xFFFF) | (((uint32_t)(start + delta) & 0xFFFF) << 16);
+ *ptr32++ = val;
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ }
+#ifdef __WRITE_IN_STRIDE__
+ while (i < stride && (height || ((PAGE_SIZE - 1) & (uint32_t)ptr32)))
+ {
+ *ptr32++ = 0;
+ i += sizeof(uint32_t);
+ }
+#else
+ ptr32 += (stride - i) / sizeof(uint32_t);
+#endif
+ }
+ else
+ {
+ for (i = 0; i < width; i += sizeof(uint16_t))
+ {
+ *ptr++ = start;
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ }
+#ifdef __WRITE_IN_STRIDE__
+ while (i < stride && (height || ((PAGE_SIZE - 1) & (uint32_t)ptr)))
+ {
+ *ptr++ = 0;
+ i += sizeof(uint16_t);
+ }
+#else
+ ptr += (stride - i) / sizeof(uint16_t);
+#endif
+
+ }
+ }
+ CHK_P((block->pixelFormat == PIXEL_FMT_32BIT ? (void *)ptr32 : (void *)ptr),==,
+ (block->ptr + size));
+ OUT;
+}
+
+/**
+ * This verifies if a range of memory at a given address was
+ * filled up using the start value.
+ *
+ * @author a0194118 (9/6/2009)
+ *
+ * @param start start value
+ * @param block pointer to block info strucure
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int check_mem(uint16_t start, MemAllocBlock *block)
+{
+ IN;
+ uint16_t *ptr = (uint16_t *)block->ptr, delta = 1, step = 1;
+ bytes_t height, width, stride, r, i;
+ if (block->pixelFormat == PIXEL_FMT_PAGE)
+ {
+ height = 1;
+ stride = width = block->dim.len;
+ }
+ else
+ {
+ height = block->dim.area.height;
+ width = block->dim.area.width;
+ stride = block->stride;
+ }
+ width *= def_bpp(block->pixelFormat);
+
+ CHK_I(width,<=,stride);
+ uint32_t *ptr32 = (uint32_t *)ptr;
+ for (r = 0; r < height; r++)
+ {
+ if (block->pixelFormat == PIXEL_FMT_32BIT)
+ {
+ for (i = 0; i < width; i += sizeof(uint32_t))
+ {
+ uint32_t val = (start & 0xFFFF) | (((uint32_t)(start + delta) & 0xFFFF) << 16);
+ if (*ptr32++ != val) {
+ DP("assert: val[%u,%u] (=0x%x) != 0x%x", r, i, *--ptr32, val);
+ return R_I(MEMMGR_ERR_GENERIC);
+ }
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ }
+#ifdef __WRITE_IN_STRIDE__
+ while (i < stride && ((r < height - 1) || ((PAGE_SIZE - 1) & (uint32_t)ptr32)))
+ {
+ if (*ptr32++) {
+ DP("assert: val[%u,%u] (=0x%x) != 0", r, i, *--ptr32);
+ return R_I(MEMMGR_ERR_GENERIC);
+ }
+ i += sizeof(uint32_t);
+ }
+#else
+ ptr32 += (stride - i) / sizeof(uint32_t);
+#endif
+ }
+ else
+ {
+ for (i = 0; i < width; i += sizeof(uint16_t))
+ {
+ if (*ptr++ != start) {
+ DP("assert: val[%u,%u] (=0x%x) != 0x%x", r, i, *--ptr, start);
+ return R_I(MEMMGR_ERR_GENERIC);
+ }
+ start += delta;
+ delta += step;
+ /* increase step if overflown */
+ if (delta < step) delta = ++step;
+ }
+#ifdef __WRITE_IN_STRIDE__
+ while (i < stride && ((r < height - 1) || ((PAGE_SIZE - 1) & (uint32_t)ptr)))
+ {
+ if (*ptr++) {
+ DP("assert: val[%u,%u] (=0x%x) != 0", r, i, *--ptr);
+ return R_I(MEMMGR_ERR_GENERIC);
+ }
+ i += sizeof(uint16_t);
+ }
+#else
+ ptr += (stride - i) / sizeof(uint16_t);
+#endif
+ }
+ }
+ return R_I(MEMMGR_ERR_NONE);
+}
+
+/**
+ * This method allocates a tiled buffer composed of an arbitrary
+ * set of tiled blocks. If successful, it checks
+ * that the block information was updated with the pointer to
+ * the block. Additionally, it verifies the correct return
+ * values for MemMgr_IsMapped, MemMgr_Is1DBlock,
+ * MemMgr_Is2DBlock, MemMgr_GetStride, TilerMem_GetStride. It
+ * also verifies TilerMem_VirtToPhys using an internally stored
+ * value of the ssptr. If any of these verifications fail, the
+ * buffer is freed. Otherwise, it is filled using the given
+ * start value.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param num_blocks Number of blocks in the buffer
+ * @param blocks Block information
+ * @param val Fill start value
+ * @param bufPtr Pointer to the allocated buffer
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+void *alloc_buf(int num_blocks, MemAllocBlock blocks[], uint16_t val)
+{
+ void *bufPtr = MemMgr_Alloc(blocks, num_blocks);
+ void *ptr = bufPtr;
+ int i;
+
+ for (i = 0; i < num_blocks; i++)
+ {
+ if (bufPtr)
+ {
+ pixel_fmt_t fmt = blocks[i].pixelFormat;
+ bytes_t cstride = (fmt == PIXEL_FMT_PAGE ? PAGE_SIZE :
+ fmt == PIXEL_FMT_8BIT ? TILER_STRIDE_8BIT :
+ fmt == PIXEL_FMT_16BIT ? TILER_STRIDE_16BIT :
+ TILER_STRIDE_32BIT);
+ if (NOT_P(blocks[i].ptr,==,ptr) ||
+ NOT_I(MemMgr_IsMapped(ptr),!=,0) ||
+ NOT_I(MemMgr_Is1DBlock(ptr),==,fmt == PIXEL_FMT_PAGE ? 1 : 0) ||
+ NOT_I(MemMgr_Is2DBlock(ptr),==,fmt == PIXEL_FMT_PAGE ? 0 : 1) ||
+ NOT_I(MemMgr_GetStride(bufPtr),==,blocks[i].stride) ||
+ NOT_P(TilerMem_VirtToPhys(ptr),==,blocks[i].reserved) ||
+ NOT_I(TilerMem_GetStride(TilerMem_VirtToPhys(ptr)),==,cstride) ||
+ NOT_L((PAGE_SIZE - 1) & (long)ptr,==,(PAGE_SIZE - 1) & blocks[i].reserved) ||
+ (fmt == PIXEL_FMT_PAGE || NOT_I(blocks[i].stride,!=,0)))
+ {
+ P(" for block %d", i);
+ MemMgr_Free(bufPtr);
+ return NULL;
+ }
+ fill_mem(val, blocks + i);
+ if (blocks[i].pixelFormat != PIXEL_FMT_PAGE)
+ {
+ ptr += def_stride(blocks[i].dim.area.width *
+ def_bpp(blocks[i].pixelFormat)) * blocks[i].dim.area.height;
+ }
+ else
+ {
+ ptr += def_stride(blocks[i].dim.len);
+ }
+ }
+ else
+ {
+ A_P(blocks[i].ptr,==,ptr);
+ A_I(blocks[i].reserved,==,0);
+ }
+ }
+ return bufPtr;
+}
+
+/**
+ * This method frees a tiled buffer composed of an arbitrary set
+ * of tiled blocks. The given start value is used to verify that
+ * the buffer is still correctly filled. In the event of any
+ * errors, the error value is returned.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param num_blocks Number of blocks in the buffer
+ * @param blocks Block information
+ * @param val Fill start value
+ * @param bufPtr Pointer to the allocated buffer
+ *
+ * @return 0 on success, non-0 error value on failure
+ */
+int free_buf(int num_blocks, MemAllocBlock blocks[], uint16_t val, void *bufPtr)
+{
+ MemAllocBlock blk;
+ void *ptr = bufPtr;
+ int ret = 0, i;
+ for (i = 0; i < num_blocks; i++)
+ {
+ blk = blocks[i];
+ blk.ptr = ptr;
+ ERR_ADD(ret, check_mem(val, &blk));
+ if (blk.pixelFormat != PIXEL_FMT_PAGE)
+ {
+ ptr += def_stride(blk.dim.area.width *
+ def_bpp(blk.pixelFormat)) * blk.dim.area.height;
+ }
+ else
+ {
+ ptr += def_stride(blk.dim.len);
+ }
+ blk.reserved = 0;
+ }
+
+ ERR_ADD(ret, MemMgr_Free(bufPtr));
+ return ret;
+}
+
+#if 0
+struct slot {
+ int op;
+ SSPtr ssptr;
+ void *buffer;
+ void *dataPtr;
+} *slots = NULL;
+
+enum op_enum {
+ op_map_1d,
+ op_alloc_1d,
+ op_alloc_8,
+ op_alloc_16,
+ op_alloc_32,
+ op_alloc_nv12,
+ op_alloc_gen,
+};
+
+static int free_slot(int ix)
+{
+ if (slots[ix].bufPtr)
+ {
+ /* check memory fill */
+ switch (slots[ix].op)
+ {
+ case op_map_1d:
+ res = unmap_1D(slot[ix].dataPtr, slot[ix].length, 0, slot[ix].val, slot[ix].bufPtr);
+ FREE(mem[ix].buffer);
+ break;
+ case op_alloc_1d:
+ res = free_1D(slot[ix].length, 0, slot[ix].val, mem[ix].bufPtr);
+ break;
+ case op_alloc_8:
+ res = free_2D(slot[ix].width, slot[ix].height, PIXEL_FMT_8BIT, 0, slot[ix].val, slot[ix].bufPtr);
+ break;
+ case op_alloc_16:
+ res = free_2D(slot[ix].width, slot[ix].height, PIXEL_FMT_16BIT, 0, slot[ix].val, slot[ix].bufPtr);
+ break;
+ case op_alloc_32:
+ res = free_2D(slot[ix].width, slot[ix].height, PIXEL_FMT_32BIT, 0, slot[ix].val, slot[ix].bufPtr);
+ break;
+ case op_alloc_nv12:
+ res = free_NV12(slot[ix].width, slot[ix].height, slot[ix].val, slot[ix].bufPtr);
+ break;
+ }
+ P("%s[%p]", mem[ix].op ? "free" : "unmap", mem[ix].bufPtr);
+ ZERO(slot[ix]);
+ }
+}
+#endif
+
+#include <tilermgr.h>
+
+char *parse_num(char *p, int *tgt)
+{
+ int len;
+ if (!strncmp(p, "0x", 2)) { /* hex number */
+ if (NOT_I(sscanf(p, "0x%x%n", tgt, &len),==,1))
+ return NULL;
+ return p + len;
+ } else {
+ if (NOT_I(sscanf(p, "%d%n", tgt, &len),==,1))
+ return NULL;
+ return p + len;
+ }
+}
+
+/**
+ * Parametric memmgr test. This is similar to the star test
+ * except the operations are read from the command line:
+ *
+ * [#=]a:w*h*bits[,w*h*bits...] allocates a list of blocks as
+ * buffer # (it frees any previously allocated/mapped buffer
+ * f:# frees a buffer
+ *
+ *
+ * @author a0194118 (11/4/2009)
+ *
+ * @param argc
+ * @param argv
+ */
+int param_test(int argc, char **argv)
+{
+ int delta_slots = 16;
+ int ix, i, n, t, type, max_n, num_slots = delta_slots;
+ struct ptr_info *slots;
+ ALLOCN(slots, num_slots);
+ if (NOT_P(slots,!=,NULL)) return 1;
+
+ int res = TilerMgr_Open();
+ for (i = 1; i < argc && !res; i++)
+ {
+ uint16_t val = (uint16_t) rand();
+
+ char *p = argv[i], *q;
+ struct ptr_info buf;
+ ZERO(buf);
+
+ /* read slot */
+ ix = -1;
+ if (isdigit(*p))
+ {
+ res = 1;
+ q = parse_num(p, &ix);
+ if (NOT_P(q,!=,NULL) || NOT_I(ix,>,0)) break;
+ p = q;
+ if (NOT_I(*p++,==,'.')) break;
+ res = 0;
+ ix--;
+ }
+
+ type = *p++;
+ /* get default slot */
+ if (ix < 0)
+ {
+ switch (type)
+ {
+ /* allocation defaults to the 1st free slot */
+ case 'a':
+ case 'A':
+ for (ix = 0; ix < num_slots && slots[ix].type; ix++);
+ break;
+
+ /* frees default to the 1st used block */
+ case 'f':
+ case 'F':
+ for (ix = 0; ix < num_slots && !slots[ix].type; ix++);
+ if (NOT_I(ix,<,num_slots)) res = 1;
+ break;
+ }
+ }
+ if (res) break;
+
+ /* allocate more slots if needed */
+ if (ix >= num_slots)
+ {
+ int more_slots = ROUND_UP_TO(ix + 1, delta_slots);
+ struct ptr_info *new_slots;
+ ALLOCN(new_slots, more_slots);
+ if (NOT_P(new_slots,!=,NULL)) break;
+ memcpy(new_slots, slots, sizeof(*slots) * num_slots);
+ FREE(slots);
+ slots = new_slots;
+ num_slots = more_slots;
+ }
+
+ /* perform opertaion */
+ res = 1; /* assume failure */
+ switch (type)
+ {
+ case 'a': /* allocate */
+ case 'A': /* tiler-allocate */
+ switch (type)
+ {
+ case 'a': buf.type = ptr_alloced; max_n = TILER_MAX_NUM_BLOCKS; break;
+ case 'A': buf.type = ptr_tiler_alloced; max_n = 1; break;
+ }
+ if (ix < num_slots && NOT_I(slots[ix].type,==,ptr_empty)) break;
+ if (NOT_I(*p++,==,':')) break;
+ for (n = 0; *p && n < max_n; n++) {
+ /* read length or width */
+ p = parse_num(p, (int *) &buf.blocks[n].dim.len);
+ if (NOT_P(p,!=,NULL)) break;
+ if (*p == '*') { /* 2d block */
+ buf.blocks[n].dim.area.width = (uint16_t) buf.blocks[n].dim.len;
+ /* read height */
+ p = parse_num(++p, &t);
+ if (NOT_P(p,!=,NULL) || NOT_I(*p++,==,'*')) break;
+ buf.blocks[n].dim.area.height = (uint16_t) t;
+ /* read bits */
+ p = parse_num(p, &t);
+ if (NOT_P(p,!=,NULL)) break;
+ /* handle nv12 */
+ if (t == 12 && n + 1 < max_n) {
+ buf.blocks[n + 1].dim.area.width = buf.blocks[n].dim.area.width >> 1;
+ buf.blocks[n + 1].dim.area.height = buf.blocks[n].dim.area.height >> 1;
+ buf.blocks[n].fmt = TILFMT_8BIT;
+ t = 16;
+ n++;
+ }
+
+ buf.blocks[n].fmt = (t == 8 ? TILFMT_8BIT :
+ t == 16 ? TILFMT_16BIT :
+ t == 32 ? TILFMT_32BIT : TILFMT_INVALID);
+ if (NOT_I(buf.blocks[n].fmt,!=,TILFMT_INVALID)) break;
+ } else { /* 1d block */
+ buf.blocks[n].fmt = TILFMT_PAGE;
+ }
+ if (*p && NOT_I(*p++,==,',')) break;
+ /* we're OK */
+ res = 0;
+ }
+ if (res || *p) break;
+ /* allocate buffer */
+
+ buf.num_blocks = n;
+ buf.val = val;
+ if (buf.type == ptr_alloced)
+ {
+ dump_slot(&buf, "==(alloc)=>");
+ buf.ptr = (int) alloc_buf(n, (MemAllocBlock *) buf.blocks, val);
+ dump_slot(&buf, "<=(alloc)==");
+ }
+ else
+ {
+ dump_slot(&buf, "==(tiler_alloc)=>");
+ if (buf.blocks[0].fmt == TILFMT_PAGE)
+ {
+ buf.ptr = (int) TilerMgr_PageModeAlloc(buf.blocks[0].dim.len);
+ }
+ else
+ {
+ buf.ptr =(int) TilerMgr_Alloc(buf.blocks[0].fmt,
+ buf.blocks[0].dim.area.width,
+ buf.blocks[0].dim.area.height);
+ }
+ buf.blocks[0].ssptr = (unsigned long) buf.ptr;
+ dump_slot(&buf, "<=(tiler_alloc)==");
+ }
+ if (NOT_I(buf.ptr,!=,0)) res = 1;
+ else memcpy(slots + ix, &buf, sizeof(buf));
+ break;
+
+ case 'f': /* free */
+ case 'F': /* tiler-free */
+ memcpy(&buf, slots + ix, sizeof(buf));
+ switch (type)
+ {
+ case 'f':
+ if (NOT_I(buf.type,==,ptr_alloced)) break;
+ dump_slot(&buf, "==(free)=>");
+ res = free_buf(buf.num_blocks, (MemAllocBlock *) buf.blocks,
+ buf.val, (void *) buf.ptr);
+ P("<=(free)==: %d", res);
+ break;
+ case 'F':
+ if (NOT_I(buf.type,==,ptr_tiler_alloced)) break;
+ dump_slot(&buf, "==(tiler_free)=>");
+ if (buf.blocks[0].fmt == TILFMT_PAGE)
+ {
+ res = TilerMgr_PageModeFree((SSPtr) buf.ptr);
+ }
+ else
+ {
+ res = TilerMgr_Free((SSPtr) buf.ptr);
+ }
+ P("<=(tiler_free)==: %d", res);
+ break;
+ }
+ ZERO(slots[ix]);
+ break;
+ }
+ }
+
+ /* free any memmgr allocated blocks */
+ for (ix = 0; ix < num_slots; ix++)
+ {
+ if (slots[ix].type == ptr_alloced)
+ {
+ dump_slot(slots + ix, "==(free)=>");
+ int res_free = free_buf(slots[ix].num_blocks, (MemAllocBlock *) slots[ix].blocks,
+ slots[ix].val, (void *) slots[ix].ptr);
+ P("<=(free)==: %d", res_free);
+ ERR_ADD(res, res_free);
+ }
+ }
+ ERR_ADD(res, TilerMgr_Close());
+
+ FREE(slots);
+ return res;
+}
+
+/**
+ * Main test function. Checks arguments for test case ranges,
+ * runs tests and prints usage or test list if required.
+ *
+ * @author a0194118 (9/7/2009)
+ *
+ * @param argc Number of arguments
+ * @param argv Arguments
+ *
+ * @return -1 on usage or test list, otherwise # of failed
+ * tests.
+ */
+int main(int argc, char **argv)
+{
+ int res = param_test(argc, argv);
+ P(res ? "FAILURE: %d" : "SUCCESS", res);
+ return res;
+}
+
diff --git a/tiler/tilermem.h b/tiler/tilermem.h
new file mode 100644
index 0000000..2c89d84
--- /dev/null
+++ b/tiler/tilermem.h
@@ -0,0 +1,79 @@
+/*
+ * tilermem.h
+ *
+ * Tiler Memory Interface functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TILERMEM_H_
+#define _TILERMEM_H_
+
+/* retrieve type definitions */
+#include "mem_types.h"
+
+/**
+ * Tiler Memory Allocator is responsible for:
+ * <ol>
+ * <li>Getting the stride information for containers(???) or
+ * buffers
+ * <li>Converting virtual addresses to physical addresses.
+ * </ol>
+ */
+
+/**
+ * Returns the tiler stride corresponding to the system space
+ * address. For 2D buffers it returns the container stride. For
+ * 1D buffers it returns the page size. For non-tiler buffers
+ * it returns 0.
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param ptr pointer to a virtual address
+ *
+ * @return The stride of the block that contains the address.
+ */
+bytes_t TilerMem_GetStride(SSPtr ssptr);
+
+/**
+ * Retrieves the physical system-space address that corresponds
+ * to the virtual address.
+ *
+ * @author a0194118 (9/1/2009)
+ *
+ * @param ptr pointer to a virtual address
+ *
+ * @return The physical system-space address that the virtual
+ * address refers to. If the virtual address is invalid
+ * or unmapped, it returns 0.
+ */
+SSPtr TilerMem_VirtToPhys(void *ptr);
+
+#endif
diff --git a/tiler/tilermem_utils.h b/tiler/tilermem_utils.h
new file mode 100644
index 0000000..1d6210d
--- /dev/null
+++ b/tiler/tilermem_utils.h
@@ -0,0 +1,52 @@
+/*
+ * tilermem_utils.h
+ *
+ * Memory Allocator Interface internal definitions and functions needed for
+ * unit testing.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TILERMEM_UTILS_H_
+#define _TILERMEM_UTILS_H_
+
+#include <tiler.h>
+
+#define TILER_PAGE_WIDTH 64
+#define TILER_PAGE_HEIGHT 64
+
+#define TILER_STRIDE_8BIT (TILER_WIDTH * TILER_PAGE_WIDTH)
+#define TILER_STRIDE_16BIT (TILER_WIDTH * TILER_PAGE_WIDTH * 2)
+#define TILER_STRIDE_32BIT (TILER_WIDTH * TILER_PAGE_WIDTH * 2)
+
+#define PAGE_SIZE TILER_PAGE
+
+#endif
+
diff --git a/tiler/tilermgr.c b/tiler/tilermgr.c
new file mode 100644
index 0000000..470de5c
--- /dev/null
+++ b/tiler/tilermgr.c
@@ -0,0 +1,203 @@
+/*
+ * tilermgr.c
+ *
+ * TILER library support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h> /* strerror() */
+#include <fcntl.h> /* open() */
+#include <unistd.h> /* close() */
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <tiler.h>
+#include "tilermgr.h"
+#include "mem_types.h"
+
+
+#define TILERMGR_ERROR() \
+ fprintf(stderr, "%s()::%d: errno(%d) - \"%s\"\n", \
+ __FUNCTION__, __LINE__, errno, strerror(errno)); \
+ fflush(stderr);
+
+static int fd;
+
+int TilerMgr_Close()
+{
+ close(fd);
+ return TILERMGR_ERR_NONE;
+}
+
+int TilerMgr_Open()
+{
+ fd = open(TILER_DEVICE_PATH, O_RDWR);
+ if (fd < 0) {
+ TILERMGR_ERROR();
+ return TILERMGR_ERR_GENERIC;
+ }
+
+ return TILERMGR_ERR_NONE;
+}
+
+SSPtr TilerMgr_Alloc(enum pixel_fmt_t pixfmt, pixels_t width, pixels_t height)
+{
+ int ret = -1;
+ struct tiler_block_info block = {0};
+
+ if (pixfmt < PIXEL_FMT_8BIT || pixfmt > PIXEL_FMT_32BIT)
+ return 0x0;
+ if (width <= 0 || width > TILER_WIDTH * 64)
+ return 0x0;
+ if (height <= 0 || height > TILER_HEIGHT * 64)
+ return 0x0;
+
+ block.fmt = pixfmt;
+ block.dim.area.width = width;
+ block.dim.area.height = height;
+
+ ret = ioctl(fd, TILIOC_GBLK, (unsigned long)(&block));
+ if (ret < 0) {
+ TILERMGR_ERROR();
+ return 0x0;
+ }
+ return block.ssptr;
+}
+
+int TilerMgr_Free(SSPtr addr)
+{
+ int ret = -1;
+ struct tiler_block_info block = {0};
+
+ if (addr < TILER_MEM_8BIT || addr >= TILER_MEM_PAGED)
+ return TILERMGR_ERR_GENERIC;
+
+ block.ssptr = addr;
+
+ ret = ioctl(fd, TILIOC_FBLK, (unsigned long)(&block));
+ if (ret < 0) {
+ TILERMGR_ERROR();
+ return TILERMGR_ERR_GENERIC;
+ }
+ return TILERMGR_ERR_NONE;
+}
+
+SSPtr TilerMgr_PageModeAlloc(bytes_t len)
+{
+ int ret = -1;
+ struct tiler_block_info block = {0};
+
+ if(len < 0 || len > TILER_LENGTH)
+ return 0x0;
+
+ block.fmt = TILFMT_PAGE;
+ block.dim.len = len;
+
+ ret = ioctl(fd, TILIOC_GBLK, (unsigned long)(&block));
+ if (ret < 0) {
+ TILERMGR_ERROR();
+ return 0x0;
+ }
+ return block.ssptr;
+}
+
+int TilerMgr_PageModeFree(SSPtr addr)
+{
+ int ret = -1;
+ struct tiler_block_info block = {0};
+
+ if (addr < TILER_MEM_PAGED || addr >= TILER_MEM_END)
+ return TILERMGR_ERR_GENERIC;
+
+ block.ssptr = addr;
+
+ ret = ioctl(fd, TILIOC_FBLK, (unsigned long)(&block));
+ if (ret < 0) {
+ TILERMGR_ERROR();
+ return TILERMGR_ERR_GENERIC;
+ }
+ return TILERMGR_ERR_NONE;
+}
+
+SSPtr TilerMgr_VirtToPhys(void *ptr)
+{
+ int ret = -1;
+ unsigned long tmp = 0x0;
+
+ if(ptr == NULL)
+ return 0x0;
+
+ tmp = (unsigned long)ptr;
+ ret = ioctl(fd, TILIOC_GSSP, tmp);
+
+ return (SSPtr)ret;
+}
+
+SSPtr TilerMgr_Map(void *ptr, bytes_t len)
+{
+ int ret = -1;
+ struct tiler_block_info block = {0};
+
+ if (len < 0 || len > TILER_LENGTH)
+ return 0x0;
+
+ block.fmt = TILFMT_PAGE;
+ block.dim.len = len;
+ block.ptr = ptr;
+
+ ret = ioctl(fd, TILIOC_MBLK, (unsigned long)(&block));
+ if (ret < 0) {
+ TILERMGR_ERROR();
+ return 0x0;
+ }
+ return block.ssptr;
+}
+
+int TilerMgr_Unmap(SSPtr addr)
+{
+ int ret = -1;
+ struct tiler_block_info block = {0};
+
+ if (addr < TILER_MEM_PAGED || addr >= TILER_MEM_END)
+ return TILERMGR_ERR_GENERIC;
+
+ block.ssptr = addr;
+
+ ret = ioctl(fd, TILIOC_UMBLK, (unsigned long)(&block));
+ if (ret < 0) {
+ TILERMGR_ERROR();
+ return TILERMGR_ERR_GENERIC;
+ }
+ return TILERMGR_ERR_NONE;
+}
+
diff --git a/tiler/tilermgr.h b/tiler/tilermgr.h
new file mode 100644
index 0000000..cd76822
--- /dev/null
+++ b/tiler/tilermgr.h
@@ -0,0 +1,54 @@
+/*
+ * tilermgr.h
+ *
+ * TILER library support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TILERMGR_H_
+#define _TILERMGR_H_
+
+#include "mem_types.h"
+
+#define TILERMGR_ERR_NONE (0)
+#define TILERMGR_ERR_GENERIC (-1)
+
+int TilerMgr_Open();
+int TilerMgr_Close();
+SSPtr TilerMgr_Alloc(enum pixel_fmt_t pixfmt, pixels_t width, pixels_t height);
+int TilerMgr_Free(SSPtr ssptr);
+SSPtr TilerMgr_PageModeAlloc(bytes_t length);
+int TilerMgr_PageModeFree(SSPtr ssptr);
+SSPtr TilerMgr_Map(void *ptr, bytes_t length);
+int TilerMgr_Unmap(SSPtr ssptr);
+SSPtr TilerMgr_VirtToPhys(void *ptr);
+
+#endif
diff --git a/tiler/utils.h b/tiler/utils.h
new file mode 100644
index 0000000..d194a43
--- /dev/null
+++ b/tiler/utils.h
@@ -0,0 +1,63 @@
+/*
+ * utils.h
+ *
+ * Utility definitions for the Memory Interface for TI OMAP processors.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+/* ---------- Generic Macros Used in Macros ---------- */
+
+/* allocation macro */
+#define NEW(type) (type*)calloc(1, sizeof(type))
+#define NEWN(type,n) (type*)calloc(n, sizeof(type))
+#define ALLOC(var) var = calloc(1, sizeof(*var))
+#define ALLOCN(var,n) var = calloc(n, sizeof(*var))
+
+
+/* free variable and set it to NULL */
+#define FREE(var) do { free(var); var = NULL; } while(0)
+
+/* clear variable */
+#define ZERO(var) memset(&(var), 0, sizeof(var))
+
+/* binary round methods */
+#define ROUND_DOWN_TO2POW(x, N) ((x) & ~((N)-1))
+#define ROUND_UP_TO2POW(x, N) ROUND_DOWN_TO2POW((x) + (N) - 1, N)
+
+/* regulare round methods */
+#define ROUND_DOWN_TO(x, N) ((x) / (N) * (N))
+#define ROUND_UP_TO(x, N) ROUND_DOWN_TO((x) + (N) - 1, N)
+
+#endif
+
diff --git a/tiler/utils_test.c b/tiler/utils_test.c
new file mode 100644
index 0000000..c152125
--- /dev/null
+++ b/tiler/utils_test.c
@@ -0,0 +1,489 @@
+/*
+ * utils_test.c
+ *
+ * Memory Allocator Utility tests.
+ *
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define __DEBUG__
+#define __DEBUG_ASSERT__
+#define __DEBUG_ENTRY__
+
+#include <utils.h>
+#include <list_utils.h>
+#include <debug_utils.h>
+#include "testlib.h"
+
+#define TESTS\
+ T(test_new())\
+ T(test_list())\
+ T(test_ezlist())\
+ T(test_dzlist())\
+ T(test_plist())\
+ T(test_mlist())\
+ T(test_math())
+
+#define F() in = head.next;
+#define N(a) res |= NOT_P(in,!=,&head); \
+ res |= NOT_P(in->me,!=,NULL) || NOT_I(in->me->data,==,a); in = in->next;
+#define Z(a) res |= NOT_P(in,!=,&head); \
+ res |= NOT_I(in->data,==,a); in = in->next;
+#define L() res |= NOT_P(in,==,&head);
+
+int all_zero(int *p, int len)
+{
+ IN;
+ int ix = 0;
+ for (ix = 0; ix < len; ix ++)
+ {
+ if (p[ix])
+ {
+ P("[%d]=%d\n", ix, p[ix]);
+ return R_I(1);
+ }
+ }
+ return R_I(0);
+}
+
+int test_new() {
+ IN;
+ int *p;
+ p = NEW(int);
+ int res = NOT_I(all_zero(p, 1),==,0);
+ FREE(p);
+ res |= NOT_I(p,==,NULL);
+ p = NEWN(int, 8000);
+ res |= NOT_I(all_zero(p, 8000),==,0);
+ FREE(p);
+ p = NEWN(int, 1000000);
+ res |= NOT_I(all_zero(p, 1000000),==,0);
+ FREE(p);
+ return R_I(res);
+}
+
+int test_list() {
+ IN;
+
+ struct elem {
+ int data;
+ } *elA, *elB;
+ struct list {
+ struct elem *me;
+ struct list *last, *next;
+ } head, *inA, *inB, *in, *in_safe;
+
+ /* initialization */
+ DLIST_INIT(head);
+ int res = NOT_I(DLIST_IS_EMPTY(head),!=,0);
+
+ /* add element at beginning of list */
+ elA = NEW(struct elem);
+ elA->data = 1;
+ inA = NEW(struct list);
+ DLIST_ADD_AFTER(head, elA, *inA);
+ F()N(1)L();
+
+ /* add element after an element */
+ elB = NEW(struct elem);
+ elB->data = 2;
+ inB = NEW(struct list);
+ DLIST_ADD_AFTER(*inA, elB, *inB);
+ F()N(1)N(2)L();
+
+ /* add element at the end of the list */
+ elB = NEW(struct elem);
+ inB = NEW(struct list);
+ (DLIST_ADD_BEFORE(head, elB, *inB))->data = 3;
+ F()N(1)N(2)N(3)L();
+
+ /* move an element to another position or another list */
+ DLIST_MOVE_AFTER(head, *inB);
+ F()N(3)N(1)N(2)L();
+
+ DLIST_MOVE_BEFORE(head, *inB);
+ F()N(1)N(2)N(3)L();
+
+ /* works even if the position is the same */
+ DLIST_MOVE_BEFORE(head, *inB);
+ F()N(1)N(2)N(3)L();
+
+ res |= NOT_I(DLIST_FIRST(head)->data,==,1);
+ res |= NOT_I(DLIST_LAST(head)->data,==,3);
+
+ DLIST_LOOP(head, in) {
+ P("%d", in->me->data);
+ }
+ P(".");
+
+ /* remove elements */
+ DLIST_SAFE_LOOP(head, in, in_safe) {
+ if (in->me->data > 1)
+ {
+ DLIST_REMOVE(*in);
+ FREE(in->me);
+ FREE(in);
+ }
+ }
+ F()N(1)L();
+
+ /* delete list */
+ DLIST_SAFE_LOOP(head, in, in_safe) {
+ DLIST_REMOVE(*in);
+ FREE(in->me);
+ FREE(in);
+ }
+ F()L();
+
+ return R_I(res);
+}
+
+int test_ezlist() {
+ IN;
+
+ struct elem {
+ int data;
+ struct elem *me, *last, *next;
+ } *elA, *elB, head, *el, *el_safe, *in;
+
+ /* initialization */
+ DLIST_INIT(head);
+ int res = NOT_I(DLIST_IS_EMPTY(head),!=,0);
+
+ /* add element at beginning of list */
+ elA = NEW(struct elem);
+ elA->data = 1;
+ DLIST_ADD_AFTER(head, elA, *elA);
+ F()N(1)L();
+
+ /* add element after an element */
+ elB = NEW(struct elem);
+ elB->data = 2;
+ DLIST_ADD_AFTER(*elA, elB, *elB);
+ F()N(1)N(2)L();
+
+ /* add element at the end of the list */
+ elB = NEW(struct elem);
+ (DLIST_ADD_BEFORE(head, elB, *elB))->data = 3;
+ F()N(1)N(2)N(3)L();
+
+ /* move an element to another position or another list */
+ DLIST_MOVE_AFTER(head, *elB);
+ F()N(3)N(1)N(2)L();
+
+ DLIST_MOVE_BEFORE(head, *elB);
+ F()N(1)N(2)N(3)L();
+
+ /* works even if the position is the same */
+ DLIST_MOVE_BEFORE(head, *elB);
+ F()N(1)N(2)N(3)L();
+
+ res |= NOT_I(DLIST_FIRST(head)->data,==,1);
+ res |= NOT_I(DLIST_LAST(head)->data,==,3);
+
+ DLIST_LOOP(head, el) {
+ P("%d", el->data);
+ }
+ P(".");
+
+ /* remove elements */
+ DLIST_SAFE_RLOOP(head, el, el_safe) {
+ if (el->me->data == 1)
+ {
+ DLIST_REMOVE(*el);
+ FREE(el);
+ }
+ }
+ F()N(2)N(3)L();
+
+ /* delete list */
+ DLIST_SAFE_LOOP(head, el, el_safe) {
+ DLIST_REMOVE(*el);
+ FREE(el);
+ }
+ F()L();
+
+ return R_I(res);
+}
+
+int test_dzlist() {
+ IN;
+
+ struct elem {
+ int data;
+ struct elem *last, *next;
+ } *elA, *elB, head, *el, *el_safe, *in;
+
+ /* initialization */
+ DZLIST_INIT(head);
+ int res = NOT_I(DZLIST_IS_EMPTY(head),!=,0);
+
+ /* add element at beginning of list */
+ elA = NEW(struct elem);
+ elA->data = 1;
+ DZLIST_ADD_AFTER(head, *elA);
+ F()Z(1)L();
+
+ /* add element after an element */
+ elB = NEW(struct elem);
+ elB->data = 2;
+ DZLIST_ADD_AFTER(*elA, *elB);
+ F()Z(1)Z(2)L();
+
+ /* add element at the end of the list */
+ elB = NEW(struct elem);
+ (DZLIST_ADD_BEFORE(head, *elB))->data = 3;
+ F()Z(1)Z(2)Z(3)L();
+
+ /* move an element to another position or another list */
+ DZLIST_MOVE_AFTER(head, *elB);
+ F()Z(3)Z(1)Z(2)L();
+
+ DZLIST_MOVE_BEFORE(head, *elB);
+ F()Z(1)Z(2)Z(3)L();
+
+ /* works even if the position is the same */
+ DZLIST_MOVE_BEFORE(head, *elB);
+ F()Z(1)Z(2)Z(3)L();
+
+ res |= NOT_I(DZLIST_FIRST(head)->data,==,1);
+ res |= NOT_I(DZLIST_LAST(head)->data,==,3);
+
+ DZLIST_LOOP(head, el) {
+ P("%d", el->data);
+ }
+ P(".");
+
+ /* remove elements */
+ DZLIST_SAFE_RLOOP(head, el, el_safe) {
+ if (el->data == 1)
+ {
+ DZLIST_REMOVE(*el);
+ FREE(el);
+ }
+ }
+ F()Z(2)Z(3)L();
+
+ /* delete list */
+ DZLIST_SAFE_LOOP(head, el, el_safe) {
+ DZLIST_REMOVE(*el);
+ FREE(el);
+ }
+ F()L();
+
+ return R_I(res);
+}
+
+int test_plist() {
+ IN;
+
+ struct elem;
+ struct list {
+ struct elem *me;
+ struct list *last, *next;
+ } head, *inA, *inB, *in;
+ struct elem {
+ int data;
+ struct list *list_data;
+ } *elA, *elB, *el, *el_safe;
+
+ /* initialization */
+ DLIST_INIT(head);
+ int res = NOT_I(DLIST_IS_EMPTY(head),!=,0);
+
+ /* add element at beginning of list */
+ elA = NEW(struct elem);
+ elA->data = 1;
+ inA = NEW(struct list);
+ DLIST_PADD_AFTER(head, elA, inA, list_data);
+ F()N(1)L();
+
+ /* add element after an element */
+ elB = NEW(struct elem);
+ elB->data = 2;
+ inB = NEW(struct list);
+ DLIST_PADD_AFTER(*inA, elB, inB, list_data);
+ F()N(1)N(2)L();
+
+ /* add element at the end of the list */
+ elB = NEW(struct elem);
+ inB = NEW(struct list);
+ (DLIST_PADD_BEFORE(head, elB, inB, list_data))->data = 3;
+ F()N(1)N(2)N(3)L();
+
+ /* move an element to another position or another list */
+ DLIST_MOVE_AFTER(head, *inB);
+ F()N(3)N(1)N(2)L();
+
+ DLIST_MOVE_BEFORE(head, *inB);
+ F()N(1)N(2)N(3)L();
+
+ /* works even if the position is the same */
+ DLIST_MOVE_BEFORE(head, *inB);
+ F()N(1)N(2)N(3)L();
+
+ res |= NOT_I(DLIST_FIRST(head)->data,==,1);
+ res |= NOT_I(DLIST_LAST(head)->data,==,3);
+
+ DLIST_LOOP(head, in) {
+ P("%d", in->me->data);
+ }
+ P(".");
+ DLIST_PLOOP(head, el, list_data) {
+ P("%d", el->data);
+ }
+ P(".");
+
+ /* remove elements */
+ DLIST_SAFE_PLOOP(head, el, el_safe, list_data) {
+ if (el->data == 2)
+ {
+ DLIST_REMOVE(*el->list_data);
+ FREE(el->list_data);
+ FREE(el);
+ }
+ }
+ F()N(1)N(3)L();
+
+ /* delete list */
+ DLIST_SAFE_PLOOP(head, el, el_safe, list_data) {
+ DLIST_REMOVE(*el->list_data);
+ FREE(el->list_data);
+ FREE(el);
+ }
+ F()L();
+
+ return R_I(res);
+}
+
+int test_mlist() {
+ IN;
+
+ struct elem {
+ int data;
+ struct list {
+ struct list *last, *next;
+ struct elem *me;
+ } list_data;
+ } *elA, *elB, *el, *el_safe;
+ struct list head, *in;
+
+ /* initialization */
+ DLIST_INIT(head);
+ int res = NOT_I(DLIST_IS_EMPTY(head),!=,0);
+
+ /* add element at beginning of list */
+ elA = NEW(struct elem);
+ elA->data = 1;
+ DLIST_MADD_AFTER(head, elA, list_data);
+ F()N(1)L();
+
+ /* add element after an element */
+ elB = NEW(struct elem);
+ elB->data = 2;
+ DLIST_MADD_AFTER(elA->list_data, elB, list_data);
+ F()N(1)N(2)L();
+
+ /* add element at the end of the list */
+ elB = NEW(struct elem);
+ (DLIST_MADD_BEFORE(head, elB, list_data))->data = 3;
+ F()N(1)N(2)N(3)L();
+
+ /* move an element to another position or another list */
+ DLIST_MOVE_AFTER(head, elB->list_data);
+ F()N(3)N(1)N(2)L();
+
+ DLIST_MOVE_BEFORE(head, elB->list_data);
+ F()N(1)N(2)N(3)L();
+
+ /* works even if the position is the same */
+ DLIST_MOVE_BEFORE(head, elB->list_data);
+ F()N(1)N(2)N(3)L();
+
+ res |= NOT_I(DLIST_FIRST(head)->data,==,1);
+ res |= NOT_I(DLIST_LAST(head)->data,==,3);
+
+ DLIST_LOOP(head, in) {
+ P("%d", in->me->data);
+ }
+ P(".");
+ DLIST_MLOOP(head, el, list_data) {
+ P("%d", el->data);
+ }
+ P(".");
+
+ /* remove elements */
+ DLIST_SAFE_MLOOP(head, el, el_safe, list_data) {
+ if (el->data != 2)
+ {
+ DLIST_REMOVE(el->list_data);
+ FREE(el);
+ }
+ }
+ F()N(2)L();
+
+ /* delete list */
+ DLIST_SAFE_MLOOP(head, el, el_safe, list_data) {
+ DLIST_REMOVE(el->list_data);
+ FREE(el);
+ }
+ F()L();
+
+ return R_I(res);
+}
+
+int test_math()
+{
+ IN;
+ int res = 0;
+ res |= NOT_I(ROUND_UP_TO2POW(0, 4096),==,0);
+ res |= NOT_I(ROUND_UP_TO2POW(1, 4096),==,4096);
+ res |= NOT_I(ROUND_UP_TO2POW(4095, 4096),==,4096);
+ res |= NOT_I(ROUND_UP_TO2POW(4096, 4096),==,4096);
+ res |= NOT_I(ROUND_UP_TO2POW(4097, 4096),==,8192);
+ res |= NOT_I(ROUND_DOWN_TO2POW(0, 4096),==,0);
+ res |= NOT_I(ROUND_DOWN_TO2POW(1, 4096),==,0);
+ res |= NOT_I(ROUND_DOWN_TO2POW(4095, 4096),==,0);
+ res |= NOT_I(ROUND_DOWN_TO2POW(4096, 4096),==,4096);
+ res |= NOT_I(ROUND_DOWN_TO2POW(4097, 4096),==,4096);
+ return R_I(res);
+}
+
+DEFINE_TESTS(TESTS)
+
+int main(int argc, char **argv)
+{
+ return TestLib_Run(argc, argv, nullfn, nullfn, NULL);
+}
+
diff --git a/tm.c b/tm.c
new file mode 100644
index 0000000..c29a190
--- /dev/null
+++ b/tm.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+static void printf_log(const char *fmt, ...)
+{
+ va_list lst;
+ va_start(lst, fmt);
+ vprintf(fmt, lst);
+ va_end(lst);
+}
+
+/* Override this for non-printf reporting */
+extern void (*malloc_log)(const char *fmt, ...);
+static void ctor(void) __attribute__((constructor));
+static void ctor(void)
+{
+ malloc_log = printf_log;
+}
+
+int main(void)
+{
+ char *ptr[6];
+ char *uaf;
+ char *cf, *cb;
+
+ ptr[0] = malloc(10);
+ ptr[1] = calloc(1,20);
+ ptr[2] = malloc(30);
+ ptr[3] = malloc(40);
+ ptr[4] = malloc(50);
+ ptr[5] = malloc(60);
+
+ free(ptr[1]);
+ free(ptr[1]);
+ free(ptr[2]);
+ ptr[2] = realloc(ptr[2], 300);
+// free(ptr[2]);
+// free(ptr[2]);
+
+ uaf = ptr[3];
+ free(uaf);
+ uaf[5] = 'a';
+
+ cf = ptr[4];
+ cf[-1] = 'a';
+
+ cb = ptr[5];
+ cb[60] = 'a';
+
+ sleep(10);
+
+ return 0;
+}