1
0
mirror of https://github.com/rofafor/vdr-plugin-iptv.git synced 2023-10-10 11:37:03 +00:00

Compare commits

..

21 Commits

Author SHA1 Message Date
Rolf Ahrenberg
aa1bfab60d Updated HISTORY. 2009-06-01 11:17:18 +03:00
Rolf Ahrenberg
3ffba13a6c Updated patches for vdr-1.7.7. 2009-05-22 11:00:54 +03:00
Rolf Ahrenberg
57d63db034 Fixed setting parameters when protocol changes (Thanks to Peter Holik for reporting this one).
Updated example scripts to use ffmpeg's direct UDP output and added a new "image.sh" script (Thanks to Peter Holik).
2009-05-22 10:50:20 +03:00
Rolf Ahrenberg
2484c3bdd6 Updated patches for vdr-1.7.5. 2009-04-14 12:58:09 +03:00
Rolf Ahrenberg
912bf068ac Added iptvstream-notrap.sh script. 2009-03-31 08:17:24 +03:00
Rolf Ahrenberg
a8d01e32a1 Modified default compilation options. 2009-03-23 21:07:50 +02:00
Rolf Ahrenberg
d1c2d48a6b Fixed remaining lint warnings. 2009-03-21 00:56:37 +02:00
Rolf Ahrenberg
e74d4f88f4 Fixed again lint warnings. 2009-03-20 23:38:26 +02:00
Rolf Ahrenberg
55bf971e3e Fixed more lint warnings. 2009-03-20 18:00:17 +02:00
Rolf Ahrenberg
30abbc3e80 Fixed some lint warnings. 2009-03-20 17:43:31 +02:00
Rolf Ahrenberg
74761da04a Fixed a locking bug with section filters. 2009-03-17 17:37:05 +02:00
Rolf Ahrenberg
b221a9a406 Added a note about recommended frequencies into README. 2009-03-17 08:30:57 +02:00
Rolf Ahrenberg
fd7a43d733 Added optional patches to disable CA updates. 2009-03-07 15:27:04 +02:00
Rolf Ahrenberg
d546cac834 Fixed pid scanner to set the existing video stream type. 2009-03-06 22:20:34 +02:00
Rolf Ahrenberg
94225ac6a4 Fixed pid scanner to default MPEG2 video stream type. 2009-03-06 19:30:56 +02:00
Rolf Ahrenberg
25ec9df0cc Whitespace cleanup. 2009-03-06 19:06:47 +02:00
Rolf Ahrenberg
abf0a5ece4 Refactored section filter class. 2009-02-27 16:05:19 +02:00
Rolf Ahrenberg
024ee7ba89 Optimized TS packet data flow. 2009-02-26 16:04:12 +02:00
Rolf Ahrenberg
73906ab698 Fixed a possible crash in pid scanner. 2009-02-25 22:52:25 +02:00
Rolf Ahrenberg
ec2ec19f68 Fixed a possible crash in sid scanner. 2009-02-25 14:34:19 +02:00
Rolf Ahrenberg
1e8f117988 Updated for vdr-1.7.4.
Fixed blacklisting of PAT section filter.
Set max IPTV device count to VDR's max devices.
2009-02-24 13:40:16 +02:00
44 changed files with 612 additions and 523 deletions

33
HISTORY
View File

@@ -70,10 +70,41 @@ VDR Plugin 'iptv' Revision History
- Updated Italian translation (Thanks to Diego Pierotto).
- Tweaked pid scanner parameters for HD broadcasts.
- Fixed opening of fifo tap.
- Updated iptvstream.sh script to support optional video resolution settings.
- Updated iptvstream.sh script to support optional video resolution
settings.
- Optimized streamer thread termination.
2008-12-16: Version 0.2.3
- Updated for vdr-1.7.2.
- Silenced a compilation warning.
2009-02-25: Version 0.2.4
- Updated for vdr-1.7.4.
- Fixed blacklisting of PAT section filter.
- Set max IPTV device count to VDR's max devices.
- Fixed a possible crash in sid and pid scanners.
2009-03-08: Version 0.2.5
- Optimized TS packet data flow.
- Refactored section filter class.
- Cleaned up example scripts.
- Fixed pid scanner to set the existing video stream type
(Thanks to ua0lnj for reporting this one).
- Added optional patches to disable CA updates.
2009-03-22: Version 0.2.6
- Added a note about recommended frequencies into README.
- Fixed a locking bug with section filters.
- Fixed some lint warnings.
2009-06-01: Version 0.3.0
- Added iptvstream-notrap.sh script.
- Fixed setting parameters when protocol changes
(Thanks to Peter Holik for reporting this one).
- Updated example scripts to use ffmpeg's direct UDP output
and added a new "image.sh" script (Thanks to Peter Holik).

View File

