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