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

bug: 132905160
test: ImageReaderTest#testHeic
Change-Id: I497b203f7e21299eb4e322af4d4c5c925cf5a48a
gugelfrei
Chong Zhang 5 years ago
parent 86bd6afc79
commit 688abaa286

@ -330,9 +330,9 @@ status_t HeicCompositeStream::getCompositeStreamInfo(const OutputStreamInfo &str
} }
bool HeicCompositeStream::isSizeSupportedByHeifEncoder(int32_t width, int32_t height, 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(); 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() { bool HeicCompositeStream::isInMemoryTempFileSupported() {
@ -1115,8 +1115,9 @@ status_t HeicCompositeStream::initializeCodec(uint32_t width, uint32_t height,
ALOGV("%s", __FUNCTION__); ALOGV("%s", __FUNCTION__);
bool useGrid = false; bool useGrid = false;
AString hevcName;
bool isSizeSupported = isSizeSupportedByHeifEncoder(width, height, bool isSizeSupported = isSizeSupportedByHeifEncoder(width, height,
&mUseHeic, &useGrid, nullptr); &mUseHeic, &useGrid, nullptr, &hevcName);
if (!isSizeSupported) { if (!isSizeSupported) {
ALOGE("%s: Encoder doesnt' support size %u x %u!", ALOGE("%s: Encoder doesnt' support size %u x %u!",
__FUNCTION__, width, height); __FUNCTION__, width, height);
@ -1138,7 +1139,11 @@ status_t HeicCompositeStream::initializeCodec(uint32_t width, uint32_t height,
} }
// Create HEIC/HEVC codec. // Create HEIC/HEVC codec.
mCodec = MediaCodec::CreateByType(mCodecLooper, desiredMime, true /*encoder*/); if (mUseHeic) {
mCodec = MediaCodec::CreateByType(mCodecLooper, desiredMime, true /*encoder*/);
} else {
mCodec = MediaCodec::CreateByComponentName(mCodecLooper, hevcName);
}
if (mCodec == nullptr) { if (mCodec == nullptr) {
ALOGE("%s: Failed to create codec for %s", __FUNCTION__, desiredMime); ALOGE("%s: Failed to create codec for %s", __FUNCTION__, desiredMime);
return NO_INIT; return NO_INIT;

@ -71,7 +71,7 @@ public:
const CameraMetadata& ch, std::vector<OutputStreamInfo>* compositeOutput /*out*/); const CameraMetadata& ch, std::vector<OutputStreamInfo>* compositeOutput /*out*/);
static bool isSizeSupportedByHeifEncoder(int32_t width, int32_t height, 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(); static bool isInMemoryTempFileSupported();
protected: protected:

@ -49,7 +49,7 @@ HeicEncoderInfoManager::~HeicEncoderInfoManager() {
} }
bool HeicEncoderInfoManager::isSizeSupported(int32_t width, int32_t height, bool* useHeic, 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) { if (useHeic == nullptr || useGrid == nullptr) {
ALOGE("%s: invalid parameters: useHeic %p, useGrid %p", ALOGE("%s: invalid parameters: useHeic %p, useGrid %p",
__FUNCTION__, useHeic, useGrid); __FUNCTION__, useHeic, useGrid);
@ -72,6 +72,9 @@ bool HeicEncoderInfoManager::isSizeSupported(int32_t width, int32_t height, bool
(width <= 1920 && height <= 1080))) { (width <= 1920 && height <= 1080))) {
enableGrid = false; enableGrid = false;
} }
if (hevcName != nullptr) {
*hevcName = mHevcName;
}
} else { } else {
// No encoder available for the requested size. // No encoder available for the requested size.
return false; return false;
@ -113,9 +116,8 @@ status_t HeicEncoderInfoManager::initialize() {
} }
sp<AMessage> heicDetails = getCodecDetails(codecsList, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC); 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) { if (heicDetails != nullptr) {
ALOGE("%s: Device must support HEVC codec if HEIC codec is available!", ALOGE("%s: Device must support HEVC codec if HEIC codec is available!",
__FUNCTION__); __FUNCTION__);
@ -123,22 +125,7 @@ status_t HeicEncoderInfoManager::initialize() {
} }
return OK; return OK;
} }
mHasHEVC = true;
// 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;
}
}
// HEIC size range // HEIC size range
if (heicDetails != nullptr) { if (heicDetails != nullptr) {
@ -152,19 +139,6 @@ status_t HeicEncoderInfoManager::initialize() {
mHasHEIC = true; 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; return OK;
} }
@ -290,5 +264,80 @@ sp<AMessage> HeicEncoderInfoManager::getCodecDetails(
return details; 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 camera3
} // namespace android } // namespace android

@ -36,7 +36,7 @@ public:
} }
bool isSizeSupported(int32_t width, int32_t height, 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 kGridWidth = 512;
static const auto kGridHeight = 512; static const auto kGridHeight = 512;
@ -61,11 +61,13 @@ private:
FrameRateMaps::const_iterator findClosestSize(const FrameRateMaps& maps, FrameRateMaps::const_iterator findClosestSize(const FrameRateMaps& maps,
int32_t width, int32_t height) const; int32_t width, int32_t height) const;
sp<AMessage> getCodecDetails(sp<IMediaCodecList> codecsList, const char* name); sp<AMessage> getCodecDetails(sp<IMediaCodecList> codecsList, const char* name);
bool getHevcCodecDetails(sp<IMediaCodecList> codecsList, const char* mime);
bool mIsInited; bool mIsInited;
std::pair<int32_t, int32_t> mMinSizeHeic, mMaxSizeHeic; std::pair<int32_t, int32_t> mMinSizeHeic, mMaxSizeHeic;
std::pair<int32_t, int32_t> mMinSizeHevc, mMaxSizeHevc; std::pair<int32_t, int32_t> mMinSizeHevc, mMaxSizeHevc;
bool mHasHEVC, mHasHEIC; bool mHasHEVC, mHasHEIC;
AString mHevcName;
FrameRateMaps mHeicFrameRateMaps, mHevcFrameRateMaps; FrameRateMaps mHeicFrameRateMaps, mHevcFrameRateMaps;
bool mDisableGrid; bool mDisableGrid;

Loading…
Cancel
Save