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 | Date | |
|---|---|---|---|
| 
						 | 
					dc64c044a1 | ||
| 
						 | 
					3dcbff0a71 | ||
| 
						 | 
					5aefd40d65 | ||
| 
						 | 
					6b0337d078 | ||
| 
						 | 
					9e6d784aec | ||
| 
						 | 
					3f3ba2ad1a | ||
| 
						 | 
					a4b9570ae6 | ||
| 
						 | 
					767b1bdac7 | ||
| 
						 | 
					6f648401a4 | ||
| 
						 | 
					b0995c9a9e | ||
| 
						 | 
					412af81271 | ||
| 
						 | 
					43326bb4ea | ||
| 
						 | 
					555c08bd4d | ||
| 
						 | 
					5ad3103626 | ||
| 
						 | 
					a4f0bdf737 | ||
| 
						 | 
					01b554a2de | ||
| 
						 | 
					225b0cc297 | ||
| 
						 | 
					d940e616e3 | ||
| 
						 | 
					f30817677e | ||
| 
						 | 
					0c6257e4ca | ||
| 
						 | 
					0caf746ef4 | 
							
								
								
									
										30
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								HISTORY
									
									
									
									
									
								
							@@ -199,3 +199,33 @@ VDR Plugin 'iptv' Revision History
 | 
			
		||||
- Fixed bugs found in the CURL implementation (Thanks
 | 
			
		||||
  to Jeremy Hall).
 | 
			
		||||
- Fixed the channel editor.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
==================================
 | 
			
		||||
VDR Plugin 'iptv' Revision History
 | 
			
		||||
==================================
 | 
			
		||||
 | 
			
		||||
2013-04-01: Version 2.0.0
 | 
			
		||||
 | 
			
		||||
- Updated for vdr-2.0.0.
 | 
			
		||||
- Enabled I/O throttling and tweaked buffer timeouts.
 | 
			
		||||
- Fixed a nasty network byte order bug.
 | 
			
		||||
- Fixed and refactored the section filtering code.
 | 
			
		||||
- Fixed a possible crash in the file protocol.
 | 
			
		||||
 | 
			
		||||
2014-01-10: Version 2.0.1
 | 
			
		||||
 | 
			
		||||
- Added missing CURL timeouts.
 | 
			
		||||
- Improved section id scanner.
 | 
			
		||||
- Added support for cDevice::IsTunedToTransponder() and
 | 
			
		||||
  cDevice::GetCurrentlyTunedTransponder().
 | 
			
		||||
- Fixed a memory leak and some issues reported by scan-build.
 | 
			
		||||
 | 
			
		||||
2014-01-18: Version 2.0.2
 | 
			
		||||
 | 
			
		||||
- Made devices to shutdown already in cPluginManager::Stop()
 | 
			
		||||
  to prevent possible crashes while VDR shutdown.
 | 
			
		||||
 | 
			
		||||
2014-03-09: Version 2.0.3
 | 
			
		||||
 | 
			
		||||
- Fixed installation target bugs (Thanks to Alexander Grothe).
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
									
									
									
									
								
							@@ -28,10 +28,12 @@ GITTAG  = $(shell git describe --always 2>/dev/null)
 | 
			
		||||
### The directory environment:
 | 
			
		||||
 | 
			
		||||
# Use package data if installed...otherwise assume we're under the VDR source directory:
 | 
			
		||||
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
 | 
			
		||||
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." pkg-config --variable=$(1) vdr))
 | 
			
		||||
LIBDIR = $(call PKGCFG,libdir)
 | 
			
		||||
LOCDIR = $(call PKGCFG,locdir)
 | 
			
		||||
PLGCFG = $(call PKGCFG,plgcfg)
 | 
			
		||||
RESDIR = $(call PKGCFG,resdir)
 | 
			
		||||
CFGDIR = $(call PKGCFG,configdir)
 | 
			
		||||
#
 | 
			
		||||
TMPDIR ?= /tmp
 | 
			
		||||
 | 
			
		||||
@@ -144,7 +146,12 @@ endif
 | 
			
		||||
install-lib: $(SOFILE)
 | 
			
		||||
	install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
 | 
			
		||||
 | 
			
		||||
install: install-lib install-i18n
 | 
			
		||||
