MediaProfiles: add support for profile
Allow Codec tags to specify the codec profile.
Bug: 171673898
Test: atest CamcorderProfileTest
Change-Id: Ia44567e965efe688edb20e8ffac34c2c5da983ea
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 9c24cba..bd17f4d 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -168,6 +168,7 @@
ALOGV("frame width: %d", codec.mFrameWidth);
ALOGV("frame height: %d", codec.mFrameHeight);
ALOGV("frame rate: %d", codec.mFrameRate);
+ ALOGV("profile: %d", codec.mProfile);
}
/*static*/ void
@@ -178,6 +179,7 @@
ALOGV("bit rate: %d", codec.mBitRate);
ALOGV("sample rate: %d", codec.mSampleRate);
ALOGV("number of channels: %d", codec.mChannels);
+ ALOGV("profile: %d", codec.mProfile);
}
/*static*/ void
@@ -230,9 +232,10 @@
}
/*static*/ void
-MediaProfiles::createVideoCodec(const char **atts, MediaProfiles *profiles)
+MediaProfiles::createVideoCodec(const char **atts, size_t natts, MediaProfiles *profiles)
{
- CHECK(!strcmp("codec", atts[0]) &&
+ CHECK(natts >= 10 &&
+ !strcmp("codec", atts[0]) &&
!strcmp("bitRate", atts[2]) &&
!strcmp("width", atts[4]) &&
!strcmp("height", atts[6]) &&
@@ -245,9 +248,14 @@
return;
}
+ int profile = -1;
+ if (natts >= 12 && !strcmp("profile", atts[10])) {
+ profile = atoi(atts[11]);
+ }
+
VideoCodec videoCodec {
static_cast<video_encoder>(codec),
- atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]) };
+ atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), profile };
logVideoCodec(videoCodec);
size_t nCamcorderProfiles;
@@ -256,9 +264,10 @@
}
/*static*/ void
-MediaProfiles::createAudioCodec(const char **atts, MediaProfiles *profiles)
+MediaProfiles::createAudioCodec(const char **atts, size_t natts, MediaProfiles *profiles)
{
- CHECK(!strcmp("codec", atts[0]) &&
+ CHECK(natts >= 8 &&
+ !strcmp("codec", atts[0]) &&
!strcmp("bitRate", atts[2]) &&
!strcmp("sampleRate", atts[4]) &&
!strcmp("channels", atts[6]));
@@ -269,9 +278,14 @@
return;
}
- AudioCodec audioCodec {
+ int profile = -1;
+ if (natts >= 10 && !strcmp("profile", atts[8])) {
+ profile = atoi(atts[9]);
+ }
+
+ AudioCodec audioCodec{
static_cast<audio_encoder>(codec),
- atoi(atts[3]), atoi(atts[5]), atoi(atts[7]) };
+ atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), profile };
logAudioCodec(audioCodec);
size_t nCamcorderProfiles;
@@ -280,9 +294,10 @@
}
/*static*/ MediaProfiles::AudioDecoderCap*
-MediaProfiles::createAudioDecoderCap(const char **atts)
+MediaProfiles::createAudioDecoderCap(const char **atts, size_t natts)
{
- CHECK(!strcmp("name", atts[0]) &&
+ CHECK(natts >= 4 &&
+ !strcmp("name", atts[0]) &&
!strcmp("enabled", atts[2]));
const size_t nMappings = sizeof(sAudioDecoderNameMap)/sizeof(sAudioDecoderNameMap[0]);
@@ -299,9 +314,10 @@
}
/*static*/ MediaProfiles::VideoDecoderCap*
-MediaProfiles::createVideoDecoderCap(const char **atts)
+MediaProfiles::createVideoDecoderCap(const char **atts, size_t natts)
{
- CHECK(!strcmp("name", atts[0]) &&
+ CHECK(natts >= 4 &&
+ !strcmp("name", atts[0]) &&
!strcmp("enabled", atts[2]));
const size_t nMappings = sizeof(sVideoDecoderNameMap)/sizeof(sVideoDecoderNameMap[0]);
@@ -318,9 +334,10 @@
}
/*static*/ MediaProfiles::VideoEncoderCap*
-MediaProfiles::createVideoEncoderCap(const char **atts)
+MediaProfiles::createVideoEncoderCap(const char **atts, size_t natts)
{
- CHECK(!strcmp("name", atts[0]) &&
+ CHECK(natts >= 20 &&
+ !strcmp("name", atts[0]) &&
!strcmp("enabled", atts[2]) &&
!strcmp("minBitRate", atts[4]) &&
!strcmp("maxBitRate", atts[6]) &&
@@ -347,9 +364,10 @@
}
/*static*/ MediaProfiles::AudioEncoderCap*
-MediaProfiles::createAudioEncoderCap(const char **atts)
+MediaProfiles::createAudioEncoderCap(const char **atts, size_t natts)
{
- CHECK(!strcmp("name", atts[0]) &&
+ CHECK(natts >= 16 &&
+ !strcmp("name", atts[0]) &&
!strcmp("enabled", atts[2]) &&
!strcmp("minBitRate", atts[4]) &&
!strcmp("maxBitRate", atts[6]) &&
@@ -373,9 +391,10 @@
}
/*static*/ output_format
-MediaProfiles::createEncoderOutputFileFormat(const char **atts)
+MediaProfiles::createEncoderOutputFileFormat(const char **atts, size_t natts)
{
- CHECK(!strcmp("name", atts[0]));
+ CHECK(natts >= 2 &&
+ !strcmp("name", atts[0]));
const size_t nMappings =sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
const int format = findTagForName(sFileFormatMap, nMappings, atts[1]);
@@ -394,9 +413,11 @@
}
/*static*/ MediaProfiles::CamcorderProfile*
-MediaProfiles::createCamcorderProfile(int cameraId, const char **atts, Vector<int>& cameraIds)
+MediaProfiles::createCamcorderProfile(
+ int cameraId, const char **atts, size_t natts, Vector<int>& cameraIds)
{
- CHECK(!strcmp("quality", atts[0]) &&
+ CHECK(natts >= 6 &&
+ !strcmp("quality", atts[0]) &&
!strcmp("fileFormat", atts[2]) &&
!strcmp("duration", atts[4]));
@@ -439,9 +460,10 @@
return NULL;
}
-void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts)
+void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts, size_t natts)
{
- CHECK(!strcmp("quality", atts[0]));
+ CHECK(natts >= 2 &&
+ !strcmp("quality", atts[0]));
int quality = atoi(atts[1]);
ALOGV("%s: cameraId=%d, quality=%d", __func__, cameraId, quality);
ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
@@ -456,18 +478,19 @@
}
/*static*/ int
-MediaProfiles::getCameraId(const char** atts)
+MediaProfiles::getCameraId(const char** atts, size_t natts)
{
if (!atts[0]) return 0; // default cameraId = 0
- CHECK(!strcmp("cameraId", atts[0]));
+ CHECK(natts >= 2 &&
+ !strcmp("cameraId", atts[0]));
return atoi(atts[1]);
}
-void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts)
+void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts, size_t natts)
{
int offsetTimeMs = 1000;
- if (atts[2]) {
- CHECK(!strcmp("startOffsetMs", atts[2]));
+ if (natts >= 3 && atts[2]) {
+ CHECK(natts >= 4 && !strcmp("startOffsetMs", atts[2]));
offsetTimeMs = atoi(atts[3]);
}
@@ -478,48 +501,58 @@
/*static*/ void
MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
{
- MediaProfiles *profiles = (MediaProfiles *) userData;
+ // determine number of attributes
+ size_t natts = 0;
+ while (atts[natts]) {
+ ++natts;
+ }
+
+ MediaProfiles *profiles = (MediaProfiles *)userData;
if (strcmp("Video", name) == 0) {
- createVideoCodec(atts, profiles);
+ createVideoCodec(atts, natts, profiles);
} else if (strcmp("Audio", name) == 0) {
- createAudioCodec(atts, profiles);
+ createAudioCodec(atts, natts, profiles);
} else if (strcmp("VideoEncoderCap", name) == 0 &&
+ natts >= 4 &&
strcmp("true", atts[3]) == 0) {
- MediaProfiles::VideoEncoderCap* cap = createVideoEncoderCap(atts);
+ MediaProfiles::VideoEncoderCap* cap = createVideoEncoderCap(atts, natts);
if (cap != nullptr) {
profiles->mVideoEncoders.add(cap);
}
} else if (strcmp("AudioEncoderCap", name) == 0 &&
+ natts >= 4 &&
strcmp("true", atts[3]) == 0) {
- MediaProfiles::AudioEncoderCap* cap = createAudioEncoderCap(atts);
+ MediaProfiles::AudioEncoderCap* cap = createAudioEncoderCap(atts, natts);
if (cap != nullptr) {
profiles->mAudioEncoders.add(cap);
}
} else if (strcmp("VideoDecoderCap", name) == 0 &&
+ natts >= 4 &&
strcmp("true", atts[3]) == 0) {
- MediaProfiles::VideoDecoderCap* cap = createVideoDecoderCap(atts);
+ MediaProfiles::VideoDecoderCap* cap = createVideoDecoderCap(atts, natts);
if (cap != nullptr) {
profiles->mVideoDecoders.add(cap);
}
} else if (strcmp("AudioDecoderCap", name) == 0 &&
+ natts >= 4 &&
strcmp("true", atts[3]) == 0) {
- MediaProfiles::AudioDecoderCap* cap = createAudioDecoderCap(atts);
+ MediaProfiles::AudioDecoderCap* cap = createAudioDecoderCap(atts, natts);
if (cap != nullptr) {
profiles->mAudioDecoders.add(cap);
}
} else if (strcmp("EncoderOutputFileFormat", name) == 0) {
- profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts));
+ profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts, natts));
} else if (strcmp("CamcorderProfiles", name) == 0) {
- profiles->mCurrentCameraId = getCameraId(atts);
- profiles->addStartTimeOffset(profiles->mCurrentCameraId, atts);
+ profiles->mCurrentCameraId = getCameraId(atts, natts);
+ profiles->addStartTimeOffset(profiles->mCurrentCameraId, atts, natts);
} else if (strcmp("EncoderProfile", name) == 0) {
MediaProfiles::CamcorderProfile* profile = createCamcorderProfile(
- profiles->mCurrentCameraId, atts, profiles->mCameraIds);
+ profiles->mCurrentCameraId, atts, natts, profiles->mCameraIds);
if (profile != nullptr) {
profiles->mCamcorderProfiles.add(profile);
}
} else if (strcmp("ImageEncoding", name) == 0) {
- profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
+ profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts, natts);
}
}
@@ -574,12 +607,12 @@
for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
// ensure at least one video and audio profile is added
- if (mCamcorderProfiles[i]->mVideoCodecs.size() == 0) {
+ if (mCamcorderProfiles[i]->mVideoCodecs.empty()) {
mCamcorderProfiles[i]->mVideoCodecs.emplace_back(
VIDEO_ENCODER_H263, 192000 /* bitrate */,
176 /* width */, 144 /* height */, 20 /* frameRate */);
}
- if (mCamcorderProfiles[i]->mAudioCodecs.size() == 0) {
+ if (mCamcorderProfiles[i]->mAudioCodecs.empty()) {
mCamcorderProfiles[i]->mAudioCodecs.emplace_back(
AUDIO_ENCODER_AMR_NB, 12200 /* bitrate */,
8000 /* sampleRate */, 1 /* channels */);
diff --git a/media/libmedia/include/media/MediaProfiles.h b/media/libmedia/include/media/MediaProfiles.h
index d06fda2..3f4fd19 100644
--- a/media/libmedia/include/media/MediaProfiles.h
+++ b/media/libmedia/include/media/MediaProfiles.h
@@ -112,13 +112,16 @@
* @param frameWidth frame width in pixels
* @param frameHeight frame height in pixels
* @param frameRate frame rate in fps
+ * @param profile codec profile (for MediaCodec) or -1 for none
*/
- VideoCodec(video_encoder codec, int bitrate, int frameWidth, int frameHeight, int frameRate)
+ VideoCodec(video_encoder codec, int bitrate, int frameWidth, int frameHeight, int frameRate,
+ int profile = -1)
: mCodec(codec),
mBitRate(bitrate),
mFrameWidth(frameWidth),
mFrameHeight(frameHeight),
- mFrameRate(frameRate) {
+ mFrameRate(frameRate),
+ mProfile(profile) {
}
VideoCodec(const VideoCodec&) = default;
@@ -150,12 +153,18 @@
return mFrameRate;
}
+ /** Returns the codec profile (or -1 for no profile). */
+ int getProfile() const {
+ return mProfile;
+ }
+
private:
video_encoder mCodec;
int mBitRate;
int mFrameWidth;
int mFrameHeight;
int mFrameRate;
+ int mProfile;
friend class MediaProfiles;
};
@@ -171,12 +180,14 @@
* @param bitrate bitrate in bps
* @param sampleRate sample rate in Hz
* @param channels number of channels
+ * @param profile codec profile (for MediaCodec) or -1 for none
*/
- AudioCodec(audio_encoder codec, int bitrate, int sampleRate, int channels)
+ AudioCodec(audio_encoder codec, int bitrate, int sampleRate, int channels, int profile = -1)
: mCodec(codec),
mBitRate(bitrate),
mSampleRate(sampleRate),
- mChannels(channels) {
+ mChannels(channels),
+ mProfile(profile) {
}
AudioCodec(const AudioCodec&) = default;
@@ -203,11 +214,17 @@
return mChannels;
}
+ /** Returns the codec profile (or -1 for no profile). */
+ int getProfile() const {
+ return mProfile;
+ }
+
private:
audio_encoder mCodec;
int mBitRate;
int mSampleRate;
int mChannels;
+ int mProfile;
friend class MediaProfiles;
};
@@ -456,23 +473,23 @@
// If the xml configuration file does exist, use the settings
// from the xml
static MediaProfiles* createInstanceFromXmlFile(const char *xml);
- static output_format createEncoderOutputFileFormat(const char **atts);
- static void createVideoCodec(const char **atts, MediaProfiles *profiles);
- static void createAudioCodec(const char **atts, MediaProfiles *profiles);
- static AudioDecoderCap* createAudioDecoderCap(const char **atts);
- static VideoDecoderCap* createVideoDecoderCap(const char **atts);
- static VideoEncoderCap* createVideoEncoderCap(const char **atts);
- static AudioEncoderCap* createAudioEncoderCap(const char **atts);
+ static output_format createEncoderOutputFileFormat(const char **atts, size_t natts);
+ static void createVideoCodec(const char **atts, size_t natts, MediaProfiles *profiles);
+ static void createAudioCodec(const char **atts, size_t natts, MediaProfiles *profiles);
+ static AudioDecoderCap* createAudioDecoderCap(const char **atts, size_t natts);
+ static VideoDecoderCap* createVideoDecoderCap(const char **atts, size_t natts);
+ static VideoEncoderCap* createVideoEncoderCap(const char **atts, size_t natts);
+ static AudioEncoderCap* createAudioEncoderCap(const char **atts, size_t natts);
static CamcorderProfile* createCamcorderProfile(
- int cameraId, const char **atts, Vector<int>& cameraIds);
+ int cameraId, const char **atts, size_t natts, Vector<int>& cameraIds);
- static int getCameraId(const char **atts);
+ static int getCameraId(const char **atts, size_t natts);
- void addStartTimeOffset(int cameraId, const char **atts);
+ void addStartTimeOffset(int cameraId, const char **atts, size_t natts);
ImageEncodingQualityLevels* findImageEncodingQualityLevels(int cameraId) const;
- void addImageEncodingQualityLevel(int cameraId, const char** atts);
+ void addImageEncodingQualityLevel(int cameraId, const char** atts, size_t natts);
// Customized element tag handler for parsing the xml configuration file.
static void startElementHandler(void *userData, const char *name, const char **atts);