Merge "Restrict APV codec to Android B and above" into main
diff --git a/apex/Android.bp b/apex/Android.bp
index b0d7c02..356bf03 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -173,6 +173,7 @@
"mediaswcodec",
],
native_shared_libs: [
+ "libapexcodecs",
"libcodec2_hidl@1.0",
"libcodec2_hidl@1.1",
"libcodec2_hidl@1.2",
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index 4dc5fb1..c24d51f 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -33,7 +33,7 @@
# TODO: replace the following when apex has a way to auto-generate this list
# namespace.default.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
+namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
###############################################################################
# "platform" namespace
@@ -138,7 +138,7 @@
# TODO: replace the following when apex has a way to auto-generate this list
# namespace.sphal.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
+namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
# Add a link for libz.so which is llndk on devices where VNDK is not enforced.
namespace.sphal.link.platform.shared_libs += libz.so
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
index c8c6e8e..33ea5ea 100644
--- a/drm/libmediadrm/DrmHalHidl.cpp
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -339,7 +339,7 @@
DrmUtils::LOG2BI("makeDrmFactories: using default passthrough drm instance");
factories.push_back(passthrough);
} else {
- DrmUtils::LOG2BE("Failed to find passthrough drm factories");
+ DrmUtils::LOG2BW("Failed to find passthrough drm factories");
}
}
return factories;
diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig
index ee697ee..c820a2c 100644
--- a/media/aconfig/codec_fwk.aconfig
+++ b/media/aconfig/codec_fwk.aconfig
@@ -21,6 +21,13 @@
}
flag {
+ name: "codec_availability"
+ namespace: "codec_fwk"
+ description: "Feature flag for codec availability HAL API support"
+ bug: "363282971"
+}
+
+flag {
name: "codec_buffer_state_cleanup"
namespace: "codec_fwk"
description: "Bugfix flag for more buffer state cleanup in MediaCodec"
diff --git a/media/audio/aconfig/Android.bp b/media/audio/aconfig/Android.bp
index a5aeff2..5f4a6a1 100644
--- a/media/audio/aconfig/Android.bp
+++ b/media/audio/aconfig/Android.bp
@@ -116,7 +116,11 @@
package: "android.media.audio",
container: "system",
srcs: ["audio_framework.aconfig"],
- visibility: ["//frameworks/base/api"],
+ visibility: [
+ "//frameworks/base/api",
+ "//frameworks/base/core/res",
+ ],
+ exportable: true,
}
aconfig_declarations {
@@ -149,6 +153,20 @@
}
java_aconfig_library {
+ name: "android.media.audio-aconfig-exported-java",
+ aconfig_declarations: "android.media.audio-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ min_sdk_version: "Tiramisu",
+ mode: "exported",
+ apex_available: [
+ "com.android.btservices",
+ ],
+ visibility: [
+ "//packages/modules/Bluetooth:__subpackages__",
+ ],
+}
+
+java_aconfig_library {
name: "android.media.audiopolicy-aconfig-java",
aconfig_declarations: "android.media.audiopolicy-aconfig",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
diff --git a/media/audio/aconfig/audio_framework.aconfig b/media/audio/aconfig/audio_framework.aconfig
index ea5f26d..b155bac 100644
--- a/media/audio/aconfig/audio_framework.aconfig
+++ b/media/audio/aconfig/audio_framework.aconfig
@@ -23,6 +23,14 @@
}
flag {
+ name: "deprecate_stream_bt_sco"
+ namespace: "media_audio"
+ description: "Deprecate STREAM_BLUETOOTH_SCO"
+ is_exported: true
+ bug: "376756660"
+}
+
+flag {
name: "feature_spatial_audio_headtracking_low_latency"
is_exported: true
namespace: "media_audio"
diff --git a/media/codec2/components/apv/C2SoftApvDec.cpp b/media/codec2/components/apv/C2SoftApvDec.cpp
index 0617d06..0064cec 100644
--- a/media/codec2/components/apv/C2SoftApvDec.cpp
+++ b/media/codec2/components/apv/C2SoftApvDec.cpp
@@ -493,10 +493,13 @@
mOutBufferFlush(nullptr),
mIvColorformat(IV_YUV_420P),
mOutputDelay(kDefaultOutputDelay),
+ mHeaderDecoded(false),
+ mOutIndex(0u),
+ mHalPixelFormat(HAL_PIXEL_FORMAT_YV12),
mWidth(320),
mHeight(240),
- mHeaderDecoded(false),
- mOutIndex(0u) {
+ mSignalledOutputEos(false),
+ mSignalledError(false) {
oapvdHandle = NULL;
oapvmHandle = NULL;
outputCsp = OUTPUT_CSP_NATIVE;
diff --git a/media/codec2/components/apv/C2SoftApvDec.h b/media/codec2/components/apv/C2SoftApvDec.h
index 22bfcff..f5beb8f 100644
--- a/media/codec2/components/apv/C2SoftApvDec.h
+++ b/media/codec2/components/apv/C2SoftApvDec.h
@@ -66,7 +66,7 @@
namespace android {
-struct C2SoftApvDec : public SimpleC2Component {
+struct C2SoftApvDec final : public SimpleC2Component {
class IntfImpl;
C2SoftApvDec(const char* name, c2_node_id_t id, const std::shared_ptr<IntfImpl>& intfImpl);
diff --git a/media/codec2/components/apv/C2SoftApvEnc.cpp b/media/codec2/components/apv/C2SoftApvEnc.cpp
index 999c08d..a61cfd6 100644
--- a/media/codec2/components/apv/C2SoftApvEnc.cpp
+++ b/media/codec2/components/apv/C2SoftApvEnc.cpp
@@ -505,6 +505,8 @@
mReceivedFrames = 0;
mReceivedFirstFrame = false;
mColorFormat = OAPV_CF_PLANAR2;
+ memset(&mInputFrames, 0, sizeof(mInputFrames));
+ memset(&mReconFrames, 0, sizeof(mReconFrames));
return C2_OK;
}
@@ -512,6 +514,7 @@
for (int32_t i = 0; i < MAX_NUM_FRMS; i++) {
if (mInputFrames.frm[i].imgb != nullptr) {
imgb_release(mInputFrames.frm[i].imgb);
+ mInputFrames.frm[i].imgb = nullptr;
}
}
diff --git a/media/codec2/components/apv/C2SoftApvEnc.h b/media/codec2/components/apv/C2SoftApvEnc.h
index 445b042..441c663 100644
--- a/media/codec2/components/apv/C2SoftApvEnc.h
+++ b/media/codec2/components/apv/C2SoftApvEnc.h
@@ -31,11 +31,11 @@
#define APV_QP_MIN 1
#define APV_QP_MAX 51
-struct C2SoftApvEnc : public SimpleC2Component {
+struct C2SoftApvEnc final : public SimpleC2Component {
class IntfImpl;
C2SoftApvEnc(const char* name, c2_node_id_t id, const std::shared_ptr<IntfImpl>& intfImpl);
- ~C2SoftApvEnc();
+ virtual ~C2SoftApvEnc();
// From SimpleC2Component
c2_status_t onInit() override;
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 665f9fc..17dfe9c 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -997,7 +997,7 @@
return -1;
}
- if (toUsage != graphicBuffer->getUsage()) {
+ if ((toUsage & graphicBuffer->getUsage()) != toUsage) {
sp<GraphicBuffer> newBuffer = new GraphicBuffer(
graphicBuffer->handle, GraphicBuffer::CLONE_HANDLE,
graphicBuffer->width, graphicBuffer->height, graphicBuffer->format,
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index b369a62..67c6715 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -58,8 +58,6 @@
"libaudioclient",
"libaudioutils",
"libbase_ndk",
- "libcgrouprc",
- "libcgrouprc_format",
"libcutils",
"libjsoncpp",
"liblog",
diff --git a/media/libaudioclient/aidl/fuzzer/Android.bp b/media/libaudioclient/aidl/fuzzer/Android.bp
index a215c0b..14e528f 100644
--- a/media/libaudioclient/aidl/fuzzer/Android.bp
+++ b/media/libaudioclient/aidl/fuzzer/Android.bp
@@ -24,8 +24,6 @@
"android.hardware.audio.common@7.0-enums",
"audiopermissioncontroller",
"libaudiomockhal",
- "libcgrouprc",
- "libcgrouprc_format",
"libfakeservicemanager",
"libjsoncpp",
"libmediametricsservice",
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index 8bca8df..65ada70 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -37,8 +37,6 @@
"effect-aidl-cpp",
"libaudioclient",
"libbase",
- "libcgrouprc",
- "libcgrouprc_format",
"libcutils",
"libjsoncpp",
"liblog",
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index ddf14a3..3941280 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -107,7 +107,6 @@
"framework-permission-aidl-cpp",
"libaudioutils",
"libbase",
- "libcgrouprc",
"libdl",
"libmedia",
"libmedia_helper",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b17be6b..8cb1674 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1189,6 +1189,19 @@
return new PersistentSurface(bufferProducer, bufferSource);
}
+//static
+status_t MediaCodec::getGloballyAvailableResources(std::vector<GlobalResourceInfo>& resources) {
+ resources.clear();
+ // Make sure codec availability feature is on.
+ if (!android::media::codec::codec_availability()) {
+ return ERROR_UNSUPPORTED;
+ }
+ // TODO: For now this is just an empty function.
+ // The actual implementation should use component store to query the
+ // available resources from hal, and fill in resources with the same.
+ return ERROR_UNSUPPORTED;
+}
+
// GenerateCodecId generates a 64bit Random ID for each codec that is created.
// The Codec ID is generated as:
// - A process-unique random high 32bits
@@ -1295,7 +1308,12 @@
CHECK_EQ(mState, UNINITIALIZED);
mResourceManagerProxy->removeClient();
- flushMediametrics();
+ flushMediametrics(); // this deletes mMetricsHandle
+ // don't keep the last metrics handle around
+ if (mLastMetricsHandle != 0) {
+ mediametrics_delete(mLastMetricsHandle);
+ mLastMetricsHandle = 0;
+ }
// clean any saved metrics info we stored as part of configure()
if (mConfigureMsg != nullptr) {
@@ -1306,7 +1324,7 @@
}
}
-// except for in constructor, called from the looper thread (and therefore mutexed)
+// except for in constructor, called from the looper thread (and therefore not mutexed)
void MediaCodec::initMediametrics() {
if (mMetricsHandle == 0) {
mMetricsHandle = mediametrics_create(kCodecKeyName);
@@ -1332,6 +1350,7 @@
mInputBufferCounter = 0;
}
+ mSubsessionCount = 0;
mLifetimeStartNs = systemTime(SYSTEM_TIME_MONOTONIC);
resetMetricsFields();
}
@@ -1343,6 +1362,17 @@
mReliabilityContextMetrics = ReliabilityContextMetrics();
}
+// always called from the looper thread (and therefore not mutexed)
+void MediaCodec::resetSubsessionMetricsFields() {
+ mBytesEncoded = 0;
+ mFramesEncoded = 0;
+ mFramesInput = 0;
+ mBytesInput = 0;
+ mEarliestEncodedPtsUs = INT64_MAX;
+ mLatestEncodedPtsUs = INT64_MIN;
+}
+
+// always called from the looper thread
void MediaCodec::updateMediametrics() {
if (mMetricsHandle == 0) {
ALOGV("no metrics handle found");
@@ -1707,6 +1737,7 @@
}
}
+// except for in destructor, called from the looper thread
void MediaCodec::flushMediametrics() {
ALOGV("flushMediametrics");
@@ -1720,7 +1751,14 @@
if (mMetricsToUpload && mediametrics_count(mMetricsHandle) > 0) {
mediametrics_selfRecord(mMetricsHandle);
}
- mediametrics_delete(mMetricsHandle);
+ // keep previous metrics handle for subsequent getMetrics() calls.
+ // NOTE: There could be multiple error events, each flushing the metrics.
+ // We keep the last non-empty metrics handle, so getMetrics() in the
+ // next call will get the latest metrics prior to the errors.
+ if (mLastMetricsHandle != 0) {
+ mediametrics_delete(mLastMetricsHandle);
+ }
+ mLastMetricsHandle = mMetricsHandle;
mMetricsHandle = 0;
}
// we no longer have anything pending upload
@@ -1885,7 +1923,10 @@
});
}
- if (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder)) {
+ // NOTE: these were erroneously restricted to video encoders, but we want them for all
+ // codecs.
+ if (android::media::codec::provider_->subsession_metrics()
+ || (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder))) {
mBytesInput += buffer->size();
mFramesInput++;
}
@@ -1907,12 +1948,15 @@
++mInputBufferCounter;
}
-// when we get a buffer back from the codec
+// when we get a buffer back from the codec, always called from the looper thread
void MediaCodec::statsBufferReceived(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer) {
CHECK_NE(mState, UNINITIALIZED);
- if (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder)) {
+ // NOTE: these were erroneously restricted to video encoders, but we want them for all
+ // codecs.
+ if (android::media::codec::provider_->subsession_metrics()
+ || (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder))) {
int32_t flags = 0;
(void) buffer->meta()->findInt32("flags", &flags);
@@ -2522,6 +2566,31 @@
return err;
}
+status_t MediaCodec::getRequiredResources(std::vector<InstanceResourceInfo>& resources) {
+ resources.clear();
+ // Make sure codec availability feature is on.
+ if (!android::media::codec::codec_availability()) {
+ return ERROR_UNSUPPORTED;
+ }
+ // Make sure that the codec was configured already.
+ if (mState != CONFIGURED && mState != STARTING && mState != STARTED &&
+ mState != FLUSHING && mState != FLUSHED) {
+ ALOGE("Codec wasn't configured yet!");
+ return INVALID_OPERATION;
+ }
+
+ if (!mRequiredResourceInfo.empty()) {
+ resources = mRequiredResourceInfo;
+ return OK;
+ }
+
+ // TODO: For now this is just an empty function.
+ // The actual implementation should use component interface
+ // (for example, through mCodec->getRequiredDeviceResources) to query the
+ // the required resources for this configuration, and fill in resources with the same.
+ return ERROR_UNSUPPORTED;
+}
+
// Media Format Shaping support
//
@@ -3610,6 +3679,10 @@
updateMediametrics();
results = mediametrics_dup(mMetricsHandle);
updateEphemeralMediametrics(results);
+ } else if (mLastMetricsHandle != 0) {
+ // After error, mMetricsHandle is cleared, but we keep the last
+ // metrics around so that it can be queried by getMetrics().
+ results = mediametrics_dup(mLastMetricsHandle);
} else {
results = mediametrics_dup(mMetricsHandle);
}
@@ -3879,6 +3952,7 @@
return true;
}
+// always called from the looper thread
MediaCodec::DequeueOutputResult MediaCodec::handleDequeueOutputBuffer(
const sp<AReplyToken> &replyID, bool newRequest) {
if (!isExecuting()) {
@@ -3934,6 +4008,9 @@
response->setInt32("flags", flags);
+ // NOTE: we must account the stats for an output buffer only after we
+ // already handled a potential output format change that could have
+ // started a new subsession.
statsBufferReceived(timeUs, buffer);
response->postReply(replyID);
@@ -5838,6 +5915,7 @@
}
}
+// always called from the looper thread
void MediaCodec::handleOutputFormatChangeIfNeeded(const sp<MediaCodecBuffer> &buffer) {
sp<AMessage> format = buffer->format();
if (mOutputFormat == format) {
@@ -5921,6 +5999,24 @@
}
}
}
+
+ // Update the width and the height.
+ int32_t left = 0, top = 0, right = 0, bottom = 0, width = 0, height = 0;
+ bool newSubsession = false;
+ if (android::media::codec::provider_->subsession_metrics()
+ && mOutputFormat->findInt32("width", &width)
+ && mOutputFormat->findInt32("height", &height)
+ && (width != mWidth || height != mHeight)) {
+ // consider a new subsession if the width or height changes.
+ newSubsession = true;
+ }
+ // TODO: properly detect new audio subsession
+
+ // Only consider a new subsession if we already have output (from a previous subsession).
+ if (newSubsession && mMetricsToUpload && mBytesEncoded > 0) {
+ handleStartingANewSubsession();
+ }
+
if (mFlags & kFlagIsAsync) {
onOutputFormatChanged();
} else {
@@ -5928,8 +6024,6 @@
postActivityNotificationIfPossible();
}
- // Update the width and the height.
- int32_t left = 0, top = 0, right = 0, bottom = 0, width = 0, height = 0;
bool resolutionChanged = false;
if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
mWidth = right - left + 1;
@@ -5956,6 +6050,35 @@
updateHdrMetrics(false /* isConfig */);
}
+// always called from the looper thread (and therefore not mutexed)
+void MediaCodec::handleStartingANewSubsession() {
+ // create a new metrics item for the subsession with the new resolution.
+ // TODO: properly account input counts for the previous and the new
+ // subsessions. We only find out that a new subsession started from the
+ // output format, but by that time we already accounted the input counts
+ // to the previous subsession.
+ flushMediametrics(); // this deletes mMetricsHandle, but stores it in mLastMetricsHandle
+
+ // hence mLastMetricsHandle has the metrics item for the previous subsession.
+ if ((mFlags & kFlagIsAsync) && mCallback != nullptr) {
+ sp<AMessage> msg = mCallback->dup();
+ msg->setInt32("callbackID", CB_METRICS_FLUSHED);
+ std::unique_ptr<mediametrics::Item> flushedMetrics(
+ mediametrics::Item::convert(mediametrics_dup(mLastMetricsHandle)));
+ msg->setObject("metrics", new WrapperObject<std::unique_ptr<mediametrics::Item>>(
+ std::move(flushedMetrics)));
+ msg->post();
+ }
+
+ // reuse/continue old metrics item for the new subsession.
+ mMetricsHandle = mediametrics_dup(mLastMetricsHandle);
+ mMetricsToUpload = true;
+ // TODO: configured width/height for the new subsession should be the
+ // previous width/height.
+ mSubsessionCount++;
+ resetSubsessionMetricsFields();
+}
+
void MediaCodec::extractCSD(const sp<AMessage> &format) {
mCSD.clear();
@@ -6956,6 +7079,18 @@
}
}
+void MediaCodec::onRequiredResourcesChanged(
+ const std::vector<InstanceResourceInfo>& resourceInfo) {
+ mRequiredResourceInfo = resourceInfo;
+ // Make sure codec availability feature is on.
+ if (mCallback != nullptr && android::media::codec::codec_availability()) {
+ // Post the callback
+ sp<AMessage> msg = mCallback->dup();
+ msg->setInt32("callbackID", CB_REQUIRED_RESOURCES_CHANGED);
+ msg->post();
+ }
+}
+
void MediaCodec::postActivityNotificationIfPossible() {
if (mActivityNotify == NULL) {
return;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 7169b1e..df1ebd7 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -123,6 +123,18 @@
CB_RESOURCE_RECLAIMED = 5,
CB_CRYPTO_ERROR = 6,
CB_LARGE_FRAME_OUTPUT_AVAILABLE = 7,
+
+ /** Callback ID for when the metrics for this codec have been flushed
+ * due to the start of a new subsession. The associated AMessage will
+ * contain an sp<WrapperObject<std::unique_ptr<mediametrics::Item>>>
+ * Object at the "metrics" key.
+ */
+ CB_METRICS_FLUSHED = 8,
+
+ /** Callback ID to notify the change in resource requirement
+ * for the codec component.
+ */
+ CB_REQUIRED_RESOURCES_CHANGED = 9,
};
static const pid_t kNoPid = -1;
@@ -142,6 +154,73 @@
static sp<PersistentSurface> CreatePersistentInputSurface();
+ /**
+ * Abstraction for the Global Codec resources.
+ * This encapsulates all the available codec resources on the device.
+ */
+ struct GlobalResourceInfo {
+ /**
+ * Name of the Resource type.
+ */
+ std::string mName;
+ /**
+ * Total count/capacity of resources of this type.
+ */
+ int mCapacity;
+ /**
+ * Available count of this resource type.
+ */
+ int mAvailable;
+
+ GlobalResourceInfo(const std::string& name, int capacity, int available) :
+ mName(name),
+ mCapacity(capacity),
+ mAvailable(available) {}
+
+ GlobalResourceInfo(const GlobalResourceInfo& info) :
+ mName(info.mName),
+ mCapacity(info.mCapacity),
+ mAvailable(info.mAvailable) {}
+ };
+
+ /**
+ * Abstraction for the resources associated with a codec instance.
+ * This encapsulates the required codec resources for a configured codec instance.
+ */
+ struct InstanceResourceInfo {
+ /**
+ * Name of the Resource type.
+ */
+ std::string mName;
+ /**
+ * Required resource count of this type.
+ */
+ int mStaticCount;
+ /**
+ * Per frame resource requirement of this resource type.
+ */
+ int mPerFrameCount;
+
+ InstanceResourceInfo(const std::string& name, int staticCount, int perFrameCount) :
+ mName(name),
+ mStaticCount(staticCount),
+ mPerFrameCount(perFrameCount) {}
+
+ InstanceResourceInfo(const InstanceResourceInfo& info) :
+ mName(info.mName),
+ mStaticCount(info.mStaticCount),
+ mPerFrameCount(info.mPerFrameCount) {}
+ };
+
+ /**
+ * Get a list of Globally available device codec resources.
+ *
+ * It will return INVALID_OPERATION if:
+ * - HAL does not implement codec availability API
+ * - codec_availability feature flag isn't defined.
+ */
+ static status_t getGloballyAvailableResources(std::vector<GlobalResourceInfo>& resources);
+
status_t configure(
const sp<AMessage> &format,
const sp<Surface> &nativeWindow,
@@ -155,6 +234,19 @@
const sp<IDescrambler> &descrambler,
uint32_t flags);
+ /**
+ * Get a list of required codec resources.
+ *
+ * This may only be called after configuring the codec.
+ *
+ * Calling this while the codec wasn't configured, will result in
+ * returning INVALID_OPERATION error code.
+ * It will also return INVALID_OPERATION if:
+ * - HAL does not implement codec availability API
+ * - codec_availability feature flag isn't defined.
+ */
+ status_t getRequiredResources(std::vector<InstanceResourceInfo>& resources);
+
status_t releaseCrypto();
status_t setCallback(const sp<AMessage> &callback);
@@ -484,12 +576,21 @@
Mutex mMetricsLock;
mediametrics_handle_t mMetricsHandle = 0;
+ mediametrics_handle_t mLastMetricsHandle = 0; // only accessed from the looper or destructor
bool mMetricsToUpload = false;
nsecs_t mLifetimeStartNs = 0;
void initMediametrics();
void updateMediametrics();
void flushMediametrics();
void resetMetricsFields();
+
+ // Reset the metrics fields for a new subsession.
+ void resetSubsessionMetricsFields();
+
+ // Start a new subsession (for metrics). This includes flushing the current
+ // metrics, notifying the client and resetting the session fields.
+ void handleStartingANewSubsession();
+
void updateEphemeralMediametrics(mediametrics_handle_t item);
void updateLowLatency(const sp<AMessage> &msg);
void updateCodecImportance(const sp<AMessage>& msg);
@@ -551,6 +652,7 @@
int32_t setOutputSurfaceCount;
int32_t resolutionChangeCount;
} mReliabilityContextMetrics;
+ int32_t mSubsessionCount;
// initial create parameters
AString mInitName;
@@ -671,6 +773,7 @@
void onCryptoError(const sp<AMessage> &msg);
void onError(status_t err, int32_t actionCode, const char *detail = NULL);
void onOutputFormatChanged();
+ void onRequiredResourcesChanged(const std::vector<InstanceResourceInfo>& resourceInfo);
status_t onSetParameters(const sp<AMessage> ¶ms);
@@ -770,6 +873,8 @@
friend class MediaTestHelper;
CodecErrorLog mErrorLog;
+ // Required resource info for this codec.
+ std::vector<InstanceResourceInfo> mRequiredResourceInfo;
DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
};
diff --git a/media/module/extractors/mpeg2/Android.bp b/media/module/extractors/mpeg2/Android.bp
index aa59a0c..63dbcda 100644
--- a/media/module/extractors/mpeg2/Android.bp
+++ b/media/module/extractors/mpeg2/Android.bp
@@ -44,7 +44,6 @@
shared_libs: [
"libbase",
- "libcgrouprc#29",
],
header_libs: [
diff --git a/media/module/libapexcodecs/Android.bp b/media/module/libapexcodecs/Android.bp
new file mode 100644
index 0000000..790b749
--- /dev/null
+++ b/media/module/libapexcodecs/Android.bp
@@ -0,0 +1,71 @@
+//
+// Copyright (C) 2024 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.
+//
+
+package {
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_defaults {
+ name: "libapexcodecs-defaults",
+ header_libs: [
+ "libbase_headers",
+ ],
+
+ srcs: ["ApexCodecs.cpp"],
+
+ shared_libs: [
+ "libbase",
+ "libnativewindow",
+ ],
+
+ export_include_dirs: ["include"],
+
+ export_shared_lib_headers: [
+ "libbase",
+ "libnativewindow",
+ ],
+
+}
+
+cc_library {
+ name: "libapexcodecs-testing",
+ defaults: ["libapexcodecs-defaults"],
+
+ visibility: [
+ ":__subpackages__",
+ ],
+}
+
+cc_library {
+ name: "libapexcodecs",
+ defaults: ["libapexcodecs-defaults"],
+
+ visibility: [
+ "//frameworks/av/apex:__subpackages__",
+ "//frameworks/av/media/codec2/hal/client",
+ ],
+
+ min_sdk_version: "apex_inherit",
+ version_script: "libapexcodecs.map.txt",
+ stubs: {
+ symbol_file: "libapexcodecs.map.txt",
+ versions: ["36"],
+ },
+
+ apex_available: [
+ "com.android.media.swcodec",
+ ],
+}
diff --git a/media/module/libapexcodecs/ApexCodecs.cpp b/media/module/libapexcodecs/ApexCodecs.cpp
new file mode 100644
index 0000000..7101677
--- /dev/null
+++ b/media/module/libapexcodecs/ApexCodecs.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2024 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 <new>
+
+#include <android-base/no_destructor.h>
+#include <apex/ApexCodecs.h>
+
+// TODO: remove when we have real implementations
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
+struct ApexCodec_ComponentStore {
+ ApexCodec_ComponentStore() = default;
+};
+
+ApexCodec_ComponentStore *ApexCodec_GetComponentStore() {
+ ::android::base::NoDestructor<ApexCodec_ComponentStore> store;
+ return store.get();
+}
+
+ApexCodec_ComponentTraits *ApexCodec_Traits_get(
+ ApexCodec_ComponentStore *store, size_t index) {
+ return nullptr;
+}
+
+ApexCodec_Status ApexCodec_Component_create(
+ ApexCodec_ComponentStore *store, const char *name, ApexCodec_Component **comp) {
+ *comp = nullptr;
+ return APEXCODEC_STATUS_NOT_FOUND;
+}
+
+void ApexCodec_Component_destroy(ApexCodec_Component *comp) {}
+
+ApexCodec_Status ApexCodec_Component_start(ApexCodec_Component *comp) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_Component_flush(ApexCodec_Component *comp) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_Component_reset(ApexCodec_Component *comp) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Configurable *ApexCodec_Component_getConfigurable(
+ ApexCodec_Component *comp) {
+ return nullptr;
+}
+
+ApexCodec_Status ApexCodec_SupportedValues_getTypeAndValues(
+ ApexCodec_SupportedValues *supportedValues,
+ ApexCodec_SupportedValuesType *type,
+ ApexCodec_SupportedValuesNumberType *numberType,
+ ApexCodec_Value **values,
+ uint32_t *numValues) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+void ApexCodec_SupportedValues_release(ApexCodec_SupportedValues *values) {}
+
+ApexCodec_Status ApexCodec_SettingResults_getResultAtIndex(
+ ApexCodec_SettingResults *results,
+ size_t index,
+ ApexCodec_SettingResultFailure *failure,
+ ApexCodec_ParamFieldValues *field,
+ ApexCodec_ParamFieldValues **conflicts,
+ size_t *numConflicts) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+void ApexCodec_SettingResults_release(ApexCodec_SettingResults *results) {}
+
+ApexCodec_Status ApexCodec_Component_process(
+ ApexCodec_Component *comp,
+ const ApexCodec_Buffer *input,
+ ApexCodec_Buffer *output,
+ size_t *consumed,
+ size_t *produced) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_Configurable_config(
+ ApexCodec_Configurable *comp,
+ ApexCodec_LinearBuffer *config,
+ ApexCodec_SettingResults **results) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_Configurable_query(
+ ApexCodec_Configurable *comp,
+ uint32_t indices[],
+ size_t numIndices,
+ ApexCodec_LinearBuffer *config,
+ size_t *written) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_ParamDescriptors_getIndices(
+ ApexCodec_ParamDescriptors *descriptors,
+ uint32_t **indices,
+ size_t *numIndices) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_ParamDescriptors_getDescriptor(
+ ApexCodec_ParamDescriptors *descriptors,
+ uint32_t index,
+ ApexCodec_ParamAttribute *attr,
+ const char **name,
+ uint32_t **dependencies,
+ size_t *numDependencies) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_ParamDescriptors_release(
+ ApexCodec_ParamDescriptors *descriptors) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_Configurable_querySupportedParams(
+ ApexCodec_Configurable *comp,
+ ApexCodec_ParamDescriptors **descriptors) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+ApexCodec_Status ApexCodec_Configurable_querySupportedValues(
+ ApexCodec_Configurable *comp,
+ ApexCodec_SupportedValuesQuery *queries,
+ size_t numQueries) {
+ return APEXCODEC_STATUS_OMITTED;
+}
+
+#pragma clang diagnostic pop
\ No newline at end of file
diff --git a/media/module/libapexcodecs/include/apex/ApexCodecs.h b/media/module/libapexcodecs/include/apex/ApexCodecs.h
new file mode 100644
index 0000000..b9f2e83
--- /dev/null
+++ b/media/module/libapexcodecs/include/apex/ApexCodecs.h
@@ -0,0 +1,768 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <android/api-level.h>
+#include <android/hardware_buffer.h>
+#include <android/versioning.h>
+
+__BEGIN_DECLS
+
+/**
+ * An API to access and operate codecs implemented within an APEX module,
+ * used only by the OS when using the codecs within a client process
+ * (instead of via a HAL).
+ *
+ * NOTE: Many of the constants and types mirror the ones in the Codec 2.0 API.
+ */
+
+/**
+ * Error code for ApexCodec APIs.
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_Status : int32_t {
+ APEXCODEC_STATUS_OK = 0,
+
+ /* bad input */
+ APEXCODEC_STATUS_BAD_VALUE = EINVAL,
+ APEXCODEC_STATUS_BAD_INDEX = ENXIO,
+ APEXCODEC_STATUS_CANNOT_DO = ENOTSUP,
+
+ /* bad sequencing of events */
+ APEXCODEC_STATUS_DUPLICATE = EEXIST,
+ APEXCODEC_STATUS_NOT_FOUND = ENOENT,
+ APEXCODEC_STATUS_BAD_STATE = EPERM,
+ APEXCODEC_STATUS_BLOCKING = EWOULDBLOCK,
+ APEXCODEC_STATUS_CANCELED = EINTR,
+
+ /* bad environment */
+ APEXCODEC_STATUS_NO_MEMORY = ENOMEM,
+ APEXCODEC_STATUS_REFUSED = EACCES,
+
+ APEXCODEC_STATUS_TIMED_OUT = ETIMEDOUT,
+
+ /* bad versioning */
+ APEXCODEC_STATUS_OMITTED = ENOSYS,
+
+ /* unknown fatal */
+ APEXCODEC_STATUS_CORRUPTED = EFAULT,
+ APEXCODEC_STATUS_NO_INIT = ENODEV,
+} ApexCodec_Status;
+
+/**
+ * Enum that represents the kind of component
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_Kind : uint32_t {
+ /**
+ * The component is of a kind that is not listed below.
+ */
+ APEXCODEC_KIND_OTHER = 0x0,
+ /**
+ * The component is a decoder, which decodes coded bitstream
+ * into raw buffers.
+ *
+ * Introduced in API 36.
+ */
+ APEXCODEC_KIND_DECODER = 0x1,
+ /**
+ * The component is an encoder, which encodes raw buffers
+ * into coded bitstream.
+ *
+ * Introduced in API 36.
+ */
+ APEXCODEC_KIND_ENCODER = 0x2,
+} ApexCodec_Kind;
+
+typedef enum ApexCodec_Domain : uint32_t {
+ /**
+ * A component domain that is not listed below.
+ *
+ * Introduced in API 36.
+ */
+ APEXCODEC_DOMAIN_OTHER = 0x0,
+ /**
+ * A component domain that operates on video.
+ *
+ * Introduced in API 36.
+ */
+ APEXCODEC_DOMAIN_VIDEO = 0x1,
+ /**
+ * A component domain that operates on audio.
+ *
+ * Introduced in API 36.
+ */
+ APEXCODEC_DOMAIN_AUDIO = 0x2,
+ /**
+ * A component domain that operates on image.
+ *
+ * Introduced in API 36.
+ */
+ APEXCODEC_DOMAIN_IMAGE = 0x3,
+} ApexCodec_Domain;
+
+/**
+ * Handle for component traits such as name, media type, kind (decoder/encoder),
+ * domain (audio/video/image), etc.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_ComponentTraits {
+ /**
+ * The name of the component.
+ */
+ const char *name;
+ /**
+ * The supported media type of the component.
+ */
+ const char *mediaType;
+ /**
+ * The kind of the component.
+ */
+ ApexCodec_Kind kind;
+ /**
+ * The domain on which the component operates.
+ */
+ ApexCodec_Domain domain;
+} ApexCodec_ComponentTraits;
+
+/**
+ * An opaque struct that represents a component store.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_ComponentStore ApexCodec_ComponentStore;
+
+/**
+ * Get the component store object. This function never fails.
+ *
+ * \return component store object.
+ */
+ApexCodec_ComponentStore *ApexCodec_GetComponentStore()
+ __INTRODUCED_IN(36);
+
+/**
+ * Get the traits object of a component at given index. ApexCodecs_Traits_*
+ * functions are used to extract information from the traits object.
+ *
+ * Returns nullptr if index is out of bounds. The returned object is owned by
+ * ApexCodec_ComponentStore object and the client should not delete it.
+ *
+ * The client can iterate through the traits objects by calling this function
+ * with an index incrementing from 0 until it gets a nullptr.
+ *
+ * \param index index of the traits object to query
+ * \return traits object at the index, or nullptr if the index is out of bounds.
+ */
+ApexCodec_ComponentTraits *ApexCodec_Traits_get(
+ ApexCodec_ComponentStore *store, size_t index) __INTRODUCED_IN(36);
+
+/**
+ * An opaque struct that represents a codec.
+ */
+typedef struct ApexCodec_Component ApexCodec_Component;
+
+/**
+ * Create a component by the name.
+ *
+ * \param store the component store
+ * \param name the name of the component
+ * \param component out-param to be filled with the component; must not be null
+ * \return APEXCODEC_STATUS_OK if successful
+ * APEXCODEC_STATUS_NOT_FOUND if the name is not found
+ */
+ApexCodec_Status ApexCodec_Component_create(
+ ApexCodec_ComponentStore *store, const char *name, ApexCodec_Component **comp)
+ __INTRODUCED_IN(36);
+
+/**
+ * Destroy the component by the handle. It is invalid to call component methods on the handle
+ * after calling this method. It is no-op to call this method with |comp| == nullptr.
+ *
+ * \param comp the handle for the component
+ */
+void ApexCodec_Component_destroy(ApexCodec_Component *comp) __INTRODUCED_IN(36);
+
+/**
+ * Start the component. The component is ready to process buffers after this call.
+ *
+ * \param comp the handle for the component
+ */
+ApexCodec_Status ApexCodec_Component_start(
+ ApexCodec_Component *comp) __INTRODUCED_IN(36);
+
+/**
+ * Flush the component's internal states. This operation preserves the existing configurations.
+ *
+ * \param comp the handle for the component
+ */
+ApexCodec_Status ApexCodec_Component_flush(
+ ApexCodec_Component *comp) __INTRODUCED_IN(36);
+
+/**
+ * Resets the component to the initial state, right after creation. Note that the configuration
+ * will also revert to the initial state, so if there are configurations required those should be
+ * set again to use the component.
+ *
+ * \param comp the handle for the component
+ */
+ApexCodec_Status ApexCodec_Component_reset(
+ ApexCodec_Component *comp) __INTRODUCED_IN(36);
+
+/**
+ * An opaque struct that represents a configurable part of the component.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_Configurable ApexCodec_Configurable;
+
+/**
+ * Return the configurable object for the given ApexCodec_Component.
+ * The returned object has the same lifecycle as |comp|.
+ *
+ * \param comp the handle for the component
+ * \return the configurable object handle
+ */
+ApexCodec_Configurable *ApexCodec_Component_getConfigurable(
+ ApexCodec_Component *comp) __INTRODUCED_IN(36);
+
+/**
+ * Enum that represents the flags for ApexCodec_Buffer.
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_BufferFlags : uint32_t {
+ APEXCODEC_FLAG_DROP_FRAME = (1 << 0),
+ APEXCODEC_FLAG_END_OF_STREAM = (1 << 1),
+ APEXCODEC_FLAG_DISCARD_FRAME = (1 << 2),
+ APEXCODEC_FLAG_INCOMPLETE = (1 << 3),
+ APEXCODEC_FLAG_CORRECTED = (1 << 4),
+ APEXCODEC_FLAG_CORRUPT = (1 << 5),
+ APEXCODEC_FLAG_CODEC_CONFIG = (1u << 31),
+} ApexCodec_BufferFlags;
+
+/**
+ * Enum that represents the type of buffer.
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_BufferType : uint32_t {
+ APEXCODEC_BUFFER_TYPE_INVALID,
+ APEXCODEC_BUFFER_TYPE_LINEAR,
+ APEXCODEC_BUFFER_TYPE_LINEAR_CHUNKS,
+ APEXCODEC_BUFFER_TYPE_GRAPHIC,
+ APEXCODEC_BUFFER_TYPE_GRAPHIC_CHUNKS,
+} ApexCodec_BufferType;
+
+/**
+ * Struct that represents the memory for ApexCodec_Buffer.
+ *
+ * All memory regions have the simple 1D representation.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_LinearBuffer {
+ /**
+ * A pointer to the start of the buffer. This is not aligned.
+ */
+ uint8_t *data;
+ /**
+ * Size of the buffer. The memory region between |data| (inclusive) and
+ * |data + size| (exclusive) is assumed to be valid for read/write.
+ */
+ size_t size;
+} ApexCodec_LinearBuffer;
+
+/**
+ * Struct that represents a buffer for ApexCodec_Component.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_Buffer {
+ /**
+ * Flags associated with the buffer.
+ */
+ ApexCodec_BufferFlags flags;
+ /**
+ * For input buffers client assign a unique sequential index for each buffer. For output buffers
+ * it is the same as the associated input buffer's frame index.
+ */
+ uint64_t frameIndex;
+ /**
+ * A timestamp associated with the buffer in microseconds.
+ */
+ uint64_t timestampUs;
+ /**
+ * The type of the buffer. The component may reject request to process a buffer with the wrong
+ * type. For example, a video decoder will reject an input buffer with type BUFFER_TYPE_GRAPHIC,
+ * or an output buffer with type BUFFER_TYPE_LINEAR.
+ */
+ ApexCodec_BufferType type;
+ /**
+ * The actual memory for the buffer.
+ */
+ union {
+ ApexCodec_LinearBuffer linear;
+ AHardwareBuffer *graphic;
+ } memory;
+ /**
+ * Config updates associated with the buffer. For input buffers these are sent to the component
+ * at the specific input frame. For output buffers these are config updates as a result of
+ * processing the buffer.
+ */
+ ApexCodec_LinearBuffer configUpdates;
+} ApexCodec_Buffer;
+
+/**
+ * Enum that represents the query type for the supported values.
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_SupportedValuesQueryType : uint32_t {
+ /** Query all possible supported values regardless of current configuration */
+ APEXCODEC_SUPPORTED_VALUES_QUERY_POSSIBLE,
+ /** Query supported values at current configuration */
+ APEXCODEC_SUPPORTED_VALUES_QUERY_CURRENT,
+} ApexCodec_SupportedValuesQueryType;
+
+/**
+ * Enum that represents the type of the supported values.
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_SupportedValuesType : uint32_t {
+ /** The supported values are empty. */
+ APEXCODEC_SUPPORTED_VALUES_EMPTY,
+ /**
+ * The supported values are represented by a range defined with {min, max, step, num, den}.
+ *
+ * If step is 0 and num and denom are both 1, the supported values are any value, for which
+ * min <= value <= max.
+ *
+ * Otherwise, the range represents a geometric/arithmetic/multiply-accumulate series, where
+ * successive supported values can be derived from previous values (starting at min), using the
+ * following formula:
+ * v[0] = min
+ * v[i] = v[i-1] * num / denom + step for i >= 1, while min < v[i] <= max.
+ */
+ APEXCODEC_SUPPORTED_VALUES_RANGE,
+ /** The supported values are represented by a list of values. */
+ APEXCODEC_SUPPORTED_VALUES_VALUES,
+ /** The supported values are represented by a list of flags. */
+ APEXCODEC_SUPPORTED_VALUES_FLAGS,
+} ApexCodec_SupportedValuesType;
+
+/**
+ * Enum that represents numeric types of the supported values.
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_SupportedValuesNumberType : uint32_t {
+ APEXCODEC_SUPPORTED_VALUES_TYPE_NONE = 0,
+ APEXCODEC_SUPPORTED_VALUES_TYPE_INT32 = 1,
+ APEXCODEC_SUPPORTED_VALUES_TYPE_UINT32 = 2,
+ // RESERVED = 3,
+ APEXCODEC_SUPPORTED_VALUES_TYPE_INT64 = 4,
+ APEXCODEC_SUPPORTED_VALUES_TYPE_UINT64 = 5,
+ // RESERVED = 6,
+ APEXCODEC_SUPPORTED_VALUES_TYPE_FLOAT = 7,
+} ApexCodec_SupportedValuesNumberType;
+
+/**
+ * Union of primitive types.
+ *
+ * Introduced in API 36.
+ */
+typedef union {
+ int32_t i32;
+ uint32_t u32;
+ int64_t i64;
+ uint64_t u64;
+ float f;
+} ApexCodec_Value;
+
+/**
+ * An opaque struct that represents the supported values of a parameter.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_SupportedValues ApexCodec_SupportedValues;
+
+/**
+ * Extract information from ApexCodec_SupportedValues object.
+ *
+ * \param [in] supportedValues the supported values object
+ * \param [out] type pointer to be filled with the type of the supported values
+ * \param [out] numberType pointer to be filled with the numeric type of the supported values
+ * \param [out] values pointer to be filled with the array of the actual supported values.
+ * if type == APEXCODEC_SUPPORTED_VALUES_EMPTY: nullptr
+ * if type == APEXCODEC_SUPPORTED_VALUES_RANGE: {min, max, step, num, den}
+ * if type == APEXCODEC_SUPPORTED_VALUES_VALUES/_FLAGS:
+ * the array of supported values/flags
+ * the array is owned by the |supportedValues| object and the client
+ * should not free it.
+ * \param [out] numValues pointer to be filled with the number of values.
+ * if type == APEXCODEC_SUPPORTED_VALUES_EMPTY: 0
+ * if type == APEXCODEC_SUPPORTED_VALUES_RANGE: 5
+ * if type == APEXCODEC_SUPPORTED_VALUES_VALUES/_FLAGS: varies
+ */
+ApexCodec_Status ApexCodec_SupportedValues_getTypeAndValues(
+ ApexCodec_SupportedValues *supportedValues,
+ ApexCodec_SupportedValuesType *type,
+ ApexCodec_SupportedValuesNumberType *numberType,
+ ApexCodec_Value **values,
+ uint32_t *numValues) __INTRODUCED_IN(36);
+
+/**
+ * Release the supported values object.
+ *
+ * \param values the supported values object
+ */
+void ApexCodec_SupportedValues_release(
+ ApexCodec_SupportedValues *values) __INTRODUCED_IN(36);
+
+/**
+ * Struct that represents the result of ApexCodec_Configurable_config.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_SettingResults ApexCodec_SettingResults;
+
+/**
+ * Enum that represents the failure code of ApexCodec_SettingResults.
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_SettingResultFailure : uint32_t {
+ /** parameter type is not supported */
+ APEXCODEC_SETTING_RESULT_BAD_TYPE,
+ /** parameter is not supported on the specific port */
+ APEXCODEC_SETTING_RESULT_BAD_PORT,
+ /** parameter is not supported on the specific stream */
+ APEXCODEC_SETTING_RESULT_BAD_INDEX,
+ /** parameter is read-only */
+ APEXCODEC_SETTING_RESULT_READ_ONLY,
+ /** parameter mismatches input data */
+ APEXCODEC_SETTING_RESULT_MISMATCH,
+ /** strict parameter does not accept value for the field at all */
+ APEXCODEC_SETTING_RESULT_BAD_VALUE,
+ /** strict parameter field value conflicts with another settings */
+ APEXCODEC_SETTING_RESULT_CONFLICT,
+ /** strict parameter field is out of range due to other settings */
+ APEXCODEC_SETTING_RESULT_UNSUPPORTED,
+ /**
+ * field does not accept the requested parameter value at all. It has been corrected to
+ * the closest supported value. This failure mode is provided to give guidance as to what
+ * are the currently supported values for this field (which may be a subset of the at-all-
+ * potential values)
+ */
+ APEXCODEC_SETTING_RESULT_INFO_BAD_VALUE,
+ /**
+ * requested parameter value is in conflict with an/other setting(s)
+ * and has been corrected to the closest supported value. This failure
+ * mode is given to provide guidance as to what are the currently supported values as well
+ * as to optionally provide suggestion to the client as to how to enable the requested
+ * parameter value.
+ */
+ APEXCODEC_SETTING_RESULT_INFO_CONFLICT,
+} ApexCodec_SettingResultFailure;
+
+/**
+ * Struct that represents a field and its supported values of a parameter.
+ *
+ * The offset and size of the field are where the field is located in the blob representation of
+ * the parameter, as used in the ApexCodec_Configurable_query() and ApexCodec_Configurable_config(),
+ * for example.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_ParamFieldValues {
+ /** index of the param */
+ uint32_t index;
+ /** offset of the param field */
+ uint32_t offset;
+ /** size of the param field */
+ uint32_t size;
+ /** currently supported values of the param field */
+ ApexCodec_SupportedValues *values;
+} ApexCodec_ParamFieldValues;
+
+/**
+ * Extract the result of ApexCodec_Configurable_config.
+ * The client can iterate through the results with index starting from 0 until this function returns
+ * APEXCODEC_STATUS_NOT_FOUND.
+ *
+ * \param [in] result the result object
+ * \param [in] index the index of the result to extract, starts from 0.
+ * \param [out] failure pointer to be filled with the failure code
+ * \param [out] field pointer to be filled with the field that failed.
+ * |field->value| is owned by the |result| object and the client should not
+ * free it.
+ * \param [out] conflicts pointer to be filled with the array of conflicts.
+ * nullptr if |numConflicts| is 0.
+ * the array and its content is owned by the |result| object and the client
+ * should not free it.
+ * \param [out] numConflicts pointer to be filled with the number of conflicts
+ * may be 0 if there are no conflicts
+ * \return APEXCODEC_STATUS_OK if successful
+ * \return APEXCODEC_STATUS_NOT_FOUND if index is out of range
+ */
+ApexCodec_Status ApexCodec_SettingResults_getResultAtIndex(
+ ApexCodec_SettingResults *results,
+ size_t index,
+ ApexCodec_SettingResultFailure *failure,
+ ApexCodec_ParamFieldValues *field,
+ ApexCodec_ParamFieldValues **conflicts,
+ size_t *numConflicts) __INTRODUCED_IN(36);
+
+/**
+ * Release the setting result object.
+ *
+ * \param result the setting result object
+ */
+void ApexCodec_SettingResults_release(
+ ApexCodec_SettingResults *results) __INTRODUCED_IN(36);
+
+/**
+ * Process one frame from |input|, and produce one frame to |output| if possible.
+ * When successfully filled, |output->memory.linear| has the size adjusted to the produced
+ * output size, in case of linear buffers. |input->configUpdates| is applied with the input
+ * buffer; |output->configUpdates| contains config updates as a result of processing the frame.
+ *
+ * \param comp the component to process the buffers
+ * \param input the input buffer; when nullptr, the component should fill |output| if there are
+ * any pending output buffers.
+ * \param output the output buffer, should not be nullptr.
+ * \param consumed the number of consumed bytes from the input buffer
+ * set to 0 if no input buffer has been consumed, including |input| is nullptr.
+ * for graphic buffers, any non-zero value means that the input buffer is consumed.
+ * \param produced the number of bytes produced on the output buffer
+ * set to 0 if no output buffer has been produced.
+ * for graphic buffers, any non-zero value means that the output buffer is filled.
+ * \return APEXCODEC_STATUS_OK if successful
+ * \return APEXCODEC_STATUS_NO_MEMORY if the output buffer is not suitable to hold the output frame
+ * the client should retry with a new output buffer;
+ * configUpdates should have the information to update
+ * the buffer size.
+ * \return APEXCODEC_STATUS_BAD_VALUE if the parameters are bad
+ * \return APEXCODEC_STATUS_BAD_STATE if the component is not in the right state
+ * to process the frame
+ * \return APEXCODEC_STATUS_CORRUPTED if unexpected error has occurred
+ */
+ApexCodec_Status ApexCodec_Component_process(
+ ApexCodec_Component *comp,
+ const ApexCodec_Buffer *input,
+ ApexCodec_Buffer *output,
+ size_t *consumed,
+ size_t *produced) __INTRODUCED_IN(36);
+
+/**
+ * Configure the component with the given config.
+ *
+ * Configurations are Codec 2.0 configs in binary blobs,
+ * concatenated if there are multiple configs.
+ *
+ * frameworks/av/media/codec2/core/include/C2Param.h contains more details about the configuration
+ * blob layout.
+ *
+ * The component may correct the configured parameters to the closest supported values, and could
+ * fail in case there are no values that the component can auto-correct to. |result| contains the
+ * information about the failures. See ApexCodec_SettingResultFailure and ApexCodec_SettingResults
+ * for more details.
+ *
+ * \param [in] comp the handle for the component
+ * \param [inout] config the config blob; after the call, the config blob is updated to the actual
+ * config by the component.
+ * \param [out] result the result of the configuration.
+ * the client should call ApexCodec_SettingResult_getResultAtIndex()
+ * to extract the result. The result object is owned by the client and should
+ * be released with ApexCodec_SettingResult_release().
+ * |result| may be nullptr if empty.
+ * \return APEXCODEC_STATUS_OK if successful
+ * \return APEXCODEC_STATUS_BAD_VALUE if the config is invalid
+ * \return APEXCODEC_STATUS_BAD_STATE if the component is not in the right state to be configured
+ * \return APEXCODEC_STATUS_CORRUPTED if unexpected error has occurred
+ */
+ApexCodec_Status ApexCodec_Configurable_config(
+ ApexCodec_Configurable *comp,
+ ApexCodec_LinearBuffer *config,
+ ApexCodec_SettingResults **results) __INTRODUCED_IN(36);
+
+/**
+ * Query the component for the given indices.
+ *
+ * Parameter indices are defined in frameworks/av/media/codec2/core/include/C2Config.h.
+ *
+ * \param [in] comp the handle for the component
+ * \param [in] indices the array of indices to query
+ * \param [in] numIndices the size of the indices array
+ * \param [inout] config the output buffer for the config blob, allocated by the client.
+ * if the |config->size| was insufficient, it is set to the required size
+ * and |config->data| remains unchanged.
+ * \param [out] written the number of bytes written to |config|.
+ * \return APEXCODEC_STATUS_OK if successful
+ * \return APEXCODEC_STATUS_NO_MEMORY if |config.size| is too small; |config.size| is updated to the
+ * requested buffer size.
+ * \return APEXCODEC_STATUS_BAD_VALUE if the parameters are bad. e.g. |indices|, |config|,
+ * |config->data| or |written| is nullptr.
+ */
+ApexCodec_Status ApexCodec_Configurable_query(
+ ApexCodec_Configurable *comp,
+ uint32_t indices[],
+ size_t numIndices,
+ ApexCodec_LinearBuffer *config,
+ size_t *written) __INTRODUCED_IN(36);
+
+/**
+ * Struct that represents a parameter descriptor.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_ParamDescriptors ApexCodec_ParamDescriptors;
+
+/**
+ * Enum that represents the attributes of a parameter.
+ *
+ * Introduced in API 36.
+ */
+typedef enum ApexCodec_ParamAttribute : uint32_t {
+ /** parameter is required to be specified */
+ APEXCODEC_PARAM_IS_REQUIRED = 1u << 0,
+ /** parameter retains its value */
+ APEXCODEC_PARAM_IS_PERSISTENT = 1u << 1,
+ /** parameter is strict */
+ APEXCODEC_PARAM_IS_STRICT = 1u << 2,
+ /** parameter is read-only */
+ APEXCODEC_PARAM_IS_READ_ONLY = 1u << 3,
+ /** parameter shall not be visible to clients */
+ APEXCODEC_PARAM_IS_HIDDEN = 1u << 4,
+ /** parameter shall not be used by framework (other than testing) */
+ APEXCODEC_PARAM_IS_INTERNAL = 1u << 5,
+ /** parameter is publicly const (hence read-only) */
+ APEXCODEC_PARAM_IS_CONST = 1u << 6 | APEXCODEC_PARAM_IS_READ_ONLY,
+} ApexCodec_ParamAttribute;
+
+/**
+ * Get the parameter indices of the param descriptors.
+ *
+ * \param [in] descriptors the param descriptors object
+ * \param [out] indices the pointer to be filled with the array of the indices;
+ * the array is owned by |descriptors| and should not be freed by the client.
+ * \param [out] numIndices the size of the indices array
+ * \return APEXCODEC_STATUS_OK if successful
+ * \return APEXCODEC_STATUS_BAD_VALUE if parameters are bad. e.g. |descriptors|, |indices| or
+ * |numIndices| is nullptr.
+ */
+ApexCodec_Status ApexCodec_ParamDescriptors_getIndices(
+ ApexCodec_ParamDescriptors *descriptors,
+ uint32_t **indices,
+ size_t *numIndices) __INTRODUCED_IN(36);
+
+/**
+ * Get the descriptor of the param.
+ *
+ * \param [in] descriptors the param descriptors object
+ * \param [in] index the index of the param
+ * \param [out] attr the attribute of the param
+ * \param [out] name the pointer to be filled with the name of the param
+ * the string is owned by |descriptors| and should not be freed by the client.
+ * \param [out] dependencies the pointer to be filled with an array of the parameter indices
+ * that the parameter with |index| depends on.
+ * may be null if empty.
+ * the array is owned by |descriptors| and should not be freed by the client.
+ * \param [out] numDependencies the number of dependencies
+ * \return APEXCODEC_STATUS_OK if successful
+ * \return APEXCODEC_STATUS_BAD_VALUE if parameters are bad. e.g. |descriptors|, |attr|, |name|,
+ * |dependencies| or |numDependencies| is nullptr.
+ * \return APEXCODEC_STATUS_BAD_INDEX if the index is not included in the param descriptors.
+ */
+ApexCodec_Status ApexCodec_ParamDescriptors_getDescriptor(
+ ApexCodec_ParamDescriptors *descriptors,
+ uint32_t index,
+ ApexCodec_ParamAttribute *attr,
+ const char **name,
+ uint32_t **dependencies,
+ size_t *numDependencies) __INTRODUCED_IN(36);
+
+/**
+ * Release the param descriptors object.
+ *
+ * \param descriptors the param descriptors object
+ */
+ApexCodec_Status ApexCodec_ParamDescriptors_release(
+ ApexCodec_ParamDescriptors *descriptors) __INTRODUCED_IN(36);
+
+/**
+ * Query the component for the supported parameters.
+ *
+ * \param comp the handle for the component
+ * \param descriptors the pointer to be filled with the param descriptors object
+ * the object should be released with ApexCodec_ParamDescriptors_release().
+ * \return APEXCODEC_STATUS_OK if successful
+ * \return APEXCODEC_STATUS_BAD_VALUE if parameters are bad. e.g. |descriptors| is nullptr.
+ */
+ApexCodec_Status ApexCodec_Configurable_querySupportedParams(
+ ApexCodec_Configurable *comp,
+ ApexCodec_ParamDescriptors **descriptors) __INTRODUCED_IN(36);
+
+/**
+ * Struct that represents the query for the supported values of a parameter.
+ *
+ * The offset of the field can be found in the layout of the parameter blob.
+ *
+ * Introduced in API 36.
+ */
+typedef struct ApexCodec_SupportedValuesQuery {
+ /* in-params */
+
+ /** index of the param */
+ uint32_t index;
+ /** offset to the param field */
+ size_t offset;
+ /** query type */
+ ApexCodec_SupportedValuesQueryType type;
+
+ /* out-params */
+
+ /** status of the query */
+ ApexCodec_Status status;
+
+ /** supported values. must be released with ApexCodec_SupportedValues_release(). */
+ ApexCodec_SupportedValues *values;
+} ApexCodec_SupportedValuesQuery;
+
+/**
+ * Query the component for the supported values of the given indices.
+ *
+ * \param comp the handle for the component
+ * \param queries the array of queries
+ * \param numQueries the size of the queries array
+ * \return APEXCODEC_STATUS_OK if successful
+ * APEXCODEC_STATUS_CORRUPTED if unexpected error has occurred
+ */
+ApexCodec_Status ApexCodec_Configurable_querySupportedValues(
+ ApexCodec_Configurable *comp,
+ ApexCodec_SupportedValuesQuery *queries,
+ size_t numQueries) __INTRODUCED_IN(36);
+
+__END_DECLS
\ No newline at end of file
diff --git a/media/module/libapexcodecs/libapexcodecs.map.txt b/media/module/libapexcodecs/libapexcodecs.map.txt
new file mode 100644
index 0000000..672cf89
--- /dev/null
+++ b/media/module/libapexcodecs/libapexcodecs.map.txt
@@ -0,0 +1,26 @@
+LIBAPEXCODECS_36 { # introduced=36
+ global:
+ ApexCodec_Component_create; # apex
+ ApexCodec_Component_destroy; # apex
+ ApexCodec_Component_flush; # apex
+ ApexCodec_Component_getConfigurable; # apex
+ ApexCodec_Component_process; # apex
+ ApexCodec_Component_start; # apex
+ ApexCodec_Component_reset; # apex
+ ApexCodec_Configurable_config; # apex
+ ApexCodec_Configurable_query; # apex
+ ApexCodec_Configurable_querySupportedParams; # apex
+ ApexCodec_Configurable_querySupportedValues; # apex
+ ApexCodec_GetComponentStore; # apex
+ ApexCodec_ParamDescriptors_getDescriptor; # apex
+ ApexCodec_ParamDescriptors_getIndices; # apex
+ ApexCodec_ParamDescriptors_release; # apex
+ ApexCodec_SettingResults_getResultAtIndex; # apex
+ ApexCodec_SettingResults_release; # apex
+ ApexCodec_SupportedValues_getTypeAndValues; # apex
+ ApexCodec_SupportedValues_release; # apex
+ ApexCodec_Traits_get; # apex
+
+ local:
+ *;
+};
\ No newline at end of file
diff --git a/media/module/libapexcodecs/tests/Android.bp b/media/module/libapexcodecs/tests/Android.bp
new file mode 100644
index 0000000..162d12c
--- /dev/null
+++ b/media/module/libapexcodecs/tests/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2024 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.
+//
+
+package {
+ default_team: "trendy_team_android_media_codec_framework",
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_test {
+ name: "libapexcodecs_tests",
+ shared_libs: [
+ "libapexcodecs-testing",
+ "libcodec2",
+ ],
+
+ srcs: ["ApexCodecsTest.cpp"],
+}
diff --git a/media/module/libapexcodecs/tests/ApexCodecsTest.cpp b/media/module/libapexcodecs/tests/ApexCodecsTest.cpp
new file mode 100644
index 0000000..cd5ebba
--- /dev/null
+++ b/media/module/libapexcodecs/tests/ApexCodecsTest.cpp
@@ -0,0 +1,100 @@
+#include <C2.h>
+#include <C2Component.h>
+
+#include <apex/ApexCodecs.h>
+
+// static_asserts for enum values match
+static_assert((uint32_t)APEXCODEC_STATUS_OK == (uint32_t)C2_OK);
+static_assert((uint32_t)APEXCODEC_STATUS_BAD_VALUE == (uint32_t)C2_BAD_VALUE);
+static_assert((uint32_t)APEXCODEC_STATUS_BAD_INDEX == (uint32_t)C2_BAD_INDEX);
+static_assert((uint32_t)APEXCODEC_STATUS_CANNOT_DO == (uint32_t)C2_CANNOT_DO);
+static_assert((uint32_t)APEXCODEC_STATUS_DUPLICATE == (uint32_t)C2_DUPLICATE);
+static_assert((uint32_t)APEXCODEC_STATUS_NOT_FOUND == (uint32_t)C2_NOT_FOUND);
+static_assert((uint32_t)APEXCODEC_STATUS_BAD_STATE == (uint32_t)C2_BAD_STATE);
+static_assert((uint32_t)APEXCODEC_STATUS_BLOCKING == (uint32_t)C2_BLOCKING);
+static_assert((uint32_t)APEXCODEC_STATUS_CANCELED == (uint32_t)C2_CANCELED);
+static_assert((uint32_t)APEXCODEC_STATUS_NO_MEMORY == (uint32_t)C2_NO_MEMORY);
+static_assert((uint32_t)APEXCODEC_STATUS_REFUSED == (uint32_t)C2_REFUSED);
+static_assert((uint32_t)APEXCODEC_STATUS_TIMED_OUT == (uint32_t)C2_TIMED_OUT);
+static_assert((uint32_t)APEXCODEC_STATUS_OMITTED == (uint32_t)C2_OMITTED);
+static_assert((uint32_t)APEXCODEC_STATUS_CORRUPTED == (uint32_t)C2_CORRUPTED);
+static_assert((uint32_t)APEXCODEC_STATUS_NO_INIT == (uint32_t)C2_NO_INIT);
+
+static_assert((uint32_t)APEXCODEC_KIND_OTHER == (uint32_t)C2Component::KIND_OTHER);
+static_assert((uint32_t)APEXCODEC_KIND_DECODER == (uint32_t)C2Component::KIND_DECODER);
+static_assert((uint32_t)APEXCODEC_KIND_ENCODER == (uint32_t)C2Component::KIND_ENCODER);
+
+static_assert((uint32_t)APEXCODEC_DOMAIN_OTHER == (uint32_t)C2Component::DOMAIN_OTHER);
+static_assert((uint32_t)APEXCODEC_DOMAIN_VIDEO == (uint32_t)C2Component::DOMAIN_VIDEO);
+static_assert((uint32_t)APEXCODEC_DOMAIN_AUDIO == (uint32_t)C2Component::DOMAIN_AUDIO);
+static_assert((uint32_t)APEXCODEC_DOMAIN_IMAGE == (uint32_t)C2Component::DOMAIN_IMAGE);
+
+static_assert((uint32_t)APEXCODEC_FLAG_DROP_FRAME == (uint32_t)C2FrameData::FLAG_DROP_FRAME);
+static_assert((uint32_t)APEXCODEC_FLAG_END_OF_STREAM == (uint32_t)C2FrameData::FLAG_END_OF_STREAM);
+static_assert((uint32_t)APEXCODEC_FLAG_DISCARD_FRAME == (uint32_t)C2FrameData::FLAG_DISCARD_FRAME);
+static_assert((uint32_t)APEXCODEC_FLAG_INCOMPLETE == (uint32_t)C2FrameData::FLAG_INCOMPLETE);
+static_assert((uint32_t)APEXCODEC_FLAG_CORRECTED == (uint32_t)C2FrameData::FLAG_CORRECTED);
+static_assert((uint32_t)APEXCODEC_FLAG_CORRUPT == (uint32_t)C2FrameData::FLAG_CORRUPT);
+static_assert((uint32_t)APEXCODEC_FLAG_CODEC_CONFIG == (uint32_t)C2FrameData::FLAG_CODEC_CONFIG);
+
+static_assert((uint32_t)APEXCODEC_BUFFER_TYPE_INVALID ==
+ (uint32_t)C2BufferData::INVALID);
+static_assert((uint32_t)APEXCODEC_BUFFER_TYPE_LINEAR ==
+ (uint32_t)C2BufferData::LINEAR);
+static_assert((uint32_t)APEXCODEC_BUFFER_TYPE_LINEAR_CHUNKS ==
+ (uint32_t)C2BufferData::LINEAR_CHUNKS);
+static_assert((uint32_t)APEXCODEC_BUFFER_TYPE_GRAPHIC ==
+ (uint32_t)C2BufferData::GRAPHIC);
+static_assert((uint32_t)APEXCODEC_BUFFER_TYPE_GRAPHIC_CHUNKS ==
+ (uint32_t)C2BufferData::GRAPHIC_CHUNKS);
+
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_QUERY_CURRENT ==
+ (uint32_t)C2FieldSupportedValuesQuery::CURRENT);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_QUERY_POSSIBLE ==
+ (uint32_t)C2FieldSupportedValuesQuery::POSSIBLE);
+
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_EMPTY ==
+ (uint32_t)C2FieldSupportedValues::EMPTY);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_RANGE ==
+ (uint32_t)C2FieldSupportedValues::RANGE);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_VALUES ==
+ (uint32_t)C2FieldSupportedValues::VALUES);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_FLAGS ==
+ (uint32_t)C2FieldSupportedValues::FLAGS);
+
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_TYPE_NONE == (uint32_t)C2Value::NO_INIT);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_TYPE_INT32 == (uint32_t)C2Value::INT32);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_TYPE_UINT32 == (uint32_t)C2Value::UINT32);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_TYPE_INT64 == (uint32_t)C2Value::INT64);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_TYPE_UINT64 == (uint32_t)C2Value::UINT64);
+static_assert((uint32_t)APEXCODEC_SUPPORTED_VALUES_TYPE_FLOAT == (uint32_t)C2Value::FLOAT);
+
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_BAD_TYPE ==
+ (uint32_t)C2SettingResult::BAD_TYPE);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_BAD_PORT ==
+ (uint32_t)C2SettingResult::BAD_PORT);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_BAD_INDEX ==
+ (uint32_t)C2SettingResult::BAD_INDEX);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_READ_ONLY ==
+ (uint32_t)C2SettingResult::READ_ONLY);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_MISMATCH ==
+ (uint32_t)C2SettingResult::MISMATCH);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_BAD_VALUE ==
+ (uint32_t)C2SettingResult::BAD_VALUE);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_CONFLICT ==
+ (uint32_t)C2SettingResult::CONFLICT);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_UNSUPPORTED ==
+ (uint32_t)C2SettingResult::UNSUPPORTED);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_INFO_BAD_VALUE ==
+ (uint32_t)C2SettingResult::INFO_BAD_VALUE);
+static_assert((uint32_t)APEXCODEC_SETTING_RESULT_INFO_CONFLICT ==
+ (uint32_t)C2SettingResult::INFO_CONFLICT);
+
+static_assert((uint32_t)APEXCODEC_PARAM_IS_REQUIRED == (uint32_t)C2ParamDescriptor::IS_REQUIRED);
+static_assert((uint32_t)APEXCODEC_PARAM_IS_PERSISTENT ==
+ (uint32_t)C2ParamDescriptor::IS_PERSISTENT);
+static_assert((uint32_t)APEXCODEC_PARAM_IS_STRICT == (uint32_t)C2ParamDescriptor::IS_STRICT);
+static_assert((uint32_t)APEXCODEC_PARAM_IS_READ_ONLY == (uint32_t)C2ParamDescriptor::IS_READ_ONLY);
+static_assert((uint32_t)APEXCODEC_PARAM_IS_HIDDEN == (uint32_t)C2ParamDescriptor::IS_HIDDEN);
+static_assert((uint32_t)APEXCODEC_PARAM_IS_INTERNAL == (uint32_t)C2ParamDescriptor::IS_INTERNAL);
+static_assert((uint32_t)APEXCODEC_PARAM_IS_CONST == (uint32_t)C2ParamDescriptor::IS_CONST);
\ No newline at end of file