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