This is an IPTV plugin for the Video Disk Recorder (VDR).

Written by:                  Rolf Ahrenberg
                             < R o l f . A h r e n b e r g @ s c i . f i >

                             Antti Seppälä
                             < a . s e p p a l a @ g m a i l . c o m >

Original Project's homepage:  http://www.saunalahti.fi/~rahrenbe/vdr/iptv/
Current Project's homepage:   https://github.com/Zabrimus/vdr-plugin-iptv

Latest version available at: https://github.com/Zabrimus/vdr-plugin-iptv

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
See the file COPYING for more information.

Requirements:

- Libcurl - the multiprotocol file transfer library
  http://curl.haxx.se/libcurl/
- optional: yt-dlp. Used for protocol M3U.
  https://github.com/yt-dlp/yt-dlp
- optional: dash2ts and the Kodi Addon inputstream-adaptive
  https://github.com/jojo61/dash2ts
  https://github.com/xbmc/inputstream.adaptive
- either vlc or ffmpeg or both

Description:

This plugin integrates multicast IPTV transport streams seamlessly into
VDR. You can use any IPTV channel like any other normal DVB channel for
live viewing, recording, etc. The plugin also features full section
filtering capabilities which allow for example EIT information to be
extracted from the incoming stream.

Currently the IPTV plugin has direct support for both multicast UDP/RTP
and unicast HTTP MPEG1/2, H.264 and H.265 transport streams. Also a file
input method is supported, but a file delay must be selected individually
to prevent VDR's transfer buffer over/underflow. Therefore the file input
should be considered as a testing feature only.

IPTV plugin also features a support for external streaming applications.
With proper helper applications and configuration IPTV plugin is able to
display not only MPEG1/2, H.264 and H.265 transport streams but also other
formats like MP3 radio streams, mms video streams and many more.

Installation:

tar -xzf /put/your/path/here/vdr-iptv-X.Y.Z.tgz
make -C iptv-X.Y.Z install

Setup menu:

- Protocol base port = 4321        Defines base port used in CURL/EXT
                                   protocol. Two ports are defined for
                                   each device.
                                   The port range is defined by the number
                                   of IPTV devices times two (max. 32).
                                   Valid range: 0...65503
- Use section filtering = 1        Defines whether section filtering shall
                                   be used.
                                   Valid range: 0...1
- Disable filters = 0              Certain section filters might cause some
                                   unwanted behaviour to VDR such as time
                                   being falsely synchronized etc. This
                                   option allows creation of blacklists of
                                   ill-behaving filters. If this option is
                                   set to a non-zero value, the menu page
                                   will contain that many "Disable filter"
                                   options which allow you to disable the
                                   individual section filters.
                                   Valid range: 0...7
- [Blue:Info]                      Opens IPTV information/statistics menu.

Information menu:

- [Red:General]                    Opens the general information page.
- [Green:Pids]                     Opens the pid statistics page.
- [Yellow:Filters]                 Opens the section filter statistics page.
- [Blue:Bits/bytes]                Toggles between bits and bytes mode.

Plugin parameters:
   -d <num>,  --devices=<number>            number of devices to be created
   -t <mode>, --trace=<mode>               set the tracing mode
   -s <num>,  --thread-queue-size=<number> set the FFmpeg thread-queue-size
   -y <path>, --ytdlp=<path>               set the path to yt-dlp. Default /usr/local/bin/yt-dlp


channels.conf:
The channels.conf configuration is used to define the protocol and the necessary parameters for each different protocol.
The common configuration and described below is
<Name of channel>;IPTV:<Frequence>:S=1|P=0|F=<PROTOCOL>|<Protocol Parameter>|<Stream Parameter>:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>
    - <Name of channel>
      Select a useful name to identify the stream in the channel.conf
    - <Frequency>
      It's recommended to use frequencies in decades (10, 20, 30, 40, ...) for all IPTV channel entries.
      See also the last entry in the channels.conf. You could use the same value as the first frequency to prevent
      that VDR deletes a channel, because of a found duplicate.
    - S=1 or S=0: Section id (Sid/Nid/Tid) scanner ("0" disable, "1" enable)
    - P=0 or P=1: Pid scanner ("0" disable, "1" enable)
    - <VPID>: Video pids. If P=1, then the VPIDs are read from the stream. Select initially e.g. 200
    - <APID>: Audio pids. If P=1, then the APIDs are read from the stream. Select initially e.g. 201
    - <TPID>: Teletext pid or 0 if not available

