Files
go2rtc/pkg/h265/sps.go
T
Sergey Krashevich 2b7682cdb3 refactor(dvrip): simplify broadcast loop structure
- replace traditional for loop with range-based for loop for clarity

refactor(ffmpeg): simplify cut function loop
- utilize range-based for loop instead of traditional for loop

refactor(ring): update API response mapping type
- change map type from `interface{}` to `any` for better type safety

refactor(stream): handle nil source in NewStream
- add nil check for source elements before processing

refactor(webrtc): unify payload handling in GetToken
- change map type from `interface{}` to `any` for consistency

refactor(ascii): optimize nested loops in Write function
- replace traditional for loops with range-based for loops for readability

refactor(bits): enhance readability in Reader methods
- replace traditional for loops with range-based for loops in Read functions

refactor(h264): modernize loop structures in DecodeConfig
- switch to range-based for loops for cleaner code

refactor(h265): streamline profile_tier_level loops
- utilize range-based for loops instead of traditional for loops

chore(core): remove commented-out test function for clarity

refactor(core): simplify RandString function loop
- change traditional for loop to range-based for loop

refactor(flvt): optimize timestamp handling in TestTimeToRTP
- switch to range-based for loop for iterating frames

refactor(nest): improve error handling in ExchangeSDP
- format error message with printf-style formatting for clarity

refactor(tapo): enhance securityEncode function
- change traditional for loop to range-based for loop for readability

fix(tcp): correct masking in websocket Write method
- replace traditional for loop with range-based for loop

refactor(tutk): modernize encoding loops in crypto functions
- utilize range-based for loops for better readability

refactor(tuya): unify data types in MQTT message struct
- change map type from `interface{}` to `any` for consistency

refactor(webrtc): standardize codec registration
- change map type from `interface{}` to `any` for type safety

refactor(yaml): simplify Unmarshal function signature
- update parameter type from `interface{}` to `any` for better clarity
2026-03-10 23:26:45 +03:00

127 lines
3.0 KiB
Go

package h265
import (
"bytes"
"github.com/AlexxIT/go2rtc/pkg/bits"
)
// http://www.itu.int/rec/T-REC-H.265
//goland:noinspection GoSnakeCaseUsage
type SPS struct {
sps_video_parameter_set_id uint8
sps_max_sub_layers_minus1 uint8
sps_temporal_id_nesting_flag byte
general_profile_space uint8
general_tier_flag byte
general_profile_idc uint8
general_profile_compatibility_flags uint32
general_level_idc uint8
sub_layer_profile_present_flag []byte
sub_layer_level_present_flag []byte
sps_seq_parameter_set_id uint32
chroma_format_idc uint32
separate_colour_plane_flag byte
pic_width_in_luma_samples uint32
pic_height_in_luma_samples uint32
}
func (s *SPS) Width() uint16 {
return uint16(s.pic_width_in_luma_samples)
}
func (s *SPS) Height() uint16 {
return uint16(s.pic_height_in_luma_samples)
}
func DecodeSPS(nalu []byte) *SPS {
rbsp := bytes.ReplaceAll(nalu[2:], []byte{0, 0, 3}, []byte{0, 0})
r := bits.NewReader(rbsp)
s := &SPS{}
s.sps_video_parameter_set_id = r.ReadBits8(4)
s.sps_max_sub_layers_minus1 = r.ReadBits8(3)
s.sps_temporal_id_nesting_flag = r.ReadBit()
if !s.profile_tier_level(r) {
return nil
}
s.sps_seq_parameter_set_id = r.ReadUEGolomb()
s.chroma_format_idc = r.ReadUEGolomb()
if s.chroma_format_idc == 3 {
s.separate_colour_plane_flag = r.ReadBit()
}
s.pic_width_in_luma_samples = r.ReadUEGolomb()
s.pic_height_in_luma_samples = r.ReadUEGolomb()
//...
if r.EOF {
return nil
}
return s
}
// profile_tier_level supports ONLY general_profile_idc == 1
// over variants very complicated...
//
//goland:noinspection GoSnakeCaseUsage
func (s *SPS) profile_tier_level(r *bits.Reader) bool {
s.general_profile_space = r.ReadBits8(2)
s.general_tier_flag = r.ReadBit()
s.general_profile_idc = r.ReadBits8(5)
s.general_profile_compatibility_flags = r.ReadBits(32)
_ = r.ReadBits64(48) // other flags
if s.general_profile_idc != 1 {
return false
}
s.general_level_idc = r.ReadBits8(8)
s.sub_layer_profile_present_flag = make([]byte, s.sps_max_sub_layers_minus1)
s.sub_layer_level_present_flag = make([]byte, s.sps_max_sub_layers_minus1)
for i := range s.sps_max_sub_layers_minus1 {
s.sub_layer_profile_present_flag[i] = r.ReadBit()
s.sub_layer_level_present_flag[i] = r.ReadBit()
}
if s.sps_max_sub_layers_minus1 > 0 {
for i := s.sps_max_sub_layers_minus1; i < 8; i++ {
_ = r.ReadBits8(2) // reserved_zero_2bits
}
}
for i := range s.sps_max_sub_layers_minus1 {
if s.sub_layer_profile_present_flag[i] != 0 {
_ = r.ReadBits8(2) // sub_layer_profile_space
_ = r.ReadBit() // sub_layer_tier_flag
sub_layer_profile_idc := r.ReadBits8(5) // sub_layer_profile_idc
_ = r.ReadBits(32) // sub_layer_profile_compatibility_flag
_ = r.ReadBits64(48) // other flags
if sub_layer_profile_idc != 1 {
return false
}
}
if s.sub_layer_level_present_flag[i] != 0 {
_ = r.ReadBits8(8)
}
}
return true
}