| /* |
| * 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 "CodecProperties.h" |
| #include "VideoShaper.h" |
| #include "VQops.h" |
| |
| #include <media/formatshaper/FormatShaper.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; |
| } |
| |
| // save a map of all features |
| codec->setFeatureValue(feature, value); |
| |
| return 0; |
| } |
| |
| int setTuning(shaperHandle_t shaper, const char *tuning, const char *value) { |
| ALOGV("setTuning: tuning %s value %s", tuning, value); |
| CodecProperties *codec = (CodecProperties*) shaper; |
| if (codec == nullptr) { |
| return -1; |
| } |
| // must not yet be registered |
| if (codec->isRegistered()) { |
| return -1; |
| } |
| |
| // save a map of all features |
| codec->setTuningValue(tuning, value); |
| |
| 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); |
| if (codec != nullptr) { |
| codec->Seed(); |
| } |
| 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; |
| } |
| |
| // any final cleanup for the parameters. This allows us to override |
| // bad parameters from a devices XML file. |
| codec->Finish(); |
| |
| // may return a different codec, if we lost a race. |
| // if so, registerCodec() reclaims the one we tried to register for us. |
| 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, |
| |
| .setTuning = setTuning, |
| }; |
| |
| } // namespace mediaformatshaper |
| } // namespace android |
| |