@@ -23,7 +23,7 @@ VERSION = $(shell grep 'static const char VERSION\[\] *=' $(PLUGIN).c | awk '{ p
### The C++ compiler and options:
CXX ?= g++
CXXFLAGS ?= -fPIC -g -O2 -Wall -Woverloaded-virtual -Wno-parentheses
CXXFLAGS ?= -fPIC -g -O2 -Wall -Wextra -Wswitch-default -Wfloat-equal -Wundef -Wpointer-arith -Wconversion -Wcast-align -Wredundant-decls -Wno-unused-parameter -Woverloaded-virtual -Wno-parentheses
### The directory environment:

30
README
View File

@@ -111,17 +111,17 @@ Configuration:
- channels.conf
TV4;IPTV:4:IPTV|S1P0|EXT|iptvstream.sh|0:P:0:0:680:0:0:4:0:0:0
TV3;IPTV:3:IPTV|S0P1|FILE|/video/stream.ts|5:P:0:514:670:2321:0:3:0:0:0
TV2;IPTV:2:IPTV|S0P1|HTTP|127.0.0.1/TS/2|3000:P:0:513:660:2321:0:2:0:0:0
TV1;IPTV:1:IPTV|S1P0|UDP|127.0.0.1|1234:P:0:512:650:2321:0:1:0:0:0
^ ^ ^ ^ ^ ^ ^
| | | | | | Source type ("P")
| | | | | IP Port Number, File delay (ms), Script parameter
| | | | IP Address, File location, Script location
| | | Protocol ("UDP", "HTTP", "FILE", "EXT")
| | Parameters ("S" Sid scan, "P" Pid scan, "0" disable, "1" enable)
| Plugin ID ("IPTV")
TV4;IPTV:40:IPTV|S1P0|EXT|iptvstream.sh|0:P:0:0:680:0:0:4:0:0:0
TV3;IPTV:30:IPTV|S0P1|FILE|/video/stream.ts|5:P:0:514:670:2321:0:3:0:0:0
TV2;IPTV:20:IPTV|S0P1|HTTP|127.0.0.1/TS/2|3000:P:0:513:660:2321:0:2:0:0:0
TV1;IPTV:10:IPTV|S1P0|UDP|127.0.0.1|1234:P:0:512:650:2321:0:1:0:0:0
^ ^ ^ ^ ^ ^ ^
| | | | | | Source type ("P")
| | | | | IP Port Number, File delay (ms), Script parameter
| | | | IP Address, File location, Script location
| | | Protocol ("UDP", "HTTP", "FILE", "EXT")
| | Parameters ("S" Sid scan, "P" Pid scan, "0" disable, "1" enable)
| Plugin ID ("IPTV")
Unique enumeration
- UDP multicast rules for iptables firewall
@@ -167,6 +167,14 @@ Notes:
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.
Acknowledgements:
- The IPTV section filtering code is derived from Linux kernel.

View File

@@ -10,14 +10,13 @@
cIptvConfig IptvConfig;
cIptvConfig::cIptvConfig(void)
: readBufferTsCount(48),
tsBufferSize(2),
: tsBufferSize(2),
tsBufferPrefillRatio(0),
extProtocolBasePort(4321),
useBytes(1),
sectionFiltering(1)
{
for (unsigned int i = 0; i < ARRAY_SIZE(disabledFilters) - 1; ++i)
for (unsigned int i = 0; i < ARRAY_SIZE(disabledFilters); ++i)
disabledFilters[i] = -1;
memset(configDirectory, '\0', sizeof(configDirectory));
}
@@ -25,7 +24,7 @@ cIptvConfig::cIptvConfig(void)
unsigned int cIptvConfig::GetDisabledFiltersCount(void) const
{
unsigned int n = 0;
while ((disabledFilters[n] != -1) && (n < ARRAY_SIZE(disabledFilters) - 1))
while ((n < ARRAY_SIZE(disabledFilters) && (disabledFilters[n] != -1)))
n++;
return n;
}

View File

@@ -14,7 +14,6 @@
class cIptvConfig
{
private:
unsigned int readBufferTsCount;
unsigned int tsBufferSize;
unsigned int tsBufferPrefillRatio;
unsigned int extProtocolBasePort;
@@ -25,7 +24,6 @@ private:
public:
cIptvConfig();
unsigned int GetReadBufferTsCount(void) const { return readBufferTsCount; }
unsigned int GetTsBufferSize(void) const { return tsBufferSize; }
unsigned int GetTsBufferPrefillRatio(void) const { return tsBufferPrefillRatio; }
unsigned int GetExtProtocolBasePort(void) const { return extProtocolBasePort; }

View File

@@ -8,9 +8,9 @@
#include "config.h"
#include "device.h"
#define IPTV_MAX_DEVICES 8
#define IPTV_MAX_DEVICES MAXDEVICES
cIptvDevice * IptvDevices[IPTV_MAX_DEVICES] = { NULL };
static cIptvDevice * IptvDevices[IPTV_MAX_DEVICES] = { NULL };
unsigned int cIptvDevice::deviceCount = 0;
@@ -20,21 +20,20 @@ cIptvDevice::cIptvDevice(unsigned int Index)
isPacketDelivered(false),
isOpenDvr(false),
sidScanEnabled(false),
pidScanEnabled(false),
mutex()
pidScanEnabled(false)
{
//debug("cIptvDevice::cIptvDevice(%d)\n", deviceIndex);
unsigned int bufsize = MEGABYTE(IptvConfig.GetTsBufferSize());
bufsize -= (bufsize % TS_SIZE);
isyslog("creating IPTV device %d (CardIndex=%d)", deviceIndex, CardIndex());
tsBuffer = new cRingBufferLinear(MEGABYTE(IptvConfig.GetTsBufferSize()),
(TS_SIZE * IptvConfig.GetReadBufferTsCount()),
false, "IPTV");
tsBuffer->SetTimeouts(100, 100);
tsBuffer = new cRingBufferLinear(bufsize + 1, TS_SIZE, false,
*cString::sprintf("IPTV %d", deviceIndex));
tsBuffer->SetTimeouts(10, 10);
ResetBuffering();
pUdpProtocol = new cIptvProtocolUdp();
pHttpProtocol = new cIptvProtocolHttp();
pFileProtocol = new cIptvProtocolFile();
pExtProtocol = new cIptvProtocolExt();
pIptvStreamer = new cIptvStreamer(tsBuffer, &mutex);
pIptvStreamer = new cIptvStreamer(tsBuffer, (100 * TS_SIZE));
pPidScanner = new cPidScanner;
// Initialize filter pointers
memset(secfilters, '\0', sizeof(secfilters));
@@ -305,7 +304,7 @@ bool cIptvDevice::DeleteFilter(unsigned int Index)
return false;
}
bool cIptvDevice::IsBlackListed(u_short Pid, u_char Tid, u_char Mask)
bool cIptvDevice::IsBlackListed(u_short Pid, u_char Tid, u_char Mask) const
{
//debug("cIptvDevice::IsBlackListed(%d) Pid=%d Tid=%02X Mask=%02X\n", deviceIndex, Pid, Tid, Mask);
// loop through section filter table
@@ -330,11 +329,13 @@ int cIptvDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
// Blacklist check, refuse certain filters
if (IsBlackListed(Pid, Tid, Mask))
return -1;
// Lock
cMutexLock MutexLock(&mutex);
// Search the next free filter slot
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
if (!secfilters[i]) {
//debug("cIptvDevice::OpenFilter(%d): Pid=%d Tid=%02X Mask=%02X Index=%d\n", deviceIndex, Pid, Tid, Mask, i);
secfilters[i] = new cIptvSectionFilter(i, deviceIndex, Pid, Tid, Mask);
secfilters[i] = new cIptvSectionFilter(deviceIndex, i, Pid, Tid, Mask);
return secfilters[i]->GetReadDesc();
}
}
@@ -344,6 +345,9 @@ int cIptvDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
void cIptvDevice::CloseFilter(int Handle)
{
// Lock
cMutexLock MutexLock(&mutex);
// Search the filter for deletion
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
if (secfilters[i] && (Handle == secfilters[i]->GetReadDesc())) {
//debug("cIptvDevice::CloseFilter(%d): %d\n", deviceIndex, Handle);
@@ -356,14 +360,13 @@ void cIptvDevice::CloseFilter(int Handle)
bool cIptvDevice::OpenDvr(void)
{
debug("cIptvDevice::OpenDvr(%d)\n", deviceIndex);
mutex.Lock();
isPacketDelivered = false;
tsBuffer->Clear();
mutex.Unlock();
ResetBuffering();
pIptvStreamer->Open();
if (pIptvStreamer)
pIptvStreamer->Open();
if (sidScanEnabled && pSidScanner && IptvConfig.GetSectionFiltering())
pSidScanner->SetStatus(true);
pSidScanner->Open();
isOpenDvr = true;
return true;
}
@@ -372,7 +375,7 @@ void cIptvDevice::CloseDvr(void)
{
debug("cIptvDevice::CloseDvr(%d)\n", deviceIndex);
if (sidScanEnabled && pSidScanner && IptvConfig.GetSectionFiltering())
pSidScanner->SetStatus(false);
pSidScanner->Close();
if (pIptvStreamer)
pIptvStreamer->Close();
isOpenDvr = false;
@@ -407,7 +410,7 @@ bool cIptvDevice::GetTSPacket(uchar *&Data)
{
int Count = 0;
//debug("cIptvDevice::GetTSPacket(%d)\n", deviceIndex);
if (!IsBuffering()) {
if (tsBuffer && !IsBuffering()) {
if (isPacketDelivered) {
tsBuffer->Del(TS_SIZE);
isPacketDelivered = false;
@@ -429,24 +432,26 @@ bool cIptvDevice::GetTSPacket(uchar *&Data)
}
isPacketDelivered = true;
Data = p;
// Update pid statistics
// Update pid statistics
AddPidStatistic(ts_pid(p), payload(p));
// Send data also to dvr fifo
if ((dvrFd >= 0) && (write(dvrFd, p, TS_SIZE) != TS_SIZE))
error("ERROR: write failed to FIFO\n");
if (dvrFd >= 0)
Count = write(dvrFd, p, TS_SIZE);
// Analyze incomplete streams with built-in pid analyzer
if (pidScanEnabled && pPidScanner)
pPidScanner->Process(p);
// Lock
cMutexLock MutexLock(&mutex);
// Run the data through all filters
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
if (secfilters[i])
secfilters[i]->ProcessData(p);
secfilters[i]->Process(p);
}
return true;
}
}
// Reduce cpu load by preventing busylooping
cCondWait::SleepMs(100);
cCondWait::SleepMs(10);
Data = NULL;
return true;
}

View File

@@ -74,7 +74,7 @@ private:
void ResetBuffering(void);
bool IsBuffering(void);
bool DeleteFilter(unsigned int Index);
bool IsBlackListed(u_short Pid, u_char Tid, u_char Mask);
bool IsBlackListed(u_short Pid, u_char Tid, u_char Mask) const;
// for channel selection
public:

4
iptv.c
View File

@@ -20,7 +20,7 @@
#error "VDR-1.6.0 API version or greater is required!"
#endif
static const char VERSION[] = "0.2.3";
static const char VERSION[] = "0.3.0";
static const char DESCRIPTION[] = trNOOP("Experience the IPTV");
class cPluginIptv : public cPlugin {
@@ -78,7 +78,7 @@ bool cPluginIptv::ProcessArgs(int argc, char *argv[])
// Implement command line argument processing here if applicable.
static const struct option long_options[] = {
{ "devices", required_argument, NULL, 'd' },
{ NULL }
{ NULL, 0, NULL, 0 }
};
int c;

84
iptv/image.sh Executable file
View File

@@ -0,0 +1,84 @@
#!/bin/sh
set -e
# image.sh is used by the VDR iptv plugin to transcode images from
# a web server to provide a video stream.
#
# The script originates from Peter Holik
#
# Example channels.conf entries:
# Energy;IPTV:50:IPTV|S0P0|EXT|png.sh|1:P:0:256:257:0:0:3:0:0:0
# Temperature;IPTV:60:IPTV|S0P0|EXT|png.sh|2:P:0:256:257:0:0:3:0:0:0
# Temperature Week;IPTV:70:IPTV|S0P0|EXT|png.sh|3:P:0:256:257:0:0:3:0:0:0
# Server Temperature;IPTV:80:IPTV|S0P0|EXT|png.sh|4:P:0:256:257:0:0:3:0:0:0
# Server Temperature Week;IPTV:90:IPTV|S0P0|EXT|png.sh|5:P:0:256:257:0:0:3:0:0:0
# Traffic;IPTV:100:IPTV|S0P0|EXT|png.sh|6:P:0:256:257:0:0:3:0:0:0
#
# webcam.sh is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This package is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this package; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
if [ $# -ne 2 ]; then
logger "$0: error: Invalid parameter count '$#' $*"
exit 1
fi
# Channels.conf parameter
case ${1} in
1)
URL="http://proxy/cgi-bin/bin/graph.cgi?hostname=proxy;plugin=energy;type=electricity"
;;
2)
URL="http://proxy/cgi-bin/bin/graph.cgi?hostname=proxy;plugin=temp;type=temperature;type_instance=Outdoor"
;;
3)
URL="http://proxy/cgi-bin/bin/graph.cgi?hostname=proxy;plugin=temp;type=temperature;type_instance=Outdoor;begin=-604800"
;;
4)
URL="http://proxy/cgi-bin/bin/graph.cgi?hostname=proxy;plugin=temp;type=temperature;type_instance=Server"
;;
5)
URL="http://proxy/cgi-bin/bin/graph.cgi?hostname=proxy;plugin=temp;type=temperature;type_instance=Server;begin=-604800"
;;
6)
URL="http://proxy/cgi-bin/bin/graph.cgi?hostname=proxy;plugin=interface;type=if_octets;type_instance=ppp0"
;;
*)
URL="" # Default URL - TODO get dummy picture
;;
esac
# Iptv plugin listens this port
PORT=${2}
# Stream temporary files
IMAGE=/tmp/image.png
LOG=/dev/null
{
# Using wget because ffmpeg cannot handle http/1.1 "Transfer-Encoding: chunked"
wget -q -O "${IMAGE}" "${URL}"
# Build stream from audiodump with cycle image as video
# PID 0x100/256 = Video 0x101/257 = Audio
exec ffmpeg -v 10 \
-analyzeduration 0 \
-loop_input \
-i "${IMAGE}" \
-f mpegts -r 25 -vcodec mpeg2video -b 4000k -s 664x540 -padleft 20 -padright 20 -padtop 16 -padbottom 20 \
-an \
"udp://127.0.0.1:${PORT}?pkt_size=16356"
} > ${LOG} 2>&1

View File

@@ -27,7 +27,7 @@
if [ $# -ne 2 ]; then
logger "$0: error: Invalid parameter count '$#' $*"
exit 1;
exit 1
fi
# Channels.conf parameter
@@ -49,8 +49,8 @@ rm -f "${FIFO}"
mkfifo "${FIFO}"
mplayer -dumpstream "${URL}" \
-quiet -nolirc -noautosub -noconsolecontrols -novideo -nojoystick \
-dumpfile "$FIFO" &
-quiet -nolirc -noautosub -noconsolecontrols -novideo -nojoystick \
-dumpfile "$FIFO" &
# Time to connect and fill pipe
sleep 3
@@ -58,10 +58,10 @@ sleep 3
# Build audio only stream
# PID 0x100/256 = Audio
ffmpeg -v -1 \
-i "${FIFO}" \
-title "${TITLE}" \
-f mpegts -acodec mp2 -ac 2 -ab 96k -ar 48000 \
- | nc -u 127.0.0.1 ${PORT}
-i "${FIFO}" \
-title "${TITLE}" \
-f mpegts -acodec mp2 -ac 2 -ab 96k -ar 48000 \
"udp://127.0.0.1:${PORT}?pkt_size=16356"
rm -f "${FIFO}"
} > ${LOG} 2>&1

76
iptv/iptvstream-notrap.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/sh
#
# iptvstream.sh can be used by the VDR iptv plugin to transcode external
# sources
#
# (C) 2007 Rolf Ahrenberg, Antti Seppälä
#
# iptvstream.sh is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This package is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this package; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA.
if [ $# -ne 2 ]; then
logger "$0: error: Invalid parameter count '$#' $*"
exit 1
fi
# Channels.conf parameter
PARAMETER=${1}
# Iptv plugin listens this port
PORT=${2}
# Default settings for stream transcoding
VCODEC=mp2v
VBITRATE=2400
ACODEC=mpga
ABITRATE=320
# There is a way to specify multiple URLs in the same script. The selection is
# then controlled by the extra parameter passed by IPTV plugin to the script
case ${PARAMETER} in
1)
URL=""
WIDTH=720
HEIGHT=576
;;
2)
URL=""
;;
3)
URL=""
;;
*)
URL="" # Default URL
;;
esac
if [ -z "${URL}" ]; then
logger "$0: error: URL not defined!"
exit 1
fi
# Create transcoding options
TRANSCODE_OPTS="vcodec=${VCODEC},acodec=${ACODEC},vb=${VBITRATE},ab=${ABITRATE}"
if [ -n "${WIDTH}" -a -n "${HEIGHT}" ] ; then
TRANSCODE_OPTS="${TRANSCODE_OPTS},width=${WIDTH},height=${HEIGHT}"
fi
# Create unique pids for the stream
let VPID=${PARAMETER}+1
let APID=${PARAMETER}+2
let SPID=${PARAMETER}+3
# Execute VLC
exec vlc "${URL}" --sout "#transcode{${TRANSCODE_OPTS}}:standard{access=udp,mux=ts{pid-video=${VPID},pid-audio=${APID},pid-spu=${SPID}},dst=127.0.0.1:${PORT}}" --intf dummy

