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