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

Commit 72061e5a authored by Lajos Molnar's avatar Lajos Molnar
Browse files

stagefright: determine if an HEVC file is HDR

Bug: 28671284
Change-Id: Ib567a75c2df759bfef4335d91fd6786946cfee82
parent 70bdd112
Loading
Loading
Loading
Loading
+124 −1
Original line number Diff line number Diff line
@@ -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 @@ static const uint8_t kHevcNalUnitTypes[5] = {
    kHevcNalUnitTypeSuffixSei,
};

HevcParameterSets::HevcParameterSets() {
HevcParameterSets::HevcParameterSets()
    : mInfo(kInfoNone) {
}

status_t HevcParameterSets::addNalUnit(const uint8_t* data, size_t size) {
@@ -221,6 +223,127 @@ status_t HevcParameterSets::parseSps(const uint8_t* data, size_t size) {
    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;
}

+17 −0
Original line number Diff line number Diff line
@@ -56,10 +56,24 @@ enum {
    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 @@ public:
    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 @@ private:

    KeyedVector<uint32_t, uint64_t> mParams;
    Vector<sp<ABuffer>> mNalUnits;
    Info mInfo;

    DISALLOW_EVIL_CONSTRUCTORS(HevcParameterSets);
};