361 lines
10 KiB
C++
361 lines
10 KiB
C++
/*
|
|
* Copyright (C) Texas Instruments - http://www.ti.com/
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* @file OMXDccDataSave.cpp
|
|
*
|
|
* This file contains functionality for handling DCC data save
|
|
*
|
|
*/
|
|
|
|
#include "CameraHal.h"
|
|
#include "OMXCameraAdapter.h"
|
|
|
|
|
|
namespace Ti {
|
|
namespace Camera {
|
|
|
|
status_t OMXCameraAdapter::initDccFileDataSave(OMX_HANDLETYPE* omxHandle, int portIndex)
|
|
{
|
|
OMX_CONFIG_EXTRADATATYPE extraDataControl;
|
|
status_t ret = NO_ERROR;
|
|
OMX_ERRORTYPE eError = OMX_ErrorNone;
|
|
|
|
LOG_FUNCTION_NAME;
|
|
|
|
OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE);
|
|
extraDataControl.nPortIndex = portIndex;
|
|
extraDataControl.eExtraDataType = OMX_TI_DccData;
|
|
extraDataControl.bEnable = OMX_TRUE;
|
|
|
|
eError = OMX_SetConfig(*omxHandle,
|
|
( OMX_INDEXTYPE ) OMX_IndexConfigOtherExtraDataControl,
|
|
&extraDataControl);
|
|
|
|
if ( OMX_ErrorNone != eError )
|
|
{
|
|
CAMHAL_LOGEB("Error while configuring dcc data overwrite extra data 0x%x",
|
|
eError);
|
|
|
|
ret = NO_INIT;
|
|
}
|
|
|
|
if (mDccData.pData) {
|
|
free(mDccData.pData);
|
|
mDccData.pData = NULL;
|
|
}
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
|
|
return ret;
|
|
}
|
|
|
|
status_t OMXCameraAdapter::sniffDccFileDataSave(OMX_BUFFERHEADERTYPE* pBuffHeader)
|
|
{
|
|
OMX_OTHER_EXTRADATATYPE *extraData;
|
|
OMX_TI_DCCDATATYPE* dccData;
|
|
status_t ret = NO_ERROR;
|
|
|
|
LOG_FUNCTION_NAME;
|
|
|
|
android::AutoMutex lock(mDccDataLock);
|
|
|
|
if ( NULL == pBuffHeader ) {
|
|
CAMHAL_LOGEA("Invalid Buffer header");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return -EINVAL;
|
|
}
|
|
|
|
extraData = getExtradata(pBuffHeader->pPlatformPrivate,
|
|
(OMX_EXTRADATATYPE)OMX_TI_DccData);
|
|
|
|
if ( NULL != extraData ) {
|
|
CAMHAL_LOGVB("Size = %d, sizeof = %d, eType = 0x%x, nDataSize= %d, nPortIndex = 0x%x, nVersion = 0x%x",
|
|
extraData->nSize,
|
|
sizeof(OMX_OTHER_EXTRADATATYPE),
|
|
extraData->eType,
|
|
extraData->nDataSize,
|
|
extraData->nPortIndex,
|
|
extraData->nVersion);
|
|
} else {
|
|
CAMHAL_LOGVA("Invalid OMX_TI_DCCDATATYPE");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
dccData = ( OMX_TI_DCCDATATYPE * ) extraData->data;
|
|
|
|
if (NULL == dccData) {
|
|
CAMHAL_LOGVA("OMX_TI_DCCDATATYPE is not found in extra data");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if (mDccData.pData) {
|
|
free(mDccData.pData);
|
|
}
|
|
|
|
memcpy(&mDccData, dccData, sizeof(mDccData));
|
|
|
|
int dccDataSize = (int)dccData->nSize - (int)(&(((OMX_TI_DCCDATATYPE*)0)->pData));
|
|
|
|
mDccData.pData = (OMX_PTR)malloc(dccDataSize);
|
|
|
|
if (NULL == mDccData.pData) {
|
|
CAMHAL_LOGVA("not enough memory for DCC data");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
memcpy(mDccData.pData, &(dccData->pData), dccDataSize);
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Recursively searches given directory contents for the correct DCC file.
|
|
// The directory must be opened and its stream pointer + path passed
|
|
// as arguments. As this function is called recursively, to avoid excessive
|
|
// stack usage the path param is reused -> this MUST be char array with
|
|
// enough length!!! (260 should suffice). Path must end with "/".
|
|
// The directory must also be closed in the caller function.
|
|
// If the correct camera DCC file is found (based on the OMX measurement data)
|
|
// its file stream pointer is returned. NULL is returned otherwise
|
|
FILE * OMXCameraAdapter::parseDCCsubDir(DIR *pDir, char *path)
|
|
{
|
|
FILE *pFile;
|
|
DIR *pSubDir;
|
|
struct dirent *dirEntry;
|
|
int initialPathLength = strlen(path);
|
|
|
|
LOG_FUNCTION_NAME;
|
|
|
|
/* check each directory entry */
|
|
while ((dirEntry = readdir(pDir)) != NULL)
|
|
{
|
|
if (dirEntry->d_name[0] == '.')
|
|
continue;
|
|
|
|
strcat(path, dirEntry->d_name);
|
|
// dirEntry might be sub directory -> check it
|
|
pSubDir = opendir(path);
|
|
if (pSubDir) {
|
|
// dirEntry is sub directory -> parse it
|
|
strcat(path, "/");
|
|
pFile = parseDCCsubDir(pSubDir, path);
|
|
closedir(pSubDir);
|
|
if (pFile) {
|
|
// the correct DCC file found!
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return pFile;
|
|
}
|
|
} else {
|
|
// dirEntry is file -> open it
|
|
pFile = fopen(path, "rb");
|
|
if (pFile) {
|
|
// now check if this is the correct DCC file for that camera
|
|
OMX_U32 dccFileIDword;
|
|
OMX_U32 *dccFileDesc = (OMX_U32 *) &mDccData.nCameraModuleId;
|
|
int i;
|
|
|
|
// DCC file ID is 3 4-byte words
|
|
for (i = 0; i < 3; i++) {
|
|
if (fread(&dccFileIDword, sizeof(OMX_U32), 1, pFile) != 1) {
|
|
// file too short
|
|
break;
|
|
}
|
|
if (dccFileIDword != dccFileDesc[i]) {
|
|
// DCC file ID word i does not match
|
|
break;
|
|
}
|
|
}
|
|
|
|
fclose(pFile);
|
|
if (i == 3) {
|
|
// the correct DCC file found!
|
|
CAMHAL_LOGDB("DCC file to be updated: %s", path);
|
|
// reopen it for modification
|
|
pFile = fopen(path, "rb+");
|
|
if (!pFile)
|
|
CAMHAL_LOGEB("ERROR: DCC file %s failed to open for modification", path);
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return pFile;
|
|
}
|
|
} else {
|
|
CAMHAL_LOGEB("ERROR: Failed to open file %s for reading", path);
|
|
}
|
|
}
|
|
// restore original path
|
|
path[initialPathLength] = '\0';
|
|
}
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
|
|
// DCC file not found in this directory tree
|
|
return NULL;
|
|
}
|
|
|
|
// Finds the DCC file corresponding to the current camera based on the
|
|
// OMX measurement data, opens it and returns the file stream pointer
|
|
// (NULL on error or if file not found).
|
|
// The folder string dccFolderPath must end with "/"
|
|
FILE * OMXCameraAdapter::fopenCameraDCC(const char *dccFolderPath)
|
|
{
|
|
FILE *pFile;
|
|
DIR *pDir;
|
|
char dccPath[260];
|
|
|
|
LOG_FUNCTION_NAME;
|
|
|
|
strcpy(dccPath, dccFolderPath);
|
|
|
|
pDir = opendir(dccPath);
|
|
if (!pDir) {
|
|
CAMHAL_LOGEB("ERROR: Opening DCC directory %s failed", dccPath);
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return NULL;
|
|
}
|
|
|
|
pFile = parseDCCsubDir(pDir, dccPath);
|
|
closedir(pDir);
|
|
if (pFile) {
|
|
CAMHAL_LOGDB("DCC file %s opened for modification", dccPath);
|
|
}
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
|
|
return pFile;
|
|
}
|
|
|
|
// Positions the DCC file stream pointer to the correct offset within the
|
|
// correct usecase based on the OMX mesurement data. Returns 0 on success
|
|
status_t OMXCameraAdapter::fseekDCCuseCasePos(FILE *pFile)
|
|
{
|
|
OMX_U32 dccNumUseCases = 0;
|
|
OMX_U32 dccUseCaseData[3];
|
|
OMX_U32 i;
|
|
|
|
LOG_FUNCTION_NAME;
|
|
|
|
// position the file pointer to the DCC use cases section
|
|
if (fseek(pFile, 80, SEEK_SET)) {
|
|
CAMHAL_LOGEA("ERROR: Unexpected end of DCC file");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (fread(&dccNumUseCases, sizeof(OMX_U32), 1, pFile) != 1 ||
|
|
dccNumUseCases == 0) {
|
|
CAMHAL_LOGEA("ERROR: DCC file contains 0 use cases");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < dccNumUseCases; i++) {
|
|
if (fread(dccUseCaseData, sizeof(OMX_U32), 3, pFile) != 3) {
|
|
CAMHAL_LOGEA("ERROR: Unexpected end of DCC file");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (dccUseCaseData[0] == mDccData.nUseCaseId) {
|
|
// DCC use case match!
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == dccNumUseCases) {
|
|
CAMHAL_LOGEB("ERROR: Use case ID %lu not found in DCC file", mDccData.nUseCaseId);
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return -EINVAL;
|
|
}
|
|
|
|
// dccUseCaseData[1] is the offset to the beginning of the actual use case
|
|
// from the beginning of the file
|
|
// mDccData.nOffset is the offset within the actual use case (from the
|
|
// beginning of the use case to the data to be modified)
|
|
|
|
if (fseek(pFile,dccUseCaseData[1] + mDccData.nOffset, SEEK_SET ))
|
|
{
|
|
CAMHAL_LOGEA("ERROR: Error setting the correct offset");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return -EINVAL;
|
|
}
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t OMXCameraAdapter::saveDccFileDataSave()
|
|
{
|
|
status_t ret = NO_ERROR;
|
|
|
|
LOG_FUNCTION_NAME;
|
|
|
|
android::AutoMutex lock(mDccDataLock);
|
|
|
|
if (mDccData.pData)
|
|
{
|
|
FILE *fd = fopenCameraDCC(DCC_PATH);
|
|
|
|
if (fd)
|
|
{
|
|
if (!fseekDCCuseCasePos(fd))
|
|
{
|
|
int dccDataSize = (int)mDccData.nSize - (int)(&(((OMX_TI_DCCDATATYPE*)0)->pData));
|
|
|
|
if (fwrite(mDccData.pData, dccDataSize, 1, fd) != 1)
|
|
{
|
|
CAMHAL_LOGEA("ERROR: Writing to DCC file failed");
|
|
}
|
|
else
|
|
{
|
|
CAMHAL_LOGDA("DCC file successfully updated");
|
|
}
|
|
}
|
|
fclose(fd);
|
|
}
|
|
else
|
|
{
|
|
CAMHAL_LOGEA("ERROR: Correct DCC file not found or failed to open for modification");
|
|
}
|
|
}
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
|
|
return ret;
|
|
}
|
|
|
|
status_t OMXCameraAdapter::closeDccFileDataSave()
|
|
{
|
|
status_t ret = NO_ERROR;
|
|
|
|
LOG_FUNCTION_NAME;
|
|
|
|
android::AutoMutex lock(mDccDataLock);
|
|
|
|
if (mDccData.pData) {
|
|
free(mDccData.pData);
|
|
mDccData.pData = NULL;
|
|
}
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
|
|
return ret;
|
|
}
|
|
|
|
} // namespace Camera
|
|
} // namespace Ti
|