stagefright: fix profile handling for HDR streams
Bug: 28671284
Change-Id: Ic7f3b7906f437aec94b0488b480d89a49b404f96
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 208b238..c461ca0 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -141,6 +141,28 @@
}
}
+static bool isHdr(const sp<AMessage> &format) {
+ // if CSD specifies HDR transfer(s), we assume HDR. Otherwise, if it specifies non-HDR
+ // transfers, we must assume non-HDR. This is because CSD trumps any color-transfer key
+ // in the format.
+ int32_t isHdr;
+ if (format->findInt32("android._is-hdr", &isHdr)) {
+ return isHdr;
+ }
+
+ // if user/container supplied HDR static info without transfer set, assume true
+ if (format->contains("hdr-static-info") && !format->contains("color-transfer")) {
+ return true;
+ }
+ // otherwise, verify that an HDR transfer function is set
+ int32_t transfer;
+ if (format->findInt32("color-transfer", &transfer)) {
+ return transfer == ColorUtils::kColorTransferST2084
+ || transfer == ColorUtils::kColorTransferHLG;
+ }
+ return false;
+}
+
static void parseAacProfileFromCsd(const sp<ABuffer> &csd, sp<AMessage> &format) {
if (csd->size() < 2) {
return;
@@ -322,6 +344,12 @@
return;
}
}
+
+ // bump to HDR profile
+ if (isHdr(format) && codecProfile == OMX_VIDEO_HEVCProfileMain10) {
+ codecProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
+ }
+
format->setInt32("profile", codecProfile);
if (levels.map(std::make_pair(tier, level), &codecLevel)) {
format->setInt32("level", codecLevel);
@@ -514,8 +542,18 @@
{ 3, OMX_VIDEO_VP9Profile3 },
};
+ const static ALookup<OMX_VIDEO_VP9PROFILETYPE, OMX_VIDEO_VP9PROFILETYPE> toHdr {
+ { OMX_VIDEO_VP9Profile2, OMX_VIDEO_VP9Profile2HDR },
+ { OMX_VIDEO_VP9Profile3, OMX_VIDEO_VP9Profile3HDR },
+ };
+
OMX_VIDEO_VP9PROFILETYPE profile;
if (profiles.map(data[0], &profile)) {
+ // convert to HDR profile
+ if (isHdr(format)) {
+ toHdr.lookup(profile, &profile);
+ }
+
format->setInt32("profile", profile);
}
}
@@ -818,7 +856,7 @@
return BAD_VALUE;
}
- parseHevcProfileLevelFromHvcc(ptr, size, msg);
+ const size_t dataSize = size; // save for later
ptr += 22;
size -= 22;
@@ -833,6 +871,8 @@
}
buffer->setRange(0, 0);
+ HevcParameterSets hvcc;
+
for (i = 0; i < numofArrays; i++) {
if (size < 3) {
ALOGE("b/23680780");
@@ -864,6 +904,7 @@
if (err != OK) {
return err;
}
+ (void)hvcc.addNalUnit(ptr, length);
ptr += length;
size -= length;
@@ -873,6 +914,14 @@
buffer->meta()->setInt64("timeUs", 0);
msg->setBuffer("csd-0", buffer);
+ // if we saw VUI color information we know whether this is HDR because VUI trumps other
+ // format parameters for HEVC.
+ HevcParameterSets::Info info = hvcc.getInfo();
+ if (info & hvcc.kInfoHasColorDescription) {
+ msg->setInt32("android._is-hdr", (info & hvcc.kInfoIsHdr) != 0);
+ }
+
+ parseHevcProfileLevelFromHvcc((const uint8_t *)data, dataSize, msg);
} else if (meta->findData(kKeyESDS, &type, &data, &size)) {
ESDS esds((const char *)data, size);
if (esds.InitCheck() != (status_t)OK) {