Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

disable check for missing key frames (#1904) #2161

Merged
merged 1 commit into from
Aug 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 2 additions & 26 deletions internal/formatprocessor/av1.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/bluenviron/gortsplib/v3/pkg/formats"
"github.com/bluenviron/gortsplib/v3/pkg/formats/rtpav1"
"github.com/bluenviron/mediacommon/pkg/codecs/av1"
"github.com/pion/rtp"

"github.com/bluenviron/mediamtx/internal/logger"
Expand All @@ -24,10 +23,8 @@ type formatProcessorAV1 struct {
format *formats.AV1
log logger.Writer

encoder *rtpav1.Encoder
decoder *rtpav1.Decoder
lastKeyFrameTimeReceived bool
lastKeyFrameTime time.Time
encoder *rtpav1.Encoder
decoder *rtpav1.Decoder
}

func newAV1(
Expand Down Expand Up @@ -59,24 +56,6 @@ func (t *formatProcessorAV1) createEncoder() error {
return t.encoder.Init()
}

func (t *formatProcessorAV1) checkKeyFrameInterval(ntp time.Time, isKeyFrame bool) {
if !t.lastKeyFrameTimeReceived || isKeyFrame {
t.lastKeyFrameTimeReceived = true
t.lastKeyFrameTime = ntp
return
}

if ntp.Sub(t.lastKeyFrameTime) >= maxKeyFrameInterval {
t.lastKeyFrameTime = ntp
t.log.Log(logger.Warn, "no AV1 key frames received in %v, stream can't be decoded", maxKeyFrameInterval)
}
}

func (t *formatProcessorAV1) checkOBUs(ntp time.Time, obus [][]byte) {
containsKeyFrame, _ := av1.ContainsKeyFrame(obus)
t.checkKeyFrameInterval(ntp, containsKeyFrame)
}

func (t *formatProcessorAV1) Process(unit Unit, hasNonRTSPReaders bool) error { //nolint:dupl
tunit := unit.(*UnitAV1)

Expand Down Expand Up @@ -112,16 +91,13 @@ func (t *formatProcessorAV1) Process(unit Unit, hasNonRTSPReaders bool) error {
}

tunit.OBUs = obus
t.checkOBUs(tunit.NTP, obus)
tunit.PTS = pts
}

// route packet as is
return nil
}

t.checkOBUs(tunit.NTP, tunit.OBUs)

// encode into RTP
pkts, err := t.encoder.Encode(tunit.OBUs, tunit.PTS)
if err != nil {
Expand Down
43 changes: 0 additions & 43 deletions internal/formatprocessor/av1_test.go
Original file line number Diff line number Diff line change
@@ -1,44 +1 @@
package formatprocessor

import (
"testing"
"time"

"github.com/bluenviron/gortsplib/v3/pkg/formats"
"github.com/stretchr/testify/require"
)

func TestAV1KeyFrameWarning(t *testing.T) { //nolint:dupl
forma := &formats.AV1{
PayloadTyp: 96,
}

w := &testLogWriter{recv: make(chan string, 1)}
p, err := New(1472, forma, true, w)
require.NoError(t, err)

ntp := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
err = p.Process(&UnitAV1{
BaseUnit: BaseUnit{
NTP: ntp,
},
OBUs: [][]byte{
{0x01},
},
}, false)
require.NoError(t, err)

ntp = ntp.Add(30 * time.Second)
err = p.Process(&UnitAV1{
BaseUnit: BaseUnit{
NTP: ntp,
},
OBUs: [][]byte{
{0x01},
},
}, false)
require.NoError(t, err)

logl := <-w.recv
require.Equal(t, "no AV1 key frames received in 10s, stream can't be decoded", logl)
}
37 changes: 10 additions & 27 deletions internal/formatprocessor/h264.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,8 @@ type formatProcessorH264 struct {
format *formats.H264
log logger.Writer

encoder *rtph264.Encoder
decoder *rtph264.Decoder
lastKeyFrameTimeReceived bool
lastKeyFrameTime time.Time
encoder *rtph264.Encoder
decoder *rtph264.Decoder
}

func newH264(
Expand Down Expand Up @@ -146,12 +144,12 @@ func (t *formatProcessorH264) updateTrackParametersFromRTPPacket(pkt *rtp.Packet
}
}

func (t *formatProcessorH264) updateTrackParametersFromNALUs(nalus [][]byte) {
func (t *formatProcessorH264) updateTrackParametersFromAU(au [][]byte) {
sps := t.format.SPS
pps := t.format.PPS
update := false

for _, nalu := range nalus {
for _, nalu := range au {
typ := h264.NALUType(nalu[0] & 0x1F)

switch typ {
Expand All @@ -174,24 +172,11 @@ func (t *formatProcessorH264) updateTrackParametersFromNALUs(nalus [][]byte) {
}
}

func (t *formatProcessorH264) checkKeyFrameInterval(ntp time.Time, isKeyFrame bool) {
if !t.lastKeyFrameTimeReceived || isKeyFrame {
t.lastKeyFrameTimeReceived = true
t.lastKeyFrameTime = ntp
return
}

if ntp.Sub(t.lastKeyFrameTime) >= maxKeyFrameInterval {
t.lastKeyFrameTime = ntp
t.log.Log(logger.Warn, "no H264 key frames received in %v, stream can't be decoded", maxKeyFrameInterval)
}
}

func (t *formatProcessorH264) remuxAccessUnit(ntp time.Time, nalus [][]byte) [][]byte {
func (t *formatProcessorH264) remuxAccessUnit(au [][]byte) [][]byte {
isKeyFrame := false
n := 0

for _, nalu := range nalus {
for _, nalu := range au {
typ := h264.NALUType(nalu[0] & 0x1F)

switch typ {
Expand All @@ -214,8 +199,6 @@ func (t *formatProcessorH264) remuxAccessUnit(ntp time.Time, nalus [][]byte) [][
n++
}

t.checkKeyFrameInterval(ntp, isKeyFrame)

if n == 0 {
return nil
}
Expand All @@ -229,7 +212,7 @@ func (t *formatProcessorH264) remuxAccessUnit(ntp time.Time, nalus [][]byte) [][
i = 2
}

for _, nalu := range nalus {
for _, nalu := range au {
typ := h264.NALUType(nalu[0] & 0x1F)

switch typ {
Expand Down Expand Up @@ -294,7 +277,7 @@ func (t *formatProcessorH264) Process(unit Unit, hasNonRTSPReaders bool) error {
return err
}

tunit.AU = t.remuxAccessUnit(tunit.NTP, au)
tunit.AU = t.remuxAccessUnit(au)
tunit.PTS = pts
}

Expand All @@ -303,8 +286,8 @@ func (t *formatProcessorH264) Process(unit Unit, hasNonRTSPReaders bool) error {
return nil
}
} else {
t.updateTrackParametersFromNALUs(tunit.AU)
tunit.AU = t.remuxAccessUnit(tunit.NTP, tunit.AU)
t.updateTrackParametersFromAU(tunit.AU)
tunit.AU = t.remuxAccessUnit(tunit.AU)
}

// encode into RTP
Expand Down
48 changes: 0 additions & 48 deletions internal/formatprocessor/h264_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,14 @@ package formatprocessor

import (
"bytes"
"fmt"
"testing"
"time"

"github.com/bluenviron/gortsplib/v3/pkg/formats"
"github.com/bluenviron/mediacommon/pkg/codecs/h264"
"github.com/pion/rtp"
"github.com/stretchr/testify/require"

"github.com/bluenviron/mediamtx/internal/logger"
)

type testLogWriter struct {
recv chan string
}

func (w *testLogWriter) Log(_ logger.Level, format string, args ...interface{}) {
w.recv <- fmt.Sprintf(format, args...)
}

func TestH264DynamicParams(t *testing.T) {
forma := &formats.H264{
PayloadTyp: 96,
Expand Down Expand Up @@ -207,39 +195,3 @@ func TestH264EmptyPacket(t *testing.T) {
// if all NALUs have been removed, no RTP packets must be generated.
require.Equal(t, []*rtp.Packet(nil), unit.RTPPackets)
}

func TestH264KeyFrameWarning(t *testing.T) {
forma := &formats.H264{
PayloadTyp: 96,
PacketizationMode: 1,
}

w := &testLogWriter{recv: make(chan string, 1)}
p, err := New(1472, forma, true, w)
require.NoError(t, err)

ntp := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
err = p.Process(&UnitH264{
BaseUnit: BaseUnit{
NTP: ntp,
},
AU: [][]byte{
{0x01},
},
}, false)
require.NoError(t, err)

ntp = ntp.Add(30 * time.Second)
err = p.Process(&UnitH264{
BaseUnit: BaseUnit{
NTP: ntp,
},
AU: [][]byte{
{0x01},
},
}, false)
require.NoError(t, err)

logl := <-w.recv
require.Equal(t, "no H264 key frames received in 10s, stream can't be decoded", logl)
}
37 changes: 10 additions & 27 deletions internal/formatprocessor/h265.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,8 @@ type formatProcessorH265 struct {
format *formats.H265
log logger.Writer

encoder *rtph265.Encoder
decoder *rtph265.Decoder
lastKeyFrameTimeReceived bool
lastKeyFrameTime time.Time
encoder *rtph265.Encoder
decoder *rtph265.Decoder
}

func newH265(
Expand Down Expand Up @@ -160,13 +158,13 @@ func (t *formatProcessorH265) updateTrackParametersFromRTPPacket(pkt *rtp.Packet
}
}

func (t *formatProcessorH265) updateTrackParametersFromNALUs(nalus [][]byte) {
func (t *formatProcessorH265) updateTrackParametersFromAU(au [][]byte) {
vps := t.format.VPS
sps := t.format.SPS
pps := t.format.PPS
update := false

for _, nalu := range nalus {
for _, nalu := range au {
typ := h265.NALUType((nalu[0] >> 1) & 0b111111)

switch typ {
Expand Down Expand Up @@ -195,24 +193,11 @@ func (t *formatProcessorH265) updateTrackParametersFromNALUs(nalus [][]byte) {
}
}

func (t *formatProcessorH265) checkKeyFrameInterval(ntp time.Time, isKeyFrame bool) {
if !t.lastKeyFrameTimeReceived || isKeyFrame {
t.lastKeyFrameTimeReceived = true
t.lastKeyFrameTime = ntp
return
}

if ntp.Sub(t.lastKeyFrameTime) >= maxKeyFrameInterval {
t.lastKeyFrameTime = ntp
t.log.Log(logger.Warn, "no H265 key frames received in %v, stream can't be decoded", maxKeyFrameInterval)
}
}

func (t *formatProcessorH265) remuxAccessUnit(ntp time.Time, nalus [][]byte) [][]byte {
func (t *formatProcessorH265) remuxAccessUnit(au [][]byte) [][]byte {
isKeyFrame := false
n := 0

for _, nalu := range nalus {
for _, nalu := range au {
typ := h265.NALUType((nalu[0] >> 1) & 0b111111)

switch typ {
Expand All @@ -235,8 +220,6 @@ func (t *formatProcessorH265) remuxAccessUnit(ntp time.Time, nalus [][]byte) [][
n++
}

t.checkKeyFrameInterval(ntp, isKeyFrame)

if n == 0 {
return nil
}
Expand All @@ -251,7 +234,7 @@ func (t *formatProcessorH265) remuxAccessUnit(ntp time.Time, nalus [][]byte) [][
i = 3
}

for _, nalu := range nalus {
for _, nalu := range au {
typ := h265.NALUType((nalu[0] >> 1) & 0b111111)

switch typ {
Expand Down Expand Up @@ -316,7 +299,7 @@ func (t *formatProcessorH265) Process(unit Unit, hasNonRTSPReaders bool) error {
return err
}

tunit.AU = t.remuxAccessUnit(tunit.NTP, au)
tunit.AU = t.remuxAccessUnit(au)
tunit.PTS = pts
}

Expand All @@ -325,8 +308,8 @@ func (t *formatProcessorH265) Process(unit Unit, hasNonRTSPReaders bool) error {
return nil
}
} else {
t.updateTrackParametersFromNALUs(tunit.AU)
tunit.AU = t.remuxAccessUnit(tunit.NTP, tunit.AU)
t.updateTrackParametersFromAU(tunit.AU)
tunit.AU = t.remuxAccessUnit(tunit.AU)
}

// encode into RTP
Expand Down
Loading
Loading