diff --git a/Makefile b/Makefile index 4a2f7f2..9ba0646 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # # Makefile for a Video Disk Recorder plugin # -# $Id: Makefile,v 1.14 2007/10/01 18:14:57 rahrenbe Exp $ +# $Id: Makefile,v 1.15 2007/10/05 19:00:44 ajhseppa Exp $ # Debugging on/off #IPTV_DEBUG = 1 @@ -58,7 +58,8 @@ endif ### The object files (add further files here): OBJS = $(PLUGIN).o config.o setup.o device.o streamer.o protocoludp.o \ - protocolhttp.o protocolfile.o sectionfilter.o sidscanner.o + protocolhttp.o protocolfile.o sectionfilter.o sidscanner.o \ + statistics.o ### The main target: diff --git a/device.c b/device.c index d5b30f2..8545fcd 100644 --- a/device.c +++ b/device.c @@ -3,12 +3,13 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: device.c,v 1.49 2007/10/01 18:14:57 rahrenbe Exp $ + * $Id: device.c,v 1.50 2007/10/05 19:00:44 ajhseppa Exp $ */ #include "common.h" #include "config.h" #include "device.h" +#include "sectionfilter.h" #define IPTV_MAX_DEVICES 8 @@ -299,6 +300,9 @@ bool cIptvDevice::GetTSPacket(uchar *&Data) } isPacketDelivered = true; Data = p; + // Increment statistics counter + dataBytes += Count; + UpdateActivePids(ts_pid(p), payload(p)); // Run the data through all filters for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) { if (secfilters[i]) @@ -310,4 +314,3 @@ bool cIptvDevice::GetTSPacket(uchar *&Data) Data = NULL; return true; } - diff --git a/device.h b/device.h index 1c74085..11f5619 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.23 2007/10/01 18:14:57 rahrenbe Exp $ + * $Id: device.h,v 1.24 2007/10/05 19:00:44 ajhseppa Exp $ */ #ifndef __IPTV_DEVICE_H @@ -16,8 +16,9 @@ #include "streamer.h" #include "sectionfilter.h" #include "sidscanner.h" +#include "statistics.h" -class cIptvDevice : public cDevice { +class cIptvDevice : public cDevice, public cIptvDeviceStatistics { // static ones public: static unsigned int deviceCount; diff --git a/sectionfilter.c b/sectionfilter.c index 7e854fd..273cebc 100644 --- a/sectionfilter.c +++ b/sectionfilter.c @@ -3,13 +3,34 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: sectionfilter.c,v 1.6 2007/09/27 11:48:28 ajhseppa Exp $ + * $Id: sectionfilter.c,v 1.7 2007/10/05 19:00:44 ajhseppa Exp $ */ #include "sectionfilter.h" +#include "statistics.h" #define IPTV_FILTER_FILENAME "/tmp/vdr-iptv%d.filter%d" +uint16_t ts_pid(const uint8_t *buf) +{ + return ((buf[1] & 0x1f) << 8) + buf[2]; +} + +uint8_t payload(const uint8_t *tsp) +{ + if (!(tsp[3] & 0x10)) // no payload? + return 0; + + if (tsp[3] & 0x20) { // adaptation field? + if (tsp[4] > 183) // corrupted data? + return 0; + else + return 184 - 1 - tsp[4]; + } + + return 184; +} + cIptvSectionFilter::cIptvSectionFilter(int Index, int devInd, u_short Pid, u_char Tid, u_char Mask) : pusi_seen(0), @@ -93,26 +114,6 @@ inline uint16_t cIptvSectionFilter::section_length(const uint8_t *buf) return 3 + ((buf[1] & 0x0f) << 8) + buf[2]; } -inline uint16_t cIptvSectionFilter::ts_pid(const uint8_t *buf) -{ - return ((buf[1] & 0x1f) << 8) + buf[2]; -} - -inline uint8_t cIptvSectionFilter::payload(const uint8_t *tsp) -{ - if (!(tsp[3] & 0x10)) // no payload? - return 0; - - if (tsp[3] & 0x20) { // adaptation field? - if (tsp[4] > 183) // corrupted data? - return 0; - else - return 184 - 1 - tsp[4]; - } - - return 184; -} - int cIptvSectionFilter::dvb_dmxdev_section_callback(const uint8_t *buffer1, size_t buffer1_len, const uint8_t *buffer2, size_t buffer2_len, enum dmx_success success) @@ -143,6 +144,9 @@ int cIptvSectionFilter::dvb_dmxdev_section_callback(const uint8_t *buffer1, size char tmp[64]; error("ERROR: write(): %s", strerror_r(errno, tmp, sizeof(tmp))); } + // Increment statistics counters + filteredData += retval; + ++numberOfCalls; } #ifdef DEBUG_PRINTF else if (retval) diff --git a/sectionfilter.h b/sectionfilter.h index 19a6b05..8dee4a3 100644 --- a/sectionfilter.h +++ b/sectionfilter.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: sectionfilter.h,v 1.2 2007/09/24 17:20:58 rahrenbe Exp $ + * $Id: sectionfilter.h,v 1.3 2007/10/05 19:00:44 ajhseppa Exp $ */ #ifndef __IPTV_SECTIONFILTER_H @@ -23,6 +23,7 @@ #include #include "common.h" +#include "statistics.h" #ifndef DMX_MAX_FILTER_SIZE #define DMX_MAX_FILTER_SIZE 18 @@ -37,7 +38,10 @@ #define DVB_DEMUX_MASK_MAX 18 -class cIptvSectionFilter { +uint16_t ts_pid(const uint8_t *buf); +uint8_t payload(const uint8_t *tsp); + +class cIptvSectionFilter : public cIptvSectionStatistics { private: enum dmx_success { DMX_OK = 0, /* Received Ok */ @@ -76,8 +80,6 @@ private: char pipeName[128]; inline uint16_t section_length(const uint8_t *buf); - inline uint16_t ts_pid(const uint8_t *buf); - inline uint8_t payload(const uint8_t *tsp); int dvb_dmxdev_section_callback(const uint8_t *buffer1, size_t buffer1_len, diff --git a/statisticif.h b/statisticif.h new file mode 100644 index 0000000..a02d9b6 --- /dev/null +++ b/statisticif.h @@ -0,0 +1,23 @@ +/* + * statisticif.h: IPTV plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: statisticif.h,v 1.1 2007/10/05 19:00:44 ajhseppa Exp $ + */ + +#ifndef __IPTV_STATISTICIF_H +#define __IPTV_STATISTICIF_H + +class cIptvStatisticIf { +public: + cIptvStatisticIf() {} + virtual ~cIptvStatisticIf() {} + virtual char* GetStatistic() = 0; + +private: + cIptvStatisticIf(const cIptvStatisticIf&); + cIptvStatisticIf& operator=(const cIptvStatisticIf&); +}; + +#endif // __IPTV_STATISTICIF_H diff --git a/statistics.c b/statistics.c new file mode 100644 index 0000000..172fdff --- /dev/null +++ b/statistics.c @@ -0,0 +1,130 @@ +/* + * statistics.c: IPTV plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: statistics.c,v 1.1 2007/10/05 19:00:44 ajhseppa Exp $ + */ + +#include "common.h" +#include "statistics.h" + +// Section statistic class +cIptvSectionStatistics::cIptvSectionStatistics() + : filteredData(0), + numberOfCalls(0) +{ + debug("cIptvSectionStatistics::cIptvSectionStatistics()\n"); +} + +cIptvSectionStatistics::~cIptvSectionStatistics() +{ + debug("cIptvSectionStatistics::~cIptvSectionStatistics()\n"); +} + +char* cIptvSectionStatistics::GetStatistic() +{ + debug("cIptvSectionStatistics::GetStatistic()\n"); + char* retval; + asprintf(&retval, "Filtered data: %ld Data packets passed: %ld", + filteredData, numberOfCalls); + + filteredData = numberOfCalls = 0; + + return retval; +} + +// Device statistic class +cIptvDeviceStatistics::cIptvDeviceStatistics() + : dataBytes(0) +{ + debug("cIptvDeviceStatistics::cIptvDeviceStatistics()\n"); + memset(mostActivePids, '\0', sizeof(mostActivePids)); +} + +cIptvDeviceStatistics::~cIptvDeviceStatistics() +{ + debug("cIptvDeviceStatistics::~cIptvDeviceStatistics()\n"); +} + +char* cIptvDeviceStatistics::GetStatistic() +{ + debug("cIptvDeviceStatistics::GetStatistic()\n"); + char* retval; + asprintf(&retval, "Stream data bytes: %ld, Active Pids: 1: Pid %d %ld 2: Pid %d %ld 3: %d %ld", dataBytes, mostActivePids[0].pid, + mostActivePids[0].DataAmount, mostActivePids[1].pid, + mostActivePids[1].DataAmount, mostActivePids[2].pid, + mostActivePids[2].DataAmount); + + dataBytes = 0; + memset(&mostActivePids, '\0', sizeof(mostActivePids)); + + return retval; +} + +int SortFunc(const void* data1, const void* data2) +{ + debug("cIptvDeviceStatistics::SortFunc()\n"); + + pidStruct *comp1 = (pidStruct*)data1; + pidStruct *comp2 = (pidStruct*)data2; + + if (comp1->DataAmount > comp2->DataAmount) + return 1; + + if (comp1->DataAmount < comp2->DataAmount) + return -1; + + return 0; +} + +void cIptvDeviceStatistics::UpdateActivePids(u_short pid, long payload) +{ + debug("cIptvDeviceStatistics::UpdateActivePids()\n"); + + const int numberOfElements = sizeof(mostActivePids) / sizeof(pidStruct); + + // If our statistic already is in the array, update it and quit + for (int i = 0; i < numberOfElements; ++i) { + if (mostActivePids[i].pid == pid) { + mostActivePids[i].DataAmount += payload; + // Now re-sort the array and quit + qsort(&mostActivePids, numberOfElements, sizeof(pidStruct), SortFunc); + return; + } + } + + // Apparently our pid isn't in the array. Replace the last element with this + // one if new payload is greater + if (mostActivePids[numberOfElements - 1].DataAmount < payload) { + mostActivePids[numberOfElements - 1].pid = pid; + mostActivePids[numberOfElements - 1].DataAmount = payload; + } + + // Re-sort + qsort(&mostActivePids, numberOfElements, sizeof(pidStruct), SortFunc); +} + + +// Streamer statistic class +cIptvStreamerStatistics::cIptvStreamerStatistics() + : dataBytes(0) +{ + debug("cIptvStreamerStatistics::cIptvStreamerStatistics()\n"); +} + +cIptvStreamerStatistics::~cIptvStreamerStatistics() +{ + debug("cIptvStreamerStatistics::~cIptvStreamerStatistics()\n"); +} + +char* cIptvStreamerStatistics::GetStatistic() +{ + debug("cIptvStreamerStatistics::GetStatistic()\n"); + char* retval; + asprintf(&retval, "Stream data bytes: %ld", dataBytes); + + dataBytes = 0; + + return retval; +} diff --git a/statistics.h b/statistics.h new file mode 100644 index 0000000..675f96d --- /dev/null +++ b/statistics.h @@ -0,0 +1,64 @@ +/* + * statistics.h: IPTV plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: statistics.h,v 1.1 2007/10/05 19:00:44 ajhseppa Exp $ + */ + +#ifndef __IPTV_STATISTICS_H +#define __IPTV_STATISTICS_H + +#include "statisticif.h" + +struct pidStruct { + u_short pid; + long DataAmount; +}; + +// Section statistics +class cIptvSectionStatistics : public cIptvStatisticIf { +protected: + long filteredData; + long numberOfCalls; + +public: + cIptvSectionStatistics(); + virtual ~cIptvSectionStatistics(); + + char* GetStatistic(); +}; + +// Device statistics +class cIptvDeviceStatistics : public cIptvStatisticIf { +protected: + long dataBytes; + +public: + cIptvDeviceStatistics(); + virtual ~cIptvDeviceStatistics(); + + char* GetStatistic(); + +protected: + void UpdateActivePids(u_short pid, long payload); + +private: + pidStruct mostActivePids[10]; + +}; + +// Streamer statistics +class cIptvStreamerStatistics : public cIptvStatisticIf { +protected: + long dataBytes; + +public: + cIptvStreamerStatistics(); + virtual ~cIptvStreamerStatistics(); + + char* GetStatistic(); +}; + +#endif // __IPTV_STATISTICS_H + diff --git a/streamer.c b/streamer.c index 9c4ec83..72679d5 100644 --- a/streamer.c +++ b/streamer.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: streamer.c,v 1.16 2007/09/29 16:21:05 rahrenbe Exp $ + * $Id: streamer.c,v 1.17 2007/10/05 19:00:44 ajhseppa Exp $ */ #include @@ -37,6 +37,7 @@ void cIptvStreamer::Action(void) unsigned char *buffer = NULL; int length = protocol->Read(&buffer); if (length >= 0) { + dataBytes += length; // Statistics update mutex->Lock(); int p = ringBuffer->Put(buffer, length); if (p != length && Running()) diff --git a/streamer.h b/streamer.h index 9ae5e71..b75e524 100644 --- a/streamer.h +++ b/streamer.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: streamer.h,v 1.7 2007/09/29 16:21:05 rahrenbe Exp $ + * $Id: streamer.h,v 1.8 2007/10/05 19:00:44 ajhseppa Exp $ */ #ifndef __IPTV_STREAMER_H @@ -15,8 +15,9 @@ #include #include "protocolif.h" +#include "statistics.h" -class cIptvStreamer : public cThread { +class cIptvStreamer : public cThread, public cIptvStreamerStatistics { private: cRingBufferLinear* ringBuffer; cMutex* mutex;