Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webrtc: support publishing H265 tracks (#3435) #3492

Merged
merged 1 commit into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ Live streams can be published to the server with:
|--------|--------|------------|------------|
|[SRT clients](#srt-clients)||H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3|
|[SRT cameras and servers](#srt-cameras-and-servers)||H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3|
|[WebRTC clients](#webrtc-clients)|Browser-based, WHIP|AV1, VP9, VP8, H264|Opus, G722, G711 (PCMA, PCMU)|
|[WebRTC servers](#webrtc-servers)|WHEP|AV1, VP9, VP8, H264|Opus, G722, G711 (PCMA, PCMU)|
|[WebRTC clients](#webrtc-clients)|Browser-based, WHIP|AV1, VP9, VP8, H265, H264|Opus, G722, G711 (PCMA, PCMU)|
|[WebRTC servers](#webrtc-servers)|WHEP|AV1, VP9, VP8, H265, H264|Opus, G722, G711 (PCMA, PCMU)|
|[RTSP clients](#rtsp-clients)|UDP, TCP, RTSPS|AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG and any RTP-compatible codec|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM and any RTP-compatible codec|
|[RTSP cameras and servers](#rtsp-cameras-and-servers)|UDP, UDP-Multicast, TCP, RTSPS|AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), MPEG-1/2 Video, M-JPEG and any RTP-compatible codec|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), AC-3, G726, G722, G711 (PCMA, PCMU), LPCM and any RTP-compatible codec|
|[RTMP clients](#rtmp-clients)|RTMP, RTMPS, Enhanced RTMP|AV1, VP9, H265, H264|MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3), G711 (PCMA, PCMU), LPCM|
Expand Down
41 changes: 31 additions & 10 deletions internal/protocols/webrtc/incoming_track.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"strings"
"time"

"github.com/bluenviron/gortsplib/v4/pkg/description"
"github.com/bluenviron/gortsplib/v4/pkg/format"
"github.com/bluenviron/gortsplib/v4/pkg/liberrors"
"github.com/bluenviron/gortsplib/v4/pkg/rtpreorderer"
Expand Down Expand Up @@ -79,21 +80,28 @@
},
PayloadType: 102,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH265,
ClockRate: 90000,
},
PayloadType: 103,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264,
ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
},
PayloadType: 103,
PayloadType: 104,
},
{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH264,
ClockRate: 90000,
SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f",
},
PayloadType: 104,
PayloadType: 105,
},
}

Expand Down Expand Up @@ -229,6 +237,7 @@
track *webrtc.TrackRemote
log logger.Writer

typ description.MediaType
format format.Format
reorderer *rtpreorderer.Reorderer
pkts []*rtp.Packet
Expand All @@ -246,41 +255,47 @@
reorderer: rtpreorderer.New(),
}

isVideo := false

switch strings.ToLower(track.Codec().MimeType) {
case strings.ToLower(webrtc.MimeTypeAV1):
isVideo = true
t.typ = description.MediaTypeVideo
t.format = &format.AV1{
PayloadTyp: uint8(track.PayloadType()),
}

case strings.ToLower(webrtc.MimeTypeVP9):
isVideo = true
t.typ = description.MediaTypeVideo
t.format = &format.VP9{
PayloadTyp: uint8(track.PayloadType()),
}

case strings.ToLower(webrtc.MimeTypeVP8):
isVideo = true
t.typ = description.MediaTypeVideo
t.format = &format.VP8{
PayloadTyp: uint8(track.PayloadType()),
}

case strings.ToLower(webrtc.MimeTypeH265):
t.typ = description.MediaTypeVideo
t.format = &format.H265{
PayloadTyp: uint8(track.PayloadType()),
}

case strings.ToLower(webrtc.MimeTypeH264):
isVideo = true
t.typ = description.MediaTypeVideo
t.format = &format.H264{
PayloadTyp: uint8(track.PayloadType()),
PacketizationMode: 1,
}

case strings.ToLower(mimeTypeMultiopus):
t.typ = description.MediaTypeAudio
t.format = &format.Opus{
PayloadTyp: uint8(track.PayloadType()),
ChannelCount: int(track.Codec().Channels),
}

case strings.ToLower(webrtc.MimeTypeOpus):
t.typ = description.MediaTypeAudio
t.format = &format.Opus{
PayloadTyp: uint8(track.PayloadType()),
ChannelCount: func() int {
Expand All @@ -292,9 +307,12 @@
}

case strings.ToLower(webrtc.MimeTypeG722):
t.typ = description.MediaTypeAudio
t.format = &format.G722{}

case strings.ToLower(webrtc.MimeTypePCMU):
t.typ = description.MediaTypeAudio

channels := track.Codec().Channels
if channels == 0 {
channels = 1
Expand All @@ -313,6 +331,8 @@
}

case strings.ToLower(webrtc.MimeTypePCMA):
t.typ = description.MediaTypeAudio

channels := track.Codec().Channels
if channels == 0 {
channels = 1
Expand All @@ -331,6 +351,7 @@
}

case strings.ToLower(mimeTypeL16):
t.typ = description.MediaTypeAudio
t.format = &format.LPCM{
PayloadTyp: uint8(track.PayloadType()),
BitDepth: 16,
Expand All @@ -339,7 +360,7 @@
}

default:
return nil, fmt.Errorf("unsupported codec: %+v", track.Codec())
return nil, fmt.Errorf("unsupported codec: %+v", track.Codec().RTPCodecCapability)

Check warning on line 363 in internal/protocols/webrtc/incoming_track.go

View check run for this annotation

Codecov / codecov/patch

internal/protocols/webrtc/incoming_track.go#L363

Added line #L363 was not covered by tests
}

// read incoming RTCP packets to make interceptors work
Expand All @@ -354,7 +375,7 @@
}()

// send period key frame requests
if isVideo {
if t.typ == description.MediaTypeVideo {
go func() {
keyframeTicker := time.NewTicker(keyFrameInterval)
defer keyframeTicker.Stop()
Expand Down
10 changes: 10 additions & 0 deletions internal/protocols/webrtc/outgoing_track.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ func (t *OutgoingTrack) codecParameters() (webrtc.RTPCodecParameters, error) {
PayloadType: 96,
}, nil

case *format.H265:
return webrtc.RTPCodecParameters{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeH265,
ClockRate: 90000,
},
PayloadType: 96,
}, nil

case *format.H264:
return webrtc.RTPCodecParameters{
RTPCodecCapability: webrtc.RTPCodecCapability{
Expand Down Expand Up @@ -205,6 +214,7 @@ func (t *OutgoingTrack) isVideo() bool {
case *format.AV1,
*format.VP9,
*format.VP8,
*format.H265,
*format.H264:
return true
}
Expand Down
11 changes: 11 additions & 0 deletions internal/protocols/webrtc/peer_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ func TestPeerConnectionPublishRead(t *testing.T) {
PayloadTyp: 96,
},
},
{
"h265",
test.FormatH265,
webrtc.RTPCodecCapability{
MimeType: "video/H265",
ClockRate: 90000,
},
&format.H265{
PayloadTyp: 96,
},
},
{
"h264",
test.FormatH264,
Expand Down
16 changes: 2 additions & 14 deletions internal/protocols/webrtc/tracks_to_medias.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,9 @@
ret := make([]*description.Media, len(tracks))

for i, track := range tracks {
forma := track.Format()

var mediaType description.MediaType

switch forma.(type) {
case *format.AV1, *format.VP9, *format.VP8, *format.H264:
mediaType = description.MediaTypeVideo

default:
mediaType = description.MediaTypeAudio
}

ret[i] = &description.Media{
Type: mediaType,
Formats: []format.Format{forma},
Type: track.typ,
Formats: []format.Format{track.format},

Check warning on line 15 in internal/protocols/webrtc/tracks_to_medias.go

View check run for this annotation

Codecov / codecov/patch

internal/protocols/webrtc/tracks_to_medias.go#L14-L15

Added lines #L14 - L15 were not covered by tests
}
}

Expand Down
Loading