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