Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0da8875a authored by Ray Essick's avatar Ray Essick Committed by Android (Google) Code Review
Browse files

Merge "Initial libmediaformatshaper" into sc-dev

parents 3612da74 1831f7bd
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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",
+4 −1
Original line number Diff line number Diff line
@@ -432,5 +432,8 @@ cc_library_static {
        },
    },

    apex_available: ["com.android.media"],
    apex_available: [
        "//apex_available:platform",
        "com.android.media"
    ],
}
+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",

}
+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
+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