View File

@@ -22,7 +22,7 @@
if [ $# -ne 2 ]; then
logger "$0: error: Invalid parameter count '$#' $*"
exit 1;
exit 1
fi
# Channels.conf parameter
@@ -41,24 +41,24 @@ ABITRATE=320
# then controlled by the extra parameter passed by IPTV plugin to the script
case ${PARAMETER} in
1)
URL=""
WIDTH=720
HEIGHT=576
;;
URL=""
WIDTH=720
HEIGHT=576
;;
2)
URL=""
;;
URL=""
;;
3)
URL=""
;;
URL=""
;;
*)
URL="" # Default URL
;;
URL="" # Default URL
;;
esac
if [ -z "${URL}" ]; then
logger "$0: error: URL not defined!"
exit 1;
exit 1
fi
# Create transcoding options

View File

@@ -27,7 +27,7 @@
if [ $# -ne 2 ]; then
logger "$0: error: Invalid parameter count '$#' $*"
exit 1;
exit 1
fi
# Channels.conf parameter
@@ -46,9 +46,9 @@ LOG=/dev/null
# PID 0x100/256 = Audio
arecord -q -D hw:0,0 -f dat | \
ffmpeg -v -1 \
-f wav \
-i - \
-title "${TITLE}" \
-f mpegts -acodec mp2 -ac 2 -ab 128k -ar 48000 \
- | nc -nu 127.0.0.1 ${PORT}
-f wav \
-i - \
-title "${TITLE}" \
-f mpegts -acodec mp2 -ac 2 -ab 128k -ar 48000 \
"udp://127.0.0.1:${PORT}?pkt_size=16356"
} > ${LOG} 2>&1

View File

@@ -37,7 +37,7 @@ AUDIO_BITRATE=320
exit_with_error()
{
logger "vlc2iptv: error: $*"
exit 1;
exit 1
}
read_arguments()

View File

@@ -27,7 +27,7 @@
if [ $# -ne 2 ]; then
logger "$0: error: Invalid parameter count '$#' $*"
exit 1;
exit 1
fi
# Channels.conf parameter
@@ -50,8 +50,8 @@ rm -f "${FIFO}"
mkfifo "${FIFO}"
mplayer -dumpstream "${URL}" \
-quiet -nolirc -noautosub -noconsolecontrols -novideo -nojoystick \
-dumpfile "${FIFO}" &
-quiet -nolirc -noautosub -noconsolecontrols -novideo -nojoystick \
-dumpfile "${FIFO}" &
# Time to connect and fill pipe
sleep 3
@@ -59,11 +59,11 @@ sleep 3
# Build stream from audiodump with cycle image as video
# PID 0x100/256 = Video 0x101/257 = Audio
ffmpeg -v -1 \
-i "${FIFO}" -r 0.5 -loop_input -i '${IMAGE}' \
-title "${TITLE}" \
-f mpegts -intra -r 24 -vcodec mpeg2video -b 500k -s 352x288 \
-acodec mp2 -ac 2 -ab 96k -ar 48000 \
- | nc -u 127.0.0.1 ${PORT}
-i "${FIFO}" -r 0.5 -loop_input -i '${IMAGE}' \
-title "${TITLE}" \
-f mpegts -intra -r 24 -vcodec mpeg2video -b 500k -s 352x288 \
-acodec mp2 -ac 2 -ab 96k -ar 48000 \
"udp://127.0.0.1:${PORT}?pkt_size=16356"
rm -f "${FIFO}"
} > ${LOG} 2>&1

View File

@@ -0,0 +1,11 @@
diff -Nru vdr-1.6.0-vanilla/pat.c vdr-1.6.0-disable-ca-updates/pat.c
--- vdr-1.6.0-vanilla/pat.c 2008-02-08 15:48:31.000000000 +0200
+++ vdr-1.6.0-disable-ca-updates/pat.c 2009-03-07 14:56:42.000000000 +0200
@@ -440,6 +440,7 @@
}
if (Setup.UpdateChannels >= 2) {
Channel->SetPids(Vpid, Vpid ? Ppid : 0, Apids, ALangs, Dpids, DLangs, Spids, SLangs, Tpid);
+ if (!Channel->IsPlug())
Channel->SetCaIds(CaDescriptors->CaIds());
}
Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors));

View File

@@ -0,0 +1,11 @@
diff -Nru vdr-1.7.7-vanilla/pat.c vdr-1.7.7-disable_ca_updates/pat.c
--- vdr-1.7.7-vanilla/pat.c 2008-07-06 17:01:32.000000000 +0300
+++ vdr-1.7.7-disable_ca_updates/pat.c 2009-05-22 10:57:58.000000000 +0300
@@ -444,6 +444,7 @@
}
if (Setup.UpdateChannels >= 2) {
Channel->SetPids(Vpid, Ppid, Vtype, Apids, ALangs, Dpids, DLangs, Spids, SLangs, Tpid);
+ if (!Channel->IsPlug())
Channel->SetCaIds(CaDescriptors->CaIds());
}
Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors));

View File

