TS mux cuts large video frames short (not unbounded PES)
I also reported this in the Forum, but got no response yet. Since there is no similar bug open I'll file one...
We use H264/AAC live streaming VLC->TS->RTP->Wowza and have troubles with defective frames. We did lots of debugging with wireshark and we are absolutely sure they are not cause by UDP packetloss.
We were even able to reproduce this locally on one machine transcoding with VLC 2.1.5, streaming it to some RTP port and playing it back with VLC 2.1.5 again.
Only to set a reference to some reports in the Wowza-Forum: Wowza complains with "RTPPacket.write: Bad packet: Incomplete NAL Units" in case VLC sent a defective frame.
With verbose=1 on x264 encoder we were able to see that every time x264 outputs a frame larger then ~64k (or PES_PAYLOAD_SIZE_MAX) the videoframe is damaged (cut short).
Looking into the code at modules/mux/mpeg/ts.h:MuxStreams() shows that
i_max_pes_size = INT_MAX;
is only set for VLC_CODEC_DIRAC, but modules/mux/mpeg/pes.c:EStoPES(), which is called by MuxStreams() mentions
* EStoPES will only produce an unbounded PES packet if:
* - ES is VIDEO_ES
* - i_max_pes_size > PES_PAYLOAD_SIZE_MAX
* - length of p_es > PES_PAYLOAD_SIZE_MAX
Looking at the ITU papers it looks like VLC should send Videoframes >64k in MPEG-TS as unbounded RTP as well.
I added a check for VLC_CODEC_H264 like
--- ts.c.orig 2013-09-12 17:18:33.000000000 +0200
+++ ts.c 2014-10-13 14:45:59.701929549 +0200
@@ -1414,6 +1414,9 @@
i_max_pes_size = INT_MAX;
}
+ if( p_input->p_fmt->i_codec == VLC_CODEC_H264 )
+ i_max_pes_size = INT_MAX;
+
EStoPES ( &p_data, p_data, p_input->p_fmt, p_stream->i_stream_id,
1, b_data_alignment, i_header_size,
i_max_pes_size );
to modules/mux/mpeg/ts.c
It fixes our problems for H264.
Maybe a generic check like
--- ts.c.orig 2013-09-12 17:18:33.000000000 +0200
+++ ts.c 2014-10-13 14:48:12.674650788 +0200
@@ -1414,6 +1414,9 @@
i_max_pes_size = INT_MAX;
}
+ if( p_input->p_fmt->i_cat == VIDEO_ES )
+ i_max_pes_size = INT_MAX;
+
EStoPES ( &p_data, p_data, p_input->p_fmt, p_stream->i_stream_id,
1, b_data_alignment, i_header_size,
i_max_pes_size );
should be added? I'm not sure about all the specs.
Reproducing this is quite simple. Take a fast machine (core i5-4670 on Fedora 20 here), download a high quality video, eg.: https://www.scene.org/file.php?file=%2Fparties%2F2009%2Fbreakpoint09%2Fin4k%2Felevated_8000.avi&fileinfo
and transcode it live with VLC using (using mp3 as audio works as well):
vlc -vvv -I dummy --sout-avcodec-strict=-2 elevated_8000.avi :sout="#transcode{venc=x264{keyint=25,profile=baseline,crf=15,verbose=1},width=1024,vcodec=h264,scale=1,acodec=mp4a,ab=128,channels=2,samplerate=44100,audio-sync}:rtp{mux=ts,dst=127.0.0.1,port=20071}"
and replay it using VLC with
vlc rtp://@:20071
watch for the damaged picture. Most of the time the lower 1/2-1/3 is damaged. Every time you see this you will find Slice:I output from x264 with >64k frame size.
After building a VLC with the first patch the test shows no broken frame at all.
I tried this with same older VLC versions as well. Oldest I found was 1.1.4... same result.