summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLajos Molnar <lajos@google.com>2014-08-06 16:55:46 -0700
committerLajos Molnar <lajos@google.com>2014-08-07 17:40:13 -0700
commit60b1c0e79d12a1c70758bc8d060156924635f8ba (patch)
tree300d26ea36bca500a7105b7a94497dd1c2aa9fda
parent8accee4f0e94f19866d260be6eecd6c219eb4982 (diff)
downloadframeworks_av-60b1c0e79d12a1c70758bc8d060156924635f8ba.zip
frameworks_av-60b1c0e79d12a1c70758bc8d060156924635f8ba.tar.gz
frameworks_av-60b1c0e79d12a1c70758bc8d060156924635f8ba.tar.bz2
stagefright: rework media codec list and infos
This is in preparation of serving the codec list and codec infos from the mediaserver Bug: 11990470 Change-Id: Ib8e2708679c9ce461a4ba179974a740cdcdf2731
-rw-r--r--include/media/IMediaCodecList.h55
-rw-r--r--include/media/MediaCodecInfo.h121
-rw-r--r--include/media/stagefright/MediaCodecList.h54
-rw-r--r--include/media/stagefright/OMXCodec.h4
-rw-r--r--media/libmedia/Android.mk3
-rw-r--r--media/libmedia/IMediaCodecList.cpp163
-rw-r--r--media/libmedia/MediaCodecInfo.cpp252
-rw-r--r--media/libstagefright/MediaCodec.cpp16
-rw-r--r--media/libstagefright/MediaCodecList.cpp374
-rw-r--r--media/libstagefright/OMXCodec.cpp26
10 files changed, 772 insertions, 296 deletions
diff --git a/include/media/IMediaCodecList.h b/include/media/IMediaCodecList.h
new file mode 100644
index 0000000..e93ea8b
--- /dev/null
+++ b/include/media/IMediaCodecList.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IMEDIACODECLIST_H
+#define ANDROID_IMEDIACODECLIST_H
+
+#include <utils/Errors.h> // for status_t
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+struct MediaCodecInfo;
+
+class IMediaCodecList: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaCodecList);
+
+ virtual size_t countCodecs() const = 0;
+ virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const = 0;
+
+ virtual ssize_t findCodecByType(
+ const char *type, bool encoder, size_t startIndex = 0) const = 0;
+
+ virtual ssize_t findCodecByName(const char *name) const = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaCodecList: public BnInterface<IMediaCodecList>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIACODECLIST_H
diff --git a/include/media/MediaCodecInfo.h b/include/media/MediaCodecInfo.h
new file mode 100644
index 0000000..29315ce
--- /dev/null
+++ b/include/media/MediaCodecInfo.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_CODEC_INFO_H_
+
+#define MEDIA_CODEC_INFO_H_
+
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+struct AMessage;
+struct Parcel;
+struct CodecCapabilities;
+
+struct MediaCodecInfo : public RefBase {
+ struct ProfileLevel {
+ uint32_t mProfile;
+ uint32_t mLevel;
+ };
+
+ struct Capabilities : public RefBase {
+ void getSupportedProfileLevels(Vector<ProfileLevel> *profileLevels) const;
+ void getSupportedColorFormats(Vector<uint32_t> *colorFormats) const;
+ uint32_t getFlags() const;
+ const sp<AMessage> &getDetails() const;
+
+ private:
+ Vector<ProfileLevel> mProfileLevels;
+ Vector<uint32_t> mColorFormats;
+ uint32_t mFlags;
+ sp<AMessage> mDetails;
+
+ Capabilities();
+
+ // read object from parcel even if object creation fails
+ static sp<Capabilities> FromParcel(const Parcel &parcel);
+ status_t writeToParcel(Parcel *parcel) const;
+
+ DISALLOW_EVIL_CONSTRUCTORS(Capabilities);
+
+ friend class MediaCodecInfo;
+ };
+
+ bool isEncoder() const;
+ bool hasQuirk(const char *name) const;
+ void getSupportedMimes(Vector<AString> *mimes) const;
+ const sp<Capabilities> &getCapabilitiesFor(const char *mime) const;
+ const char *getCodecName() const;
+
+ /**
+ * Serialization over Binder
+ */
+ static sp<MediaCodecInfo> FromParcel(const Parcel &parcel);
+ status_t writeToParcel(Parcel *parcel) const;
+
+private:
+ // variable set only in constructor - these are accessed by MediaCodecList
+ // to avoid duplication of same variables
+ AString mName;
+ bool mIsEncoder;
+ bool mHasSoleMime; // was initialized with mime
+
+ Vector<AString> mQuirks;
+ KeyedVector<AString, sp<Capabilities> > mCaps;
+
+ sp<Capabilities> mCurrentCaps; // currently initalized capabilities
+
+ ssize_t getCapabilityIndex(const char *mime) const;
+
+ /* Methods used by MediaCodecList to construct the info
+ * object from XML.
+ *
+ * After info object is created:
+ * - additional quirks can be added
+ * - additional mimes can be added
+ * - OMX codec capabilities can be set for the current mime-type
+ * - a capability detail can be set for the current mime-type
+ * - a feature can be set for the current mime-type
+ * - info object can be completed when parsing of a mime-type is done
+ */
+ MediaCodecInfo(AString name, bool encoder, const char *mime);
+ void addQuirk(const char *name);
+ status_t addMime(const char *mime);
+ status_t initializeCapabilities(const CodecCapabilities &caps);
+ void addDetail(const AString &key, const AString &value);
+ void addFeature(const AString &key, int32_t value);
+ void complete();
+
+ DISALLOW_EVIL_CONSTRUCTORS(MediaCodecInfo);
+
+ friend class MediaCodecList;
+};
+
+} // namespace android
+
+#endif // MEDIA_CODEC_INFO_H_
+
+
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
index c11fcc9..8605d99 100644
--- a/include/media/stagefright/MediaCodecList.h
+++ b/include/media/stagefright/MediaCodecList.h
@@ -20,6 +20,9 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AString.h>
+#include <media/IMediaCodecList.h>
+#include <media/IOMX.h>
+#include <media/MediaCodecInfo.h>
#include <sys/types.h>
#include <utils/Errors.h>
@@ -31,32 +34,22 @@ namespace android {
struct AMessage;
-struct MediaCodecList {
- static const MediaCodecList *getInstance();
+struct MediaCodecList : public BnMediaCodecList {
+ static sp<IMediaCodecList> getInstance();
- ssize_t findCodecByType(
+ virtual ssize_t findCodecByType(
const char *type, bool encoder, size_t startIndex = 0) const;
- ssize_t findCodecByName(const char *name) const;
+ virtual ssize_t findCodecByName(const char *name) const;
- size_t countCodecs() const;
- const char *getCodecName(size_t index) const;
- bool isEncoder(size_t index) const;
- bool codecHasQuirk(size_t index, const char *quirkName) const;
+ virtual size_t countCodecs() const;
- status_t getSupportedTypes(size_t index, Vector<AString> *types) const;
+ virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const {
+ return mCodecInfos.itemAt(index);
+ }
- struct ProfileLevel {
- uint32_t mProfile;
- uint32_t mLevel;
- };
- status_t getCodecCapabilities(
- size_t index, const char *type,
- Vector<ProfileLevel> *profileLevels,
- Vector<uint32_t> *colorFormats,
- uint32_t *flags,
- // TODO default argument is only for compatibility with existing JNI
- sp<AMessage> *capabilities = NULL) const;
+ // to be used by MediaPlayerService alone
+ static sp<IMediaCodecList> getLocalInstance();
private:
enum Section {
@@ -70,17 +63,8 @@ private:
SECTION_INCLUDE,
};
- struct CodecInfo {
- AString mName;
- bool mIsEncoder;
- uint32_t mTypes;
- uint32_t mSoleType;
- uint32_t mQuirks;
- KeyedVector<uint32_t, sp<AMessage> > mCaps;
- sp<AMessage> mCurrentCaps;
- };
-
- static MediaCodecList *sCodecList;
+ static sp<IMediaCodecList> sCodecList;
+ static sp<IMediaCodecList> sRemoteList;
status_t mInitCheck;
Section mCurrentSection;
@@ -88,9 +72,9 @@ private:
int32_t mDepth;
AString mHrefBase;
- Vector<CodecInfo> mCodecInfos;
- KeyedVector<AString, size_t> mCodecQuirks;
- KeyedVector<AString, size_t> mTypes;
+ Vector<sp<MediaCodecInfo> > mCodecInfos;
+ sp<MediaCodecInfo> mCurrentInfo;
+ sp<IOMX> mOMX;
MediaCodecList();
~MediaCodecList();
@@ -117,6 +101,8 @@ private:
status_t addFeature(const char **attrs);
void addType(const char *name);
+ status_t initializeCapabilities(const char *type);
+
DISALLOW_EVIL_CONSTRUCTORS(MediaCodecList);
};
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 5590b60..e341160 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -28,7 +28,7 @@
namespace android {
-struct MediaCodecList;
+struct MediaCodecInfo;
class MemoryDealer;
struct OMXCodecObserver;
struct CodecProfileLevel;
@@ -115,7 +115,7 @@ struct OMXCodec : public MediaSource,
Vector<CodecNameAndQuirks> *matchingCodecNamesAndQuirks);
static uint32_t getComponentQuirks(
- const MediaCodecList *list, size_t index);
+ const sp<MediaCodecInfo> &list);
static bool findCodecQuirks(const char *componentName, uint32_t *quirks);
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index cee26d9..3be0651 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -25,6 +25,7 @@ LOCAL_SRC_FILES:= \
AudioRecord.cpp \
AudioSystem.cpp \
mediaplayer.cpp \
+ IMediaCodecList.cpp \
IMediaHTTPConnection.cpp \
IMediaHTTPService.cpp \
IMediaLogService.cpp \
@@ -36,6 +37,7 @@ LOCAL_SRC_FILES:= \
IRemoteDisplay.cpp \
IRemoteDisplayClient.cpp \
IStreamSource.cpp \
+ MediaCodecInfo.cpp \
Metadata.cpp \
mediarecorder.cpp \
IMediaMetadataRetriever.cpp \
@@ -74,6 +76,7 @@ LOCAL_MODULE:= libmedia
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/frameworks/av/media/libstagefright \
external/icu/icu4c/source/common \
external/icu/icu4c/source/i18n \
$(call include-path-for, audio-effects) \
diff --git a/media/libmedia/IMediaCodecList.cpp b/media/libmedia/IMediaCodecList.cpp
new file mode 100644
index 0000000..bf7c5ca
--- /dev/null
+++ b/media/libmedia/IMediaCodecList.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/IMediaCodecList.h>
+#include <media/MediaCodecInfo.h>
+
+#include <utils/Errors.h> // for status_t
+
+namespace android {
+
+enum {
+ CREATE = IBinder::FIRST_CALL_TRANSACTION,
+ COUNT_CODECS,
+ GET_CODEC_INFO,
+ FIND_CODEC_BY_TYPE,
+ FIND_CODEC_BY_NAME,
+};
+
+class BpMediaCodecList: public BpInterface<IMediaCodecList>
+{
+public:
+ BpMediaCodecList(const sp<IBinder>& impl)
+ : BpInterface<IMediaCodecList>(impl)
+ {
+ }
+
+ virtual size_t countCodecs() const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
+ remote()->transact(COUNT_CODECS, data, &reply);
+ return static_cast<size_t>(reply.readInt32());
+ }
+
+ virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
+ data.writeInt32(index);
+ remote()->transact(GET_CODEC_INFO, data, &reply);
+ status_t err = reply.readInt32();
+ if (err == OK) {
+ return MediaCodecInfo::FromParcel(reply);
+ } else {
+ return NULL;
+ }
+ }
+
+ virtual ssize_t findCodecByType(
+ const char *type, bool encoder, size_t startIndex = 0) const
+ {
+ if (startIndex > INT32_MAX) {
+ return NAME_NOT_FOUND;
+ }
+
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
+ data.writeCString(type);
+ data.writeInt32(encoder);
+ data.writeInt32(startIndex);
+ remote()->transact(FIND_CODEC_BY_TYPE, data, &reply);
+ return static_cast<ssize_t>(reply.readInt32());
+ }
+
+ virtual ssize_t findCodecByName(const char *name) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
+ data.writeCString(name);
+ remote()->transact(FIND_CODEC_BY_NAME, data, &reply);
+ return static_cast<ssize_t>(reply.readInt32());
+ }
+};
+
+IMPLEMENT_META_INTERFACE(MediaCodecList, "android.media.IMediaCodecList");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaCodecList::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case COUNT_CODECS:
+ {
+ CHECK_INTERFACE(IMediaCodecList, data, reply);
+ size_t count = countCodecs();
+ if (count > INT32_MAX) {
+ count = INT32_MAX;
+ }
+ reply->writeInt32(count);
+ return NO_ERROR;
+ }
+ break;
+
+ case GET_CODEC_INFO:
+ {
+ CHECK_INTERFACE(IMediaCodecList, data, reply);
+ size_t index = static_cast<size_t>(data.readInt32());
+ const sp<MediaCodecInfo> info = getCodecInfo(index);
+ if (info != NULL) {
+ reply->writeInt32(OK);
+ info->writeToParcel(reply);
+ } else {
+ reply->writeInt32(-ERANGE);
+ }
+ return NO_ERROR;
+ }
+ break;
+
+ case FIND_CODEC_BY_TYPE:
+ {
+ CHECK_INTERFACE(IMediaCodecList, data, reply);
+ const char *type = data.readCString();
+ bool isEncoder = static_cast<bool>(data.readInt32());
+ size_t startIndex = static_cast<size_t>(data.readInt32());
+ ssize_t index = findCodecByType(type, isEncoder, startIndex);
+ if (index > INT32_MAX || index < 0) {
+ index = NAME_NOT_FOUND;
+ }
+ reply->writeInt32(index);
+ return NO_ERROR;
+ }
+ break;
+
+ case FIND_CODEC_BY_NAME:
+ {
+ CHECK_INTERFACE(IMediaCodecList, data, reply);
+ const char *name = data.readCString();
+ ssize_t index = findCodecByName(name);
+ if (index > INT32_MAX || index < 0) {
+ index = NAME_NOT_FOUND;
+ }
+ reply->writeInt32(index);
+ return NO_ERROR;
+ }
+ break;
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
new file mode 100644
index 0000000..7900eae
--- /dev/null
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaCodecInfo"
+#include <utils/Log.h>
+
+#include <media/IOMX.h>
+
+#include <media/MediaCodecInfo.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <binder/Parcel.h>
+
+#include <media/stagefright/OMXCodec.h>
+
+namespace android {
+
+void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
+ Vector<ProfileLevel> *profileLevels) const {
+ profileLevels->clear();
+ profileLevels->appendVector(mProfileLevels);
+}
+
+void MediaCodecInfo::Capabilities::getSupportedColorFormats(
+ Vector<uint32_t> *colorFormats) const {
+ colorFormats->clear();
+ colorFormats->appendVector(mColorFormats);
+}
+
+uint32_t MediaCodecInfo::Capabilities::getFlags() const {
+ return mFlags;
+}
+
+const sp<AMessage> &MediaCodecInfo::Capabilities::getDetails() const {
+ return mDetails;
+}
+
+MediaCodecInfo::Capabilities::Capabilities()
+ : mFlags(0) {
+ mDetails = new AMessage;
+}
+
+// static
+sp<MediaCodecInfo::Capabilities> MediaCodecInfo::Capabilities::FromParcel(
+ const Parcel &parcel) {
+ sp<MediaCodecInfo::Capabilities> caps = new Capabilities();
+ size_t size = static_cast<size_t>(parcel.readInt32());
+ for (size_t i = 0; i < size; i++) {
+ ProfileLevel profileLevel;
+ profileLevel.mProfile = static_cast<uint32_t>(parcel.readInt32());
+ profileLevel.mLevel = static_cast<uint32_t>(parcel.readInt32());
+ if (caps != NULL) {
+ caps->mProfileLevels.push_back(profileLevel);
+ }
+ }
+ size = static_cast<size_t>(parcel.readInt32());
+ for (size_t i = 0; i < size; i++) {
+ uint32_t color = static_cast<uint32_t>(parcel.readInt32());
+ if (caps != NULL) {
+ caps->mColorFormats.push_back(color);
+ }
+ }
+ uint32_t flags = static_cast<uint32_t>(parcel.readInt32());
+ sp<AMessage> details = AMessage::FromParcel(parcel);
+ if (caps != NULL) {
+ caps->mFlags = flags;
+ caps->mDetails = details;
+ }
+ return caps;
+}
+
+status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const {
+ CHECK_LE(mProfileLevels.size(), INT32_MAX);
+ parcel->writeInt32(mProfileLevels.size());
+ for (size_t i = 0; i < mProfileLevels.size(); i++) {
+ parcel->writeInt32(mProfileLevels.itemAt(i).mProfile);
+ parcel->writeInt32(mProfileLevels.itemAt(i).mLevel);
+ }
+ CHECK_LE(mColorFormats.size(), INT32_MAX);
+ parcel->writeInt32(mColorFormats.size());
+ for (size_t i = 0; i < mColorFormats.size(); i++) {
+ parcel->writeInt32(mColorFormats.itemAt(i));
+ }
+ parcel->writeInt32(mFlags);
+ mDetails->writeToParcel(parcel);
+ return OK;
+}
+
+bool MediaCodecInfo::isEncoder() const {
+ return mIsEncoder;
+}
+
+bool MediaCodecInfo::hasQuirk(const char *name) const {
+ for (size_t ix = 0; ix < mQuirks.size(); ix++) {
+ if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
+ mimes->clear();
+ for (size_t ix = 0; ix < mCaps.size(); ix++) {
+ mimes->push_back(mCaps.keyAt(ix));
+ }
+}
+
+const sp<MediaCodecInfo::Capabilities> &
+MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
+ ssize_t ix = getCapabilityIndex(mime);
+ if (ix >= 0) {
+ return mCaps.valueAt(ix);
+ }
+ return NULL;
+}
+
+const char *MediaCodecInfo::getCodecName() const {
+ return mName.c_str();
+}
+
+// static
+sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
+ AString name = AString::FromParcel(parcel);
+ bool isEncoder = static_cast<bool>(parcel.readInt32());
+ sp<MediaCodecInfo> info = new MediaCodecInfo(name, isEncoder, NULL);
+ size_t size = static_cast<size_t>(parcel.readInt32());
+ for (size_t i = 0; i < size; i++) {
+ AString quirk = AString::FromParcel(parcel);
+ if (info != NULL) {
+ info->mQuirks.push_back(quirk);
+ }
+ }
+ size = static_cast<size_t>(parcel.readInt32());
+ for (size_t i = 0; i < size; i++) {
+ AString mime = AString::FromParcel(parcel);
+ sp<Capabilities> caps = Capabilities::FromParcel(parcel);
+ if (info != NULL) {
+ info->mCaps.add(mime, caps);
+ }
+ }
+ return info;
+}
+
+status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
+ mName.writeToParcel(parcel);
+ parcel->writeInt32(mIsEncoder);
+ parcel->writeInt32(mQuirks.size());
+ for (size_t i = 0; i < mQuirks.size(); i++) {
+ mQuirks.itemAt(i).writeToParcel(parcel);
+ }
+ parcel->writeInt32(mCaps.size());
+ for (size_t i = 0; i < mCaps.size(); i++) {
+ mCaps.keyAt(i).writeToParcel(parcel);
+ mCaps.valueAt(i)->writeToParcel(parcel);
+ }
+ return OK;
+}
+
+ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
+ for (size_t ix = 0; ix < mCaps.size(); ix++) {
+ if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
+ return ix;
+ }
+ }
+ return -1;
+}
+
+MediaCodecInfo::MediaCodecInfo(AString name, bool encoder, const char *mime)
+ : mName(name),
+ mIsEncoder(encoder),
+ mHasSoleMime(false) {
+ if (mime != NULL) {
+ addMime(mime);
+ mHasSoleMime = true;
+ }
+}
+
+status_t MediaCodecInfo::addMime(const char *mime) {
+ if (mHasSoleMime) {
+ ALOGE("Codec '%s' already had its type specified", mName.c_str());
+ return -EINVAL;
+ }
+ ssize_t ix = getCapabilityIndex(mime);
+ if (ix >= 0) {
+ mCurrentCaps = mCaps.valueAt(ix);
+ } else {
+ mCurrentCaps = new Capabilities();
+ mCaps.add(AString(mime), mCurrentCaps);
+ }
+ return OK;
+}
+
+status_t MediaCodecInfo::initializeCapabilities(const CodecCapabilities &caps) {
+ mCurrentCaps->mProfileLevels.clear();
+ mCurrentCaps->mColorFormats.clear();
+
+ for (size_t i = 0; i < caps.mProfileLevels.size(); ++i) {
+ const CodecProfileLevel &src = caps.mProfileLevels.itemAt(i);
+
+ ProfileLevel profileLevel;
+ profileLevel.mProfile = src.mProfile;
+ profileLevel.mLevel = src.mLevel;
+ mCurrentCaps->mProfileLevels.push_back(profileLevel);
+ }
+
+ for (size_t i = 0; i < caps.mColorFormats.size(); ++i) {
+ mCurrentCaps->mColorFormats.push_back(caps.mColorFormats.itemAt(i));
+ }
+
+ mCurrentCaps->mFlags = caps.mFlags;
+ mCurrentCaps->mDetails = new AMessage;
+
+ return OK;
+}
+
+void MediaCodecInfo::addQuirk(const char *name) {
+ if (!hasQuirk(name)) {
+ mQuirks.push(name);
+ }
+}
+
+void MediaCodecInfo::complete() {
+ mCurrentCaps = NULL;
+}
+
+void MediaCodecInfo::addDetail(const AString &key, const AString &value) {
+ mCurrentCaps->mDetails->setString(key.c_str(), value.c_str());
+}
+
+void MediaCodecInfo::addFeature(const AString &key, int32_t value) {
+ AString tag = "feature-";
+ tag.append(key);
+ mCurrentCaps->mDetails->setInt32(tag.c_str(), value);
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7c02959..a67a933 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -195,16 +195,16 @@ status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
if (tmp.endsWith(".secure")) {
tmp.erase(tmp.size() - 7, 7);
}
- const MediaCodecList *mcl = MediaCodecList::getInstance();
+ const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
if (codecIdx >= 0) {
- Vector<AString> types;
- if (mcl->getSupportedTypes(codecIdx, &types) == OK) {
- for (size_t i = 0; i < types.size(); i++) {
- if (types[i].startsWith("video/")) {
- needDedicatedLooper = true;
- break;
- }
+ const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
+ Vector<AString> mimes;
+ info->getSupportedMimes(&mimes);
+ for (size_t i = 0; i < mimes.size(); i++) {
+ if (mimes[i].startsWith("video/")) {
+ needDedicatedLooper = true;
+ break;
}
}
}
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index d021533..60809c1 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -18,13 +18,19 @@
#define LOG_TAG "MediaCodecList"
#include <utils/Log.h>
-#include <media/stagefright/MediaCodecList.h>
+#include <binder/IServiceManager.h>
+
+#include <media/IMediaCodecList.h>
+#include <media/IMediaPlayerService.h>
+#include <media/MediaCodecInfo.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
+
#include <utils/threads.h>
#include <libexpat/expat.h>
@@ -33,18 +39,32 @@ namespace android {
static Mutex sInitMutex;
+static MediaCodecList *gCodecList = NULL;
+
// static
-MediaCodecList *MediaCodecList::sCodecList;
+sp<IMediaCodecList> MediaCodecList::sCodecList;
// static
-const MediaCodecList *MediaCodecList::getInstance() {
+sp<IMediaCodecList> MediaCodecList::getLocalInstance() {
Mutex::Autolock autoLock(sInitMutex);
- if (sCodecList == NULL) {
- sCodecList = new MediaCodecList;
+ if (gCodecList == NULL) {
+ gCodecList = new MediaCodecList;
+ if (gCodecList->initCheck() == OK) {
+ sCodecList = gCodecList;
+ }
}
- return sCodecList->initCheck() == OK ? sCodecList : NULL;
+ return sCodecList;
+}
+
+static Mutex sRemoteInitMutex;
+
+sp<IMediaCodecList> MediaCodecList::sRemoteList;
+
+// static
+sp<IMediaCodecList> MediaCodecList::getInstance() {
+ return getLocalInstance();
}
MediaCodecList::MediaCodecList()
@@ -59,37 +79,69 @@ void MediaCodecList::parseTopLevelXMLFile(const char *codecs_xml) {
mHrefBase = AString(codecs_xml, href_base_end - codecs_xml + 1);
}
- mInitCheck = OK;
+ mInitCheck = OK; // keeping this here for safety
mCurrentSection = SECTION_TOPLEVEL;
mDepth = 0;
+ OMXClient client;
+ mInitCheck = client.connect();
+ if (mInitCheck != OK) {
+ return;
+ }
+ mOMX = client.interface();
parseXMLFile(codecs_xml);
+ mOMX.clear();
if (mInitCheck != OK) {
mCodecInfos.clear();
- mCodecQuirks.clear();
return;
}
for (size_t i = mCodecInfos.size(); i-- > 0;) {
- CodecInfo *info = &mCodecInfos.editItemAt(i);
+ const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get();
- if (info->mTypes == 0) {
+ if (info.mCaps.size() == 0) {
// No types supported by this component???
ALOGW("Component %s does not support any type of media?",
- info->mName.c_str());
+ info.mName.c_str());
mCodecInfos.removeAt(i);
#if LOG_NDEBUG == 0
} else {
- for (size_t type_ix = 0; type_ix < mTypes.size(); ++type_ix) {
- uint32_t typeMask = 1ul << mTypes.valueAt(type_ix);
- if (info->mTypes & typeMask) {
- AString mime = mTypes.keyAt(type_ix);
- uint32_t bit = mTypes.valueAt(type_ix);
-
- ALOGV("%s codec info for %s: %s", info->mName.c_str(), mime.c_str(),
- info->mCaps.editValueFor(bit)->debugString().c_str());
+ for (size_t type_ix = 0; type_ix < info.mCaps.size(); ++type_ix) {
+ AString mime = info.mCaps.keyAt(type_ix);
+ const sp<MediaCodecInfo::Capabilities> &caps = info.mCaps.valueAt(type_ix);
+
+ ALOGV("%s codec info for %s: %s", info.mName.c_str(), mime.c_str(),
+ caps->getDetails()->debugString().c_str());
+ ALOGV(" flags=%d", caps->getFlags());
+ {
+ Vector<uint32_t> colorFormats;
+ caps->getSupportedColorFormats(&colorFormats);
+ AString nice;
+ for (size_t ix = 0; ix < colorFormats.size(); ix++) {
+ if (ix > 0) {
+ nice.append(", ");
+ }
+ nice.append(colorFormats.itemAt(ix));
+ }
+ ALOGV(" colors=[%s]", nice.c_str());
+ }
+ {
+ Vector<MediaCodecInfo::ProfileLevel> profileLevels;
+ caps->getSupportedProfileLevels(&profileLevels);
+ AString nice;
+ for (size_t ix = 0; ix < profileLevels.size(); ix++) {
+ if (ix > 0) {
+ nice.append(", ");
+ }
+ const MediaCodecInfo::ProfileLevel &pl =
+ profileLevels.itemAt(ix);
+ nice.append(pl.mProfile);
+ nice.append("/");
+ nice.append(pl.mLevel);
+ }
+ ALOGV(" levels=[%s]", nice.c_str());
}
}
#endif
@@ -294,9 +346,8 @@ void MediaCodecList::startElementHandler(
case SECTION_DECODER_TYPE:
case SECTION_ENCODER_TYPE:
{
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
// ignore limits and features specified outside of type
- bool outside = !inType && info->mSoleType == 0;
+ bool outside = !inType && !mCurrentInfo->mHasSoleMime;
if (outside && (!strcmp(name, "Limit") || !strcmp(name, "Feature"))) {
ALOGW("ignoring %s specified outside of a Type", name);
} else if (!strcmp(name, "Limit")) {
@@ -344,8 +395,7 @@ void MediaCodecList::endElementHandler(const char *name) {
(mCurrentSection == SECTION_DECODER_TYPE
? SECTION_DECODER : SECTION_ENCODER);
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
- info->mCurrentCaps = NULL;
+ mCurrentInfo->complete();
}
break;
}
@@ -354,9 +404,8 @@ void MediaCodecList::endElementHandler(const char *name) {
{
if (!strcmp(name, "MediaCodec")) {
mCurrentSection = SECTION_DECODERS;
-
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
- info->mCurrentCaps = NULL;
+ mCurrentInfo->complete();
+ mCurrentInfo = NULL;
}
break;
}
@@ -365,9 +414,8 @@ void MediaCodecList::endElementHandler(const char *name) {
{
if (!strcmp(name, "MediaCodec")) {
mCurrentSection = SECTION_ENCODERS;
-
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
- info->mCurrentCaps = NULL;
+ mCurrentInfo->complete();;
+ mCurrentInfo = NULL;
}
break;
}
@@ -418,28 +466,27 @@ status_t MediaCodecList::addMediaCodecFromAttributes(
return -EINVAL;
}
- addMediaCodec(encoder, name, type);
-
- return OK;
+ mCurrentInfo = new MediaCodecInfo(name, encoder, type);
+ mCodecInfos.push_back(mCurrentInfo);
+ return initializeCapabilities(type);
}
-void MediaCodecList::addMediaCodec(
- bool encoder, const char *name, const char *type) {
- mCodecInfos.push();
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
- info->mName = name;
- info->mIsEncoder = encoder;
- info->mSoleType = 0;
- info->mTypes = 0;
- info->mQuirks = 0;
- info->mCurrentCaps = NULL;
-
- if (type != NULL) {
- addType(type);
- // if type was specified in attributes, we do not allow
- // subsequent types
- info->mSoleType = info->mTypes;
+status_t MediaCodecList::initializeCapabilities(const char *type) {
+ ALOGV("initializeCapabilities %s:%s",
+ mCurrentInfo->mName.c_str(), type);
+
+ CodecCapabilities caps;
+ status_t err = QueryCodec(
+ mOMX,
+ mCurrentInfo->mName.c_str(),
+ type,
+ mCurrentInfo->mIsEncoder,
+ &caps);
+ if (err != OK) {
+ return err;
}
+
+ return mCurrentInfo->initializeCapabilities(caps);
}
status_t MediaCodecList::addQuirk(const char **attrs) {
@@ -464,36 +511,13 @@ status_t MediaCodecList::addQuirk(const char **attrs) {
return -EINVAL;
}
- uint32_t bit;
- ssize_t index = mCodecQuirks.indexOfKey(name);
- if (index < 0) {
- bit = mCodecQuirks.size();
-
- if (bit == 32) {
- ALOGW("Too many distinct quirk names in configuration.");
- return OK;
- }
-
- mCodecQuirks.add(name, bit);
- } else {
- bit = mCodecQuirks.valueAt(index);
- }
-
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
- info->mQuirks |= 1ul << bit;
-
+ mCurrentInfo->addQuirk(name);
return OK;
}
status_t MediaCodecList::addTypeFromAttributes(const char **attrs) {
const char *name = NULL;
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
- if (info->mSoleType != 0) {
- ALOGE("Codec '%s' already had its type specified", info->mName.c_str());
- return -EINVAL;
- }
-
size_t i = 0;
while (attrs[i] != NULL) {
if (!strcmp(attrs[i], "name")) {
@@ -513,54 +537,47 @@ status_t MediaCodecList::addTypeFromAttributes(const char **attrs) {
return -EINVAL;
}
- addType(name);
-
- return OK;
-}
-
-void MediaCodecList::addType(const char *name) {
- uint32_t bit;
- ssize_t index = mTypes.indexOfKey(name);
- if (index < 0) {
- bit = mTypes.size();
-
- if (bit == 32) {
- ALOGW("Too many distinct type names in configuration.");
- return;
- }
-
- mTypes.add(name, bit);
- } else {
- bit = mTypes.valueAt(index);
- }
-
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
- info->mTypes |= 1ul << bit;
- if (info->mCaps.indexOfKey(bit) < 0) {
- AMessage *msg = new AMessage();
- info->mCaps.add(bit, msg);
+ status_t ret = mCurrentInfo->addMime(name);
+ if (ret == OK) {
+ ret = initializeCapabilities(name);
}
- info->mCurrentCaps = info->mCaps.editValueFor(bit);
+ return ret;
}
+// legacy method for non-advanced codecs
ssize_t MediaCodecList::findCodecByType(
const char *type, bool encoder, size_t startIndex) const {
- ssize_t typeIndex = mTypes.indexOfKey(type);
+ static const char *advancedFeatures[] = {
+ "feature-secure-playback",
+ "feature-tunneled-playback",
+ };
- if (typeIndex < 0) {
- return -ENOENT;
- }
+ size_t numCodecs = mCodecInfos.size();
+ for (; startIndex < numCodecs; ++startIndex) {
+ const MediaCodecInfo &info = *mCodecInfos.itemAt(startIndex).get();
- uint32_t typeMask = 1ul << mTypes.valueAt(typeIndex);
+ if (info.isEncoder() != encoder) {
+ continue;
+ }
+ sp<MediaCodecInfo::Capabilities> capabilities = info.getCapabilitiesFor(type);
+ if (capabilities == NULL) {
+ continue;
+ }
+ const sp<AMessage> &details = capabilities->getDetails();
- while (startIndex < mCodecInfos.size()) {
- const CodecInfo &info = mCodecInfos.itemAt(startIndex);
+ int32_t required;
+ bool isAdvanced = false;
+ for (size_t ix = 0; ix < ARRAY_SIZE(advancedFeatures); ix++) {
+ if (details->findInt32(advancedFeatures[ix], &required) &&
+ required != 0) {
+ isAdvanced = true;
+ break;
+ }
+ }
- if (info.mIsEncoder == encoder && (info.mTypes & typeMask)) {
+ if (!isAdvanced) {
return startIndex;
}
-
- ++startIndex;
}
return -ENOENT;
@@ -616,12 +633,11 @@ status_t MediaCodecList::addLimit(const char **attrs) {
return -EINVAL;
}
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
-
// size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio: range
// quality: range + default + [scale]
// complexity: range + default
bool found;
+
if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
|| name == "blocks-per-second" || name == "complexity"
|| name == "frame-rate" || name == "quality" || name == "size") {
@@ -672,16 +688,16 @@ status_t MediaCodecList::addLimit(const char **attrs) {
name = in_;
}
if (name == "quality") {
- info->mCurrentCaps->setString("quality-scale", scale);
+ mCurrentInfo->addDetail("quality-scale", scale);
}
if (name == "quality" || name == "complexity") {
AString tag = name;
tag.append("-default");
- info->mCurrentCaps->setString(tag.c_str(), def);
+ mCurrentInfo->addDetail(tag, def);
}
AString tag = name;
tag.append("-range");
- info->mCurrentCaps->setString(tag.c_str(), range);
+ mCurrentInfo->addDetail(tag, range);
} else {
AString max, value, ranges;
if (msg->contains("default")) {
@@ -708,13 +724,13 @@ status_t MediaCodecList::addLimit(const char **attrs) {
if (max.size()) {
AString tag = "max-";
tag.append(name);
- info->mCurrentCaps->setString(tag.c_str(), max);
+ mCurrentInfo->addDetail(tag, max);
} else if (value.size()) {
- info->mCurrentCaps->setString(name.c_str(), value);
+ mCurrentInfo->addDetail(name, value);
} else if (ranges.size()) {
AString tag = name;
tag.append("-ranges");
- info->mCurrentCaps->setString(tag.c_str(), ranges);
+ mCurrentInfo->addDetail(tag, ranges);
} else {
ALOGW("Ignoring unrecognized limit '%s'", name.c_str());
}
@@ -769,16 +785,13 @@ status_t MediaCodecList::addFeature(const char **attrs) {
return -EINVAL;
}
- CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
- AString tag = "feature-";
- tag.append(name);
- info->mCurrentCaps->setInt32(tag.c_str(), (required == 1) || (optional == 0));
+ mCurrentInfo->addFeature(name, (required == 1) || (optional == 0));
return OK;
}
ssize_t MediaCodecList::findCodecByName(const char *name) const {
for (size_t i = 0; i < mCodecInfos.size(); ++i) {
- const CodecInfo &info = mCodecInfos.itemAt(i);
+ const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get();
if (info.mName == name) {
return i;
@@ -792,121 +805,4 @@ size_t MediaCodecList::countCodecs() const {
return mCodecInfos.size();
}
-const char *MediaCodecList::getCodecName(size_t index) const {
- if (index >= mCodecInfos.size()) {
- return NULL;
- }
-
- const CodecInfo &info = mCodecInfos.itemAt(index);
- return info.mName.c_str();
-}
-
-bool MediaCodecList::isEncoder(size_t index) const {
- if (index >= mCodecInfos.size()) {
- return false;
- }
-
- const CodecInfo &info = mCodecInfos.itemAt(index);
- return info.mIsEncoder;
-}
-
-bool MediaCodecList::codecHasQuirk(
- size_t index, const char *quirkName) const {
- if (index >= mCodecInfos.size()) {
- return false;
- }
-
- const CodecInfo &info = mCodecInfos.itemAt(index);
-
- if (info.mQuirks != 0) {
- ssize_t index = mCodecQuirks.indexOfKey(quirkName);
- if (index >= 0 && info.mQuirks & (1ul << mCodecQuirks.valueAt(index))) {
- return true;
- }
- }
-
- return false;
-}
-
-status_t MediaCodecList::getSupportedTypes(
- size_t index, Vector<AString> *types) const {
- types->clear();
-
- if (index >= mCodecInfos.size()) {
- return -ERANGE;
- }
-
- const CodecInfo &info = mCodecInfos.itemAt(index);
-
- for (size_t i = 0; i < mTypes.size(); ++i) {
- uint32_t typeMask = 1ul << mTypes.valueAt(i);
-
- if (info.mTypes & typeMask) {
- types->push(mTypes.keyAt(i));
- }
- }
-
- return OK;
-}
-
-status_t MediaCodecList::getCodecCapabilities(
- size_t index, const char *type,
- Vector<ProfileLevel> *profileLevels,
- Vector<uint32_t> *colorFormats,
- uint32_t *flags,
- sp<AMessage> *capabilities) const {
- profileLevels->clear();
- colorFormats->clear();
-
- if (index >= mCodecInfos.size()) {
- return -ERANGE;
- }
-
- const CodecInfo &info = mCodecInfos.itemAt(index);
-
- ssize_t typeIndex = mTypes.indexOfKey(type);
- if (typeIndex < 0) {
- return -EINVAL;
- }
- // essentially doing valueFor without the CHECK abort
- typeIndex = mTypes.valueAt(typeIndex);
-
- OMXClient client;
- status_t err = client.connect();
- if (err != OK) {
- return err;
- }
-
- CodecCapabilities caps;
- err = QueryCodec(
- client.interface(),
- info.mName.c_str(), type, info.mIsEncoder, &caps);
-
- if (err != OK) {
- return err;
- }
-
- for (size_t i = 0; i < caps.mProfileLevels.size(); ++i) {
- const CodecProfileLevel &src = caps.mProfileLevels.itemAt(i);
-
- ProfileLevel profileLevel;
- profileLevel.mProfile = src.mProfile;
- profileLevel.mLevel = src.mLevel;
- profileLevels->push(profileLevel);
- }
-
- for (size_t i = 0; i < caps.mColorFormats.size(); ++i) {
- colorFormats->push(caps.mColorFormats.itemAt(i));
- }
-
- *flags = caps.mFlags;
-
- // TODO this check will be removed once JNI side is merged
- if (capabilities != NULL) {
- *capabilities = info.mCaps.valueFor(typeIndex);
- }
-
- return OK;
-}
-
} // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 354712c..da590a2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -197,7 +197,7 @@ void OMXCodec::findMatchingCodecs(
Vector<CodecNameAndQuirks> *matchingCodecs) {
matchingCodecs->clear();
- const MediaCodecList *list = MediaCodecList::getInstance();
+ const sp<IMediaCodecList> list = MediaCodecList::getInstance();
if (list == NULL) {
return;
}
@@ -213,7 +213,9 @@ void OMXCodec::findMatchingCodecs(
index = matchIndex + 1;
- const char *componentName = list->getCodecName(matchIndex);
+ const sp<MediaCodecInfo> info = list->getCodecInfo(matchIndex);
+ CHECK(info != NULL);
+ const char *componentName = info->getCodecName();
// If a specific codec is requested, skip the non-matching ones.
if (matchComponentName && strcmp(componentName, matchComponentName)) {
@@ -231,7 +233,7 @@ void OMXCodec::findMatchingCodecs(
ssize_t index = matchingCodecs->add();
CodecNameAndQuirks *entry = &matchingCodecs->editItemAt(index);
entry->mName = String8(componentName);
- entry->mQuirks = getComponentQuirks(list, matchIndex);
+ entry->mQuirks = getComponentQuirks(info);
ALOGV("matching '%s' quirks 0x%08x",
entry->mName.string(), entry->mQuirks);
@@ -245,18 +247,15 @@ void OMXCodec::findMatchingCodecs(
// static
uint32_t OMXCodec::getComponentQuirks(
- const MediaCodecList *list, size_t index) {
+ const sp<MediaCodecInfo> &info) {
uint32_t quirks = 0;
- if (list->codecHasQuirk(
- index, "requires-allocate-on-input-ports")) {
+ if (info->hasQuirk("requires-allocate-on-input-ports")) {
quirks |= kRequiresAllocateBufferOnInputPorts;
}
- if (list->codecHasQuirk(
- index, "requires-allocate-on-output-ports")) {
+ if (info->hasQuirk("requires-allocate-on-output-ports")) {
quirks |= kRequiresAllocateBufferOnOutputPorts;
}
- if (list->codecHasQuirk(
- index, "output-buffers-are-unreadable")) {
+ if (info->hasQuirk("output-buffers-are-unreadable")) {
quirks |= kOutputBuffersAreUnreadable;
}
@@ -265,8 +264,7 @@ uint32_t OMXCodec::getComponentQuirks(
// static
bool OMXCodec::findCodecQuirks(const char *componentName, uint32_t *quirks) {
- const MediaCodecList *list = MediaCodecList::getInstance();
-
+ const sp<IMediaCodecList> list = MediaCodecList::getInstance();
if (list == NULL) {
return false;
}
@@ -277,7 +275,9 @@ bool OMXCodec::findCodecQuirks(const char *componentName, uint32_t *quirks) {
return false;
}
- *quirks = getComponentQuirks(list, index);
+ const sp<MediaCodecInfo> info = list->getCodecInfo(index);
+ CHECK(info != NULL);
+ *quirks = getComponentQuirks(info);
return true;
}