Creating DVB-T compatible MPEG2 streams using FFMPEG
I have been trying to generate MPEG2 streams using FFMPEG for a cable TV project I'm working on. The streams are to be created in real-time and encapsulated in MPEG-TS and sent over an Ethernet network using multicast UDP. No RTP just plain MPEG-TS in UDP. These streams are to be received by Telesté Luminato boxes equipped with DVB-T muxes. This has been somewhat a struggle. Generating a stable stream without errors and dropouts was definitely harder than I initially thought. DVB muxers (or shall we call them modulators?) need to run at a constant bit rate, CBR. I won't go into the details of DVB-T modulation but this is quite reasonable since it is most likely the only way of keeping it in sync and locked. In the same time the material transferred is in most cases MPEG2 video (at least here in Sweden). This is a bit odd to begin with since as far as I know there is no such thing as a CBR MPEG2. But why are people in the TV biz talking about CBR MPEG2? This needed some research and I discovered that my assumption was not totally wrong. MPEG2 in its initial form will always be a stream with variable bit rate, VBR. In order to generate a CBR stream a buffer is used to "even out" the variable bit rate into a somewhat constant bit rate. INPUT--->[MPEG2 encoder]--VBR-->[buffer]--CBR-->OUTPUT Similarly a buffer is used on the receiving end to decode the MPEG2 stream. INPUT--CBR-->[buffer]--VBR-->[MPEG2 decoder]--->OUTPUT So far so good. No magic is happening here. Using a buffer in this way is quite common. Now let's look into how FFMPEG fits into this picture. My experiments are based on the latest release of FFMPEG (at the time of writing 0.11.1 "Happiness"). Creating a basic PAL MPEG2 TS stream using FFMPEG is quite straight forward. # ffmpeg -re -i [source] -vcodec mpeg2video -s 720x576 -r 25 -acodec mp2 -ac 2 -f mpegts outfile.ts This will generate an MPEG-TS file but sending the material over UDP requires just replacing "outfile.ts" with "udp://239.253.253.4:1234?pkt_size=1316". The size of an MPEG-TS packet is 188 Bytes and 7 of them will fit into an Ethernet frame, 7*188=1316. The command is simplified and since for example no bit rates are defined the resulting stream will be of low quality using the pre-compiled default values of FFMPEG. For my purpose the maximum bit rate per channel is 5Mbit/sec in order to not overload the muxes/modulators. The obvious first thing to try for me was to define some bit rates for FFMPEG to work with. For example "-b:v 2M" and "-b:a 192k" for video and audio respectively. # ffmpeg -re -i [source] -vcodec mpeg2video -s 720x576 -r 25 -b:v 2M -acodec mp2 -ac 2 -b:a 192k -f mpegts udp://239.253.253.4:1234?pkt_size=1316 The above command looks like a good start. 2Mb/s video and 192kb/s audio should give some headroom and not hit the limit of 5Mb/s. Right? Well, not really. Analyzing the resulting network utilization showed me an accumulated bit rate of over 50Mb/s at some points! This is quite far away from the requested 2Mb/s video bit rate. Obviously more is needed for this to work. FFMPEG has another parameter "-bt:v" which, according to the built in help, is the bit rate tolerance for video. However, adding something like "-bt:v 200k" to the command did not improve on the situation very much. The bit rate spikes was still way to high. Reading the documentation even further three other parameters looks promising, "-maxrate", "-minrate" and "-bufsize". Using these parameters instead of the single bit rate tolerance parameter has a better effect on the stream. # ffmpeg -re -i [source] -vcodec mpeg2video -s 720x576 -r 25 -b:v 2M -minrate:v 2M -maxrate:v 2M -bufsize:v 1.4M -acodec mp2 -ac 2 -b:a 192k -f mpegts udp://239.253.253.4:1234?pkt_size=1316 Using the command above the spikes are significantly reduced and the bandwidth looks like it is keeping well below 5Mb/s, more likely 2.5Mb/s. The stream actually plays quite nicely on my DVB-T receiver. The playback quality is however not as good as "real" DVB-T channels and there are occasional dropped frames and errors in both video and audio. Increasing the video bit rate variables and playing with GOP and BF, "-g 12 -bf 2", increases the quality to be quite good actually but the occasional dropouts and errors are still there. Forcing FFMPEG to use a constant GOP size with "-flags cgop -sc_threshold 1000000000" improves this even more but it is still not nearly perfect. It turns out that increasing bit rate also increases the frequency of the errors. A bit rate of around 1Mb/s has almost no errors but is of course of way to low quality. A bit rate of 3Mb/s yields good quality but too many errors. 2Mb/s is the best compromise by my observations. Worth mentioning is that VLC has no problem playing back this stream. Playing even more with bufsize shows that FFMPEG is a bit picky about this value. Too small and FFMPEG won't start and too large and it will run but give the following error: "Warning vbv_delay will be set to 0xFFFF (=VBR) as the specified vbv buffer is too large for the given bitrate!". Varying bufsize within the limits according to FFMPEG has no obvious impact on playback quality. The MPEG-TS muxer of FFMPEG has the ability to send out NULL packets using the parameter "-muxrate" to keep a constant total bit rate. This however does not make any difference. Probably because the Luminato modulators I use remuxes the streams anyway. The best working command I have for now is the following. # ffmpeg -re -i [source] -vcodec mpeg2video -s 720x576 -r 25 -flags cgop+ilme -sc_threshold 1000000000 -b:v 2M -minrate:v 2M -maxrate:v 2M -bufsize:v 1.4M -acodec mp2 -ac 2 -b:a 192k -f mpegts udp://239.253.253.4:1234?pkt_size=1316 Just sending out a raw DVB-T MPEG-TS recording using FFMPEG is working very well though. No errors during playback. # ffmpeg -re -i recording.ts -vcodec copy -acodec copy -f mpegts udp://239.253.253.4?pkt_size=1316 This makes me wonder. Even if the MPEG-TS muxer part of FFMPEG appears to be working, is the MPEG2 encoder still not keeping the bit rate under control? If the transfer bit rate is within limits, is the playback bit rate after the buffer within reasonable limits? Perhaps a hardware decoder such as an DVB-T set-top box have a lower limit for how high playback bit rate it can handle. More investigation is needed.
by Alok 2013-01-10 07:40 UTC
Thank you very much for this informative article. I was trying very hard to come across a command line for DVB-S compatible mpeg-2 stream from ffmpeg, and this helped me very much. The latest version of ffmpeg seems to be doing a better job of mpeg-2 encoding. You can pull this from git.


