Browse Source

hls source: support proxying H265 and Opus tracks

pull/1364/head
aler9 3 years ago
parent
commit
f837ba6a83
  1. 2
      README.md
  2. 24
      internal/core/hls_source.go
  3. 4
      internal/hls/codecparameters.go
  4. 12
      internal/hls/fmp4/boxes_h265.go
  5. 0
      internal/hls/fmp4/boxes_opus.go
  6. 3
      internal/hls/fmp4/init.go

2
README.md

@ -13,7 +13,7 @@ Live streams can be published to the server with: @@ -13,7 +13,7 @@ Live streams can be published to the server with:
|RTSP servers and cameras|UDP, UDP-Multicast, TCP, RTSPS|H264, H265, VP8, VP9, AV1, MPEG2, M-JPEG, MP3, MPEG4 Audio (AAC), Opus, G711, G722, LPCM and any RTP-compatible codec|
|RTMP clients (OBS Studio)|RTMP, RTMPS|H264, H265, MPEG4 Audio (AAC)|
|RTMP servers and cameras|RTMP, RTMPS|H264, MPEG4 Audio (AAC)|
|HLS servers and cameras|Low-Latency HLS, MP4-based HLS, legacy HLS|H264, MPEG4 Audio (AAC)|
|HLS servers and cameras|Low-Latency HLS, MP4-based HLS, legacy HLS|H264, H265, MPEG4 Audio (AAC), Opus|
|Raspberry Pi Cameras||H264|
And can be read from the server with:

24
internal/core/hls_source.go

@ -83,6 +83,18 @@ func (s *hlsSource) run(ctx context.Context) error { @@ -83,6 +83,18 @@ func (s *hlsSource) run(ctx context.Context) error {
}
})
case *format.H265:
c.OnData(track, func(pts time.Duration, dat interface{}) {
err := stream.writeData(medi, ctrack, &formatprocessor.DataH265{
PTS: pts,
AU: dat.([][]byte),
NTP: time.Now(),
})
if err != nil {
s.Log(logger.Warn, "%v", err)
}
})
case *format.MPEG4Audio:
c.OnData(track, func(pts time.Duration, dat interface{}) {
err := stream.writeData(medi, ctrack, &formatprocessor.DataMPEG4Audio{
@ -94,6 +106,18 @@ func (s *hlsSource) run(ctx context.Context) error { @@ -94,6 +106,18 @@ func (s *hlsSource) run(ctx context.Context) error {
s.Log(logger.Warn, "%v", err)
}
})
case *format.Opus:
c.OnData(track, func(pts time.Duration, dat interface{}) {
err := stream.writeData(medi, ctrack, &formatprocessor.DataOpus{
PTS: pts,
Frame: dat.([]byte),
NTP: time.Now(),
})
if err != nil {
s.Log(logger.Warn, "%v", err)
}
})
}
}

4
internal/hls/codecparameters.go

@ -39,7 +39,9 @@ func codecParametersGenerate(track format.Format) string { @@ -39,7 +39,9 @@ func codecParametersGenerate(track format.Format) string {
func codecParametersAreSupported(codecs string) bool {
for _, codec := range strings.Split(codecs, ",") {
if !strings.HasPrefix(codec, "avc1.") &&
!strings.HasPrefix(codec, "mp4a.") {
!strings.HasPrefix(codec, "hvc1.") &&
!strings.HasPrefix(codec, "mp4a.") &&
codec != "opus" {
return false
}
}

12
internal/hls/fmp4/boxes_h265.go

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
//nolint:gochecknoinits,revive,gocritic
package fmp4
import (
gomp4 "github.com/abema/go-mp4"
)
func BoxTypeHvc1() gomp4.BoxType { return gomp4.StrToBoxType("hvc1") }
func init() {
gomp4.AddAnyTypeBoxDef(&gomp4.VisualSampleEntry{}, BoxTypeHvc1())
}

0
internal/hls/fmp4/opus.go → internal/hls/fmp4/boxes_opus.go

3
internal/hls/fmp4/init.go

@ -76,7 +76,6 @@ func (i *Init) Unmarshal(byts []byte) error { @@ -76,7 +76,6 @@ func (i *Init) Unmarshal(byts []byte) error {
if state != waitingCodec {
return nil, fmt.Errorf("unexpected box 'avc1'")
}
state = waitingAvcC
case "avcC":
@ -116,7 +115,7 @@ func (i *Init) Unmarshal(byts []byte) error { @@ -116,7 +115,7 @@ func (i *Init) Unmarshal(byts []byte) error {
}
state = waitingTrak
case "hev1":
case "hev1", "hvc1":
if state != waitingCodec {
return nil, fmt.Errorf("unexpected box 'hev1'")
}

Loading…
Cancel
Save