Skip to content

Commit ffcdd28

Browse files
committed
rtmp: Support Opus writes from internal stream.
1 parent e6b83c2 commit ffcdd28

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

internal/protocols/rtmp/from_stream.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
)
1717

1818
var errNoSupportedCodecsFrom = errors.New(
19-
"the stream doesn't contain any supported codec, which are currently H264, MPEG-4 Audio, MPEG-1/2 Audio")
19+
"the stream doesn't contain any supported codec, which are currently H264, MPEG-4 Audio, MPEG-1/2 Audio, Opus")
2020

2121
func multiplyAndDivide2(v, m, d time.Duration) time.Duration {
2222
secs := v / d
@@ -179,6 +179,24 @@ func setupAudio(
179179
return audioFormatMPEG1
180180
}
181181

182+
var audioFormatOpus *format.Opus
183+
audioMedia = strea.Desc().FindFormat(&audioFormatOpus)
184+
if audioMedia != nil {
185+
strea.AddReader(
186+
reader,
187+
audioMedia,
188+
audioFormatOpus,
189+
func(u unit.Unit) error {
190+
tunit := u.(*unit.Opus)
191+
if tunit.Packets == nil {
192+
return nil
193+
}
194+
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
195+
return (*w).WriteOpus(timestampToDuration(tunit.PTS, audioFormatOpus.ClockRate()), tunit.Packets)
196+
})
197+
return audioFormatOpus
198+
}
199+
182200
return nil
183201
}
184202

internal/protocols/rtmp/writer.go

+34
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ func (w *Writer) writeTracks(videoTrack format.Format, audioTrack format.Format)
100100
case *format.MPEG4Audio:
101101
return message.CodecMPEG4Audio
102102

103+
case *format.Opus:
104+
return float64(message.FourCCOpus)
105+
103106
default:
104107
return 0
105108
}
@@ -162,6 +165,21 @@ func (w *Writer) writeTracks(videoTrack format.Format, audioTrack format.Format)
162165
}
163166
}
164167

168+
if track, ok := audioTrack.(*format.Opus); ok {
169+
err = w.conn.Write(&message.AudioExSequenceStart{
170+
ChunkStreamID: message.AudioChunkStreamID,
171+
MessageStreamID: 0x1000000,
172+
FourCC: message.FourCCOpus,
173+
OpusHeader: &message.OpusIDHeader{
174+
ChannelCount: uint8(track.ChannelCount),
175+
PreSkip: 3840,
176+
},
177+
})
178+
if err != nil {
179+
return err
180+
}
181+
}
182+
165183
return nil
166184
}
167185

@@ -212,3 +230,19 @@ func (w *Writer) WriteMPEG1Audio(pts time.Duration, h *mpeg1audio.FrameHeader, f
212230
DTS: pts,
213231
})
214232
}
233+
234+
func (w *Writer) WriteOpus(pts time.Duration, packets [][]byte) error {
235+
// only write one packet for now
236+
// additional packets will require self-delimiting framing
237+
// see Appendix B of RFC 6716
238+
for _, packet := range packets {
239+
return w.conn.Write(&message.AudioExCodedFrames{
240+
ChunkStreamID: message.AudioChunkStreamID,
241+
MessageStreamID: 0x1000000,
242+
DTS: pts,
243+
FourCC: message.FourCCOpus,
244+
Payload: packet,
245+
})
246+
}
247+
return nil
248+
}

0 commit comments

Comments
 (0)