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 OMXDCC.cpp
19 *
20 * This file contains functionality for loading the DCC binaries.
21 *
22 */
23 
24 #include "CameraHal.h"
25 #include "OMXCameraAdapter.h"
26 #include "ErrorUtils.h"
27 #include "OMXDCC.h"
28 #include <utils/String8.h>
29 #include <utils/Vector.h>
30 
31 namespace Ti {
32 namespace Camera {
33 
34 android::String8 DCCHandler::DCCPath("/data/misc/camera/");
35 bool DCCHandler::mDCCLoaded = false;
36 
loadDCC(OMX_HANDLETYPE hComponent)37 status_t DCCHandler::loadDCC(OMX_HANDLETYPE hComponent)
38 {
39     OMX_ERRORTYPE dccError = OMX_ErrorNone;
40 
41     if (!mDCCLoaded) {
42         dccError = initDCC(hComponent);
43         if (dccError != OMX_ErrorNone) {
44             CAMHAL_LOGE(" Error in DCC Init");
45         }
46 
47         mDCCLoaded = true;
48     }
49 
50     return Utils::ErrorUtils::omxToAndroidError(dccError);
51 }
52 
initDCC(OMX_HANDLETYPE hComponent)53 OMX_ERRORTYPE DCCHandler::initDCC(OMX_HANDLETYPE hComponent)
54 {
55     OMX_TI_PARAM_DCCURIINFO param;
56     OMX_PTR ptempbuf;
57     OMX_U16 nIndex = 0;
58     OMX_ERRORTYPE eError = OMX_ErrorNone;
59     int ret;
60     OMX_S32 status = 0;
61     android::Vector<android::String8 *> dccDirs;
62     OMX_U16 i;
63     MemoryManager memMgr;
64     CameraBuffer *dccBuffer = NULL;
65     int dccbuf_size = 0;
66     OMX_INIT_STRUCT_PTR(&param, OMX_TI_PARAM_DCCURIINFO);
67 
68     // Read the the DCC URI info
69     for (nIndex = 0; eError != OMX_ErrorNoMore; nIndex++) {
70         param.nIndex = nIndex;
71         eError = OMX_GetParameter(hComponent,
72                                   ( OMX_INDEXTYPE )OMX_TI_IndexParamDccUriInfo,
73                                   &param);
74 
75         if (eError == OMX_ErrorNone) {
76             CAMHAL_LOGD("DCC URI's %s ", param.sDCCURI);
77             android::String8 *dccDir = new android::String8();
78             if ( NULL != dccDir ) {
79                 dccDir->clear();
80                 dccDir->append(DCCPath);
81                 dccDir->append((const char *) param.sDCCURI);
82                 dccDir->append("/");
83                 dccDirs.add(dccDir);
84             } else {
85                 CAMHAL_LOGE("DCC URI not allocated");
86                 eError = OMX_ErrorInsufficientResources;
87                 goto EXIT;
88             }
89         }
90     }
91 
92     // setting  back errortype OMX_ErrorNone
93     if (eError == OMX_ErrorNoMore) {
94         eError = OMX_ErrorNone;
95     }
96 
97     dccbuf_size = readDCCdir(NULL, dccDirs);
98     if(dccbuf_size <= 0) {
99         CAMHAL_LOGE("No DCC files found, switching back to default DCC");
100         eError = OMX_ErrorInsufficientResources;
101         goto EXIT;
102     }
103     dccbuf_size = ((dccbuf_size + 4095 )/4096)*4096;
104 
105     if ( memMgr.initialize() != NO_ERROR ) {
106         CAMHAL_LOGE("DCC memory manager initialization failed!!!");
107         eError = OMX_ErrorInsufficientResources;
108         goto EXIT;
109     }
110 
111     dccBuffer = memMgr.allocateBufferList(0, 0, NULL, dccbuf_size, 1);
112     if ( NULL == dccBuffer ) {
113         CAMHAL_LOGE("DCC buffer allocation failed!!!");
114         eError = OMX_ErrorInsufficientResources;
115         goto EXIT;
116     }
117 
118     dccbuf_size = readDCCdir(dccBuffer[0].mapped, dccDirs);
119     CAMHAL_ASSERT_X(dccbuf_size > 0,"ERROR in copy DCC files into buffer");
120 
121     eError = sendDCCBufPtr(hComponent, dccBuffer);
122 
123 EXIT:
124 
125     for (i = 0; i < dccDirs.size(); i++) {
126         android::String8 *dccDir = dccDirs.itemAt(0);
127         dccDirs.removeAt(0);
128         delete dccDir;
129     }
130 
131     if ( NULL != dccBuffer ) {
132         memMgr.freeBufferList(dccBuffer);
133     }
134 
135      return eError;
136 }
137 
sendDCCBufPtr(OMX_HANDLETYPE hComponent,CameraBuffer * dccBuffer)138 OMX_ERRORTYPE DCCHandler::sendDCCBufPtr(OMX_HANDLETYPE hComponent,
139                                     CameraBuffer *dccBuffer)
140 {
141     OMX_TI_CONFIG_SHAREDBUFFER uribufparam;
142     OMX_ERRORTYPE eError = OMX_ErrorNone;
143     OMX_INIT_STRUCT_PTR(&uribufparam, OMX_TI_CONFIG_SHAREDBUFFER);
144 
145     CAMHAL_ASSERT_X(dccBuffer != NULL,"ERROR invalid DCC buffer");
146 
147     uribufparam.nPortIndex = OMX_ALL;
148     uribufparam.nSharedBuffSize = dccBuffer->size;
149     uribufparam.pSharedBuff = (OMX_U8 *) camera_buffer_get_omx_ptr(dccBuffer);
150 
151     eError = OMX_SetParameter(hComponent,
152                                 ( OMX_INDEXTYPE )OMX_TI_IndexParamDccUriBuffer,
153                                 &uribufparam);
154     if (eError != OMX_ErrorNone) {
155         CAMHAL_LOGEB(" Error in SetParam for DCC Uri Buffer 0x%x", eError);
156     }
157 
158     return eError;
159 }
160 
readDCCdir(OMX_PTR buffer,const android::Vector<android::String8 * > & dirPaths)161 size_t DCCHandler::readDCCdir(OMX_PTR buffer,
162                           const android::Vector<android::String8 *> &dirPaths)
163 {
164     FILE *pFile;
165     OMX_S32 lSize;
166     OMX_S32 dcc_buf_size = 0;
167     size_t result;
168     OMX_STRING filename;
169     android::String8 temp;
170     const char *dotdot = "..";
171     DIR *d;
172     struct dirent *dir;
173     OMX_U16 i = 0;
174     status_t stat = NO_ERROR;
175     size_t ret = 0;
176 
177     for (i = 0; i < dirPaths.size(); i++) {
178         d = opendir(dirPaths.itemAt(i)->string());
179         if (d) {
180             // read each filename
181             while ((dir = readdir(d)) != NULL) {
182                 filename = dir->d_name;
183                 temp.clear();
184                 temp.append(dirPaths.itemAt(i)->string());
185                 temp.append(filename);
186                 if ((*filename != *dotdot)) {
187                     pFile = fopen(temp.string(), "rb");
188                     if (pFile == NULL) {
189                         stat = -errno;
190                     } else {
191                         fseek(pFile, 0, SEEK_END);
192                         lSize = ftell(pFile);
193                         rewind(pFile);
194                         // buffer is not NULL then copy all the DCC profiles into buffer
195                         // else return the size of the DCC directory.
196                         if (buffer) {
197                             // copy file into the buffer:
198                             result = fread(buffer, 1, lSize, pFile);
199                             if (result != (size_t) lSize) {
200                                 stat = INVALID_OPERATION;
201                             }
202                             buffer = buffer + lSize;
203                         }
204                         // getting the size of the total dcc files available in FS */
205                         dcc_buf_size = dcc_buf_size + lSize;
206                         // terminate
207                         fclose(pFile);
208                     }
209                 }
210             }
211             closedir(d);
212         }
213     }
214 
215     if (stat == NO_ERROR) {
216         ret = dcc_buf_size;
217     }
218 
219     return ret;
220 }
221 
222 } // namespace Camera
223 } // namespace Ti
224