MediaProfiles.cpp revision 8bb5603cc735315c8691dc9b7a81b4ad4d6e253e
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/MediaDebug.h> 29 30namespace android { 31 32Mutex MediaProfiles::sLock; 33bool MediaProfiles::sIsInitialized = false; 34MediaProfiles *MediaProfiles::sInstance = NULL; 35 36const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = { 37 {"h263", VIDEO_ENCODER_H263}, 38 {"h264", VIDEO_ENCODER_H264}, 39 {"m4v", VIDEO_ENCODER_MPEG_4_SP} 40}; 41 42const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = { 43 {"amrnb", AUDIO_ENCODER_AMR_NB}, 44 {"amrwb", AUDIO_ENCODER_AMR_WB}, 45 {"aac", AUDIO_ENCODER_AAC}, 46}; 47 48const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = { 49 {"3gp", OUTPUT_FORMAT_THREE_GPP}, 50 {"mp4", OUTPUT_FORMAT_MPEG_4} 51}; 52 53const MediaProfiles::NameToTagMap MediaProfiles::sVideoDecoderNameMap[] = { 54 {"wmv", VIDEO_DECODER_WMV} 55}; 56 57const MediaProfiles::NameToTagMap MediaProfiles::sAudioDecoderNameMap[] = { 58 {"wma", AUDIO_DECODER_WMA} 59}; 60 61const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { 62 {"low", CAMCORDER_QUALITY_LOW}, 63 {"high", CAMCORDER_QUALITY_HIGH}, 64 {"qcif", CAMCORDER_QUALITY_QCIF}, 65 {"480p", CAMCORDER_QUALITY_480P}, 66 {"720p", CAMCORDER_QUALITY_720P}, 67 {"1080p", CAMCORDER_QUALITY_1080P}, 68 69 {"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW}, 70 {"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH}, 71 {"timelapseqcif", CAMCORDER_QUALITY_TIME_LAPSE_QCIF}, 72 {"timelapse480p", CAMCORDER_QUALITY_TIME_LAPSE_480P}, 73 {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P}, 74 {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P} 75}; 76 77/*static*/ void 78MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec) 79{ 80 LOGV("video codec:"); 81 LOGV("codec = %d", codec.mCodec); 82 LOGV("bit rate: %d", codec.mBitRate); 83 LOGV("frame width: %d", codec.mFrameWidth); 84 LOGV("frame height: %d", codec.mFrameHeight); 85 LOGV("frame rate: %d", codec.mFrameRate); 86} 87 88/*static*/ void 89MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec) 90{ 91 LOGV("audio codec:"); 92 LOGV("codec = %d", codec.mCodec); 93 LOGV("bit rate: %d", codec.mBitRate); 94 LOGV("sample rate: %d", codec.mSampleRate); 95 LOGV("number of channels: %d", codec.mChannels); 96} 97 98/*static*/ void 99MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap) 100{ 101 LOGV("video encoder cap:"); 102 LOGV("codec = %d", cap.mCodec); 103 LOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate); 104 LOGV("frame width: min = %d and max = %d", cap.mMinFrameWidth, cap.mMaxFrameWidth); 105 LOGV("frame height: min = %d and max = %d", cap.mMinFrameHeight, cap.mMaxFrameHeight); 106 LOGV("frame rate: min = %d and max = %d", cap.mMinFrameRate, cap.mMaxFrameRate); 107} 108 109/*static*/ void 110MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap) 111{ 112 LOGV("audio encoder cap:"); 113 LOGV("codec = %d", cap.mCodec); 114 LOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate); 115 LOGV("sample rate: min = %d and max = %d", cap.mMinSampleRate, cap.mMaxSampleRate); 116 LOGV("number of channels: min = %d and max = %d", cap.mMinChannels, cap.mMaxChannels); 117} 118 119/*static*/ void 120MediaProfiles::logVideoDecoderCap(const MediaProfiles::VideoDecoderCap& cap) 121{ 122 LOGV("video decoder cap:"); 123 LOGV("codec = %d", cap.mCodec); 124} 125 126/*static*/ void 127MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap) 128{ 129 LOGV("audio codec cap:"); 130 LOGV("codec = %d", cap.mCodec); 131} 132 133/*static*/ int 134MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name) 135{ 136 int tag = -1; 137 for (size_t i = 0; i < nMappings; ++i) { 138 if (!strcmp(map[i].name, name)) { 139 tag = map[i].tag; 140 break; 141 } 142 } 143 return tag; 144} 145 146/*static*/ MediaProfiles::VideoCodec* 147MediaProfiles::createVideoCodec(const char **atts, MediaProfiles *profiles) 148{ 149 CHECK(!strcmp("codec", atts[0]) && 150 !strcmp("bitRate", atts[2]) && 151 !strcmp("width", atts[4]) && 152 !strcmp("height", atts[6]) && 153 !strcmp("frameRate", atts[8])); 154 155 const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]); 156 const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]); 157 CHECK(codec != -1); 158 159 MediaProfiles::VideoCodec *videoCodec = 160 new MediaProfiles::VideoCodec(static_cast<video_encoder>(codec), 161 atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9])); 162 logVideoCodec(*videoCodec); 163 164 size_t nCamcorderProfiles; 165 CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1); 166 profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mVideoCodec = videoCodec; 167 return videoCodec; 168} 169 170/*static*/ MediaProfiles::AudioCodec* 171MediaProfiles::createAudioCodec(const char **atts, MediaProfiles *profiles) 172{ 173 CHECK(!strcmp("codec", atts[0]) && 174 !strcmp("bitRate", atts[2]) && 175 !strcmp("sampleRate", atts[4]) && 176 !strcmp("channels", atts[6])); 177 const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]); 178 const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]); 179 CHECK(codec != -1); 180 181 MediaProfiles::AudioCodec *audioCodec = 182 new MediaProfiles::AudioCodec(static_cast<audio_encoder>(codec), 183 atoi(atts[3]), atoi(atts[5]), atoi(atts[7])); 184 logAudioCodec(*audioCodec); 185 186 size_t nCamcorderProfiles; 187 CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1); 188 profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mAudioCodec = audioCodec; 189 return audioCodec; 190} 191/*static*/ MediaProfiles::AudioDecoderCap* 192MediaProfiles::createAudioDecoderCap(const char **atts) 193{ 194 CHECK(!strcmp("name", atts[0]) && 195 !strcmp("enabled", atts[2])); 196 197 const size_t nMappings = sizeof(sAudioDecoderNameMap)/sizeof(sAudioDecoderNameMap[0]); 198 const int codec = findTagForName(sAudioDecoderNameMap, nMappings, atts[1]); 199 CHECK(codec != -1); 200 201 MediaProfiles::AudioDecoderCap *cap = 202 new MediaProfiles::AudioDecoderCap(static_cast<audio_decoder>(codec)); 203 logAudioDecoderCap(*cap); 204 return cap; 205} 206 207/*static*/ MediaProfiles::VideoDecoderCap* 208MediaProfiles::createVideoDecoderCap(const char **atts) 209{ 210 CHECK(!strcmp("name", atts[0]) && 211 !strcmp("enabled", atts[2])); 212 213 const size_t nMappings = sizeof(sVideoDecoderNameMap)/sizeof(sVideoDecoderNameMap[0]); 214 const int codec = findTagForName(sVideoDecoderNameMap, nMappings, atts[1]); 215 CHECK(codec != -1); 216 217 MediaProfiles::VideoDecoderCap *cap = 218 new MediaProfiles::VideoDecoderCap(static_cast<video_decoder>(codec)); 219 logVideoDecoderCap(*cap); 220 return cap; 221} 222 223/*static*/ MediaProfiles::VideoEncoderCap* 224MediaProfiles::createVideoEncoderCap(const char **atts) 225{ 226 CHECK(!strcmp("name", atts[0]) && 227 !strcmp("enabled", atts[2]) && 228 !strcmp("minBitRate", atts[4]) && 229 !strcmp("maxBitRate", atts[6]) && 230 !strcmp("minFrameWidth", atts[8]) && 231 !strcmp("maxFrameWidth", atts[10]) && 232 !strcmp("minFrameHeight", atts[12]) && 233 !strcmp("maxFrameHeight", atts[14]) && 234 !strcmp("minFrameRate", atts[16]) && 235 !strcmp("maxFrameRate", atts[18])); 236 237 const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]); 238 const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]); 239 CHECK(codec != -1); 240 241 MediaProfiles::VideoEncoderCap *cap = 242 new MediaProfiles::VideoEncoderCap(static_cast<video_encoder>(codec), 243 atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]), 244 atoi(atts[15]), atoi(atts[17]), atoi(atts[19])); 245 logVideoEncoderCap(*cap); 246 return cap; 247} 248 249/*static*/ MediaProfiles::AudioEncoderCap* 250MediaProfiles::createAudioEncoderCap(const char **atts) 251{ 252 CHECK(!strcmp("name", atts[0]) && 253 !strcmp("enabled", atts[2]) && 254 !strcmp("minBitRate", atts[4]) && 255 !strcmp("maxBitRate", atts[6]) && 256 !strcmp("minSampleRate", atts[8]) && 257 !strcmp("maxSampleRate", atts[10]) && 258 !strcmp("minChannels", atts[12]) && 259 !strcmp("maxChannels", atts[14])); 260 261 const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]); 262 const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]); 263 CHECK(codec != -1); 264 265 MediaProfiles::AudioEncoderCap *cap = 266 new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]), atoi(atts[7]), 267 atoi(atts[9]), atoi(atts[11]), atoi(atts[13]), 268 atoi(atts[15])); 269 logAudioEncoderCap(*cap); 270 return cap; 271} 272 273/*static*/ output_format 274MediaProfiles::createEncoderOutputFileFormat(const char **atts) 275{ 276 CHECK(!strcmp("name", atts[0])); 277 278 const size_t nMappings =sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]); 279 const int format = findTagForName(sFileFormatMap, nMappings, atts[1]); 280 CHECK(format != -1); 281 282 return static_cast<output_format>(format); 283} 284 285/*static*/ MediaProfiles::CamcorderProfile* 286MediaProfiles::createCamcorderProfile(int cameraId, const char **atts) 287{ 288 CHECK(!strcmp("quality", atts[0]) && 289 !strcmp("fileFormat", atts[2]) && 290 !strcmp("duration", atts[4])); 291 292 const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/sizeof(sCamcorderQualityNameMap[0]); 293 const int quality = findTagForName(sCamcorderQualityNameMap, nProfileMappings, atts[1]); 294 CHECK(quality != -1); 295 296 const size_t nFormatMappings = sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]); 297 const int fileFormat = findTagForName(sFileFormatMap, nFormatMappings, atts[3]); 298 CHECK(fileFormat != -1); 299 300 MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 301 profile->mCameraId = cameraId; 302 profile->mFileFormat = static_cast<output_format>(fileFormat); 303 profile->mQuality = static_cast<camcorder_quality>(quality); 304 profile->mDuration = atoi(atts[5]); 305 return profile; 306} 307 308MediaProfiles::ImageEncodingQualityLevels* 309MediaProfiles::findImageEncodingQualityLevels(int cameraId) const 310{ 311 int n = mImageEncodingQualityLevels.size(); 312 for (int i = 0; i < n; i++) { 313 ImageEncodingQualityLevels *levels = mImageEncodingQualityLevels[i]; 314 if (levels->mCameraId == cameraId) { 315 return levels; 316 } 317 } 318 return NULL; 319} 320 321void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts) 322{ 323 CHECK(!strcmp("quality", atts[0])); 324 int quality = atoi(atts[1]); 325 LOGV("%s: cameraId=%d, quality=%d\n", __func__, cameraId, quality); 326 ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId); 327 328 if (levels == NULL) { 329 levels = new ImageEncodingQualityLevels(); 330 levels->mCameraId = cameraId; 331 mImageEncodingQualityLevels.add(levels); 332 } 333 334 levels->mLevels.add(quality); 335} 336 337/*static*/ int 338MediaProfiles::getCameraId(const char** atts) 339{ 340 if (!atts[0]) return 0; // default cameraId = 0 341 CHECK(!strcmp("cameraId", atts[0])); 342 return atoi(atts[1]); 343} 344 345/*static*/ void 346MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts) 347{ 348 MediaProfiles *profiles = (MediaProfiles *) userData; 349 if (strcmp("Video", name) == 0) { 350 createVideoCodec(atts, profiles); 351 } else if (strcmp("Audio", name) == 0) { 352 createAudioCodec(atts, profiles); 353 } else if (strcmp("VideoEncoderCap", name) == 0 && 354 strcmp("true", atts[3]) == 0) { 355 profiles->mVideoEncoders.add(createVideoEncoderCap(atts)); 356 } else if (strcmp("AudioEncoderCap", name) == 0 && 357 strcmp("true", atts[3]) == 0) { 358 profiles->mAudioEncoders.add(createAudioEncoderCap(atts)); 359 } else if (strcmp("VideoDecoderCap", name) == 0 && 360 strcmp("true", atts[3]) == 0) { 361 profiles->mVideoDecoders.add(createVideoDecoderCap(atts)); 362 } else if (strcmp("AudioDecoderCap", name) == 0 && 363 strcmp("true", atts[3]) == 0) { 364 profiles->mAudioDecoders.add(createAudioDecoderCap(atts)); 365 } else if (strcmp("EncoderOutputFileFormat", name) == 0) { 366 profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts)); 367 } else if (strcmp("CamcorderProfiles", name) == 0) { 368 profiles->mCurrentCameraId = getCameraId(atts); 369 } else if (strcmp("EncoderProfile", name) == 0) { 370 profiles->mCamcorderProfiles.add( 371 createCamcorderProfile(profiles->mCurrentCameraId, atts)); 372 } else if (strcmp("ImageEncoding", name) == 0) { 373 profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts); 374 } 375} 376 377/*static*/ MediaProfiles* 378MediaProfiles::getInstance() 379{ 380 LOGV("getInstance"); 381 Mutex::Autolock lock(sLock); 382 if (!sIsInitialized) { 383 char value[PROPERTY_VALUE_MAX]; 384 if (property_get("media.settings.xml", value, NULL) <= 0) { 385 const char *defaultXmlFile = "/etc/media_profiles.xml"; 386 FILE *fp = fopen(defaultXmlFile, "r"); 387 if (fp == NULL) { 388 LOGW("could not find media config xml file"); 389 sInstance = createDefaultInstance(); 390 } else { 391 fclose(fp); // close the file first. 392 sInstance = createInstanceFromXmlFile(defaultXmlFile); 393 } 394 } else { 395 sInstance = createInstanceFromXmlFile(value); 396 } 397 } 398 399 return sInstance; 400} 401 402/*static*/ MediaProfiles::VideoEncoderCap* 403MediaProfiles::createDefaultH263VideoEncoderCap() 404{ 405 return new MediaProfiles::VideoEncoderCap( 406 VIDEO_ENCODER_H263, 192000, 420000, 176, 352, 144, 288, 1, 20); 407} 408 409/*static*/ MediaProfiles::VideoEncoderCap* 410MediaProfiles::createDefaultM4vVideoEncoderCap() 411{ 412 return new MediaProfiles::VideoEncoderCap( 413 VIDEO_ENCODER_MPEG_4_SP, 192000, 420000, 176, 352, 144, 288, 1, 20); 414} 415 416 417/*static*/ void 418MediaProfiles::createDefaultVideoEncoders(MediaProfiles *profiles) 419{ 420 profiles->mVideoEncoders.add(createDefaultH263VideoEncoderCap()); 421 profiles->mVideoEncoders.add(createDefaultM4vVideoEncoderCap()); 422} 423 424/*static*/ MediaProfiles::CamcorderProfile* 425MediaProfiles::createDefaultCamcorderTimeLapseHighProfile() 426{ 427 MediaProfiles::VideoCodec *videoCodec = 428 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 20000000, 720, 480, 20); 429 430 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); 431 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 432 profile->mCameraId = 0; 433 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; 434 profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_HIGH; 435 profile->mDuration = 60; 436 profile->mVideoCodec = videoCodec; 437 profile->mAudioCodec = audioCodec; 438 return profile; 439} 440 441/*static*/ MediaProfiles::CamcorderProfile* 442MediaProfiles::createDefaultCamcorderTimeLapseLowProfile() 443{ 444 MediaProfiles::VideoCodec *videoCodec = 445 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 1000000, 176, 144, 20); 446 447 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); 448 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 449 profile->mCameraId = 0; 450 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; 451 profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_LOW; 452 profile->mDuration = 60; 453 profile->mVideoCodec = videoCodec; 454 profile->mAudioCodec = audioCodec; 455 return profile; 456} 457 458/*static*/ MediaProfiles::CamcorderProfile* 459MediaProfiles::createDefaultCamcorderHighProfile() 460{ 461 MediaProfiles::VideoCodec *videoCodec = 462 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20); 463 464 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); 465 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 466 profile->mCameraId = 0; 467 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; 468 profile->mQuality = CAMCORDER_QUALITY_HIGH; 469 profile->mDuration = 60; 470 profile->mVideoCodec = videoCodec; 471 profile->mAudioCodec = audioCodec; 472 return profile; 473} 474 475/*static*/ MediaProfiles::CamcorderProfile* 476MediaProfiles::createDefaultCamcorderLowProfile() 477{ 478 MediaProfiles::VideoCodec *videoCodec = 479 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 192000, 176, 144, 20); 480 481 MediaProfiles::AudioCodec *audioCodec = 482 new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1); 483 484 MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile; 485 profile->mCameraId = 0; 486 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP; 487 profile->mQuality = CAMCORDER_QUALITY_LOW; 488 profile->mDuration = 30; 489 profile->mVideoCodec = videoCodec; 490 profile->mAudioCodec = audioCodec; 491 return profile; 492} 493 494/*static*/ void 495MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles) 496{ 497 profiles->mCamcorderProfiles.add(createDefaultCamcorderTimeLapseHighProfile()); 498 profiles->mCamcorderProfiles.add(createDefaultCamcorderTimeLapseLowProfile()); 499 profiles->mCamcorderProfiles.add(createDefaultCamcorderHighProfile()); 500 profiles->mCamcorderProfiles.add(createDefaultCamcorderLowProfile()); 501} 502 503/*static*/ void 504MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles) 505{ 506 profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap()); 507} 508 509/*static*/ void 510MediaProfiles::createDefaultVideoDecoders(MediaProfiles *profiles) 511{ 512 MediaProfiles::VideoDecoderCap *cap = 513 new MediaProfiles::VideoDecoderCap(VIDEO_DECODER_WMV); 514 515 profiles->mVideoDecoders.add(cap); 516} 517 518/*static*/ void 519MediaProfiles::createDefaultAudioDecoders(MediaProfiles *profiles) 520{ 521 MediaProfiles::AudioDecoderCap *cap = 522 new MediaProfiles::AudioDecoderCap(AUDIO_DECODER_WMA); 523 524 profiles->mAudioDecoders.add(cap); 525} 526 527/*static*/ void 528MediaProfiles::createDefaultEncoderOutputFileFormats(MediaProfiles *profiles) 529{ 530 profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_THREE_GPP); 531 profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_MPEG_4); 532} 533 534/*static*/ MediaProfiles::AudioEncoderCap* 535MediaProfiles::createDefaultAmrNBEncoderCap() 536{ 537 return new MediaProfiles::AudioEncoderCap( 538 AUDIO_ENCODER_AMR_NB, 5525, 12200, 8000, 8000, 1, 1); 539} 540 541/*static*/ void 542MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles) 543{ 544 ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels(); 545 levels->mCameraId = 0; 546 levels->mLevels.add(70); 547 levels->mLevels.add(80); 548 levels->mLevels.add(90); 549 profiles->mImageEncodingQualityLevels.add(levels); 550} 551 552/*static*/ MediaProfiles* 553MediaProfiles::createDefaultInstance() 554{ 555 MediaProfiles *profiles = new MediaProfiles; 556 createDefaultCamcorderProfiles(profiles); 557 createDefaultVideoEncoders(profiles); 558 createDefaultAudioEncoders(profiles); 559 createDefaultVideoDecoders(profiles); 560 createDefaultAudioDecoders(profiles); 561 createDefaultEncoderOutputFileFormats(profiles); 562 createDefaultImageEncodingQualityLevels(profiles); 563 sIsInitialized = true; 564 return profiles; 565} 566 567/*static*/ MediaProfiles* 568MediaProfiles::createInstanceFromXmlFile(const char *xml) 569{ 570 FILE *fp = NULL; 571 CHECK((fp = fopen(xml, "r"))); 572 573 XML_Parser parser = ::XML_ParserCreate(NULL); 574 CHECK(parser != NULL); 575 576 MediaProfiles *profiles = new MediaProfiles(); 577 ::XML_SetUserData(parser, profiles); 578 ::XML_SetElementHandler(parser, startElementHandler, NULL); 579 580 /* 581 FIXME: 582 expat is not compiled with -DXML_DTD. We don't have DTD parsing support. 583 584 if (!::XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS)) { 585 LOGE("failed to enable DTD support in the xml file"); 586 return UNKNOWN_ERROR; 587 } 588 589 */ 590 591 const int BUFF_SIZE = 512; 592 for (;;) { 593 void *buff = ::XML_GetBuffer(parser, BUFF_SIZE); 594 if (buff == NULL) { 595 LOGE("failed to in call to XML_GetBuffer()"); 596 delete profiles; 597 profiles = NULL; 598 goto exit; 599 } 600 601 int bytes_read = ::fread(buff, 1, BUFF_SIZE, fp); 602 if (bytes_read < 0) { 603 LOGE("failed in call to read"); 604 delete profiles; 605 profiles = NULL; 606 goto exit; 607 } 608 609 CHECK(::XML_ParseBuffer(parser, bytes_read, bytes_read == 0)); 610 611 if (bytes_read == 0) break; // done parsing the xml file 612 } 613 614exit: 615 ::XML_ParserFree(parser); 616 ::fclose(fp); 617 if (profiles) { 618 sIsInitialized = true; 619 } 620 return profiles; 621} 622 623Vector<output_format> MediaProfiles::getOutputFileFormats() const 624{ 625 return mEncoderOutputFileFormats; // copy out 626} 627 628Vector<video_encoder> MediaProfiles::getVideoEncoders() const 629{ 630 Vector<video_encoder> encoders; 631 for (size_t i = 0; i < mVideoEncoders.size(); ++i) { 632 encoders.add(mVideoEncoders[i]->mCodec); 633 } 634 return encoders; // copy out 635} 636 637int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder codec) const 638{ 639 LOGV("getVideoEncoderParamByName: %s for codec %d", name, codec); 640 int index = -1; 641 for (size_t i = 0, n = mVideoEncoders.size(); i < n; ++i) { 642 if (mVideoEncoders[i]->mCodec == codec) { 643 index = i; 644 break; 645 } 646 } 647 if (index == -1) { 648 LOGE("The given video encoder %d is not found", codec); 649 return -1; 650 } 651 652 if (!strcmp("enc.vid.width.min", name)) return mVideoEncoders[index]->mMinFrameWidth; 653 if (!strcmp("enc.vid.width.max", name)) return mVideoEncoders[index]->mMaxFrameWidth; 654 if (!strcmp("enc.vid.height.min", name)) return mVideoEncoders[index]->mMinFrameHeight; 655 if (!strcmp("enc.vid.height.max", name)) return mVideoEncoders[index]->mMaxFrameHeight; 656 if (!strcmp("enc.vid.bps.min", name)) return mVideoEncoders[index]->mMinBitRate; 657 if (!strcmp("enc.vid.bps.max", name)) return mVideoEncoders[index]->mMaxBitRate; 658 if (!strcmp("enc.vid.fps.min", name)) return mVideoEncoders[index]->mMinFrameRate; 659 if (!strcmp("enc.vid.fps.max", name)) return mVideoEncoders[index]->mMaxFrameRate; 660 661 LOGE("The given video encoder param name %s is not found", name); 662 return -1; 663} 664 665Vector<audio_encoder> MediaProfiles::getAudioEncoders() const 666{ 667 Vector<audio_encoder> encoders; 668 for (size_t i = 0; i < mAudioEncoders.size(); ++i) { 669 encoders.add(mAudioEncoders[i]->mCodec); 670 } 671 return encoders; // copy out 672} 673 674int MediaProfiles::getAudioEncoderParamByName(const char *name, audio_encoder codec) const 675{ 676 LOGV("getAudioEncoderParamByName: %s for codec %d", name, codec); 677 int index = -1; 678 for (size_t i = 0, n = mAudioEncoders.size(); i < n; ++i) { 679 if (mAudioEncoders[i]->mCodec == codec) { 680 index = i; 681 break; 682 } 683 } 684 if (index == -1) { 685 LOGE("The given audio encoder %d is not found", codec); 686 return -1; 687 } 688 689 if (!strcmp("enc.aud.ch.min", name)) return mAudioEncoders[index]->mMinChannels; 690 if (!strcmp("enc.aud.ch.max", name)) return mAudioEncoders[index]->mMaxChannels; 691 if (!strcmp("enc.aud.bps.min", name)) return mAudioEncoders[index]->mMinBitRate; 692 if (!strcmp("enc.aud.bps.max", name)) return mAudioEncoders[index]->mMaxBitRate; 693 if (!strcmp("enc.aud.hz.min", name)) return mAudioEncoders[index]->mMinSampleRate; 694 if (!strcmp("enc.aud.hz.max", name)) return mAudioEncoders[index]->mMaxSampleRate; 695 696 LOGE("The given audio encoder param name %s is not found", name); 697 return -1; 698} 699 700Vector<video_decoder> MediaProfiles::getVideoDecoders() const 701{ 702 Vector<video_decoder> decoders; 703 for (size_t i = 0; i < mVideoDecoders.size(); ++i) { 704 decoders.add(mVideoDecoders[i]->mCodec); 705 } 706 return decoders; // copy out 707} 708 709Vector<audio_decoder> MediaProfiles::getAudioDecoders() const 710{ 711 Vector<audio_decoder> decoders; 712 for (size_t i = 0; i < mAudioDecoders.size(); ++i) { 713 decoders.add(mAudioDecoders[i]->mCodec); 714 } 715 return decoders; // copy out 716} 717 718int MediaProfiles::getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const 719{ 720 int index = -1; 721 for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) { 722 if (mCamcorderProfiles[i]->mCameraId == cameraId && 723 mCamcorderProfiles[i]->mQuality == quality) { 724 index = i; 725 break; 726 } 727 } 728 return index; 729} 730 731int MediaProfiles::getCamcorderProfileParamByName(const char *name, 732 int cameraId, 733 camcorder_quality quality) const 734{ 735 LOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d", 736 name, cameraId, quality); 737 738 int index = getCamcorderProfileIndex(cameraId, quality); 739 if (index == -1) { 740 LOGE("The given camcorder profile camera %d quality %d is not found", 741 cameraId, quality); 742 return -1; 743 } 744 745 if (!strcmp("duration", name)) return mCamcorderProfiles[index]->mDuration; 746 if (!strcmp("file.format", name)) return mCamcorderProfiles[index]->mFileFormat; 747 if (!strcmp("vid.codec", name)) return mCamcorderProfiles[index]->mVideoCodec->mCodec; 748 if (!strcmp("vid.width", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameWidth; 749 if (!strcmp("vid.height", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameHeight; 750 if (!strcmp("vid.bps", name)) return mCamcorderProfiles[index]->mVideoCodec->mBitRate; 751 if (!strcmp("vid.fps", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameRate; 752 if (!strcmp("aud.codec", name)) return mCamcorderProfiles[index]->mAudioCodec->mCodec; 753 if (!strcmp("aud.bps", name)) return mCamcorderProfiles[index]->mAudioCodec->mBitRate; 754 if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels; 755 if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate; 756 757 LOGE("The given camcorder profile param id %d name %s is not found", cameraId, name); 758 return -1; 759} 760 761bool MediaProfiles::hasCamcorderProfile(int cameraId, camcorder_quality quality) const 762{ 763 return (getCamcorderProfileIndex(cameraId, quality) != -1); 764} 765 766Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const 767{ 768 Vector<int> result; 769 ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId); 770 if (levels != NULL) { 771 result = levels->mLevels; // copy out 772 } 773 return result; 774} 775 776MediaProfiles::~MediaProfiles() 777{ 778 CHECK("destructor should never be called" == 0); 779#if 0 780 for (size_t i = 0; i < mAudioEncoders.size(); ++i) { 781 delete mAudioEncoders[i]; 782 } 783 mAudioEncoders.clear(); 784 785 for (size_t i = 0; i < mVideoEncoders.size(); ++i) { 786 delete mVideoEncoders[i]; 787 } 788 mVideoEncoders.clear(); 789 790 for (size_t i = 0; i < mVideoDecoders.size(); ++i) { 791 delete mVideoDecoders[i]; 792 } 793 mVideoDecoders.clear(); 794 795 for (size_t i = 0; i < mAudioDecoders.size(); ++i) { 796 delete mAudioDecoders[i]; 797 } 798 mAudioDecoders.clear(); 799 800 for (size_t i = 0; i < mCamcorderProfiles.size(); ++i) { 801 delete mCamcorderProfiles[i]; 802 } 803 mCamcorderProfiles.clear(); 804#endif 805} 806} // namespace android 807