diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp index 051f88a29b..96f86e8d59 100644 --- a/media/codec2/sfplugin/CCodecConfig.cpp +++ b/media/codec2/sfplugin/CCodecConfig.cpp @@ -617,6 +617,11 @@ void CCodecConfig::initializeStandardParams() { return C2Value(); })); + add(ConfigMapper(KEY_PIXEL_ASPECT_RATIO_WIDTH, C2_PARAMKEY_PIXEL_ASPECT_RATIO, "width") + .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); + add(ConfigMapper(KEY_PIXEL_ASPECT_RATIO_HEIGHT, C2_PARAMKEY_PIXEL_ASPECT_RATIO, "height") + .limitTo((D::VIDEO | D::IMAGE) & D::RAW)); + add(ConfigMapper(KEY_CHANNEL_COUNT, C2_PARAMKEY_CHANNEL_COUNT, "value") .limitTo(D::AUDIO)); // read back to both formats add(ConfigMapper(KEY_CHANNEL_COUNT, C2_PARAMKEY_CODED_CHANNEL_COUNT, "value") diff --git a/media/codec2/sfplugin/tests/CCodecConfig_test.cpp b/media/codec2/sfplugin/tests/CCodecConfig_test.cpp index 7b445a0960..c9caa018a1 100644 --- a/media/codec2/sfplugin/tests/CCodecConfig_test.cpp +++ b/media/codec2/sfplugin/tests/CCodecConfig_test.cpp @@ -24,6 +24,8 @@ #include #include +#include + namespace { enum ExtendedC2ParamIndexKind : C2Param::type_index_t { @@ -56,9 +58,15 @@ public: CCodecConfigTest() : mReflector{std::make_shared()} { + } + + void init( + C2Component::domain_t domain, + C2Component::kind_t kind, + const char *mediaType) { sp cachedConfigurable = new hardware::media::c2::V1_0::utils::CachedConfigurable( - std::make_unique(mReflector)); + std::make_unique(mReflector, domain, kind, mediaType)); cachedConfigurable->init(std::make_shared()); mConfigurable = std::make_shared(cachedConfigurable); } @@ -71,9 +79,13 @@ public: class Configurable : public hardware::media::c2::V1_0::utils::ConfigurableC2Intf { public: - explicit Configurable(const std::shared_ptr &reflector) + Configurable( + const std::shared_ptr &reflector, + C2Component::domain_t domain, + C2Component::kind_t kind, + const char *mediaType) : ConfigurableC2Intf("name", 0u), - mImpl(reflector) { + mImpl(reflector, domain, kind, mediaType) { } c2_status_t query( @@ -104,10 +116,67 @@ public: private: class Impl : public C2InterfaceHelper { public: - explicit Impl(const std::shared_ptr &reflector) + Impl(const std::shared_ptr &reflector, + C2Component::domain_t domain, + C2Component::kind_t kind, + const char *mediaType) : C2InterfaceHelper{reflector} { + setDerivedInstance(this); + addParameter( + DefineParam(mDomain, C2_PARAMKEY_COMPONENT_DOMAIN) + .withConstValue(new C2ComponentDomainSetting(domain)) + .build()); + + addParameter( + DefineParam(mKind, C2_PARAMKEY_COMPONENT_KIND) + .withConstValue(new C2ComponentKindSetting(kind)) + .build()); + + addParameter( + DefineParam(mInputStreamCount, C2_PARAMKEY_INPUT_STREAM_COUNT) + .withConstValue(new C2PortStreamCountTuning::input(1)) + .build()); + + addParameter( + DefineParam(mOutputStreamCount, C2_PARAMKEY_OUTPUT_STREAM_COUNT) + .withConstValue(new C2PortStreamCountTuning::output(1)) + .build()); + + const char *rawMediaType = ""; + switch (domain) { + case C2Component::DOMAIN_IMAGE: [[fallthrough]]; + case C2Component::DOMAIN_VIDEO: + rawMediaType = MIMETYPE_VIDEO_RAW; + break; + case C2Component::DOMAIN_AUDIO: + rawMediaType = MIMETYPE_AUDIO_RAW; + break; + default: + break; + } + bool isEncoder = kind == C2Component::KIND_ENCODER; + std::string inputMediaType{isEncoder ? rawMediaType : mediaType}; + std::string outputMediaType{isEncoder ? mediaType : rawMediaType}; + + auto allocSharedString = [](const auto ¶m, const std::string &str) { + typedef typename std::remove_reference::type::element_type T; + std::shared_ptr ret = T::AllocShared(str.length() + 1); + strcpy(ret->m.value, str.c_str()); + return ret; + }; + + addParameter( + DefineParam(mInputMediaType, C2_PARAMKEY_INPUT_MEDIA_TYPE) + .withConstValue(allocSharedString(mInputMediaType, inputMediaType)) + .build()); + + addParameter( + DefineParam(mOutputMediaType, C2_PARAMKEY_OUTPUT_MEDIA_TYPE) + .withConstValue(allocSharedString(mOutputMediaType, outputMediaType)) + .build()); + addParameter( DefineParam(mInt32Input, C2_PARAMKEY_VENDOR_INT32) .withDefault(new C2PortVendorInt32Info::input(0)) @@ -129,12 +198,29 @@ public: .withSetter(Setter) .build()); - // TODO: SDK params + addParameter( + DefineParam(mPixelAspectRatio, C2_PARAMKEY_PIXEL_ASPECT_RATIO) + .withDefault(new C2StreamPixelAspectRatioInfo::output(0u, 1, 1)) + .withFields({ + C2F(mPixelAspectRatio, width).any(), + C2F(mPixelAspectRatio, height).any(), + }) + .withSetter(Setter) + .build()); + + // TODO: more SDK params } private: + std::shared_ptr mDomain; + std::shared_ptr mKind; + std::shared_ptr mInputStreamCount; + std::shared_ptr mOutputStreamCount; + std::shared_ptr mInputMediaType; + std::shared_ptr mOutputMediaType; std::shared_ptr mInt32Input; std::shared_ptr mInt64Output; std::shared_ptr mStringInput; + std::shared_ptr mPixelAspectRatio; template static C2R Setter(bool, C2P &) { @@ -163,6 +249,10 @@ T *FindParam(const std::vector> &vec) { } TEST_F(CCodecConfigTest, SetVendorParam) { + // Test at audio domain, as video domain has a few local parameters that + // interfere with the testing. + init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC); + ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable)); sp format{new AMessage}; @@ -172,7 +262,7 @@ TEST_F(CCodecConfigTest, SetVendorParam) { std::vector> configUpdate; ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams( - mConfigurable, format, D::IS_INPUT | D::IS_OUTPUT, C2_MAY_BLOCK, &configUpdate)); + mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate)); ASSERT_EQ(3u, configUpdate.size()); C2PortVendorInt32Info::input *i32 = @@ -192,6 +282,10 @@ TEST_F(CCodecConfigTest, SetVendorParam) { } TEST_F(CCodecConfigTest, VendorParamUpdate_Unsubscribed) { + // Test at audio domain, as video domain has a few local parameters that + // interfere with the testing. + init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC); + ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable)); std::vector> configUpdate; @@ -204,7 +298,7 @@ TEST_F(CCodecConfigTest, VendorParamUpdate_Unsubscribed) { configUpdate.push_back(std::move(str)); // The vendor parameters are not yet subscribed - ASSERT_FALSE(mConfig.updateConfiguration(configUpdate, D::IS_INPUT | D::IS_OUTPUT)); + ASSERT_FALSE(mConfig.updateConfiguration(configUpdate, D::ALL)); int32_t vendorInt32{0}; ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32)) @@ -226,6 +320,10 @@ TEST_F(CCodecConfigTest, VendorParamUpdate_Unsubscribed) { } TEST_F(CCodecConfigTest, VendorParamUpdate_AllSubscribed) { + // Test at audio domain, as video domain has a few local parameters that + // interfere with the testing. + init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC); + ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable)); // Force subscribe to all vendor params @@ -240,7 +338,7 @@ TEST_F(CCodecConfigTest, VendorParamUpdate_AllSubscribed) { configUpdate.push_back(C2Param::Copy(i64)); configUpdate.push_back(std::move(str)); - ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::IS_INPUT | D::IS_OUTPUT)); + ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL)); int32_t vendorInt32{0}; ASSERT_TRUE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32)) @@ -265,6 +363,10 @@ TEST_F(CCodecConfigTest, VendorParamUpdate_AllSubscribed) { } TEST_F(CCodecConfigTest, VendorParamUpdate_PartiallySubscribed) { + // Test at audio domain, as video domain has a few local parameters that + // interfere with the testing. + init(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER, MIMETYPE_AUDIO_AAC); + ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable)); // Subscribe to example.int32 only @@ -273,7 +375,7 @@ TEST_F(CCodecConfigTest, VendorParamUpdate_PartiallySubscribed) { format->setInt32(KEY_VENDOR_INT32, 0); configUpdate.clear(); ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams( - mConfigurable, format, D::IS_INPUT | D::IS_OUTPUT, C2_MAY_BLOCK, &configUpdate)); + mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate)); ASSERT_EQ(OK, mConfig.setParameters(mConfigurable, configUpdate, C2_MAY_BLOCK)); C2PortVendorInt32Info::input i32(kCodec2Int32); @@ -286,7 +388,7 @@ TEST_F(CCodecConfigTest, VendorParamUpdate_PartiallySubscribed) { configUpdate.push_back(std::move(str)); // Only example.i32 should be updated - ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::IS_INPUT | D::IS_OUTPUT)); + ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL)); int32_t vendorInt32{0}; ASSERT_TRUE(mConfig.mInputFormat->findInt32(KEY_VENDOR_INT32, &vendorInt32)) @@ -308,4 +410,51 @@ TEST_F(CCodecConfigTest, VendorParamUpdate_PartiallySubscribed) { << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str(); } +TEST_F(CCodecConfigTest, SetPixelAspectRatio) { + init(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER, MIMETYPE_VIDEO_AVC); + + ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable)); + + sp format{new AMessage}; + format->setInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, 12); + format->setInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, 11); + + std::vector> configUpdate; + ASSERT_EQ(OK, mConfig.getConfigUpdateFromSdkParams( + mConfigurable, format, D::ALL, C2_MAY_BLOCK, &configUpdate)); + + ASSERT_EQ(1u, configUpdate.size()); + C2StreamPixelAspectRatioInfo::output *par = + FindParam::type>(configUpdate); + ASSERT_NE(nullptr, par); + ASSERT_EQ(12, par->width); + ASSERT_EQ(11, par->height); +} + +TEST_F(CCodecConfigTest, PixelAspectRatioUpdate) { + init(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER, MIMETYPE_VIDEO_AVC); + + ASSERT_EQ(OK, mConfig.initialize(mReflector, mConfigurable)); + + std::vector> configUpdate; + C2StreamPixelAspectRatioInfo::output par(0u, 12, 11); + configUpdate.push_back(C2Param::Copy(par)); + + ASSERT_TRUE(mConfig.updateConfiguration(configUpdate, D::ALL)); + + int32_t parWidth{0}; + ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, &parWidth)) + << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str(); + ASSERT_EQ(12, parWidth); + ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_WIDTH, &parWidth)) + << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str(); + + int32_t parHeight{0}; + ASSERT_TRUE(mConfig.mOutputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, &parHeight)) + << "mOutputFormat = " << mConfig.mOutputFormat->debugString().c_str(); + ASSERT_EQ(11, parHeight); + ASSERT_FALSE(mConfig.mInputFormat->findInt32(KEY_PIXEL_ASPECT_RATIO_HEIGHT, &parHeight)) + << "mInputFormat = " << mConfig.mInputFormat->debugString().c_str(); +} + } // namespace android diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h index bfdc9e7376..178d3342d8 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h +++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h @@ -790,6 +790,8 @@ constexpr char KEY_MIME[] = "mime"; constexpr char KEY_OPERATING_RATE[] = "operating-rate"; constexpr char KEY_OUTPUT_REORDER_DEPTH[] = "output-reorder-depth"; constexpr char KEY_PCM_ENCODING[] = "pcm-encoding"; +constexpr char KEY_PIXEL_ASPECT_RATIO_HEIGHT[] = "sar-height"; +constexpr char KEY_PIXEL_ASPECT_RATIO_WIDTH[] = "sar-width"; constexpr char KEY_PREPEND_HEADERS_TO_SYNC_FRAMES[] = "prepend-sps-pps-to-idr-frames"; constexpr char KEY_PRIORITY[] = "priority"; constexpr char KEY_PROFILE[] = "profile";