@@ -1,6 +1,6 @@
diff -Nru vdr-1.7.2-vanilla/channels.c vdr-1.7.2-pluginparam/channels.c
--- vdr-1.7.2-vanilla/channels.c 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/channels.c 2008-12-14 19:52:45.000000000 +0200
diff -Nru vdr-1.7.7-vanilla/channels.c vdr-1.7.7-pluginparam/channels.c
--- vdr-1.7.7-vanilla/channels.c 2009-04-25 16:57:32.000000000 +0300
+++ vdr-1.7.7-pluginparam/channels.c 2009-05-22 10:57:39.000000000 +0300
@@ -188,6 +188,7 @@
shortName = strdup("");
provider = strdup("");
@@ -122,9 +122,9 @@ diff -Nru vdr-1.7.2-vanilla/channels.c vdr-1.7.2-pluginparam/channels.c
free(parambuf);
free(sourcebuf);
diff -Nru vdr-1.7.2-vanilla/channels.h vdr-1.7.2-pluginparam/channels.h
--- vdr-1.7.2-vanilla/channels.h 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/channels.h 2008-12-14 19:53:44.000000000 +0200
diff -Nru vdr-1.7.7-vanilla/channels.h vdr-1.7.7-pluginparam/channels.h
--- vdr-1.7.7-vanilla/channels.h 2008-11-22 15:35:52.000000000 +0200
+++ vdr-1.7.7-pluginparam/channels.h 2009-05-22 10:57:39.000000000 +0300
@@ -116,6 +116,7 @@
char *shortName;
char *provider;
@@ -164,22 +164,22 @@ diff -Nru vdr-1.7.2-vanilla/channels.h vdr-1.7.2-pluginparam/channels.h
void SetPids(int Vpid, int Ppid, int Vtype, int *Apids, char ALangs[][MAXLANGCODE2], int *Dpids, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid);
void SetCaIds(const int *CaIds); // list must be zero-terminated
void SetCaDescriptors(int Level);
diff -Nru vdr-1.7.2-vanilla/config.h vdr-1.7.2-pluginparam/config.h
--- vdr-1.7.2-vanilla/config.h 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/config.h 2008-12-14 19:52:45.000000000 +0200
diff -Nru vdr-1.7.7-vanilla/config.h vdr-1.7.7-pluginparam/config.h
--- vdr-1.7.7-vanilla/config.h 2009-05-03 16:15:35.000000000 +0300
+++ vdr-1.7.7-pluginparam/config.h 2009-05-22 10:57:39.000000000 +0300
@@ -30,6 +30,8 @@
#define APIVERSION "1.7.0"
#define APIVERSNUM 10700 // Version * 10000 + Major * 100 + Minor
#define APIVERSION "1.7.7"
#define APIVERSNUM 10707 // Version * 10000 + Major * 100 + Minor
+#define PLUGINPARAMPATCHVERSNUM 1
+
// When loading plugins, VDR searches them by their APIVERSION, which
// may be smaller than VDRVERSION in case there have been no changes to
// VDR header files since the last APIVERSION. This allows compiled
diff -Nru vdr-1.7.2-vanilla/menu.c vdr-1.7.2-pluginparam/menu.c
--- vdr-1.7.2-vanilla/menu.c 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/menu.c 2008-12-14 19:52:45.000000000 +0200
@@ -189,6 +189,7 @@
diff -Nru vdr-1.7.7-vanilla/menu.c vdr-1.7.7-pluginparam/menu.c
--- vdr-1.7.7-vanilla/menu.c 2009-05-03 16:30:13.000000000 +0300
+++ vdr-1.7.7-pluginparam/menu.c 2009-05-22 10:57:39.000000000 +0300
@@ -190,6 +190,7 @@
cChannel *channel;
cChannel data;
char name[256];
@@ -187,7 +187,7 @@ diff -Nru vdr-1.7.2-vanilla/menu.c vdr-1.7.2-pluginparam/menu.c
void Setup(void);
public:
cMenuEditChannel(cChannel *Channel, bool New = false);
@@ -221,6 +222,7 @@
@@ -222,6 +223,7 @@
// Parameters for all types of sources:
strn0cpy(name, data.name, sizeof(name));
@@ -195,7 +195,7 @@ diff -Nru vdr-1.7.2-vanilla/menu.c vdr-1.7.2-pluginparam/menu.c
Add(new cMenuEditStrItem( tr("Name"), name, sizeof(name)));
Add(new cMenuEditSrcItem( tr("Source"), &data.source));
Add(new cMenuEditIntItem( tr("Frequency"), &data.frequency));
@@ -253,6 +255,7 @@
@@ -254,6 +256,7 @@
ST(" T") Add(new cMenuEditMapItem( tr("Guard"), &data.guard, GuardValues));
ST(" T") Add(new cMenuEditMapItem( tr("Hierarchy"), &data.hierarchy, HierarchyValues));
ST(" S ") Add(new cMenuEditMapItem( tr("Rolloff"), &data.rollOff, RollOffValues));
@@ -203,7 +203,7 @@ diff -Nru vdr-1.7.2-vanilla/menu.c vdr-1.7.2-pluginparam/menu.c
SetCurrent(Get(current));
Display();
@@ -267,6 +270,7 @@
@@ -268,6 +271,7 @@
if (Key == kOk) {
if (Channels.HasUniqueChannelID(&data, channel)) {
data.name = strcpyrealloc(data.name, name);
@@ -211,9 +211,9 @@ diff -Nru vdr-1.7.2-vanilla/menu.c vdr-1.7.2-pluginparam/menu.c
if (channel) {
*channel = data;
isyslog("edited channel %d %s", channel->Number(), *data.ToText());
diff -Nru vdr-1.7.2-vanilla/po/fi_FI.po vdr-1.7.2-pluginparam/po/fi_FI.po
--- vdr-1.7.2-vanilla/po/fi_FI.po 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/po/fi_FI.po 2008-12-14 19:52:45.000000000 +0200
diff -Nru vdr-1.7.7-vanilla/po/fi_FI.po vdr-1.7.7-pluginparam/po/fi_FI.po
--- vdr-1.7.7-vanilla/po/fi_FI.po 2009-05-03 17:15:20.000000000 +0300
+++ vdr-1.7.7-pluginparam/po/fi_FI.po 2009-05-22 10:57:39.000000000 +0300
@@ -1010,3 +1010,6 @@
#, c-format
msgid "VDR will shut down in %s minutes"
@@ -221,9 +221,9 @@ diff -Nru vdr-1.7.2-vanilla/po/fi_FI.po vdr-1.7.2-pluginparam/po/fi_FI.po
+
+msgid "Parameters"
+msgstr "Parametrit"
diff -Nru vdr-1.7.2-vanilla/po/fr_FR.po vdr-1.7.2-pluginparam/po/fr_FR.po
--- vdr-1.7.2-vanilla/po/fr_FR.po 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/po/fr_FR.po 2008-12-14 19:52:45.000000000 +0200
diff -Nru vdr-1.7.7-vanilla/po/fr_FR.po vdr-1.7.7-pluginparam/po/fr_FR.po
--- vdr-1.7.7-vanilla/po/fr_FR.po 2009-05-03 17:15:20.000000000 +0300
+++ vdr-1.7.7-pluginparam/po/fr_FR.po 2009-05-22 10:57:39.000000000 +0300
@@ -1013,3 +1013,6 @@
#, c-format
msgid "VDR will shut down in %s minutes"
@@ -231,9 +231,9 @@ diff -Nru vdr-1.7.2-vanilla/po/fr_FR.po vdr-1.7.2-pluginparam/po/fr_FR.po
+
+msgid "Parameters"
+msgstr "Paramètres"
diff -Nru vdr-1.7.2-vanilla/sources.c vdr-1.7.2-pluginparam/sources.c
--- vdr-1.7.2-vanilla/sources.c 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/sources.c 2008-12-14 19:52:45.000000000 +0200
diff -Nru vdr-1.7.7-vanilla/sources.c vdr-1.7.7-pluginparam/sources.c
--- vdr-1.7.7-vanilla/sources.c 2008-02-10 16:07:26.000000000 +0200
+++ vdr-1.7.7-pluginparam/sources.c 2009-05-22 10:57:39.000000000 +0300
@@ -37,6 +37,7 @@
char buffer[16];
char *q = buffer;
@@ -250,9 +250,9 @@ diff -Nru vdr-1.7.2-vanilla/sources.c vdr-1.7.2-pluginparam/sources.c
case 'C': type = stCable; break;
case 'S': type = stSat; break;
case 'T': type = stTerr; break;
diff -Nru vdr-1.7.2-vanilla/sources.conf vdr-1.7.2-pluginparam/sources.conf
--- vdr-1.7.2-vanilla/sources.conf 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/sources.conf 2008-12-14 19:52:45.000000000 +0200
diff -Nru vdr-1.7.7-vanilla/sources.conf vdr-1.7.7-pluginparam/sources.conf
--- vdr-1.7.7-vanilla/sources.conf 2008-08-16 13:02:27.000000000 +0300
+++ vdr-1.7.7-pluginparam/sources.conf 2009-05-22 10:57:39.000000000 +0300
@@ -194,3 +194,7 @@
# Terrestrial
@@ -261,9 +261,9 @@ diff -Nru vdr-1.7.2-vanilla/sources.conf vdr-1.7.2-pluginparam/sources.conf
+# Plugin
+
+P Plugin
diff -Nru vdr-1.7.2-vanilla/sources.h vdr-1.7.2-pluginparam/sources.h
--- vdr-1.7.2-vanilla/sources.h 2008-12-14 18:36:17.000000000 +0200
+++ vdr-1.7.2-pluginparam/sources.h 2008-12-14 19:52:45.000000000 +0200
diff -Nru vdr-1.7.7-vanilla/sources.h vdr-1.7.7-pluginparam/sources.h
--- vdr-1.7.7-vanilla/sources.h 2005-05-14 12:30:41.000000000 +0300
+++ vdr-1.7.7-pluginparam/sources.h 2009-05-22 10:57:39.000000000 +0300
@@ -16,10 +16,11 @@
public:
enum eSourceType {

View File

@@ -120,36 +120,39 @@ void cPidScanner::Process(const uint8_t* buf)
return;
}
cChannel *IptvChannel = Channels.GetByChannelID(channel.GetChannelID());
int Apids[MAXAPIDS + 1] = { 0 }; // these lists are zero-terminated
int Dpids[MAXDPIDS + 1] = { 0 };
int Spids[MAXSPIDS + 1] = { 0 };
char ALangs[MAXAPIDS][MAXLANGCODE2] = { "" };
char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" };
char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" };
int Ppid = IptvChannel->Ppid();
int Tpid = IptvChannel->Tpid();
bool foundApid = false;
if (numVpids < PIDSCANNER_VPID_COUNT)
Vpid = 0; // No detected video pid
else if (numApids < PIDSCANNER_APID_COUNT)
Apid = 0; // No detected audio pid
for (unsigned int i = 1; i < MAXAPIDS; ++i) {
Apids[i] = IptvChannel->Apid(i);
if (Apids[i] && (Apids[i] == Apid))
foundApid = true;
}
if (!foundApid)
Apids[0] = Apid;
for (unsigned int i = 0; i < MAXDPIDS; ++i)
Dpids[i] = IptvChannel->Dpid(i);
for (unsigned int i = 0; i < MAXSPIDS; ++i)
Spids[i] = IptvChannel->Spid(i);
debug("cPidScanner::Process(): Vpid=0x%04X, Apid=0x%04X\n", Vpid, Apid);
#if defined(APIVERSNUM) && APIVERSNUM >= 10700
IptvChannel->SetPids(Vpid, Ppid, 0, Apids, ALangs, Dpids, DLangs, Spids, SLangs, Tpid);
if (IptvChannel) {
int Apids[MAXAPIDS + 1] = { 0 }; // these lists are zero-terminated
int Dpids[MAXDPIDS + 1] = { 0 };
int Spids[MAXSPIDS + 1] = { 0 };
char ALangs[MAXAPIDS][MAXLANGCODE2] = { "" };
char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" };
char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" };
int Ppid = IptvChannel->Ppid();
int Tpid = IptvChannel->Tpid();
bool foundApid = false;
if (numVpids < PIDSCANNER_VPID_COUNT)
Vpid = 0; // No detected video pid
else if (numApids < PIDSCANNER_APID_COUNT)
Apid = 0; // No detected audio pid
for (unsigned int i = 1; i < MAXAPIDS; ++i) {
Apids[i] = IptvChannel->Apid(i);
if (Apids[i] && (Apids[i] == Apid))
foundApid = true;
}
if (!foundApid)
Apids[0] = Apid;
for (unsigned int i = 0; i < MAXDPIDS; ++i)
Dpids[i] = IptvChannel->Dpid(i);
for (unsigned int i = 0; i < MAXSPIDS; ++i)
Spids[i] = IptvChannel->Spid(i);
debug("cPidScanner::Process(): Vpid=0x%04X, Apid=0x%04X\n", Vpid, Apid);
#if defined(APIVERSNUM) && APIVERSNUM >= 10704
int Vtype = IptvChannel->Vtype();
IptvChannel->SetPids(Vpid, Ppid, Vtype, Apids, ALangs, Dpids, DLangs, Spids, SLangs, Tpid);
#else
IptvChannel->SetPids(Vpid, Ppid, Apids, ALangs, Dpids, DLangs, Spids, SLangs, Tpid);
IptvChannel->SetPids(Vpid, Ppid, Apids, ALangs, Dpids, DLangs, Spids, SLangs, Tpid);
#endif
}
Channels.Unlock();
process = false;
}

View File

@@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: iptv 0.2.0\n"
"Project-Id-Version: iptv 0.2.5\n"
"Report-Msgid-Bugs-To: Rolf Ahrenberg\n"
"POT-Creation-Date: 2008-02-01 23:43+0200\n"
"POT-Creation-Date: 2009-03-06 22:15+0200\n"
"PO-Revision-Date: 2007-10-29 21:19+0100\n"
"Last-Translator: Tobias Grimm <tg@e-tobi.net>\n"
"Language-Team: German\n"
@@ -76,6 +76,9 @@ msgstr "Scanne SID"
msgid "Scan pids"
msgstr "Scanne PIDS"
msgid "Vtype"
msgstr "Vtype"
msgid "Nid"
msgstr "Nid"

View File

@@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: iptv 0.2.0\n"
"Project-Id-Version: iptv 0.2.5\n"
"Report-Msgid-Bugs-To: Rolf Ahrenberg\n"
"POT-Creation-Date: 2008-02-01 23:43+0200\n"
"POT-Creation-Date: 2009-03-06 22:15+0200\n"
"PO-Revision-Date: 2007-08-12 23:22+0300\n"
"Last-Translator: Rolf Ahrenberg\n"
"Language-Team: <vdr@linuxtv.org>\n"
@@ -75,6 +75,9 @@ msgstr "Etsi palvelu-ID"
msgid "Scan pids"
msgstr "Etsi pidit"
msgid "Vtype"
msgstr "Kuvatyyppi"
msgid "Nid"
msgstr "Verkko-ID"

View File

@@ -6,9 +6,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: iptv 0.2.0\n"
"Project-Id-Version: iptv 0.2.5\n"
"Report-Msgid-Bugs-To: Rolf Ahrenberg\n"
"POT-Creation-Date: 2008-02-01 23:43+0200\n"
"POT-Creation-Date: 2009-03-06 22:15+0200\n"
"PO-Revision-Date: 2008-01-26 13:14+0100\n"
"Last-Translator: NIVAL Michaël <mnival@club-internet.fr>\n"
"Language-Team: French\n"
@@ -77,6 +77,9 @@ msgstr "Scanne les SID"
msgid "Scan pids"
msgstr "Scanne les PID"
msgid "Vtype"
msgstr "Vtype"
msgid "Nid"
msgstr "Nid"

View File

@@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: iptv 0.2.0\n"
"Project-Id-Version: iptv 0.2.5\n"
"Report-Msgid-Bugs-To: Rolf Ahrenberg\n"
"POT-Creation-Date: 2008-02-01 23:43+0200\n"
"POT-Creation-Date: 2009-03-06 22:15+0200\n"
"PO-Revision-Date: 2008-07-13 03:28+0100\n"
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
"Language-Team: Italian\n"
@@ -76,6 +76,9 @@ msgstr "Scansione Sid"
msgid "Scan pids"
msgstr "Scansione Pids"
msgid "Vtype"
msgstr "Vtype"
msgid "Nid"
msgstr "Nid"
@@ -180,4 +183,3 @@ msgstr "Definisci un filtro corrotto che sarà messo nella lista nera."
msgid "Help"
msgstr "Aiuto"

View File

@@ -5,9 +5,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: iptv 0.2.0\n"
"Project-Id-Version: iptv 0.2.5\n"
"Report-Msgid-Bugs-To: Rolf Ahrenberg\n"
"POT-Creation-Date: 2008-02-01 23:43+0200\n"
"POT-Creation-Date: 2009-03-06 22:15+0200\n"
"PO-Revision-Date: 2008-03-16 12:14+0100\n"
"Last-Translator: Alexander Gross <Bikalexander@gmail.com>\n"
"Language-Team: Russian <de@li.org>\n"
@@ -77,6 +77,9 @@ msgstr "Сканировать SID"
msgid "Scan pids"
msgstr "Сканировать пиды"
msgid "Vtype"
msgstr "Vtype"
msgid "Nid"
msgstr "Nid"
@@ -165,4 +168,3 @@ msgstr "Неправильно работающий фильтр, занести
msgid "Help"
msgstr "Справка"

View File

@@ -106,7 +106,7 @@ bool cIptvProtocolExt::Open(void)
{
debug("cIptvProtocolExt::Open()\n");
// Reject empty script files
if (!strlen(scriptFile))
if (!strlen(*scriptFile))
return false;
// Create the listening socket
OpenSocket(socketPort);
@@ -127,9 +127,9 @@ bool cIptvProtocolExt::Close(void)
return true;
}
int cIptvProtocolExt::Read(unsigned char* *BufferAddr)
int cIptvProtocolExt::Read(unsigned char* BufferAddr, unsigned int BufferLen)
{
return cIptvUdpSocket::Read(BufferAddr);
return cIptvUdpSocket::Read(BufferAddr, BufferLen);
}
bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int Index)
@@ -139,7 +139,7 @@ bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int
struct stat stbuf;
// Update script file and parameter
scriptFile = cString::sprintf("%s/%s", IptvConfig.GetConfigDirectory(), Location);
if ((stat(scriptFile, &stbuf) != 0) || (strstr(scriptFile, "..") != 0)) {
if ((stat(*scriptFile, &stbuf) != 0) || (strstr(*scriptFile, "..") != 0)) {
error("ERROR: Non-existent or relative path script '%s'", *scriptFile);
return false;
}

View File

@@ -25,7 +25,7 @@ private:
public:
cIptvProtocolExt();
virtual ~cIptvProtocolExt();
int Read(unsigned char* *BufferAddr);
int Read(unsigned char* BufferAddr, unsigned int BufferLen);
bool Set(const char* Location, const int Parameter, const int Index);
bool Open(void);
bool Close(void);

View File

@@ -16,15 +16,11 @@
cIptvProtocolFile::cIptvProtocolFile()
: fileDelay(0),
readBufferLen(TS_SIZE * IptvConfig.GetReadBufferTsCount()),
fileStream(NULL),
isActive(false)
{
debug("cIptvProtocolFile::cIptvProtocolFile()\n");
fileLocation = strdup("");
// Allocate receive buffer
readBuffer = MALLOC(unsigned char, readBufferLen);
if (!readBuffer)
error("ERROR: MALLOC() failed in ProtocolFile()");
}
cIptvProtocolFile::~cIptvProtocolFile()
@@ -34,7 +30,6 @@ cIptvProtocolFile::~cIptvProtocolFile()
cIptvProtocolFile::Close();
// Free allocated memory
free(fileLocation);
free(readBuffer);
}
bool cIptvProtocolFile::OpenFile(void)
@@ -61,10 +56,9 @@ void cIptvProtocolFile::CloseFile(void)
}
}
int cIptvProtocolFile::Read(unsigned char* *BufferAddr)
int cIptvProtocolFile::Read(unsigned char* BufferAddr, unsigned int BufferLen)
{
//debug("cIptvProtocolFile::Read()\n");
*BufferAddr = readBuffer;
// Check errors
if (ferror(fileStream)) {
debug("Read error\n");
@@ -81,7 +75,7 @@ int cIptvProtocolFile::Read(unsigned char* *BufferAddr)
// during the sleep and buffers are disposed. Check here that the plugin is
// still active before accessing the buffers
if (isActive)
return fread(readBuffer, sizeof(unsigned char), readBufferLen, fileStream);
return fread(BufferAddr, sizeof(unsigned char), BufferLen, fileStream);
return -1;
}

View File

@@ -16,8 +16,6 @@ private:
char* fileLocation;
int fileDelay;
FILE* fileStream;
unsigned char* readBuffer;
unsigned int readBufferLen;
bool isActive;
private:
@@ -27,7 +25,7 @@ private:
public:
cIptvProtocolFile();
virtual ~cIptvProtocolFile();
int Read(unsigned char* *BufferAddr);
int Read(unsigned char* BufferAddr, unsigned int BufferLen);
bool Set(const char* Location, const int Parameter, const int Index);
bool Open(void);
bool Close(void);

View File

@@ -45,7 +45,7 @@ bool cIptvProtocolHttp::Connect(void)
// First try only the IP address
sockAddr.sin_addr.s_addr = inet_addr(streamAddr);
if (sockAddr.sin_addr.s_addr == INADDR_NONE) {
debug("Cannot convert %s directly to internet address\n", streamAddr);
@@ -62,8 +62,7 @@ bool cIptvProtocolHttp::Connect(void)
sockAddr.sin_addr.s_addr = inet_addr(*host->h_addr_list);
}
int err = connect(socketDesc, (struct sockaddr*)&sockAddr,
sizeof(sockAddr));
int err = connect(socketDesc, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
// Non-blocking sockets always report in-progress error when connected
ERROR_IF_FUNC(err < 0 && errno != EINPROGRESS, "connect()", CloseSocket(), return false);
// Select with 800ms timeout on the socket completion, check if it is writable
@@ -123,7 +122,7 @@ bool cIptvProtocolHttp::Disconnect(void)
}
bool cIptvProtocolHttp::GetHeaderLine(char* dest, unsigned int destLen,
unsigned int &recvLen)
unsigned int &recvLen)
{
debug("cIptvProtocolHttp::GetHeaderLine()\n");
bool linefeed = false;
@@ -214,9 +213,9 @@ bool cIptvProtocolHttp::Close(void)
return true;
}
int cIptvProtocolHttp::Read(unsigned char* *BufferAddr)
int cIptvProtocolHttp::Read(unsigned char* BufferAddr, unsigned int BufferLen)
{
return cIptvTcpSocket::Read(BufferAddr);
return cIptvTcpSocket::Read(BufferAddr, BufferLen);
}
bool cIptvProtocolHttp::Set(const char* Location, const int Parameter, const int Index)