All protocol parameters are appened using the character '|' as separator. E.g: U=URL|Y=1|H=F

Every <PROTOCOL> has his own configuration parameter <Protocol parameter>.
- Protocol UDP
  The protocol UDP receives a stream via multicast [source@]group address.

  Stream parameter:
  U=<multicast IP address>

  Protocol parameter:
  A=<multicast port>

  Example:
  <Name of channel>;IPTV:Frequence>:S=1|P=0|F=UDP|U=<multicast IP address>|A=<multicast port>:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  Multicast Stream;IPTV:10:S=1|P=0|F=UDP|U=127.0.0.1|A=1234:I:0:200:201:0:0:1:0:0:10

- Protocol CURL
  Receives a stream via cURL (RTMP)

  Stream parameter:
  U=HTTP/HTTPS URL; colons (%3A) and pipes (%7C) shall be URL encoded

  Protocol parameter:
  A=0 (needs to be checked!)

  Example:
  <Name of channel>;IPTV:<Frequence>:S=1|P=0|F=CURL|U=<HTTP/HTTPS address>|A=0:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  Curl Demo;IPTV:20:S=1|P=0|F=CURL|U=http%3A//foo%3Abar@127.0.0.1%3A3000/TS/2|A=0:I:0:200:201:0:0:1:0:0:20

- Protocol FILE
  Reads a file

  Stream parameter:
  U=File name

  Protocol parameter:
  A=0 (needs to be defined)

  Example:
  <Name of channel>;IPTV:<Frequence>:S=1|P=0|F=CURL|U=<file name>|A=0:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  Local File;IPTV:30:S=0|P=1|F=FILE|U=/video/stream.ts|A=5:I:0:200:201:0:0:1:0:0:30

- Protocol EXT
  Calls a script which gets all parameters of the channels.conf. The script itself decides itself what to do and
  sends the TS stream via UDP to the plugin.

  Stream parameter:
  U=Location of the script

  Protocol parameter:
  A=<value> The parameter will be used by the script

  Example:
  <Name of channel>;IPTV:<Frequence>:S=1|P=0|F=EXT|U=<script name>|A=0:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  Script UDP;IPTV:40:S=1|P=0|F=EXT|U=iptvstream.sh|A=0:I:0:200:201:0:0:1:0:0:40

  Check also the script iptvstream.sh in directory iptv. The script uses the Parameter A to select the URL and some
  transcoding parameters. The URL will be transcoded using vlc and the stream will be sent to the plugin via UDP.
  The existing script can be used as a template or a whole new script can be written of course.

- Protocol EXTT
  Very similar to protocol EXT, but the TS stream must be sent via TCP.

  Calls a script which gets all parameters of the channels.conf. The script itself decides itself what to do and
  sends the TS stream via UDP to the plugin.

  Stream parameter:
  U=Location of the script

  Protocol parameter:
  A=<value> The parameter will be used by the script

  Example:
  <Name of channel>;IPTV:<Frequence>:S=1|P=0|F=EXTT|U=<script name>|A=0:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  Script TCP;IPTV:50:S=1|P=0|F=EXTT|U=iptvstreamtcp.sh|A=0:I:0:200:201:0:0:1:0:0:50

  Check also the script iptvstream.sh in directory iptv. The script uses the Parameter A to select the URL and some
  transcoding parameters. The URL will be transcoded using vlc and the stream will be sent to the plugin via UDP.
  The existing script can be used as a template or a whole new script can be written of course.

  YTDLP-1-1;IPTV:140:S=1|P=0|F=EXTT|U=ytdlp-1.sh|A=1|H=V:I:0:256=27:257=@15:0:0:1:0:0:140
  YTDLP-1-2;IPTV:150:S=1|P=0|F=EXTT|U=ytdlp-1.sh|A=2|H=V:I:0:256=27:257=@15:0:0:1:0:0:150

  The script ytdlp-1.sh uses yt-dlp to download the stream and uses either ffmpeg (A=1) or netcat (A=2) to send the stream
  via TCP.

  YTDLP-2-1;IPTV:160:S=1|P=0|F=EXTT|U=ytdlp-2.sh|A=1:I:0:256=27:257=@15:0:0:1:0:0:160
  YTDLP-2-2;IPTV:170:S=1|P=0|F=EXTT|U=ytdlp-2.sh|A=2:I:0:256=27:257=@15:0:0:1:0:0:170
  YTDLP-2-3;IPTV:180:S=1|P=0|F=EXTT|U=ytdlp-2.sh|A=6:I:0:256=27:257=@15:0:0:1:0:0:180

  The script ytdlp-2.sh uses yt-dlp to download the stream and selects the channel in file m3u-list-main.cfg (see also protocol M3U)
  The stream will be downloaded with yt-dlp send uses netcat to send the stream via TCP.

  dash2ts;IPTV:190:S=1|P=0|F=EXTT|U=dash2ts.sh|A=1:I:0:256=27:257=@15:0:0:1:0:0:190

  The script dash2ts uses dash2ts and the Kodi inputstream-adaptive Addon to download and play the video.

