Loading media/codec2/sfplugin/Codec2InfoBuilder.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -637,6 +637,10 @@ status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) { if (encoder) { if (encoder) { attrs |= MediaCodecInfo::kFlagIsEncoder; attrs |= MediaCodecInfo::kFlagIsEncoder; } } if (codec.quirkSet.find("attribute::enforce-xml-capabilities") != codec.quirkSet.end()) { attrs |= MediaCodecInfo::kFlagIsEnforceXmlCapabilities; } if (trait.owner == "software") { if (trait.owner == "software") { attrs |= MediaCodecInfo::kFlagIsSoftwareOnly; attrs |= MediaCodecInfo::kFlagIsSoftwareOnly; } else { } else { Loading media/libmedia/MediaCodecInfo.cpp +105 −0 Original line number Original line Diff line number Diff line Loading @@ -102,6 +102,111 @@ status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const { return OK; return OK; } } static int32_t convertToIntNoSign(const AString &str) { char *end; unsigned long u = strtoul(str.c_str(), &end, 10); if (end == str.c_str() || *end != '\0') { // malformed integer return -1; } if (u > INT32_MAX) { // The number is too big return -1; } return static_cast<int32_t>(u); } static void parseSize(const AString &str, int32_t *width, int32_t *height) { ssize_t ix = str.find("x"); if (ix == -1) { ix = str.find("*"); if (ix == -1) { return; } } AString wStr(str, 0, ix); AString hStr(str, ix + 1, str.size() - ix - 1); *width = convertToIntNoSign(wStr); *height = convertToIntNoSign(hStr); } static void parseRange(const AString &str, int32_t *min, int32_t *max) { ssize_t ix = str.find("-"); if (ix == -1) { return; } AString minStr(str, 0, ix); AString maxStr(str, ix + 1, str.size() - ix - 1); *min = convertToIntNoSign(minStr); *max = convertToIntNoSign(maxStr); } static void parseSizeRange(const AString &str, int32_t *minWidth, int32_t *minHeight, int32_t *maxWidth, int32_t *maxHeight) { ssize_t ix = str.find("-"); if (ix == -1) { return; } AString minSize(str, 0, ix); AString maxSize(str, ix + 1, str.size() - ix - 1); parseSize(minSize, minWidth, minHeight); parseSize(maxSize, maxWidth, maxHeight); } bool MediaCodecInfo::Capabilities::isResolutionSupported(int32_t width, int32_t height) { AString blockSizeStr; AString blockCountStr; int32_t blockWidth = -1; int32_t blockHeight = -1; int32_t maxBlocks = -1; int32_t minBlocks = -1; if (mDetails->findString("block-size", &blockSizeStr)) { parseSize(blockSizeStr, &blockWidth, &blockHeight); } if (mDetails->findString("block-count-range", &blockCountStr)) { parseRange(blockCountStr, &minBlocks, &maxBlocks); } if (maxBlocks != -1 && blockWidth != -1 && blockHeight != -1) { if (maxBlocks < ((width + blockWidth - 1) / blockWidth) * ((height + blockHeight - 1) / blockHeight)) { return false; } } AString sizeRangeStr; int32_t maxWidth = -1; int32_t maxHeight = -1; int32_t minWidth = -1; int32_t minHeight = -1; if (mDetails->findString("size-range", &sizeRangeStr)) { parseSizeRange(sizeRangeStr, &minWidth, &minHeight, &maxWidth, &maxHeight); } if (maxWidth != -1 && maxHeight != -1) { // The logic is that the format is not supported if width or height is outside // of min-max limits, UNLESS codec allows to swap it and in this case format is // not supported if width is outside of min-max height or height is outside of // min-max width if (width < minWidth || height < minHeight || width > maxWidth || height > maxHeight) { int32_t swappable = 0; if (!mDetails->findInt32("feature-can-swap-width-height", &swappable) || swappable == 0) { return false; } if (width < minHeight || height < minWidth || width > maxHeight || height > maxWidth) { return false; } } } return true; } void MediaCodecInfo::CapabilitiesWriter::addDetail( void MediaCodecInfo::CapabilitiesWriter::addDetail( const char* key, const char* value) { const char* key, const char* value) { mCap->mDetails->setString(key, value); mCap->mDetails->setString(key, value); Loading media/libmedia/include/media/MediaCodecInfo.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -59,6 +59,7 @@ struct MediaCodecInfo : public RefBase { kFlagIsVendor = 1 << 1, kFlagIsVendor = 1 << 1, kFlagIsSoftwareOnly = 1 << 2, kFlagIsSoftwareOnly = 1 << 2, kFlagIsHardwareAccelerated = 1 << 3, kFlagIsHardwareAccelerated = 1 << 3, kFlagIsEnforceXmlCapabilities = 1 << 4, }; }; struct Capabilities : public RefBase { struct Capabilities : public RefBase { Loading Loading @@ -96,6 +97,8 @@ struct MediaCodecInfo : public RefBase { */ */ const sp<AMessage> getDetails() const; const sp<AMessage> getDetails() const; bool isResolutionSupported(int32_t width, int32_t height); protected: protected: Vector<ProfileLevel> mProfileLevels; Vector<ProfileLevel> mProfileLevels; SortedVector<ProfileLevel> mProfileLevelsSorted; SortedVector<ProfileLevel> mProfileLevelsSorted; Loading media/libstagefright/MediaCodec.cpp +53 −1 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include "include/SoftwareRenderer.h" #include "include/SoftwareRenderer.h" #include <android/api-level.h> #include <android/binder_manager.h> #include <android/binder_manager.h> #include <android/content/pm/IPackageManagerNative.h> #include <android/content/pm/IPackageManagerNative.h> #include <android/hardware/cas/native/1.0/IDescrambler.h> #include <android/hardware/cas/native/1.0/IDescrambler.h> Loading Loading @@ -2043,6 +2044,40 @@ status_t MediaCodec::configure( return configure(format, nativeWindow, crypto, NULL, flags); return configure(format, nativeWindow, crypto, NULL, flags); } } bool MediaCodec::isResolutionSupported(const sp<AMessage>& format) { int32_t width = -1; int32_t height = -1; int32_t maxWidth = -1; int32_t maxHeight = -1; format->findInt32("width", &width); format->findInt32("height", &height); format->findInt32("max-width", &maxWidth); format->findInt32("max-height", &maxHeight); AString mediaType; if (!format->findString("mime", &mediaType)) { ALOGI("Can not check mediaFormat: No MIME set."); return true; } sp<MediaCodecInfo::Capabilities> caps = mCodecInfo->getCapabilitiesFor(mediaType.c_str()); if (caps == NULL) { ALOGI("Can not get Capabilities for MIME %s.", mediaType.c_str()); return true; } if (width != -1 && height != -1) { if (!caps->isResolutionSupported(width, height)) { ALOGD("Frame resolution (%dx%d) is beyond codec capabilities", width, height); return false; } } if (maxWidth != -1 && maxHeight != -1) { if (!caps->isResolutionSupported(maxWidth, maxHeight)) { ALOGD("Max frame resolution (%dx%d) is beyond codec capabilities", maxWidth, maxHeight); return false; } } return true; } status_t MediaCodec::configure( status_t MediaCodec::configure( const sp<AMessage> &format, const sp<AMessage> &format, const sp<Surface> &surface, const sp<Surface> &surface, Loading Loading @@ -2130,7 +2165,24 @@ status_t MediaCodec::configure( mediametrics_delete(nextMetricsHandle); mediametrics_delete(nextMetricsHandle); return BAD_VALUE; return BAD_VALUE; } } // For applications built with targetSdkVersion of Android U or later (or if MediaCodec's // caller is not an app) we enforce codec resolution capabilities if such enforcement is // required by 'enforce-xml-capabilities' attribute if (android_get_application_target_sdk_version() >= __ANDROID_API_U__) { if (mCodecInfo != nullptr && (mCodecInfo->getAttributes() & MediaCodecInfo::kFlagIsEnforceXmlCapabilities)) { if (!isResolutionSupported(format)) { mErrorLog.log(LOG_TAG, base::StringPrintf("The input resolution of %dx%d is not " "supported for this codec; please query MediaCodecList " "for the supported formats including the resolution. See " "CodecCapabilities#isFormatSupported() and " "VideoCapabilities#isSizeSupported()", mWidth, mHeight)); return BAD_VALUE; } } } } else { } else { if (nextMetricsHandle != 0) { if (nextMetricsHandle != 0) { int32_t channelCount; int32_t channelCount; Loading media/libstagefright/include/media/stagefright/MediaCodec.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -462,6 +462,7 @@ private: constexpr const char *asString(TunnelPeekState state, const char *default_string="?"); constexpr const char *asString(TunnelPeekState state, const char *default_string="?"); void updateTunnelPeek(const sp<AMessage> &msg); void updateTunnelPeek(const sp<AMessage> &msg); void processRenderedFrames(const sp<AMessage> &msg); void processRenderedFrames(const sp<AMessage> &msg); bool isResolutionSupported(const sp<AMessage> &format); inline void initClientConfigParcel(ClientConfigParcel& clientConfig); inline void initClientConfigParcel(ClientConfigParcel& clientConfig); Loading Loading
media/codec2/sfplugin/Codec2InfoBuilder.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -637,6 +637,10 @@ status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) { if (encoder) { if (encoder) { attrs |= MediaCodecInfo::kFlagIsEncoder; attrs |= MediaCodecInfo::kFlagIsEncoder; } } if (codec.quirkSet.find("attribute::enforce-xml-capabilities") != codec.quirkSet.end()) { attrs |= MediaCodecInfo::kFlagIsEnforceXmlCapabilities; } if (trait.owner == "software") { if (trait.owner == "software") { attrs |= MediaCodecInfo::kFlagIsSoftwareOnly; attrs |= MediaCodecInfo::kFlagIsSoftwareOnly; } else { } else { Loading
media/libmedia/MediaCodecInfo.cpp +105 −0 Original line number Original line Diff line number Diff line Loading @@ -102,6 +102,111 @@ status_t MediaCodecInfo::Capabilities::writeToParcel(Parcel *parcel) const { return OK; return OK; } } static int32_t convertToIntNoSign(const AString &str) { char *end; unsigned long u = strtoul(str.c_str(), &end, 10); if (end == str.c_str() || *end != '\0') { // malformed integer return -1; } if (u > INT32_MAX) { // The number is too big return -1; } return static_cast<int32_t>(u); } static void parseSize(const AString &str, int32_t *width, int32_t *height) { ssize_t ix = str.find("x"); if (ix == -1) { ix = str.find("*"); if (ix == -1) { return; } } AString wStr(str, 0, ix); AString hStr(str, ix + 1, str.size() - ix - 1); *width = convertToIntNoSign(wStr); *height = convertToIntNoSign(hStr); } static void parseRange(const AString &str, int32_t *min, int32_t *max) { ssize_t ix = str.find("-"); if (ix == -1) { return; } AString minStr(str, 0, ix); AString maxStr(str, ix + 1, str.size() - ix - 1); *min = convertToIntNoSign(minStr); *max = convertToIntNoSign(maxStr); } static void parseSizeRange(const AString &str, int32_t *minWidth, int32_t *minHeight, int32_t *maxWidth, int32_t *maxHeight) { ssize_t ix = str.find("-"); if (ix == -1) { return; } AString minSize(str, 0, ix); AString maxSize(str, ix + 1, str.size() - ix - 1); parseSize(minSize, minWidth, minHeight); parseSize(maxSize, maxWidth, maxHeight); } bool MediaCodecInfo::Capabilities::isResolutionSupported(int32_t width, int32_t height) { AString blockSizeStr; AString blockCountStr; int32_t blockWidth = -1; int32_t blockHeight = -1; int32_t maxBlocks = -1; int32_t minBlocks = -1; if (mDetails->findString("block-size", &blockSizeStr)) { parseSize(blockSizeStr, &blockWidth, &blockHeight); } if (mDetails->findString("block-count-range", &blockCountStr)) { parseRange(blockCountStr, &minBlocks, &maxBlocks); } if (maxBlocks != -1 && blockWidth != -1 && blockHeight != -1) { if (maxBlocks < ((width + blockWidth - 1) / blockWidth) * ((height + blockHeight - 1) / blockHeight)) { return false; } } AString sizeRangeStr; int32_t maxWidth = -1; int32_t maxHeight = -1; int32_t minWidth = -1; int32_t minHeight = -1; if (mDetails->findString("size-range", &sizeRangeStr)) { parseSizeRange(sizeRangeStr, &minWidth, &minHeight, &maxWidth, &maxHeight); } if (maxWidth != -1 && maxHeight != -1) { // The logic is that the format is not supported if width or height is outside // of min-max limits, UNLESS codec allows to swap it and in this case format is // not supported if width is outside of min-max height or height is outside of // min-max width if (width < minWidth || height < minHeight || width > maxWidth || height > maxHeight) { int32_t swappable = 0; if (!mDetails->findInt32("feature-can-swap-width-height", &swappable) || swappable == 0) { return false; } if (width < minHeight || height < minWidth || width > maxHeight || height > maxWidth) { return false; } } } return true; } void MediaCodecInfo::CapabilitiesWriter::addDetail( void MediaCodecInfo::CapabilitiesWriter::addDetail( const char* key, const char* value) { const char* key, const char* value) { mCap->mDetails->setString(key, value); mCap->mDetails->setString(key, value); Loading
media/libmedia/include/media/MediaCodecInfo.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -59,6 +59,7 @@ struct MediaCodecInfo : public RefBase { kFlagIsVendor = 1 << 1, kFlagIsVendor = 1 << 1, kFlagIsSoftwareOnly = 1 << 2, kFlagIsSoftwareOnly = 1 << 2, kFlagIsHardwareAccelerated = 1 << 3, kFlagIsHardwareAccelerated = 1 << 3, kFlagIsEnforceXmlCapabilities = 1 << 4, }; }; struct Capabilities : public RefBase { struct Capabilities : public RefBase { Loading Loading @@ -96,6 +97,8 @@ struct MediaCodecInfo : public RefBase { */ */ const sp<AMessage> getDetails() const; const sp<AMessage> getDetails() const; bool isResolutionSupported(int32_t width, int32_t height); protected: protected: Vector<ProfileLevel> mProfileLevels; Vector<ProfileLevel> mProfileLevels; SortedVector<ProfileLevel> mProfileLevelsSorted; SortedVector<ProfileLevel> mProfileLevelsSorted; Loading
media/libstagefright/MediaCodec.cpp +53 −1 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include "include/SoftwareRenderer.h" #include "include/SoftwareRenderer.h" #include <android/api-level.h> #include <android/binder_manager.h> #include <android/binder_manager.h> #include <android/content/pm/IPackageManagerNative.h> #include <android/content/pm/IPackageManagerNative.h> #include <android/hardware/cas/native/1.0/IDescrambler.h> #include <android/hardware/cas/native/1.0/IDescrambler.h> Loading Loading @@ -2043,6 +2044,40 @@ status_t MediaCodec::configure( return configure(format, nativeWindow, crypto, NULL, flags); return configure(format, nativeWindow, crypto, NULL, flags); } } bool MediaCodec::isResolutionSupported(const sp<AMessage>& format) { int32_t width = -1; int32_t height = -1; int32_t maxWidth = -1; int32_t maxHeight = -1; format->findInt32("width", &width); format->findInt32("height", &height); format->findInt32("max-width", &maxWidth); format->findInt32("max-height", &maxHeight); AString mediaType; if (!format->findString("mime", &mediaType)) { ALOGI("Can not check mediaFormat: No MIME set."); return true; } sp<MediaCodecInfo::Capabilities> caps = mCodecInfo->getCapabilitiesFor(mediaType.c_str()); if (caps == NULL) { ALOGI("Can not get Capabilities for MIME %s.", mediaType.c_str()); return true; } if (width != -1 && height != -1) { if (!caps->isResolutionSupported(width, height)) { ALOGD("Frame resolution (%dx%d) is beyond codec capabilities", width, height); return false; } } if (maxWidth != -1 && maxHeight != -1) { if (!caps->isResolutionSupported(maxWidth, maxHeight)) { ALOGD("Max frame resolution (%dx%d) is beyond codec capabilities", maxWidth, maxHeight); return false; } } return true; } status_t MediaCodec::configure( status_t MediaCodec::configure( const sp<AMessage> &format, const sp<AMessage> &format, const sp<Surface> &surface, const sp<Surface> &surface, Loading Loading @@ -2130,7 +2165,24 @@ status_t MediaCodec::configure( mediametrics_delete(nextMetricsHandle); mediametrics_delete(nextMetricsHandle); return BAD_VALUE; return BAD_VALUE; } } // For applications built with targetSdkVersion of Android U or later (or if MediaCodec's // caller is not an app) we enforce codec resolution capabilities if such enforcement is // required by 'enforce-xml-capabilities' attribute if (android_get_application_target_sdk_version() >= __ANDROID_API_U__) { if (mCodecInfo != nullptr && (mCodecInfo->getAttributes() & MediaCodecInfo::kFlagIsEnforceXmlCapabilities)) { if (!isResolutionSupported(format)) { mErrorLog.log(LOG_TAG, base::StringPrintf("The input resolution of %dx%d is not " "supported for this codec; please query MediaCodecList " "for the supported formats including the resolution. See " "CodecCapabilities#isFormatSupported() and " "VideoCapabilities#isSizeSupported()", mWidth, mHeight)); return BAD_VALUE; } } } } else { } else { if (nextMetricsHandle != 0) { if (nextMetricsHandle != 0) { int32_t channelCount; int32_t channelCount; Loading
media/libstagefright/include/media/stagefright/MediaCodec.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -462,6 +462,7 @@ private: constexpr const char *asString(TunnelPeekState state, const char *default_string="?"); constexpr const char *asString(TunnelPeekState state, const char *default_string="?"); void updateTunnelPeek(const sp<AMessage> &msg); void updateTunnelPeek(const sp<AMessage> &msg); void processRenderedFrames(const sp<AMessage> &msg); void processRenderedFrames(const sp<AMessage> &msg); bool isResolutionSupported(const sp<AMessage> &format); inline void initClientConfigParcel(ClientConfigParcel& clientConfig); inline void initClientConfigParcel(ClientConfigParcel& clientConfig); Loading