1 /*-------------------------------------------------------------------------- 2 Copyright (c) 2017, The Linux Foundation. All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are 6 met: 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above 10 copyright notice, this list of conditions and the following 11 disclaimer in the documentation and/or other materials provided 12 with the distribution. 13 * Neither the name of The Linux Foundation nor the names of its 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 --------------------------------------------------------------------------*/ 29 30 #define LOG_TAG "OMX-VENDOR-EXT" 31 #include <utils/Log.h> 32 #include "vidc_debug.h" 33 34 #include "OMX_Core.h" 35 #include "OMX_QCOMExtns.h" 36 #include "OMX_VideoExt.h" 37 #include "OMX_IndexExt.h" 38 #include "vidc_vendor_extensions.h" 39 40 VendorExtension::VendorExtension(OMX_INDEXTYPE id, const char *name, OMX_DIRTYPE dir, 41 const ParamListBuilder& p) 42 : mId(id), 43 mName(name), 44 mPortDir(dir), 45 mParams(std::move(p.mParams)), 46 mIsSet(false) { 47 } 48 49 // copy extension Info to OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE* struct passed 50 OMX_ERRORTYPE VendorExtension::copyInfoTo( 51 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) const { 52 53 // Extension info 54 strncpy((char *)ext->cName, mName.c_str(), OMX_MAX_STRINGNAME_SIZE); 55 ext->eDir = mPortDir; 56 ext->nParamCount = paramCount(); 57 58 // Per-parameter info 59 // Must be copied only if there are enough params to fill-in 60 if (ext->nParamSizeUsed < ext->nParamCount) { 61 return OMX_ErrorNone; 62 } 63 64 int i = 0; 65 for (const Param& p : mParams) { 66 strncpy((char *)ext->nParam[i].cKey, p.name(), OMX_MAX_STRINGNAME_SIZE); 67 ext->nParam[i].bSet = mIsSet ? OMX_TRUE : OMX_FALSE; 68 ext->nParam[i].eValueType = p.type(); 69 ++i; 70 } 71 return OMX_ErrorNone; 72 } 73 74 bool VendorExtension::setParamInt32( 75 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey, 76 OMX_S32 setInt32) const { 77 int paramIndex = indexOfParam(paramKey); 78 if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueInt32)) { 79 return false; 80 } 81 ext->nParam[paramIndex].nInt32 = setInt32; 82 return true; 83 } 84 85 bool VendorExtension::setParamInt64( 86 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey, 87 OMX_S32 setInt64) const { 88 int paramIndex = indexOfParam(paramKey); 89 if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueInt64)) { 90 return false; 91 } 92 ext->nParam[paramIndex].nInt64 = setInt64; 93 return true; 94 } 95 96 bool VendorExtension::setParamString( 97 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey, 98 const char *setStr) const { 99 int paramIndex = indexOfParam(paramKey); 100 if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueString)) { 101 return false; 102 } 103 strncpy((char *)ext->nParam[paramIndex].cString, setStr, OMX_MAX_STRINGVALUE_SIZE); 104 return true; 105 } 106 107 bool VendorExtension::readParamInt32( 108 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey, 109 OMX_S32 *readInt32) const { 110 int paramIndex = indexOfParam(paramKey); 111 if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueInt32)) { 112 return false; 113 } 114 if (ext->nParam[paramIndex].bSet == OMX_TRUE) { 115 *readInt32 = ext->nParam[paramIndex].nInt32; 116 return true; 117 } 118 return false; 119 } 120 121 bool VendorExtension::readParamInt64( 122 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey, 123 OMX_S32 *readInt64) const { 124 int paramIndex = indexOfParam(paramKey); 125 if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueInt64)) { 126 return false; 127 } 128 if (ext->nParam[paramIndex].bSet == OMX_TRUE) { 129 *readInt64 = ext->nParam[paramIndex].nInt64; 130 return true; 131 } 132 return false; 133 } 134 135 bool VendorExtension::readParamInt64( 136 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey, 137 char *readStr) const { 138 int paramIndex = indexOfParam(paramKey); 139 if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueString)) { 140 return false; 141 } 142 if (ext->nParam[paramIndex].bSet == OMX_TRUE) { 143 strncpy(readStr, 144 (const char *)ext->nParam[paramIndex].cString, OMX_MAX_STRINGVALUE_SIZE); 145 return true; 146 } 147 return false; 148 } 149 150 // Checkers 151 OMX_ERRORTYPE VendorExtension::isConfigValid( 152 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) const { 153 ALOGI("isConfigValid"); 154 155 if (ext->nParamSizeUsed < ext->nParamCount) { 156 DEBUG_PRINT_ERROR("allotted params(%u) < required(%u) for %s", 157 ext->nParamSizeUsed, ext->nParamCount, mName.c_str()); 158 return OMX_ErrorBadParameter; 159 } 160 if (ext->nParamCount != paramCount()) { 161 DEBUG_PRINT_ERROR("incorrect param count(%u) v/s required(%u) for %s", 162 ext->nParamCount, paramCount(), mName.c_str()); 163 return OMX_ErrorBadParameter; 164 } 165 if (strncmp((char *)ext->cName, mName.c_str(), OMX_MAX_STRINGNAME_SIZE) != 0) { 166 DEBUG_PRINT_ERROR("extension name mismatch(%s) v/s expected(%s)", 167 (char *)ext->cName, mName.c_str()); 168 return OMX_ErrorBadParameter; 169 } 170 171 for (OMX_U32 i = 0; i < paramCount(); ++i) { 172 if (!_isParamAccessOK(ext, i)) { 173 ALOGI("_isParamAccessOK failed for %u", i); 174 return OMX_ErrorBadParameter; 175 } 176 } 177 178 return OMX_ErrorNone; 179 } 180 181 //static 182 const char* VendorExtension::typeString(OMX_ANDROID_VENDOR_VALUETYPE type) { 183 switch (type) { 184 case OMX_AndroidVendorValueInt32: return "Int32"; 185 case OMX_AndroidVendorValueInt64: return "Int64"; 186 case OMX_AndroidVendorValueString: return "String"; 187 default: return "InvalidType"; 188 } 189 } 190 191 std::string VendorExtension::debugString() const { 192 std::string str = "vendor." + mName + "{"; 193 for (const Param& p : mParams) { 194 str += "{ "; 195 str += p.name(); 196 str += " : "; 197 str += typeString(p.type()); 198 str += " }, "; 199 } 200 str += "}"; 201 return str; 202 } 203 204 bool VendorExtension::_isParamAccessTypeOK( 205 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, int paramIndex, 206 OMX_ANDROID_VENDOR_VALUETYPE type) const { 207 if (paramIndex < 0 208 || paramIndex >= (int)ext->nParamSizeUsed 209 || paramIndex >= (int)paramCount()) { 210 DEBUG_PRINT_ERROR("Invalid Param index(%d) for %s (max=%u)", 211 paramIndex, mName.c_str(), paramCount()); 212 return false; 213 } 214 if (type != mParams[paramIndex].type()) { 215 DEBUG_PRINT_ERROR("Invalid Type for field(%s) for %s.%s (expected=%s)", 216 typeString(type), mName.c_str(), mParams[paramIndex].name(), 217 typeString(mParams[paramIndex].type())); 218 return false; 219 } 220 return true; 221 } 222 223 bool VendorExtension::_isParamAccessOK( 224 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, int paramIndex) const { 225 if (paramIndex < 0 226 || paramIndex >= (int)ext->nParamSizeUsed 227 || paramIndex >= (int)paramCount()) { 228 DEBUG_PRINT_ERROR("Invalid Param index(%d) for %s (max=%u)", 229 paramIndex, mName.c_str(), paramCount()); 230 return false; 231 } 232 if (ext->nParam[paramIndex].eValueType != mParams[paramIndex].type()) { 233 DEBUG_PRINT_ERROR("Invalid Type for field(%s) for %s.%s (expected=%s)", 234 typeString(ext->nParam[paramIndex].eValueType), 235 mName.c_str(), mParams[paramIndex].name(), 236 typeString(mParams[paramIndex].type())); 237 return false; 238 } 239 if (strncmp((const char *)ext->nParam[paramIndex].cKey, 240 mParams[paramIndex].name(), OMX_MAX_STRINGNAME_SIZE) != 0) { 241 DEBUG_PRINT_ERROR("Invalid Key for field(%s) for %s.%s (expected=%s)", 242 ext->nParam[paramIndex].cKey, 243 mName.c_str(), mParams[paramIndex].name(), 244 mParams[paramIndex].name()); 245 return false; 246 } 247 return true; 248 } 249 250 int VendorExtension::indexOfParam(const char *key) const { 251 int i = 0; 252 for (const Param& p : mParams) { 253 if (!strncmp(key, p.name(), OMX_MAX_STRINGNAME_SIZE)) { 254 return i; 255 } 256 ++i; 257 } 258 DEBUG_PRINT_ERROR("Failed to lookup param(%s) in extension(%s)", 259 key, mName.c_str()); 260 return -1; 261 } 262 263 void VendorExtensionStore::dumpExtensions(const char *prefix) const { 264 DEBUG_PRINT_HIGH("%s : Vendor extensions supported (%u)", prefix, size()); 265 for (const VendorExtension& v : mExt) { 266 DEBUG_PRINT_HIGH(" %s", v.debugString().c_str()); 267 } 268 } 269