- Protocol M3U
  The M3U protocol reads a configurable file (Parameter U=) line by line and uses the value in line (Parameter A=) as m3u URL to stream

  Stream parameter:
  U=<m3u configuration file>
  Y=0 (default)
  Y=1 (uses yt-dlp to determine the video URL, recommended)
  H=F (uses FFmpeg to transcode the stream)
  H=V (uses vlc to transcode the stream)

  Protocol parameter:
  A=<number of the desired entry>

  If you have a file list1.cfg in the plugin configuration directory of VDR with the following lines
  1:https://mcdn.daserste.de/daserste/de/master.m3u8
  2:https://zdf-hls-15.akamaized.net/hls/live/2016498/de/veryhigh/master.m3u8
  3:https://zdf-hls-18.akamaized.net/hls/live/2016501/dach/veryhigh/master.m3u8
  4:https://artesimulcast.akamaized.net/hls/live/2030993/artelive_de/master.m3u8
  5:https://dbjwcot8t7nyd.cloudfront.net/out/v1/9d068a9428444b458324ad77b5a0a4b8/index.m3u8
  6:https://mcdn.br.de/br/fs/ard_alpha/hls/de/master.m3u8
  7:https://mcdn.one.ard.de/ardone/hls/master.m3u8

  then you can add some entries to the channels.conf to stream either the first, second or sixth entry.

  Example:
  <Name of channel>;IPTV:<Frequence>:S=1|P=0|F=M3U|U=<m3u configuration file>|A=<number of the desired entry>:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  M3U List Entry 1 Internal;IPTV:60:S=1|P=0|F=M3U|U=m3u-list-main.cfg|H=F|Y=0|A=1:I:0:200=27:201=@15,202=@15,203=@15:0:0:1:0:0:60
  M3U List Entry 2 Internal;IPTV:70:S=1|P=0|F=M3U|U=m3u-list-main.cfg|A=2:I:0:200=27:201=@15,202=@15,203=@15:0:0:1:0:0:70
  M3U List Entry 6 Internal;IPTV:80:S=1|P=0|F=M3U|U=m3u-list-main.cfg|A=6:I:0:200=27:201=@15,202=@15:0:0:1:0:0:80
  M3U List Entry 1 yt_dlp;IPTV:90:S=1|P=0|F=M3U|U=m3u-list-main.cfg|H=F|Y=1|A=1:I:0:200=27:201=@15,202=@15,203=@15:0:0:1:0:0:90
  M3U List Entry 2 yt_dlp;IPTV:100:S=1|P=0|F=M3U|U=m3u-list-main.cfg|H=F|Y=1|A=2:I:0:200=27:201=@15,202=@15,203=@15:0:0:1:0:0:100
  M3U List Entry 6 yt_dlp;IPTV:110:S=1|P=0|F=M3U|U=m3u-list-main.cfg|H=F|Y=1|A=6:I:0:200=27:201=@15,202=@15:0:0:1:0:0:110

