1 /* 2 * Copyright (C) 2014 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 #include <expat.h> 18 #include <string.h> 19 #include <stdio.h> 20 #include <utils/Log.h> 21 #include "isv_profile.h" 22 23 #undef LOG_TAG 24 #define LOG_TAG "ISVProfile" 25 26 #define QCIF_AREA (176 * 144) 27 28 #define DEFAULT_XML_FILE "/etc/video_isv_profile.xml" 29 30 using namespace android; 31 static const char StatusOn[][5] = {"1frc", "1vpp"}; 32 33 ISVProfile::ISVProfile(const uint32_t width, const uint32_t height) 34 { 35 int i; 36 37 mWidth = width; 38 mHeight = height; 39 40 mCurrentFilter = 0; 41 mCurrentFrcTab = 0; 42 mDefaultVPPStatus = 0; 43 mDefaultFRCStatus = 0; 44 45 mStatus = 0; 46 47 memset(mConfigs, 0, sizeof(ISVConfig) * ProcFilterCount); 48 49 for (i = 0; i < MAX_TAB_SIZE; i++) { 50 mFrcRates[i].input_fps = 0; 51 mFrcRates[i].rate = FRC_RATE_1X; 52 } 53 54 /* get the vpp global setting */ 55 //getGlobalStatus(); 56 57 /* load the config data from XML file */ 58 getDataFromXmlFile(); 59 60 /* update the filter status according to the configs */ 61 updateFilterStatus(); 62 63 /* dump data for debug */ 64 dumpConfigData(); 65 } 66 67 ISVProfile::~ISVProfile() 68 { 69 } 70 71 FRC_RATE ISVProfile::getFRCRate(uint32_t inputFps) 72 { 73 FRC_RATE rate = FRC_RATE_1X; 74 int i; 75 76 for (i = 0; i < MAX_TAB_SIZE; i++) { 77 if (mFrcRates[i].input_fps == inputFps) { 78 rate = mFrcRates[i].rate; 79 break; 80 } 81 } 82 return rate; 83 } 84 85 uint32_t ISVProfile::getFilterStatus() 86 { 87 return mStatus; 88 } 89 90 bool ISVProfile::isVPPOn() 91 { 92 int32_t status = getGlobalStatus(); 93 return (status != -1) ? (((status & VPP_COMMON_ON) != 0) ? true : false) : false; 94 } 95 96 bool ISVProfile::isFRCOn() 97 { 98 int32_t status = getGlobalStatus(); 99 return (status != -1) ? (((status & VPP_FRC_ON) != 0) ? true : false) : false; 100 } 101 102 void ISVProfile::updateFilterStatus() { 103 int i; 104 uint32_t area = mWidth * mHeight; 105 106 for (i = 1; i < ProcFilterCount; i++) { 107 /* check config */ 108 if (mConfigs[i].enabled == false) 109 continue; 110 111 if (area > mConfigs[i].minResolution && area <= mConfigs[i].maxResolution) 112 mStatus |= 1 << i; 113 /* we should cover QCIF */ 114 else if (area == mConfigs[i].minResolution && area == QCIF_AREA) 115 mStatus |= 1 << i; 116 } 117 } 118 119 int ISVProfile::getFilterID(const char * name) 120 { 121 int index = 0; 122 123 if (strcmp(name, "ProcFilterNoiseReduction") == 0) 124 index = ProcFilterNoiseReduction; 125 else if (strcmp(name, "ProcFilterDeinterlacing") == 0) 126 index = ProcFilterDeinterlacing; 127 else if (strcmp(name, "ProcFilterSharpening") == 0) 128 index = ProcFilterSharpening; 129 else if (strcmp(name, "ProcFilterColorBalance") == 0) 130 index = ProcFilterColorBalance; 131 else if (strcmp(name, "ProcFilterDeblocking") == 0) 132 index = ProcFilterDeblocking; 133 else if (strcmp(name, "ProcFilterFrameRateConversion") == 0) 134 index = ProcFilterFrameRateConversion; 135 else if (strcmp(name, "ProcFilterSkinToneEnhancement") == 0) 136 index = ProcFilterSkinToneEnhancement; 137 else if (strcmp(name, "ProcFilterTotalColorCorrection") == 0) 138 index = ProcFilterTotalColorCorrection; 139 else if (strcmp(name, "ProcFilterNonLinearAnamorphicScaling") == 0) 140 index = ProcFilterNonLinearAnamorphicScaling; 141 else if (strcmp(name, "ProcFilterImageStabilization") == 0) 142 index = ProcFilterImageStabilization; 143 else 144 index = 0; 145 146 mCurrentFilter = index; 147 148 return index; 149 } 150 151 uint32_t ISVProfile::getResolution(const char * name) 152 { 153 uint32_t width = 0, height = 0; 154 char *p = NULL, *str = NULL; 155 int32_t lenth = strlen(name); 156 157 str = (char*)malloc(lenth+1); 158 if (NULL == str) { 159 ALOGE("%s: failed to malloc buffer", __func__); 160 return 0; 161 } 162 strncpy(str, name, lenth); 163 str[lenth] = '\0'; 164 165 p = strtok(str, "x"); 166 if (p) 167 width = atoi(p); 168 p = strtok(NULL, "x"); 169 if (p) 170 height = atoi(p); 171 172 if (str) { 173 free(str); 174 str = NULL; 175 } 176 return width * height; 177 } 178 179 void ISVProfile::getConfigData(const char *name, const char **atts) 180 { 181 int attIndex = 0; 182 183 if (strcmp(name, "VideoPostProcessSettings") == 0) { 184 return; 185 } else if (strcmp(name, "Filter") == 0) { 186 if (strcmp(atts[attIndex], "name") == 0) { 187 if (getFilterID(atts[attIndex + 1]) == 0) { 188 ALOGE("Couldn't parase the filter %s\n", atts[attIndex+1]); 189 } 190 } else { 191 ALOGE("couldn't handle \"%s\" element for Filter\n", name); 192 } 193 } else if (strcmp(name, "enabled") == 0) { 194 if (mCurrentFilter) { 195 if (!strcmp(atts[attIndex], "value") && !strcmp(atts[attIndex + 1], "true")) 196 mConfigs[mCurrentFilter].enabled = true; 197 } else { 198 ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name); 199 } 200 } else if (strcmp(name, "minResolution") == 0) { 201 if (mCurrentFilter && !strcmp(atts[attIndex], "value")) { 202 if (!strcmp(atts[attIndex + 1], "0")) 203 mConfigs[mCurrentFilter].minResolution = 0; 204 else if (!strcmp(atts[attIndex + 1], "FFFFFFFF")) 205 mConfigs[mCurrentFilter].minResolution = 0xFFFFFFFF; 206 else 207 mConfigs[mCurrentFilter].minResolution = getResolution(atts[attIndex + 1]); 208 } else { 209 ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name); 210 } 211 } else if (strcmp(name, "maxResolution") == 0) { 212 if (mCurrentFilter && !strcmp(atts[attIndex], "value")) { 213 if (!strcmp(atts[attIndex + 1], "0")) 214 mConfigs[mCurrentFilter].maxResolution = 0; 215 else if (!strcmp(atts[attIndex + 1], "FFFFFFFF")) 216 mConfigs[mCurrentFilter].maxResolution = 0xFFFFFFFF; 217 else 218 mConfigs[mCurrentFilter].maxResolution = getResolution(atts[attIndex + 1]); 219 } else { 220 ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name); 221 } 222 } else if (strcmp(name, "FRCRate") == 0) { 223 if (mCurrentFilter == ProcFilterFrameRateConversion) { 224 if (!strcmp(atts[attIndex], "input") && !strcmp(atts[attIndex + 2], "rate")) { 225 mFrcRates[mCurrentFrcTab].input_fps = atoi(atts[attIndex + 1]); 226 if (!strcmp(atts[attIndex + 3], "2")) 227 mFrcRates[mCurrentFrcTab].rate = FRC_RATE_2X; 228 else if (!strcmp(atts[attIndex + 3], "2.5")) 229 mFrcRates[mCurrentFrcTab].rate = FRC_RATE_2_5X; 230 else if (!strcmp(atts[attIndex + 3], "4")) 231 mFrcRates[mCurrentFrcTab].rate = FRC_RATE_4X; 232 else 233 mFrcRates[mCurrentFrcTab].rate = FRC_RATE_1X; 234 235 /* update the pointer */ 236 if (mCurrentFrcTab < MAX_TAB_SIZE) 237 mCurrentFrcTab++; 238 } 239 } else { 240 ALOGE("\"FRCRate\" element is only for ProcFilterFrameRateConversion\n"); 241 } 242 } else if (strcmp(name, "parameter") == 0) { 243 /* <parameter /> */ 244 handleFilterParameter(name, atts); 245 } else if (strcmp(name, "Parameter") == 0) { 246 /* <Parameter /> */ 247 handleCommonParameter(name, atts); 248 } else 249 ALOGE("Couldn't handle this element %s!\n", name); 250 } 251 252 void ISVProfile::handleFilterParameter(const char *name, const char **atts) 253 { 254 int attIndex = 0; 255 256 if (!mCurrentFilter) { 257 ALOGE("\"%s\" must be in Filter element\n", name); 258 return; 259 } 260 261 if (strcmp(atts[attIndex], "name") || strcmp(atts[attIndex + 2], "value")) { 262 ALOGE("\"%s\" or \"%s\" couldn't match the %s format\n", atts[attIndex], atts[attIndex + 2], name); 263 return; 264 } 265 266 } 267 268 void ISVProfile::handleCommonParameter(const char *name, const char **atts) 269 { 270 int attIndex = 0; 271 272 if (strcmp(atts[attIndex], "name") || strcmp(atts[attIndex + 2], "value")) { 273 ALOGE("\"%s\" or \"%s\" couldn't match the %s format\n", atts[attIndex], atts[attIndex + 2], name); 274 return; 275 } 276 277 /* The default status of VPP */ 278 if (strcmp(atts[attIndex + 1], "DefaultVPPStatus") == 0) 279 mDefaultVPPStatus = atoi(atts[attIndex + 3]); 280 /* The default status of FRC */ 281 else if (strcmp(atts[attIndex + 1], "DefaultFRCStatus") == 0) 282 mDefaultFRCStatus = atoi(atts[attIndex + 3]); 283 } 284 285 void ISVProfile::startElement(void *userData, const char *name, const char **atts) 286 { 287 ISVProfile *profile = (ISVProfile *)userData; 288 289 profile->getConfigData(name, atts); 290 } 291 292 void ISVProfile::endElement(void *userData, const char *name) 293 { 294 ISVProfile *profile = (ISVProfile *)userData; 295 296 if (!strcmp(name, "Filter")) 297 profile->mCurrentFilter = 0; 298 } 299 300 void ISVProfile::getDataFromXmlFile() 301 { 302 int done; 303 void *pBuf = NULL; 304 FILE *fp = NULL; 305 306 fp = ::fopen(DEFAULT_XML_FILE, "r"); 307 if (NULL == fp) { 308 ALOGE("@%s, line:%d, couldn't open profile %s", __func__, __LINE__, DEFAULT_XML_FILE); 309 return; 310 } 311 312 XML_Parser parser = ::XML_ParserCreate(NULL); 313 if (NULL == parser) { 314 ALOGE("@%s, line:%d, parser is NULL", __func__, __LINE__); 315 goto exit; 316 } 317 ::XML_SetUserData(parser, this); 318 ::XML_SetElementHandler(parser, startElement, endElement); 319 320 pBuf = malloc(mBufSize); 321 if (NULL == pBuf) { 322 ALOGE("@%s, line:%d, failed to malloc buffer", __func__, __LINE__); 323 goto exit; 324 } 325 326 do { 327 int len = (int)::fread(pBuf, 1, mBufSize, fp); 328 if (!len) { 329 if (ferror(fp)) { 330 clearerr(fp); 331 goto exit; 332 } 333 } 334 done = len < mBufSize; 335 if (XML_Parse(parser, (const char *)pBuf, len, done) == XML_STATUS_ERROR) { 336 ALOGE("@%s, line:%d, XML_Parse error", __func__, __LINE__); 337 goto exit; 338 } 339 } while (!done); 340 341 exit: 342 if (parser) 343 ::XML_ParserFree(parser); 344 if (pBuf) 345 free(pBuf); 346 if (fp) 347 ::fclose(fp); 348 } 349 350 int32_t ISVProfile::getGlobalStatus() 351 { 352 char path[80]; 353 int userId = 0; 354 int32_t status = 0; 355 FILE *setting_handle, *config_handle; 356 357 snprintf(path, 80, "/data/user/%d/com.intel.vpp/shared_prefs/vpp_settings.xml", userId); 358 ALOGV("%s: %s",__func__, path); 359 setting_handle = fopen(path, "r"); 360 if(setting_handle == NULL) { 361 ALOGE("%s: failed to open file %s\n", __func__, path); 362 363 /* Read the Filter config file to get default value */ 364 config_handle = fopen(DEFAULT_XML_FILE, "r"); 365 if (config_handle == NULL) { 366 ALOGE("%s: failed to open file %s\n", __func__, DEFAULT_XML_FILE); 367 return -1; 368 } 369 370 char xml_buf[MAX_BUF_SIZE + 1] = {0}; 371 memset(xml_buf, 0, MAX_BUF_SIZE); 372 if (fread(xml_buf, 1, MAX_BUF_SIZE, config_handle) <= 0) { 373 ALOGE("%s: failed to read config xml file!\n", __func__); 374 fclose(config_handle); 375 return -1; 376 } 377 xml_buf[MAX_BUF_SIZE] = '\0'; 378 379 if (strstr(xml_buf, "name=\"DefaultVPPStatus\" value=\"1\"") != NULL) 380 status |= VPP_COMMON_ON; 381 if (strstr(xml_buf, "name=\"DefaultFRCStatus\" value=\"1\"") != NULL) 382 status |= VPP_FRC_ON; 383 384 ALOGV("%s: using the default status: VPP=%d, FRC=%d\n", __func__, 385 ((status & VPP_COMMON_ON) == 0) ? 0 : 1, 386 ((status & VPP_FRC_ON) == 0) ? 0: 1); 387 388 fclose(config_handle); 389 return status; 390 } 391 392 const int MAXLEN = 1024; 393 char buf[MAXLEN] = {0}; 394 memset(buf, 0 ,MAXLEN); 395 if(fread(buf, 1, MAXLEN, setting_handle) <= 0) { 396 ALOGE("%s: failed to read vpp config file %d", __func__, userId); 397 fclose(setting_handle); 398 return -1; 399 } 400 buf[MAXLEN - 1] = '\0'; 401 402 if(strstr(buf, StatusOn[0]) != NULL) 403 status |= VPP_FRC_ON; 404 405 if(strstr(buf, StatusOn[1]) != NULL) 406 status |= VPP_COMMON_ON; 407 408 fclose(setting_handle); 409 return status; 410 } 411 412 void ISVProfile::dumpConfigData() 413 { 414 uint32_t i, j; 415 char filterNames[][50] = { 416 "ProcFilterNone", 417 "ProcFilterNoiseReduction", 418 "ProcFilterDeinterlacing", 419 "ProcFilterSharpening", 420 "ProcFilterColorBalance", 421 "ProcFilterDeblocking", 422 "ProcFilterFrameRateConversion", 423 "ProcFilterSkinToneEnhancement", 424 "ProcFilterTotalColorCorrection", 425 "ProcFilterNonLinearAnamorphicScaling", 426 "ProcFilterImageStabilization" 427 }; 428 char rateNames[][20] = { 429 "FRC_RATE_0X", 430 "FRC_RATE_1X", 431 "FRC_RATE_2X", 432 "FRC_RATE_2_5X", 433 "FRC_RATE_4X", 434 }; 435 436 ALOGV("========== VPP filter configs:==========\n"); 437 for (i = 1; i < ProcFilterCount; i++) { 438 ALOGV("name=%s, enabled=%s, minResolution=%d, maxResolution=%d, isOn=%s\n", 439 filterNames[i], 440 (mConfigs[i].enabled == true) ? "true" : "false", 441 mConfigs[i].minResolution, 442 mConfigs[i].maxResolution, 443 ((mStatus & (1 << i)) == 0) ? "false" : "true"); 444 if (mConfigs[i].paraSize) { 445 ALOGV("\t\t parameters: "); 446 for(j = 0; j < mConfigs[i].paraSize; j++) 447 ALOGE("%s=%f,", mConfigs[i].paraTables[j].name, mConfigs[i].paraTables[j].value); 448 ALOGV("\n"); 449 } 450 } 451 452 ALOGV("========== FRC rate configs:===========\n"); 453 for (i = 0; i < MAX_TAB_SIZE; i++) { 454 if (mFrcRates[i].input_fps == 0) 455 break; 456 ALOGV("input_fps=%d, rate=%s\n", mFrcRates[i].input_fps, rateNames[mFrcRates[i].rate]); 457 } 458 459 ALOGI("========== common parameter configs:===========\n"); 460 ALOGI("mDefaultVPPStatus=%d\n", mDefaultVPPStatus); 461 ALOGI("mDefaultFRCStatus=%d\n", mDefaultFRCStatus); 462 463 } 464