Skip to content

Commit 002fcfa

Browse files
committed
Adding an option to disable audio PTS adjustment on sender reports
API consumers should use this option when the media processing pipeline needs stable - monotonically increasing PTS sequence - small adjustments coming from RTCP sender reports could cause gaps in the audio. Media processing pipeline could opt out of auto PTS adjustments and handle the gap by e.g modifying tempo to compensate instead
1 parent d57b069 commit 002fcfa

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

pkg/synchronizer/synchronizer.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ type SynchronizerOption func(*SynchronizerConfig)
2929

3030
// SynchronizerConfig holds configuration for the Synchronizer
3131
type SynchronizerConfig struct {
32-
MaxTsDiff time.Duration
33-
OnStarted func()
32+
MaxTsDiff time.Duration
33+
OnStarted func()
34+
AudioPTSAdjustmentDisabled bool
3435
}
3536

3637
// WithMaxTsDiff sets the maximum acceptable difference between RTP packets
@@ -48,6 +49,17 @@ func WithOnStarted(onStarted func()) SynchronizerOption {
4849
}
4950
}
5051

52+
// WithAudioPTSAdjustmentDisabled - disables auto PTS adjustments after sender reports
53+
// Use case: when media processing pipeline needs stable - monotonically increasing
54+
// PTS sequence - small adjustments coming from RTCP sender reports could cause gaps in the audio
55+
// Media processing pipeline could opt out of auto PTS adjustments and handle the gap
56+
// by e.g modifying tempo to compensate instead
57+
func WithAudioPTSAdjustmentDisabled() SynchronizerOption {
58+
return func(config *SynchronizerConfig) {
59+
config.AudioPTSAdjustmentDisabled = true
60+
}
61+
}
62+
5163
// a single Synchronizer is shared between all audio and video writers
5264
type Synchronizer struct {
5365
sync.RWMutex

pkg/synchronizer/track.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ type TrackSynchronizer struct {
4646
*rtpConverter
4747

4848
// config
49-
maxTsDiff time.Duration // maximum acceptable difference between RTP packets
49+
maxTsDiff time.Duration // maximum acceptable difference between RTP packets
50+
audioPTSAdjustmentsDisabled bool // disable audio packets PTS adjustments on SRs
5051

5152
// timing info
5253
startTime time.Time // time first packet was pushed
@@ -67,11 +68,12 @@ type TrackSynchronizer struct {
6768

6869
func newTrackSynchronizer(s *Synchronizer, track TrackRemote) *TrackSynchronizer {
6970
t := &TrackSynchronizer{
70-
sync: s,
71-
track: track,
72-
logger: logger.GetLogger().WithValues("trackID", track.ID(), "codec", track.Codec().MimeType),
73-
rtpConverter: newRTPConverter(int64(track.Codec().ClockRate)),
74-
maxTsDiff: s.config.MaxTsDiff,
71+
sync: s,
72+
track: track,
73+
logger: logger.GetLogger().WithValues("trackID", track.ID(), "codec", track.Codec().MimeType),
74+
rtpConverter: newRTPConverter(int64(track.Codec().ClockRate)),
75+
maxTsDiff: s.config.MaxTsDiff,
76+
audioPTSAdjustmentsDisabled: s.config.AudioPTSAdjustmentDisabled,
7577
}
7678

7779
return t
@@ -123,11 +125,14 @@ func (t *TrackSynchronizer) GetPTS(pkt *rtp.Packet) (time.Duration, error) {
123125
t.startRTP = ts - t.toRTP(pts)
124126
}
125127

126-
if t.currentPTSOffset > t.desiredPTSOffset {
127-
t.currentPTSOffset = max(t.currentPTSOffset-maxAdjustment, t.desiredPTSOffset)
128-
} else if t.currentPTSOffset < t.desiredPTSOffset {
129-
t.currentPTSOffset = min(t.currentPTSOffset+maxAdjustment, t.desiredPTSOffset)
128+
if t.shouldAdjustPTS() {
129+
if t.currentPTSOffset > t.desiredPTSOffset {
130+
t.currentPTSOffset = max(t.currentPTSOffset-maxAdjustment, t.desiredPTSOffset)
131+
} else if t.currentPTSOffset < t.desiredPTSOffset {
132+
t.currentPTSOffset = min(t.currentPTSOffset+maxAdjustment, t.desiredPTSOffset)
133+
}
130134
}
135+
131136
adjusted := pts + t.currentPTSOffset
132137

133138
// if past end time, return EOF
@@ -179,6 +184,14 @@ func (t *TrackSynchronizer) acceptable(d time.Duration) bool {
179184
return d > -t.maxTsDiff && d < t.maxTsDiff
180185
}
181186

187+
func (t *TrackSynchronizer) shouldAdjustPTS() bool {
188+
adjustmentEnabled := true
189+
if t.track.Kind() == webrtc.RTPCodecTypeAudio {
190+
adjustmentEnabled = !t.audioPTSAdjustmentsDisabled
191+
}
192+
return adjustmentEnabled && (t.currentPTSOffset != t.desiredPTSOffset)
193+
}
194+
182195
type rtpConverter struct {
183196
ts uint64
184197
rtp uint64

0 commit comments

Comments
 (0)