Search in sources :

Example 1 with ParsableNalUnitBitArray

use of com.google.android.exoplayer2.util.ParsableNalUnitBitArray in project ExoPlayer by google.

the class H265Reader method parseMediaFormat.

private static Format parseMediaFormat(String formatId, NalUnitTargetBuffer vps, NalUnitTargetBuffer sps, NalUnitTargetBuffer pps) {
    // Build codec-specific data.
    byte[] csd = new byte[vps.nalLength + sps.nalLength + pps.nalLength];
    System.arraycopy(vps.nalData, 0, csd, 0, vps.nalLength);
    System.arraycopy(sps.nalData, 0, csd, vps.nalLength, sps.nalLength);
    System.arraycopy(pps.nalData, 0, csd, vps.nalLength + sps.nalLength, pps.nalLength);
    // Parse the SPS NAL unit, as per H.265/HEVC (2014) 7.3.2.2.1.
    ParsableNalUnitBitArray bitArray = new ParsableNalUnitBitArray(sps.nalData, 0, sps.nalLength);
    // NAL header, sps_video_parameter_set_id
    bitArray.skipBits(40 + 4);
    int maxSubLayersMinus1 = bitArray.readBits(3);
    // sps_temporal_id_nesting_flag
    bitArray.skipBits(1);
    // profile_tier_level(1, sps_max_sub_layers_minus1)
    // if (profilePresentFlag) {...}
    bitArray.skipBits(88);
    // general_level_idc
    bitArray.skipBits(8);
    int toSkip = 0;
    for (int i = 0; i < maxSubLayersMinus1; i++) {
        if (bitArray.readBit()) {
            // sub_layer_profile_present_flag[i]
            toSkip += 89;
        }
        if (bitArray.readBit()) {
            // sub_layer_level_present_flag[i]
            toSkip += 8;
        }
    }
    bitArray.skipBits(toSkip);
    if (maxSubLayersMinus1 > 0) {
        bitArray.skipBits(2 * (8 - maxSubLayersMinus1));
    }
    // sps_seq_parameter_set_id
    bitArray.readUnsignedExpGolombCodedInt();
    int chromaFormatIdc = bitArray.readUnsignedExpGolombCodedInt();
    if (chromaFormatIdc == 3) {
        // separate_colour_plane_flag
        bitArray.skipBits(1);
    }
    int picWidthInLumaSamples = bitArray.readUnsignedExpGolombCodedInt();
    int picHeightInLumaSamples = bitArray.readUnsignedExpGolombCodedInt();
    if (bitArray.readBit()) {
        // conformance_window_flag
        int confWinLeftOffset = bitArray.readUnsignedExpGolombCodedInt();
        int confWinRightOffset = bitArray.readUnsignedExpGolombCodedInt();
        int confWinTopOffset = bitArray.readUnsignedExpGolombCodedInt();
        int confWinBottomOffset = bitArray.readUnsignedExpGolombCodedInt();
        // H.265/HEVC (2014) Table 6-1
        int subWidthC = chromaFormatIdc == 1 || chromaFormatIdc == 2 ? 2 : 1;
        int subHeightC = chromaFormatIdc == 1 ? 2 : 1;
        picWidthInLumaSamples -= subWidthC * (confWinLeftOffset + confWinRightOffset);
        picHeightInLumaSamples -= subHeightC * (confWinTopOffset + confWinBottomOffset);
    }
    // bit_depth_luma_minus8
    bitArray.readUnsignedExpGolombCodedInt();
    // bit_depth_chroma_minus8
    bitArray.readUnsignedExpGolombCodedInt();
    int log2MaxPicOrderCntLsbMinus4 = bitArray.readUnsignedExpGolombCodedInt();
    // for (i = sps_sub_layer_ordering_info_present_flag ? 0 : sps_max_sub_layers_minus1; ...)
    for (int i = bitArray.readBit() ? 0 : maxSubLayersMinus1; i <= maxSubLayersMinus1; i++) {
        // sps_max_dec_pic_buffering_minus1[i]
        bitArray.readUnsignedExpGolombCodedInt();
        // sps_max_num_reorder_pics[i]
        bitArray.readUnsignedExpGolombCodedInt();
        // sps_max_latency_increase_plus1[i]
        bitArray.readUnsignedExpGolombCodedInt();
    }
    // log2_min_luma_coding_block_size_minus3
    bitArray.readUnsignedExpGolombCodedInt();
    // log2_diff_max_min_luma_coding_block_size
    bitArray.readUnsignedExpGolombCodedInt();
    // log2_min_luma_transform_block_size_minus2
    bitArray.readUnsignedExpGolombCodedInt();
    // log2_diff_max_min_luma_transform_block_size
    bitArray.readUnsignedExpGolombCodedInt();
    // max_transform_hierarchy_depth_inter
    bitArray.readUnsignedExpGolombCodedInt();
    // max_transform_hierarchy_depth_intra
    bitArray.readUnsignedExpGolombCodedInt();
    // if (scaling_list_enabled_flag) { if (sps_scaling_list_data_present_flag) {...}}
    boolean scalingListEnabled = bitArray.readBit();
    if (scalingListEnabled && bitArray.readBit()) {
        skipScalingList(bitArray);
    }
    // amp_enabled_flag (1), sample_adaptive_offset_enabled_flag (1)
    bitArray.skipBits(2);
    if (bitArray.readBit()) {
        // pcm_enabled_flag
        // pcm_sample_bit_depth_luma_minus1 (4), pcm_sample_bit_depth_chroma_minus1 (4)
        bitArray.skipBits(8);
        // log2_min_pcm_luma_coding_block_size_minus3
        bitArray.readUnsignedExpGolombCodedInt();
        // log2_diff_max_min_pcm_luma_coding_block_size
        bitArray.readUnsignedExpGolombCodedInt();
        // pcm_loop_filter_disabled_flag
        bitArray.skipBits(1);
    }
    // Skips all short term reference picture sets.
    skipShortTermRefPicSets(bitArray);
    if (bitArray.readBit()) {
        // num_long_term_ref_pics_sps
        for (int i = 0; i < bitArray.readUnsignedExpGolombCodedInt(); i++) {
            int ltRefPicPocLsbSpsLength = log2MaxPicOrderCntLsbMinus4 + 4;
            // lt_ref_pic_poc_lsb_sps[i], used_by_curr_pic_lt_sps_flag[i]
            bitArray.skipBits(ltRefPicPocLsbSpsLength + 1);
        }
    }
    // sps_temporal_mvp_enabled_flag, strong_intra_smoothing_enabled_flag
    bitArray.skipBits(2);
    float pixelWidthHeightRatio = 1;
    if (bitArray.readBit()) {
        // vui_parameters_present_flag
        if (bitArray.readBit()) {
            // aspect_ratio_info_present_flag
            int aspectRatioIdc = bitArray.readBits(8);
            if (aspectRatioIdc == NalUnitUtil.EXTENDED_SAR) {
                int sarWidth = bitArray.readBits(16);
                int sarHeight = bitArray.readBits(16);
                if (sarWidth != 0 && sarHeight != 0) {
                    pixelWidthHeightRatio = (float) sarWidth / sarHeight;
                }
            } else if (aspectRatioIdc < NalUnitUtil.ASPECT_RATIO_IDC_VALUES.length) {
                pixelWidthHeightRatio = NalUnitUtil.ASPECT_RATIO_IDC_VALUES[aspectRatioIdc];
            } else {
                Log.w(TAG, "Unexpected aspect_ratio_idc value: " + aspectRatioIdc);
            }
        }
    }
    return Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_H265, null, Format.NO_VALUE, Format.NO_VALUE, picWidthInLumaSamples, picHeightInLumaSamples, Format.NO_VALUE, Collections.singletonList(csd), Format.NO_VALUE, pixelWidthHeightRatio, null);
}
Also used : ParsableNalUnitBitArray(com.google.android.exoplayer2.util.ParsableNalUnitBitArray)

Aggregations

ParsableNalUnitBitArray (com.google.android.exoplayer2.util.ParsableNalUnitBitArray)1