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

Commit f01afea9 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Enumerate all hevc encoders to find one that support CQ @ 512x512 size" into qt-dev

parents 7d44121e 688abaa2
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -330,9 +330,9 @@ status_t HeicCompositeStream::getCompositeStreamInfo(const OutputStreamInfo &str
}

bool HeicCompositeStream::isSizeSupportedByHeifEncoder(int32_t width, int32_t height,
        bool* useHeic, bool* useGrid, int64_t* stall) {
        bool* useHeic, bool* useGrid, int64_t* stall, AString* hevcName) {
    static HeicEncoderInfoManager& heicManager = HeicEncoderInfoManager::getInstance();
    return heicManager.isSizeSupported(width, height, useHeic, useGrid, stall);
    return heicManager.isSizeSupported(width, height, useHeic, useGrid, stall, hevcName);
}

bool HeicCompositeStream::isInMemoryTempFileSupported() {
@@ -1115,8 +1115,9 @@ status_t HeicCompositeStream::initializeCodec(uint32_t width, uint32_t height,
    ALOGV("%s", __FUNCTION__);

    bool useGrid = false;
    AString hevcName;
    bool isSizeSupported = isSizeSupportedByHeifEncoder(width, height,
            &mUseHeic, &useGrid, nullptr);
            &mUseHeic, &useGrid, nullptr, &hevcName);
    if (!isSizeSupported) {
        ALOGE("%s: Encoder doesnt' support size %u x %u!",
                __FUNCTION__, width, height);
@@ -1138,7 +1139,11 @@ status_t HeicCompositeStream::initializeCodec(uint32_t width, uint32_t height,
    }

    // Create HEIC/HEVC codec.
    if (mUseHeic) {
        mCodec = MediaCodec::CreateByType(mCodecLooper, desiredMime, true /*encoder*/);
    } else {
        mCodec = MediaCodec::CreateByComponentName(mCodecLooper, hevcName);
    }
    if (mCodec == nullptr) {
        ALOGE("%s: Failed to create codec for %s", __FUNCTION__, desiredMime);
        return NO_INIT;
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ public:
            const CameraMetadata& ch, std::vector<OutputStreamInfo>* compositeOutput /*out*/);

    static bool isSizeSupportedByHeifEncoder(int32_t width, int32_t height,
            bool* useHeic, bool* useGrid, int64_t* stall);
            bool* useHeic, bool* useGrid, int64_t* stall, AString* hevcName = nullptr);
    static bool isInMemoryTempFileSupported();
protected:

+81 −32
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ HeicEncoderInfoManager::~HeicEncoderInfoManager() {
}

bool HeicEncoderInfoManager::isSizeSupported(int32_t width, int32_t height, bool* useHeic,
        bool* useGrid, int64_t* stall) const {
        bool* useGrid, int64_t* stall, AString* hevcName) const {
    if (useHeic == nullptr || useGrid == nullptr) {
        ALOGE("%s: invalid parameters: useHeic %p, useGrid %p",
                __FUNCTION__, useHeic, useGrid);
@@ -72,6 +72,9 @@ bool HeicEncoderInfoManager::isSizeSupported(int32_t width, int32_t height, bool
                (width <= 1920 && height <= 1080))) {
            enableGrid = false;
        }
        if (hevcName != nullptr) {
            *hevcName = mHevcName;
        }
    } else {
        // No encoder available for the requested size.
        return false;
@@ -113,9 +116,8 @@ status_t HeicEncoderInfoManager::initialize() {
    }

    sp<AMessage> heicDetails = getCodecDetails(codecsList, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
    sp<AMessage> hevcDetails = getCodecDetails(codecsList, MEDIA_MIMETYPE_VIDEO_HEVC);

    if (hevcDetails == nullptr) {
    if (!getHevcCodecDetails(codecsList, MEDIA_MIMETYPE_VIDEO_HEVC)) {
        if (heicDetails != nullptr) {
            ALOGE("%s: Device must support HEVC codec if HEIC codec is available!",
                    __FUNCTION__);
@@ -123,22 +125,7 @@ status_t HeicEncoderInfoManager::initialize() {
        }
        return OK;
    }

    // Check CQ mode for HEVC codec
    {
        AString bitrateModes;
        auto hasItem = hevcDetails->findString("feature-bitrate-modes", &bitrateModes);
        if (!hasItem) {
            ALOGE("%s: Failed to query bitrate modes for HEVC codec", __FUNCTION__);
            return BAD_VALUE;
        }
        ALOGV("%s: HEVC codec's feature-bitrate-modes value is %d, %s",
                __FUNCTION__, hasItem, bitrateModes.c_str());
        std::regex pattern("(^|,)CQ($|,)", std::regex_constants::icase);
        if (!std::regex_search(bitrateModes.c_str(), pattern)) {
            return OK;
        }
    }
    mHasHEVC = true;

    // HEIC size range
    if (heicDetails != nullptr) {
@@ -152,19 +139,6 @@ status_t HeicEncoderInfoManager::initialize() {
        mHasHEIC = true;
    }

    // HEVC size range
    {
        auto res = getCodecSizeRange(MEDIA_MIMETYPE_VIDEO_HEVC,
                hevcDetails, &mMinSizeHevc, &mMaxSizeHevc, &mHevcFrameRateMaps);
        if (res != OK) {
            ALOGE("%s: Failed to get HEVC codec size range: %s (%d)", __FUNCTION__,
                    strerror(-res), res);
            return BAD_VALUE;
        }

        mHasHEVC = true;
    }

    return OK;
}

@@ -290,5 +264,80 @@ sp<AMessage> HeicEncoderInfoManager::getCodecDetails(

    return details;
}

bool HeicEncoderInfoManager::getHevcCodecDetails(
        sp<IMediaCodecList> codecsList, const char* mime) {
    bool found = false;
    ssize_t idx = 0;
    while ((idx = codecsList->findCodecByType(mime, true /*encoder*/, idx)) >= 0) {
        const sp<MediaCodecInfo> info = codecsList->getCodecInfo(idx++);
        if (info == nullptr) {
            ALOGE("%s: Failed to get codec info for %s", __FUNCTION__, mime);
            break;
        }

        // Filter out software ones as they may be too slow
        if (!(info->getAttributes() & MediaCodecInfo::kFlagIsHardwareAccelerated)) {
            continue;
        }

        const sp<MediaCodecInfo::Capabilities> caps =
                info->getCapabilitiesFor(mime);
        if (caps == nullptr) {
            ALOGE("%s: [%s] Failed to get capabilities", __FUNCTION__,
                    info->getCodecName());
            break;
        }
        const sp<AMessage> details = caps->getDetails();
        if (details == nullptr) {
            ALOGE("%s: [%s] Failed to get details", __FUNCTION__,
                    info->getCodecName());
            break;
        }

        // Check CQ mode
        AString bitrateModes;
        auto hasItem = details->findString("feature-bitrate-modes", &bitrateModes);
        if (!hasItem) {
            ALOGE("%s: [%s] Failed to query bitrate modes", __FUNCTION__,
                    info->getCodecName());
            break;
        }
        ALOGV("%s: [%s] feature-bitrate-modes value is %d, %s",
                __FUNCTION__, info->getCodecName(), hasItem, bitrateModes.c_str());
        std::regex pattern("(^|,)CQ($|,)", std::regex_constants::icase);
        if (!std::regex_search(bitrateModes.c_str(), pattern)) {
            continue; // move on to next encoder
        }

        std::pair<int32_t, int32_t> minSizeHevc, maxSizeHevc;
        FrameRateMaps hevcFrameRateMaps;
        auto res = getCodecSizeRange(MEDIA_MIMETYPE_VIDEO_HEVC,
                details, &minSizeHevc, &maxSizeHevc, &hevcFrameRateMaps);
        if (res != OK) {
            ALOGE("%s: [%s] Failed to get size range: %s (%d)", __FUNCTION__,
                    info->getCodecName(), strerror(-res), res);
            break;
        }
        if (kGridWidth < minSizeHevc.first
                || kGridWidth > maxSizeHevc.first
                || kGridHeight < minSizeHevc.second
                || kGridHeight > maxSizeHevc.second) {
            continue; // move on to next encoder
        }

        // Found: save name, size, frame rate
        mHevcName = info->getCodecName();
        mMinSizeHevc = minSizeHevc;
        mMaxSizeHevc = maxSizeHevc;
        mHevcFrameRateMaps = hevcFrameRateMaps;

        found = true;
        break;
    }

    return found;
}

} //namespace camera3
} // namespace android
+3 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ public:
    }

    bool isSizeSupported(int32_t width, int32_t height,
            bool* useHeic, bool* useGrid, int64_t* stall) const;
            bool* useHeic, bool* useGrid, int64_t* stall, AString* hevcName) const;

    static const auto kGridWidth = 512;
    static const auto kGridHeight = 512;
@@ -61,11 +61,13 @@ private:
    FrameRateMaps::const_iterator findClosestSize(const FrameRateMaps& maps,
            int32_t width, int32_t height) const;
    sp<AMessage> getCodecDetails(sp<IMediaCodecList> codecsList, const char* name);
    bool getHevcCodecDetails(sp<IMediaCodecList> codecsList, const char* mime);

    bool mIsInited;
    std::pair<int32_t, int32_t> mMinSizeHeic, mMaxSizeHeic;
    std::pair<int32_t, int32_t> mMinSizeHevc, mMaxSizeHevc;
    bool mHasHEVC, mHasHEIC;
    AString mHevcName;
    FrameRateMaps mHeicFrameRateMaps, mHevcFrameRateMaps;
    bool mDisableGrid;