blob: ca4dc72a7ae551ada270b84e3e7035fab5a92d8b [file] [log] [blame]
/*
* 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