move units into dedicated package (#2245)
Some checks reported warnings
lint / code (push) Has been cancelled
lint / mod-tidy (push) Has been cancelled
lint / apidocs (push) Has been cancelled
test / test64 (push) Has been cancelled
test / test32 (push) Has been cancelled
test / test_highlevel (push) Has been cancelled

needed by #2244
This commit is contained in:
Alessandro Ros
2023-08-25 18:11:02 +02:00
committed by GitHub
parent 23ddaac481
commit e0fb11040e
40 changed files with 390 additions and 318 deletions

View File

@@ -20,7 +20,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
src/internal/hls.min.js is Copyright (c) Dailymotion and is protected by internal/core/hls.min.js is Copyright (c) Dailymotion and is protected by
its own license (Apache License, Version 2.0) available at its own license (Apache License, Version 2.0) available at
https://github.com/video-dev/hls.js/blob/master/LICENSE https://github.com/video-dev/hls.js/blob/master/LICENSE

View File

@@ -565,7 +565,7 @@ srt://localhost:8890?streamid=publish:mystream:user:pass&pkt_size=1316
If you want to publish a stream by using a client in listening mode (i.e. with `mode=listener` appended to the URL), read the next section. If you want to publish a stream by using a client in listening mode (i.e. with `mode=listener` appended to the URL), read the next section.
Known clients that can publish with SRT are [FFmpeg](#ffmpeg), [Gstreamer](#gstreamer), [OBS Studio](#obs-studio). Known clients that can publish with SRT are [FFmpeg](#ffmpeg), [GStreamer](#gstreamer), [OBS Studio](#obs-studio).
#### SRT servers #### SRT servers
@@ -596,7 +596,7 @@ http://localhost:8889/mystream/whip
Depending on the network it may be difficult to establish a connection between server and clients, see [WebRTC-specific features](#webrtc-specific-features) for remediations. Depending on the network it may be difficult to establish a connection between server and clients, see [WebRTC-specific features](#webrtc-specific-features) for remediations.
Known clients that can publish with WebRTC and WHIP are [FFmpeg](#ffmpeg), [Gstreamer](#gstreamer), [OBS Studio](#obs-studio). Known clients that can publish with WebRTC and WHIP are [FFmpeg](#ffmpeg), [GStreamer](#gstreamer), [OBS Studio](#obs-studio).
#### WebRTC servers #### WebRTC servers
@@ -619,7 +619,7 @@ rtsp://localhost:8554/mystream
The resulting stream will be available in path `/mystream`. The resulting stream will be available in path `/mystream`.
Known clients that can publish with RTSP are [FFmpeg](#ffmpeg), [Gstreamer](#gstreamer), [OBS Studio](#obs-studio). Known clients that can publish with RTSP are [FFmpeg](#ffmpeg), [GStreamer](#gstreamer), [OBS Studio](#obs-studio).
#### RTSP cameras and servers #### RTSP cameras and servers
@@ -661,7 +661,7 @@ In case authentication is enabled, credentials can be passed to the server by us
rtmp://localhost/mystream?user=myuser&pass=mypass rtmp://localhost/mystream?user=myuser&pass=mypass
``` ```
Known clients that can publish with RTMP are [FFmpeg](#ffmpeg), [Gstreamer](#gstreamer), [OBS Studio](#obs-studio). Known clients that can publish with RTMP are [FFmpeg](#ffmpeg), [GStreamer](#gstreamer), [OBS Studio](#obs-studio).
#### RTMP cameras and servers #### RTMP cameras and servers
@@ -717,7 +717,7 @@ paths:
The resulting stream will be available in path `/mypath`. The resulting stream will be available in path `/mypath`.
Known clients that can publish with WebRTC and WHIP are [FFmpeg](#ffmpeg) and [Gstreamer](#gstreamer). Known clients that can publish with WebRTC and WHIP are [FFmpeg](#ffmpeg) and [GStreamer](#gstreamer).
## Read from the server ## Read from the server
@@ -842,7 +842,7 @@ If credentials are enabled, append username and password to `streamid`;
srt://localhost:8890?streamid=publish:mystream:user:pass srt://localhost:8890?streamid=publish:mystream:user:pass
``` ```
Known clients that can read with SRT are [FFmpeg](#ffmpeg-1), [Gstreamer](#gstreamer-1) and [VLC](#vlc). Known clients that can read with SRT are [FFmpeg](#ffmpeg-1), [GStreamer](#gstreamer-1) and [VLC](#vlc).
#### WebRTC #### WebRTC
@@ -860,7 +860,7 @@ http://localhost:8889/mystream/whep
Depending on the network it may be difficult to establish a connection between server and clients, see [WebRTC-specific features](#webrtc-specific-features) for remediations. Depending on the network it may be difficult to establish a connection between server and clients, see [WebRTC-specific features](#webrtc-specific-features) for remediations.
Known clients that can read with WebRTC and WHEP are [FFmpeg](#ffmpeg-1), [Gstreamer](#gstreamer-1) and [web browsers](#web-browsers-1). Known clients that can read with WebRTC and WHEP are [FFmpeg](#ffmpeg-1), [GStreamer](#gstreamer-1) and [web browsers](#web-browsers-1).
#### RTSP #### RTSP
@@ -870,7 +870,7 @@ RTSP is a protocol that allows to publish and read streams. It supports differen
rtsp://localhost:8554/mystream rtsp://localhost:8554/mystream
``` ```
Known clients that can read with RTSP are [FFmpeg](#ffmpeg-1), [Gstreamer](#gstreamer-1) and [VLC](#vlc). Known clients that can read with RTSP are [FFmpeg](#ffmpeg-1), [GStreamer](#gstreamer-1) and [VLC](#vlc).
##### Latency ##### Latency
@@ -894,7 +894,7 @@ In case authentication is enabled, credentials can be passed to the server by us
rtmp://localhost/mystream?user=myuser&pass=mypass rtmp://localhost/mystream?user=myuser&pass=mypass
``` ```
Known clients that can read with RTMP are [FFmpeg](#ffmpeg-1), [Gstreamer](#gstreamer-1) and [VLC](#vlc). Known clients that can read with RTMP are [FFmpeg](#ffmpeg-1), [GStreamer](#gstreamer-1) and [VLC](#vlc).
#### HLS #### HLS
@@ -923,7 +923,7 @@ ffmpeg -i rtsp://original-source \
-f rtsp rtsp://localhost:8554/mystream -f rtsp rtsp://localhost:8554/mystream
``` ```
Known clients that can read with HLS are [FFmpeg](#ffmpeg-1), [Gstreamer](#gstreamer-1), [VLC](#vlc) and [web browsers](#web-browsers-1). Known clients that can read with HLS are [FFmpeg](#ffmpeg-1), [GStreamer](#gstreamer-1), [VLC](#vlc) and [web browsers](#web-browsers-1).
##### LL-HLS ##### LL-HLS

View File

@@ -19,9 +19,9 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
const ( const (
@@ -343,9 +343,9 @@ func (m *hlsMuxer) createVideoTrack(stream *stream.Stream) (*media.Media, *gohls
startPTSFilled := false startPTSFilled := false
var startPTS time.Duration var startPTS time.Duration
stream.AddReader(m, videoMedia, videoFormatAV1, func(unit formatprocessor.Unit) { stream.AddReader(m, videoMedia, videoFormatAV1, func(u unit.Unit) {
m.ringBuffer.Push(func() error { m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitAV1) tunit := u.(*unit.AV1)
if tunit.TU == nil { if tunit.TU == nil {
return nil return nil
@@ -378,9 +378,9 @@ func (m *hlsMuxer) createVideoTrack(stream *stream.Stream) (*media.Media, *gohls
startPTSFilled := false startPTSFilled := false
var startPTS time.Duration var startPTS time.Duration
stream.AddReader(m, videoMedia, videoFormatVP9, func(unit formatprocessor.Unit) { stream.AddReader(m, videoMedia, videoFormatVP9, func(u unit.Unit) {
m.ringBuffer.Push(func() error { m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitVP9) tunit := u.(*unit.VP9)
if tunit.Frame == nil { if tunit.Frame == nil {
return nil return nil
@@ -413,9 +413,9 @@ func (m *hlsMuxer) createVideoTrack(stream *stream.Stream) (*media.Media, *gohls
startPTSFilled := false startPTSFilled := false
var startPTS time.Duration var startPTS time.Duration
stream.AddReader(m, videoMedia, videoFormatH265, func(unit formatprocessor.Unit) { stream.AddReader(m, videoMedia, videoFormatH265, func(u unit.Unit) {
m.ringBuffer.Push(func() error { m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitH265) tunit := u.(*unit.H265)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil
@@ -454,9 +454,9 @@ func (m *hlsMuxer) createVideoTrack(stream *stream.Stream) (*media.Media, *gohls
startPTSFilled := false startPTSFilled := false
var startPTS time.Duration var startPTS time.Duration
stream.AddReader(m, videoMedia, videoFormatH264, func(unit formatprocessor.Unit) { stream.AddReader(m, videoMedia, videoFormatH264, func(u unit.Unit) {
m.ringBuffer.Push(func() error { m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitH264) tunit := u.(*unit.H264)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil
@@ -498,9 +498,9 @@ func (m *hlsMuxer) createAudioTrack(stream *stream.Stream) (*media.Media, *gohls
audioStartPTSFilled := false audioStartPTSFilled := false
var audioStartPTS time.Duration var audioStartPTS time.Duration
stream.AddReader(m, audioMedia, audioFormatOpus, func(unit formatprocessor.Unit) { stream.AddReader(m, audioMedia, audioFormatOpus, func(u unit.Unit) {
m.ringBuffer.Push(func() error { m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitOpus) tunit := u.(*unit.Opus)
if !audioStartPTSFilled { if !audioStartPTSFilled {
audioStartPTSFilled = true audioStartPTSFilled = true
@@ -539,9 +539,9 @@ func (m *hlsMuxer) createAudioTrack(stream *stream.Stream) (*media.Media, *gohls
audioStartPTSFilled := false audioStartPTSFilled := false
var audioStartPTS time.Duration var audioStartPTS time.Duration
stream.AddReader(m, audioMedia, audioFormatMPEG4AudioGeneric, func(unit formatprocessor.Unit) { stream.AddReader(m, audioMedia, audioFormatMPEG4AudioGeneric, func(u unit.Unit) {
m.ringBuffer.Push(func() error { m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitMPEG4AudioGeneric) tunit := u.(*unit.MPEG4AudioGeneric)
if tunit.AUs == nil { if tunit.AUs == nil {
return nil return nil
@@ -582,9 +582,9 @@ func (m *hlsMuxer) createAudioTrack(stream *stream.Stream) (*media.Media, *gohls
audioStartPTSFilled := false audioStartPTSFilled := false
var audioStartPTS time.Duration var audioStartPTS time.Duration
stream.AddReader(m, audioMedia, audioFormatMPEG4AudioLATM, func(unit formatprocessor.Unit) { stream.AddReader(m, audioMedia, audioFormatMPEG4AudioLATM, func(u unit.Unit) {
m.ringBuffer.Push(func() error { m.ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitMPEG4AudioLATM) tunit := u.(*unit.MPEG4AudioLATM)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil

View File

@@ -11,9 +11,9 @@ import (
"github.com/bluenviron/gortsplib/v3/pkg/media" "github.com/bluenviron/gortsplib/v3/pkg/media"
"github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
type hlsSourceParent interface { type hlsSourceParent interface {
@@ -82,8 +82,8 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
} }
c.OnDataAV1(track, func(pts time.Duration, tu [][]byte) { c.OnDataAV1(track, func(pts time.Duration, tu [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitAV1{ stream.WriteUnit(medi, medi.Formats[0], &unit.AV1{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -98,8 +98,8 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
} }
c.OnDataVP9(track, func(pts time.Duration, frame []byte) { c.OnDataVP9(track, func(pts time.Duration, frame []byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitVP9{ stream.WriteUnit(medi, medi.Formats[0], &unit.VP9{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -119,8 +119,8 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
} }
c.OnDataH26x(track, func(pts time.Duration, dts time.Duration, au [][]byte) { c.OnDataH26x(track, func(pts time.Duration, dts time.Duration, au [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH264{ stream.WriteUnit(medi, medi.Formats[0], &unit.H264{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -140,8 +140,8 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
} }
c.OnDataH26x(track, func(pts time.Duration, dts time.Duration, au [][]byte) { c.OnDataH26x(track, func(pts time.Duration, dts time.Duration, au [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH265{ stream.WriteUnit(medi, medi.Formats[0], &unit.H265{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -162,8 +162,8 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
} }
c.OnDataMPEG4Audio(track, func(pts time.Duration, aus [][]byte) { c.OnDataMPEG4Audio(track, func(pts time.Duration, aus [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG4AudioGeneric{ stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG4AudioGeneric{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -181,8 +181,8 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
} }
c.OnDataOpus(track, func(pts time.Duration, packets [][]byte) { c.OnDataOpus(track, func(pts time.Duration, packets [][]byte) {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitOpus{ stream.WriteUnit(medi, medi.Formats[0], &unit.Opus{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,

View File

@@ -8,10 +8,10 @@ import (
"github.com/bluenviron/gortsplib/v3/pkg/media" "github.com/bluenviron/gortsplib/v3/pkg/media"
"github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/rpicamera" "github.com/bluenviron/mediamtx/internal/rpicamera"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
func paramsFromConf(cnf *conf.PathConf) rpicamera.Params { func paramsFromConf(cnf *conf.PathConf) rpicamera.Params {
@@ -98,8 +98,8 @@ func (s *rpiCameraSource) run(ctx context.Context, cnf *conf.PathConf, reloadCon
stream = res.stream stream = res.stream
} }
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH264{ stream.WriteUnit(medi, medi.Formats[0], &unit.H264{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: dts, PTS: dts,

View File

@@ -20,10 +20,10 @@ import (
"github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/externalcmd" "github.com/bluenviron/mediamtx/internal/externalcmd"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/rtmp" "github.com/bluenviron/mediamtx/internal/rtmp"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
const ( const (
@@ -338,9 +338,9 @@ func (c *rtmpConn) setupVideo(
var startPTS time.Duration var startPTS time.Duration
var videoDTSExtractor *h264.DTSExtractor var videoDTSExtractor *h264.DTSExtractor
stream.AddReader(c, videoMedia, videoFormatH264, func(unit formatprocessor.Unit) { stream.AddReader(c, videoMedia, videoFormatH264, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitH264) tunit := u.(*unit.H264)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil
@@ -427,9 +427,9 @@ func (c *rtmpConn) setupAudio(
startPTSFilled := false startPTSFilled := false
var startPTS time.Duration var startPTS time.Duration
stream.AddReader(c, audioMedia, audioFormatMPEG4Generic, func(unit formatprocessor.Unit) { stream.AddReader(c, audioMedia, audioFormatMPEG4Generic, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitMPEG4AudioGeneric) tunit := u.(*unit.MPEG4AudioGeneric)
if tunit.AUs == nil { if tunit.AUs == nil {
return nil return nil
@@ -481,9 +481,9 @@ func (c *rtmpConn) setupAudio(
startPTSFilled := false startPTSFilled := false
var startPTS time.Duration var startPTS time.Duration
stream.AddReader(c, audioMedia, audioFormatMPEG4AudioLATM, func(unit formatprocessor.Unit) { stream.AddReader(c, audioMedia, audioFormatMPEG4AudioLATM, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitMPEG4AudioLATM) tunit := u.(*unit.MPEG4AudioLATM)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil
@@ -521,9 +521,9 @@ func (c *rtmpConn) setupAudio(
startPTSFilled := false startPTSFilled := false
var startPTS time.Duration var startPTS time.Duration
stream.AddReader(c, audioMedia, audioFormatMPEG1, func(unit formatprocessor.Unit) { stream.AddReader(c, audioMedia, audioFormatMPEG1, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitMPEG1Audio) tunit := u.(*unit.MPEG1Audio)
if !startPTSFilled { if !startPTSFilled {
startPTSFilled = true startPTSFilled = true
@@ -624,8 +624,8 @@ func (c *rtmpConn) runPublish(conn *rtmp.Conn, u *url.URL) error {
switch videoFormat.(type) { switch videoFormat.(type) {
case *formats.AV1: case *formats.AV1:
r.OnDataAV1(func(pts time.Duration, tu [][]byte) { r.OnDataAV1(func(pts time.Duration, tu [][]byte) {
stream.WriteUnit(videoMedia, videoFormat, &formatprocessor.UnitAV1{ stream.WriteUnit(videoMedia, videoFormat, &unit.AV1{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -635,8 +635,8 @@ func (c *rtmpConn) runPublish(conn *rtmp.Conn, u *url.URL) error {
case *formats.VP9: case *formats.VP9:
r.OnDataVP9(func(pts time.Duration, frame []byte) { r.OnDataVP9(func(pts time.Duration, frame []byte) {
stream.WriteUnit(videoMedia, videoFormat, &formatprocessor.UnitVP9{ stream.WriteUnit(videoMedia, videoFormat, &unit.VP9{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -646,8 +646,8 @@ func (c *rtmpConn) runPublish(conn *rtmp.Conn, u *url.URL) error {
case *formats.H265: case *formats.H265:
r.OnDataH265(func(pts time.Duration, au [][]byte) { r.OnDataH265(func(pts time.Duration, au [][]byte) {
stream.WriteUnit(videoMedia, videoFormat, &formatprocessor.UnitH265{ stream.WriteUnit(videoMedia, videoFormat, &unit.H265{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -657,8 +657,8 @@ func (c *rtmpConn) runPublish(conn *rtmp.Conn, u *url.URL) error {
case *formats.H264: case *formats.H264:
r.OnDataH264(func(pts time.Duration, au [][]byte) { r.OnDataH264(func(pts time.Duration, au [][]byte) {
stream.WriteUnit(videoMedia, videoFormat, &formatprocessor.UnitH264{ stream.WriteUnit(videoMedia, videoFormat, &unit.H264{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -681,8 +681,8 @@ func (c *rtmpConn) runPublish(conn *rtmp.Conn, u *url.URL) error {
switch audioFormat.(type) { switch audioFormat.(type) {
case *formats.MPEG4AudioGeneric: case *formats.MPEG4AudioGeneric:
r.OnDataMPEG4Audio(func(pts time.Duration, au []byte) { r.OnDataMPEG4Audio(func(pts time.Duration, au []byte) {
stream.WriteUnit(audioMedia, audioFormat, &formatprocessor.UnitMPEG4AudioGeneric{ stream.WriteUnit(audioMedia, audioFormat, &unit.MPEG4AudioGeneric{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -692,8 +692,8 @@ func (c *rtmpConn) runPublish(conn *rtmp.Conn, u *url.URL) error {
case *formats.MPEG1Audio: case *formats.MPEG1Audio:
r.OnDataMPEG1Audio(func(pts time.Duration, frame []byte) { r.OnDataMPEG1Audio(func(pts time.Duration, frame []byte) {
stream.WriteUnit(audioMedia, audioFormat, &formatprocessor.UnitMPEG1Audio{ stream.WriteUnit(audioMedia, audioFormat, &unit.MPEG1Audio{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,

View File

@@ -12,10 +12,10 @@ import (
"github.com/bluenviron/gortsplib/v3/pkg/media" "github.com/bluenviron/gortsplib/v3/pkg/media"
"github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/rtmp" "github.com/bluenviron/mediamtx/internal/rtmp"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
type rtmpSourceParent interface { type rtmpSourceParent interface {
@@ -126,8 +126,8 @@ func (s *rtmpSource) runReader(u *url.URL, nconn net.Conn) error {
switch videoFormat.(type) { switch videoFormat.(type) {
case *formats.H264: case *formats.H264:
mc.OnDataH264(func(pts time.Duration, au [][]byte) { mc.OnDataH264(func(pts time.Duration, au [][]byte) {
stream.WriteUnit(videoMedia, videoFormat, &formatprocessor.UnitH264{ stream.WriteUnit(videoMedia, videoFormat, &unit.H264{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -150,8 +150,8 @@ func (s *rtmpSource) runReader(u *url.URL, nconn net.Conn) error {
switch audioFormat.(type) { switch audioFormat.(type) {
case *formats.MPEG4AudioGeneric: case *formats.MPEG4AudioGeneric:
mc.OnDataMPEG4Audio(func(pts time.Duration, au []byte) { mc.OnDataMPEG4Audio(func(pts time.Duration, au []byte) {
stream.WriteUnit(audioMedia, audioFormat, &formatprocessor.UnitMPEG4AudioGeneric{ stream.WriteUnit(audioMedia, audioFormat, &unit.MPEG4AudioGeneric{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,
@@ -161,8 +161,8 @@ func (s *rtmpSource) runReader(u *url.URL, nconn net.Conn) error {
case *formats.MPEG1Audio: case *formats.MPEG1Audio:
mc.OnDataMPEG1Audio(func(pts time.Duration, frame []byte) { mc.OnDataMPEG1Audio(func(pts time.Duration, frame []byte) {
stream.WriteUnit(audioMedia, audioFormat, &formatprocessor.UnitMPEG1Audio{ stream.WriteUnit(audioMedia, audioFormat, &unit.MPEG1Audio{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: pts, PTS: pts,

View File

@@ -21,9 +21,9 @@ import (
"github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/externalcmd" "github.com/bluenviron/mediamtx/internal/externalcmd"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
func durationGoToMPEGTS(v time.Duration) int64 { func durationGoToMPEGTS(v time.Duration) int64 {
@@ -260,8 +260,8 @@ func (c *srtConn) runPublishReader(sconn srt.Conn, path *path) error {
} }
r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error { r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH264{ stream.WriteUnit(medi, medi.Formats[0], &unit.H264{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -279,8 +279,8 @@ func (c *srtConn) runPublishReader(sconn srt.Conn, path *path) error {
} }
r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error { r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH265{ stream.WriteUnit(medi, medi.Formats[0], &unit.H265{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -302,8 +302,8 @@ func (c *srtConn) runPublishReader(sconn srt.Conn, path *path) error {
} }
r.OnDataMPEG4Audio(track, func(pts int64, aus [][]byte) error { r.OnDataMPEG4Audio(track, func(pts int64, aus [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG4AudioGeneric{ stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG4AudioGeneric{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -322,8 +322,8 @@ func (c *srtConn) runPublishReader(sconn srt.Conn, path *path) error {
} }
r.OnDataOpus(track, func(pts int64, packets [][]byte) error { r.OnDataOpus(track, func(pts int64, packets [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitOpus{ stream.WriteUnit(medi, medi.Formats[0], &unit.Opus{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -339,8 +339,8 @@ func (c *srtConn) runPublishReader(sconn srt.Conn, path *path) error {
} }
r.OnDataMPEG1Audio(track, func(pts int64, frames [][]byte) error { r.OnDataMPEG1Audio(track, func(pts int64, frames [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG1Audio{ stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG1Audio{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -459,9 +459,9 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
randomAccessReceived := false randomAccessReceived := false
dtsExtractor := h265.NewDTSExtractor() dtsExtractor := h265.NewDTSExtractor()
res.stream.AddReader(c, medi, format, func(unit formatprocessor.Unit) { res.stream.AddReader(c, medi, format, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitH265) tunit := u.(*unit.H265)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil
} }
@@ -523,9 +523,9 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
firstIDRReceived := false firstIDRReceived := false
dtsExtractor := h264.NewDTSExtractor() dtsExtractor := h264.NewDTSExtractor()
res.stream.AddReader(c, medi, format, func(unit formatprocessor.Unit) { res.stream.AddReader(c, medi, format, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitH264) tunit := u.(*unit.H264)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil
} }
@@ -579,9 +579,9 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
var startPTS time.Duration var startPTS time.Duration
startPTSFilled := false startPTSFilled := false
res.stream.AddReader(c, medi, format, func(unit formatprocessor.Unit) { res.stream.AddReader(c, medi, format, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitMPEG4AudioGeneric) tunit := u.(*unit.MPEG4AudioGeneric)
if tunit.AUs == nil { if tunit.AUs == nil {
return nil return nil
} }
@@ -619,9 +619,9 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
var startPTS time.Duration var startPTS time.Duration
startPTSFilled := false startPTSFilled := false
res.stream.AddReader(c, medi, format, func(unit formatprocessor.Unit) { res.stream.AddReader(c, medi, format, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitMPEG4AudioLATM) tunit := u.(*unit.MPEG4AudioLATM)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil
} }
@@ -662,9 +662,9 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
var startPTS time.Duration var startPTS time.Duration
startPTSFilled := false startPTSFilled := false
res.stream.AddReader(c, medi, format, func(unit formatprocessor.Unit) { res.stream.AddReader(c, medi, format, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitOpus) tunit := u.(*unit.Opus)
if tunit.Packets == nil { if tunit.Packets == nil {
return nil return nil
} }
@@ -697,9 +697,9 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
var startPTS time.Duration var startPTS time.Duration
startPTSFilled := false startPTSFilled := false
res.stream.AddReader(c, medi, format, func(unit formatprocessor.Unit) { res.stream.AddReader(c, medi, format, func(u unit.Unit) {
ringBuffer.Push(func() error { ringBuffer.Push(func() error {
tunit := unit.(*formatprocessor.UnitMPEG1Audio) tunit := u.(*unit.MPEG1Audio)
if tunit.Frames == nil { if tunit.Frames == nil {
return nil return nil
} }

View File

@@ -11,9 +11,9 @@ import (
"github.com/datarhei/gosrt" "github.com/datarhei/gosrt"
"github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
type srtSourceParent interface { type srtSourceParent interface {
@@ -116,8 +116,8 @@ func (s *srtSource) runReader(sconn srt.Conn) error {
} }
r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error { r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH264{ stream.WriteUnit(medi, medi.Formats[0], &unit.H264{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -135,8 +135,8 @@ func (s *srtSource) runReader(sconn srt.Conn) error {
} }
r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error { r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH265{ stream.WriteUnit(medi, medi.Formats[0], &unit.H265{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -158,8 +158,8 @@ func (s *srtSource) runReader(sconn srt.Conn) error {
} }
r.OnDataMPEG4Audio(track, func(pts int64, aus [][]byte) error { r.OnDataMPEG4Audio(track, func(pts int64, aus [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG4AudioGeneric{ stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG4AudioGeneric{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -178,8 +178,8 @@ func (s *srtSource) runReader(sconn srt.Conn) error {
} }
r.OnDataOpus(track, func(pts int64, packets [][]byte) error { r.OnDataOpus(track, func(pts int64, packets [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitOpus{ stream.WriteUnit(medi, medi.Formats[0], &unit.Opus{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -195,8 +195,8 @@ func (s *srtSource) runReader(sconn srt.Conn) error {
} }
r.OnDataMPEG1Audio(track, func(pts int64, frames [][]byte) error { r.OnDataMPEG1Audio(track, func(pts int64, frames [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG1Audio{ stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG1Audio{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),

View File

@@ -12,9 +12,9 @@ import (
"golang.org/x/net/ipv4" "golang.org/x/net/ipv4"
"github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
const ( const (
@@ -165,8 +165,8 @@ func (s *udpSource) runReader(pc net.PacketConn) error {
} }
r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error { r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH264{ stream.WriteUnit(medi, medi.Formats[0], &unit.H264{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -184,8 +184,8 @@ func (s *udpSource) runReader(pc net.PacketConn) error {
} }
r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error { r.OnDataH26x(track, func(pts int64, _ int64, au [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitH265{ stream.WriteUnit(medi, medi.Formats[0], &unit.H265{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -207,8 +207,8 @@ func (s *udpSource) runReader(pc net.PacketConn) error {
} }
r.OnDataMPEG4Audio(track, func(pts int64, aus [][]byte) error { r.OnDataMPEG4Audio(track, func(pts int64, aus [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG4AudioGeneric{ stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG4AudioGeneric{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -227,8 +227,8 @@ func (s *udpSource) runReader(pc net.PacketConn) error {
} }
r.OnDataOpus(track, func(pts int64, packets [][]byte) error { r.OnDataOpus(track, func(pts int64, packets [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitOpus{ stream.WriteUnit(medi, medi.Formats[0], &unit.Opus{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),
@@ -244,8 +244,8 @@ func (s *udpSource) runReader(pc net.PacketConn) error {
} }
r.OnDataMPEG1Audio(track, func(pts int64, frames [][]byte) error { r.OnDataMPEG1Audio(track, func(pts int64, frames [][]byte) error {
stream.WriteUnit(medi, medi.Formats[0], &formatprocessor.UnitMPEG1Audio{ stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG1Audio{
BaseUnit: formatprocessor.BaseUnit{ Base: unit.Base{
NTP: time.Now(), NTP: time.Now(),
}, },
PTS: decodeTime(pts), PTS: decodeTime(pts),

View File

@@ -14,8 +14,8 @@ import (
"github.com/bluenviron/gortsplib/v3/pkg/ringbuffer" "github.com/bluenviron/gortsplib/v3/pkg/ringbuffer"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/stream" "github.com/bluenviron/mediamtx/internal/stream"
"github.com/bluenviron/mediamtx/internal/unit"
) )
type webRTCOutgoingTrack struct { type webRTCOutgoingTrack struct {
@@ -23,7 +23,7 @@ type webRTCOutgoingTrack struct {
media *media.Media media *media.Media
format formats.Format format formats.Format
track *webrtc.TrackLocalStaticRTP track *webrtc.TrackLocalStaticRTP
cb func(formatprocessor.Unit) error cb func(unit.Unit) error
} }
func newWebRTCOutgoingTrackVideo(medias media.Medias) (*webRTCOutgoingTrack, error) { func newWebRTCOutgoingTrackVideo(medias media.Medias) (*webRTCOutgoingTrack, error) {
@@ -56,8 +56,8 @@ func newWebRTCOutgoingTrackVideo(medias media.Medias) (*webRTCOutgoingTrack, err
media: videoMedia, media: videoMedia,
format: av1Format, format: av1Format,
track: webRTCTrak, track: webRTCTrak,
cb: func(unit formatprocessor.Unit) error { cb: func(u unit.Unit) error {
tunit := unit.(*formatprocessor.UnitAV1) tunit := u.(*unit.AV1)
if tunit.TU == nil { if tunit.TU == nil {
return nil return nil
@@ -106,8 +106,8 @@ func newWebRTCOutgoingTrackVideo(medias media.Medias) (*webRTCOutgoingTrack, err
media: videoMedia, media: videoMedia,
format: vp9Format, format: vp9Format,
track: webRTCTrak, track: webRTCTrak,
cb: func(unit formatprocessor.Unit) error { cb: func(u unit.Unit) error {
tunit := unit.(*formatprocessor.UnitVP9) tunit := u.(*unit.VP9)
if tunit.Frame == nil { if tunit.Frame == nil {
return nil return nil
@@ -156,8 +156,8 @@ func newWebRTCOutgoingTrackVideo(medias media.Medias) (*webRTCOutgoingTrack, err
media: videoMedia, media: videoMedia,
format: vp8Format, format: vp8Format,
track: webRTCTrak, track: webRTCTrak,
cb: func(unit formatprocessor.Unit) error { cb: func(u unit.Unit) error {
tunit := unit.(*formatprocessor.UnitVP8) tunit := u.(*unit.VP8)
if tunit.Frame == nil { if tunit.Frame == nil {
return nil return nil
@@ -209,8 +209,8 @@ func newWebRTCOutgoingTrackVideo(medias media.Medias) (*webRTCOutgoingTrack, err
media: videoMedia, media: videoMedia,
format: h264Format, format: h264Format,
track: webRTCTrak, track: webRTCTrak,
cb: func(unit formatprocessor.Unit) error { cb: func(u unit.Unit) error {
tunit := unit.(*formatprocessor.UnitH264) tunit := u.(*unit.H264)
if tunit.AU == nil { if tunit.AU == nil {
return nil return nil
@@ -265,8 +265,8 @@ func newWebRTCOutgoingTrackAudio(medias media.Medias) (*webRTCOutgoingTrack, err
media: audioMedia, media: audioMedia,
format: opusFormat, format: opusFormat,
track: webRTCTrak, track: webRTCTrak,
cb: func(unit formatprocessor.Unit) error { cb: func(u unit.Unit) error {
for _, pkt := range unit.GetRTPPackets() { for _, pkt := range u.GetRTPPackets() {
webRTCTrak.WriteRTP(pkt) //nolint:errcheck webRTCTrak.WriteRTP(pkt) //nolint:errcheck
} }
@@ -295,8 +295,8 @@ func newWebRTCOutgoingTrackAudio(medias media.Medias) (*webRTCOutgoingTrack, err
media: audioMedia, media: audioMedia,
format: g722Format, format: g722Format,
track: webRTCTrak, track: webRTCTrak,
cb: func(unit formatprocessor.Unit) error { cb: func(u unit.Unit) error {
for _, pkt := range unit.GetRTPPackets() { for _, pkt := range u.GetRTPPackets() {
webRTCTrak.WriteRTP(pkt) //nolint:errcheck webRTCTrak.WriteRTP(pkt) //nolint:errcheck
} }
@@ -332,8 +332,8 @@ func newWebRTCOutgoingTrackAudio(medias media.Medias) (*webRTCOutgoingTrack, err
media: audioMedia, media: audioMedia,
format: g711Format, format: g711Format,
track: webRTCTrak, track: webRTCTrak,
cb: func(unit formatprocessor.Unit) error { cb: func(u unit.Unit) error {
for _, pkt := range unit.GetRTPPackets() { for _, pkt := range u.GetRTPPackets() {
webRTCTrak.WriteRTP(pkt) //nolint:errcheck webRTCTrak.WriteRTP(pkt) //nolint:errcheck
} }
@@ -363,9 +363,9 @@ func (t *webRTCOutgoingTrack) start(
} }
}() }()
stream.AddReader(r, t.media, t.format, func(unit formatprocessor.Unit) { stream.AddReader(r, t.media, t.format, func(u unit.Unit) {
ringBuffer.Push(func() { ringBuffer.Push(func() {
err := t.cb(unit) err := t.cb(u)
if err != nil { if err != nil {
select { select {
case writeError <- err: case writeError <- err:

View File

@@ -9,15 +9,9 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// UnitAV1 is an AV1 data unit.
type UnitAV1 struct {
BaseUnit
PTS time.Duration
TU [][]byte
}
type formatProcessorAV1 struct { type formatProcessorAV1 struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.AV1 format *formats.AV1
@@ -56,8 +50,8 @@ func (t *formatProcessorAV1) createEncoder() error {
return t.encoder.Init() return t.encoder.Init()
} }
func (t *formatProcessorAV1) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorAV1) Process(u unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitAV1) tunit := u.(*unit.AV1)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -108,9 +102,9 @@ func (t *formatProcessorAV1) Process(unit Unit, hasNonRTSPReaders bool) error {
return nil return nil
} }
func (t *formatProcessorAV1) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorAV1) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitAV1{ return &unit.AV1{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -8,13 +8,9 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// UnitGeneric is a generic data unit.
type UnitGeneric struct {
BaseUnit
}
type formatProcessorGeneric struct { type formatProcessorGeneric struct {
udpMaxPayloadSize int udpMaxPayloadSize int
} }
@@ -34,8 +30,8 @@ func newGeneric(
}, nil }, nil
} }
func (t *formatProcessorGeneric) Process(unit Unit, _ bool) error { func (t *formatProcessorGeneric) Process(u unit.Unit, _ bool) error {
tunit := unit.(*UnitGeneric) tunit := u.(*unit.Generic)
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -51,9 +47,9 @@ func (t *formatProcessorGeneric) Process(unit Unit, _ bool) error {
return nil return nil
} }
func (t *formatProcessorGeneric) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorGeneric) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitGeneric{ return &unit.Generic{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -6,6 +6,8 @@ import (
"github.com/bluenviron/gortsplib/v3/pkg/formats" "github.com/bluenviron/gortsplib/v3/pkg/formats"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/bluenviron/mediamtx/internal/unit"
) )
func TestGenericRemovePadding(t *testing.T) { func TestGenericRemovePadding(t *testing.T) {
@@ -33,8 +35,8 @@ func TestGenericRemovePadding(t *testing.T) {
PaddingSize: 20, PaddingSize: 20,
} }
err = p.Process(&UnitGeneric{ err = p.Process(&unit.Generic{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
}, },
}, false) }, false)

View File

@@ -10,6 +10,7 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// extract SPS and PPS without decoding RTP packets // extract SPS and PPS without decoding RTP packets
@@ -69,13 +70,6 @@ func rtpH264ExtractSPSPPS(pkt *rtp.Packet) ([]byte, []byte) {
} }
} }
// UnitH264 is a H264 data unit.
type UnitH264 struct {
BaseUnit
PTS time.Duration
AU [][]byte
}
type formatProcessorH264 struct { type formatProcessorH264 struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.H264 format *formats.H264
@@ -230,8 +224,8 @@ func (t *formatProcessorH264) remuxAccessUnit(au [][]byte) [][]byte {
return filteredNALUs return filteredNALUs
} }
func (t *formatProcessorH264) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorH264) Process(u unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitH264) tunit := u.(*unit.H264)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -304,9 +298,9 @@ func (t *formatProcessorH264) Process(unit Unit, hasNonRTSPReaders bool) error {
return nil return nil
} }
func (t *formatProcessorH264) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorH264) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitH264{ return &unit.H264{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -8,6 +8,8 @@ import (
"github.com/bluenviron/mediacommon/pkg/codecs/h264" "github.com/bluenviron/mediacommon/pkg/codecs/h264"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/bluenviron/mediamtx/internal/unit"
) )
func TestH264DynamicParams(t *testing.T) { func TestH264DynamicParams(t *testing.T) {
@@ -25,8 +27,8 @@ func TestH264DynamicParams(t *testing.T) {
pkts, err := enc.Encode([][]byte{{byte(h264.NALUTypeIDR)}}, 0) pkts, err := enc.Encode([][]byte{{byte(h264.NALUTypeIDR)}}, 0)
require.NoError(t, err) require.NoError(t, err)
data := &UnitH264{ data := &unit.H264{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
} }
@@ -40,8 +42,8 @@ func TestH264DynamicParams(t *testing.T) {
pkts, err = enc.Encode([][]byte{{7, 4, 5, 6}}, 0) // SPS pkts, err = enc.Encode([][]byte{{7, 4, 5, 6}}, 0) // SPS
require.NoError(t, err) require.NoError(t, err)
err = p.Process(&UnitH264{ err = p.Process(&unit.H264{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
}, false) }, false)
@@ -50,8 +52,8 @@ func TestH264DynamicParams(t *testing.T) {
pkts, err = enc.Encode([][]byte{{8, 1}}, 0) // PPS pkts, err = enc.Encode([][]byte{{8, 1}}, 0) // PPS
require.NoError(t, err) require.NoError(t, err)
err = p.Process(&UnitH264{ err = p.Process(&unit.H264{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
}, false) }, false)
@@ -63,8 +65,8 @@ func TestH264DynamicParams(t *testing.T) {
pkts, err = enc.Encode([][]byte{{byte(h264.NALUTypeIDR)}}, 0) pkts, err = enc.Encode([][]byte{{byte(h264.NALUTypeIDR)}}, 0)
require.NoError(t, err) require.NoError(t, err)
data = &UnitH264{ data = &unit.H264{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
} }
@@ -129,8 +131,8 @@ func TestH264OversizedPackets(t *testing.T) {
Payload: []byte{0x1c, 0b01000000, 0x01, 0x02, 0x03, 0x04}, Payload: []byte{0x1c, 0b01000000, 0x01, 0x02, 0x03, 0x04},
}, },
} { } {
data := &UnitH264{ data := &unit.H264{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
}, },
} }
@@ -192,7 +194,7 @@ func TestH264EmptyPacket(t *testing.T) {
p, err := New(1472, forma, true, nil) p, err := New(1472, forma, true, nil)
require.NoError(t, err) require.NoError(t, err)
unit := &UnitH264{ unit := &unit.H264{
AU: [][]byte{ AU: [][]byte{
{0x07, 0x01, 0x02, 0x03}, // SPS {0x07, 0x01, 0x02, 0x03}, // SPS
{0x08, 0x01, 0x02}, // PPS {0x08, 0x01, 0x02}, // PPS

View File

@@ -10,6 +10,7 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// extract VPS, SPS and PPS without decoding RTP packets // extract VPS, SPS and PPS without decoding RTP packets
@@ -76,13 +77,6 @@ func rtpH265ExtractVPSSPSPPS(pkt *rtp.Packet) ([]byte, []byte, []byte) {
} }
} }
// UnitH265 is a H265 data unit.
type UnitH265 struct {
BaseUnit
PTS time.Duration
AU [][]byte
}
type formatProcessorH265 struct { type formatProcessorH265 struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.H265 format *formats.H265
@@ -252,8 +246,8 @@ func (t *formatProcessorH265) remuxAccessUnit(au [][]byte) [][]byte {
return filteredNALUs return filteredNALUs
} }
func (t *formatProcessorH265) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorH265) Process(u unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitH265) tunit := u.(*unit.H265)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -326,9 +320,9 @@ func (t *formatProcessorH265) Process(unit Unit, hasNonRTSPReaders bool) error {
return nil return nil
} }
func (t *formatProcessorH265) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorH265) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitH265{ return &unit.H265{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -8,6 +8,8 @@ import (
"github.com/bluenviron/mediacommon/pkg/codecs/h265" "github.com/bluenviron/mediacommon/pkg/codecs/h265"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/bluenviron/mediamtx/internal/unit"
) )
func TestH265DynamicParams(t *testing.T) { func TestH265DynamicParams(t *testing.T) {
@@ -24,8 +26,8 @@ func TestH265DynamicParams(t *testing.T) {
pkts, err := enc.Encode([][]byte{{byte(h265.NALUType_CRA_NUT) << 1, 0}}, 0) pkts, err := enc.Encode([][]byte{{byte(h265.NALUType_CRA_NUT) << 1, 0}}, 0)
require.NoError(t, err) require.NoError(t, err)
data := &UnitH265{ data := &unit.H265{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
} }
@@ -39,8 +41,8 @@ func TestH265DynamicParams(t *testing.T) {
pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_VPS_NUT) << 1, 1, 2, 3}}, 0) pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_VPS_NUT) << 1, 1, 2, 3}}, 0)
require.NoError(t, err) require.NoError(t, err)
err = p.Process(&UnitH265{ err = p.Process(&unit.H265{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
}, false) }, false)
@@ -49,8 +51,8 @@ func TestH265DynamicParams(t *testing.T) {
pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_SPS_NUT) << 1, 4, 5, 6}}, 0) pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_SPS_NUT) << 1, 4, 5, 6}}, 0)
require.NoError(t, err) require.NoError(t, err)
err = p.Process(&UnitH265{ err = p.Process(&unit.H265{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
}, false) }, false)
@@ -59,8 +61,8 @@ func TestH265DynamicParams(t *testing.T) {
pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_PPS_NUT) << 1, 7, 8, 9}}, 0) pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_PPS_NUT) << 1, 7, 8, 9}}, 0)
require.NoError(t, err) require.NoError(t, err)
err = p.Process(&UnitH265{ err = p.Process(&unit.H265{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
}, false) }, false)
@@ -73,8 +75,8 @@ func TestH265DynamicParams(t *testing.T) {
pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_CRA_NUT) << 1, 0}}, 0) pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_CRA_NUT) << 1, 0}}, 0)
require.NoError(t, err) require.NoError(t, err)
data = &UnitH265{ data = &unit.H265{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkts[0]}, RTPPackets: []*rtp.Packet{pkts[0]},
}, },
} }
@@ -128,8 +130,8 @@ func TestH265OversizedPackets(t *testing.T) {
Payload: bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04}, 2000/4), Payload: bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04}, 2000/4),
}, },
} { } {
data := &UnitH265{ data := &unit.H265{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
}, },
} }
@@ -190,7 +192,7 @@ func TestH265EmptyPacket(t *testing.T) {
p, err := New(1472, forma, true, nil) p, err := New(1472, forma, true, nil)
require.NoError(t, err) require.NoError(t, err)
unit := &UnitH265{ unit := &unit.H265{
AU: [][]byte{ AU: [][]byte{
{byte(h265.NALUType_VPS_NUT) << 1, 10, 11, 12}, // VPS {byte(h265.NALUType_VPS_NUT) << 1, 10, 11, 12}, // VPS
{byte(h265.NALUType_SPS_NUT) << 1, 13, 14, 15}, // SPS {byte(h265.NALUType_SPS_NUT) << 1, 13, 14, 15}, // SPS

View File

@@ -9,15 +9,9 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// UnitMPEG1Audio is a MPEG-1/2 Audio data unit.
type UnitMPEG1Audio struct {
BaseUnit
PTS time.Duration
Frames [][]byte
}
type formatProcessorMPEG1Audio struct { type formatProcessorMPEG1Audio struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.MPEG1Audio format *formats.MPEG1Audio
@@ -53,8 +47,8 @@ func (t *formatProcessorMPEG1Audio) createEncoder() error {
return t.encoder.Init() return t.encoder.Init()
} }
func (t *formatProcessorMPEG1Audio) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorMPEG1Audio) Process(u unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitMPEG1Audio) tunit := u.(*unit.MPEG1Audio)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -104,9 +98,9 @@ func (t *formatProcessorMPEG1Audio) Process(unit Unit, hasNonRTSPReaders bool) e
return nil return nil
} }
func (t *formatProcessorMPEG1Audio) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorMPEG1Audio) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitMPEG1Audio{ return &unit.MPEG1Audio{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -9,15 +9,9 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// UnitMPEG4AudioGeneric is a MPEG-4 Audio data unit.
type UnitMPEG4AudioGeneric struct {
BaseUnit
PTS time.Duration
AUs [][]byte
}
type formatProcessorMPEG4AudioGeneric struct { type formatProcessorMPEG4AudioGeneric struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.MPEG4Audio format *formats.MPEG4Audio
@@ -58,8 +52,8 @@ func (t *formatProcessorMPEG4AudioGeneric) createEncoder() error {
return t.encoder.Init() return t.encoder.Init()
} }
func (t *formatProcessorMPEG4AudioGeneric) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorMPEG4AudioGeneric) Process(u unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitMPEG4AudioGeneric) tunit := u.(*unit.MPEG4AudioGeneric)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -109,9 +103,9 @@ func (t *formatProcessorMPEG4AudioGeneric) Process(unit Unit, hasNonRTSPReaders
return nil return nil
} }
func (t *formatProcessorMPEG4AudioGeneric) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorMPEG4AudioGeneric) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitMPEG4AudioGeneric{ return &unit.MPEG4AudioGeneric{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -9,15 +9,9 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// UnitMPEG4AudioLATM is a MPEG-4 Audio data unit.
type UnitMPEG4AudioLATM struct {
BaseUnit
PTS time.Duration
AU []byte
}
type formatProcessorMPEG4AudioLATM struct { type formatProcessorMPEG4AudioLATM struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.MPEG4AudioLATM format *formats.MPEG4AudioLATM
@@ -54,8 +48,8 @@ func (t *formatProcessorMPEG4AudioLATM) createEncoder() error {
return t.encoder.Init() return t.encoder.Init()
} }
func (t *formatProcessorMPEG4AudioLATM) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorMPEG4AudioLATM) Process(u unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitMPEG4AudioLATM) tunit := u.(*unit.MPEG4AudioLATM)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -105,9 +99,9 @@ func (t *formatProcessorMPEG4AudioLATM) Process(unit Unit, hasNonRTSPReaders boo
return nil return nil
} }
func (t *formatProcessorMPEG4AudioLATM) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorMPEG4AudioLATM) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitMPEG4AudioLATM{ return &unit.MPEG4AudioLATM{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -10,15 +10,9 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// UnitOpus is a Opus data unit.
type UnitOpus struct {
BaseUnit
PTS time.Duration
Packets [][]byte
}
type formatProcessorOpus struct { type formatProcessorOpus struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.Opus format *formats.Opus
@@ -56,8 +50,8 @@ func (t *formatProcessorOpus) createEncoder() error {
return t.encoder.Init() return t.encoder.Init()
} }
func (t *formatProcessorOpus) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorOpus) Process(u unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitOpus) tunit := u.(*unit.Opus)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -111,9 +105,9 @@ func (t *formatProcessorOpus) Process(unit Unit, hasNonRTSPReaders bool) error {
return nil return nil
} }
func (t *formatProcessorOpus) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorOpus) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitOpus{ return &unit.Opus{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -8,15 +8,16 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// Processor cleans and normalizes streams. // Processor cleans and normalizes streams.
type Processor interface { type Processor interface {
// cleans and normalizes a data unit. // cleans and normalizes a data unit.
Process(Unit, bool) error Process(unit.Unit, bool) error
// wraps a RTP packet into a Unit. // wraps a RTP packet into a Unit.
UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit
} }
// New allocates a Processor. // New allocates a Processor.

View File

@@ -1,32 +0,0 @@
package formatprocessor
import (
"time"
"github.com/pion/rtp"
)
// BaseUnit contains fields shared across all units.
type BaseUnit struct {
RTPPackets []*rtp.Packet
NTP time.Time
}
// GetRTPPackets implements Unit.
func (u *BaseUnit) GetRTPPackets() []*rtp.Packet {
return u.RTPPackets
}
// GetNTP implements Unit.
func (u *BaseUnit) GetNTP() time.Time {
return u.NTP
}
// Unit is the elementary data unit routed across the server.
type Unit interface {
// returns RTP packets contained into the unit.
GetRTPPackets() []*rtp.Packet
// returns the NTP timestamp of the unit.
GetNTP() time.Time
}

View File

@@ -9,15 +9,9 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// UnitVP8 is a VP8 data unit.
type UnitVP8 struct {
BaseUnit
PTS time.Duration
Frame []byte
}
type formatProcessorVP8 struct { type formatProcessorVP8 struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.VP8 format *formats.VP8
@@ -54,8 +48,8 @@ func (t *formatProcessorVP8) createEncoder() error {
return t.encoder.Init() return t.encoder.Init()
} }
func (t *formatProcessorVP8) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorVP8) Process(y unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitVP8) tunit := y.(*unit.VP8)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -105,9 +99,9 @@ func (t *formatProcessorVP8) Process(unit Unit, hasNonRTSPReaders bool) error {
return nil return nil
} }
func (t *formatProcessorVP8) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorVP8) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitVP8{ return &unit.VP8{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -9,15 +9,9 @@ import (
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// UnitVP9 is a VP9 data unit.
type UnitVP9 struct {
BaseUnit
PTS time.Duration
Frame []byte
}
type formatProcessorVP9 struct { type formatProcessorVP9 struct {
udpMaxPayloadSize int udpMaxPayloadSize int
format *formats.VP9 format *formats.VP9
@@ -54,8 +48,8 @@ func (t *formatProcessorVP9) createEncoder() error {
return t.encoder.Init() return t.encoder.Init()
} }
func (t *formatProcessorVP9) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl func (t *formatProcessorVP9) Process(u unit.Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitVP9) tunit := u.(*unit.VP9)
if tunit.RTPPackets != nil { if tunit.RTPPackets != nil {
pkt := tunit.RTPPackets[0] pkt := tunit.RTPPackets[0]
@@ -105,9 +99,9 @@ func (t *formatProcessorVP9) Process(unit Unit, hasNonRTSPReaders bool) error {
return nil return nil
} }
func (t *formatProcessorVP9) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) Unit { func (t *formatProcessorVP9) UnitForRTPPacket(pkt *rtp.Packet, ntp time.Time) unit.Unit {
return &UnitVP9{ return &unit.VP9{
BaseUnit: BaseUnit{ Base: unit.Base{
RTPPackets: []*rtp.Packet{pkt}, RTPPackets: []*rtp.Packet{pkt},
NTP: ntp, NTP: ntp,
}, },

View File

@@ -9,8 +9,8 @@ import (
"github.com/bluenviron/gortsplib/v3/pkg/media" "github.com/bluenviron/gortsplib/v3/pkg/media"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
// Stream is a media stream. // Stream is a media stream.
@@ -64,7 +64,7 @@ func (s *Stream) RTSPStream() *gortsplib.ServerStream {
} }
// AddReader adds a reader. // AddReader adds a reader.
func (s *Stream) AddReader(r interface{}, medi *media.Media, forma formats.Format, cb func(formatprocessor.Unit)) { func (s *Stream) AddReader(r interface{}, medi *media.Media, forma formats.Format, cb func(unit.Unit)) {
sm := s.smedias[medi] sm := s.smedias[medi]
sf := sm.formats[forma] sf := sm.formats[forma]
sf.addReader(r, cb) sf.addReader(r, cb)
@@ -80,7 +80,7 @@ func (s *Stream) RemoveReader(r interface{}) {
} }
// WriteUnit writes a Unit. // WriteUnit writes a Unit.
func (s *Stream) WriteUnit(medi *media.Media, forma formats.Format, data formatprocessor.Unit) { func (s *Stream) WriteUnit(medi *media.Media, forma formats.Format, data unit.Unit) {
sm := s.smedias[medi] sm := s.smedias[medi]
sf := sm.formats[forma] sf := sm.formats[forma]
sf.writeUnit(s, medi, data) sf.writeUnit(s, medi, data)

View File

@@ -11,13 +11,14 @@ import (
"github.com/bluenviron/mediamtx/internal/formatprocessor" "github.com/bluenviron/mediamtx/internal/formatprocessor"
"github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/unit"
) )
type streamFormat struct { type streamFormat struct {
source logger.Writer source logger.Writer
proc formatprocessor.Processor proc formatprocessor.Processor
mutex sync.RWMutex mutex sync.RWMutex
nonRTSPReaders map[interface{}]func(formatprocessor.Unit) nonRTSPReaders map[interface{}]func(unit.Unit)
} }
func newStreamFormat( func newStreamFormat(
@@ -34,13 +35,13 @@ func newStreamFormat(
sf := &streamFormat{ sf := &streamFormat{
source: source, source: source,
proc: proc, proc: proc,
nonRTSPReaders: make(map[interface{}]func(formatprocessor.Unit)), nonRTSPReaders: make(map[interface{}]func(unit.Unit)),
} }
return sf, nil return sf, nil
} }
func (sf *streamFormat) addReader(r interface{}, cb func(formatprocessor.Unit)) { func (sf *streamFormat) addReader(r interface{}, cb func(unit.Unit)) {
sf.mutex.Lock() sf.mutex.Lock()
defer sf.mutex.Unlock() defer sf.mutex.Unlock()
sf.nonRTSPReaders[r] = cb sf.nonRTSPReaders[r] = cb
@@ -52,7 +53,7 @@ func (sf *streamFormat) removeReader(r interface{}) {
delete(sf.nonRTSPReaders, r) delete(sf.nonRTSPReaders, r)
} }
func (sf *streamFormat) writeUnit(s *Stream, medi *media.Media, data formatprocessor.Unit) { func (sf *streamFormat) writeUnit(s *Stream, medi *media.Media, data unit.Unit) {
sf.mutex.RLock() sf.mutex.RLock()
defer sf.mutex.RUnlock() defer sf.mutex.RUnlock()

12
internal/unit/av1.go Normal file
View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// AV1 is an AV1 data unit.
type AV1 struct {
Base
PTS time.Duration
TU [][]byte
}

23
internal/unit/base.go Normal file
View File

@@ -0,0 +1,23 @@
package unit
import (
"time"
"github.com/pion/rtp"
)
// Base contains fields shared across all units.
type Base struct {
RTPPackets []*rtp.Packet
NTP time.Time
}
// GetRTPPackets implements Unit.
func (u *Base) GetRTPPackets() []*rtp.Packet {
return u.RTPPackets
}
// GetNTP implements Unit.
func (u *Base) GetNTP() time.Time {
return u.NTP
}

6
internal/unit/generic.go Normal file
View File

@@ -0,0 +1,6 @@
package unit
// Generic is a generic data unit.
type Generic struct {
Base
}

12
internal/unit/h264.go Normal file
View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// H264 is a H264 data unit.
type H264 struct {
Base
PTS time.Duration
AU [][]byte
}

12
internal/unit/h265.go Normal file
View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// H265 is a H265 data unit.
type H265 struct {
Base
PTS time.Duration
AU [][]byte
}

View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// MPEG1Audio is a MPEG-1/2 Audio data unit.
type MPEG1Audio struct {
Base
PTS time.Duration
Frames [][]byte
}

View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// MPEG4AudioGeneric is a MPEG-4 Audio data unit.
type MPEG4AudioGeneric struct {
Base
PTS time.Duration
AUs [][]byte
}

View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// MPEG4AudioLATM is a MPEG-4 Audio data unit.
type MPEG4AudioLATM struct {
Base
PTS time.Duration
AU []byte
}

12
internal/unit/opus.go Normal file
View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// Opus is a Opus data unit.
type Opus struct {
Base
PTS time.Duration
Packets [][]byte
}

17
internal/unit/unit.go Normal file
View File

@@ -0,0 +1,17 @@
// Package unit contains the Unit definition.
package unit
import (
"time"
"github.com/pion/rtp"
)
// Unit is the elementary data unit routed across the server.
type Unit interface {
// returns RTP packets contained into the unit.
GetRTPPackets() []*rtp.Packet
// returns the NTP timestamp of the unit.
GetNTP() time.Time
}

12
internal/unit/vp8.go Normal file
View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// VP8 is a VP8 data unit.
type VP8 struct {
Base
PTS time.Duration
Frame []byte
}

12
internal/unit/vp9.go Normal file
View File

@@ -0,0 +1,12 @@
package unit
import (
"time"
)
// VP9 is a VP9 data unit.
type VP9 struct {
Base
PTS time.Duration
Frame []byte
}