mirror of
https://github.com/wader/fq.git
synced 2024-11-25 23:13:19 +03:00
77 lines
2.4 KiB
Go
77 lines
2.4 KiB
Go
package mpeg
|
|
|
|
// https://www.itu.int/rec/T-REC-H.265
|
|
|
|
import (
|
|
"github.com/wader/fq/format"
|
|
"github.com/wader/fq/pkg/decode"
|
|
"github.com/wader/fq/pkg/interp"
|
|
)
|
|
|
|
func init() {
|
|
interp.RegisterFormat(
|
|
format.HEVC_VPS,
|
|
&decode.Format{
|
|
Description: "H.265/HEVC Video Parameter Set",
|
|
DecodeFn: hevcVPSDecode,
|
|
})
|
|
}
|
|
|
|
const maxVpsLayers = 1000
|
|
|
|
// H.265 page 33
|
|
func hevcVPSDecode(d *decode.D) any {
|
|
d.FieldU4("vps_video_parameter_set_id")
|
|
d.FieldBool("vps_base_layer_internal_flag")
|
|
d.FieldBool("vps_base_layer_available_flag")
|
|
d.FieldU6("vps_max_layers_minus1")
|
|
vpsMaxSubLayersMinus1 := d.FieldU3("vps_max_sub_layers_minus1")
|
|
d.FieldBool("vps_temporal_id_nesting_flag")
|
|
d.FieldU16("vps_reserved_0xffff_16bits")
|
|
profileTierLevelDecode(d, true, vpsMaxSubLayersMinus1)
|
|
vpsSubLayerOrderingInfoPresentFlag := d.FieldBool("vps_sub_layer_ordering_info_present_flag")
|
|
d.FieldArray("vps_sub_layer_ordering_infos", func(d *decode.D) {
|
|
i := vpsMaxSubLayersMinus1
|
|
if vpsSubLayerOrderingInfoPresentFlag {
|
|
i = 0
|
|
}
|
|
for ; i <= vpsMaxSubLayersMinus1; i++ {
|
|
d.FieldStruct("sps_sub_layer_ordering_info", func(d *decode.D) {
|
|
d.FieldUintFn("sps_max_dec_pic_buffering_minus1", uEV)
|
|
d.FieldUintFn("sps_max_num_reorder_pics", uEV)
|
|
d.FieldUintFn("sps_max_latency_increase_plus1", uEV)
|
|
})
|
|
}
|
|
})
|
|
vpsMaxLayerID := d.FieldU6("vps_max_layer_id")
|
|
vpsNumLayerSetsMinus1 := d.FieldUintFn("vps_num_layer_sets_minus1", uEV)
|
|
if vpsNumLayerSetsMinus1 > maxVpsLayers {
|
|
d.Errorf("too many vps layers %d > %d", vpsNumLayerSetsMinus1, maxVpsLayers)
|
|
}
|
|
d.FieldArray("layer_id_included_sets_flags", func(d *decode.D) {
|
|
for i := uint64(0); i <= vpsNumLayerSetsMinus1; i++ {
|
|
d.FieldArray("layer_id_included_sets_flags", func(d *decode.D) {
|
|
for j := uint64(0); j <= vpsMaxLayerID; j++ {
|
|
d.FieldBool("layer_id_included_flag_sets_flag")
|
|
}
|
|
})
|
|
}
|
|
})
|
|
vpsTimingInfoPresentFlag := d.FieldBool("vps_timing_info_present_flag")
|
|
if vpsTimingInfoPresentFlag {
|
|
d.FieldU32("vps_num_units_in_tick")
|
|
d.FieldU32("vps_time_scale")
|
|
vpsPocProportionalToTimingFlag := d.FieldBool("vps_poc_proportional_to_timing_flag")
|
|
if vpsPocProportionalToTimingFlag {
|
|
d.FieldUintFn("vps_num_ticks_poc_diff_one_minus1", uEV)
|
|
}
|
|
vpsHrdParametersPresentFlag := d.FieldBool("vps_hrd_parameters_present_flag")
|
|
if vpsHrdParametersPresentFlag {
|
|
hevcHrdParameters(d, true, vpsMaxSubLayersMinus1)
|
|
}
|
|
}
|
|
// TODO:
|
|
|
|
return nil
|
|
}
|