- Protocol M3US
  It's a simpler version of M3U. Instead of a configuration file, the URL (colons (%3A) and pipes (%7C) shall be URL encoded)
  will be configured directly.

  Stream parameter:
  U=<m3u URL> (colons (%3A) and pipes (%7C) shall be URL encoded)
  Y=0 (default)
  Y=1 (uses yt-dlp to determine the video URL, recommended)
  H=F (uses FFmpeg to transcode the stream)
  H=V (uses vlc to transcode the stream)

  Protocol parameter:
  A=0 (needs to be defined)

  Example:
  <Name of channel>;IPTV:<Frequence>:S=1|P=0|F=M3US|U=<m3u URL>|A=0:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  M3U URL;IPTV:120:S=1|P=0|F=M3US|U=https%3A//mcdn.daserste.de/daserste/de/masters.m3u8|A=0:I:0:200:201:0:0:1:0:0:120
  M3U URL yt-dlpL;IPTV:130:S=1|P=0|F=M3US|U=https%3A//daserste-live.ard-mcdn.de/daserste/live/hls/de/master.m3u8|A=0|H=F|Y=1:I:0:200=2:201=@4:0:0:1:0:0:130

- Protocol STREAM
  Streams a TS stream provided e.g. by a local FFmpeg server.

  Stream parameter:
  U=<URL> (colons (%3A) and pipes (%7C) shall be URL encoded)
  H=F (uses FFmpeg to transcode the stream)
  H=V (uses vlc to transcode the stream)
  H=E (calls the script iptv-cmdline-expert.py to get the commandline)

  Protocol parameter:
  A=0 (needs to be defined)

  Start e.g. an ffmpeg server with 'ffmpeg -i 00001.ts -f mpegts tcp://127.0.0.1:6666?listen' and use the url in
  the channel.conf configuration.

  Example:
  <Name of channel>;IPTV:<Frequence>:S=1|P=0|F=STREAM|U=<URL>|A=0:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  Stream name:IPTV:140:S=1|P=0|F=STREAM|U=http%3A//127.0.0.1%3A6666|A=0|H=V:I:0:200:201:0:0:1:0:0:140

- Protocol RADIO
  This protocol is useful for audio only streams. It is recommended to use vlc as transcoder (see below)

  Stream parameter:
  U=<URL> (colons (%3A) and pipes (%7C) shall be URL encoded)
  H=F (uses FFmpeg to transcode the stream)
  H=V (uses vlc to transcode the stream)
  H=E (calls the script iptv-cmdline-expert.py to get the commandline)

  Protocol parameter
  A=0 (needs to be defined)

  Example:
  <Name of channel>:IPTV:<Frequence>:S=1|P=0|F=RADIO|U=<URL>>|A=0:I:0:<VPID>:0:<TPID>:0:1:0:0:<Frequence>

  Radio;IPTV:150:S=1|P=0|F=RADIO|U=http%3A//wdr-1live-live.icecast.wdr.de/wdr/1live/live/mp3/128/stream.mp3|A=0|H=V:I:0:0:201:0:0:1:0:0:150

- Protocol YT
  Streams a youtube or an other supported video. Please check the tool yt-dlp (get the least recent version to prevent problems)
  to get supported sites. The final URL of the stream will be determined using the tool yt-dlp.

  Stream parameter:
  U=<URL> (colons (%3A) and pipes (%7C) shall be URL encoded)

  Protocol parameter:
  A=0 (needs to be defined)

  Example:
  <Name of channel>;IPTV:<Frequence>:S=1|P=0|F=YT|U=<URL>|A=0:I:0:<VPID>:<APID>:<TPID>:0:1:0:0:<Frequence>

  YT URL;IPTV:160:S=1|P=0|F=YT|U=https%3A//www.youtube.com/watch?v=Li3Dvqlo5uE|A=0:I:0:200=2:201=@4:0:0:1:0:0:160

