Skip to content

Commit 965969a

Browse files
authored
Adding an option to disable audio PTS adjustment on sender reports (#721)
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 37d6ce4 commit 965969a

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
@@ -49,7 +49,8 @@ type TrackSynchronizer struct {
4949
*rtpConverter
5050

5151
// config
52-
maxTsDiff time.Duration // maximum acceptable difference between RTP packets
52+
maxTsDiff time.Duration // maximum acceptable difference between RTP packets
53+
audioPTSAdjustmentsDisabled bool // disable audio packets PTS adjustments on SRs
5354

5455
// timing info
5556
startTime time.Time // time first packet was pushed
@@ -71,11 +72,12 @@ type TrackSynchronizer struct {
7172

7273
func newTrackSynchronizer(s *Synchronizer, track TrackRemote) *TrackSynchronizer {
7374
t := &TrackSynchronizer{
74-
sync: s,
75-
track: track,
76-
logger: logger.GetLogger().WithValues("trackID", track.ID(), "codec", track.Codec().MimeType),
77-
rtpConverter: newRTPConverter(int64(track.Codec().ClockRate)),
78-
maxTsDiff: s.config.MaxTsDiff,
75+
sync: s,
76+
track: track,
77+
logger: logger.GetLogger().WithValues("trackID", track.ID(), "codec", track.Codec().MimeType),
78+
rtpConverter: newRTPConverter(int64(track.Codec().ClockRate)),
79+
maxTsDiff: s.config.MaxTsDiff,
80+
audioPTSAdjustmentsDisabled: s.config.AudioPTSAdjustmentDisabled,
7981
}
8082

8183
return t
@@ -128,11 +130,14 @@ func (t *TrackSynchronizer) GetPTS(pkt *rtp.Packet) (time.Duration, error) {
128130
t.startRTP = ts - t.toRTP(pts)
129131
}
130132

131-
if t.currentPTSOffset > t.desiredPTSOffset {
132-
t.currentPTSOffset = max(t.currentPTSOffset-maxAdjustment, t.desiredPTSOffset)
133-
} else if t.currentPTSOffset < t.desiredPTSOffset {
134-
t.currentPTSOffset = min(t.currentPTSOffset+maxAdjustment, t.desiredPTSOffset)
133+
if t.shouldAdjustPTS() {
134+
if t.currentPTSOffset > t.desiredPTSOffset {
135+
t.currentPTSOffset = max(t.currentPTSOffset-maxAdjustment, t.desiredPTSOffset)
136+
} else if t.currentPTSOffset < t.desiredPTSOffset {
137+
t.currentPTSOffset = min(t.currentPTSOffset+maxAdjustment, t.desiredPTSOffset)
138+
}
135139
}
140+
136141
adjusted := pts + t.currentPTSOffset
137142

138143
// if past end time, return EOF
@@ -184,6 +189,14 @@ func (t *TrackSynchronizer) acceptable(d time.Duration) bool {
184189
return d > -t.maxTsDiff && d < t.maxTsDiff
185190
}
186191

192+
func (t *TrackSynchronizer) shouldAdjustPTS() bool {
193+
adjustmentEnabled := true
194+
if t.track.Kind() == webrtc.RTPCodecTypeAudio {
195+
adjustmentEnabled = !t.audioPTSAdjustmentsDisabled
196+
}
197+
return adjustmentEnabled && (t.currentPTSOffset != t.desiredPTSOffset)
198+
}
199+
187200
type rtpConverter struct {
188201
ts uint64
189202
rtp uint64

0 commit comments

Comments
 (0)