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