2007-09-12 19:28:59 +02:00
|
|
|
/*
|
|
|
|
* device.c: IPTV plugin for the Video Disk Recorder
|
|
|
|
*
|
|
|
|
* See the README file for copyright information and how to reach the author.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2007-09-15 17:38:38 +02:00
|
|
|
#include "config.h"
|
2010-03-04 16:34:21 +01:00
|
|
|
#include "source.h"
|
2007-09-12 19:28:59 +02:00
|
|
|
#include "device.h"
|
|
|
|
|
2009-02-24 12:40:16 +01:00
|
|
|
#define IPTV_MAX_DEVICES MAXDEVICES
|
2007-09-12 19:28:59 +02:00
|
|
|
|
2009-03-20 23:56:37 +01:00
|
|
|
static cIptvDevice * IptvDevices[IPTV_MAX_DEVICES] = { NULL };
|
2007-09-12 19:28:59 +02:00
|
|
|
|
|
|
|
unsigned int cIptvDevice::deviceCount = 0;
|
|
|
|
|
|
|
|
cIptvDevice::cIptvDevice(unsigned int Index)
|
|
|
|
: deviceIndex(Index),
|
2008-02-17 20:18:47 +01:00
|
|
|
dvrFd(-1),
|
2007-09-12 19:28:59 +02:00
|
|
|
isPacketDelivered(false),
|
|
|
|
isOpenDvr(false),
|
2008-01-31 23:28:53 +01:00
|
|
|
sidScanEnabled(false),
|
2010-11-29 20:09:17 +01:00
|
|
|
pidScanEnabled(false),
|
|
|
|
channelId(tChannelID::InvalidID)
|
2007-09-12 19:28:59 +02:00
|
|
|
{
|
2010-03-04 16:34:21 +01:00
|
|
|
unsigned int bufsize = (unsigned int)MEGABYTE(IptvConfig.GetTsBufferSize());
|
2009-02-26 15:04:12 +01:00
|
|
|
bufsize -= (bufsize % TS_SIZE);
|
2008-08-31 11:56:22 +02:00
|
|
|
isyslog("creating IPTV device %d (CardIndex=%d)", deviceIndex, CardIndex());
|
2009-02-26 15:04:12 +01:00
|
|
|
tsBuffer = new cRingBufferLinear(bufsize + 1, TS_SIZE, false,
|
|
|
|
*cString::sprintf("IPTV %d", deviceIndex));
|
|
|
|
tsBuffer->SetTimeouts(10, 10);
|
2007-09-21 23:50:52 +02:00
|
|
|
ResetBuffering();
|
2007-09-14 17:44:25 +02:00
|
|
|
pUdpProtocol = new cIptvProtocolUdp();
|
2007-09-16 11:38:00 +02:00
|
|
|
pHttpProtocol = new cIptvProtocolHttp();
|
2007-09-16 14:18:15 +02:00
|
|
|
pFileProtocol = new cIptvProtocolFile();
|
2007-10-15 22:06:38 +02:00
|
|
|
pExtProtocol = new cIptvProtocolExt();
|
2009-02-26 15:04:12 +01:00
|
|
|
pIptvStreamer = new cIptvStreamer(tsBuffer, (100 * TS_SIZE));
|
2010-11-29 20:09:17 +01:00
|
|
|
pPidScanner = new cPidScanner();
|
2007-09-24 15:03:38 +02:00
|
|
|
// Initialize filter pointers
|
2008-01-05 00:36:37 +01:00
|
|
|
memset(secfilters, '\0', sizeof(secfilters));
|
2007-10-01 20:14:57 +02:00
|
|
|
// Start section handler for iptv device
|
2007-09-20 23:15:08 +02:00
|
|
|
StartSectionHandler();
|
2007-10-01 20:14:57 +02:00
|
|
|
// Sid scanner must be created after the section handler
|
2010-11-29 20:09:17 +01:00
|
|
|
pSidScanner = new cSidScanner();
|
2007-10-01 20:14:57 +02:00
|
|
|
if (pSidScanner)
|
|
|
|
AttachFilter(pSidScanner);
|
2008-02-17 20:18:47 +01:00
|
|
|
// Check if dvr fifo exists
|
|
|
|
struct stat sb;
|
|
|
|
cString filename = cString::sprintf(IPTV_DVR_FILENAME, deviceIndex);
|
|
|
|
stat(filename, &sb);
|
|
|
|
if (S_ISFIFO(sb.st_mode)) {
|
2008-08-31 11:56:22 +02:00
|
|
|
dvrFd = open(filename, O_RDWR | O_NONBLOCK);
|
2008-02-17 20:18:47 +01:00
|
|
|
if (dvrFd >= 0)
|
|
|
|
dsyslog("IPTV device %d redirecting input stream to '%s'", deviceIndex, *filename);
|
|
|
|
}
|
2007-09-12 19:28:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
cIptvDevice::~cIptvDevice()
|
|
|
|
{
|
2007-09-12 20:55:31 +02:00
|
|
|
debug("cIptvDevice::~cIptvDevice(%d)\n", deviceIndex);
|
2008-02-17 20:18:47 +01:00
|
|
|
// Stop section handler of iptv device
|
|
|
|
StopSectionHandler();
|
2007-10-22 21:32:19 +02:00
|
|
|
DELETE_POINTER(pIptvStreamer);
|
|
|
|
DELETE_POINTER(pUdpProtocol);
|
|
|
|
DELETE_POINTER(pHttpProtocol);
|
|
|
|
DELETE_POINTER(pFileProtocol);
|
|
|
|
DELETE_POINTER(pExtProtocol);
|
|
|
|
DELETE_POINTER(tsBuffer);
|
2008-01-30 23:41:58 +01:00
|
|
|
DELETE_POINTER(pPidScanner);
|
2007-09-29 01:23:12 +02:00
|
|
|
// Detach and destroy sid filter
|
2007-10-01 20:14:57 +02:00
|
|
|
if (pSidScanner) {
|
|
|
|
Detach(pSidScanner);
|
2007-10-22 21:32:19 +02:00
|
|
|
DELETE_POINTER(pSidScanner);
|
2007-09-29 01:23:12 +02:00
|
|
|
}
|
2007-09-24 15:03:38 +02:00
|
|
|
// Destroy all filters
|
2007-09-24 19:20:58 +02:00
|
|
|
for (int i = 0; i < eMaxSecFilterCount; ++i)
|
2007-09-22 10:17:35 +02:00
|
|
|
DeleteFilter(i);
|
2008-02-17 20:18:47 +01:00
|
|
|
// Close dvr fifo
|
|
|
|
if (dvrFd >= 0) {
|
|
|
|
int fd = dvrFd;
|
|
|
|
dvrFd = -1;
|
|
|
|
close(fd);
|
|
|
|
}
|
2007-09-12 19:28:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool cIptvDevice::Initialize(unsigned int DeviceCount)
|
|
|
|
{
|
2007-10-06 22:57:53 +02:00
|
|
|
debug("cIptvDevice::Initialize(): DeviceCount=%d\n", DeviceCount);
|
2010-03-04 16:34:21 +01:00
|
|
|
new cIptvSourceParam(IPTV_SOURCE_CHARACTER, "IPTV");
|
2007-09-12 19:28:59 +02:00
|
|
|
if (DeviceCount > IPTV_MAX_DEVICES)
|
|
|
|
DeviceCount = IPTV_MAX_DEVICES;
|
|
|
|
for (unsigned int i = 0; i < DeviceCount; ++i)
|
|
|
|
IptvDevices[i] = new cIptvDevice(i);
|
2007-10-06 22:57:53 +02:00
|
|
|
for (unsigned int i = DeviceCount; i < IPTV_MAX_DEVICES; ++i)
|
|
|
|
IptvDevices[i] = NULL;
|
2007-09-12 19:28:59 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int cIptvDevice::Count(void)
|
|
|
|
{
|
|
|
|
unsigned int count = 0;
|
|
|
|
debug("cIptvDevice::Count()\n");
|
|
|
|
for (unsigned int i = 0; i < IPTV_MAX_DEVICES; ++i) {
|
2007-10-06 22:57:53 +02:00
|
|
|
if (IptvDevices[i] != NULL)
|
2007-09-12 19:28:59 +02:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2007-10-06 22:57:53 +02:00
|
|
|
cIptvDevice *cIptvDevice::GetIptvDevice(int CardIndex)
|
2007-09-12 19:28:59 +02:00
|
|
|
{
|
2007-10-06 22:57:53 +02:00
|
|
|
//debug("cIptvDevice::GetIptvDevice(%d)\n", CardIndex);
|
|
|
|
for (unsigned int i = 0; i < IPTV_MAX_DEVICES; ++i) {
|
|
|
|
if ((IptvDevices[i] != NULL) && (IptvDevices[i]->CardIndex() == CardIndex)) {
|
|
|
|
//debug("cIptvDevice::GetIptvDevice(%d): FOUND!\n", CardIndex);
|
|
|
|
return IptvDevices[i];
|
|
|
|
}
|
|
|
|
}
|
2007-09-12 19:28:59 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-10-09 01:51:58 +02:00
|
|
|
cString cIptvDevice::GetGeneralInformation(void)
|
2007-10-06 22:57:53 +02:00
|
|
|
{
|
2007-10-09 01:51:58 +02:00
|
|
|
//debug("cIptvDevice::GetGeneralInformation(%d)\n", deviceIndex);
|
2012-04-01 21:46:08 +02:00
|
|
|
return cString::sprintf("IPTV device: %d\nCardIndex: %d\nStream: %s\nStream bitrate: %s\n%sChannel: %s",
|
2007-10-12 01:06:49 +02:00
|
|
|
deviceIndex, CardIndex(),
|
|
|
|
pIptvStreamer ? *pIptvStreamer->GetInformation() : "",
|
2008-01-19 22:08:02 +01:00
|
|
|
pIptvStreamer ? *pIptvStreamer->GetStreamerStatistic() : "",
|
|
|
|
*GetBufferStatistic(),
|
2007-10-12 01:06:49 +02:00
|
|
|
*Channels.GetByNumber(cDevice::CurrentChannel())->ToText());
|
2007-10-09 01:51:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
cString cIptvDevice::GetPidsInformation(void)
|
|
|
|
{
|
|
|
|
//debug("cIptvDevice::GetPidsInformation(%d)\n", deviceIndex);
|
2008-01-19 22:08:02 +01:00
|
|
|
return GetPidStatistic();
|
2007-10-09 01:51:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
cString cIptvDevice::GetFiltersInformation(void)
|
|
|
|
{
|
|
|
|
//debug("cIptvDevice::GetFiltersInformation(%d)\n", deviceIndex);
|
|
|
|
unsigned int count = 0;
|
|
|
|
cString info("Active section filters:\n");
|
2007-10-08 00:54:09 +02:00
|
|
|
// loop through active section filters
|
|
|
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
2007-10-09 01:51:58 +02:00
|
|
|
if (secfilters[i]) {
|
2007-10-10 21:41:10 +02:00
|
|
|
info = cString::sprintf("%sFilter %d: %s Pid=0x%02X (%s)\n", *info, i,
|
2008-01-19 22:08:02 +01:00
|
|
|
*secfilters[i]->GetSectionStatistic(), secfilters[i]->GetPid(),
|
2007-10-10 21:41:10 +02:00
|
|
|
id_pid(secfilters[i]->GetPid()));
|
2007-10-09 01:51:58 +02:00
|
|
|
if (++count > IPTV_STATS_ACTIVE_FILTERS_COUNT)
|
|
|
|
break;
|
|
|
|
}
|
2007-10-08 00:54:09 +02:00
|
|
|
}
|
2007-10-09 01:51:58 +02:00
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
cString cIptvDevice::GetInformation(unsigned int Page)
|
|
|
|
{
|
2007-10-08 00:54:09 +02:00
|
|
|
// generate information string
|
2007-10-09 01:51:58 +02:00
|
|
|
cString info;
|
|
|
|
switch (Page) {
|
|
|
|
case IPTV_DEVICE_INFO_GENERAL:
|
|
|
|
info = GetGeneralInformation();
|
|
|
|
break;
|
|
|
|
case IPTV_DEVICE_INFO_PIDS:
|
|
|
|
info = GetPidsInformation();
|
|
|
|
break;
|
|
|
|
case IPTV_DEVICE_INFO_FILTERS:
|
|
|
|
info = GetFiltersInformation();
|
|
|
|
break;
|
2012-04-01 21:46:08 +02:00
|
|
|
case IPTV_DEVICE_INFO_PROTOCOL:
|
|
|
|
info = pIptvStreamer ? *pIptvStreamer->GetInformation() : "";
|
|
|
|
break;
|
|
|
|
case IPTV_DEVICE_INFO_BITRATE:
|
|
|
|
info = pIptvStreamer ? *pIptvStreamer->GetStreamerStatistic() : "";
|
|
|
|
break;
|
2007-10-09 01:51:58 +02:00
|
|
|
default:
|
2007-10-09 18:37:16 +02:00
|
|
|
info = cString::sprintf("%s%s%s",
|
2007-10-09 01:51:58 +02:00
|
|
|
*GetGeneralInformation(),
|
|
|
|
*GetPidsInformation(),
|
2007-10-09 18:37:16 +02:00
|
|
|
*GetFiltersInformation());
|
2007-10-09 01:51:58 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return info;
|
2007-10-06 22:57:53 +02:00
|
|
|
}
|
|
|
|
|
2012-04-02 18:15:53 +02:00
|
|
|
cString cIptvDevice::DeviceType(void) const
|
|
|
|
{
|
|
|
|
debug("cIptvDevice::DeviceType(%d)\n", deviceIndex);
|
|
|
|
return "IPTV";
|
|
|
|
}
|
|
|
|
|
2012-03-25 15:42:06 +02:00
|
|
|
cString cIptvDevice::DeviceName(void) const
|
|
|
|
{
|
2012-03-30 17:22:10 +02:00
|
|
|
debug("cIptvDevice::DeviceName(%d)\n", deviceIndex);
|
|
|
|
return cString::sprintf("IPTV %d", deviceIndex);
|
2012-03-25 15:42:06 +02:00
|
|
|
}
|
|
|
|
|
2011-06-19 21:07:01 +02:00
|
|
|
int cIptvDevice::SignalStrength(void) const
|
|
|
|
{
|
|
|
|
debug("cIptvDevice::SignalStrength(%d)\n", deviceIndex);
|
|
|
|
return (100);
|
|
|
|
}
|
|
|
|
|
|
|
|
int cIptvDevice::SignalQuality(void) const
|
|
|
|
{
|
|
|
|
debug("cIptvDevice::SignalQuality(%d)\n", deviceIndex);
|
|
|
|
return (100);
|
|
|
|
}
|
|
|
|
|
2007-09-12 19:28:59 +02:00
|
|
|
bool cIptvDevice::ProvidesSource(int Source) const
|
|
|
|
{
|
2007-09-12 20:55:31 +02:00
|
|
|
debug("cIptvDevice::ProvidesSource(%d)\n", deviceIndex);
|
2010-03-14 16:39:52 +01:00
|
|
|
return (cSource::IsType(Source, IPTV_SOURCE_CHARACTER));
|
2007-09-12 19:28:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool cIptvDevice::ProvidesTransponder(const cChannel *Channel) const
|
|
|
|
{
|
2007-09-12 20:55:31 +02:00
|
|
|
debug("cIptvDevice::ProvidesTransponder(%d)\n", deviceIndex);
|
2010-03-04 16:34:21 +01:00
|
|
|
return (ProvidesSource(Channel->Source()));
|
2007-09-12 19:28:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool cIptvDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
|
|
|
|
{
|
|
|
|
bool result = false;
|
2012-06-02 14:37:05 +02:00
|
|
|
bool hasPriority = Priority == IDLEPRIORITY || Priority > this->Priority();
|
|
|
|
bool needsDetachReceivers = false;
|
2007-09-12 19:28:59 +02:00
|
|
|
|
2007-09-12 20:55:31 +02:00
|
|
|
debug("cIptvDevice::ProvidesChannel(%d)\n", deviceIndex);
|
2012-06-02 14:37:05 +02:00
|
|
|
|
|
|
|
if (Channel && ProvidesTransponder(Channel)) {
|
|
|
|
result = hasPriority;
|
|
|
|
if (Receiving()) {
|
|
|
|
if (Channel->GetChannelID() == channelId)
|
|
|
|
result = true;
|
|
|
|
else
|
|
|
|
needsDetachReceivers = Receiving();
|
|
|
|
}
|
|
|
|
}
|
2007-09-12 19:28:59 +02:00
|
|
|
if (NeedsDetachReceivers)
|
|
|
|
*NeedsDetachReceivers = needsDetachReceivers;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-09-04 16:58:18 +02:00
|
|
|
bool cIptvDevice::ProvidesEIT(void) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-01-28 22:36:32 +01:00
|
|
|
int cIptvDevice::NumProvidedSystems(void) const
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2007-09-12 19:28:59 +02:00
|
|
|
bool cIptvDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
|
|
|
{
|
2007-09-14 17:44:25 +02:00
|
|
|
cIptvProtocolIf *protocol;
|
2010-03-04 16:34:21 +01:00
|
|
|
cIptvTransponderParameters itp(Channel->Parameters());
|
2007-09-12 19:28:59 +02:00
|
|
|
|
2007-09-12 20:55:31 +02:00
|
|
|
debug("cIptvDevice::SetChannelDevice(%d)\n", deviceIndex);
|
2011-06-15 16:49:15 +02:00
|
|
|
|
2010-03-04 16:34:21 +01:00
|
|
|
if (isempty(itp.Address())) {
|
|
|
|
error("Unrecognized IPTV address: %s", Channel->Parameters());
|
2007-09-14 23:36:05 +02:00
|
|
|
return false;
|
|
|
|
}
|
2010-03-04 16:34:21 +01:00
|
|
|
switch (itp.Protocol()) {
|
|
|
|
case cIptvTransponderParameters::eProtocolUDP:
|
|
|
|
protocol = pUdpProtocol;
|
|
|
|
break;
|
|
|
|
case cIptvTransponderParameters::eProtocolHTTP:
|
|
|
|
protocol = pHttpProtocol;
|
|
|
|
break;
|
|
|
|
case cIptvTransponderParameters::eProtocolFILE:
|
|
|
|
protocol = pFileProtocol;
|
|
|
|
break;
|
|
|
|
case cIptvTransponderParameters::eProtocolEXT:
|
|
|
|
protocol = pExtProtocol;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("Unrecognized IPTV protocol: %s", Channel->Parameters());
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sidScanEnabled = itp.SidScan() ? true : false;
|
|
|
|
pidScanEnabled = itp.PidScan() ? true : false;
|
|
|
|
if (pIptvStreamer->Set(itp.Address(), itp.Parameter(), deviceIndex, protocol)) {
|
2010-11-29 20:09:17 +01:00
|
|
|
channelId = Channel->GetChannelID();
|
2008-04-02 22:22:48 +02:00
|
|
|
if (sidScanEnabled && pSidScanner && IptvConfig.GetSectionFiltering())
|
2010-11-29 20:09:17 +01:00
|
|
|
pSidScanner->SetChannel(channelId);
|
2008-04-02 22:22:48 +02:00
|
|
|
if (pidScanEnabled && pPidScanner)
|
2010-11-29 20:09:17 +01:00
|
|
|
pPidScanner->SetChannel(channelId);
|
2008-04-02 22:22:48 +02:00
|
|
|
}
|
2007-09-12 19:28:59 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cIptvDevice::SetPid(cPidHandle *Handle, int Type, bool On)
|
|
|
|
{
|
2007-09-19 20:02:38 +02:00
|
|
|
debug("cIptvDevice::SetPid(%d) Pid=%d Type=%d On=%d\n", deviceIndex, Handle->pid, Type, On);
|
2007-09-12 19:28:59 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-09-22 10:17:35 +02:00
|
|
|
bool cIptvDevice::DeleteFilter(unsigned int Index)
|
|
|
|
{
|
2007-09-24 19:20:58 +02:00
|
|
|
if ((Index < eMaxSecFilterCount) && secfilters[Index]) {
|
2007-09-24 23:25:53 +02:00
|
|
|
//debug("cIptvDevice::DeleteFilter(%d) Index=%d\n", deviceIndex, Index);
|
|
|
|
cIptvSectionFilter *tmp = secfilters[Index];
|
2007-09-24 15:03:38 +02:00
|
|
|
secfilters[Index] = NULL;
|
2007-09-24 23:25:53 +02:00
|
|
|
delete tmp;
|
2007-09-22 10:17:35 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-03-20 23:56:37 +01:00
|
|
|
bool cIptvDevice::IsBlackListed(u_short Pid, u_char Tid, u_char Mask) const
|
2007-09-28 16:49:10 +02:00
|
|
|
{
|
|
|
|
//debug("cIptvDevice::IsBlackListed(%d) Pid=%d Tid=%02X Mask=%02X\n", deviceIndex, Pid, Tid, Mask);
|
2007-10-06 02:02:50 +02:00
|
|
|
// 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) &&
|
2007-10-07 00:25:49 +02:00
|
|
|
(section_filter_table[index].pid == Pid) && (section_filter_table[index].tid == Tid) &&
|
|
|
|
(section_filter_table[index].mask == Mask)) {
|
|
|
|
//debug("cIptvDevice::IsBlackListed(%d) Found=%s\n", deviceIndex, section_filter_table[index].description);
|
2007-09-28 18:44:59 +02:00
|
|
|
return true;
|
2007-10-06 02:02:50 +02:00
|
|
|
}
|
|
|
|
}
|
2007-09-28 16:49:10 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-09-14 18:10:44 +02:00
|
|
|
int cIptvDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
|
|
|
|
{
|
2007-09-30 23:38:31 +02:00
|
|
|
// Check if disabled by user
|
|
|
|
if (!IptvConfig.GetSectionFiltering())
|
|
|
|
return -1;
|
2007-10-06 02:02:50 +02:00
|
|
|
// Blacklist check, refuse certain filters
|
2007-09-28 16:49:10 +02:00
|
|
|
if (IsBlackListed(Pid, Tid, Mask))
|
|
|
|
return -1;
|
2009-03-17 16:37:05 +01:00
|
|
|
// Lock
|
|
|
|
cMutexLock MutexLock(&mutex);
|
2007-09-19 17:14:32 +02:00
|
|
|
// Search the next free filter slot
|
2007-09-24 19:20:58 +02:00
|
|
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
2007-09-24 15:03:38 +02:00
|
|
|
if (!secfilters[i]) {
|
2007-09-24 23:25:53 +02:00
|
|
|
//debug("cIptvDevice::OpenFilter(%d): Pid=%d Tid=%02X Mask=%02X Index=%d\n", deviceIndex, Pid, Tid, Mask, i);
|
2009-02-27 15:05:19 +01:00
|
|
|
secfilters[i] = new cIptvSectionFilter(deviceIndex, i, Pid, Tid, Mask);
|
2007-09-24 15:03:38 +02:00
|
|
|
return secfilters[i]->GetReadDesc();
|
2007-09-20 23:15:08 +02:00
|
|
|
}
|
|
|
|
}
|
2007-09-19 17:14:32 +02:00
|
|
|
// No free filter slot found
|
|
|
|
return -1;
|
2007-09-14 18:10:44 +02:00
|
|
|
}
|
|
|
|
|
2007-10-14 20:45:34 +02:00
|
|
|
void cIptvDevice::CloseFilter(int Handle)
|
2007-09-22 10:17:35 +02:00
|
|
|
{
|
2009-03-17 16:37:05 +01:00
|
|
|
// Lock
|
|
|
|
cMutexLock MutexLock(&mutex);
|
|
|
|
// Search the filter for deletion
|
2007-09-24 19:20:58 +02:00
|
|
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
2007-09-24 23:25:53 +02:00
|
|
|
if (secfilters[i] && (Handle == secfilters[i]->GetReadDesc())) {
|
|
|
|
//debug("cIptvDevice::CloseFilter(%d): %d\n", deviceIndex, Handle);
|
2007-10-14 20:45:34 +02:00
|
|
|
DeleteFilter(i);
|
|
|
|
break;
|
2007-09-24 23:25:53 +02:00
|
|
|
}
|
2007-09-22 10:17:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-12 19:28:59 +02:00
|
|
|
bool cIptvDevice::OpenDvr(void)
|
|
|
|
{
|
2007-09-12 20:55:31 +02:00
|
|
|
debug("cIptvDevice::OpenDvr(%d)\n", deviceIndex);
|
2007-09-12 19:28:59 +02:00
|
|
|
isPacketDelivered = false;
|
|
|
|
tsBuffer->Clear();
|
2007-09-21 23:50:52 +02:00
|
|
|
ResetBuffering();
|
2009-02-26 15:04:12 +01:00
|
|
|
if (pIptvStreamer)
|
|
|
|
pIptvStreamer->Open();
|
2008-02-01 22:54:24 +01:00
|
|
|
if (sidScanEnabled && pSidScanner && IptvConfig.GetSectionFiltering())
|
2009-03-20 23:56:37 +01:00
|
|
|
pSidScanner->Open();
|
2007-09-12 19:28:59 +02:00
|
|
|
isOpenDvr = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cIptvDevice::CloseDvr(void)
|
|
|
|
{
|
2007-09-12 20:55:31 +02:00
|
|
|
debug("cIptvDevice::CloseDvr(%d)\n", deviceIndex);
|
2008-04-03 00:55:04 +02:00
|
|
|
if (sidScanEnabled && pSidScanner && IptvConfig.GetSectionFiltering())
|
2009-03-20 23:56:37 +01:00
|
|
|
pSidScanner->Close();
|
2008-01-05 00:36:37 +01:00
|
|
|
if (pIptvStreamer)
|
2008-01-30 22:57:33 +01:00
|
|
|
pIptvStreamer->Close();
|
2007-09-12 19:28:59 +02:00
|
|
|
isOpenDvr = false;
|
|
|
|
}
|
|
|
|
|
2007-09-21 00:01:42 +02:00
|
|
|
bool cIptvDevice::HasLock(int TimeoutMs)
|
|
|
|
{
|
2007-09-21 23:50:52 +02:00
|
|
|
//debug("cIptvDevice::HasLock(%d): %d\n", deviceIndex, TimeoutMs);
|
|
|
|
return (!IsBuffering());
|
|
|
|
}
|
|
|
|
|
|
|
|
void cIptvDevice::ResetBuffering(void)
|
|
|
|
{
|
|
|
|
debug("cIptvDevice::ResetBuffering(%d)\n", deviceIndex);
|
|
|
|
// pad prefill to multiple of TS_SIZE
|
2010-03-04 16:34:21 +01:00
|
|
|
tsBufferPrefill = (unsigned int)MEGABYTE(IptvConfig.GetTsBufferSize()) *
|
2007-09-21 23:50:52 +02:00
|
|
|
IptvConfig.GetTsBufferPrefillRatio() / 100;
|
|
|
|
tsBufferPrefill -= (tsBufferPrefill % TS_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cIptvDevice::IsBuffering(void)
|
|
|
|
{
|
|
|
|
//debug("cIptvDevice::IsBuffering(%d): %d\n", deviceIndex);
|
2007-09-21 00:01:42 +02:00
|
|
|
if (tsBufferPrefill && tsBuffer->Available() < tsBufferPrefill)
|
2007-09-21 23:50:52 +02:00
|
|
|
return true;
|
|
|
|
else
|
|
|
|
tsBufferPrefill = 0;
|
|
|
|
return false;
|
2007-09-21 00:01:42 +02:00
|
|
|
}
|
|
|
|
|
2007-09-12 19:28:59 +02:00
|
|
|
bool cIptvDevice::GetTSPacket(uchar *&Data)
|
|
|
|
{
|
2007-09-12 20:55:31 +02:00
|
|
|
//debug("cIptvDevice::GetTSPacket(%d)\n", deviceIndex);
|
2009-02-26 15:04:12 +01:00
|
|
|
if (tsBuffer && !IsBuffering()) {
|
2007-09-21 23:50:52 +02:00
|
|
|
if (isPacketDelivered) {
|
|
|
|
tsBuffer->Del(TS_SIZE);
|
|
|
|
isPacketDelivered = false;
|
2007-10-10 00:12:17 +02:00
|
|
|
// Update buffer statistics
|
2008-01-19 22:08:02 +01:00
|
|
|
AddBufferStatistic(TS_SIZE, tsBuffer->Available());
|
2007-09-12 19:28:59 +02:00
|
|
|
}
|
2011-06-15 16:49:15 +02:00
|
|
|
int Count = 0;
|
2007-09-21 23:50:52 +02:00
|
|
|
uchar *p = tsBuffer->Get(Count);
|
|
|
|
if (p && Count >= TS_SIZE) {
|
|
|
|
if (*p != TS_SYNC_BYTE) {
|
|
|
|
for (int i = 1; i < Count; i++) {
|
|
|
|
if (p[i] == TS_SYNC_BYTE) {
|
|
|
|
Count = i;
|
|
|
|
break;
|
2007-09-19 20:02:38 +02:00
|
|
|
}
|
2007-09-21 23:50:52 +02:00
|
|
|
}
|
|
|
|
tsBuffer->Del(Count);
|
2009-10-01 17:48:28 +02:00
|
|
|
error("Skipped %d bytes to sync on TS packet\n", Count);
|
2007-09-21 23:50:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
isPacketDelivered = true;
|
|
|
|
Data = p;
|
2009-02-24 12:40:16 +01:00
|
|
|
// Update pid statistics
|
2008-01-30 23:41:58 +01:00
|
|
|
AddPidStatistic(ts_pid(p), payload(p));
|
2008-02-17 20:18:47 +01:00
|
|
|
// Send data also to dvr fifo
|
2009-02-26 15:04:12 +01:00
|
|
|
if (dvrFd >= 0)
|
2009-06-19 12:28:53 +02:00
|
|
|
Count = (int)write(dvrFd, p, TS_SIZE);
|
2008-01-30 23:41:58 +01:00
|
|
|
// Analyze incomplete streams with built-in pid analyzer
|
2008-02-01 22:54:24 +01:00
|
|
|
if (pidScanEnabled && pPidScanner)
|
2008-04-03 00:55:04 +02:00
|
|
|
pPidScanner->Process(p);
|
2009-03-17 16:37:05 +01:00
|
|
|
// Lock
|
|
|
|
cMutexLock MutexLock(&mutex);
|
2007-09-24 15:03:38 +02:00
|
|
|
// Run the data through all filters
|
2007-09-24 19:20:58 +02:00
|
|
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
|
|
|
if (secfilters[i])
|
2009-02-27 15:05:19 +01:00
|
|
|
secfilters[i]->Process(p);
|
2007-09-19 20:02:38 +02:00
|
|
|
}
|
2007-09-21 23:50:52 +02:00
|
|
|
return true;
|
|
|
|
}
|
2007-09-12 19:28:59 +02:00
|
|
|
}
|
2007-10-27 01:48:30 +02:00
|
|
|
// Reduce cpu load by preventing busylooping
|
2009-02-26 15:04:12 +01:00
|
|
|
cCondWait::SleepMs(10);
|
2007-09-12 19:28:59 +02:00
|
|
|
Data = NULL;
|
|
|
|
return true;
|
|
|
|
}
|