mirror of
https://github.com/aler9/gortsplib
synced 2025-10-07 08:01:14 +08:00
fix timestamp encode error after some hours (#206)
previous formula was: uint32(a + uint32(b)) this formula overflows two times, while it should overflow once. new formula is: uint32(uint64(a) + uint64(b))
This commit is contained in:
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/codecs/h264"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptimedec"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
// ErrMorePacketsNeeded is returned when more packets are needed.
|
||||
@@ -27,7 +27,7 @@ type Decoder struct {
|
||||
// indicates the packetization mode.
|
||||
PacketizationMode int
|
||||
|
||||
timeDecoder *rtptimedec.Decoder
|
||||
timeDecoder *rtptime.Decoder
|
||||
firstPacketReceived bool
|
||||
fragmentedSize int
|
||||
fragments [][]byte
|
||||
@@ -39,7 +39,7 @@ type Decoder struct {
|
||||
|
||||
// Init initializes the decoder.
|
||||
func (d *Decoder) Init() {
|
||||
d.timeDecoder = rtptimedec.New(rtpClockRate)
|
||||
d.timeDecoder = rtptime.NewDecoder(rtpClockRate)
|
||||
}
|
||||
|
||||
// Decode decodes NALUs from a RTP/H264 packet.
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/codecs/h264"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -44,6 +45,7 @@ type Encoder struct {
|
||||
PacketizationMode int
|
||||
|
||||
sequenceNumber uint16
|
||||
timeEncoder *rtptime.Encoder
|
||||
}
|
||||
|
||||
// Init initializes the encoder.
|
||||
@@ -65,10 +67,7 @@ func (e *Encoder) Init() {
|
||||
}
|
||||
|
||||
e.sequenceNumber = *e.InitialSequenceNumber
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTimestamp(ts time.Duration) uint32 {
|
||||
return *e.InitialTimestamp + uint32(ts.Seconds()*rtpClockRate)
|
||||
e.timeEncoder = rtptime.NewEncoder(rtpClockRate, *e.InitialTimestamp)
|
||||
}
|
||||
|
||||
// Encode encodes NALUs into RTP/H264 packets.
|
||||
@@ -131,7 +130,7 @@ func (e *Encoder) writeSingle(nalu []byte, pts time.Duration, marker bool) ([]*r
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: marker,
|
||||
},
|
||||
@@ -153,7 +152,7 @@ func (e *Encoder) writeFragmented(nalu []byte, pts time.Duration, marker bool) (
|
||||
}
|
||||
|
||||
ret := make([]*rtp.Packet, packetCount)
|
||||
encPTS := e.encodeTimestamp(pts)
|
||||
encPTS := e.timeEncoder.Encode(pts)
|
||||
|
||||
nri := (nalu[0] >> 5) & 0x03
|
||||
typ := nalu[0] & 0x1F
|
||||
@@ -238,7 +237,7 @@ func (e *Encoder) writeAggregated(nalus [][]byte, pts time.Duration, marker bool
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: marker,
|
||||
},
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/codecs/h265"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptimedec"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
// ErrMorePacketsNeeded is returned when more packets are needed.
|
||||
@@ -26,7 +26,7 @@ type Decoder struct {
|
||||
// indicates that NALUs have an additional field that specifies the decoding order.
|
||||
MaxDONDiff int
|
||||
|
||||
timeDecoder *rtptimedec.Decoder
|
||||
timeDecoder *rtptime.Decoder
|
||||
firstPacketReceived bool
|
||||
fragmentedSize int
|
||||
fragments [][]byte
|
||||
@@ -37,7 +37,7 @@ type Decoder struct {
|
||||
|
||||
// Init initializes the decoder.
|
||||
func (d *Decoder) Init() {
|
||||
d.timeDecoder = rtptimedec.New(rtpClockRate)
|
||||
d.timeDecoder = rtptime.NewDecoder(rtpClockRate)
|
||||
}
|
||||
|
||||
// Decode decodes NALUs from a RTP/H265 packet.
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -43,6 +45,7 @@ type Encoder struct {
|
||||
MaxDONDiff int
|
||||
|
||||
sequenceNumber uint16
|
||||
timeEncoder *rtptime.Encoder
|
||||
}
|
||||
|
||||
// Init initializes the encoder.
|
||||
@@ -64,10 +67,7 @@ func (e *Encoder) Init() {
|
||||
}
|
||||
|
||||
e.sequenceNumber = *e.InitialSequenceNumber
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTimestamp(ts time.Duration) uint32 {
|
||||
return *e.InitialTimestamp + uint32(ts.Seconds()*rtpClockRate)
|
||||
e.timeEncoder = rtptime.NewEncoder(rtpClockRate, *e.InitialTimestamp)
|
||||
}
|
||||
|
||||
// Encode encodes NALUs into RTP/H265 packets.
|
||||
@@ -130,7 +130,7 @@ func (e *Encoder) writeSingle(nalu []byte, pts time.Duration, marker bool) ([]*r
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: marker,
|
||||
},
|
||||
@@ -150,7 +150,7 @@ func (e *Encoder) writeFragmentationUnits(nalu []byte, pts time.Duration, marker
|
||||
}
|
||||
|
||||
ret := make([]*rtp.Packet, n)
|
||||
encPTS := e.encodeTimestamp(pts)
|
||||
encPTS := e.timeEncoder.Encode(pts)
|
||||
|
||||
head := nalu[:2]
|
||||
nalu = nalu[2:]
|
||||
@@ -234,7 +234,7 @@ func (e *Encoder) writeAggregationUnit(nalus [][]byte, pts time.Duration, marker
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: marker,
|
||||
},
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptimedec"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
// Decoder is a RTP/LPCM decoder.
|
||||
@@ -15,13 +15,13 @@ type Decoder struct {
|
||||
SampleRate int
|
||||
ChannelCount int
|
||||
|
||||
timeDecoder *rtptimedec.Decoder
|
||||
timeDecoder *rtptime.Decoder
|
||||
sampleSize int
|
||||
}
|
||||
|
||||
// Init initializes the decoder.
|
||||
func (d *Decoder) Init() {
|
||||
d.timeDecoder = rtptimedec.New(d.SampleRate)
|
||||
d.timeDecoder = rtptime.NewDecoder(d.SampleRate)
|
||||
d.sampleSize = d.BitDepth * d.ChannelCount / 8
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -44,6 +46,7 @@ type Encoder struct {
|
||||
ChannelCount int
|
||||
|
||||
sequenceNumber uint16
|
||||
timeEncoder *rtptime.Encoder
|
||||
sampleSize int
|
||||
maxPayloadSize int
|
||||
}
|
||||
@@ -67,14 +70,11 @@ func (e *Encoder) Init() {
|
||||
}
|
||||
|
||||
e.sequenceNumber = *e.InitialSequenceNumber
|
||||
e.timeEncoder = rtptime.NewEncoder(e.SampleRate, *e.InitialTimestamp)
|
||||
e.sampleSize = e.BitDepth * e.ChannelCount / 8
|
||||
e.maxPayloadSize = (e.PayloadMaxSize / e.sampleSize) * e.sampleSize
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTimestamp(ts time.Duration) uint32 {
|
||||
return *e.InitialTimestamp + uint32(ts.Seconds()*float64(e.SampleRate))
|
||||
}
|
||||
|
||||
// Encode encodes audio samples into RTP packets.
|
||||
func (e *Encoder) Encode(samples []byte, pts time.Duration) ([]*rtp.Packet, error) {
|
||||
slen := len(samples)
|
||||
@@ -102,7 +102,7 @@ func (e *Encoder) Encode(samples []byte, pts time.Duration) ([]*rtp.Packet, erro
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: false,
|
||||
},
|
||||
|
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/codecs/jpeg"
|
||||
"github.com/aler9/gortsplib/v2/pkg/formatdecenc/rtpmjpeg/headers"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptimedec"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
// ErrMorePacketsNeeded is returned when more packets are needed.
|
||||
@@ -96,7 +96,7 @@ var chmAcSymbols = []byte{ //nolint:dupl
|
||||
|
||||
// Decoder is a RTP/M-JPEG decoder.
|
||||
type Decoder struct {
|
||||
timeDecoder *rtptimedec.Decoder
|
||||
timeDecoder *rtptime.Decoder
|
||||
firstPacketReceived bool
|
||||
fragmentedSize int
|
||||
fragments [][]byte
|
||||
@@ -106,7 +106,7 @@ type Decoder struct {
|
||||
|
||||
// Init initializes the decoder.
|
||||
func (d *Decoder) Init() {
|
||||
d.timeDecoder = rtptimedec.New(rtpClockRate)
|
||||
d.timeDecoder = rtptime.NewDecoder(rtpClockRate)
|
||||
}
|
||||
|
||||
// Decode decodes an image from a RTP/M-JPEG packet.
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/codecs/jpeg"
|
||||
"github.com/aler9/gortsplib/v2/pkg/formatdecenc/rtpmjpeg/headers"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,6 +42,7 @@ type Encoder struct {
|
||||
PayloadMaxSize int
|
||||
|
||||
sequenceNumber uint16
|
||||
timeEncoder *rtptime.Encoder
|
||||
}
|
||||
|
||||
// Init initializes the encoder.
|
||||
@@ -62,10 +64,7 @@ func (e *Encoder) Init() {
|
||||
}
|
||||
|
||||
e.sequenceNumber = *e.InitialSequenceNumber
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTimestamp(ts time.Duration) uint32 {
|
||||
return *e.InitialTimestamp + uint32(ts.Seconds()*rtpClockRate)
|
||||
e.timeEncoder = rtptime.NewEncoder(rtpClockRate, *e.InitialTimestamp)
|
||||
}
|
||||
|
||||
// Encode encodes an image into RTP/M-JPEG packets.
|
||||
@@ -260,7 +259,7 @@ outer:
|
||||
Version: rtpVersion,
|
||||
PayloadType: 26,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: len(data) == 0,
|
||||
},
|
||||
|
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/bits"
|
||||
"github.com/aler9/gortsplib/v2/pkg/codecs/mpeg4audio"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptimedec"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
// ErrMorePacketsNeeded is returned when more packets are needed.
|
||||
@@ -29,7 +29,7 @@ type Decoder struct {
|
||||
// The number of bits in which the AU-Index-delta field is encoded in any non-first AU-header.
|
||||
IndexDeltaLength int
|
||||
|
||||
timeDecoder *rtptimedec.Decoder
|
||||
timeDecoder *rtptime.Decoder
|
||||
firstAUParsed bool
|
||||
adtsMode bool
|
||||
fragments [][]byte
|
||||
@@ -38,7 +38,7 @@ type Decoder struct {
|
||||
|
||||
// Init initializes the decoder.
|
||||
func (d *Decoder) Init() {
|
||||
d.timeDecoder = rtptimedec.New(d.SampleRate)
|
||||
d.timeDecoder = rtptime.NewDecoder(d.SampleRate)
|
||||
}
|
||||
|
||||
// Decode decodes AUs from a RTP/MPEG4-audio packet.
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/bits"
|
||||
"github.com/aler9/gortsplib/v2/pkg/codecs/mpeg4audio"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -54,6 +55,7 @@ type Encoder struct {
|
||||
IndexDeltaLength int
|
||||
|
||||
sequenceNumber uint16
|
||||
timeEncoder *rtptime.Encoder
|
||||
}
|
||||
|
||||
// Init initializes the encoder.
|
||||
@@ -75,10 +77,7 @@ func (e *Encoder) Init() {
|
||||
}
|
||||
|
||||
e.sequenceNumber = *e.InitialSequenceNumber
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTimestamp(ts time.Duration) uint32 {
|
||||
return *e.InitialTimestamp + uint32(ts.Seconds()*float64(e.SampleRate))
|
||||
e.timeEncoder = rtptime.NewEncoder(e.SampleRate, *e.InitialTimestamp)
|
||||
}
|
||||
|
||||
// Encode encodes AUs into RTP/MPEG4-audio packets.
|
||||
@@ -145,7 +144,7 @@ func (e *Encoder) writeFragmented(au []byte, pts time.Duration) ([]*rtp.Packet,
|
||||
}
|
||||
|
||||
ret := make([]*rtp.Packet, packetCount)
|
||||
encPTS := e.encodeTimestamp(pts)
|
||||
encPTS := e.timeEncoder.Encode(pts)
|
||||
|
||||
for i := range ret {
|
||||
var le int
|
||||
@@ -260,7 +259,7 @@ func (e *Encoder) writeAggregated(aus [][]byte, pts time.Duration) ([]*rtp.Packe
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: true,
|
||||
},
|
||||
|
@@ -5,19 +5,19 @@ import (
|
||||
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptimedec"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
// Decoder is a RTP/simple audio decoder.
|
||||
type Decoder struct {
|
||||
SampleRate int
|
||||
|
||||
timeDecoder *rtptimedec.Decoder
|
||||
timeDecoder *rtptime.Decoder
|
||||
}
|
||||
|
||||
// Init initializes the decoder.
|
||||
func (d *Decoder) Init() {
|
||||
d.timeDecoder = rtptimedec.New(d.SampleRate)
|
||||
d.timeDecoder = rtptime.NewDecoder(d.SampleRate)
|
||||
}
|
||||
|
||||
// Decode decodes an audio frame from a RTP packet.
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -42,6 +44,7 @@ type Encoder struct {
|
||||
SampleRate int
|
||||
|
||||
sequenceNumber uint16
|
||||
timeEncoder *rtptime.Encoder
|
||||
}
|
||||
|
||||
// Init initializes the encoder.
|
||||
@@ -63,10 +66,7 @@ func (e *Encoder) Init() {
|
||||
}
|
||||
|
||||
e.sequenceNumber = *e.InitialSequenceNumber
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTimestamp(ts time.Duration) uint32 {
|
||||
return *e.InitialTimestamp + uint32(ts.Seconds()*float64(e.SampleRate))
|
||||
e.timeEncoder = rtptime.NewEncoder(e.SampleRate, *e.InitialTimestamp)
|
||||
}
|
||||
|
||||
// Encode encodes an audio frame into a RTP packet.
|
||||
@@ -80,7 +80,7 @@ func (e *Encoder) Encode(frame []byte, pts time.Duration) (*rtp.Packet, error) {
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: false,
|
||||
},
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptimedec"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
// ErrMorePacketsNeeded is returned when more packets are needed.
|
||||
@@ -23,14 +23,14 @@ var ErrNonStartingPacketAndNoPrevious = errors.New(
|
||||
|
||||
// Decoder is a RTP/VP8 decoder.
|
||||
type Decoder struct {
|
||||
timeDecoder *rtptimedec.Decoder
|
||||
timeDecoder *rtptime.Decoder
|
||||
firstPacketReceived bool
|
||||
fragments [][]byte
|
||||
}
|
||||
|
||||
// Init initializes the decoder.
|
||||
func (d *Decoder) Init() {
|
||||
d.timeDecoder = rtptimedec.New(rtpClockRate)
|
||||
d.timeDecoder = rtptime.NewDecoder(rtpClockRate)
|
||||
}
|
||||
|
||||
// Decode decodes a VP8 frame from a RTP/VP8 packet.
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,6 +43,7 @@ type Encoder struct {
|
||||
PayloadMaxSize int
|
||||
|
||||
sequenceNumber uint16
|
||||
timeEncoder *rtptime.Encoder
|
||||
vp codecs.VP8Payloader
|
||||
}
|
||||
|
||||
@@ -63,10 +66,7 @@ func (e *Encoder) Init() {
|
||||
}
|
||||
|
||||
e.sequenceNumber = *e.InitialSequenceNumber
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTimestamp(ts time.Duration) uint32 {
|
||||
return *e.InitialTimestamp + uint32(ts.Seconds()*rtpClockRate)
|
||||
e.timeEncoder = rtptime.NewEncoder(rtpClockRate, *e.InitialTimestamp)
|
||||
}
|
||||
|
||||
// Encode encodes a VP8 frame into RTP/VP8 packets.
|
||||
@@ -85,7 +85,7 @@ func (e *Encoder) Encode(frame []byte, pts time.Duration) ([]*rtp.Packet, error)
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: i == (plen - 1),
|
||||
},
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptimedec"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
// ErrMorePacketsNeeded is returned when more packets are needed.
|
||||
@@ -23,14 +23,14 @@ var ErrNonStartingPacketAndNoPrevious = errors.New(
|
||||
|
||||
// Decoder is a RTP/VP9 decoder.
|
||||
type Decoder struct {
|
||||
timeDecoder *rtptimedec.Decoder
|
||||
timeDecoder *rtptime.Decoder
|
||||
firstPacketReceived bool
|
||||
fragments [][]byte
|
||||
}
|
||||
|
||||
// Init initializes the decoder.
|
||||
func (d *Decoder) Init() {
|
||||
d.timeDecoder = rtptimedec.New(rtpClockRate)
|
||||
d.timeDecoder = rtptime.NewDecoder(rtpClockRate)
|
||||
}
|
||||
|
||||
// Decode decodes a VP9 frame from a RTP/VP9 packet.
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/rtp/codecs"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtptime"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -45,6 +47,7 @@ type Encoder struct {
|
||||
InitialPictureID *uint16
|
||||
|
||||
sequenceNumber uint16
|
||||
timeEncoder *rtptime.Encoder
|
||||
vp codecs.VP9Payloader
|
||||
}
|
||||
|
||||
@@ -71,16 +74,13 @@ func (e *Encoder) Init() {
|
||||
}
|
||||
|
||||
e.sequenceNumber = *e.InitialSequenceNumber
|
||||
e.timeEncoder = rtptime.NewEncoder(rtpClockRate, *e.InitialTimestamp)
|
||||
|
||||
e.vp.InitialPictureIDFn = func() uint16 {
|
||||
return *e.InitialPictureID
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeTimestamp(ts time.Duration) uint32 {
|
||||
return *e.InitialTimestamp + uint32(ts.Seconds()*rtpClockRate)
|
||||
}
|
||||
|
||||
// Encode encodes a VP9 frame into RTP/VP9 packets.
|
||||
func (e *Encoder) Encode(frame []byte, pts time.Duration) ([]*rtp.Packet, error) {
|
||||
payloads := e.vp.Payload(uint16(e.PayloadMaxSize), frame)
|
||||
@@ -97,7 +97,7 @@ func (e *Encoder) Encode(frame []byte, pts time.Duration) ([]*rtp.Packet, error)
|
||||
Version: rtpVersion,
|
||||
PayloadType: e.PayloadType,
|
||||
SequenceNumber: e.sequenceNumber,
|
||||
Timestamp: e.encodeTimestamp(pts),
|
||||
Timestamp: e.timeEncoder.Encode(pts),
|
||||
SSRC: *e.SSRC,
|
||||
Marker: i == (plen - 1),
|
||||
},
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Package rtptimedec contains a RTP timestamp decoder.
|
||||
package rtptimedec
|
||||
// Package rtptime contains a RTP timestamp decoder and encoder.
|
||||
package rtptime
|
||||
|
||||
import (
|
||||
"time"
|
||||
@@ -15,14 +15,14 @@ type Decoder struct {
|
||||
prev uint32
|
||||
}
|
||||
|
||||
// New allocates a Decoder.
|
||||
func New(clockRate int) *Decoder {
|
||||
// NewDecoder allocates a Decoder.
|
||||
func NewDecoder(clockRate int) *Decoder {
|
||||
return &Decoder{
|
||||
clockRate: time.Duration(clockRate),
|
||||
}
|
||||
}
|
||||
|
||||
// Decode decodes a RTP timestamp.
|
||||
// Decode decodes a timestamp.
|
||||
func (d *Decoder) Decode(ts uint32) time.Duration {
|
||||
if !d.initialized {
|
||||
d.initialized = true
|
||||
@@ -42,7 +42,7 @@ func (d *Decoder) Decode(ts uint32) time.Duration {
|
||||
d.overall += time.Duration(diff)
|
||||
}
|
||||
|
||||
// avoid an int64 overflow and keep resolution by splitting division into two parts:
|
||||
// avoid an int64 overflow and preserve resolution by splitting division into two parts:
|
||||
// first add the integer part, then the decimal part.
|
||||
secs := d.overall / d.clockRate
|
||||
dec := d.overall % d.clockRate
|
@@ -1,4 +1,4 @@
|
||||
package rtptimedec
|
||||
package rtptime
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNegativeDiff(t *testing.T) {
|
||||
d := New(90000)
|
||||
func TestDecoderNegativeDiff(t *testing.T) {
|
||||
d := NewDecoder(90000)
|
||||
|
||||
i := uint32(0)
|
||||
pts := d.Decode(i)
|
||||
@@ -27,8 +27,8 @@ func TestNegativeDiff(t *testing.T) {
|
||||
require.Equal(t, 3*time.Second, pts)
|
||||
}
|
||||
|
||||
func TestOverflow(t *testing.T) {
|
||||
d := New(90000)
|
||||
func TestDecoderOverflow(t *testing.T) {
|
||||
d := NewDecoder(90000)
|
||||
|
||||
i := uint32(0xFFFFFFFF - 90000 + 1)
|
||||
secs := time.Duration(0)
|
||||
@@ -56,8 +56,8 @@ func TestOverflow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOverflowAndBack(t *testing.T) {
|
||||
d := New(90000)
|
||||
func TestDecoderOverflowAndBack(t *testing.T) {
|
||||
d := NewDecoder(90000)
|
||||
|
||||
pts := d.Decode(0xFFFFFFFF - 90000 + 1)
|
||||
require.Equal(t, time.Duration(0), pts)
|
||||
@@ -81,7 +81,7 @@ func TestOverflowAndBack(t *testing.T) {
|
||||
func BenchmarkDecoder(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
func() {
|
||||
d := New(90000)
|
||||
d := NewDecoder(90000)
|
||||
n := uint32(0)
|
||||
for j := 0; j < 200; j++ {
|
||||
if (j % 2) == 0 {
|
25
pkg/rtptime/encoder.go
Normal file
25
pkg/rtptime/encoder.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package rtptime
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Encoder is a RTP timestamp encoder.
|
||||
type Encoder struct {
|
||||
clockRate float64
|
||||
initialTimestamp time.Duration
|
||||
}
|
||||
|
||||
// NewEncoder allocates an Encoder.
|
||||
func NewEncoder(clockRate int, initialTimestamp uint32) *Encoder {
|
||||
return &Encoder{
|
||||
clockRate: float64(clockRate),
|
||||
initialTimestamp: time.Duration(math.Ceil(float64(initialTimestamp) * float64(time.Second) / float64(clockRate))),
|
||||
}
|
||||
}
|
||||
|
||||
// Encode encodes a timestamp.
|
||||
func (e *Encoder) Encode(ts time.Duration) uint32 {
|
||||
return uint32((e.initialTimestamp + ts).Seconds() * e.clockRate)
|
||||
}
|
14
pkg/rtptime/encoder_test.go
Normal file
14
pkg/rtptime/encoder_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package rtptime
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEncoder(t *testing.T) {
|
||||
e := NewEncoder(90000, 12345)
|
||||
|
||||
ts := e.Encode(0)
|
||||
require.Equal(t, uint32(12345), ts)
|
||||
}
|
Reference in New Issue
Block a user