by daniel 2013-02-12 08:47 UTC
Thank you! I'm glad you found my writing useful. I agree with you that the latest version of ffmpeg does a better job although still not perfect. Not sure exactly what has changed since my initial testing. I have experimented a bit with vlc as well. This line also produces a DVB-T compatible stream that actually has fewer dropouts and better quality (using vlc 1.1.3 and ffmpeg 1.0). cvlc <source> vlc://quit --sout '#transcode{width=720,height=576,fps=25,vcodec=mp2v,vb=3500,acodec=mp4a,ab=192,channels=2,samplerate=48000,audio-sync}:standard{access=udp,mux=ts{use-key-frames},dst=239.253.253.2:1234}'


by rowy 2013-04-23 03:10 UTC
we've had some improved results using 2 pass encoding to even out the bitrate. this still doesnt fix the fact that: a) ffmpeg does not mux a compliant MPEG-2 TS b) doesnt allow you to alter the PCR rate c) ffmpeg and vlc as muxers will get you nowhere fast with cheaper TV's (massive sync issues). i'm assuming this is thanks to their lack of buffering, lack of standards compliance, and possibly the PCR clocking from the muxers not being adjustable to something reasonable (40ms) we are currently looking at Opencaster to mux, to see if we get better results. we'll let you know.


by rowy 2013-04-23 03:14 UTC
on another note, i noticed a ffmpeg dev discussion here: http://comments.gmane.org/gmane.comp.video.ffmpeg.devel/157919 regarding possibly fixing the mpegtsenc compliance... just hope it finds its way into a release sooner rather than later...


