summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/MediaCodecList.cpp
diff options
context:
space:
mode:
authorLajos Molnar <lajos@google.com>2014-03-18 19:46:52 -0700
committerLajos Molnar <lajos@google.com>2014-03-19 10:20:22 -0700
commitd74110cdef2becd4f7fd2334c34c3ca73f56b355 (patch)
treee2c336f499b4d56fecb122dc0f203217ab5e9103 /media/libstagefright/MediaCodecList.cpp
parent8c75ab3416313843314446c5bbeafa62b83f0d63 (diff)
downloadframeworks_av-d74110cdef2becd4f7fd2334c34c3ca73f56b355.zip
frameworks_av-d74110cdef2becd4f7fd2334c34c3ca73f56b355.tar.gz
frameworks_av-d74110cdef2becd4f7fd2334c34c3ca73f56b355.tar.bz2
stagefright: add include support for MediaCodecList xml parser
One can include full-formed XML files using <Include href=".." />. For security/simplicity, file names must be in the form of "media_codecs_.*\.xml" Change-Id: Id039a4fd0ade390224485fcf5ecc1d107b2bdb9a
Diffstat (limited to 'media/libstagefright/MediaCodecList.cpp')
-rw-r--r--media/libstagefright/MediaCodecList.cpp142
1 files changed, 104 insertions, 38 deletions
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 6248e90..8a451c8 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -48,22 +48,43 @@ const MediaCodecList *MediaCodecList::getInstance() {
MediaCodecList::MediaCodecList()
: mInitCheck(NO_INIT) {
- FILE *file = fopen("/etc/media_codecs.xml", "r");
+ parseTopLevelXMLFile("/etc/media_codecs.xml");
+}
- if (file == NULL) {
- ALOGW("unable to open media codecs configuration xml file.");
+void MediaCodecList::parseTopLevelXMLFile(const char *codecs_xml) {
+ // get href_base
+ char *href_base_end = strrchr(codecs_xml, '/');
+ if (href_base_end != NULL) {
+ mHrefBase = AString(codecs_xml, href_base_end - codecs_xml + 1);
+ }
+
+ mInitCheck = OK;
+ mCurrentSection = SECTION_TOPLEVEL;
+ mDepth = 0;
+
+ parseXMLFile(codecs_xml);
+
+ if (mInitCheck != OK) {
+ mCodecInfos.clear();
+ mCodecQuirks.clear();
return;
}
- parseXMLFile(file);
+ // These are currently still used by the video editing suite.
+ addMediaCodec(true /* encoder */, "AACEncoder", "audio/mp4a-latm");
+ addMediaCodec(
+ false /* encoder */, "OMX.google.raw.decoder", "audio/raw");
- if (mInitCheck == OK) {
- // These are currently still used by the video editing suite.
+ for (size_t i = mCodecInfos.size(); i-- > 0;) {
+ CodecInfo *info = &mCodecInfos.editItemAt(i);
- addMediaCodec(true /* encoder */, "AACEncoder", "audio/mp4a-latm");
+ if (info->mTypes == 0) {
+ // No types supported by this component???
+ ALOGW("Component %s does not support any type of media?",
+ info->mName.c_str());
- addMediaCodec(
- false /* encoder */, "OMX.google.raw.decoder", "audio/raw");
+ mCodecInfos.removeAt(i);
+ }
}
#if 0
@@ -84,9 +105,6 @@ MediaCodecList::MediaCodecList()
ALOGI("%s", line.c_str());
}
#endif
-
- fclose(file);
- file = NULL;
}
MediaCodecList::~MediaCodecList() {
@@ -96,10 +114,14 @@ status_t MediaCodecList::initCheck() const {
return mInitCheck;
}
-void MediaCodecList::parseXMLFile(FILE *file) {
- mInitCheck = OK;
- mCurrentSection = SECTION_TOPLEVEL;
- mDepth = 0;
+void MediaCodecList::parseXMLFile(const char *path) {
+ FILE *file = fopen(path, "r");
+
+ if (file == NULL) {
+ ALOGW("unable to open media codecs configuration xml file: %s", path);
+ mInitCheck = NAME_NOT_FOUND;
+ return;
+ }
XML_Parser parser = ::XML_ParserCreate(NULL);
CHECK(parser != NULL);
@@ -112,7 +134,7 @@ void MediaCodecList::parseXMLFile(FILE *file) {
while (mInitCheck == OK) {
void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
if (buff == NULL) {
- ALOGE("failed to in call to XML_GetBuffer()");
+ ALOGE("failed in call to XML_GetBuffer()");
mInitCheck = UNKNOWN_ERROR;
break;
}
@@ -124,8 +146,9 @@ void MediaCodecList::parseXMLFile(FILE *file) {
break;
}
- if (::XML_ParseBuffer(parser, bytes_read, bytes_read == 0)
- != XML_STATUS_OK) {
+ XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
+ if (status != XML_STATUS_OK) {
+ ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser)));
mInitCheck = ERROR_MALFORMED;
break;
}
@@ -137,25 +160,8 @@ void MediaCodecList::parseXMLFile(FILE *file) {
::XML_ParserFree(parser);
- if (mInitCheck == OK) {
- for (size_t i = mCodecInfos.size(); i-- > 0;) {
- CodecInfo *info = &mCodecInfos.editItemAt(i);
-
- if (info->mTypes == 0) {
- // No types supported by this component???
-
- ALOGW("Component %s does not support any type of media?",
- info->mName.c_str());
-
- mCodecInfos.removeAt(i);
- }
- }
- }
-
- if (mInitCheck != OK) {
- mCodecInfos.clear();
- mCodecQuirks.clear();
- }
+ fclose(file);
+ file = NULL;
}
// static
@@ -169,12 +175,63 @@ void MediaCodecList::EndElementHandlerWrapper(void *me, const char *name) {
static_cast<MediaCodecList *>(me)->endElementHandler(name);
}
+status_t MediaCodecList::includeXMLFile(const char **attrs) {
+ const char *href = NULL;
+ size_t i = 0;
+ while (attrs[i] != NULL) {
+ if (!strcmp(attrs[i], "href")) {
+ if (attrs[i + 1] == NULL) {
+ return -EINVAL;
+ }
+ href = attrs[i + 1];
+ ++i;
+ } else {
+ return -EINVAL;
+ }
+ ++i;
+ }
+
+ // For security reasons and for simplicity, file names can only contain
+ // [a-zA-Z0-9_.] and must start with media_codecs_ and end with .xml
+ for (i = 0; href[i] != '\0'; i++) {
+ if (href[i] == '.' || href[i] == '_' ||
+ (href[i] >= '0' && href[i] <= '9') ||
+ (href[i] >= 'A' && href[i] <= 'Z') ||
+ (href[i] >= 'a' && href[i] <= 'z')) {
+ continue;
+ }
+ ALOGE("invalid include file name: %s", href);
+ return -EINVAL;
+ }
+
+ AString filename = href;
+ if (!filename.startsWith("media_codecs_") ||
+ !filename.endsWith(".xml")) {
+ ALOGE("invalid include file name: %s", href);
+ return -EINVAL;
+ }
+ filename.insert(mHrefBase, 0);
+
+ parseXMLFile(filename.c_str());
+ return mInitCheck;
+}
+
void MediaCodecList::startElementHandler(
const char *name, const char **attrs) {
if (mInitCheck != OK) {
return;
}
+ if (!strcmp(name, "Include")) {
+ mInitCheck = includeXMLFile(attrs);
+ if (mInitCheck == OK) {
+ mPastSections.push(mCurrentSection);
+ mCurrentSection = SECTION_INCLUDE;
+ }
+ ++mDepth;
+ return;
+ }
+
switch (mCurrentSection) {
case SECTION_TOPLEVEL:
{
@@ -264,6 +321,15 @@ void MediaCodecList::endElementHandler(const char *name) {
break;
}
+ case SECTION_INCLUDE:
+ {
+ if (!strcmp(name, "Include") && mPastSections.size() > 0) {
+ mCurrentSection = mPastSections.top();
+ mPastSections.pop();
+ }
+ break;
+ }
+
default:
break;
}