Loading apex/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,10 @@ apex_defaults { }, }, // JNI native_shared_libs: ["libmediaparser-jni"], native_shared_libs: [ "libmediaparser-jni", "libmediaformatshaper", ], compile_multilib: "both", prebuilts: [ "code_coverage.policy", Loading media/libmedia/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -432,5 +432,8 @@ cc_library_static { }, }, apex_available: ["com.android.media"], apex_available: [ "//apex_available:platform", "com.android.media" ], } media/libmediaformatshaper/Android.bp 0 → 100644 +91 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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. */ // these headers include the structure of needed function pointers cc_library_headers { name: "libmediaformatshaper_headers", export_include_dirs: ["include"], apex_available: [ "//apex_available:platform", "com.android.media", ], min_sdk_version: "29", host_supported: true, target: { darwin: { enabled: false, }, }, } cc_defaults { name: "libmediaformatshaper_defaults", srcs: [ "CodecProperties.cpp", "FormatShaper.cpp", "ManageShapingCodecs.cpp", "VideoShaper.cpp", "VQApply.cpp", ], local_include_dirs: [ "include", ], shared_libs: [ "liblog", "libutils", ], cflags: [ "-Werror", "-Wall", "-fvisibility=hidden", "-Wthread-safety", // enables GUARDED_BY() ], target: { android: { shared_libs: [ "libmediandk#29", ], }, }, sanitize: { cfi: true, misc_undefined: [ "unsigned-integer-overflow", "signed-integer-overflow", ], }, } cc_library { name: "libmediaformatshaper", defaults: ["libmediaformatshaper_defaults"], min_sdk_version: "29", apex_available: [ "//apex_available:platform", "com.android.media", ], version_script: "exports.lds", } media/libmediaformatshaper/CodecProperties.cpp 0 → 100644 +143 −0 Original line number Diff line number Diff line /* * Copyright 2021, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "CodecProperties" #include <utils/Log.h> #include <string> #include <media/formatshaper/CodecProperties.h> namespace android { namespace mediaformatshaper { CodecProperties::CodecProperties(std::string name, std::string mediaType) { mName = name; mMediaType = mediaType; } std::string CodecProperties::getName(){ return mName; } std::string CodecProperties::getMediaType(){ return mMediaType; } int CodecProperties::supportedMinimumQuality() { return mMinimumQuality; } void CodecProperties::setSupportedMinimumQuality(int vmaf) { mMinimumQuality = vmaf; } int CodecProperties::targetQpMax() { return mTargetQpMax; } void CodecProperties::setTargetQpMax(int qpMax) { mTargetQpMax = qpMax; } // what API is this codec set up for (e.g. API of the associated partition) // vendor-side (OEM) codecs may be older, due to 'vendor freeze' and treble int CodecProperties::supportedApi() { return mApi; } std::string CodecProperties::getMapping(std::string key, std::string kind) { ALOGV("getMapping(key %s, kind %s )", key.c_str(), kind.c_str()); //play with mMappings auto mapped = mMappings.find(kind + "-" + key); if (mapped != mMappings.end()) { std::string result = mapped->second; ALOGV("getMapping(%s, %s) -> %s", key.c_str(), kind.c_str(), result.c_str()); return result; } ALOGV("nope, return unchanged key"); return key; } // really a bit of debugging code here. void CodecProperties::showMappings() { ALOGD("Mappings:"); int count = 0; for (const auto& [key, value] : mMappings) { count++; ALOGD("'%s' -> '%s'", key.c_str(), value.c_str()); } ALOGD("total %d mappings", count); } void CodecProperties::setMapping(std::string kind, std::string key, std::string value) { ALOGV("setMapping(%s,%s,%s)", kind.c_str(), key.c_str(), value.c_str()); std::string metaKey = kind + "-" + key; mMappings.insert({metaKey, value}); } const char **CodecProperties::getMappings(std::string kind, bool reverse) { ALOGV("getMappings(kind %s, reverse %d", kind.c_str(), reverse); // how many do we need? int count = mMappings.size(); if (count == 0) { ALOGV("empty mappings"); return nullptr; } size_t size = sizeof(char *) * (2 * count + 2); const char **result = (const char **)malloc(size); if (result == nullptr) { ALOGW("no memory to return mappings"); return nullptr; } memset(result, '\0', size); const char **pp = result; for (const auto& [key, value] : mMappings) { // split out the kind/key size_t pos = key.find('-'); if (pos == std::string::npos) { ALOGD("ignoring malformed key: %s", key.c_str()); continue; } std::string actualKind = key.substr(0,pos); if (kind.length() != 0 && kind != actualKind) { ALOGD("kinds don't match: want '%s' got '%s'", kind.c_str(), actualKind.c_str()); continue; } if (reverse) { // codec specific -> std aka 'unmapping' pp[0] = strdup( value.c_str()); pp[1] = strdup( key.substr(pos+1).c_str()); } else { // std -> codec specific pp[0] = strdup( key.substr(pos+1).c_str()); pp[1] = strdup( value.c_str()); } ALOGV(" %s -> %s", pp[0], pp[1]); pp += 2; } pp[0] = nullptr; pp[1] = nullptr; return result; } } // namespace mediaformatshaper } // namespace android media/libmediaformatshaper/FormatShaper.cpp 0 → 100644 +184 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "FormatShaper" #include <utils/Log.h> #include <string> #include <inttypes.h> #include <media/NdkMediaFormat.h> #include <media/formatshaper/VQops.h> #include <media/formatshaper/CodecProperties.h> #include <media/formatshaper/FormatShaper.h> #include <media/formatshaper/VideoShaper.h> namespace android { namespace mediaformatshaper { // // Caller retains ownership of and responsibility for inFormat // // // the interface to the outside // int shapeFormat(shaperHandle_t shaper, AMediaFormat* inFormat, int flags) { CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) { return -1; } if (!codec->isRegistered()) { return -1; } // run through the list of possible transformations // std::string mediaType = codec->getMediaType(); if (strncmp(mediaType.c_str(), "video/", 6) == 0) { // video specific shaping (void) videoShaper(codec, inFormat, flags); } else if (strncmp(mediaType.c_str(), "audio/", 6) == 0) { // audio specific shaping } else { ALOGV("unknown mediatype '%s', left untouched", mediaType.c_str()); } return 0; } int setMap(shaperHandle_t shaper, const char *kind, const char *key, const char *value) { ALOGV("setMap: kind %s key %s -> value %s", kind, key, value); CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) { return -1; } // must not yet be registered if (codec->isRegistered()) { return -1; } codec->setMapping(kind, key, value); return 0; } int setFeature(shaperHandle_t shaper, const char *feature, int value) { ALOGV("set_feature: feature %s value %d", feature, value); CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) { return -1; } // must not yet be registered if (codec->isRegistered()) { return -1; } if (!strcmp(feature, "vq-minimum-quality")) { codec->setSupportedMinimumQuality(value); } else if (!strcmp(feature, "vq-supports-qp")) { codec->setSupportsQp(value != 0); } else if (!strcmp(feature, "vq-target-qpmax")) { codec->setTargetQpMax(value); } else if (!strcmp(feature, "vq-target-bppx100")) { double bpp = value / 100.0; codec->setBpp(bpp); } else { // changed nothing, don't mark as configured return 0; } return 0; } /* * The routines that manage finding, creating, and registering the shapers. */ shaperHandle_t findShaper(const char *codecName, const char *mediaType) { CodecProperties *codec = findCodec(codecName, mediaType); return (shaperHandle_t) codec; } shaperHandle_t createShaper(const char *codecName, const char *mediaType) { CodecProperties *codec = new CodecProperties(codecName, mediaType); return (shaperHandle_t) codec; } shaperHandle_t registerShaper(shaperHandle_t shaper, const char *codecName, const char *mediaType) { ALOGV("registerShaper(handle, codecName %s, mediaType %s", codecName, mediaType); CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) { return nullptr; } // must not yet be registered if (codec->isRegistered()) { return nullptr; } codec = registerCodec(codec, codecName, mediaType); return (shaperHandle_t) codec; } // mapping & unmapping // give me the mappings for 'kind'. // kind==null (or empty string), means *all* mappings const char **getMappings(shaperHandle_t shaper, const char *kind) { CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) return nullptr; if (kind == nullptr) kind = ""; return codec->getMappings(kind, /* reverse */ false); } const char **getReverseMappings(shaperHandle_t shaper, const char *kind) { CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) return nullptr; if (kind == nullptr) kind = ""; return codec->getMappings(kind, /* reverse */ true); } // the system grabs this structure __attribute__ ((visibility ("default"))) extern "C" FormatShaperOps_t shaper_ops = { .version = SHAPER_VERSION_V1, .findShaper = findShaper, .createShaper = createShaper, .setMap = setMap, .setFeature = setFeature, .registerShaper = registerShaper, .shapeFormat = shapeFormat, .getMappings = getMappings, .getReverseMappings = getReverseMappings, }; } // namespace mediaformatshaper } // namespace android Loading
apex/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,10 @@ apex_defaults { }, }, // JNI native_shared_libs: ["libmediaparser-jni"], native_shared_libs: [ "libmediaparser-jni", "libmediaformatshaper", ], compile_multilib: "both", prebuilts: [ "code_coverage.policy", Loading
media/libmedia/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -432,5 +432,8 @@ cc_library_static { }, }, apex_available: ["com.android.media"], apex_available: [ "//apex_available:platform", "com.android.media" ], }
media/libmediaformatshaper/Android.bp 0 → 100644 +91 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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. */ // these headers include the structure of needed function pointers cc_library_headers { name: "libmediaformatshaper_headers", export_include_dirs: ["include"], apex_available: [ "//apex_available:platform", "com.android.media", ], min_sdk_version: "29", host_supported: true, target: { darwin: { enabled: false, }, }, } cc_defaults { name: "libmediaformatshaper_defaults", srcs: [ "CodecProperties.cpp", "FormatShaper.cpp", "ManageShapingCodecs.cpp", "VideoShaper.cpp", "VQApply.cpp", ], local_include_dirs: [ "include", ], shared_libs: [ "liblog", "libutils", ], cflags: [ "-Werror", "-Wall", "-fvisibility=hidden", "-Wthread-safety", // enables GUARDED_BY() ], target: { android: { shared_libs: [ "libmediandk#29", ], }, }, sanitize: { cfi: true, misc_undefined: [ "unsigned-integer-overflow", "signed-integer-overflow", ], }, } cc_library { name: "libmediaformatshaper", defaults: ["libmediaformatshaper_defaults"], min_sdk_version: "29", apex_available: [ "//apex_available:platform", "com.android.media", ], version_script: "exports.lds", }
media/libmediaformatshaper/CodecProperties.cpp 0 → 100644 +143 −0 Original line number Diff line number Diff line /* * Copyright 2021, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "CodecProperties" #include <utils/Log.h> #include <string> #include <media/formatshaper/CodecProperties.h> namespace android { namespace mediaformatshaper { CodecProperties::CodecProperties(std::string name, std::string mediaType) { mName = name; mMediaType = mediaType; } std::string CodecProperties::getName(){ return mName; } std::string CodecProperties::getMediaType(){ return mMediaType; } int CodecProperties::supportedMinimumQuality() { return mMinimumQuality; } void CodecProperties::setSupportedMinimumQuality(int vmaf) { mMinimumQuality = vmaf; } int CodecProperties::targetQpMax() { return mTargetQpMax; } void CodecProperties::setTargetQpMax(int qpMax) { mTargetQpMax = qpMax; } // what API is this codec set up for (e.g. API of the associated partition) // vendor-side (OEM) codecs may be older, due to 'vendor freeze' and treble int CodecProperties::supportedApi() { return mApi; } std::string CodecProperties::getMapping(std::string key, std::string kind) { ALOGV("getMapping(key %s, kind %s )", key.c_str(), kind.c_str()); //play with mMappings auto mapped = mMappings.find(kind + "-" + key); if (mapped != mMappings.end()) { std::string result = mapped->second; ALOGV("getMapping(%s, %s) -> %s", key.c_str(), kind.c_str(), result.c_str()); return result; } ALOGV("nope, return unchanged key"); return key; } // really a bit of debugging code here. void CodecProperties::showMappings() { ALOGD("Mappings:"); int count = 0; for (const auto& [key, value] : mMappings) { count++; ALOGD("'%s' -> '%s'", key.c_str(), value.c_str()); } ALOGD("total %d mappings", count); } void CodecProperties::setMapping(std::string kind, std::string key, std::string value) { ALOGV("setMapping(%s,%s,%s)", kind.c_str(), key.c_str(), value.c_str()); std::string metaKey = kind + "-" + key; mMappings.insert({metaKey, value}); } const char **CodecProperties::getMappings(std::string kind, bool reverse) { ALOGV("getMappings(kind %s, reverse %d", kind.c_str(), reverse); // how many do we need? int count = mMappings.size(); if (count == 0) { ALOGV("empty mappings"); return nullptr; } size_t size = sizeof(char *) * (2 * count + 2); const char **result = (const char **)malloc(size); if (result == nullptr) { ALOGW("no memory to return mappings"); return nullptr; } memset(result, '\0', size); const char **pp = result; for (const auto& [key, value] : mMappings) { // split out the kind/key size_t pos = key.find('-'); if (pos == std::string::npos) { ALOGD("ignoring malformed key: %s", key.c_str()); continue; } std::string actualKind = key.substr(0,pos); if (kind.length() != 0 && kind != actualKind) { ALOGD("kinds don't match: want '%s' got '%s'", kind.c_str(), actualKind.c_str()); continue; } if (reverse) { // codec specific -> std aka 'unmapping' pp[0] = strdup( value.c_str()); pp[1] = strdup( key.substr(pos+1).c_str()); } else { // std -> codec specific pp[0] = strdup( key.substr(pos+1).c_str()); pp[1] = strdup( value.c_str()); } ALOGV(" %s -> %s", pp[0], pp[1]); pp += 2; } pp[0] = nullptr; pp[1] = nullptr; return result; } } // namespace mediaformatshaper } // namespace android
media/libmediaformatshaper/FormatShaper.cpp 0 → 100644 +184 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "FormatShaper" #include <utils/Log.h> #include <string> #include <inttypes.h> #include <media/NdkMediaFormat.h> #include <media/formatshaper/VQops.h> #include <media/formatshaper/CodecProperties.h> #include <media/formatshaper/FormatShaper.h> #include <media/formatshaper/VideoShaper.h> namespace android { namespace mediaformatshaper { // // Caller retains ownership of and responsibility for inFormat // // // the interface to the outside // int shapeFormat(shaperHandle_t shaper, AMediaFormat* inFormat, int flags) { CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) { return -1; } if (!codec->isRegistered()) { return -1; } // run through the list of possible transformations // std::string mediaType = codec->getMediaType(); if (strncmp(mediaType.c_str(), "video/", 6) == 0) { // video specific shaping (void) videoShaper(codec, inFormat, flags); } else if (strncmp(mediaType.c_str(), "audio/", 6) == 0) { // audio specific shaping } else { ALOGV("unknown mediatype '%s', left untouched", mediaType.c_str()); } return 0; } int setMap(shaperHandle_t shaper, const char *kind, const char *key, const char *value) { ALOGV("setMap: kind %s key %s -> value %s", kind, key, value); CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) { return -1; } // must not yet be registered if (codec->isRegistered()) { return -1; } codec->setMapping(kind, key, value); return 0; } int setFeature(shaperHandle_t shaper, const char *feature, int value) { ALOGV("set_feature: feature %s value %d", feature, value); CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) { return -1; } // must not yet be registered if (codec->isRegistered()) { return -1; } if (!strcmp(feature, "vq-minimum-quality")) { codec->setSupportedMinimumQuality(value); } else if (!strcmp(feature, "vq-supports-qp")) { codec->setSupportsQp(value != 0); } else if (!strcmp(feature, "vq-target-qpmax")) { codec->setTargetQpMax(value); } else if (!strcmp(feature, "vq-target-bppx100")) { double bpp = value / 100.0; codec->setBpp(bpp); } else { // changed nothing, don't mark as configured return 0; } return 0; } /* * The routines that manage finding, creating, and registering the shapers. */ shaperHandle_t findShaper(const char *codecName, const char *mediaType) { CodecProperties *codec = findCodec(codecName, mediaType); return (shaperHandle_t) codec; } shaperHandle_t createShaper(const char *codecName, const char *mediaType) { CodecProperties *codec = new CodecProperties(codecName, mediaType); return (shaperHandle_t) codec; } shaperHandle_t registerShaper(shaperHandle_t shaper, const char *codecName, const char *mediaType) { ALOGV("registerShaper(handle, codecName %s, mediaType %s", codecName, mediaType); CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) { return nullptr; } // must not yet be registered if (codec->isRegistered()) { return nullptr; } codec = registerCodec(codec, codecName, mediaType); return (shaperHandle_t) codec; } // mapping & unmapping // give me the mappings for 'kind'. // kind==null (or empty string), means *all* mappings const char **getMappings(shaperHandle_t shaper, const char *kind) { CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) return nullptr; if (kind == nullptr) kind = ""; return codec->getMappings(kind, /* reverse */ false); } const char **getReverseMappings(shaperHandle_t shaper, const char *kind) { CodecProperties *codec = (CodecProperties*) shaper; if (codec == nullptr) return nullptr; if (kind == nullptr) kind = ""; return codec->getMappings(kind, /* reverse */ true); } // the system grabs this structure __attribute__ ((visibility ("default"))) extern "C" FormatShaperOps_t shaper_ops = { .version = SHAPER_VERSION_V1, .findShaper = findShaper, .createShaper = createShaper, .setMap = setMap, .setFeature = setFeature, .registerShaper = registerShaper, .shapeFormat = shapeFormat, .getMappings = getMappings, .getReverseMappings = getReverseMappings, }; } // namespace mediaformatshaper } // namespace android