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

muxer fail then panic "writePacket: can't write 185 bytes of payload: only 184 is available... " on muxer.WriteData(&astits.MuxerData{ ... #50

Open
ayhangenc opened this issue Jun 13, 2023 · 1 comment

Comments

@ayhangenc
Copy link

ayhangenc commented Jun 13, 2023

Hi,

I'm working on a simple RTSP to SRT/MPEG-TS gateway (X.7). Lately I'm having error messages and panics during my development and tests.
Here is the test flow:

ffmpeg (mimicing a RTSP camera) --> RTSP server ( mediamtx) --> X.7 gateway app --> ffplay (mimicing SRT consumer)

RTSP Source:

ffmpeg -re -f lavfi -i "smptehdbars=rate=15:size=1280x720" -f lavfi -i "sine=frequency=1000:sample_rate=48000" -vf drawtext="text='Test Stream #1 // :timecode=01\:00\:00\:00':rate=25:x=(w-tw)/2:y=(h-lh)/2:fontsize=55:fontcolor=black:box=1:boxcolor=red" -f rtsp -c:v h264 -crf 26 -preset fast -tune zerolatency -c:a aac -b:a 128k "rtsp://127.0.0.1:8554/live1"

mediamtx is the prebuilt binary with default configuration available on github.

X.7 is using the following packages:
"github.com/asticode/go-astits"
"github.com/haivision/srtgo"
"github.com/bluenviron/gortsplib/v3"

X.7 decode H.264 video and MPEG-4 audio from RTSP stream using gortsplib, extract access units then feed them to MPEG-TS/SRT encoder.
the encoder muxes the access units into TS stream withgo- astits with SRT wrapping using srtgo then transmit it to SRT consumer.

and finally ffplay is acting like a SRT consumer
ffplay "srt://127.0.0.1:5808?mode=listener"

This workflow was working fine for several hours without any error or panic. Then last week I faced a panic with the working code.
The panic is not instant, I run the code, have a fine stream on ffplay for a while (several minutes mainly) then start to get error messages on app log

2023/06/13 10:46:23 SRT MPEGTS muxer write SRT Video error: writePacket: can't write 213 bytes of payload: only 182 is available... 

after some point the video on ffplay freeze and stay frozen forever and ffplay log popping the following following messages continously.

...
[mpegts @ 0x7fbf19f16c00] changing packet size to 192    0B f=0/0   
[mpegts @ 0x7fbf19f16c00] changing packet size to 188    0B f=0/0   
[mpegts @ 0x7fbf19f16c00] changing packet size to 192    0B f=0/0   
[mpegts @ 0x7fbf19f16c00] changing packet size to 188    0B f=0/0   
[mpegts @ 0x7fbf19f16c00] changing packet size to 204    0B f=0/0   
[mpegts @ 0x7fbf19f16c00] changing packet size to 188    0B f=0/0   
1906.04 A-V:520.879 fd= 123 aq=    0KB vq=    0KB sq=    0B f=0/0   
...

after a while, I have panic on app:

panic: runtime error: slice bounds out of range [120:0]

goroutine 52 [running]:
bytes.(*Buffer).Write(0x3?, {0xc000280318?, 0xc00004a970?, 0x10039f53b?})
        /usr/local/go/src/bytes/buffer.go:172 +0xd6
github.com/asticode/go-astikit.(*BitsWriter).write(0xc000298320, {0xc000280318, 0x1, 0x1})
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:142 +0x3d
github.com/asticode/go-astikit.(*BitsWriter).flushBsCache(...)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:169
github.com/asticode/go-astikit.(*BitsWriter).writeFullByte(0x0?, 0x20?)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:179 +0x7e
github.com/asticode/go-astikit.(*BitsWriter).writeByteSlice(0xc000298320, {0xc000599180, 0xa8, 0xc00004aaa0?})
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:130 +0x89
github.com/asticode/go-astikit.(*BitsWriter).Write(0xc000298320?, {0x1003e5cc0?, 0xc00004aa50?})
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:75 +0xa5
github.com/asticode/go-astits.writePESData(0x100405d00?, 0xc000282570?, {0xc000599180?, 0x1aa?, 0x1aa?}, 0x8?, 0xb6?)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astits@v1.11.0/data_pes.go:465 +0xb3
github.com/asticode/go-astits.(*Muxer).WriteData(0xc0002846e0, 0xc00004acb8)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astits@v1.11.0/muxer.go:230 +0x4dd
X.7/gateway.(*SRT).Encode(0xc0000e2580, {0xc0003c9aa0, 0x4, 0x10038d28a?}, {0x0?, 0x10005687f?, 0x10004e552?}, 0x7db35b0a00)
        /Users/anyuser/GolandProjects/X.7/gateway/srt.go:175 +0x10cd
X.7/gateway.(*Gateway).RunRTSP.func1(0xc000292140?)
        /Users/anyuser/GolandProjects/X.7/gateway/rtsp.go:127 +0x191
github.com/bluenviron/gortsplib/v3.(*clientFormat).readRTPUDP(0xc0002983c0, 0xc000282870?)
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_format.go:117 +0x185
github.com/bluenviron/gortsplib/v3.(*clientMedia).readRTPUDPPlay(0xc000296480, {0xc000176000, 0xc00004af20?, 0x5c1})
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_media.go:291 +0xae
github.com/bluenviron/gortsplib/v3.(*clientUDPListener).runReader(0xc0002b80e0)
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_udp_listener.go:195 +0x1e5
created by github.com/bluenviron/gortsplib/v3.(*clientUDPListener).start
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_udp_listener.go:153 +0xaa
exit status 2

This is how I implemented the encoder:
(error handling removed for brevity)

func (s *SRT) Encode(auv [][]byte, aua []byte, pts time.Duration) error {
	if auv != nil && aua == nil { //Video stream
		filteredNALUs := [][]byte{
			{byte(h264.NALUTypeAccessUnitDelimiter), 240},
		}
		nonIDRPresent := false
		idrPresent := false
		for _, nalu := range auv {
			typ := h264.NALUType(nalu[0] & 0x1F)
			switch typ {
			case h264.NALUTypeSPS:
				s.sps = append([]byte(nil), nalu...)
				continue
			case h264.NALUTypePPS:
				s.pps = append([]byte(nil), nalu...)
				continue
			case h264.NALUTypeAccessUnitDelimiter:
				continue
			case h264.NALUTypeIDR:
				idrPresent = true
			case h264.NALUTypeNonIDR:
				nonIDRPresent = true
			}
			filteredNALUs = append(filteredNALUs, nalu)
		}
		auv = filteredNALUs
		if !nonIDRPresent && !idrPresent {
			log.Println("IDR-nonIDR Not Present Error: ")
			return fmt.Errorf("IDR-nonIDR Not Present Error")
		}
		if idrPresent {
			auv = append([][]byte{s.sps, s.pps}, auv...)
		}
		var dts time.Duration
		if !s.firstIDRReceived {
			// skip samples silently until we find one with a IDR
			if !idrPresent {
				log.Println("IDR Not Present Error: ")
				return fmt.Errorf("IDR Not Present Error")
			}
			s.firstIDRReceived = true
			s.dtsExtractor = h264.NewDTSExtractor()
			dts, err = s.dtsExtractor.Extract(auv, pts)
			s.startDTS = dts
			dts = 0
			pts -= s.startDTS
		} else {
			dts, err = s.dtsExtractor.Extract(auv, pts)
			if err != nil {
				log.Println("DTS Extract Error: ", err)
			}
			dts -= s.startDTS
			pts -= s.startDTS
		}
		oh := &astits.PESOptionalHeader{
			MarkerBits: 2,
		}
		if dts == pts {
			oh.PTSDTSIndicator = astits.PTSDTSIndicatorOnlyPTS
			oh.PTS = &astits.ClockReference{Base: int64(pts.Seconds() * 90000)}
		} else {
			oh.PTSDTSIndicator = astits.PTSDTSIndicatorBothPresent
			oh.DTS = &astits.ClockReference{Base: int64(dts.Seconds() * 90000)}
			oh.PTS = &astits.ClockReference{Base: int64(pts.Seconds() * 90000)}
		}
		// encode into Annex-B
		annexb, err := h264.AnnexBMarshal(auv)
		// write TS packet to srt
		_, err = s.muxSRT.WriteData(&astits.MuxerData{   //////// this is where I get the error message !
			PID: 256,
			AdaptationField: &astits.PacketAdaptationField{
				RandomAccessIndicator: idrPresent,
			},
			PES: &astits.PESData{
				Header: &astits.PESHeader{
					OptionalHeader: oh,
					StreamID:       224, // video
				},
				Data: annexb,
			},
		})
	} else if auv == nil && aua != nil{ //Audio stream
		// wrap access unit inside an ADTS packet
		pkts := mpeg4audio.ADTSPackets{
			{
				Type:         s.config.Type,
				SampleRate:   s.config.SampleRate,
				ChannelCount: s.config.ChannelCount,
				AU:           aua,
			},
		}
		enc, err := pkts.Marshal()
		err = s.muxSRT.WriteData(&astits.MuxerData{  //////// this is where I get the error message !
			PID: 257,
			AdaptationField: &astits.PacketAdaptationField{
				RandomAccessIndicator: true,
			},
			PES: &astits.PESData{
				Header: &astits.PESHeader{
					OptionalHeader: &astits.PESOptionalHeader{
						MarkerBits:      2,
						PTSDTSIndicator: astits.PTSDTSIndicatorOnlyPTS,
						PTS:             &astits.ClockReference{Base: int64(pts.Seconds() * 90000)},
					},
					PacketLength: uint16(len(enc) + 8),
					StreamID:     192, // audio
				},
				Data: enc,
			},
		})
	}
	return nil
}

Thanks...

@ayhangenc
Copy link
Author

ayhangenc commented Jun 13, 2023

Hi,

here is an additional panic with no preceding error message on logs

panic: runtime error: slice bounds out of range [:1317] with capacity 1316

goroutine 11 [running]:
bufio.(*Writer).Flush(0x10014c575?)
        /usr/local/go/src/bufio/bufio.go:628 +0x185
bufio.(*Writer).Write(0xc000062780, {0xc000246000?, 0x1?, 0x1?})
        /usr/local/go/src/bufio/bufio.go:672 +0xd0
github.com/asticode/go-astikit.(*BitsWriter).write(0xc00006eb90, {0xc000246000, 0xb2, 0xc0})
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:142 +0x3d
github.com/asticode/go-astikit.(*BitsWriter).writeByteSlice(0xc00006eb40?, {0xc000246000?, 0x0?, 0x0?})
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:135 +0x45
github.com/asticode/go-astikit.(*BitsWriter).Write(0xc00006eb90?, {0x1003e5ca0?, 0xc000049a28?})
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:75 +0xa5
github.com/asticode/go-astits.writePacket(0x100405ce0?, 0xc000049ad8, 0xbc)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astits@v1.11.0/packet.go:347 +0x11d
github.com/asticode/go-astits.(*Muxer).WriteData(0xc0001702c0, 0xc000049cb8)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astits@v1.11.0/muxer.go:257 +0x5cf
X.7/gateway.(*SRT).Encode(0xc00012e420, {0xc0002c7200?, 0x4, 0x10038d20a?}, {0x0?, 0x1000567ff?, 0x10004e4d2?}, 0x3d0463fcaa)
        /Users/anyuser/GolandProjects/X.7/gateway/srt.go:174 +0x112d
X.7/gateway.(*Gateway).RunRTSP.func1(0xc00017bf40?)
        /Users/anyuser/GolandProjects/X.7/gateway/rtsp.go:127 +0x191
github.com/bluenviron/gortsplib/v3.(*clientFormat).readRTPUDP(0xc00006ec80, 0xc00017d020?)
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_format.go:117 +0x185
github.com/bluenviron/gortsplib/v3.(*clientMedia).readRTPUDPPlay(0xc000144c00, {0xc0002e4c00, 0xc000049f20?, 0x5c1})
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_media.go:291 +0xae
github.com/bluenviron/gortsplib/v3.(*clientUDPListener).runReader(0xc00015f180)
        /Users/anyuser/go/pkg/mod/github.com/b:195 +0x1e5
created by github.com/bluenviron/gortsplib/v3.(*clientUDPListener).start
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_udp_listener.go:153 +0xaa
exit status 2

and one more with a different rtsp source:
rtsp://zephyr.rtsp.stream/movie?streamKey=4***

panic: runtime error: slice bounds out of range [1318:1316]

goroutine 39 [running]:
bufio.(*Writer).Write(0xc00022a000, {0xc000210011?, 0x10014c655?, 0x10014c655?})
        /usr/local/go/src/bufio/bufio.go:670 +0x1c8
github.com/asticode/go-astikit.(*BitsWriter).write(0xc0002160a0, {0xc000210011, 0x1, 0x1})
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:142 +0x3d
github.com/asticode/go-astikit.(*BitsWriter).flushBsCache(...)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:169
github.com/asticode/go-astikit.(*BitsWriter).writeFullByte(0xc0002160a0?, 0xa6?)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:179 +0x7e
github.com/asticode/go-astikit.(*BitsWriter).Write(0x10039fb05?, {0x1003ebd80?, 0x100751498?})
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:83 +0x111
github.com/asticode/go-astikit.(*BitsWriterBatch).Write(...)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astikit@v0.40.0/binary.go:281
github.com/asticode/go-astits.writePacketAdaptationField(0xc0002160a0, 0xc0004605b0)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astits@v1.11.0/packet.go:473 +0x4d9
github.com/asticode/go-astits.writePacket(0x100405d20?, 0xc000048ad0, 0xbc)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astits@v1.11.0/packet.go:331 +0xa5
github.com/asticode/go-astits.(*Muxer).WriteData(0xc00022c000, 0xc000048c98)
        /Users/anyuser/go/pkg/mod/github.com/asticode/go-astits@v1.11.0/muxer.go:257 +0x5cf
X.7/gateway.(*SRT).Encode(0xc00012e420, {0x0?, 0xc000048da0?, 0xc000048df0?}, {0xc00045ef77?, 0xc11a7028aa97e288?, 0x61a1f258b?}, 0x44d2d0aaa)
        /Users/anyuser/GolandProjects/X.7/gateway/srt.go:216 +0x3d6
X.7/gateway.(*Gateway).RunRTSP.func2(0xc00025a0a0?)
        /Users/anyuser/GolandProjects/X.7/gateway/rtsp.go:155 +0x145
github.com/bluenviron/gortsplib/v3.(*clientFormat).readRTPUDP(0xc0002161e0, 0xc000220570?)
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_format.go:117 +0x185
github.com/bluenviron/gortsplib/v3.(*clientMedia).readRTPUDPPlay(0xc000234180, {0xc00045ec00, 0xc000048f20?, 0x5c1})
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_media.go:291 +0xae
github.com/bluenviron/gortsplib/v3.(*clientUDPListener).runReader(0xc00023a0e0)
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_udp_listener.go:195 +0x1e5
created by github.com/bluenviron/gortsplib/v3.(*clientUDPListener).start
        /Users/anyuser/go/pkg/mod/github.com/bluenviron/gortsplib/v3@v3.7.0/client_udp_listener.go:153 +0xaa
exit status 2

FYI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant