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

Commit f9672d70 authored by Songyue Han's avatar Songyue Han Committed by Automerger Merge Worker
Browse files

Merge "CodecCapabilities NDK: Introduce AMediaCodecStore and AMediaCodecInfo."...

Merge "CodecCapabilities NDK: Introduce AMediaCodecStore and AMediaCodecInfo." into main am: 9e0d0921 am: 15afaf7f

Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/3391053



Change-Id: I67204fc2412033e8f55d122d55df50a4db4e47f7
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 3a1a5382 15afaf7f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ cc_library_shared {
    srcs: [
        "NdkJavaVMHelper.cpp",
        "NdkMediaCodec.cpp",
        "NdkMediaCodecInfo.cpp",
        "NdkMediaCodecStore.cpp",
        "NdkMediaCrypto.cpp",
        "NdkMediaDataSource.cpp",
        "NdkMediaExtractor.cpp",
@@ -131,6 +133,8 @@ cc_library_shared {
        "libbase",
        "libdatasource",
        "libmedia",
        "libmedia_codeclist",
        "libmedia_codeclist_capabilities",
        "libmediadrm",
        "libmedia_omx",
        "libmedia_jni_utils",
+520 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "NdkMediaCodecInfo"

#include "NdkMediaCodecInfoPriv.h"

#include <media/NdkMediaFormatPriv.h>

using namespace android;

extern "C" {

// Utils

EXPORT
void AIntRange_delete(AIntRange *range) {
    free(range);
}

EXPORT
void ADoubleRange_delete(ADoubleRange *range) {
    free(range);
}

// AMediaCodecInfo

EXPORT
const char* AMediaCodecInfo_getCanonicalName(const AMediaCodecInfo *info) {
    if (info == nullptr || info->mInfo == nullptr) {
        return nullptr;
    }

    return info->mInfo->getCodecName();
}

EXPORT
bool AMediaCodecInfo_isEncoder(const AMediaCodecInfo *info) {
    return info->mInfo->isEncoder();
}

EXPORT
bool AMediaCodecInfo_isVendor(const AMediaCodecInfo *info) {
    int32_t attributes = info->mInfo->getAttributes();
    return (attributes & android::MediaCodecInfo::kFlagIsVendor);
}

EXPORT
AMediaCodecType AMediaCodecInfo_getMediaCodecInfoType(const AMediaCodecInfo *info) {
    if (info == nullptr || info->mInfo == nullptr) {
        return (AMediaCodecType)0;
    }

    int32_t attributes = info->mInfo->getAttributes();

    if (attributes & android::MediaCodecInfo::kFlagIsSoftwareOnly) {
        return SOFTWARE_ONLY;
    }
    if (attributes & android::MediaCodecInfo::kFlagIsHardwareAccelerated) {
        return HARDWARE_ACCELERATED;
    }
    return SOFTWARE_WITH_DEVICE_ACCESS;
}

EXPORT
const char* AMediaCodecInfo_getMediaType(const AMediaCodecInfo *info) {
    if (info == nullptr || info->mInfo == nullptr) {
        return nullptr;
    }

    return info->mMediaType.c_str();
}

EXPORT
int32_t AMediaCodecInfo_getMaxSupportedInstances(const AMediaCodecInfo *info) {
    if (info == nullptr) {
        return -1;
    }

    return info->mCodecCaps->getMaxSupportedInstances();
}

EXPORT
int32_t AMediaCodecInfo_isFeatureSupported(const AMediaCodecInfo *info, const char *featureName) {
    if (featureName == nullptr) {
        return -1;
    }
    return info->mCodecCaps->isFeatureSupported(std::string(featureName));
}

EXPORT
int32_t AMediaCodecInfo_isFeatureRequired(const AMediaCodecInfo *info, const char *featureName) {
    if (featureName == nullptr) {
        return -1;
    }
    return info->mCodecCaps->isFeatureRequired(std::string(featureName));
}

EXPORT
int32_t AMediaCodecInfo_isFormatSupported(const AMediaCodecInfo *info, const AMediaFormat *format) {
    if (format == nullptr) {
        return -1;
    }

    sp<AMessage> nativeFormat;
    AMediaFormat_getFormat(format, &nativeFormat);

    return info->mCodecCaps->isFormatSupported(nativeFormat);
}

EXPORT
media_status_t AMediaCodecInfo_getAudioCapabilities(const AMediaCodecInfo *info,
        const ACodecAudioCapabilities **outAudioCaps) {
    if (info == nullptr || info->mInfo == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    *outAudioCaps = info->mAAudioCaps.get();

    if ((*outAudioCaps) == nullptr) {
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    return AMEDIA_OK;
}

EXPORT
media_status_t AMediaCodecInfo_getVideoCapabilities(const AMediaCodecInfo *info,
        const ACodecVideoCapabilities **outVideoCaps) {
    if (info == nullptr || info->mInfo == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    *outVideoCaps = info->mAVideoCaps.get();

    if ((*outVideoCaps) == nullptr) {
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    return AMEDIA_OK;
}

EXPORT
media_status_t AMediaCodecInfo_getEncoderCapabilities(const AMediaCodecInfo *info,
        const ACodecEncoderCapabilities **outEncoderCaps) {
    if (info == nullptr || info->mInfo == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    *outEncoderCaps = info->mAEncoderCaps.get();

    if ((*outEncoderCaps) == nullptr) {
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    return AMEDIA_OK;
}

// ACodecAudioCapabilities

EXPORT
media_status_t ACodecAudioCapabilities_getBitrateRange(const ACodecAudioCapabilities *audioCaps,
        AIntRange *outRange) {
    if (audioCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    const Range<int32_t>& bitrateRange = audioCaps->mAudioCaps->getBitrateRange();
    outRange->mLower = bitrateRange.lower();
    outRange->mUpper = bitrateRange.upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecAudioCapabilities_getSupportedSampleRates(
        const ACodecAudioCapabilities *audioCaps, const int **outArrayPtr, size_t *outCount) {
    if (audioCaps == nullptr || outArrayPtr == nullptr || outCount == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    if (audioCaps->mSampleRates.empty()) {
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    *outArrayPtr = audioCaps->mSampleRates.data();
    *outCount = audioCaps->mSampleRates.size();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecAudioCapabilities_getSupportedSampleRateRanges(
        const ACodecAudioCapabilities *audioCaps, const AIntRange **outArrayPtr, size_t *outCount) {
    if (audioCaps == nullptr || outArrayPtr == nullptr || outCount == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    *outArrayPtr = audioCaps->mSampleRateRanges.data();
    *outCount = audioCaps->mSampleRateRanges.size();

    return AMEDIA_OK;
}

EXPORT
int32_t ACodecAudioCapabilities_getMaxInputChannelCount(const ACodecAudioCapabilities *audioCaps) {
    if (audioCaps == nullptr) {
        return -1;
    }
    return audioCaps->mAudioCaps->getMaxInputChannelCount();
}

EXPORT
int32_t ACodecAudioCapabilities_getMinInputChannelCount(const ACodecAudioCapabilities *audioCaps) {
    if (audioCaps == nullptr) {
        return -1;
    }
    return audioCaps->mAudioCaps->getMinInputChannelCount();
}

EXPORT
media_status_t ACodecAudioCapabilities_getInputChannelCountRanges(
        const ACodecAudioCapabilities *audioCaps, const AIntRange **outArrayPtr, size_t *outCount) {
    if (audioCaps == nullptr || outArrayPtr == nullptr || outCount == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    *outArrayPtr = audioCaps->mInputChannelCountRanges.data();
    *outCount = audioCaps->mInputChannelCountRanges.size();

    return AMEDIA_OK;
}

EXPORT
int32_t ACodecAudioCapabilities_isSampleRateSupported(const ACodecAudioCapabilities *audioCaps,
        int32_t sampleRate) {
    if (audioCaps == nullptr) {
        return -1;
    }
    return audioCaps->mAudioCaps->isSampleRateSupported(sampleRate);
}

// ACodecPerformancePoint

EXPORT
ACodecPerformancePoint* ACodecPerformancePoint_create(int32_t width, int32_t height,
        int32_t frameRate) {
    return new ACodecPerformancePoint(
            std::make_shared<VideoCapabilities::PerformancePoint>(width, height, frameRate));
}

EXPORT
media_status_t ACodecPerformancePoint_delete(ACodecPerformancePoint *performancePoint) {
    if (performancePoint == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    delete performancePoint;

    return AMEDIA_OK;
}

EXPORT
bool ACodecPerformancePoint_coversFormat(const ACodecPerformancePoint *performancePoint,
        const AMediaFormat *format) {
    sp<AMessage> nativeFormat;
    AMediaFormat_getFormat(format, &nativeFormat);

    return performancePoint->mPerformancePoint->covers(nativeFormat);
}

EXPORT
bool ACodecPerformancePoint_covers(const ACodecPerformancePoint *one,
        const ACodecPerformancePoint *another) {
    return one->mPerformancePoint->covers(*(another->mPerformancePoint));
}

EXPORT
bool ACodecPerformancePoint_equals(const ACodecPerformancePoint *one,
        const ACodecPerformancePoint *another) {
    return one->mPerformancePoint->equals(*(another->mPerformancePoint));
}

// ACodecVideoCapabilities

EXPORT
media_status_t ACodecVideoCapabilities_getBitrateRange(const ACodecVideoCapabilities *videoCaps,
        AIntRange *outRange) {
    if (videoCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    const Range<int32_t>& bitrateRange = videoCaps->mVideoCaps->getBitrateRange();
    outRange->mLower = bitrateRange.lower();
    outRange->mUpper = bitrateRange.upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecVideoCapabilities_getSupportedWidths(const ACodecVideoCapabilities *videoCaps,
        AIntRange *outRange) {
    if (videoCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    const Range<int32_t>& supportedWidths = videoCaps->mVideoCaps->getSupportedWidths();
    outRange->mLower = supportedWidths.lower();
    outRange->mUpper = supportedWidths.upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecVideoCapabilities_getSupportedHeights(const ACodecVideoCapabilities *videoCaps,
        AIntRange *outRange) {
    if (videoCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    const Range<int32_t>& supportedHeights = videoCaps->mVideoCaps->getSupportedHeights();
    outRange->mLower = supportedHeights.lower();
    outRange->mUpper = supportedHeights.upper();

    return AMEDIA_OK;
}

EXPORT
int32_t ACodecVideoCapabilities_getWidthAlignment(const ACodecVideoCapabilities *videoCaps) {
    if (videoCaps == nullptr) {
        return -1;
    }
    return videoCaps->mVideoCaps->getWidthAlignment();
}

EXPORT
int32_t ACodecVideoCapabilities_getHeightAlignment(const ACodecVideoCapabilities *videoCaps) {
    if (videoCaps == nullptr) {
        return -1;
    }
    return videoCaps->mVideoCaps->getHeightAlignment();
}

EXPORT
media_status_t ACodecVideoCapabilities_getSupportedFrameRates(
        const ACodecVideoCapabilities *videoCaps, AIntRange *outRange) {
    if (videoCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    const Range<int32_t>& frameRateRange = videoCaps->mVideoCaps->getSupportedFrameRates();
    outRange->mLower = frameRateRange.lower();
    outRange->mUpper = frameRateRange.upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecVideoCapabilities_getSupportedWidthsFor(
        const ACodecVideoCapabilities *videoCaps, int32_t height, AIntRange *outRange) {
    if (videoCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    std::optional<Range<int32_t>> widthRange = videoCaps->mVideoCaps->getSupportedWidthsFor(height);
    if (!widthRange) {
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    outRange->mLower = widthRange.value().lower();
    outRange->mUpper = widthRange.value().upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecVideoCapabilities_getSupportedHeightsFor(
        const ACodecVideoCapabilities *videoCaps, int32_t width, AIntRange *outRange) {
    if (videoCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    std::optional<Range<int32_t>> heightRange
            = videoCaps->mVideoCaps->getSupportedHeightsFor(width);
    if (!heightRange) {
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    outRange->mLower = heightRange.value().lower();
    outRange->mUpper = heightRange.value().upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecVideoCapabilities_getSupportedFrameRatesFor(
        const ACodecVideoCapabilities *videoCaps, int32_t width, int32_t height,
        ADoubleRange *outRange) {
    if (videoCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    std::optional<Range<double>> frameRates
            = videoCaps->mVideoCaps->getSupportedFrameRatesFor(width, height);
    if (!frameRates) {
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    outRange->mLower = frameRates.value().lower();
    outRange->mUpper = frameRates.value().upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecVideoCapabilities_getAchievableFrameRatesFor(
        const ACodecVideoCapabilities *videoCaps, int32_t width, int32_t height,
        ADoubleRange *outRange) {
    if (videoCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    std::optional<Range<double>> frameRates
            = videoCaps->mVideoCaps->getAchievableFrameRatesFor(width, height);
    if (!frameRates) {
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    outRange->mLower = frameRates.value().lower();
    outRange->mUpper = frameRates.value().upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecVideoCapabilities_getSupportedPerformancePoints(
        const ACodecVideoCapabilities *videoCaps,
        const ACodecPerformancePoint **outPerformancePointArray, size_t *outCount) {
    if (videoCaps == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    *outPerformancePointArray = videoCaps->mPerformancePoints.data();
    *outCount = videoCaps->mPerformancePoints.size();

    return AMEDIA_OK;
}

EXPORT
int32_t ACodecVideoCapabilities_areSizeAndRateSupported(const ACodecVideoCapabilities *videoCaps,
        int32_t width, int32_t height, double frameRate) {
    if (videoCaps == nullptr) {
        return -1;
    }
    return videoCaps->mVideoCaps->areSizeAndRateSupported(width, height, frameRate);
}

EXPORT
int32_t ACodecVideoCapabilities_isSizeSupported(const ACodecVideoCapabilities *videoCaps,
        int32_t width, int32_t height) {
    if (videoCaps == nullptr) {
        return -1;
    }
    return videoCaps->mVideoCaps->isSizeSupported(width, height);
}

// ACodecEncoderCapabilities

EXPORT
media_status_t ACodecEncoderCapabilities_getQualityRange(
        const ACodecEncoderCapabilities *encoderCaps, AIntRange *outRange) {
    if (encoderCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    const Range<int32_t>& qualityRange = encoderCaps->mEncoderCaps->getQualityRange();
    outRange->mLower = qualityRange.lower();
    outRange->mUpper = qualityRange.upper();

    return AMEDIA_OK;
}

EXPORT
media_status_t ACodecEncoderCapabilities_getComplexityRange(
        const ACodecEncoderCapabilities *encoderCaps, AIntRange *outRange) {
    if (encoderCaps == nullptr || outRange == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    const Range<int32_t>& complexityRange = encoderCaps->mEncoderCaps->getComplexityRange();
    outRange->mLower = complexityRange.lower();
    outRange->mUpper = complexityRange.upper();

    return AMEDIA_OK;
}

int32_t ACodecEncoderCapabilities_isBitrateModeSupported(
        const ACodecEncoderCapabilities *encoderCaps, ABiterateMode mode) {
    if (encoderCaps == nullptr) {
        return -1;
    }
    return encoderCaps->mEncoderCaps->isBitrateModeSupported(mode);
}


}
 No newline at end of file
+122 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef _NDK_MEDIA_CODEC_INFO_PRIV_H
#define _NDK_MEDIA_CODEC_INFO_PRIV_H

#include <media/MediaCodecInfo.h>
#include <media/NdkMediaCodecInfo.h>

struct ACodecAudioCapabilities {
    std::shared_ptr<android::AudioCapabilities> mAudioCaps;

    std::vector<int> mSampleRates;
    std::vector<AIntRange> mSampleRateRanges;
    std::vector<AIntRange> mInputChannelCountRanges;

    void initSampleRates() {
        mSampleRates = mAudioCaps->getSupportedSampleRates();
    }

    void initSampleRateRanges() {
        const std::vector<android::Range<int>>& sampleRateRanges
                = mAudioCaps->getSupportedSampleRateRanges();
        for (auto it = sampleRateRanges.begin(); it != sampleRateRanges.end(); it++) {
            mSampleRateRanges.emplace_back(it->lower(), it->upper());
        }
    }

    void initInputChannelCountRanges() {
        const std::vector<android::Range<int>>& inputChannels
                = mAudioCaps->getInputChannelCountRanges();
        for (auto it = inputChannels.begin(); it != inputChannels.end(); it++) {
            mInputChannelCountRanges.emplace_back(it->lower(), it->upper());
        }
    }

    ACodecAudioCapabilities(std::shared_ptr<android::AudioCapabilities> audioCaps)
            : mAudioCaps(audioCaps) {
        initSampleRates();
        initSampleRateRanges();
        initInputChannelCountRanges();
    }
};

struct ACodecPerformancePoint {
    std::shared_ptr<const android::VideoCapabilities::PerformancePoint> mPerformancePoint;

    ACodecPerformancePoint(std::shared_ptr<const android::VideoCapabilities::PerformancePoint>
            performancePoint) : mPerformancePoint(performancePoint) {}
};

struct ACodecVideoCapabilities {
    std::shared_ptr<android::VideoCapabilities> mVideoCaps;

    std::vector<ACodecPerformancePoint> mPerformancePoints;

    void initPerformancePoints() {
        const std::vector<android::VideoCapabilities::PerformancePoint>& performancePoints
            = mVideoCaps->getSupportedPerformancePoints();
        for (auto it = performancePoints.begin(); it != performancePoints.end(); it++) {
            mPerformancePoints.emplace_back(
                    std::shared_ptr<const android::VideoCapabilities::PerformancePoint>(&(*it)));
        }
    }

    ACodecVideoCapabilities(std::shared_ptr<android::VideoCapabilities> videoCaps)
            : mVideoCaps(videoCaps) {
        initPerformancePoints();
    }
};

struct ACodecEncoderCapabilities {
    std::shared_ptr<android::EncoderCapabilities> mEncoderCaps;

    ACodecEncoderCapabilities(std::shared_ptr<android::EncoderCapabilities> encoderCaps)
            : mEncoderCaps(encoderCaps) {}
};

struct AMediaCodecInfo {
    std::string mName;
    android::sp<android::MediaCodecInfo> mInfo;
    std::string mMediaType;
    std::shared_ptr<android::CodecCapabilities> mCodecCaps;

    std::shared_ptr<const ACodecAudioCapabilities> mAAudioCaps;
    std::shared_ptr<const ACodecVideoCapabilities> mAVideoCaps;
    std::shared_ptr<const ACodecEncoderCapabilities> mAEncoderCaps;

    AMediaCodecInfo(std::string name, android::sp<android::MediaCodecInfo> info,
            std::shared_ptr<android::CodecCapabilities> codecCaps, std::string mediaType)
            : mName(name), mInfo(info), mMediaType(mediaType), mCodecCaps(codecCaps) {
        if (!mName.empty() && mInfo != nullptr && !mMediaType.empty() && mCodecCaps != nullptr) {
            if (mCodecCaps->getAudioCapabilities() != nullptr) {
                mAAudioCaps = std::make_shared<const ACodecAudioCapabilities>(
                        mCodecCaps->getAudioCapabilities());
            }
            if (mCodecCaps->getVideoCapabilities() != nullptr) {
                mAVideoCaps = std::make_shared<const ACodecVideoCapabilities>(
                        mCodecCaps->getVideoCapabilities());
            }
            if (mCodecCaps->getEncoderCapabilities() != nullptr) {
                mAEncoderCaps = std::make_shared<const ACodecEncoderCapabilities>(
                    mCodecCaps->getEncoderCapabilities());
            }
        }
    }
};

#endif //_NDK_MEDIA_CODEC_INFO_PRIV_H
 No newline at end of file
+254 −0

File added.

Preview size limit exceeded, changes collapsed.

+625 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading