update h264

This commit is contained in:
notch
2021-01-09 07:09:48 +08:00
parent 34998b2478
commit db8f2790f8
7 changed files with 230 additions and 390 deletions

View File

@@ -1,126 +0,0 @@
// Copyright (c) 2019,CAOHONGJU All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package h264
import (
bits "github.com/cnotch/bitutil"
)
func u8(r *bits.Reader, w int, target *uint8) (err error) {
*target, err = r.ReadUint8(w)
return
}
func u16(r *bits.Reader, w int, target *uint16) (err error) {
*target, err = r.ReadUint16(w)
return
}
func u32(r *bits.Reader, w int, target *uint32) (err error) {
*target, err = r.ReadUint32(w)
return
}
func flag(r *bits.Reader, target *uint8) (err error) {
*target, err = r.ReadBit()
return
}
func ue(r *bits.Reader) (res uint32, err error) {
i := 0
for {
var bit uint8
if bit, err = r.ReadBit(); err != nil {
return
}
if !(bit == 0 && i < 32) {
break
}
i++
}
if res, err = r.ReadUint32(i); err != nil {
return
}
res += (1 << uint(i)) - 1
return
}
func ue8(r *bits.Reader, target *uint8) error {
temp, err := ue(r)
*target = uint8(temp)
return err
}
func ue16(r *bits.Reader, target *uint16) error {
temp, err := ue(r)
*target = uint16(temp)
return err
}
func ue32(r *bits.Reader, target *uint32) (err error) {
*target, err = ue(r)
return
}
func se(r *bits.Reader) (res int32, err error) {
var ui32 uint32
if ui32, err = ue(r); err != nil {
return
}
res = int32(ui32)
if res&0x01 != 0 {
res = (res + 1) / 2
} else {
res = -res / 2
}
return
}
func se8(r *bits.Reader, target *int8) error {
temp, err := se(r)
*target = int8(temp)
return err
}
func se16(r *bits.Reader, target *int16) error {
temp, err := se(r)
*target = int16(temp)
return err
}
func se32(r *bits.Reader, target *int32) (err error) {
*target, err = se(r)
return
}
// copy from live555
// A general routine for making a copy of a (H.264 or H.265) NAL unit, removing 'emulation' bytes from the copy
func removeH264or5EmulationBytes(from []byte) []byte {
to := make([]byte, len(from))
toMaxSize := len(to)
fromSize := len(from)
toSize := 0
i := 0
for i < fromSize && toSize+1 < toMaxSize {
if i+2 < fromSize && from[i] == 0 && from[i+1] == 0 && from[i+2] == 3 {
to[toSize] = 0
to[toSize+1] = 0
toSize += 2
i += 3
} else {
to[toSize] = from[i]
toSize++
i++
}
}
// 如果剩余最后一个字节,拷贝它
if i < fromSize && toSize < toMaxSize {
to[toSize] = from[i]
toSize++
i++
}
return to[:toSize]
// return bytes.Replace(from, []byte{0, 0, 3}, []byte{0, 0}, -1)
}

View File

@@ -54,6 +54,34 @@ const (
NalTypeBitmask = 0x1F NalTypeBitmask = 0x1F
) )
// Profile
const (
ProfileConstrained = (1 << 9) // 8+1; constraint_set1_flag
ProfileIntra = (1 << 11) // 8+3; constraint_set3_flag
ProfileBaseline = 66
ProfileConstrainedBaseline = (66 | ProfileConstrained)
ProfileMain = 77
ProfileExtended = 88
ProfileHigh = 100
ProfileHigh10 = 110
ProfileHigh10Intra = (110 | ProfileIntra)
ProfileMultiViewHigh = 118
ProfileHigh422 = 122
ProfileHigh422Intra = (122 | ProfileIntra)
ProfileStereoHigh = 128
ProfileHigh444 = 144
ProfileHigh444Predictive = 244
ProfileHigh444Intra = (244 | ProfileIntra)
ProfileCAVLC444 = 44
)
// 参数集索引
const (
ParameterSetSps = iota
ParameterSetPps
)
// 其他常量 // 其他常量
const ( const (
// 7.4.2.1.1: seq_parameter_set_id is in [0, 31]. // 7.4.2.1.1: seq_parameter_set_id is in [0, 31].
@@ -97,28 +125,3 @@ const (
MaxWidth = MaxMbWidth * 16 MaxWidth = MaxMbWidth * 16
MaxHeight = MaxMbHeight * 16 MaxHeight = MaxMbHeight * 16
) )
// NulType .
func NulType(b byte) byte {
return b & NalTypeBitmask
}
// IsSps .
func IsSps(b byte) bool {
return b&NalTypeBitmask == NalSps
}
// IsPps .
func IsPps(b byte) bool {
return b&NalTypeBitmask == NalPps
}
// IsIdrSlice .
func IsIdrSlice(b byte) bool {
return b&NalTypeBitmask == NalIdrSlice
}
// IsFillerData .
func IsFillerData(b byte) bool {
return b&NalTypeBitmask == NalFillerData
}

54
av/codec/h264/shortcut.go Normal file
View File

@@ -0,0 +1,54 @@
// Copyright (c) 2019,CAOHONGJU All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package h264
import "github.com/cnotch/ipchub/av/codec"
// MetadataIsReady .
func MetadataIsReady(vm *codec.VideoMeta) bool {
sps := vm.Sps //ParameterSet(ParameterSetSps)
pps := vm.Pps //ParameterSet(ParameterSetPps)
if len(sps) == 0 || len(pps) == 0 {
return false
}
if vm.Width == 0 {
// decode
var rawsps RawSPS
if err := rawsps.Decode(sps); err != nil {
return false
}
vm.Width = rawsps.Width()
vm.Height = rawsps.Height()
vm.FixedFrameRate = rawsps.IsFixedFrameRate()
vm.FrameRate = rawsps.FrameRate()
}
return true
}
// NulType .
func NulType(nt byte) byte {
return nt & NalTypeBitmask
}
// IsSps .
func IsSps(nt byte) bool {
return nt&NalTypeBitmask == NalSps
}
// IsPps .
func IsPps(nt byte) bool {
return nt&NalTypeBitmask == NalPps
}
// IsIdrSlice .
func IsIdrSlice(nt byte) bool {
return nt&NalTypeBitmask == NalIdrSlice
}
// IsFillerData .
func IsFillerData(nt byte) bool {
return nt&NalTypeBitmask == NalFillerData
}

View File

@@ -1,15 +1,19 @@
// Copyright (c) 2019,CAOHONGJU All rights reserved. // Copyright (c) 2019,CAOHONGJU All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//
// Translate from FFmpeg cbs_h264.h cbs_h264_syntax_template.c
//
package h264 package h264
import ( import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"runtime/debug"
bits "github.com/cnotch/bitutil" "github.com/cnotch/ipchub/utils"
"github.com/cnotch/ipchub/utils/bits"
) )
// RawNALUnitHeader 原始 h264 Nal单元头 // RawNALUnitHeader 原始 h264 Nal单元头
@@ -220,13 +224,13 @@ type RawSPS struct {
Vui RawVUI Vui RawVUI
} }
// Width Video Width // Width 视频宽度(像素)
func (sps *RawSPS) Width() int { func (sps *RawSPS) Width() int {
w := (sps.PicWidthInMbsMinus1+1)*16 - sps.FrameCropLeftOffset*2 - sps.FrameCropRightOffset*2 w := (sps.PicWidthInMbsMinus1+1)*16 - sps.FrameCropLeftOffset*2 - sps.FrameCropRightOffset*2
return int(w) return int(w)
} }
// Height Video Height // Height 视频高度(像素)
func (sps *RawSPS) Height() int { func (sps *RawSPS) Height() int {
h := (2-uint16(sps.FrameMbsOnlyFlag))*(sps.PicHeightInMapUnitsMinus1+1)*16 - sps.FrameCropTopOffset*2 - sps.FrameCropBottomOffset*2 h := (2-uint16(sps.FrameMbsOnlyFlag))*(sps.PicHeightInMapUnitsMinus1+1)*16 - sps.FrameCropTopOffset*2 - sps.FrameCropBottomOffset*2
return int(h) return int(h)
@@ -256,7 +260,13 @@ func (sps *RawSPS) DecodeString(b64 string) error {
// Decode 从字节序列中解码 sps NAL // Decode 从字节序列中解码 sps NAL
func (sps *RawSPS) Decode(data []byte) (err error) { func (sps *RawSPS) Decode(data []byte) (err error) {
spsWEB := removeH264or5EmulationBytes(data) defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("RawSPS decode panicr = %v \n %s", r, debug.Stack())
}
}()
spsWEB := utils.RemoveH264or5EmulationBytes(data)
if len(spsWEB) < 4 { if len(spsWEB) < 4 {
return errors.New("The data is not enough") return errors.New("The data is not enough")
} }
@@ -271,56 +281,41 @@ func (sps *RawSPS) Decode(data []byte) (err error) {
} }
// 前三个字节 // 前三个字节
sps.ProfileIdc, _ = r.ReadUint8(8) sps.ProfileIdc = r.ReadUint8(8)
sps.ConstraintSet0Flag, _ = r.ReadBit() sps.ConstraintSet0Flag = r.ReadBit()
sps.ConstraintSet1Flag, _ = r.ReadBit() sps.ConstraintSet1Flag = r.ReadBit()
sps.ConstraintSet2Flag, _ = r.ReadBit() sps.ConstraintSet2Flag = r.ReadBit()
sps.ConstraintSet3Flag, _ = r.ReadBit() sps.ConstraintSet3Flag = r.ReadBit()
sps.ConstraintSet4Flag, _ = r.ReadBit() sps.ConstraintSet4Flag = r.ReadBit()
sps.ConstraintSet5Flag, _ = r.ReadBit() sps.ConstraintSet5Flag = r.ReadBit()
sps.ReservedZero2Bits, _ = r.ReadUint8(2) sps.ReservedZero2Bits = r.ReadUint8(2)
sps.LevelIdc, _ = r.ReadUint8(8) sps.LevelIdc = r.ReadUint8(8)
// seq_parameter_set_id // seq_parameter_set_id
if err = ue8(r, &sps.SeqParameterSetID); err != nil { sps.SeqParameterSetID = r.ReadUe8()
return
}
if sps.ProfileIdc == 100 || sps.ProfileIdc == 110 || if sps.ProfileIdc == 100 || sps.ProfileIdc == 110 ||
sps.ProfileIdc == 122 || sps.ProfileIdc == 244 || sps.ProfileIdc == 122 || sps.ProfileIdc == 244 ||
sps.ProfileIdc == 44 || sps.ProfileIdc == 83 || sps.ProfileIdc == 44 || sps.ProfileIdc == 83 ||
sps.ProfileIdc == 86 || sps.ProfileIdc == 118 { sps.ProfileIdc == 86 || sps.ProfileIdc == 118 {
sps.ChromaFormatIdc = r.ReadUe8()
if err = ue8(r, &sps.ChromaFormatIdc); err != nil {
return
}
if sps.ChromaFormatIdc == 3 { if sps.ChromaFormatIdc == 3 {
// separate_colour_plane_flag // separate_colour_plane_flag
if sps.SeparateColourPlaneFlag, err = r.ReadBit(); err != nil { sps.SeparateColourPlaneFlag = r.ReadBit()
return
}
} else { } else {
sps.SeparateColourPlaneFlag = 0 sps.SeparateColourPlaneFlag = 0
} }
if err = ue8(r, &sps.BitDepthLumaMinus8); err != nil { sps.BitDepthLumaMinus8 = r.ReadUe8()
return sps.BitDepthChromaMinus8 = r.ReadUe8()
}
if err = ue8(r, &sps.BitDepthChromaMinus8); err != nil {
return
}
// qpprime_y_zero_transform_bypass_flag // qpprime_y_zero_transform_bypass_flag
if sps.QpprimeYZeroTransformBypassFlag, err = r.ReadBit(); err != nil { sps.QpprimeYZeroTransformBypassFlag = r.ReadBit()
return
}
if sps.SeqScalingMatrixPresentFlag, err = r.ReadBit(); err != nil { sps.SeqScalingMatrixPresentFlag = r.ReadBit()
return
}
if sps.SeqScalingMatrixPresentFlag != 0 { if sps.SeqScalingMatrixPresentFlag != 0 {
maxI := 8 maxI := 8
@@ -329,9 +324,7 @@ func (sps *RawSPS) Decode(data []byte) (err error) {
} }
for i := 0; i < maxI; i++ { for i := 0; i < maxI; i++ {
if sps.SeqScalingListPresentFlag[i], err = r.ReadBit(); err != nil { sps.SeqScalingListPresentFlag[i] = r.ReadBit()
return
}
if sps.SeqScalingListPresentFlag[i] != 0 { if sps.SeqScalingListPresentFlag[i] != 0 {
sps.scanList(r, i) sps.scanList(r, i)
} }
@@ -350,109 +343,70 @@ func (sps *RawSPS) Decode(data []byte) (err error) {
} }
// log2_max_frame_num_minus4 // log2_max_frame_num_minus4
if err = ue8(r, &sps.Log2MaxFrameNumMinus4); err != nil { sps.Log2MaxFrameNumMinus4 = r.ReadUe8()
return
}
// pic_order_cnt_type // pic_order_cnt_type
if err = ue8(r, &sps.PicOrderCntType); err != nil { sps.PicOrderCntType = r.ReadUe8()
return
}
if sps.PicOrderCntType == 0 { if sps.PicOrderCntType == 0 {
// log2_max_pic_order_cnt_lsb_minus4 // log2_max_pic_order_cnt_lsb_minus4
if err = ue8(r, &sps.Log2MaxPicOrderCntLsbMinus4); err != nil { sps.Log2MaxPicOrderCntLsbMinus4 = r.ReadUe8()
return
}
} else if sps.PicOrderCntType == 1 { } else if sps.PicOrderCntType == 1 {
// delta_pic_order_always_zero_flag // delta_pic_order_always_zero_flag
if sps.DeltaPicOrderAlwaysZeroFlag, err = r.ReadBit(); err != nil { sps.DeltaPicOrderAlwaysZeroFlag = r.ReadBit()
return
}
// offset_for_non_ref_pic // offset_for_non_ref_pic
if err = se32(r, &sps.OffsetForNonRefPic); err != nil { sps.OffsetForNonRefPic = r.ReadSe()
return
}
// offset_for_top_to_bottom_field // offset_for_top_to_bottom_field
if err = se32(r, &sps.OffsetForTopToBottomField); err != nil { sps.OffsetForTopToBottomField = r.ReadSe()
return
}
// num_ref_frames_in_pic_order_cnt_cycle // num_ref_frames_in_pic_order_cnt_cycle
if err = ue8(r, &sps.NumRefFramesInPicOrderCntCycle); err != nil { sps.NumRefFramesInPicOrderCntCycle = r.ReadUe8()
return
}
for i := uint8(0); i < sps.NumRefFramesInPicOrderCntCycle; i++ { for i := uint8(0); i < sps.NumRefFramesInPicOrderCntCycle; i++ {
// offset_for_ref_frame // offset_for_ref_frame
if err = se32(r, &sps.OffsetForRefFrame[i]); err != nil { sps.OffsetForRefFrame[i] = r.ReadSe()
return
}
} }
} }
// max_num_ref_frames // max_num_ref_frames
if err = ue8(r, &sps.MaxNumRefFrames); err != nil { sps.MaxNumRefFrames = r.ReadUe8()
return
}
// gaps_in_frame_num_allowed_flag // gaps_in_frame_num_allowed_flag
if sps.GapsInFrameNumAllowedFlag, err = r.ReadBit(); err != nil { sps.GapsInFrameNumAllowedFlag = r.ReadBit()
return
}
// pic_width_in_mbs_minus1 // pic_width_in_mbs_minus1
if err = ue16(r, &sps.PicWidthInMbsMinus1); err != nil { sps.PicWidthInMbsMinus1 = r.ReadUe16()
return
}
// pic_height_in_map_units_minus1 // pic_height_in_map_units_minus1
if err = ue16(r, &sps.PicHeightInMapUnitsMinus1); err != nil { sps.PicHeightInMapUnitsMinus1 = r.ReadUe16()
return
}
// frame_mbs_only_flag // frame_mbs_only_flag
if sps.FrameMbsOnlyFlag, err = r.ReadBit(); err != nil { sps.FrameMbsOnlyFlag = r.ReadBit()
return
}
if sps.FrameMbsOnlyFlag == 0 { if sps.FrameMbsOnlyFlag == 0 {
// mb_adaptive_frame_field_flag // mb_adaptive_frame_field_flag
if sps.MbAdaptiveFrameFieldFlag, err = r.ReadBit(); err != nil { sps.MbAdaptiveFrameFieldFlag = r.ReadBit()
return
}
} }
// direct_8x8_inference_flag // direct_8x8_inference_flag
if sps.Direct8x8InferenceFlag, err = r.ReadBit(); err != nil { sps.Direct8x8InferenceFlag = r.ReadBit()
return
}
// frame_cropping_flag // frame_cropping_flag
if sps.FrameCroppingFlag, err = r.ReadBit(); err != nil { sps.FrameCroppingFlag = r.ReadBit()
return
}
if sps.FrameCroppingFlag == 1 { if sps.FrameCroppingFlag == 1 {
// frame_crop_left_offset // frame_crop_left_offset
if err = ue16(r, &sps.FrameCropLeftOffset); err != nil { sps.FrameCropLeftOffset = r.ReadUe16()
return
}
// frame_crop_right_offset // frame_crop_right_offset
if err = ue16(r, &sps.FrameCropRightOffset); err != nil { sps.FrameCropRightOffset = r.ReadUe16()
return
}
// frame_crop_top_offset // frame_crop_top_offset
if err = ue16(r, &sps.FrameCropTopOffset); err != nil { sps.FrameCropTopOffset = r.ReadUe16()
return // frame_crop_bottom_offset
} // frame_crop_bottom_offset sps.FrameCropBottomOffset = r.ReadUe16()
if err = ue16(r, &sps.FrameCropBottomOffset); err != nil {
return
}
} }
// vui_parameters_present_flag // vui_parameters_present_flag
if sps.VuiParametersPresentFlag, err = r.ReadBit(); err != nil { sps.VuiParametersPresentFlag = r.ReadBit()
return
}
// vui parameters // vui parameters
if sps.VuiParametersPresentFlag == 1 { if sps.VuiParametersPresentFlag == 1 {
@@ -479,9 +433,7 @@ func (sps *RawSPS) scanList(r *bits.Reader, i int) (err error) {
scale := 8 scale := 8
for i = 0; i < sizeOfScan; i++ { for i = 0; i < sizeOfScan; i++ {
if err = se8(r, &current[i]); err != nil { current[i] = r.ReadSe8()
return
}
scale = (scale + int(current[i]) + 256) % 256 scale = (scale + int(current[i]) + 256) % 256
if scale == 0 { if scale == 0 {
break break
@@ -492,9 +444,9 @@ func (sps *RawSPS) scanList(r *bits.Reader, i int) (err error) {
} }
func (h *RawNALUnitHeader) decode(r *bits.Reader) (err error) { func (h *RawNALUnitHeader) decode(r *bits.Reader) (err error) {
h.ForbiddenZeroBit, _ = r.ReadBit() h.ForbiddenZeroBit = r.ReadBit()
h.NalRefIdc, _ = r.ReadUint8(2) h.NalRefIdc = r.ReadUint8(2)
h.NalUnitType, _ = r.ReadUint8(5) h.NalUnitType = r.ReadUint8(5)
if h.NalUnitType == NalPrefix || if h.NalUnitType == NalPrefix ||
h.NalUnitType == NalExtenSlice || h.NalUnitType == NalExtenSlice ||
@@ -505,58 +457,31 @@ func (h *RawNALUnitHeader) decode(r *bits.Reader) (err error) {
} }
func (vui *RawVUI) decode(r *bits.Reader, sps *RawSPS) (err error) { func (vui *RawVUI) decode(r *bits.Reader, sps *RawSPS) (err error) {
if err = flag(r, &vui.AspectRatioInfoPresentFlag); err != nil { vui.AspectRatioInfoPresentFlag = r.ReadBit()
return
}
if vui.AspectRatioInfoPresentFlag == 1 { if vui.AspectRatioInfoPresentFlag == 1 {
if err = u8(r, 8, &vui.AspectRatioIdc); err != nil { vui.AspectRatioIdc = r.ReadUint8(8)
return
}
if vui.AspectRatioIdc == 255 { if vui.AspectRatioIdc == 255 {
if err = u16(r, 16, &vui.SarWidth); err != nil { vui.SarWidth = r.ReadUint16(16)
return vui.SarHeight = r.ReadUint16(16)
}
if err = u16(r, 16, &vui.SarHeight); err != nil {
return
}
} }
} else { } else {
vui.AspectRatioIdc = 0 vui.AspectRatioIdc = 0
} }
if err = flag(r, &vui.OverscanInfoPresentFlag); err != nil { vui.OverscanInfoPresentFlag = r.ReadBit()
return
}
if vui.OverscanInfoPresentFlag == 1 { if vui.OverscanInfoPresentFlag == 1 {
if err = flag(r, &vui.OverscanAppropriateFlag); err != nil { vui.OverscanAppropriateFlag = r.ReadBit()
return
}
} }
if err = flag(r, &vui.VideoSignalTypePresentFlag); err != nil { vui.VideoSignalTypePresentFlag = r.ReadBit()
return
}
if vui.VideoSignalTypePresentFlag == 1 { if vui.VideoSignalTypePresentFlag == 1 {
if err = u8(r, 3, &vui.VideoFormat); err != nil { vui.VideoFormat = r.ReadUint8(3)
return vui.VideoFullRangeFlag = r.ReadBit()
} vui.ColourDescriptionPresentFlag = r.ReadBit()
if err = flag(r, &vui.VideoFullRangeFlag); err != nil {
return
}
if err = flag(r, &vui.ColourDescriptionPresentFlag); err != nil {
return
}
if vui.ColourDescriptionPresentFlag == 1 { if vui.ColourDescriptionPresentFlag == 1 {
if err = u8(r, 8, &vui.ColourPrimaries); err != nil { vui.ColourPrimaries = r.ReadUint8(8)
return vui.TransferCharacteristics = r.ReadUint8(8)
} vui.MatrixCoefficients = r.ReadUint8(8)
if err = u8(r, 8, &vui.TransferCharacteristics); err != nil {
return
}
if err = u8(r, 8, &vui.MatrixCoefficients); err != nil {
return
}
} }
} else { } else {
vui.VideoFormat = 5 vui.VideoFormat = 5
@@ -566,50 +491,32 @@ func (vui *RawVUI) decode(r *bits.Reader, sps *RawSPS) (err error) {
vui.MatrixCoefficients = 2 vui.MatrixCoefficients = 2
} }
if err = flag(r, &vui.ChromaLocInfoPresentFlag); err != nil { vui.ChromaLocInfoPresentFlag = r.ReadBit()
return
}
if vui.ChromaLocInfoPresentFlag == 1 { if vui.ChromaLocInfoPresentFlag == 1 {
if err = ue8(r, &vui.ChromaSampleLocTypeTopField); err != nil { vui.ChromaSampleLocTypeTopField = r.ReadUe8()
return vui.ChromaSampleLocTypeBottomField = r.ReadUe8()
}
if err = ue8(r, &vui.ChromaSampleLocTypeBottomField); err != nil {
return
}
} else { } else {
vui.ChromaSampleLocTypeTopField = 0 vui.ChromaSampleLocTypeTopField = 0
vui.ChromaSampleLocTypeBottomField = 0 vui.ChromaSampleLocTypeBottomField = 0
} }
if err = flag(r, &vui.TimingInfoPresentFlag); err != nil { vui.TimingInfoPresentFlag = r.ReadBit()
return
}
if vui.TimingInfoPresentFlag == 1 { if vui.TimingInfoPresentFlag == 1 {
if err = u32(r, 32, &vui.NumUnitsInTick); err != nil { vui.NumUnitsInTick = r.ReadUint32(32)
return vui.TimeScale = r.ReadUint32(32)
} vui.FixedFrameRateFlag = r.ReadBit()
if err = u32(r, 32, &vui.TimeScale); err != nil {
return
}
if err = flag(r, &vui.FixedFrameRateFlag); err != nil {
return
}
} else { } else {
vui.FixedFrameRateFlag = 0 vui.FixedFrameRateFlag = 0
} }
if err = flag(r, &vui.NalHrdParametersPresentFlag); err != nil { vui.NalHrdParametersPresentFlag = r.ReadBit()
return
}
if vui.NalHrdParametersPresentFlag == 1 { if vui.NalHrdParametersPresentFlag == 1 {
if err = vui.NalHrdParameters.decode(r); err != nil { if err = vui.NalHrdParameters.decode(r); err != nil {
return return
} }
} }
if err = flag(r, &vui.VclHrdParametersPresentFlag); err != nil { vui.VclHrdParametersPresentFlag = r.ReadBit()
return
}
if vui.VclHrdParametersPresentFlag == 1 { if vui.VclHrdParametersPresentFlag == 1 {
if err = vui.VclHrdParameters.decode(r); err != nil { if err = vui.VclHrdParameters.decode(r); err != nil {
return return
@@ -618,44 +525,24 @@ func (vui *RawVUI) decode(r *bits.Reader, sps *RawSPS) (err error) {
if vui.NalHrdParametersPresentFlag == 1 || if vui.NalHrdParametersPresentFlag == 1 ||
vui.VclHrdParametersPresentFlag == 1 { vui.VclHrdParametersPresentFlag == 1 {
if err = flag(r, &vui.LowDelayHrdFlag); err != nil { vui.LowDelayHrdFlag = r.ReadBit()
return
}
} else { } else {
vui.LowDelayHrdFlag = 1 - vui.FixedFrameRateFlag vui.LowDelayHrdFlag = 1 - vui.FixedFrameRateFlag
} }
if err = flag(r, &vui.PicStructPresentFlag); err != nil { vui.PicStructPresentFlag = r.ReadBit()
return
}
if err = flag(r, &vui.BitstreamRestrictionFlag); err != nil { vui.BitstreamRestrictionFlag = r.ReadBit()
return
}
if vui.BitstreamRestrictionFlag == 1 { if vui.BitstreamRestrictionFlag == 1 {
if err = flag(r, &vui.MotionVectorsOverPicBoundariesFlag); err != nil { vui.MotionVectorsOverPicBoundariesFlag = r.ReadBit()
return vui.MaxBytesPerPicDenom = r.ReadUe8()
} vui.MaxBitsPerMbDenom = r.ReadUe8()
if err = ue8(r, &vui.MaxBytesPerPicDenom); err != nil {
return
}
if err = ue8(r, &vui.MaxBitsPerMbDenom); err != nil {
return
}
// The current version of the standard constrains this to be in // The current version of the standard constrains this to be in
// [0,15], but older versions allow 16. // [0,15], but older versions allow 16.
if err = ue8(r, &vui.Log2MaxMvLengthHorizontal); err != nil { vui.Log2MaxMvLengthHorizontal = r.ReadUe8()
return vui.Log2MaxMvLengthVertical = r.ReadUe8()
} vui.MaxNumReorderFrames = r.ReadUe8()
if err = ue8(r, &vui.Log2MaxMvLengthVertical); err != nil { vui.MaxDecFrameBuffering = r.ReadUe8()
return
}
if err = ue8(r, &vui.MaxNumReorderFrames); err != nil {
return
}
if err = ue8(r, &vui.MaxDecFrameBuffering); err != nil {
return
}
} else { } else {
vui.MotionVectorsOverPicBoundariesFlag = 1 vui.MotionVectorsOverPicBoundariesFlag = 1
vui.MaxBytesPerPicDenom = 2 vui.MaxBytesPerPicDenom = 2
@@ -716,40 +603,19 @@ func (vui *RawVUI) parametersDefault(sps *RawSPS) (err error) {
} }
func (hrd *RawHRD) decode(r *bits.Reader) (err error) { func (hrd *RawHRD) decode(r *bits.Reader) (err error) {
if err = ue8(r, &hrd.CpbCntMinus1); err != nil { hrd.CpbCntMinus1 = r.ReadUe8()
return hrd.BitRateScale = r.ReadUint8(4)
} hrd.CpbSizeScale = r.ReadUint8(4)
if err = u8(r, 4, &hrd.BitRateScale); err != nil {
return
}
if err = u8(r, 4, &hrd.CpbSizeScale); err != nil {
return
}
for i := 0; i <= int(hrd.CpbCntMinus1); i++ { for i := 0; i <= int(hrd.CpbCntMinus1); i++ {
if err = ue32(r, &hrd.BitRateValueMinus1[i]); err != nil { hrd.BitRateValueMinus1[i] = r.ReadUe()
return hrd.CpbSizeValueMinus1[i] = r.ReadUe()
} hrd.CbrFlag[i] = r.ReadBit()
if err = ue32(r, &hrd.CpbSizeValueMinus1[i]); err != nil {
return
}
if err = flag(r, &hrd.CbrFlag[i]); err != nil {
return
}
}
if err = u8(r, 5, &hrd.InitialCpbRemovalDelayLengthMinus1); err != nil {
return
}
if err = u8(r, 5, &hrd.CpbRemovalDelayLengthMinus1); err != nil {
return
}
if err = u8(r, 5, &hrd.DpbOutputDelayLengthMinus1); err != nil {
return
}
if err = u8(r, 5, &hrd.TimeOffsetLength); err != nil {
return
} }
hrd.InitialCpbRemovalDelayLengthMinus1 = r.ReadUint8(5)
hrd.CpbRemovalDelayLengthMinus1 = r.ReadUint8(5)
hrd.DpbOutputDelayLengthMinus1 = r.ReadUint8(5)
hrd.TimeOffsetLength = r.ReadUint8(5)
return return
} }

View File

@@ -16,6 +16,12 @@ type VideoMeta struct {
Sps []byte `json:"-"` Sps []byte `json:"-"`
Pps []byte `json:"-"` Pps []byte `json:"-"`
Vps []byte `json:"-"` Vps []byte `json:"-"`
// // 媒体的参数集,如 sdp中的 sprop_xxx
// parameterSets `json:"-"`
// // 不同封装和传输方式的特别参数
// // 比如 RTP 封装: streamid, packetization-mode, profile-level-id 等
// specificParams `json:"-"`
} }
// AudioMeta 音频元数据 // AudioMeta 音频元数据
@@ -26,4 +32,44 @@ type AudioMeta struct {
Channels int `json:"channels,omitempty"` Channels int `json:"channels,omitempty"`
DataRate float64 `json:"datarate,omitempty"` DataRate float64 `json:"datarate,omitempty"`
Sps []byte `json:"-"` // sps Sps []byte `json:"-"` // sps
// // 媒体的参数集,如 sdp中的 sprop_xxx
// parameterSets `json:"-"`
// // 不同封装和传输方式的特别参数
// // 比如 RTP 封装: streamid, mode, profile-level-id,sizelength, indexlength,indexdeltalength 等
// specificParams `json:"-"`
}
type parameterSets [][]byte
func (pss *parameterSets) ParameterSet(idx int) []byte {
if len(*pss) <= idx {
return nil
}
return (*pss)[idx]
}
func (pss *parameterSets) SetParameterSet(idx int, paramSet []byte) {
if len(*pss) <= idx {
temp := make(parameterSets, idx+1)
copy(temp, *pss)
*pss = temp
}
(*pss)[idx] = paramSet
}
type specificParams map[string]string
func (params *specificParams) SpecificParam(name string) (value string, ok bool) {
if params == nil {
return
}
value, ok = (*params)[name]
return
}
func (params *specificParams) SetSpecificParam(name, value string) {
if params == nil {
*params = make(specificParams)
}
(*params)[name] = value
} }

1
go.mod
View File

@@ -5,7 +5,6 @@ go 1.14
require ( require (
github.com/BurntSushi/toml v0.3.1 // indirect github.com/BurntSushi/toml v0.3.1 // indirect
github.com/cnotch/apirouter v0.0.0-20200731232942-89e243a791f3 github.com/cnotch/apirouter v0.0.0-20200731232942-89e243a791f3
github.com/cnotch/bitutil v0.0.0-20200512012328-08db448fb960
github.com/cnotch/loader v0.0.0-20200405015128-d9d964d09439 github.com/cnotch/loader v0.0.0-20200405015128-d9d964d09439
github.com/cnotch/queue v0.0.0-20201224060551-4191569ce8f6 github.com/cnotch/queue v0.0.0-20201224060551-4191569ce8f6
github.com/cnotch/scheduler v0.0.0-20200522024700-1d2da93eefc5 github.com/cnotch/scheduler v0.0.0-20200522024700-1d2da93eefc5

2
go.sum
View File

@@ -2,8 +2,6 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cnotch/apirouter v0.0.0-20200731232942-89e243a791f3 h1:Y8fe6nOk/UMsVZOPPLEVd9axxbIuBBjhZ+g6RpMz6vI= github.com/cnotch/apirouter v0.0.0-20200731232942-89e243a791f3 h1:Y8fe6nOk/UMsVZOPPLEVd9axxbIuBBjhZ+g6RpMz6vI=
github.com/cnotch/apirouter v0.0.0-20200731232942-89e243a791f3/go.mod h1:5deJPLON/x/s2dLOQfuKS0lenhOIT4xX0pvtN/OEIuY= github.com/cnotch/apirouter v0.0.0-20200731232942-89e243a791f3/go.mod h1:5deJPLON/x/s2dLOQfuKS0lenhOIT4xX0pvtN/OEIuY=
github.com/cnotch/bitutil v0.0.0-20200512012328-08db448fb960 h1:mZGYgYjlZOh+oMLvv3uxT61J0y8SWStIoOaqWU9S3Lk=
github.com/cnotch/bitutil v0.0.0-20200512012328-08db448fb960/go.mod h1:ivZKsbAhsndNi8A5NFiDkBUY3+lVINm+IXNUnQNn6JM=
github.com/cnotch/loader v0.0.0-20200405015128-d9d964d09439 h1:iNWyllf6zuby+nDNC6zKEkM7aUFbp4RccfWVdQ3HFfQ= github.com/cnotch/loader v0.0.0-20200405015128-d9d964d09439 h1:iNWyllf6zuby+nDNC6zKEkM7aUFbp4RccfWVdQ3HFfQ=
github.com/cnotch/loader v0.0.0-20200405015128-d9d964d09439/go.mod h1:oWpDagHB6p+Kqqq7RoRZKyC4XAXft50hR8pbTxdbYYs= github.com/cnotch/loader v0.0.0-20200405015128-d9d964d09439/go.mod h1:oWpDagHB6p+Kqqq7RoRZKyC4XAXft50hR8pbTxdbYYs=
github.com/cnotch/queue v0.0.0-20200326024423-6e88bdbf2ad4 h1:bU2h1mvmsh6V1gQDGKgA9lHfBMLCmaVs1t2xyloDYHY= github.com/cnotch/queue v0.0.0-20200326024423-6e88bdbf2ad4 h1:bU2h1mvmsh6V1gQDGKgA9lHfBMLCmaVs1t2xyloDYHY=