Files
monibuca/pkg/codec/video.go
2024-11-12 10:19:55 +08:00

277 lines
5.7 KiB
Go

package codec
import (
"bytes"
"encoding/binary"
"m7s.live/v5/pkg/util"
)
type FourCC [4]byte
var (
FourCC_H264 = FourCC{'a', 'v', 'c', '1'}
FourCC_H265 = FourCC{'h', 'v', 'c', '1'}
FourCC_AV1 = FourCC{'a', 'v', '0', '1'}
FourCC_VP9 = FourCC{'v', 'p', '0', '9'}
FourCC_VP8 = FourCC{'v', 'p', '8', '0'}
FourCC_MP4A = FourCC{'m', 'p', '4', 'a'}
FourCC_OPUS = FourCC{'O', 'p', 'u', 's'}
FourCC_ALAW = FourCC{'a', 'l', 'a', 'w'}
FourCC_ULAW = FourCC{'u', 'l', 'a', 'w'}
)
func ParseFourCC(s string) (f FourCC) {
copy(f[:], s)
return f
}
func (f FourCC) String() string {
return string(f[:])
}
func (f FourCC) Name() string {
switch f {
case FourCC_H264:
return "H264"
case FourCC_H265:
return "H265"
case FourCC_AV1:
return "AV1"
case FourCC_VP9:
return "VP9"
case FourCC_VP8:
return "VP8"
case FourCC_MP4A:
return "AAC"
case FourCC_OPUS:
return "OPUS"
case FourCC_ALAW:
return "PCMA"
case FourCC_ULAW:
return "PCMU"
}
return ""
}
func (f FourCC) Uint32() uint32 {
return binary.BigEndian.Uint32(f[:])
}
func (f FourCC) FourCC() FourCC {
return f
}
func (f FourCC) Is(fourcc FourCC) bool {
return f == fourcc
}
type SPSInfo struct {
ConstraintSetFlag uint
ProfileIdc uint
LevelIdc uint
MbWidth uint
MbHeight uint
CropLeft uint
CropRight uint
CropTop uint
CropBottom uint
Width uint
Height uint
}
func (info *SPSInfo) Unmarshal(data []byte) (err error) {
r := &util.GolombBitReader{R: bytes.NewReader(data)}
if _, err = r.ReadBits(8); err != nil {
return
}
if info.ProfileIdc, err = r.ReadBits(8); err != nil {
return
}
// constraint_set0_flag-constraint_set6_flag,reserved_zero_2bits
if info.ConstraintSetFlag, err = r.ReadBits(8); err != nil {
return
}
// level_idc
if info.LevelIdc, err = r.ReadBits(8); err != nil {
return
}
// seq_parameter_set_id
if _, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if info.ProfileIdc == 100 || info.ProfileIdc == 110 ||
info.ProfileIdc == 122 || info.ProfileIdc == 244 ||
info.ProfileIdc == 44 || info.ProfileIdc == 83 ||
info.ProfileIdc == 86 || info.ProfileIdc == 118 {
var chroma_format_idc uint
if chroma_format_idc, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if chroma_format_idc == 3 {
// residual_colour_transform_flag
if _, err = r.ReadBit(); err != nil {
return
}
}
// bit_depth_luma_minus8
if _, err = r.ReadExponentialGolombCode(); err != nil {
return
}
// bit_depth_chroma_minus8
if _, err = r.ReadExponentialGolombCode(); err != nil {
return
}
// qpprime_y_zero_transform_bypass_flag
if _, err = r.ReadBit(); err != nil {
return
}
var seq_scaling_matrix_present_flag uint
if seq_scaling_matrix_present_flag, err = r.ReadBit(); err != nil {
return
}
if seq_scaling_matrix_present_flag != 0 {
for i := 0; i < 8; i++ {
var seq_scaling_list_present_flag uint
if seq_scaling_list_present_flag, err = r.ReadBit(); err != nil {
return
}
if seq_scaling_list_present_flag != 0 {
var sizeOfScalingList uint
if i < 6 {
sizeOfScalingList = 16
} else {
sizeOfScalingList = 64
}
lastScale := uint(8)
nextScale := uint(8)
for j := uint(0); j < sizeOfScalingList; j++ {
if nextScale != 0 {
var delta_scale uint
if delta_scale, err = r.ReadSE(); err != nil {
return
}
nextScale = (lastScale + delta_scale + 256) % 256
}
if nextScale != 0 {
lastScale = nextScale
}
}
}
}
}
}
// log2_max_frame_num_minus4
if _, err = r.ReadExponentialGolombCode(); err != nil {
return
}
var pic_order_cnt_type uint
if pic_order_cnt_type, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if pic_order_cnt_type == 0 {
// log2_max_pic_order_cnt_lsb_minus4
if _, err = r.ReadExponentialGolombCode(); err != nil {
return
}
} else if pic_order_cnt_type == 1 {
// delta_pic_order_always_zero_flag
if _, err = r.ReadBit(); err != nil {
return
}
// offset_for_non_ref_pic
if _, err = r.ReadSE(); err != nil {
return
}
// offset_for_top_to_bottom_field
if _, err = r.ReadSE(); err != nil {
return
}
var num_ref_frames_in_pic_order_cnt_cycle uint
if num_ref_frames_in_pic_order_cnt_cycle, err = r.ReadExponentialGolombCode(); err != nil {
return
}
for i := uint(0); i < num_ref_frames_in_pic_order_cnt_cycle; i++ {
if _, err = r.ReadSE(); err != nil {
return
}
}
}
// max_num_ref_frames
if _, err = r.ReadExponentialGolombCode(); err != nil {
return
}
// gaps_in_frame_num_value_allowed_flag
if _, err = r.ReadBit(); err != nil {
return
}
if info.MbWidth, err = r.ReadExponentialGolombCode(); err != nil {
return
}
info.MbWidth++
if info.MbHeight, err = r.ReadExponentialGolombCode(); err != nil {
return
}
info.MbHeight++
var frame_mbs_only_flag uint
if frame_mbs_only_flag, err = r.ReadBit(); err != nil {
return
}
if frame_mbs_only_flag == 0 {
// mb_adaptive_frame_field_flag
if _, err = r.ReadBit(); err != nil {
return
}
}
// direct_8x8_inference_flag
if _, err = r.ReadBit(); err != nil {
return
}
var frame_cropping_flag uint
if frame_cropping_flag, err = r.ReadBit(); err != nil {
return
}
if frame_cropping_flag != 0 {
if info.CropLeft, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if info.CropRight, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if info.CropTop, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if info.CropBottom, err = r.ReadExponentialGolombCode(); err != nil {
return
}
}
info.Width = (info.MbWidth * 16) - info.CropLeft*2 - info.CropRight*2
info.Height = ((2 - frame_mbs_only_flag) * info.MbHeight * 16) - info.CropTop*2 - info.CropBottom*2
return
}