mediamtx/internal/stream/rtp_decoder.go
Alessandro Ros 653d10fb75
use the same filtering process for every codec (#5324)
this allows to apply features that were previously implemented for
single codecs (like RTP packet resizing), to any codec, and simplifies
future development.
2026-01-16 14:03:13 +01:00

366 lines
8.7 KiB
Go

package stream
import (
"errors"
"github.com/bluenviron/gortsplib/v5/pkg/format"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpac3"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpav1"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpfragmented"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtph264"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtph265"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpklv"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtplpcm"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmjpeg"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmpeg1audio"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmpeg1video"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmpeg4audio"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpsimpleaudio"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpvp8"
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpvp9"
"github.com/bluenviron/mediamtx/internal/unit"
"github.com/pion/rtp"
)
type rtpDecoder interface {
decode(*rtp.Packet) (unit.Payload, error)
}
type rtpDecoderAV1 rtpav1.Decoder
func (d *rtpDecoderAV1) decode(pkt *rtp.Packet) (unit.Payload, error) {
tu, err := (*rtpav1.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpav1.ErrNonStartingPacketAndNoPrevious) ||
errors.Is(err, rtpav1.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadAV1(tu), nil
}
type rtpDecoderVP9 rtpvp9.Decoder
func (d *rtpDecoderVP9) decode(pkt *rtp.Packet) (unit.Payload, error) {
frame, err := (*rtpvp9.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpvp9.ErrNonStartingPacketAndNoPrevious) ||
errors.Is(err, rtpvp9.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadVP9(frame), nil
}
type rtpDecoderVP8 rtpvp8.Decoder
func (d *rtpDecoderVP8) decode(pkt *rtp.Packet) (unit.Payload, error) {
frame, err := (*rtpvp8.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpvp8.ErrNonStartingPacketAndNoPrevious) ||
errors.Is(err, rtpvp8.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadVP8(frame), nil
}
type rtpDecoderH265 rtph265.Decoder
func (d *rtpDecoderH265) decode(pkt *rtp.Packet) (unit.Payload, error) {
au, err := (*rtph265.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtph265.ErrNonStartingPacketAndNoPrevious) ||
errors.Is(err, rtph265.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadH265(au), nil
}
type rtpDecoderH264 rtph264.Decoder
func (d *rtpDecoderH264) decode(pkt *rtp.Packet) (unit.Payload, error) {
au, err := (*rtph264.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtph264.ErrNonStartingPacketAndNoPrevious) ||
errors.Is(err, rtph264.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadH264(au), nil
}
type rtpDecoderMPEG4Video rtpfragmented.Decoder
func (d *rtpDecoderMPEG4Video) decode(pkt *rtp.Packet) (unit.Payload, error) {
frame, err := (*rtpfragmented.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpfragmented.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadMPEG4Video(frame), nil
}
type rtpDecoderMPEG1Video rtpmpeg1video.Decoder
func (d *rtpDecoderMPEG1Video) decode(pkt *rtp.Packet) (unit.Payload, error) {
frame, err := (*rtpmpeg1video.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpmpeg1video.ErrNonStartingPacketAndNoPrevious) ||
errors.Is(err, rtpmpeg1video.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadMPEG1Video(frame), nil
}
type rtpDecoderMJPEG rtpmjpeg.Decoder
func (d *rtpDecoderMJPEG) decode(pkt *rtp.Packet) (unit.Payload, error) {
frame, err := (*rtpmjpeg.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpmjpeg.ErrNonStartingPacketAndNoPrevious) ||
errors.Is(err, rtpmjpeg.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadMJPEG(frame), nil
}
type rtpDecoderOpus rtpsimpleaudio.Decoder
func (d *rtpDecoderOpus) decode(pkt *rtp.Packet) (unit.Payload, error) {
packet, err := (*rtpsimpleaudio.Decoder)(d).Decode(pkt)
if err != nil {
return nil, err
}
return unit.PayloadOpus{packet}, nil
}
type rtpDecoderMPEG4Audio rtpmpeg4audio.Decoder
func (d *rtpDecoderMPEG4Audio) decode(pkt *rtp.Packet) (unit.Payload, error) {
aus, err := (*rtpmpeg4audio.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpmpeg4audio.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadMPEG4Audio(aus), nil
}
type rtpDecoderMPEG4AudioLATM rtpfragmented.Decoder
func (d *rtpDecoderMPEG4AudioLATM) decode(pkt *rtp.Packet) (unit.Payload, error) {
payload, err := (*rtpfragmented.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpfragmented.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadMPEG4AudioLATM(payload), nil
}
type rtpDecoderMPEG1Audio rtpmpeg1audio.Decoder
func (d *rtpDecoderMPEG1Audio) decode(pkt *rtp.Packet) (unit.Payload, error) {
frames, err := (*rtpmpeg1audio.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpmpeg1audio.ErrNonStartingPacketAndNoPrevious) ||
errors.Is(err, rtpmpeg1audio.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadMPEG1Audio(frames), nil
}
type rtpDecoderAC3 rtpac3.Decoder
func (d *rtpDecoderAC3) decode(pkt *rtp.Packet) (unit.Payload, error) {
frames, err := (*rtpac3.Decoder)(d).Decode(pkt)
if err != nil {
if errors.Is(err, rtpac3.ErrMorePacketsNeeded) {
return nil, nil
}
return nil, err
}
return unit.PayloadAC3(frames), nil
}
type rtpDecoderG711 rtplpcm.Decoder
func (d *rtpDecoderG711) decode(pkt *rtp.Packet) (unit.Payload, error) {
samples, err := (*rtplpcm.Decoder)(d).Decode(pkt)
if err != nil {
return nil, err
}
return unit.PayloadG711(samples), nil
}
type rtpDecoderLPCM rtplpcm.Decoder
func (d *rtpDecoderLPCM) decode(pkt *rtp.Packet) (unit.Payload, error) {
samples, err := (*rtplpcm.Decoder)(d).Decode(pkt)
if err != nil {
return nil, err
}
return unit.PayloadLPCM(samples), nil
}
type rtpDecoderKLV rtpklv.Decoder
func (d *rtpDecoderKLV) decode(pkt *rtp.Packet) (unit.Payload, error) {
payload, err := (*rtpklv.Decoder)(d).Decode(pkt)
if err != nil {
return nil, err
}
return unit.PayloadKLV(payload), nil
}
func newRTPDecoder(forma format.Format) (rtpDecoder, error) {
switch forma := forma.(type) {
case *format.AV1:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderAV1)(wrapped), nil
case *format.VP9:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderVP9)(wrapped), nil
case *format.VP8:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderVP8)(wrapped), nil
case *format.H265:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderH265)(wrapped), nil
case *format.H264:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderH264)(wrapped), nil
case *format.MPEG4Video:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderMPEG4Video)(wrapped), nil
case *format.MPEG1Video:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderMPEG1Video)(wrapped), nil
case *format.MJPEG:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderMJPEG)(wrapped), nil
case *format.Opus:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderOpus)(wrapped), nil
case *format.MPEG4Audio:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderMPEG4Audio)(wrapped), nil
case *format.MPEG4AudioLATM:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderMPEG4AudioLATM)(wrapped), nil
case *format.MPEG1Audio:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderMPEG1Audio)(wrapped), nil
case *format.AC3:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderAC3)(wrapped), nil
case *format.G711:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderG711)(wrapped), nil
case *format.LPCM:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderLPCM)(wrapped), nil
case *format.KLV:
wrapped, err := forma.CreateDecoder()
if err != nil {
return nil, err
}
return (*rtpDecoderKLV)(wrapped), nil
default:
return nil, nil
}
}