Home | History | Annotate | Download | only in OMXCameraAdapter
      1 /*
      2  * Copyright (C) Texas Instruments - http://www.ti.com/
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18 * @file OMXDccDataSave.cpp
     19 *
     20 * This file contains functionality for handling DCC data save
     21 *
     22 */
     23 
     24 #include "CameraHal.h"
     25 #include "OMXCameraAdapter.h"
     26 
     27 
     28 namespace Ti {
     29 namespace Camera {
     30 
     31 status_t OMXCameraAdapter::initDccFileDataSave(OMX_HANDLETYPE* omxHandle, int portIndex)
     32 {
     33     OMX_CONFIG_EXTRADATATYPE extraDataControl;
     34     status_t ret = NO_ERROR;
     35     OMX_ERRORTYPE eError = OMX_ErrorNone;
     36 
     37     LOG_FUNCTION_NAME;
     38 
     39     OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE);
     40     extraDataControl.nPortIndex = portIndex;
     41     extraDataControl.eExtraDataType = OMX_TI_DccData;
     42     extraDataControl.bEnable = OMX_TRUE;
     43 
     44     eError =  OMX_SetConfig(*omxHandle,
     45                         ( OMX_INDEXTYPE ) OMX_IndexConfigOtherExtraDataControl,
     46                         &extraDataControl);
     47 
     48     if ( OMX_ErrorNone != eError )
     49         {
     50         CAMHAL_LOGEB("Error while configuring dcc data overwrite extra data 0x%x",
     51                     eError);
     52 
     53         ret =  NO_INIT;
     54         }
     55 
     56     if (mDccData.pData) {
     57         free(mDccData.pData);
     58         mDccData.pData = NULL;
     59     }
     60     LOG_FUNCTION_NAME_EXIT;
     61 
     62     return ret;
     63 }
     64 
     65 status_t OMXCameraAdapter::sniffDccFileDataSave(OMX_BUFFERHEADERTYPE* pBuffHeader)
     66 {
     67     OMX_OTHER_EXTRADATATYPE *extraData;
     68     OMX_TI_DCCDATATYPE* dccData;
     69     status_t ret = NO_ERROR;
     70 
     71     LOG_FUNCTION_NAME;
     72 
     73     android::AutoMutex lock(mDccDataLock);
     74 
     75     if ( NULL == pBuffHeader ) {
     76         CAMHAL_LOGEA("Invalid Buffer header");
     77         LOG_FUNCTION_NAME_EXIT;
     78         return -EINVAL;
     79     }
     80 
     81     extraData = getExtradata(pBuffHeader->pPlatformPrivate,
     82                              (OMX_EXTRADATATYPE)OMX_TI_DccData);
     83 
     84     if ( NULL != extraData ) {
     85         CAMHAL_LOGVB("Size = %d, sizeof = %d, eType = 0x%x, nDataSize= %d, nPortIndex = 0x%x, nVersion = 0x%x",
     86                      extraData->nSize,
     87                      sizeof(OMX_OTHER_EXTRADATATYPE),
     88                      extraData->eType,
     89                      extraData->nDataSize,
     90                      extraData->nPortIndex,
     91                      extraData->nVersion);
     92     } else {
     93         CAMHAL_LOGVA("Invalid OMX_TI_DCCDATATYPE");
     94         LOG_FUNCTION_NAME_EXIT;
     95         return NO_ERROR;
     96     }
     97 
     98     dccData = ( OMX_TI_DCCDATATYPE * ) extraData->data;
     99 
    100     if (NULL == dccData) {
    101         CAMHAL_LOGVA("OMX_TI_DCCDATATYPE is not found in extra data");
    102         LOG_FUNCTION_NAME_EXIT;
    103         return NO_ERROR;
    104     }
    105 
    106     if (mDccData.pData) {
    107         free(mDccData.pData);
    108     }
    109 
    110     memcpy(&mDccData, dccData, sizeof(mDccData));
    111 
    112     int dccDataSize = (int)dccData->nSize - (int)(&(((OMX_TI_DCCDATATYPE*)0)->pData));
    113 
    114     mDccData.pData = (OMX_PTR)malloc(dccDataSize);
    115 
    116     if (NULL == mDccData.pData) {
    117         CAMHAL_LOGVA("not enough memory for DCC data");
    118         LOG_FUNCTION_NAME_EXIT;
    119         return NO_ERROR;
    120     }
    121 
    122     memcpy(mDccData.pData, &(dccData->pData), dccDataSize);
    123 
    124     LOG_FUNCTION_NAME_EXIT;
    125 
    126     return ret;
    127 }
    128 
    129 // Recursively searches given directory contents for the correct DCC file.
    130 // The directory must be opened and its stream pointer + path passed
    131 // as arguments. As this function is called recursively, to avoid excessive
    132 // stack usage the path param is reused -> this MUST be char array with
    133 // enough length!!! (260 should suffice). Path must end with "/".
    134 // The directory must also be closed in the caller function.
    135 // If the correct camera DCC file is found (based on the OMX measurement data)
    136 // its file stream pointer is returned. NULL is returned otherwise
    137 FILE * OMXCameraAdapter::parseDCCsubDir(DIR *pDir, char *path)
    138 {
    139     FILE *pFile;
    140     DIR *pSubDir;
    141     struct dirent *dirEntry;
    142     int initialPathLength = strlen(path);
    143 
    144     LOG_FUNCTION_NAME;
    145 
    146     /* check each directory entry */
    147     while ((dirEntry = readdir(pDir)) != NULL)
    148     {
    149         if (dirEntry->d_name[0] == '.')
    150             continue;
    151 
    152         strcat(path, dirEntry->d_name);
    153         // dirEntry might be sub directory -> check it
    154         pSubDir = opendir(path);
    155         if (pSubDir) {
    156             // dirEntry is sub directory -> parse it
    157             strcat(path, "/");
    158             pFile = parseDCCsubDir(pSubDir, path);
    159             closedir(pSubDir);
    160             if (pFile) {
    161                 // the correct DCC file found!
    162                 LOG_FUNCTION_NAME_EXIT;
    163                 return pFile;
    164             }
    165         } else {
    166             // dirEntry is file -> open it
    167             pFile = fopen(path, "rb");
    168             if (pFile) {
    169                 // now check if this is the correct DCC file for that camera
    170                 OMX_U32 dccFileIDword;
    171                 OMX_U32 *dccFileDesc = (OMX_U32 *) &mDccData.nCameraModuleId;
    172                 int i;
    173 
    174                 // DCC file ID is 3 4-byte words
    175                 for (i = 0; i < 3; i++) {
    176                     if (fread(&dccFileIDword, sizeof(OMX_U32), 1, pFile) != 1) {
    177                         // file too short
    178                         break;
    179                     }
    180                     if (dccFileIDword != dccFileDesc[i]) {
    181                         // DCC file ID word i does not match
    182                         break;
    183                     }
    184                 }
    185 
    186                 fclose(pFile);
    187                 if (i == 3) {
    188                     // the correct DCC file found!
    189                     CAMHAL_LOGDB("DCC file to be updated: %s", path);
    190                     // reopen it for modification
    191                     pFile = fopen(path, "rb+");
    192                     if (!pFile)
    193                         CAMHAL_LOGEB("ERROR: DCC file %s failed to open for modification", path);
    194                     LOG_FUNCTION_NAME_EXIT;
    195                     return pFile;
    196                 }
    197             } else {
    198                 CAMHAL_LOGEB("ERROR: Failed to open file %s for reading", path);
    199             }
    200         }
    201         // restore original path
    202         path[initialPathLength] = '\0';
    203     }
    204 
    205     LOG_FUNCTION_NAME_EXIT;
    206 
    207     // DCC file not found in this directory tree
    208     return NULL;
    209 }
    210 
    211 // Finds the DCC file corresponding to the current camera based on the
    212 // OMX measurement data, opens it and returns the file stream pointer
    213 // (NULL on error or if file not found).
    214 // The folder string dccFolderPath must end with "/"
    215 FILE * OMXCameraAdapter::fopenCameraDCC(const char *dccFolderPath)
    216 {
    217     FILE *pFile;
    218     DIR *pDir;
    219     char dccPath[260];
    220 
    221     LOG_FUNCTION_NAME;
    222 
    223     strcpy(dccPath, dccFolderPath);
    224 
    225     pDir = opendir(dccPath);
    226     if (!pDir) {
    227         CAMHAL_LOGEB("ERROR: Opening DCC directory %s failed", dccPath);
    228         LOG_FUNCTION_NAME_EXIT;
    229         return NULL;
    230     }
    231 
    232     pFile = parseDCCsubDir(pDir, dccPath);
    233     closedir(pDir);
    234     if (pFile) {
    235         CAMHAL_LOGDB("DCC file %s opened for modification", dccPath);
    236     }
    237 
    238     LOG_FUNCTION_NAME_EXIT;
    239 
    240     return pFile;
    241 }
    242 
    243 // Positions the DCC file stream pointer to the correct offset within the
    244 // correct usecase based on the OMX mesurement data. Returns 0 on success
    245 status_t OMXCameraAdapter::fseekDCCuseCasePos(FILE *pFile)
    246 {
    247     OMX_U32 dccNumUseCases = 0;
    248     OMX_U32 dccUseCaseData[3];
    249     OMX_U32 i;
    250 
    251     LOG_FUNCTION_NAME;
    252 
    253     // position the file pointer to the DCC use cases section
    254     if (fseek(pFile, 80, SEEK_SET)) {
    255         CAMHAL_LOGEA("ERROR: Unexpected end of DCC file");
    256         LOG_FUNCTION_NAME_EXIT;
    257         return -EINVAL;
    258     }
    259 
    260     if (fread(&dccNumUseCases, sizeof(OMX_U32), 1, pFile) != 1 ||
    261         dccNumUseCases == 0) {
    262         CAMHAL_LOGEA("ERROR: DCC file contains 0 use cases");
    263         LOG_FUNCTION_NAME_EXIT;
    264         return -EINVAL;
    265     }
    266 
    267     for (i = 0; i < dccNumUseCases; i++) {
    268         if (fread(dccUseCaseData, sizeof(OMX_U32), 3, pFile) != 3) {
    269             CAMHAL_LOGEA("ERROR: Unexpected end of DCC file");
    270             LOG_FUNCTION_NAME_EXIT;
    271             return -EINVAL;
    272         }
    273 
    274         if (dccUseCaseData[0] == mDccData.nUseCaseId) {
    275             // DCC use case match!
    276             break;
    277         }
    278     }
    279 
    280     if (i == dccNumUseCases) {
    281         CAMHAL_LOGEB("ERROR: Use case ID %lu not found in DCC file", mDccData.nUseCaseId);
    282         LOG_FUNCTION_NAME_EXIT;
    283         return -EINVAL;
    284     }
    285 
    286     // dccUseCaseData[1] is the offset to the beginning of the actual use case
    287     // from the beginning of the file
    288     // mDccData.nOffset is the offset within the actual use case (from the
    289     // beginning of the use case to the data to be modified)
    290 
    291     if (fseek(pFile,dccUseCaseData[1] + mDccData.nOffset, SEEK_SET ))
    292     {
    293         CAMHAL_LOGEA("ERROR: Error setting the correct offset");
    294         LOG_FUNCTION_NAME_EXIT;
    295         return -EINVAL;
    296     }
    297 
    298     LOG_FUNCTION_NAME_EXIT;
    299 
    300     return NO_ERROR;
    301 }
    302 
    303 status_t OMXCameraAdapter::saveDccFileDataSave()
    304 {
    305     status_t ret = NO_ERROR;
    306 
    307     LOG_FUNCTION_NAME;
    308 
    309     android::AutoMutex lock(mDccDataLock);
    310 
    311     if (mDccData.pData)
    312         {
    313         FILE *fd = fopenCameraDCC(DCC_PATH);
    314 
    315         if (fd)
    316             {
    317             if (!fseekDCCuseCasePos(fd))
    318                 {
    319                 int dccDataSize = (int)mDccData.nSize - (int)(&(((OMX_TI_DCCDATATYPE*)0)->pData));
    320 
    321                 if (fwrite(mDccData.pData, dccDataSize, 1, fd) != 1)
    322                     {
    323                     CAMHAL_LOGEA("ERROR: Writing to DCC file failed");
    324                     }
    325                 else
    326                     {
    327                     CAMHAL_LOGDA("DCC file successfully updated");
    328                     }
    329                 }
    330             fclose(fd);
    331             }
    332         else
    333             {
    334             CAMHAL_LOGEA("ERROR: Correct DCC file not found or failed to open for modification");
    335             }
    336         }
    337 
    338     LOG_FUNCTION_NAME_EXIT;
    339 
    340     return ret;
    341 }
    342 
    343 status_t OMXCameraAdapter::closeDccFileDataSave()
    344 {
    345     status_t ret = NO_ERROR;
    346 
    347     LOG_FUNCTION_NAME;
    348 
    349     android::AutoMutex lock(mDccDataLock);
    350 
    351     if (mDccData.pData) {
    352         free(mDccData.pData);
    353         mDccData.pData = NULL;
    354     }
    355     LOG_FUNCTION_NAME_EXIT;
    356 
    357     return ret;
    358 }
    359 
    360 } // namespace Camera
    361 } // namespace Ti
    362