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

Commit 515abd8d authored by Chong Zhang's avatar Chong Zhang Committed by android-build-merger
Browse files

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

am: f01afea9

Change-Id: I02e83c76178e2b673f65730343b6bee598f3a7e1
parents 940ec51a f01afea9
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;