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