blob: 37a33ed2184e5e804cc762f6685dcbaf58151389 [file] [log] [blame]
James Dongc3711942010-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>
29
30namespace android {
31
32Mutex MediaProfiles::sLock;
33bool MediaProfiles::sIsInitialized = false;
34MediaProfiles *MediaProfiles::sInstance = NULL;
35
36const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = {
37 {"h263", VIDEO_ENCODER_H263},
38 {"h264", VIDEO_ENCODER_H264},
39 {"m4v", VIDEO_ENCODER_MPEG_4_SP}
40};
41
42const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
43 {"amrnb", AUDIO_ENCODER_AMR_NB},
44 {"amrwb", AUDIO_ENCODER_AMR_WB},
45 {"aac", AUDIO_ENCODER_AAC},
46};
47
48const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = {
49 {"3gp", OUTPUT_FORMAT_THREE_GPP},
50 {"mp4", OUTPUT_FORMAT_MPEG_4}
51};
52
53const MediaProfiles::NameToTagMap MediaProfiles::sVideoDecoderNameMap[] = {
54 {"wmv", VIDEO_DECODER_WMV}
55};
56
57const MediaProfiles::NameToTagMap MediaProfiles::sAudioDecoderNameMap[] = {
58 {"wma", AUDIO_DECODER_WMA}
59};
60
61const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = {
Nipun Kwatra4af0dfd2010-09-06 15:59:02 -070062 {"low", CAMCORDER_QUALITY_LOW},
James Dongc3711942010-01-19 17:45:38 -080063 {"high", CAMCORDER_QUALITY_HIGH},
Nipun Kwatra4af0dfd2010-09-06 15:59:02 -070064 {"qcif", CAMCORDER_QUALITY_QCIF},
65 {"480p", CAMCORDER_QUALITY_480P},
66 {"720p", CAMCORDER_QUALITY_720P},
67 {"1080p", CAMCORDER_QUALITY_1080P},
68
69 {"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW},
70 {"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH},
71 {"timelapseqcif", CAMCORDER_QUALITY_TIME_LAPSE_QCIF},
72 {"timelapse480p", CAMCORDER_QUALITY_TIME_LAPSE_480P},
73 {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P},
74 {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P}
James Dongc3711942010-01-19 17:45:38 -080075};
76
77/*static*/ void
78MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec)
79{
80 LOGV("video codec:");
81 LOGV("codec = %d", codec.mCodec);
82 LOGV("bit rate: %d", codec.mBitRate);
83 LOGV("frame width: %d", codec.mFrameWidth);
84 LOGV("frame height: %d", codec.mFrameHeight);
85 LOGV("frame rate: %d", codec.mFrameRate);
86}
87
88/*static*/ void
89MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec)
90{
91 LOGV("audio codec:");
92 LOGV("codec = %d", codec.mCodec);
93 LOGV("bit rate: %d", codec.mBitRate);
94 LOGV("sample rate: %d", codec.mSampleRate);
95 LOGV("number of channels: %d", codec.mChannels);
96}
97
98/*static*/ void
99MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap)
100{
101 LOGV("video encoder cap:");
102 LOGV("codec = %d", cap.mCodec);
103 LOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate);
104 LOGV("frame width: min = %d and max = %d", cap.mMinFrameWidth, cap.mMaxFrameWidth);
105 LOGV("frame height: min = %d and max = %d", cap.mMinFrameHeight, cap.mMaxFrameHeight);
106 LOGV("frame rate: min = %d and max = %d", cap.mMinFrameRate, cap.mMaxFrameRate);
107}
108
109/*static*/ void
110MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap)
111{
112 LOGV("audio encoder cap:");
113 LOGV("codec = %d", cap.mCodec);
114 LOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate);
115 LOGV("sample rate: min = %d and max = %d", cap.mMinSampleRate, cap.mMaxSampleRate);
116 LOGV("number of channels: min = %d and max = %d", cap.mMinChannels, cap.mMaxChannels);
117}
118
119/*static*/ void
120MediaProfiles::logVideoDecoderCap(const MediaProfiles::VideoDecoderCap& cap)
121{
122 LOGV("video decoder cap:");
123 LOGV("codec = %d", cap.mCodec);
124}
125
126/*static*/ void
127MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap)
128{
129 LOGV("audio codec cap:");
130 LOGV("codec = %d", cap.mCodec);
131}
132
133/*static*/ int
134MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name)
135{
136 int tag = -1;
137 for (size_t i = 0; i < nMappings; ++i) {
138 if (!strcmp(map[i].name, name)) {
139 tag = map[i].tag;
140 break;
141 }
142 }
143 return tag;
144}
145
146/*static*/ MediaProfiles::VideoCodec*
147MediaProfiles::createVideoCodec(const char **atts, MediaProfiles *profiles)
148{
149 CHECK(!strcmp("codec", atts[0]) &&
150 !strcmp("bitRate", atts[2]) &&
151 !strcmp("width", atts[4]) &&
152 !strcmp("height", atts[6]) &&
153 !strcmp("frameRate", atts[8]));
154
155 const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
156 const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
157 CHECK(codec != -1);
158
159 MediaProfiles::VideoCodec *videoCodec =
160 new MediaProfiles::VideoCodec(static_cast<video_encoder>(codec),
161 atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]));
162 logVideoCodec(*videoCodec);
163
164 size_t nCamcorderProfiles;
165 CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
166 profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mVideoCodec = videoCodec;
167 return videoCodec;
168}
169
170/*static*/ MediaProfiles::AudioCodec*
171MediaProfiles::createAudioCodec(const char **atts, MediaProfiles *profiles)
172{
173 CHECK(!strcmp("codec", atts[0]) &&
174 !strcmp("bitRate", atts[2]) &&
175 !strcmp("sampleRate", atts[4]) &&
176 !strcmp("channels", atts[6]));
177 const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
178 const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
179 CHECK(codec != -1);
180
181 MediaProfiles::AudioCodec *audioCodec =
182 new MediaProfiles::AudioCodec(static_cast<audio_encoder>(codec),
183 atoi(atts[3]), atoi(atts[5]), atoi(atts[7]));
184 logAudioCodec(*audioCodec);
185
186 size_t nCamcorderProfiles;
187 CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
188 profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mAudioCodec = audioCodec;
189 return audioCodec;
190}
191/*static*/ MediaProfiles::AudioDecoderCap*
192MediaProfiles::createAudioDecoderCap(const char **atts)
193{
194 CHECK(!strcmp("name", atts[0]) &&
195 !strcmp("enabled", atts[2]));
196
197 const size_t nMappings = sizeof(sAudioDecoderNameMap)/sizeof(sAudioDecoderNameMap[0]);
198 const int codec = findTagForName(sAudioDecoderNameMap, nMappings, atts[1]);
199 CHECK(codec != -1);
200
201 MediaProfiles::AudioDecoderCap *cap =
202 new MediaProfiles::AudioDecoderCap(static_cast<audio_decoder>(codec));
203 logAudioDecoderCap(*cap);
204 return cap;
205}
206
207/*static*/ MediaProfiles::VideoDecoderCap*
208MediaProfiles::createVideoDecoderCap(const char **atts)
209{
210 CHECK(!strcmp("name", atts[0]) &&
211 !strcmp("enabled", atts[2]));
212
213 const size_t nMappings = sizeof(sVideoDecoderNameMap)/sizeof(sVideoDecoderNameMap[0]);
214 const int codec = findTagForName(sVideoDecoderNameMap, nMappings, atts[1]);
215 CHECK(codec != -1);
216
217 MediaProfiles::VideoDecoderCap *cap =
218 new MediaProfiles::VideoDecoderCap(static_cast<video_decoder>(codec));
219 logVideoDecoderCap(*cap);
220 return cap;
221}
222
223/*static*/ MediaProfiles::VideoEncoderCap*
224MediaProfiles::createVideoEncoderCap(const char **atts)
225{
226 CHECK(!strcmp("name", atts[0]) &&
227 !strcmp("enabled", atts[2]) &&
228 !strcmp("minBitRate", atts[4]) &&
229 !strcmp("maxBitRate", atts[6]) &&
230 !strcmp("minFrameWidth", atts[8]) &&
231 !strcmp("maxFrameWidth", atts[10]) &&
232 !strcmp("minFrameHeight", atts[12]) &&
233 !strcmp("maxFrameHeight", atts[14]) &&
234 !strcmp("minFrameRate", atts[16]) &&
235 !strcmp("maxFrameRate", atts[18]));
236
237 const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
238 const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
239 CHECK(codec != -1);
240
241 MediaProfiles::VideoEncoderCap *cap =
242 new MediaProfiles::VideoEncoderCap(static_cast<video_encoder>(codec),
243 atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]),
244 atoi(atts[15]), atoi(atts[17]), atoi(atts[19]));
245 logVideoEncoderCap(*cap);
246 return cap;
247}
248
249/*static*/ MediaProfiles::AudioEncoderCap*
250MediaProfiles::createAudioEncoderCap(const char **atts)
251{
252 CHECK(!strcmp("name", atts[0]) &&
253 !strcmp("enabled", atts[2]) &&
254 !strcmp("minBitRate", atts[4]) &&
255 !strcmp("maxBitRate", atts[6]) &&
256 !strcmp("minSampleRate", atts[8]) &&
257 !strcmp("maxSampleRate", atts[10]) &&
258 !strcmp("minChannels", atts[12]) &&
259 !strcmp("maxChannels", atts[14]));
260
261 const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
262 const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
263 CHECK(codec != -1);
264
265 MediaProfiles::AudioEncoderCap *cap =
266 new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]), atoi(atts[7]),
267 atoi(atts[9]), atoi(atts[11]), atoi(atts[13]),
268 atoi(atts[15]));
269 logAudioEncoderCap(*cap);
270 return cap;
271}
272
273/*static*/ output_format
274MediaProfiles::createEncoderOutputFileFormat(const char **atts)
275{
276 CHECK(!strcmp("name", atts[0]));
277
278 const size_t nMappings =sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
279 const int format = findTagForName(sFileFormatMap, nMappings, atts[1]);
280 CHECK(format != -1);
281
282 return static_cast<output_format>(format);
283}
284
285/*static*/ MediaProfiles::CamcorderProfile*
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800286MediaProfiles::createCamcorderProfile(int cameraId, const char **atts)
James Dongc3711942010-01-19 17:45:38 -0800287{
288 CHECK(!strcmp("quality", atts[0]) &&
289 !strcmp("fileFormat", atts[2]) &&
290 !strcmp("duration", atts[4]));
291
292 const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/sizeof(sCamcorderQualityNameMap[0]);
293 const int quality = findTagForName(sCamcorderQualityNameMap, nProfileMappings, atts[1]);
294 CHECK(quality != -1);
295
296 const size_t nFormatMappings = sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
297 const int fileFormat = findTagForName(sFileFormatMap, nFormatMappings, atts[3]);
298 CHECK(fileFormat != -1);
299
300 MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800301 profile->mCameraId = cameraId;
James Dongc3711942010-01-19 17:45:38 -0800302 profile->mFileFormat = static_cast<output_format>(fileFormat);
303 profile->mQuality = static_cast<camcorder_quality>(quality);
304 profile->mDuration = atoi(atts[5]);
305 return profile;
306}
307
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800308MediaProfiles::ImageEncodingQualityLevels*
309MediaProfiles::findImageEncodingQualityLevels(int cameraId) const
310{
311 int n = mImageEncodingQualityLevels.size();
312 for (int i = 0; i < n; i++) {
313 ImageEncodingQualityLevels *levels = mImageEncodingQualityLevels[i];
314 if (levels->mCameraId == cameraId) {
315 return levels;
316 }
317 }
318 return NULL;
319}
320
321void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts)
James Dong9b433f02010-02-23 17:21:44 -0800322{
323 CHECK(!strcmp("quality", atts[0]));
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800324 int quality = atoi(atts[1]);
325 LOGV("%s: cameraId=%d, quality=%d\n", __func__, cameraId, quality);
326 ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
327
328 if (levels == NULL) {
329 levels = new ImageEncodingQualityLevels();
330 levels->mCameraId = cameraId;
331 mImageEncodingQualityLevels.add(levels);
332 }
333
334 levels->mLevels.add(quality);
335}
336
337/*static*/ int
338MediaProfiles::getCameraId(const char** atts)
339{
340 if (!atts[0]) return 0; // default cameraId = 0
341 CHECK(!strcmp("cameraId", atts[0]));
James Dong9b433f02010-02-23 17:21:44 -0800342 return atoi(atts[1]);
343}
344
James Dongc3711942010-01-19 17:45:38 -0800345/*static*/ void
346MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
347{
348 MediaProfiles *profiles = (MediaProfiles *) userData;
349 if (strcmp("Video", name) == 0) {
350 createVideoCodec(atts, profiles);
351 } else if (strcmp("Audio", name) == 0) {
352 createAudioCodec(atts, profiles);
353 } else if (strcmp("VideoEncoderCap", name) == 0 &&
354 strcmp("true", atts[3]) == 0) {
355 profiles->mVideoEncoders.add(createVideoEncoderCap(atts));
356 } else if (strcmp("AudioEncoderCap", name) == 0 &&
357 strcmp("true", atts[3]) == 0) {
358 profiles->mAudioEncoders.add(createAudioEncoderCap(atts));
359 } else if (strcmp("VideoDecoderCap", name) == 0 &&
360 strcmp("true", atts[3]) == 0) {
361 profiles->mVideoDecoders.add(createVideoDecoderCap(atts));
362 } else if (strcmp("AudioDecoderCap", name) == 0 &&
363 strcmp("true", atts[3]) == 0) {
364 profiles->mAudioDecoders.add(createAudioDecoderCap(atts));
365 } else if (strcmp("EncoderOutputFileFormat", name) == 0) {
366 profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts));
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800367 } else if (strcmp("CamcorderProfiles", name) == 0) {
368 profiles->mCurrentCameraId = getCameraId(atts);
James Dongc3711942010-01-19 17:45:38 -0800369 } else if (strcmp("EncoderProfile", name) == 0) {
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800370 profiles->mCamcorderProfiles.add(
371 createCamcorderProfile(profiles->mCurrentCameraId, atts));
James Dong9b433f02010-02-23 17:21:44 -0800372 } else if (strcmp("ImageEncoding", name) == 0) {
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800373 profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
James Dongc3711942010-01-19 17:45:38 -0800374 }
375}
376
377/*static*/ MediaProfiles*
378MediaProfiles::getInstance()
379{
380 LOGV("getInstance");
381 Mutex::Autolock lock(sLock);
382 if (!sIsInitialized) {
383 char value[PROPERTY_VALUE_MAX];
384 if (property_get("media.settings.xml", value, NULL) <= 0) {
385 const char *defaultXmlFile = "/etc/media_profiles.xml";
386 FILE *fp = fopen(defaultXmlFile, "r");
387 if (fp == NULL) {
388 LOGW("could not find media config xml file");
389 sInstance = createDefaultInstance();
390 } else {
391 fclose(fp); // close the file first.
392 sInstance = createInstanceFromXmlFile(defaultXmlFile);
393 }
394 } else {
395 sInstance = createInstanceFromXmlFile(value);
396 }
397 }
398
399 return sInstance;
400}
401
402/*static*/ MediaProfiles::VideoEncoderCap*
403MediaProfiles::createDefaultH263VideoEncoderCap()
404{
405 return new MediaProfiles::VideoEncoderCap(
406 VIDEO_ENCODER_H263, 192000, 420000, 176, 352, 144, 288, 1, 20);
407}
408
409/*static*/ MediaProfiles::VideoEncoderCap*
410MediaProfiles::createDefaultM4vVideoEncoderCap()
411{
412 return new MediaProfiles::VideoEncoderCap(
413 VIDEO_ENCODER_MPEG_4_SP, 192000, 420000, 176, 352, 144, 288, 1, 20);
414}
415
416
417/*static*/ void
418MediaProfiles::createDefaultVideoEncoders(MediaProfiles *profiles)
419{
420 profiles->mVideoEncoders.add(createDefaultH263VideoEncoderCap());
421 profiles->mVideoEncoders.add(createDefaultM4vVideoEncoderCap());
422}
423
424/*static*/ MediaProfiles::CamcorderProfile*
Nipun Kwatra4af0dfd2010-09-06 15:59:02 -0700425MediaProfiles::createDefaultCamcorderTimeLapseHighProfile()
426{
427 MediaProfiles::VideoCodec *videoCodec =
428 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 20000000, 720, 480, 20);
429
430 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
431 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
432 profile->mCameraId = 0;
433 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
434 profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_HIGH;
435 profile->mDuration = 60;
436 profile->mVideoCodec = videoCodec;
437 profile->mAudioCodec = audioCodec;
438 return profile;
439}
440
441/*static*/ MediaProfiles::CamcorderProfile*
442MediaProfiles::createDefaultCamcorderTimeLapseLowProfile()
443{
444 MediaProfiles::VideoCodec *videoCodec =
445 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 1000000, 176, 144, 20);
446
447 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
448 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
449 profile->mCameraId = 0;
450 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
451 profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_LOW;
452 profile->mDuration = 60;
453 profile->mVideoCodec = videoCodec;
454 profile->mAudioCodec = audioCodec;
455 return profile;
456}
457
458/*static*/ MediaProfiles::CamcorderProfile*
James Dongc3711942010-01-19 17:45:38 -0800459MediaProfiles::createDefaultCamcorderHighProfile()
460{
461 MediaProfiles::VideoCodec *videoCodec =
462 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20);
463
464 AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800465 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
466 profile->mCameraId = 0;
James Dongc3711942010-01-19 17:45:38 -0800467 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
468 profile->mQuality = CAMCORDER_QUALITY_HIGH;
469 profile->mDuration = 60;
470 profile->mVideoCodec = videoCodec;
471 profile->mAudioCodec = audioCodec;
472 return profile;
473}
474
475/*static*/ MediaProfiles::CamcorderProfile*
476MediaProfiles::createDefaultCamcorderLowProfile()
477{
478 MediaProfiles::VideoCodec *videoCodec =
479 new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 192000, 176, 144, 20);
480
481 MediaProfiles::AudioCodec *audioCodec =
482 new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
483
484 MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800485 profile->mCameraId = 0;
James Dongc3711942010-01-19 17:45:38 -0800486 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
487 profile->mQuality = CAMCORDER_QUALITY_LOW;
488 profile->mDuration = 30;
489 profile->mVideoCodec = videoCodec;
490 profile->mAudioCodec = audioCodec;
491 return profile;
492}
493
494/*static*/ void
495MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles)
496{
Nipun Kwatra4af0dfd2010-09-06 15:59:02 -0700497 profiles->mCamcorderProfiles.add(createDefaultCamcorderTimeLapseHighProfile());
498 profiles->mCamcorderProfiles.add(createDefaultCamcorderTimeLapseLowProfile());
James Dongc3711942010-01-19 17:45:38 -0800499 profiles->mCamcorderProfiles.add(createDefaultCamcorderHighProfile());
500 profiles->mCamcorderProfiles.add(createDefaultCamcorderLowProfile());
501}
502
503/*static*/ void
504MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles)
505{
506 profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap());
507}
508
509/*static*/ void
510MediaProfiles::createDefaultVideoDecoders(MediaProfiles *profiles)
511{
512 MediaProfiles::VideoDecoderCap *cap =
513 new MediaProfiles::VideoDecoderCap(VIDEO_DECODER_WMV);
514
515 profiles->mVideoDecoders.add(cap);
516}
517
518/*static*/ void
519MediaProfiles::createDefaultAudioDecoders(MediaProfiles *profiles)
520{
521 MediaProfiles::AudioDecoderCap *cap =
522 new MediaProfiles::AudioDecoderCap(AUDIO_DECODER_WMA);
523
524 profiles->mAudioDecoders.add(cap);
525}
526
527/*static*/ void
528MediaProfiles::createDefaultEncoderOutputFileFormats(MediaProfiles *profiles)
529{
530 profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_THREE_GPP);
531 profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_MPEG_4);
532}
533
534/*static*/ MediaProfiles::AudioEncoderCap*
535MediaProfiles::createDefaultAmrNBEncoderCap()
536{
537 return new MediaProfiles::AudioEncoderCap(
538 AUDIO_ENCODER_AMR_NB, 5525, 12200, 8000, 8000, 1, 1);
539}
540
James Dong9b433f02010-02-23 17:21:44 -0800541/*static*/ void
542MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
543{
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800544 ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels();
545 levels->mCameraId = 0;
546 levels->mLevels.add(70);
547 levels->mLevels.add(80);
548 levels->mLevels.add(90);
549 profiles->mImageEncodingQualityLevels.add(levels);
James Dong9b433f02010-02-23 17:21:44 -0800550}
551
James Dongc3711942010-01-19 17:45:38 -0800552/*static*/ MediaProfiles*
553MediaProfiles::createDefaultInstance()
554{
555 MediaProfiles *profiles = new MediaProfiles;
556 createDefaultCamcorderProfiles(profiles);
557 createDefaultVideoEncoders(profiles);
558 createDefaultAudioEncoders(profiles);
559 createDefaultVideoDecoders(profiles);
560 createDefaultAudioDecoders(profiles);
561 createDefaultEncoderOutputFileFormats(profiles);
James Dong9b433f02010-02-23 17:21:44 -0800562 createDefaultImageEncodingQualityLevels(profiles);
James Dongc3711942010-01-19 17:45:38 -0800563 sIsInitialized = true;
564 return profiles;
565}
566
567/*static*/ MediaProfiles*
568MediaProfiles::createInstanceFromXmlFile(const char *xml)
569{
570 FILE *fp = NULL;
571 CHECK((fp = fopen(xml, "r")));
572
573 XML_Parser parser = ::XML_ParserCreate(NULL);
574 CHECK(parser != NULL);
575
576 MediaProfiles *profiles = new MediaProfiles();
577 ::XML_SetUserData(parser, profiles);
578 ::XML_SetElementHandler(parser, startElementHandler, NULL);
579
580 /*
581 FIXME:
582 expat is not compiled with -DXML_DTD. We don't have DTD parsing support.
583
584 if (!::XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS)) {
585 LOGE("failed to enable DTD support in the xml file");
586 return UNKNOWN_ERROR;
587 }
588
589 */
590
591 const int BUFF_SIZE = 512;
592 for (;;) {
593 void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
594 if (buff == NULL) {
595 LOGE("failed to in call to XML_GetBuffer()");
596 delete profiles;
597 profiles = NULL;
598 goto exit;
599 }
600
601 int bytes_read = ::fread(buff, 1, BUFF_SIZE, fp);
602 if (bytes_read < 0) {
603 LOGE("failed in call to read");
604 delete profiles;
605 profiles = NULL;
606 goto exit;
607 }
608
609 CHECK(::XML_ParseBuffer(parser, bytes_read, bytes_read == 0));
610
611 if (bytes_read == 0) break; // done parsing the xml file
612 }
613
614exit:
615 ::XML_ParserFree(parser);
616 ::fclose(fp);
617 if (profiles) {
618 sIsInitialized = true;
619 }
620 return profiles;
621}
622
623Vector<output_format> MediaProfiles::getOutputFileFormats() const
624{
625 return mEncoderOutputFileFormats; // copy out
626}
627
628Vector<video_encoder> MediaProfiles::getVideoEncoders() const
629{
630 Vector<video_encoder> encoders;
631 for (size_t i = 0; i < mVideoEncoders.size(); ++i) {
632 encoders.add(mVideoEncoders[i]->mCodec);
633 }
634 return encoders; // copy out
635}
636
637int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder codec) const
638{
639 LOGV("getVideoEncoderParamByName: %s for codec %d", name, codec);
640 int index = -1;
641 for (size_t i = 0, n = mVideoEncoders.size(); i < n; ++i) {
642 if (mVideoEncoders[i]->mCodec == codec) {
643 index = i;
644 break;
645 }
646 }
647 if (index == -1) {
648 LOGE("The given video encoder %d is not found", codec);
649 return -1;
650 }
651
652 if (!strcmp("enc.vid.width.min", name)) return mVideoEncoders[index]->mMinFrameWidth;
653 if (!strcmp("enc.vid.width.max", name)) return mVideoEncoders[index]->mMaxFrameWidth;
654 if (!strcmp("enc.vid.height.min", name)) return mVideoEncoders[index]->mMinFrameHeight;
655 if (!strcmp("enc.vid.height.max", name)) return mVideoEncoders[index]->mMaxFrameHeight;
656 if (!strcmp("enc.vid.bps.min", name)) return mVideoEncoders[index]->mMinBitRate;
657 if (!strcmp("enc.vid.bps.max", name)) return mVideoEncoders[index]->mMaxBitRate;
658 if (!strcmp("enc.vid.fps.min", name)) return mVideoEncoders[index]->mMinFrameRate;
659 if (!strcmp("enc.vid.fps.max", name)) return mVideoEncoders[index]->mMaxFrameRate;
660
661 LOGE("The given video encoder param name %s is not found", name);
662 return -1;
663}
664
665Vector<audio_encoder> MediaProfiles::getAudioEncoders() const
666{
667 Vector<audio_encoder> encoders;
668 for (size_t i = 0; i < mAudioEncoders.size(); ++i) {
669 encoders.add(mAudioEncoders[i]->mCodec);
670 }
671 return encoders; // copy out
672}
673
674int MediaProfiles::getAudioEncoderParamByName(const char *name, audio_encoder codec) const
675{
676 LOGV("getAudioEncoderParamByName: %s for codec %d", name, codec);
677 int index = -1;
678 for (size_t i = 0, n = mAudioEncoders.size(); i < n; ++i) {
679 if (mAudioEncoders[i]->mCodec == codec) {
680 index = i;
681 break;
682 }
683 }
684 if (index == -1) {
685 LOGE("The given audio encoder %d is not found", codec);
686 return -1;
687 }
688
689 if (!strcmp("enc.aud.ch.min", name)) return mAudioEncoders[index]->mMinChannels;
690 if (!strcmp("enc.aud.ch.max", name)) return mAudioEncoders[index]->mMaxChannels;
691 if (!strcmp("enc.aud.bps.min", name)) return mAudioEncoders[index]->mMinBitRate;
692 if (!strcmp("enc.aud.bps.max", name)) return mAudioEncoders[index]->mMaxBitRate;
693 if (!strcmp("enc.aud.hz.min", name)) return mAudioEncoders[index]->mMinSampleRate;
694 if (!strcmp("enc.aud.hz.max", name)) return mAudioEncoders[index]->mMaxSampleRate;
695
696 LOGE("The given audio encoder param name %s is not found", name);
697 return -1;
698}
699
700Vector<video_decoder> MediaProfiles::getVideoDecoders() const
701{
702 Vector<video_decoder> decoders;
703 for (size_t i = 0; i < mVideoDecoders.size(); ++i) {
704 decoders.add(mVideoDecoders[i]->mCodec);
705 }
706 return decoders; // copy out
707}
708
709Vector<audio_decoder> MediaProfiles::getAudioDecoders() const
710{
711 Vector<audio_decoder> decoders;
712 for (size_t i = 0; i < mAudioDecoders.size(); ++i) {
713 decoders.add(mAudioDecoders[i]->mCodec);
714 }
715 return decoders; // copy out
716}
717
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800718int MediaProfiles::getCamcorderProfileParamByName(const char *name,
719 int cameraId,
720 camcorder_quality quality) const
James Dongc3711942010-01-19 17:45:38 -0800721{
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800722 LOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d",
723 name, cameraId, quality);
James Dongc3711942010-01-19 17:45:38 -0800724
725 int index = -1;
726 for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800727 if (mCamcorderProfiles[i]->mCameraId == cameraId &&
728 mCamcorderProfiles[i]->mQuality == quality) {
James Dongc3711942010-01-19 17:45:38 -0800729 index = i;
730 break;
731 }
732 }
733 if (index == -1) {
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800734 LOGE("The given camcorder profile camera %d quality %d is not found",
735 cameraId, quality);
James Dongc3711942010-01-19 17:45:38 -0800736 return -1;
737 }
738
James Dong9b433f02010-02-23 17:21:44 -0800739 if (!strcmp("duration", name)) return mCamcorderProfiles[index]->mDuration;
James Dongc3711942010-01-19 17:45:38 -0800740 if (!strcmp("file.format", name)) return mCamcorderProfiles[index]->mFileFormat;
741 if (!strcmp("vid.codec", name)) return mCamcorderProfiles[index]->mVideoCodec->mCodec;
742 if (!strcmp("vid.width", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameWidth;
743 if (!strcmp("vid.height", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameHeight;
744 if (!strcmp("vid.bps", name)) return mCamcorderProfiles[index]->mVideoCodec->mBitRate;
745 if (!strcmp("vid.fps", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameRate;
746 if (!strcmp("aud.codec", name)) return mCamcorderProfiles[index]->mAudioCodec->mCodec;
747 if (!strcmp("aud.bps", name)) return mCamcorderProfiles[index]->mAudioCodec->mBitRate;
748 if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels;
749 if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate;
750
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800751 LOGE("The given camcorder profile param id %d name %s is not found", cameraId, name);
James Dongc3711942010-01-19 17:45:38 -0800752 return -1;
753}
754
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800755Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const
James Dong9b433f02010-02-23 17:21:44 -0800756{
Chih-Chung Chang09b90052010-06-22 20:50:55 +0800757 Vector<int> result;
758 ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
759 if (levels != NULL) {
760 result = levels->mLevels; // copy out
761 }
762 return result;
James Dong9b433f02010-02-23 17:21:44 -0800763}
764
James Dongc3711942010-01-19 17:45:38 -0800765MediaProfiles::~MediaProfiles()
766{
767 CHECK("destructor should never be called" == 0);
768#if 0
769 for (size_t i = 0; i < mAudioEncoders.size(); ++i) {
770 delete mAudioEncoders[i];
771 }
772 mAudioEncoders.clear();
773
774 for (size_t i = 0; i < mVideoEncoders.size(); ++i) {
775 delete mVideoEncoders[i];
776 }
777 mVideoEncoders.clear();
778
779 for (size_t i = 0; i < mVideoDecoders.size(); ++i) {
780 delete mVideoDecoders[i];
781 }
782 mVideoDecoders.clear();
783
784 for (size_t i = 0; i < mAudioDecoders.size(); ++i) {
785 delete mAudioDecoders[i];
786 }
787 mAudioDecoders.clear();
788
789 for (size_t i = 0; i < mCamcorderProfiles.size(); ++i) {
790 delete mCamcorderProfiles[i];
791 }
792 mCamcorderProfiles.clear();
793#endif
794}
795} // namespace android