by daniel 2013-05-07 11:00 UTC
Good input! Feels good to hear I'm not the only one tinkering with this. I also noted that cheaper receivers are having bigger troubles. Interesting to hear that 2 pass encoding improves the situation. It is not an option for me though as I'm doing only live encoding. I have actually had quite good results lately using VLC 2.0.3 and 2.0.6 instead. Using 2.0.3 from debian backports and compiled 2.0.6 from source now with comparable results (had to build from source only to get Blackmagic DeckLink modules working). Quality is quite acceptable for SD material using the line below and plays nicely on cheap decoders too! cvlc [source] --sout '#transcode{width=720,height=576,fps=25,vcodec=mp2v,vb=3500,acodec=mp2a,ab=128,channels=2,samplerate=48000,audio-sync}:standard{access=udp,mux=ts{use-key-frames},dst=239.253.253.3:1234}' Hopefully the encoding in ffmpeg will be worked out soon.


by dvbman 2013-08-13 19:57 UTC
Nice solution, I have question about licensing for mpeg codec, buying license is necessary or not? Please check MPEG LA


by daniel 2013-08-19 21:51 UTC
I'm definitely no expert on this matter but as far as I know MPEGLA does not deal with end users and FFmpeg and VLC are both released under GPL.


by josef 2013-09-07 05:44 UTC
Did you really use these cmd line arguments: -v:b and -v:a ? ffmpeg -re -i [source] -vcodec mpeg2video -s 720x576 -r 25 -flags cgop+ilme -sc_threshold 1000000000 -v:b 2M -minrate:v 2M -maxrate:v 2M -bufsize:v 1.4M -acodec mp2 -ac 2 -a:b 192k -f mpegts udp://239.253.253.4:1234??pkt_size=1316 I assume the correct one is: ffmpeg -re -i [source] -vcodec mpeg2video -s 720x576 -r 25 -flags cgop+ilme -sc_threshold 1000000000 -b:v 2M -minrate:v 2M -maxrate:v 2M -bufsize:v 1.4M -acodec mp2 -ac 2 -b:a 192k -f mpegts udp://239.253.253.4:1234??pkt_size=1316 otherwise you get a ffmpeg complain about unknown loglevel (which -v stands for) Anyway, thansk for the greta post and analysis Josef


by daniel 2013-09-11 06:54 UTC
Thank you Josef! You are correct. That's a typo from my side. I have corrected the article now. I'm glad you found my writing useful.


by jfrez 2013-10-23 14:07 UTC
HI, I HAVE A VERY SENSITIVE VBR PLAYOUT, AND IN ORDER TO GET A CBR MPEGTS UDP STREAM A GOT THIS COMMAND: ffmpeg -re -i [input] -preset ultrafast -qp 0 -vcodec libx264 -an -bufsize:v 10M -minrate:v 10M -maxrate:v 10M -ac 2 -x264opts bitrate=10000:vbv-maxrate=10000:vbv-bufsize=400:ratetol=400:bitrate=10000:vbv-init=800 -acodec mp2 -strict -2 -b:a 192k -mpegts_transport_stream_id 0x0001 -mpegts_service_id 0x0bba -mpegts_start_pid 0x0bba -muxrate 11M -s 720x576 -flags cgop+ilme -sc_threshold 1000000000 -f mpegts udp://172.16.101.80:8000??pkt_size=1316


by jep 2013-11-05 10:59 UTC
Thanks for useful article. Some additional informations: 1. "-muxrate" makes the difference for hw decoders bacause it also sets pcr interval to around 20ms (default is 70-80 and causes clock jitter > 500ns). 2. On my windows system, I have to set just 1 "?" before "pkt_size=1316". 3. hw decoders are very sensitive about stream features. Don't know if this is a normal fact due to hw limitations of ffmpeg/vlc issue.


by Ramon 2013-12-26 11:00 UTC
Hi Nice article. Nevertheless, I have problems with memory leaks and the ffmpeg first consumes all memory, changes than to swap and when this is finished. Output is not consumable. Did you face similar problems? ramat@pizzly:~$ ffmpeg --version ffmpeg version N-59193-g4a2570f Copyright (c) 2000-2013 the FFmpeg developers built on Dec 18 2013 19:51:41 with gcc 4.6 (Ubuntu/Linaro 4.6.3-1ubuntu5) configuration: --enable-libx264 --enable-gpl --enable-nonfree --enable-libfdk-aac --prefix=/usr/local libavutil 52. 58.101 / 52. 58.101 libavcodec 55. 45.102 / 55. 45.102 libavformat 55. 22.100 / 55. 22.100 libavdevice 55. 5.102 / 55. 5.102 libavfilter 4. 0.100 / 4. 0.100 libswscale 2. 5.101 / 2. 5.101 libswresample 0. 17.104 / 0. 17.104 libpostproc 52. 3.100 / 52. 3.100 Any Idea? What ffmpeg version are you using? Regards