install-conf:
 | 
			
		||||
	@mkdir -p $(DESTDIR)$(CFGDIR)/plugins/$(PLUGIN)
 | 
			
		||||
	@mkdir -p $(DESTDIR)$(RESDIR)/plugins/$(PLUGIN)
 | 
			
		||||
	@cp -pn $(PLUGIN)/* $(DESTDIR)$(RESDIR)/plugins/$(PLUGIN)/
 | 
			
		||||
 | 
			
		||||
install: install-lib install-i18n install-conf
 | 
			
		||||
 | 
			
		||||
dist: $(I18Npo) clean
 | 
			
		||||
	@-rm -rf $(TMPDIR)/$(ARCHIVE)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								README
									
									
									
									
									
								
							@@ -41,14 +41,8 @@ MP3 radio streams, mms video streams and so on.
 | 
			
		||||
 | 
			
		||||
Installation:
 | 
			
		||||
 | 
			
		||||
cd /put/your/path/here/VDR/PLUGINS/src
 | 
			
		||||
tar -xzf /put/your/path/here/vdr-iptv-X.Y.Z.tgz
 | 
			
		||||
ln -s iptv-X.Y.Z iptv
 | 
			
		||||
cd /put/your/path/here/VDR
 | 
			
		||||
cp -R PLUGINS/src/iptv/iptv /path/to/vdrresource/plugins/
 | 
			
		||||
make
 | 
			
		||||
make plugins
 | 
			
		||||
./vdr -P iptv
 | 
			
		||||
make -C iptv-X.Y.Z install
 | 
			
		||||
 | 
			
		||||
Setup menu:
 | 
			
		||||
 | 
			
		||||
@@ -89,11 +83,11 @@ Configuration:
 | 
			
		||||
 | 
			
		||||
- channels.conf
 | 
			
		||||
 | 
			
		||||
  TV4;IPTV:60:S=1|P=0|F=EXT|U=iptvstream.sh|A=0:I:0:0:680:0:0:6:0:0:0
 | 
			
		||||
  TV3;IPTV:50:S=0|P=1|F=FILE|U=/video/stream.ts|A=5:I:0:514:670:2321:0:5:0:0:0
 | 
			
		||||
  TV2;IPTV:40:S=0|P=1|F=HTTP|U=127.0.0.1/TS/2|A=3000:I:0:513:660:2321:0:4:0:0:0
 | 
			
		||||
  TV1;IPTV:30:S=1|P=0|F=CURL|U=http%3A//foo%3Abar@127.0.0.1%3A3000/TS/2|A=0:I:0:512:650:2321:0:3:0:0:0
 | 
			
		||||
  TV1;IPTV:20:S=1|P=0|F=UDP|U=127.0.0.1@127.0.0.1|A=1234:I:0:512:650:2321:0:2:0:0:0
 | 
			
		||||
  TV6;IPTV:60:S=1|P=0|F=EXT|U=iptvstream.sh|A=0:I:0:0:680:0:0:6:0:0:0
 | 
			
		||||
  TV5;IPTV:50:S=0|P=1|F=FILE|U=/video/stream.ts|A=5:I:0:514:670:2321:0:5:0:0:0
 | 
			
		||||
  TV4;IPTV:40:S=0|P=1|F=HTTP|U=127.0.0.1/TS/2|A=3000:I:0:513:660:2321:0:4:0:0:0
 | 
			
		||||
  TV3;IPTV:30:S=1|P=0|F=CURL|U=http%3A//foo%3Abar@127.0.0.1%3A3000/TS/2|A=0:I:0:512:650:2321:0:3:0:0:0
 | 
			
		||||
  TV2;IPTV:20:S=1|P=0|F=UDP|U=127.0.0.1@127.0.0.1|A=1234:I:0:512:650:2321:0:2:0:0:0
 | 
			
		||||
  TV1;IPTV:10:S=1|P=0|F=UDP|U=127.0.0.1|A=1234:I:0:512:650:2321:0:1:0:0:0
 | 
			
		||||
           ^  ^   ^   ^     ^           ^      ^
 | 
			
		||||
           |  |   |   |     |           |      Source type ("I")
 | 
			
		||||
@@ -171,8 +165,7 @@ Notes:
 | 
			
		||||
  "disable_ca_updates" patch to the VDR in order to get rid of "Channel not
 | 
			
		||||
  available" messages.
 | 
			
		||||
 | 
			
		||||
- EIT scanning functionality can be disabled for all IPTV channels by applying
 | 
			
		||||
  the "disable_eitscan" patch to the VDR.
 | 
			
		||||
- 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.
 | 
			
		||||
@@ -186,7 +179,12 @@ Notes:
 | 
			
		||||
  netrc configuration file for authentication:
 | 
			
		||||
  $(CONFDIR)/iptv/netrc
 | 
			
		||||
 | 
			
		||||
- CURL implementation
 | 
			
		||||
- 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.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								common.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								common.h
									
									
									
									
									
								
							@@ -44,7 +44,8 @@
 | 
			
		||||
  do {                                                            \
 | 
			
		||||
     if (exp) {                                                   \
 | 
			
		||||
        char tmp[64];                                             \
 | 
			
		||||
        error(errstr": %s", strerror_r(errno, tmp, sizeof(tmp))); \
 | 
			
		||||
        error("[%s,%d]: "errstr": %s", __FILE__, __LINE__,        \
 | 
			
		||||
              strerror_r(errno, tmp, sizeof(tmp)));               \
 | 
			
		||||
        func;                                                     \
 | 
			
		||||
        ret;                                                      \
 | 
			
		||||
        }                                                         \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								config.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								config.c
									
									
									
									
									
								
							@@ -19,6 +19,7 @@ cIptvConfig::cIptvConfig(void)
 | 
			
		||||
  for (unsigned int i = 0; i < ARRAY_SIZE(disabledFiltersM); ++i)
 | 
			
		||||
      disabledFiltersM[i] = -1;
 | 
			
		||||
  memset(configDirectoryM, 0, sizeof(configDirectoryM));
 | 
			
		||||
  memset(resourceDirectoryM, 0, sizeof(resourceDirectoryM));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int cIptvConfig::GetDisabledFiltersCount(void) const
 | 
			
		||||
@@ -45,3 +46,9 @@ void cIptvConfig::SetConfigDirectory(const char *directoryP)
 | 
			
		||||
  debug("cIptvConfig::%s(%s)", __FUNCTION__, directoryP);
 | 
			
		||||
  ERROR_IF(!realpath(directoryP, configDirectoryM), "Cannot canonicalize configuration directory");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cIptvConfig::SetResourceDirectory(const char *directoryP)
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvConfig::%s(%s)", __FUNCTION__, directoryP);
 | 
			
		||||
  ERROR_IF(!realpath(directoryP, resourceDirectoryM), "Cannot canonicalize resource directory");
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								config.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								config.h
									
									
									
									
									
								
							@@ -21,6 +21,7 @@ private:
 | 
			
		||||
  unsigned int sectionFilteringM;
 | 
			
		||||
  int disabledFiltersM[SECTION_FILTER_TABLE_SIZE];
 | 
			
		||||
  char configDirectoryM[PATH_MAX];
 | 
			
		||||
  char resourceDirectoryM[PATH_MAX];
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cIptvConfig();
 | 
			
		||||
@@ -30,6 +31,7 @@ public:
 | 
			
		||||
  unsigned int GetUseBytes(void) const { return useBytesM; }
 | 
			
		||||
  unsigned int GetSectionFiltering(void) const { return sectionFilteringM; }
 | 
			
		||||
  const char *GetConfigDirectory(void) const { return configDirectoryM; }
 | 
			
		||||
  const char *GetResourceDirectory(void) const { return resourceDirectoryM; }
 | 
			
		||||
  unsigned int GetDisabledFiltersCount(void) const;
 | 
			
		||||
  int GetDisabledFilters(unsigned int indexP) const;
 | 
			
		||||
  void SetTsBufferSize(unsigned int sizeP) { tsBufferSizeM = sizeP; }
 | 
			
		||||
@@ -39,6 +41,7 @@ public:
 | 
			
		||||
  void SetSectionFiltering(unsigned int onOffP) { sectionFilteringM = onOffP; }
 | 
			
		||||
  void SetDisabledFilters(unsigned int indexP, int numberP);
 | 
			
		||||
  void SetConfigDirectory(const char *directoryP);
 | 
			
		||||
  void SetResourceDirectory(const char *directoryP);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern cIptvConfig IptvConfig;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										210
									
								
								device.c
									
									
									
									
									
								
							
							
						
						
									
										210
									
								
								device.c
									
									
									
									
									
								
							@@ -20,25 +20,27 @@ cIptvDevice::cIptvDevice(unsigned int indexP)
 | 
			
		||||
  isOpenDvrM(false),
 | 
			
		||||
  sidScanEnabledM(false),
 | 
			
		||||
  pidScanEnabledM(false),
 | 
			
		||||
  channelIdM(tChannelID::InvalidID)
 | 
			
		||||
  channelM()
 | 
			
		||||
{
 | 
			
		||||
  unsigned int bufsize = (unsigned int)MEGABYTE(IptvConfig.GetTsBufferSize());
 | 
			
		||||
  bufsize -= (bufsize % TS_SIZE);
 | 
			
		||||
  isyslog("creating IPTV device %d (CardIndex=%d)", deviceIndexM, CardIndex());
 | 
			
		||||
  tsBufferM = new cRingBufferLinear(bufsize + 1, TS_SIZE, false,
 | 
			
		||||
                                   *cString::sprintf("IPTV %d", deviceIndexM));
 | 
			
		||||
  tsBufferM->SetTimeouts(10, 10);
 | 
			
		||||
                                   *cString::sprintf("IPTV TS %d", deviceIndexM));
 | 
			
		||||
  if (tsBufferM) {
 | 
			
		||||
     tsBufferM->SetTimeouts(100, 100);
 | 
			
		||||
     tsBufferM->SetIoThrottle();
 | 
			
		||||
     pIptvStreamerM = new cIptvStreamer(*this, tsBufferM->Free());
 | 
			
		||||
     }
 | 
			
		||||
  ResetBuffering();
 | 
			
		||||
  pUdpProtocolM = new cIptvProtocolUdp();
 | 
			
		||||
  pCurlProtocolM = new cIptvProtocolCurl();
 | 
			
		||||
  pHttpProtocolM = new cIptvProtocolHttp();
 | 
			
		||||
  pFileProtocolM = new cIptvProtocolFile();
 | 
			
		||||
  pExtProtocolM = new cIptvProtocolExt();
 | 
			
		||||
  pIptvStreamerM = new cIptvStreamer(tsBufferM, (100 * TS_SIZE));
 | 
			
		||||
  pPidScannerM = new cPidScanner();
 | 
			
		||||
  // Initialize filter pointers
 | 
			
		||||
  memset(secFiltersM, 0, sizeof(secFiltersM));
 | 
			
		||||
  // Start section handler for iptv device
 | 
			
		||||
  pIptvSectionM = new cIptvSectionFilterHandler(deviceIndexM, bufsize + 1);
 | 
			
		||||
  StartSectionHandler();
 | 
			
		||||
  // Sid scanner must be created after the section handler
 | 
			
		||||
  AttachFilter(pSidScannerM = new cSidScanner());
 | 
			
		||||
@@ -56,21 +58,18 @@ cIptvDevice::cIptvDevice(unsigned int indexP)
 | 
			
		||||
cIptvDevice::~cIptvDevice()
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  DELETE_POINTER(pIptvStreamerM);
 | 
			
		||||
  DELETE_POINTER(pUdpProtocolM);
 | 
			
		||||
  DELETE_POINTER(pCurlProtocolM);
 | 
			
		||||
  DELETE_POINTER(pHttpProtocolM);
 | 
			
		||||
  DELETE_POINTER(pFileProtocolM);
 | 
			
		||||
  DELETE_POINTER(pExtProtocolM);
 | 
			
		||||
  DELETE_POINTER(tsBufferM);
 | 
			
		||||
  DELETE_POINTER(pPidScannerM);
 | 
			
		||||
  DELETE_POINTER(pSidScannerM);
 | 
			
		||||
  // Stop section handler of iptv device
 | 
			
		||||
  StopSectionHandler();
 | 
			
		||||
  // Destroy all filters
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  for (int i = 0; i < eMaxSecFilterCount; ++i)
 | 
			
		||||
      DeleteFilter(i);
 | 
			
		||||
  DELETE_POINTER(pIptvSectionM);
 | 
			
		||||
  DELETE_POINTER(pSidScannerM);
 | 
			
		||||
  DELETE_POINTER(pPidScannerM);
 | 
			
		||||
  DELETE_POINTER(pIptvStreamerM);
 | 
			
		||||
  DELETE_POINTER(pExtProtocolM);
 | 
			
		||||
  DELETE_POINTER(pFileProtocolM);
 | 
			
		||||
  DELETE_POINTER(pHttpProtocolM);
 | 
			
		||||
  DELETE_POINTER(pCurlProtocolM);
 | 
			
		||||
  DELETE_POINTER(pUdpProtocolM);
 | 
			
		||||
  DELETE_POINTER(tsBufferM);
 | 
			
		||||
  // Close dvr fifo
 | 
			
		||||
  if (dvrFdM >= 0) {
 | 
			
		||||
     int fd = dvrFdM;
 | 
			
		||||
@@ -92,6 +91,15 @@ bool cIptvDevice::Initialize(unsigned int deviceCountP)
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cIptvDevice::Shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvDevice::%s()", __FUNCTION__);
 | 
			
		||||
  for (int i = 0; i < IPTV_MAX_DEVICES; ++i) {
 | 
			
		||||
      if (IptvDevicesS[i])
 | 
			
		||||
         IptvDevicesS[i]->CloseDvr();
 | 
			
		||||
      }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int cIptvDevice::Count(void)
 | 
			
		||||
{
 | 
			
		||||
  unsigned int count = 0;
 | 
			
		||||
@@ -107,7 +115,7 @@ cIptvDevice *cIptvDevice::GetIptvDevice(int cardIndexP)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvDevice::%s(%d)", __FUNCTION__, cardIndexP);
 | 
			
		||||
  for (unsigned int i = 0; i < IPTV_MAX_DEVICES; ++i) {
 | 
			
		||||
      if ((IptvDevicesS[i] != NULL) && (IptvDevicesS[i]->CardIndex() == cardIndexP)) {
 | 
			
		||||
      if (IptvDevicesS[i] && (IptvDevicesS[i]->CardIndex() == cardIndexP)) {
 | 
			
		||||
         //debug("cIptvDevice::%s(%d): found!", __FUNCTION__, cardIndexP);
 | 
			
		||||
         return IptvDevicesS[i];
 | 
			
		||||
         }
 | 
			
		||||
@@ -135,20 +143,7 @@ cString cIptvDevice::GetPidsInformation(void)
 | 
			
		||||
cString cIptvDevice::GetFiltersInformation(void)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  unsigned int count = 0;
 | 
			
		||||
  cString s("Active section filters:\n");
 | 
			
		||||
  // loop through active section filters
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
			
		||||
      if (secFiltersM[i]) {
 | 
			
		||||
         s = cString::sprintf("%sFilter %d: %s Pid=0x%02X (%s)\n", *s, i,
 | 
			
		||||
                              *secFiltersM[i]->GetSectionStatistic(), secFiltersM[i]->GetPid(),
 | 
			
		||||
                              id_pid(secFiltersM[i]->GetPid()));
 | 
			
		||||
         if (++count > IPTV_STATS_ACTIVE_FILTERS_COUNT)
 | 
			
		||||
            break;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  return s;
 | 
			
		||||
  return cString::sprintf("Active section filters:\n%s", pIptvSectionM ? *pIptvSectionM->GetInformation() : "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cString cIptvDevice::GetInformation(unsigned int pageP)
 | 
			
		||||
@@ -183,7 +178,7 @@ cString cIptvDevice::GetInformation(unsigned int pageP)
 | 
			
		||||
 | 
			
		||||
cString cIptvDevice::DeviceType(void) const
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  //debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  return "IPTV";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -228,7 +223,7 @@ bool cIptvDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
 | 
			
		||||
  if (channelP && ProvidesTransponder(channelP)) {
 | 
			
		||||
     result = hasPriority;
 | 
			
		||||
     if (Receiving()) {
 | 
			
		||||
        if (channelP->GetChannelID() == channelIdM)
 | 
			
		||||
        if (channelP->GetChannelID() == channelM.GetChannelID())
 | 
			
		||||
           result = true;
 | 
			
		||||
        else
 | 
			
		||||
           needsDetachReceivers = Receiving();
 | 
			
		||||
@@ -249,6 +244,21 @@ int cIptvDevice::NumProvidedSystems(void) const
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const cChannel *cIptvDevice::GetCurrentlyTunedTransponder(void) const
 | 
			
		||||
{
 | 
			
		||||
  return &channelM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvDevice::IsTunedToTransponder(const cChannel *channelP) const
 | 
			
		||||
{
 | 
			
		||||
  return channelP ? (channelP->GetChannelID() == channelM.GetChannelID()) : false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvDevice::MaySwitchTransponder(const cChannel *channelP) const
 | 
			
		||||
{
 | 
			
		||||
  return cDevice::MaySwitchTransponder(channelP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
 | 
			
		||||
{
 | 
			
		||||
  cIptvProtocolIf *protocol;
 | 
			
		||||
@@ -284,11 +294,11 @@ bool cIptvDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
 | 
			
		||||
  sidScanEnabledM = itp.SidScan() ? true : false;
 | 
			
		||||
  pidScanEnabledM = itp.PidScan() ? true : false;
 | 
			
		||||
  if (pIptvStreamerM->Set(itp.Address(), itp.Parameter(), deviceIndexM, protocol)) {
 | 
			
		||||
     channelIdM = channelP->GetChannelID();
 | 
			
		||||
     channelM = *channelP;
 | 
			
		||||
     if (sidScanEnabledM && pSidScannerM && IptvConfig.GetSectionFiltering())
 | 
			
		||||
        pSidScannerM->SetChannel(channelIdM);
 | 
			
		||||
        pSidScannerM->SetChannel(channelM.GetChannelID());
 | 
			
		||||
     if (pidScanEnabledM && pPidScannerM)
 | 
			
		||||
        pPidScannerM->SetChannel(channelIdM);
 | 
			
		||||
        pPidScannerM->SetChannel(channelM.GetChannelID());
 | 
			
		||||
     }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
@@ -299,80 +309,19 @@ bool cIptvDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvDevice::DeleteFilter(unsigned int indexP)
 | 
			
		||||
{
 | 
			
		||||
  if ((indexP < eMaxSecFilterCount) && secFiltersM[indexP]) {
 | 
			
		||||
     //debug("cIptvDevice::%s(%d): index=%d", __FUNCTION__, deviceIndexM, indexP);
 | 
			
		||||
     cIptvSectionFilter *tmp = secFiltersM[indexP];
 | 
			
		||||
     secFiltersM[indexP] = NULL;
 | 
			
		||||
     delete tmp;
 | 
			
		||||
     return true;
 | 
			
		||||
     }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvDevice::IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvDevice::%s(%d): pid=%d tid=%02X mask=%02X", __FUNCTION__, deviceIndexM, pidP, tidP, maskP);
 | 
			
		||||
  // loop through section filter table
 | 
			
		||||
  for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
 | 
			
		||||
      int index = IptvConfig.GetDisabledFilters(i);
 | 
			
		||||
      // Check if matches
 | 
			
		||||
      if ((index >= 0) && (index < SECTION_FILTER_TABLE_SIZE) &&
 | 
			
		||||
          (section_filter_table[index].pid == pidP) && (section_filter_table[index].tid == tidP) &&
 | 
			
		||||
          (section_filter_table[index].mask == maskP)) {
 | 
			
		||||
         //debug("cIptvDevice::%s(%d): found %s", __FUNCTION__, deviceIndexM, section_filter_table[index].description);
 | 
			
		||||
         return true;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cIptvDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
 | 
			
		||||
{
 | 
			
		||||
  // Check if disabled by user
 | 
			
		||||
  if (!IptvConfig.GetSectionFiltering())
 | 
			
		||||
     return -1;
 | 
			
		||||
  // Lock
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  // Blacklist check, refuse certain filters
 | 
			
		||||
  if (IsBlackListed(pidP, tidP, maskP))
 | 
			
		||||
     return -1;
 | 
			
		||||
  // Search the next free filter slot
 | 
			
		||||
  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
			
		||||
      if (!secFiltersM[i]) {
 | 
			
		||||
         //debug("cIptvDevice::%s(%d): pid=%d tid=%02X mask=%02X index=%d", __FUNCTION__, deviceIndexM, pidP, tidP, maskP, i);
 | 
			
		||||
         secFiltersM[i] = new cIptvSectionFilter(deviceIndexM, pidP, tidP, maskP);
 | 
			
		||||
         if (secFiltersM[i])
 | 
			
		||||
            return i;
 | 
			
		||||
         break;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  // No free filter slot found
 | 
			
		||||
  //debug("cIptvDevice::%s(%d): pid=%d tid=%d mask=%d", __FUNCTION__, deviceIndexM, pidP, tidP,  maskP);
 | 
			
		||||
  if (pIptvSectionM && IptvConfig.GetSectionFiltering())
 | 
			
		||||
     return pIptvSectionM->Open(pidP, tidP, maskP);
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cIptvDevice::ReadFilter(int handleP, void *bufferP, size_t lengthP)
 | 
			
		||||
{
 | 
			
		||||
  // Lock
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  // ... and load
 | 
			
		||||
  if (secFiltersM[handleP]) {
 | 
			
		||||
     return secFiltersM[handleP]->Read(bufferP, lengthP);
 | 
			
		||||
     //debug("cIptvDevice::%s(%d): handle=%d length=%d", __FUNCTION__, deviceIndexM, handleP, lengthP);
 | 
			
		||||
     }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cIptvDevice::CloseFilter(int handleP)
 | 
			
		||||
{
 | 
			
		||||
  // Lock
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  // ... and load
 | 
			
		||||
  if (secFiltersM[handleP]) {
 | 
			
		||||
     //debug("cIptvDevice::%s(%d): handle=%d", __FUNCTION__, deviceIndexM, handleP);
 | 
			
		||||
     DeleteFilter(handleP);
 | 
			
		||||
     }
 | 
			
		||||
  //debug("cIptvDevice::%s(%d): handle=%d", __FUNCTION__, deviceIndexM, handleP);
 | 
			
		||||
  if (pIptvSectionM)
 | 
			
		||||
     pIptvSectionM->Close(handleP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvDevice::OpenDvr(void)
 | 
			
		||||
@@ -385,6 +334,8 @@ bool cIptvDevice::OpenDvr(void)
 | 
			
		||||
     pIptvStreamerM->Open();
 | 
			
		||||
  if (sidScanEnabledM && pSidScannerM && IptvConfig.GetSectionFiltering())
 | 
			
		||||
     pSidScannerM->Open();
 | 
			
		||||
  if (pidScanEnabledM && pPidScannerM)
 | 
			
		||||
     pPidScannerM->Open();
 | 
			
		||||
  isOpenDvrM = true;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
@@ -392,7 +343,9 @@ bool cIptvDevice::OpenDvr(void)
 | 
			
		||||
void cIptvDevice::CloseDvr(void)
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  if (sidScanEnabledM && pSidScannerM )
 | 
			
		||||
  if (pidScanEnabledM && pPidScannerM)
 | 
			
		||||
     pPidScannerM->Close();
 | 
			
		||||
  if (sidScanEnabledM && pSidScannerM)
 | 
			
		||||
     pSidScannerM->Close();
 | 
			
		||||
  if (pIptvStreamerM)
 | 
			
		||||
     pIptvStreamerM->Close();
 | 
			
		||||
@@ -430,10 +383,36 @@ bool cIptvDevice::IsBuffering(void) const
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cIptvDevice::WriteData(uchar *bufferP, int lengthP)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  int len;
 | 
			
		||||
  // Send data to dvr fifo
 | 
			
		||||
  if (dvrFdM >= 0)
 | 
			
		||||
     len = write(dvrFdM, bufferP, lengthP);
 | 
			
		||||
  // Fill up TS buffer
 | 
			
		||||
  if (tsBufferM) {
 | 
			
		||||
     len = tsBufferM->Put(bufferP, lengthP);
 | 
			
		||||
     if (len != lengthP)
 | 
			
		||||
        tsBufferM->ReportOverflow(lengthP - len);
 | 
			
		||||
     }
 | 
			
		||||
  // Filter the sections
 | 
			
		||||
  if (pIptvSectionM && IptvConfig.GetSectionFiltering())
 | 
			
		||||
     pIptvSectionM->Write(bufferP, lengthP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int cIptvDevice::CheckData(void)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  if (tsBufferM)
 | 
			
		||||
     return (unsigned int)tsBufferM->Free();
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvDevice::GetTSPacket(uchar *&Data)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  if (tsBufferM && !IsBuffering()) {
 | 
			
		||||
  if (isOpenDvrM && tsBufferM && !IsBuffering()) {
 | 
			
		||||
     if (isPacketDeliveredM) {
 | 
			
		||||
        tsBufferM->Del(TS_SIZE);
 | 
			
		||||
        isPacketDeliveredM = false;
 | 
			
		||||
@@ -451,26 +430,13 @@ bool cIptvDevice::GetTSPacket(uchar *&Data)
 | 
			
		||||
                  }
 | 
			
		||||
               }
 | 
			
		||||
           tsBufferM->Del(Count);
 | 
			
		||||
           error("Skipped %d bytes to sync on TS packet\n", Count);
 | 
			
		||||
           error("Skipped %d bytes to sync on TS packet", Count);
 | 
			
		||||
           return false;
 | 
			
		||||
           }
 | 
			
		||||
        isPacketDeliveredM = true;
 | 
			
		||||
        Data = p;
 | 
			
		||||
        // Update pid statistics
 | 
			
		||||
        AddPidStatistic(ts_pid(p), payload(p));
 | 
			
		||||
        // Send data also to dvr fifo
 | 
			
		||||
        if (dvrFdM >= 0)
 | 
			
		||||
           Count = (int)write(dvrFdM, p, TS_SIZE);
 | 
			
		||||
        // Analyze incomplete streams with built-in pid analyzer
 | 
			
		||||
        if (pidScanEnabledM && pPidScannerM)
 | 
			
		||||
           pPidScannerM->Process(p);
 | 
			
		||||
        // Lock
 | 
			
		||||
        cMutexLock MutexLock(&mutexM);
 | 
			
		||||
        // Run the data through all filters
 | 
			
		||||
        for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
			
		||||
            if (secFiltersM[i])
 | 
			
		||||
               secFiltersM[i]->Process(p);
 | 
			
		||||
            }
 | 
			
		||||
        return true;
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								device.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								device.h
									
									
									
									
									
								
							@@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
#include <vdr/device.h>
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "deviceif.h"
 | 
			
		||||
#include "protocoludp.h"
 | 
			
		||||
#include "protocolcurl.h"
 | 
			
		||||
#include "protocolhttp.h"
 | 
			
		||||
@@ -21,19 +22,17 @@
 | 
			
		||||
#include "sidscanner.h"
 | 
			
		||||
#include "statistics.h"
 | 
			
		||||
 | 
			
		||||
class cIptvDevice : public cDevice, public cIptvPidStatistics, public cIptvBufferStatistics {
 | 
			
		||||
class cIptvDevice : public cDevice, public cIptvPidStatistics, public cIptvBufferStatistics, public cIptvDeviceIf {
 | 
			
		||||
  // static ones
 | 
			
		||||
public:
 | 
			
		||||
  static unsigned int deviceCount;
 | 
			
		||||
  static bool Initialize(unsigned int DeviceCount);
 | 
			
		||||
  static void Shutdown(void);
 | 
			
		||||
  static unsigned int Count(void);
 | 
			
		||||
  static cIptvDevice *GetIptvDevice(int CardIndex);
 | 
			
		||||
 | 
			
		||||
  // private parts
 | 
			
		||||
private:
 | 
			
		||||
  enum {
 | 
			
		||||
    eMaxSecFilterCount = 32
 | 
			
		||||
  };
 | 
			
		||||
  unsigned int deviceIndexM;
 | 
			
		||||
  int dvrFdM;
 | 
			
		||||
  bool isPacketDeliveredM;
 | 
			
		||||
@@ -42,17 +41,17 @@ private:
 | 
			
		||||
  bool pidScanEnabledM;
 | 
			
		||||
  cRingBufferLinear *tsBufferM;
 | 
			
		||||
  mutable int tsBufferPrefillM;
 | 
			
		||||
  tChannelID channelIdM;
 | 
			
		||||
  cChannel channelM;
 | 
			
		||||
  cIptvProtocolUdp *pUdpProtocolM;
 | 
			
		||||
  cIptvProtocolCurl *pCurlProtocolM;
 | 
			
		||||
  cIptvProtocolHttp *pHttpProtocolM;
 | 
			
		||||
  cIptvProtocolFile *pFileProtocolM;
 | 
			
		||||
  cIptvProtocolExt *pExtProtocolM;
 | 
			
		||||
  cIptvStreamer *pIptvStreamerM;
 | 
			
		||||
  cIptvSectionFilterHandler *pIptvSectionM;
 | 
			
		||||
  cPidScanner *pPidScannerM;
 | 
			
		||||
  cSidScanner *pSidScannerM;
 | 
			
		||||
  cMutex mutexM;
 | 
			
		||||
  cIptvSectionFilter *secFiltersM[eMaxSecFilterCount];
 | 
			
		||||
 | 
			
		||||
  // constructor & destructor
 | 
			
		||||
public:
 | 
			
		||||
@@ -74,8 +73,6 @@ private:
 | 
			
		||||
private:
 | 
			
		||||
  void ResetBuffering(void);
 | 
			
		||||
  bool IsBuffering(void) const;
 | 
			
		||||
  bool DeleteFilter(unsigned int indexP);
 | 
			
		||||
  bool IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const;
 | 
			
		||||
 | 
			
		||||
  // for channel info
 | 
			
		||||
public:
 | 
			
		||||
@@ -91,6 +88,10 @@ public:
 | 
			
		||||
  virtual bool ProvidesChannel(const cChannel *channelP, int priorityP = -1, bool *needsDetachReceiversP = NULL) const;
 | 
			
		||||
  virtual bool ProvidesEIT(void) const;
 | 
			
		||||
  virtual int NumProvidedSystems(void) const;
 | 
			
		||||
  virtual const cChannel *GetCurrentlyTunedTransponder(void) const;
 | 
			
		||||
  virtual bool IsTunedToTransponder(const cChannel *channelP) const;
 | 
			
		||||
  virtual bool MaySwitchTransponder(const cChannel *channelP) const;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual bool SetChannelDevice(const cChannel *channelP, bool liveViewP);
 | 
			
		||||
 | 
			
		||||
@@ -104,7 +105,6 @@ protected:
 | 
			
		||||
  // for section filtering
 | 
			
		||||
public:
 | 
			
		||||
  virtual int OpenFilter(u_short pidP, u_char tidP, u_char maskP);
 | 
			
		||||
  virtual int ReadFilter(int handleP, void *bufferP, size_t lengthP);
 | 
			
		||||
  virtual void CloseFilter(int handleP);
 | 
			
		||||
 | 
			
		||||
  // for transponder lock
 | 
			
		||||
@@ -114,6 +114,11 @@ public:
 | 
			
		||||
  // for common interface
 | 
			
		||||
public:
 | 
			
		||||
  virtual bool HasInternalCam(void);
 | 
			
		||||
 | 
			
		||||
  // for internal device interface
 | 
			
		||||
public:
 | 
			
		||||
  virtual void WriteData(u_char *bufferP, int lengthP);
 | 
			
		||||
  virtual unsigned int CheckData(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // __IPTV_DEVICE_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								deviceif.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								deviceif.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * deviceif.h: IPTV plugin for the Video Disk Recorder
 | 
			
		||||
 *
 | 
			
		||||
 * See the README file for copyright information and how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __IPTV_DEVICEIF_H
 | 
			
		||||
#define __IPTV_DEVICEIF_H
 | 
			
		||||
 | 
			
		||||
class cIptvDeviceIf {
 | 
			
		||||
public:
 | 
			
		||||
  cIptvDeviceIf() {}
 | 
			
		||||
  virtual ~cIptvDeviceIf() {}
 | 
			
		||||
  virtual void WriteData(u_char *bufferP, int lengthP) = 0;
 | 
			
		||||
  virtual unsigned int CheckData(void) = 0;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  cIptvDeviceIf(const cIptvDeviceIf&);
 | 
			
		||||
  cIptvDeviceIf& operator=(const cIptvDeviceIf&);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // __IPTV_DEVICEIF_H
 | 
			
		||||
							
								
								
									
										10
									
								
								iptv.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								iptv.c
									
									
									
									
									
								
							@@ -13,15 +13,15 @@
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "iptvservice.h"
 | 
			
		||||
 | 
			
		||||
#if defined(APIVERSNUM) && APIVERSNUM < 10738
 | 
			
		||||
#error "VDR-1.7.38 API version or greater is required!"
 | 
			
		||||
#if defined(APIVERSNUM) && APIVERSNUM < 20000
 | 
			
		||||
#error "VDR-2.0.0 API version or greater is required!"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GITVERSION
 | 
			
		||||
#define GITVERSION ""
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
       const char VERSION[]     = "1.2.1" GITVERSION;
 | 
			
		||||
       const char VERSION[]     = "2.0.3" GITVERSION;
 | 
			
		||||
static const char DESCRIPTION[] = trNOOP("Experience the IPTV");
 | 
			
		||||
 | 
			
		||||
class cPluginIptv : public cPlugin {
 | 
			
		||||
@@ -99,7 +99,8 @@ bool cPluginIptv::Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
  debug("cPluginIptv::%s()", __FUNCTION__);
 | 
			
		||||
  // Initialize any background activities the plugin shall perform.
 | 
			
		||||
  IptvConfig.SetConfigDirectory(cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
 | 
			
		||||
  IptvConfig.SetConfigDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N));
 | 
			
		||||
  IptvConfig.SetResourceDirectory(cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
 | 
			
		||||
  return cIptvDevice::Initialize(deviceCountM);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -118,6 +119,7 @@ void cPluginIptv::Stop(void)
 | 
			
		||||
{
 | 
			
		||||
  debug("cPluginIptv::%s()", __FUNCTION__);
 | 
			
		||||
  // Stop any background activities the plugin is performing.
 | 
			
		||||
  cIptvDevice::Shutdown();
 | 
			
		||||
  curl_global_cleanup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,6 @@ void cPidScanner::SetChannel(const tChannelID &channelIdP)
 | 
			
		||||
  aPidM = 0xFFFF;
 | 
			
		||||
  numApidsM = 0;
 | 
			
		||||
  processM = true;
 | 
			
		||||
  timeoutM.Set(PIDSCANNER_TIMEOUT_IN_MS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPidScanner::Process(const uint8_t* bufP)
 | 
			
		||||
@@ -56,7 +55,7 @@ void cPidScanner::Process(const uint8_t* bufP)
 | 
			
		||||
 | 
			
		||||
  // Verify TS packet
 | 
			
		||||
  if (bufP[0] != 0x47) {
 | 
			
		||||
     error("Not TS packet: 0x%X\n", bufP[0]);
 | 
			
		||||
     error("Not TS packet: 0x%02X", bufP[0]);
 | 
			
		||||
     return;
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,12 @@
 | 
			
		||||
 | 
			
		||||
class cPidScanner {
 | 
			
		||||
private:
 | 
			
		||||
  enum {
 | 
			
		||||
    PIDSCANNER_APID_COUNT      = 5,    /* minimum count of audio pid samples for pid detection */
 | 
			
		||||
    PIDSCANNER_VPID_COUNT      = 5,    /* minimum count of video pid samples for pid detection */
 | 
			
		||||
    PIDSCANNER_PID_DELTA_COUNT = 100,  /* minimum count of pid samples for audio/video only pid detection */
 | 
			
		||||
    PIDSCANNER_TIMEOUT_IN_MS   = 15000 /* 15s timeout for detection */
 | 
			
		||||
  };
 | 
			
		||||
  cTimeMs timeoutM;
 | 
			
		||||
  tChannelID channelIdM;
 | 
			
		||||
  bool processM;
 | 
			
		||||
