Merge "stagefright: move all codecs into codec process unless excluded" into nyc-dev
diff --git a/media/libstagefright/HevcUtils.cpp b/media/libstagefright/HevcUtils.cpp
index e7e99ff..718710a 100644
--- a/media/libstagefright/HevcUtils.cpp
+++ b/media/libstagefright/HevcUtils.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "HevcUtils"
#include <cstring>
+#include <utility>
#include "include/HevcUtils.h"
#include "include/avc_utils.h"
@@ -39,7 +40,8 @@
kHevcNalUnitTypeSuffixSei,
};
-HevcParameterSets::HevcParameterSets() {
+HevcParameterSets::HevcParameterSets()
+ : mInfo(kInfoNone) {
}
status_t HevcParameterSets::addNalUnit(const uint8_t* data, size_t size) {
@@ -221,6 +223,127 @@
mParams.add(kBitDepthLumaMinus8, parseUEWithFallback(&reader, 0));
mParams.add(kBitDepthChromaMinus8, parseUEWithFallback(&reader, 0));
+ // log2_max_pic_order_cnt_lsb_minus4
+ size_t log2MaxPicOrderCntLsb = parseUEWithFallback(&reader, 0) + (size_t)4;
+ bool spsSubLayerOrderingInfoPresentFlag = reader.getBitsWithFallback(1, 0);
+ for (uint32_t i = spsSubLayerOrderingInfoPresentFlag ? 0 : maxSubLayersMinus1;
+ i <= maxSubLayersMinus1; ++i) {
+ skipUE(&reader); // sps_max_dec_pic_buffering_minus1[i]
+ skipUE(&reader); // sps_max_num_reorder_pics[i]
+ skipUE(&reader); // sps_max_latency_increase_plus1[i]
+ }
+
+ skipUE(&reader); // log2_min_luma_coding_block_size_minus3
+ skipUE(&reader); // log2_diff_max_min_luma_coding_block_size
+ skipUE(&reader); // log2_min_luma_transform_block_size_minus2
+ skipUE(&reader); // log2_diff_max_min_luma_transform_block_size
+ skipUE(&reader); // max_transform_hierarchy_depth_inter
+ skipUE(&reader); // max_transform_hierarchy_depth_intra
+ if (reader.getBitsWithFallback(1, 0)) { // scaling_list_enabled_flag u(1)
+ // scaling_list_data
+ if (reader.getBitsWithFallback(1, 0)) { // sps_scaling_list_data_present_flag
+ for (uint32_t sizeId = 0; sizeId < 4; ++sizeId) {
+ for (uint32_t matrixId = 0; matrixId < 6; matrixId += (sizeId == 3) ? 3 : 1) {
+ if (!reader.getBitsWithFallback(1, 1)) {
+ // scaling_list_pred_mode_flag[sizeId][matrixId]
+ skipUE(&reader); // scaling_list_pred_matrix_id_delta[sizeId][matrixId]
+ } else {
+ uint32_t coefNum = std::min(64, (1 << (4 + (sizeId << 1))));
+ if (sizeId > 1) {
+ skipSE(&reader); // scaling_list_dc_coef_minus8[sizeId − 2][matrixId]
+ }
+ for (uint32_t i = 0; i < coefNum; ++i) {
+ skipSE(&reader); // scaling_list_delta_coef
+ }
+ }
+ }
+ }
+ }
+ }
+ reader.skipBits(1); // amp_enabled_flag
+ reader.skipBits(1); // sample_adaptive_offset_enabled_flag u(1)
+ if (reader.getBitsWithFallback(1, 0)) { // pcm_enabled_flag
+ reader.skipBits(4); // pcm_sample_bit_depth_luma_minus1
+ reader.skipBits(4); // pcm_sample_bit_depth_chroma_minus1 u(4)
+ skipUE(&reader); // log2_min_pcm_luma_coding_block_size_minus3
+ skipUE(&reader); // log2_diff_max_min_pcm_luma_coding_block_size
+ reader.skipBits(1); // pcm_loop_filter_disabled_flag
+ }
+ uint32_t numShortTermRefPicSets = parseUEWithFallback(&reader, 0);
+ uint32_t numPics = 0;
+ for (uint32_t i = 0; i < numShortTermRefPicSets; ++i) {
+ // st_ref_pic_set(i)
+ if (i != 0 && reader.getBitsWithFallback(1, 0)) { // inter_ref_pic_set_prediction_flag
+ reader.skipBits(1); // delta_rps_sign
+ skipUE(&reader); // abs_delta_rps_minus1
+ uint32_t nextNumPics = 0;
+ for (uint32_t j = 0; j <= numPics; ++j) {
+ if (reader.getBitsWithFallback(1, 0) // used_by_curr_pic_flag[j]
+ || reader.getBitsWithFallback(1, 0)) { // use_delta_flag[j]
+ ++nextNumPics;
+ }
+ }
+ numPics = nextNumPics;
+ } else {
+ uint32_t numNegativePics = parseUEWithFallback(&reader, 0);
+ uint32_t numPositivePics = parseUEWithFallback(&reader, 0);
+ if (numNegativePics > UINT32_MAX - numPositivePics) {
+ return ERROR_MALFORMED;
+ }
+ numPics = numNegativePics + numPositivePics;
+ for (uint32_t j = 0; j < numPics; ++j) {
+ skipUE(&reader); // delta_poc_s0|1_minus1[i]
+ reader.skipBits(1); // used_by_curr_pic_s0|1_flag[i]
+ }
+ }
+ }
+ if (reader.getBitsWithFallback(1, 0)) { // long_term_ref_pics_present_flag
+ uint32_t numLongTermRefPicSps = parseUEWithFallback(&reader, 0);
+ for (uint32_t i = 0; i < numLongTermRefPicSps; ++i) {
+ reader.skipBits(log2MaxPicOrderCntLsb); // lt_ref_pic_poc_lsb_sps[i]
+ reader.skipBits(1); // used_by_curr_pic_lt_sps_flag[i]
+ }
+ }
+ reader.skipBits(1); // sps_temporal_mvp_enabled_flag
+ reader.skipBits(1); // strong_intra_smoothing_enabled_flag
+ if (reader.getBitsWithFallback(1, 0)) { // vui_parameters_present_flag
+ if (reader.getBitsWithFallback(1, 0)) { // aspect_ratio_info_present_flag
+ uint32_t aspectRatioIdc = reader.getBitsWithFallback(8, 0);
+ if (aspectRatioIdc == 0xFF /* EXTENDED_SAR */) {
+ reader.skipBits(16); // sar_width
+ reader.skipBits(16); // sar_height
+ }
+ }
+ if (reader.getBitsWithFallback(1, 0)) { // overscan_info_present_flag
+ reader.skipBits(1); // overscan_appropriate_flag
+ }
+ if (reader.getBitsWithFallback(1, 0)) { // video_signal_type_present_flag
+ reader.skipBits(3); // video_format
+ uint32_t videoFullRangeFlag;
+ if (reader.getBitsGraceful(1, &videoFullRangeFlag)) {
+ mParams.add(kVideoFullRangeFlag, videoFullRangeFlag);
+ }
+ if (reader.getBitsWithFallback(1, 0)) { // colour_description_present_flag
+ mInfo = (Info)(mInfo | kInfoHasColorDescription);
+ uint32_t colourPrimaries, transferCharacteristics, matrixCoeffs;
+ if (reader.getBitsGraceful(8, &colourPrimaries)) {
+ mParams.add(kColourPrimaries, colourPrimaries);
+ }
+ if (reader.getBitsGraceful(8, &transferCharacteristics)) {
+ mParams.add(kTransferCharacteristics, transferCharacteristics);
+ if (transferCharacteristics == 16 /* ST 2084 */
+ || transferCharacteristics == 18 /* ARIB STD-B67 HLG */) {
+ mInfo = (Info)(mInfo | kInfoIsHdr);
+ }
+ }
+ if (reader.getBitsGraceful(8, &matrixCoeffs)) {
+ mParams.add(kMatrixCoeffs, matrixCoeffs);
+ }
+ }
+ // skip rest of VUI
+ }
+ }
+
return reader.overRead() ? ERROR_MALFORMED : OK;
}
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) {
diff --git a/media/libstagefright/include/HevcUtils.h b/media/libstagefright/include/HevcUtils.h
index 0d7bb2f..0f59631 100644
--- a/media/libstagefright/include/HevcUtils.h
+++ b/media/libstagefright/include/HevcUtils.h
@@ -56,10 +56,24 @@
kBitDepthLumaMinus8,
// uint8_t
kBitDepthChromaMinus8,
+ // uint8_t
+ kVideoFullRangeFlag,
+ // uint8_t
+ kColourPrimaries,
+ // uint8_t
+ kTransferCharacteristics,
+ // uint8_t
+ kMatrixCoeffs,
};
class HevcParameterSets {
public:
+ enum Info : uint32_t {
+ kInfoNone = 0,
+ kInfoIsHdr = 1 << 0,
+ kInfoHasColorDescription = 1 << 1,
+ };
+
HevcParameterSets();
status_t addNalUnit(const uint8_t* data, size_t size);
@@ -77,6 +91,8 @@
bool write(size_t index, uint8_t* dest, size_t size);
status_t makeHvcc(uint8_t *hvcc, size_t *hvccSize, size_t nalSizeLength);
+ Info getInfo() const { return mInfo; }
+
private:
status_t parseVps(const uint8_t* data, size_t size);
status_t parseSps(const uint8_t* data, size_t size);
@@ -84,6 +100,7 @@
KeyedVector<uint32_t, uint64_t> mParams;
Vector<sp<ABuffer>> mNalUnits;
+ Info mInfo;
DISALLOW_EVIL_CONSTRUCTORS(HevcParameterSets);
};