diff options
author | Prateek Chaubey <chaubeyprateek@gmail.com> | 2018-01-07 20:55:14 +0530 |
---|---|---|
committer | Davide Garberi <dade.garberi@gmail.com> | 2018-01-19 14:09:15 +0100 |
commit | 6616278131edd80a12545085e06ee6b0e0a0a788 (patch) | |
tree | 0aef88ed11809a9d67f6abe4dc2ff782a14737e2 /camera/QCamera2/util | |
parent | cc4ccf34871da343111bf68d16ba4e4c67cac1dc (diff) |
msm8996-common: zuk: Import OSS Camera HAL
Tag: LA.HB.1.3.2-32600-8x96.0
Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
Diffstat (limited to 'camera/QCamera2/util')
-rw-r--r-- | camera/QCamera2/util/QCameraBufferMaps.cpp | 246 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraBufferMaps.h | 80 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraCmdThread.cpp | 225 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraCmdThread.h | 76 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraCommon.cpp | 226 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraCommon.h | 61 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraDisplay.cpp | 282 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraDisplay.h | 76 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraFlash.cpp | 413 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraFlash.h | 69 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraPerf.cpp | 545 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraPerf.h | 93 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraQueue.cpp | 464 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraQueue.h | 79 | ||||
-rw-r--r-- | camera/QCamera2/util/QCameraTrace.h | 150 |
15 files changed, 3085 insertions, 0 deletions
diff --git a/camera/QCamera2/util/QCameraBufferMaps.cpp b/camera/QCamera2/util/QCameraBufferMaps.cpp new file mode 100644 index 0000000..d7c058e --- /dev/null +++ b/camera/QCamera2/util/QCameraBufferMaps.cpp @@ -0,0 +1,246 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#define LOG_TAG "QCameraBufferMaps" + +// System dependencies +#include <utils/Errors.h> +#include <stdlib.h> +#include <string.h> + +// Camera dependencies +#include "QCameraBufferMaps.h" + +using namespace android; + +namespace qcamera { + +/*=========================================================================== + * FUNCTION : QCameraBufferMaps + * + * DESCRIPTION: default constructor of QCameraBufferMaps + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraBufferMaps::QCameraBufferMaps() +{ + memset(&mBufMapList, 0, sizeof(mBufMapList)); +} + +/*=========================================================================== + * FUNCTION : QCameraBufferMaps + * + * DESCRIPTION: copy constructor of QCameraBufferMaps + * + * PARAMETERS : + * @pBufferMaps : object to be copied + * + * RETURN : None + *==========================================================================*/ +QCameraBufferMaps::QCameraBufferMaps(const QCameraBufferMaps& pBufferMaps) +{ + memcpy(&mBufMapList, &pBufferMaps.mBufMapList, sizeof(mBufMapList)); +} + +/*=========================================================================== + * FUNCTION : QCameraBufferMaps + * + * DESCRIPTION: constructor of QCameraBufferMaps + * + * PARAMETERS : + * @pBufMapList : list of buffer maps + * + * RETURN : None + *==========================================================================*/ +QCameraBufferMaps::QCameraBufferMaps(const cam_buf_map_type_list& pBufMapList) +{ + memcpy(&mBufMapList, &pBufMapList, sizeof(mBufMapList)); +} + +/*=========================================================================== + * FUNCTION : QCameraBufferMaps + * + * DESCRIPTION: constructor of QCameraBufferMaps + * + * PARAMETERS : + * @pType : Type of buffer + * @pStreamId : Stream id + * @pFrameIndex : Frame index + * @pPlaneIndex : Plane index + * @pCookie : Could be job_id to identify mapping job + * @pFd : Origin file descriptor + * @pSize : Size of the buffer + * + * RETURN : None + *==========================================================================*/ +QCameraBufferMaps::QCameraBufferMaps(cam_mapping_buf_type pType, + uint32_t pStreamId, + uint32_t pFrameIndex, + int32_t pPlaneIndex, + uint32_t pCookie, + int32_t pFd, + size_t pSize) +{ + memset(&mBufMapList, 0, sizeof(mBufMapList)); + enqueue(pType, pStreamId, pFrameIndex, pPlaneIndex, pCookie, pFd, pSize); +} + +/*=========================================================================== + * FUNCTION : ~QCameraBufferMaps + * + * DESCRIPTION: destructor of QCameraBufferMaps + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraBufferMaps::~QCameraBufferMaps() +{ +} + +/*=========================================================================== + * FUNCTION : operator= + * + * DESCRIPTION: assignment operator of QCameraBufferMaps + * + * PARAMETERS : + * @pBufferMaps : object to be copied + * + * RETURN : *this, with updated contents + *==========================================================================*/ +QCameraBufferMaps& QCameraBufferMaps::operator=(const QCameraBufferMaps& pBufferMaps) +{ + if (&pBufferMaps != this) { + memcpy(&mBufMapList, &pBufferMaps.mBufMapList, sizeof(mBufMapList)); + } + return *this; +} + +/*=========================================================================== + * FUNCTION : enqueue + * + * DESCRIPTION: Add a buffer map + * + * PARAMETERS : + * @pType : Type of buffer + * @pStreamId : Stream id + * @pFrameIndex : Frame index + * @pPlaneIndex : Plane index + * @pCookie : Could be job_id to identify mapping job + * @pFd : Origin file descriptor + * @pSize : Size of the buffer + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +uint32_t QCameraBufferMaps::enqueue(cam_mapping_buf_type pType, + uint32_t pStreamId, + uint32_t pFrameIndex, + int32_t pPlaneIndex, + uint32_t pCookie, + int32_t pFd, + size_t pSize) +{ + uint32_t pos = mBufMapList.length++; + mBufMapList.buf_maps[pos].type = pType; + mBufMapList.buf_maps[pos].stream_id = pStreamId; + mBufMapList.buf_maps[pos].frame_idx = pFrameIndex; + mBufMapList.buf_maps[pos].plane_idx = pPlaneIndex; + mBufMapList.buf_maps[pos].cookie = pCookie; + mBufMapList.buf_maps[pos].fd = pFd; + mBufMapList.buf_maps[pos].size = pSize; + + return NO_ERROR; +} + +/*=========================================================================== + * FUNCTION : getCamBufMapList + * + * DESCRIPTION: Populate the list + * + * PARAMETERS : + * @pBufMapList : [output] the list of buffer maps + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +uint32_t QCameraBufferMaps::getCamBufMapList(cam_buf_map_type_list& pBufMapList) const +{ + memcpy(&pBufMapList, &mBufMapList, sizeof(pBufMapList)); + + return NO_ERROR; +} + +/*=========================================================================== + * FUNCTION : makeSingletonBufMapList + * + * DESCRIPTION: Create a buffer map list of a single element + * + * PARAMETERS : + * @pType : Type of buffer + * @pStreamId : Stream id + * @pFrameIndex : Frame index + * @pPlaneIndex : Plane index + * @pCookie : Could be job_id to identify mapping job + * @pFd : Origin file descriptor + * @pSize : Size of the buffer + * @pBufMapList : [output] the list of buffer maps + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +uint32_t QCameraBufferMaps::makeSingletonBufMapList(cam_mapping_buf_type pType, + uint32_t pStreamId, + uint32_t pFrameIndex, + int32_t pPlaneIndex, + uint32_t pCookie, + int32_t pFd, + size_t pSize, + cam_buf_map_type_list& pBufMapList) +{ + uint32_t rc = NO_ERROR; + + QCameraBufferMaps bufferMaps(pType, + pStreamId, + pFrameIndex, + pPlaneIndex, + pCookie, + pFd, + pSize); + rc = bufferMaps.getCamBufMapList(pBufMapList); + + return rc; +} + +}; // namespace qcamera diff --git a/camera/QCamera2/util/QCameraBufferMaps.h b/camera/QCamera2/util/QCameraBufferMaps.h new file mode 100644 index 0000000..eaa4707 --- /dev/null +++ b/camera/QCamera2/util/QCameraBufferMaps.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __QCAMERA_BUFFERMAPS_H__ +#define __QCAMERA_BUFFERMAPS_H__ + +// Camera dependencies +#include "cam_types.h" + +namespace qcamera { + +class QCameraBufferMaps { +public: + QCameraBufferMaps(); + QCameraBufferMaps(const QCameraBufferMaps& pBufferMaps); + QCameraBufferMaps(const cam_buf_map_type_list& pBufMapList); + QCameraBufferMaps(cam_mapping_buf_type pType, + uint32_t pStreamId, + uint32_t pFrameIndex, + int32_t pPlaneIndex, + uint32_t pCookie, + int32_t pFd, + size_t pSize); + + ~QCameraBufferMaps(); + + QCameraBufferMaps& operator=(const QCameraBufferMaps& pBufferMaps); + + uint32_t enqueue(cam_mapping_buf_type pType, + uint32_t pStreamId, + uint32_t pFrameIndex, + int32_t pPlaneIndex, + uint32_t pCookie, + int32_t pFd, + size_t pSize); + + uint32_t getCamBufMapList(cam_buf_map_type_list& pBufMapList) const; + + static uint32_t makeSingletonBufMapList(cam_mapping_buf_type pType, + uint32_t pStreamId, + uint32_t pFrameIndex, + int32_t pPlaneIndex, + uint32_t pCookie, + int32_t pFd, + size_t pSize, + cam_buf_map_type_list& pBufMapList); + +private: + cam_buf_map_type_list mBufMapList; +}; + +}; // namespace qcamera +#endif /* __QCAMERA_BUFFERMAPS_H__ */ + diff --git a/camera/QCamera2/util/QCameraCmdThread.cpp b/camera/QCamera2/util/QCameraCmdThread.cpp new file mode 100644 index 0000000..8b191b0 --- /dev/null +++ b/camera/QCamera2/util/QCameraCmdThread.cpp @@ -0,0 +1,225 @@ +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +// System dependencies +#include <string.h> +#include <utils/Errors.h> +#define PRCTL_H <SYSTEM_HEADER_PREFIX/prctl.h> +#include PRCTL_H + +// Camera dependencies +#include "QCameraCmdThread.h" + +extern "C" { +#include "mm_camera_dbg.h" +} + +using namespace android; + +namespace qcamera { + +/*=========================================================================== + * FUNCTION : QCameraCmdThread + * + * DESCRIPTION: default constructor of QCameraCmdThread + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraCmdThread::QCameraCmdThread() : + cmd_queue() +{ + cmd_pid = 0; + cam_sem_init(&sync_sem, 0); + cam_sem_init(&cmd_sem, 0); +} + +/*=========================================================================== + * FUNCTION : ~QCameraCmdThread + * + * DESCRIPTION: deconstructor of QCameraCmdThread + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraCmdThread::~QCameraCmdThread() +{ + exit(); + cam_sem_destroy(&sync_sem); + cam_sem_destroy(&cmd_sem); +} + +/*=========================================================================== + * FUNCTION : launch + * + * DESCRIPTION: launch Cmd Thread + * + * PARAMETERS : + * @start_routine : thread routine function ptr + * @user_data : user data ptr + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +int32_t QCameraCmdThread::launch(void *(*start_routine)(void *), + void* user_data) +{ + /* launch the thread */ + pthread_create(&cmd_pid, + NULL, + start_routine, + user_data); + return NO_ERROR; +} + +/*=========================================================================== + * FUNCTION : setName + * + * DESCRIPTION: name the cmd thread + * + * PARAMETERS : + * @name : desired name for the thread + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +int32_t QCameraCmdThread::setName(const char* name) +{ + /* name the thread */ + prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); + return NO_ERROR; +} + +/*=========================================================================== + * FUNCTION : sendCmd + * + * DESCRIPTION: send a command to the Cmd Thread + * + * PARAMETERS : + * @cmd : command to be executed. + * @sync_cmd: flag to indicate if this is a synchorinzed cmd. If true, this call + * will wait until signal is set after the command is completed. + * @priority: flag to indicate if this is a cmd with priority. If true, the cmd + * will be enqueued to the head with priority. + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +int32_t QCameraCmdThread::sendCmd(camera_cmd_type_t cmd, uint8_t sync_cmd, uint8_t priority) +{ + camera_cmd_t *node = (camera_cmd_t *)malloc(sizeof(camera_cmd_t)); + if (NULL == node) { + LOGE("No memory for camera_cmd_t"); + return NO_MEMORY; + } + memset(node, 0, sizeof(camera_cmd_t)); + node->cmd = cmd; + + if (priority) { + if (!cmd_queue.enqueueWithPriority((void *)node)) { + free(node); + node = NULL; + } + } else { + if (!cmd_queue.enqueue((void *)node)) { + free(node); + node = NULL; + } + } + cam_sem_post(&cmd_sem); + + /* if is a sync call, need to wait until it returns */ + if (sync_cmd) { + cam_sem_wait(&sync_sem); + } + return NO_ERROR; +} + +/*=========================================================================== + * FUNCTION : getCmd + * + * DESCRIPTION: dequeue a cmommand from cmd queue + * + * PARAMETERS : None + * + * RETURN : cmd dequeued + *==========================================================================*/ +camera_cmd_type_t QCameraCmdThread::getCmd() +{ + camera_cmd_type_t cmd = CAMERA_CMD_TYPE_NONE; + camera_cmd_t *node = (camera_cmd_t *)cmd_queue.dequeue(); + if (NULL == node) { + LOGD("No notify avail"); + return CAMERA_CMD_TYPE_NONE; + } else { + cmd = node->cmd; + free(node); + } + return cmd; +} + +/*=========================================================================== + * FUNCTION : exit + * + * DESCRIPTION: exit the CMD thread + * + * PARAMETERS : None + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +int32_t QCameraCmdThread::exit() +{ + int32_t rc = NO_ERROR; + + if (cmd_pid == 0) { + return rc; + } + + rc = sendCmd(CAMERA_CMD_TYPE_EXIT, 0, 1); + if (NO_ERROR != rc) { + LOGE("Error during exit, rc = %d", rc); + return rc; + } + + /* wait until cmd thread exits */ + if (pthread_join(cmd_pid, NULL) != 0) { + LOGD("pthread dead already\n"); + } + cmd_pid = 0; + return rc; +} + +}; // namespace qcamera diff --git a/camera/QCamera2/util/QCameraCmdThread.h b/camera/QCamera2/util/QCameraCmdThread.h new file mode 100644 index 0000000..b0764b6 --- /dev/null +++ b/camera/QCamera2/util/QCameraCmdThread.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2012, 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __QCAMERA_CMD_THREAD_H__ +#define __QCAMERA_CMD_THREAD_H__ + +// System dependencies +#include <pthread.h> + +// Camera dependencies +#include "cam_semaphore.h" +#include "cam_types.h" +#include "QCameraQueue.h" + +namespace qcamera { + +typedef enum +{ + CAMERA_CMD_TYPE_NONE, + CAMERA_CMD_TYPE_START_DATA_PROC, + CAMERA_CMD_TYPE_STOP_DATA_PROC, + CAMERA_CMD_TYPE_DO_NEXT_JOB, + CAMERA_CMD_TYPE_EXIT, + CAMERA_CMD_TYPE_MAX +} camera_cmd_type_t; + +typedef struct { + camera_cmd_type_t cmd; +} camera_cmd_t; + +class QCameraCmdThread { +public: + QCameraCmdThread(); + ~QCameraCmdThread(); + + int32_t launch(void *(*start_routine)(void *), void* user_data); + int32_t setName(const char* name); + int32_t exit(); + int32_t sendCmd(camera_cmd_type_t cmd, uint8_t sync_cmd, uint8_t priority); + camera_cmd_type_t getCmd(); + + QCameraQueue cmd_queue; /* cmd queue */ + pthread_t cmd_pid; /* cmd thread ID */ + cam_semaphore_t cmd_sem; /* semaphore for cmd thread */ + cam_semaphore_t sync_sem; /* semaphore for synchronized call signal */ +}; + +}; // namespace qcamera + +#endif /* __QCAMERA_CMD_THREAD_H__ */ diff --git a/camera/QCamera2/util/QCameraCommon.cpp b/camera/QCamera2/util/QCameraCommon.cpp new file mode 100644 index 0000000..0cc2654 --- /dev/null +++ b/camera/QCamera2/util/QCameraCommon.cpp @@ -0,0 +1,226 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#define LOG_TAG "QCameraCommon" + +// System dependencies +#include <utils/Errors.h> +#include <stdlib.h> +#include <string.h> +#include <utils/Log.h> + +// Camera dependencies +#include "QCameraCommon.h" + +using namespace android; + +namespace qcamera { + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/*=========================================================================== + * FUNCTION : QCameraCommon + * + * DESCRIPTION: default constructor of QCameraCommon + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraCommon::QCameraCommon() : + m_pCapability(NULL) +{ +} + +/*=========================================================================== + * FUNCTION : ~QCameraCommon + * + * DESCRIPTION: destructor of QCameraCommon + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraCommon::~QCameraCommon() +{ +} + +/*=========================================================================== + * FUNCTION : init + * + * DESCRIPTION: Init function for QCameraCommon + * + * PARAMETERS : + * @pCapability : Capabilities + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +int32_t QCameraCommon::init(cam_capability_t *pCapability) +{ + m_pCapability = pCapability; + + return NO_ERROR; +} + +/*=========================================================================== + * FUNCTION : calculateLCM + * + * DESCRIPTION: Get the LCM of 2 numbers + * + * PARAMETERS : + * @num1 : First number + * @num2 : second number + * + * RETURN : int32_t type (LCM) + * + *==========================================================================*/ +uint32_t QCameraCommon::calculateLCM(int32_t num1, int32_t num2) +{ + uint32_t lcm = 0; + uint32_t temp = 0; + + if ((num1 < 1) && (num2 < 1)) { + return 0; + } else if (num1 < 1) { + return num2; + } else if (num2 < 1) { + return num1; + } + + if (num1 > num2) { + lcm = num1; + } else { + lcm = num2; + } + temp = lcm; + + while (1) { + if (((lcm % num1) == 0) && ((lcm % num2) == 0)) { + break; + } + lcm += temp; + } + return lcm; +} + +/*=========================================================================== + * FUNCTION : getAnalysisInfo + * + * DESCRIPTION: Get the Analysis information based on + * current mode and feature mask + * + * PARAMETERS : + * @fdVideoEnabled : Whether fdVideo enabled currently + * @hal3 : Whether hal3 or hal1 + * @featureMask : Feature mask + * @pAnalysis_info : Analysis info to be filled + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + *==========================================================================*/ +int32_t QCameraCommon::getAnalysisInfo( + bool fdVideoEnabled, + bool hal3, + cam_feature_mask_t featureMask, + cam_analysis_info_t *pAnalysisInfo) +{ + if (!pAnalysisInfo) { + return BAD_VALUE; + } + + pAnalysisInfo->valid = 0; + + if ((fdVideoEnabled == TRUE) && (hal3 == FALSE) && + (m_pCapability->analysis_info[CAM_ANALYSIS_INFO_FD_VIDEO].hw_analysis_supported) && + (m_pCapability->analysis_info[CAM_ANALYSIS_INFO_FD_VIDEO].valid)) { + *pAnalysisInfo = + m_pCapability->analysis_info[CAM_ANALYSIS_INFO_FD_VIDEO]; + } else if (m_pCapability->analysis_info[CAM_ANALYSIS_INFO_FD_STILL].valid) { + *pAnalysisInfo = + m_pCapability->analysis_info[CAM_ANALYSIS_INFO_FD_STILL]; + if (hal3 == TRUE) { + pAnalysisInfo->analysis_max_res = pAnalysisInfo->analysis_recommended_res; + } + } + + if ((featureMask & CAM_QCOM_FEATURE_PAAF) && + (m_pCapability->analysis_info[CAM_ANALYSIS_INFO_PAAF].valid)) { + cam_analysis_info_t *pPaafInfo = + &m_pCapability->analysis_info[CAM_ANALYSIS_INFO_PAAF]; + + if (!pAnalysisInfo->valid) { + *pAnalysisInfo = *pPaafInfo; + } else { + pAnalysisInfo->analysis_max_res.width = + MAX(pAnalysisInfo->analysis_max_res.width, + pPaafInfo->analysis_max_res.width); + pAnalysisInfo->analysis_max_res.height = + MAX(pAnalysisInfo->analysis_max_res.height, + pPaafInfo->analysis_max_res.height); + pAnalysisInfo->analysis_padding_info.height_padding = + calculateLCM(pAnalysisInfo->analysis_padding_info.height_padding, + pPaafInfo->analysis_padding_info.height_padding); + pAnalysisInfo->analysis_padding_info.width_padding = + calculateLCM(pAnalysisInfo->analysis_padding_info.width_padding, + pPaafInfo->analysis_padding_info.width_padding); + pAnalysisInfo->analysis_padding_info.plane_padding = + calculateLCM(pAnalysisInfo->analysis_padding_info.plane_padding, + pPaafInfo->analysis_padding_info.plane_padding); + pAnalysisInfo->analysis_padding_info.min_stride = + MAX(pAnalysisInfo->analysis_padding_info.min_stride, + pPaafInfo->analysis_padding_info.min_stride); + pAnalysisInfo->analysis_padding_info.min_stride = + ALIGN(pAnalysisInfo->analysis_padding_info.min_stride, + pAnalysisInfo->analysis_padding_info.width_padding); + + pAnalysisInfo->analysis_padding_info.min_scanline = + MAX(pAnalysisInfo->analysis_padding_info.min_scanline, + pPaafInfo->analysis_padding_info.min_scanline); + pAnalysisInfo->analysis_padding_info.min_scanline = + ALIGN(pAnalysisInfo->analysis_padding_info.min_scanline, + pAnalysisInfo->analysis_padding_info.height_padding); + + pAnalysisInfo->hw_analysis_supported |= + pPaafInfo->hw_analysis_supported; + } + } + + return pAnalysisInfo->valid ? NO_ERROR : BAD_VALUE; +} + +}; // namespace qcamera diff --git a/camera/QCamera2/util/QCameraCommon.h b/camera/QCamera2/util/QCameraCommon.h new file mode 100644 index 0000000..844b087 --- /dev/null +++ b/camera/QCamera2/util/QCameraCommon.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __QCAMERA_COMMON_H__ +#define __QCAMERA_COMMON_H__ + +// Camera dependencies +#include "cam_types.h" +#include "cam_intf.h" + +namespace qcamera { + +#define ALIGN(a, b) (((a) + (b)) & ~(b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +class QCameraCommon { +public: + QCameraCommon(); + ~QCameraCommon(); + + int32_t init(cam_capability_t *cap); + + int32_t getAnalysisInfo( + bool fdVideoEnabled, bool hal3, cam_feature_mask_t featureMask, + cam_analysis_info_t *pAnalysisInfo); + static uint32_t calculateLCM(int32_t num1, int32_t num2); + +private: + cam_capability_t *m_pCapability; + +}; + +}; // namespace qcamera +#endif /* __QCAMERA_COMMON_H__ */ + diff --git a/camera/QCamera2/util/QCameraDisplay.cpp b/camera/QCamera2/util/QCameraDisplay.cpp new file mode 100644 index 0000000..108cc72 --- /dev/null +++ b/camera/QCamera2/util/QCameraDisplay.cpp @@ -0,0 +1,282 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#define LOG_TAG "QCameraDisplay" + +// To remove +#include <cutils/properties.h> + +// Camera dependencies +#include "QCamera2HWI.h" +#include "QCameraDisplay.h" + +extern "C" { +#include "mm_camera_dbg.h" +} + +#define CAMERA_VSYNC_WAIT_MS 33 // Used by vsync thread to wait for vsync timeout. +#define DISPLAY_EVENT_RECEIVER_ARRAY_SIZE 1 +#define DISPLAY_DEFAULT_FPS 60 + +namespace qcamera { + +/*=========================================================================== + * FUNCTION : vsyncEventReceiverCamera + * + * DESCRIPTION: Computes average vsync interval. Called by display + * event handler for every vsync event. + * + * PARAMETERS : + * @fd : file descriptor + * @events : events + * @data : pointer to user data provided during call back registration. + * + * RETURN : always returns 1 + *==========================================================================*/ +int QCameraDisplay::vsyncEventReceiverCamera(__unused int fd, + __unused int events, void* data) { + android::DisplayEventReceiver::Event buffer[DISPLAY_EVENT_RECEIVER_ARRAY_SIZE]; + QCameraDisplay* pQCameraDisplay = (QCameraDisplay *) data; + ssize_t n; + + while ((n = pQCameraDisplay->mDisplayEventReceiver.getEvents(buffer, + DISPLAY_EVENT_RECEIVER_ARRAY_SIZE)) > 0) { + for (int i = 0 ; i < n ; i++) { + if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { + pQCameraDisplay->computeAverageVsyncInterval(buffer[i].header.timestamp); + } + } + } + return 1; +} + +/*=========================================================================== + * FUNCTION : vsyncThreadCamera + * + * DESCRIPTION: Thread registers a call back function for every vsync event + * waits on the looper for the next vsync. + * + * PARAMETERS : + * @data : receives vsync_info_t structure. + * + * RETURN : NULL.Just to fullfill the type requirement of thread function. + *==========================================================================*/ +void* QCameraDisplay::vsyncThreadCamera(void * data) +{ + QCameraDisplay* pQCameraDisplay = (QCameraDisplay *) data; + android::sp<Looper> looper; + + looper = new android::Looper(false); + status_t status = pQCameraDisplay->mDisplayEventReceiver.initCheck(); + if (status != NO_ERROR) { + LOGE("Initialization of DisplayEventReceiver failed with status: %d", status); + return NULL; + } + looper->addFd(pQCameraDisplay->mDisplayEventReceiver.getFd(), 0, ALOOPER_EVENT_INPUT, + QCameraDisplay::vsyncEventReceiverCamera, pQCameraDisplay); + pQCameraDisplay->mDisplayEventReceiver.setVsyncRate(1); + while(pQCameraDisplay->mThreadExit == 0) + { + looper->pollOnce(CAMERA_VSYNC_WAIT_MS); + } + return NULL; +} + +/*=========================================================================== + * FUNCTION : ~QCameraDisplay + * + * DESCRIPTION: constructor of QCameraDisplay + * + * PARAMETERS : none + * + * RETURN : none + *==========================================================================*/ +QCameraDisplay::QCameraDisplay() + : mVsyncTimeStamp(0), + mAvgVsyncInterval(0), + mOldTimeStamp(0), + mVsyncHistoryIndex(0), + mAdditionalVsyncOffsetForWiggle(0), + mThreadExit(0), + mNum_vsync_from_vfe_isr_to_presentation_timestamp(0), + mSet_timestamp_num_ms_prior_to_vsync(0), + mVfe_and_mdp_freq_wiggle_filter_max_ms(0), + mVfe_and_mdp_freq_wiggle_filter_min_ms(0) +{ + int rc = NO_ERROR; + + memset(&mVsyncIntervalHistory, 0, sizeof(mVsyncIntervalHistory)); + rc = pthread_create(&mVsyncThreadCameraHandle, NULL, vsyncThreadCamera, (void *)this); + if (rc == NO_ERROR) { + char value[PROPERTY_VALUE_MAX]; + nsecs_t default_vsync_interval; + pthread_setname_np(mVsyncThreadCameraHandle, "CAM_Vsync_Thread"); + // Read a list of properties used for tuning + property_get("persist.camera.disp.num_vsync", value, "4"); + mNum_vsync_from_vfe_isr_to_presentation_timestamp = atoi(value); + property_get("persist.camera.disp.ms_to_vsync", value, "2"); + mSet_timestamp_num_ms_prior_to_vsync = atoi(value); + property_get("persist.camera.disp.filter_max", value, "2"); + mVfe_and_mdp_freq_wiggle_filter_max_ms = atoi(value); + property_get("persist.camera.disp.filter_min", value, "4"); + mVfe_and_mdp_freq_wiggle_filter_min_ms = atoi(value); + property_get("persist.camera.disp.fps", value, "60"); + if (atoi(value) > 0) { + default_vsync_interval= s2ns(1) / atoi(value); + } else { + default_vsync_interval= s2ns(1) / DISPLAY_DEFAULT_FPS; + } + for (int i=0; i < CAMERA_NUM_VSYNC_INTERVAL_HISTORY; i++) { + mVsyncIntervalHistory[i] = default_vsync_interval; + } + LOGD("display jitter num_vsync_from_vfe_isr_to_presentation_timestamp %u \ + set_timestamp_num_ms_prior_to_vsync %u", + mNum_vsync_from_vfe_isr_to_presentation_timestamp, + mSet_timestamp_num_ms_prior_to_vsync); + LOGD("display jitter vfe_and_mdp_freq_wiggle_filter_max_ms %u \ + vfe_and_mdp_freq_wiggle_filter_min_ms %u", + mVfe_and_mdp_freq_wiggle_filter_max_ms, + mVfe_and_mdp_freq_wiggle_filter_min_ms); + } else { + mVsyncThreadCameraHandle = 0; + } +} + +/*=========================================================================== + * FUNCTION : ~QCameraDisplay + * + * DESCRIPTION: destructor of QCameraDisplay + * + * PARAMETERS : none + * + * RETURN : none + *==========================================================================*/ +QCameraDisplay::~QCameraDisplay() +{ + mThreadExit = 1; + if (mVsyncThreadCameraHandle != 0) { + pthread_join(mVsyncThreadCameraHandle, NULL); + } +} + +/*=========================================================================== + * FUNCTION : computeAverageVsyncInterval + * + * DESCRIPTION: Computes average vsync interval using current and previously + * stored vsync data. + * + * PARAMETERS : current vsync time stamp + * + * RETURN : none + *==========================================================================*/ +void QCameraDisplay::computeAverageVsyncInterval(nsecs_t currentVsyncTimeStamp) +{ + nsecs_t sum; + nsecs_t vsyncMaxOutlier; + nsecs_t vsyncMinOutlier; + + mVsyncTimeStamp = currentVsyncTimeStamp; + if (mOldTimeStamp) { + // Compute average vsync interval using current and previously stored vsync data. + // Leave the max and min vsync interval from history in computing the average. + mVsyncIntervalHistory[mVsyncHistoryIndex] = currentVsyncTimeStamp - mOldTimeStamp; + mVsyncHistoryIndex++; + mVsyncHistoryIndex = mVsyncHistoryIndex % CAMERA_NUM_VSYNC_INTERVAL_HISTORY; + sum = mVsyncIntervalHistory[0]; + vsyncMaxOutlier = mVsyncIntervalHistory[0]; + vsyncMinOutlier = mVsyncIntervalHistory[0]; + for (int j=1; j<CAMERA_NUM_VSYNC_INTERVAL_HISTORY; j++) { + sum += mVsyncIntervalHistory[j]; + if (vsyncMaxOutlier < mVsyncIntervalHistory[j]) { + vsyncMaxOutlier = mVsyncIntervalHistory[j]; + } else if (vsyncMinOutlier > mVsyncIntervalHistory[j]) { + vsyncMinOutlier = mVsyncIntervalHistory[j]; + } + } + sum = sum - vsyncMaxOutlier - vsyncMinOutlier; + mAvgVsyncInterval = sum / (CAMERA_NUM_VSYNC_INTERVAL_HISTORY - 2); + } + mOldTimeStamp = currentVsyncTimeStamp; +} + +/*=========================================================================== + * FUNCTION : computePresentationTimeStamp + * + * DESCRIPTION: Computes presentation time stamp using vsync interval + * and last vsync time stamp and few other tunable variables + * to place the time stamp at the expected future vsync + * + * PARAMETERS : current frame time stamp set by VFE when buffer copy done. + * + * RETURN : time stamp in future or 0 in case of failure. + *==========================================================================*/ +nsecs_t QCameraDisplay::computePresentationTimeStamp(nsecs_t frameTimeStamp) +{ + nsecs_t moveToNextVsync; + nsecs_t keepInCurrentVsync; + nsecs_t timeDifference = 0; + nsecs_t presentationTimeStamp = 0; + int expectedVsyncOffset = 0; + int vsyncOffset; + + if ( (mAvgVsyncInterval != 0) && (mVsyncTimeStamp != 0) ) { + // Compute presentation time stamp in future as per the following formula + // future time stamp = vfe time stamp + N * average vsync interval + // Adjust the time stamp so that it is placed few milliseconds before + // the expected vsync. + // Adjust the time stamp for the period where vsync time stamp and VFE + // timstamp cross over due difference in fps. + presentationTimeStamp = frameTimeStamp + + (mNum_vsync_from_vfe_isr_to_presentation_timestamp * mAvgVsyncInterval); + if (presentationTimeStamp > mVsyncTimeStamp) { + timeDifference = presentationTimeStamp - mVsyncTimeStamp; + moveToNextVsync = mAvgVsyncInterval - mVfe_and_mdp_freq_wiggle_filter_min_ms; + keepInCurrentVsync = mAvgVsyncInterval - mVfe_and_mdp_freq_wiggle_filter_max_ms; + vsyncOffset = timeDifference % mAvgVsyncInterval; + expectedVsyncOffset = mAvgVsyncInterval - + mSet_timestamp_num_ms_prior_to_vsync - vsyncOffset; + if (vsyncOffset > moveToNextVsync) { + mAdditionalVsyncOffsetForWiggle = mAvgVsyncInterval; + } else if (vsyncOffset < keepInCurrentVsync) { + mAdditionalVsyncOffsetForWiggle = 0; + } + LOGD("vsyncTimeStamp: %llu presentationTimeStamp: %llu expectedVsyncOffset: %d \ + timeDifference: %llu vsyncffset: %d avgvsync: %llu \ + additionalvsyncOffsetForWiggle: %llu", + mVsyncTimeStamp, presentationTimeStamp, expectedVsyncOffset, + timeDifference, vsyncOffset, mAvgVsyncInterval, + mAdditionalVsyncOffsetForWiggle); + } + presentationTimeStamp = presentationTimeStamp + expectedVsyncOffset + + mAdditionalVsyncOffsetForWiggle; + } + return presentationTimeStamp; +} + +}; // namespace qcamera diff --git a/camera/QCamera2/util/QCameraDisplay.h b/camera/QCamera2/util/QCameraDisplay.h new file mode 100644 index 0000000..8b7e4c9 --- /dev/null +++ b/camera/QCamera2/util/QCameraDisplay.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __QCAMERADISPLAY_H__ +#define __QCAMERADISPLAY_H__ + +#include <gui/DisplayEventReceiver.h> +#include <android/looper.h> +#include <utils/Looper.h> + +namespace qcamera { + +#define CAMERA_NUM_VSYNC_INTERVAL_HISTORY 6 + +class QCameraDisplay { +public: + QCameraDisplay(); + ~QCameraDisplay(); + static int vsyncEventReceiverCamera(int fd, int events, void* data); + static void* vsyncThreadCamera(void * data); + void computeAverageVsyncInterval(nsecs_t currentVsyncTimeStamp); + nsecs_t computePresentationTimeStamp(nsecs_t frameTimeStamp); + +private: + pthread_t mVsyncThreadCameraHandle; + nsecs_t mVsyncTimeStamp; + nsecs_t mAvgVsyncInterval; + nsecs_t mOldTimeStamp; + nsecs_t mVsyncIntervalHistory[CAMERA_NUM_VSYNC_INTERVAL_HISTORY]; + nsecs_t mVsyncHistoryIndex; + nsecs_t mAdditionalVsyncOffsetForWiggle; + uint32_t mThreadExit; + // Tunable property. Increasing this will increase the frame delay and will loose + // the real time display. + uint32_t mNum_vsync_from_vfe_isr_to_presentation_timestamp; + // Tunable property. Set the time stamp x ms prior to expected vsync so that + // it will be picked in that vsync + uint32_t mSet_timestamp_num_ms_prior_to_vsync; + // Tunable property for filtering timestamp wiggle when VFE ISR crosses + // over MDP ISR over a period. Typical scenario is VFE is running at + // 30.2 fps vs display running at 60 fps. + uint32_t mVfe_and_mdp_freq_wiggle_filter_max_ms; + uint32_t mVfe_and_mdp_freq_wiggle_filter_min_ms; + + android::DisplayEventReceiver mDisplayEventReceiver; +}; + +}; // namespace qcamera + +#endif /* __QCAMERADISPLAY_H__ */ diff --git a/camera/QCamera2/util/QCameraFlash.cpp b/camera/QCamera2/util/QCameraFlash.cpp new file mode 100644 index 0000000..db517b6 --- /dev/null +++ b/camera/QCamera2/util/QCameraFlash.cpp @@ -0,0 +1,413 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +// System dependencies +#include <stdio.h> +#include <fcntl.h> +#include <media/msm_cam_sensor.h> + +// Camera dependencies +#include "HAL3/QCamera3HWI.h" +#include "QCameraFlash.h" + +extern "C" { +#include "mm_camera_dbg.h" +} + +#define STRING_LENGTH_OF_64_BIT_NUMBER 21 + +volatile uint32_t gCamHal3LogLevel = 1; + +namespace qcamera { + +/*=========================================================================== + * FUNCTION : getInstance + * + * DESCRIPTION: Get and create the QCameraFlash singleton. + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraFlash& QCameraFlash::getInstance() +{ + static QCameraFlash flashInstance; + return flashInstance; +} + +/*=========================================================================== + * FUNCTION : QCameraFlash + * + * DESCRIPTION: default constructor of QCameraFlash + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraFlash::QCameraFlash() : m_callbacks(NULL) +{ + memset(&m_flashOn, 0, sizeof(m_flashOn)); + memset(&m_cameraOpen, 0, sizeof(m_cameraOpen)); + for (int pos = 0; pos < MM_CAMERA_MAX_NUM_SENSORS; pos++) { + m_flashFds[pos] = -1; + } +} + +/*=========================================================================== + * FUNCTION : ~QCameraFlash + * + * DESCRIPTION: deconstructor of QCameraFlash + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraFlash::~QCameraFlash() +{ + for (int pos = 0; pos < MM_CAMERA_MAX_NUM_SENSORS; pos++) { + if (m_flashFds[pos] >= 0) + { + setFlashMode(pos, false); + close(m_flashFds[pos]); + m_flashFds[pos] = -1; + } + } +} + +/*=========================================================================== + * FUNCTION : registerCallbacks + * + * DESCRIPTION: provide flash module with reference to callbacks to framework + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +int32_t QCameraFlash::registerCallbacks( + const camera_module_callbacks_t* callbacks) +{ + int32_t retVal = 0; + m_callbacks = callbacks; + return retVal; +} + +/*=========================================================================== + * FUNCTION : initFlash + * + * DESCRIPTION: Reserve and initialize the flash unit associated with a + * given camera id. This function is blocking until the + * operation completes or fails. Each flash unit can be "inited" + * by only one process at a time. + * + * PARAMETERS : + * @camera_id : Camera id of the flash. + * + * RETURN : + * 0 : success + * -EBUSY : The flash unit or the resource needed to turn on the + * the flash is busy, typically because the flash is + * already in use. + * -EINVAL : No flash present at camera_id. + *==========================================================================*/ +int32_t QCameraFlash::initFlash(const int camera_id) +{ + int32_t retVal = 0; + bool hasFlash = false; + char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; + char flashPath[QCAMERA_MAX_FILEPATH_LENGTH] = "/dev/"; + + if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { + LOGE("Invalid camera id: %d", camera_id); + return -EINVAL; + } + + QCamera3HardwareInterface::getFlashInfo(camera_id, + hasFlash, + flashNode); + + strlcat(flashPath, + flashNode, + sizeof(flashPath)); + + if (!hasFlash) { + LOGE("No flash available for camera id: %d", + camera_id); + retVal = -EINVAL; + } else if (m_cameraOpen[camera_id]) { + LOGE("Camera in use for camera id: %d", + camera_id); + retVal = -EBUSY; + } else if (m_flashFds[camera_id] >= 0) { + LOGD("Flash is already inited for camera id: %d", + camera_id); + } else { + m_flashFds[camera_id] = open(flashPath, O_RDWR | O_NONBLOCK); + + if (m_flashFds[camera_id] < 0) { + LOGE("Unable to open node '%s'", + flashPath); + retVal = -EBUSY; + } else { + struct msm_flash_cfg_data_t cfg; + struct msm_flash_init_info_t init_info; + memset(&cfg, 0, sizeof(struct msm_flash_cfg_data_t)); + memset(&init_info, 0, sizeof(struct msm_flash_init_info_t)); + init_info.flash_driver_type = FLASH_DRIVER_DEFAULT; + cfg.cfg.flash_init_info = &init_info; + cfg.cfg_type = CFG_FLASH_INIT; + retVal = ioctl(m_flashFds[camera_id], + VIDIOC_MSM_FLASH_CFG, + &cfg); + if (retVal < 0) { + LOGE("Unable to init flash for camera id: %d", + camera_id); + close(m_flashFds[camera_id]); + m_flashFds[camera_id] = -1; + } + + /* wait for PMIC to init */ + usleep(5000); + } + } + + LOGD("X, retVal = %d", retVal); + return retVal; +} + +/*=========================================================================== + * FUNCTION : setFlashMode + * + * DESCRIPTION: Turn on or off the flash associated with a given handle. + * This function is blocking until the operation completes or + * fails. + * + * PARAMETERS : + * @camera_id : Camera id of the flash + * @on : Whether to turn flash on (true) or off (false) + * + * RETURN : + * 0 : success + * -EINVAL : No camera present at camera_id, or it is not inited. + * -EALREADY: Flash is already in requested state + *==========================================================================*/ +int32_t QCameraFlash::setFlashMode(const int camera_id, const bool mode) +{ + int32_t retVal = 0; + struct msm_flash_cfg_data_t cfg; + + if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { + LOGE("Invalid camera id: %d", camera_id); + retVal = -EINVAL; + } else if (mode == m_flashOn[camera_id]) { + LOGD("flash %d is already in requested state: %d", + camera_id, + mode); + retVal = -EALREADY; + } else if (m_flashFds[camera_id] < 0) { + LOGE("called for uninited flash: %d", camera_id); + retVal = -EINVAL; + } else { + memset(&cfg, 0, sizeof(struct msm_flash_cfg_data_t)); + for (int i = 0; i < MAX_LED_TRIGGERS; i++) + cfg.flash_current[i] = QCAMERA_TORCH_CURRENT_VALUE; + cfg.cfg_type = mode ? CFG_FLASH_LOW: CFG_FLASH_OFF; + + retVal = ioctl(m_flashFds[camera_id], + VIDIOC_MSM_FLASH_CFG, + &cfg); + if (retVal < 0) { + LOGE("Unable to change flash mode to %d for camera id: %d", + mode, camera_id); + } else + { + m_flashOn[camera_id] = mode; + } + } + return retVal; +} + +/*=========================================================================== + * FUNCTION : deinitFlash + * + * DESCRIPTION: Release the flash unit associated with a given camera + * position. This function is blocking until the operation + * completes or fails. + * + * PARAMETERS : + * @camera_id : Camera id of the flash. + * + * RETURN : + * 0 : success + * -EINVAL : No camera present at camera_id or not inited. + *==========================================================================*/ +int32_t QCameraFlash::deinitFlash(const int camera_id) +{ + int32_t retVal = 0; + + if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { + LOGE("Invalid camera id: %d", camera_id); + retVal = -EINVAL; + } else if (m_flashFds[camera_id] < 0) { + LOGE("called deinitFlash for uninited flash"); + retVal = -EINVAL; + } else { + setFlashMode(camera_id, false); + + struct msm_flash_cfg_data_t cfg; + cfg.cfg_type = CFG_FLASH_RELEASE; + retVal = ioctl(m_flashFds[camera_id], + VIDIOC_MSM_FLASH_CFG, + &cfg); + if (retVal < 0) { + LOGE("Failed to release flash for camera id: %d", + camera_id); + } + + close(m_flashFds[camera_id]); + m_flashFds[camera_id] = -1; + } + + return retVal; +} + +/*=========================================================================== + * FUNCTION : reserveFlashForCamera + * + * DESCRIPTION: Give control of the flash to the camera, and notify + * framework that the flash has become unavailable. + * + * PARAMETERS : + * @camera_id : Camera id of the flash. + * + * RETURN : + * 0 : success + * -EINVAL : No camera present at camera_id or not inited. + * -ENOSYS : No callback available for torch_mode_status_change. + *==========================================================================*/ +int32_t QCameraFlash::reserveFlashForCamera(const int camera_id) +{ + int32_t retVal = 0; + + if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { + LOGE("Invalid camera id: %d", camera_id); + retVal = -EINVAL; + } else if (m_cameraOpen[camera_id]) { + LOGD("Flash already reserved for camera id: %d", + camera_id); + } else { + if (m_flashOn[camera_id]) { + setFlashMode(camera_id, false); + deinitFlash(camera_id); + } + m_cameraOpen[camera_id] = true; + + bool hasFlash = false; + char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; + + QCamera3HardwareInterface::getFlashInfo(camera_id, + hasFlash, + flashNode); + + if (m_callbacks == NULL || + m_callbacks->torch_mode_status_change == NULL) { + LOGE("Callback is not defined!"); + retVal = -ENOSYS; + } else if (!hasFlash) { + LOGD("Suppressing callback " + "because no flash exists for camera id: %d", + camera_id); + } else { + char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER]; + snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER, + "%d", camera_id); + m_callbacks->torch_mode_status_change(m_callbacks, + cameraIdStr, + TORCH_MODE_STATUS_NOT_AVAILABLE); + } + } + + return retVal; +} + +/*=========================================================================== + * FUNCTION : releaseFlashFromCamera + * + * DESCRIPTION: Release control of the flash from the camera, and notify + * framework that the flash has become available. + * + * PARAMETERS : + * @camera_id : Camera id of the flash. + * + * RETURN : + * 0 : success + * -EINVAL : No camera present at camera_id or not inited. + * -ENOSYS : No callback available for torch_mode_status_change. + *==========================================================================*/ +int32_t QCameraFlash::releaseFlashFromCamera(const int camera_id) +{ + int32_t retVal = 0; + + if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { + LOGE("Invalid camera id: %d", camera_id); + retVal = -EINVAL; + } else if (!m_cameraOpen[camera_id]) { + LOGD("Flash not reserved for camera id: %d", + camera_id); + } else { + m_cameraOpen[camera_id] = false; + + bool hasFlash = false; + char flashNode[QCAMERA_MAX_FILEPATH_LENGTH]; + + QCamera3HardwareInterface::getFlashInfo(camera_id, + hasFlash, + flashNode); + + if (m_callbacks == NULL || + m_callbacks->torch_mode_status_change == NULL) { + LOGE("Callback is not defined!"); + retVal = -ENOSYS; + } else if (!hasFlash) { + LOGD("Suppressing callback " + "because no flash exists for camera id: %d", + camera_id); + } else { + char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER]; + snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER, + "%d", camera_id); + m_callbacks->torch_mode_status_change(m_callbacks, + cameraIdStr, + TORCH_MODE_STATUS_AVAILABLE_OFF); + } + } + + return retVal; +} + +}; // namespace qcamera diff --git a/camera/QCamera2/util/QCameraFlash.h b/camera/QCamera2/util/QCameraFlash.h new file mode 100644 index 0000000..fa5e3ea --- /dev/null +++ b/camera/QCamera2/util/QCameraFlash.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __QCAMERA_FLASH_H__ +#define __QCAMERA_FLASH_H__ + +// Camera dependencies +#include "camera_common.h" + +extern "C" { +#include "mm_camera_interface.h" +} + +namespace qcamera { + +#define QCAMERA_TORCH_CURRENT_VALUE 200 + +class QCameraFlash { +public: + static QCameraFlash& getInstance(); + + int32_t registerCallbacks(const camera_module_callbacks_t* callbacks); + int32_t initFlash(const int camera_id); + int32_t setFlashMode(const int camera_id, const bool on); + int32_t deinitFlash(const int camera_id); + int32_t reserveFlashForCamera(const int camera_id); + int32_t releaseFlashFromCamera(const int camera_id); + +private: + QCameraFlash(); + virtual ~QCameraFlash(); + QCameraFlash(const QCameraFlash&); + QCameraFlash& operator=(const QCameraFlash&); + + const camera_module_callbacks_t *m_callbacks; + int32_t m_flashFds[MM_CAMERA_MAX_NUM_SENSORS]; + bool m_flashOn[MM_CAMERA_MAX_NUM_SENSORS]; + bool m_cameraOpen[MM_CAMERA_MAX_NUM_SENSORS]; +}; + +}; // namespace qcamera + +#endif /* __QCAMERA_FLASH_H__ */ diff --git a/camera/QCamera2/util/QCameraPerf.cpp b/camera/QCamera2/util/QCameraPerf.cpp new file mode 100644 index 0000000..83ba4cc --- /dev/null +++ b/camera/QCamera2/util/QCameraPerf.cpp @@ -0,0 +1,545 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#define LOG_TAG "QCameraPerf" + +// To remove +#include <cutils/properties.h> + +// System dependencies +#include <stdlib.h> +#include <dlfcn.h> + +// Camera dependencies +#include "QCameraPerf.h" +#include "QCameraTrace.h" + +extern "C" { +#include "mm_camera_dbg.h" +} + +namespace qcamera { + +/*=========================================================================== + * FUNCTION : QCameraPerfLock constructor + * + * DESCRIPTION: initialize member variables + * + * PARAMETERS : + * None + * + * RETURN : void + * + *==========================================================================*/ +QCameraPerfLock::QCameraPerfLock() : + perf_lock_acq(NULL), + perf_lock_rel(NULL), + mDlHandle(NULL), + mPerfLockEnable(0), + mPerfLockHandle(-1), + mPerfLockHandleTimed(-1), + mTimerSet(0), + mPerfLockTimeout(0), + mStartTimeofLock(0) +{ +} + +/*=========================================================================== + * FUNCTION : QCameraPerfLock destructor + * + * DESCRIPTION: class desctructor + * + * PARAMETERS : + * None + * + * RETURN : void + * + *==========================================================================*/ +QCameraPerfLock::~QCameraPerfLock() +{ + lock_deinit(); +} + + +/*=========================================================================== + * FUNCTION : lock_init + * + * DESCRIPTION: opens the performance lib and initilizes the perf lock functions + * + * PARAMETERS : + * None + * + * RETURN : void + * + *==========================================================================*/ +void QCameraPerfLock::lock_init() +{ + const char *rc; + char value[PROPERTY_VALUE_MAX]; + + LOGD("E"); + Mutex::Autolock lock(mLock); + + // Clear the list of active power hints + mActivePowerHints.clear(); + mCurrentPowerHint = static_cast<power_hint_t>(0); + mCurrentPowerHintEnable = false; + + property_get("persist.camera.perflock.enable", value, "1"); + mPerfLockEnable = atoi(value); +#ifdef HAS_MULTIMEDIA_HINTS + if (hw_get_module(POWER_HARDWARE_MODULE_ID, (const hw_module_t **)&m_pPowerModule)) { + LOGE("%s module not found", POWER_HARDWARE_MODULE_ID); + } +#endif + + if (mPerfLockEnable) { + perf_lock_acq = NULL; + perf_lock_rel = NULL; + mPerfLockHandle = -1; + /* Retrieve name of vendor extension library */ + if (property_get("ro.vendor.extension_library", value, NULL) <= 0) { + goto cleanup; + } + + mDlHandle = dlopen(value, RTLD_NOW | RTLD_LOCAL); + if (mDlHandle == NULL) { + goto cleanup; + } + + dlerror(); + + perf_lock_acq = (int (*) (int, int, int[], int))dlsym(mDlHandle, "perf_lock_acq"); + if ((rc = dlerror()) != NULL) { + LOGE("failed to perf_lock_acq function handle"); + goto cleanup; + } + + perf_lock_rel = (int (*) (int))dlsym(mDlHandle, "perf_lock_rel"); + if ((rc = dlerror()) != NULL) { + LOGE("failed to perf_lock_rel function handle"); + goto cleanup; + } + LOGD("X"); + return; + +cleanup: + perf_lock_acq = NULL; + perf_lock_rel = NULL; + mPerfLockEnable = 0; + if (mDlHandle) { + dlclose(mDlHandle); + mDlHandle = NULL; + } + } + LOGD("X"); +} + +/*=========================================================================== + * FUNCTION : lock_deinit + * + * DESCRIPTION: deinitialize the perf lock parameters + * + * PARAMETERS : + * None + * + * RETURN : void + * + *==========================================================================*/ +void QCameraPerfLock::lock_deinit() +{ + Mutex::Autolock lock(mLock); + if (mPerfLockEnable) { + LOGD("E"); + + if (mActivePowerHints.empty() == false) { + // Disable the active power hint + mCurrentPowerHint = *mActivePowerHints.begin(); + powerHintInternal(mCurrentPowerHint, false); + mActivePowerHints.clear(); + } + + if ((NULL != perf_lock_rel) && (mPerfLockHandleTimed >= 0)) { + (*perf_lock_rel)(mPerfLockHandleTimed); + } + + if ((NULL != perf_lock_rel) && (mPerfLockHandle >= 0)) { + (*perf_lock_rel)(mPerfLockHandle); + } + + if (mDlHandle) { + perf_lock_acq = NULL; + perf_lock_rel = NULL; + + dlclose(mDlHandle); + mDlHandle = NULL; + } + mPerfLockEnable = 0; + LOGD("X"); + } +} + +/*=========================================================================== + * FUNCTION : isTimerReset + * + * DESCRIPTION: Check if timout duration is reached + * + * PARAMETERS : None + * + * RETURN : true if timeout reached + * false if timeout not reached + * + *==========================================================================*/ +bool QCameraPerfLock::isTimerReset() +{ + Mutex::Autolock lock(mLock); + if (mPerfLockEnable && mTimerSet) { + nsecs_t timeDiff = systemTime() - mStartTimeofLock; + if (ns2ms(timeDiff) > (uint32_t)mPerfLockTimeout) { + resetTimer(); + return true; + } + } + return false; +} + +/*=========================================================================== + * FUNCTION : resetTimer + * + * DESCRIPTION: Reset the timer used in timed perf lock + * + * PARAMETERS : None + * + * RETURN : void + * + *==========================================================================*/ +void QCameraPerfLock::resetTimer() +{ + mPerfLockTimeout = 0; + mTimerSet = 0; +} + +/*=========================================================================== + * FUNCTION : start_timer + * + * DESCRIPTION: get the start of the timer + * + * PARAMETERS : + * @timer_val: timer duration in milliseconds + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + * + *==========================================================================*/ +void QCameraPerfLock::startTimer(uint32_t timer_val) +{ + mStartTimeofLock = systemTime(); + mTimerSet = 1; + mPerfLockTimeout = timer_val; +} + +/*=========================================================================== + * FUNCTION : lock_acq_timed + * + * DESCRIPTION: Acquire the performance lock for the specified duration. + * If an existing lock timeout has not elapsed, extend the + * lock further for the specified duration + * + * PARAMETERS : + * @timer_val: lock duration + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + * + *==========================================================================*/ +int32_t QCameraPerfLock::lock_acq_timed(int32_t timer_val) +{ + int32_t ret = -1; + + LOGD("E"); + Mutex::Autolock lock(mLock); + + if (mPerfLockEnable) { + int32_t perf_lock_params[] = { + ALL_CPUS_PWR_CLPS_DIS, + CPU0_MIN_FREQ_TURBO_MAX, + CPU4_MIN_FREQ_TURBO_MAX + }; + if (mTimerSet) { + nsecs_t curElapsedTime = systemTime() - mStartTimeofLock; + int32_t pendingTimeout = mPerfLockTimeout - ns2ms(curElapsedTime); + timer_val += pendingTimeout; + } + startTimer(timer_val); + + // Disable power hint when acquiring the perf lock + if (mCurrentPowerHintEnable) { + LOGD("mCurrentPowerHintEnable %d" ,mCurrentPowerHintEnable); + powerHintInternal(mCurrentPowerHint, false); + } + + if ((NULL != perf_lock_acq) && (mPerfLockHandleTimed < 0)) { + ret = (*perf_lock_acq)(mPerfLockHandleTimed, timer_val, perf_lock_params, + sizeof(perf_lock_params) / sizeof(int32_t)); + LOGD("ret %d", ret); + if (ret < 0) { + LOGE("failed to acquire lock"); + } else { + mPerfLockHandleTimed = ret; + } + } + LOGD("perf_handle_acq %d ", mPerfLockHandleTimed); + } + + LOGD("X"); + return ret; +} + +/*=========================================================================== + * FUNCTION : lock_acq + * + * DESCRIPTION: acquire the performance lock + * + * PARAMETERS : + * None + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + * + *==========================================================================*/ +int32_t QCameraPerfLock::lock_acq() +{ + int32_t ret = -1; + + LOGD("E"); + Mutex::Autolock lock(mLock); + + if (mPerfLockEnable) { + int32_t perf_lock_params[] = { + ALL_CPUS_PWR_CLPS_DIS, + CPU0_MIN_FREQ_TURBO_MAX, + CPU4_MIN_FREQ_TURBO_MAX + }; + + // Disable power hint when acquiring the perf lock + if (mCurrentPowerHintEnable) { + powerHintInternal(mCurrentPowerHint, false); + } + + if ((NULL != perf_lock_acq) && (mPerfLockHandle < 0)) { + ret = (*perf_lock_acq)(mPerfLockHandle, ONE_SEC, perf_lock_params, + sizeof(perf_lock_params) / sizeof(int32_t)); + LOGD("ret %d", ret); + if (ret < 0) { + LOGE("failed to acquire lock"); + } else { + mPerfLockHandle = ret; + } + } + LOGD("perf_handle_acq %d ", mPerfLockHandle); + } + + LOGD("X"); + return ret; +} + +/*=========================================================================== + * FUNCTION : lock_rel_timed + * + * DESCRIPTION: release the performance lock + * + * PARAMETERS : + * None + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + * + *==========================================================================*/ +int32_t QCameraPerfLock::lock_rel_timed() +{ + int ret = -1; + Mutex::Autolock lock(mLock); + if (mPerfLockEnable) { + LOGD("E"); + if (mPerfLockHandleTimed < 0) { + LOGW("mPerfLockHandle < 0,check if lock is acquired"); + return ret; + } + LOGD("perf_handle_rel %d ", mPerfLockHandleTimed); + + if ((NULL != perf_lock_rel) && (0 <= mPerfLockHandleTimed)) { + ret = (*perf_lock_rel)(mPerfLockHandleTimed); + if (ret < 0) { + LOGE("failed to release lock"); + } + mPerfLockHandleTimed = -1; + resetTimer(); + } + + if ((mCurrentPowerHintEnable == 1) && (mTimerSet == 0)) { + powerHintInternal(mCurrentPowerHint, mCurrentPowerHintEnable); + } + LOGD("X"); + } + return ret; +} + +/*=========================================================================== + * FUNCTION : lock_rel + * + * DESCRIPTION: release the performance lock + * + * PARAMETERS : + * None + * + * RETURN : int32_t type of status + * NO_ERROR -- success + * none-zero failure code + * + *==========================================================================*/ +int32_t QCameraPerfLock::lock_rel() +{ + int ret = -1; + Mutex::Autolock lock(mLock); + if (mPerfLockEnable) { + LOGD("E"); + if (mPerfLockHandle < 0) { + LOGW("mPerfLockHandle < 0,check if lock is acquired"); + return ret; + } + LOGD("perf_handle_rel %d ", mPerfLockHandle); + + if ((NULL != perf_lock_rel) && (0 <= mPerfLockHandle)) { + ret = (*perf_lock_rel)(mPerfLockHandle); + if (ret < 0) { + LOGE("failed to release lock"); + } + mPerfLockHandle = -1; + } + + if (mCurrentPowerHintEnable == 1) { + powerHintInternal(mCurrentPowerHint, mCurrentPowerHintEnable); + } + LOGD("X"); + } + return ret; +} + +/*=========================================================================== + * FUNCTION : powerHintInternal + * + * DESCRIPTION: Sets the requested power hint and state to power HAL. + * + * PARAMETERS : + * hint : Power hint + * enable : Enable power hint if set to 1. Disable if set to 0. + * RETURN : void + * + *==========================================================================*/ +void QCameraPerfLock::powerHintInternal(power_hint_t hint, bool enable) +{ +#ifdef HAS_MULTIMEDIA_HINTS + if (m_pPowerModule != NULL) { + if (enable == true) { + m_pPowerModule->powerHint(m_pPowerModule, hint, (void *)"state=1"); + } else { + m_pPowerModule->powerHint(m_pPowerModule, hint, (void *)"state=0"); + } + } +#endif +} + +/*=========================================================================== + * FUNCTION : powerHint + * + * DESCRIPTION: Updates the list containing active/enabled power hints. + * If needed, calls the internal powerHint function with + * requested power hint and state. + * PARAMETERS : + * hint : Power hint + * enable : Enable power hint if set to 1. Disable if set to 0. + * RETURN : void + * + *==========================================================================*/ +void QCameraPerfLock::powerHint(power_hint_t hint, bool enable) +{ +#ifdef HAS_MULTIMEDIA_HINTS + if (enable == true) { + if ((hint != mCurrentPowerHint) || (enable != mCurrentPowerHintEnable)) { + // Disable the current active power hint + if (mCurrentPowerHintEnable == true) { + powerHintInternal(mCurrentPowerHint, false); + } + // Push the new power hint at the head of the active power hint list + mActivePowerHints.push_front(hint); + + // Set the new power hint + mCurrentPowerHint = hint; + mCurrentPowerHintEnable = enable; + powerHintInternal(hint, enable); + } + } else { + // Remove the power hint from the list + for (List<power_hint_t>::iterator it = mActivePowerHints.begin(); + it != mActivePowerHints.end(); ++it) { + if (*it == hint) { + if (it != mActivePowerHints.begin()) { + LOGW("Request to remove the previous power hint: %d instead of " + "currently active power hint: %d", static_cast<int>(hint), + static_cast<int>(mCurrentPowerHint)); + } + mActivePowerHints.erase(it); + break; + } + } + + if (hint == mCurrentPowerHint) { + // Disable the power hint + powerHintInternal(hint, false); + + // If the active power hint list is not empty, + // restore the previous power hint from the head of the list + if (mActivePowerHints.empty() == false) { + mCurrentPowerHint = *mActivePowerHints.begin(); + mCurrentPowerHintEnable = true; + powerHintInternal(mCurrentPowerHint, true); + } else { + mCurrentPowerHint = static_cast<power_hint_t>(0); + mCurrentPowerHintEnable = false; + } + } + } +#endif +} + +}; // namespace qcamera diff --git a/camera/QCamera2/util/QCameraPerf.h b/camera/QCamera2/util/QCameraPerf.h new file mode 100644 index 0000000..0096139 --- /dev/null +++ b/camera/QCamera2/util/QCameraPerf.h @@ -0,0 +1,93 @@ +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __QCAMERAPERF_H__ +#define __QCAMERAPERF_H__ + +// System dependencies +#include <utils/List.h> +#include <utils/Mutex.h> + +// Camera dependencies +#include "power.h" + +typedef enum { + ALL_CORES_ONLINE = 0x7FE, + ALL_CPUS_PWR_CLPS_DIS = 0x101, + CPU0_MIN_FREQ_TURBO_MAX = 0x2FE, + CPU4_MIN_FREQ_TURBO_MAX = 0x1FFE, +}perf_lock_params_t; + +/* Time related macros */ +#define ONE_SEC 1000 +typedef int64_t nsecs_t; +#define NSEC_PER_SEC 1000000000LLU + +using namespace android; + +namespace qcamera { + +class QCameraPerfLock { +public: + QCameraPerfLock(); + ~QCameraPerfLock(); + + void lock_init(); + void lock_deinit(); + int32_t lock_rel(); + int32_t lock_acq(); + int32_t lock_acq_timed(int32_t timer_val); + int32_t lock_rel_timed(); + bool isTimerReset(); + void powerHintInternal(power_hint_t hint, bool enable); + void powerHint(power_hint_t hint, bool enable); + bool isPerfLockTimedAcquired() { return (0 <= mPerfLockHandleTimed); } + +private: + int32_t (*perf_lock_acq)(int, int, int[], int); + int32_t (*perf_lock_rel)(int); + void startTimer(uint32_t timer_val); + void resetTimer(); + void *mDlHandle; + uint32_t mPerfLockEnable; + Mutex mLock; + int32_t mPerfLockHandle; // Performance lock library handle + int32_t mPerfLockHandleTimed; // Performance lock library handle + power_module_t *m_pPowerModule; // power module Handle + power_hint_t mCurrentPowerHint; + bool mCurrentPowerHintEnable; + uint32_t mTimerSet; + uint32_t mPerfLockTimeout; + nsecs_t mStartTimeofLock; + List<power_hint_t> mActivePowerHints; // Active/enabled power hints list +}; + +}; // namespace qcamera + +#endif /* __QCAMREAPERF_H__ */ diff --git a/camera/QCamera2/util/QCameraQueue.cpp b/camera/QCamera2/util/QCameraQueue.cpp new file mode 100644 index 0000000..3b9d239 --- /dev/null +++ b/camera/QCamera2/util/QCameraQueue.cpp @@ -0,0 +1,464 @@ +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +// System dependencies +#include <string.h> +#include <utils/Errors.h> + +// Camera dependencies +#include "QCameraQueue.h" + +extern "C" { +#include "mm_camera_dbg.h" +} + +namespace qcamera { + +/*=========================================================================== + * FUNCTION : QCameraQueue + * + * DESCRIPTION: default constructor of QCameraQueue + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraQueue::QCameraQueue() +{ + pthread_mutex_init(&m_lock, NULL); + cam_list_init(&m_head.list); + m_size = 0; + m_dataFn = NULL; + m_userData = NULL; + m_active = true; +} + +/*=========================================================================== + * FUNCTION : QCameraQueue + * + * DESCRIPTION: constructor of QCameraQueue + * + * PARAMETERS : + * @data_rel_fn : function ptr to release node data internal resource + * @user_data : user data ptr + * + * RETURN : None + *==========================================================================*/ +QCameraQueue::QCameraQueue(release_data_fn data_rel_fn, void *user_data) +{ + pthread_mutex_init(&m_lock, NULL); + cam_list_init(&m_head.list); + m_size = 0; + m_dataFn = data_rel_fn; + m_userData = user_data; + m_active = true; +} + +/*=========================================================================== + * FUNCTION : ~QCameraQueue + * + * DESCRIPTION: deconstructor of QCameraQueue + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +QCameraQueue::~QCameraQueue() +{ + flush(); + pthread_mutex_destroy(&m_lock); +} + +/*=========================================================================== + * FUNCTION : init + * + * DESCRIPTION: Put the queue to active state (ready to enqueue and dequeue) + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +void QCameraQueue::init() +{ + pthread_mutex_lock(&m_lock); + m_active = true; + pthread_mutex_unlock(&m_lock); +} + +/*=========================================================================== + * FUNCTION : isEmpty + * + * DESCRIPTION: return if the queue is empty or not + * + * PARAMETERS : None + * + * RETURN : true -- queue is empty; false -- not empty + *==========================================================================*/ +bool QCameraQueue::isEmpty() +{ + bool flag = true; + pthread_mutex_lock(&m_lock); + if (m_size > 0) { + flag = false; + } + pthread_mutex_unlock(&m_lock); + return flag; +} + +/*=========================================================================== + * FUNCTION : enqueue + * + * DESCRIPTION: enqueue data into the queue + * + * PARAMETERS : + * @data : data to be enqueued + * + * RETURN : true -- success; false -- failed + *==========================================================================*/ +bool QCameraQueue::enqueue(void *data) +{ + bool rc; + camera_q_node *node = + (camera_q_node *)malloc(sizeof(camera_q_node)); + if (NULL == node) { + LOGE("No memory for camera_q_node"); + return false; + } + + memset(node, 0, sizeof(camera_q_node)); + node->data = data; + + pthread_mutex_lock(&m_lock); + if (m_active) { + cam_list_add_tail_node(&node->list, &m_head.list); + m_size++; + rc = true; + } else { + free(node); + rc = false; + } + pthread_mutex_unlock(&m_lock); + return rc; +} + +/*=========================================================================== + * FUNCTION : enqueueWithPriority + * + * DESCRIPTION: enqueue data into queue with priority, will insert into the + * head of the queue + * + * PARAMETERS : + * @data : data to be enqueued + * + * RETURN : true -- success; false -- failed + *==========================================================================*/ +bool QCameraQueue::enqueueWithPriority(void *data) +{ + bool rc; + camera_q_node *node = + (camera_q_node *)malloc(sizeof(camera_q_node)); + if (NULL == node) { + LOGE("No memory for camera_q_node"); + return false; + } + + memset(node, 0, sizeof(camera_q_node)); + node->data = data; + + pthread_mutex_lock(&m_lock); + if (m_active) { + struct cam_list *p_next = m_head.list.next; + + m_head.list.next = &node->list; + p_next->prev = &node->list; + node->list.next = p_next; + node->list.prev = &m_head.list; + + m_size++; + rc = true; + } else { + free(node); + rc = false; + } + pthread_mutex_unlock(&m_lock); + return rc; +} + +/*=========================================================================== + * FUNCTION : peek + * + * DESCRIPTION: return the head element without removing it + * + * PARAMETERS : None + * + * RETURN : data ptr. NULL if not any data in the queue. + *==========================================================================*/ +void* QCameraQueue::peek() +{ + camera_q_node* node = NULL; + void* data = NULL; + struct cam_list *head = NULL; + struct cam_list *pos = NULL; + + pthread_mutex_lock(&m_lock); + if (m_active) { + head = &m_head.list; + pos = head->next; + if (pos != head) { + node = member_of(pos, camera_q_node, list); + } + } + pthread_mutex_unlock(&m_lock); + + if (NULL != node) { + data = node->data; + } + + return data; +} + +/*=========================================================================== + * FUNCTION : dequeue + * + * DESCRIPTION: dequeue data from the queue + * + * PARAMETERS : + * @bFromHead : if true, dequeue from the head + * if false, dequeue from the tail + * + * RETURN : data ptr. NULL if not any data in the queue. + *==========================================================================*/ +void* QCameraQueue::dequeue(bool bFromHead) +{ + camera_q_node* node = NULL; + void* data = NULL; + struct cam_list *head = NULL; + struct cam_list *pos = NULL; + + pthread_mutex_lock(&m_lock); + if (m_active) { + head = &m_head.list; + if (bFromHead) { + pos = head->next; + } else { + pos = head->prev; + } + if (pos != head) { + node = member_of(pos, camera_q_node, list); + cam_list_del_node(&node->list); + m_size--; + } + } + pthread_mutex_unlock(&m_lock); + + if (NULL != node) { + data = node->data; + free(node); + } + + return data; +} + +/*=========================================================================== + * FUNCTION : dequeue + * + * DESCRIPTION: dequeue data from the queue + * + * PARAMETERS : + * @match : matching function callback + * @match_data : the actual data to be matched + * + * RETURN : data ptr. NULL if not any data in the queue. + *==========================================================================*/ +void* QCameraQueue::dequeue(match_fn_data match, void *match_data){ + camera_q_node* node = NULL; + struct cam_list *head = NULL; + struct cam_list *pos = NULL; + void* data = NULL; + + if ( NULL == match || NULL == match_data ) { + return NULL; + } + + pthread_mutex_lock(&m_lock); + if (m_active) { + head = &m_head.list; + pos = head->next; + + while(pos != head) { + node = member_of(pos, camera_q_node, list); + pos = pos->next; + if (NULL != node) { + if ( match(node->data, m_userData, match_data) ) { + cam_list_del_node(&node->list); + m_size--; + data = node->data; + free(node); + pthread_mutex_unlock(&m_lock); + return data; + } + } + } + } + pthread_mutex_unlock(&m_lock); + return NULL; +} + +/*=========================================================================== + * FUNCTION : flush + * + * DESCRIPTION: flush all nodes from the queue, queue will be empty after this + * operation. + * + * PARAMETERS : None + * + * RETURN : None + *==========================================================================*/ +void QCameraQueue::flush(){ + camera_q_node* node = NULL; + struct cam_list *head = NULL; + struct cam_list *pos = NULL; + + pthread_mutex_lock(&m_lock); + if (m_active) { + head = &m_head.list; + pos = head->next; + + while(pos != head) { + node = member_of(pos, camera_q_node, list); + pos = pos->next; + cam_list_del_node(&node->list); + m_size--; + + if (NULL != node->data) { + if (m_dataFn) { + m_dataFn(node->data, m_userData); + } + free(node->data); + } + free(node); + + } + m_size = 0; + m_active = false; + } + pthread_mutex_unlock(&m_lock); +} + +/*=========================================================================== + * FUNCTION : flushNodes + * + * DESCRIPTION: flush only specific nodes, depending on + * the given matching function. + * + * PARAMETERS : + * @match : matching function + * + * RETURN : None + *==========================================================================*/ +void QCameraQueue::flushNodes(match_fn match){ + camera_q_node* node = NULL; + struct cam_list *head = NULL; + struct cam_list *pos = NULL; + + if ( NULL == match ) { + return; + } + + pthread_mutex_lock(&m_lock); + if (m_active) { + head = &m_head.list; + pos = head->next; + + while(pos != head) { + node = member_of(pos, camera_q_node, list); + pos = pos->next; + if ( match(node->data, m_userData) ) { + cam_list_del_node(&node->list); + m_size--; + + if (NULL != node->data) { + if (m_dataFn) { + m_dataFn(node->data, m_userData); + } + free(node->data); + } + free(node); + } + } + } + pthread_mutex_unlock(&m_lock); +} + +/*=========================================================================== + * FUNCTION : flushNodes + * + * DESCRIPTION: flush only specific nodes, depending on + * the given matching function. + * + * PARAMETERS : + * @match : matching function + * + * RETURN : None + *==========================================================================*/ +void QCameraQueue::flushNodes(match_fn_data match, void *match_data){ + camera_q_node* node = NULL; + struct cam_list *head = NULL; + struct cam_list *pos = NULL; + + if ( NULL == match ) { + return; + } + + pthread_mutex_lock(&m_lock); + if (m_active) { + head = &m_head.list; + pos = head->next; + + while(pos != head) { + node = member_of(pos, camera_q_node, list); + pos = pos->next; + if ( match(node->data, m_userData, match_data) ) { + cam_list_del_node(&node->list); + m_size--; + + if (NULL != node->data) { + if (m_dataFn) { + m_dataFn(node->data, m_userData); + } + free(node->data); + } + free(node); + } + } + } + pthread_mutex_unlock(&m_lock); +} + +}; // namespace qcamera diff --git a/camera/QCamera2/util/QCameraQueue.h b/camera/QCamera2/util/QCameraQueue.h new file mode 100644 index 0000000..dfa221e --- /dev/null +++ b/camera/QCamera2/util/QCameraQueue.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __QCAMERA_QUEUE_H__ +#define __QCAMERA_QUEUE_H__ + +// System dependencies +#include <pthread.h> + +// Camera dependencies +#include "cam_list.h" + +namespace qcamera { + +typedef bool (*match_fn_data)(void *data, void *user_data, void *match_data); +typedef void (*release_data_fn)(void* data, void *user_data); +typedef bool (*match_fn)(void *data, void *user_data); + +class QCameraQueue { +public: + QCameraQueue(); + QCameraQueue(release_data_fn data_rel_fn, void *user_data); + virtual ~QCameraQueue(); + void init(); + bool enqueue(void *data); + bool enqueueWithPriority(void *data); + /* This call will put queue into uninitialized state. + * Need to call init() in order to use the queue again */ + void flush(); + void flushNodes(match_fn match); + void flushNodes(match_fn_data match, void *spec_data); + void* dequeue(bool bFromHead = true); + void* dequeue(match_fn_data match, void *spec_data); + void* peek(); + bool isEmpty(); + int getCurrentSize() {return m_size;} +private: + typedef struct { + struct cam_list list; + void* data; + } camera_q_node; + + camera_q_node m_head; // dummy head + int m_size; + bool m_active; + pthread_mutex_t m_lock; + release_data_fn m_dataFn; + void * m_userData; +}; + +}; // namespace qcamera + +#endif /* __QCAMERA_QUEUE_H__ */ diff --git a/camera/QCamera2/util/QCameraTrace.h b/camera/QCamera2/util/QCameraTrace.h new file mode 100644 index 0000000..d7eeb8f --- /dev/null +++ b/camera/QCamera2/util/QCameraTrace.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2012 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 __QCAMERATRACE_H__ +#define __QCAMERATRACE_H__ + +#include <utils/Trace.h> + +#ifdef QCAMERA_REDEFINE_LOG +#define CAM_MODULE CAM_HAL_MODULE +extern "C" { +#include "mm_camera_dbg.h" +} +#endif + +#undef ATRACE_CALL +#undef ATRACE_NAME +#undef ATRACE_BEGIN +#undef ATRACE_INT +#undef ATRACE_END +#undef ATRACE_BEGIN_SNPRINTF +#undef KPI_ATRACE_BEGIN +#undef KPI_ATRACE_END +#undef KPI_ATRACE_INT +#undef ATRACE_TAG +#undef ATRACE_BEGIN_DBG +#undef ATRACE_INT_DBG +#undef ATRACE_END_DBG + +#define KPI_ONLY 1 +#define KPI_DBG 2 + +#define CAMERA_TRACE_BUF 32 + +#define ATRACE_TAG ATRACE_TAG_CAMERA + +//to enable only KPI logs +#define KPI_ATRACE_BEGIN(name) ({\ +if (gKpiDebugLevel >= KPI_ONLY) { \ + atrace_begin(ATRACE_TAG, name); \ +}\ +}) + +#define KPI_ATRACE_END() ({\ +if (gKpiDebugLevel >= KPI_ONLY) { \ + atrace_end(ATRACE_TAG); \ +}\ +}) + +#define KPI_ATRACE_INT(name,val) ({\ +if (gKpiDebugLevel >= KPI_ONLY) { \ + atrace_int(ATRACE_TAG, name, val); \ +}\ +}) + + +#define ATRACE_BEGIN_SNPRINTF(fmt_str, ...) \ + if (gKpiDebugLevel >= KPI_DBG) { \ + char trace_tag[CAMERA_TRACE_BUF]; \ + snprintf(trace_tag, CAMERA_TRACE_BUF, fmt_str, ##__VA_ARGS__); \ + ATRACE_BEGIN(trace_tag); \ +} + +#define ATRACE_BEGIN_DBG(name) ({\ +if (gKpiDebugLevel >= KPI_DBG) { \ + atrace_begin(ATRACE_TAG, name); \ +}\ +}) + +#define ATRACE_END_DBG() ({\ +if (gKpiDebugLevel >= KPI_DBG) { \ + atrace_end(ATRACE_TAG); \ +}\ +}) + +#define ATRACE_INT_DBG(name,val) ({\ +if (gKpiDebugLevel >= KPI_DBG) { \ + atrace_int(ATRACE_TAG, name, val); \ +}\ +}) + +#define ATRACE_BEGIN ATRACE_BEGIN_DBG +#define ATRACE_INT ATRACE_INT_DBG +#define ATRACE_END ATRACE_END_DBG + +#define KPI_ATRACE_NAME(name) qcamera::ScopedTraceKpi ___tracer(ATRACE_TAG, name) +#define ATRACE_NAME(name) qcamera::ScopedTraceDbg ___tracer(ATRACE_TAG, name) +#define KPI_ATRACE_CALL() KPI_ATRACE_NAME(__FUNCTION__) +#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__) + +namespace qcamera { +extern volatile uint32_t gKpiDebugLevel; +class ScopedTraceKpi { +public: + inline ScopedTraceKpi(uint64_t tag, const char *name) + : mTag(tag) { + if (gKpiDebugLevel >= KPI_ONLY) { + atrace_begin(mTag,name); + } + } + + inline ~ScopedTraceKpi() { + if (gKpiDebugLevel >= KPI_ONLY) { + atrace_end(mTag); + } + } + + private: + uint64_t mTag; +}; + +class ScopedTraceDbg { +public: + inline ScopedTraceDbg(uint64_t tag, const char *name) + : mTag(tag) { + if (gKpiDebugLevel >= KPI_DBG) { + atrace_begin(mTag,name); + } + } + + inline ~ScopedTraceDbg() { + if (gKpiDebugLevel >= KPI_DBG) { + atrace_end(mTag); + } + } + + private: + uint64_t mTag; +}; +}; + +extern volatile uint32_t gKpiDebugLevel; + +#endif /* __QCAMREATRACE_H__ */ |