codec2: query supported pixel formats from Codec2InfoBuilder
Bug: 216246193
Test: adb shell dumpsys media.player
Change-Id: Id1bf4f81bcd1a8c489fc664ea7dd3a436b667ab8
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index 67d7ed2..63bd64b 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -54,6 +54,9 @@
using Traits = C2Component::Traits;
+// HAL pixel format -> framework color format
+typedef std::map<uint32_t, int32_t> PixelFormatMap;
+
namespace /* unnamed */ {
bool hasPrefix(const std::string& s, const char* prefix) {
@@ -67,6 +70,26 @@
s.compare(s.size() - suffixLen, suffixLen, suffix) == 0;
}
+std::optional<int32_t> findFrameworkColorFormat(
+ const C2FlexiblePixelFormatDescriptorStruct &desc) {
+ switch (desc.bitDepth) {
+ case 8u:
+ if (desc.layout == C2Color::PLANAR_PACKED
+ || desc.layout == C2Color::SEMIPLANAR_PACKED) {
+ return COLOR_FormatYUV420Flexible;
+ }
+ break;
+ case 10u:
+ if (desc.layout == C2Color::SEMIPLANAR_PACKED) {
+ return COLOR_FormatYUVP010;
+ }
+ break;
+ default:
+ break;
+ }
+ return std::nullopt;
+}
+
// returns true if component advertised supported profile level(s)
bool addSupportedProfileLevels(
std::shared_ptr<Codec2Client::Interface> intf,
@@ -211,27 +234,69 @@
void addSupportedColorFormats(
std::shared_ptr<Codec2Client::Interface> intf,
MediaCodecInfo::CapabilitiesWriter *caps,
- const Traits& trait, const std::string &mediaType) {
- (void)intf;
-
+ const Traits& trait, const std::string &mediaType,
+ const PixelFormatMap &pixelFormatMap) {
// TODO: get this from intf() as well, but how do we map them to
// MediaCodec color formats?
bool encoder = trait.kind == C2Component::KIND_ENCODER;
if (mediaType.find("video") != std::string::npos
|| mediaType.find("image") != std::string::npos) {
+
+ std::vector<C2FieldSupportedValuesQuery> query;
+ if (encoder) {
+ C2StreamPixelFormatInfo::input pixelFormat;
+ query.push_back(C2FieldSupportedValuesQuery::Possible(
+ C2ParamField::Make(pixelFormat, pixelFormat.value)));
+ } else {
+ C2StreamPixelFormatInfo::output pixelFormat;
+ query.push_back(C2FieldSupportedValuesQuery::Possible(
+ C2ParamField::Make(pixelFormat, pixelFormat.value)));
+ }
+ std::list<int32_t> supportedColorFormats;
+ if (intf->querySupportedValues(query, C2_DONT_BLOCK) == C2_OK) {
+ if (query[0].status == C2_OK) {
+ const C2FieldSupportedValues &fsv = query[0].values;
+ if (fsv.type == C2FieldSupportedValues::VALUES) {
+ for (C2Value::Primitive value : fsv.values) {
+ auto it = pixelFormatMap.find(value.u32);
+ if (it != pixelFormatMap.end()) {
+ auto it2 = std::find(
+ supportedColorFormats.begin(),
+ supportedColorFormats.end(),
+ it->second);
+ if (it2 == supportedColorFormats.end()) {
+ supportedColorFormats.push_back(it->second);
+ }
+ }
+ }
+ }
+ }
+ }
+ auto addDefaultColorFormat = [caps, &supportedColorFormats](int32_t colorFormat) {
+ caps->addColorFormat(colorFormat);
+ auto it = std::find(
+ supportedColorFormats.begin(), supportedColorFormats.end(), colorFormat);
+ if (it != supportedColorFormats.end()) {
+ supportedColorFormats.erase(it);
+ }
+ };
+
// vendor video codecs prefer opaque format
if (trait.name.find("android") == std::string::npos) {
- caps->addColorFormat(COLOR_FormatSurface);
+ addDefaultColorFormat(COLOR_FormatSurface);
}
- caps->addColorFormat(COLOR_FormatYUV420Flexible);
- caps->addColorFormat(COLOR_FormatYUV420Planar);
- caps->addColorFormat(COLOR_FormatYUV420SemiPlanar);
- caps->addColorFormat(COLOR_FormatYUV420PackedPlanar);
- caps->addColorFormat(COLOR_FormatYUV420PackedSemiPlanar);
+ addDefaultColorFormat(COLOR_FormatYUV420Flexible);
+ addDefaultColorFormat(COLOR_FormatYUV420Planar);
+ addDefaultColorFormat(COLOR_FormatYUV420SemiPlanar);
+ addDefaultColorFormat(COLOR_FormatYUV420PackedPlanar);
+ addDefaultColorFormat(COLOR_FormatYUV420PackedSemiPlanar);
// framework video encoders must support surface format, though it is unclear
// that they will be able to map it if it is opaque
if (encoder && trait.name.find("android") != std::string::npos) {
- caps->addColorFormat(COLOR_FormatSurface);
+ addDefaultColorFormat(COLOR_FormatSurface);
+ }
+ for (int32_t colorFormat : supportedColorFormats) {
+ caps->addColorFormat(colorFormat);
}
}
}
@@ -423,6 +488,7 @@
}
}
+ std::map<std::string, PixelFormatMap> nameToPixelFormatMap;
for (const Traits& trait : traits) {
C2Component::rank_t rank = trait.rank;
@@ -436,8 +502,9 @@
nameAndAliases.insert(nameAndAliases.begin(), trait.name);
for (const std::string &nameOrAlias : nameAndAliases) {
bool isAlias = trait.name != nameOrAlias;
+ std::shared_ptr<Codec2Client> client;
std::shared_ptr<Codec2Client::Interface> intf =
- Codec2Client::CreateInterfaceByName(nameOrAlias.c_str());
+ Codec2Client::CreateInterfaceByName(nameOrAlias.c_str(), &client);
if (!intf) {
ALOGD("could not create interface for %s'%s'",
isAlias ? "alias " : "",
@@ -631,7 +698,40 @@
caps->addProfileLevel(VP8ProfileMain, VP8Level_Version0);
}
}
- addSupportedColorFormats(intf, caps.get(), trait, mediaType);
+
+ auto it = nameToPixelFormatMap.find(client->getServiceName());
+ if (it == nameToPixelFormatMap.end()) {
+ it = nameToPixelFormatMap.try_emplace(client->getServiceName()).first;
+ PixelFormatMap &pixelFormatMap = it->second;
+ pixelFormatMap[HAL_PIXEL_FORMAT_YCBCR_420_888] = COLOR_FormatYUV420Flexible;
+ pixelFormatMap[HAL_PIXEL_FORMAT_YCBCR_P010] = COLOR_FormatYUVP010;
+ pixelFormatMap[HAL_PIXEL_FORMAT_RGBA_1010102] = COLOR_Format32bitABGR2101010;
+ pixelFormatMap[HAL_PIXEL_FORMAT_RGBA_FP16] = COLOR_Format64bitABGRFloat;
+
+ std::shared_ptr<C2StoreFlexiblePixelFormatDescriptorsInfo> pixelFormatInfo;
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ if (client->query(
+ {},
+ {C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
+ C2_MAY_BLOCK,
+ &heapParams) == C2_OK
+ && heapParams.size() == 1u) {
+ pixelFormatInfo.reset(C2StoreFlexiblePixelFormatDescriptorsInfo::From(
+ heapParams[0].release()));
+ }
+ if (pixelFormatInfo && *pixelFormatInfo) {
+ for (size_t i = 0; i < pixelFormatInfo->flexCount(); ++i) {
+ C2FlexiblePixelFormatDescriptorStruct &desc =
+ pixelFormatInfo->m.values[i];
+ std::optional<int32_t> colorFormat = findFrameworkColorFormat(desc);
+ if (colorFormat) {
+ pixelFormatMap[desc.pixelFormat] = *colorFormat;
+ }
+ }
+ }
+ }
+ addSupportedColorFormats(
+ intf, caps.get(), trait, mediaType, it->second);
}
}
}
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index f557830..c075199 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -18,6 +18,9 @@
#define LOG_TAG "Codec2Mapper"
#include <utils/Log.h>
+#include <map>
+#include <optional>
+
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/SurfaceUtils.h>
#include <media/stagefright/foundation/ALookup.h>
@@ -402,6 +405,30 @@
{ C2Config::PROFILE_AV1_0, AV1ProfileMain10HDR10Plus },
};
+// HAL_PIXEL_FORMAT_* -> COLOR_Format*
+ALookup<uint32_t, int32_t> sPixelFormats = {
+ { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, COLOR_FormatSurface },
+
+ // YCBCR_420_888 maps to YUV420Flexible and vice versa
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420Flexible },
+
+ // Fallback matches for YCBCR_420_888
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420Planar },
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420SemiPlanar },
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420PackedPlanar },
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420PackedSemiPlanar },
+
+ // Fallback matches for YUV420Flexible
+ { HAL_PIXEL_FORMAT_YCRCB_420_SP, COLOR_FormatYUV420Flexible },
+ { HAL_PIXEL_FORMAT_YV12, COLOR_FormatYUV420Flexible },
+
+ { HAL_PIXEL_FORMAT_YCBCR_422_SP, COLOR_FormatYUV422PackedSemiPlanar },
+ { HAL_PIXEL_FORMAT_YCBCR_422_I, COLOR_FormatYUV422PackedPlanar },
+ { HAL_PIXEL_FORMAT_YCBCR_P010, COLOR_FormatYUVP010 },
+ { HAL_PIXEL_FORMAT_RGBA_1010102, COLOR_Format32bitABGR2101010 },
+ { HAL_PIXEL_FORMAT_RGBA_FP16, COLOR_Format64bitABGRFloat },
+};
+
/**
* A helper that passes through vendor extension profile and level values.
*/
@@ -975,41 +1002,19 @@
// static
bool C2Mapper::mapPixelFormatFrameworkToCodec(
int32_t frameworkValue, uint32_t *c2Value) {
- switch (frameworkValue) {
- case COLOR_FormatSurface:
- *c2Value = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- return true;
- case COLOR_FormatYUV420Flexible:
- case COLOR_FormatYUV420Planar:
- case COLOR_FormatYUV420SemiPlanar:
- case COLOR_FormatYUV420PackedPlanar:
- case COLOR_FormatYUV420PackedSemiPlanar:
- *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
- return true;
- default:
- // Passthrough
- *c2Value = uint32_t(frameworkValue);
- return true;
+ if (!sPixelFormats.map(frameworkValue, c2Value)) {
+ // passthrough if not mapped
+ *c2Value = uint32_t(frameworkValue);
}
+ return true;
}
// static
bool C2Mapper::mapPixelFormatCodecToFramework(
uint32_t c2Value, int32_t *frameworkValue) {
- switch (c2Value) {
- case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
- *frameworkValue = COLOR_FormatSurface;
- return true;
- case HAL_PIXEL_FORMAT_YCBCR_422_SP:
- case HAL_PIXEL_FORMAT_YCRCB_420_SP:
- case HAL_PIXEL_FORMAT_YCBCR_422_I:
- case HAL_PIXEL_FORMAT_YCBCR_420_888:
- case HAL_PIXEL_FORMAT_YV12:
- *frameworkValue = COLOR_FormatYUV420Flexible;
- return true;
- default:
- // Passthrough
- *frameworkValue = int32_t(c2Value);
- return true;
+ if (!sPixelFormats.map(c2Value, frameworkValue)) {
+ // passthrough if not mapped
+ *frameworkValue = int32_t(c2Value);
}
+ return true;
}