Enumerate all hevc encoders to find one that support CQ @ 512x512 size

bug: 132905160
test: ImageReaderTest#testHeic
Change-Id: I497b203f7e21299eb4e322af4d4c5c925cf5a48a
diff --git a/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp b/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
index ed9be6e..d7cc2bf 100644
--- a/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
+++ b/services/camera/libcameraservice/api2/HeicEncoderInfoManager.cpp
@@ -49,7 +49,7 @@
 }
 
 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 @@
                 (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 @@
     }
 
     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 @@
         }
         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 @@
         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 @@
 
     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