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