rewrite Unit definition (#5079)
Stream units now share the same struct, with a specialized payload.
This commit is contained in:
@@ -3,11 +3,9 @@ package codecprocessor
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpac3"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -47,10 +45,8 @@ func (t *ac3) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *ac3) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.AC3)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.Frames)
|
||||
func (t *ac3) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadAC3))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -64,25 +60,17 @@ func (t *ac3) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *ac3) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.AC3{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -92,7 +80,7 @@ func (t *ac3) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,14 +88,13 @@ func (t *ac3) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpac3.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtpac3.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Frames = frames
|
||||
u.Payload = unit.PayloadAC3(frames)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,12 +3,10 @@ package codecprocessor //nolint:dupl
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpav1"
|
||||
mcav1 "github.com/bluenviron/mediacommon/v2/pkg/codecs/av1"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -49,7 +47,7 @@ func (t *av1) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *av1) remuxTemporalUnit(tu [][]byte) [][]byte {
|
||||
func (t *av1) remuxTemporalUnit(tu unit.PayloadAV1) unit.PayloadAV1 {
|
||||
n := 0
|
||||
|
||||
for _, obu := range tu {
|
||||
@@ -82,12 +80,10 @@ func (t *av1) remuxTemporalUnit(tu [][]byte) [][]byte {
|
||||
return filteredTU
|
||||
}
|
||||
|
||||
func (t *av1) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.AV1)
|
||||
func (t *av1) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
u.Payload = t.remuxTemporalUnit(u.Payload.(unit.PayloadAV1))
|
||||
|
||||
u.TU = t.remuxTemporalUnit(u.TU)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.TU)
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadAV1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -101,25 +97,17 @@ func (t *av1) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *av1) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.AV1{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -129,7 +117,7 @@ func (t *av1) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,14 +125,13 @@ func (t *av1) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpav1.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtpav1.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.TU = t.remuxTemporalUnit(tu)
|
||||
u.Payload = t.remuxTemporalUnit(tu)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -15,11 +15,9 @@ func TestAV1RemoveTUD(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
u := &unit.AV1{
|
||||
Base: unit.Base{
|
||||
PTS: 30000,
|
||||
},
|
||||
TU: [][]byte{
|
||||
u := &unit.Unit{
|
||||
PTS: 30000,
|
||||
Payload: unit.PayloadAV1{
|
||||
{byte(mcav1.OBUTypeTemporalDelimiter) << 3},
|
||||
{5},
|
||||
},
|
||||
@@ -28,7 +26,7 @@ func TestAV1RemoveTUD(t *testing.T) {
|
||||
err = p.ProcessUnit(u)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadAV1{
|
||||
{5},
|
||||
}, u.TU)
|
||||
}, u.Payload)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@ package codecprocessor //nolint:dupl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtplpcm"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -49,10 +47,8 @@ func (t *g711) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *g711) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.G711)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.Samples)
|
||||
func (t *g711) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadG711))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,25 +62,17 @@ func (t *g711) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *g711) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.G711{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -94,18 +82,17 @@ func (t *g711) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
samples, err := t.decoder.Decode(pkt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Samples = samples
|
||||
u.Payload = unit.PayloadG711(samples)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ func TestG711ProcessUnit(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
unit := &unit.G711{
|
||||
Samples: []byte{1, 2, 3, 4},
|
||||
unit := &unit.Unit{
|
||||
Payload: unit.PayloadG711{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
err = p.ProcessUnit(unit)
|
||||
@@ -50,8 +50,8 @@ func TestG711ProcessUnit(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
unit := &unit.G711{
|
||||
Samples: []byte{1, 2, 3, 4},
|
||||
unit := &unit.Unit{
|
||||
Payload: unit.PayloadG711{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
err = p.ProcessUnit(unit)
|
||||
|
||||
@@ -2,10 +2,8 @@ package codecprocessor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -26,32 +24,24 @@ func (t *generic) initialize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *generic) ProcessUnit(_ unit.Unit) error {
|
||||
func (t *generic) ProcessUnit(_ *unit.Unit) error {
|
||||
return fmt.Errorf("using a generic unit without RTP is not supported")
|
||||
}
|
||||
|
||||
func (t *generic) ProcessRTPPacket(
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
_ bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.Generic{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package codecprocessor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -34,7 +34,8 @@ func TestGenericProcessRTPPacket(t *testing.T) {
|
||||
PaddingSize: 20,
|
||||
}
|
||||
|
||||
_, err = p.ProcessRTPPacket(pkt, time.Time{}, 0, false)
|
||||
u := &unit.Unit{RTPPackets: []*rtp.Packet{pkt}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
// check that padding has been removed
|
||||
|
||||
@@ -3,12 +3,10 @@ package codecprocessor
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtph264"
|
||||
mch264 "github.com/bluenviron/mediacommon/v2/pkg/codecs/h264"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -138,7 +136,7 @@ func (t *h264) updateTrackParametersFromRTPPacket(payload []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *h264) updateTrackParametersFromAU(au [][]byte) {
|
||||
func (t *h264) updateTrackParametersFromAU(au unit.PayloadH264) {
|
||||
sps := t.Format.SPS
|
||||
pps := t.Format.PPS
|
||||
update := false
|
||||
@@ -166,7 +164,7 @@ func (t *h264) updateTrackParametersFromAU(au [][]byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *h264) remuxAccessUnit(au [][]byte) [][]byte {
|
||||
func (t *h264) remuxAccessUnit(au unit.PayloadH264) unit.PayloadH264 {
|
||||
isKeyFrame := false
|
||||
n := 0
|
||||
|
||||
@@ -224,14 +222,12 @@ func (t *h264) remuxAccessUnit(au [][]byte) [][]byte {
|
||||
return filteredAU
|
||||
}
|
||||
|
||||
func (t *h264) ProcessUnit(uu unit.Unit) error {
|
||||
u := uu.(*unit.H264)
|
||||
func (t *h264) ProcessUnit(u *unit.Unit) error {
|
||||
t.updateTrackParametersFromAU(u.Payload.(unit.PayloadH264))
|
||||
u.Payload = t.remuxAccessUnit(u.Payload.(unit.PayloadH264))
|
||||
|
||||
t.updateTrackParametersFromAU(u.AU)
|
||||
u.AU = t.remuxAccessUnit(u.AU)
|
||||
|
||||
if u.AU != nil {
|
||||
pkts, err := t.encoder.Encode(u.AU)
|
||||
if !u.NilPayload() {
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadH264))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -246,18 +242,10 @@ func (t *h264) ProcessUnit(uu unit.Unit) error {
|
||||
}
|
||||
|
||||
func (t *h264) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.H264{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
t.updateTrackParametersFromRTPPacket(pkt.Payload)
|
||||
|
||||
@@ -274,7 +262,7 @@ func (t *h264) ProcessRTPPacket( //nolint:dupl
|
||||
v2 := pkt.SequenceNumber
|
||||
err := t.createEncoder(&v1, &v2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,7 +273,7 @@ func (t *h264) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,24 +286,24 @@ func (t *h264) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtph264.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtph264.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.AU = t.remuxAccessUnit(au)
|
||||
u.Payload = t.remuxAccessUnit(au)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
if t.encoder == nil {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// encode into RTP
|
||||
if len(u.AU) != 0 {
|
||||
pkts, err := t.encoder.Encode(u.AU)
|
||||
if !u.NilPayload() {
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadH264))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
u.RTPPackets = pkts
|
||||
|
||||
@@ -324,5 +312,5 @@ func (t *h264) ProcessRTPPacket( //nolint:dupl
|
||||
}
|
||||
}
|
||||
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
mch264 "github.com/bluenviron/mediacommon/v2/pkg/codecs/h264"
|
||||
@@ -34,11 +33,9 @@ func TestH264RemoveAUD(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
u := &unit.H264{
|
||||
Base: unit.Base{
|
||||
PTS: 30000,
|
||||
},
|
||||
AU: [][]byte{
|
||||
u := &unit.Unit{
|
||||
PTS: 30000,
|
||||
Payload: unit.PayloadH264{
|
||||
{9, 24}, // AUD
|
||||
{5, 1}, // IDR
|
||||
},
|
||||
@@ -47,9 +44,9 @@ func TestH264RemoveAUD(t *testing.T) {
|
||||
err = p.ProcessUnit(u)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH264{
|
||||
{5, 1}, // IDR
|
||||
}, u.AU)
|
||||
}, u.Payload)
|
||||
}
|
||||
|
||||
func TestH264AddParams(t *testing.T) {
|
||||
@@ -58,11 +55,9 @@ func TestH264AddParams(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
u1 := &unit.H264{
|
||||
Base: unit.Base{
|
||||
PTS: 30000,
|
||||
},
|
||||
AU: [][]byte{
|
||||
u1 := &unit.Unit{
|
||||
PTS: 30000,
|
||||
Payload: unit.PayloadH264{
|
||||
{7, 4, 5, 6}, // SPS
|
||||
{8, 1}, // PPS
|
||||
{5, 1}, // IDR
|
||||
@@ -72,17 +67,15 @@ func TestH264AddParams(t *testing.T) {
|
||||
err = p.ProcessUnit(u1)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH264{
|
||||
{7, 4, 5, 6}, // SPS
|
||||
{8, 1}, // PPS
|
||||
{5, 1}, // IDR
|
||||
}, u1.AU)
|
||||
}, u1.Payload)
|
||||
|
||||
u2 := &unit.H264{
|
||||
Base: unit.Base{
|
||||
PTS: 30000 * 2,
|
||||
},
|
||||
AU: [][]byte{
|
||||
u2 := &unit.Unit{
|
||||
PTS: 30000 * 2,
|
||||
Payload: unit.PayloadH264{
|
||||
{5, 2}, // IDR
|
||||
},
|
||||
}
|
||||
@@ -95,11 +88,11 @@ func TestH264AddParams(t *testing.T) {
|
||||
require.Equal(t, []byte{8, 1}, forma.PPS)
|
||||
|
||||
// test that params have been added to the frame
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH264{
|
||||
{7, 4, 5, 6}, // SPS
|
||||
{8, 1}, // PPS
|
||||
{5, 2}, // IDR
|
||||
}, u2.AU)
|
||||
}, u2.Payload)
|
||||
|
||||
// test that timestamp has increased
|
||||
require.Equal(t, u1.RTPPackets[0].Timestamp+30000, u2.RTPPackets[0].Timestamp)
|
||||
@@ -114,8 +107,8 @@ func TestH264ProcessEmptyUnit(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
unit := &unit.H264{
|
||||
AU: [][]byte{
|
||||
unit := &unit.Unit{
|
||||
Payload: unit.PayloadH264{
|
||||
{0x07, 0x01, 0x02, 0x03}, // SPS
|
||||
{0x08, 0x01, 0x02}, // PPS
|
||||
},
|
||||
@@ -145,24 +138,27 @@ func TestH264RTPExtractParams(t *testing.T) {
|
||||
pkts, err := enc.Encode([][]byte{{byte(mch264.NALUTypeIDR)}})
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := p.ProcessRTPPacket(pkts[0], time.Time{}, 0, true)
|
||||
u := &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH264{
|
||||
{byte(mch264.NALUTypeIDR)},
|
||||
}, data.(*unit.H264).AU)
|
||||
}, u.Payload)
|
||||
|
||||
if ca == "standard" {
|
||||
pkts, err = enc.Encode([][]byte{{7, 4, 5, 6}}) // SPS
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, false)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
pkts, err = enc.Encode([][]byte{{8, 1}}) // PPS
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, false)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
pkts, err = enc.Encode([][]byte{
|
||||
@@ -171,7 +167,8 @@ func TestH264RTPExtractParams(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, false)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -181,14 +178,15 @@ func TestH264RTPExtractParams(t *testing.T) {
|
||||
pkts, err = enc.Encode([][]byte{{byte(mch264.NALUTypeIDR)}})
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, true)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH264{
|
||||
{0x07, 4, 5, 6},
|
||||
{0x08, 1},
|
||||
{byte(mch264.NALUTypeIDR)},
|
||||
}, data.(*unit.H264).AU)
|
||||
}, u.Payload)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -250,11 +248,11 @@ func TestH264RTPOversized(t *testing.T) {
|
||||
Payload: []byte{0x1c, 0b01000000, 0x01, 0x02, 0x03, 0x04},
|
||||
},
|
||||
} {
|
||||
var data unit.Unit
|
||||
data, err = p.ProcessRTPPacket(pkt, time.Time{}, 0, false)
|
||||
u := &unit.Unit{RTPPackets: []*rtp.Packet{pkt}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
out = append(out, data.GetRTPPackets()...)
|
||||
out = append(out, u.RTPPackets...)
|
||||
}
|
||||
|
||||
require.Equal(t, []*rtp.Packet{
|
||||
|
||||
@@ -3,12 +3,10 @@ package codecprocessor
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtph265"
|
||||
mch265 "github.com/bluenviron/mediacommon/v2/pkg/codecs/h265"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -162,7 +160,7 @@ func (t *h265) updateTrackParametersFromRTPPacket(payload []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *h265) updateTrackParametersFromAU(au [][]byte) {
|
||||
func (t *h265) updateTrackParametersFromAU(au unit.PayloadH265) {
|
||||
vps := t.Format.VPS
|
||||
sps := t.Format.SPS
|
||||
pps := t.Format.PPS
|
||||
@@ -197,7 +195,7 @@ func (t *h265) updateTrackParametersFromAU(au [][]byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *h265) remuxAccessUnit(au [][]byte) [][]byte {
|
||||
func (t *h265) remuxAccessUnit(au unit.PayloadH265) unit.PayloadH265 {
|
||||
isKeyFrame := false
|
||||
n := 0
|
||||
|
||||
@@ -256,14 +254,12 @@ func (t *h265) remuxAccessUnit(au [][]byte) [][]byte {
|
||||
return filteredAU
|
||||
}
|
||||
|
||||
func (t *h265) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.H265)
|
||||
func (t *h265) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
t.updateTrackParametersFromAU(u.Payload.(unit.PayloadH265))
|
||||
u.Payload = t.remuxAccessUnit(u.Payload.(unit.PayloadH265))
|
||||
|
||||
t.updateTrackParametersFromAU(u.AU)
|
||||
u.AU = t.remuxAccessUnit(u.AU)
|
||||
|
||||
if u.AU != nil {
|
||||
pkts, err := t.encoder.Encode(u.AU)
|
||||
if !u.NilPayload() {
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadH265))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -278,18 +274,10 @@ func (t *h265) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *h265) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.H265{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
t.updateTrackParametersFromRTPPacket(pkt.Payload)
|
||||
|
||||
@@ -306,7 +294,7 @@ func (t *h265) ProcessRTPPacket( //nolint:dupl
|
||||
v2 := pkt.SequenceNumber
|
||||
err := t.createEncoder(&v1, &v2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -317,7 +305,7 @@ func (t *h265) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,24 +318,24 @@ func (t *h265) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtph265.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtph265.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.AU = t.remuxAccessUnit(au)
|
||||
u.Payload = t.remuxAccessUnit(au)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
if t.encoder == nil {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// encode into RTP
|
||||
if len(u.AU) != 0 {
|
||||
pkts, err := t.encoder.Encode(u.AU)
|
||||
if !u.NilPayload() {
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadH265))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
u.RTPPackets = pkts
|
||||
|
||||
@@ -356,5 +344,5 @@ func (t *h265) ProcessRTPPacket( //nolint:dupl
|
||||
}
|
||||
}
|
||||
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
mch265 "github.com/bluenviron/mediacommon/v2/pkg/codecs/h265"
|
||||
@@ -21,11 +20,9 @@ func TestH265RemoveAUD(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
u := &unit.H265{
|
||||
Base: unit.Base{
|
||||
PTS: 30000,
|
||||
},
|
||||
AU: [][]byte{
|
||||
u := &unit.Unit{
|
||||
PTS: 30000,
|
||||
Payload: unit.PayloadH265{
|
||||
{byte(mch265.NALUType_AUD_NUT) << 1, 0},
|
||||
{byte(mch265.NALUType_CRA_NUT) << 1, 0},
|
||||
},
|
||||
@@ -34,9 +31,9 @@ func TestH265RemoveAUD(t *testing.T) {
|
||||
err = p.ProcessUnit(u)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH265{
|
||||
{byte(mch265.NALUType_CRA_NUT) << 1, 0},
|
||||
}, u.AU)
|
||||
}, u.Payload)
|
||||
}
|
||||
|
||||
func TestH265AddParams(t *testing.T) {
|
||||
@@ -45,11 +42,9 @@ func TestH265AddParams(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
u1 := &unit.H265{
|
||||
Base: unit.Base{
|
||||
PTS: 30000,
|
||||
},
|
||||
AU: [][]byte{
|
||||
u1 := &unit.Unit{
|
||||
PTS: 30000,
|
||||
Payload: unit.PayloadH265{
|
||||
{byte(mch265.NALUType_VPS_NUT) << 1, 1, 2, 3},
|
||||
{byte(mch265.NALUType_SPS_NUT) << 1, 4, 5, 6},
|
||||
{byte(mch265.NALUType_PPS_NUT) << 1, 7, 8, 9},
|
||||
@@ -60,18 +55,16 @@ func TestH265AddParams(t *testing.T) {
|
||||
err = p.ProcessUnit(u1)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH265{
|
||||
{byte(mch265.NALUType_VPS_NUT) << 1, 1, 2, 3},
|
||||
{byte(mch265.NALUType_SPS_NUT) << 1, 4, 5, 6},
|
||||
{byte(mch265.NALUType_PPS_NUT) << 1, 7, 8, 9},
|
||||
{byte(mch265.NALUType_CRA_NUT) << 1, 0},
|
||||
}, u1.AU)
|
||||
}, u1.Payload)
|
||||
|
||||
u2 := &unit.H265{
|
||||
Base: unit.Base{
|
||||
PTS: 30000 * 2,
|
||||
},
|
||||
AU: [][]byte{
|
||||
u2 := &unit.Unit{
|
||||
PTS: 30000 * 2,
|
||||
Payload: unit.PayloadH265{
|
||||
{byte(mch265.NALUType_CRA_NUT) << 1, 1},
|
||||
},
|
||||
}
|
||||
@@ -85,12 +78,12 @@ func TestH265AddParams(t *testing.T) {
|
||||
require.Equal(t, []byte{byte(mch265.NALUType_PPS_NUT) << 1, 7, 8, 9}, forma.PPS)
|
||||
|
||||
// test that params have been added to the frame
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH265{
|
||||
{byte(mch265.NALUType_VPS_NUT) << 1, 1, 2, 3},
|
||||
{byte(mch265.NALUType_SPS_NUT) << 1, 4, 5, 6},
|
||||
{byte(mch265.NALUType_PPS_NUT) << 1, 7, 8, 9},
|
||||
{byte(mch265.NALUType_CRA_NUT) << 1, 1},
|
||||
}, u2.AU)
|
||||
}, u2.Payload)
|
||||
|
||||
// test that timestamp has increased
|
||||
require.Equal(t, u1.RTPPackets[0].Timestamp+30000, u2.RTPPackets[0].Timestamp)
|
||||
@@ -104,8 +97,8 @@ func TestH265ProcessEmptyUnit(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
unit := &unit.H265{
|
||||
AU: [][]byte{
|
||||
unit := &unit.Unit{
|
||||
Payload: unit.PayloadH265{
|
||||
{byte(mch265.NALUType_VPS_NUT) << 1, 10, 11, 12}, // VPS
|
||||
{byte(mch265.NALUType_SPS_NUT) << 1, 13, 14, 15}, // SPS
|
||||
{byte(mch265.NALUType_PPS_NUT) << 1, 16, 17, 18}, // PPS
|
||||
@@ -135,30 +128,34 @@ func TestH265RTPExtractParams(t *testing.T) {
|
||||
pkts, err := enc.Encode([][]byte{{byte(mch265.NALUType_CRA_NUT) << 1, 0}})
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := p.ProcessRTPPacket(pkts[0], time.Time{}, 0, true)
|
||||
u := &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH265{
|
||||
{byte(mch265.NALUType_CRA_NUT) << 1, 0},
|
||||
}, data.(*unit.H265).AU)
|
||||
}, u.Payload)
|
||||
|
||||
if ca == "standard" {
|
||||
pkts, err = enc.Encode([][]byte{{byte(mch265.NALUType_VPS_NUT) << 1, 1, 2, 3}})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, false)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
pkts, err = enc.Encode([][]byte{{byte(mch265.NALUType_SPS_NUT) << 1, 4, 5, 6}})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, false)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
pkts, err = enc.Encode([][]byte{{byte(mch265.NALUType_PPS_NUT) << 1, 7, 8, 9}})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, false)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
pkts, err = enc.Encode([][]byte{
|
||||
@@ -168,7 +165,8 @@ func TestH265RTPExtractParams(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, false)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -179,15 +177,16 @@ func TestH265RTPExtractParams(t *testing.T) {
|
||||
pkts, err = enc.Encode([][]byte{{byte(mch265.NALUType_CRA_NUT) << 1, 0}})
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err = p.ProcessRTPPacket(pkts[0], time.Time{}, 0, true)
|
||||
u = &unit.Unit{RTPPackets: []*rtp.Packet{pkts[0]}}
|
||||
err = p.ProcessRTPPacket(u, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, [][]byte{
|
||||
require.Equal(t, unit.PayloadH265{
|
||||
{byte(mch265.NALUType_VPS_NUT) << 1, 1, 2, 3},
|
||||
{byte(mch265.NALUType_SPS_NUT) << 1, 4, 5, 6},
|
||||
{byte(mch265.NALUType_PPS_NUT) << 1, 7, 8, 9},
|
||||
{byte(mch265.NALUType_CRA_NUT) << 1, 0},
|
||||
}, data.(*unit.H265).AU)
|
||||
}, u.Payload)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -237,11 +236,11 @@ func TestH265RTPOversized(t *testing.T) {
|
||||
Payload: bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04}, 2000/4),
|
||||
},
|
||||
} {
|
||||
var data unit.Unit
|
||||
data, err = p.ProcessRTPPacket(pkt, time.Time{}, 0, false)
|
||||
u := &unit.Unit{RTPPackets: []*rtp.Packet{pkt}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
out = append(out, data.GetRTPPackets()...)
|
||||
out = append(out, u.RTPPackets...)
|
||||
}
|
||||
|
||||
require.Equal(t, []*rtp.Packet{
|
||||
|
||||
@@ -2,11 +2,9 @@ package codecprocessor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpklv"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -47,52 +45,39 @@ func (t *klv) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *klv) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.KLV)
|
||||
|
||||
if u.Unit != nil {
|
||||
// ensure the format processor's encoder is initialized
|
||||
if t.encoder == nil {
|
||||
err := t.createEncoder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
pkts, err := t.encoder.Encode(u.Unit)
|
||||
func (t *klv) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
if t.encoder == nil {
|
||||
err := t.createEncoder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.RTPPackets = pkts
|
||||
}
|
||||
|
||||
for _, pkt := range u.RTPPackets {
|
||||
pkt.Timestamp += t.randomStart + uint32(u.PTS)
|
||||
}
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadKLV))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.RTPPackets = pkts
|
||||
|
||||
for _, pkt := range u.RTPPackets {
|
||||
pkt.Timestamp += t.randomStart + uint32(u.PTS)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *klv) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.KLV{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -102,18 +87,17 @@ func (t *klv) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
unit, err := t.decoder.Decode(pkt)
|
||||
un, err := t.decoder.Decode(pkt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Unit = unit
|
||||
u.Payload = unit.PayloadKLV(un)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package codecprocessor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -30,15 +29,11 @@ func TestKlvProcessUnit(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// create test Unit
|
||||
theTime := time.Now()
|
||||
when := int64(5000000000) // 5 seconds in nanoseconds
|
||||
u := unit.KLV{
|
||||
Base: unit.Base{
|
||||
RTPPackets: nil,
|
||||
NTP: theTime,
|
||||
PTS: when,
|
||||
},
|
||||
Unit: []byte{1, 2, 3, 4},
|
||||
u := unit.Unit{
|
||||
RTPPackets: nil,
|
||||
PTS: when,
|
||||
Payload: unit.PayloadKLV{1, 2, 3, 4},
|
||||
}
|
||||
uu := &u
|
||||
|
||||
@@ -67,7 +62,8 @@ func TestKlvProcessRTPPacket(t *testing.T) {
|
||||
Payload: []byte{1, 2, 3, 4},
|
||||
PaddingSize: 20,
|
||||
}
|
||||
_, err = p.ProcessRTPPacket(pkt, time.Time{}, 0, false)
|
||||
u := &unit.Unit{RTPPackets: []*rtp.Packet{pkt}}
|
||||
err = p.ProcessRTPPacket(u, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, &rtp.Packet{
|
||||
|
||||
@@ -2,11 +2,9 @@ package codecprocessor //nolint:dupl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtplpcm"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -49,10 +47,8 @@ func (t *lpcm) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *lpcm) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.LPCM)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.Samples)
|
||||
func (t *lpcm) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadLPCM))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,25 +62,17 @@ func (t *lpcm) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *lpcm) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.LPCM{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -94,18 +82,17 @@ func (t *lpcm) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
samples, err := t.decoder.Decode(pkt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Samples = samples
|
||||
u.Payload = unit.PayloadLPCM(samples)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ func TestLPCMProcessUnit(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
unit := &unit.LPCM{
|
||||
Samples: []byte{1, 2, 3, 4},
|
||||
unit := &unit.Unit{
|
||||
Payload: unit.PayloadLPCM{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
err = p.ProcessUnit(unit)
|
||||
|
||||
@@ -3,11 +3,9 @@ package codecprocessor //nolint:dupl
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmjpeg"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -47,11 +45,9 @@ func (t *mjpeg) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *mjpeg) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.MJPEG)
|
||||
|
||||
func (t *mjpeg) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
// encode into RTP
|
||||
pkts, err := t.encoder.Encode(u.Frame)
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadMJPEG))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -65,25 +61,17 @@ func (t *mjpeg) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *mjpeg) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.MJPEG{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -93,7 +81,7 @@ func (t *mjpeg) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,14 +89,13 @@ func (t *mjpeg) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpmjpeg.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtpmjpeg.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Frame = frame
|
||||
u.Payload = unit.PayloadMJPEG(frame)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ package codecprocessor //nolint:dupl
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmpeg1audio"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -47,10 +45,8 @@ func (t *mpeg1Audio) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *mpeg1Audio) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.MPEG1Audio)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.Frames)
|
||||
func (t *mpeg1Audio) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadMPEG1Audio))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -64,25 +60,17 @@ func (t *mpeg1Audio) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *mpeg1Audio) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.MPEG1Audio{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -92,7 +80,7 @@ func (t *mpeg1Audio) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,14 +88,13 @@ func (t *mpeg1Audio) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpmpeg1audio.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtpmpeg1audio.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Frames = frames
|
||||
u.Payload = unit.PayloadMPEG1Audio(frames)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ package codecprocessor //nolint:dupl
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmpeg1video"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -56,11 +54,9 @@ func (t *mpeg1Video) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *mpeg1Video) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.MPEG1Video)
|
||||
|
||||
func (t *mpeg1Video) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
// encode into RTP
|
||||
pkts, err := t.encoder.Encode(u.Frame)
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadMPEG1Video))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -74,25 +70,17 @@ func (t *mpeg1Video) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *mpeg1Video) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.MPEG1Video{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -102,7 +90,7 @@ func (t *mpeg1Video) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,14 +98,13 @@ func (t *mpeg1Video) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpmpeg1video.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtpmpeg1video.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Frame = frame
|
||||
u.Payload = unit.PayloadMPEG1Video(frame)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ package codecprocessor
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmpeg4audio"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -51,10 +49,8 @@ func (t *mpeg4Audio) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *mpeg4Audio) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.MPEG4Audio)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.AUs)
|
||||
func (t *mpeg4Audio) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadMPEG4Audio))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -68,25 +64,17 @@ func (t *mpeg4Audio) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *mpeg4Audio) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.MPEG4Audio{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -96,21 +84,20 @@ func (t *mpeg4Audio) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
aus, err := t.decoder.Decode(pkt)
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpmpeg4audio.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.AUs = aus
|
||||
u.Payload = unit.PayloadMPEG4Audio(aus)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,12 +3,10 @@ package codecprocessor
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpfragmented"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpmpeg4audio"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -49,10 +47,8 @@ func (t *mpeg4AudioLATM) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *mpeg4AudioLATM) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.MPEG4AudioLATM)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.Element)
|
||||
func (t *mpeg4AudioLATM) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadMPEG4AudioLATM))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,25 +62,17 @@ func (t *mpeg4AudioLATM) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *mpeg4AudioLATM) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.MPEG4AudioLATM{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -94,21 +82,20 @@ func (t *mpeg4AudioLATM) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
el, err := t.decoder.Decode(pkt)
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpmpeg4audio.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Element = el
|
||||
u.Payload = unit.PayloadMPEG4AudioLATM(el)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,12 +4,10 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpfragmented"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/codecs/mpeg4video"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -62,7 +60,7 @@ func (t *mpeg4Video) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *mpeg4Video) updateTrackParameters(frame []byte) {
|
||||
func (t *mpeg4Video) updateTrackParameters(frame unit.PayloadMPEG4Video) {
|
||||
if bytes.HasPrefix(frame, []byte{0, 0, 1, byte(mpeg4video.VisualObjectSequenceStartCode)}) {
|
||||
end := bytes.Index(frame[4:], []byte{0, 0, 1, byte(mpeg4video.GroupOfVOPStartCode)})
|
||||
if end < 0 {
|
||||
@@ -76,7 +74,7 @@ func (t *mpeg4Video) updateTrackParameters(frame []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *mpeg4Video) remuxFrame(frame []byte) []byte {
|
||||
func (t *mpeg4Video) remuxFrame(frame unit.PayloadMPEG4Video) unit.PayloadMPEG4Video {
|
||||
// remove config
|
||||
if bytes.HasPrefix(frame, []byte{0, 0, 1, byte(mpeg4video.VisualObjectSequenceStartCode)}) {
|
||||
end := bytes.Index(frame[4:], []byte{0, 0, 1, byte(mpeg4video.GroupOfVOPStartCode)})
|
||||
@@ -93,17 +91,19 @@ func (t *mpeg4Video) remuxFrame(frame []byte) []byte {
|
||||
frame = f
|
||||
}
|
||||
|
||||
if len(frame) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return frame
|
||||
}
|
||||
|
||||
func (t *mpeg4Video) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.MPEG4Video)
|
||||
func (t *mpeg4Video) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
t.updateTrackParameters(u.Payload.(unit.PayloadMPEG4Video))
|
||||
u.Payload = t.remuxFrame(u.Payload.(unit.PayloadMPEG4Video))
|
||||
|
||||
t.updateTrackParameters(u.Frame)
|
||||
u.Frame = t.remuxFrame(u.Frame)
|
||||
|
||||
if len(u.Frame) != 0 {
|
||||
pkts, err := t.encoder.Encode(u.Frame)
|
||||
if !u.NilPayload() {
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadMPEG4Video))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -118,18 +118,10 @@ func (t *mpeg4Video) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *mpeg4Video) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.MPEG4Video{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
t.updateTrackParameters(pkt.Payload)
|
||||
|
||||
@@ -138,7 +130,7 @@ func (t *mpeg4Video) ProcessRTPPacket( //nolint:dupl
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -148,21 +140,20 @@ func (t *mpeg4Video) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
frame, err := t.decoder.Decode(pkt)
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpfragmented.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Frame = t.remuxFrame(frame)
|
||||
u.Payload = t.remuxFrame(frame)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17,11 +17,9 @@ func TestMPEG4VideoProcessUnit(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
u1 := &unit.MPEG4Video{
|
||||
Base: unit.Base{
|
||||
PTS: 30000,
|
||||
},
|
||||
Frame: []byte{
|
||||
u1 := &unit.Unit{
|
||||
PTS: 30000,
|
||||
Payload: unit.PayloadMPEG4Video{
|
||||
0, 0, 1, byte(mpeg4video.VisualObjectSequenceStartCode),
|
||||
0, 0, 1, 0xFF,
|
||||
0, 0, 1, byte(mpeg4video.GroupOfVOPStartCode),
|
||||
@@ -32,18 +30,16 @@ func TestMPEG4VideoProcessUnit(t *testing.T) {
|
||||
err = p.ProcessUnit(u1)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, []byte{
|
||||
require.Equal(t, unit.PayloadMPEG4Video{
|
||||
0, 0, 1, byte(mpeg4video.VisualObjectSequenceStartCode),
|
||||
0, 0, 1, 0xFF,
|
||||
0, 0, 1, byte(mpeg4video.GroupOfVOPStartCode),
|
||||
0, 0, 1, 0xF0,
|
||||
}, u1.Frame)
|
||||
}, u1.Payload)
|
||||
|
||||
u2 := &unit.MPEG4Video{
|
||||
Base: unit.Base{
|
||||
PTS: 30000 * 2,
|
||||
},
|
||||
Frame: []byte{
|
||||
u2 := &unit.Unit{
|
||||
PTS: 30000 * 2,
|
||||
Payload: unit.PayloadMPEG4Video{
|
||||
0, 0, 1, byte(mpeg4video.GroupOfVOPStartCode),
|
||||
0, 0, 1, 0xF1,
|
||||
},
|
||||
@@ -59,12 +55,12 @@ func TestMPEG4VideoProcessUnit(t *testing.T) {
|
||||
}, forma.Config)
|
||||
|
||||
// test that params have been added to the frame
|
||||
require.Equal(t, []byte{
|
||||
require.Equal(t, unit.PayloadMPEG4Video{
|
||||
0, 0, 1, byte(mpeg4video.VisualObjectSequenceStartCode),
|
||||
0, 0, 1, 0xFF,
|
||||
0, 0, 1, byte(mpeg4video.GroupOfVOPStartCode),
|
||||
0, 0, 1, 0xF1,
|
||||
}, u2.Frame)
|
||||
}, u2.Payload)
|
||||
|
||||
// test that timestamp has increased
|
||||
require.Equal(t, u1.RTPPackets[0].Timestamp+30000, u2.RTPPackets[0].Timestamp)
|
||||
|
||||
@@ -2,7 +2,6 @@ package codecprocessor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpsimpleaudio"
|
||||
@@ -48,13 +47,11 @@ func (t *opus) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *opus) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.Opus)
|
||||
|
||||
func (t *opus) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
var rtpPackets []*rtp.Packet //nolint:prealloc
|
||||
pts := u.PTS
|
||||
|
||||
for _, packet := range u.Packets {
|
||||
for _, packet := range u.Payload.(unit.PayloadOpus) {
|
||||
pkt, err := t.encoder.Encode(packet)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -72,25 +69,17 @@ func (t *opus) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *opus) ProcessRTPPacket(
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.Opus{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -100,18 +89,17 @@ func (t *opus) ProcessRTPPacket(
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
packet, err := t.decoder.Decode(pkt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Packets = [][]byte{packet}
|
||||
u.Payload = unit.PayloadOpus{packet}
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ func TestOpusProcessUnit(t *testing.T) {
|
||||
p, err := New(1450, forma, true, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
unit := &unit.Opus{
|
||||
Packets: [][]byte{
|
||||
unit := &unit.Unit{
|
||||
Payload: unit.PayloadOpus{
|
||||
{
|
||||
0xfc, 0x1e, 0x61, 0x96, 0xfc, 0xf7, 0x9b, 0x23,
|
||||
0x5b, 0xc9, 0x56, 0xad, 0x05, 0x12, 0x2f, 0x6c,
|
||||
|
||||
@@ -3,10 +3,8 @@ package codecprocessor
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -24,15 +22,13 @@ func randUint32() (uint32, error) {
|
||||
// Processor is the codec-specific part of the processing that happens inside stream.Stream.
|
||||
type Processor interface {
|
||||
// process a Unit.
|
||||
ProcessUnit(unit.Unit) error
|
||||
ProcessUnit(*unit.Unit) error
|
||||
|
||||
// process a RTP packet and convert it into a unit.
|
||||
// process a RTP packet.
|
||||
ProcessRTPPacket(
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error)
|
||||
) error
|
||||
|
||||
initialize() error
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ package codecprocessor //nolint:dupl
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpvp8"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -48,10 +46,8 @@ func (t *vp8) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *vp8) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.VP8)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.Frame)
|
||||
func (t *vp8) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadVP8))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -65,25 +61,17 @@ func (t *vp8) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *vp8) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.VP8{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -93,7 +81,7 @@ func (t *vp8) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,14 +89,13 @@ func (t *vp8) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpvp8.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtpvp8.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Frame = frame
|
||||
u.Payload = unit.PayloadVP8(frame)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ package codecprocessor //nolint:dupl
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format"
|
||||
"github.com/bluenviron/gortsplib/v5/pkg/format/rtpvp9"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@@ -48,10 +46,8 @@ func (t *vp9) createEncoder() error {
|
||||
return t.encoder.Init()
|
||||
}
|
||||
|
||||
func (t *vp9) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
u := uu.(*unit.VP9)
|
||||
|
||||
pkts, err := t.encoder.Encode(u.Frame)
|
||||
func (t *vp9) ProcessUnit(u *unit.Unit) error { //nolint:dupl
|
||||
pkts, err := t.encoder.Encode(u.Payload.(unit.PayloadVP9))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -65,25 +61,17 @@ func (t *vp9) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||
}
|
||||
|
||||
func (t *vp9) ProcessRTPPacket( //nolint:dupl
|
||||
pkt *rtp.Packet,
|
||||
ntp time.Time,
|
||||
pts int64,
|
||||
u *unit.Unit,
|
||||
hasNonRTSPReaders bool,
|
||||
) (unit.Unit, error) {
|
||||
u := &unit.VP9{
|
||||
Base: unit.Base{
|
||||
RTPPackets: []*rtp.Packet{pkt},
|
||||
NTP: ntp,
|
||||
PTS: pts,
|
||||
},
|
||||
}
|
||||
) error {
|
||||
pkt := u.RTPPackets[0]
|
||||
|
||||
// remove padding
|
||||
pkt.Padding = false
|
||||
pkt.PaddingSize = 0
|
||||
|
||||
if len(pkt.Payload) > t.RTPMaxPayloadSize {
|
||||
return nil, fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
return fmt.Errorf("RTP payload size (%d) is greater than maximum allowed (%d)",
|
||||
len(pkt.Payload), t.RTPMaxPayloadSize)
|
||||
}
|
||||
|
||||
@@ -93,7 +81,7 @@ func (t *vp9) ProcessRTPPacket( //nolint:dupl
|
||||
var err error
|
||||
t.decoder, err = t.Format.CreateDecoder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,14 +89,13 @@ func (t *vp9) ProcessRTPPacket( //nolint:dupl
|
||||
if err != nil {
|
||||
if errors.Is(err, rtpvp9.ErrNonStartingPacketAndNoPrevious) ||
|
||||
errors.Is(err, rtpvp9.ErrMorePacketsNeeded) {
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
u.Frame = frame
|
||||
u.Payload = unit.PayloadVP9(frame)
|
||||
}
|
||||
|
||||
// route packet as is
|
||||
return u, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user