summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--p2pvr/daemon/maintenance/events.cpp19
-rw-r--r--p2pvr/daemon/maintenance/network.cpp8
-rw-r--r--p2pvr/daemon/maintenance/services.cpp9
-rw-r--r--p2pvr/daemon/sql/si/allDeliveriesTransportStreamId.sql2
-rw-r--r--p2pvr/daemon/sql/si/serviceIdsWithEit.sql4
-rw-r--r--p2pvr/daemon/unittests/mockDevices.cpp2
-rw-r--r--p2pvr/daemon/unittests/testErrorHandling.cpp7
-rw-r--r--p2pvr/daemon/unittests/testMaint.cpp32
-rw-r--r--p2pvr/devices/Jamfile.jam28
-rw-r--r--p2pvr/devices/mockData.cpp75
-rw-r--r--p2pvr/devices/mockData.h35
-rw-r--r--p2pvr/devices/mockDataValidate.cpp126
-rw-r--r--p2pvr/devices/mockTuner.cpp68
-rw-r--r--p2pvr/devices/mockTuner.h9
-rw-r--r--p2pvr/devices/sampleSiData/events1.datxzbin1112857 -> 1532360 bytes
-rw-r--r--p2pvr/devices/sampleSiData/events2.datxzbin1108428 -> 1542916 bytes
-rw-r--r--p2pvr/devices/sampleSiData/network.datxzbin1244 -> 1532 bytes
-rw-r--r--p2pvr/devices/sampleSiData/services.datxzbin2392 -> 3164 bytes
-rw-r--r--p2pvr/devices/tuner.cpp5
-rw-r--r--p2pvr/devices/tuner.h1
-rw-r--r--p2pvr/devices/tunerSendSi.cpp6
-rw-r--r--p2pvr/devices/tunerSendSi.h1
-rw-r--r--p2pvr/devices/tunerSendTs.cpp5
-rw-r--r--p2pvr/devices/tunerSendTs.h1
-rw-r--r--p2pvr/dvb/siParsers/event.cpp6
-rw-r--r--p2pvr/dvb/siParsers/event.h1
-rw-r--r--p2pvr/dvb/siParsers/network.cpp1
-rw-r--r--p2pvr/dvb/siParsers/programAssociation.cpp1
-rw-r--r--p2pvr/dvb/siParsers/programMap.cpp1
-rw-r--r--p2pvr/dvb/siParsers/service.cpp6
-rw-r--r--p2pvr/dvb/siParsers/service.h1
-rw-r--r--p2pvr/dvb/siParsers/table.cpp15
-rw-r--r--p2pvr/dvb/siParsers/table.h12
-rw-r--r--p2pvr/dvb/siParsers/table.impl.h27
-rw-r--r--p2pvr/dvb/unittests/createSamples.cpp63
-rw-r--r--p2pvr/dvb/unittests/network.datbin0 -> 2809 bytes
-rw-r--r--p2pvr/dvb/unittests/services.datbin0 -> 11274 bytes
37 files changed, 436 insertions, 141 deletions
diff --git a/p2pvr/daemon/maintenance/events.cpp b/p2pvr/daemon/maintenance/events.cpp
index 2dd91af..fbdeb51 100644
--- a/p2pvr/daemon/maintenance/events.cpp
+++ b/p2pvr/daemon/maintenance/events.cpp
@@ -8,13 +8,15 @@
#include <sqlWriter.h>
#include <slicer/modelPartsTypes.impl.h>
#include "sql/maintenance/pruneEvents.sql.h"
+#include "sql/si/serviceIdsWithEit.sql.h"
namespace P2PVR {
class SiEventsStream : public Slicer::Stream<::DVBSI::EventPtr> {
private:
class SiEventsHandler : public DVBSI::SiEpgParser {
public:
- SiEventsHandler(const Consumer & c, IceTray::Logging::LoggerPtr l) :
+ SiEventsHandler(const Consumer & c, DB::Connection * d, IceTray::Logging::LoggerPtr l) :
+ DVBSI::SiEpgParser(getIds(d)),
consumer(c),
logger(l)
{
@@ -28,14 +30,22 @@ class SiEventsStream : public Slicer::Stream<::DVBSI::EventPtr> {
return false;
}
+ static RequiredContentIds getIds(DB::Connection * db)
+ {
+ auto sel = sql::si::serviceIdsWithEit.select(db);
+ auto ids = Slicer::DeserializeAny<Slicer::SqlSelectDeserializer, std::vector<Ice::Int>>(*sel);
+ return {ids.begin(), ids.end()};
+ }
+
private:
const Consumer & consumer;
const IceTray::Logging::LoggerPtr logger;
};
public:
- SiEventsStream(const Ice::Current & i, IceTray::Logging::LoggerPtr l) :
+ SiEventsStream(const Ice::Current & i, DB::Connection * d, IceTray::Logging::LoggerPtr l) :
ice(i),
+ db(d),
logger(l)
{
}
@@ -55,13 +65,14 @@ class SiEventsStream : public Slicer::Stream<::DVBSI::EventPtr> {
}
logger->messagebf(LOG::DEBUG, "%s: Getting a tuner", __PRETTY_FUNCTION__);
logger->messagebf(LOG::DEBUG, "%s: Fetching events", __PRETTY_FUNCTION__);
- TemporaryIceAdapterObject<RawDataClient> parser(ice.adapter, new SiEventsHandler(ch, logger));
+ TemporaryIceAdapterObject<RawDataClient> parser(ice.adapter, new SiEventsHandler(ch, db, logger));
devs->SendEventInformation(delivery, parser);
}
private:
const Ice::Current & ice;
+ DB::Connection * db;
const IceTray::Logging::LoggerPtr logger;
};
@@ -71,7 +82,7 @@ MaintenanceI::UpdateEvents(const Ice::Current & ice)
auto dbc = db->get();
auto ic = ice.adapter->getCommunicator();
- SiEventsStream stream(ice, logger);
+ SiEventsStream stream(ice, dbc.get(), logger);
DB::TransactionScope tx(dbc.get());
DB::TablePatch tp;
diff --git a/p2pvr/daemon/maintenance/network.cpp b/p2pvr/daemon/maintenance/network.cpp
index c514175..2f74050 100644
--- a/p2pvr/daemon/maintenance/network.cpp
+++ b/p2pvr/daemon/maintenance/network.cpp
@@ -43,7 +43,9 @@ class SiNetworkInformationMerger : public DVBSI::SiNetworkInformationParser {
::DVBSI::NetworkServiceList services;
for (const auto & ts : n->TransportStreams) {
for (const auto & s : ts->Services) {
- services.push_back(s);
+ if (std::find_if(services.begin(), services.end(), [&s](const auto & es) { return es.ServiceId == s.ServiceId; }) == services.end()) {
+ services.push_back(s);
+ }
}
}
DB::TablePatch mergeServices;
@@ -62,7 +64,9 @@ class SiNetworkInformationMerger : public DVBSI::SiNetworkInformationParser {
std::vector<Delivery> dels;
for (const auto & s : n->TransportStreams) {
if (auto d = s.get()->*member) {
- dels.push_back(d);
+ if (std::find_if(dels.begin(), dels.end(), [&d](const auto & ed) { return ed->Frequency == d->Frequency; }) == dels.end()) {
+ dels.push_back(d);
+ }
}
}
Slicer::SerializeAny<Slicer::SqlTablePatchSerializer>(dels, dbc, tp);
diff --git a/p2pvr/daemon/maintenance/services.cpp b/p2pvr/daemon/maintenance/services.cpp
index 12b23ce..288dd99 100644
--- a/p2pvr/daemon/maintenance/services.cpp
+++ b/p2pvr/daemon/maintenance/services.cpp
@@ -6,11 +6,13 @@
#include <slicer/slicer.h>
#include <db/sqlTablePatchSerializer.h>
#include <tablepatch.h>
+#include <sql/si/allDeliveriesTransportStreamId.sql.h>
namespace P2PVR {
class SiServicesMerger : public DVBSI::SiServicesParser {
public:
SiServicesMerger(IceTray::Logging::LoggerPtr l, DB::Connection * d) :
+ DVBSI::SiServicesParser(getIds(d)),
logger(l),
dbc(d)
{
@@ -34,6 +36,13 @@ class SiServicesMerger : public DVBSI::SiServicesParser {
return false;
}
+ static RequiredContentIds getIds(DB::Connection * db)
+ {
+ auto sel = sql::si::allDeliveriesTransportStreamId.select(db);
+ auto ids = Slicer::DeserializeAny<Slicer::SqlSelectDeserializer, std::vector<Ice::Int>>(*sel);
+ return {ids.begin(), ids.end()};
+ }
+
private:
IceTray::Logging::LoggerPtr logger;
DB::Connection * dbc;
diff --git a/p2pvr/daemon/sql/si/allDeliveriesTransportStreamId.sql b/p2pvr/daemon/sql/si/allDeliveriesTransportStreamId.sql
new file mode 100644
index 0000000..55ff3c8
--- /dev/null
+++ b/p2pvr/daemon/sql/si/allDeliveriesTransportStreamId.sql
@@ -0,0 +1,2 @@
+SELECT transportStreamId
+FROM allDeliveries
diff --git a/p2pvr/daemon/sql/si/serviceIdsWithEit.sql b/p2pvr/daemon/sql/si/serviceIdsWithEit.sql
new file mode 100644
index 0000000..ca4883d
--- /dev/null
+++ b/p2pvr/daemon/sql/si/serviceIdsWithEit.sql
@@ -0,0 +1,4 @@
+SELECT s.serviceId
+FROM allDeliveries d, services s
+WHERE d.transportStreamId = s.transportStreamId
+AND s.eitschedule
diff --git a/p2pvr/daemon/unittests/mockDevices.cpp b/p2pvr/daemon/unittests/mockDevices.cpp
index 5ff2cb9..e5ec6a4 100644
--- a/p2pvr/daemon/unittests/mockDevices.cpp
+++ b/p2pvr/daemon/unittests/mockDevices.cpp
@@ -13,7 +13,7 @@ namespace P2PVR {
TunerPtr
MockDevices::openTuner(const boost::filesystem::path & path) const
{
- return new MockTuner(path, ic);
+ return new P2PVR::DVB::Testing::MockTuner(path, ic);
}
}
}
diff --git a/p2pvr/daemon/unittests/testErrorHandling.cpp b/p2pvr/daemon/unittests/testErrorHandling.cpp
index 80af051..5b53999 100644
--- a/p2pvr/daemon/unittests/testErrorHandling.cpp
+++ b/p2pvr/daemon/unittests/testErrorHandling.cpp
@@ -32,10 +32,15 @@ class Core : public StandardMockDatabase {
class TestDataClient : public RawDataClient {
public:
+ TestDataClient() :
+ packets(3)
+ {
+ }
virtual bool NewData(const Data &, const Ice::Current &) override
{
- return false;
+ return !--packets;
}
+ unsigned int packets;
};
class FailingTestClient : public RawDataClient {
diff --git a/p2pvr/daemon/unittests/testMaint.cpp b/p2pvr/daemon/unittests/testMaint.cpp
index e918d74..a166d04 100644
--- a/p2pvr/daemon/unittests/testMaint.cpp
+++ b/p2pvr/daemon/unittests/testMaint.cpp
@@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE( GetDeliveryForTransport )
BOOST_AUTO_TEST_CASE( GetServices_stubs )
{
auto services = si->GetServices();
- BOOST_REQUIRE_EQUAL(services.size(), 145);
+ BOOST_REQUIRE_EQUAL(services.size(), 180);
BOOST_REQUIRE_EQUAL(services[0]->ServiceId, 4170);
BOOST_REQUIRE_EQUAL(services[0]->TransportStreamId, 4170);
// Definitely a stub
@@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE( update_services )
BOOST_AUTO_TEST_CASE( GetServices )
{
auto services = si->GetServices();
- BOOST_REQUIRE_EQUAL(services.size(), 145);
+ BOOST_REQUIRE_EQUAL(services.size(), 180);
BOOST_REQUIRE_EQUAL(services[0]->ServiceId, 4170);
BOOST_REQUIRE_EQUAL(services[0]->TransportStreamId, 4170);
BOOST_REQUIRE_EQUAL(services[0]->Name, "BBC ONE Yorks");
@@ -186,17 +186,17 @@ BOOST_AUTO_TEST_CASE( update_events )
auto db = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("postgres"));
BOOST_TEST_CHECKPOINT("Write first events");
- MockTuner::SetEventsSet(0);
+ P2PVR::DVB::Testing::MockTuner::SetEventsSet(0);
maint->UpdateEvents();
auto dayOneEvents = si->EventSearch(IceUtil::Optional<std::string>(), IceUtil::Optional<int>(),
- Common::DateTime {2014, 12, 18, 3, 0}, Common::DateTime {2014, 12, 19, 3, 0});
- BOOST_REQUIRE_EQUAL(dayOneEvents.size(), 3345);
- BOOST_REQUIRE(si->GetEvent(14448, 27052));
+ Common::DateTime {2017, 8, 22, 3, 0}, Common::DateTime {2017, 8, 23, 3, 0});
+ BOOST_REQUIRE_EQUAL(dayOneEvents.size(), 3023);
+ BOOST_REQUIRE(si->GetEvent(15048, 29747));
BOOST_REQUIRE_THROW(si->GetEvent(15856, 3591), P2PVR::NotFound);
BOOST_TEST_CHECKPOINT("Fake some recorded stuff");
- auto keyEvent1 = si->GetEvent(25664, 55689);
- auto keyEvent2 = si->GetEvent(24256, 1014);
+ auto keyEvent1 = dayOneEvents[1000];
+ auto keyEvent2 = dayOneEvents[2000];
db->execute("INSERT INTO schedules(repeats) VALUES(false)");
auto irecorded = boost::shared_ptr<DB::ModifyCommand>(
db->newModifyCommand("INSERT INTO recorded(scheduleId, eventUid) VALUES(?, ?)"));
@@ -211,21 +211,23 @@ BOOST_AUTO_TEST_CASE( update_events )
BOOST_REQUIRE(keyEvent1);
BOOST_REQUIRE(keyEvent2);
BOOST_REQUIRE(keyEvent1->Current);
- BOOST_REQUIRE_EQUAL(keyEvent1->StartTime, Common::DateTime({2014, 12, 18, 21, 0}));
+ BOOST_REQUIRE_EQUAL(keyEvent1->StartTime, Common::DateTime({2017, 8, 22, 5, 0}));
BOOST_REQUIRE(keyEvent2->Current);
- BOOST_REQUIRE_EQUAL(keyEvent2->StartTime, Common::DateTime({2014, 12, 17, 5, 30}));
+ BOOST_REQUIRE_EQUAL(keyEvent2->StartTime, Common::DateTime({2017, 8, 22, 6, 30}));
BOOST_TEST_CHECKPOINT("Write second events");
- MockTuner::SetEventsSet(1);
+ P2PVR::DVB::Testing::MockTuner::SetEventsSet(1);
maint->UpdateEvents();
- BOOST_REQUIRE_THROW(si->GetEvent(14448, 27052), P2PVR::NotFound);
- BOOST_REQUIRE(si->GetEvent(15856, 3591));
+ auto dayTwoEvents = si->EventSearch(IceUtil::Optional<std::string>(), IceUtil::Optional<int>(),
+ Common::DateTime {2017, 8, 23, 3, 0}, Common::DateTime {2017, 8, 24, 3, 0});
+ BOOST_REQUIRE_THROW(si->GetEvent(15064, 22), P2PVR::NotFound);
+ BOOST_REQUIRE(si->GetEvent(15048, 29791));
BOOST_TEST_CHECKPOINT("Check our faked stuff is still there and right");
auto dayOneEventsOnDayTwo = si->EventSearch(IceUtil::Optional<std::string>(), IceUtil::Optional<int>(),
- Common::DateTime {2014, 12, 18, 3, 0}, Common::DateTime {2014, 12, 19, 3, 0});
+ Common::DateTime {2017, 8, 22, 3, 0}, Common::DateTime {2017, 8, 23, 3, 0});
// Some datetime range overlap, but most are gone
- BOOST_REQUIRE_EQUAL(dayOneEventsOnDayTwo.size(), 373);
+ BOOST_REQUIRE_EQUAL(dayOneEventsOnDayTwo.size(), 316);
BOOST_REQUIRE_EQUAL(std::count_if(dayOneEventsOnDayTwo.begin(), dayOneEventsOnDayTwo.end(),
[](const P2PVR::EventPtr & e) {
return (e->ServiceId == 25664 && e->EventId == 55689)
diff --git a/p2pvr/devices/Jamfile.jam b/p2pvr/devices/Jamfile.jam
index 92573d5..bb9f70e 100644
--- a/p2pvr/devices/Jamfile.jam
+++ b/p2pvr/devices/Jamfile.jam
@@ -1,5 +1,6 @@
import type ;
import generators ;
+import testing ;
lib boost_system ;
lib boost_thread ;
@@ -8,7 +9,7 @@ lib boost_program_options ;
lib lzma ;
lib p2pvrdevices :
- [ glob-tree *.cpp : mockTuner.cpp ]
+ [ glob-tree *.cpp : mock*.cpp ]
:
<library>boost_system
<library>boost_filesystem
@@ -40,9 +41,8 @@ IMPORT $(__name__) : datxz.embed.asm : : datxz.embed.asm ;
lib p2pvrMockTuner :
mockTuner.cpp
- [ glob-tree *.datxz ]
:
- <library>lzma
+ <library>mockdata
<library>boost_system
<library>boost_thread
<library>boost_filesystem
@@ -60,3 +60,25 @@ lib p2pvrMockTuner :
<include>.
;
+lib mockdata :
+ mockData.cpp
+ [ glob-tree *.datxz ]
+ :
+ <library>lzma
+ <library>../ice//p2pvrice
+ <implicit-dependency>../ice//p2pvrice
+ ;
+
+run
+ mockDataValidate.cpp
+ : : :
+ <library>../dvb//p2pvrdvb
+ <library>../ice//p2pvrice
+ <library>..//adhocutil
+ <library>..//icetray
+ <library>mockdata
+ <library>boost_filesystem
+ <library>boost_system
+ <library>..//boost_utf
+ <define>BOOST_TEST_DYN_LINK
+ ;
diff --git a/p2pvr/devices/mockData.cpp b/p2pvr/devices/mockData.cpp
new file mode 100644
index 0000000..31a7100
--- /dev/null
+++ b/p2pvr/devices/mockData.cpp
@@ -0,0 +1,75 @@
+#include "mockData.h"
+#include <lzma.h>
+#include <Ice/Stream.h>
+#include <Ice/Initialize.h>
+#include <Ice/Communicator.h>
+
+#define ResourceFile(resource) \
+extern "C" { \
+ extern char resource##_start, resource##_end;\
+ extern unsigned int resource##_len; \
+}
+
+namespace P2PVR {
+ namespace DVB {
+ namespace Testing {
+ ResourceFile(network);
+ ResourceFile(services);
+ ResourceFile(events1);
+ ResourceFile(events2);
+ ResourceFile(pat);
+ ResourceFile(pmt);
+ ResourceFile(vid);
+
+ void LZMA_ASSERT(int ret_xz)
+ {
+ if (ret_xz != LZMA_OK) {
+ throw std::runtime_error("LZMA Decompressor error");
+ }
+ }
+
+ MockData::MockData(Ice::CommunicatorPtr c) : ic(c) { }
+
+ ::P2PVR::Data MockData::decompress(const char * front, size_t len) const
+ {
+ lzma_stream strm = LZMA_STREAM_INIT;
+ const uint32_t flags = LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED;
+ const uint64_t memory_limit = UINT64_MAX;
+ LZMA_ASSERT(lzma_stream_decoder(&strm, memory_limit, flags));
+ strm.next_in = (unsigned char *)front;
+ strm.avail_in = len;
+ uint8_t buf[BUFSIZ];
+
+ ::P2PVR::Data data;
+ data.reserve(len * 20);
+ do {
+ strm.next_out = buf;
+ strm.avail_out = BUFSIZ;
+ LZMA_ASSERT(lzma_code(&strm, LZMA_RUN));
+ for (auto idx = 0u; idx < BUFSIZ - strm.avail_out; idx += 1) {
+ data.push_back(buf[idx]);
+ }
+ } while (strm.avail_out == 0);
+ data.shrink_to_fit();
+ return data;
+ }
+
+ MockData::PacketList MockData::decompressAndRead(const char * front, size_t len) const
+ {
+ PacketList packets;
+ auto istrm = Ice::createInputStream(ic, decompress(front, len));
+ istrm->read(packets);
+ return packets;
+ }
+
+ MockData::PacketList MockData::getNetwork() const { return decompressAndRead(&network_start, network_len); }
+ MockData::PacketList MockData::getServices() const { return decompressAndRead(&services_start, services_len); }
+ MockData::PacketList MockData::getEvents1() const { return decompressAndRead(&events1_start, events1_len); }
+ MockData::PacketList MockData::getEvents2() const { return decompressAndRead(&events2_start, events2_len); }
+ MockData::PacketList MockData::getPAT() const { return decompressAndRead(&pat_start, pat_len); }
+ MockData::PacketList MockData::getPMT() const { return decompressAndRead(&pmt_start, pmt_len); }
+ MockData::PacketList MockData::getVideo() const { return decompressAndRead(&vid_start, vid_len); }
+ }
+ }
+}
+
diff --git a/p2pvr/devices/mockData.h b/p2pvr/devices/mockData.h
new file mode 100644
index 0000000..b86807d
--- /dev/null
+++ b/p2pvr/devices/mockData.h
@@ -0,0 +1,35 @@
+#ifndef P2PVR_DEVICES_MOCKDATA_H
+#define P2PVR_DEVICES_MOCKDATA_H
+
+#include <dvb.h>
+#include <list>
+#include <visibility.h>
+
+namespace P2PVR {
+ namespace DVB {
+ namespace Testing {
+ class DLL_PUBLIC MockData {
+ public:
+ typedef std::list<::P2PVR::Data> PacketList;
+
+ MockData(Ice::CommunicatorPtr);
+
+ PacketList getNetwork() const;
+ PacketList getServices() const;
+ PacketList getEvents1() const;
+ PacketList getEvents2() const;
+ PacketList getPMT() const;
+ PacketList getPAT() const;
+ PacketList getVideo() const;
+
+ protected:
+ DLL_PRIVATE ::P2PVR::Data decompress(const char * front, size_t len) const;
+ DLL_PRIVATE PacketList decompressAndRead(const char * front, size_t len) const;
+
+ Ice::CommunicatorPtr ic;
+ };
+ }
+ }
+}
+
+#endif
diff --git a/p2pvr/devices/mockDataValidate.cpp b/p2pvr/devices/mockDataValidate.cpp
new file mode 100644
index 0000000..6bd6b5b
--- /dev/null
+++ b/p2pvr/devices/mockDataValidate.cpp
@@ -0,0 +1,126 @@
+#define BOOST_TEST_MODULE ValidateTestData
+#include <boost/test/unit_test.hpp>
+#include <Ice/Communicator.h>
+#include <Ice/Initialize.h>
+#include <siParsers/event.h>
+#include <siParsers/network.h>
+#include <siParsers/programAssociation.h>
+#include <siParsers/programMap.h>
+#include <siParsers/service.h>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/bind.hpp>
+#include "mockData.h"
+
+BOOST_TEST_DONT_PRINT_LOG_VALUE(P2PVR::DVB::Testing::MockData::PacketList::const_iterator);
+
+template <typename SIObject, typename Base>
+class DiscardSI : public Base, public P2PVR::DVB::Testing::MockData {
+ public:
+ DiscardSI() :
+ MockData(Ice::initialize({}))
+ {
+ }
+ DiscardSI(const P2PVR::DVBSI::SiTableParserBase::RequiredContentIds & ids) :
+ Base(ids),
+ MockData(Ice::initialize({}))
+ {
+ }
+ virtual ~DiscardSI() { ic->destroy(); }
+
+ bool HandleTable(const SIObject & o) override
+ {
+ objects.push_back(o);
+ return false;
+ }
+
+ std::list<SIObject> validate(const P2PVR::DVB::Testing::MockData::PacketList & packets, unsigned int count, unsigned int objectCount)
+ {
+ BOOST_REQUIRE_EQUAL(count, packets.size());
+ auto ends = std::count_if(packets.begin(), packets.end(), [this](const auto & p) { return this->NewData(p, current); });
+ for (const auto & x : Base::parents) {
+ BOOST_TEST_INFO(x);
+ }
+ BOOST_REQUIRE_GT(ends, 0);
+ BOOST_REQUIRE_EQUAL(objectCount, objects.size());
+ return objects;
+ }
+
+ protected:
+ std::list<SIObject> objects;
+ Ice::Current current;
+};
+
+::DVBSI::NetworkPtr network;
+std::list<::DVBSI::TransportStreamPtr> streams;
+class NetworkTester : public DiscardSI<::DVBSI::NetworkPtr, ::P2PVR::DVBSI::SiNetworkInformationParser> {
+ public:
+};
+class ServiceTester : public DiscardSI<::DVBSI::TransportStreamPtr, ::P2PVR::DVBSI::SiServicesParser> {
+ public:
+ ServiceTester() : DiscardSI<::DVBSI::TransportStreamPtr, ::P2PVR::DVBSI::SiServicesParser>(getIds())
+ {
+ }
+ static P2PVR::DVBSI::SiTableParserBase::RequiredContentIds getIds()
+ {
+ P2PVR::DVBSI::SiTableParserBase::RequiredContentIds ids;
+ for (const auto & t : network->TransportStreams) {
+ if (t->Satellite || t->Cable || t->Terrestrial) {
+ ids.insert(t->TransportStreamId);
+ }
+ }
+ return ids;
+ }
+};
+class Events1Tester : public DiscardSI<::DVBSI::EventPtr, ::P2PVR::DVBSI::SiEpgParser> {
+ public:
+ Events1Tester() : DiscardSI<::DVBSI::EventPtr, ::P2PVR::DVBSI::SiEpgParser>(getIds())
+ {
+ }
+ static P2PVR::DVBSI::SiTableParserBase::RequiredContentIds getIds()
+ {
+ P2PVR::DVBSI::SiTableParserBase::RequiredContentIds ids;
+ for (const auto & st : streams) {
+ for (const auto & s : st->Services) {
+ if (s->EitSchedule) {
+ ids.insert(s->ServiceId);
+ }
+ }
+ }
+ return ids;
+ }
+};
+typedef DiscardSI<::DVBSI::ProgramMapPtr, ::P2PVR::DVBSI::SiProgramMapParser> PMTester;
+typedef DiscardSI<::P2PVR::DVBSI::ProgramAssociationMapPtr, ::P2PVR::DVBSI::SiProgramAssociationParser> PATester;
+
+BOOST_FIXTURE_TEST_SUITE(ValidateTestDataNetwork, NetworkTester);
+
+BOOST_AUTO_TEST_CASE( networkPackets )
+{
+ network = validate(getNetwork(), 3, 1).front();
+}
+
+BOOST_AUTO_TEST_SUITE_END();
+
+BOOST_FIXTURE_TEST_SUITE(ValidateTestDataService, ServiceTester);
+
+BOOST_AUTO_TEST_CASE( servicePackets )
+{
+ streams = validate(getServices(), 25, 8);
+}
+
+BOOST_AUTO_TEST_SUITE_END();
+
+BOOST_FIXTURE_TEST_SUITE(ValidateTestDataEvents1, Events1Tester);
+
+BOOST_AUTO_TEST_CASE( events1Packets )
+{
+ validate(getEvents1(), 64266, 23132);
+}
+
+BOOST_AUTO_TEST_CASE( events2Packets )
+{
+ validate(getEvents2(), 64847, 23126);
+}
+
+BOOST_AUTO_TEST_SUITE_END();
+
diff --git a/p2pvr/devices/mockTuner.cpp b/p2pvr/devices/mockTuner.cpp
index 8e772c6..706bbd9 100644
--- a/p2pvr/devices/mockTuner.cpp
+++ b/p2pvr/devices/mockTuner.cpp
@@ -12,24 +12,8 @@ extern "C" { \
static const Ice::ByteSeq resource(&resource##_start, &resource##_end);
namespace P2PVR {
+namespace DVB {
namespace Testing {
-void
-MockTuner::LZMA_ASSERT(int ret_xz)
-{
- if (ret_xz != LZMA_OK) {
- MockTuner::logger->messagebf(LOG::ERR, "%s: LZMA error (%d)", __PRETTY_FUNCTION__, ret_xz);
- throw P2PVR::DeviceError("LZMA", "Decompressor error", ret_xz);
- }
-}
-
-ResourceFile(network);
-ResourceFile(services);
-ResourceFile(events1);
-ResourceFile(events2);
-ResourceFile(pat);
-ResourceFile(pmt);
-ResourceFile(vid);
-
int MockTuner::eventSet = 0;
IceTray::Logging::LoggerPtr MockTuner::logger = LOGMANAGER()->getLogger<MockTuner>();
@@ -61,45 +45,11 @@ class MockFrontend : public DVB::Frontend {
MockTuner::MockTuner(const boost::filesystem::path & deviceFrontend, Ice::CommunicatorPtr c) :
TunerI(deviceFrontend, DVB::FrontendPtr(new MockFrontend(this, dvb_frontend_info(), logger))),
+ MockData(c),
ic(c)
{
}
-Ice::ByteSeq MockTuner::Decompress(const Ice::ByteSeq & dataxz)
-{
- lzma_stream strm = LZMA_STREAM_INIT;
- const uint32_t flags = LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED;
- const uint64_t memory_limit = UINT64_MAX;
- LZMA_ASSERT(lzma_stream_decoder(&strm, memory_limit, flags));
- strm.next_in = &dataxz.front();
- strm.avail_in = dataxz.size();
- uint8_t buf[BUFSIZ];
-
- Ice::ByteSeq data;
- data.reserve(dataxz.size() * 20);
- do {
- strm.next_out = buf;
- strm.avail_out = BUFSIZ;
- LZMA_ASSERT(lzma_code(&strm, LZMA_RUN));
- for (auto idx = 0u; idx < BUFSIZ - strm.avail_out; idx += 1) {
- data.push_back(buf[idx]);
- }
- } while (strm.avail_out == 0);
- data.shrink_to_fit();
- return data;
-}
-
-std::list<Ice::ByteSeq>
-MockTuner::DecompressAndRead(const Ice::ByteSeq & dataxz) const
-{
- logger->messagef(LOG::DEBUG, "%s: decompress %zu bytes", __PRETTY_FUNCTION__, dataxz.size());
- std::list<Ice::ByteSeq> packets;
- auto istrm = Ice::createInputStream(ic, Decompress(dataxz));
- istrm->read(packets);
- logger->messagef(LOG::DEBUG, "%s: read %zu packets", __PRETTY_FUNCTION__, packets.size());
- return packets;
-}
-
AdHoc::FileUtils::FileHandle
MockTuner::OpenDemux() const
{
@@ -111,6 +61,7 @@ MockTuner::iopoll(struct pollfd *fds, nfds_t nfds, int) const
{
auto & packets = selectedPackets[fds[0].fd];
if (packets.empty()) {
+ sleep(1);
return -2;
}
if (nfds > 0) {
@@ -169,19 +120,19 @@ MockTuner::RequestPID(int pid, int fh) const
logger->messagef(LOG::DEBUG, "%s: pid %x, fh %d", __PRETTY_FUNCTION__, pid, fh);
switch (pid) {
case 0: // pat
- selectedPackets[fh] = DecompressAndRead(pat);
+ selectedPackets[fh] = getPAT();
break;
case 0x10:
- selectedPackets[fh] = DecompressAndRead(network);
+ selectedPackets[fh] = getNetwork();
break;
case 0x11:
- selectedPackets[fh] = DecompressAndRead(services);
+ selectedPackets[fh] = getServices();
break;
case 0x12:
- selectedPackets[fh] = DecompressAndRead(eventSet == 0 ? events1 : events2);
+ selectedPackets[fh] = (eventSet == 0 ? getEvents1() : getEvents2());
break;
case 100: // sample pmt
- selectedPackets[fh] = DecompressAndRead(pmt);
+ selectedPackets[fh] = getPMT();
break;
}
}
@@ -190,9 +141,10 @@ void
MockTuner::RequestTS(const PacketIds & pids, int fh) const
{
logger->messagef(LOG::DEBUG, "%s: pids %zu, fh %d", __PRETTY_FUNCTION__, pids.size(), fh);
- selectedPackets[fh] = DecompressAndRead(vid);
+ selectedPackets[fh] = getVideo();
}
}
}
+}
diff --git a/p2pvr/devices/mockTuner.h b/p2pvr/devices/mockTuner.h
index 74578db..2277deb 100644
--- a/p2pvr/devices/mockTuner.h
+++ b/p2pvr/devices/mockTuner.h
@@ -7,10 +7,12 @@
#include <boost/thread.hpp>
#include <logger.h>
#include "tuner.h"
+#include "mockData.h"
namespace P2PVR {
+namespace DVB {
namespace Testing {
-class DLL_PUBLIC MockTuner : public DVB::TunerI {
+class DLL_PUBLIC MockTuner : public DVB::TunerI, MockData {
public:
MockTuner(const boost::filesystem::path & deviceFrontend, Ice::CommunicatorPtr);
@@ -25,10 +27,6 @@ class DLL_PUBLIC MockTuner : public DVB::TunerI {
ssize_t ioread(int fd, void *buf, size_t count) const override;
int ioselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) const override;
- static Ice::ByteSeq Decompress(const Ice::ByteSeq &);
- static void LZMA_ASSERT(int ret_xz);
- std::list<Ice::ByteSeq> DecompressAndRead(const Ice::ByteSeq &) const;
-
Ice::CommunicatorPtr ic;
// The open fh -> list of DVB packets
mutable std::map<int, std::list<Ice::ByteSeq>> selectedPackets;
@@ -38,6 +36,7 @@ class DLL_PUBLIC MockTuner : public DVB::TunerI {
};
}
}
+}
#endif
diff --git a/p2pvr/devices/sampleSiData/events1.datxz b/p2pvr/devices/sampleSiData/events1.datxz
index 43358a9..dff36dc 100644
--- a/p2pvr/devices/sampleSiData/events1.datxz
+++ b/p2pvr/devices/sampleSiData/events1.datxz
Binary files differ
diff --git a/p2pvr/devices/sampleSiData/events2.datxz b/p2pvr/devices/sampleSiData/events2.datxz
index b2fa9c2..035bfaf 100644
--- a/p2pvr/devices/sampleSiData/events2.datxz
+++ b/p2pvr/devices/sampleSiData/events2.datxz
Binary files differ
diff --git a/p2pvr/devices/sampleSiData/network.datxz b/p2pvr/devices/sampleSiData/network.datxz
index f2e74cd..b779e5f 100644
--- a/p2pvr/devices/sampleSiData/network.datxz
+++ b/p2pvr/devices/sampleSiData/network.datxz
Binary files differ
diff --git a/p2pvr/devices/sampleSiData/services.datxz b/p2pvr/devices/sampleSiData/services.datxz
index 0961e92..89509d7 100644
--- a/p2pvr/devices/sampleSiData/services.datxz
+++ b/p2pvr/devices/sampleSiData/services.datxz
Binary files differ
diff --git a/p2pvr/devices/tuner.cpp b/p2pvr/devices/tuner.cpp
index d3d0488..7358428 100644
--- a/p2pvr/devices/tuner.cpp
+++ b/p2pvr/devices/tuner.cpp
@@ -181,7 +181,6 @@ TunerI::ReadDemuxAndSend(AdHoc::FileUtils::FileHandle demux, const RawDataClient
// Wait for data to appear
switch (iopoll(&ufd, 1, options->DemuxReadTimeout)) {
case -2:
- //logger->messagef(LOG::DEBUG, "%s: All test data has been read... waiting...", __PRETTY_FUNCTION__);
break;
case -1:
logger->messagef(LOG::ERR, "%s: poll error reading demux (%d:%s)", __PRETTY_FUNCTION__, errno, strerror(errno));
@@ -203,12 +202,10 @@ TunerI::ReadDemuxAndSend(AdHoc::FileUtils::FileHandle demux, const RawDataClient
size_t n = nr;
buf.resize(n);
- logger->messagef(LOG::DEBUG, "%s: sending", __PRETTY_FUNCTION__);
client->NewData(buf);
- logger->messagef(LOG::DEBUG, "%s: sent", __PRETTY_FUNCTION__);
}
}
- } while (!client->IsFinished() && client->HasPending());
+ } while (!client->IsFinished());
auto packetsSent = client->PacketsSent();
client.reset();
logger->messagebf(LOG::DEBUG, "%s: end (sent %d packets)", __PRETTY_FUNCTION__, packetsSent);
diff --git a/p2pvr/devices/tuner.h b/p2pvr/devices/tuner.h
index 983d3ff..5a70e94 100644
--- a/p2pvr/devices/tuner.h
+++ b/p2pvr/devices/tuner.h
@@ -31,7 +31,6 @@ class DLL_PUBLIC TunerI : public Tuner {
virtual void NewData(const Data &) = 0;
virtual bool IsFinished() = 0;
- virtual bool HasPending() = 0;
uint64_t PacketsSent() const;
int fileHandle() const;
diff --git a/p2pvr/devices/tunerSendSi.cpp b/p2pvr/devices/tunerSendSi.cpp
index 822ec14..76eb2b7 100644
--- a/p2pvr/devices/tunerSendSi.cpp
+++ b/p2pvr/devices/tunerSendSi.cpp
@@ -66,12 +66,6 @@ SendSiStream::IsFinished()
}
bool
-SendSi::HasPending()
-{
- return !asyncs.empty();
-}
-
-bool
SendSi::IsValidSection(const Data & buf)
{
auto n = buf.size();
diff --git a/p2pvr/devices/tunerSendSi.h b/p2pvr/devices/tunerSendSi.h
index e6517c6..a2b8b4f 100644
--- a/p2pvr/devices/tunerSendSi.h
+++ b/p2pvr/devices/tunerSendSi.h
@@ -13,7 +13,6 @@ class SendSi : public TunerI::IDataSender {
void NewData(const P2PVR::Data &) override;
bool IsFinished() override;
- bool HasPending() override;
protected:
static bool crc32(const P2PVR::Data &);
diff --git a/p2pvr/devices/tunerSendTs.cpp b/p2pvr/devices/tunerSendTs.cpp
index 23bc3b4..0cddb93 100644
--- a/p2pvr/devices/tunerSendTs.cpp
+++ b/p2pvr/devices/tunerSendTs.cpp
@@ -77,11 +77,6 @@ SendTs::IsFinished()
}
}
-bool
-SendTs::HasPending()
-{
- return async;
-}
}
}
diff --git a/p2pvr/devices/tunerSendTs.h b/p2pvr/devices/tunerSendTs.h
index 5390882..a3f584c 100644
--- a/p2pvr/devices/tunerSendTs.h
+++ b/p2pvr/devices/tunerSendTs.h
@@ -13,7 +13,6 @@ class SendTs : public TunerI::IDataSender {
void NewData(const P2PVR::Data &);
bool IsFinished();
- bool HasPending();
private:
void sendBufferChunk();
diff --git a/p2pvr/dvb/siParsers/event.cpp b/p2pvr/dvb/siParsers/event.cpp
index a9ec158..26751a7 100644
--- a/p2pvr/dvb/siParsers/event.cpp
+++ b/p2pvr/dvb/siParsers/event.cpp
@@ -75,6 +75,11 @@ static Glib::RefPtr<Glib::Regex> seasonEpisodeRegex = Glib::Regex::create("[ ([]
static Glib::RefPtr<Glib::Regex> yearRegex = Glib::Regex::create("[[(]([0-9]{4})[ ).\\]]+");
static Glib::RefPtr<Glib::Regex> flagsRegex = Glib::Regex::create("[ []+([A-Z,]+)\\]");
+SiEpgParser::SiEpgParser(const RequiredContentIds & serviceIds) :
+ SiTableParser<EventInformation, ::DVBSI::EitInformationPtr, int>(serviceIds)
+{
+}
+
void
SiEpgParser::parseDescriptor_ShortEvent(::DVBSI::EventPtr current, const u_char * data)
{
@@ -264,6 +269,7 @@ SiEpgParser::ParseSiTable(const EventInformation * eit, const ::DVBSI::EitInform
HandleTable(e);
});
}
+template DLL_PUBLIC SiTableParser<EventInformation, ::DVBSI::EitInformationPtr, int>::SiTableParser(const RequiredContentIds &);
template bool DLL_PUBLIC SiTableParser<EventInformation, ::DVBSI::EitInformationPtr, int>::ParseInfoTable(const u_char * data, size_t len);
}
}
diff --git a/p2pvr/dvb/siParsers/event.h b/p2pvr/dvb/siParsers/event.h
index 73da292..8c98f93 100644
--- a/p2pvr/dvb/siParsers/event.h
+++ b/p2pvr/dvb/siParsers/event.h
@@ -18,6 +18,7 @@ struct EventInformation {
class DLL_PUBLIC SiEpgParser : public SiTableParser<EventInformation, ::DVBSI::EitInformationPtr, int> {
protected:
+ SiEpgParser(const RequiredContentIds & serviceIds);
bool CheckTableId(u_char tableId) const override;
int SectionNumberShift() const override { return 3; }
uint8_t FirstTableId(const EventInformation * ei) override { return (ei->header.tableid >= 0x60 ? 0x60 : 0x50); }
diff --git a/p2pvr/dvb/siParsers/network.cpp b/p2pvr/dvb/siParsers/network.cpp
index 9aa1525..ea39209 100644
--- a/p2pvr/dvb/siParsers/network.cpp
+++ b/p2pvr/dvb/siParsers/network.cpp
@@ -298,6 +298,7 @@ SiNetworkInformationParser::parseDescriptor_ServiceList(::DVBSI::NetworkTranspor
data += sizeof(ServiceListDescriptor);
}
}
+template DLL_PUBLIC SiTableParser<NetworkInformation, ::DVBSI::NetworkPtr, u_char>::SiTableParser();
template bool DLL_PUBLIC SiTableParser<NetworkInformation, ::DVBSI::NetworkPtr, u_char>::ParseInfoTable(const u_char * data, size_t len);
}
}
diff --git a/p2pvr/dvb/siParsers/programAssociation.cpp b/p2pvr/dvb/siParsers/programAssociation.cpp
index 43ef79d..64beff2 100644
--- a/p2pvr/dvb/siParsers/programAssociation.cpp
+++ b/p2pvr/dvb/siParsers/programAssociation.cpp
@@ -28,6 +28,7 @@ SiProgramAssociationParser::ParseSiTable(const ProgramAssociationSection * pas,
(*pam)[ntohs(sd->program_number)] = HILO(sd->pid);
});
}
+template DLL_PUBLIC SiTableParser<ProgramAssociationSection, ProgramAssociationMapPtr, int>::SiTableParser();
template bool DLL_PUBLIC SiTableParser<ProgramAssociationSection, ProgramAssociationMapPtr, int>::ParseInfoTable(const u_char * data, size_t len);
}
}
diff --git a/p2pvr/dvb/siParsers/programMap.cpp b/p2pvr/dvb/siParsers/programMap.cpp
index 492c2c2..3491e88 100644
--- a/p2pvr/dvb/siParsers/programMap.cpp
+++ b/p2pvr/dvb/siParsers/programMap.cpp
@@ -47,6 +47,7 @@ SiProgramMapParser::ParseSiTable(const struct ProgramMap * pm, const ::DVBSI::Pr
pms = ParseDescriptors<ProgramMapStream>(pms->data, HILO(pms->ES_info_length));
}
}
+template DLL_PUBLIC SiTableParser<ProgramMap, ::DVBSI::ProgramMapPtr, u_char>::SiTableParser();
template bool DLL_PUBLIC SiTableParser<ProgramMap, ::DVBSI::ProgramMapPtr, u_char>::ParseInfoTable(const u_char * data, size_t len);
}
}
diff --git a/p2pvr/dvb/siParsers/service.cpp b/p2pvr/dvb/siParsers/service.cpp
index a3fa464..9ee9341 100644
--- a/p2pvr/dvb/siParsers/service.cpp
+++ b/p2pvr/dvb/siParsers/service.cpp
@@ -28,6 +28,11 @@ struct ServiceDescriptor {
u_char data[];
} __attribute__((packed));
+SiServicesParser::SiServicesParser(const RequiredContentIds & transportStreamIds) :
+ SiTableParser<TransportStreamDescriptor, ::DVBSI::TransportStreamPtr, int>(transportStreamIds)
+{
+}
+
bool
SiServicesParser::CheckTableId(u_char tableId) const
{
@@ -69,6 +74,7 @@ SiServicesParser::parseDescriptor_DefaultAuthority(::DVBSI::ServicePtr s, const
{
s->DefaultAuthority = *convert((const char *)p, len);
}
+template DLL_PUBLIC SiTableParser<TransportStreamDescriptor, ::DVBSI::TransportStreamPtr, int>::SiTableParser(const RequiredContentIds &);
template bool DLL_PUBLIC SiTableParser<TransportStreamDescriptor, ::DVBSI::TransportStreamPtr, int>::ParseInfoTable(const u_char * data, size_t len);
}
}
diff --git a/p2pvr/dvb/siParsers/service.h b/p2pvr/dvb/siParsers/service.h
index 6834f52..b8c2b86 100644
--- a/p2pvr/dvb/siParsers/service.h
+++ b/p2pvr/dvb/siParsers/service.h
@@ -16,6 +16,7 @@ struct TransportStreamDescriptor {
class DLL_PUBLIC SiServicesParser : public SiTableParser<TransportStreamDescriptor, ::DVBSI::TransportStreamPtr, int> {
protected:
+ SiServicesParser(const RequiredContentIds & transportStreamIds);
bool CheckTableId(u_char tableId) const override;
void ParseSiTable(const struct TransportStreamDescriptor * nit, const ::DVBSI::TransportStreamPtr &) override;
diff --git a/p2pvr/dvb/siParsers/table.cpp b/p2pvr/dvb/siParsers/table.cpp
index b4a052a..e1214bf 100644
--- a/p2pvr/dvb/siParsers/table.cpp
+++ b/p2pvr/dvb/siParsers/table.cpp
@@ -10,8 +10,13 @@ const std::string SiTableParserBase::EitEncoding("ISO6937");
const std::string SiTableParserBase::UTF8("UTF8");
SiTableParserBase::SiTableParserBase() :
- startTime(time(NULL)),
- incomplete(0)
+ parentsOnly(false)
+{
+}
+
+SiTableParserBase::SiTableParserBase(const RequiredContentIds & p) :
+ parents(p),
+ parentsOnly(true)
{
}
@@ -32,12 +37,6 @@ SiTableParserBase::CurrentRawData() const
return *currentRawData;
}
-bool
-SiTableParserBase::IsFinished() const
-{
- return ((incomplete == 0) && (startTime < (time(NULL) - 10)));
-}
-
SiTableParserBase::StrPtr
SiTableParserBase::convert(const char * txt, size_t len)
{
diff --git a/p2pvr/dvb/siParsers/table.h b/p2pvr/dvb/siParsers/table.h
index ec74090..30d3614 100644
--- a/p2pvr/dvb/siParsers/table.h
+++ b/p2pvr/dvb/siParsers/table.h
@@ -23,18 +23,19 @@ namespace P2PVR {
namespace DVBSI {
class DLL_PUBLIC SiTableParserBase : public P2PVR::RawDataClient {
public:
+ typedef std::set<uint16_t> RequiredContentIds;
+
const P2PVR::Data & CurrentRawData() const;
protected:
SiTableParserBase();
+ SiTableParserBase(const RequiredContentIds & requiredParents);
virtual ~SiTableParserBase() = 0;
typedef std::unique_ptr<Glib::ustring> StrPtr;
bool NewData(const P2PVR::Data & bytes, const Ice::Current&) override;
- virtual bool IsFinished() const;
-
static StrPtr convert(const char * txt, size_t len);
static const std::string ISO10646;
@@ -42,9 +43,9 @@ class DLL_PUBLIC SiTableParserBase : public P2PVR::RawDataClient {
static const std::string UTF8;
virtual bool ParseInfoTable(const u_char * data, size_t len) = 0;
- time_t startTime;
- unsigned int incomplete;
std::mutex lock;
+ RequiredContentIds parents;
+ bool parentsOnly;
private:
const P2PVR::Data * currentRawData;
@@ -88,6 +89,9 @@ struct SiDescriptorHeader {
template <class TableType, class TargetType, class Key>
class SiTableParser : public SiTableParserBase {
protected:
+ SiTableParser();
+ SiTableParser(const RequiredContentIds & requiredParents);
+
typedef std::set<uint8_t> Sections; // Section numbers
typedef boost::tuple<uint8_t, Sections> TargetSections; // Last section number | Seen section numbers
typedef std::map<uint8_t, TargetSections> TableTargetSections; // TableID -> Needed references
diff --git a/p2pvr/dvb/siParsers/table.impl.h b/p2pvr/dvb/siParsers/table.impl.h
index c5fed98..aa2fa1e 100644
--- a/p2pvr/dvb/siParsers/table.impl.h
+++ b/p2pvr/dvb/siParsers/table.impl.h
@@ -3,16 +3,32 @@
namespace P2PVR {
namespace DVBSI {
template <class TableType, class TargetType, class Key>
+ SiTableParser<TableType, TargetType, Key>::SiTableParser()
+ {
+ }
+
+ template <class TableType, class TargetType, class Key>
+ SiTableParser<TableType, TargetType, Key>::SiTableParser(const RequiredContentIds & rcIds) :
+ SiTableParserBase(rcIds)
+ {
+ }
+
+ template <class TableType, class TargetType, class Key>
bool
SiTableParser<TableType, TargetType, Key>::ParseInfoTable(const u_char * data, size_t len)
{
const u_char * dataEnd = data + len;
- while (data < dataEnd) {
- auto siTable = reinterpret_cast<const TableType *>(data);
+ bool completed = false;
+ for (const TableType * siTable = NULL;
+ data < dataEnd && (siTable = reinterpret_cast<const TableType *>(data));
+ data += HILO(siTable->header.section_length) + 4) {
if (siTable->header.current_next_indicator == 1 // current only, please.
&& CheckTableId(siTable->header.tableid)) { // only tables we're interested in, please.
std::lock_guard<std::mutex> g(lock);
uint16_t contentId = ntohs(siTable->header.content_id);
+ if (parentsOnly && parents.find(contentId) == parents.end()) {
+ continue;
+ }
ContentType & content = contents[contentId];
uint8_t sectionNumber = siTable->header.section_number >> SectionNumberShift();
TableTargetSections & targetTableSections = boost::get<1>(content);
@@ -23,7 +39,6 @@ namespace P2PVR {
auto & obj = boost::get<0>(content);
if (!obj) {
obj = TargetType(new typename TargetType::element_type());
- incomplete += 1;
}
ParseSiTable(siTable, obj);
seen.insert(sectionNumber);
@@ -46,13 +61,13 @@ namespace P2PVR {
else {
obj = TargetType();
}
- incomplete -= 1;
+ parents.erase(contentId);
+ completed = parents.empty();
}
}
}
- data += HILO(siTable->header.section_length) + 4;
}
- return IsFinished();
+ return completed;
}
template <class TableType, class TargetType, class Key>
diff --git a/p2pvr/dvb/unittests/createSamples.cpp b/p2pvr/dvb/unittests/createSamples.cpp
index 3c07620..d0d4890 100644
--- a/p2pvr/dvb/unittests/createSamples.cpp
+++ b/p2pvr/dvb/unittests/createSamples.cpp
@@ -15,10 +15,10 @@
namespace P2PVR {
namespace Testing {
-template <class Parser>
+template <class Parser, class ... P>
static
-boost::tuple<Ice::CommunicatorPtr, Ice::ObjectAdapterPtr, Parser *>
-standardConfig()
+boost::tuple<Ice::CommunicatorPtr, Ice::ObjectAdapterPtr, IceUtil::Handle<Parser>>
+standardConfig(const P & ... p)
{
Ice::StringSeq params {
"--Ice.ThreadPool.Client.Size=5",
@@ -28,7 +28,7 @@ standardConfig()
};
Ice::CommunicatorPtr ic = Ice::initialize(params);
auto adapter = ic->createObjectAdapterWithEndpoints("Adp", "tcp -p 12000");
- auto parser = new Parser();
+ IceUtil::Handle<Parser> parser = new Parser(p...);
adapter->add(parser, ic->stringToIdentity("parser"));
adapter->activate();
return { ic, adapter, parser };
@@ -37,13 +37,16 @@ standardConfig()
template <class Base, class Object>
class SiSampleCollector : public Base {
public:
- SiSampleCollector() :
+ template<class ... P>
+ SiSampleCollector(const P & ... p) :
+ Base(p...),
packets(0)
{
}
- bool HandleTable(const Object &) override
+ bool HandleTable(const Object & o) override
{
+ objects.push_back(o);
return false;
}
@@ -55,17 +58,18 @@ class SiSampleCollector : public Base {
}
std::list<Data> packets;
+ std::list<Object> objects;
private:
std::mutex lock;
};
-template <class Base, class Object>
+template <class Base, class Object, class ... P>
static
-void
-CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<void(TunersPrx, ::DVBSI::DeliveryPtr, RawDataClientPrx)> & method)
+IceUtil::Handle<SiSampleCollector<Base, Object>>
+CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<void(TunersPrx, ::DVBSI::DeliveryPtr, RawDataClientPrx)> & method, const P & ... pp)
{
- auto icp = standardConfig<SiSampleCollector<Base, Object>>();
+ auto icp = standardConfig<SiSampleCollector<Base, Object>>(pp...);
auto ic = boost::get<0>(icp);
auto adap = boost::get<1>(icp);
auto p = boost::get<2>(icp);
@@ -90,7 +94,10 @@ CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<v
method(devs, transport, parser);
BOOST_TEST_MESSAGE("Total packets: " << p->packets.size());
- BOOST_REQUIRE(p->packets.size() > 0);
+ BOOST_REQUIRE_GT(p->packets.size(), 0);
+
+ BOOST_TEST_MESSAGE("Total objects: " << p->objects.size());
+ BOOST_REQUIRE_GT(p->objects.size(), 0);
auto out = Ice::createOutputStream(ic);
out->write(p->packets);
@@ -101,6 +108,7 @@ CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<v
BOOST_REQUIRE(outFile);
BOOST_REQUIRE_EQUAL(1, fwrite(&buf.front(), buf.size(), 1, outFile));
BOOST_REQUIRE_EQUAL(0, fclose(outFile));
+ return boost::get<2>(icp);
}
}
}
@@ -108,22 +116,45 @@ CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<v
using namespace P2PVR;
using namespace P2PVR::Testing;
using namespace P2PVR::DVBSI;
+::DVBSI::NetworkPtr network;
+std::list<::DVBSI::TransportStreamPtr> streams;
BOOST_AUTO_TEST_CASE( network_sample )
{
- CaptureAndSave<SiNetworkInformationParser, ::DVBSI::NetworkPtr>("network.dat",
- [](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendNetworkInformation(del, rdc); });
+ auto parser = CaptureAndSave<SiNetworkInformationParser, ::DVBSI::NetworkPtr>("network.dat",
+ [](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendNetworkInformation(del, rdc); });
+ network = parser->objects.front();
}
BOOST_AUTO_TEST_CASE( services_sample )
{
- CaptureAndSave<SiServicesParser, ::DVBSI::TransportStreamPtr>("services.dat",
- [](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendServiceDescriptions(del, rdc); });
+ SiTableParserBase::RequiredContentIds ids;
+ for (const auto & t : network->TransportStreams) {
+ if (t->Satellite || t->Cable || t->Terrestrial) {
+ ids.insert(t->TransportStreamId);
+ }
+ }
+ auto parser = CaptureAndSave<SiServicesParser, ::DVBSI::TransportStreamPtr>("services.dat",
+ [ids](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendServiceDescriptions(del, rdc); }, ids);
+ streams = parser->objects;
+ streams.erase(std::remove_if(streams.begin(), streams.end(), [ids](const auto & s) {
+ return ids.find(s->TransportStreamId) == ids.end();
+ }), streams.end());
}
BOOST_AUTO_TEST_CASE( events_sample )
{
+ SiTableParserBase::RequiredContentIds ids;
+ for (const auto & st : streams) {
+ for (const auto & s : st->Services) {
+ if (s->EitSchedule) {
+ std::cerr << "Adding " << s->ServiceId << " " << *s->Name << std::endl;
+ ids.insert(s->ServiceId);
+ }
+ }
+ }
+ std::cerr << "Added " << ids.size() << std::endl;
CaptureAndSave<SiEpgParser, ::DVBSI::EventPtr>("events.dat",
- [](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendEventInformation(del, rdc); });
+ [ids](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendEventInformation(del, rdc); }, ids);
}
diff --git a/p2pvr/dvb/unittests/network.dat b/p2pvr/dvb/unittests/network.dat
new file mode 100644
index 0000000..b3c97fe
--- /dev/null
+++ b/p2pvr/dvb/unittests/network.dat
Binary files differ
diff --git a/p2pvr/dvb/unittests/services.dat b/p2pvr/dvb/unittests/services.dat
new file mode 100644
index 0000000..74f0c51
--- /dev/null
+++ b/p2pvr/dvb/unittests/services.dat
Binary files differ