diff --git a/README b/README index 25339d8..b247375 100644 --- a/README +++ b/README @@ -159,6 +159,19 @@ Notes: from their webpage: http://www.inverto.tv/support/ An update to a newer firmware should be offered afterwards. +- If you are experiencing glitches in the video stream, one possible + reason can be buffer overflows in RTP receive sockets. You can verify + this by checking "receive buffer errors" counter by running "netstat -s" + command. If the counter increases every time a video glitch happens, + you should try to tweak the RTP receive buffer size with the "--rcvbuf" + (-r) plugin parameter. + A good starting point for the buffer size is to double the operating + system default value until errors disappear or the maximum value is + reached. You can check these values in Linux by checking the kernel + parameters: + $ cat /proc/sys/net/core/rmem_default + $ cat /proc/sys/net/core/rmem_max + Acknowledgements: - Big thanks to Digital Devices GmbH for providing the Octopus Net diff --git a/config.c b/config.c index 6743e9c..05dc44e 100644 --- a/config.c +++ b/config.c @@ -22,7 +22,8 @@ cSatipConfig::cSatipConfig(void) transportModeM(eTransportModeUnicast), detachedModeM(false), disableServerQuirksM(false), - useSingleModelServersM(false) + useSingleModelServersM(false), + rtpRcvBufSizeM(0) { for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i) cicamsM[i] = 0; diff --git a/config.h b/config.h index 45503f6..394fc8a 100644 --- a/config.h +++ b/config.h @@ -28,6 +28,7 @@ private: int cicamsM[MAX_CICAM_COUNT]; int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT]; int disabledFiltersM[SECTION_FILTER_TABLE_SIZE]; + size_t rtpRcvBufSizeM; public: enum eOperatingMode { @@ -89,6 +90,7 @@ public: int GetDisabledFilters(unsigned int indexP) const; unsigned int GetPortRangeStart(void) const { return portRangeStartM; } unsigned int GetPortRangeStop(void) const { return portRangeStopM; } + size_t GetRtpRcvBufSize(void) const { return rtpRcvBufSizeM; } void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; } void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); } @@ -104,6 +106,7 @@ public: void SetDisabledFilters(unsigned int indexP, int numberP); void SetPortRangeStart(unsigned int rangeStartP) { portRangeStartM = rangeStartP; } void SetPortRangeStop(unsigned int rangeStopP) { portRangeStopM = rangeStopP; } + void SetRtpRcvBufSize(size_t sizeP) { rtpRcvBufSizeM = sizeP; } }; extern cSatipConfig SatipConfig; diff --git a/rtp.c b/rtp.c index 2d015bb..71b7f2d 100644 --- a/rtp.c +++ b/rtp.c @@ -14,7 +14,8 @@ #include "rtp.h" cSatipRtp::cSatipRtp(cSatipTunerIf &tunerP) -: tunerM(tunerP), +: cSatipSocket(SatipConfig.GetRtpRcvBufSize()), + tunerM(tunerP), bufferLenM(eRtpPacketReadCount * eMaxUdpPacketSizeB), bufferM(MALLOC(unsigned char, bufferLenM)), lastErrorReportM(0), diff --git a/satip.c b/satip.c index 5358337..797e5f2 100644 --- a/satip.c +++ b/satip.c @@ -91,7 +91,8 @@ const char *cPluginSatip::CommandLineHelp(void) " -S, --single set the single model server mode on\n" " -n, --noquirks disable autodetection of the server quirks\n" " -p, --portrange=- set a range of ports used for the RT[C]P server\n" - " a minimum of 2 ports per device is required.\n"; + " a minimum of 2 ports per device is required.\n" + " -r, --rcvbuf override the size of the RTP receive buffer in bytes\n"; } bool cPluginSatip::ProcessArgs(int argc, char *argv[]) @@ -103,6 +104,7 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[]) { "trace", required_argument, NULL, 't' }, { "server", required_argument, NULL, 's' }, { "portrange",required_argument, NULL, 'p' }, + { "rcvbuf", required_argument, NULL, 'r' }, { "detach", no_argument, NULL, 'D' }, { "single", no_argument, NULL, 'S' }, { "noquirks", no_argument, NULL, 'n' }, @@ -112,7 +114,7 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[]) cString server; cString portrange; int c; - while ((c = getopt_long(argc, argv, "d:t:s:p:DSn", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "d:t:s:p:r:DSn", long_options, NULL)) != -1) { switch (c) { case 'd': deviceCountM = strtol(optarg, NULL, 0); @@ -135,6 +137,9 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[]) case 'p': portrange = optarg; break; + case 'r': + SatipConfig.SetRtpRcvBufSize(strtol(optarg, NULL, 0)); + break; default: return false; } diff --git a/socket.c b/socket.c index c3baa71..7ea436b 100644 --- a/socket.c +++ b/socket.c @@ -28,12 +28,18 @@ #endif cSatipSocket::cSatipSocket() +: cSatipSocket(0) +{ +} + +cSatipSocket::cSatipSocket(size_t rcvBufSizeP) : socketPortM(0), socketDescM(-1), isMulticastM(false), useSsmM(false), streamAddrM(htonl(INADDR_ANY)), - sourceAddrM(htonl(INADDR_ANY)) + sourceAddrM(htonl(INADDR_ANY)), + rcvBufSizeM(rcvBufSizeP) { debug1("%s", __PRETTY_FUNCTION__); memset(&sockAddrM, 0, sizeof(sockAddrM)); @@ -78,6 +84,11 @@ bool cSatipSocket::Open(const int portP, const bool reuseP) ERROR_IF_FUNC(setsockopt(socketDescM, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0, "setsockopt(IP_PKTINFO)", Close(), return false); #endif // __FreeBSD__ + // Tweak receive buffer size if requested + if (rcvBufSizeM > 0) { + ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_RCVBUF, &rcvBufSizeM, sizeof(rcvBufSizeM)) < 0, + "setsockopt(SO_RCVBUF)", Close(), return false); + } // Bind socket memset(&sockAddrM, 0, sizeof(sockAddrM)); sockAddrM.sin_family = AF_INET; diff --git a/socket.h b/socket.h index 12d1ac4..cd4b75d 100644 --- a/socket.h +++ b/socket.h @@ -19,12 +19,14 @@ private: bool useSsmM; in_addr_t streamAddrM; in_addr_t sourceAddrM; + size_t rcvBufSizeM; bool CheckAddress(const char *addrP, in_addr_t *inAddrP); bool Join(void); bool Leave(void); public: cSatipSocket(); + cSatipSocket(size_t rcvBufSizeP); virtual ~cSatipSocket(); bool Open(const int portP = 0, const bool reuseP = false); bool OpenMulticast(const int portP, const char *streamAddrP, const char *sourceAddrP);