refactor timestamp handling
This commit is contained in:
+46
-41
@@ -247,28 +247,39 @@ func (cs *channelState) reset() {
|
|||||||
cs.lastPktIdx = 0
|
cs.lastPktIdx = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseAudioParams(payload []byte, fi *FrameInfo) (sampleRate uint32, channels uint8) {
|
|
||||||
if aac.IsADTS(payload) {
|
|
||||||
codec := aac.ADTSToCodec(payload)
|
|
||||||
if codec != nil {
|
|
||||||
return codec.ClockRate, codec.Channels
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi != nil {
|
|
||||||
return fi.SampleRate(), fi.Channels()
|
|
||||||
}
|
|
||||||
|
|
||||||
return 16000, 1
|
|
||||||
}
|
|
||||||
|
|
||||||
const tsWrapPeriod uint32 = 1000000
|
const tsWrapPeriod uint32 = 1000000
|
||||||
|
|
||||||
type FrameHandler struct {
|
type tsTracker struct {
|
||||||
channels map[byte]*channelState
|
|
||||||
lastRawTS uint32
|
lastRawTS uint32
|
||||||
accumUS uint64
|
accumUS uint64
|
||||||
firstTS bool
|
firstTS bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tsTracker) update(rawTS uint32) uint64 {
|
||||||
|
if !t.firstTS {
|
||||||
|
t.firstTS = true
|
||||||
|
t.lastRawTS = rawTS
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var delta uint32
|
||||||
|
if rawTS >= t.lastRawTS {
|
||||||
|
delta = rawTS - t.lastRawTS
|
||||||
|
} else {
|
||||||
|
// Wrapped: delta = (wrap - last) + new
|
||||||
|
delta = (tsWrapPeriod - t.lastRawTS) + rawTS
|
||||||
|
}
|
||||||
|
|
||||||
|
t.accumUS += uint64(delta)
|
||||||
|
t.lastRawTS = rawTS
|
||||||
|
|
||||||
|
return t.accumUS
|
||||||
|
}
|
||||||
|
|
||||||
|
type FrameHandler struct {
|
||||||
|
channels map[byte]*channelState
|
||||||
|
videoTS tsTracker
|
||||||
|
audioTS tsTracker
|
||||||
output chan *Packet
|
output chan *Packet
|
||||||
verbose bool
|
verbose bool
|
||||||
}
|
}
|
||||||
@@ -289,27 +300,6 @@ func (h *FrameHandler) Close() {
|
|||||||
close(h.output)
|
close(h.output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *FrameHandler) updateTimestamp(rawTS uint32) uint64 {
|
|
||||||
if !h.firstTS {
|
|
||||||
h.firstTS = true
|
|
||||||
h.lastRawTS = rawTS
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var delta uint32
|
|
||||||
if rawTS >= h.lastRawTS {
|
|
||||||
delta = rawTS - h.lastRawTS
|
|
||||||
} else {
|
|
||||||
// Wrapped: delta = (wrap - last) + new
|
|
||||||
delta = (tsWrapPeriod - h.lastRawTS) + rawTS
|
|
||||||
}
|
|
||||||
|
|
||||||
h.accumUS += uint64(delta)
|
|
||||||
h.lastRawTS = rawTS
|
|
||||||
|
|
||||||
return h.accumUS
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *FrameHandler) Handle(data []byte) {
|
func (h *FrameHandler) Handle(data []byte) {
|
||||||
hdr := ParsePacketHeader(data)
|
hdr := ParsePacketHeader(data)
|
||||||
if hdr == nil {
|
if hdr == nil {
|
||||||
@@ -464,7 +454,7 @@ func (h *FrameHandler) emitVideo(channel byte, cs *channelState) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accumUS := h.updateTimestamp(fi.Timestamp)
|
accumUS := h.videoTS.update(fi.Timestamp)
|
||||||
rtpTS := uint32(accumUS * 90000 / 1000000)
|
rtpTS := uint32(accumUS * 90000 / 1000000)
|
||||||
|
|
||||||
// Copy payload (buffer will be reused)
|
// Copy payload (buffer will be reused)
|
||||||
@@ -510,13 +500,13 @@ func (h *FrameHandler) handleAudio(payload []byte, fi *FrameInfo) {
|
|||||||
|
|
||||||
switch fi.CodecID {
|
switch fi.CodecID {
|
||||||
case AudioCodecAACRaw, AudioCodecAACADTS, AudioCodecAACLATM, AudioCodecAACWyze:
|
case AudioCodecAACRaw, AudioCodecAACADTS, AudioCodecAACLATM, AudioCodecAACWyze:
|
||||||
sampleRate, channels = ParseAudioParams(payload, fi)
|
sampleRate, channels = parseAudioParams(payload, fi)
|
||||||
default:
|
default:
|
||||||
sampleRate = fi.SampleRate()
|
sampleRate = fi.SampleRate()
|
||||||
channels = fi.Channels()
|
channels = fi.Channels()
|
||||||
}
|
}
|
||||||
|
|
||||||
accumUS := h.updateTimestamp(fi.Timestamp)
|
accumUS := h.audioTS.update(fi.Timestamp)
|
||||||
rtpTS := uint32(accumUS * uint64(sampleRate) / 1000000)
|
rtpTS := uint32(accumUS * uint64(sampleRate) / 1000000)
|
||||||
|
|
||||||
pkt := &Packet{
|
pkt := &Packet{
|
||||||
@@ -559,6 +549,21 @@ func (h *FrameHandler) queue(pkt *Packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseAudioParams(payload []byte, fi *FrameInfo) (sampleRate uint32, channels uint8) {
|
||||||
|
if aac.IsADTS(payload) {
|
||||||
|
codec := aac.ADTSToCodec(payload)
|
||||||
|
if codec != nil {
|
||||||
|
return codec.ClockRate, codec.Channels
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi != nil {
|
||||||
|
return fi.SampleRate(), fi.Channels()
|
||||||
|
}
|
||||||
|
|
||||||
|
return 16000, 1
|
||||||
|
}
|
||||||
|
|
||||||
func dumpHex(fi *FrameInfo) string {
|
func dumpHex(fi *FrameInfo) string {
|
||||||
b := make([]byte, FrameInfoSize)
|
b := make([]byte, FrameInfoSize)
|
||||||
binary.LittleEndian.PutUint16(b[0:], fi.CodecID)
|
binary.LittleEndian.PutUint16(b[0:], fi.CodecID)
|
||||||
|
|||||||
Reference in New Issue
Block a user