- All samples in one channels.conf:
    Multicast Stream;IPTV:10:S=1|P=0|F=UDP|U=127.0.0.1|A=1234:I:0:200:201:0:0:1:0:0:10
    Curl Demo;IPTV:20:S=1|P=0|F=CURL|U=http%3A//foo%3Abar@127.0.0.1%3A3000/TS/2|A=0:I:0:200:201:0:0:1:0:0:20
    Local File;IPTV:30:S=0|P=1|F=FILE|U=/video/stream.ts|A=5:I:0:200:201:0:0:1:0:0:30
    Script UDP;IPTV:40:S=1|P=0|F=EXT|U=iptvstream.sh|A=0:I:0:200:201:0:0:1:0:0:40
    Script TCP;IPTV:50:S=1|P=0|F=EXTT|U=iptvstreamtcp.sh|A=0:I:0:200:201:0:0:1:0:0:50
    YTDLP-1-1;IPTV:140:S=1|P=0|F=EXTT|U=ytdlp-1.sh|A=1|H=V:I:0:256=27:257=@15:0:0:1:0:0:140
    YTDLP-1-2;IPTV:150:S=1|P=0|F=EXTT|U=ytdlp-1.sh|A=2|H=V:I:0:256=27:257=@15:0:0:1:0:0:150
    YTDLP-2-1;IPTV:160:S=1|P=0|F=EXTT|U=ytdlp-2.sh|A=1:I:0:256=27:257=@15:0:0:1:0:0:160
    YTDLP-2-2;IPTV:170:S=1|P=0|F=EXTT|U=ytdlp-2.sh|A=2:I:0:256=27:257=@15:0:0:1:0:0:170
    YTDLP-2-3;IPTV:180:S=1|P=0|F=EXTT|U=ytdlp-2.sh|A=6:I:0:256=27:257=@15:0:0:1:0:0:180
    dash2ts;IPTV:190:S=1|P=0|F=EXTT|U=dash2ts.sh|A=1:I:0:256=27:257=@15:0:0:1:0:0:190
    M3U List Entry 1 Internal;IPTV:60:S=1|P=0|F=M3U|U=m3u-list-main.cfg|H=F|Y=0|A=1:I:0:200=27:201=@15,202=@15,203=@15:0:0:1:0:0:60
    M3U List Entry 2 Internal;IPTV:70:S=1|P=0|F=M3U|U=m3u-list-main.cfg|A=2:I:0:200=27:201=@15,202=@15,203=@15:0:0:1:0:0:70
    M3U List Entry 6 Internal;IPTV:80:S=1|P=0|F=M3U|U=m3u-list-main.cfg|A=6:I:0:200=27:201=@15,202=@15:0:0:1:0:0:80
    M3U List Entry 1 yt_dlp;IPTV:90:S=1|P=0|F=M3U|U=m3u-list-main.cfg|H=F|Y=1|A=1:I:0:200=27:201=@15,202=@15,203=@15:0:0:1:0:0:90
    M3U List Entry 2 yt_dlp;IPTV:100:S=1|P=0|F=M3U|U=m3u-list-main.cfg|H=F|Y=1|A=2:I:0:200=27:201=@15,202=@15,203=@15:0:0:1:0:0:100
    M3U List Entry 6 yt_dlp;IPTV:110:S=1|P=0|F=M3U|U=m3u-list-main.cfg|H=F|Y=1|A=6:I:0:200=27:201=@15,202=@15:0:0:1:0:0:110
    M3U URL;IPTV:120:S=1|P=0|F=M3US|U=https%3A//mcdn.daserste.de/daserste/de/masters.m3u8|A=0:I:0:200:201:0:0:1:0:0:120
    M3U URL yt-dlpL;IPTV:130:S=1|P=0|F=M3US|U=https%3A//daserste-live.ard-mcdn.de/daserste/live/hls/de/master.m3u8|A=0|H=F|Y=1:I:0:200=2:201=@4:0:0:1:0:0:130
    Stream name:IPTV:140:S=1|P=0|F=STREAM|U=http%3A//127.0.0.1%3A6666|A=0|H=V:I:0:200:201:0:0:1:0:0:140
    Radio;IPTV:150:S=1|P=0|F=RADIO|U=http%3A//wdr-1live-live.icecast.wdr.de/wdr/1live/live/mp3/128/stream.mp3|A=0|H=V:I:0:0:201:0:0:1:0:0:150
    YT URL;IPTV:160:S=1|P=0|F=YT|U=https%3A//www.youtube.com/watch?v=Li3Dvqlo5uE|A=0:I:0:200=2:201=@4:0:0:1:0:0:160

- UDP multicast rules for iptables firewall

  # Multicast UDP packets
  iptables -A INPUT -i eth0 -p udp -d 224.0.0.0/4 --dport 1234 -j ACCEPT

  # IGMP required by multicasts
  iptables -A INPUT -i eth0 -p igmp -d 224.0.0.0/4 -j ACCEPT

  # Default routing for multicast
  route add -net 224.0.0.0 netmask 224.0.0.0 eth0

