1 /* 2 ** 3 ** Copyright 2010, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 19 //#define LOG_NDEBUG 0 20 #define LOG_TAG "MediaProfiles" 21 22 #include <stdlib.h> 23 #include <utils/Log.h> 24 #include <utils/Vector.h> 25 #include <cutils/properties.h> 26 #include <expat.h> 27 #include <media/MediaProfiles.h> 28 #include <media/stagefright/foundation/ADebug.h> 29 #include <OMX_Video.h> 30 #include <sys/stat.h> 31 32 namespace android { 33 34 constexpr char const * const MediaProfiles::xmlFiles[]; 35 Mutex MediaProfiles::sLock; 36 bool MediaProfiles::sIsInitialized = false; 37 MediaProfiles *MediaProfiles::sInstance = NULL; 38 39 const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = { 40 {"h263", VIDEO_ENCODER_H263}, 41 {"h264", VIDEO_ENCODER_H264}, 42 {"m4v", VIDEO_ENCODER_MPEG_4_SP}, 43 {"hevc", VIDEO_ENCODER_HEVC} 44 }; 45 46 const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = { 47 {"amrnb", AUDIO_ENCODER_AMR_NB}, 48 {"amrwb", AUDIO_ENCODER_AMR_WB}, 49 {"aac", AUDIO_ENCODER_AAC}, 50 {"heaac", AUDIO_ENCODER_HE_AAC}, 51 {"aaceld", AUDIO_ENCODER_AAC_ELD}, 52 {"opus", AUDIO_ENCODER_OPUS} 53 }; 54 55 const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = { 56 {"3gp", OUTPUT_FORMAT_THREE_GPP}, 57 {"mp4", OUTPUT_FORMAT_MPEG_4} 58 }; 59 60 const MediaProfiles::NameToTagMap MediaProfiles::sVideoDecoderNameMap[] = { 61 {"wmv", VIDEO_DECODER_WMV} 62 }; 63 64 const MediaProfiles::NameToTagMap MediaProfiles::sAudioDecoderNameMap[] = { 65 {"wma", AUDIO_DECODER_WMA} 66 }; 67 68 const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { 69 {"low", CAMCORDER_QUALITY_LOW}, 70 {"high", CAMCORDER_QUALITY_HIGH}, 71 {"qcif", CAMCORDER_QUALITY_QCIF}, 72 {"cif", CAMCORDER_QUALITY_CIF}, 73 {"480p", CAMCORDER_QUALITY_480P}, 74 {"720p", CAMCORDER_QUALITY_720P}, 75 {"1080p", CAMCORDER_QUALITY_1080P}, 76 {"2160p", CAMCORDER_QUALITY_2160P}, 77 {"qvga", CAMCORDER_QUALITY_QVGA}, 78 79 {"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW}, 80 {"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH}, 81 {"timelapseqcif", CAMCORDER_QUALITY_TIME_LAPSE_QCIF}, 82 {"timelapsecif", CAMCORDER_QUALITY_TIME_LAPSE_CIF}, 83 {"timelapse480p", CAMCORDER_QUALITY_TIME_LAPSE_480P}, 84 {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P}, 85 {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P}, 86 {"timelapse2160p", CAMCORDER_QUALITY_TIME_LAPSE_2160P}, 87 {"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA}, 88 89 {"highspeedlow", CAMCORDER_QUALITY_HIGH_SPEED_LOW}, 90 {"highspeedhigh", CAMCORDER_QUALITY_HIGH_SPEED_HIGH}, 91 {"highspeed480p", CAMCORDER_QUALITY_HIGH_SPEED_480P}, 92 {"highspeed720p", CAMCORDER_QUALITY_HIGH_SPEED_720P}, 93 {"highspeed1080p", CAMCORDER_QUALITY_HIGH_SPEED_1080P}, 94 {"highspeed2160p", CAMCORDER_QUALITY_HIGH_SPEED_2160P}, 95 96 // Vendor-specific profiles 97 {"vga", CAMCORDER_QUALITY_VGA}, 98 {"4kdci", CAMCORDER_QUALITY_4KDCI}, 99 {"timelapsevga", CAMCORDER_QUALITY_TIME_LAPSE_VGA}, 100 {"timelapse4kdci", CAMCORDER_QUALITY_TIME_LAPSE_4KDCI}, 101 {"highspeedcif", CAMCORDER_QUALITY_HIGH_SPEED_CIF}, 102 {"highspeedvga", CAMCORDER_QUALITY_HIGH_SPEED_VGA}, 103 {"highspeed4kdci", CAMCORDER_QUALITY_HIGH_SPEED_4KDCI}, 104 {"qhd", CAMCORDER_QUALITY_QHD}, 105 {"2k", CAMCORDER_QUALITY_2k}, 106 {"timelapseqhd", CAMCORDER_QUALITY_TIME_LAPSE_QHD}, 107 {"timelapse2k", CAMCORDER_QUALITY_TIME_LAPSE_2k}, 108 }; 109 110 #if LOG_NDEBUG 111 #define UNUSED __unused 112 #else 113 #define UNUSED 114 #endif 115 116 /*static*/ void 117 MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec UNUSED) 118 { 119 ALOGV("video codec:"); 120 ALOGV("codec = %d", codec.mCodec); 121 ALOGV("bit rate: %d", codec.mBitRate); 122 ALOGV("frame width: %d", codec.mFrameWidth); 123 ALOGV("frame height: %d", codec.mFrameHeight); 124 ALOGV("frame rate: %d", codec.mFrameRate); 125 } 126 127 /*static*/ void 128 MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec UNUSED) 129 { 130 ALOGV("audio codec:"); 131 ALOGV("codec = %d", codec.mCodec); 132 ALOGV("bit rate: %d", codec.mBitRate); 133 ALOGV("sample rate: %d", codec.mSampleRate); 134 ALOGV("number of channels: %d", codec.mChannels); 135 } 136 137 /*static*/ void 138 MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap UNUSED) 139 { 140 ALOGV("video encoder cap:"); 141 ALOGV("codec = %d", cap.mCodec); 142 ALOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate); 143 ALOGV("frame width: min = %d and max = %d", cap.mMinFrameWidth, cap.mMaxFrameWidth); 144 ALOGV("frame height: min = %d and max = %d", cap.mMinFrameHeight, cap.mMaxFrameHeight); 145 ALOGV("frame rate: min = %d and max = %d", cap.mMinFrameRate, cap.mMaxFrameRate); 146 } 147 148 /*static*/ void 149 MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap UNUSED) 150 { 151 ALOGV("audio encoder cap:"); 152 ALOGV("codec = %d", cap.mCodec); 153 ALOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate); 154 ALOGV("sample rate: min = %d and max = %d", cap.mMinSampleRate, cap.mMaxSampleRate); 155 ALOGV("number of channels: min = %d and max = %d", cap.mMinChannels, cap.mMaxChannels); 156 } 157 158 /*static*/ void 159 MediaProfiles::logVideoDecoderCap(const MediaProfiles::VideoDecoderCap& cap UNUSED) 160 { 161 ALOGV("video decoder cap:"); 162 ALOGV("codec = %d", cap.mCodec); 163 } 164 165 /*static*/ void 166 MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap UNUSED) 167 { 168 ALOGV("audio codec cap:"); 169 ALOGV("codec = %d", cap.mCodec); 170 } 171 172 /*static*/ int 173 MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, 174 const char *name) 175 { 176 int tag = -1; 177 for (size_t i = 0; i < nMappings; ++i) { 178 if (!strcmp(map[i].name, name)) { 179 tag = map[i].tag; 180 break; 181 } 182 } 183 return tag; 184 } 185 186 /*static*/ MediaProfiles::VideoCodec* 187 MediaProfiles::createVideoCodec(const char **atts, MediaProfiles *profiles) 188 { 189 CHECK(!strcmp("codec", atts[0]) && 190 !strcmp("bitRate", atts[2]) && 191 !strcmp("width", atts[4]) && 192 !strcmp("height", atts[6]) && 193 !strcmp("frameRate", atts[8])); 194 195 const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]); 196 const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]); 197 CHECK(codec != -1); 198 199 MediaProfiles::VideoCodec *videoCodec = 200 new MediaProfiles::VideoCodec(static_cast<video_encoder>(codec), 201 atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9])); 202 logVideoCodec(*videoCodec); 203 204 size_t nCamcorderProfiles; 205 CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1); 206 profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mVideoCodec = videoCodec; 207 return videoCodec; 208 } 209 210 /*static*/ MediaProfiles::AudioCodec* 211 MediaProfiles::createAudioCodec(const char **atts, MediaProfiles *profiles) 212 { 213 CHECK(!strcmp("codec", atts[0]) && 214 !strcmp("bitRate", atts[2]) && 215 !strcmp("sampleRate", atts[4]) && 216 !strcmp("channels", atts[6])); 217 const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]); 218 const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]); 219 CHECK(codec != -1); 220 221 MediaProfiles::AudioCodec *audioCodec = 222 new MediaProfiles::AudioCodec(static_cast<audio_encoder>(codec), 223 atoi(atts[3]), atoi(atts[5]), atoi(atts[7])); 224 logAudioCodec(*audioCodec); 225 226 size_t nCamcorderProfiles; 227 CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1); 228 profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mAudioCodec = audioCodec; 229 return audioCodec; 230 } 231 /*static*/ MediaProfiles::AudioDecoderCap* 232 MediaProfiles::createAudioDecoderCap(const char **atts) 233 { 234 CHECK(!strcmp("name", atts[0]) && 235 !strcmp("enabled", atts[2])); 236 237 const size_t nMappings = sizeof(sAudioDecoderNameMap)/sizeof(sAudioDecoderNameMap[0]); 238 const int codec = findTagForName(sAudioDecoderNameMap, nMappings, atts[1]); 239 CHECK(codec != -1); 240 241 MediaProfiles::AudioDecoderCap *cap = 242 new MediaProfiles::AudioDecoderCap(static_cast<audio_decoder>(codec)); 243 logAudioDecoderCap(*cap); 244 return cap; 245 } 246 247 /*static*/ MediaProfiles::VideoDecoderCap* 248 MediaProfiles::createVideoDecoderCap(const char **atts) 249 { 250 CHECK(!strcmp("name", atts[0]) && 251 !strcmp("enabled", atts[2])); 252 253 const size_t nMappings = sizeof(sVideoDecoderNameMap)/sizeof(sVideoDecoderNameMap[0]); 254 const int codec = findTagForName(sVideoDecoderNameMap, nMappings, atts[1]); 255 CHECK(codec != -1); 256 257 MediaProfiles::VideoDecoderCap *cap = 258 new MediaProfiles::VideoDecoderCap(static_cast<video_decoder>(codec)); 259 logVideoDecoderCap(*cap); 260 return cap; 261 } 262 263 /*static*/ MediaProfiles::VideoEncoderCap* 264 MediaProfiles::createVideoEncoderCap(const char **atts) 265 { 266 CHECK(!strcmp("name", atts[0]) && 267 !strcmp("enabled", atts[2]) && 268 !strcmp("minBitRate", atts[4]) && 269 !strcmp("maxBitRate", atts[6]) && 270 !strcmp("minFrameWidth", atts[8]) && 271 !strcmp("maxFrameWidth", atts[10]) && 272 !strcmp("minFrameHeight", atts[12]) && 273 !strcmp("maxFrameHeight", atts[14]) && 274 !strcmp("minFrameRate", atts[16]) && 275 !strcmp("maxFrameRate", atts[18])); 276 277 const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]); 278 const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]); 279 CHECK(codec != -1); 280 281 MediaProfiles::VideoEncoderCap *cap = 282 new MediaProfiles::VideoEncoderCap(static_cast<video_encoder>(codec), 283 atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]), 284 atoi(atts[15]), atoi(atts[17]), atoi(atts[19])); 285 logVideoEncoderCap(*cap); 286 return cap; 287 } 288 289 /*static*/ MediaProfiles::AudioEncoderCap* 290 MediaProfiles::createAudioEncoderCap(const char **atts) 291 { 292 CHECK(!strcmp("name", atts[0]) && 293 !strcmp("enabled", atts[2]) && 294 !strcmp("minBitRate", atts[4]) && 295 !strcmp("maxBitRate", atts[6]) && 296 !strcmp("minSampleRate", atts[8]) && 297 !strcmp("maxSampleRate", atts[10]) && 298 !strcmp("minChannels", atts[12]) && 299 !strcmp("maxChannels", atts[14])); 300 301 const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]); 302 const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]); 303 CHECK(codec != -1); 304 305 MediaProfiles::AudioEncoderCap *cap = 306 new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]), 307 atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]), atoi(atts[15])); 308 logAudioEncoderCap(*cap); 309 return cap; 310 } 311 312 /*static*/ output_format 313 MediaProfiles::createEncoderOutputFileFormat(const char **atts) 314 { 315 CHECK(!strcmp("name", atts[0])); 316 317 const size_t nMappings =sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]); 318 const int format = findTagForName(sFileFormatMap, nMappings, atts[1]); 319 CHECK(format != -1); 320 321 return static_cast<output_format>(format); 322 } 323 324 static bool isCameraIdFound(int cameraId, const Vector<int>& cameraIds) { 325 for (int i = 0, n = cameraIds.size(); i < n; ++i) { 326 if (cameraId == cameraIds[i]) { 327 return true; 328 } 329 } 330 return false; 331 } 332 333 /*static*/ MediaProfiles::CamcorderProfile* 334 MediaProfiles::createCamcorderProfile(int cameraId, const char **atts, Vector<int>& cameraIds) 335 { 336 CHECK(!strcmp("quality", atts[0]) && 337 !strcmp("fileFormat", atts[2]) && 338 !strcmp("duration", atts[4])); 339 340 const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/ 341 sizeof(sCamcorderQualityNameMap[0]); 342 const int quality = findTagForName(sCamcorderQualityNameMap, nProfileMappings, atts[1]); 343 CHECK(quality != -1); 344 345 const size_t nFormatMappings = sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]); 346 const int fileFormat = findTagForName(sFileFormatMap, nFormatMappings, atts[3]); 347 CHECK(fileFormat != -1); 348 349 MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 350 profile->mCameraId = cameraId; 351 if (!isCameraIdFound(cameraId, cameraIds)) { 352 cameraIds.add(cameraId); 353 } 354 profile->mFileFormat = static_cast<output_format>(fileFormat); 355 profile->mQuality = static_cast<camcorder_quality>(quality); 356 profile->mDuration = atoi(atts[5]); 357 return profile; 358 } 359 360 MediaProfiles::ImageEncodingQualityLevels* 361 MediaProfiles::findImageEncodingQualityLevels(int cameraId) const 362 { 363 int n = mImageEncodingQualityLevels.size(); 364 for (int i = 0; i < n; i++) { 365 ImageEncodingQualityLevels *levels = mImageEncodingQualityLevels[i]; 366 if (levels->mCameraId == cameraId) { 367 return levels; 368 } 369 } 370 return NULL; 371 } 372 373 void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts) 374 { 375 CHECK(!strcmp("quality", atts[0])); 376 int quality = atoi(atts[1]); 377 ALOGV("%s: cameraId=%d, quality=%d", __func__, cameraId, quality); 378 ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId); 379 380 if (levels == NULL) { 381 levels = new ImageEncodingQualityLevels(); 382 levels->mCameraId = cameraId; 383 mImageEncodingQualityLevels.add(levels); 384 } 385 386 levels->mLevels.add(quality); 387 } 388 389 /*static*/ int 390 MediaProfiles::getCameraId(const char** atts) 391 { 392 if (!atts[0]) return 0; // default cameraId = 0 393 CHECK(!strcmp("cameraId", atts[0])); 394 return atoi(atts[1]); 395 } 396 397 void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts) 398 { 399 int offsetTimeMs = 1000; 400 if (atts[2]) { 401 CHECK(!strcmp("startOffsetMs", atts[2])); 402 offsetTimeMs = atoi(atts[3]); 403 } 404 405 ALOGV("%s: cameraId=%d, offset=%d ms", __func__, cameraId, offsetTimeMs); 406 mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs); 407 } 408 409 /*static*/ void 410 MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts) 411 { 412 MediaProfiles *profiles = (MediaProfiles *) userData; 413 if (strcmp("Video", name) == 0) { 414 createVideoCodec(atts, profiles); 415 } else if (strcmp("Audio", name) == 0) { 416 createAudioCodec(atts, profiles); 417 } else if (strcmp("VideoEncoderCap", name) == 0 && 418 strcmp("true", atts[3]) == 0) { 419 profiles->mVideoEncoders.add(createVideoEncoderCap(atts)); 420 } else if (strcmp("AudioEncoderCap", name) == 0 && 421 strcmp("true", atts[3]) == 0) { 422 profiles->mAudioEncoders.add(createAudioEncoderCap(atts)); 423 } else if (strcmp("VideoDecoderCap", name) == 0 && 424 strcmp("true", atts[3]) == 0) { 425 profiles->mVideoDecoders.add(createVideoDecoderCap(atts)); 426 } else if (strcmp("AudioDecoderCap", name) == 0 && 427 strcmp("true", atts[3]) == 0) { 428 profiles->mAudioDecoders.add(createAudioDecoderCap(atts)); 429 } else if (strcmp("EncoderOutputFileFormat", name) == 0) { 430 profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts)); 431 } else if (strcmp("CamcorderProfiles", name) == 0) { 432 profiles->mCurrentCameraId = getCameraId(atts); 433 profiles->addStartTimeOffset(profiles->mCurrentCameraId, atts); 434 } else if (strcmp("EncoderProfile", name) == 0) { 435 profiles->mCamcorderProfiles.add( 436 createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds)); 437 } else if (strcmp("ImageEncoding", name) == 0) { 438 profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts); 439 } 440 } 441 442 static bool isCamcorderProfile(camcorder_quality quality) { 443 return quality >= CAMCORDER_QUALITY_LIST_START && 444 quality <= CAMCORDER_QUALITY_LIST_END; 445 } 446 447 static bool isTimelapseProfile(camcorder_quality quality) { 448 return quality >= CAMCORDER_QUALITY_TIME_LAPSE_LIST_START && 449 quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END; 450 } 451 452 static bool isHighSpeedProfile(camcorder_quality quality) { 453 return quality >= CAMCORDER_QUALITY_HIGH_SPEED_LIST_START && 454 quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END; 455 } 456 457 void MediaProfiles::initRequiredProfileRefs(const Vector<int>& cameraIds) { 458 ALOGV("Number of camera ids: %zu", cameraIds.size()); 459 CHECK(cameraIds.size() > 0); 460 mRequiredProfileRefs = new RequiredProfiles[cameraIds.size()]; 461 for (size_t i = 0, n = cameraIds.size(); i < n; ++i) { 462 mRequiredProfileRefs[i].mCameraId = cameraIds[i]; 463 for (size_t j = 0; j < kNumRequiredProfiles; ++j) { 464 mRequiredProfileRefs[i].mRefs[j].mHasRefProfile = false; 465 mRequiredProfileRefs[i].mRefs[j].mRefProfileIndex = -1; 466 if ((j & 1) == 0) { // low resolution 467 mRequiredProfileRefs[i].mRefs[j].mResolutionProduct = 0x7FFFFFFF; 468 } else { // high resolution 469 mRequiredProfileRefs[i].mRefs[j].mResolutionProduct = 0; 470 } 471 } 472 } 473 } 474 475 int MediaProfiles::getRequiredProfileRefIndex(int cameraId) { 476 for (size_t i = 0, n = mCameraIds.size(); i < n; ++i) { 477 if (mCameraIds[i] == cameraId) { 478 return i; 479 } 480 } 481 return -1; 482 } 483 484 void MediaProfiles::checkAndAddRequiredProfilesIfNecessary() { 485 if (sIsInitialized) { 486 return; 487 } 488 489 initRequiredProfileRefs(mCameraIds); 490 491 for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) { 492 int product = mCamcorderProfiles[i]->mVideoCodec->mFrameWidth * 493 mCamcorderProfiles[i]->mVideoCodec->mFrameHeight; 494 495 camcorder_quality quality = mCamcorderProfiles[i]->mQuality; 496 int cameraId = mCamcorderProfiles[i]->mCameraId; 497 int index = -1; 498 int refIndex = getRequiredProfileRefIndex(cameraId); 499 CHECK(refIndex != -1); 500 RequiredProfileRefInfo *info; 501 camcorder_quality refQuality; 502 503 // Check high and low from either camcorder profile, timelapse profile 504 // or high speed profile, but not all of them. Default, check camcorder profile 505 size_t j = 0; 506 size_t o = 2; 507 if (isTimelapseProfile(quality)) { 508 // Check timelapse profile instead. 509 j = 2; 510 o = kNumRequiredProfiles; 511 } else if (isHighSpeedProfile(quality)) { 512 // Skip the check for high speed profile. 513 continue; 514 } else { 515 // Must be camcorder profile. 516 CHECK(isCamcorderProfile(quality)); 517 } 518 for (; j < o; ++j) { 519 info = &(mRequiredProfileRefs[refIndex].mRefs[j]); 520 if ((j % 2 == 0 && product > info->mResolutionProduct) || // low 521 (j % 2 != 0 && product < info->mResolutionProduct)) { // high 522 continue; 523 } 524 switch (j) { 525 case 0: 526 refQuality = CAMCORDER_QUALITY_LOW; 527 break; 528 case 1: 529 refQuality = CAMCORDER_QUALITY_HIGH; 530 break; 531 case 2: 532 refQuality = CAMCORDER_QUALITY_TIME_LAPSE_LOW; 533 break; 534 case 3: 535 refQuality = CAMCORDER_QUALITY_TIME_LAPSE_HIGH; 536 break; 537 default: 538 CHECK(!"Should never reach here"); 539 } 540 541 if (!info->mHasRefProfile) { 542 index = getCamcorderProfileIndex(cameraId, refQuality); 543 } 544 if (index == -1) { 545 // New high or low quality profile is found. 546 // Update its reference. 547 info->mHasRefProfile = true; 548 info->mRefProfileIndex = i; 549 info->mResolutionProduct = product; 550 } 551 } 552 } 553 554 for (size_t cameraId = 0; cameraId < mCameraIds.size(); ++cameraId) { 555 for (size_t j = 0; j < kNumRequiredProfiles; ++j) { 556 int refIndex = getRequiredProfileRefIndex(cameraId); 557 CHECK(refIndex != -1); 558 RequiredProfileRefInfo *info = 559 &mRequiredProfileRefs[refIndex].mRefs[j]; 560 561 if (info->mHasRefProfile) { 562 563 std::unique_ptr<CamcorderProfile> profile = 564 std::make_unique<CamcorderProfile>( 565 *mCamcorderProfiles[info->mRefProfileIndex]); 566 567 // Overwrite the quality 568 switch (j % kNumRequiredProfiles) { 569 case 0: 570 profile->mQuality = CAMCORDER_QUALITY_LOW; 571 break; 572 case 1: 573 profile->mQuality = CAMCORDER_QUALITY_HIGH; 574 break; 575 case 2: 576 profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_LOW; 577 break; 578 case 3: 579 profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_HIGH; 580 break; 581 default: 582 CHECK(!"Should never come here"); 583 } 584 585 int index = getCamcorderProfileIndex(cameraId, profile->mQuality); 586 if (index != -1) { 587 ALOGV("Profile quality %d for camera %zu already exists", 588 profile->mQuality, cameraId); 589 CHECK(index == refIndex); 590 continue; 591 } 592 593 // Insert the new profile 594 ALOGV("Add a profile: quality %d=>%d for camera %zu", 595 mCamcorderProfiles[info->mRefProfileIndex]->mQuality, 596 profile->mQuality, cameraId); 597 598 mCamcorderProfiles.add(profile.release()); 599 } 600 } 601 } 602 } 603 604 /*static*/ MediaProfiles* 605 MediaProfiles::getInstance() 606 { 607 ALOGV("getInstance"); 608 Mutex::Autolock lock(sLock); 609 if (!sIsInitialized) { 610 char value[PROPERTY_VALUE_MAX]; 611 if (property_get("media.settings.xml", value, NULL) <= 0) { 612 const char* xmlFile = nullptr; 613 for (auto const& f : xmlFiles) { 614 if (checkXmlFile(f)) { 615 xmlFile = f; 616 break; 617 } 618 } 619 if (xmlFile == nullptr) { 620 ALOGW("Could not find a validated xml file. " 621 "Using the default instance instead."); 622 sInstance = createDefaultInstance(); 623 } else { 624 sInstance = createInstanceFromXmlFile(xmlFile); 625 } 626 } else { 627 sInstance = createInstanceFromXmlFile(value); 628 } 629 CHECK(sInstance != NULL); 630 sInstance->checkAndAddRequiredProfilesIfNecessary(); 631 sIsInitialized = true; 632 } 633 634 return sInstance; 635 } 636 637 /*static*/ MediaProfiles::VideoEncoderCap* 638 MediaProfiles::createDefaultH263VideoEncoderCap() 639 { 640 return new MediaProfiles::VideoEncoderCap( 641 VIDEO_ENCODER_H263, 192000, 420000, 176, 352, 144, 288, 1, 20); 642 } 643 644 /*static*/ MediaProfiles::VideoEncoderCap* 645 MediaProfiles::createDefaultM4vVideoEncoderCap() 646 { 647 return new MediaProfiles::VideoEncoderCap( 648 VIDEO_ENCODER_MPEG_4_SP, 192000, 420000, 176, 352, 144, 288, 1, 20); 649 } 650 651 652 /*static*/ void 653 MediaProfiles::createDefaultVideoEncoders(MediaProfiles *profiles) 654 { 655 profiles->mVideoEncoders.add(createDefaultH263VideoEncoderCap()); 656 profiles->mVideoEncoders.add(createDefaultM4vVideoEncoderCap()); 657 } 658 659 /*static*/ MediaProfiles::CamcorderProfile* 660 MediaProfiles::createDefaultCamcorderTimeLapseQcifProfile(camcorder_quality quality) 661 { 662 MediaProfiles::VideoCodec *videoCodec = 663 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 1000000, 176, 144, 20); 664 665 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); 666 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 667 profile->mCameraId = 0; 668 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; 669 profile->mQuality = quality; 670 profile->mDuration = 60; 671 profile->mVideoCodec = videoCodec; 672 profile->mAudioCodec = audioCodec; 673 return profile; 674 } 675 676 /*static*/ MediaProfiles::CamcorderProfile* 677 MediaProfiles::createDefaultCamcorderTimeLapse480pProfile(camcorder_quality quality) 678 { 679 MediaProfiles::VideoCodec *videoCodec = 680 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 20000000, 720, 480, 20); 681 682 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); 683 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 684 profile->mCameraId = 0; 685 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; 686 profile->mQuality = quality; 687 profile->mDuration = 60; 688 profile->mVideoCodec = videoCodec; 689 profile->mAudioCodec = audioCodec; 690 return profile; 691 } 692 693 /*static*/ void 694 MediaProfiles::createDefaultCamcorderTimeLapseLowProfiles( 695 MediaProfiles::CamcorderProfile **lowTimeLapseProfile, 696 MediaProfiles::CamcorderProfile **lowSpecificTimeLapseProfile) { 697 *lowTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile( 698 CAMCORDER_QUALITY_TIME_LAPSE_LOW); 699 *lowSpecificTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile( 700 CAMCORDER_QUALITY_TIME_LAPSE_QCIF); 701 } 702 703 /*static*/ void 704 MediaProfiles::createDefaultCamcorderTimeLapseHighProfiles( 705 MediaProfiles::CamcorderProfile **highTimeLapseProfile, 706 MediaProfiles::CamcorderProfile **highSpecificTimeLapseProfile) { 707 *highTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile( 708 CAMCORDER_QUALITY_TIME_LAPSE_HIGH); 709 *highSpecificTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile( 710 CAMCORDER_QUALITY_TIME_LAPSE_480P); 711 } 712 713 /*static*/ MediaProfiles::CamcorderProfile* 714 MediaProfiles::createDefaultCamcorderQcifProfile(camcorder_quality quality) 715 { 716 MediaProfiles::VideoCodec *videoCodec = 717 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 192000, 176, 144, 20); 718 719 MediaProfiles::AudioCodec *audioCodec = 720 new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); 721 722 MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 723 profile->mCameraId = 0; 724 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; 725 profile->mQuality = quality; 726 profile->mDuration = 30; 727 profile->mVideoCodec = videoCodec; 728 profile->mAudioCodec = audioCodec; 729 return profile; 730 } 731 732 /*static*/ MediaProfiles::CamcorderProfile* 733 MediaProfiles::createDefaultCamcorderCifProfile(camcorder_quality quality) 734 { 735 MediaProfiles::VideoCodec *videoCodec = 736 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20); 737 738 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); 739 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 740 profile->mCameraId = 0; 741 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; 742 profile->mQuality = quality; 743 profile->mDuration = 60; 744 profile->mVideoCodec = videoCodec; 745 profile->mAudioCodec = audioCodec; 746 return profile; 747 } 748 749 /*static*/ void 750 MediaProfiles::createDefaultCamcorderLowProfiles( 751 MediaProfiles::CamcorderProfile **lowProfile, 752 MediaProfiles::CamcorderProfile **lowSpecificProfile) { 753 *lowProfile = createDefaultCamcorderQcifProfile(CAMCORDER_QUALITY_LOW); 754 *lowSpecificProfile = createDefaultCamcorderQcifProfile(CAMCORDER_QUALITY_QCIF); 755 } 756 757 /*static*/ void 758 MediaProfiles::createDefaultCamcorderHighProfiles( 759 MediaProfiles::CamcorderProfile **highProfile, 760 MediaProfiles::CamcorderProfile **highSpecificProfile) { 761 *highProfile = createDefaultCamcorderCifProfile(CAMCORDER_QUALITY_HIGH); 762 *highSpecificProfile = createDefaultCamcorderCifProfile(CAMCORDER_QUALITY_CIF); 763 } 764 765 /*static*/ void 766 MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles) 767 { 768 // low camcorder profiles. 769 MediaProfiles::CamcorderProfile *lowProfile, *lowSpecificProfile; 770 createDefaultCamcorderLowProfiles(&lowProfile, &lowSpecificProfile); 771 profiles->mCamcorderProfiles.add(lowProfile); 772 profiles->mCamcorderProfiles.add(lowSpecificProfile); 773 774 // high camcorder profiles. 775 MediaProfiles::CamcorderProfile* highProfile, *highSpecificProfile; 776 createDefaultCamcorderHighProfiles(&highProfile, &highSpecificProfile); 777 profiles->mCamcorderProfiles.add(highProfile); 778 profiles->mCamcorderProfiles.add(highSpecificProfile); 779 780 // low camcorder time lapse profiles. 781 MediaProfiles::CamcorderProfile *lowTimeLapseProfile, *lowSpecificTimeLapseProfile; 782 createDefaultCamcorderTimeLapseLowProfiles(&lowTimeLapseProfile, &lowSpecificTimeLapseProfile); 783 profiles->mCamcorderProfiles.add(lowTimeLapseProfile); 784 profiles->mCamcorderProfiles.add(lowSpecificTimeLapseProfile); 785 786 // high camcorder time lapse profiles. 787 MediaProfiles::CamcorderProfile *highTimeLapseProfile, *highSpecificTimeLapseProfile; 788 createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile, 789 &highSpecificTimeLapseProfile); 790 profiles->mCamcorderProfiles.add(highTimeLapseProfile); 791 profiles->mCamcorderProfiles.add(highSpecificTimeLapseProfile); 792 793 // For emulator and other legacy devices which does not have a 794 // media_profiles.xml file, We assume that the default camera id 795 // is 0 and that is the only camera available. 796 profiles->mCameraIds.push(0); 797 } 798 799 /*static*/ void 800 MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles) 801 { 802 profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap()); 803 } 804 805 /*static*/ void 806 MediaProfiles::createDefaultVideoDecoders(MediaProfiles *profiles) 807 { 808 MediaProfiles::VideoDecoderCap *cap = 809 new MediaProfiles::VideoDecoderCap(VIDEO_DECODER_WMV); 810 811 profiles->mVideoDecoders.add(cap); 812 } 813 814 /*static*/ void 815 MediaProfiles::createDefaultAudioDecoders(MediaProfiles *profiles) 816 { 817 MediaProfiles::AudioDecoderCap *cap = 818 new MediaProfiles::AudioDecoderCap(AUDIO_DECODER_WMA); 819 820 profiles->mAudioDecoders.add(cap); 821 } 822 823 /*static*/ void 824 MediaProfiles::createDefaultEncoderOutputFileFormats(MediaProfiles *profiles) 825 { 826 profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_THREE_GPP); 827 profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_MPEG_4); 828 } 829 830 /*static*/ MediaProfiles::AudioEncoderCap* 831 MediaProfiles::createDefaultAmrNBEncoderCap() 832 { 833 return new MediaProfiles::AudioEncoderCap( 834 AUDIO_ENCODER_AMR_NB, 5525, 12200, 8000, 8000, 1, 1); 835 } 836 837 /*static*/ void 838 MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles) 839 { 840 ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels(); 841 levels->mCameraId = 0; 842 levels->mLevels.add(70); 843 levels->mLevels.add(80); 844 levels->mLevels.add(90); 845 profiles->mImageEncodingQualityLevels.add(levels); 846 } 847 848 /*static*/ MediaProfiles* 849 MediaProfiles::createDefaultInstance() 850 { 851 MediaProfiles *profiles = new MediaProfiles; 852 createDefaultCamcorderProfiles(profiles); 853 createDefaultVideoEncoders(profiles); 854 createDefaultAudioEncoders(profiles); 855 createDefaultVideoDecoders(profiles); 856 createDefaultAudioDecoders(profiles); 857 createDefaultEncoderOutputFileFormats(profiles); 858 createDefaultImageEncodingQualityLevels(profiles); 859 return profiles; 860 } 861 862 bool MediaProfiles::checkXmlFile(const char* xmlFile) { 863 struct stat fStat; 864 return stat(xmlFile, &fStat) == 0 && S_ISREG(fStat.st_mode); 865 // TODO: Add validation 866 } 867 868 /*static*/ MediaProfiles* 869 MediaProfiles::createInstanceFromXmlFile(const char *xml) 870 { 871 FILE *fp = NULL; 872 CHECK((fp = fopen(xml, "r"))); 873 874 XML_Parser parser = ::XML_ParserCreate(NULL); 875 CHECK(parser != NULL); 876 877 MediaProfiles *profiles = new MediaProfiles(); 878 ::XML_SetUserData(parser, profiles); 879 ::XML_SetElementHandler(parser, startElementHandler, NULL); 880 881 /* 882 FIXME: 883 expat is not compiled with -DXML_DTD. We don't have DTD parsing support. 884 885 if (!::XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS)) { 886 ALOGE("failed to enable DTD support in the xml file"); 887 return UNKNOWN_ERROR; 888 } 889 890 */ 891 892 const int BUFF_SIZE = 512; 893 for (;;) { 894 void *buff = ::XML_GetBuffer(parser, BUFF_SIZE); 895 if (buff == NULL) { 896 ALOGE("failed to in call to XML_GetBuffer()"); 897 delete profiles; 898 profiles = NULL; 899 goto exit; 900 } 901 902 int bytes_read = ::fread(buff, 1, BUFF_SIZE, fp); 903 if (bytes_read < 0) { 904 ALOGE("failed in call to read"); 905 delete profiles; 906 profiles = NULL; 907 goto exit; 908 } 909 910 CHECK(::XML_ParseBuffer(parser, bytes_read, bytes_read == 0)); 911 912 if (bytes_read == 0) break; // done parsing the xml file 913 } 914 915 exit: 916 ::XML_ParserFree(parser); 917 ::fclose(fp); 918 return profiles; 919 } 920 921 Vector<output_format> MediaProfiles::getOutputFileFormats() const 922 { 923 return mEncoderOutputFileFormats; // copy out 924 } 925 926 Vector<video_encoder> MediaProfiles::getVideoEncoders() const 927 { 928 Vector<video_encoder> encoders; 929 for (size_t i = 0; i < mVideoEncoders.size(); ++i) { 930 encoders.add(mVideoEncoders[i]->mCodec); 931 } 932 return encoders; // copy out 933 } 934 935 int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder codec) const 936 { 937 ALOGV("getVideoEncoderParamByName: %s for codec %d", name, codec); 938 int index = -1; 939 for (size_t i = 0, n = mVideoEncoders.size(); i < n; ++i) { 940 if (mVideoEncoders[i]->mCodec == codec) { 941 index = i; 942 break; 943 } 944 } 945 if (index == -1) { 946 ALOGE("The given video encoder %d is not found", codec); 947 return -1; 948 } 949 950 if (!strcmp("enc.vid.width.min", name)) return mVideoEncoders[index]->mMinFrameWidth; 951 if (!strcmp("enc.vid.width.max", name)) return mVideoEncoders[index]->mMaxFrameWidth; 952 if (!strcmp("enc.vid.height.min", name)) return mVideoEncoders[index]->mMinFrameHeight; 953 if (!strcmp("enc.vid.height.max", name)) return mVideoEncoders[index]->mMaxFrameHeight; 954 if (!strcmp("enc.vid.bps.min", name)) return mVideoEncoders[index]->mMinBitRate; 955 if (!strcmp("enc.vid.bps.max", name)) return mVideoEncoders[index]->mMaxBitRate; 956 if (!strcmp("enc.vid.fps.min", name)) return mVideoEncoders[index]->mMinFrameRate; 957 if (!strcmp("enc.vid.fps.max", name)) return mVideoEncoders[index]->mMaxFrameRate; 958 959 ALOGE("The given video encoder param name %s is not found", name); 960 return -1; 961 } 962 963 Vector<audio_encoder> MediaProfiles::getAudioEncoders() const 964 { 965 Vector<audio_encoder> encoders; 966 for (size_t i = 0; i < mAudioEncoders.size(); ++i) { 967 encoders.add(mAudioEncoders[i]->mCodec); 968 } 969 return encoders; // copy out 970 } 971 972 int MediaProfiles::getAudioEncoderParamByName(const char *name, audio_encoder codec) const 973 { 974 ALOGV("getAudioEncoderParamByName: %s for codec %d", name, codec); 975 int index = -1; 976 for (size_t i = 0, n = mAudioEncoders.size(); i < n; ++i) { 977 if (mAudioEncoders[i]->mCodec == codec) { 978 index = i; 979 break; 980 } 981 } 982 if (index == -1) { 983 ALOGE("The given audio encoder %d is not found", codec); 984 return -1; 985 } 986 987 if (!strcmp("enc.aud.ch.min", name)) return mAudioEncoders[index]->mMinChannels; 988 if (!strcmp("enc.aud.ch.max", name)) return mAudioEncoders[index]->mMaxChannels; 989 if (!strcmp("enc.aud.bps.min", name)) return mAudioEncoders[index]->mMinBitRate; 990 if (!strcmp("enc.aud.bps.max", name)) return mAudioEncoders[index]->mMaxBitRate; 991 if (!strcmp("enc.aud.hz.min", name)) return mAudioEncoders[index]->mMinSampleRate; 992 if (!strcmp("enc.aud.hz.max", name)) return mAudioEncoders[index]->mMaxSampleRate; 993 994 ALOGE("The given audio encoder param name %s is not found", name); 995 return -1; 996 } 997 998 Vector<video_decoder> MediaProfiles::getVideoDecoders() const 999 { 1000 Vector<video_decoder> decoders; 1001 for (size_t i = 0; i < mVideoDecoders.size(); ++i) { 1002 decoders.add(mVideoDecoders[i]->mCodec); 1003 } 1004 return decoders; // copy out 1005 } 1006 1007 Vector<audio_decoder> MediaProfiles::getAudioDecoders() const 1008 { 1009 Vector<audio_decoder> decoders; 1010 for (size_t i = 0; i < mAudioDecoders.size(); ++i) { 1011 decoders.add(mAudioDecoders[i]->mCodec); 1012 } 1013 return decoders; // copy out 1014 } 1015 1016 int MediaProfiles::getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const 1017 { 1018 int index = -1; 1019 for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) { 1020 if (mCamcorderProfiles[i]->mCameraId == cameraId && 1021 mCamcorderProfiles[i]->mQuality == quality) { 1022 index = i; 1023 break; 1024 } 1025 } 1026 return index; 1027 } 1028 1029 int MediaProfiles::getCamcorderProfileParamByName(const char *name, 1030 int cameraId, 1031 camcorder_quality quality) const 1032 { 1033 ALOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d", 1034 name, cameraId, quality); 1035 1036 int index = getCamcorderProfileIndex(cameraId, quality); 1037 if (index == -1) { 1038 ALOGE("The given camcorder profile camera %d quality %d is not found", 1039 cameraId, quality); 1040 return -1; 1041 } 1042 1043 if (!strcmp("duration", name)) return mCamcorderProfiles[index]->mDuration; 1044 if (!strcmp("file.format", name)) return mCamcorderProfiles[index]->mFileFormat; 1045 if (!strcmp("vid.codec", name)) return mCamcorderProfiles[index]->mVideoCodec->mCodec; 1046 if (!strcmp("vid.width", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameWidth; 1047 if (!strcmp("vid.height", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameHeight; 1048 if (!strcmp("vid.bps", name)) return mCamcorderProfiles[index]->mVideoCodec->mBitRate; 1049 if (!strcmp("vid.fps", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameRate; 1050 if (!strcmp("aud.codec", name)) return mCamcorderProfiles[index]->mAudioCodec->mCodec; 1051 if (!strcmp("aud.bps", name)) return mCamcorderProfiles[index]->mAudioCodec->mBitRate; 1052 if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels; 1053 if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate; 1054 1055 ALOGE("The given camcorder profile param id %d name %s is not found", cameraId, name); 1056 return -1; 1057 } 1058 1059 bool MediaProfiles::hasCamcorderProfile(int cameraId, camcorder_quality quality) const 1060 { 1061 return (getCamcorderProfileIndex(cameraId, quality) != -1); 1062 } 1063 1064 Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const 1065 { 1066 Vector<int> result; 1067 ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId); 1068 if (levels != NULL) { 1069 result = levels->mLevels; // copy out 1070 } 1071 return result; 1072 } 1073 1074 int MediaProfiles::getStartTimeOffsetMs(int cameraId) const { 1075 int offsetTimeMs = -1; 1076 ssize_t index = mStartTimeOffsets.indexOfKey(cameraId); 1077 if (index >= 0) { 1078 offsetTimeMs = mStartTimeOffsets.valueFor(cameraId); 1079 } 1080 ALOGV("offsetTime=%d ms and cameraId=%d", offsetTimeMs, cameraId); 1081 return offsetTimeMs; 1082 } 1083 1084 MediaProfiles::~MediaProfiles() 1085 { 1086 CHECK("destructor should never be called" == 0); 1087 #if 0 1088 for (size_t i = 0; i < mAudioEncoders.size(); ++i) { 1089 delete mAudioEncoders[i]; 1090 } 1091 mAudioEncoders.clear(); 1092 1093 for (size_t i = 0; i < mVideoEncoders.size(); ++i) { 1094 delete mVideoEncoders[i]; 1095 } 1096 mVideoEncoders.clear(); 1097 1098 for (size_t i = 0; i < mVideoDecoders.size(); ++i) { 1099 delete mVideoDecoders[i]; 1100 } 1101 mVideoDecoders.clear(); 1102 1103 for (size_t i = 0; i < mAudioDecoders.size(); ++i) { 1104 delete mAudioDecoders[i]; 1105 } 1106 mAudioDecoders.clear(); 1107 1108 for (size_t i = 0; i < mCamcorderProfiles.size(); ++i) { 1109 delete mCamcorderProfiles[i]; 1110 } 1111 mCamcorderProfiles.clear(); 1112 #endif 1113 } 1114 } // namespace android 1115