Skip to content

Commit 12c9f74

Browse files
authored
Disable resampler on the input audio. (#487)
1 parent 347c57a commit 12c9f74

File tree

5 files changed

+47
-17
lines changed

5 files changed

+47
-17
lines changed

pkg/sip/inbound.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,7 @@ func (c *inboundCall) runMediaConn(tid traceid.ID, offerData []byte, enc livekit
913913
MediaTimeout: c.s.conf.MediaTimeout,
914914
EnableJitterBuffer: c.jitterBuf,
915915
Stats: &c.stats.Port,
916+
NoInputResample: !RoomResample,
916917
}, RoomSampleRate)
917918
if err != nil {
918919
return nil, err

pkg/sip/media.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ func (s *Stats) MarshalJSON() ([]byte, error) {
151151
const (
152152
channels = 1
153153
RoomSampleRate = 48000
154+
RoomResample = false
154155
)
155156

156157
func newRTPStatsHandler(mon *stats.CallMonitor, typ string, r rtp.Handler) rtp.Handler {

pkg/sip/media_port.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ type MediaOptions struct {
131131
MediaTimeout time.Duration
132132
Stats *PortStats
133133
EnableJitterBuffer bool
134+
NoInputResample bool
134135
}
135136

136137
func NewMediaPort(tid traceid.ID, log logger.Logger, mon *stats.CallMonitor, opts *MediaOptions, sampleRate int) (*MediaPort, error) {
@@ -158,6 +159,10 @@ func NewMediaPortWith(tid traceid.ID, log logger.Logger, mon *stats.CallMonitor,
158159
conn = c
159160
}
160161
mediaTimeout := make(chan struct{})
162+
inSampleRate := sampleRate
163+
if opts.NoInputResample {
164+
inSampleRate = -1 // set only after SDP is accepted
165+
}
161166
p := &MediaPort{
162167
tid: tid,
163168
log: log,
@@ -169,7 +174,7 @@ func NewMediaPortWith(tid traceid.ID, log logger.Logger, mon *stats.CallMonitor,
169174
jitterEnabled: opts.EnableJitterBuffer,
170175
port: newUDPConn(log, conn),
171176
audioOut: msdk.NewSwitchWriter(sampleRate),
172-
audioIn: msdk.NewSwitchWriter(sampleRate),
177+
audioIn: msdk.NewSwitchWriter(inSampleRate),
173178
stats: opts.Stats,
174179
}
175180
p.timeoutInitial.Store(&opts.MediaTimeoutInitial)
@@ -628,14 +633,19 @@ func (p *MediaPort) setupOutput(tid traceid.ID) error {
628633

629634
func (p *MediaPort) setupInput() {
630635
// Decoding pipeline (SIP RTP -> LK PCM)
631-
audioHandler := p.conf.Audio.Codec.DecodeRTP(p.audioIn, p.conf.Audio.Type)
636+
codec := p.conf.Audio.Codec
637+
codecInfo := codec.Info()
638+
if p.opts.NoInputResample {
639+
p.audioIn.SetSampleRate(codecInfo.SampleRate)
640+
}
641+
audioHandler := codec.DecodeRTP(p.audioIn, p.conf.Audio.Type)
632642
p.audioInHandler = audioHandler
633643

634644
mux := rtp.NewMux(nil)
635645
mux.SetDefault(newRTPStatsHandler(p.mon, "", nil))
636646
mux.Register(
637647
p.conf.Audio.Type, newRTPHandlerCount(
638-
newRTPStatsHandler(p.mon, p.conf.Audio.Codec.Info().SDPName, audioHandler),
648+
newRTPStatsHandler(p.mon, codecInfo.SDPName, audioHandler),
639649
&p.stats.AudioPackets, &p.stats.AudioBytes,
640650
),
641651
)

pkg/sip/media_port_test.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,9 @@ func TestMediaPort(t *testing.T) {
199199
log := logger.GetLogger()
200200

201201
m1, err := NewMediaPortWith(1, log.WithName("one"), nil, c1, &MediaOptions{
202-
IP: newIP("1.1.1.1"),
203-
Ports: rtcconfig.PortRange{Start: 10000},
202+
IP: newIP("1.1.1.1"),
203+
Ports: rtcconfig.PortRange{Start: 10000},
204+
NoInputResample: true,
204205
}, tconf.Rate)
205206
require.NoError(t, err)
206207
defer m1.Close()
@@ -235,11 +236,13 @@ func TestMediaPort(t *testing.T) {
235236
err = m2.SetConfig(conf)
236237
require.NoError(t, err)
237238

238-
require.Equal(t, info.SDPName, m1.Config().Audio.Codec.Info().SDPName)
239-
require.Equal(t, info.SDPName, m2.Config().Audio.Codec.Info().SDPName)
239+
codec1 := m1.Config().Audio.Codec
240+
codec2 := m2.Config().Audio.Codec
241+
require.Equal(t, info.SDPName, codec1.Info().SDPName)
242+
require.Equal(t, info.SDPName, codec2.Info().SDPName)
240243

241244
var buf1 msdk.PCM16Sample
242-
bw1 := msdk.NewPCM16BufferWriter(&buf1, tconf.Rate)
245+
bw1 := msdk.NewPCM16BufferWriter(&buf1, codec1.Info().SampleRate)
243246
m1.WriteAudioTo(bw1)
244247

245248
var buf2 msdk.PCM16Sample
@@ -257,7 +260,8 @@ func TestMediaPort(t *testing.T) {
257260
sample2[i] = -5116
258261
}
259262

260-
writes := 1
263+
writes1 := 1
264+
writes2 := 1
261265
if tconf.Rate == nativeRate {
262266
expChain := fmt.Sprintf("Switch(%d) -> %s(encode) -> RTP(%d)", nativeRate, name, nativeRate)
263267
require.Equal(t, expChain, w1.String())
@@ -271,20 +275,31 @@ func TestMediaPort(t *testing.T) {
271275
require.Equal(t, expChain, w1.String())
272276
require.Equal(t, expChain, w2.String())
273277

274-
expChain = fmt.Sprintf("RTP(%d) -> %s(decode) -> Resample(%d->48000) -> Switch(48000) -> Buffer(48000)", nativeRate, name, nativeRate)
275-
require.Equal(t, expChain, PrintAudioInWriter(m1))
276-
require.Equal(t, expChain, PrintAudioInWriter(m2))
277-
278-
writes += 2 // resampler will buffer a few frames
278+
// This side does not resample the received audio, it uses sample rate of the RTP source.
279+
expChain1 := fmt.Sprintf("RTP(%d) -> %s(decode) -> Switch(%d) -> Buffer(%d)", nativeRate, name, nativeRate, nativeRate)
280+
// This side resamples the received audio to the expected sample rate.
281+
expChain2 := fmt.Sprintf("RTP(%d) -> %s(decode) -> Resample(%d->48000) -> Switch(48000) -> Buffer(48000)", nativeRate, name, nativeRate)
282+
require.Equal(t, expChain1, PrintAudioInWriter(m1))
283+
require.Equal(t, expChain2, PrintAudioInWriter(m2))
284+
285+
// resampler will buffer a few frames
286+
writes1 += 2
287+
writes2 += 2
288+
// a few more because of higher resample quality required
279289
if nativeRate == 8000 {
280-
writes += 3 // a few more because of higher resample quality required
290+
writes1 += 3
291+
writes2 += 5
292+
}
293+
if strings.HasPrefix(info.SDPName, "G722/") {
294+
writes2 += 1
281295
}
282296
}
283297

284-
for range writes {
298+
for range writes1 {
285299
err = w1.WriteSample(sample1)
286300
require.NoError(t, err)
287-
301+
}
302+
for range writes2 {
288303
err = w2.WriteSample(sample2)
289304
require.NoError(t, err)
290305
}
@@ -309,6 +324,7 @@ func TestMediaPort(t *testing.T) {
309324
}
310325

311326
func checkPCM(t testing.TB, exp, got msdk.PCM16Sample) {
327+
t.Helper()
312328
require.Equal(t, len(exp), len(got))
313329
expSamples := slices.Clone(exp)
314330
slices.Sort(expSamples)
@@ -338,6 +354,7 @@ func newMediaPair(t testing.TB, opt1, opt2 *MediaOptions) (m1, m2 *MediaPort) {
338354

339355
opt1.IP = newIP("1.1.1.1")
340356
opt1.Ports = rtcconfig.PortRange{Start: 10000}
357+
opt1.NoInputResample = true
341358

342359
opt2.IP = newIP("2.2.2.2")
343360
opt2.Ports = rtcconfig.PortRange{Start: 20000}

pkg/sip/outbound.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ func (c *Client) newCall(ctx context.Context, tid traceid.ID, conf *config.Confi
140140
MediaTimeout: c.conf.MediaTimeout,
141141
EnableJitterBuffer: call.jitterBuf,
142142
Stats: &call.stats.Port,
143+
NoInputResample: !RoomResample,
143144
}, RoomSampleRate)
144145
if err != nil {
145146
call.close(errors.Wrap(err, "media failed"), callDropped, "media-failed", livekit.DisconnectReason_UNKNOWN_REASON)

0 commit comments

Comments
 (0)