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);
}
Aggregations