View File

@@ -20,14 +20,13 @@ private:
private:
bool Connect(void);
bool Disconnect(void);
bool GetHeaderLine(char* dest, unsigned int destLen,
unsigned int &recvLen);
bool GetHeaderLine(char* dest, unsigned int destLen, unsigned int &recvLen);
bool ProcessHeaders(void);
public:
cIptvProtocolHttp();
virtual ~cIptvProtocolHttp();
int Read(unsigned char* *BufferAddr);
int Read(unsigned char* BufferAddr, unsigned int BufferLen);
bool Set(const char* Location, const int Parameter, const int Index);
bool Open(void);
bool Close(void);

View File

@@ -12,7 +12,7 @@ class cIptvProtocolIf {
public:
cIptvProtocolIf() {}
virtual ~cIptvProtocolIf() {}
virtual int Read(unsigned char* *BufferAddr) = 0;
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen) = 0;
virtual bool Set(const char* Location, const int Parameter, const int Index) = 0;
virtual bool Open(void) = 0;
virtual bool Close(void) = 0;

View File

@@ -91,9 +91,9 @@ bool cIptvProtocolUdp::Close(void)
return true;
}
int cIptvProtocolUdp::Read(unsigned char* *BufferAddr)
int cIptvProtocolUdp::Read(unsigned char* BufferAddr, unsigned int BufferLen)
{
return cIptvUdpSocket::Read(BufferAddr);
return cIptvUdpSocket::Read(BufferAddr, BufferLen);
}
bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int Index)

View File

@@ -23,7 +23,7 @@ private:
public:
cIptvProtocolUdp();
virtual ~cIptvProtocolUdp();
int Read(unsigned char* *BufferAddr);
int Read(unsigned char* BufferAddr, unsigned int BufferLen);
bool Set(const char* Location, const int Parameter, const int Index);
bool Open(void);
bool Close(void);

View File

