Home | History | Annotate | Download | only in profile
      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