package mpeg 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_SEI, Description: "H.264/AVC Supplemental Enhancement Information", DecodeFn: avcSEIDecode, }) } const ( avcSEIUserDataUnregistered = 5 ) var seiNames = decode.UToStr{ 0: "buffering_period", 1: "pic_timing", 2: "pan_scan_rect", 3: "filler_payload", 4: "user_data_registered_itu_t_t35", avcSEIUserDataUnregistered: "user_data_unregistered", 6: "recovery_point", 7: "dec_ref_pic_marking_repetition", 8: "spare_pic", 9: "scene_info", 10: "sub_seq_info", 11: "sub_seq_layer_characteristics", 12: "sub_seq_characteristics", 13: "full_frame_freeze", 14: "full_frame_freeze_release", 15: "full_frame_snapshot", 16: "progressive_refinement_segment_start", 17: "progressive_refinement_segment_end", 18: "motion_constrained_slice_group_set", 19: "film_grain_characteristics", 20: "deblocking_filter_display_preference", 21: "stereo_video_info", 22: "post_filter_hint", 23: "tone_mapping_info", 24: "scalability_info", 25: "sub_pic_scalable_layer", 26: "non_required_layer_rep", 27: "priority_layer_info", 28: "layers_not_present", 29: "layer_dependency_change", 30: "scalable_nesting", 31: "base_layer_temporal_hrd", 32: "quality_layer_integrity_check", 33: "redundant_pic_property", 34: "tl0_dep_rep_index", 35: "tl_switching_point", 36: "parallel_decoding_info", 37: "mvc_scalable_nesting", 38: "view_scalability_info", 39: "multiview_scene_info", 40: "multiview_acquisition_info", 41: "non_required_view_component", 42: "view_dependency_change", 43: "operation_points_not_present", 44: "base_view_temporal_hrd", 45: "frame_packing_arrangement", 46: "multiview_view_position", 47: "display_orientation", 48: "mvcd_scalable_nesting", 49: "mvcd_view_scalability_info", 50: "depth_representation_info", 51: "three_dimensional_reference_displays_info", 52: "depth_timing", 53: "depth_sampling_info", 54: "constrained_depth_parameter_set_identifier", 56: "green_metadata", 137: "mastering_display_colour_volume", 181: "alternative_depth_info", } var ( x264Bytes = [16]byte{0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef} ) var userDataUnregisteredNames = decode.BytesToScalar{ {Bytes: x264Bytes[:], Scalar: decode.Scalar{Sym: "x264"}}, } // sum bytes until < 0xff func ffSum(d *decode.D) uint64 { var s uint64 for { b := d.U8() s += b if b < 0xff { break } } return s } func avcSEIDecode(d *decode.D, in interface{}) interface{} { payloadType := d.FieldUFn("payload_type", func(d *decode.D) uint64 { return ffSum(d) }, d.MapUToStrSym(seiNames)) payloadSize := d.FieldUFn("payload_size", func(d *decode.D) uint64 { return ffSum(d) }) d.LenFn(int64(payloadSize)*8, func(d *decode.D) { switch payloadType { case avcSEIUserDataUnregistered: d.FieldRawLen("uuid", 16*8, d.MapRawToScalar(userDataUnregisteredNames)) } d.FieldRawLen("data", d.BitsLeft()) }) d.FieldRawLen("rbsp_trailing_bits", d.BitsLeft()) return nil }