mirror of
https://github.com/rofafor/vdr-plugin-iptv.git
synced 2023-10-10 11:37:03 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41fe387018 | ||
|
|
2c287ef667 | ||
|
|
d7dfa0aad6 | ||
|
|
72a9f21006 | ||
|
|
d84fd79d14 | ||
|
|
f632650547 | ||
|
|
980aafb206 | ||
|
|
45192e924a | ||
|
|
e4657c1820 |
6
HISTORY
6
HISTORY
@@ -193,3 +193,9 @@ VDR Plugin 'iptv' Revision History
|
||||
|
||||
- Updated for vdr-1.7.38.
|
||||
- Added a new CURL protocol for HTTP/HTTPS.
|
||||
|
||||
2013-03-06: Version 1.2.1
|
||||
|
||||
- Fixed bugs found in the CURL implementation (Thanks
|
||||
to Jeremy Hall).
|
||||
- Fixed the channel editor.
|
||||
|
||||
10
README
10
README
@@ -89,11 +89,11 @@ Configuration:
|
||||
|
||||
- channels.conf
|
||||
|
||||
TV4;IPTV:40:S=1|P=0|F=EXT|U=iptvstream.sh|A=0:I:0:0:680:0:0:4:0:0:0
|
||||
TV3;IPTV:30:S=0|P=1|F=FILE|U=/video/stream.ts|A=5:I:0:514:670:2321:0:3:0:0:0
|
||||
TV2;IPTV:20:S=0|P=1|F=HTTP|U=127.0.0.1/TS/2|A=3000:I:0:513:660:2321:0:2:0:0:0
|
||||
TV1;IPTV:10:S=1|P=0|F=CURL|U=http%3A//foo%3Abar@127.0.0.1%3A3000/TS/2|A=0:I:0:512:650:2321:0:1:0:0:0
|
||||
TV1;IPTV:10:S=1|P=0|F=UDP|U=127.0.0.1@127.0.0.1|A=1234:I:0:512:650:2321:0:1:0:0:0
|
||||
TV4;IPTV:60:S=1|P=0|F=EXT|U=iptvstream.sh|A=0:I:0:0:680:0:0:6:0:0:0
|
||||
TV3;IPTV:50:S=0|P=1|F=FILE|U=/video/stream.ts|A=5:I:0:514:670:2321:0:5:0:0:0
|
||||
TV2;IPTV:40:S=0|P=1|F=HTTP|U=127.0.0.1/TS/2|A=3000:I:0:513:660:2321:0:4:0:0:0
|
||||
TV1;IPTV:30:S=1|P=0|F=CURL|U=http%3A//foo%3Abar@127.0.0.1%3A3000/TS/2|A=0:I:0:512:650:2321:0:3:0:0:0
|
||||
TV1;IPTV:20:S=1|P=0|F=UDP|U=127.0.0.1@127.0.0.1|A=1234:I:0:512:650:2321:0:2:0:0:0
|
||||
TV1;IPTV:10:S=1|P=0|F=UDP|U=127.0.0.1|A=1234:I:0:512:650:2321:0:1:0:0:0
|
||||
^ ^ ^ ^ ^ ^ ^
|
||||
| | | | | | Source type ("I")
|
||||
|
||||
45
common.c
45
common.c
@@ -5,44 +5,45 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <vdr/tools.h>
|
||||
#include "common.h"
|
||||
|
||||
uint16_t ts_pid(const uint8_t *buf)
|
||||
uint16_t ts_pid(const uint8_t *bufP)
|
||||
{
|
||||
return (uint16_t)(((buf[1] & 0x1f) << 8) + buf[2]);
|
||||
return (uint16_t)(((bufP[1] & 0x1f) << 8) + bufP[2]);
|
||||
}
|
||||
|
||||
uint8_t payload(const uint8_t *tsp)
|
||||
uint8_t payload(const uint8_t *bufP)
|
||||
{
|
||||
if (!(tsp[3] & 0x10)) // no payload?
|
||||
if (!(bufP[3] & 0x10)) // no payload?
|
||||
return 0;
|
||||
|
||||
if (tsp[3] & 0x20) { // adaptation field?
|
||||
if (tsp[4] > 183) // corrupted data?
|
||||
if (bufP[3] & 0x20) { // adaptation field?
|
||||
if (bufP[4] > 183) // corrupted data?
|
||||
return 0;
|
||||
else
|
||||
return (uint8_t)((184 - 1) - tsp[4]);
|
||||
return (uint8_t)((184 - 1) - bufP[4]);
|
||||
}
|
||||
|
||||
return 184;
|
||||
}
|
||||
|
||||
const char *id_pid(const u_short Pid)
|
||||
const char *id_pid(const u_short pidP)
|
||||
{
|
||||
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
|
||||
if (Pid == section_filter_table[i].pid)
|
||||
if (pidP == section_filter_table[i].pid)
|
||||
return section_filter_table[i].tag;
|
||||
}
|
||||
return "---";
|
||||
}
|
||||
|
||||
int select_single_desc(int descriptor, const int usecs, const bool selectWrite)
|
||||
int select_single_desc(int descriptorP, const int usecsP, const bool selectWriteP)
|
||||
{
|
||||
// Wait for data
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = usecs;
|
||||
tv.tv_usec = usecsP;
|
||||
// Use select
|
||||
fd_set infd;
|
||||
fd_set outfd;
|
||||
@@ -50,17 +51,28 @@ int select_single_desc(int descriptor, const int usecs, const bool selectWrite)
|
||||
FD_ZERO(&infd);
|
||||
FD_ZERO(&outfd);
|
||||
FD_ZERO(&errfd);
|
||||
FD_SET(descriptor, &errfd);
|
||||
if (selectWrite)
|
||||
FD_SET(descriptor, &outfd);
|
||||
FD_SET(descriptorP, &errfd);
|
||||
if (selectWriteP)
|
||||
FD_SET(descriptorP, &outfd);
|
||||
else
|
||||
FD_SET(descriptor, &infd);
|
||||
int retval = select(descriptor + 1, &infd, &outfd, &errfd, &tv);
|
||||
FD_SET(descriptorP, &infd);
|
||||
int retval = select(descriptorP + 1, &infd, &outfd, &errfd, &tv);
|
||||
// Check if error
|
||||
ERROR_IF_RET(retval < 0, "select()", return retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
cString ChangeCase(const cString &strP, bool upperP)
|
||||
{
|
||||
cString res(strP);
|
||||
char *p = (char *)*res;
|
||||
while (p && *p) {
|
||||
*p = upperP ? toupper(*p) : tolower(*p);
|
||||
++p;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE] =
|
||||
{
|
||||
/* description tag pid tid mask */
|
||||
@@ -72,4 +84,3 @@ const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE]
|
||||
{trNOOP("EIT (0x6X)"), "EIT", 0x12, 0x60, 0xF0},
|
||||
{trNOOP("TDT (0x70)"), "TDT", 0x14, 0x70, 0xFF},
|
||||
};
|
||||
|
||||
|
||||
9
common.h
9
common.h
@@ -66,10 +66,11 @@
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
uint16_t ts_pid(const uint8_t *buf);
|
||||
uint8_t payload(const uint8_t *tsp);
|
||||
const char *id_pid(const u_short Pid);
|
||||
int select_single_desc(int descriptor, const int usecs, const bool selectWrite);
|
||||
uint16_t ts_pid(const uint8_t *bufP);
|
||||
uint8_t payload(const uint8_t *bufP);
|
||||
const char *id_pid(const u_short pidP);
|
||||
int select_single_desc(int descriptorP, const int usecsP, const bool selectWriteP);
|
||||
cString ChangeCase(const cString &strP, bool upperP);
|
||||
|
||||
struct section_filter_table_type {
|
||||
const char *description;
|
||||
|
||||
26
device.c
26
device.c
@@ -41,9 +41,7 @@ cIptvDevice::cIptvDevice(unsigned int indexP)
|
||||
// Start section handler for iptv device
|
||||
StartSectionHandler();
|
||||
// Sid scanner must be created after the section handler
|
||||
pSidScannerM = new cSidScanner();
|
||||
if (pSidScannerM)
|
||||
AttachFilter(pSidScannerM);
|
||||
AttachFilter(pSidScannerM = new cSidScanner());
|
||||
// Check if dvr fifo exists
|
||||
struct stat sb;
|
||||
cString filename = cString::sprintf(IPTV_DVR_FILENAME, deviceIndexM);
|
||||
@@ -58,8 +56,6 @@ cIptvDevice::cIptvDevice(unsigned int indexP)
|
||||
cIptvDevice::~cIptvDevice()
|
||||
{
|
||||
debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
|
||||
// Stop section handler of iptv device
|
||||
StopSectionHandler();
|
||||
DELETE_POINTER(pIptvStreamerM);
|
||||
DELETE_POINTER(pUdpProtocolM);
|
||||
DELETE_POINTER(pCurlProtocolM);
|
||||
@@ -68,12 +64,11 @@ cIptvDevice::~cIptvDevice()
|
||||
DELETE_POINTER(pExtProtocolM);
|
||||
DELETE_POINTER(tsBufferM);
|
||||
DELETE_POINTER(pPidScannerM);
|
||||
// Detach and destroy sid filter
|
||||
if (pSidScannerM) {
|
||||
Detach(pSidScannerM);
|
||||
DELETE_POINTER(pSidScannerM);
|
||||
}
|
||||
DELETE_POINTER(pSidScannerM);
|
||||
// Stop section handler of iptv device
|
||||
StopSectionHandler();
|
||||
// Destroy all filters
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
for (int i = 0; i < eMaxSecFilterCount; ++i)
|
||||
DeleteFilter(i);
|
||||
// Close dvr fifo
|
||||
@@ -143,6 +138,7 @@ cString cIptvDevice::GetFiltersInformation(void)
|
||||
unsigned int count = 0;
|
||||
cString s("Active section filters:\n");
|
||||
// loop through active section filters
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||
if (secFiltersM[i]) {
|
||||
s = cString::sprintf("%sFilter %d: %s Pid=0x%02X (%s)\n", *s, i,
|
||||
@@ -321,7 +317,7 @@ bool cIptvDevice::IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const
|
||||
// loop through section filter table
|
||||
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
|
||||
int index = IptvConfig.GetDisabledFilters(i);
|
||||
// check if matches
|
||||
// Check if matches
|
||||
if ((index >= 0) && (index < SECTION_FILTER_TABLE_SIZE) &&
|
||||
(section_filter_table[index].pid == pidP) && (section_filter_table[index].tid == tidP) &&
|
||||
(section_filter_table[index].mask == maskP)) {
|
||||
@@ -337,11 +333,11 @@ int cIptvDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
|
||||
// Check if disabled by user
|
||||
if (!IptvConfig.GetSectionFiltering())
|
||||
return -1;
|
||||
// Lock
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
// Blacklist check, refuse certain filters
|
||||
if (IsBlackListed(pidP, tidP, maskP))
|
||||
return -1;
|
||||
// Lock
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
// Search the next free filter slot
|
||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||
if (!secFiltersM[i]) {
|
||||
@@ -396,7 +392,7 @@ bool cIptvDevice::OpenDvr(void)
|
||||
void cIptvDevice::CloseDvr(void)
|
||||
{
|
||||
debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
|
||||
if (sidScanEnabledM && pSidScannerM && IptvConfig.GetSectionFiltering())
|
||||
if (sidScanEnabledM && pSidScannerM )
|
||||
pSidScannerM->Close();
|
||||
if (pIptvStreamerM)
|
||||
pIptvStreamerM->Close();
|
||||
@@ -418,7 +414,7 @@ bool cIptvDevice::HasInternalCam(void)
|
||||
void cIptvDevice::ResetBuffering(void)
|
||||
{
|
||||
debug("cIptvDevice::%s(%d)", __FUNCTION__, deviceIndexM);
|
||||
// pad prefill to multiple of TS_SIZE
|
||||
// Pad prefill to multiple of TS_SIZE
|
||||
tsBufferPrefillM = (unsigned int)MEGABYTE(IptvConfig.GetTsBufferSize()) *
|
||||
IptvConfig.GetTsBufferPrefillRatio() / 100;
|
||||
tsBufferPrefillM -= (tsBufferPrefillM % TS_SIZE);
|
||||
|
||||
2
iptv.c
2
iptv.c
@@ -21,7 +21,7 @@
|
||||
#define GITVERSION ""
|
||||
#endif
|
||||
|
||||
const char VERSION[] = "1.2.0" GITVERSION;
|
||||
const char VERSION[] = "1.2.1" GITVERSION;
|
||||
static const char DESCRIPTION[] = trNOOP("Experience the IPTV");
|
||||
|
||||
class cPluginIptv : public cPlugin {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-iptv 1.2.0\n"
|
||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
|
||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-iptv 1.2.0\n"
|
||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
|
||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-iptv 1.2.0\n"
|
||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
|
||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-iptv 1.2.0\n"
|
||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
|
||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-iptv 1.2.0\n"
|
||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
|
||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-iptv 1.2.0\n"
|
||||
"Project-Id-Version: vdr-iptv 1.2.1\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-06-03 06:03+0300\n"
|
||||
"PO-Revision-Date: 2012-06-03 06:03+0300\n"
|
||||
|
||||
175
protocolcurl.c
175
protocolcurl.c
@@ -10,10 +10,14 @@
|
||||
#include "protocolcurl.h"
|
||||
|
||||
#define iptv_curl_easy_setopt(X, Y, Z) \
|
||||
if ((res = curl_easy_setopt((X), (Y), (Z))) != CURLE_OK) { error("curl_easy_setopt(%s, %s, %s) failed: %d\n", #X, #Y, #Z, res); }
|
||||
if ((res = curl_easy_setopt((X), (Y), (Z))) != CURLE_OK) { \
|
||||
error("curl_easy_setopt(%s, %s, %s) failed: %d\n", #X, #Y, #Z, res); \
|
||||
}
|
||||
|
||||
#define iptv_curl_easy_perform(X) \
|
||||
if ((res = curl_easy_perform((X))) != CURLE_OK) { error("curl_easy_perform(%s) failed: %d\n", #X, res); }
|
||||
if ((res = curl_easy_perform((X))) != CURLE_OK) { \
|
||||
error("curl_easy_perform(%s) failed: %d\n", #X, res); \
|
||||
}
|
||||
|
||||
cIptvProtocolCurl::cIptvProtocolCurl()
|
||||
: streamUrlM(""),
|
||||
@@ -22,7 +26,8 @@ cIptvProtocolCurl::cIptvProtocolCurl()
|
||||
handleM(NULL),
|
||||
multiM(NULL),
|
||||
headerListM(NULL),
|
||||
ringBufferM(new cRingBufferLinear(MEGABYTE(IptvConfig.GetTsBufferSize()), 7 * TS_SIZE)),
|
||||
ringBufferM(new cRingBufferLinear(MEGABYTE(IptvConfig.GetTsBufferSize()),
|
||||
7 * TS_SIZE, false, "IPTV CURL")),
|
||||
rtspControlM(),
|
||||
modeM(eModeUnknown),
|
||||
connectedM(false),
|
||||
@@ -60,30 +65,30 @@ size_t cIptvProtocolCurl::WriteRtspCallback(void *ptrP, size_t sizeP, size_t nme
|
||||
size_t len = sizeP * nmembP;
|
||||
unsigned char *p = (unsigned char *)ptrP;
|
||||
//debug("cIptvProtocolCurl::%s(%zu)", __FUNCTION__, len);
|
||||
|
||||
// validate packet header ('$') and channel (0)
|
||||
|
||||
// Validate packet header ('$') and channel (0)
|
||||
if (obj && (p[0] == 0x24 ) && (p[1] == 0)) {
|
||||
int length = (p[2] << 8) | p[3];
|
||||
if (length > 3) {
|
||||
// skip interleave header
|
||||
// Skip interleave header
|
||||
p += 4;
|
||||
// http://tools.ietf.org/html/rfc3550
|
||||
// http://tools.ietf.org/html/rfc2250
|
||||
// version
|
||||
// Version
|
||||
unsigned int v = (p[0] >> 6) & 0x03;
|
||||
// extension bit
|
||||
// Extension bit
|
||||
unsigned int x = (p[0] >> 4) & 0x01;
|
||||
// cscr count
|
||||
// CSCR count
|
||||
unsigned int cc = p[0] & 0x0F;
|
||||
// payload type: MPEG2 TS = 33
|
||||
// Payload type: MPEG2 TS = 33
|
||||
//unsigned int pt = p[1] & 0x7F;
|
||||
// header lenght
|
||||
// Header lenght
|
||||
unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
||||
// check if extension
|
||||
// Check if extension
|
||||
if (x) {
|
||||
// extension header length
|
||||
// Extension header length
|
||||
unsigned int ehl = (((p[headerlen + 2] & 0xFF) << 8) |(p[headerlen + 3] & 0xFF));
|
||||
// update header length
|
||||
// Update header length
|
||||
headerlen += (ehl + 1) * (unsigned int)sizeof(uint32_t);
|
||||
}
|
||||
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
||||
@@ -116,7 +121,7 @@ size_t cIptvProtocolCurl::DescribeCallback(void *ptrP, size_t sizeP, size_t nmem
|
||||
free(s);
|
||||
}
|
||||
r = strtok(NULL, "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!isempty(*control) && obj)
|
||||
obj->SetRtspControl(*control);
|
||||
@@ -155,9 +160,10 @@ bool cIptvProtocolCurl::PutData(unsigned char *dataP, int lenP)
|
||||
if (pausedM)
|
||||
return false;
|
||||
if (ringBufferM && (lenP >= 0)) {
|
||||
// should be pause the transfer?
|
||||
// Should we pause the transfer ?
|
||||
if (ringBufferM->Free() < (2 * CURL_MAX_WRITE_SIZE)) {
|
||||
debug("cIptvProtocolCurl::%s(pause): free=%d available=%d len=%d", __FUNCTION__, ringBufferM->Free(), ringBufferM->Available(), lenP);
|
||||
debug("cIptvProtocolCurl::%s(pause): free=%d available=%d len=%d", __FUNCTION__,
|
||||
ringBufferM->Free(), ringBufferM->Available(), lenP);
|
||||
pausedM = true;
|
||||
return false;
|
||||
}
|
||||
@@ -184,12 +190,12 @@ void cIptvProtocolCurl::ClearData()
|
||||
ringBufferM->Clear();
|
||||
}
|
||||
|
||||
unsigned char *cIptvProtocolCurl::GetData(unsigned int *lenP)
|
||||
unsigned char *cIptvProtocolCurl::GetData(int &lenP)
|
||||
{
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
//debug("cIptvProtocolCurl::%s()", __FUNCTION__);
|
||||
unsigned char *p = NULL;
|
||||
*lenP = 0;
|
||||
lenP = 0;
|
||||
if (ringBufferM) {
|
||||
int count = 0;
|
||||
p = ringBufferM->Get(count);
|
||||
@@ -204,13 +210,13 @@ unsigned char *cIptvProtocolCurl::GetData(unsigned int *lenP)
|
||||
}
|
||||
error("IPTV skipped %d bytes to sync on TS packet\n", count);
|
||||
ringBufferM->Del(count);
|
||||
*lenP = 0;
|
||||
lenP = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
count -= (count % TS_SIZE);
|
||||
*lenP = count;
|
||||
lenP = count;
|
||||
}
|
||||
|
||||
return p;
|
||||
@@ -223,7 +229,7 @@ bool cIptvProtocolCurl::Connect()
|
||||
if (connectedM)
|
||||
return true;
|
||||
|
||||
// initialize the curl session
|
||||
// Initialize the curl session
|
||||
if (!handleM)
|
||||
handleM = curl_easy_init();
|
||||
if (!multiM)
|
||||
@@ -234,78 +240,78 @@ bool cIptvProtocolCurl::Connect()
|
||||
cString netrc = cString::sprintf("%s/netrc", IptvConfig.GetConfigDirectory());
|
||||
|
||||
#ifdef DEBUG
|
||||
// verbose output
|
||||
// Verbose output
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_VERBOSE, 1L);
|
||||
#endif
|
||||
|
||||
// set callbacks
|
||||
// Set callbacks
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_WRITEFUNCTION, cIptvProtocolCurl::WriteCallback);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_WRITEDATA, this);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_HEADERFUNCTION, cIptvProtocolCurl::HeaderCallback);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_WRITEHEADER, this);
|
||||
|
||||
// no progress meter and no signaling
|
||||
// No progress meter and no signaling
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_NOPROGRESS, 1L);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_NOSIGNAL, 1L);
|
||||
|
||||
// support netrc
|
||||
// Support netrc
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_NETRC_FILE, *netrc);
|
||||
|
||||
// set timeout
|
||||
// Set timeout
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_CONNECTTIMEOUT, (long)eConnectTimeoutS);
|
||||
|
||||
// set user-agent
|
||||
// Set user-agent
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
|
||||
|
||||
// set url
|
||||
//char *p = curl_easy_unescape(handleM, *streamUrlM, 0, NULL);
|
||||
//streamUrlM = p;
|
||||
//curl_free(p);
|
||||
// Set URL
|
||||
char *p = curl_easy_unescape(handleM, *streamUrlM, 0, NULL);
|
||||
streamUrlM = p;
|
||||
curl_free(p);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_URL, *streamUrlM);
|
||||
|
||||
// protocol specific initializations
|
||||
// Protocol specific initializations
|
||||
switch (modeM) {
|
||||
case eModeRtsp:
|
||||
{
|
||||
cString uri, control, transport, range;
|
||||
|
||||
// request server options
|
||||
// Request server options
|
||||
uri = cString::sprintf("%s", *streamUrlM);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_OPTIONS);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS);
|
||||
iptv_curl_easy_perform(handleM);
|
||||
|
||||
// request session description - SDP is delivered in message body and not in the header!
|
||||
// Request session description - SDP is delivered in message body and not in the header!
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_WRITEFUNCTION, cIptvProtocolCurl::DescribeCallback);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_WRITEDATA, this);
|
||||
uri = cString::sprintf("%s", *streamUrlM);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_DESCRIBE);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
|
||||
iptv_curl_easy_perform(handleM);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_WRITEDATA, NULL);
|
||||
|
||||
// setup media stream
|
||||
// Setup media stream
|
||||
uri = cString::sprintf("%s/%s", *streamUrlM, *rtspControlM);
|
||||
transport = "RTP/AVP/TCP;unicast;interleaved=0-1";
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_TRANSPORT, *transport);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_SETUP);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_SETUP);
|
||||
iptv_curl_easy_perform(handleM);
|
||||
|
||||
// start playing
|
||||
// Start playing
|
||||
uri = cString::sprintf("%s/", *streamUrlM);
|
||||
range = "0.000-";
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RANGE, *range);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_PLAY);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
|
||||
iptv_curl_easy_perform(handleM);
|
||||
|
||||
// start receiving
|
||||
// Start receiving
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_INTERLEAVEFUNCTION, cIptvProtocolCurl::WriteRtspCallback);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_INTERLEAVEDATA, this);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_RECEIVE);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_RECEIVE);
|
||||
iptv_curl_easy_perform(handleM);
|
||||
}
|
||||
break;
|
||||
@@ -313,16 +319,16 @@ bool cIptvProtocolCurl::Connect()
|
||||
case eModeHttp:
|
||||
case eModeHttps:
|
||||
{
|
||||
// limit download speed (bytes/s)
|
||||
// Limit download speed (bytes/s)
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_MAX_RECV_SPEED_LARGE, eMaxDownloadSpeedMBits * 131072L);
|
||||
|
||||
// follow location
|
||||
// Follow location
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
// fail if HTTP return code is >= 400
|
||||
// Fail if HTTP return code is >= 400
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_FAILONERROR, 1L);
|
||||
|
||||
// set additional headers to prevent caching
|
||||
// Set additional headers to prevent caching
|
||||
headerListM = curl_slist_append(headerListM, "Cache-Control: no-store, no-cache, must-revalidate");
|
||||
headerListM = curl_slist_append(headerListM, "Cache-Control: post-check=0, pre-check=0");
|
||||
headerListM = curl_slist_append(headerListM, "Pragma: no-cache");
|
||||
@@ -337,7 +343,7 @@ bool cIptvProtocolCurl::Connect()
|
||||
break;
|
||||
}
|
||||
|
||||
// add handle into multi set
|
||||
// Add handle into multi set
|
||||
curl_multi_add_handle(multiM, handleM);
|
||||
|
||||
connectedM = true;
|
||||
@@ -351,13 +357,17 @@ bool cIptvProtocolCurl::Disconnect()
|
||||
{
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
debug("cIptvProtocolCurl::%s()", __FUNCTION__);
|
||||
if (handleM) {
|
||||
// mode specific tricks
|
||||
if (!connectedM)
|
||||
return true;
|
||||
|
||||
// Terminate curl session
|
||||
if (handleM && multiM) {
|
||||
// Mode specific tricks
|
||||
switch (modeM) {
|
||||
case eModeRtsp:
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
// teardown rtsp session
|
||||
// Teardown rtsp session
|
||||
cString uri = cString::sprintf("%s/", *streamUrlM);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
||||
@@ -374,16 +384,16 @@ bool cIptvProtocolCurl::Disconnect()
|
||||
break;
|
||||
}
|
||||
|
||||
// cleanup curl stuff
|
||||
// Cleanup curl stuff
|
||||
if (headerListM) {
|
||||
curl_slist_free_all(headerListM);
|
||||
headerListM = NULL;
|
||||
}
|
||||
curl_multi_remove_handle(multiM, handleM);
|
||||
curl_multi_cleanup(multiM);
|
||||
multiM = NULL;
|
||||
curl_easy_cleanup(handleM);
|
||||
handleM = NULL;
|
||||
curl_multi_cleanup(multiM);
|
||||
multiM = NULL;
|
||||
}
|
||||
|
||||
ClearData();
|
||||
@@ -409,21 +419,20 @@ int cIptvProtocolCurl::Read(unsigned char* bufferAddrP, unsigned int bufferLenP)
|
||||
//debug("cIptvProtocolCurl::%s()", __FUNCTION__);
|
||||
int len = 0;
|
||||
if (ringBufferM) {
|
||||
// fill up the buffer
|
||||
// Fill up the buffer
|
||||
if (handleM && multiM) {
|
||||
switch (modeM) {
|
||||
case eModeRtsp:
|
||||
{
|
||||
//CURLcode res = CURLE_OK;
|
||||
//iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_RECEIVE);
|
||||
//iptv_curl_easy_perform(handleM);
|
||||
// @todo - how to detect eof?
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
CURLcode res = CURLE_OK;
|
||||
iptv_curl_easy_setopt(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_RECEIVE);
|
||||
iptv_curl_easy_perform(handleM);
|
||||
// @todo - How to detect eof?
|
||||
}
|
||||
break;
|
||||
|
||||
case eModeFile:
|
||||
break;
|
||||
|
||||
case eModeHttp:
|
||||
case eModeHttps:
|
||||
{
|
||||
@@ -431,24 +440,29 @@ int cIptvProtocolCurl::Read(unsigned char* bufferAddrP, unsigned int bufferLenP)
|
||||
int running_handles;
|
||||
|
||||
do {
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
res = curl_multi_perform(multiM, &running_handles);
|
||||
} while (res == CURLM_CALL_MULTI_PERFORM);
|
||||
|
||||
// shall be continue filling up the buffer?
|
||||
// Shall we continue filling up the buffer?
|
||||
mutexM.Lock();
|
||||
if (pausedM && (ringBufferM->Free() > ringBufferM->Available())) {
|
||||
debug("cIptvProtocolCurl::%s(continue): free=%d available=%d", __FUNCTION__, ringBufferM->Free(), ringBufferM->Available());
|
||||
debug("cIptvProtocolCurl::%s(continue): free=%d available=%d", __FUNCTION__,
|
||||
ringBufferM->Free(), ringBufferM->Available());
|
||||
pausedM = false;
|
||||
curl_easy_pause(handleM, CURLPAUSE_CONT);
|
||||
}
|
||||
mutexM.Unlock();
|
||||
|
||||
// check end of file
|
||||
// Check if end of file
|
||||
if (running_handles == 0) {
|
||||
int msgcount;
|
||||
mutexM.Lock();
|
||||
CURLMsg *msg = curl_multi_info_read(multiM, &msgcount);
|
||||
mutexM.Unlock();
|
||||
if (msg && (msg->msg == CURLMSG_DONE)) {
|
||||
debug("cIptvProtocolCurl::%s(done): %s (%d)", __FUNCTION__, curl_easy_strerror(msg->data.result), msg->data.result);
|
||||
debug("cIptvProtocolCurl::%s(done): %s (%d)", __FUNCTION__,
|
||||
curl_easy_strerror(msg->data.result), msg->data.result);
|
||||
Disconnect();
|
||||
Connect();
|
||||
}
|
||||
@@ -456,17 +470,18 @@ int cIptvProtocolCurl::Read(unsigned char* bufferAddrP, unsigned int bufferLenP)
|
||||
}
|
||||
break;
|
||||
|
||||
case eModeUnknown:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ... and try to empty it
|
||||
unsigned char *p = GetData(&bufferLenP);
|
||||
if (p && (bufferLenP > 0)) {
|
||||
memcpy(bufferAddrP, p, bufferLenP);
|
||||
DelData(bufferLenP);
|
||||
len = bufferLenP;
|
||||
unsigned char *p = GetData(len);
|
||||
if (p && (len > 0)) {
|
||||
len = min(len, (int)bufferLenP);
|
||||
memcpy(bufferAddrP, p, len);
|
||||
DelData(len);
|
||||
//debug("cIptvProtocolCurl::%s(): get %d bytes", __FUNCTION__, len);
|
||||
}
|
||||
}
|
||||
@@ -480,22 +495,20 @@ bool cIptvProtocolCurl::Set(const char* locationP, const int parameterP, const i
|
||||
if (!isempty(locationP)) {
|
||||
// Disconnect
|
||||
Disconnect();
|
||||
// Update stream URL: colons (%3A) and pipes (%7C) shall be decoded
|
||||
char *s = strdup(locationP);
|
||||
strreplace(s, "%3A", ":");
|
||||
strreplace(s, "%7C", "|");
|
||||
streamUrlM = s;
|
||||
free(s);
|
||||
if (startswith(*streamUrlM, "rtsp") || startswith(*streamUrlM, "RTSP"))
|
||||
// Update stream URL
|
||||
streamUrlM = locationP;
|
||||
cString protocol = ChangeCase(streamUrlM, false).Truncate(5);
|
||||
if (startswith(*protocol, "rtsp"))
|
||||
modeM = eModeRtsp;
|
||||
else if (startswith(*streamUrlM, "https") || startswith(*streamUrlM, "HTTPS"))
|
||||
modeM = eModeHttp;
|
||||
else if (startswith(*streamUrlM, "http") || startswith(*streamUrlM, "HTTP"))
|
||||
else if (startswith(*protocol, "https"))
|
||||
modeM = eModeHttps;
|
||||
else if (startswith(*streamUrlM, "file") || startswith(*streamUrlM, "FILE"))
|
||||
else if (startswith(*protocol, "http"))
|
||||
modeM = eModeHttp;
|
||||
else if (startswith(*protocol, "file"))
|
||||
modeM = eModeFile;
|
||||
else
|
||||
modeM = eModeUnknown;
|
||||
debug("cIptvProtocolCurl::%s(): %s (%d)", __FUNCTION__, *protocol, modeM);
|
||||
// Update stream parameter
|
||||
streamParamM = parameterP;
|
||||
// Reconnect
|
||||
|
||||
@@ -29,7 +29,6 @@ private:
|
||||
};
|
||||
enum {
|
||||
eConnectTimeoutS = 5, // in seconds
|
||||
eSelectTimeoutMs = 10, // in milliseconds
|
||||
eMaxDownloadSpeedMBits = 20 // in megabits per second
|
||||
};
|
||||
|
||||
@@ -55,7 +54,7 @@ private:
|
||||
bool PutData(unsigned char *dataP, int lenP);
|
||||
void DelData(int lenP);
|
||||
void ClearData(void);
|
||||
unsigned char *GetData(unsigned int *lenP);
|
||||
unsigned char *GetData(int &lenP);
|
||||
|
||||
public:
|
||||
cIptvProtocolCurl();
|
||||
|
||||
@@ -55,8 +55,9 @@ bool cIptvProtocolHttp::Connect(void)
|
||||
"Connection: Close\r\n"
|
||||
"\r\n", streamPathM, streamAddrM,
|
||||
PLUGIN_NAME_I18N, VERSION);
|
||||
debug("cIptvProtocolHttp::%s(): requesting: %s", __FUNCTION__, *buffer);
|
||||
if (!Write(*buffer, (unsigned int)strlen(*buffer))) {
|
||||
unsigned int len = strlen(*buffer);
|
||||
debug("cIptvProtocolHttp::%s(): requesting %d: %s", __FUNCTION__, len, *buffer);
|
||||
if (!Write(*buffer, len)) {
|
||||
CloseSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
11
sidscanner.c
11
sidscanner.c
@@ -14,7 +14,8 @@ cSidScanner::cSidScanner(void)
|
||||
: channelIdM(tChannelID::InvalidID),
|
||||
sidFoundM(false),
|
||||
nidFoundM(false),
|
||||
tidFoundM(false)
|
||||
tidFoundM(false),
|
||||
isActiveM(false)
|
||||
{
|
||||
debug("cSidScanner::%s()", __FUNCTION__);
|
||||
Set(0x00, 0x00); // PAT
|
||||
@@ -26,12 +27,6 @@ cSidScanner::~cSidScanner()
|
||||
debug("cSidScanner::%s()", __FUNCTION__);
|
||||
}
|
||||
|
||||
void cSidScanner::SetStatus(bool onP)
|
||||
{
|
||||
debug("cSidScanner::%s(%d)", __FUNCTION__, onP);
|
||||
cFilter::SetStatus(onP);
|
||||
}
|
||||
|
||||
void cSidScanner::SetChannel(const tChannelID &channelIdP)
|
||||
{
|
||||
debug("cSidScanner::%s(%s)", __FUNCTION__, *channelIdP.ToString());
|
||||
@@ -46,6 +41,8 @@ void cSidScanner::Process(u_short pidP, u_char tidP, const u_char *dataP, int le
|
||||
int newSid = -1, newNid = -1, newTid = -1;
|
||||
|
||||
//debug("cSidScanner::%s()", __FUNCTION__);
|
||||
if (!isActiveM)
|
||||
return;
|
||||
if (channelIdM.Valid()) {
|
||||
if ((pidP == 0x00) && (tidP == 0x00)) {
|
||||
debug("cSidScanner::%s(%d, %02X)", __FUNCTION__, pidP, tidP);
|
||||
|
||||
@@ -17,17 +17,17 @@ private:
|
||||
bool sidFoundM;
|
||||
bool nidFoundM;
|
||||
bool tidFoundM;
|
||||
bool isActiveM;
|
||||
|
||||
protected:
|
||||
virtual void Process(u_short pidP, u_char tidP, const u_char *dataP, int lengthP);
|
||||
virtual void SetStatus(bool onP);
|
||||
|
||||
public:
|
||||
cSidScanner(void);
|
||||
~cSidScanner();
|
||||
void SetChannel(const tChannelID &channelIdP);
|
||||
void Open() { SetStatus(true); }
|
||||
void Close() { SetStatus(false); }
|
||||
void Open() { debug("cSidScanner::%s()", __FUNCTION__); isActiveM = true; }
|
||||
void Close() { debug("cSidScanner::%s()", __FUNCTION__); isActiveM = false; }
|
||||
};
|
||||
|
||||
#endif // __SIDSCANNER_H
|
||||
|
||||
30
socket.c
30
socket.c
@@ -56,12 +56,12 @@ bool cIptvSocket::OpenSocket(const int portP, const bool isUdpP)
|
||||
ERROR_IF_FUNC(fcntl(socketDescM, F_SETFL, O_NONBLOCK), "fcntl(O_NONBLOCK)",
|
||||
CloseSocket(), return false);
|
||||
// Allow multiple sockets to use the same PORT number
|
||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt(SO_REUSEADDR)",
|
||||
CloseSocket(), return false);
|
||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0,
|
||||
"setsockopt(SO_REUSEADDR)", CloseSocket(), return false);
|
||||
#ifndef __FreeBSD__
|
||||
// Allow packet information to be fetched
|
||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0, "setsockopt(IP_PKTINFO)",
|
||||
CloseSocket(), return false);
|
||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0,
|
||||
"setsockopt(IP_PKTINFO)", CloseSocket(), return false);
|
||||
#endif // __FreeBSD__
|
||||
// Bind socket
|
||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||
@@ -69,7 +69,8 @@ bool cIptvSocket::OpenSocket(const int portP, const bool isUdpP)
|
||||
sockAddrM.sin_port = htons((uint16_t)(portP & 0xFFFF));
|
||||
sockAddrM.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (isUdpP)
|
||||
ERROR_IF_FUNC(bind(socketDescM, (struct sockaddr *)&sockAddrM, sizeof(sockAddrM)) < 0, "bind()", CloseSocket(), return false);
|
||||
ERROR_IF_FUNC(bind(socketDescM, (struct sockaddr *)&sockAddrM, sizeof(sockAddrM)) < 0,
|
||||
"bind()", CloseSocket(), return false);
|
||||
// Update socket port
|
||||
socketPortM = portP;
|
||||
}
|
||||
@@ -99,7 +100,8 @@ bool cIptvSocket::CheckAddress(const char *addrP, in_addr_t *inAddrP)
|
||||
struct hostent *host = gethostbyname(addrP);
|
||||
if (!host) {
|
||||
char tmp[64];
|
||||
error("gethostbyname() failed: %s is not valid address: %s", addrP, strerror_r(h_errno, tmp, sizeof(tmp)));
|
||||
error("gethostbyname() failed: %s is not valid address: %s", addrP,
|
||||
strerror_r(h_errno, tmp, sizeof(tmp)));
|
||||
return false;
|
||||
}
|
||||
*inAddrP = htonl(inet_addr(*host->h_addr_list));
|
||||
@@ -264,22 +266,22 @@ int cIptvUdpSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||
else if (len > 3) {
|
||||
// http://tools.ietf.org/html/rfc3550
|
||||
// http://tools.ietf.org/html/rfc2250
|
||||
// version
|
||||
// Version
|
||||
unsigned int v = (bufferAddrP[0] >> 6) & 0x03;
|
||||
// extension bit
|
||||
// Extension bit
|
||||
unsigned int x = (bufferAddrP[0] >> 4) & 0x01;
|
||||
// cscr count
|
||||
// CSCR count
|
||||
unsigned int cc = bufferAddrP[0] & 0x0F;
|
||||
// payload type: MPEG2 TS = 33
|
||||
// Payload type: MPEG2 TS = 33
|
||||
//unsigned int pt = bufferAddrP[1] & 0x7F;
|
||||
// header lenght
|
||||
// Header lenght
|
||||
unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
||||
// check if extension
|
||||
// Check if extension
|
||||
if (x) {
|
||||
// extension header length
|
||||
// Extension header length
|
||||
unsigned int ehl = (((bufferAddrP[headerlen + 2] & 0xFF) << 8) |
|
||||
(bufferAddrP[headerlen + 3] & 0xFF));
|
||||
// update header length
|
||||
// Update header length
|
||||
headerlen += (ehl + 1) * (unsigned int)sizeof(uint32_t);
|
||||
}
|
||||
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
||||
|
||||
8
source.c
8
source.c
@@ -5,6 +5,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "common.h"
|
||||
#include "source.h"
|
||||
|
||||
@@ -70,7 +71,7 @@ bool cIptvTransponderParameters::Parse(const char *strP)
|
||||
++data;
|
||||
if (data && (*data == '=')) {
|
||||
++data;
|
||||
switch (*token) {
|
||||
switch (toupper(*token)) {
|
||||
case 'S':
|
||||
sidScanM = (int)strtol(data, (char **)NULL, 10);
|
||||
found_s = true;
|
||||
@@ -163,9 +164,8 @@ void cIptvSourceParam::SetData(cChannel *channelP)
|
||||
void cIptvSourceParam::GetData(cChannel *channelP)
|
||||
{
|
||||
debug("cIptvSourceParam::%s(%s)", __FUNCTION__, channelP->Parameters());
|
||||
dataM.SetTransponderData(channelP->Source(), channelP->Frequency(), dataM.Srate(), itpM.ToString(Source()), true);
|
||||
dataM.SetId(nidM, tidM, channelP->Sid(), ridM);
|
||||
*channelP = dataM;
|
||||
channelP->SetTransponderData(channelP->Source(), channelP->Frequency(), dataM.Srate(), itpM.ToString(Source()), true);
|
||||
channelP->SetId(nidM, tidM, channelP->Sid(), ridM);
|
||||
}
|
||||
|
||||
cOsdItem *cIptvSourceParam::GetOsdItem(void)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
cIptvStreamer::cIptvStreamer(cRingBufferLinear* ringBufferP, unsigned int packetLenP)
|
||||
: cThread("IPTV streamer"),
|
||||
ringBufferM(ringBufferP),
|
||||
sleepM(),
|
||||
packetBufferLenM(packetLenP),
|
||||
protocolM(NULL)
|
||||
{
|
||||
@@ -45,8 +46,9 @@ void cIptvStreamer::Action(void)
|
||||
// Do the thread loop
|
||||
while (packetBufferM && Running()) {
|
||||
int length = -1;
|
||||
if (protocolM)
|
||||
length = protocolM->Read(packetBufferM, min((unsigned int)ringBufferM->Free(), packetBufferLenM));
|
||||
unsigned int size = min((unsigned int)ringBufferM->Free(), packetBufferLenM);
|
||||
if (protocolM && (size > 0))
|
||||
length = protocolM->Read(packetBufferM, size);
|
||||
if (length > 0) {
|
||||
AddStreamerStatistic(length);
|
||||
if (ringBufferM) {
|
||||
|
||||
Reference in New Issue
Block a user