2020-06-08 03:29:51 +03:00
|
|
|
package mpeg
|
|
|
|
|
|
|
|
import (
|
2021-08-17 13:06:32 +03:00
|
|
|
"github.com/wader/fq/format"
|
|
|
|
"github.com/wader/fq/format/registry"
|
|
|
|
"github.com/wader/fq/pkg/decode"
|
2021-12-02 00:48:25 +03:00
|
|
|
"github.com/wader/fq/pkg/scalar"
|
2020-06-08 03:29:51 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2021-11-17 18:46:10 +03:00
|
|
|
registry.MustRegister(decode.Format{
|
2020-06-08 03:29:51 +03:00
|
|
|
Name: format.AVC_SPS,
|
|
|
|
Description: "H.264/AVC Sequence Parameter Set",
|
|
|
|
DecodeFn: avcSPSDecode,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
var avcVideoFormatMap = scalar.UToSymStr{
|
2021-11-28 18:59:45 +03:00
|
|
|
0: "component",
|
|
|
|
1: "pal",
|
|
|
|
2: "ntsc",
|
|
|
|
3: "secam",
|
|
|
|
4: "mac",
|
|
|
|
5: "unspecified",
|
|
|
|
6: "reserved",
|
|
|
|
7: "reserved",
|
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
var avcAspectRatioIdcMap = scalar.UToSymStr{
|
2021-11-28 18:59:45 +03:00
|
|
|
0: "unspecified",
|
|
|
|
1: "1:1",
|
|
|
|
2: "12:11",
|
|
|
|
3: "10:11",
|
|
|
|
4: "16:11",
|
|
|
|
5: "40:33",
|
|
|
|
6: "24:11",
|
|
|
|
7: "20:11",
|
|
|
|
8: "32:11",
|
|
|
|
9: "80:33",
|
|
|
|
10: "18:11",
|
|
|
|
11: "15:11",
|
|
|
|
12: "64:33",
|
|
|
|
13: "160:99",
|
|
|
|
14: "4:3",
|
|
|
|
15: "3:2",
|
|
|
|
16: "2:1",
|
|
|
|
}
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
func avcVuiParameters(d *decode.D) {
|
|
|
|
aspectRatioInfoPresentFlag := d.FieldBool("aspect_ratio_info_present_flag")
|
|
|
|
if aspectRatioInfoPresentFlag {
|
2021-12-02 00:48:25 +03:00
|
|
|
aspectRatioIdc := d.FieldU8("aspect_ratio_idc", avcAspectRatioIdcMap)
|
2020-06-08 03:29:51 +03:00
|
|
|
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 {
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldU3("video_format", avcVideoFormatMap)
|
2020-06-08 03:29:51 +03:00
|
|
|
d.FieldBool("video_full_range_flag")
|
|
|
|
colourDescriptionPresentFlag := d.FieldBool("colour_description_present_flag")
|
|
|
|
if colourDescriptionPresentFlag {
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldU8("colour_primaries", format.ISO_23091_2_ColourPrimariesMap)
|
|
|
|
d.FieldU8("transfer_characteristics", format.ISO_23091_2_TransferCharacteristicMap)
|
|
|
|
d.FieldU8("matrix_coefficients", format.ISO_23091_2_MatrixCoefficients)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
chromaLocInfoPresentFlag := d.FieldBool("chroma_loc_info_present_flag")
|
|
|
|
if chromaLocInfoPresentFlag {
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldUFn("chroma_sample_loc_type_top_field", uEV)
|
|
|
|
d.FieldUFn("chroma_sample_loc_type_bottom_field", uEV)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldStruct("nal_hrd_parameters", avcHdrParameters)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
vclHrdParametersPresentFlag := d.FieldBool("vcl_hrd_parameters_present_flag")
|
|
|
|
if vclHrdParametersPresentFlag {
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldStruct("vcl_hrd_parameters", avcHdrParameters)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
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")
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldUFn("max_bytes_per_pic_denom", uEV)
|
|
|
|
d.FieldUFn("max_bits_per_mb_denom", uEV)
|
|
|
|
d.FieldUFn("log2_max_mv_length_horizontal", uEV)
|
|
|
|
d.FieldUFn("log2_max_mv_length_vertical", uEV)
|
|
|
|
d.FieldUFn("max_num_reorder_frames", uEV)
|
|
|
|
d.FieldUFn("max_dec_frame_buffering", uEV)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func avcHdrParameters(d *decode.D) {
|
2021-12-02 00:48:25 +03:00
|
|
|
cpbCnt := d.FieldUFn("cpb_cnt", uEV, scalar.UAdd(1))
|
2020-06-08 03:29:51 +03:00
|
|
|
d.FieldU4("bit_rate_scale")
|
|
|
|
d.FieldU4("cpb_size_scale")
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldArray("sched_sels", func(d *decode.D) {
|
2021-11-28 18:59:45 +03:00
|
|
|
for i := uint64(0); i < cpbCnt; i++ {
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldStruct("sched_sel", func(d *decode.D) {
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldUFn("bit_rate_value", uEV, scalar.UAdd(1))
|
|
|
|
d.FieldUFn("cpb_size_value", uEV, scalar.UAdd(1))
|
2020-06-08 03:29:51 +03:00
|
|
|
d.FieldBool("cbr_flag")
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldU5("initial_cpb_removal_delay_length", scalar.UAdd(1))
|
|
|
|
d.FieldU5("cpb_removal_delay_length", scalar.UAdd(1))
|
|
|
|
d.FieldU5("dpb_output_delay_length", scalar.UAdd(1))
|
2020-06-08 03:29:51 +03:00
|
|
|
d.FieldU5("time_offset_length")
|
|
|
|
}
|
|
|
|
|
|
|
|
func avcSPSDecode(d *decode.D, in interface{}) interface{} {
|
2021-12-02 00:48:25 +03:00
|
|
|
profileIdc := d.FieldU8("profile_idc", avcProfileNames)
|
2020-06-08 03:29:51 +03:00
|
|
|
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")
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldU8("level_idc", avcLevelNames)
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldUFn("seq_parameter_set_id", uEV)
|
2020-06-08 03:29:51 +03:00
|
|
|
|
|
|
|
switch profileIdc {
|
|
|
|
// TODO: ffmpeg has some more (legacy values?)
|
|
|
|
case 100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135:
|
2021-11-05 17:04:26 +03:00
|
|
|
chromaFormatIdc := d.FieldUFn("chroma_format_idc", uEV)
|
2020-06-08 03:29:51 +03:00
|
|
|
if chromaFormatIdc == 3 {
|
|
|
|
d.FieldBool("separate_colour_plane_flag")
|
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldUFn("bit_depth_luma", uEV, scalar.UAdd(8))
|
|
|
|
d.FieldUFn("bit_depth_chroma", uEV, scalar.UAdd(8))
|
2020-06-08 03:29:51 +03:00
|
|
|
d.FieldBool("qpprime_y_zero_transform_bypass_flag")
|
|
|
|
seqScalingMatrixPresentFlag := d.FieldBool("seq_scaling_matrix_present_flag")
|
|
|
|
// TODO:
|
|
|
|
_ = seqScalingMatrixPresentFlag
|
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldUFn("log2_max_frame_num", uEV, scalar.UAdd(4))
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
picOrderCntType := d.FieldUFn("pic_order_cnt_type", uEV)
|
2020-06-08 03:29:51 +03:00
|
|
|
if picOrderCntType == 0 {
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldUFn("log2_max_pic_order_cnt_lsb", uEV, scalar.UAdd(4))
|
2020-06-08 03:29:51 +03:00
|
|
|
} else if picOrderCntType == 1 {
|
|
|
|
d.FieldBool("delta_pic_order_always_zero_flag")
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldSFn("offset_for_non_ref_pic", sEV)
|
|
|
|
d.FieldSFn("offset_for_top_to_bottom_field", sEV)
|
|
|
|
numRefFramesInPicOrderCntCycle := d.FieldUFn("num_ref_frames_in_pic_order_cnt_cycle", uEV)
|
|
|
|
d.FieldArray("offset_for_ref_frames", func(d *decode.D) {
|
2020-06-08 03:29:51 +03:00
|
|
|
for i := uint64(0); i < numRefFramesInPicOrderCntCycle; i++ {
|
|
|
|
sEV(d)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldUFn("max_num_ref_frames", uEV)
|
2020-06-08 03:29:51 +03:00
|
|
|
d.FieldBool("gaps_in_frame_num_value_allowed_flag")
|
2021-12-02 00:48:25 +03:00
|
|
|
d.FieldUFn("pic_width_in_mbs", uEV, scalar.UAdd(1))
|
|
|
|
d.FieldUFn("pic_height_in_map_units", uEV, scalar.UAdd(1))
|
2020-06-08 03:29:51 +03:00
|
|
|
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 {
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldUFn("frame_crop_left_offset", uEV)
|
|
|
|
d.FieldUFn("frame_crop_right_offset", uEV)
|
|
|
|
d.FieldUFn("frame_crop_top_offset", uEV)
|
|
|
|
d.FieldUFn("frame_crop_bottom_offset", uEV)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
vuiParametersPresentFlag := d.FieldBool("vui_parameters_present_flag")
|
|
|
|
if vuiParametersPresentFlag {
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldStruct("vui_parameters", avcVuiParameters)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldRawLen("rbsp_trailing_bits", d.BitsLeft())
|
2020-06-08 03:29:51 +03:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|