mirror of
https://github.com/rofafor/vdr-plugin-iptv.git
synced 2023-10-10 13:37:03 +02:00
Optimized TS packet data flow.
This commit is contained in:
parent
73906ab698
commit
024ee7ba89
4
HISTORY
4
HISTORY
@ -84,3 +84,7 @@ VDR Plugin 'iptv' Revision History
|
|||||||
- Fixed blacklisting of PAT section filter.
|
- Fixed blacklisting of PAT section filter.
|
||||||
- Set max IPTV device count to VDR's max devices.
|
- Set max IPTV device count to VDR's max devices.
|
||||||
- Fixed a possible crash in sid and pid scanners.
|
- Fixed a possible crash in sid and pid scanners.
|
||||||
|
|
||||||
|
2009-xx-xx: Version 0.2.4
|
||||||
|
|
||||||
|
- Optimized TS packet data flow.
|
||||||
|
3
config.c
3
config.c
@ -10,8 +10,7 @@
|
|||||||
cIptvConfig IptvConfig;
|
cIptvConfig IptvConfig;
|
||||||
|
|
||||||
cIptvConfig::cIptvConfig(void)
|
cIptvConfig::cIptvConfig(void)
|
||||||
: readBufferTsCount(48),
|
: tsBufferSize(2),
|
||||||
tsBufferSize(2),
|
|
||||||
tsBufferPrefillRatio(0),
|
tsBufferPrefillRatio(0),
|
||||||
extProtocolBasePort(4321),
|
extProtocolBasePort(4321),
|
||||||
useBytes(1),
|
useBytes(1),
|
||||||
|
2
config.h
2
config.h
@ -14,7 +14,6 @@
|
|||||||
class cIptvConfig
|
class cIptvConfig
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
unsigned int readBufferTsCount;
|
|
||||||
unsigned int tsBufferSize;
|
unsigned int tsBufferSize;
|
||||||
unsigned int tsBufferPrefillRatio;
|
unsigned int tsBufferPrefillRatio;
|
||||||
unsigned int extProtocolBasePort;
|
unsigned int extProtocolBasePort;
|
||||||
@ -25,7 +24,6 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
cIptvConfig();
|
cIptvConfig();
|
||||||
unsigned int GetReadBufferTsCount(void) const { return readBufferTsCount; }
|
|
||||||
unsigned int GetTsBufferSize(void) const { return tsBufferSize; }
|
unsigned int GetTsBufferSize(void) const { return tsBufferSize; }
|
||||||
unsigned int GetTsBufferPrefillRatio(void) const { return tsBufferPrefillRatio; }
|
unsigned int GetTsBufferPrefillRatio(void) const { return tsBufferPrefillRatio; }
|
||||||
unsigned int GetExtProtocolBasePort(void) const { return extProtocolBasePort; }
|
unsigned int GetExtProtocolBasePort(void) const { return extProtocolBasePort; }
|
||||||
|
26
device.c
26
device.c
@ -20,21 +20,20 @@ cIptvDevice::cIptvDevice(unsigned int Index)
|
|||||||
isPacketDelivered(false),
|
isPacketDelivered(false),
|
||||||
isOpenDvr(false),
|
isOpenDvr(false),
|
||||||
sidScanEnabled(false),
|
sidScanEnabled(false),
|
||||||
pidScanEnabled(false),
|
pidScanEnabled(false)
|
||||||
mutex()
|
|
||||||
{
|
{
|
||||||
//debug("cIptvDevice::cIptvDevice(%d)\n", deviceIndex);
|
unsigned int bufsize = MEGABYTE(IptvConfig.GetTsBufferSize());
|
||||||
|
bufsize -= (bufsize % TS_SIZE);
|
||||||
isyslog("creating IPTV device %d (CardIndex=%d)", deviceIndex, CardIndex());
|
isyslog("creating IPTV device %d (CardIndex=%d)", deviceIndex, CardIndex());
|
||||||
tsBuffer = new cRingBufferLinear(MEGABYTE(IptvConfig.GetTsBufferSize()),
|
tsBuffer = new cRingBufferLinear(bufsize + 1, TS_SIZE, false,
|
||||||
(TS_SIZE * IptvConfig.GetReadBufferTsCount()),
|
*cString::sprintf("IPTV %d", deviceIndex));
|
||||||
false, "IPTV");
|
tsBuffer->SetTimeouts(10, 10);
|
||||||
tsBuffer->SetTimeouts(100, 100);
|
|
||||||
ResetBuffering();
|
ResetBuffering();
|
||||||
pUdpProtocol = new cIptvProtocolUdp();
|
pUdpProtocol = new cIptvProtocolUdp();
|
||||||
pHttpProtocol = new cIptvProtocolHttp();
|
pHttpProtocol = new cIptvProtocolHttp();
|
||||||
pFileProtocol = new cIptvProtocolFile();
|
pFileProtocol = new cIptvProtocolFile();
|
||||||
pExtProtocol = new cIptvProtocolExt();
|
pExtProtocol = new cIptvProtocolExt();
|
||||||
pIptvStreamer = new cIptvStreamer(tsBuffer, &mutex);
|
pIptvStreamer = new cIptvStreamer(tsBuffer, (100 * TS_SIZE));
|
||||||
pPidScanner = new cPidScanner;
|
pPidScanner = new cPidScanner;
|
||||||
// Initialize filter pointers
|
// Initialize filter pointers
|
||||||
memset(secfilters, '\0', sizeof(secfilters));
|
memset(secfilters, '\0', sizeof(secfilters));
|
||||||
@ -356,11 +355,10 @@ void cIptvDevice::CloseFilter(int Handle)
|
|||||||
bool cIptvDevice::OpenDvr(void)
|
bool cIptvDevice::OpenDvr(void)
|
||||||
{
|
{
|
||||||
debug("cIptvDevice::OpenDvr(%d)\n", deviceIndex);
|
debug("cIptvDevice::OpenDvr(%d)\n", deviceIndex);
|
||||||
mutex.Lock();
|
|
||||||
isPacketDelivered = false;
|
isPacketDelivered = false;
|
||||||
tsBuffer->Clear();
|
tsBuffer->Clear();
|
||||||
mutex.Unlock();
|
|
||||||
ResetBuffering();
|
ResetBuffering();
|
||||||
|
if (pIptvStreamer)
|
||||||
pIptvStreamer->Open();
|
pIptvStreamer->Open();
|
||||||
if (sidScanEnabled && pSidScanner && IptvConfig.GetSectionFiltering())
|
if (sidScanEnabled && pSidScanner && IptvConfig.GetSectionFiltering())
|
||||||
pSidScanner->SetStatus(true);
|
pSidScanner->SetStatus(true);
|
||||||
@ -407,7 +405,7 @@ bool cIptvDevice::GetTSPacket(uchar *&Data)
|
|||||||
{
|
{
|
||||||
int Count = 0;
|
int Count = 0;
|
||||||
//debug("cIptvDevice::GetTSPacket(%d)\n", deviceIndex);
|
//debug("cIptvDevice::GetTSPacket(%d)\n", deviceIndex);
|
||||||
if (!IsBuffering()) {
|
if (tsBuffer && !IsBuffering()) {
|
||||||
if (isPacketDelivered) {
|
if (isPacketDelivered) {
|
||||||
tsBuffer->Del(TS_SIZE);
|
tsBuffer->Del(TS_SIZE);
|
||||||
isPacketDelivered = false;
|
isPacketDelivered = false;
|
||||||
@ -432,8 +430,8 @@ bool cIptvDevice::GetTSPacket(uchar *&Data)
|
|||||||
// Update pid statistics
|
// Update pid statistics
|
||||||
AddPidStatistic(ts_pid(p), payload(p));
|
AddPidStatistic(ts_pid(p), payload(p));
|
||||||
// Send data also to dvr fifo
|
// Send data also to dvr fifo
|
||||||
if ((dvrFd >= 0) && (write(dvrFd, p, TS_SIZE) != TS_SIZE))
|
if (dvrFd >= 0)
|
||||||
error("ERROR: write failed to FIFO\n");
|
Count = write(dvrFd, p, TS_SIZE);
|
||||||
// Analyze incomplete streams with built-in pid analyzer
|
// Analyze incomplete streams with built-in pid analyzer
|
||||||
if (pidScanEnabled && pPidScanner)
|
if (pidScanEnabled && pPidScanner)
|
||||||
pPidScanner->Process(p);
|
pPidScanner->Process(p);
|
||||||
@ -446,7 +444,7 @@ bool cIptvDevice::GetTSPacket(uchar *&Data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Reduce cpu load by preventing busylooping
|
// Reduce cpu load by preventing busylooping
|
||||||
cCondWait::SleepMs(100);
|
cCondWait::SleepMs(10);
|
||||||
Data = NULL;
|
Data = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
2
iptv.c
2
iptv.c
@ -20,7 +20,7 @@
|
|||||||
#error "VDR-1.6.0 API version or greater is required!"
|
#error "VDR-1.6.0 API version or greater is required!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char VERSION[] = "0.2.4";
|
static const char VERSION[] = "0.2.5";
|
||||||
static const char DESCRIPTION[] = trNOOP("Experience the IPTV");
|
static const char DESCRIPTION[] = trNOOP("Experience the IPTV");
|
||||||
|
|
||||||
class cPluginIptv : public cPlugin {
|
class cPluginIptv : public cPlugin {
|
||||||
|
@ -127,9 +127,9 @@ bool cIptvProtocolExt::Close(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvProtocolExt::Read(unsigned char* *BufferAddr)
|
int cIptvProtocolExt::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||||
{
|
{
|
||||||
return cIptvUdpSocket::Read(BufferAddr);
|
return cIptvUdpSocket::Read(BufferAddr, BufferLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int Index)
|
bool cIptvProtocolExt::Set(const char* Location, const int Parameter, const int Index)
|
||||||
|
@ -25,7 +25,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
cIptvProtocolExt();
|
cIptvProtocolExt();
|
||||||
virtual ~cIptvProtocolExt();
|
virtual ~cIptvProtocolExt();
|
||||||
int Read(unsigned char* *BufferAddr);
|
int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||||
bool Set(const char* Location, const int Parameter, const int Index);
|
bool Set(const char* Location, const int Parameter, const int Index);
|
||||||
bool Open(void);
|
bool Open(void);
|
||||||
bool Close(void);
|
bool Close(void);
|
||||||
|
@ -16,15 +16,10 @@
|
|||||||
|
|
||||||
cIptvProtocolFile::cIptvProtocolFile()
|
cIptvProtocolFile::cIptvProtocolFile()
|
||||||
: fileDelay(0),
|
: fileDelay(0),
|
||||||
readBufferLen(TS_SIZE * IptvConfig.GetReadBufferTsCount()),
|
|
||||||
isActive(false)
|
isActive(false)
|
||||||
{
|
{
|
||||||
debug("cIptvProtocolFile::cIptvProtocolFile()\n");
|
debug("cIptvProtocolFile::cIptvProtocolFile()\n");
|
||||||
fileLocation = strdup("");
|
fileLocation = strdup("");
|
||||||
// Allocate receive buffer
|
|
||||||
readBuffer = MALLOC(unsigned char, readBufferLen);
|
|
||||||
if (!readBuffer)
|
|
||||||
error("ERROR: MALLOC() failed in ProtocolFile()");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cIptvProtocolFile::~cIptvProtocolFile()
|
cIptvProtocolFile::~cIptvProtocolFile()
|
||||||
@ -34,7 +29,6 @@ cIptvProtocolFile::~cIptvProtocolFile()
|
|||||||
cIptvProtocolFile::Close();
|
cIptvProtocolFile::Close();
|
||||||
// Free allocated memory
|
// Free allocated memory
|
||||||
free(fileLocation);
|
free(fileLocation);
|
||||||
free(readBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cIptvProtocolFile::OpenFile(void)
|
bool cIptvProtocolFile::OpenFile(void)
|
||||||
@ -61,10 +55,9 @@ void cIptvProtocolFile::CloseFile(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvProtocolFile::Read(unsigned char* *BufferAddr)
|
int cIptvProtocolFile::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||||
{
|
{
|
||||||
//debug("cIptvProtocolFile::Read()\n");
|
//debug("cIptvProtocolFile::Read()\n");
|
||||||
*BufferAddr = readBuffer;
|
|
||||||
// Check errors
|
// Check errors
|
||||||
if (ferror(fileStream)) {
|
if (ferror(fileStream)) {
|
||||||
debug("Read error\n");
|
debug("Read error\n");
|
||||||
@ -81,7 +74,7 @@ int cIptvProtocolFile::Read(unsigned char* *BufferAddr)
|
|||||||
// during the sleep and buffers are disposed. Check here that the plugin is
|
// during the sleep and buffers are disposed. Check here that the plugin is
|
||||||
// still active before accessing the buffers
|
// still active before accessing the buffers
|
||||||
if (isActive)
|
if (isActive)
|
||||||
return fread(readBuffer, sizeof(unsigned char), readBufferLen, fileStream);
|
return fread(BufferAddr, sizeof(unsigned char), BufferLen, fileStream);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@ private:
|
|||||||
char* fileLocation;
|
char* fileLocation;
|
||||||
int fileDelay;
|
int fileDelay;
|
||||||
FILE* fileStream;
|
FILE* fileStream;
|
||||||
unsigned char* readBuffer;
|
|
||||||
unsigned int readBufferLen;
|
|
||||||
bool isActive;
|
bool isActive;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -27,7 +25,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
cIptvProtocolFile();
|
cIptvProtocolFile();
|
||||||
virtual ~cIptvProtocolFile();
|
virtual ~cIptvProtocolFile();
|
||||||
int Read(unsigned char* *BufferAddr);
|
int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||||
bool Set(const char* Location, const int Parameter, const int Index);
|
bool Set(const char* Location, const int Parameter, const int Index);
|
||||||
bool Open(void);
|
bool Open(void);
|
||||||
bool Close(void);
|
bool Close(void);
|
||||||
|
@ -214,9 +214,9 @@ bool cIptvProtocolHttp::Close(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvProtocolHttp::Read(unsigned char* *BufferAddr)
|
int cIptvProtocolHttp::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||||
{
|
{
|
||||||
return cIptvTcpSocket::Read(BufferAddr);
|
return cIptvTcpSocket::Read(BufferAddr, BufferLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cIptvProtocolHttp::Set(const char* Location, const int Parameter, const int Index)
|
bool cIptvProtocolHttp::Set(const char* Location, const int Parameter, const int Index)
|
||||||
|
@ -27,7 +27,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
cIptvProtocolHttp();
|
cIptvProtocolHttp();
|
||||||
virtual ~cIptvProtocolHttp();
|
virtual ~cIptvProtocolHttp();
|
||||||
int Read(unsigned char* *BufferAddr);
|
int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||||
bool Set(const char* Location, const int Parameter, const int Index);
|
bool Set(const char* Location, const int Parameter, const int Index);
|
||||||
bool Open(void);
|
bool Open(void);
|
||||||
bool Close(void);
|
bool Close(void);
|
||||||
|
@ -12,7 +12,7 @@ class cIptvProtocolIf {
|
|||||||
public:
|
public:
|
||||||
cIptvProtocolIf() {}
|
cIptvProtocolIf() {}
|
||||||
virtual ~cIptvProtocolIf() {}
|
virtual ~cIptvProtocolIf() {}
|
||||||
virtual int Read(unsigned char* *BufferAddr) = 0;
|
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen) = 0;
|
||||||
virtual bool Set(const char* Location, const int Parameter, const int Index) = 0;
|
virtual bool Set(const char* Location, const int Parameter, const int Index) = 0;
|
||||||
virtual bool Open(void) = 0;
|
virtual bool Open(void) = 0;
|
||||||
virtual bool Close(void) = 0;
|
virtual bool Close(void) = 0;
|
||||||
|
@ -91,9 +91,9 @@ bool cIptvProtocolUdp::Close(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvProtocolUdp::Read(unsigned char* *BufferAddr)
|
int cIptvProtocolUdp::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||||
{
|
{
|
||||||
return cIptvUdpSocket::Read(BufferAddr);
|
return cIptvUdpSocket::Read(BufferAddr, BufferLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int Index)
|
bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int Index)
|
||||||
|
@ -23,7 +23,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
cIptvProtocolUdp();
|
cIptvProtocolUdp();
|
||||||
virtual ~cIptvProtocolUdp();
|
virtual ~cIptvProtocolUdp();
|
||||||
int Read(unsigned char* *BufferAddr);
|
int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||||
bool Set(const char* Location, const int Parameter, const int Index);
|
bool Set(const char* Location, const int Parameter, const int Index);
|
||||||
bool Open(void);
|
bool Open(void);
|
||||||
bool Close(void);
|
bool Close(void);
|
||||||
|
52
socket.c
52
socket.c
@ -20,14 +20,9 @@
|
|||||||
cIptvSocket::cIptvSocket()
|
cIptvSocket::cIptvSocket()
|
||||||
: socketPort(0),
|
: socketPort(0),
|
||||||
socketDesc(-1),
|
socketDesc(-1),
|
||||||
readBufferLen(TS_SIZE * IptvConfig.GetReadBufferTsCount()),
|
|
||||||
isActive(false)
|
isActive(false)
|
||||||
{
|
{
|
||||||
debug("cIptvSocket::cIptvSocket()\n");
|
debug("cIptvSocket::cIptvSocket()\n");
|
||||||
// Allocate receive buffer
|
|
||||||
readBuffer = MALLOC(unsigned char, readBufferLen);
|
|
||||||
if (!readBuffer)
|
|
||||||
error("ERROR: MALLOC() failed in socket()");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cIptvSocket::~cIptvSocket()
|
cIptvSocket::~cIptvSocket()
|
||||||
@ -35,8 +30,6 @@ cIptvSocket::~cIptvSocket()
|
|||||||
debug("cIptvSocket::~cIptvSocket()\n");
|
debug("cIptvSocket::~cIptvSocket()\n");
|
||||||
// Close the socket
|
// Close the socket
|
||||||
CloseSocket();
|
CloseSocket();
|
||||||
// Free allocated memory
|
|
||||||
free(readBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
|
bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
|
||||||
@ -104,7 +97,7 @@ bool cIptvUdpSocket::OpenSocket(const int Port)
|
|||||||
return cIptvSocket::OpenSocket(Port, true);
|
return cIptvSocket::OpenSocket(Port, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvUdpSocket::Read(unsigned char* *BufferAddr)
|
int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||||
{
|
{
|
||||||
//debug("cIptvUdpSocket::Read()\n");
|
//debug("cIptvUdpSocket::Read()\n");
|
||||||
// Error out if socket not initialized
|
// Error out if socket not initialized
|
||||||
@ -113,34 +106,22 @@ int cIptvUdpSocket::Read(unsigned char* *BufferAddr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
socklen_t addrlen = sizeof(sockAddr);
|
socklen_t addrlen = sizeof(sockAddr);
|
||||||
// Set argument point to read buffer
|
|
||||||
*BufferAddr = readBuffer;
|
|
||||||
// Wait 500ms for data
|
|
||||||
int retval = select_single_desc(socketDesc, 500000, false);
|
|
||||||
// Check if error
|
|
||||||
if (retval < 0)
|
|
||||||
return retval;
|
|
||||||
// Check if data available
|
|
||||||
else if (retval) {
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
// Read data from socket
|
// Read data from socket
|
||||||
if (isActive)
|
if (isActive)
|
||||||
len = recvfrom(socketDesc, readBuffer, readBufferLen, MSG_DONTWAIT,
|
len = recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
|
||||||
(struct sockaddr *)&sockAddr, &addrlen);
|
(struct sockaddr *)&sockAddr, &addrlen);
|
||||||
ERROR_IF_RET(len < 0, "recvfrom()", return len);
|
if ((len > 0) && (BufferAddr[0] == 0x47)) {
|
||||||
if ((len > 0) && (readBuffer[0] == 0x47)) {
|
|
||||||
// Set argument point to read buffer
|
|
||||||
*BufferAddr = &readBuffer[0];
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
else if (len > 3) {
|
else if (len > 3) {
|
||||||
// http://www.networksorcery.com/enp/rfc/rfc2250.txt
|
// http://www.networksorcery.com/enp/rfc/rfc2250.txt
|
||||||
// version
|
// version
|
||||||
unsigned int v = (readBuffer[0] >> 6) & 0x03;
|
unsigned int v = (BufferAddr[0] >> 6) & 0x03;
|
||||||
// extension bit
|
// extension bit
|
||||||
unsigned int x = (readBuffer[0] >> 4) & 0x01;
|
unsigned int x = (BufferAddr[0] >> 4) & 0x01;
|
||||||
// cscr count
|
// cscr count
|
||||||
unsigned int cc = readBuffer[0] & 0x0F;
|
unsigned int cc = BufferAddr[0] & 0x0F;
|
||||||
// payload type: MPEG2 TS = 33
|
// payload type: MPEG2 TS = 33
|
||||||
//unsigned int pt = readBuffer[1] & 0x7F;
|
//unsigned int pt = readBuffer[1] & 0x7F;
|
||||||
// header lenght
|
// header lenght
|
||||||
@ -148,18 +129,17 @@ int cIptvUdpSocket::Read(unsigned char* *BufferAddr)
|
|||||||
// check if extension
|
// check if extension
|
||||||
if (x) {
|
if (x) {
|
||||||
// extension header length
|
// extension header length
|
||||||
unsigned int ehl = (((readBuffer[headerlen + 2] & 0xFF) << 8) | (readBuffer[headerlen + 3] & 0xFF));
|
unsigned int ehl = (((BufferAddr[headerlen + 2] & 0xFF) << 8) | (BufferAddr[headerlen + 3] & 0xFF));
|
||||||
// update header length
|
// update header length
|
||||||
headerlen += (ehl + 1) * sizeof(uint32_t);
|
headerlen += (ehl + 1) * sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
||||||
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) && (readBuffer[headerlen] == 0x47)) {
|
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) && (BufferAddr[headerlen] == 0x47)) {
|
||||||
// Set argument point to payload in read buffer
|
// Set argument point to payload in read buffer
|
||||||
*BufferAddr = &readBuffer[headerlen];
|
memmove(BufferAddr, &BufferAddr[headerlen], (len - headerlen));
|
||||||
return (len - headerlen);
|
return (len - headerlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +160,7 @@ bool cIptvTcpSocket::OpenSocket(const int Port)
|
|||||||
return cIptvSocket::OpenSocket(Port, false);
|
return cIptvSocket::OpenSocket(Port, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cIptvTcpSocket::Read(unsigned char* *BufferAddr)
|
int cIptvTcpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||||
{
|
{
|
||||||
//debug("cIptvTcpSocket::Read()\n");
|
//debug("cIptvTcpSocket::Read()\n");
|
||||||
// Error out if socket not initialized
|
// Error out if socket not initialized
|
||||||
@ -189,19 +169,9 @@ int cIptvTcpSocket::Read(unsigned char* *BufferAddr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
socklen_t addrlen = sizeof(sockAddr);
|
socklen_t addrlen = sizeof(sockAddr);
|
||||||
// Set argument point to read buffer
|
|
||||||
*BufferAddr = readBuffer;
|
|
||||||
// Wait 500ms for data
|
|
||||||
int retval = select_single_desc(socketDesc, 500000, false);
|
|
||||||
// Check if error
|
|
||||||
if (retval < 0)
|
|
||||||
return retval;
|
|
||||||
// Check if data available
|
|
||||||
else if (retval) {
|
|
||||||
// Read data from socket
|
// Read data from socket
|
||||||
if (isActive)
|
if (isActive)
|
||||||
return recvfrom(socketDesc, readBuffer, readBufferLen, MSG_DONTWAIT,
|
return recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
|
||||||
(struct sockaddr *)&sockAddr, &addrlen);
|
(struct sockaddr *)&sockAddr, &addrlen);
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
6
socket.h
6
socket.h
@ -14,8 +14,6 @@ class cIptvSocket {
|
|||||||
protected:
|
protected:
|
||||||
int socketPort;
|
int socketPort;
|
||||||
int socketDesc;
|
int socketDesc;
|
||||||
unsigned char* readBuffer;
|
|
||||||
unsigned int readBufferLen;
|
|
||||||
struct sockaddr_in sockAddr;
|
struct sockaddr_in sockAddr;
|
||||||
bool isActive;
|
bool isActive;
|
||||||
|
|
||||||
@ -32,7 +30,7 @@ class cIptvUdpSocket : public cIptvSocket {
|
|||||||
public:
|
public:
|
||||||
cIptvUdpSocket();
|
cIptvUdpSocket();
|
||||||
virtual ~cIptvUdpSocket();
|
virtual ~cIptvUdpSocket();
|
||||||
virtual int Read(unsigned char* *BufferAddr);
|
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||||
bool OpenSocket(const int Port);
|
bool OpenSocket(const int Port);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,7 +38,7 @@ class cIptvTcpSocket : public cIptvSocket {
|
|||||||
public:
|
public:
|
||||||
cIptvTcpSocket();
|
cIptvTcpSocket();
|
||||||
virtual ~cIptvTcpSocket();
|
virtual ~cIptvTcpSocket();
|
||||||
virtual int Read(unsigned char* *BufferAddr);
|
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||||
bool OpenSocket(const int Port);
|
bool OpenSocket(const int Port);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
45
streamer.c
45
streamer.c
@ -11,13 +11,19 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "streamer.h"
|
#include "streamer.h"
|
||||||
|
|
||||||
cIptvStreamer::cIptvStreamer(cRingBufferLinear* RingBuffer, cMutex* Mutex)
|
cIptvStreamer::cIptvStreamer(cRingBufferLinear* RingBuffer, unsigned int PacketLen)
|
||||||
: cThread("IPTV streamer"),
|
: cThread("IPTV streamer"),
|
||||||
ringBuffer(RingBuffer),
|
ringBuffer(RingBuffer),
|
||||||
mutex(Mutex),
|
packetBufferLen(PacketLen),
|
||||||
protocol(NULL)
|
protocol(NULL)
|
||||||
{
|
{
|
||||||
debug("cIptvStreamer::cIptvStreamer()\n");
|
debug("cIptvStreamer::cIptvStreamer(%d)\n", packetBufferLen);
|
||||||
|
// Allocate packet buffer
|
||||||
|
packetBuffer = MALLOC(unsigned char, packetBufferLen);
|
||||||
|
if (packetBuffer)
|
||||||
|
memset(packetBuffer, 0, packetBufferLen);
|
||||||
|
else
|
||||||
|
error("ERROR: MALLOC() failed for packet buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
cIptvStreamer::~cIptvStreamer()
|
cIptvStreamer::~cIptvStreamer()
|
||||||
@ -25,31 +31,30 @@ cIptvStreamer::~cIptvStreamer()
|
|||||||
debug("cIptvStreamer::~cIptvStreamer()\n");
|
debug("cIptvStreamer::~cIptvStreamer()\n");
|
||||||
// Close the protocol
|
// Close the protocol
|
||||||
Close();
|
Close();
|
||||||
|
// Free allocated memory
|
||||||
|
free(packetBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cIptvStreamer::Action(void)
|
void cIptvStreamer::Action(void)
|
||||||
{
|
{
|
||||||
debug("cIptvStreamer::Action(): Entering\n");
|
debug("cIptvStreamer::Action(): Entering\n");
|
||||||
|
// Increase priority
|
||||||
|
//SetPriority(-1);
|
||||||
// Do the thread loop
|
// Do the thread loop
|
||||||
while (Running()) {
|
while (packetBuffer && Running()) {
|
||||||
if (ringBuffer && mutex && protocol && ringBuffer->Free()) {
|
int length = -1;
|
||||||
unsigned char *buffer = NULL;
|
if (protocol)
|
||||||
mutex->Lock();
|
length = protocol->Read(packetBuffer, packetBufferLen);
|
||||||
int length = protocol->Read(&buffer);
|
|
||||||
if (length >= 0) {
|
if (length >= 0) {
|
||||||
AddStreamerStatistic(length);
|
AddStreamerStatistic(length);
|
||||||
int p = ringBuffer->Put(buffer, length);
|
if (ringBuffer) {
|
||||||
if (p != length && Running())
|
int p = ringBuffer->Put(packetBuffer, length);
|
||||||
|
if (p != length)
|
||||||
ringBuffer->ReportOverflow(length - p);
|
ringBuffer->ReportOverflow(length - p);
|
||||||
mutex->Unlock();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mutex->Unlock();
|
|
||||||
sleep.Wait(100); // to reduce cpu load
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sleep.Wait(100); // and avoid busy loop
|
sleep.Wait(10); // to avoid busy loop and reduce cpu load
|
||||||
}
|
}
|
||||||
debug("cIptvStreamer::Action(): Exiting\n");
|
debug("cIptvStreamer::Action(): Exiting\n");
|
||||||
}
|
}
|
||||||
@ -72,15 +77,9 @@ bool cIptvStreamer::Close(void)
|
|||||||
sleep.Signal();
|
sleep.Signal();
|
||||||
if (Running())
|
if (Running())
|
||||||
Cancel(3);
|
Cancel(3);
|
||||||
// Close the protocol. A mutex should be taken here to avoid a race condition
|
// Close the protocol
|
||||||
// where thread Action() may be in the process of accessing the protocol.
|
|
||||||
// Taking a mutex serializes the Close() and Action() -calls.
|
|
||||||
if (mutex)
|
|
||||||
mutex->Lock();
|
|
||||||
if (protocol)
|
if (protocol)
|
||||||
protocol->Close();
|
protocol->Close();
|
||||||
if (mutex)
|
|
||||||
mutex->Unlock();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,14 +19,13 @@
|
|||||||
class cIptvStreamer : public cThread, public cIptvStreamerStatistics {
|
class cIptvStreamer : public cThread, public cIptvStreamerStatistics {
|
||||||
private:
|
private:
|
||||||
cRingBufferLinear* ringBuffer;
|
cRingBufferLinear* ringBuffer;
|
||||||
cMutex* mutex;
|
|
||||||
cCondWait sleep;
|
cCondWait sleep;
|
||||||
unsigned char* readBuffer;
|
unsigned char* packetBuffer;
|
||||||
unsigned int readBufferLen;
|
unsigned int packetBufferLen;
|
||||||
cIptvProtocolIf* protocol;
|
cIptvProtocolIf* protocol;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cIptvStreamer(cRingBufferLinear* RingBuffer, cMutex* Mutex);
|
cIptvStreamer(cRingBufferLinear* RingBuffer, unsigned int PacketLen);
|
||||||
virtual ~cIptvStreamer();
|
virtual ~cIptvStreamer();
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
bool Set(const char* Location, const int Parameter, const int Index, cIptvProtocolIf* Protocol);
|
bool Set(const char* Location, const int Parameter, const int Index, cIptvProtocolIf* Protocol);
|
||||||
|
Loading…
Reference in New Issue
Block a user