@@ -26,6 +32,8 @@ public:
 | 
			
		||||
  ~cPidScanner();
 | 
			
		||||
  void SetChannel(const tChannelID &channelIdP);
 | 
			
		||||
  void Process(const uint8_t* bufP);
 | 
			
		||||
  void Open()  { debug("cPidScanner::%s()", __FUNCTION__); timeoutM.Set(PIDSCANNER_TIMEOUT_IN_MS); }
 | 
			
		||||
  void Close() { debug("cPidScanner::%s()", __FUNCTION__); timeoutM.Set(0); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // __PIDSCANNER_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
# VDR plugin language source file.
 | 
			
		||||
# Copyright (C) 2007 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# This file is distributed under the same license as the iptv package.
 | 
			
		||||
# Tobias <vdr@e-tobi.net>, 2007.
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
 | 
			
		||||
"Project-Id-Version: vdr-iptv 2.0.3\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: <see README>\n"
 | 
			
		||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"POT-Creation-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"Last-Translator: Tobias Grimm <tg@e-tobi.net>\n"
 | 
			
		||||
"Language-Team: German <vdr@linuxtv.org>\n"
 | 
			
		||||
"Language: de\n"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
# VDR plugin language source file.
 | 
			
		||||
# Copyright (C) 2007 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# This file is distributed under the same license as the iptv package.
 | 
			
		||||
# Rolf Ahrenberg
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
 | 
			
		||||
"Project-Id-Version: vdr-iptv 2.0.3\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: <see README>\n"
 | 
			
		||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"POT-Creation-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"Last-Translator: Rolf Ahrenberg\n"
 | 
			
		||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
 | 
			
		||||
"Language: fi\n"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,15 @@
 | 
			
		||||
# French translations for iptv package.
 | 
			
		||||
# Copyright (C) 2007 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# This file is distributed under the same license as the iptv package.
 | 
			
		||||
# Bruno ROUSSEL <bruno.roussel@free.fr>, 2007.
 | 
			
		||||
# NIVAL Michaël <mnival@club-internet.fr>, 2008.
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
 | 
			
		||||
"Project-Id-Version: vdr-iptv 2.0.3\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: <see README>\n"
 | 
			
		||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"POT-Creation-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"Last-Translator: NIVAL Michaël <mnival@club-internet.fr>\n"
 | 
			
		||||
"Language-Team: French <vdr@linuxtv.org>\n"
 | 
			
		||||
"Language: fr\n"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
# VDR plugin language source file.
 | 
			
		||||
# Copyright (C) 2007 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# This file is distributed under the same license as the iptv package.
 | 
			
		||||
# Diego Pierotto <vdr-italian@tiscali.it>, 2008.
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
 | 
			
		||||
"Project-Id-Version: vdr-iptv 2.0.3\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: <see README>\n"
 | 
			
		||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"POT-Creation-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
 | 
			
		||||
"Language-Team: Italian <vdr@linuxtv.org>\n"
 | 
			
		||||
"Language: it\n"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
# VDR plugin language source file.
 | 
			
		||||
# Copyright (C) 2007 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# This file is distributed under the same license as the iptv package.
 | 
			
		||||
# Carel, 2010.
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
 | 
			
		||||
"Project-Id-Version: vdr-iptv 2.0.3\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: <see README>\n"
 | 
			
		||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"POT-Creation-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"Last-Translator: Carel\n"
 | 
			
		||||
"Language-Team: Dutch <vdr@linuxtv.org>\n"
 | 
			
		||||
"Language: nl\n"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
# VDR plugin language source file.
 | 
			
		||||
# Copyright (C) 2007 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
 | 
			
		||||
# This file is distributed under the same license as the iptv package.
 | 
			
		||||
# Alexander Gross <Bikalexander@gmail.com>, 2008.
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
 | 
			
		||||
"Project-Id-Version: vdr-iptv 2.0.3\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: <see README>\n"
 | 
			
		||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
 | 
			
		||||
"POT-Creation-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2014-03-09 03:09+0200\n"
 | 
			
		||||
"Last-Translator: Alexander Gross <Bikalexander@gmail.com>\n"
 | 
			
		||||
"Language-Team: Russian <vdr@linuxtv.org>\n"
 | 
			
		||||
"Language: ru\n"
 | 
			
		||||
 
 | 
			
		||||
@@ -9,14 +9,18 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "protocolcurl.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CURLOPT_RTSPHEADER
 | 
			
		||||
#define USE_RTSP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define iptv_curl_easy_setopt(X, Y, Z) \
 | 
			
		||||
  if ((res = curl_easy_setopt((X), (Y), (Z))) != CURLE_OK) { \
 | 
			
		||||
     error("curl_easy_setopt(%s, %s, %s) failed: %d\n", #X, #Y, #Z, res); \
 | 
			
		||||
     error("curl_easy_setopt(%s, %s) failed: %s (%d)", #Y, #Z, curl_easy_strerror(res), res); \
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
#define iptv_curl_easy_perform(X) \
 | 
			
		||||
  if ((res = curl_easy_perform((X))) != CURLE_OK) { \
 | 
			
		||||
     error("curl_easy_perform(%s) failed: %d\n", #X, res); \
 | 
			
		||||
     error("curl_easy_perform() failed: %s (%d)", curl_easy_strerror(res), res); \
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
cIptvProtocolCurl::cIptvProtocolCurl()
 | 
			
		||||
@@ -34,8 +38,10 @@ cIptvProtocolCurl::cIptvProtocolCurl()
 | 
			
		||||
  pausedM(false)
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvProtocolCurl::%s()", __FUNCTION__);
 | 
			
		||||
  if (ringBufferM)
 | 
			
		||||
  if (ringBufferM) {
 | 
			
		||||
     ringBufferM->SetTimeouts(100, 0);
 | 
			
		||||
     ringBufferM->SetIoThrottle();
 | 
			
		||||
     }
 | 
			
		||||
  Connect();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -67,7 +73,7 @@ size_t cIptvProtocolCurl::WriteRtspCallback(void *ptrP, size_t sizeP, size_t nme
 | 
			
		||||
  //debug("cIptvProtocolCurl::%s(%zu)", __FUNCTION__, len);
 | 
			
		||||
 | 
			
		||||
  // Validate packet header ('$') and channel (0)
 | 
			
		||||
  if (obj && (p[0] == 0x24 ) && (p[1] == 0)) {
 | 
			
		||||
  if (obj && (p[0] == 0x24) && (p[1] == 0)) {
 | 
			
		||||
     int length = (p[2] << 8) | p[3];
 | 
			
		||||
     if (length > 3) {
 | 
			
		||||
        // Skip interleave header
 | 
			
		||||
@@ -208,7 +214,7 @@ unsigned char *cIptvProtocolCurl::GetData(int &lenP)
 | 
			
		||||
                  break;
 | 
			
		||||
                  }
 | 
			
		||||
               }
 | 
			
		||||
           error("IPTV skipped %d bytes to sync on TS packet\n", count);
 | 
			
		||||
           error("IPTV skipped %d bytes to sync on TS packet", count);
 | 
			
		||||
           ringBufferM->Del(count);
 | 
			
		||||
           lenP = 0;
 | 
			
		||||
           return NULL;
 | 
			
		||||
@@ -258,7 +264,8 @@ bool cIptvProtocolCurl::Connect()
 | 
			
		||||
     iptv_curl_easy_setopt(handleM, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL);
 | 
			
		||||
     iptv_curl_easy_setopt(handleM, CURLOPT_NETRC_FILE, *netrc);
 | 
			
		||||
 | 
			
		||||
     // Set timeout
 | 
			
		||||
     // Set timeouts
 | 
			
		||||
     iptv_curl_easy_setopt(handleM, CURLOPT_TIMEOUT, (long)eConnectTimeoutS);
 | 
			
		||||
     iptv_curl_easy_setopt(handleM, CURLOPT_CONNECTTIMEOUT, (long)eConnectTimeoutS);
 | 
			
		||||
 | 
			
		||||
     // Set user-agent
 | 
			
		||||
@@ -272,6 +279,7 @@ bool cIptvProtocolCurl::Connect()
 | 
			
		||||
 | 
			
		||||
     // Protocol specific initializations
 | 
			
		||||
     switch (modeM) {
 | 
			
		||||
#ifdef USE_RTSP
 | 
			
		||||
       case eModeRtsp:
 | 
			
		||||
            {
 | 
			
		||||
            cString uri, control, transport, range;
 | 
			
		||||
@@ -315,7 +323,7 @@ bool cIptvProtocolCurl::Connect()
 | 
			
		||||
            iptv_curl_easy_perform(handleM);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
       case eModeHttp:
 | 
			
		||||
       case eModeHttps:
 | 
			
		||||
            {
 | 
			
		||||
@@ -338,6 +346,10 @@ bool cIptvProtocolCurl::Connect()
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
       case eModeFile:
 | 
			
		||||
            // Set timeout
 | 
			
		||||
            iptv_curl_easy_setopt(handleM, CURLOPT_TIMEOUT_MS, 10L);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
       case eModeUnknown:
 | 
			
		||||
       default:
 | 
			
		||||
            break;
 | 
			
		||||
@@ -364,6 +376,7 @@ bool cIptvProtocolCurl::Disconnect()
 | 
			
		||||
  if (handleM && multiM) {
 | 
			
		||||
     // Mode specific tricks
 | 
			
		||||
     switch (modeM) {
 | 
			
		||||
#ifdef USE_RTSP
 | 
			
		||||
       case eModeRtsp:
 | 
			
		||||
            {
 | 
			
		||||
            CURLcode res = CURLE_OK;
 | 
			
		||||
@@ -375,7 +388,7 @@ bool cIptvProtocolCurl::Disconnect()
 | 
			
		||||
            rtspControlM = "";
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
       case eModeHttp:
 | 
			
		||||
       case eModeHttps:
 | 
			
		||||
       case eModeFile:
 | 
			
		||||
@@ -422,6 +435,7 @@ int cIptvProtocolCurl::Read(unsigned char* bufferAddrP, unsigned int bufferLenP)
 | 
			
		||||
     // Fill up the buffer
 | 
			
		||||
     if (handleM && multiM) {
 | 
			
		||||
        switch (modeM) {
 | 
			
		||||
#ifdef USE_RTSP
 | 
			
		||||
          case eModeRtsp:
 | 
			
		||||
               {
 | 
			
		||||
               cMutexLock MutexLock(&mutexM);
 | 
			
		||||
@@ -431,7 +445,7 @@ int cIptvProtocolCurl::Read(unsigned char* bufferAddrP, unsigned int bufferLenP)
 | 
			
		||||
               // @todo - How to detect eof?
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
          case eModeFile:
 | 
			
		||||
          case eModeHttp:
 | 
			
		||||
          case eModeHttps:
 | 
			
		||||
@@ -444,9 +458,9 @@ int cIptvProtocolCurl::Read(unsigned char* bufferAddrP, unsigned int bufferLenP)
 | 
			
		||||
                 res = curl_multi_perform(multiM, &running_handles);
 | 
			
		||||
               } while (res == CURLM_CALL_MULTI_PERFORM);
 | 
			
		||||
 | 
			
		||||
               // Shall we continue filling up the buffer?
 | 
			
		||||
               // Use 20% threshold before continuing to filling up the buffer.
 | 
			
		||||
               mutexM.Lock();
 | 
			
		||||
               if (pausedM && (ringBufferM->Free() > ringBufferM->Available())) {
 | 
			
		||||
               if (pausedM && (ringBufferM->Available() < (MEGABYTE(IptvConfig.GetTsBufferSize()) / 5))) {
 | 
			
		||||
                  debug("cIptvProtocolCurl::%s(continue): free=%d available=%d", __FUNCTION__,
 | 
			
		||||
                        ringBufferM->Free(), ringBufferM->Available());
 | 
			
		||||
                  pausedM = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -158,7 +158,7 @@ bool cIptvProtocolExt::Set(const char* locationP, const int parameterP, const in
 | 
			
		||||
  if (!isempty(locationP)) {
 | 
			
		||||
     struct stat stbuf;
 | 
			
		||||
     // Update script file and parameter
 | 
			
		||||
     scriptFileM = cString::sprintf("%s/%s", IptvConfig.GetConfigDirectory(), locationP);
 | 
			
		||||
     scriptFileM = cString::sprintf("%s/%s", IptvConfig.GetResourceDirectory(), locationP);
 | 
			
		||||
     if ((stat(*scriptFileM, &stbuf) != 0) || (strstr(*scriptFileM, "..") != 0)) {
 | 
			
		||||
        error("Non-existent or relative path script '%s'", *scriptFileM);
 | 
			
		||||
        return false;
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,7 @@ int cIptvProtocolFile::Read(unsigned char* bufferAddrP, unsigned int bufferLenP)
 | 
			
		||||
{
 | 
			
		||||
   //debug("cIptvProtocolFile::%s()", __FUNCTION__);
 | 
			
		||||
   // Check errors
 | 
			
		||||
   if (ferror(fileStreamM)) {
 | 
			
		||||
   if (!fileStreamM || ferror(fileStreamM)) {
 | 
			
		||||
      debug("cIptvProtocolFile::%s(): stream error", __FUNCTION__);
 | 
			
		||||
      return -1;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -113,13 +113,13 @@ bool cIptvProtocolHttp::GetHeaderLine(char* destP, unsigned int destLenP,
 | 
			
		||||
       ++bufptr;
 | 
			
		||||
       // Check that buffer won't be exceeded
 | 
			
		||||
       if (recvLenP >= destLenP) {
 | 
			
		||||
          error("Header wouldn't fit into buffer\n");
 | 
			
		||||
          error("Header wouldn't fit into buffer");
 | 
			
		||||
          recvLenP = 0;
 | 
			
		||||
          return false;
 | 
			
		||||
          }
 | 
			
		||||
       }
 | 
			
		||||
    else {
 | 
			
		||||
       error("No HTTP response received in 500ms\n");
 | 
			
		||||
       error("No HTTP response received in 500ms");
 | 
			
		||||
       return false;
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
@@ -143,14 +143,14 @@ bool cIptvProtocolHttp::ProcessHeaders(void)
 | 
			
		||||
    if (!GetHeaderLine(buf, sizeof(buf), lineLength))
 | 
			
		||||
       return false;
 | 
			
		||||
    if (!responseFound && sscanf(buf, fmt, &version, &response) != 2) {
 | 
			
		||||
       error("Expected HTTP header not found\n");
 | 
			
		||||
       error("Expected HTTP header not found");
 | 
			
		||||
       continue;
 | 
			
		||||
       }
 | 
			
		||||
    else
 | 
			
		||||
       responseFound = true;
 | 
			
		||||
    // Allow only 'OK' and 'Partial Content'
 | 
			
		||||
    if ((response != 200) && (response != 206)) {
 | 
			
		||||
       error("Invalid HTTP response (%d): %s\n", response, buf);
 | 
			
		||||
       error("Invalid HTTP response (%d): %s", response, buf);
 | 
			
		||||
       return false;
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										230
									
								
								sectionfilter.c
									
									
									
									
									
								
							
							
						
						
									
										230
									
								
								sectionfilter.c
									
									
									
									
									
								
							@@ -17,9 +17,9 @@ cIptvSectionFilter::cIptvSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t
 | 
			
		||||
  secLenM(0),
 | 
			
		||||
  tsFeedpM(0),
 | 
			
		||||
  pidM(pidP),
 | 
			
		||||
  devIdM(deviceIndexP)
 | 
			
		||||
  deviceIndexM(deviceIndexP)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvSectionFilter::%s(%d, %d)", __FUNCTION__, devIdM, pidM);
 | 
			
		||||
  //debug("cIptvSectionFilter::%s(%d, %d)", __FUNCTION__, deviceIndexM, pidM);
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  memset(secBufBaseM,     0, sizeof(secBufBaseM));
 | 
			
		||||
@@ -46,32 +46,32 @@ cIptvSectionFilter::cIptvSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t
 | 
			
		||||
      }
 | 
			
		||||
  doneqM = doneq ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
  // Create filtering buffer
 | 
			
		||||
  ringbufferM = new cRingBufferLinear(KILOBYTE(128), 0, false, *cString::sprintf("IPTV SECTION %d/%d", devIdM, pidM));
 | 
			
		||||
  if (ringbufferM)
 | 
			
		||||
     ringbufferM->SetTimeouts(10, 10);
 | 
			
		||||
  else
 | 
			
		||||
     error("Failed to allocate buffer for section filter (device=%d pid=%d): ", devIdM, pidM);
 | 
			
		||||
  // Create sockets
 | 
			
		||||
  socketM[0] = socketM[1] = -1;
 | 
			
		||||
  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socketM) != 0) {
 | 
			
		||||
     char tmp[64];
 | 
			
		||||
     error("Opening section filter sockets failed (device=%d pid=%d): %s", deviceIndexM, pidM, strerror_r(errno, tmp, sizeof(tmp)));
 | 
			
		||||
     }
 | 
			
		||||
  else if ((fcntl(socketM[0], F_SETFL, O_NONBLOCK) != 0) || (fcntl(socketM[1], F_SETFL, O_NONBLOCK) != 0)) {
 | 
			
		||||
     char tmp[64];
 | 
			
		||||
     error("Setting section filter socket to non-blocking mode failed (device=%d pid=%d): %s", deviceIndexM, pidM, strerror_r(errno, tmp, sizeof(tmp)));
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cIptvSectionFilter::~cIptvSectionFilter()
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvSectionFilter::%s(%d, %d)", __FUNCTION__, devIdM, pidM);
 | 
			
		||||
  DELETE_POINTER(ringbufferM);
 | 
			
		||||
  //debug("cIptvSectionFilter::%s(%d, %d)", __FUNCTION__, deviceIndexM, pidM);
 | 
			
		||||
  int tmp = socketM[1];
 | 
			
		||||
  socketM[1] = -1;
 | 
			
		||||
  if (tmp >= 0)
 | 
			
		||||
     close(tmp);
 | 
			
		||||
  tmp = socketM[0];
 | 
			
		||||
  socketM[0] = -1;
 | 
			
		||||
  if (tmp >= 0)
 | 
			
		||||
     close(tmp);
 | 
			
		||||
  secBufM = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cIptvSectionFilter::Read(void *Data, size_t Length)
 | 
			
		||||
{
 | 
			
		||||
  int count = 0;
 | 
			
		||||
  uchar *p = ringbufferM->Get(count);
 | 
			
		||||
  if (p && count > 0) {
 | 
			
		||||
     memcpy(Data, p, count);
 | 
			
		||||
     ringbufferM->Del(count);
 | 
			
		||||
     }
 | 
			
		||||
  return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline uint16_t cIptvSectionFilter::GetLength(const uint8_t *dataP)
 | 
			
		||||
{
 | 
			
		||||
  return (uint16_t)(3 + ((dataP[1] & 0x0f) << 8) + dataP[2]);
 | 
			
		||||
@@ -99,10 +99,10 @@ int cIptvSectionFilter::Filter(void)
 | 
			
		||||
     if (doneqM && !neq)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
     if (ringbufferM) {
 | 
			
		||||
        int len = ringbufferM->Put(secBufM, secLenM);
 | 
			
		||||
        if (len != secLenM)
 | 
			
		||||
           ringbufferM->ReportOverflow(secLenM - len);
 | 
			
		||||
     // There is no data in the read socket, more can be written
 | 
			
		||||
     if ((socketM[0] >= 0) && (socketM[1] >= 0) /*&& !select_single_desc(socketM[0], 0, false)*/) {
 | 
			
		||||
        ssize_t len = write(socketM[1], secBufM, secLenM);
 | 
			
		||||
        ERROR_IF(len < 0, "write()");
 | 
			
		||||
        // Update statistics
 | 
			
		||||
        AddSectionStatistic(len, 1);
 | 
			
		||||
        }
 | 
			
		||||
@@ -210,3 +210,183 @@ void cIptvSectionFilter::Process(const uint8_t* dataP)
 | 
			
		||||
     CopyDump(&dataP[p], count);
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
cIptvSectionFilterHandler::cIptvSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP)
 | 
			
		||||
: cThread("IPTV section handler", true),
 | 
			
		||||
  mutexM(),
 | 
			
		||||
  deviceIndexM(deviceIndexP),
 | 
			
		||||
  processedM(false),
 | 
			
		||||
  ringBufferM(new cRingBufferLinear(bufferLenP, TS_SIZE, false, *cString::sprintf("IPTV SECTION HANDLER %d", deviceIndexP)))
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
 | 
			
		||||
  // Initialize filter pointers
 | 
			
		||||
  memset(filtersM, 0, sizeof(filtersM));
 | 
			
		||||
 | 
			
		||||
  // Create input buffer
 | 
			
		||||
  if (ringBufferM) {
 | 
			
		||||
     ringBufferM->SetTimeouts(100, 100);
 | 
			
		||||
     ringBufferM->SetIoThrottle();
 | 
			
		||||
     }
 | 
			
		||||
  else
 | 
			
		||||
     error("Failed to allocate buffer for section filter handler (device=%d): ", deviceIndexM);
 | 
			
		||||
 | 
			
		||||
  Start();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cIptvSectionFilterHandler::~cIptvSectionFilterHandler()
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  Stop();
 | 
			
		||||
 | 
			
		||||
  DELETE_POINTER(ringBufferM);
 | 
			
		||||
 | 
			
		||||
  // Destroy all filters
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  for (int i = 0; i < eMaxSecFilterCount; ++i)
 | 
			
		||||
      Delete(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvSectionFilterHandler::Stop(void)
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvSectionFilterHandler::%s(%d): entering", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  // Stop thread
 | 
			
		||||
  if (Running())
 | 
			
		||||
     Cancel(3);
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cIptvSectionFilterHandler::Action(void)
 | 
			
		||||
{
 | 
			
		||||
  debug("cIptvSectionFilterHandler::%s(%d): entering", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  // Do the thread loop
 | 
			
		||||
  while (Running()) {
 | 
			
		||||
        // Read one TS packet
 | 
			
		||||
        if (ringBufferM) {
 | 
			
		||||
           int len = 0;
 | 
			
		||||
           if (processedM) {
 | 
			
		||||
              ringBufferM->Del(TS_SIZE);
 | 
			
		||||
              processedM = false;
 | 
			
		||||
              }
 | 
			
		||||
           uchar *p = ringBufferM->Get(len);
 | 
			
		||||
           if (p && (len >= TS_SIZE)) {
 | 
			
		||||
              if (*p != TS_SYNC_BYTE) {
 | 
			
		||||
                 for (int i = 1; i < len; ++i) {
 | 
			
		||||
                     if (p[i] == TS_SYNC_BYTE) {
 | 
			
		||||
                        len = i;
 | 
			
		||||
                        break;
 | 
			
		||||
                        }
 | 
			
		||||
                     }
 | 
			
		||||
                 ringBufferM->Del(len);
 | 
			
		||||
                 debug("cIptvSectionFilterHandler::%s(%d): Skipped %d bytes to sync on TS packet", __FUNCTION__, deviceIndexM, len);
 | 
			
		||||
                 continue;
 | 
			
		||||
                 }
 | 
			
		||||
              // Process TS packet through all filters
 | 
			
		||||
              mutexM.Lock();
 | 
			
		||||
              for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
			
		||||
                  if (filtersM[i])
 | 
			
		||||
                     filtersM[i]->Process(p);
 | 
			
		||||
                  }
 | 
			
		||||
              mutexM.Unlock();
 | 
			
		||||
              processedM = true;
 | 
			
		||||
              continue;
 | 
			
		||||
              }
 | 
			
		||||
           }
 | 
			
		||||
        cCondWait::SleepMs(10); // to avoid busy loop and reduce cpu load
 | 
			
		||||
        }
 | 
			
		||||
  debug("cIptvSectionFilterHandler::%s(%d): exiting", __FUNCTION__, deviceIndexM);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cString cIptvSectionFilterHandler::GetInformation(void)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
 | 
			
		||||
  // loop through active section filters
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  cString s = "";
 | 
			
		||||
  unsigned int count = 0;
 | 
			
		||||
  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
			
		||||
      if (filtersM[i]) {
 | 
			
		||||
         s = cString::sprintf("%sFilter %d: %s Pid=0x%02X (%s)\n", *s, i,
 | 
			
		||||
                              *filtersM[i]->GetSectionStatistic(), filtersM[i]->GetPid(),
 | 
			
		||||
                              id_pid(filtersM[i]->GetPid()));
 | 
			
		||||
         if (++count > IPTV_STATS_ACTIVE_FILTERS_COUNT)
 | 
			
		||||
            break;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvSectionFilterHandler::Delete(unsigned int indexP)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvSectionFilterHandler::%s(%d): index=%d", __FUNCTION__, deviceIndexM, indexP);
 | 
			
		||||
  if ((indexP < eMaxSecFilterCount) && filtersM[indexP]) {
 | 
			
		||||
     //debug("cIptvSectionFilterHandler::%s(%d): found %d", __FUNCTION__, deviceIndexM, indexP);
 | 
			
		||||
     cIptvSectionFilter *tmp = filtersM[indexP];
 | 
			
		||||
     filtersM[indexP] = NULL;
 | 
			
		||||
     delete tmp;
 | 
			
		||||
     return true;
 | 
			
		||||
     }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cIptvSectionFilterHandler::IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvSectionFilterHandler::%s(%d): pid=%d tid=%02X mask=%02X", __FUNCTION__, deviceIndexM, pidP, tidP, maskP);
 | 
			
		||||
  // loop through section filter table
 | 
			
		||||
  for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
 | 
			
		||||
      int index = IptvConfig.GetDisabledFilters(i);
 | 
			
		||||
      // Check if matches
 | 
			
		||||
      if ((index >= 0) && (index < SECTION_FILTER_TABLE_SIZE) &&
 | 
			
		||||
          (section_filter_table[index].pid == pidP) && (section_filter_table[index].tid == tidP) &&
 | 
			
		||||
          (section_filter_table[index].mask == maskP)) {
 | 
			
		||||
         //debug("cIptvSectionFilterHandler::%s(%d): found %s", __FUNCTION__, deviceIndexM, section_filter_table[index].description);
 | 
			
		||||
         return true;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cIptvSectionFilterHandler::Open(u_short pidP, u_char tidP, u_char maskP)
 | 
			
		||||
{
 | 
			
		||||
  // Lock
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  // Blacklist check, refuse certain filters
 | 
			
		||||
  if (IsBlackListed(pidP, tidP, maskP))
 | 
			
		||||
     return -1;
 | 
			
		||||
  // Search the next free filter slot
 | 
			
		||||
  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
			
		||||
      if (!filtersM[i]) {
 | 
			
		||||
         filtersM[i] = new cIptvSectionFilter(deviceIndexM, pidP, tidP, maskP);
 | 
			
		||||
         debug("cIptvSectionFilterHandler::%s(%d): pid=%d tid=%02X mask=%02X handle=%d index=%d", __FUNCTION__, deviceIndexM, pidP, tidP, maskP, filtersM[i]->GetFd(), i);
 | 
			
		||||
         return filtersM[i]->GetFd();
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  // No free filter slot found
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cIptvSectionFilterHandler::Close(int handleP)
 | 
			
		||||
{
 | 
			
		||||
  // Lock
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  // Search the filter for deletion
 | 
			
		||||
  for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
 | 
			
		||||
      if (filtersM[i] && (handleP == filtersM[i]->GetFd())) {
 | 
			
		||||
         debug("cIptvSectionFilterHandler::%s(%d): pid=%d handle=%d index=%d", __FUNCTION__, deviceIndexM, filtersM[i]->GetPid(), filtersM[i]->GetFd(), i);
 | 
			
		||||
         Delete(i);
 | 
			
		||||
         break;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cIptvSectionFilterHandler::Write(uchar *bufferP, int lengthP)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvSectionFilterHandler::%s(%d): length=%d", __FUNCTION__, deviceIndexM, lengthP);
 | 
			
		||||
  // Fill up the buffer
 | 
			
		||||
  if (ringBufferM) {
 | 
			
		||||
     int len = ringBufferM->Put(bufferP, lengthP);
 | 
			
		||||
     if (len != lengthP)
 | 
			
		||||
        ringBufferM->ReportOverflow(lengthP - len);
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,8 @@ private:
 | 
			
		||||
  uint16_t tsFeedpM;
 | 
			
		||||
  uint16_t pidM;
 | 
			
		||||
 | 
			
		||||
  int devIdM;
 | 
			
		||||
  int deviceIndexM;
 | 
			
		||||
  int socketM[2];
 | 
			
		||||
 | 
			
		||||
  uint8_t filterValueM[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
  uint8_t filterMaskM[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
@@ -44,8 +45,6 @@ private:
 | 
			
		||||
  uint8_t maskAndModeM[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
  uint8_t maskAndNotModeM[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
 | 
			
		||||
  cRingBufferLinear *ringbufferM;
 | 
			
		||||
 | 
			
		||||
  inline uint16_t GetLength(const uint8_t *dataP);
 | 
			
		||||
  void New(void);
 | 
			
		||||
  int Filter(void);
 | 
			
		||||
@@ -57,8 +56,35 @@ public:
 | 
			
		||||
  cIptvSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP);
 | 
			
		||||
  virtual ~cIptvSectionFilter();
 | 
			
		||||
  void Process(const uint8_t* dataP);
 | 
			
		||||
  int Read(void *bufferP, size_t lengthP);
 | 
			
		||||
  int GetFd(void) { return socketM[0]; }
 | 
			
		||||
  uint16_t GetPid(void) const { return pidM; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class cIptvSectionFilterHandler : public cThread {
 | 
			
		||||
private:
 | 
			
		||||
  enum {
 | 
			
		||||
    eMaxSecFilterCount = 32
 | 
			
		||||
  };
 | 
			
		||||
  cMutex mutexM;
 | 
			
		||||
  int deviceIndexM;
 | 
			
		||||
  bool processedM;
 | 
			
		||||
  cRingBufferLinear *ringBufferM;
 | 
			
		||||
  cIptvSectionFilter *filtersM[eMaxSecFilterCount];
 | 
			
		||||
 | 
			
		||||
  bool Delete(unsigned int indexP);
 | 
			
		||||
  bool IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  virtual void Action(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cIptvSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP);
 | 
			
		||||
  virtual ~cIptvSectionFilterHandler();
 | 
			
		||||
  bool Stop(void);
 | 
			
		||||
  cString GetInformation(void);
 | 
			
		||||
  int Open(u_short pidP, u_char tidP, u_char maskP);
 | 
			
		||||
  void Close(int handleP);
 | 
			
		||||
  void Write(u_char *bufferP, int lengthP);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // __IPTV_SECTIONFILTER_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								setup.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								setup.c
									
									
									
									
									
								
							@@ -124,6 +124,7 @@ cIptvPluginSetup::cIptvPluginSetup()
 | 
			
		||||
      disabledFilterIndexesM[i] = IptvConfig.GetDisabledFilters(i);
 | 
			
		||||
      disabledFilterNamesM[i] = tr(section_filter_table[i].description);
 | 
			
		||||
      }
 | 
			
		||||
  SetMenuCategory(mcSetupPlugins);
 | 
			
		||||
  Setup();
 | 
			
		||||
  SetHelp(NULL, NULL, NULL, trVDR("Button$Info"));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								sidscanner.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								sidscanner.c
									
									
									
									
									
								
							@@ -45,7 +45,7 @@ void cSidScanner::Process(u_short pidP, u_char tidP, const u_char *dataP, int le
 | 
			
		||||
     return;
 | 
			
		||||
  if (channelIdM.Valid()) {
 | 
			
		||||
     if ((pidP == 0x00) && (tidP == 0x00)) {
 | 
			
		||||
        debug("cSidScanner::%s(%d, %02X)", __FUNCTION__, pidP, tidP);
 | 
			
		||||
        //debug("cSidScanner::%s(%d, %02X)", __FUNCTION__, pidP, tidP);
 | 
			
		||||
        SI::PAT pat(dataP, false);
 | 
			
		||||
        if (!pat.CheckCRCAndParse())
 | 
			
		||||
           return;
 | 
			
		||||
@@ -71,15 +71,21 @@ void cSidScanner::Process(u_short pidP, u_char tidP, const u_char *dataP, int le
 | 
			
		||||
            if (ts.getTransportStreamId() != channelIdM.Tid()) {
 | 
			
		||||
               debug("cSidScanner::%s(): tsid=%d", __FUNCTION__, ts.getTransportStreamId());
 | 
			
		||||
               newTid = ts.getTransportStreamId();
 | 
			
		||||
               tidFoundM = true;
 | 
			
		||||
               }
 | 
			
		||||
            if (ts.getOriginalNetworkId() != channelIdM.Nid()) {
 | 
			
		||||
               debug("cSidScanner::%s(): onid=%d", __FUNCTION__, ts.getOriginalNetworkId());
 | 
			
		||||
               newNid = ts.getOriginalNetworkId();
 | 
			
		||||
               nidFoundM = true;
 | 
			
		||||
               }
 | 
			
		||||
            tidFoundM = true;
 | 
			
		||||
            break; // default to the first one
 | 
			
		||||
            }
 | 
			
		||||
        if (nit.getNetworkId() != channelIdM.Nid()) {
 | 
			
		||||
           debug("cSidScanner::%s(): nid=%d\n", __FUNCTION__, ts.getTransportStreamId());
 | 
			
		||||
        // fallback for network id if not found already
 | 
			
		||||
        if (!nidFoundM && (nit.getNetworkId() != channelIdM.Nid())) {
 | 
			
		||||
           debug("cSidScanner::%s(): nid=%d", __FUNCTION__, nit.getNetworkId());
 | 
			
		||||
           newNid = nit.getNetworkId();
 | 
			
		||||
           nidFoundM = true;
 | 
			
		||||
           }
 | 
			
		||||
        nidFoundM = true; 
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
  if ((newSid >= 0) || (newNid >= 0) || (newTid >= 0)) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								socket.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								socket.c
									
									
									
									
									
								
							@@ -93,7 +93,7 @@ bool cIptvSocket::CheckAddress(const char *addrP, in_addr_t *inAddrP)
 | 
			
		||||
{
 | 
			
		||||
  if (inAddrP) {
 | 
			
		||||
     // First try only the IP address
 | 
			
		||||
     *inAddrP = htonl(inet_addr(addrP));
 | 
			
		||||
     *inAddrP = inet_addr(addrP);
 | 
			
		||||
     if (*inAddrP == htonl(INADDR_NONE)) {
 | 
			
		||||
        debug("cIptvSocket::%s(%s): cannot convert to address", __FUNCTION__, addrP);
 | 
			
		||||
        // It may be a host name, get the name
 | 
			
		||||
@@ -104,7 +104,7 @@ bool cIptvSocket::CheckAddress(const char *addrP, in_addr_t *inAddrP)
 | 
			
		||||
                 strerror_r(h_errno, tmp, sizeof(tmp)));
 | 
			
		||||
           return false;
 | 
			
		||||
           }
 | 
			
		||||
        *inAddrP = htonl(inet_addr(*host->h_addr_list));
 | 
			
		||||
        *inAddrP = inet_addr(*host->h_addr_list);
 | 
			
		||||
        }
 | 
			
		||||
     return true;
 | 
			
		||||
     }
 | 
			
		||||
@@ -226,7 +226,7 @@ int cIptvUdpSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
 | 
			
		||||
  //debug("cIptvUdpSocket::%s()", __FUNCTION__);
 | 
			
		||||
  // Error out if socket not initialized
 | 
			
		||||
  if (socketDescM <= 0) {
 | 
			
		||||
     error("Invalid socket in cIptvUdpSocket::%s()\n", __FUNCTION__);
 | 
			
		||||
     error("Invalid socket in cIptvUdpSocket::%s()", __FUNCTION__);
 | 
			
		||||
     return -1;
 | 
			
		||||
     }
 | 
			
		||||
  int len = 0;
 | 
			
		||||
@@ -359,7 +359,7 @@ int cIptvTcpSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
 | 
			
		||||
  //debug("cIptvTcpSocket::%s()", __FUNCTION__);
 | 
			
		||||
  // Error out if socket not initialized
 | 
			
		||||
  if (socketDescM <= 0) {
 | 
			
		||||
     error("Invalid socket in cIptvTcpSocket::%s()\n", __FUNCTION__);
 | 
			
		||||
     error("Invalid socket in cIptvTcpSocket::%s()", __FUNCTION__);
 | 
			
		||||
     return -1;
 | 
			
		||||
     }
 | 
			
		||||
  int len = 0;
 | 
			
		||||
@@ -376,7 +376,7 @@ bool cIptvTcpSocket::ReadChar(char *bufferAddrP, unsigned int timeoutMsP)
 | 
			
		||||
  //debug("cIptvTcpSocket::%s()", __FUNCTION__);
 | 
			
		||||
  // Error out if socket not initialized
 | 
			
		||||
  if (socketDescM <= 0) {
 | 
			
		||||
     error("Invalid socket in cIptvTcpSocket::%s()\n", __FUNCTION__);
 | 
			
		||||
     error("Invalid socket in cIptvTcpSocket::%s()", __FUNCTION__);
 | 
			
		||||
     return false;
 | 
			
		||||
     }
 | 
			
		||||
  socklen_t addrlen = sizeof(sockAddrM);
 | 
			
		||||
@@ -401,7 +401,7 @@ bool cIptvTcpSocket::Write(const char *bufferAddrP, unsigned int bufferLenP)
 | 
			
		||||
  //debug("cIptvTcpSocket::%s()", __FUNCTION__);
 | 
			
		||||
  // Error out if socket not initialized
 | 
			
		||||
  if (socketDescM <= 0) {
 | 
			
		||||
     error("Invalid socket in cIptvTcpSocket::%s()\n", __FUNCTION__);
 | 
			
		||||
     error("Invalid socket in cIptvTcpSocket::%s()", __FUNCTION__);
 | 
			
		||||
     return false;
 | 
			
		||||
     }
 | 
			
		||||
  ERROR_IF_RET(send(socketDescM, bufferAddrP, bufferLenP, 0) < 0, "send()", return false);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								source.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								source.c
									
									
									
									
									
								
							@@ -58,6 +58,7 @@ bool cIptvTransponderParameters::Parse(const char *strP)
 | 
			
		||||
  if (strP && *strP) {
 | 
			
		||||
     const char *delim = "|";
 | 
			
		||||
     char *str = strdup(strP);
 | 
			
		||||
     char *p = str;
 | 
			
		||||
     char *saveptr = NULL;
 | 
			
		||||
     char *token = NULL;
 | 
			
		||||
     bool found_s = false;
 | 
			
		||||
@@ -120,9 +121,9 @@ bool cIptvTransponderParameters::Parse(const char *strP)
 | 
			
		||||
     if (found_s && found_p && found_f && found_u && found_a)
 | 
			
		||||
        result = true;
 | 
			
		||||
     else
 | 
			
		||||
        error("Invalid channel parameters: %s\n", str);
 | 
			
		||||
        error("Invalid channel parameters: %s", p);
 | 
			
		||||
 | 
			
		||||
     free(str);
 | 
			
		||||
     free(p);
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
  return (result);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								source.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								source.h
									
									
									
									
									
								
							@@ -20,7 +20,7 @@ private:
 | 
			
		||||
  int sidScanM;
 | 
			
		||||
  int pidScanM;
 | 
			
		||||
  int protocolM;
 | 
			
		||||
  char addressM[NAME_MAX];
 | 
			
		||||
  char addressM[NAME_MAX + 1];
 | 
			
		||||
  int parameterM;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ cString cIptvSectionStatistics::GetSectionStatistic()
 | 
			
		||||
 | 
			
		||||
void cIptvSectionStatistics::AddSectionStatistic(long bytesP, long callsP)
 | 
			
		||||
{
 | 
			
		||||
  //debug("cIptvSectionStatistics::%s(%ld, %ld)", __FUNCTION__, bytesP, callsP); 
 | 
			
		||||
  //debug("cIptvSectionStatistics::%s(%ld, %ld)", __FUNCTION__, bytesP, callsP);
 | 
			
		||||
  cMutexLock MutexLock(&mutexM);
 | 
			
		||||
  filteredDataM += bytesP;
 | 
			
		||||
  numberOfCallsM += callsP;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								streamer.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								streamer.c
									
									
									
									
									
								
							@@ -5,16 +5,13 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <vdr/thread.h>
 | 
			
		||||
#include <vdr/ringbuffer.h>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "streamer.h"
 | 
			
		||||
 | 
			
		||||
cIptvStreamer::cIptvStreamer(cRingBufferLinear* ringBufferP, unsigned int packetLenP)
 | 
			
		||||
cIptvStreamer::cIptvStreamer(cIptvDeviceIf &deviceP, unsigned int packetLenP)
 | 
			
		||||
: cThread("IPTV streamer"),
 | 
			
		||||
  ringBufferM(ringBufferP),
 | 
			
		||||
  sleepM(),
 | 
			
		||||
  deviceM(&deviceP),
 | 
			
		||||
  packetBufferLenM(packetLenP),
 | 
			
		||||
  protocolM(NULL)
 | 
			
		||||
{
 | 
			
		||||
@@ -33,7 +30,6 @@ cIptvStreamer::~cIptvStreamer()
 | 
			
		||||
  // Close the protocol
 | 
			
		||||
  Close();
 | 
			
		||||
  protocolM = NULL;
 | 
			
		||||
  ringBufferM = NULL;
 | 
			
		||||
  // Free allocated memory
 | 
			
		||||
  free(packetBufferM);
 | 
			
		||||
}
 | 
			
		||||
@@ -46,16 +42,12 @@ void cIptvStreamer::Action(void)
 | 
			
		||||
  // Do the thread loop
 | 
			
		||||
  while (packetBufferM && Running()) {
 | 
			
		||||
        int length = -1;
 | 
			
		||||
        unsigned int size = min((unsigned int)ringBufferM->Free(), packetBufferLenM);
 | 
			
		||||
        unsigned int size = min(deviceM->CheckData(), packetBufferLenM);
 | 
			
		||||
        if (protocolM && (size > 0))
 | 
			
		||||
           length = protocolM->Read(packetBufferM, size);
 | 
			
		||||
        if (length > 0) {
 | 
			
		||||
           AddStreamerStatistic(length);
 | 
			
		||||
           if (ringBufferM) {
 | 
			
		||||
              int p = ringBufferM->Put(packetBufferM, length);
 | 
			
		||||
              if (p != length)
 | 
			
		||||
                 ringBufferM->ReportOverflow(length - p);
 | 
			
		||||
              }
 | 
			
		||||
           deviceM->WriteData(packetBufferM, length);
 | 
			
		||||
           }
 | 
			
		||||
        else
 | 
			
		||||
           sleepM.Wait(10); // to avoid busy loop and reduce cpu load
 | 
			
		||||
 
 | 
			
		||||
@@ -11,15 +11,15 @@
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
 | 
			
		||||
#include <vdr/thread.h>
 | 
			
		||||
#include <vdr/ringbuffer.h>
 | 
			
		||||
 | 
			
		||||
#include "deviceif.h"
 | 
			
		||||
#include "protocolif.h"
 | 
			
		||||
#include "statistics.h"
 | 
			
		||||
 | 
			
		||||
class cIptvStreamer : public cThread, public cIptvStreamerStatistics {
 | 
			
		||||
private:
 | 
			
		||||
  cRingBufferLinear* ringBufferM;
 | 
			
		||||
  cCondWait sleepM;
 | 
			
		||||
  cIptvDeviceIf* deviceM;
 | 
			
		||||
  unsigned char* packetBufferM;
 | 
			
		||||
  unsigned int packetBufferLenM;
 | 
			
		||||
  cIptvProtocolIf* protocolM;
 | 
			
		||||
@@ -28,7 +28,7 @@ protected:
 | 
			
		||||
  virtual void Action(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  cIptvStreamer(cRingBufferLinear* ringBufferP, unsigned int packetLenP);
 | 
			
		||||
  cIptvStreamer(cIptvDeviceIf &deviceP, unsigned int packetLenP);
 | 
			
		||||
  virtual ~cIptvStreamer();
 | 
			
		||||
  bool Set(const char* locationP, const int parameterP, const int indexP, cIptvProtocolIf* protocolP);
 | 
			
		||||
  bool Open(void);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user