blob: 67d33fad5b0c5b12f73318eafde5e356c8652b2a [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>
Elliott Hughes242b4002015-07-10 11:09:23 -070026#include <expat.h>
James Dong1d7491b2010-01-19 17:45:38 -080027#include <media/MediaProfiles.h>
James Dongf1d5aa12012-02-06 23:46:37 -080028#include <media/stagefright/foundation/ADebug.h>
James Dong6c6b4d02012-03-12 14:37:53 -070029#include <OMX_Video.h>
Pawin Vongmasad7db05b2017-05-03 04:19:20 -070030#include <sys/stat.h>
James Dong1d7491b2010-01-19 17:45:38 -080031
Pawin Vongmasa7f5e10e2020-03-07 04:09:55 -080032#include <array>
33#include <string>
34#include <vector>
35
James Dong1d7491b2010-01-19 17:45:38 -080036namespace android {
37
Pawin Vongmasa7f5e10e2020-03-07 04:09:55 -080038namespace /* unnamed */ {
39
40// Returns a list of possible paths for the media_profiles XML file.
41std::array<char const*, 5> const& getXmlPaths() {
42 static std::array<std::string const, 5> const paths =
43 []() -> decltype(paths) {
44 // Directories for XML file that will be searched (in this order).
45 constexpr std::array<char const*, 4> searchDirs = {
46 "product/etc/",
47 "odm/etc/",
48 "vendor/etc/",
49 "system/etc/",
50 };
51
52 // The file name may contain a variant if the vendor property
53 // ro.vendor.media_profiles_xml_variant is set.
54 char variant[PROPERTY_VALUE_MAX];
55 property_get("ro.media.xml_variant.profiles",
56 variant,
57 "_V1_0");
58
59 std::string fileName =
60 std::string("media_profiles") + variant + ".xml";
61
62 return { searchDirs[0] + fileName,
63 searchDirs[1] + fileName,
64 searchDirs[2] + fileName,
65 searchDirs[3] + fileName,
Matthias Springer0f44db02020-08-14 14:32:05 +090066 "system/etc/media_profiles.xml" // System fallback
Pawin Vongmasa7f5e10e2020-03-07 04:09:55 -080067 };
68 }();
69 static std::array<char const*, 5> const cPaths = {
70 paths[0].data(),
71 paths[1].data(),
72 paths[2].data(),
73 paths[3].data(),
74 paths[4].data()
75 };
76 return cPaths;
77}
78
79} // unnamed namespace
80
James Dong1d7491b2010-01-19 17:45:38 -080081Mutex MediaProfiles::sLock;
82bool MediaProfiles::sIsInitialized = false;
83MediaProfiles *MediaProfiles::sInstance = NULL;
84
85const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = {
86 {"h263", VIDEO_ENCODER_H263},
87 {"h264", VIDEO_ENCODER_H264},
Wonsik Kim9aa87d42015-12-07 13:52:02 +090088 {"m4v", VIDEO_ENCODER_MPEG_4_SP},
89 {"hevc", VIDEO_ENCODER_HEVC}
James Dong1d7491b2010-01-19 17:45:38 -080090};
91
92const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
Dave Burkeaeb8fd42012-04-19 00:14:27 -070093 {"amrnb", AUDIO_ENCODER_AMR_NB},
94 {"amrwb", AUDIO_ENCODER_AMR_WB},
95 {"aac", AUDIO_ENCODER_AAC},
Dave Burkef60c6602012-04-28 21:58:22 -070096 {"heaac", AUDIO_ENCODER_HE_AAC},
Pawin Vongmasa7f5e10e2020-03-07 04:09:55 -080097 {"aaceld", AUDIO_ENCODER_AAC_ELD},
Ray Essickdf27b042018-11-27 18:55:09 -080098 {"opus", AUDIO_ENCODER_OPUS}
James Dong1d7491b2010-01-19 17:45:38 -080099};
100
101const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = {
102 {"3gp", OUTPUT_FORMAT_THREE_GPP},
103 {"mp4", OUTPUT_FORMAT_MPEG_4}
104};
105
106const MediaProfiles::NameToTagMap MediaProfiles::sVideoDecoderNameMap[] = {
107 {"wmv", VIDEO_DECODER_WMV}
108};
109
110const MediaProfiles::NameToTagMap MediaProfiles::sAudioDecoderNameMap[] = {
111 {"wma", AUDIO_DECODER_WMA}
112};
113
114const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = {
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700115 {"low", CAMCORDER_QUALITY_LOW},
James Dong1d7491b2010-01-19 17:45:38 -0800116 {"high", CAMCORDER_QUALITY_HIGH},
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700117 {"qcif", CAMCORDER_QUALITY_QCIF},
Nipun Kwatra9783ed82010-09-10 15:45:57 -0700118 {"cif", CAMCORDER_QUALITY_CIF},
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700119 {"480p", CAMCORDER_QUALITY_480P},
120 {"720p", CAMCORDER_QUALITY_720P},
121 {"1080p", CAMCORDER_QUALITY_1080P},
Zhijun He5f6af1a2014-06-10 08:26:33 -0700122 {"2160p", CAMCORDER_QUALITY_2160P},
James Dong669012d2011-09-19 16:27:31 -0700123 {"qvga", CAMCORDER_QUALITY_QVGA},
Lajos Molnar5e35f772021-02-06 00:33:07 -0800124 {"vga", CAMCORDER_QUALITY_VGA},
125 {"4kdci", CAMCORDER_QUALITY_4KDCI},
126 {"qhd", CAMCORDER_QUALITY_QHD},
127 {"2k", CAMCORDER_QUALITY_2K},
128 {"8kuhd", CAMCORDER_QUALITY_8KUHD},
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700129
130 {"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW},
131 {"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH},
132 {"timelapseqcif", CAMCORDER_QUALITY_TIME_LAPSE_QCIF},
Nipun Kwatra9783ed82010-09-10 15:45:57 -0700133 {"timelapsecif", CAMCORDER_QUALITY_TIME_LAPSE_CIF},
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700134 {"timelapse480p", CAMCORDER_QUALITY_TIME_LAPSE_480P},
135 {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P},
James Dong669012d2011-09-19 16:27:31 -0700136 {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P},
Zhijun He5f6af1a2014-06-10 08:26:33 -0700137 {"timelapse2160p", CAMCORDER_QUALITY_TIME_LAPSE_2160P},
James Dong669012d2011-09-19 16:27:31 -0700138 {"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA},
Lajos Molnar5e35f772021-02-06 00:33:07 -0800139 {"timelapsevga", CAMCORDER_QUALITY_TIME_LAPSE_VGA},
140 {"timelapse4kdci", CAMCORDER_QUALITY_TIME_LAPSE_4KDCI},
141 {"timelapseqhd", CAMCORDER_QUALITY_TIME_LAPSE_QHD},
142 {"timelapse2k", CAMCORDER_QUALITY_TIME_LAPSE_2K},
Zhijun Hee0790972014-07-23 15:17:26 -0700143
144 {"highspeedlow", CAMCORDER_QUALITY_HIGH_SPEED_LOW},
145 {"highspeedhigh", CAMCORDER_QUALITY_HIGH_SPEED_HIGH},
146 {"highspeed480p", CAMCORDER_QUALITY_HIGH_SPEED_480P},
147 {"highspeed720p", CAMCORDER_QUALITY_HIGH_SPEED_720P},
148 {"highspeed1080p", CAMCORDER_QUALITY_HIGH_SPEED_1080P},
Zhijun He9520aa62014-09-09 16:18:31 -0700149 {"highspeed2160p", CAMCORDER_QUALITY_HIGH_SPEED_2160P},
Praveen Chavanb5bfa0e2019-01-16 15:49:42 -0800150 {"highspeedcif", CAMCORDER_QUALITY_HIGH_SPEED_CIF},
151 {"highspeedvga", CAMCORDER_QUALITY_HIGH_SPEED_VGA},
152 {"highspeed4kdci", CAMCORDER_QUALITY_HIGH_SPEED_4KDCI},
Lajos Molnar5e35f772021-02-06 00:33:07 -0800153
154 // Vendor-specific profiles
James Dong1d7491b2010-01-19 17:45:38 -0800155};
156
Glenn Kasten80520382014-01-31 16:49:31 -0800157#if LOG_NDEBUG
158#define UNUSED __unused
159#else
160#define UNUSED
161#endif
162
James Dong1d7491b2010-01-19 17:45:38 -0800163/*static*/ void
Glenn Kasten80520382014-01-31 16:49:31 -0800164MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec UNUSED)
James Dong1d7491b2010-01-19 17:45:38 -0800165{
Steve Block3856b092011-10-20 11:56:00 +0100166 ALOGV("video codec:");
167 ALOGV("codec = %d", codec.mCodec);
168 ALOGV("bit rate: %d", codec.mBitRate);
169 ALOGV("frame width: %d", codec.mFrameWidth);
170 ALOGV("frame height: %d", codec.mFrameHeight);
171 ALOGV("frame rate: %d", codec.mFrameRate);
Lajos Molnar28091432021-05-03 20:42:32 -0700172 ALOGV("profile: %d", codec.mProfile);
James Dong1d7491b2010-01-19 17:45:38 -0800173}
174
175/*static*/ void
Glenn Kasten80520382014-01-31 16:49:31 -0800176MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec UNUSED)
James Dong1d7491b2010-01-19 17:45:38 -0800177{
Steve Block3856b092011-10-20 11:56:00 +0100178 ALOGV("audio codec:");
179 ALOGV("codec = %d", codec.mCodec);
180 ALOGV("bit rate: %d", codec.mBitRate);
181 ALOGV("sample rate: %d", codec.mSampleRate);
182 ALOGV("number of channels: %d", codec.mChannels);
Lajos Molnar28091432021-05-03 20:42:32 -0700183 ALOGV("profile: %d", codec.mProfile);
James Dong1d7491b2010-01-19 17:45:38 -0800184}
185
186/*static*/ void
Glenn Kasten80520382014-01-31 16:49:31 -0800187MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap UNUSED)
James Dong1d7491b2010-01-19 17:45:38 -0800188{
Steve Block3856b092011-10-20 11:56:00 +0100189 ALOGV("video encoder cap:");
190 ALOGV("codec = %d", cap.mCodec);
191 ALOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate);
192 ALOGV("frame width: min = %d and max = %d", cap.mMinFrameWidth, cap.mMaxFrameWidth);
193 ALOGV("frame height: min = %d and max = %d", cap.mMinFrameHeight, cap.mMaxFrameHeight);
194 ALOGV("frame rate: min = %d and max = %d", cap.mMinFrameRate, cap.mMaxFrameRate);
James Dong1d7491b2010-01-19 17:45:38 -0800195}
196
197/*static*/ void
Glenn Kasten80520382014-01-31 16:49:31 -0800198MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap UNUSED)
James Dong1d7491b2010-01-19 17:45:38 -0800199{
Steve Block3856b092011-10-20 11:56:00 +0100200 ALOGV("audio encoder cap:");
201 ALOGV("codec = %d", cap.mCodec);
202 ALOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate);
203 ALOGV("sample rate: min = %d and max = %d", cap.mMinSampleRate, cap.mMaxSampleRate);
204 ALOGV("number of channels: min = %d and max = %d", cap.mMinChannels, cap.mMaxChannels);
James Dong1d7491b2010-01-19 17:45:38 -0800205}
206
207/*static*/ void
Glenn Kasten80520382014-01-31 16:49:31 -0800208MediaProfiles::logVideoDecoderCap(const MediaProfiles::VideoDecoderCap& cap UNUSED)
James Dong1d7491b2010-01-19 17:45:38 -0800209{
Steve Block3856b092011-10-20 11:56:00 +0100210 ALOGV("video decoder cap:");
211 ALOGV("codec = %d", cap.mCodec);
James Dong1d7491b2010-01-19 17:45:38 -0800212}
213
214/*static*/ void
Glenn Kasten80520382014-01-31 16:49:31 -0800215MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap UNUSED)
James Dong1d7491b2010-01-19 17:45:38 -0800216{
Steve Block3856b092011-10-20 11:56:00 +0100217 ALOGV("audio codec cap:");
218 ALOGV("codec = %d", cap.mCodec);
James Dong1d7491b2010-01-19 17:45:38 -0800219}
220
221/*static*/ int
Glenn Kastenb187de12014-12-30 08:18:15 -0800222MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings,
223 const char *name)
James Dong1d7491b2010-01-19 17:45:38 -0800224{
225 int tag = -1;
226 for (size_t i = 0; i < nMappings; ++i) {
227 if (!strcmp(map[i].name, name)) {
228 tag = map[i].tag;
229 break;
230 }
231 }
232 return tag;
233}
234
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700235/*static*/ void
Lajos Molnar28091432021-05-03 20:42:32 -0700236MediaProfiles::createVideoCodec(const char **atts, size_t natts, MediaProfiles *profiles)
James Dong1d7491b2010-01-19 17:45:38 -0800237{
Lajos Molnar28091432021-05-03 20:42:32 -0700238 CHECK(natts >= 10 &&
239 !strcmp("codec", atts[0]) &&
James Dong1d7491b2010-01-19 17:45:38 -0800240 !strcmp("bitRate", atts[2]) &&
241 !strcmp("width", atts[4]) &&
242 !strcmp("height", atts[6]) &&
243 !strcmp("frameRate", atts[8]));
244
245 const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
246 const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
Alex Zhang032f7a12020-04-17 16:08:24 -0700247 if (codec == -1) {
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700248 ALOGE("MediaProfiles::createVideoCodec failed to locate codec %s", atts[1]);
249 return;
Alex Zhang032f7a12020-04-17 16:08:24 -0700250 }
James Dong1d7491b2010-01-19 17:45:38 -0800251
Lajos Molnar28091432021-05-03 20:42:32 -0700252 int profile = -1;
253 if (natts >= 12 && !strcmp("profile", atts[10])) {
254 profile = atoi(atts[11]);
255 }
256
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700257 VideoCodec videoCodec {
258 static_cast<video_encoder>(codec),
Lajos Molnar28091432021-05-03 20:42:32 -0700259 atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), profile };
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700260 logVideoCodec(videoCodec);
James Dong1d7491b2010-01-19 17:45:38 -0800261
262 size_t nCamcorderProfiles;
263 CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700264 profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mVideoCodecs.emplace_back(videoCodec);
James Dong1d7491b2010-01-19 17:45:38 -0800265}
266
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700267/*static*/ void
Lajos Molnar28091432021-05-03 20:42:32 -0700268MediaProfiles::createAudioCodec(const char **atts, size_t natts, MediaProfiles *profiles)
James Dong1d7491b2010-01-19 17:45:38 -0800269{
Lajos Molnar28091432021-05-03 20:42:32 -0700270 CHECK(natts >= 8 &&
271 !strcmp("codec", atts[0]) &&
James Dong1d7491b2010-01-19 17:45:38 -0800272 !strcmp("bitRate", atts[2]) &&
273 !strcmp("sampleRate", atts[4]) &&
274 !strcmp("channels", atts[6]));
275 const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
276 const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
Alex Zhang032f7a12020-04-17 16:08:24 -0700277 if (codec == -1) {
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700278 ALOGE("MediaProfiles::createAudioCodec failed to locate codec %s", atts[1]);
279 return;
Alex Zhang032f7a12020-04-17 16:08:24 -0700280 }
James Dong1d7491b2010-01-19 17:45:38 -0800281
Lajos Molnar28091432021-05-03 20:42:32 -0700282 int profile = -1;
283 if (natts >= 10 && !strcmp("profile", atts[8])) {
284 profile = atoi(atts[9]);
285 }
286
287 AudioCodec audioCodec{
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700288 static_cast<audio_encoder>(codec),
Lajos Molnar28091432021-05-03 20:42:32 -0700289 atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), profile };
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700290 logAudioCodec(audioCodec);
James Dong1d7491b2010-01-19 17:45:38 -0800291
292 size_t nCamcorderProfiles;
293 CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700294 profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mAudioCodecs.emplace_back(audioCodec);
James Dong1d7491b2010-01-19 17:45:38 -0800295}
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700296
James Dong1d7491b2010-01-19 17:45:38 -0800297/*static*/ MediaProfiles::AudioDecoderCap*
Lajos Molnar28091432021-05-03 20:42:32 -0700298MediaProfiles::createAudioDecoderCap(const char **atts, size_t natts)
James Dong1d7491b2010-01-19 17:45:38 -0800299{
Lajos Molnar28091432021-05-03 20:42:32 -0700300 CHECK(natts >= 4 &&
301 !strcmp("name", atts[0]) &&
James Dong1d7491b2010-01-19 17:45:38 -0800302 !strcmp("enabled", atts[2]));
303
304 const size_t nMappings = sizeof(sAudioDecoderNameMap)/sizeof(sAudioDecoderNameMap[0]);
305 const int codec = findTagForName(sAudioDecoderNameMap, nMappings, atts[1]);
Alex Zhang032f7a12020-04-17 16:08:24 -0700306 if (codec == -1) {
307 ALOGE("MediaProfiles::createAudioDecoderCap failed to locate codec %s", atts[1]);
308 return nullptr;
309 }
James Dong1d7491b2010-01-19 17:45:38 -0800310
311 MediaProfiles::AudioDecoderCap *cap =
312 new MediaProfiles::AudioDecoderCap(static_cast<audio_decoder>(codec));
313 logAudioDecoderCap(*cap);
314 return cap;
315}
316
317/*static*/ MediaProfiles::VideoDecoderCap*
Lajos Molnar28091432021-05-03 20:42:32 -0700318MediaProfiles::createVideoDecoderCap(const char **atts, size_t natts)
James Dong1d7491b2010-01-19 17:45:38 -0800319{
Lajos Molnar28091432021-05-03 20:42:32 -0700320 CHECK(natts >= 4 &&
321 !strcmp("name", atts[0]) &&
James Dong1d7491b2010-01-19 17:45:38 -0800322 !strcmp("enabled", atts[2]));
323
324 const size_t nMappings = sizeof(sVideoDecoderNameMap)/sizeof(sVideoDecoderNameMap[0]);
325 const int codec = findTagForName(sVideoDecoderNameMap, nMappings, atts[1]);
Alex Zhang032f7a12020-04-17 16:08:24 -0700326 if (codec == -1) {
327 ALOGE("MediaProfiles::createVideoDecoderCap failed to locate codec %s", atts[1]);
328 return nullptr;
329 }
James Dong1d7491b2010-01-19 17:45:38 -0800330
331 MediaProfiles::VideoDecoderCap *cap =
332 new MediaProfiles::VideoDecoderCap(static_cast<video_decoder>(codec));
333 logVideoDecoderCap(*cap);
334 return cap;
335}
336
337/*static*/ MediaProfiles::VideoEncoderCap*
Lajos Molnar28091432021-05-03 20:42:32 -0700338MediaProfiles::createVideoEncoderCap(const char **atts, size_t natts)
James Dong1d7491b2010-01-19 17:45:38 -0800339{
Lajos Molnar28091432021-05-03 20:42:32 -0700340 CHECK(natts >= 20 &&
341 !strcmp("name", atts[0]) &&
James Dong1d7491b2010-01-19 17:45:38 -0800342 !strcmp("enabled", atts[2]) &&
343 !strcmp("minBitRate", atts[4]) &&
344 !strcmp("maxBitRate", atts[6]) &&
345 !strcmp("minFrameWidth", atts[8]) &&
346 !strcmp("maxFrameWidth", atts[10]) &&
347 !strcmp("minFrameHeight", atts[12]) &&
348 !strcmp("maxFrameHeight", atts[14]) &&
349 !strcmp("minFrameRate", atts[16]) &&
350 !strcmp("maxFrameRate", atts[18]));
351
352 const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
353 const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
Alex Zhang032f7a12020-04-17 16:08:24 -0700354 if (codec == -1) {
355 ALOGE("MediaProfiles::createVideoEncoderCap failed to locate codec %s", atts[1]);
356 return nullptr;
357 }
James Dong1d7491b2010-01-19 17:45:38 -0800358
359 MediaProfiles::VideoEncoderCap *cap =
360 new MediaProfiles::VideoEncoderCap(static_cast<video_encoder>(codec),
361 atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]),
362 atoi(atts[15]), atoi(atts[17]), atoi(atts[19]));
363 logVideoEncoderCap(*cap);
364 return cap;
365}
366
367/*static*/ MediaProfiles::AudioEncoderCap*
Lajos Molnar28091432021-05-03 20:42:32 -0700368MediaProfiles::createAudioEncoderCap(const char **atts, size_t natts)
James Dong1d7491b2010-01-19 17:45:38 -0800369{
Lajos Molnar28091432021-05-03 20:42:32 -0700370 CHECK(natts >= 16 &&
371 !strcmp("name", atts[0]) &&
James Dong1d7491b2010-01-19 17:45:38 -0800372 !strcmp("enabled", atts[2]) &&
373 !strcmp("minBitRate", atts[4]) &&
374 !strcmp("maxBitRate", atts[6]) &&
375 !strcmp("minSampleRate", atts[8]) &&
376 !strcmp("maxSampleRate", atts[10]) &&
377 !strcmp("minChannels", atts[12]) &&
378 !strcmp("maxChannels", atts[14]));
379
380 const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
381 const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
Alex Zhang032f7a12020-04-17 16:08:24 -0700382 if (codec == -1) {
383 ALOGE("MediaProfiles::createAudioEncoderCap failed to locate codec %s", atts[1]);
384 return nullptr;
385 }
James Dong1d7491b2010-01-19 17:45:38 -0800386
387 MediaProfiles::AudioEncoderCap *cap =
Glenn Kastenb187de12014-12-30 08:18:15 -0800388 new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]),
389 atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]), atoi(atts[15]));
James Dong1d7491b2010-01-19 17:45:38 -0800390 logAudioEncoderCap(*cap);
391 return cap;
392}
393
394/*static*/ output_format
Lajos Molnar28091432021-05-03 20:42:32 -0700395MediaProfiles::createEncoderOutputFileFormat(const char **atts, size_t natts)
James Dong1d7491b2010-01-19 17:45:38 -0800396{
Lajos Molnar28091432021-05-03 20:42:32 -0700397 CHECK(natts >= 2 &&
398 !strcmp("name", atts[0]));
James Dong1d7491b2010-01-19 17:45:38 -0800399
400 const size_t nMappings =sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
401 const int format = findTagForName(sFileFormatMap, nMappings, atts[1]);
402 CHECK(format != -1);
403
404 return static_cast<output_format>(format);
405}
406
James Dong2a7e0a12011-02-28 21:07:39 -0800407static bool isCameraIdFound(int cameraId, const Vector<int>& cameraIds) {
408 for (int i = 0, n = cameraIds.size(); i < n; ++i) {
409 if (cameraId == cameraIds[i]) {
410 return true;
411 }
412 }
413 return false;
414}
415
James Dong1d7491b2010-01-19 17:45:38 -0800416/*static*/ MediaProfiles::CamcorderProfile*
Lajos Molnar28091432021-05-03 20:42:32 -0700417MediaProfiles::createCamcorderProfile(
418 int cameraId, const char **atts, size_t natts, Vector<int>& cameraIds)
James Dong1d7491b2010-01-19 17:45:38 -0800419{
Lajos Molnar28091432021-05-03 20:42:32 -0700420 CHECK(natts >= 6 &&
421 !strcmp("quality", atts[0]) &&
James Dong1d7491b2010-01-19 17:45:38 -0800422 !strcmp("fileFormat", atts[2]) &&
423 !strcmp("duration", atts[4]));
424
Glenn Kastenb187de12014-12-30 08:18:15 -0800425 const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/
426 sizeof(sCamcorderQualityNameMap[0]);
James Dong1d7491b2010-01-19 17:45:38 -0800427 const int quality = findTagForName(sCamcorderQualityNameMap, nProfileMappings, atts[1]);
Alex Zhang032f7a12020-04-17 16:08:24 -0700428 if (quality == -1) {
429 ALOGE("MediaProfiles::createCamcorderProfile failed to locate quality %s", atts[1]);
430 return nullptr;
431 }
James Dong1d7491b2010-01-19 17:45:38 -0800432
433 const size_t nFormatMappings = sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
434 const int fileFormat = findTagForName(sFileFormatMap, nFormatMappings, atts[3]);
Alex Zhang032f7a12020-04-17 16:08:24 -0700435 if (fileFormat == -1) {
436 ALOGE("MediaProfiles::createCamcorderProfile failed to locate file format %s", atts[1]);
437 return nullptr;
438 }
James Dong1d7491b2010-01-19 17:45:38 -0800439
440 MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800441 profile->mCameraId = cameraId;
James Dong2a7e0a12011-02-28 21:07:39 -0800442 if (!isCameraIdFound(cameraId, cameraIds)) {
443 cameraIds.add(cameraId);
444 }
James Dong1d7491b2010-01-19 17:45:38 -0800445 profile->mFileFormat = static_cast<output_format>(fileFormat);
446 profile->mQuality = static_cast<camcorder_quality>(quality);
447 profile->mDuration = atoi(atts[5]);
448 return profile;
449}
450
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800451MediaProfiles::ImageEncodingQualityLevels*
452MediaProfiles::findImageEncodingQualityLevels(int cameraId) const
453{
454 int n = mImageEncodingQualityLevels.size();
455 for (int i = 0; i < n; i++) {
456 ImageEncodingQualityLevels *levels = mImageEncodingQualityLevels[i];
457 if (levels->mCameraId == cameraId) {
458 return levels;
459 }
460 }
461 return NULL;
462}
463
Lajos Molnar28091432021-05-03 20:42:32 -0700464void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts, size_t natts)
James Dongf5a83852010-02-23 17:21:44 -0800465{
Lajos Molnar28091432021-05-03 20:42:32 -0700466 CHECK(natts >= 2 &&
467 !strcmp("quality", atts[0]));
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800468 int quality = atoi(atts[1]);
Glenn Kasten90bebef2012-01-27 15:24:38 -0800469 ALOGV("%s: cameraId=%d, quality=%d", __func__, cameraId, quality);
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800470 ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
471
472 if (levels == NULL) {
473 levels = new ImageEncodingQualityLevels();
474 levels->mCameraId = cameraId;
475 mImageEncodingQualityLevels.add(levels);
476 }
477
478 levels->mLevels.add(quality);
479}
480
481/*static*/ int
Lajos Molnar28091432021-05-03 20:42:32 -0700482MediaProfiles::getCameraId(const char** atts, size_t natts)
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800483{
484 if (!atts[0]) return 0; // default cameraId = 0
Lajos Molnar28091432021-05-03 20:42:32 -0700485 CHECK(natts >= 2 &&
486 !strcmp("cameraId", atts[0]));
James Dongf5a83852010-02-23 17:21:44 -0800487 return atoi(atts[1]);
488}
489
Lajos Molnar28091432021-05-03 20:42:32 -0700490void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts, size_t natts)
James Dong0f056292011-05-09 18:49:31 -0700491{
Eric Laurentb1eb1a02012-10-22 17:44:24 -0700492 int offsetTimeMs = 1000;
Lajos Molnar28091432021-05-03 20:42:32 -0700493 if (natts >= 3 && atts[2]) {
494 CHECK(natts >= 4 && !strcmp("startOffsetMs", atts[2]));
James Dong0f056292011-05-09 18:49:31 -0700495 offsetTimeMs = atoi(atts[3]);
496 }
497
Steve Block3856b092011-10-20 11:56:00 +0100498 ALOGV("%s: cameraId=%d, offset=%d ms", __func__, cameraId, offsetTimeMs);
James Dong0f056292011-05-09 18:49:31 -0700499 mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs);
500}
Hong Tengcabd5f82011-07-06 18:33:09 -0700501
James Dong1d7491b2010-01-19 17:45:38 -0800502/*static*/ void
503MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
504{
Lajos Molnar28091432021-05-03 20:42:32 -0700505 // determine number of attributes
506 size_t natts = 0;
507 while (atts[natts]) {
508 ++natts;
509 }
510
511 MediaProfiles *profiles = (MediaProfiles *)userData;
James Dong1d7491b2010-01-19 17:45:38 -0800512 if (strcmp("Video", name) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700513 createVideoCodec(atts, natts, profiles);
James Dong1d7491b2010-01-19 17:45:38 -0800514 } else if (strcmp("Audio", name) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700515 createAudioCodec(atts, natts, profiles);
James Dong1d7491b2010-01-19 17:45:38 -0800516 } else if (strcmp("VideoEncoderCap", name) == 0 &&
Lajos Molnar28091432021-05-03 20:42:32 -0700517 natts >= 4 &&
James Dong1d7491b2010-01-19 17:45:38 -0800518 strcmp("true", atts[3]) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700519 MediaProfiles::VideoEncoderCap* cap = createVideoEncoderCap(atts, natts);
Alex Zhang032f7a12020-04-17 16:08:24 -0700520 if (cap != nullptr) {
521 profiles->mVideoEncoders.add(cap);
522 }
James Dong1d7491b2010-01-19 17:45:38 -0800523 } else if (strcmp("AudioEncoderCap", name) == 0 &&
Lajos Molnar28091432021-05-03 20:42:32 -0700524 natts >= 4 &&
James Dong1d7491b2010-01-19 17:45:38 -0800525 strcmp("true", atts[3]) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700526 MediaProfiles::AudioEncoderCap* cap = createAudioEncoderCap(atts, natts);
Alex Zhang032f7a12020-04-17 16:08:24 -0700527 if (cap != nullptr) {
528 profiles->mAudioEncoders.add(cap);
529 }
James Dong1d7491b2010-01-19 17:45:38 -0800530 } else if (strcmp("VideoDecoderCap", name) == 0 &&
Lajos Molnar28091432021-05-03 20:42:32 -0700531 natts >= 4 &&
James Dong1d7491b2010-01-19 17:45:38 -0800532 strcmp("true", atts[3]) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700533 MediaProfiles::VideoDecoderCap* cap = createVideoDecoderCap(atts, natts);
Alex Zhang032f7a12020-04-17 16:08:24 -0700534 if (cap != nullptr) {
535 profiles->mVideoDecoders.add(cap);
536 }
James Dong1d7491b2010-01-19 17:45:38 -0800537 } else if (strcmp("AudioDecoderCap", name) == 0 &&
Lajos Molnar28091432021-05-03 20:42:32 -0700538 natts >= 4 &&
James Dong1d7491b2010-01-19 17:45:38 -0800539 strcmp("true", atts[3]) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700540 MediaProfiles::AudioDecoderCap* cap = createAudioDecoderCap(atts, natts);
Alex Zhang032f7a12020-04-17 16:08:24 -0700541 if (cap != nullptr) {
542 profiles->mAudioDecoders.add(cap);
543 }
James Dong1d7491b2010-01-19 17:45:38 -0800544 } else if (strcmp("EncoderOutputFileFormat", name) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700545 profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts, natts));
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800546 } else if (strcmp("CamcorderProfiles", name) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700547 profiles->mCurrentCameraId = getCameraId(atts, natts);
548 profiles->addStartTimeOffset(profiles->mCurrentCameraId, atts, natts);
James Dong1d7491b2010-01-19 17:45:38 -0800549 } else if (strcmp("EncoderProfile", name) == 0) {
Alex Zhang032f7a12020-04-17 16:08:24 -0700550 MediaProfiles::CamcorderProfile* profile = createCamcorderProfile(
Lajos Molnar28091432021-05-03 20:42:32 -0700551 profiles->mCurrentCameraId, atts, natts, profiles->mCameraIds);
Alex Zhang032f7a12020-04-17 16:08:24 -0700552 if (profile != nullptr) {
553 profiles->mCamcorderProfiles.add(profile);
554 }
James Dongf5a83852010-02-23 17:21:44 -0800555 } else if (strcmp("ImageEncoding", name) == 0) {
Lajos Molnar28091432021-05-03 20:42:32 -0700556 profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts, natts);
James Dong1d7491b2010-01-19 17:45:38 -0800557 }
558}
559
James Dong2a7e0a12011-02-28 21:07:39 -0800560static bool isCamcorderProfile(camcorder_quality quality) {
561 return quality >= CAMCORDER_QUALITY_LIST_START &&
562 quality <= CAMCORDER_QUALITY_LIST_END;
563}
564
565static bool isTimelapseProfile(camcorder_quality quality) {
566 return quality >= CAMCORDER_QUALITY_TIME_LAPSE_LIST_START &&
567 quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END;
568}
569
Zhijun Hee0790972014-07-23 15:17:26 -0700570static bool isHighSpeedProfile(camcorder_quality quality) {
571 return quality >= CAMCORDER_QUALITY_HIGH_SPEED_LIST_START &&
572 quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END;
573}
574
James Dong2a7e0a12011-02-28 21:07:39 -0800575void MediaProfiles::initRequiredProfileRefs(const Vector<int>& cameraIds) {
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700576 ALOGV("Number of camera ids: %zu", cameraIds.size());
James Dong2a7e0a12011-02-28 21:07:39 -0800577 CHECK(cameraIds.size() > 0);
578 mRequiredProfileRefs = new RequiredProfiles[cameraIds.size()];
579 for (size_t i = 0, n = cameraIds.size(); i < n; ++i) {
580 mRequiredProfileRefs[i].mCameraId = cameraIds[i];
581 for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
582 mRequiredProfileRefs[i].mRefs[j].mHasRefProfile = false;
583 mRequiredProfileRefs[i].mRefs[j].mRefProfileIndex = -1;
584 if ((j & 1) == 0) { // low resolution
585 mRequiredProfileRefs[i].mRefs[j].mResolutionProduct = 0x7FFFFFFF;
586 } else { // high resolution
587 mRequiredProfileRefs[i].mRefs[j].mResolutionProduct = 0;
588 }
589 }
590 }
591}
592
593int MediaProfiles::getRequiredProfileRefIndex(int cameraId) {
594 for (size_t i = 0, n = mCameraIds.size(); i < n; ++i) {
595 if (mCameraIds[i] == cameraId) {
596 return i;
597 }
598 }
599 return -1;
600}
601
602void MediaProfiles::checkAndAddRequiredProfilesIfNecessary() {
603 if (sIsInitialized) {
604 return;
605 }
606
607 initRequiredProfileRefs(mCameraIds);
608
609 for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700610 // ensure at least one video and audio profile is added
Lajos Molnar28091432021-05-03 20:42:32 -0700611 if (mCamcorderProfiles[i]->mVideoCodecs.empty()) {
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700612 mCamcorderProfiles[i]->mVideoCodecs.emplace_back(
613 VIDEO_ENCODER_H263, 192000 /* bitrate */,
614 176 /* width */, 144 /* height */, 20 /* frameRate */);
615 }
Lajos Molnar28091432021-05-03 20:42:32 -0700616 if (mCamcorderProfiles[i]->mAudioCodecs.empty()) {
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700617 mCamcorderProfiles[i]->mAudioCodecs.emplace_back(
618 AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
619 8000 /* sampleRate */, 1 /* channels */);
620 }
621
622 int product = mCamcorderProfiles[i]->mVideoCodecs[0].mFrameWidth *
623 mCamcorderProfiles[i]->mVideoCodecs[0].mFrameHeight;
James Dong2a7e0a12011-02-28 21:07:39 -0800624
625 camcorder_quality quality = mCamcorderProfiles[i]->mQuality;
626 int cameraId = mCamcorderProfiles[i]->mCameraId;
627 int index = -1;
628 int refIndex = getRequiredProfileRefIndex(cameraId);
629 CHECK(refIndex != -1);
630 RequiredProfileRefInfo *info;
631 camcorder_quality refQuality;
James Dong2a7e0a12011-02-28 21:07:39 -0800632
Zhijun Hee0790972014-07-23 15:17:26 -0700633 // Check high and low from either camcorder profile, timelapse profile
634 // or high speed profile, but not all of them. Default, check camcorder profile
James Dong2a7e0a12011-02-28 21:07:39 -0800635 size_t j = 0;
Bernhard Rosenkraenzer3c8889e2012-03-29 11:38:59 +0200636 size_t o = 2;
James Dong2a7e0a12011-02-28 21:07:39 -0800637 if (isTimelapseProfile(quality)) {
638 // Check timelapse profile instead.
639 j = 2;
Bernhard Rosenkraenzer3c8889e2012-03-29 11:38:59 +0200640 o = kNumRequiredProfiles;
Zhijun Hee0790972014-07-23 15:17:26 -0700641 } else if (isHighSpeedProfile(quality)) {
642 // Skip the check for high speed profile.
643 continue;
James Dong2a7e0a12011-02-28 21:07:39 -0800644 } else {
645 // Must be camcorder profile.
646 CHECK(isCamcorderProfile(quality));
647 }
Bernhard Rosenkraenzer3c8889e2012-03-29 11:38:59 +0200648 for (; j < o; ++j) {
James Dong2a7e0a12011-02-28 21:07:39 -0800649 info = &(mRequiredProfileRefs[refIndex].mRefs[j]);
650 if ((j % 2 == 0 && product > info->mResolutionProduct) || // low
651 (j % 2 != 0 && product < info->mResolutionProduct)) { // high
652 continue;
653 }
654 switch (j) {
655 case 0:
656 refQuality = CAMCORDER_QUALITY_LOW;
657 break;
658 case 1:
659 refQuality = CAMCORDER_QUALITY_HIGH;
660 break;
661 case 2:
662 refQuality = CAMCORDER_QUALITY_TIME_LAPSE_LOW;
663 break;
664 case 3:
665 refQuality = CAMCORDER_QUALITY_TIME_LAPSE_HIGH;
666 break;
667 default:
668 CHECK(!"Should never reach here");
669 }
670
671 if (!info->mHasRefProfile) {
672 index = getCamcorderProfileIndex(cameraId, refQuality);
673 }
674 if (index == -1) {
675 // New high or low quality profile is found.
676 // Update its reference.
677 info->mHasRefProfile = true;
678 info->mRefProfileIndex = i;
679 info->mResolutionProduct = product;
680 }
681 }
682 }
683
684 for (size_t cameraId = 0; cameraId < mCameraIds.size(); ++cameraId) {
685 for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
686 int refIndex = getRequiredProfileRefIndex(cameraId);
687 CHECK(refIndex != -1);
688 RequiredProfileRefInfo *info =
689 &mRequiredProfileRefs[refIndex].mRefs[j];
690
691 if (info->mHasRefProfile) {
692
George Burgess IV215545b2018-07-25 10:06:30 -0700693 std::unique_ptr<CamcorderProfile> profile =
694 std::make_unique<CamcorderProfile>(
James Dong2a7e0a12011-02-28 21:07:39 -0800695 *mCamcorderProfiles[info->mRefProfileIndex]);
696
697 // Overwrite the quality
698 switch (j % kNumRequiredProfiles) {
699 case 0:
700 profile->mQuality = CAMCORDER_QUALITY_LOW;
701 break;
702 case 1:
703 profile->mQuality = CAMCORDER_QUALITY_HIGH;
704 break;
705 case 2:
706 profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_LOW;
707 break;
708 case 3:
709 profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_HIGH;
710 break;
711 default:
712 CHECK(!"Should never come here");
713 }
714
715 int index = getCamcorderProfileIndex(cameraId, profile->mQuality);
716 if (index != -1) {
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700717 ALOGV("Profile quality %d for camera %zu already exists",
James Dong2a7e0a12011-02-28 21:07:39 -0800718 profile->mQuality, cameraId);
719 CHECK(index == refIndex);
720 continue;
721 }
722
723 // Insert the new profile
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700724 ALOGV("Add a profile: quality %d=>%d for camera %zu",
James Dong2a7e0a12011-02-28 21:07:39 -0800725 mCamcorderProfiles[info->mRefProfileIndex]->mQuality,
726 profile->mQuality, cameraId);
727
George Burgess IV215545b2018-07-25 10:06:30 -0700728 mCamcorderProfiles.add(profile.release());
James Dong2a7e0a12011-02-28 21:07:39 -0800729 }
730 }
731 }
732}
733
James Dong1d7491b2010-01-19 17:45:38 -0800734/*static*/ MediaProfiles*
735MediaProfiles::getInstance()
736{
Steve Block3856b092011-10-20 11:56:00 +0100737 ALOGV("getInstance");
James Dong1d7491b2010-01-19 17:45:38 -0800738 Mutex::Autolock lock(sLock);
739 if (!sIsInitialized) {
740 char value[PROPERTY_VALUE_MAX];
741 if (property_get("media.settings.xml", value, NULL) <= 0) {
Pawin Vongmasad7db05b2017-05-03 04:19:20 -0700742 const char* xmlFile = nullptr;
Pawin Vongmasa7f5e10e2020-03-07 04:09:55 -0800743 for (auto const& f : getXmlPaths()) {
Pawin Vongmasad7db05b2017-05-03 04:19:20 -0700744 if (checkXmlFile(f)) {
745 xmlFile = f;
746 break;
747 }
748 }
749 if (xmlFile == nullptr) {
750 ALOGW("Could not find a validated xml file. "
751 "Using the default instance instead.");
James Dong1d7491b2010-01-19 17:45:38 -0800752 sInstance = createDefaultInstance();
753 } else {
Pawin Vongmasad7db05b2017-05-03 04:19:20 -0700754 sInstance = createInstanceFromXmlFile(xmlFile);
James Dong1d7491b2010-01-19 17:45:38 -0800755 }
756 } else {
757 sInstance = createInstanceFromXmlFile(value);
758 }
James Dong2a7e0a12011-02-28 21:07:39 -0800759 CHECK(sInstance != NULL);
760 sInstance->checkAndAddRequiredProfilesIfNecessary();
761 sIsInitialized = true;
James Dong1d7491b2010-01-19 17:45:38 -0800762 }
763
764 return sInstance;
765}
766
767/*static*/ MediaProfiles::VideoEncoderCap*
768MediaProfiles::createDefaultH263VideoEncoderCap()
769{
770 return new MediaProfiles::VideoEncoderCap(
771 VIDEO_ENCODER_H263, 192000, 420000, 176, 352, 144, 288, 1, 20);
772}
773
774/*static*/ MediaProfiles::VideoEncoderCap*
775MediaProfiles::createDefaultM4vVideoEncoderCap()
776{
777 return new MediaProfiles::VideoEncoderCap(
778 VIDEO_ENCODER_MPEG_4_SP, 192000, 420000, 176, 352, 144, 288, 1, 20);
779}
780
781
782/*static*/ void
783MediaProfiles::createDefaultVideoEncoders(MediaProfiles *profiles)
784{
785 profiles->mVideoEncoders.add(createDefaultH263VideoEncoderCap());
786 profiles->mVideoEncoders.add(createDefaultM4vVideoEncoderCap());
787}
788
789/*static*/ MediaProfiles::CamcorderProfile*
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700790MediaProfiles::createDefaultCamcorderTimeLapseQcifProfile(camcorder_quality quality)
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700791{
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700792 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
793 profile->mCameraId = 0;
794 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700795 profile->mQuality = quality;
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700796 profile->mDuration = 60;
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700797 profile->mVideoCodecs.emplace_back(
798 VIDEO_ENCODER_H263, 1000000 /* bitrate */,
799 176 /* width */, 144 /* height */, 20 /* frameRate */);
800 profile->mAudioCodecs.emplace_back(
801 AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
802 8000 /* sampleRate */, 1 /* channels */);
803
Nipun Kwatrac0a84782010-09-06 15:59:02 -0700804 return profile;
805}
806
807/*static*/ MediaProfiles::CamcorderProfile*
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700808MediaProfiles::createDefaultCamcorderTimeLapse480pProfile(camcorder_quality quality)
James Dong1d7491b2010-01-19 17:45:38 -0800809{
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800810 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
811 profile->mCameraId = 0;
James Dong1d7491b2010-01-19 17:45:38 -0800812 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700813 profile->mQuality = quality;
James Dong1d7491b2010-01-19 17:45:38 -0800814 profile->mDuration = 60;
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700815 profile->mVideoCodecs.emplace_back(
816 VIDEO_ENCODER_H263, 20000000 /* bitrate */,
817 720 /* width */, 480 /* height */, 20 /* frameRate */);
818 profile->mAudioCodecs.emplace_back(
819 AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
820 8000 /* sampleRate */, 1 /* channels */);
James Dong1d7491b2010-01-19 17:45:38 -0800821 return profile;
822}
823
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700824/*static*/ void
825MediaProfiles::createDefaultCamcorderTimeLapseLowProfiles(
826 MediaProfiles::CamcorderProfile **lowTimeLapseProfile,
827 MediaProfiles::CamcorderProfile **lowSpecificTimeLapseProfile) {
Glenn Kastenb187de12014-12-30 08:18:15 -0800828 *lowTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(
829 CAMCORDER_QUALITY_TIME_LAPSE_LOW);
830 *lowSpecificTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(
831 CAMCORDER_QUALITY_TIME_LAPSE_QCIF);
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700832}
833
834/*static*/ void
835MediaProfiles::createDefaultCamcorderTimeLapseHighProfiles(
836 MediaProfiles::CamcorderProfile **highTimeLapseProfile,
837 MediaProfiles::CamcorderProfile **highSpecificTimeLapseProfile) {
Glenn Kastenb187de12014-12-30 08:18:15 -0800838 *highTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(
839 CAMCORDER_QUALITY_TIME_LAPSE_HIGH);
840 *highSpecificTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(
841 CAMCORDER_QUALITY_TIME_LAPSE_480P);
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700842}
843
James Dong1d7491b2010-01-19 17:45:38 -0800844/*static*/ MediaProfiles::CamcorderProfile*
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700845MediaProfiles::createDefaultCamcorderQcifProfile(camcorder_quality quality)
James Dong1d7491b2010-01-19 17:45:38 -0800846{
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700847 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800848 profile->mCameraId = 0;
James Dong1d7491b2010-01-19 17:45:38 -0800849 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700850 profile->mQuality = quality;
James Dong1d7491b2010-01-19 17:45:38 -0800851 profile->mDuration = 30;
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700852 profile->mVideoCodecs.emplace_back(
853 VIDEO_ENCODER_H263, 192000 /* bitrate */,
854 176 /* width */, 144 /* height */, 20 /* frameRate */);
855 profile->mAudioCodecs.emplace_back(
856 AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
857 8000 /* sampleRate */, 1 /* channels */);
James Dong1d7491b2010-01-19 17:45:38 -0800858 return profile;
859}
860
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700861/*static*/ MediaProfiles::CamcorderProfile*
862MediaProfiles::createDefaultCamcorderCifProfile(camcorder_quality quality)
863{
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700864 CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
865 profile->mCameraId = 0;
866 profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
867 profile->mQuality = quality;
868 profile->mDuration = 60;
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -0700869 profile->mVideoCodecs.emplace_back(
870 VIDEO_ENCODER_H263, 360000 /* bitrate */,
871 352 /* width */, 288 /* height */, 20 /* frameRate */);
872 profile->mAudioCodecs.emplace_back(
873 AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
874 8000 /* sampleRate */, 1 /* channels */);
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700875 return profile;
876}
877
878/*static*/ void
879MediaProfiles::createDefaultCamcorderLowProfiles(
880 MediaProfiles::CamcorderProfile **lowProfile,
881 MediaProfiles::CamcorderProfile **lowSpecificProfile) {
882 *lowProfile = createDefaultCamcorderQcifProfile(CAMCORDER_QUALITY_LOW);
883 *lowSpecificProfile = createDefaultCamcorderQcifProfile(CAMCORDER_QUALITY_QCIF);
884}
885
886/*static*/ void
887MediaProfiles::createDefaultCamcorderHighProfiles(
888 MediaProfiles::CamcorderProfile **highProfile,
889 MediaProfiles::CamcorderProfile **highSpecificProfile) {
890 *highProfile = createDefaultCamcorderCifProfile(CAMCORDER_QUALITY_HIGH);
891 *highSpecificProfile = createDefaultCamcorderCifProfile(CAMCORDER_QUALITY_CIF);
892}
893
James Dong1d7491b2010-01-19 17:45:38 -0800894/*static*/ void
895MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles)
896{
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700897 // low camcorder profiles.
898 MediaProfiles::CamcorderProfile *lowProfile, *lowSpecificProfile;
899 createDefaultCamcorderLowProfiles(&lowProfile, &lowSpecificProfile);
900 profiles->mCamcorderProfiles.add(lowProfile);
901 profiles->mCamcorderProfiles.add(lowSpecificProfile);
902
903 // high camcorder profiles.
904 MediaProfiles::CamcorderProfile* highProfile, *highSpecificProfile;
905 createDefaultCamcorderHighProfiles(&highProfile, &highSpecificProfile);
906 profiles->mCamcorderProfiles.add(highProfile);
907 profiles->mCamcorderProfiles.add(highSpecificProfile);
908
909 // low camcorder time lapse profiles.
910 MediaProfiles::CamcorderProfile *lowTimeLapseProfile, *lowSpecificTimeLapseProfile;
911 createDefaultCamcorderTimeLapseLowProfiles(&lowTimeLapseProfile, &lowSpecificTimeLapseProfile);
912 profiles->mCamcorderProfiles.add(lowTimeLapseProfile);
913 profiles->mCamcorderProfiles.add(lowSpecificTimeLapseProfile);
914
915 // high camcorder time lapse profiles.
916 MediaProfiles::CamcorderProfile *highTimeLapseProfile, *highSpecificTimeLapseProfile;
Glenn Kastenb187de12014-12-30 08:18:15 -0800917 createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile,
918 &highSpecificTimeLapseProfile);
Nipun Kwatrad5672bc2010-09-16 22:25:23 -0700919 profiles->mCamcorderProfiles.add(highTimeLapseProfile);
920 profiles->mCamcorderProfiles.add(highSpecificTimeLapseProfile);
James Dong8031ec72011-03-16 14:09:50 -0700921
922 // For emulator and other legacy devices which does not have a
923 // media_profiles.xml file, We assume that the default camera id
924 // is 0 and that is the only camera available.
925 profiles->mCameraIds.push(0);
James Dong1d7491b2010-01-19 17:45:38 -0800926}
927
928/*static*/ void
929MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles)
930{
931 profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap());
932}
933
934/*static*/ void
935MediaProfiles::createDefaultVideoDecoders(MediaProfiles *profiles)
936{
937 MediaProfiles::VideoDecoderCap *cap =
938 new MediaProfiles::VideoDecoderCap(VIDEO_DECODER_WMV);
939
940 profiles->mVideoDecoders.add(cap);
941}
942
943/*static*/ void
944MediaProfiles::createDefaultAudioDecoders(MediaProfiles *profiles)
945{
946 MediaProfiles::AudioDecoderCap *cap =
947 new MediaProfiles::AudioDecoderCap(AUDIO_DECODER_WMA);
948
949 profiles->mAudioDecoders.add(cap);
950}
951
952/*static*/ void
953MediaProfiles::createDefaultEncoderOutputFileFormats(MediaProfiles *profiles)
954{
955 profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_THREE_GPP);
956 profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_MPEG_4);
957}
958
959/*static*/ MediaProfiles::AudioEncoderCap*
960MediaProfiles::createDefaultAmrNBEncoderCap()
961{
962 return new MediaProfiles::AudioEncoderCap(
963 AUDIO_ENCODER_AMR_NB, 5525, 12200, 8000, 8000, 1, 1);
964}
965
James Dongf5a83852010-02-23 17:21:44 -0800966/*static*/ void
967MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
968{
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +0800969 ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels();
970 levels->mCameraId = 0;
971 levels->mLevels.add(70);
972 levels->mLevels.add(80);
973 levels->mLevels.add(90);
974 profiles->mImageEncodingQualityLevels.add(levels);
James Dongf5a83852010-02-23 17:21:44 -0800975}
976
James Dong1d7491b2010-01-19 17:45:38 -0800977/*static*/ MediaProfiles*
978MediaProfiles::createDefaultInstance()
979{
980 MediaProfiles *profiles = new MediaProfiles;
981 createDefaultCamcorderProfiles(profiles);
982 createDefaultVideoEncoders(profiles);
983 createDefaultAudioEncoders(profiles);
984 createDefaultVideoDecoders(profiles);
985 createDefaultAudioDecoders(profiles);
986 createDefaultEncoderOutputFileFormats(profiles);
James Dongf5a83852010-02-23 17:21:44 -0800987 createDefaultImageEncodingQualityLevels(profiles);
James Dong1d7491b2010-01-19 17:45:38 -0800988 return profiles;
989}
990
Pawin Vongmasad7db05b2017-05-03 04:19:20 -0700991bool MediaProfiles::checkXmlFile(const char* xmlFile) {
992 struct stat fStat;
993 return stat(xmlFile, &fStat) == 0 && S_ISREG(fStat.st_mode);
994 // TODO: Add validation
995}
996
James Dong1d7491b2010-01-19 17:45:38 -0800997/*static*/ MediaProfiles*
998MediaProfiles::createInstanceFromXmlFile(const char *xml)
999{
1000 FILE *fp = NULL;
1001 CHECK((fp = fopen(xml, "r")));
1002
1003 XML_Parser parser = ::XML_ParserCreate(NULL);
1004 CHECK(parser != NULL);
1005
1006 MediaProfiles *profiles = new MediaProfiles();
1007 ::XML_SetUserData(parser, profiles);
1008 ::XML_SetElementHandler(parser, startElementHandler, NULL);
1009
1010 /*
1011 FIXME:
1012 expat is not compiled with -DXML_DTD. We don't have DTD parsing support.
1013
1014 if (!::XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS)) {
Steve Block29357bc2012-01-06 19:20:56 +00001015 ALOGE("failed to enable DTD support in the xml file");
James Dong1d7491b2010-01-19 17:45:38 -08001016 return UNKNOWN_ERROR;
1017 }
1018
1019 */
1020
1021 const int BUFF_SIZE = 512;
1022 for (;;) {
1023 void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
1024 if (buff == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +00001025 ALOGE("failed to in call to XML_GetBuffer()");
James Dong1d7491b2010-01-19 17:45:38 -08001026 delete profiles;
1027 profiles = NULL;
1028 goto exit;
1029 }
1030
1031 int bytes_read = ::fread(buff, 1, BUFF_SIZE, fp);
1032 if (bytes_read < 0) {
Steve Block29357bc2012-01-06 19:20:56 +00001033 ALOGE("failed in call to read");
James Dong1d7491b2010-01-19 17:45:38 -08001034 delete profiles;
1035 profiles = NULL;
1036 goto exit;
1037 }
1038
1039 CHECK(::XML_ParseBuffer(parser, bytes_read, bytes_read == 0));
1040
1041 if (bytes_read == 0) break; // done parsing the xml file
1042 }
1043
1044exit:
1045 ::XML_ParserFree(parser);
1046 ::fclose(fp);
James Dong1d7491b2010-01-19 17:45:38 -08001047 return profiles;
1048}
1049
1050Vector<output_format> MediaProfiles::getOutputFileFormats() const
1051{
1052 return mEncoderOutputFileFormats; // copy out
1053}
1054
1055Vector<video_encoder> MediaProfiles::getVideoEncoders() const
1056{
1057 Vector<video_encoder> encoders;
1058 for (size_t i = 0; i < mVideoEncoders.size(); ++i) {
1059 encoders.add(mVideoEncoders[i]->mCodec);
1060 }
1061 return encoders; // copy out
1062}
1063
1064int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder codec) const
1065{
Steve Block3856b092011-10-20 11:56:00 +01001066 ALOGV("getVideoEncoderParamByName: %s for codec %d", name, codec);
James Dong1d7491b2010-01-19 17:45:38 -08001067 int index = -1;
1068 for (size_t i = 0, n = mVideoEncoders.size(); i < n; ++i) {
1069 if (mVideoEncoders[i]->mCodec == codec) {
1070 index = i;
1071 break;
1072 }
1073 }
1074 if (index == -1) {
Steve Block29357bc2012-01-06 19:20:56 +00001075 ALOGE("The given video encoder %d is not found", codec);
James Dong1d7491b2010-01-19 17:45:38 -08001076 return -1;
1077 }
1078
1079 if (!strcmp("enc.vid.width.min", name)) return mVideoEncoders[index]->mMinFrameWidth;
1080 if (!strcmp("enc.vid.width.max", name)) return mVideoEncoders[index]->mMaxFrameWidth;
1081 if (!strcmp("enc.vid.height.min", name)) return mVideoEncoders[index]->mMinFrameHeight;
1082 if (!strcmp("enc.vid.height.max", name)) return mVideoEncoders[index]->mMaxFrameHeight;
1083 if (!strcmp("enc.vid.bps.min", name)) return mVideoEncoders[index]->mMinBitRate;
1084 if (!strcmp("enc.vid.bps.max", name)) return mVideoEncoders[index]->mMaxBitRate;
1085 if (!strcmp("enc.vid.fps.min", name)) return mVideoEncoders[index]->mMinFrameRate;
1086 if (!strcmp("enc.vid.fps.max", name)) return mVideoEncoders[index]->mMaxFrameRate;
1087
Steve Block29357bc2012-01-06 19:20:56 +00001088 ALOGE("The given video encoder param name %s is not found", name);
James Dong1d7491b2010-01-19 17:45:38 -08001089 return -1;
1090}
Hong Tengcabd5f82011-07-06 18:33:09 -07001091
James Dong1d7491b2010-01-19 17:45:38 -08001092Vector<audio_encoder> MediaProfiles::getAudioEncoders() const
1093{
1094 Vector<audio_encoder> encoders;
1095 for (size_t i = 0; i < mAudioEncoders.size(); ++i) {
1096 encoders.add(mAudioEncoders[i]->mCodec);
1097 }
1098 return encoders; // copy out
1099}
1100
1101int MediaProfiles::getAudioEncoderParamByName(const char *name, audio_encoder codec) const
1102{
Steve Block3856b092011-10-20 11:56:00 +01001103 ALOGV("getAudioEncoderParamByName: %s for codec %d", name, codec);
James Dong1d7491b2010-01-19 17:45:38 -08001104 int index = -1;
1105 for (size_t i = 0, n = mAudioEncoders.size(); i < n; ++i) {
1106 if (mAudioEncoders[i]->mCodec == codec) {
1107 index = i;
1108 break;
1109 }
1110 }
1111 if (index == -1) {
Steve Block29357bc2012-01-06 19:20:56 +00001112 ALOGE("The given audio encoder %d is not found", codec);
James Dong1d7491b2010-01-19 17:45:38 -08001113 return -1;
1114 }
1115
1116 if (!strcmp("enc.aud.ch.min", name)) return mAudioEncoders[index]->mMinChannels;
1117 if (!strcmp("enc.aud.ch.max", name)) return mAudioEncoders[index]->mMaxChannels;
1118 if (!strcmp("enc.aud.bps.min", name)) return mAudioEncoders[index]->mMinBitRate;
1119 if (!strcmp("enc.aud.bps.max", name)) return mAudioEncoders[index]->mMaxBitRate;
1120 if (!strcmp("enc.aud.hz.min", name)) return mAudioEncoders[index]->mMinSampleRate;
1121 if (!strcmp("enc.aud.hz.max", name)) return mAudioEncoders[index]->mMaxSampleRate;
1122
Steve Block29357bc2012-01-06 19:20:56 +00001123 ALOGE("The given audio encoder param name %s is not found", name);
James Dong1d7491b2010-01-19 17:45:38 -08001124 return -1;
1125}
1126
1127Vector<video_decoder> MediaProfiles::getVideoDecoders() const
1128{
1129 Vector<video_decoder> decoders;
1130 for (size_t i = 0; i < mVideoDecoders.size(); ++i) {
1131 decoders.add(mVideoDecoders[i]->mCodec);
1132 }
1133 return decoders; // copy out
1134}
1135
1136Vector<audio_decoder> MediaProfiles::getAudioDecoders() const
1137{
1138 Vector<audio_decoder> decoders;
1139 for (size_t i = 0; i < mAudioDecoders.size(); ++i) {
1140 decoders.add(mAudioDecoders[i]->mCodec);
1141 }
1142 return decoders; // copy out
1143}
1144
Nipun Kwatra8bb56032010-09-09 16:25:08 -07001145int MediaProfiles::getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const
James Dong1d7491b2010-01-19 17:45:38 -08001146{
James Dong1d7491b2010-01-19 17:45:38 -08001147 int index = -1;
1148 for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +08001149 if (mCamcorderProfiles[i]->mCameraId == cameraId &&
1150 mCamcorderProfiles[i]->mQuality == quality) {
James Dong1d7491b2010-01-19 17:45:38 -08001151 index = i;
1152 break;
1153 }
1154 }
Nipun Kwatra8bb56032010-09-09 16:25:08 -07001155 return index;
1156}
1157
Lajos Molnard64df6d2021-04-29 23:20:57 -07001158const MediaProfiles::CamcorderProfile *MediaProfiles::getCamcorderProfile(
1159 int cameraId, camcorder_quality quality) const {
1160 int index = getCamcorderProfileIndex(cameraId, quality);
1161 if (index == -1) {
1162 ALOGE("The given camcorder profile camera %d quality %d is not found",
1163 cameraId, quality);
1164 return nullptr;
1165 }
1166
1167 return mCamcorderProfiles[index];
1168}
1169
1170std::vector<const MediaProfiles::AudioCodec *>
1171MediaProfiles::CamcorderProfile::getAudioCodecs() const {
1172 std::vector<const MediaProfiles::AudioCodec *> res;
1173 for (const MediaProfiles::AudioCodec &ac : mAudioCodecs) {
1174 res.push_back(&ac);
1175 }
1176 return res;
1177}
1178
1179std::vector<const MediaProfiles::VideoCodec *>
1180MediaProfiles::CamcorderProfile::getVideoCodecs() const {
1181 std::vector<const MediaProfiles::VideoCodec *> res;
1182 for (const MediaProfiles::VideoCodec &vc : mVideoCodecs) {
1183 res.push_back(&vc);
1184 }
1185 return res;
1186}
1187
Nipun Kwatra8bb56032010-09-09 16:25:08 -07001188int MediaProfiles::getCamcorderProfileParamByName(const char *name,
1189 int cameraId,
1190 camcorder_quality quality) const
1191{
Steve Block3856b092011-10-20 11:56:00 +01001192 ALOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001193 name, cameraId, quality);
Nipun Kwatra8bb56032010-09-09 16:25:08 -07001194
1195 int index = getCamcorderProfileIndex(cameraId, quality);
James Dong1d7491b2010-01-19 17:45:38 -08001196 if (index == -1) {
Steve Block29357bc2012-01-06 19:20:56 +00001197 ALOGE("The given camcorder profile camera %d quality %d is not found",
Glenn Kastene53b9ea2012-03-12 16:29:55 -07001198 cameraId, quality);
James Dong1d7491b2010-01-19 17:45:38 -08001199 return -1;
1200 }
1201
James Dongf5a83852010-02-23 17:21:44 -08001202 if (!strcmp("duration", name)) return mCamcorderProfiles[index]->mDuration;
James Dong1d7491b2010-01-19 17:45:38 -08001203 if (!strcmp("file.format", name)) return mCamcorderProfiles[index]->mFileFormat;
Lajos Molnarb0aeb8b2021-03-24 10:11:41 -07001204 if (!strcmp("vid.codec", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mCodec;
1205 if (!strcmp("vid.width", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mFrameWidth;
1206 if (!strcmp("vid.height", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mFrameHeight;
1207 if (!strcmp("vid.bps", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mBitRate;
1208 if (!strcmp("vid.fps", name)) return mCamcorderProfiles[index]->mVideoCodecs[0].mFrameRate;
1209 if (!strcmp("aud.codec", name)) return mCamcorderProfiles[index]->mAudioCodecs[0].mCodec;
1210 if (!strcmp("aud.bps", name)) return mCamcorderProfiles[index]->mAudioCodecs[0].mBitRate;
1211 if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodecs[0].mChannels;
1212 if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodecs[0].mSampleRate;
James Dong1d7491b2010-01-19 17:45:38 -08001213
Steve Block29357bc2012-01-06 19:20:56 +00001214 ALOGE("The given camcorder profile param id %d name %s is not found", cameraId, name);
James Dong1d7491b2010-01-19 17:45:38 -08001215 return -1;
1216}
1217
Nipun Kwatra8bb56032010-09-09 16:25:08 -07001218bool MediaProfiles::hasCamcorderProfile(int cameraId, camcorder_quality quality) const
1219{
1220 return (getCamcorderProfileIndex(cameraId, quality) != -1);
1221}
1222
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +08001223Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const
James Dongf5a83852010-02-23 17:21:44 -08001224{
Chih-Chung Chang3eaa4e92010-06-22 20:50:55 +08001225 Vector<int> result;
1226 ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
1227 if (levels != NULL) {
1228 result = levels->mLevels; // copy out
1229 }
1230 return result;
James Dongf5a83852010-02-23 17:21:44 -08001231}
1232
James Dong0f056292011-05-09 18:49:31 -07001233int MediaProfiles::getStartTimeOffsetMs(int cameraId) const {
1234 int offsetTimeMs = -1;
1235 ssize_t index = mStartTimeOffsets.indexOfKey(cameraId);
1236 if (index >= 0) {
1237 offsetTimeMs = mStartTimeOffsets.valueFor(cameraId);
1238 }
Steve Block3856b092011-10-20 11:56:00 +01001239 ALOGV("offsetTime=%d ms and cameraId=%d", offsetTimeMs, cameraId);
James Dong0f056292011-05-09 18:49:31 -07001240 return offsetTimeMs;
1241}
1242
James Dong1d7491b2010-01-19 17:45:38 -08001243MediaProfiles::~MediaProfiles()
1244{
1245 CHECK("destructor should never be called" == 0);
1246#if 0
1247 for (size_t i = 0; i < mAudioEncoders.size(); ++i) {
1248 delete mAudioEncoders[i];
1249 }
1250 mAudioEncoders.clear();
1251
1252 for (size_t i = 0; i < mVideoEncoders.size(); ++i) {
1253 delete mVideoEncoders[i];
1254 }
1255 mVideoEncoders.clear();
1256
1257 for (size_t i = 0; i < mVideoDecoders.size(); ++i) {
1258 delete mVideoDecoders[i];
1259 }
1260 mVideoDecoders.clear();
1261
1262 for (size_t i = 0; i < mAudioDecoders.size(); ++i) {
1263 delete mAudioDecoders[i];
1264 }
1265 mAudioDecoders.clear();
1266
1267 for (size_t i = 0; i < mCamcorderProfiles.size(); ++i) {
1268 delete mCamcorderProfiles[i];
1269 }
1270 mCamcorderProfiles.clear();
1271#endif
1272}
1273} // namespace android