/* * Copyright (c) 2010, Texas Instruments Incorporated * 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 Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file omx_proxy_camera.c * This file contains methods that provides the functionality for * the OpenMAX1.1 DOMX Framework Tunnel Proxy component. ****************************************************************************** This is the proxy specific wrapper that passes the component name to the generic proxy init() The proxy wrapper also does some runtime/static time config on per proxy basis This is a thin wrapper that is called when componentiit() of the proxy is called static OMX_ERRORTYPE PROXY_Wrapper_init (OMX_HANDLETYPE hComponent, OMX_PTR pAppData); this layer gets called first whenever a proxy s get handle is called ****************************************************************************** * @path WTSD_DucatiMMSW\omx\omx_il_1_x\omx_proxy_component\src * * @rev 1.0 */ /*============================================================== *! Revision History *! ============================ *! 19-August-2009 B Ravi Kiran ravi.kiran@ti.com: Initial Version *================================================================*/ /****************************************************************** * INCLUDE FILES ******************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "omx_proxy_common.h" #include "timm_osal_mutex.h" #ifdef USE_ION #include #include #include #include #include #include #else /* Tiler APIs */ #include #endif #define COMPONENT_NAME "OMX.TI.DUCATI1.VIDEO.CAMERA" /*Needs to be specific for every configuration wrapper*/ #undef LOG_TAG #define LOG_TAG "CameraHAL" #define DEFAULT_DCC 1 #ifdef _Android #define DCC_PATH "/data/misc/camera/" #else #define DCC_PATH "/usr/share/omapcam/" #endif #define LINUX_PAGE_SIZE (4 * 1024) #define _PROXY_OMX_INIT_PARAM(param,type) do { \ TIMM_OSAL_Memset((param), 0, sizeof (type)); \ (param)->nSize = sizeof (type); \ (param)->nVersion.s.nVersionMajor = 1; \ (param)->nVersion.s.nVersionMinor = 1; \ } while(0) /* Incase of multiple instance, making sure DCC is initialized only for first instance */ static OMX_S16 numofInstance = 0; int dcc_flag = 0; TIMM_OSAL_PTR cam_mutex = NULL; /* To store DCC buffer size */ OMX_S32 dccbuf_size = 0; /* Ducati Mapped Addr */ OMX_PTR DCC_Buff = NULL; #ifdef USE_ION OMX_PTR DCC_Buff_ptr = NULL; int ion_fd; int mmap_fd; #else MemAllocBlock *MemReqDescTiler; #endif OMX_S32 read_DCCdir(OMX_PTR, OMX_STRING *, OMX_U16); OMX_ERRORTYPE DCC_Init(OMX_HANDLETYPE); OMX_ERRORTYPE send_DCCBufPtr(OMX_HANDLETYPE hComponent); void DCC_DeInit(); OMX_ERRORTYPE PROXY_ComponentDeInit(OMX_HANDLETYPE); OMX_ERRORTYPE __PROXY_SetConfig(OMX_HANDLETYPE, OMX_INDEXTYPE, OMX_PTR, OMX_PTR); OMX_ERRORTYPE __PROXY_GetConfig(OMX_HANDLETYPE, OMX_INDEXTYPE, OMX_PTR, OMX_PTR); OMX_ERRORTYPE __PROXY_SetParameter(OMX_IN OMX_HANDLETYPE, OMX_INDEXTYPE, OMX_PTR, OMX_PTR); OMX_ERRORTYPE __PROXY_GetParameter(OMX_IN OMX_HANDLETYPE, OMX_INDEXTYPE, OMX_PTR, OMX_PTR); OMX_ERRORTYPE CameraMaptoTilerDuc(OMX_TI_CONFIG_SHAREDBUFFER *, OMX_PTR *); //COREID TARGET_CORE_ID = CORE_APPM3; static OMX_ERRORTYPE ComponentPrivateDeInit(OMX_IN OMX_HANDLETYPE hComponent) { OMX_ERRORTYPE eError = OMX_ErrorNone; TIMM_OSAL_ERRORTYPE eOsalError = TIMM_OSAL_ERR_NONE; if (dcc_flag) { eOsalError = TIMM_OSAL_MutexObtain(cam_mutex, TIMM_OSAL_SUSPEND); if (eOsalError != TIMM_OSAL_ERR_NONE) { TIMM_OSAL_Error("Mutex Obtain failed"); } numofInstance = numofInstance - 1; eOsalError = TIMM_OSAL_MutexRelease(cam_mutex); PROXY_assert(eOsalError == TIMM_OSAL_ERR_NONE, OMX_ErrorInsufficientResources, "Mutex release failed"); } eError = PROXY_ComponentDeInit(hComponent); EXIT: return eError; } /* ===========================================================================*/ /** * @name CameraGetConfig() * @brief For some specific indices, buffer allocated on A9 side * needs to be mapped and sent to Ducati. * @param * @return OMX_ErrorNone = Successful */ /* ===========================================================================*/ static OMX_ERRORTYPE CameraGetConfig(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, OMX_INOUT OMX_PTR pComponentParameterStructure) { OMX_ERRORTYPE eError = OMX_ErrorNone; OMX_TI_CONFIG_SHAREDBUFFER *pConfigSharedBuffer = NULL; OMX_PTR pTempSharedBuff = NULL; OMX_U32 status = 0; switch (nParamIndex) { case OMX_TI_IndexConfigAAAskipBuffer: case OMX_TI_IndexConfigCamCapabilities: case OMX_TI_IndexConfigExifTags: case OMX_TI_IndexConfigAlgoAreas: pConfigSharedBuffer = (OMX_TI_CONFIG_SHAREDBUFFER *) pComponentParameterStructure; pTempSharedBuff = pConfigSharedBuffer->pSharedBuff; // TODO(XXX): Cache API is not yet available. Client needs to // allocate tiler buffer directly and assign to pSharedBuff. // Ptr allocated by MemMgr_Alloc in uncacheable so there // would be no need to cache API eError = __PROXY_GetConfig(hComponent, nParamIndex, pConfigSharedBuffer, &(pConfigSharedBuffer->pSharedBuff)); PROXY_assert((eError == OMX_ErrorNone), eError, "Error in GetConfig"); pConfigSharedBuffer->pSharedBuff = pTempSharedBuff; goto EXIT; break; default: break; } return __PROXY_GetConfig(hComponent, nParamIndex, pComponentParameterStructure, NULL); EXIT: return eError; } /* ===========================================================================*/ /** * @name CameraSetConfig() * @brief For some specific indices, buffer allocated on A9 side needs to * be mapped and sent to Ducati. * @param * @return OMX_ErrorNone = Successful */ /* ===========================================================================*/ static OMX_ERRORTYPE CameraSetConfig(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, OMX_INOUT OMX_PTR pComponentParameterStructure) { OMX_ERRORTYPE eError = OMX_ErrorNone; OMX_TI_CONFIG_SHAREDBUFFER *pConfigSharedBuffer = NULL; OMX_PTR pTempSharedBuff = NULL; OMX_U32 status = 0; switch (nParamIndex) { case OMX_TI_IndexConfigAAAskipBuffer: case OMX_TI_IndexConfigCamCapabilities: case OMX_TI_IndexConfigExifTags: case OMX_TI_IndexConfigAlgoAreas: pConfigSharedBuffer = (OMX_TI_CONFIG_SHAREDBUFFER *) pComponentParameterStructure; pTempSharedBuff = pConfigSharedBuffer->pSharedBuff; // TODO(XXX): Cache API is not yet available. Client needs to // allocate tiler buffer directly and assign to pSharedBuff. // Ptr allocated by MemMgr_Alloc in uncacheable so there // would be no need to cache API eError = __PROXY_SetConfig(hComponent, nParamIndex, pConfigSharedBuffer, &(pConfigSharedBuffer->pSharedBuff)); PROXY_assert((eError == OMX_ErrorNone), eError, "Error in GetConfig"); pConfigSharedBuffer->pSharedBuff = pTempSharedBuff; goto EXIT; break; default: break; } return __PROXY_SetConfig(hComponent, nParamIndex, pComponentParameterStructure, NULL); EXIT: return eError; } OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE hComponent) { OMX_ERRORTYPE eError = OMX_ErrorNone; OMX_ERRORTYPE dcc_eError = OMX_ErrorNone; OMX_COMPONENTTYPE *pHandle = NULL; PROXY_COMPONENT_PRIVATE *pComponentPrivate; pHandle = (OMX_COMPONENTTYPE *) hComponent; TIMM_OSAL_ERRORTYPE eOsalError = TIMM_OSAL_ERR_NONE; DOMX_ENTER("_____________________INSIDE CAMERA PROXY" "WRAPPER__________________________\n"); pHandle->pComponentPrivate = (PROXY_COMPONENT_PRIVATE *) TIMM_OSAL_Malloc(sizeof(PROXY_COMPONENT_PRIVATE), TIMM_OSAL_TRUE, 0, TIMMOSAL_MEM_SEGMENT_INT); pComponentPrivate = (PROXY_COMPONENT_PRIVATE *) pHandle->pComponentPrivate; if (pHandle->pComponentPrivate == NULL) { DOMX_ERROR(" ERROR IN ALLOCATING PROXY COMPONENT" "PRIVATE STRUCTURE"); eError = OMX_ErrorInsufficientResources; goto EXIT; } TIMM_OSAL_Memset(pComponentPrivate, 0, sizeof(PROXY_COMPONENT_PRIVATE)); pComponentPrivate->cCompName = TIMM_OSAL_Malloc(MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8), TIMM_OSAL_TRUE, 0, TIMMOSAL_MEM_SEGMENT_INT); /*Copying component Name - this will be picked up in the proxy common */ assert(strlen(COMPONENT_NAME) + 1 < MAX_COMPONENT_NAME_LENGTH); TIMM_OSAL_Memcpy(pComponentPrivate->cCompName, COMPONENT_NAME, strlen(COMPONENT_NAME) + 1); /*Calling Proxy Common Init() */ eError = OMX_ProxyCommonInit(hComponent); if (eError != OMX_ErrorNone) { DOMX_ERROR("\Error in Initializing Proxy"); TIMM_OSAL_Free(pComponentPrivate->cCompName); TIMM_OSAL_Free(pComponentPrivate); goto EXIT; } pHandle->ComponentDeInit = ComponentPrivateDeInit; pHandle->GetConfig = CameraGetConfig; pHandle->SetConfig = CameraSetConfig; char *val = getenv("SET_DCC"); dcc_flag = val ? strtol(val, NULL, 0) : DEFAULT_DCC; DOMX_DEBUG(" DCC: 0 - disabled 1 - enabled : val: %d", dcc_flag); if (dcc_flag) { eOsalError = TIMM_OSAL_MutexObtain(cam_mutex, TIMM_OSAL_SUSPEND); PROXY_assert(eOsalError == TIMM_OSAL_ERR_NONE, OMX_ErrorInsufficientResources, "Mutex lock failed"); if (numofInstance == 0) { dcc_eError = DCC_Init(hComponent); if (dcc_eError != OMX_ErrorNone) { DOMX_DEBUG(" Error in DCC Init"); } /* Configure Ducati to use DCC buffer from A9 side *ONLY* if DCC_Init is successful. */ if (dcc_eError == OMX_ErrorNone) { dcc_eError = send_DCCBufPtr(hComponent); if (dcc_eError != OMX_ErrorNone) { DOMX_DEBUG(" Error in Sending DCC Buf ptr"); } DCC_DeInit(); } } numofInstance = numofInstance + 1; eOsalError = TIMM_OSAL_MutexRelease(cam_mutex); PROXY_assert(eOsalError == TIMM_OSAL_ERR_NONE, OMX_ErrorInsufficientResources, "Mutex release failed"); } EXIT: return eError; } /* ===========================================================================*/ /** * @name DCC_Init() * @brief * @param void * @return OMX_ErrorNone = Successful * @sa TBD * */ /* ===========================================================================*/ OMX_ERRORTYPE DCC_Init(OMX_HANDLETYPE hComponent) { OMX_TI_PARAM_DCCURIINFO param; OMX_PTR ptempbuf; OMX_U16 nIndex = 0; OMX_ERRORTYPE eError = OMX_ErrorNone; #ifdef USE_ION int ret; #endif OMX_S32 status = 0; OMX_STRING dcc_dir[200]; OMX_U16 i; _PROXY_OMX_INIT_PARAM(¶m, OMX_TI_PARAM_DCCURIINFO); DOMX_ENTER("ENTER"); /* Read the the DCC URI info */ for (nIndex = 0; eError != OMX_ErrorNoMore; nIndex++) { param.nIndex = nIndex; eError = OMX_GetParameter(hComponent, OMX_TI_IndexParamDccUriInfo, ¶m); PROXY_assert((eError == OMX_ErrorNone) || (eError == OMX_ErrorNoMore), eError, "Error in GetParam for Dcc URI info"); if (eError == OMX_ErrorNone) { DOMX_DEBUG("DCC URI's %s ", param.sDCCURI); dcc_dir[nIndex] = TIMM_OSAL_Malloc(sizeof(OMX_U8) * (strlen(DCC_PATH) + MAX_URI_LENGTH + 1), TIMM_OSAL_TRUE, 0, TIMMOSAL_MEM_SEGMENT_INT); PROXY_assert(dcc_dir[nIndex] != NULL, OMX_ErrorInsufficientResources, "Malloc failed"); strcpy(dcc_dir[nIndex], DCC_PATH); strncat(dcc_dir[nIndex], (OMX_STRING) param.sDCCURI, MAX_URI_LENGTH); strcat(dcc_dir[nIndex], "/"); } } /* setting back errortype OMX_ErrorNone */ if (eError == OMX_ErrorNoMore) { eError = OMX_ErrorNone; } dccbuf_size = read_DCCdir(NULL, dcc_dir, nIndex); if(dccbuf_size <= 0) { DOMX_DEBUG("No DCC files found, switching back to default DCC"); return OMX_ErrorInsufficientResources; } #ifdef USE_ION ion_fd = ion_open(); if(ion_fd == 0) { DOMX_ERROR("ion_open failed!!!"); return OMX_ErrorInsufficientResources; } dccbuf_size = (dccbuf_size + LINUX_PAGE_SIZE -1) & ~(LINUX_PAGE_SIZE - 1); ret = ion_alloc(ion_fd, dccbuf_size, 0x1000, 1 << ION_HEAP_TYPE_CARVEOUT, &DCC_Buff); if (ret) return OMX_ErrorInsufficientResources; if (ion_map(ion_fd, DCC_Buff, dccbuf_size, PROT_READ | PROT_WRITE, MAP_SHARED, 0, &DCC_Buff_ptr,&mmap_fd) < 0) { DOMX_ERROR("userspace mapping of ION buffers returned error"); return OMX_ErrorInsufficientResources; } ptempbuf = DCC_Buff_ptr; #else MemReqDescTiler = (MemAllocBlock *) TIMM_OSAL_Malloc((sizeof(MemAllocBlock) * 2), TIMM_OSAL_TRUE, 0, TIMMOSAL_MEM_SEGMENT_EXT); PROXY_assert(MemReqDescTiler != NULL, OMX_ErrorInsufficientResources, "Malloc failed"); /* Allocate 1D Tiler buffer for 'N'DCC files */ MemReqDescTiler[0].fmt = PIXEL_FMT_PAGE; MemReqDescTiler[0].dim.len = dccbuf_size; MemReqDescTiler[0].stride = 0; DCC_Buff = MemMgr_Alloc(MemReqDescTiler, 1); PROXY_assert(DCC_Buff != NULL, OMX_ErrorInsufficientResources, "ERROR Allocating 1D TILER BUF"); ptempbuf = DCC_Buff; #endif dccbuf_size = read_DCCdir(ptempbuf, dcc_dir, nIndex); PROXY_assert(dccbuf_size > 0, OMX_ErrorInsufficientResources, "ERROR in copy DCC files into buffer"); EXIT: for (i = 0; i < nIndex - 1; i++) { TIMM_OSAL_Free(dcc_dir[i]); } return eError; } /* ===========================================================================*/ /** * @name send_DCCBufPtr() * @brief : Sending the DCC uri buff addr to ducati * @param void * @return return = 0 is successful * @sa TBD * */ /* ===========================================================================*/ OMX_ERRORTYPE send_DCCBufPtr(OMX_HANDLETYPE hComponent) { OMX_TI_CONFIG_SHAREDBUFFER uribufparam; OMX_ERRORTYPE eError = OMX_ErrorNone; _PROXY_OMX_INIT_PARAM(&uribufparam, OMX_TI_CONFIG_SHAREDBUFFER); uribufparam.nPortIndex = OMX_ALL; DOMX_ENTER("ENTER"); uribufparam.nSharedBuffSize = dccbuf_size; uribufparam.pSharedBuff = (OMX_U8 *) DCC_Buff; DOMX_DEBUG("SYSLINK MAPPED ADDR: 0x%x sizeof buffer %d", uribufparam.pSharedBuff, uribufparam.nSharedBuffSize); eError = __PROXY_SetParameter(hComponent, OMX_TI_IndexParamDccUriBuffer, &uribufparam, &(uribufparam.pSharedBuff)); if (eError != OMX_ErrorNone) { DOMX_ERROR(" Error in SetParam for DCC Uri Buffer 0x%x", eError); } DOMX_EXIT("EXIT"); return eError; } /* ===========================================================================*/ /** * @name read_DCCdir() * @brief : copies all the dcc profiles into the allocated 1D-Tiler buffer * and returns the size of the buffer. * @param void : OMX_PTR is null then returns the size of the DCC directory * @return return = size of the DCC directory or error in case of any failures * in file read or open * @sa TBD * */ /* ===========================================================================*/ OMX_S32 read_DCCdir(OMX_PTR buffer, OMX_STRING * dir_path, OMX_U16 numofURI) { FILE *pFile; OMX_S32 lSize; OMX_S32 dcc_buf_size = 0; size_t result; OMX_STRING filename; char temp[200]; OMX_STRING dotdot = ".."; DIR *d; struct dirent *dir; OMX_U16 i = 0; OMX_S32 ret = 0; DOMX_ENTER("ENTER"); for (i = 0; i < numofURI - 1; i++) { d = opendir(dir_path[i]); if (d) { /* read each filename */ while ((dir = readdir(d)) != NULL) { filename = dir->d_name; strcpy(temp, dir_path[i]); strcat(temp, filename); if ((*filename != *dotdot)) { DOMX_DEBUG ("\n\t DCC Profiles copying into buffer => %s mpu_addr: %p", temp, buffer); pFile = fopen(temp, "rb"); if (pFile == NULL) { DOMX_ERROR("File open error"); ret = -1; } else { fseek(pFile, 0, SEEK_END); lSize = ftell(pFile); rewind(pFile); /* buffer is not NULL then copy all the DCC profiles into buffer else return the size of the DCC directory */ if (buffer) { // copy file into the buffer: result = fread(buffer, 1, lSize, pFile); if (result != (size_t) lSize) { DOMX_ERROR ("fread: Reading error"); ret = -1; } buffer = buffer + lSize; } /* getting the size of the total dcc files available in FS */ dcc_buf_size = dcc_buf_size + lSize; // terminate fclose(pFile); } } } closedir(d); } } if (ret == 0) ret = dcc_buf_size; DOMX_EXIT("return %d", ret); return ret; } /* ===========================================================================*/ /** * @name DCC_Deinit() * @brief * @param void * @return void * @sa TBD * */ /* ===========================================================================*/ void DCC_DeInit() { DOMX_ENTER("ENTER"); if (DCC_Buff) { #ifdef USE_ION munmap(DCC_Buff_ptr, dccbuf_size); close(mmap_fd); ion_free(ion_fd, DCC_Buff); ion_close(ion_fd); DCC_Buff = NULL; #else MemMgr_Free(DCC_Buff); #endif } #ifndef USE_ION if (MemReqDescTiler) TIMM_OSAL_Free(MemReqDescTiler); #endif DOMX_EXIT("EXIT"); } /*===============================================================*/ /** @fn Cam_Setup : This function is called when the the OMX Camera library is * loaded. It creates a mutex, which is used during DCC_Init() */ /*===============================================================*/ void __attribute__ ((constructor)) Cam_Setup(void) { TIMM_OSAL_ERRORTYPE eError = TIMM_OSAL_ERR_NONE; eError = TIMM_OSAL_MutexCreate(&cam_mutex); if (eError != TIMM_OSAL_ERR_NONE) { TIMM_OSAL_Error("Creation of default mutex failed"); } } /*===============================================================*/ /** @fn Cam_Destroy : This function is called when the the OMX Camera library is * unloaded. It destroys the mutex which was created by * Core_Setup(). * */ /*===============================================================*/ void __attribute__ ((destructor)) Cam_Destroy(void) { TIMM_OSAL_ERRORTYPE eError = TIMM_OSAL_ERR_NONE; eError = TIMM_OSAL_MutexDelete(cam_mutex); if (eError != TIMM_OSAL_ERR_NONE) { TIMM_OSAL_Error("Destruction of default mutex failed"); } }