@@ -7,8 +7,8 @@
#include "sectionfilter.h"
cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
u_short Pid, u_char Tid, u_char Mask)
cIptvSectionFilter::cIptvSectionFilter(int DeviceIndex, int Index,
u_short Pid, u_char Tid, u_char Mask)
: pusi_seen(0),
feedcc(0),
doneq(0),
@@ -17,10 +17,13 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
seclen(0),
tsfeedp(0),
pid(Pid),
devid(DeviceIndex),
id(Index),
pipeName("")
{
//debug("cIptvSectionFilter::cIptvSectionFilter(%d)\n", Index);
//debug("cIptvSectionFilter::cIptvSectionFilter(%d, %d)\n", devid, id);
int i;
memset(secbuf_base, '\0', sizeof(secbuf_base));
memset(filter_value, '\0', sizeof(filter_value));
memset(filter_mask, '\0', sizeof(filter_mask));
@@ -28,17 +31,15 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
memset(maskandmode, '\0', sizeof(maskandmode));
memset(maskandnotmode, '\0', sizeof(maskandnotmode));
SetPipeName(devInd);
filter_value[0] = Tid;
filter_mask[0] = Mask;
// Invert the filter
for (int i = 0; i < DMX_MAX_FILTER_SIZE; ++i)
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i)
filter_value[i] ^= 0xff;
uint8_t mask, mode, local_doneq = 0;
for (int i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
mode = filter_mode[i];
mask = filter_mask[i];
maskandmode[i] = mask & mode;
@@ -47,11 +48,12 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
doneq = local_doneq ? 1 : 0;
struct stat sb;
pipeName = cString::sprintf(IPTV_FILTER_FILENAME, devid, id);
stat(pipeName, &sb);
if (S_ISFIFO(sb.st_mode))
unlink(pipeName);
int err = mknod(pipeName, 0644 | S_IFIFO, 0);
ERROR_IF_RET(err < 0, "mknod()", return);
i = mknod(pipeName, 0644 | S_IFIFO, 0);
ERROR_IF_RET(i < 0, "mknod()", return);
// Create descriptors
fifoDescriptor = open(pipeName, O_RDWR | O_NONBLOCK);
@@ -60,127 +62,75 @@ cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd,
cIptvSectionFilter::~cIptvSectionFilter()
{
//debug("cIptvSectionFilter::~cIptvSectionfilter(%d)\n", id);
//debug("cIptvSectionFilter::~cIptvSectionfilter(%d, %d)\n", devid, id);
close(fifoDescriptor);
close(readDescriptor);
unlink(pipeName);
fifoDescriptor = -1;
readDescriptor = -1;
secbuf = NULL;
}
void cIptvSectionFilter::SetPipeName(int deviceIndex)
{
pipeName = cString::sprintf(IPTV_FILTER_FILENAME, deviceIndex, id);
}
int cIptvSectionFilter::GetReadDesc()
int cIptvSectionFilter::GetReadDesc(void)
{
return readDescriptor;
}
inline uint16_t cIptvSectionFilter::section_length(const uint8_t *buf)
inline uint16_t cIptvSectionFilter::GetLength(const uint8_t *Data)
{
return 3 + ((buf[1] & 0x0f) << 8) + buf[2];
return 3 + ((Data[1] & 0x0f) << 8) + Data[2];
}
int cIptvSectionFilter::dmxdev_section_callback(const uint8_t *buffer1, size_t buffer1_len,
const uint8_t *buffer2, size_t buffer2_len,
enum dmx_success success)
void cIptvSectionFilter::New(void)
{
// See if there is data in the fifo
int retval = select_single_desc(fifoDescriptor, 0, false);
// There is no data in the fifo, more can be written
if (!retval) {
#ifdef DEBUG_PRINTF
printf("id = %d, pid %d would now write %d data to buffer\n", id, pid, buffer1_len);
for (unsigned int i = 0; i < buffer1_len; ++i)
printf("0x%X ", buffer1[i]);
printf("\n");
#endif
retval = write(fifoDescriptor, buffer1, buffer1_len);
ERROR_IF(retval < 0, "write()");
// Update statistics
AddSectionStatistic(retval, 1);
}
#ifdef DEBUG_PRINTF
else if (retval)
printf("id %d pid %d data is already present\n", id, pid);
#endif
return 0;
}
void cIptvSectionFilter::demux_swfilter_section_new()
{
#ifdef DEMUX_SECTION_LOSS_LOG
if (secbufp < tsfeedp) {
int i, n = tsfeedp - secbufp;
/*
* Section padding is done with 0xff bytes entirely.
* Due to speed reasons, we won't check all of them
* but just first and last.
*/
if (secbuf[0] != 0xff || secbuf[n - 1] != 0xff) {
printf("sectionfilter.c section ts padding loss: %d/%d\n",
n, tsfeedp);
printf("sectionfilter.c pad data:");
for (i = 0; i < n; ++i)
printf(" %02x", secbuf[i]);
printf("\n");
}
}
#endif
tsfeedp = secbufp = seclen = 0;
secbuf = secbuf_base;
}
int cIptvSectionFilter::demux_swfilter_sectionfilter()
int cIptvSectionFilter::Filter(void)
{
uint8_t neq = 0;
int i;
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
uint8_t local_xor = filter_value[i] ^ secbuf[i];
if (maskandmode[i] & local_xor) {
#ifdef DEBUG_PRINTF
printf("maskandmode discard\n");
#endif
return 0;
if (secbuf) {
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
uint8_t local_xor = filter_value[i] ^ secbuf[i];
if (maskandmode[i] & local_xor)
return 0;
neq |= maskandnotmode[i] & local_xor;
}
neq |= maskandnotmode[i] & local_xor;
}
if (doneq && !neq) {
#ifdef DEBUG_PRINTF
printf("doneq discard, doneq = 0x%X, neq = 0x%X\n", doneq, !neq);
#endif
return 0;
if (doneq && !neq)
return 0;
// There is no data in the fifo, more can be written
if (!select_single_desc(fifoDescriptor, 0, false)) {
i = write(fifoDescriptor, secbuf, seclen);
ERROR_IF(i < 0, "write()");
// Update statistics
AddSectionStatistic(i, 1);
}
}
return dmxdev_section_callback(secbuf, seclen, NULL, 0, DMX_OK);
return 0;
}
inline int cIptvSectionFilter::demux_swfilter_section_feed()
inline int cIptvSectionFilter::Feed(void)
{
if (demux_swfilter_sectionfilter() < 0)
if (Filter() < 0)
return -1;
seclen = 0;
return 0;
}
int cIptvSectionFilter::demux_swfilter_section_copy_dump(const uint8_t *buf, uint8_t len)
int cIptvSectionFilter::CopyDump(const uint8_t *buf, uint8_t len)
{
uint16_t limit, seclen_local, n;
if (tsfeedp >= DMX_MAX_SECFEED_SIZE)
return 0;
if (tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
#ifdef DEMUX_SECTION_LOSS_LOG
printf("sectionfilter.c section buffer full loss: %d/%d\n",
tsfeedp + len - DMX_MAX_SECFEED_SIZE,
DMX_MAX_SECFEED_SIZE);
#endif
if (tsfeedp + len > DMX_MAX_SECFEED_SIZE)
len = DMX_MAX_SECFEED_SIZE - tsfeedp;
}
if (len <= 0)
return 0;
@@ -188,108 +138,80 @@ int cIptvSectionFilter::demux_swfilter_section_copy_dump(const uint8_t *buf, uin
memcpy(secbuf_base + tsfeedp, buf, len);
tsfeedp += len;
/*
* Dump all the sections we can find in the data (Emard)
*/
limit = tsfeedp;
if (limit > DMX_MAX_SECFEED_SIZE)
return -1; /* internal error should never happen */
return -1; // internal error should never happen
/* to be sure always set secbuf */
// Always set secbuf
secbuf = secbuf_base + secbufp;
for (n = 0; secbufp + 2 < limit; ++n) {
seclen_local = section_length(secbuf);
seclen_local = GetLength(secbuf);
if (seclen_local <= 0 || seclen_local > DMX_MAX_SECTION_SIZE ||
seclen_local + secbufp > limit)
return 0;
#ifdef DEBUG_PRINTF
printf("Non-mismatching seclen! %d, limit = %d\n", seclen_local, limit);
#endif
seclen = seclen_local;
/* dump [secbuf .. secbuf+seclen) */
if (pusi_seen)
demux_swfilter_section_feed();
#ifdef DEMUX_SECTION_LOSS_LOG
else
printf("sectionfilter.c pusi not seen, discarding section data\n");
#endif
secbufp += seclen_local; /* secbufp and secbuf moving together is */
secbuf += seclen_local; /* redundant but saves pointer arithmetic */
Feed();
secbufp += seclen_local;
secbuf += seclen_local;
}
return 0;
}
void cIptvSectionFilter::ProcessData(const uint8_t* buf)
void cIptvSectionFilter::Process(const uint8_t* Data)
{
if (buf[0] != 0x47) {
error("Not TS packet: 0x%X\n", buf[0]);
if (Data[0] != TS_SYNC_BYTE)
return;
}
// Stop if not the PID this filter is looking for
if (ts_pid(buf) != pid)
if (ts_pid(Data) != pid)
return;
uint8_t count = payload(buf);
uint8_t count = payload(Data);
if (count == 0) /* count == 0 if no payload or out of range */
// Check if no payload or out of range
if (count == 0)
return;
uint8_t p = 188 - count; /* payload start */
// Payload start
uint8_t p = TS_SIZE - count;
uint8_t cc = buf[3] & 0x0f;
uint8_t cc = Data[3] & 0x0f;
int ccok = ((feedcc + 1) & 0x0f) == cc;
feedcc = cc;
feedcc = cc;
int dc_i = 0;
if (buf[3] & 0x20) {
/* adaption field present, check for discontinuity_indicator */
if ((buf[4] > 0) && (buf[5] & 0x80))
if (Data[3] & 0x20) {
// Adaption field present, check for discontinuity_indicator
if ((Data[4] > 0) && (Data[5] & 0x80))
dc_i = 1;
}
if (!ccok || dc_i) {
#ifdef DEMUX_SECTION_LOSS_LOG
printf("sectionfilter.c discontinuity detected %d bytes lost\n",
count);
/*
* those bytes under sume circumstances will again be reported
* in the following demux_swfilter_section_new
*/
#endif
/*
* Discontinuity detected. Reset pusi_seen = 0 to
* stop feeding of suspicious data until next PUSI=1 arrives
*/
// Discontinuity detected. Reset pusi_seen = 0 to
// stop feeding of suspicious data until next PUSI=1 arrives
pusi_seen = 0;
demux_swfilter_section_new();
New();
}
if (buf[1] & 0x40) {
/* PUSI=1 (is set), section boundary is here */
if (count > 1 && buf[p] < count) {
#ifdef DEBUG_PRINTF
printf("Valid section\n");
#endif
const uint8_t *before = &buf[p + 1];
uint8_t before_len = buf[p];
if (Data[1] & 0x40) {
// PUSI=1 (is set), section boundary is here
if (count > 1 && Data[p] < count) {
const uint8_t *before = &Data[p + 1];
uint8_t before_len = Data[p];
const uint8_t *after = &before[before_len];
uint8_t after_len = (count - 1) - before_len;
CopyDump(before, before_len);
demux_swfilter_section_copy_dump(before, before_len);
/* before start of new section, set pusi_seen = 1 */
// Before start of new section, set pusi_seen = 1
pusi_seen = 1;
demux_swfilter_section_new();
demux_swfilter_section_copy_dump(after, after_len);
New();
CopyDump(after, after_len);
}
#ifdef DEMUX_SECTION_LOSS_LOG
else if (count > 0)
printf("sectionfilter.c PUSI=1 but %d bytes lost\n", count);
#endif
}
else {
/* PUSI=0 (is not set), no section boundary */
demux_swfilter_section_copy_dump(&buf[p], count);
// PUSI=0 (is not set), no section boundary
CopyDump(&Data[p], count);
}
}

View File

@@ -8,38 +8,17 @@
#ifndef __IPTV_SECTIONFILTER_H
#define __IPTV_SECTIONFILTER_H
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <libgen.h>
#include <stdint.h>
#include <sys/param.h>
#include <vdr/device.h>
#include "common.h"
#include "statistics.h"
class cIptvSectionFilter : public cIptvSectionStatistics {
private:
enum dmx_success {
DMX_OK = 0, /* Received Ok */
DMX_LENGTH_ERROR, /* Incorrect length */
DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
DMX_CRC_ERROR, /* Incorrect CRC */
DMX_FRAME_ERROR, /* Frame alignment error */
DMX_FIFO_ERROR, /* Receiver FIFO overrun */
DMX_MISSED_ERROR /* Receiver missed packet */
};
enum dmx_limits {
DMX_MAX_FILTER_SIZE = 18,
DMX_MAX_SECTION_SIZE = 4096,
DMX_MAX_SECFEED_SIZE = (DMX_MAX_SECTION_SIZE + 188)
DMX_MAX_SECFEED_SIZE = (DMX_MAX_SECTION_SIZE + TS_SIZE)
};
int fifoDescriptor;
@@ -55,49 +34,32 @@ private:
uint16_t seclen;
uint16_t tsfeedp;
uint16_t pid;
int devid;
int id;
cString pipeName;
uint8_t filter_value[DMX_MAX_FILTER_SIZE];
uint8_t filter_mask[DMX_MAX_FILTER_SIZE];
uint8_t filter_mode[DMX_MAX_FILTER_SIZE];
uint8_t maskandmode[DMX_MAX_FILTER_SIZE];
uint8_t maskandnotmode[DMX_MAX_FILTER_SIZE];
cString pipeName;
inline uint16_t section_length(const uint8_t *buf);
int dmxdev_section_callback(const uint8_t *buffer1,
size_t buffer1_len,
const uint8_t *buffer2,
size_t buffer2_len,
enum dmx_success success);
void demux_swfilter_section_new();
int demux_swfilter_sectionfilter();
inline int demux_swfilter_section_feed();
int demux_swfilter_section_copy_dump(const uint8_t *buf,
uint8_t len);
int GetFifoDesc();
void ClearPipeName();
void SetPipeName(int deviceIndex);
inline uint16_t GetLength(const uint8_t *Data);
void New(void);
int Filter(void);
inline int Feed(void);
int CopyDump(const uint8_t *buf, uint8_t len);
public:
// constructor & destructor
cIptvSectionFilter(int Index, int devInd, u_short Pid, u_char Tid,
u_char Mask);
cIptvSectionFilter(int Index, int DeviceIndex, u_short Pid,
u_char Tid, u_char Mask);
virtual ~cIptvSectionFilter();
void ProcessData(const uint8_t* buf);
int GetReadDesc();
uint16_t GetPid() { return pid; }
void Process(const uint8_t* Data);
int GetReadDesc(void);
uint16_t GetPid(void) const { return pid; }
};
#endif // __IPTV_SECTIONFILTER_H

23
setup.c
View File

@@ -17,10 +17,6 @@
#include "device.h"
#include "setup.h"
#ifndef trVDR
#define trVDR(s) tr(s)
#endif
// --- cIptvMenuEditChannel --------------------------------------------------
class cIptvMenuEditChannel : public cOsdMenu
@@ -127,7 +123,7 @@ void cIptvMenuEditChannel::GetChannelData(cChannel *Channel)
data.source = Channel->Source();
data.vpid = Channel->Vpid();
data.ppid = Channel->Ppid();
#if defined(APIVERSNUM) && APIVERSNUM >= 10700
#if defined(APIVERSNUM) && APIVERSNUM >= 10704
data.vtype = Channel->Vtype();
#endif
data.tpid = Channel->Tpid();
@@ -200,7 +196,7 @@ void cIptvMenuEditChannel::SetChannelData(cChannel *Channel)
break;
}
char slangs[MAXSPIDS][MAXLANGCODE2] = { "" };
#if defined(APIVERSNUM) && APIVERSNUM >= 10700
#if defined(APIVERSNUM) && APIVERSNUM >= 10704
Channel->SetPids(data.vpid, data.ppid, data.vtype, data.apid, alangs, data.dpid, dlangs, data.spid, slangs, data.tpid);
#else
Channel->SetPids(data.vpid, data.ppid, data.apid, alangs, data.dpid, dlangs, data.spid, slangs, data.tpid);
@@ -244,6 +240,9 @@ void cIptvMenuEditChannel::Setup(void)
Add(new cMenuEditStrItem(trVDR("Name"), data.name, sizeof(data.name)));
Add(new cMenuEditIntItem(trVDR("Frequency"), &data.frequency));
Add(new cMenuEditIntItem(trVDR("Vpid"), &data.vpid, 0, 0x1FFF));
#if defined(APIVERSNUM) && APIVERSNUM >= 10704
Add(new cMenuEditIntItem(tr ("Vtype"), &data.vtype, 0, 0xFF));
#endif
Add(new cMenuEditIntItem(trVDR("Ppid"), &data.ppid, 0, 0x1FFF));
Add(new cMenuEditIntItem(trVDR("Apid1"), &data.apid[0], 0, 0x1FFF));
Add(new cMenuEditIntItem(trVDR("Apid2"), &data.apid[1], 0, 0x1FFF));
@@ -388,7 +387,7 @@ class cIptvMenuChannels : public cOsdMenu
{
private:
void Setup(void);
cChannel *GetChannel(int Index);
cChannel *GetChannel(int Index) const;
void Propagate(void);
protected:
@@ -428,16 +427,16 @@ void cIptvMenuChannels::Setup(void)
Display();
}
cChannel *cIptvMenuChannels::GetChannel(int Index)
cChannel *cIptvMenuChannels::GetChannel(int Index) const
{
cIptvMenuChannelItem *p = (cIptvMenuChannelItem *)Get(Index);
cIptvMenuChannelItem *p = dynamic_cast<cIptvMenuChannelItem *>(Get(Index));
return p ? (cChannel *)p->Channel() : NULL;
}
void cIptvMenuChannels::Propagate(void)
{
Channels.ReNumber();
for (cIptvMenuChannelItem *ci = (cIptvMenuChannelItem *)First(); ci; ci = (cIptvMenuChannelItem *)ci->Next())
for (cIptvMenuChannelItem *ci = dynamic_cast<cIptvMenuChannelItem *>(First()); ci; ci = dynamic_cast<cIptvMenuChannelItem *>(ci->Next()))
ci->Set();
Display();
Channels.SetModified(true);
@@ -615,7 +614,7 @@ eOSState cIptvMenuInfo::ProcessKey(eKeys Key)
case kYellow: page = IPTV_DEVICE_INFO_FILTERS;
UpdateInfo();
break;
case kBlue: IptvConfig.SetUseBytes(!IptvConfig.GetUseBytes());
case kBlue: IptvConfig.SetUseBytes(IptvConfig.GetUseBytes() ? 0 : 1);
UpdateInfo();
break;
default: if (timeout.TimedOut())
@@ -709,7 +708,7 @@ eOSState cIptvPluginSetup::ProcessKey(eKeys Key)
case kBlue: return ShowInfo();
case kInfo: if (Current() < help.Size())
return AddSubMenu(new cMenuText(cString::sprintf("%s - %s '%s'", tr("Help"), trVDR("Plugin"), PLUGIN_NAME_I18N), help[Current()]));
default: state = osContinue;
default: state = osContinue; break;
}
}

View File

@@ -25,7 +25,7 @@ private:
eOSState EditChannel(void);
eOSState ShowInfo(void);
virtual void Setup(void);
void Setup(void);
void StoreFilters(const char *Name, int *Values);
protected:

View File

@@ -51,8 +51,9 @@ void cSidScanner::Process(u_short Pid, u_char Tid, const u_char *Data, int Lengt
if (!Channels.Lock(true, 10))
return;
cChannel *IptvChannel = Channels.GetByChannelID(channel.GetChannelID());
IptvChannel->SetId(IptvChannel->Nid(), IptvChannel->Tid(),
assoc.getServiceId(), IptvChannel->Rid());
if (IptvChannel)
IptvChannel->SetId(IptvChannel->Nid(), IptvChannel->Tid(),
assoc.getServiceId(), IptvChannel->Rid());
Channels.Unlock();
}
SetChannel(NULL);

View File

@@ -17,11 +17,13 @@ private:
protected:
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
virtual void SetStatus(bool On);
public:
cSidScanner(void);
virtual void SetStatus(bool On);
void SetChannel(const cChannel *Channel);
void Open() { SetStatus(true); }
void Close() { SetStatus(false); }
};
#endif // __SIDSCANNER_H

115
socket.c
View File

@@ -20,14 +20,9 @@
cIptvSocket::cIptvSocket()
: socketPort(0),
socketDesc(-1),
readBufferLen(TS_SIZE * IptvConfig.GetReadBufferTsCount()),
isActive(false)
{
debug("cIptvSocket::cIptvSocket()\n");
// Allocate receive buffer
readBuffer = MALLOC(unsigned char, readBufferLen);
if (!readBuffer)
error("ERROR: MALLOC() failed in socket()");
}
cIptvSocket::~cIptvSocket()
@@ -35,8 +30,6 @@ cIptvSocket::~cIptvSocket()
debug("cIptvSocket::~cIptvSocket()\n");
// Close the socket
CloseSocket();
// Free allocated memory
free(readBuffer);
}
bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
@@ -50,7 +43,7 @@ bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
}
// Bind to the socket if it is not active already
if (socketDesc < 0) {
int yes = 1;
int yes = 1;
// Create socket
if (isUdp)
socketDesc = socket(PF_INET, SOCK_DGRAM, 0);
@@ -58,10 +51,11 @@ bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
socketDesc = socket(PF_INET, SOCK_STREAM, 0);
ERROR_IF_RET(socketDesc < 0, "socket()", return false);
// Make it use non-blocking I/O to avoid stuck read calls
ERROR_IF_FUNC(fcntl(socketDesc, F_SETFL, O_NONBLOCK), "fcntl()", CloseSocket(), return false);
ERROR_IF_FUNC(fcntl(socketDesc, F_SETFL, O_NONBLOCK), "fcntl()",
CloseSocket(), return false);
// Allow multiple sockets to use the same PORT number
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(yes)) < 0, "setsockopt()", CloseSocket(), return false);
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt()",
CloseSocket(), return false);
// Bind socket
memset(&sockAddr, '\0', sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
@@ -104,7 +98,7 @@ bool cIptvUdpSocket::OpenSocket(const int Port)
return cIptvSocket::OpenSocket(Port, true);
}
int cIptvUdpSocket::Read(unsigned char* *BufferAddr)
int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
{
//debug("cIptvUdpSocket::Read()\n");
// Error out if socket not initialized
@@ -113,51 +107,40 @@ int cIptvUdpSocket::Read(unsigned char* *BufferAddr)
return -1;
}
socklen_t addrlen = sizeof(sockAddr);
// Set argument point to read buffer
*BufferAddr = readBuffer;
// Wait 500ms for data
int retval = select_single_desc(socketDesc, 500000, false);
// Check if error
if (retval < 0)
return retval;
// Check if data available
else if (retval) {
int len = 0;
// Read data from socket
if (isActive)
len = recvfrom(socketDesc, readBuffer, readBufferLen, MSG_DONTWAIT,
(struct sockaddr *)&sockAddr, &addrlen);
ERROR_IF_RET(len < 0, "recvfrom()", return len);
if ((len > 0) && (readBuffer[0] == 0x47)) {
// Set argument point to read buffer
*BufferAddr = &readBuffer[0];
return len;
int len = 0;
// Read data from socket
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
len = recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
(struct sockaddr *)&sockAddr, &addrlen);
if ((len > 0) && (BufferAddr[0] == TS_SYNC_BYTE)) {
return len;
}
else if (len > 3) {
// http://www.networksorcery.com/enp/rfc/rfc2250.txt
// version
unsigned int v = (BufferAddr[0] >> 6) & 0x03;
// extension bit
unsigned int x = (BufferAddr[0] >> 4) & 0x01;
// cscr count
unsigned int cc = BufferAddr[0] & 0x0F;
// payload type: MPEG2 TS = 33
//unsigned int pt = readBuffer[1] & 0x7F;
// header lenght
unsigned int headerlen = (3 + cc) * sizeof(uint32_t);
// check if extension
if (x) {
// extension header length
unsigned int ehl = (((BufferAddr[headerlen + 2] & 0xFF) << 8) |
(BufferAddr[headerlen + 3] & 0xFF));
// update header length
headerlen += (ehl + 1) * sizeof(uint32_t);
}
else if (len > 3) {
// http://www.networksorcery.com/enp/rfc/rfc2250.txt
// version
unsigned int v = (readBuffer[0] >> 6) & 0x03;
// extension bit
unsigned int x = (readBuffer[0] >> 4) & 0x01;
// cscr count
unsigned int cc = readBuffer[0] & 0x0F;
// payload type: MPEG2 TS = 33
//unsigned int pt = readBuffer[1] & 0x7F;
// header lenght
unsigned int headerlen = (3 + cc) * sizeof(uint32_t);
// check if extension
if (x) {
// extension header length
unsigned int ehl = (((readBuffer[headerlen + 2] & 0xFF) << 8) | (readBuffer[headerlen + 3] & 0xFF));
// update header length
headerlen += (ehl + 1) * sizeof(uint32_t);
}
// Check that rtp is version 2 and payload contains multiple of TS packet data
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) && (readBuffer[headerlen] == 0x47)) {
// Set argument point to payload in read buffer
*BufferAddr = &readBuffer[headerlen];
return (len - headerlen);
}
// Check that rtp is version 2 and payload contains multiple of TS packet data
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) &&
(BufferAddr[headerlen] == TS_SYNC_BYTE)) {
// Set argument point to payload in read buffer
memmove(BufferAddr, &BufferAddr[headerlen], (len - headerlen));
return (len - headerlen);
}
}
return 0;
@@ -180,7 +163,7 @@ bool cIptvTcpSocket::OpenSocket(const int Port)
return cIptvSocket::OpenSocket(Port, false);
}
int cIptvTcpSocket::Read(unsigned char* *BufferAddr)
int cIptvTcpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
{
//debug("cIptvTcpSocket::Read()\n");
// Error out if socket not initialized
@@ -189,19 +172,9 @@ int cIptvTcpSocket::Read(unsigned char* *BufferAddr)
return -1;
}
socklen_t addrlen = sizeof(sockAddr);
// Set argument point to read buffer
*BufferAddr = readBuffer;
// Wait 500ms for data
int retval = select_single_desc(socketDesc, 500000, false);
// Check if error
if (retval < 0)
return retval;
// Check if data available
else if (retval) {
// Read data from socket
if (isActive)
return recvfrom(socketDesc, readBuffer, readBufferLen, MSG_DONTWAIT,
(struct sockaddr *)&sockAddr, &addrlen);
}
// Read data from socket
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
return recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
(struct sockaddr *)&sockAddr, &addrlen);
return 0;
}

