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"
|
2020-06-08 03:29:51 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
registry.MustRegister(&decode.Format{
|
|
|
|
Name: format.AVC_SEI,
|
|
|
|
Description: "H.264/AVC Supplemental Enhancement Information",
|
|
|
|
DecodeFn: avcSEIDecode,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
avcSEIUserDataUnregistered = 5
|
|
|
|
)
|
|
|
|
|
|
|
|
var seiNames = map[uint64]string{
|
|
|
|
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 userDataUnregisteredNames = map[[16]byte]string{
|
|
|
|
{0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef}: "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.FieldStringMapFn("payload_type", seiNames, "Unknown", func() uint64 { return ffSum(d) }, decode.NumberDecimal)
|
|
|
|
payloadSize := d.FieldUFn("payload_size", func() (uint64, decode.DisplayFormat, string) {
|
|
|
|
return ffSum(d), decode.NumberDecimal, ""
|
|
|
|
})
|
|
|
|
|
|
|
|
d.DecodeLenFn(int64(payloadSize)*8, func(d *decode.D) {
|
|
|
|
switch payloadType {
|
|
|
|
case avcSEIUserDataUnregistered:
|
|
|
|
d.FieldStringUUIDMapFn("uuid", userDataUnregisteredNames, "Unknown", func() []byte { return d.BytesLen(16) })
|
|
|
|
d.FieldBytesLen("data", int(d.BitsLeft()/8))
|
|
|
|
default:
|
|
|
|
d.FieldBitBufLen("data", d.BitsLeft())
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
d.FieldBitBufLen("rbsp_trailing_bits", d.BitsLeft())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|