aboutsummaryrefslogtreecommitdiff
path: root/camera/QCamera2/HAL/QCameraMuxer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'camera/QCamera2/HAL/QCameraMuxer.cpp')
-rw-r--r--camera/QCamera2/HAL/QCameraMuxer.cpp2823
1 files changed, 2823 insertions, 0 deletions
diff --git a/camera/QCamera2/HAL/QCameraMuxer.cpp b/camera/QCamera2/HAL/QCameraMuxer.cpp
new file mode 100644
index 0000000..e2ec989
--- /dev/null
+++ b/camera/QCamera2/HAL/QCameraMuxer.cpp
@@ -0,0 +1,2823 @@
+/* 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 "QCameraMuxer"
+
+// System dependencies
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <utils/Errors.h>
+#define STAT_H <SYSTEM_HEADER_PREFIX/stat.h>
+#include STAT_H
+
+// Camera dependencies
+#include "QCameraMuxer.h"
+#include "QCamera2HWI.h"
+#include "QCamera3HWI.h"
+
+extern "C" {
+#include "mm_camera_dbg.h"
+}
+
+/* Muxer implementation */
+using namespace android;
+namespace qcamera {
+
+QCameraMuxer *gMuxer = NULL;
+
+//Error Check Macros
+#define CHECK_MUXER() \
+ if (!gMuxer) { \
+ LOGE("Error getting muxer "); \
+ return; \
+ } \
+
+#define CHECK_MUXER_ERROR() \
+ if (!gMuxer) { \
+ LOGE("Error getting muxer "); \
+ return -ENODEV; \
+ } \
+
+#define CHECK_CAMERA(pCam) \
+ if (!pCam) { \
+ LOGE("Error getting physical camera"); \
+ return; \
+ } \
+
+#define CHECK_CAMERA_ERROR(pCam) \
+ if (!pCam) { \
+ LOGE("Error getting physical camera"); \
+ return -ENODEV; \
+ } \
+
+#define CHECK_HWI(hwi) \
+ if (!hwi) { \
+ LOGE("Error !! HWI not found!!"); \
+ return; \
+ } \
+
+#define CHECK_HWI_ERROR(hwi) \
+ if (!hwi) { \
+ LOGE("Error !! HWI not found!!"); \
+ return -ENODEV; \
+ } \
+
+
+/*===========================================================================
+ * FUNCTION : getCameraMuxer
+ *
+ * DESCRIPTION : Creates Camera Muxer if not created
+ *
+ * PARAMETERS:
+ * @pMuxer : Pointer to retrieve Camera Muxer
+ * @num_of_cameras : Number of Physical Cameras on device
+ *
+ * RETURN : NONE
+ *==========================================================================*/
+void QCameraMuxer::getCameraMuxer(
+ QCameraMuxer** pMuxer, uint32_t num_of_cameras)
+{
+ *pMuxer = NULL;
+ if (!gMuxer) {
+ gMuxer = new QCameraMuxer(num_of_cameras);
+ }
+ CHECK_MUXER();
+ *pMuxer = gMuxer;
+ LOGH("gMuxer: %p ", gMuxer);
+ return;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraMuxer
+ *
+ * DESCRIPTION : QCameraMuxer Constructor
+ *
+ * PARAMETERS:
+ * @num_of_cameras : Number of Physical Cameras on device
+ *
+ *==========================================================================*/
+QCameraMuxer::QCameraMuxer(uint32_t num_of_cameras)
+ : mJpegClientHandle(0),
+ m_pPhyCamera(NULL),
+ m_pLogicalCamera(NULL),
+ m_pCallbacks(NULL),
+ m_bAuxCameraExposed(FALSE),
+ m_nPhyCameras(num_of_cameras),
+ m_nLogicalCameras(0),
+ m_MainJpegQ(releaseJpegInfo, this),
+ m_AuxJpegQ(releaseJpegInfo, this),
+ m_pRelCamMpoJpeg(NULL),
+ m_pMpoCallbackCookie(NULL),
+ m_pJpegCallbackCookie(NULL),
+ m_bDumpImages(FALSE),
+ m_bMpoEnabled(TRUE),
+ m_bFrameSyncEnabled(FALSE),
+ m_bRecordingHintInternallySet(FALSE)
+{
+ setupLogicalCameras();
+ memset(&mJpegOps, 0, sizeof(mJpegOps));
+ memset(&mJpegMpoOps, 0, sizeof(mJpegMpoOps));
+ memset(&mGetMemoryCb, 0, sizeof(mGetMemoryCb));
+ memset(&mDataCb, 0, sizeof(mDataCb));
+
+ // initialize mutex for MPO composition
+ pthread_mutex_init(&m_JpegLock, NULL);
+ // launch MPO composition thread
+ m_ComposeMpoTh.launch(composeMpoRoutine, this);
+
+ //Check whether dual camera images need to be dumped
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("persist.camera.dual.camera.dump", prop, "0");
+ m_bDumpImages = atoi(prop);
+ LOGH("dualCamera dump images:%d ", m_bDumpImages);
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraMuxer
+ *
+ * DESCRIPTION : QCameraMuxer Desctructor
+ *
+ *==========================================================================*/
+QCameraMuxer::~QCameraMuxer() {
+ if (m_pLogicalCamera) {
+ delete [] m_pLogicalCamera;
+ m_pLogicalCamera = NULL;
+ }
+ if (m_pPhyCamera) {
+ delete [] m_pPhyCamera;
+ m_pPhyCamera = NULL;
+ }
+
+ if (NULL != m_pRelCamMpoJpeg) {
+ m_pRelCamMpoJpeg->release(m_pRelCamMpoJpeg);
+ m_pRelCamMpoJpeg = NULL;
+ }
+ // flush Jpeg Queues
+ m_MainJpegQ.flush();
+ m_AuxJpegQ.flush();
+
+ // stop and exit MPO composition thread
+ m_ComposeMpoTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, FALSE);
+ m_ComposeMpoTh.exit();
+
+ pthread_mutex_destroy(&m_JpegLock);
+}
+
+/*===========================================================================
+ * FUNCTION : get_number_of_cameras
+ *
+ * DESCRIPTION : Provide number of Logical Cameras
+ *
+ * RETURN : Number of logical Cameras
+ *==========================================================================*/
+int QCameraMuxer::get_number_of_cameras()
+{
+ return gMuxer->getNumberOfCameras();
+}
+
+/*===========================================================================
+ * FUNCTION : get_camera_info
+ *
+ * DESCRIPTION : get logical camera info
+ *
+ * PARAMETERS:
+ * @camera_id : Logical Camera ID
+ * @info : Logical Main Camera Info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * ENODEV : Camera not found
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::get_camera_info(int camera_id, struct camera_info *info)
+{
+ int rc = NO_ERROR;
+ LOGH("E");
+ cam_sync_type_t type;
+ if ((camera_id < 0) || (camera_id >= gMuxer->getNumberOfCameras())) {
+ LOGE("Camera id %d not found!", camera_id);
+ return -ENODEV;
+ }
+ if(info) {
+ rc = gMuxer->getCameraInfo(camera_id, info, &type);
+ }
+ LOGH("X, rc: %d", rc);
+ return rc;
+}
+
+
+/*===========================================================================
+ * FUNCTION : set_callbacks
+ *
+ * DESCRIPTION : Not Implemented
+ *
+ * PARAMETERS:
+ * @callbacks : Camera Module Callbacks
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::set_callbacks(__unused const camera_module_callbacks_t *callbacks)
+{
+ // Not implemented
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : camera_device_open
+ *
+ * DESCRIPTION: static function to open a camera device by its ID
+ *
+ * PARAMETERS :
+ * @modue: hw module
+ * @id : camera ID
+ * @hw_device : ptr to struct storing camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * BAD_VALUE : Invalid Camera ID
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::camera_device_open(
+ __unused const struct hw_module_t *module, const char *id,
+ struct hw_device_t **hw_device)
+{
+ int rc = NO_ERROR;
+ LOGH("id= %d",atoi(id));
+ if (!id) {
+ LOGE("Invalid camera id");
+ return BAD_VALUE;
+ }
+
+ rc = gMuxer->cameraDeviceOpen(atoi(id), hw_device);
+ LOGH("id= %d, rc: %d", atoi(id), rc);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : open_legacy
+ *
+ * DESCRIPTION: static function to open a camera device by its ID
+ *
+ * PARAMETERS :
+ * @modue: hw module
+ * @id : camera ID
+ * @halVersion: hal version
+ * @hw_device : ptr to struct storing camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * BAD_VALUE : Invalid Camera ID
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::open_legacy(__unused const struct hw_module_t* module,
+ const char* id, __unused uint32_t halVersion, struct hw_device_t** hw_device)
+{
+ int rc = NO_ERROR;
+ LOGH("id= %d", atoi(id));
+ if (!id) {
+ LOGE("Invalid camera id");
+ return BAD_VALUE;
+ }
+
+ rc = gMuxer->cameraDeviceOpen(atoi(id), hw_device);
+ LOGH("id= %d, rc: %d", atoi(id), rc);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : set_preview_window
+ *
+ * DESCRIPTION: Set Preview window for main camera
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @window: Preview window ops
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::set_preview_window(struct camera_device * device,
+ struct preview_stream_ops *window)
+{
+ int rc = NO_ERROR;
+ CHECK_MUXER_ERROR();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ // Set preview window only for primary camera
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+ rc = hwi->set_preview_window(pCam->dev, window);
+ if (rc != NO_ERROR) {
+ LOGE("Error!! setting preview window");
+ return rc;
+ }
+ break;
+ }
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : set_callBacks
+ *
+ * DESCRIPTION: Set Framework callbacks to notify various frame data asynchronously
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @notify_cb: Notification callback
+ * @data_cb: data callback
+ * @data_cb_timestamp: data timestamp callback
+ * @get_memory: callback to obtain memory
+ * @user : userdata
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::set_callBacks(struct camera_device * device,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user)
+{
+ LOGH("E");
+ CHECK_MUXER();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA(cam);
+
+ // Set callbacks to HWI
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ hwi->set_CallBacks(pCam->dev, notify_cb, data_cb, data_cb_timestamp,
+ get_memory, user);
+
+ // Set JPG callbacks
+ // sending the physical camera description with the Jpeg callback
+ // this will be retrieved in callbacks to get the cam instance
+ // delivering JPEGs
+ hwi->setJpegCallBacks(jpeg_data_callback, (void*)pCam);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ rc = gMuxer->setMainJpegCallbackCookie((void*)(pCam));
+ if(rc != NO_ERROR) {
+ LOGW("Error setting Jpeg callback cookie");
+ }
+ }
+ }
+ // Store callback in Muxer to send data callbacks
+ rc = gMuxer->setDataCallback(data_cb);
+ if(rc != NO_ERROR) {
+ LOGW("Error setting data callback");
+ }
+ // memory callback stored to allocate memory for MPO buffer
+ rc = gMuxer->setMemoryCallback(get_memory);
+ if(rc != NO_ERROR) {
+ LOGW("Error setting memory callback");
+ }
+ // actual user callback cookie is saved in Muxer
+ // this will be used to deliver final MPO callback to the framework
+ rc = gMuxer->setMpoCallbackCookie(user);
+ if(rc != NO_ERROR) {
+ LOGW("Error setting mpo cookie");
+ }
+
+ LOGH("X");
+
+}
+
+/*===========================================================================
+ * FUNCTION : enable_msg_type
+ *
+ * DESCRIPTION: Enable msg_type to send callbacks
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @msg_type: callback Message type to be enabled
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::enable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ LOGH("E");
+ CHECK_MUXER();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+ hwi->enable_msg_type(pCam->dev, msg_type);
+ }
+ LOGH("X");
+}
+
+/*===========================================================================
+ * FUNCTION : disable_msg_type
+ *
+ * DESCRIPTION: disable msg_type to send callbacks
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @msg_type: callback Message type to be disabled
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::disable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ LOGH("E");
+ CHECK_MUXER();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+ hwi->disable_msg_type(pCam->dev, msg_type);
+ }
+ LOGH("X");
+}
+
+/*===========================================================================
+ * FUNCTION : msg_type_enabled
+ *
+ * DESCRIPTION: Check if message type enabled
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @msg_type: message type
+ *
+ * RETURN : true/false
+ *==========================================================================*/
+int QCameraMuxer::msg_type_enabled(struct camera_device * device, int32_t msg_type)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ return hwi->msg_type_enabled(pCam->dev, msg_type);
+ }
+ }
+ LOGH("X");
+ return false;
+}
+
+/*===========================================================================
+ * FUNCTION : start_preview
+ *
+ * DESCRIPTION: Starts logical camera preview
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::start_preview(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ // prepare preview first for all cameras
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->prepare_preview(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error preparing preview !! ");
+ return rc;
+ }
+ }
+
+ if (cam->numCameras > 1) {
+ uint sessionId = 0;
+ // Set up sync for camera sessions
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if(pCam->mode == CAM_MODE_PRIMARY) {
+ // bundle primary cam with all aux cameras
+ for (uint32_t j = 0; j < cam->numCameras; j++) {
+ if (j == cam->nPrimaryPhyCamIndex) {
+ continue;
+ }
+ sessionId = cam->sId[j];
+ LOGH("Related cam id: %d, server id: %d sync ON"
+ " related session_id %d",
+ cam->pId[i], cam->sId[i], sessionId);
+ rc = hwi->bundleRelatedCameras(true, sessionId);
+ if (rc != NO_ERROR) {
+ LOGE("Error Bundling physical cameras !! ");
+ return rc;
+ }
+ }
+ }
+
+ if (pCam->mode == CAM_MODE_SECONDARY) {
+ // bundle all aux cam with primary cams
+ sessionId = cam->sId[cam->nPrimaryPhyCamIndex];
+ LOGH("Related cam id: %d, server id: %d sync ON"
+ " related session_id %d",
+ cam->pId[i], cam->sId[i], sessionId);
+ rc = hwi->bundleRelatedCameras(true, sessionId);
+ if (rc != NO_ERROR) {
+ LOGE("Error Bundling physical cameras !! ");
+ return rc;
+ }
+ }
+ }
+
+ // Remember Sync is ON
+ cam->bSyncOn = true;
+ }
+ // Start Preview for all cameras
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+ rc = hwi->start_preview(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error starting preview !! ");
+ return rc;
+ }
+ }
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : stop_preview
+ *
+ * DESCRIPTION: Stops logical camera preview
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::stop_preview(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ QCamera2HardwareInterface::stop_preview(pCam->dev);
+ }
+
+ //Flush JPEG Queues. Nodes in Main and Aux JPEGQ are not valid after preview stopped.
+ gMuxer->m_MainJpegQ.flush();
+ gMuxer->m_AuxJpegQ.flush();
+ LOGH(" X");
+}
+
+/*===========================================================================
+ * FUNCTION : preview_enabled
+ *
+ * DESCRIPTION: Checks preview enabled
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN : true/false
+ *==========================================================================*/
+int QCameraMuxer::preview_enabled(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ return hwi->preview_enabled(pCam->dev);
+ }
+ }
+ LOGH("X");
+ return false;
+}
+
+/*===========================================================================
+ * FUNCTION : store_meta_data_in_buffers
+ *
+ * DESCRIPTION: Stores metadata in buffers
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @enable: Enable/disable metadata
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::store_meta_data_in_buffers(struct camera_device * device, int enable)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->store_meta_data_in_buffers(pCam->dev, enable);
+ if (rc != NO_ERROR) {
+ LOGE("Error storing metat data !! ");
+ return rc;
+ }
+ }
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : start_recording
+ *
+ * DESCRIPTION: Starts recording on camcorder
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::start_recording(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ bool previewRestartNeeded = false;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ // In cases where recording hint is not set, hwi->start_recording will
+ // internally restart the preview.
+ // To take the preview restart control in muxer,
+ // 1. call pre_start_recording first
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->pre_start_recording(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error preparing recording start!! ");
+ return rc;
+ }
+ }
+
+ // 2. Check if preview restart is needed. Check all cameras.
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if (hwi->isPreviewRestartNeeded()) {
+ previewRestartNeeded = hwi->isPreviewRestartNeeded();
+ break;
+ }
+ }
+
+ if (previewRestartNeeded) {
+ // 3. if preview restart needed. stop the preview first
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->restart_stop_preview(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error in restart stop preview!! ");
+ return rc;
+ }
+ }
+
+ //4. Update the recording hint value to TRUE
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->setRecordingHintValue(TRUE);
+ if (rc != NO_ERROR) {
+ LOGE("Error in setting recording hint value!! ");
+ return rc;
+ }
+ gMuxer->m_bRecordingHintInternallySet = TRUE;
+ }
+
+ // 5. start the preview
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->restart_start_preview(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error in restart start preview!! ");
+ return rc;
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ rc = hwi->start_recording(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error starting recording!! ");
+ }
+ break;
+ }
+ }
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : stop_recording
+ *
+ * DESCRIPTION: Stops recording on camcorder
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::stop_recording(struct camera_device * device)
+{
+
+ int rc = NO_ERROR;
+ LOGH("E");
+
+ CHECK_MUXER();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ QCamera2HardwareInterface::stop_recording(pCam->dev);
+ break;
+ }
+ }
+
+ // If recording hint is set internally to TRUE,
+ // we need to set it to FALSE.
+ // preview restart is needed in between
+ if (gMuxer->m_bRecordingHintInternallySet) {
+ // stop the preview first
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ rc = hwi->restart_stop_preview(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error in restart stop preview!! ");
+ return;
+ }
+ }
+
+ // Update the recording hint value to FALSE
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ rc = hwi->setRecordingHintValue(FALSE);
+ if (rc != NO_ERROR) {
+ LOGE("Error in setting recording hint value!! ");
+ return;
+ }
+ gMuxer->m_bRecordingHintInternallySet = FALSE;
+ }
+
+ // start the preview
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ rc = hwi->restart_start_preview(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error in restart start preview!! ");
+ return;
+ }
+ }
+ }
+ LOGH("X");
+}
+
+/*===========================================================================
+ * FUNCTION : recording_enabled
+ *
+ * DESCRIPTION: Checks for recording enabled
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN : true/false
+ *==========================================================================*/
+int QCameraMuxer::recording_enabled(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ return hwi->recording_enabled(pCam->dev);
+ }
+ }
+ LOGH("X");
+ return false;
+}
+
+/*===========================================================================
+ * FUNCTION : release_recording_frame
+ *
+ * DESCRIPTION: Release the recording frame
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @opaque: Frame to be released
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::release_recording_frame(struct camera_device * device,
+ const void *opaque)
+{
+ LOGH("E");
+ CHECK_MUXER();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ QCamera2HardwareInterface::release_recording_frame(pCam->dev, opaque);
+ break;
+ }
+ }
+ LOGH("X");
+}
+
+/*===========================================================================
+ * FUNCTION : auto_focus
+ *
+ * DESCRIPTION: Performs auto focus on camera
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::auto_focus(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+ // Call auto focus on main camera
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ rc = QCamera2HardwareInterface::auto_focus(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error auto focusing !! ");
+ return rc;
+ }
+ break;
+ }
+ }
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : cancel_auto_focus
+ *
+ * DESCRIPTION: Cancels auto focus
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::cancel_auto_focus(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+ // Cancel auto focus on primary camera
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ rc = QCamera2HardwareInterface::cancel_auto_focus(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error cancelling auto focus !! ");
+ return rc;
+ }
+ break;
+ }
+ }
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : take_picture
+ *
+ * DESCRIPTION: Take snapshots on device
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::take_picture(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ bool previewRestartNeeded = false;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("persist.camera.dual.camera.mpo", prop, "1");
+ gMuxer->m_bMpoEnabled = atoi(prop);
+ // If only one Physical Camera included in Logical, disable MPO
+ int numOfAcitvePhyCam = 0;
+ gMuxer->getActiveNumOfPhyCam(cam, numOfAcitvePhyCam);
+ if (gMuxer->m_bMpoEnabled && numOfAcitvePhyCam <= 1) {
+ gMuxer->m_bMpoEnabled = 0;
+ }
+ LOGH("dualCamera MPO Enabled:%d ", gMuxer->m_bMpoEnabled);
+
+ if (!gMuxer->mJpegClientHandle) {
+ // set up jpeg handles
+ pCam = gMuxer->getPhysicalCamera(cam, 0);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->getJpegHandleInfo(&gMuxer->mJpegOps, &gMuxer->mJpegMpoOps,
+ &gMuxer->mJpegClientHandle);
+ if (rc != NO_ERROR) {
+ LOGE("Error retrieving jpeg handle!");
+ return rc;
+ }
+
+ for (uint32_t i = 1; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->setJpegHandleInfo(&gMuxer->mJpegOps, &gMuxer->mJpegMpoOps,
+ gMuxer->mJpegClientHandle);
+ if (rc != NO_ERROR) {
+ LOGE("Error setting jpeg handle %d!", i);
+ return rc;
+ }
+ }
+ }
+
+ // prepare snapshot for main camera
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ rc = hwi->prepare_snapshot(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error preparing for snapshot !! ");
+ return rc;
+ }
+ }
+ // set Mpo composition for each session
+ rc = hwi->setMpoComposition(gMuxer->m_bMpoEnabled);
+ //disable MPO if AOST features are enabled
+ if (rc != NO_ERROR) {
+ gMuxer->m_bMpoEnabled = 0;
+ rc = NO_ERROR;
+ }
+ }
+
+ // initialize Jpeg Queues
+ gMuxer->m_MainJpegQ.init();
+ gMuxer->m_AuxJpegQ.init();
+ gMuxer->m_ComposeMpoTh.sendCmd(
+ CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE);
+
+ // In cases where recording hint is set, preview is running,
+ // hwi->take_picture will internally restart the preview.
+ // To take the preview restart control in muxer,
+ // 1. call pre_take_picture first
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ // no need to call pre_take_pic on Aux if not MPO (for AOST,liveshot...etc.)
+ if ( (gMuxer->m_bMpoEnabled == 1) || (pCam->mode == CAM_MODE_PRIMARY) ) {
+ rc = hwi->pre_take_picture(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error preparing take_picture!! ");
+ return rc;
+ }
+ }
+ }
+
+ // 2. Check if preview restart is needed. Check all cameras.
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if (hwi->isPreviewRestartNeeded()) {
+ previewRestartNeeded = hwi->isPreviewRestartNeeded();
+ break;
+ }
+ }
+
+ if (previewRestartNeeded) {
+ // 3. if preview restart needed. stop the preview first
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->restart_stop_preview(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error in restart stop preview!! ");
+ return rc;
+ }
+ }
+
+ //4. Update the recording hint value to FALSE
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->setRecordingHintValue(FALSE);
+ if (rc != NO_ERROR) {
+ LOGE("Error in setting recording hint value!! ");
+ return rc;
+ }
+ }
+
+ // 5. start the preview
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = hwi->restart_start_preview(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error in restart start preview!! ");
+ return rc;
+ }
+ }
+ }
+
+ // As frame sync for dual cameras is enabled, the take picture call
+ // for secondary camera is handled only till HAL level to init corresponding
+ // pproc channel and update statemachine.
+ // This call is forwarded to mm-camera-intf only for primary camera
+ // Primary camera should receive the take picture call after all secondary
+ // camera statemachines are updated
+ for (int32_t i = cam->numCameras-1 ; i >= 0; i--) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ // no need to call take_pic on Aux if not MPO (for AOST)
+ if ( (gMuxer->m_bMpoEnabled == 1) || (pCam->mode == CAM_MODE_PRIMARY) ) {
+ rc = QCamera2HardwareInterface::take_picture(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error taking picture !! ");
+ return rc;
+ }
+ }
+ }
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : cancel_picture
+ *
+ * DESCRIPTION: Cancel the take picture call
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::cancel_picture(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = QCamera2HardwareInterface::cancel_picture(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error cancelling picture !! ");
+ return rc;
+ }
+ }
+ gMuxer->m_ComposeMpoTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, FALSE, FALSE);
+ // flush Jpeg Queues
+ gMuxer->m_MainJpegQ.flush();
+ gMuxer->m_AuxJpegQ.flush();
+
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : set_parameters
+ *
+ * DESCRIPTION: Sets the parameters on camera
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @parms : Parameters to be set on camera
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::set_parameters(struct camera_device * device,
+ const char *parms)
+
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ bool needRestart = false;
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = QCamera2HardwareInterface::set_parameters(pCam->dev, parms);
+ if (rc != NO_ERROR) {
+ LOGE("Error setting parameters !! ");
+ return rc;
+ }
+
+ needRestart |= hwi->getNeedRestart();
+ }
+
+ if (needRestart) {
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ LOGD("stopping preview for cam %d", i);
+ rc = QCamera2HardwareInterface::stop_after_set_params(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error stopping camera rc=%d!! ", rc);
+ return rc;
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ LOGD("commiting parameters for cam %d", i);
+ rc = QCamera2HardwareInterface::commit_params(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error committing parameters rc=%d!! ", rc);
+ return rc;
+ }
+ }
+
+ if (needRestart) {
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ LOGD("restarting preview for cam %d", i);
+ rc = QCamera2HardwareInterface::restart_after_set_params(pCam->dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error restarting camera rc=%d!! ", rc);
+ return rc;
+ }
+ }
+ }
+
+ LOGH(" X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : get_parameters
+ *
+ * DESCRIPTION: Gets the parameters on camera
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN : Parameter string or NULL
+ *==========================================================================*/
+char* QCameraMuxer::get_parameters(struct camera_device * device)
+{
+ LOGH("E");
+
+ if (!gMuxer)
+ return NULL;
+
+ char* ret = NULL;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ if (!cam) {
+ LOGE("Error getting logical camera");
+ return NULL;
+ }
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ if (!pCam) {
+ LOGE("Error getting physical camera");
+ return NULL;
+ }
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ if (!hwi) {
+ LOGE("Allocation of hardware interface failed");
+ return NULL;
+ }
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ // Get only primary camera parameters
+ ret = QCamera2HardwareInterface::get_parameters(pCam->dev);
+ break;
+ }
+ }
+
+ LOGH("X");
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : put_parameters
+ *
+ * DESCRIPTION: Puts parameters on camera
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @parm : parameters
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::put_parameters(struct camera_device * device, char *parm)
+{
+ LOGH("E");
+ CHECK_MUXER();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ if (pCam->mode == CAM_MODE_PRIMARY) {
+ // Parameters are not used in HWI and hence freed
+ QCamera2HardwareInterface::put_parameters(pCam->dev, parm);
+ break;
+ }
+ }
+ LOGH("X");
+}
+
+/*===========================================================================
+ * FUNCTION : send_command
+ *
+ * DESCRIPTION: Send command to camera
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @cmd : Command
+ * @arg1/arg2 : command arguments
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::send_command(struct camera_device * device,
+ int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = QCamera2HardwareInterface::send_command(pCam->dev, cmd, arg1, arg2);
+ if (rc != NO_ERROR) {
+ LOGE("Error sending command !! ");
+ return rc;
+ }
+ }
+
+ switch (cmd) {
+#ifndef VANILLA_HAL
+ case CAMERA_CMD_LONGSHOT_ON:
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = QCamera2HardwareInterface::send_command_restart(pCam->dev,
+ cmd, arg1, arg2);
+ if (rc != NO_ERROR) {
+ LOGE("Error sending command restart !! ");
+ return rc;
+ }
+ }
+ break;
+ case CAMERA_CMD_LONGSHOT_OFF:
+ gMuxer->m_ComposeMpoTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC,
+ FALSE, FALSE);
+ // flush Jpeg Queues
+ gMuxer->m_MainJpegQ.flush();
+ gMuxer->m_AuxJpegQ.flush();
+ break;
+#endif
+ default:
+ // do nothing
+ rc = NO_ERROR;
+ break;
+ }
+
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : release
+ *
+ * DESCRIPTION: Release the camera
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::release(struct camera_device * device)
+{
+ LOGH("E");
+ CHECK_MUXER();
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI(hwi);
+
+ QCamera2HardwareInterface::release(pCam->dev);
+ }
+ LOGH("X");
+}
+
+/*===========================================================================
+ * FUNCTION : dump
+ *
+ * DESCRIPTION: Dump the camera info
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ * @fd : fd
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::dump(struct camera_device * device, int fd)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(device);
+ CHECK_CAMERA_ERROR(cam);
+
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ rc = QCamera2HardwareInterface::dump(pCam->dev, fd);
+ if (rc != NO_ERROR) {
+ LOGE("Error dumping");
+ return rc;
+ }
+ }
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : close_camera_device
+ *
+ * DESCRIPTION: Close the camera
+ *
+ * PARAMETERS :
+ * @hw_dev : camera hardware device info
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::close_camera_device(hw_device_t *hw_dev)
+{
+ LOGH("E");
+ CHECK_MUXER_ERROR();
+ int rc = NO_ERROR;
+ qcamera_physical_descriptor_t *pCam = NULL;
+ camera_device_t *cam_dev = (camera_device_t*)hw_dev;
+ qcamera_logical_descriptor_t *cam = gMuxer->getLogicalCamera(cam_dev);
+ CHECK_CAMERA_ERROR(cam);
+
+ // Unlink camera sessions
+ if (cam->bSyncOn) {
+ if (cam->numCameras > 1) {
+ uint sessionId = 0;
+ // unbundle primary camera with all aux cameras
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ if(pCam->mode == CAM_MODE_PRIMARY) {
+ // bundle primary cam with all aux cameras
+ for (uint32_t j = 0; j < cam->numCameras; j++) {
+ if (j == cam->nPrimaryPhyCamIndex) {
+ continue;
+ }
+ sessionId = cam->sId[j];
+ LOGH("Related cam id: %d, server id: %d sync OFF"
+ " related session_id %d",
+ cam->pId[i], cam->sId[i], sessionId);
+ rc = hwi->bundleRelatedCameras(false, sessionId);
+ if (rc != NO_ERROR) {
+ LOGE("Error Bundling physical cameras !! ");
+ break;
+ }
+ }
+ }
+
+ if (pCam->mode == CAM_MODE_SECONDARY) {
+ // unbundle all aux cam with primary cams
+ sessionId = cam->sId[cam->nPrimaryPhyCamIndex];
+ LOGH("Related cam id: %d, server id: %d sync OFF"
+ " related session_id %d",
+ cam->pId[i], cam->sId[i], sessionId);
+ rc = hwi->bundleRelatedCameras(false, sessionId);
+ if (rc != NO_ERROR) {
+ LOGE("Error Bundling physical cameras !! ");
+ break;
+ }
+ }
+ }
+ }
+ cam->bSyncOn = false;
+ }
+
+ // Attempt to close all cameras regardless of unbundle results
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ pCam = gMuxer->getPhysicalCamera(cam, i);
+ CHECK_CAMERA_ERROR(pCam);
+
+ hw_device_t *dev = (hw_device_t*)(pCam->dev);
+ LOGH("hw device %x, hw %x", dev, pCam->hwi);
+
+ rc = QCamera2HardwareInterface::close_camera_device(dev);
+ if (rc != NO_ERROR) {
+ LOGE("Error closing camera");
+ }
+ pCam->hwi = NULL;
+ pCam->dev = NULL;
+ }
+
+ // Reset JPEG client handle
+ gMuxer->setJpegHandle(0);
+ LOGH("X, rc: %d", rc);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : setupLogicalCameras
+ *
+ * DESCRIPTION : Creates Camera Muxer if not created
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * other: non-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::setupLogicalCameras()
+{
+ int rc = NO_ERROR;
+ char prop[PROPERTY_VALUE_MAX];
+ int i = 0;
+ int primaryType = CAM_TYPE_MAIN;
+
+ LOGH("[%d] E: rc = %d", rc);
+ // Signifies whether AUX camera has to be exposed as physical camera
+ property_get("persist.camera.aux.camera", prop, "0");
+ m_bAuxCameraExposed = atoi(prop);
+
+ // Signifies whether AUX camera needs to be swapped
+ property_get("persist.camera.auxcamera.swap", prop, "0");
+ int swapAux = atoi(prop);
+ if (swapAux != 0) {
+ primaryType = CAM_TYPE_AUX;
+ }
+
+ // Check for number of camera present on device
+ if (!m_nPhyCameras || (m_nPhyCameras > MM_CAMERA_MAX_NUM_SENSORS)) {
+ LOGE("Error!! Invalid number of cameras: %d",
+ m_nPhyCameras);
+ return BAD_VALUE;
+ }
+
+ m_pPhyCamera = new qcamera_physical_descriptor_t[m_nPhyCameras];
+ if (!m_pPhyCamera) {
+ LOGE("Error allocating camera info buffer!!");
+ return NO_MEMORY;
+ }
+ memset(m_pPhyCamera, 0x00,
+ (m_nPhyCameras * sizeof(qcamera_physical_descriptor_t)));
+ uint32_t cameraId = 0;
+ m_nLogicalCameras = 0;
+
+ // Enumerate physical cameras and logical
+ for (i = 0; i < m_nPhyCameras ; i++, cameraId++) {
+ camera_info *info = &m_pPhyCamera[i].cam_info;
+ rc = QCamera2HardwareInterface::getCapabilities(cameraId,
+ info, &m_pPhyCamera[i].type);
+ m_pPhyCamera[i].id = cameraId;
+ m_pPhyCamera[i].device_version = CAMERA_DEVICE_API_VERSION_1_0;
+ m_pPhyCamera[i].mode = CAM_MODE_PRIMARY;
+
+ if (!m_bAuxCameraExposed && (m_pPhyCamera[i].type != primaryType)) {
+ m_pPhyCamera[i].mode = CAM_MODE_SECONDARY;
+ LOGH("Camera ID: %d, Aux Camera, type: %d, facing: %d",
+ cameraId, m_pPhyCamera[i].type,
+ m_pPhyCamera[i].cam_info.facing);
+ }
+ else {
+ m_nLogicalCameras++;
+ LOGH("Camera ID: %d, Main Camera, type: %d, facing: %d",
+ cameraId, m_pPhyCamera[i].type,
+ m_pPhyCamera[i].cam_info.facing);
+ }
+ }
+
+ if (!m_nLogicalCameras) {
+ // No Main camera detected, return from here
+ LOGE("Error !!!! detecting main camera!!");
+ delete [] m_pPhyCamera;
+ m_pPhyCamera = NULL;
+ return -ENODEV;
+ }
+ // Allocate Logical Camera descriptors
+ m_pLogicalCamera = new qcamera_logical_descriptor_t[m_nLogicalCameras];
+ if (!m_pLogicalCamera) {
+ LOGE("Error !!!! allocating camera info buffer!!");
+ delete [] m_pPhyCamera;
+ m_pPhyCamera = NULL;
+ return NO_MEMORY;
+ }
+ memset(m_pLogicalCamera, 0x00,
+ (m_nLogicalCameras * sizeof(qcamera_logical_descriptor_t)));
+ // Assign MAIN cameras for each logical camera
+ int index = 0;
+ for (i = 0; i < m_nPhyCameras ; i++) {
+ if (m_pPhyCamera[i].mode == CAM_MODE_PRIMARY) {
+ m_pLogicalCamera[index].nPrimaryPhyCamIndex = 0;
+ m_pLogicalCamera[index].id = index;
+ m_pLogicalCamera[index].device_version = CAMERA_DEVICE_API_VERSION_1_0;
+ m_pLogicalCamera[index].pId[0] = i;
+ m_pLogicalCamera[index].type[0] = CAM_TYPE_MAIN;
+ m_pLogicalCamera[index].mode[0] = CAM_MODE_PRIMARY;
+ m_pLogicalCamera[index].facing = m_pPhyCamera[i].cam_info.facing;
+ m_pLogicalCamera[index].numCameras++;
+ LOGH("Logical Main Camera ID: %d, facing: %d,"
+ "Phy Id: %d type: %d mode: %d",
+ m_pLogicalCamera[index].id,
+ m_pLogicalCamera[index].facing,
+ m_pLogicalCamera[index].pId[0],
+ m_pLogicalCamera[index].type[0],
+ m_pLogicalCamera[index].mode[0]);
+
+ index++;
+ }
+ }
+ //Now assign AUX cameras to logical camera
+ for (i = 0; i < m_nPhyCameras ; i++) {
+ if (m_pPhyCamera[i].mode == CAM_MODE_SECONDARY) {
+ for (int j = 0; j < m_nLogicalCameras; j++) {
+ int n = m_pLogicalCamera[j].numCameras;
+ ///@note n can only be 1 at this point
+ if ((n < MAX_NUM_CAMERA_PER_BUNDLE) &&
+ (m_pLogicalCamera[j].facing ==
+ m_pPhyCamera[i].cam_info.facing)) {
+ m_pLogicalCamera[j].pId[n] = i;
+ m_pLogicalCamera[j].type[n] = CAM_TYPE_AUX;
+ m_pLogicalCamera[j].mode[n] = CAM_MODE_SECONDARY;
+ m_pLogicalCamera[j].numCameras++;
+ LOGH("Aux %d for Logical Camera ID: %d,"
+ "aux phy id:%d, type: %d mode: %d",
+ n, j, m_pLogicalCamera[j].pId[n],
+ m_pLogicalCamera[j].type[n], m_pLogicalCamera[j].mode[n]);
+ }
+ }
+ }
+ }
+ //Print logical and physical camera tables
+ for (i = 0; i < m_nLogicalCameras ; i++) {
+ for (uint8_t j = 0; j < m_pLogicalCamera[i].numCameras; j++) {
+ LOGH("Logical Camera ID: %d, index: %d, "
+ "facing: %d, Phy Id: %d type: %d mode: %d",
+ i, j, m_pLogicalCamera[i].facing,
+ m_pLogicalCamera[i].pId[j], m_pLogicalCamera[i].type[j],
+ m_pLogicalCamera[i].mode[j]);
+ }
+ }
+ LOGH("[%d] X: rc = %d", rc);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : getNumberOfCameras
+ *
+ * DESCRIPTION: query number of logical cameras detected
+ *
+ * RETURN : number of cameras detected
+ *==========================================================================*/
+int QCameraMuxer::getNumberOfCameras()
+{
+ return m_nLogicalCameras;
+}
+
+/*===========================================================================
+ * FUNCTION : getCameraInfo
+ *
+ * DESCRIPTION: query camera information with its ID
+ *
+ * PARAMETERS :
+ * @camera_id : camera ID
+ * @info : ptr to camera info struct
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::getCameraInfo(int camera_id,
+ struct camera_info *info, __unused cam_sync_type_t *p_cam_type)
+{
+ int rc = NO_ERROR;
+ LOGH("E, camera_id = %d", camera_id);
+ cam_sync_type_t cam_type = CAM_TYPE_MAIN;
+
+ if (!m_nLogicalCameras || (camera_id >= m_nLogicalCameras) ||
+ !info || (camera_id < 0)) {
+ LOGE("m_nLogicalCameras: %d, camera id: %d",
+ m_nLogicalCameras, camera_id);
+ return -ENODEV;
+ }
+
+ if (!m_pLogicalCamera || !m_pPhyCamera) {
+ LOGE("Error! Cameras not initialized!");
+ return NO_INIT;
+ }
+ uint32_t phy_id =
+ m_pLogicalCamera[camera_id].pId[
+ m_pLogicalCamera[camera_id].nPrimaryPhyCamIndex];
+ // Call HAL3 getCamInfo to get the flash light info through static metatdata
+ // regardless of HAL version
+ rc = QCamera3HardwareInterface::getCamInfo(phy_id, info);
+ info->device_version = CAMERA_DEVICE_API_VERSION_1_0; // Hardcode the HAL to HAL1
+ LOGH("X");
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : setCallbacks
+ *
+ * DESCRIPTION: set callback functions to send asynchronous notifications to
+ * frameworks.
+ *
+ * PARAMETERS :
+ * @callbacks : callback function pointer
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraMuxer::setCallbacks(const camera_module_callbacks_t *callbacks)
+{
+ if(callbacks) {
+ m_pCallbacks = callbacks;
+ return NO_ERROR;
+ } else {
+ return BAD_TYPE;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : setDataCallback
+ *
+ * DESCRIPTION: set data callback function for snapshots
+ *
+ * PARAMETERS :
+ * @data_cb : callback function pointer
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraMuxer::setDataCallback(camera_data_callback data_cb)
+{
+ if(data_cb) {
+ mDataCb = data_cb;
+ return NO_ERROR;
+ } else {
+ return BAD_TYPE;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : setMemoryCallback
+ *
+ * DESCRIPTION: set get memory callback for memory allocations
+ *
+ * PARAMETERS :
+ * @get_memory : callback function pointer
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraMuxer::setMemoryCallback(camera_request_memory get_memory)
+{
+ if(get_memory) {
+ mGetMemoryCb = get_memory;
+ return NO_ERROR;
+ } else {
+ return BAD_TYPE;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : setMpoCallbackCookie
+ *
+ * DESCRIPTION: set mpo callback cookie. will be used for sending final MPO callbacks
+ * to framework
+ *
+ * PARAMETERS :
+ * @mpoCbCookie : callback function pointer
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraMuxer::setMpoCallbackCookie(void* mpoCbCookie)
+{
+ if(mpoCbCookie) {
+ m_pMpoCallbackCookie = mpoCbCookie;
+ return NO_ERROR;
+ } else {
+ return BAD_TYPE;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : getMpoCallbackCookie
+ *
+ * DESCRIPTION: gets the mpo callback cookie. will be used for sending final MPO callbacks
+ * to framework
+ *
+ * PARAMETERS :none
+ *
+ * RETURN :void ptr to the mpo callback cookie
+ *==========================================================================*/
+void* QCameraMuxer::getMpoCallbackCookie(void)
+{
+ return m_pMpoCallbackCookie;
+}
+
+/*===========================================================================
+ * FUNCTION : setMainJpegCallbackCookie
+ *
+ * DESCRIPTION: set jpeg callback cookie.
+ * set to phy cam instance of the primary related cam instance
+ *
+ * PARAMETERS :
+ * @jpegCbCookie : ptr to jpeg cookie
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraMuxer::setMainJpegCallbackCookie(void* jpegCbCookie)
+{
+ if(jpegCbCookie) {
+ m_pJpegCallbackCookie = jpegCbCookie;
+ return NO_ERROR;
+ } else {
+ return BAD_TYPE;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : getMainJpegCallbackCookie
+ *
+ * DESCRIPTION: gets the jpeg callback cookie for primary related cam instance
+ * set to phy cam instance of the primary related cam instance
+ *
+ * PARAMETERS :none
+ *
+ * RETURN :void ptr to the jpeg callback cookie
+ *==========================================================================*/
+void* QCameraMuxer::getMainJpegCallbackCookie(void)
+{
+ return m_pJpegCallbackCookie;
+}
+
+/*===========================================================================
+ * FUNCTION : cameraDeviceOpen
+ *
+ * DESCRIPTION: open a camera device with its ID
+ *
+ * PARAMETERS :
+ * @camera_id : camera ID
+ * @hw_device : ptr to struct storing camera hardware device info
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCameraMuxer::cameraDeviceOpen(int camera_id,
+ struct hw_device_t **hw_device)
+{
+ int rc = NO_ERROR;
+ uint32_t phyId = 0;
+ qcamera_logical_descriptor_t *cam = NULL;
+
+ if (camera_id < 0 || camera_id >= m_nLogicalCameras) {
+ LOGE("Camera id %d not found!", camera_id);
+ return -ENODEV;
+ }
+
+ if ( NULL == m_pLogicalCamera) {
+ LOGE("Hal descriptor table is not initialized!");
+ return NO_INIT;
+ }
+
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("persist.camera.dc.frame.sync", prop, "1");
+ m_bFrameSyncEnabled = atoi(prop);
+
+ // Get logical camera
+ cam = &m_pLogicalCamera[camera_id];
+
+ if (m_pLogicalCamera[camera_id].device_version ==
+ CAMERA_DEVICE_API_VERSION_1_0) {
+ // HW Dev Holders
+ hw_device_t *hw_dev[cam->numCameras];
+
+ if (m_pPhyCamera[cam->pId[0]].type != CAM_TYPE_MAIN) {
+ LOGE("Physical camera at index 0 is not main!");
+ return UNKNOWN_ERROR;
+ }
+
+ // Open all physical cameras
+ for (uint32_t i = 0; i < cam->numCameras; i++) {
+ phyId = cam->pId[i];
+ QCamera2HardwareInterface *hw =
+ new QCamera2HardwareInterface((uint32_t)phyId);
+ if (!hw) {
+ LOGE("Allocation of hardware interface failed");
+ return NO_MEMORY;
+ }
+ hw_dev[i] = NULL;
+
+ // Make Camera HWI aware of its mode
+ cam_sync_related_sensors_event_info_t info;
+ info.sync_control = CAM_SYNC_RELATED_SENSORS_ON;
+ info.mode = m_pPhyCamera[phyId].mode;
+ info.type = m_pPhyCamera[phyId].type;
+ rc = hw->setRelatedCamSyncInfo(&info);
+ hw->setFrameSyncEnabled(m_bFrameSyncEnabled);
+ if (rc != NO_ERROR) {
+ LOGE("setRelatedCamSyncInfo failed %d", rc);
+ delete hw;
+ return rc;
+ }
+
+ rc = hw->openCamera(&hw_dev[i]);
+ if (rc != NO_ERROR) {
+ delete hw;
+ return rc;
+ }
+ hw->getCameraSessionId(&m_pPhyCamera[phyId].camera_server_id);
+ m_pPhyCamera[phyId].dev = reinterpret_cast<camera_device_t*>(hw_dev[i]);
+ m_pPhyCamera[phyId].hwi = hw;
+ cam->sId[i] = m_pPhyCamera[phyId].camera_server_id;
+ LOGH("camera id %d server id : %d hw device %x, hw %x",
+ phyId, cam->sId[i], hw_dev[i], hw);
+ }
+ } else {
+ LOGE("Device version for camera id %d invalid %d",
+ camera_id, m_pLogicalCamera[camera_id].device_version);
+ return BAD_VALUE;
+ }
+
+ cam->dev.common.tag = HARDWARE_DEVICE_TAG;
+ cam->dev.common.version = HARDWARE_DEVICE_API_VERSION(1, 0);
+ cam->dev.common.close = close_camera_device;
+ cam->dev.ops = &mCameraMuxerOps;
+ cam->dev.priv = (void*)cam;
+ *hw_device = &cam->dev.common;
+ return rc;
+}
+
+
+/*===========================================================================
+ * FUNCTION : getLogicalCamera
+ *
+ * DESCRIPTION: Get logical camera descriptor
+ *
+ * PARAMETERS :
+ * @device : camera hardware device info
+ *
+ * RETURN : logical camera descriptor or NULL
+ *==========================================================================*/
+qcamera_logical_descriptor_t* QCameraMuxer::getLogicalCamera(
+ struct camera_device * device)
+{
+ if(device && device->priv){
+ return (qcamera_logical_descriptor_t*)(device->priv);
+ }
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : getPhysicalCamera
+ *
+ * DESCRIPTION: Get physical camera descriptor
+ *
+ * PARAMETERS :
+ * @log_cam : Logical camera descriptor
+ * @index : physical camera index
+ *
+ * RETURN : physical camera descriptor or NULL
+ *==========================================================================*/
+qcamera_physical_descriptor_t* QCameraMuxer::getPhysicalCamera(
+ qcamera_logical_descriptor_t* log_cam, uint32_t index)
+{
+ if(!log_cam){
+ return NULL;
+ }
+ return &m_pPhyCamera[log_cam->pId[index]];
+}
+
+/*===========================================================================
+ * FUNCTION : getActiveNumOfPhyCam
+ *
+ * DESCRIPTION: Get active physical camera number in Logical Camera
+ *
+ * PARAMETERS :
+ * @log_cam : Logical camera descriptor
+ * @numOfAcitvePhyCam : number of active physical camera in Logical Camera.
+ *
+ * RETURN :
+ * NO_ERROR : success
+ * ENODEV : Camera not found
+ * other: non-zero failure code
+ *==========================================================================*/
+int32_t QCameraMuxer::getActiveNumOfPhyCam(
+ qcamera_logical_descriptor_t* log_cam, int& numOfAcitvePhyCam)
+{
+ CHECK_CAMERA_ERROR(log_cam);
+
+ numOfAcitvePhyCam = log_cam->numCameras;
+ return NO_ERROR;
+}
+
+
+/*===========================================================================
+ * FUNCTION : sendEvtNotify
+ *
+ * DESCRIPTION: send event notify to HWI for error callbacks
+ *
+ * PARAMETERS :
+ * @msg_type: msg type to be sent
+ * @ext1 : optional extension1
+ * @ext2 : optional extension2
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraMuxer::sendEvtNotify(int32_t msg_type, int32_t ext1,
+ int32_t ext2)
+{
+ LOGH("E");
+
+ CHECK_MUXER_ERROR();
+
+ qcamera_physical_descriptor_t *pCam = NULL;
+ pCam = (qcamera_physical_descriptor_t*)(gMuxer->getMainJpegCallbackCookie());
+
+ CHECK_CAMERA_ERROR(pCam);
+
+ QCamera2HardwareInterface *hwi = pCam->hwi;
+ CHECK_HWI_ERROR(hwi);
+
+ LOGH("X");
+ return pCam->hwi->sendEvtNotify(msg_type, ext1, ext2);
+}
+
+/*===========================================================================
+ * FUNCTION : composeMpo
+ *
+ * DESCRIPTION: Composition of the 2 MPOs
+ *
+ * PARAMETERS : none
+ * @main_Jpeg: pointer to info to Main Jpeg
+ * @aux_Jpeg : pointer to info to Aux JPEG
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraMuxer::composeMpo(cam_compose_jpeg_info_t* main_Jpeg,
+ cam_compose_jpeg_info_t* aux_Jpeg)
+{
+ LOGH("E Main Jpeg %p Aux Jpeg %p", main_Jpeg, aux_Jpeg);
+
+ CHECK_MUXER();
+ if(main_Jpeg == NULL || aux_Jpeg == NULL) {
+ LOGE("input buffers invalid, ret = NO_MEMORY");
+ gMuxer->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+ return;
+ }
+
+ pthread_mutex_lock(&m_JpegLock);
+
+ m_pRelCamMpoJpeg = mGetMemoryCb(-1, main_Jpeg->buffer->size +
+ aux_Jpeg->buffer->size, 1, m_pMpoCallbackCookie);
+ if (NULL == m_pRelCamMpoJpeg) {
+ LOGE("getMemory for mpo, ret = NO_MEMORY");
+ gMuxer->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+ pthread_mutex_unlock(&m_JpegLock);
+ return;
+ }
+
+ // fill all structures to send for composition
+ mm_jpeg_mpo_info_t mpo_compose_info;
+ mpo_compose_info.num_of_images = 2;
+ mpo_compose_info.primary_image.buf_filled_len = main_Jpeg->buffer->size;
+ mpo_compose_info.primary_image.buf_vaddr =
+ (uint8_t*)(main_Jpeg->buffer->data);
+ mpo_compose_info.aux_images[0].buf_filled_len = aux_Jpeg->buffer->size;
+ mpo_compose_info.aux_images[0].buf_vaddr =
+ (uint8_t*)(aux_Jpeg->buffer->data);
+ mpo_compose_info.output_buff.buf_vaddr =
+ (uint8_t*)m_pRelCamMpoJpeg->data;
+ mpo_compose_info.output_buff.buf_filled_len = 0;
+ mpo_compose_info.output_buff_size = main_Jpeg->buffer->size +
+ aux_Jpeg->buffer->size;
+
+ LOGD("MPO buffer size %d\n"
+ "expected size %d, mpo_compose_info.output_buff_size %d",
+ m_pRelCamMpoJpeg->size,
+ main_Jpeg->buffer->size + aux_Jpeg->buffer->size,
+ mpo_compose_info.output_buff_size);
+
+ LOGD("MPO primary buffer filled lengths\n"
+ "mpo_compose_info.primary_image.buf_filled_len %d\n"
+ "mpo_compose_info.primary_image.buf_vaddr %p",
+ mpo_compose_info.primary_image.buf_filled_len,
+ mpo_compose_info.primary_image.buf_vaddr);
+
+ LOGD("MPO aux buffer filled lengths\n"
+ "mpo_compose_info.aux_images[0].buf_filled_len %d"
+ "mpo_compose_info.aux_images[0].buf_vaddr %p",
+ mpo_compose_info.aux_images[0].buf_filled_len,
+ mpo_compose_info.aux_images[0].buf_vaddr);
+
+ if(m_bDumpImages) {
+ LOGD("Dumping Main Image for MPO");
+ char buf_main[QCAMERA_MAX_FILEPATH_LENGTH];
+ memset(buf_main, 0, sizeof(buf_main));
+ snprintf(buf_main, sizeof(buf_main),
+ QCAMERA_DUMP_FRM_LOCATION "Main.jpg");
+
+ int file_fd_main = open(buf_main, O_RDWR | O_CREAT, 0777);
+ if (file_fd_main >= 0) {
+ ssize_t written_len = write(file_fd_main,
+ mpo_compose_info.primary_image.buf_vaddr,
+ mpo_compose_info.primary_image.buf_filled_len);
+ fchmod(file_fd_main, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ LOGD("written number of bytes for main Image %zd\n",
+ written_len);
+ close(file_fd_main);
+ }
+
+ LOGD("Dumping Aux Image for MPO");
+ char buf_aux[QCAMERA_MAX_FILEPATH_LENGTH];
+ memset(buf_aux, 0, sizeof(buf_aux));
+ snprintf(buf_aux, sizeof(buf_aux),
+ QCAMERA_DUMP_FRM_LOCATION "Aux.jpg");
+
+ int file_fd_aux = open(buf_aux, O_RDWR | O_CREAT, 0777);
+ if (file_fd_aux >= 0) {
+ ssize_t written_len = write(file_fd_aux,
+ mpo_compose_info.aux_images[0].buf_vaddr,
+ mpo_compose_info.aux_images[0].buf_filled_len);
+ fchmod(file_fd_aux, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ LOGD("written number of bytes for Aux Image %zd\n",
+ written_len);
+ close(file_fd_aux);
+ }
+ }
+
+ int32_t rc = mJpegMpoOps.compose_mpo(&mpo_compose_info);
+ LOGD("Compose mpo returned %d", rc);
+
+ if(rc != NO_ERROR) {
+ LOGE("ComposeMpo failed, ret = %d", rc);
+ gMuxer->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+ pthread_mutex_unlock(&m_JpegLock);
+ return;
+ }
+
+ if(m_bDumpImages) {
+ char buf_mpo[QCAMERA_MAX_FILEPATH_LENGTH];
+ memset(buf_mpo, 0, sizeof(buf_mpo));
+ snprintf(buf_mpo, sizeof(buf_mpo),
+ QCAMERA_DUMP_FRM_LOCATION "Composed.MPO");
+
+ int file_fd_mpo = open(buf_mpo, O_RDWR | O_CREAT, 0777);
+ if (file_fd_mpo >= 0) {
+ ssize_t written_len = write(file_fd_mpo,
+ m_pRelCamMpoJpeg->data,
+ m_pRelCamMpoJpeg->size);
+ fchmod(file_fd_mpo, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ LOGD("written number of bytes for MPO Image %zd\n",
+ written_len);
+ close(file_fd_mpo);
+ }
+ }
+
+ mDataCb(main_Jpeg->msg_type,
+ m_pRelCamMpoJpeg,
+ main_Jpeg->index,
+ main_Jpeg->metadata,
+ m_pMpoCallbackCookie);
+
+ if (NULL != m_pRelCamMpoJpeg) {
+ m_pRelCamMpoJpeg->release(m_pRelCamMpoJpeg);
+ m_pRelCamMpoJpeg = NULL;
+ }
+
+ pthread_mutex_unlock(&m_JpegLock);
+ LOGH("X");
+ return;
+}
+
+/*===========================================================================
+ * FUNCTION : matchFrameId
+ *
+ * DESCRIPTION: function to match frame ids within queue nodes
+ *
+ * PARAMETERS :
+ * @data: pointer to queue node to be matched for condition
+ * @user_data: caller can add more info here
+ * @match_data : value to be matched against
+ *
+ * RETURN : true or false based on whether match was successful or not
+ *==========================================================================*/
+bool QCameraMuxer::matchFrameId(void *data, __unused void *user_data,
+ void *match_data)
+{
+ LOGH("E");
+
+ if (!data || !match_data) {
+ return false;
+ }
+
+ cam_compose_jpeg_info_t * node = (cam_compose_jpeg_info_t *) data;
+ uint32_t frame_idx = *((uint32_t *) match_data);
+ LOGH("X");
+ return node->frame_idx == frame_idx;
+}
+
+/*===========================================================================
+ * FUNCTION : findPreviousJpegs
+ *
+ * DESCRIPTION: Finds Jpegs in the queue with index less than delivered one
+ *
+ * PARAMETERS :
+ * @data: pointer to queue node to be matched for condition
+ * @user_data: caller can add more info here
+ * @match_data : value to be matched against
+ *
+ * RETURN : true or false based on whether match was successful or not
+ *==========================================================================*/
+bool QCameraMuxer::findPreviousJpegs(void *data, __unused void *user_data,
+ void *match_data)
+{
+ LOGH("E");
+
+ if (!data || !match_data) {
+ return false;
+ }
+ cam_compose_jpeg_info_t * node = (cam_compose_jpeg_info_t *) data;
+ uint32_t frame_idx = *((uint32_t *) match_data);
+ LOGH("X");
+ return node->frame_idx < frame_idx;
+}
+
+/*===========================================================================
+ * FUNCTION : releaseJpegInfo
+ *
+ * DESCRIPTION: callback function for the release of individual nodes
+ * in the JPEG queues.
+ *
+ * PARAMETERS :
+ * @data : ptr to the data to be released
+ * @user_data : caller can add more info here
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraMuxer::releaseJpegInfo(void *data, __unused void *user_data)
+{
+ LOGH("E");
+
+ cam_compose_jpeg_info_t *jpegInfo = (cam_compose_jpeg_info_t *)data;
+ if(jpegInfo && jpegInfo->release_cb) {
+ if (jpegInfo->release_data != NULL) {
+ jpegInfo->release_cb(jpegInfo->release_data,
+ jpegInfo->release_cookie,
+ NO_ERROR);
+ }
+ }
+ LOGH("X");
+}
+
+/*===========================================================================
+ * FUNCTION : composeMpoRoutine
+ *
+ * DESCRIPTION: specialized thread for MPO composition
+ *
+ * PARAMETERS :
+ * @data : pointer to the thread owner
+ *
+ * RETURN : void* to thread
+ *==========================================================================*/
+void* QCameraMuxer::composeMpoRoutine(__unused void *data)
+{
+ LOGH("E");
+ if (!gMuxer) {
+ LOGE("Error getting muxer ");
+ return NULL;
+ }
+
+ int running = 1;
+ int ret;
+ uint8_t is_active = FALSE;
+ QCameraCmdThread *cmdThread = &gMuxer->m_ComposeMpoTh;
+ cmdThread->setName("CAM_ComposeMpo");
+
+ do {
+ do {
+ ret = cam_sem_wait(&cmdThread->cmd_sem);
+ if (ret != 0 && errno != EINVAL) {
+ LOGE("cam_sem_wait error (%s)", strerror(errno));
+ return NULL;
+ }
+ } while (ret != 0);
+
+ // we got notified about new cmd avail in cmd queue
+ camera_cmd_type_t cmd = cmdThread->getCmd();
+ switch (cmd) {
+ case CAMERA_CMD_TYPE_START_DATA_PROC:
+ {
+ LOGH("start ComposeMpo processing");
+ is_active = TRUE;
+
+ // signal cmd is completed
+ cam_sem_post(&cmdThread->sync_sem);
+ }
+ break;
+ case CAMERA_CMD_TYPE_STOP_DATA_PROC:
+ {
+ LOGH("stop ComposeMpo processing");
+ is_active = FALSE;
+
+ // signal cmd is completed
+ cam_sem_post(&cmdThread->sync_sem);
+ }
+ break;
+ case CAMERA_CMD_TYPE_DO_NEXT_JOB:
+ {
+ if (is_active == TRUE) {
+ LOGH("Mpo Composition Requested");
+ cam_compose_jpeg_info_t *main_jpeg_node = NULL;
+ cam_compose_jpeg_info_t *aux_jpeg_node = NULL;
+ bool foundMatch = false;
+ while (!gMuxer->m_MainJpegQ.isEmpty() &&
+ !gMuxer->m_AuxJpegQ.isEmpty()) {
+ main_jpeg_node = (cam_compose_jpeg_info_t *)
+ gMuxer->m_MainJpegQ.dequeue();
+ if (main_jpeg_node != NULL) {
+ LOGD("main_jpeg_node found frame idx %d"
+ "ptr %p buffer_ptr %p buffer_size %d",
+ main_jpeg_node->frame_idx,
+ main_jpeg_node,
+ main_jpeg_node->buffer->data,
+ main_jpeg_node->buffer->size);
+ // find matching aux node in Aux Jpeg Queue
+ aux_jpeg_node =
+ (cam_compose_jpeg_info_t *) gMuxer->
+ m_AuxJpegQ.dequeue();
+ if (aux_jpeg_node != NULL) {
+ LOGD("aux_jpeg_node found frame idx %d"
+ "ptr %p buffer_ptr %p buffer_size %d",
+ aux_jpeg_node->frame_idx,
+ aux_jpeg_node,
+ aux_jpeg_node->buffer->data,
+ aux_jpeg_node->buffer->size);
+ foundMatch = true;
+ // start MPO composition
+ gMuxer->composeMpo(main_jpeg_node,
+ aux_jpeg_node);
+ }
+ }
+ if (main_jpeg_node != NULL) {
+ if ( main_jpeg_node->release_cb ) {
+ main_jpeg_node->release_cb(
+ main_jpeg_node->release_data,
+ main_jpeg_node->release_cookie,
+ NO_ERROR);
+ }
+ free(main_jpeg_node);
+ main_jpeg_node = NULL;
+ } else {
+ LOGH("Mpo Match not found");
+ }
+ if (aux_jpeg_node != NULL) {
+ if (aux_jpeg_node->release_cb) {
+ aux_jpeg_node->release_cb(
+ aux_jpeg_node->release_data,
+ aux_jpeg_node->release_cookie,
+ NO_ERROR);
+ }
+ free(aux_jpeg_node);
+ aux_jpeg_node = NULL;
+ } else {
+ LOGH("Mpo Match not found");
+ }
+ }
+ }
+ break;
+ }
+ case CAMERA_CMD_TYPE_EXIT:
+ LOGH("ComposeMpo thread exit");
+ running = 0;
+ break;
+ default:
+ break;
+ }
+ } while (running);
+ LOGH("X");
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : jpeg_data_callback
+ *
+ * DESCRIPTION: JPEG data callback for snapshot
+ *
+ * PARAMETERS :
+ * @msg_type : callback msg type
+ * @data : data ptr of the buffer
+ * @index : index of the frame
+ * @metadata : metadata associated with the buffer
+ * @user : callback cookie returned back to the user
+ * @frame_idx : frame index for matching frames
+ * @release_cb : callback function for releasing the data memory
+ * @release_cookie : cookie for the release callback function
+ * @release_data :pointer indicating what needs to be released
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraMuxer::jpeg_data_callback(int32_t msg_type,
+ const camera_memory_t *data, unsigned int index,
+ camera_frame_metadata_t *metadata, void *user,
+ uint32_t frame_idx, camera_release_callback release_cb,
+ void *release_cookie, void *release_data)
+{
+ LOGH("E");
+ CHECK_MUXER();
+
+ if(data != NULL) {
+ LOGH("jpeg received: data %p size %d data ptr %p frameIdx %d",
+ data, data->size, data->data, frame_idx);
+ int rc = gMuxer->storeJpeg(((qcamera_physical_descriptor_t*)(user))->type,
+ msg_type, data, index, metadata, user, frame_idx, release_cb,
+ release_cookie, release_data);
+ if(rc != NO_ERROR) {
+ gMuxer->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+ }
+ } else {
+ gMuxer->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+ }
+ LOGH("X");
+ return;
+}
+
+/*===========================================================================
+ * FUNCTION : storeJpeg
+ *
+ * DESCRIPTION: Stores jpegs from multiple related cam instances into a common Queue
+ *
+ * PARAMETERS :
+ * @cam_type : indicates whether main or aux camera sent the Jpeg callback
+ * @msg_type : callback msg type
+ * @data : data ptr of the buffer
+ * @index : index of the frame
+ * @metadata : metadata associated with the buffer
+ * @user : callback cookie returned back to the user
+ * @frame_idx : frame index for matching frames
+ * @release_cb : callback function for releasing the data memory
+ * @release_cookie : cookie for the release callback function
+ * @release_data :pointer indicating what needs to be released
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraMuxer::storeJpeg(cam_sync_type_t cam_type,
+ int32_t msg_type, const camera_memory_t *data, unsigned int index,
+ camera_frame_metadata_t *metadata, void *user,uint32_t frame_idx,
+ camera_release_callback release_cb, void *release_cookie,
+ void *release_data)
+{
+ LOGH("E jpeg received: data %p size %d data ptr %p frameIdx %d",
+ data, data->size, data->data, frame_idx);
+
+ CHECK_MUXER_ERROR();
+
+ if (!m_bMpoEnabled) {
+ if (cam_type == CAM_TYPE_MAIN) {
+ // send data callback only incase of main camera
+ // aux image is ignored and released back
+ mDataCb(msg_type,
+ data,
+ index,
+ metadata,
+ m_pMpoCallbackCookie);
+ }
+ if (release_cb) {
+ release_cb(release_data, release_cookie, NO_ERROR);
+ }
+ LOGH("X");
+ return NO_ERROR;
+ }
+
+ cam_compose_jpeg_info_t* pJpegFrame =
+ (cam_compose_jpeg_info_t*)malloc(sizeof(cam_compose_jpeg_info_t));
+ if (!pJpegFrame) {
+ LOGE("Allocation failed for MPO nodes");
+ return NO_MEMORY;
+ }
+ memset(pJpegFrame, 0, sizeof(*pJpegFrame));
+
+ pJpegFrame->msg_type = msg_type;
+ pJpegFrame->buffer = const_cast<camera_memory_t*>(data);
+ pJpegFrame->index = index;
+ pJpegFrame->metadata = metadata;
+ pJpegFrame->user = user;
+ pJpegFrame->valid = true;
+ pJpegFrame->frame_idx = frame_idx;
+ pJpegFrame->release_cb = release_cb;
+ pJpegFrame->release_cookie = release_cookie;
+ pJpegFrame->release_data = release_data;
+ if(cam_type == CAM_TYPE_MAIN) {
+ if (m_MainJpegQ.enqueue((void *)pJpegFrame)) {
+ LOGD("Main FrameIdx %d", pJpegFrame->frame_idx);
+ if (m_MainJpegQ.getCurrentSize() > 0) {
+ LOGD("Trigger Compose");
+ m_ComposeMpoTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
+ }
+ } else {
+ LOGE("Enqueue Failed for Main Jpeg Q");
+ if ( pJpegFrame->release_cb ) {
+ // release other buffer also here
+ pJpegFrame->release_cb(
+ pJpegFrame->release_data,
+ pJpegFrame->release_cookie,
+ NO_ERROR);
+ }
+ free(pJpegFrame);
+ pJpegFrame = NULL;
+ return NO_MEMORY;
+ }
+
+ } else {
+ if (m_AuxJpegQ.enqueue((void *)pJpegFrame)) {
+ LOGD("Aux FrameIdx %d", pJpegFrame->frame_idx);
+ if (m_AuxJpegQ.getCurrentSize() > 0) {
+ LOGD("Trigger Compose");
+ m_ComposeMpoTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
+ }
+ } else {
+ LOGE("Enqueue Failed for Aux Jpeg Q");
+ if ( pJpegFrame->release_cb ) {
+ // release other buffer also here
+ pJpegFrame->release_cb(
+ pJpegFrame->release_data,
+ pJpegFrame->release_cookie,
+ NO_ERROR);
+ }
+ free(pJpegFrame);
+ pJpegFrame = NULL;
+ return NO_MEMORY;
+ }
+ }
+ LOGH("X");
+
+ return NO_ERROR;
+}
+
+
+// Muxer Ops
+camera_device_ops_t QCameraMuxer::mCameraMuxerOps = {
+ .set_preview_window = QCameraMuxer::set_preview_window,
+ .set_callbacks = QCameraMuxer::set_callBacks,
+ .enable_msg_type = QCameraMuxer::enable_msg_type,
+ .disable_msg_type = QCameraMuxer::disable_msg_type,
+ .msg_type_enabled = QCameraMuxer::msg_type_enabled,
+
+ .start_preview = QCameraMuxer::start_preview,
+ .stop_preview = QCameraMuxer::stop_preview,
+ .preview_enabled = QCameraMuxer::preview_enabled,
+ .store_meta_data_in_buffers= QCameraMuxer::store_meta_data_in_buffers,
+
+ .start_recording = QCameraMuxer::start_recording,
+ .stop_recording = QCameraMuxer::stop_recording,
+ .recording_enabled = QCameraMuxer::recording_enabled,
+ .release_recording_frame = QCameraMuxer::release_recording_frame,
+
+ .auto_focus = QCameraMuxer::auto_focus,
+ .cancel_auto_focus = QCameraMuxer::cancel_auto_focus,
+
+ .take_picture = QCameraMuxer::take_picture,
+ .cancel_picture = QCameraMuxer::cancel_picture,
+
+ .set_parameters = QCameraMuxer::set_parameters,
+ .get_parameters = QCameraMuxer::get_parameters,
+ .put_parameters = QCameraMuxer::put_parameters,
+ .send_command = QCameraMuxer::send_command,
+
+ .release = QCameraMuxer::release,
+ .dump = QCameraMuxer::dump,
+};
+
+
+}; // namespace android