Skip to content

Commit 04db579

Browse files
committed
fix: output codec resolution
1 parent 71e93b0 commit 04db579

4 files changed

Lines changed: 69 additions & 45 deletions

File tree

internal/codec.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package internal
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/pion/rtp"
7+
"github.com/pion/rtp/codecs"
8+
"github.com/pion/webrtc/v3"
9+
)
10+
11+
type OutputCodec struct {
12+
webrtc.RTPCodecCapability
13+
rtp.Payloader
14+
GStreamerEncoder string
15+
}
16+
17+
func ResolveOutputCodec(tr *webrtc.TrackRemote, mimeType, pipelineStr string) (*OutputCodec, error) {
18+
if mimeType == "" {
19+
// use the default output codec for the track remote kind.
20+
switch tr.Kind() {
21+
case webrtc.RTPCodecTypeVideo:
22+
return &OutputCodec{
23+
RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeH264, ClockRate: 90000},
24+
Payloader: &codecs.H264Payloader{},
25+
GStreamerEncoder: "x264enc speed-preset=ultrafast tune=zerolatency key-int-max=20",
26+
}, nil
27+
case webrtc.RTPCodecTypeAudio:
28+
return &OutputCodec{
29+
RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000},
30+
Payloader: &codecs.OpusPayloader{},
31+
GStreamerEncoder: "opusenc",
32+
}, nil
33+
}
34+
return nil, fmt.Errorf("unsupported track remote kind %s", tr.Kind())
35+
}
36+
output := &OutputCodec{}
37+
switch mimeType {
38+
case webrtc.MimeTypeH264:
39+
output.RTPCodecCapability = webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeH264, ClockRate: 90000}
40+
output.Payloader = &codecs.H264Payloader{}
41+
output.GStreamerEncoder = "x264enc speed-preset=ultrafast tune=zerolatency key-int-max=20"
42+
case webrtc.MimeTypeVP8:
43+
output.RTPCodecCapability = webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}
44+
output.Payloader = &codecs.VP8Payloader{}
45+
output.GStreamerEncoder = "vp8enc deadline=1"
46+
case webrtc.MimeTypeOpus:
47+
output.RTPCodecCapability = webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000}
48+
output.Payloader = &codecs.OpusPayloader{}
49+
output.GStreamerEncoder = "opusenc"
50+
default:
51+
return nil, fmt.Errorf("unsupported codec %s", mimeType)
52+
}
53+
if pipelineStr != "" {
54+
output.GStreamerEncoder = pipelineStr
55+
}
56+
return output, nil
57+
}

internal/server.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,13 @@ func (s *TranscoderServer) Transcode(ctx context.Context, request *api.Transcode
183183
s.onTrack.L.Unlock()
184184
}
185185

186+
outputCodec, err := ResolveOutputCodec(matched.TrackRemote, request.MimeType, request.GstreamerPipeline)
187+
if err != nil {
188+
return nil, err
189+
}
186190

187191
// tr is the remote track that matches the request.
188-
tl, err := TranscodeTrackRemote(matched.Parent, matched.TrackRemote, request.GstreamerPipeline, request.MimeType)
192+
tl, err := TranscodeTrackRemote(matched.Parent, matched.TrackRemote, outputCodec)
189193
if err != nil {
190194
return nil, err
191195
}

internal/transcode.go

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212

1313
"github.com/notedit/gst"
1414
"github.com/pion/rtp"
15-
"github.com/pion/rtp/codecs"
1615
"github.com/pion/webrtc/v3"
1716
"go.uber.org/zap"
1817
)
@@ -66,52 +65,15 @@ func PipelineString(trCodec webrtc.RTPCodecParameters, encodingStr string) (stri
6665
return "", fmt.Errorf("unsupported codec %s", trCodec.MimeType)
6766
}
6867

69-
func EncodingPipelineStr(mimeType string) (string, error) {
70-
switch mimeType {
71-
case webrtc.MimeTypeH264, "" /* default */:
72-
return "x264enc speed-preset=ultrafast tune=zerolatency key-int-max=20", nil
73-
case webrtc.MimeTypeVP8:
74-
return "vp8enc deadline=1", nil
75-
case webrtc.MimeTypeOpus:
76-
return "opusenc", nil
77-
}
78-
return "", fmt.Errorf("unsupported codec %s", mimeType)
79-
}
80-
81-
func TargetCodec(mimeType string) (*webrtc.RTPCodecCapability, rtp.Payloader, error) {
82-
switch mimeType {
83-
case webrtc.MimeTypeH264, "" /* default */:
84-
return &webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeH264, ClockRate: 90000}, &codecs.H264Payloader{}, nil
85-
case webrtc.MimeTypeVP8:
86-
return &webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000}, &codecs.VP8Payloader{}, nil
87-
case webrtc.MimeTypeOpus:
88-
return &webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000}, &codecs.OpusPayloader{}, nil
89-
}
90-
return nil, nil, fmt.Errorf("unsupported codec %s", mimeType)
91-
}
68+
func TranscodeTrackRemote(parent *gst.Pipeline, tr *webrtc.TrackRemote, outputCodec *OutputCodec) (webrtc.TrackLocal, error) {
69+
packetizer := NewTSPacketizer(1200, outputCodec.Payloader, rtp.NewRandomSequencer())
9270

93-
94-
func TranscodeTrackRemote(parent *gst.Pipeline, tr *webrtc.TrackRemote, pipelineStr, mimeType string) (webrtc.TrackLocal, error) {
95-
targetCodec, payloader, err := TargetCodec(mimeType)
71+
tl, err := webrtc.NewTrackLocalStaticRTP(outputCodec.RTPCodecCapability, tr.ID(), tr.StreamID())
9672
if err != nil {
9773
return nil, err
9874
}
9975

100-
packetizer := NewTSPacketizer(1200, payloader, rtp.NewRandomSequencer())
101-
102-
tl, err := webrtc.NewTrackLocalStaticRTP(*targetCodec, tr.ID(), tr.StreamID())
103-
if err != nil {
104-
return nil, err
105-
}
106-
107-
if pipelineStr == "" {
108-
pipelineStr, err = EncodingPipelineStr(mimeType)
109-
if err != nil {
110-
return nil, err
111-
}
112-
}
113-
114-
transcodingPipelineStr, err := PipelineString(tr.Codec(), pipelineStr)
76+
transcodingPipelineStr, err := PipelineString(tr.Codec(), outputCodec.GStreamerEncoder)
11577
if err != nil {
11678
return nil, err
11779
}
@@ -161,7 +123,7 @@ func TranscodeTrackRemote(parent *gst.Pipeline, tr *webrtc.TrackRemote, pipeline
161123

162124
// GStreamer doesn't set the buffer duration for RTP packets, so we compute the timestamp
163125
// based on the dts.
164-
rtpts := uint32(uint64(sample.Dts) / 1000 * (uint64(targetCodec.ClockRate) / 1000) / 1000)
126+
rtpts := uint32(uint64(sample.Dts) / 1000 * (uint64(outputCodec.ClockRate) / 1000) / 1000)
165127
for _, p := range packetizer.Packetize(sample.Data, rtpts) {
166128
if err := tl.WriteRTP(p); err != nil {
167129
zap.L().Error("could not write rtp", zap.Error(err))

pkg/transcoder/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"sync"
88

99
"github.com/muxable/transcoder/api"
10+
"github.com/muxable/transcoder/internal"
1011
"github.com/pion/webrtc/v3"
1112
"go.uber.org/zap"
1213
"google.golang.org/grpc"
@@ -22,7 +23,7 @@ type Client struct {
2223
}
2324

2425
func NewClient(ctx context.Context, conn *grpc.ClientConn) (*Client, error) {
25-
peerConnection, err := webrtc.NewPeerConnection(webrtc.Configuration{
26+
peerConnection, err := internal.NewTranscoderPeerConnection(webrtc.Configuration{
2627
ICEServers: []webrtc.ICEServer{
2728
{URLs: []string{"stun:stun.l.google.com:19302"}},
2829
},

0 commit comments

Comments
 (0)