From 68459e65531ce015757873bf3ae533a45c6ee3e0 Mon Sep 17 00:00:00 2001 From: Rolf Ahrenberg Date: Wed, 30 Jan 2008 22:41:58 +0000 Subject: [PATCH] Added preliminary automatic Pid scanning functionality. --- HISTORY | 1 + Makefile | 4 +- device.c | 13 ++++-- device.h | 4 +- pidscanner.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ pidscanner.h | 30 +++++++++++++ 6 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 pidscanner.c create mode 100644 pidscanner.h diff --git a/HISTORY b/HISTORY index 88973d3..d2304b3 100644 --- a/HISTORY +++ b/HISTORY @@ -43,3 +43,4 @@ VDR Plugin 'iptv' Revision History - Updated French translation (Thanks to Michaël Nival). - Modified VDR locale support detection. +- Added preliminary automatic Pid scanning functionality. diff --git a/Makefile b/Makefile index 04ae6df..325a180 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # # Makefile for a Video Disk Recorder plugin # -# $Id: Makefile,v 1.25 2008/01/28 22:37:27 rahrenbe Exp $ +# $Id: Makefile,v 1.26 2008/01/30 22:41:58 rahrenbe Exp $ # Debugging on/off #IPTV_DEBUG = 1 @@ -64,7 +64,7 @@ endif OBJS = $(PLUGIN).o config.o setup.o device.o streamer.o protocoludp.o \ protocolhttp.o protocolfile.o protocolext.o sectionfilter.o \ - sidscanner.o statistics.o common.o socket.o i18n.o + sidscanner.o pidscanner.o statistics.o common.o socket.o i18n.o ### The main target: diff --git a/device.c b/device.c index 6f8cbab..d9d2b50 100644 --- a/device.c +++ b/device.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: device.c,v 1.80 2008/01/30 21:57:33 rahrenbe Exp $ + * $Id: device.c,v 1.81 2008/01/30 22:41:59 rahrenbe Exp $ */ #include "config.h" @@ -32,6 +32,7 @@ cIptvDevice::cIptvDevice(unsigned int Index) pFileProtocol = new cIptvProtocolFile(); pExtProtocol = new cIptvProtocolExt(); pIptvStreamer = new cIptvStreamer(tsBuffer, &mutex); + pPidScanner = new cPidScanner; // Initialize filter pointers memset(secfilters, '\0', sizeof(secfilters)); // Start section handler for iptv device @@ -51,6 +52,7 @@ cIptvDevice::~cIptvDevice() DELETE_POINTER(pFileProtocol); DELETE_POINTER(pExtProtocol); DELETE_POINTER(tsBuffer); + DELETE_POINTER(pPidScanner); // Detach and destroy sid filter if (pSidScanner) { Detach(pSidScanner); @@ -236,6 +238,8 @@ bool cIptvDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) pIptvStreamer->Set(location, parameter, deviceIndex, protocol); if (pSidScanner && IptvConfig.GetSectionFiltering() && IptvConfig.GetSidScanning()) pSidScanner->SetChannel(Channel); + if (pPidScanner && IptvConfig.GetPidScanning()) + pPidScanner->SetChannel(Channel); return true; } @@ -381,8 +385,11 @@ bool cIptvDevice::GetTSPacket(uchar *&Data) } isPacketDelivered = true; Data = p; - // Update pid statistics - AddPidStatistic(ts_pid(p), payload(p)); + // Update pid statistics + AddPidStatistic(ts_pid(p), payload(p)); + // Analyze incomplete streams with built-in pid analyzer + if (pPidScanner && IptvConfig.GetPidScanning()) + pPidScanner->Process(p); // Run the data through all filters for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) { if (secfilters[i]) diff --git a/device.h b/device.h index ce77e9f..b8c5cee 100644 --- a/device.h +++ b/device.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: device.h,v 1.36 2008/01/28 21:36:33 rahrenbe Exp $ + * $Id: device.h,v 1.37 2008/01/30 22:41:59 rahrenbe Exp $ */ #ifndef __IPTV_DEVICE_H @@ -17,6 +17,7 @@ #include "protocolext.h" #include "streamer.h" #include "sectionfilter.h" +#include "pidscanner.h" #include "sidscanner.h" #include "statistics.h" @@ -43,6 +44,7 @@ private: cIptvProtocolFile *pFileProtocol; cIptvProtocolExt *pExtProtocol; cIptvStreamer *pIptvStreamer; + cPidScanner *pPidScanner; cSidScanner *pSidScanner; cMutex mutex; cIptvSectionFilter* secfilters[eMaxSecFilterCount]; diff --git a/pidscanner.c b/pidscanner.c new file mode 100644 index 0000000..5eef296 --- /dev/null +++ b/pidscanner.c @@ -0,0 +1,116 @@ +/* + * pidscanner.c: IPTV plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: pidscanner.c,v 1.1 2008/01/30 22:41:59 rahrenbe Exp $ + */ + +#include "common.h" +#include "pidscanner.h" + +cPidScanner::cPidScanner(void) +: process(true), + Vpid(0xFFFF), + Apid(0xFFFF), + numVpids(0), + numApids(0) +{ + debug("cPidScanner::cPidScanner()\n"); + channel = cChannel(); +} + +cPidScanner::~cPidScanner() +{ + debug("cPidScanner::~cPidScanner()\n"); +} + +void cPidScanner::Process(const uint8_t* buf) +{ + //debug("cPidScanner::Process()\n"); + if (!process) + return; + + if (buf[0] != 0x47) { + error("Not TS packet: 0x%X\n", buf[0]); + return; + } + + // Found TS packet + int pid = ts_pid(buf); + int xpid = (buf[1] << 8 | buf[2]); + + // count == 0 if no payload or out of range + uint8_t count = payload(buf); + if (count == 0) + return; + + if (xpid & 0x4000) { + // Stream start (Payload Unit Start Indicator) + uchar *d = (uint8_t*)buf; + d += 4; + // pointer to payload + if (buf[3] & 0x20) + d += d[0] + 1; + // Skip adaption field + if (buf[3] & 0x10) { + // Payload present + if ((d[0] == 0) && (d[1] == 0) && (d[2] == 1)) { + // PES packet start + int sid = d[3]; + // Stream ID + if ((sid >= 0xC0) && (sid <= 0xDF)) { + if (pid < Apid) { + Apid = pid; + numApids = 1; + } + else if (pid == Apid) + ++numApids; + } + else if ((sid >= 0xE0) && (sid <= 0xEF)) { + if (pid < Vpid) { + Vpid = pid; + numVpids = 1; + } + else if (pid == Vpid) + ++numVpids; + } + } + if (numVpids > 10 && numApids > 5) { + if (!Channels.Lock(true, 10)) + return; + debug("cPidScanner::Process(): Vpid=0x%04X, Apid=0x%04X\n", Vpid, Apid); + cChannel *IptvChannel = Channels.GetByChannelID(channel.GetChannelID()); + int Ppid = 0; + 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 Tpid = 0; + Apids[0] = Apid; + IptvChannel->SetPids(Vpid, Ppid, Apids, ALangs, Dpids, DLangs, Spids, SLangs, Tpid); + Channels.Unlock(); + process = false; + } + } + } +} + +void cPidScanner::SetChannel(const cChannel *Channel) +{ + if (Channel) { + debug("cPidScanner::SetChannel(): %s\n", Channel->PluginParam()); + channel = *Channel; + } + else { + debug("cPidScanner::SetChannel()\n"); + channel = cChannel(); + } + Vpid = 0xFFFF; + numVpids = 0; + Apid = 0xFFFF; + numApids = 0; + process = true; +} diff --git a/pidscanner.h b/pidscanner.h new file mode 100644 index 0000000..ec60fc6 --- /dev/null +++ b/pidscanner.h @@ -0,0 +1,30 @@ +/* + * pidscanner.h: IPTV plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: pidscanner.h,v 1.1 2008/01/30 22:41:59 rahrenbe Exp $ + */ + +#ifndef __PIDSCANNER_H +#define __PIDSCANNER_H + +#include + +class cPidScanner { +private: + cChannel channel; + bool process; + int Vpid; + int Apid; + int numVpids; + int numApids; + +public: + cPidScanner(void); + ~cPidScanner(); + void Process(const uint8_t* buf); + void SetChannel(const cChannel *Channel); +}; + +#endif // __PIDSCANNER_H