by Ramon 2013-12-27 17:42 UTC
I actually had a misconfiguration and twise $input in the command line, which lead to some problems. Regards


by Levi 2014-01-06 10:12 UTC
You might want to take a look at OpenCaster for the transport stream muxing -- you can use ffmpeg to generate the video elementary stream and then put it through the opencaster utilities to get something that actually works (at least that's what we did). Caveat: there's a fair bit of documentation to wade through but the manual is quite well written. Beware that [at least with older versions] ffmpeg's rate control is pretty poor (setting low VBV constraints was as good as useless).


by Dion 2014-02-13 10:18 UTC
Hi, Very good artilcle . I am also trying to transcode with ffmpeg live multicast input into live multicast ts output. This is my command line : sudo ffmpeg -i udp://224.1.*.*:1234 -vcodec libx264 -profile:v main -preset veryfast -pix_fmt yuv420p -s 720x576 -r 25 -g 200 -keyint_min 12 -bf 3 -b_strategy 1 -crf 17 -b:v 900k -minrate 900k -maxrate 900k -bufsize 900k -threads 16 -acodec libfdk_aac -ar 48000 -b:a 128k -f mpegts -muxrate 1500k -flags cgop+ilme -sc_threshold 1000000000 udp://224.2.*.*:1234?pkt_size=1316 I get good results with muxrate and CBR output, but the output has many PTS discontinuities which were discovered only through careful examination of the output stream ( Stream expert analyzer software did not display any errors ) . Those PTS discontinuities can affect playback on STBs if the encoded ffmpeg output will be used for catch-up TV recordings. I have the impression that it is ffmpeg's muxer that is causing the problem. I will also give a shot to OpenCaster but i am not sure if it works only with files or can accept directly multicast input and if i can combine it with the ffmpeg. Any advise will be appreciated.


by svyatko 2014-02-28 08:50 UTC
HI guys. I am having some serious problems with decoding MPEGTS produced by FFMPEG. I am using uk's CBBC HD channel off air as a source, compressing that to 4Mbps multicast SPTS stream. with the following command: ./ffmpeg -threads 0 -f mpegts -i udp://@239.255.2.18:1234?reuse=true -map v:0 -map a:0 -c:v libx264 -tune zerolatency -preset:v veryfast -x264opts bitrate=4000:vbv-maxrate=4000:vbv-bufsize=3000:ratetol=200:vbv-init=200 -pix_fmt yuv420p -bf 3 -b_strategy 1 -crf 17 -profile:v high -level:v 4.1 -r 25.00 -g 25 -s 1920x1080 -aspect 16:9 -b:v 4M -minrate 4M -maxrate 4M -bufsize 2M -c:a libvo_aacenc -b:a 128000 -ar 44100 -ac 2 -mpegts_flags resend_headers -f mpegts -muxrate 5000k -flags cgop -sc_threshold 500 udp://239.0.0.8:5000?pkt_size=1316 That bit works fine, I am not seeing any issues. Then my problem begins when I try to decode the stream created with the above command using FFMPEG. Errors I am getting are of this sort: [mpegts @ 0x38caa60] PES packet size mismatch= 7170kB time=00:01:56.15 bitrate= 505.6kbits/s [h264 @ 0x64e8460] error while decoding MB 102 61, bytestream -7 [h264 @ 0x64e8460] Cannot use next picture in error concealment [h264 @ 0x64e8460] concealing 787 DC, 787 AC, 787 MV errors in P frame [mpegts @ 0x38caa60] PES packet size mismatch= 7641kB time=00:02:03.79 bitrate= 505.6kbits/s [h264 @ 0x639c600] error while decoding MB 97 60, bytestream -5 [h264 @ 0x639c600] Cannot use next picture in error concealment [h264 @ 0x639c600] concealing 912 DC, 912 AC, 912 MV errors in P frame This results in constant picture break up and distortion. Any advise would be appreciated. cheers svyatko


by devil 2014-04-10 07:14 UTC
Hi! This article helped a lot to me in creating DVB streams, so I would like to say thanks to the creator. After some experiencing, I found that ffmpeg-vlc combination will be the best for me. Vlc has some problems with encoding, ffmpeg's ts muxer seems to be broken. So my actually working solution: mkfifo /tmp/ffmpeg.fifo cvlc /tmp/ffmpeg.fifo --sout-all --sout-ts-shaping=1000 --sout=#'standard{access=udp,mux=ts{pcr=40,pid-pmt=310,pid-video=311,pid-audio=312,tsid=1,netid=1,program-pmt="302",sdtdesc="provider,program name",use-key-frames},dst=233.0.0.1:1001}' -I dummy -d --file-logging --pidfile /tmp/vlc_mux.pid --logfile /tmp/vlc_mux.log ffmpeg -i udp://233.1.1.1:1111 -pix_fmt yuv420p -g 12 -c:v mpeg2video -b:v 3M -minrate:v 3M -maxrate:v 3M -bufsize:v 1.8M -c:a mp2 -b:a 128k -flags cgop+ilme -sc_threshold 1000000000 -map 0:0 -map 0:1 -loglevel warning -f mpegts - > /tmp/ffmpeg.fifo FFmpeg (current) does the demultiplexing from a SPTS stream (to filter out one program from a MPTS, check VideoLAN's DVBlast), decoding and encoding, passes it to VLC (2.0.3), who creates a DVB compliant mpeg ts. Unfortunately the created stream is VBR, but it seems to work fine with our multiplexer, and after the set-top boxes and tvs. Regards, devil (ps: sorry for my english)