View File

@@ -14,8 +14,6 @@ class cIptvSocket {
protected:
int socketPort;
int socketDesc;
unsigned char* readBuffer;
unsigned int readBufferLen;
struct sockaddr_in sockAddr;
bool isActive;
@@ -32,7 +30,7 @@ class cIptvUdpSocket : public cIptvSocket {
public:
cIptvUdpSocket();
virtual ~cIptvUdpSocket();
virtual int Read(unsigned char* *BufferAddr);
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
bool OpenSocket(const int Port);
};
@@ -40,7 +38,7 @@ class cIptvTcpSocket : public cIptvSocket {
public:
cIptvTcpSocket();
virtual ~cIptvTcpSocket();
virtual int Read(unsigned char* *BufferAddr);
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
bool OpenSocket(const int Port);
};

View File

@@ -32,7 +32,7 @@ cString cIptvSectionStatistics::GetSectionStatistic()
cMutexLock MutexLock(&mutex);
uint64_t elapsed = timer.Elapsed(); /* in milliseconds */
timer.Set();
long bitrate = elapsed ? (long)((float)1000 / KILOBYTE(1) * filteredData / elapsed) : 0L;
long bitrate = elapsed ? (long)(((float)1000 / KILOBYTE(1)) * filteredData / elapsed) : 0L;
if (!IptvConfig.GetUseBytes())
bitrate *= 8;
// no trailing linefeed here!
@@ -75,7 +75,7 @@ cString cIptvPidStatistics::GetPidStatistic()
cString info("Active pids:\n");
for (unsigned int i = 0; i < IPTV_STATS_ACTIVE_PIDS_COUNT; ++i) {
if (mostActivePids[i].pid) {
long bitrate = elapsed ? (long)((float)1000 / KILOBYTE(1) * mostActivePids[i].DataAmount / elapsed) : 0L;
long bitrate = elapsed ? (long)(((float)1000 / KILOBYTE(1)) * mostActivePids[i].DataAmount / elapsed) : 0L;
if (!IptvConfig.GetUseBytes())
bitrate *= 8;
info = cString::sprintf("%sPid %d: %4d (%4ld k%s/s)\n", *info, i,
@@ -119,7 +119,7 @@ void cIptvPidStatistics::AddPidStatistic(u_short Pid, long Payload)
mostActivePids[numberOfElements - 1].pid = Pid;
mostActivePids[numberOfElements - 1].DataAmount = Payload;
// Re-sort
qsort(&mostActivePids, numberOfElements, sizeof(pidStruct), SortPids);
qsort(mostActivePids, numberOfElements, sizeof(pidStruct), SortPids);
}
}
@@ -145,7 +145,7 @@ cString cIptvStreamerStatistics::GetStreamerStatistic()
cMutexLock MutexLock(&mutex);
uint64_t elapsed = timer.Elapsed(); /* in milliseconds */
timer.Set();
long bitrate = elapsed ? (long)((float)1000 / KILOBYTE(1) * dataBytes / elapsed) : 0L;
long bitrate = elapsed ? (long)(((float)1000 / KILOBYTE(1)) * dataBytes / elapsed) : 0L;
if (!IptvConfig.GetUseBytes())
bitrate *= 8;
cString info = cString::sprintf("Stream bitrate: %ld k%s/s\n", bitrate, IptvConfig.GetUseBytes() ? "B" : "bit");
@@ -182,7 +182,7 @@ cString cIptvBufferStatistics::GetBufferStatistic()
cMutexLock MutexLock(&mutex);
uint64_t elapsed = timer.Elapsed(); /* in milliseconds */
timer.Set();
long bitrate = elapsed ? (long)((float)1000 / KILOBYTE(1) * dataBytes / elapsed) : 0L;
long bitrate = elapsed ? (long)(((float)1000 / KILOBYTE(1)) * dataBytes / elapsed) : 0L;
long totalSpace = MEGABYTE(IptvConfig.GetTsBufferSize());
float percentage = (float)((float)usedSpace / (float)totalSpace * 100.0);
long totalKilos = totalSpace / KILOBYTE(1);

View File

@@ -11,13 +11,19 @@
#include "common.h"
#include "streamer.h"
cIptvStreamer::cIptvStreamer(cRingBufferLinear* RingBuffer, cMutex* Mutex)
cIptvStreamer::cIptvStreamer(cRingBufferLinear* RingBuffer, unsigned int PacketLen)
: cThread("IPTV streamer"),
ringBuffer(RingBuffer),
mutex(Mutex),
packetBufferLen(PacketLen),
protocol(NULL)
{
debug("cIptvStreamer::cIptvStreamer()\n");
debug("cIptvStreamer::cIptvStreamer(%d)\n", packetBufferLen);
// Allocate packet buffer
packetBuffer = MALLOC(unsigned char, packetBufferLen);
if (packetBuffer)
memset(packetBuffer, 0, packetBufferLen);
else
error("ERROR: MALLOC() failed for packet buffer");
}
cIptvStreamer::~cIptvStreamer()
@@ -25,32 +31,33 @@ cIptvStreamer::~cIptvStreamer()
debug("cIptvStreamer::~cIptvStreamer()\n");
// Close the protocol
Close();
protocol = NULL;
ringBuffer = NULL;
// Free allocated memory
free(packetBuffer);
}
void cIptvStreamer::Action(void)
{
debug("cIptvStreamer::Action(): Entering\n");
// Increase priority
//SetPriority(-1);
// Do the thread loop
while (Running()) {
if (ringBuffer && mutex && protocol && ringBuffer->Free()) {
unsigned char *buffer = NULL;
mutex->Lock();
int length = protocol->Read(&buffer);
if (length >= 0) {
AddStreamerStatistic(length);
int p = ringBuffer->Put(buffer, length);
if (p != length && Running())
ringBuffer->ReportOverflow(length - p);
mutex->Unlock();
}
else {
mutex->Unlock();
sleep.Wait(100); // to reduce cpu load
}
}
else
sleep.Wait(100); // and avoid busy loop
}
while (packetBuffer && Running()) {
int length = -1;
if (protocol)
length = protocol->Read(packetBuffer, packetBufferLen);
if (length > 0) {
AddStreamerStatistic(length);
if (ringBuffer) {
int p = ringBuffer->Put(packetBuffer, length);
if (p != length)
ringBuffer->ReportOverflow(length - p);
}
}
else
sleep.Wait(10); // to avoid busy loop and reduce cpu load
}
debug("cIptvStreamer::Action(): Exiting\n");
}
@@ -72,15 +79,9 @@ bool cIptvStreamer::Close(void)
sleep.Signal();
if (Running())
Cancel(3);
// Close the protocol. A mutex should be taken here to avoid a race condition
// where thread Action() may be in the process of accessing the protocol.
// Taking a mutex serializes the Close() and Action() -calls.
if (mutex)
mutex->Lock();
// Close the protocol
if (protocol)
protocol->Close();
if (mutex)
mutex->Unlock();
return true;
}
@@ -88,16 +89,17 @@ bool cIptvStreamer::Set(const char* Location, const int Parameter, const int Ind
{
debug("cIptvStreamer::Set(): %s:%d\n", Location, Parameter);
if (!isempty(Location)) {
// Update protocol; Close the existing one if changed
// Update protocol and set location and parameter; Close the existing one if changed
if (protocol != Protocol) {
if (protocol)
protocol->Close();
protocol = Protocol;
if (protocol)
if (protocol) {
protocol->Set(Location, Parameter, Index);
protocol->Open();
}
}
// Set protocol location and parameter
if (protocol)
else if (protocol)
protocol->Set(Location, Parameter, Index);
}
return true;

View File

@@ -19,16 +19,17 @@
class cIptvStreamer : public cThread, public cIptvStreamerStatistics {
private:
cRingBufferLinear* ringBuffer;
cMutex* mutex;
cCondWait sleep;
unsigned char* readBuffer;
unsigned int readBufferLen;
unsigned char* packetBuffer;
unsigned int packetBufferLen;
cIptvProtocolIf* protocol;
public:
cIptvStreamer(cRingBufferLinear* RingBuffer, cMutex* Mutex);
virtual ~cIptvStreamer();
protected:
virtual void Action(void);
public:
cIptvStreamer(cRingBufferLinear* RingBuffer, unsigned int PacketLen);
virtual ~cIptvStreamer();
bool Set(const char* Location, const int Parameter, const int Index, cIptvProtocolIf* Protocol);
bool Open(void);
bool Close(void);