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 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 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 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 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 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 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 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 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 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