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