External streaming:

- To watch an externally received channel add an EXT entry to channels.conf
  and specify a script name and parameter. The specified script is executed
  from plugin resource directory when VDR tunes to the channel. The specified
  script parameter is passed to the script and it can be used to select for
  example between different URLs.

- When an EXT or CURL/RTSP channel is opened the IPTV plugin opens an UDP
  listening port on the localhost. The external script is responsible for
  supplying IPTV plugin with MPEG2 TS data in UDP/RTP format to the listening
  port. The data will be processed in VDR like a normal DVB broadcast. The
  listening base port can be specified in the plugin configuration menu.

- When an EXTT channel is opened the IPTV plugin opens an TCP
  listening port on the localhost. The external script is responsible for
  supplying IPTV plugin with MPEG2 TS data in TCP format to the listening
  port. The data will be processed in VDR like a normal DVB broadcast. The
  listening base port can be specified in the plugin configuration menu.

- Each IPTV device has different listen port. The port number is specified
  as a base port number plus IPTV device index minus one. Maximum of 8 IPTV
  devices can be used simultaneously.

- IPTV plugin includes an example script which uses VLC media player for
  receiving streams, transcoding and handing the result to IPTV plugin.

- M3U needs additional configuration
  Sample from above:
  U=list1.cfg The configuration file (located in plugin directory) contains
              a list of URL in the format "5:https://URL". Where 5 is the
              programm number within the file (must be unique) and the URL points
              to an m3u8 URL.
  A=5         Plays the channel with ID 5 (see above)
  VPID = 200  (select a unique one for a transponder TID)
  APID = 201,202,203,204,205 (select unique ones for a transponder TID)
  TPID = 0    (currently not supported, need to find a live stream with Teletext)
  CAID = 0    (0 is a good value)
  SID  = 11   (select a unique one for a transponder TID)
  NID  = 1    (doesn't matter, but must be set)
  TID  = 100  Select a transponder.
  RID  = 0    (Radio only 1)

  It is possible to use parameter Y=1 to use yt-dlp to determine the m3u8 URL.
  Useful e.g. for youtube videos. Needs yt-dlp.

Notes:

- Working EIT requires correct Nid/Tid/Sid values as the NIT filter cannot
  determine the type (satellite/cable/terrestrial) of the IPTV transport
  stream.

- The following section filters are recommended to be disabled:
  "NIT (0x40)", "SDT (0x42)", "TDT (0x70)"

- The IPTV devices look for a "/tmp/vdr-iptv<devicenumber>.dvr" fifo at
  startup. If the fifo is found and succesfully opened, the device writes
  the current data stream into it. This can be used for debugging purposes.

- Multiple channels with identical service id should have frequency
  difference of 4 or greater. It's recommended to use frequencies in decades
  (10, 20, 30, 40, ...) for all IPTV channel entries.

- VLC processes won't get killed on some setups with the provided iptvstream.sh
  script and the iptvstream-notrap.sh script should be used instead in these
  cases.

- If received MPEG-2 TS streams carry CA descriptors, you'll have to apply
  "disable_ca_updates" patch to the VDR in order to get rid of "Channel not
  available" messages.

- EIT scanning functionality is disabled by default.

- Section id and pid scanners should be disabled after the correct data is
  found. This can be made via VDR's channel editor.

- Source-specific multicast (SSM) can be enabled by defining both the source
  address and the group address separated by a '@' character. This will use
  IGMP v3 protocol:
  "U=<source address>@<group address>"

- The CURL implementation supports only RTSP/HTTP/HTTPS protocols and an
  optional netrc configuration file for authentication:
  $(CONFDIR)/iptv/netrc

- You can quite easily figure out correct DVB triplet values by using the
  multicat and dvbsnoop tools:
  $ multicat -u -d 1620000000 @127.0.0.1:1234 /tmp/video.ts
  $ dvbsnoop -s ts -if /tmp/video.ts -tssubdecode -hexdumpbuffer 0x12 | \
    grep -m1 -A8 Service_ID | grep _ID

Acknowledgements:

- The IPTV section filtering code is derived from Linux kernel.

- The pid scanning code is derived from Udo Richter's streamplayer plugin.
