1 /*
2 * * Copyright (c) 2015 Intel Corporation. All rights reserved.
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 //#define LOG_NDEBUG 0
19 #define LOG_TAG "MRM_OMX_Adaptor"
20
21 #include <utils/Log.h>
22 #include <utils/threads.h>
23 #include "OMX_adaptor.h"
24
25 const char* CODECS_LIMITATION_FILE = "/etc/codec_resources_limitation.xml";
26
27 using namespace android;
28
29 // static member declare
30 MRM_OMX_Adaptor* MRM_OMX_Adaptor::sInstance = NULL;
31 Mutex MRM_OMX_Adaptor::sLock;
32
33 typedef enum {
34 kPortIndexInput = 0,
35 kPortIndexOutput = 1
36 } PORT_INDEX;
37
38
39 // case insensitive string finding
strstri(const char * str,const char * subStr)40 static const char* strstri(const char* str, const char* subStr) {
41 int len = strlen(subStr);
42 if (len == 0) {
43 return NULL;
44 }
45
46 while(*str) {
47 if(strncasecmp(str, subStr, len) == 0) {
48 return str;
49 }
50 ++str;
51 }
52 return NULL;
53 }
54
55
56 //static
getInstance()57 MRM_OMX_Adaptor* MRM_OMX_Adaptor::getInstance() {
58 ALOGV("getInstance()");
59 Mutex::Autolock lock(sLock);
60
61 if (sInstance == NULL) {
62 sInstance = new MRM_OMX_Adaptor();
63 }
64
65 return sInstance;
66 }
67
68
MRM_OMX_Init(void)69 OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_Init(void) {
70 ALOGV("MRM_OMX_Init");
71 OMX_ERRORTYPE err = OMX_ErrorNone;
72 if (mArbitrator != NULL) {
73 err = (OMX_ERRORTYPE)mArbitrator->Config(CODECS_LIMITATION_FILE);
74 }
75 return err;
76 }
77
78
MRM_OMX_CheckIfFullLoad(OMX_STRING cComponentName)79 OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_CheckIfFullLoad(OMX_STRING cComponentName) {
80 ALOGV("MRM_OMX_CheckIfFullLoad");
81 Mutex::Autolock lock(sLock);
82
83 String8 sComponentName(cComponentName);
84 AdaptorCodecInfo codecInfo;
85 ParseCodecInfoFromComponentName(sComponentName.string(), &codecInfo);
86
87 if (codecInfo.isEncoder) {
88 ALOGV("Checking full load status of encoder.");
89 if (mArbitrator->CheckIfFullLoad(true/*encoder*/)) {
90 ALOGV("encoder in full load status. return OMX_ErrorInsufficientResources");
91 return OMX_ErrorInsufficientResources;
92 } else {
93 return OMX_ErrorNone;
94 }
95 } else {
96 ALOGV("Checking full load status of decoder.");
97 if (mArbitrator->CheckIfFullLoad(false/*decoder*/)) {
98 ALOGV("decoder in full load status. return OMX_ErrorInsufficientResources");
99 return OMX_ErrorInsufficientResources;
100 } else {
101 return OMX_ErrorNone;
102 }
103 }
104 }
105
106
MRM_OMX_SetComponent(OMX_HANDLETYPE pComponentHandle,OMX_STRING cComponentName)107 void MRM_OMX_Adaptor::MRM_OMX_SetComponent(
108 OMX_HANDLETYPE pComponentHandle,
109 OMX_STRING cComponentName) {
110 ALOGV("MRM_OMX_SetComponent: %s", cComponentName);
111 String8 sComponentName(cComponentName);
112 ALOGV("pComponentHandle = 0x%x, componentName = %s", pComponentHandle, sComponentName.string());
113 mComponentNameMap.add(pComponentHandle, sComponentName);
114 }
115
116
MRM_OMX_SetParameter(OMX_HANDLETYPE hComponent,OMX_INDEXTYPE nIndex,OMX_PTR pComponentParameterStructure)117 OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_SetParameter(
118 OMX_HANDLETYPE hComponent,
119 OMX_INDEXTYPE nIndex,
120 OMX_PTR pComponentParameterStructure) {
121 ALOGV("MRM_OMX_SetParameter");
122 ALOGV("hComponent = 0x%x", hComponent);
123 OMX_ERRORTYPE err = OMX_ErrorNone;
124
125 Mutex::Autolock lock(sLock);
126
127 if (nIndex == OMX_IndexParamPortDefinition) {
128 OMX_PARAM_PORTDEFINITIONTYPE *def =
129 static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pComponentParameterStructure);
130
131 if (def->nPortIndex == kPortIndexInput) {
132 ALOGV("MRM_OMX_SetParameter for inport param def");
133 if (mComponentFramerateMap.indexOfKey(hComponent) >= 0) {
134 ALOGV("setParameter is called again for component 0x%x inport", hComponent);
135 return OMX_ErrorNone;
136 }
137
138 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
139 uint frameRate = (uint)(video_def->xFramerate/65536);
140 ALOGV("frame rate from inport = %d", frameRate);
141 mComponentFramerateMap.add(hComponent, frameRate);
142 }
143
144 if (def->nPortIndex == kPortIndexOutput) {
145 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
146
147 // if setParameter is not first called to this component's outport
148 // do not try to record its info for the second time
149 if (mComponentInfoMap.indexOfKey(hComponent) >= 0) {
150 ALOGV("setParameter is called again for component 0x%x outport", hComponent);
151 return OMX_ErrorNone;
152 }
153
154 String8 sComponentName = mComponentNameMap.valueFor(hComponent);
155 ALOGV("component name from component map is %s", sComponentName.string());
156
157 AdaptorCodecInfo codecInfo;
158 ParseCodecInfoFromComponentName(sComponentName.string(), &codecInfo);
159
160 if (mArbitrator->CheckIfFullLoad(codecInfo.isEncoder)) {
161 return OMX_ErrorInsufficientResources;
162 }
163
164 ResolutionType resolution;
165 unsigned int height = video_def->nFrameHeight;
166 ALOGV("video resulotion = %d x %d", video_def->nFrameWidth, video_def->nFrameHeight);
167 if (height <= 480) {
168 resolution = Resolution_480;
169 } else if (height <= 720) {
170 resolution = Resolution_720;
171 } else if (height <= 1080) {
172 resolution = Resolution_1080;
173 } else if (height <= 1440) {
174 resolution = Resolution_2K;
175 } else if (height <= 2160) {
176 resolution = Resolution_4K;
177 } else {
178 ALOGE("resolution > 4K is not supported!");
179 }
180 codecInfo.resolution = resolution;
181
182 unsigned int frameRate = 0;
183 if (mComponentFramerateMap.indexOfKey(hComponent) >= 0) {
184 frameRate = mComponentFramerateMap.valueFor(hComponent);
185 } else {
186 ALOGW("frame rate was not set in inport def...");
187 }
188
189 ALOGV("frame rate from inport def = %d", frameRate);
190 if ((frameRate > 55) && (frameRate < 65)) {
191 frameRate = 60;
192 // This is a w/a to set default frame rate as 30 in case it is not
193 // set from framewrok.
194 } else {
195 frameRate = 30;
196 }
197 codecInfo.frameRate = frameRate;
198 err = (OMX_ERRORTYPE)mArbitrator->AddResource(codecInfo.codecType,
199 codecInfo.isEncoder,
200 codecInfo.isSecured,
201 codecInfo.resolution,
202 codecInfo.frameRate);
203
204 mComponentInfoMap.add(hComponent, codecInfo);
205 }
206 }
207 return err;
208 }
209
210
MRM_OMX_UseBuffer(OMX_HANDLETYPE hComponent,OMX_BUFFERHEADERTYPE ** ppBufferHdr,OMX_U32 nPortIndex,OMX_PTR pAppPrivate,OMX_U32 nSizeBytes,OMX_U8 * pBuffer)211 OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_UseBuffer(
212 OMX_HANDLETYPE hComponent,
213 OMX_BUFFERHEADERTYPE **ppBufferHdr,
214 OMX_U32 nPortIndex,
215 OMX_PTR pAppPrivate,
216 OMX_U32 nSizeBytes,
217 OMX_U8 *pBuffer) {
218 ALOGV("MRM_OMX_UseBuffer");
219 OMX_ERRORTYPE err = OMX_ErrorNone;
220 return err;
221 }
222
223
MRM_OMX_RemoveComponent(OMX_HANDLETYPE pComponentHandle)224 OMX_ERRORTYPE MRM_OMX_Adaptor::MRM_OMX_RemoveComponent(
225 OMX_HANDLETYPE pComponentHandle) {
226 ALOGV("MRM_OMX_RemoveComponent 0x%x", pComponentHandle);
227 OMX_ERRORTYPE err = OMX_ErrorNone;
228
229 if (mComponentInfoMap.indexOfKey(pComponentHandle) < 0) {
230 ALOGE("component 0x%x was not added by setParameter before! something is wrong?",pComponentHandle);
231 return OMX_ErrorNone; // TODO: change to specific error.
232 }
233
234 const AdaptorCodecInfo& codecInfo = mComponentInfoMap.valueFor(pComponentHandle);
235
236 err = (OMX_ERRORTYPE)mArbitrator->RemoveResource(codecInfo.codecType,
237 codecInfo.isEncoder,
238 codecInfo.isSecured,
239 codecInfo.resolution,
240 codecInfo.frameRate);
241 mComponentInfoMap.removeItem(pComponentHandle);
242 return err;
243 }
244
245
246
247
ParseCodecInfoFromComponentName(const char * componentName,AdaptorCodecInfo * codecInfo)248 void MRM_OMX_Adaptor::ParseCodecInfoFromComponentName(
249 const char* componentName,
250 AdaptorCodecInfo* codecInfo) {
251 ALOGV("ParseCodecInfoFromComponentName");
252 ALOGV("componentName = %s", componentName);
253 bool isSecured = false;
254 if (strstri(componentName,"SECURE") != NULL) {
255 isSecured = true;
256 }
257 codecInfo->isSecured = isSecured;
258
259 bool isEncoder = false;
260 if ((strstri(componentName, "ENCODER") != NULL) ||
261 (strstri(componentName, "sw_ve") != NULL)) {
262 isEncoder = true;
263 }
264 codecInfo->isEncoder = isEncoder;
265
266 CodecType codecType = CODEC_TYPE_MAX;
267 if (strstri(componentName, "AVC") != NULL) {
268 codecType = CODEC_TYPE_AVC;
269 } else if (strstri(componentName, "VP8") != NULL) {
270 codecType = CODEC_TYPE_VP8;
271 } else if (strstri(componentName, "VP9") != NULL) {
272 codecType = CODEC_TYPE_VP9;
273 } else if (strstri(componentName, "MPEG4") != NULL) {
274 codecType = CODEC_TYPE_MPEG4;
275 } else if (strstri(componentName, "MPEG2") != NULL) {
276 codecType = CODEC_TYPE_MPEG2;
277 } else if (strstri(componentName, "H263") != NULL) {
278 codecType = CODEC_TYPE_H263;
279 } else if (strstri(componentName, "H265") != NULL) {
280 codecType = CODEC_TYPE_HEVC;
281 } else if (strstri(componentName, "WMV") != NULL) {
282 codecType = CODEC_TYPE_WMV;
283 }
284 ALOGV("video codec type = %d", codecType);
285 codecInfo->codecType = codecType;
286 }
287
288
289