1
1
mirror of https://github.com/wader/fq.git synced 2024-12-26 15:02:28 +03:00
fq/format/mpeg/avc_sps.go
2021-09-12 13:08:50 +02:00

172 lines
5.5 KiB
Go

package mpeg
// ISO/IEC 14496-15 AVC file format, 5.3.3.1.2 Syntax
// ISO_IEC_14496-10 AVC
import (
"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/pkg/decode"
)
func init() {
registry.MustRegister(&decode.Format{
Name: format.AVC_SPS,
Description: "H.264/AVC Sequence Parameter Set",
DecodeFn: avcSPSDecode,
})
}
func avcVuiParameters(d *decode.D) {
aspectRatioInfoPresentFlag := d.FieldBool("aspect_ratio_info_present_flag")
if aspectRatioInfoPresentFlag {
aspectRatioIdc := d.FieldU8("aspect_ratio_idc")
const extendedSAR = 255
if aspectRatioIdc == extendedSAR {
d.FieldU16("width")
d.FieldU16("height")
}
}
overscanInfoPresentFlag := d.FieldBool("overscan_info_present_flag")
if overscanInfoPresentFlag {
d.FieldBool("overscan_appropriate_flag")
}
videoSignalTypePresentFlag := d.FieldBool("video_signal_type_present_flag")
if videoSignalTypePresentFlag {
d.FieldU3("video_format")
d.FieldBool("video_full_range_flag")
colourDescriptionPresentFlag := d.FieldBool("colour_description_present_flag")
if colourDescriptionPresentFlag {
d.FieldU8("colour_primaries")
d.FieldU8("transfer_characteristics")
d.FieldU8("matrix_coefficients")
}
}
chromaLocInfoPresentFlag := d.FieldBool("chroma_loc_info_present_flag")
if chromaLocInfoPresentFlag {
fieldUEV(d, "chroma_sample_loc_type_top_field")
fieldUEV(d, "chroma_sample_loc_type_bottom_field")
}
timingInfoPresentFlag := d.FieldBool("timing_info_present_flag")
if timingInfoPresentFlag {
d.FieldU32("num_units_in_tick")
d.FieldU32("time_scale")
d.FieldBool("fixed_frame_rate_flag")
}
nalHrdParametersPresentFlag := d.FieldBool("nal_hrd_parameters_present_flag")
if nalHrdParametersPresentFlag {
d.FieldStructFn("nal_hrd_parameters", avcHdrParameters)
}
vclHrdParametersPresentFlag := d.FieldBool("vcl_hrd_parameters_present_flag")
if vclHrdParametersPresentFlag {
d.FieldStructFn("vcl_hrd_parameters", avcHdrParameters)
}
if nalHrdParametersPresentFlag || vclHrdParametersPresentFlag {
d.FieldBool("low_delay_hrd_flag")
}
d.FieldBool("pic_struct_present_flag")
bitstreamRestrictionFlag := d.FieldBool("bitstream_restriction_flag")
if bitstreamRestrictionFlag {
d.FieldBool("motion_vectors_over_pic_boundaries_flag")
fieldUEV(d, "max_bytes_per_pic_denom")
fieldUEV(d, "max_bits_per_mb_denom")
fieldUEV(d, "log2_max_mv_length_horizontal")
fieldUEV(d, "log2_max_mv_length_vertical")
fieldUEV(d, "max_num_reorder_frames")
fieldUEV(d, "max_dec_frame_buffering")
}
}
func avcHdrParameters(d *decode.D) {
cpbCntMinus1 := fieldUEV(d, "cpb_cnt_minus1")
_ = cpbCntMinus1
d.FieldU4("bit_rate_scale")
d.FieldU4("cpb_size_scale")
d.FieldArrayFn("sched_sels", func(d *decode.D) {
for i := uint64(0); i <= cpbCntMinus1; i++ {
d.FieldStructFn("sched_sel", func(d *decode.D) {
fieldUEV(d, "bit_rate_value_minus1")
fieldUEV(d, "cpb_size_value_minus1")
d.FieldBool("cbr_flag")
})
}
})
d.FieldU5("initial_cpb_removal_delay_length_minus1")
d.FieldU5("cpb_removal_delay_length_minus1")
d.FieldU5("dpb_output_delay_length_minus1")
d.FieldU5("time_offset_length")
}
func avcSPSDecode(d *decode.D, in interface{}) interface{} {
profileIdc, _ := d.FieldStringMapFn("profile_idc", avcProfileNames, "Unknown", d.U8, decode.NumberDecimal)
d.FieldBool("constraint_set0_flag")
d.FieldBool("constraint_set1_flag")
d.FieldBool("constraint_set2_flag")
d.FieldBool("constraint_set3_flag")
d.FieldBool("constraint_set4_flag")
d.FieldBool("constraint_set5_flag")
d.FieldU2("reserved_zero_2bits")
d.FieldStringMapFn("level_idc", avcLevelNames, "Unknown", d.U8, decode.NumberDecimal)
fieldUEV(d, "seq_parameter_set_id")
switch profileIdc {
// TODO: ffmpeg has some more (legacy values?)
case 100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135:
chromaFormatIdc := fieldUEV(d, "chroma_format_idc")
if chromaFormatIdc == 3 {
d.FieldBool("separate_colour_plane_flag")
}
fieldUEV(d, "bit_depth_luma_minus8")
fieldUEV(d, "bit_depth_chroma_minus8")
d.FieldBool("qpprime_y_zero_transform_bypass_flag")
seqScalingMatrixPresentFlag := d.FieldBool("seq_scaling_matrix_present_flag")
// TODO:
_ = seqScalingMatrixPresentFlag
}
fieldUEV(d, "log2_max_frame_num_minus4")
picOrderCntType := fieldUEV(d, "pic_order_cnt_type")
if picOrderCntType == 0 {
fieldUEV(d, "log2_max_pic_order_cnt_lsb_minus4")
} else if picOrderCntType == 1 {
d.FieldBool("delta_pic_order_always_zero_flag")
fieldSEV(d, "offset_for_non_ref_pic")
fieldSEV(d, "offset_for_top_to_bottom_field")
numRefFramesInPicOrderCntCycle := fieldUEV(d, "num_ref_frames_in_pic_order_cnt_cycle")
d.FieldArrayFn("offset_for_ref_frames", func(d *decode.D) {
for i := uint64(0); i < numRefFramesInPicOrderCntCycle; i++ {
sEV(d)
}
})
}
fieldUEV(d, "max_num_ref_frames")
d.FieldBool("gaps_in_frame_num_value_allowed_flag")
fieldUEV(d, "pic_width_in_mbs_minus1")
fieldUEV(d, "pic_height_in_map_units_minus1")
frameMbsOnlyFlag := d.FieldBool("frame_mbs_only_flag")
if !frameMbsOnlyFlag {
d.FieldBool("mb_adaptive_frame_field_flag")
}
d.FieldBool("direct_8x8_inference_flag")
frameCroppingFlag := d.FieldBool("frame_cropping_flag")
if frameCroppingFlag {
fieldUEV(d, "frame_crop_left_offset")
fieldUEV(d, "frame_crop_right_offset")
fieldUEV(d, "frame_crop_top_offset")
fieldUEV(d, "frame_crop_bottom_offset")
}
vuiParametersPresentFlag := d.FieldBool("vui_parameters_present_flag")
if vuiParametersPresentFlag {
d.FieldStructFn("vui_parameters", avcVuiParameters)
}
d.FieldBitBufLen("rbsp_trailing_bits", d.BitsLeft())
return nil
}