Home | History | Annotate | Download | only in arbitrator
      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_Arbitrator"
     20 
     21 #include <expat.h>
     22 #include <string.h>
     23 #include <stdio.h>
     24 #include <utils/Log.h>
     25 #include <unistd.h>
     26 #include "MediaResourceArbitrator.h"
     27 
     28 using namespace android;
     29 
     30 
     31 MediaResourceArbitrator::MediaResourceArbitrator()
     32     : mIsEncoderUnderFullLoad (false),
     33       mIsDecoderUnderFullLoad (false) {
     34     ALOGV("construct MediaResourceArbitrator");
     35     pthread_mutex_init(&mArbitratorLock, NULL);
     36     //InitializeCodecNameTypeMap();
     37     //InitializeResolutionNameTypeMap();
     38 }
     39 
     40 
     41 MediaResourceArbitrator::~MediaResourceArbitrator() {}
     42 
     43 
     44 ArbitratorErrorType MediaResourceArbitrator::Config(const char* configFilePath) {
     45     FILE *fp = NULL;
     46 
     47     fp = ::fopen(configFilePath, "r");
     48     if (fp == NULL) {
     49         ALOGV("%s: can not open config xml file.\
     50                try to set up default codec limitation");
     51         SetupDefaultCodecLimitation();
     52         return ArbitratorErrorNone;
     53     }
     54 
     55     ParseXMLFile(fp);
     56     return ArbitratorErrorNone;
     57 }
     58 
     59 
     60 bool MediaResourceArbitrator::CheckIfFullLoad(bool isEncoder) {
     61     if (isEncoder) {
     62         return mIsEncoderUnderFullLoad;
     63     } else {
     64         return mIsDecoderUnderFullLoad;
     65     }
     66 }
     67 
     68 
     69 ArbitratorErrorType MediaResourceArbitrator::AddResource(
     70                     /* in */  CodecType codecType,
     71                     /* in */  bool isEncoder,
     72                     /* in */  bool isSecured,
     73                     /* in */  ResolutionType resolution,
     74                     /* in */  uint frameRate) {
     75     ALOGV("MediaResourceArbitrator::AddResource ++");
     76     pthread_mutex_lock(&mArbitratorLock);
     77 
     78     ArbitratorErrorType err = ArbitratorErrorNone;
     79 
     80     if (CheckIfFullLoad(isEncoder) == true) {
     81         pthread_mutex_unlock(&mArbitratorLock);
     82         return ArbitratorErrorInsufficientResources;
     83     }
     84 
     85     CodecInfo resource;
     86     resource.codecType = codecType;
     87     resource.isEncoder = isEncoder;
     88     resource.isSecured = isSecured;
     89     resource.resolution = resolution;
     90     resource.frameRate = frameRate;
     91 
     92     ALOGV("Adding resource: codecType = %d, isEncoder = %d, isSecured = %d, resolution = %d, frameRate = %d",
     93           codecType, isEncoder, isSecured, resolution, frameRate);
     94 
     95     if (isEncoder) {
     96         mLivingEncodersTable.livingEncoders.push_back(resource);
     97         if (resolution > mLivingEncodersTable.maxResolution) {
     98             mLivingEncodersTable.maxResolution = resolution;
     99         }
    100         if (frameRate > mLivingEncodersTable.maxFrameRate) {
    101             mLivingEncodersTable.maxFrameRate = frameRate;
    102         }
    103     } else { // decoder
    104          mLivingDecodersTable.livingDecoders.push_back(resource);
    105         if (resolution > mLivingDecodersTable.maxResolution) {
    106             mLivingDecodersTable.maxResolution = resolution;
    107         }
    108         if (frameRate > mLivingDecodersTable.maxFrameRate) {
    109             mLivingDecodersTable.maxFrameRate = frameRate;
    110         }
    111     }
    112 
    113     err = ArbitrateFullLoad(resource);
    114     pthread_mutex_unlock(&mArbitratorLock);
    115 
    116     ALOGV("AddResource --");
    117     return err;
    118 }
    119 
    120 
    121 uint MediaResourceArbitrator::GetLivingCodecsNum(void) {
    122     return mLivingDecodersTable.livingDecoders.size() +
    123            mLivingEncodersTable.livingEncoders.size();
    124 }
    125 
    126 
    127 
    128 ArbitratorErrorType MediaResourceArbitrator::RemoveResource(
    129                                    CodecType codecType,
    130                                    bool isEncoder,
    131                                    bool isSecured,
    132                                    ResolutionType resolution,
    133                                    uint frameRate) {
    134     ALOGV("MediaResourceArbitrator::RemoveResource");
    135 
    136     uint i;
    137     ArbitratorErrorType err = ArbitratorErrorNone;
    138 
    139     pthread_mutex_lock(&mArbitratorLock);
    140 
    141     if (isEncoder) {
    142         for(i=0; i<mLivingEncodersTable.livingEncoders.size(); i++) {
    143             const CodecInfo& livingCodec = mLivingEncodersTable.livingEncoders[i];
    144             if ((livingCodec.codecType == codecType) &&
    145                 (livingCodec.resolution == resolution) &&
    146                 (livingCodec.frameRate == frameRate)) {
    147                 mLivingEncodersTable.livingEncoders.removeAt(i);
    148                 break;
    149             }
    150         }
    151         mIsEncoderUnderFullLoad = false;
    152     } else {
    153         for(i=0; i<mLivingDecodersTable.livingDecoders.size(); i++) {
    154             const CodecInfo& livingCodec = mLivingDecodersTable.livingDecoders[i];
    155             if ((livingCodec.codecType == codecType) &&
    156                 (livingCodec.resolution == resolution) &&
    157                 (livingCodec.isSecured == isSecured) &&
    158                 (livingCodec.frameRate == frameRate)) {
    159                 mLivingDecodersTable.livingDecoders.removeAt(i);
    160                 break;
    161             }
    162         }
    163         mIsDecoderUnderFullLoad = false;
    164     }
    165     pthread_mutex_unlock(&mArbitratorLock);
    166     return err;
    167 }
    168 
    169 
    170 void MediaResourceArbitrator::ParseXMLFile(FILE* fp) {
    171     ALOGV("MediaResourceArbitrator::ParseXMLFile");
    172 
    173     int done;
    174     void *pBuf = NULL;
    175 
    176     XML_Parser parser = ::XML_ParserCreate(NULL);
    177     if (NULL == parser) {
    178         ALOGE("@%s, line:%d, parser is NULL", __func__, __LINE__);
    179         goto exit;
    180     }
    181     ::XML_SetUserData(parser, this);
    182     ::XML_SetElementHandler(parser, startElement, endElement);
    183 
    184     pBuf = malloc(mBufSize);
    185     if (NULL == pBuf) {
    186         ALOGE("@%s, line:%d, failed to malloc buffer", __func__, __LINE__);
    187         goto exit;
    188     }
    189 
    190     do {
    191         int len = (int)::fread(pBuf, 1, mBufSize, fp);
    192         if (!len) {
    193             if (ferror(fp)) {
    194                 clearerr(fp);
    195                 goto exit;
    196             }
    197         }
    198         done = len < mBufSize;
    199         if (XML_Parse(parser, (const char *)pBuf, len, done) == XML_STATUS_ERROR) {
    200             ALOGE("@%s, line:%d, XML_Parse error", __func__, __LINE__);
    201             goto exit;
    202         }
    203     } while (!done);
    204 
    205 exit:
    206     if (parser)
    207         ::XML_ParserFree(parser);
    208     if (pBuf)
    209         free(pBuf);
    210     if (fp)
    211     ::fclose(fp);
    212 
    213 }
    214 
    215 
    216 ArbitratorErrorType MediaResourceArbitrator::ArbitrateFullLoad(CodecInfo& codec) {
    217     ALOGV("MediaResourceArbitrator::ArbitrateFullLoad");
    218     ALOGV("giving codec type :%d, isEncoder = %d, frameRate = %d",
    219            codec.codecType, codec.isEncoder, codec.frameRate);
    220     ArbitratorErrorType err = ArbitratorErrorNone;
    221     int livingInstanceNum = 0;
    222 
    223     if (codec.isEncoder == true) {
    224         livingInstanceNum = mLivingEncodersTable.livingEncoders.size();
    225     } else {
    226         livingInstanceNum = mLivingDecodersTable.livingDecoders.size();
    227     }
    228 
    229     ALOGV("current living codec number of %s is %d",
    230            codec.isEncoder ? "encoder" : "decoder", livingInstanceNum);
    231 
    232     // check if living instance number reaches the limitation
    233     int targetInstanceLimit = 5; // most optimistic
    234     uint i,j;
    235 
    236     if (codec.isEncoder == false) { // decoder
    237         for (i=0; i<mLivingDecodersTable.livingDecoders.size(); i++) {
    238             const CodecInfo& livingCodec = mLivingDecodersTable.livingDecoders[i];
    239             for (j=0; j<mDecoderLimitInfos.size(); j++) {
    240                 const CodecInfo& targetCodec = mDecoderLimitInfos[j].codecInfo;
    241                 ALOGV("%dth codec in DecoderLimitInfos.",j);
    242                 if (CheckCodecMatched(livingCodec, targetCodec) == true) {
    243                     if (targetInstanceLimit > mDecoderLimitInfos[j].instanceLimit) {
    244                         targetInstanceLimit = mDecoderLimitInfos[j].instanceLimit;
    245                         break;
    246                     }
    247                 }
    248             }
    249         }
    250         ALOGV("Go through decoder limit table and get current instance limit = %d",
    251               targetInstanceLimit);
    252         if (livingInstanceNum >= targetInstanceLimit) {
    253             ALOGV("setting full load flag to true.");
    254             mIsDecoderUnderFullLoad = true;
    255         } else {
    256             ALOGV("setting full load flag to false.");
    257             mIsDecoderUnderFullLoad = false;
    258         }
    259     } else { // encoder
    260         for(i=0; i<mLivingEncodersTable.livingEncoders.size(); i++) {
    261             const CodecInfo& livingCodec = mLivingEncodersTable.livingEncoders[i];
    262             for (j=0; j<mEncoderLimitInfos.size(); j++) {
    263                 const CodecInfo& targetCodec = mEncoderLimitInfos[j].codecInfo;
    264                 if (CheckCodecMatched(livingCodec, targetCodec) == true) {
    265                     if (targetInstanceLimit > mEncoderLimitInfos[j].instanceLimit) {
    266                         targetInstanceLimit = mEncoderLimitInfos[j].instanceLimit;
    267                         break;
    268                     }
    269                 }
    270             }
    271         }
    272         ALOGV("Go through encoder limit table and get current instance limit = %d",
    273               targetInstanceLimit);
    274         if (livingInstanceNum >= targetInstanceLimit) {
    275             ALOGV("setting full load flag to true.");
    276             mIsEncoderUnderFullLoad = true;
    277         } else {
    278             ALOGV("setting full load flag to false.");
    279             mIsEncoderUnderFullLoad = false;
    280         }
    281     }
    282 
    283     return err;
    284 }
    285 
    286 
    287 bool MediaResourceArbitrator::CheckCodecMatched(
    288                                   const CodecInfo& sourceCodec,
    289                                   const CodecInfo& targetCodec) {
    290     ALOGV("CheckCodecMatched");
    291     return ((sourceCodec.codecType == targetCodec.codecType) &&
    292             (sourceCodec.isSecured == targetCodec.isSecured) &&
    293             (sourceCodec.resolution == targetCodec.resolution) &&
    294             (sourceCodec.frameRate == targetCodec.frameRate));
    295 }
    296 
    297 
    298 void MediaResourceArbitrator::DumpCodecTypeFromVector(void) {
    299     unsigned int i;
    300     ALOGV("MediaResourceArbitrator::DumpCodecTypeFromVector");
    301     for (i=0; i<mCodecNameTypeMap.size(); i++) {
    302         ALOGV("codec type in vector %s : %d",
    303                mCodecNameTypeMap.keyAt(i), mCodecNameTypeMap.valueAt(i));
    304     }
    305 }
    306 
    307 
    308 CodecType MediaResourceArbitrator::MapCodecTypeFromName(const char* name) {
    309     if (strcmp(name, "CODEC_TYPE_AVC") == 0) {
    310         return CODEC_TYPE_AVC;
    311     } else if (strcmp(name, "CODEC_TYPE_HEVC") == 0) {
    312         return CODEC_TYPE_HEVC;
    313     } else if (strcmp(name, "CODEC_TYPE_VP8") == 0) {
    314         return CODEC_TYPE_VP8;
    315     } else if (strcmp(name, "CODEC_TYPE_VP9") == 0) {
    316         return CODEC_TYPE_VP9;
    317     } else if (strcmp(name, "CODEC_TYPE_MPEG2") == 0) {
    318         return CODEC_TYPE_MPEG2;
    319     } else if (strcmp(name, "CODEC_TYPE_MPEG4") == 0){
    320         return CODEC_TYPE_MPEG4;
    321     } else if (strcmp(name, "CODEC_TYPE_H263") == 0) {
    322         return CODEC_TYPE_H263;
    323     } else if (strcmp(name, "CODEC_TYPE_WMV") == 0) {
    324         return CODEC_TYPE_WMV;
    325     } else if (strcmp(name, "CODEC_TYPE_VC1") == 0) {
    326         return CODEC_TYPE_VC1;
    327     } else {
    328         ALOGE("unknown codec name: %s, try to return avc", name);
    329         return CODEC_TYPE_AVC;
    330     }
    331 }
    332 
    333 
    334 ResolutionType MediaResourceArbitrator::
    335                    MapResolutionTypeFromName(const char* name) {
    336     if (strcmp(name, "480") == 0) {
    337         return Resolution_480;
    338     } else if (strcmp(name, "720") == 0) {
    339         return Resolution_720;
    340     } else if (strcmp(name, "1080") == 0) {
    341         return Resolution_1080;
    342     } else if (strcmp(name, "2K") == 0) {
    343         return Resolution_2K;
    344     } else if (strcmp(name, "4K") == 0) {
    345         return Resolution_4K;
    346     } else {
    347         ALOGE("unkown resolution name: %s, try to return 1080", name);
    348         return Resolution_1080;
    349     }
    350 }
    351 
    352 
    353 void MediaResourceArbitrator::InitializeCodecNameTypeMap(void) {
    354     ALOGV("MediaResourceArbitrator::InitializeCodecNameTypeMap");
    355     mCodecNameTypeMap.add("CODEC_TYPE_AVC", CODEC_TYPE_AVC);
    356     mCodecNameTypeMap.add("CODEC_TYPE_HEVC", CODEC_TYPE_HEVC);
    357     mCodecNameTypeMap.add("CODEC_TYPE_VP8", CODEC_TYPE_VP8);
    358     mCodecNameTypeMap.add("CODEC_TYPE_VP9", CODEC_TYPE_VP9);
    359     mCodecNameTypeMap.add("CODEC_TYPE_MPEG4", CODEC_TYPE_MPEG4);
    360     mCodecNameTypeMap.add("CODEC_TYPE_MPEG2", CODEC_TYPE_MPEG2);
    361     mCodecNameTypeMap.add("CODEC_TYPE_H263", CODEC_TYPE_H263);
    362     mCodecNameTypeMap.add("CODEC_TYPE_VC1", CODEC_TYPE_VC1);
    363     mCodecNameTypeMap.add("CODEC_TYPE_WMV", CODEC_TYPE_WMV);
    364     //DumpCodecTypeFromVector();
    365 }
    366 
    367 
    368 void MediaResourceArbitrator::InitializeResolutionNameTypeMap(void) {
    369     ALOGV("MediaResourceArbitrator::InitializeResolutionNameTypeMap");
    370     mResolutionNameTypeMap.add("480", Resolution_480);
    371     mResolutionNameTypeMap.add("720", Resolution_720);
    372     mResolutionNameTypeMap.add("1080", Resolution_1080);
    373     mResolutionNameTypeMap.add("2K", Resolution_2K);
    374     mResolutionNameTypeMap.add("4K", Resolution_4K);
    375 }
    376 
    377 // Hard coded limitation
    378 void MediaResourceArbitrator::SetupDefaultCodecLimitation(void) {
    379     ALOGV("MediaResourceArbitrator::SetupDefaultCodecLimitation");
    380     uint i,j,k;
    381     CodecType codecType;
    382     ResolutionType resolutionType;
    383     uint frameRate;
    384 
    385     // non-secure decoders
    386     for (i=(int)CODEC_TYPE_AVC; i<(int)CODEC_TYPE_MAX; i++) {
    387             codecType = (CodecType)i;
    388         for (j=(int)Resolution_CIF; j<(int)Resolution_MAX; j++) {
    389             resolutionType = (ResolutionType)j;
    390             for (k=0; k<2; k++) {
    391                 frameRate = (k+1)*30;
    392                 bool isSecured = false;
    393                 CodecLimitInfo codecLimitInfo;
    394                 codecLimitInfo.codecInfo.codecType = codecType;
    395                 codecLimitInfo.codecInfo.resolution = resolutionType;
    396                 codecLimitInfo.codecInfo.isSecured = isSecured;
    397                 codecLimitInfo.codecInfo.isEncoder = false;
    398                 codecLimitInfo.codecInfo.frameRate = frameRate;
    399                 codecLimitInfo.instanceLimit = 2;
    400                 mDecoderLimitInfos.add(codecLimitInfo);
    401             }
    402         }
    403     }
    404 
    405     // secure avc decoder
    406     codecType = CODEC_TYPE_AVC;
    407     for (j=(int)Resolution_CIF; j<(int)Resolution_MAX; j++) {
    408         resolutionType = (ResolutionType)j;
    409         for (k=0; k<2; k++) {
    410             frameRate = (k+1)*30;
    411             bool isSecured = true;
    412             CodecLimitInfo codecLimitInfo;
    413             codecLimitInfo.codecInfo.codecType = codecType;
    414             codecLimitInfo.codecInfo.resolution = resolutionType;
    415             codecLimitInfo.codecInfo.isSecured = isSecured;
    416             codecLimitInfo.codecInfo.isEncoder = false;
    417             codecLimitInfo.instanceLimit = 2;
    418             mDecoderLimitInfos.add(codecLimitInfo);
    419         }
    420     }
    421 
    422     // Encoder limitation Map
    423     for (i=(int)CODEC_TYPE_AVC; i<(int)CODEC_TYPE_MAX; i++) {
    424             codecType = (CodecType)i;
    425         for (j=(int)Resolution_CIF; j<(int)Resolution_MAX; j++) {
    426             resolutionType = (ResolutionType)j;
    427             for (k=0; k<2; k++) {
    428                 frameRate = (k+1)*30;
    429                 bool isSecured = false;
    430                 CodecLimitInfo codecLimitInfo;
    431                 codecLimitInfo.codecInfo.codecType = codecType;
    432                 codecLimitInfo.codecInfo.resolution = resolutionType;
    433                 codecLimitInfo.codecInfo.isSecured = isSecured;
    434                 codecLimitInfo.codecInfo.isEncoder = true;
    435                 codecLimitInfo.instanceLimit = 2;
    436                 mEncoderLimitInfos.add(codecLimitInfo);
    437             }
    438         }
    439     }
    440 }
    441 
    442 
    443 void MediaResourceArbitrator::getConfigData(const char *name,
    444                                             const char **atts) {
    445     ALOGV("MediaResourceArbitrator::getConfigData");
    446     int attIndex = 0;
    447     if (strcmp(name, "CodecResourcesLimitation") == 0) {
    448         return;
    449     } else if (strcmp(name, "Codec") == 0) {
    450         if (strcmp(atts[attIndex], "name") == 0) {
    451             ALOGV("Parsing codec %s", atts[attIndex+1]);
    452             mIfParsingCodec = true;
    453         } else {
    454             ALOGE("Codec tag with no name, anything wrong?");
    455         }
    456     } else if (strcmp(name, "codecType") == 0) {
    457         ALOGV("parse tag codecType");
    458         if (mIfParsingCodec) {
    459             if (strcmp(atts[attIndex], "value") == 0) {
    460                 //DumpCodecTypeFromVector();
    461                 mParsingCodecLimitInfo.codecInfo.codecType =
    462                     MapCodecTypeFromName((const char*)atts[attIndex+1]);
    463             }
    464         } else {
    465             ALOGE("Skip this element(%s) becaue this codec couldn't be supported\n", name);
    466         }
    467     } else if (strcmp(name, "isEncoder") == 0) {
    468         ALOGV("parse tag isEncoder");
    469         if (mIfParsingCodec && !strcmp(atts[attIndex], "value")) {
    470             if (!strcmp(atts[attIndex + 1], "false"))
    471                 mParsingCodecLimitInfo.codecInfo.isEncoder = false;
    472             else {
    473                 mParsingCodecLimitInfo.codecInfo.isEncoder = true;
    474             }
    475         } else {
    476             ALOGE("Skip this element(%s) becaue this tag couldn't be supported\n", name);
    477         }
    478     } else if (strcmp(name, "isSecured") == 0) {
    479         ALOGV("parse tag isSecured");
    480         if (mIfParsingCodec && !strcmp(atts[attIndex], "value")) {
    481             if (!strcmp(atts[attIndex + 1], "false"))
    482                 mParsingCodecLimitInfo.codecInfo.isSecured = false;
    483             else {
    484                 mParsingCodecLimitInfo.codecInfo.isSecured = true;
    485             }
    486         } else {
    487             ALOGE("Skip this element(%s) becaue this tag couldn't be supported\n", name);
    488         }
    489     } else if (strcmp(name, "resolutionType") == 0) {
    490         ALOGV("parse tag resolutionType");
    491         if (mIfParsingCodec) {
    492             if (strcmp(atts[attIndex], "value") == 0) {
    493                 mParsingCodecLimitInfo.codecInfo.resolution =
    494                     MapResolutionTypeFromName((const char*)atts[attIndex+1]);
    495                     //mResolutionNameTypeMap.valueFor(atts[attIndex+1]);
    496             }
    497         } else {
    498             ALOGE("Skip this element(%s) becaue this codec couldn't be supported\n", name);
    499         }
    500     } else if (strcmp(name, "frameRate") == 0) {
    501         ALOGV("parse tag frameRate");
    502         if (mIfParsingCodec) {
    503             if (strcmp(atts[attIndex], "value") == 0) {
    504                 mParsingCodecLimitInfo.codecInfo.frameRate = atoi(atts[attIndex+1]);
    505             }
    506         } else {
    507             ALOGE("Skip this element(%s) becaue this codec couldn't be supported\n", name);
    508         }
    509     } else if (strcmp(name, "instanceLimit") == 0) {
    510         ALOGV("parse tag instanceLimit");
    511         if (mIfParsingCodec) {
    512             if (strcmp(atts[attIndex], "value") == 0) {
    513                 mParsingCodecLimitInfo.instanceLimit = atoi(atts[attIndex+1]);
    514             }
    515         } else {
    516             ALOGE("Skip this element(%s) becaue this codec couldn't be supported\n", name);
    517         }
    518     }
    519 }
    520 
    521 // Start tag
    522 void MediaResourceArbitrator::startElement(void *userData,
    523                                            const char *name,
    524                                            const char **atts) {
    525     MediaResourceArbitrator* arbitrator = (MediaResourceArbitrator*)userData;
    526     arbitrator->getConfigData(name, atts);
    527 }
    528 
    529 
    530 // End tag
    531 void MediaResourceArbitrator::endElement(void *userData, const char *name) {
    532     MediaResourceArbitrator* arbitrator = (MediaResourceArbitrator*)userData;
    533     if (strcmp(name, "Codec") == 0) {
    534         if (arbitrator->mParsingCodecLimitInfo.codecInfo.isEncoder == true) {
    535             arbitrator->mEncoderLimitInfos.push_back(arbitrator->mParsingCodecLimitInfo);
    536         } else {
    537             arbitrator->mDecoderLimitInfos.push_back(arbitrator->mParsingCodecLimitInfo);
    538         }
    539         arbitrator->mIfParsingCodec = false;
    540     }
    541 }
    542