by M+AUDIO 2014-08-26 11:50 UTC
Hello some notes to some comments: libx264 in ffmpeg does not know -minrate at all. and setting both -crf and -b:v is wrong. they will never be used together at all. two different ratecontrol modes. ffmpeg will prefer one and ignore the other switch. and about buffer size of mpeg-2 streams, according to itu-t h262 1995 tech spec (http://www.itu.int/rec/T-REC-H.262), the buffer size of SD mpeg2 video in main@main should be 1835008 bits. which means 224 kilobytes. and means -bufsize:v 1835008. for other resolutions and other profiles, just download the spec in pdf and search "table 8-14" in your pdf viewer. so some new test would be welcome? (and sorry for my bad english!)


by Tao Lei 2015-04-08 01:19 UTC
Really good and practical article ! Worthful step by step guidance.


by Karthikeyan 2015-04-19 02:29 UTC
Great article Daniel and devil's solution to mix ffmpeg and vlc is also a good fix to ffmpeg's ts problems.


by ztutberidze 2015-07-31 22:11 UTC
The big problem to generate cbr live stream over udp in ffmpeg is that, there is little mistake in udp protocol implementation. even if you configured ffmpeg correctly there is proble with bitrate. when ffmpeg's mpegts muxer sends the muxed packet over udp, the udp protocol implementation is sending the whole packet without any delay. for example: if we have stream with 25fps we should send 25 frames with 40ms delay between them and each encoded frame 25k size. so what ffmpeg will do, it will send the 25k frame as quick as possible an will wait until the next frame will be available. it gives us about 100mbps in short time, and then will wait about 39ms until next frame will be available. so the picture we have: transfer whole frame in very short time and getting high bitrate in ~1ms and then wait 39ms before next frame arrives to be send on the muxer. if we calculate bitrate for one secund then we get the same result which we expect, but it's not correct result and makes problems in low speed networks and in special kind of muxers which expects real stable constant bitrate, because the buffer is filling very fast in short time and thus u are lossing multicast packets. i made little patch in ffmpeg udp and added small delay between udp packet sends and the problem solved. i suggest u make the same thing.


by Alberto 2015-08-10 21:07 UTC
Dear ztutberidze, where can we find the UDP patch you mentioned?


by Gabriel 2015-08-12 12:18 UTC
Hi, could you please provide some more information about the concrete model of DVB muxer (or modulator) you're using to feed ffmpeg's input? Thank you!


by nesa 2015-10-30 16:42 UTC
no one has found a solution? I found a solution for peaks, but have blurred picture here and there. I put the buffer to be 1 frame or buffer = max datarate / framrate, and so I do not have drop and have no errors, but also with the picture I'm not satisfied, if someone is interested to complete (since the ffmpeg team has no interest to solve the problem, given the problem is not good for WebTV, or for IPTV or DVB-C), there is no one patch that will correct to deploy packages - without peaks


by nesa 2015-10-30 16:45 UTC
Dropped packets 12 Duplicate packets 0 Reordered packets 0 Discontinuities detected 28 Incorrect sequence numbers 97 this is with 1.4M buffer


by nesa 2015-10-31 02:11 UTC
#!/bin/bash killall ffmpeg-298 # transcode RT HD x264 to SD x264, without errors, without spikes, bursts and clear video picture # please try & assist isbr=8000000; # input stream bitrate [bps], enter maximum value isbd=$(( $isbr / 8 * 10 )) # input stream buffer for decoding [bytes] for 10 seconds isff=$(( $isbr / 8 / 188 * 10 )) # input stream fifo_size [ 1 = 188 byte packets ] for 10 seconds osbr=1700000; # output stream bit rate [bytes] osfs=25; # output stream FPS osbe=$(( $osbr * 4 / $osfs )); # output stream buffer for encoding [bytes] # ^ this can be 3 or 4 /my_dvb/bin/ffmpeg-298 \ -re -v 40 \ -f mpegts -i "udp://127.0.0.1:3298?buffer_size=$isbd&fifo_size=$isff" \ -pix_fmt yuv420p -vf "yadif=0:-1:0, scale=min(720\,iw):min(480\,ow)" \ -c:v libx264 -preset:v fast -profile:v main -level 3.1 \ -g 12 -bf 2 -flags +cgop -sc_threshold 1000000000 -b_strategy 0 -mpv_flags +strict_gop -threads 4 \ -maxrate $osbr -bufsize $osbe \ -c:a libfdk_aac -ac 2 -b:a 96k \ -y -r $osfs -vsync 1 -async $osfs \ -f rtp_mpegts "rtp://239.191.21.98:3000?ttl=1"


by Federico Allegretti 2017-08-10 16:20 UTC
this page is really a gold mine! thanks for sharing. I'm actually trying to get more TS from more sources (screen cast or live video) to the same mux (every ts on a different port), add description tables (lcn, epg ..) and then mux all togheter to feed and ASI playout card. I'm trying to use oppencaster from avalpa and/or open broadcast encoder, but i have a lot of problem compiling this stuf ... so not to mantion doing some final mux. Any one have an open source mux solution t test out? Cheers


by Federico Allegretti 2017-08-14 11:48 UTC
Hello everybody. I'm trying to add a radio station to our multiplex, but have some problems. We actually use a real cheap 6 channels wellav encoder, that has 6 analog a/v inputs but can accept 2 incoming signals from ASI ports. I got a DVeo ASi i/o card (ebay) and i plan to capture audio from PC integrated sound card -> encode with ffmpeg -> pipe to the ASI card -> mux to the 6 a/v channels of the wellav -> broadcast. Now i got this command line on a simple cheap pc (trashcan of my neighboor :D ) running an headless ubuntu server OS: ffmpeg -threads 0 -f alsa -ac 2 -ar 48000 -i default -c:a mp2 -b:a 224k -ar 48000 -ac 2 -mpegts_flags resend_headers -f mpegts -muxrate 384k -flags cgop -sc_threshold 500 -mpegts_original_network_id 12293 -mpegts_service_id 7 -mpegts_pmt_start_pid 95 -streamid 0:96 -streamid 1:97 -mpegts_service_type 0x02 -metadata service_provider="MEDIANOV" -metadata service_name="Radio Galileo" -metadata service_type=0x02 - | txtest /dev/asitx0 0 105560 0 0 0 0 Multiplexer successfully get the incoming stream, BUT there are some strange things. If i look to an internally encoded a/v stream i got those IDs: A/V6 [pmt:35] = pcr:38 | video:36 | audio:37 but my asi input trasport stream is: ASI1 [pmt:95] = pcr:96 | audio:96 so PCR and audio share the same pid !!!! have to mention tv scan do not detect the transported stream of the radio station ... What i'm missing? Someone has an idea? How can i address the pcr pid?


Write a comment

Name

E-mail (not visible)

Comment


Code from above