support reading and proxying VP9 tracks with HLS (#2162)

This commit is contained in:
Alessandro Ros 2023-08-06 21:10:16 +02:00 committed by GitHub
parent 9051ccc219
commit 40b4fa1e8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 15 deletions

View File

@ -28,7 +28,7 @@ Live streams can be published to the server with:
|[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), G726, G722, G711, LPCM and any RTP-compatible codec|
|[RTMP clients](#rtmp-clients)|RTMP, RTMPS, Enhanced RTMP|AV1, H265, H264|MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3)|
|[RTMP cameras and servers](#rtmp-cameras-and-servers)|RTMP, RTMPS, Enhanced RTMP|H264|MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3)|
|[HLS cameras and servers](#hls-cameras-and-servers)|Low-Latency HLS, MP4-based HLS, legacy HLS|AV1, H265, H264|Opus, MPEG-4 Audio (AAC)|
|[HLS cameras and servers](#hls-cameras-and-servers)|Low-Latency HLS, MP4-based HLS, legacy HLS|AV1, VP9, H265, H264|Opus, MPEG-4 Audio (AAC)|
|[UDP/MPEG-TS](#udpmpeg-ts)|Unicast, broadcast, multicast|H265, H264|Opus, MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3)|
|[Raspberry Pi Cameras](#raspberry-pi-cameras)||H264||
@ -40,7 +40,7 @@ And can be read from the server with:
|[WebRTC](#webrtc)|Browser-based, WHEP|AV1, VP9, VP8, H264|Opus, G722, G711|
|[RTSP](#rtsp)|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), G726, G722, G711, LPCM and any RTP-compatible codec|
|[RTMP](#rtmp)|RTMP, RTMPS, Enhanced RTMP|H264|MPEG-4 Audio (AAC), MPEG-1/2 Audio (MP3)|
|[HLS](#hls)|Low-Latency HLS, MP4-based HLS, legacy HLS|AV1, H265, H264|Opus, MPEG-4 Audio (AAC)|
|[HLS](#hls)|Low-Latency HLS, MP4-based HLS, legacy HLS|AV1, VP9, H265, H264|Opus, MPEG-4 Audio (AAC)|
**Features**

6
go.mod
View File

@ -6,9 +6,9 @@ require (
code.cloudfoundry.org/bytefmt v0.0.0
github.com/abema/go-mp4 v0.11.0
github.com/alecthomas/kong v0.8.0
github.com/bluenviron/gohlslib v0.3.1-0.20230806000705-4ca609772363
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806001215-926a452fb745
github.com/bluenviron/mediacommon v0.7.1-0.20230805234008-34d20294a26b
github.com/bluenviron/gohlslib v0.3.1-0.20230806182538-54b835e0ef2c
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806185830-e6e9e8490907
github.com/bluenviron/mediacommon v0.7.1-0.20230806185229-f060a1e5295b
github.com/datarhei/gosrt v0.5.3
github.com/fsnotify/fsnotify v1.6.0
github.com/gin-gonic/gin v1.9.1

12
go.sum
View File

@ -14,12 +14,12 @@ github.com/asticode/go-astits v1.12.0 h1:BiefTgVEyPgEB8nT6J+Sys/uxE4H/a04SW/aedp
github.com/asticode/go-astits v1.12.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c h1:8XZeJrs4+ZYhJeJ2aZxADI2tGADS15AzIF8MQ8XAhT4=
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c/go.mod h1:x1vxHcL/9AVzuk5HOloOEPrtJY0MaalYr78afXZ+pWI=
github.com/bluenviron/gohlslib v0.3.1-0.20230806000705-4ca609772363 h1:ysN/BZSY9Q7Ditvro4zvSLLYyxTPyiiVl0ALeY/rHHQ=
github.com/bluenviron/gohlslib v0.3.1-0.20230806000705-4ca609772363/go.mod h1:2aXz4lSl2pToXk9zYmWhdhR02OiRRZCQiFdrQcIWLBc=
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806001215-926a452fb745 h1:LR8F5ng75c9KxWLrPWj8bskXCR7AJXv8gm4duKfzUjc=
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806001215-926a452fb745/go.mod h1:7owCGeF8gQfziPCWL9UbL+Yqogl13gKJeRI8jhnpadg=
github.com/bluenviron/mediacommon v0.7.1-0.20230805234008-34d20294a26b h1:/csYQQDmZyXw0CVATJSPBkwT3JYap418W7LLX7mscxw=
github.com/bluenviron/mediacommon v0.7.1-0.20230805234008-34d20294a26b/go.mod h1:LR4w8cpvzo2ZcmBwXcentvBj7ZlyF9g9xP4dDbt8uJw=
github.com/bluenviron/gohlslib v0.3.1-0.20230806182538-54b835e0ef2c h1:wztDQy5iTijIZz4v+mkbJkTIHoQ/MHtdMSPirTQy5uQ=
github.com/bluenviron/gohlslib v0.3.1-0.20230806182538-54b835e0ef2c/go.mod h1:SoCWetcOsLi70kcUBBrckYFfmLPJuqmXVGP10OlEc70=
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806185830-e6e9e8490907 h1:EPRg+yYqp7eZr9ROvjSvHJf7TIcu31spCGKbjHzpilM=
github.com/bluenviron/gortsplib/v3 v3.9.1-0.20230806185830-e6e9e8490907/go.mod h1:tK2JtJRkKUIhmZEyRWCd8rtiqbirO4eMXt7fN5Yont4=
github.com/bluenviron/mediacommon v0.7.1-0.20230806185229-f060a1e5295b h1:53WQf0Kam0/Rj4bnTWhpo6n6cCrRE84tjf9xrwq8mWo=
github.com/bluenviron/mediacommon v0.7.1-0.20230806185229-f060a1e5295b/go.mod h1:LR4w8cpvzo2ZcmBwXcentvBj7ZlyF9g9xP4dDbt8uJw=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=

View File

@ -176,7 +176,7 @@ func TestHLSRead(t *testing.T) {
"#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=2\\.50000,CAN-SKIP-UNTIL=6\\.00000\n"+
"#EXT-X-PART-INF:PART-TARGET=1\\.00000\n"+
"#EXT-X-MEDIA-SEQUENCE:1\n"+
"#EXT-X-MAP:URI=\"init.mp4\"\n"+
"#EXT-X-MAP:URI=\".*?_init.mp4\"\n"+
"#EXT-X-GAP\n"+
"#EXTINF:1\\.00000,\n"+
"gap.mp4\n"+
@ -196,10 +196,10 @@ func TestHLSRead(t *testing.T) {
"#EXTINF:1\\.00000,\n"+
"gap.mp4\n"+
"#EXT-X-PROGRAM-DATE-TIME:.+?Z\n"+
"#EXT-X-PART:DURATION=1\\.00000,URI=\"part0.mp4\",INDEPENDENT=YES\n"+
"#EXT-X-PART:DURATION=1\\.00000,URI=\".*?_part0.mp4\",INDEPENDENT=YES\n"+
"#EXTINF:1\\.00000,\n"+
"seg7.mp4\n"+
"#EXT-X-PRELOAD-HINT:TYPE=PART,URI=\"part1.mp4\"\n", string(cnt))
".*?_seg7.mp4\n"+
"#EXT-X-PRELOAD-HINT:TYPE=PART,URI=\".*?_part1.mp4\"\n", string(cnt))
/*trak := <-c.track

View File

@ -371,6 +371,41 @@ func (m *hlsMuxer) createVideoTrack(stream *stream.Stream) (*media.Media, *gohls
}
}
var videoFormatVP9 *formats.VP9
videoMedia = stream.Medias().FindFormat(&videoFormatVP9)
if videoFormatVP9 != nil {
startPTSFilled := false
var startPTS time.Duration
stream.AddReader(m, videoMedia, videoFormatVP9, func(unit formatprocessor.Unit) {
m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitVP9)
if tunit.Frame == nil {
return nil
}
if !startPTSFilled {
startPTSFilled = true
startPTS = tunit.PTS
}
pts := tunit.PTS - startPTS
err := m.muxer.WriteVP9(tunit.NTP, pts, tunit.Frame)
if err != nil {
return fmt.Errorf("muxer error: %v", err)
}
return nil
})
})
return videoMedia, &gohlslib.Track{
Codec: &codecs.VP9{},
}
}
var videoFormatH265 *formats.H265
videoMedia = stream.Medias().FindFormat(&videoFormatH265)

View File

@ -92,6 +92,22 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
})
})
case *codecs.VP9:
medi = &media.Media{
Type: media.TypeVideo,
Formats: []formats.Format{&formats.VP9{}},
}
c.OnDataVP9(track, func(pts time.Duration, frame []byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitVP9{
BaseUnit: formatprocessor.BaseUnit{
NTP: time.Now(),
},
PTS: pts,
Frame: frame,
})
})
case *codecs.H264:
medi = &media.Media{
Type: media.TypeVideo,