mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 13:37:42 +02:00
Merge pull request #3 from rofafor/poller
Refactored poller implementation.
This commit is contained in:
commit
0896df33e6
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,3 +4,6 @@
|
|||||||
*~
|
*~
|
||||||
po/*.pot
|
po/*.pot
|
||||||
po/*.mo
|
po/*.mo
|
||||||
|
.settings
|
||||||
|
.cproject
|
||||||
|
.project
|
||||||
|
2
HISTORY
2
HISTORY
@ -65,7 +65,7 @@ VDR Plugin 'satip' Revision History
|
|||||||
- Added a validity check for the session member.
|
- Added a validity check for the session member.
|
||||||
- Added a session id quirk for Triax TSS 400.
|
- Added a session id quirk for Triax TSS 400.
|
||||||
|
|
||||||
2014-11-11: Version 0.3.4
|
2014-11-22: Version 1.0.0
|
||||||
|
|
||||||
- Fixed the cable only device detection.
|
- Fixed the cable only device detection.
|
||||||
- Added support for blacklisted sources.
|
- Added support for blacklisted sources.
|
||||||
|
5
Makefile
5
Makefile
@ -88,8 +88,9 @@ all-redirect: all
|
|||||||
|
|
||||||
### The object files (add further files here):
|
### The object files (add further files here):
|
||||||
|
|
||||||
OBJS = $(PLUGIN).o common.o config.o device.o discover.o param.o rtsp.o \
|
OBJS = $(PLUGIN).o common.o config.o device.o discover.o msearch.o param.o \
|
||||||
sectionfilter.o server.o setup.o socket.o statistics.o tuner.o
|
poller.o rtp.o rtcp.o rtsp.o sectionfilter.o server.o setup.o socket.o \
|
||||||
|
statistics.o tuner.o
|
||||||
|
|
||||||
### The main target:
|
### The main target:
|
||||||
|
|
||||||
|
3
common.h
3
common.h
@ -8,6 +8,7 @@
|
|||||||
#ifndef __SATIP_COMMON_H
|
#ifndef __SATIP_COMMON_H
|
||||||
#define __SATIP_COMMON_H
|
#define __SATIP_COMMON_H
|
||||||
|
|
||||||
|
#include <vdr/device.h>
|
||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
#include <vdr/config.h>
|
#include <vdr/config.h>
|
||||||
#include <vdr/i18n.h>
|
#include <vdr/i18n.h>
|
||||||
@ -24,6 +25,8 @@
|
|||||||
|
|
||||||
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
|
#define SATIP_MAX_DEVICES MAXDEVICES
|
||||||
|
|
||||||
#define SATIP_BUFFER_SIZE KILOBYTE(512)
|
#define SATIP_BUFFER_SIZE KILOBYTE(512)
|
||||||
|
|
||||||
#define SATIP_DEVICE_INFO_ALL 0
|
#define SATIP_DEVICE_INFO_ALL 0
|
||||||
|
2
device.c
2
device.c
@ -12,8 +12,6 @@
|
|||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
#define SATIP_MAX_DEVICES MAXDEVICES
|
|
||||||
|
|
||||||
static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
|
static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
|
||||||
|
|
||||||
cSatipDevice::cSatipDevice(unsigned int indexP)
|
cSatipDevice::cSatipDevice(unsigned int indexP)
|
||||||
|
138
discover.c
138
discover.c
@ -18,13 +18,6 @@
|
|||||||
|
|
||||||
cSatipDiscover *cSatipDiscover::instanceS = NULL;
|
cSatipDiscover *cSatipDiscover::instanceS = NULL;
|
||||||
|
|
||||||
const char *cSatipDiscover::bcastAddressS = "239.255.255.250";
|
|
||||||
const char *cSatipDiscover::bcastMessageS = "M-SEARCH * HTTP/1.1\r\n" \
|
|
||||||
"HOST: 239.255.255.250:1900\r\n" \
|
|
||||||
"MAN: \"ssdp:discover\"\r\n" \
|
|
||||||
"ST: urn:ses-com:device:SatIPServer:1\r\n" \
|
|
||||||
"MX: 2\r\n\r\n";
|
|
||||||
|
|
||||||
cSatipDiscover *cSatipDiscover::GetInstance(void)
|
cSatipDiscover *cSatipDiscover::GetInstance(void)
|
||||||
{
|
{
|
||||||
if (!instanceS)
|
if (!instanceS)
|
||||||
@ -126,11 +119,12 @@ int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *data
|
|||||||
cSatipDiscover::cSatipDiscover()
|
cSatipDiscover::cSatipDiscover()
|
||||||
: cThread("SAT>IP discover"),
|
: cThread("SAT>IP discover"),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
|
msearchM(),
|
||||||
|
probeUrlListM(),
|
||||||
handleM(curl_easy_init()),
|
handleM(curl_easy_init()),
|
||||||
socketM(new cSatipSocket()),
|
|
||||||
sleepM(),
|
sleepM(),
|
||||||
probeIntervalM(0),
|
probeIntervalM(0),
|
||||||
serversM(new cSatipServers())
|
serversM()
|
||||||
{
|
{
|
||||||
debug("cSatipDiscover::%s()", __FUNCTION__);
|
debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
}
|
}
|
||||||
@ -141,11 +135,10 @@ cSatipDiscover::~cSatipDiscover()
|
|||||||
Deactivate();
|
Deactivate();
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
// Free allocated memory
|
// Free allocated memory
|
||||||
DELETENULL(socketM);
|
|
||||||
DELETENULL(serversM);
|
|
||||||
if (handleM)
|
if (handleM)
|
||||||
curl_easy_cleanup(handleM);
|
curl_easy_cleanup(handleM);
|
||||||
handleM = NULL;
|
handleM = NULL;
|
||||||
|
probeUrlListM.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::Activate(void)
|
void cSatipDiscover::Activate(void)
|
||||||
@ -166,84 +159,49 @@ void cSatipDiscover::Deactivate(void)
|
|||||||
void cSatipDiscover::Action(void)
|
void cSatipDiscover::Action(void)
|
||||||
{
|
{
|
||||||
debug("cSatipDiscover::%s(): entering", __FUNCTION__);
|
debug("cSatipDiscover::%s(): entering", __FUNCTION__);
|
||||||
|
probeIntervalM.Set(eProbeIntervalMs);
|
||||||
|
msearchM.Probe();
|
||||||
// Do the thread loop
|
// Do the thread loop
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
|
cStringList tmp;
|
||||||
|
|
||||||
if (probeIntervalM.TimedOut()) {
|
if (probeIntervalM.TimedOut()) {
|
||||||
probeIntervalM.Set(eProbeIntervalMs);
|
probeIntervalM.Set(eProbeIntervalMs);
|
||||||
Probe();
|
msearchM.Probe();
|
||||||
Janitor();
|
mutexM.Lock();
|
||||||
|
serversM.Cleanup(eProbeIntervalMs * 2);
|
||||||
|
mutexM.Unlock();
|
||||||
|
}
|
||||||
|
mutexM.Lock();
|
||||||
|
if (probeUrlListM.Size()) {
|
||||||
|
for (int i = 0; i < probeUrlListM.Size(); ++i)
|
||||||
|
tmp.Insert(strdup(probeUrlListM.At(i)));
|
||||||
|
probeUrlListM.Clear();
|
||||||
|
}
|
||||||
|
mutexM.Unlock();
|
||||||
|
if (tmp.Size()) {
|
||||||
|
for (int i = 0; i < tmp.Size(); ++i)
|
||||||
|
Fetch(tmp.At(i));
|
||||||
|
tmp.Clear();
|
||||||
}
|
}
|
||||||
// to avoid busy loop and reduce cpu load
|
// to avoid busy loop and reduce cpu load
|
||||||
sleepM.Wait(10);
|
sleepM.Wait(eSleepTimeoutMs);
|
||||||
}
|
}
|
||||||
debug("cSatipDiscover::%s(): exiting", __FUNCTION__);
|
debug("cSatipDiscover::%s(): exiting", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::Janitor(void)
|
void cSatipDiscover::Probe(const char *urlP)
|
||||||
{
|
{
|
||||||
debug("cSatipDiscover::%s()", __FUNCTION__);
|
debug("cSatipDiscover::%s(%s)", __FUNCTION__, urlP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (serversM)
|
probeUrlListM.Insert(strdup(urlP));
|
||||||
serversM->Cleanup(eProbeIntervalMs * 2);
|
sleepM.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::Probe(void)
|
void cSatipDiscover::Fetch(const char *urlP)
|
||||||
{
|
{
|
||||||
debug("cSatipDiscover::%s()", __FUNCTION__);
|
debug("cSatipDiscover::%s(%s)", __FUNCTION__, urlP);
|
||||||
if (socketM && socketM->Open(eDiscoveryPort)) {
|
if (handleM && !isempty(urlP)) {
|
||||||
cTimeMs timeout(eProbeTimeoutMs);
|
|
||||||
socketM->Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
|
|
||||||
while (Running() && !timeout.TimedOut()) {
|
|
||||||
Read();
|
|
||||||
// to avoid busy loop and reduce cpu load
|
|
||||||
sleepM.Wait(100);
|
|
||||||
}
|
|
||||||
socketM->Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipDiscover::Read(void)
|
|
||||||
{
|
|
||||||
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
|
||||||
if (socketM) {
|
|
||||||
unsigned char *buf = MALLOC(unsigned char, eProbeBufferSize + 1);
|
|
||||||
if (buf) {
|
|
||||||
memset(buf, 0, eProbeBufferSize + 1);
|
|
||||||
int len = socketM->Read(buf, eProbeBufferSize);
|
|
||||||
if (len > 0) {
|
|
||||||
//debug("cSatipDiscover::%s(): len=%d", __FUNCTION__, len);
|
|
||||||
bool status = false, valid = false;
|
|
||||||
char *s, *p = reinterpret_cast<char *>(buf), *location = NULL;
|
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
|
||||||
while (r) {
|
|
||||||
//debug("cSatipDiscover::%s(): %s", __FUNCTION__, r);
|
|
||||||
// Check the status code
|
|
||||||
// HTTP/1.1 200 OK
|
|
||||||
if (!status && startswith(r, "HTTP/1.1 200 OK")) {
|
|
||||||
status = true;
|
|
||||||
}
|
|
||||||
if (status) {
|
|
||||||
// Check the location data
|
|
||||||
// LOCATION: http://192.168.0.115:8888/octonet.xml
|
|
||||||
if (startswith(r, "LOCATION:")) {
|
|
||||||
location = compactspace(r + 9);
|
|
||||||
debug("cSatipDiscover::%s(): location='%s'", __FUNCTION__, location);
|
|
||||||
}
|
|
||||||
// Check the source type
|
|
||||||
// ST: urn:ses-com:device:SatIPServer:1
|
|
||||||
else if (startswith(r, "ST:")) {
|
|
||||||
char *st = compactspace(r + 3);
|
|
||||||
if (strstr(st, "urn:ses-com:device:SatIPServer:1"))
|
|
||||||
valid = true;
|
|
||||||
debug("cSatipDiscover::%s(): st='%s'", __FUNCTION__, st);
|
|
||||||
}
|
|
||||||
// Check whether all the required data is found
|
|
||||||
if (valid && !isempty(location))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
if (handleM && valid && !isempty(location)) {
|
|
||||||
long rc = 0;
|
long rc = 0;
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -268,7 +226,7 @@ void cSatipDiscover::Read(void)
|
|||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
|
||||||
|
|
||||||
// Set URL
|
// Set URL
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, location);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, urlP);
|
||||||
|
|
||||||
// Fetch the data
|
// Fetch the data
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
@ -277,88 +235,80 @@ void cSatipDiscover::Read(void)
|
|||||||
error("Discovery detected invalid status code: %ld", rc);
|
error("Discovery detected invalid status code: %ld", rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP)
|
void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP)
|
||||||
{
|
{
|
||||||
debug("cSatipDiscover::%s(%s, %s, %s)", __FUNCTION__, addrP, modelP, descP);
|
debug("cSatipDiscover::%s(%s, %s, %s)", __FUNCTION__, addrP, modelP, descP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (serversM) {
|
|
||||||
cSatipServer *tmp = new cSatipServer(addrP, modelP, descP);
|
cSatipServer *tmp = new cSatipServer(addrP, modelP, descP);
|
||||||
// Validate against existing servers
|
// Validate against existing servers
|
||||||
if (!serversM->Update(tmp)) {
|
if (!serversM.Update(tmp)) {
|
||||||
info("Adding device '%s|%s|%s'", tmp->Address(), tmp->Model(), tmp->Description());
|
info("Adding device '%s|%s|%s'", tmp->Address(), tmp->Model(), tmp->Description());
|
||||||
serversM->Add(tmp);
|
serversM.Add(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DELETENULL(tmp);
|
DELETENULL(tmp);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipDiscover::GetServerCount(void)
|
int cSatipDiscover::GetServerCount(void)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM ? serversM->Count() : -1;
|
return serversM.Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipDiscover::GetServer(int sourceP, int transponderP, int systemP)
|
cSatipServer *cSatipDiscover::GetServer(int sourceP, int transponderP, int systemP)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s(%d, %d, %d)", __FUNCTION__, sourceP, transponderP, systemP);
|
//debug("cSatipDiscover::%s(%d, %d, %d)", __FUNCTION__, sourceP, transponderP, systemP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM ? serversM->Find(sourceP, transponderP, systemP) : NULL;
|
return serversM.Find(sourceP, transponderP, systemP);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
|
cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM ? serversM->Find(serverP) : NULL;
|
return serversM.Find(serverP);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServers *cSatipDiscover::GetServers(void)
|
cSatipServers *cSatipDiscover::GetServers(void)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM;
|
return &serversM;
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDiscover::GetServerString(cSatipServer *serverP)
|
cString cSatipDiscover::GetServerString(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM ? serversM->GetString(serverP) : "";
|
return serversM.GetString(serverP);
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDiscover::GetServerList(void)
|
cString cSatipDiscover::GetServerList(void)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM ? serversM->List() : "";
|
return serversM.List();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::SetTransponder(cSatipServer *serverP, int transponderP)
|
void cSatipDiscover::SetTransponder(cSatipServer *serverP, int transponderP)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, transponderP);
|
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, transponderP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (serversM)
|
serversM.SetTransponder(serverP, transponderP);
|
||||||
serversM->SetTransponder(serverP, transponderP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::UseServer(cSatipServer *serverP, bool onOffP)
|
void cSatipDiscover::UseServer(cSatipServer *serverP, bool onOffP)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, onOffP);
|
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, onOffP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (serversM)
|
serversM.Use(serverP, onOffP);
|
||||||
serversM->Use(serverP, onOffP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipDiscover::NumProvidedSystems(void)
|
int cSatipDiscover::NumProvidedSystems(void)
|
||||||
{
|
{
|
||||||
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM ? serversM->NumProvidedSystems() : 0;
|
return serversM.NumProvidedSystems();
|
||||||
}
|
}
|
||||||
|
16
discover.h
16
discover.h
@ -13,6 +13,7 @@
|
|||||||
#include <vdr/thread.h>
|
#include <vdr/thread.h>
|
||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
|
#include "msearch.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
@ -37,29 +38,25 @@ class cSatipDiscoverServers : public cList<cSatipDiscoverServer> {
|
|||||||
class cSatipDiscover : public cThread {
|
class cSatipDiscover : public cThread {
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
|
eSleepTimeoutMs = 500, // in milliseconds
|
||||||
eConnectTimeoutMs = 1500, // in milliseconds
|
eConnectTimeoutMs = 1500, // in milliseconds
|
||||||
eDiscoveryPort = 1900,
|
|
||||||
eProbeBufferSize = 1024, // in bytes
|
|
||||||
eProbeTimeoutMs = 2000, // in milliseconds
|
eProbeTimeoutMs = 2000, // in milliseconds
|
||||||
eProbeIntervalMs = 60000 // in milliseconds
|
eProbeIntervalMs = 60000 // in milliseconds
|
||||||
};
|
};
|
||||||
static cSatipDiscover *instanceS;
|
static cSatipDiscover *instanceS;
|
||||||
static const char *bcastAddressS;
|
|
||||||
static const char *bcastMessageS;
|
|
||||||
static size_t WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static size_t WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
|
cSatipMsearch msearchM;
|
||||||
|
cStringList probeUrlListM;
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
cSatipSocket *socketM;
|
|
||||||
cCondWait sleepM;
|
cCondWait sleepM;
|
||||||
cTimeMs probeIntervalM;
|
cTimeMs probeIntervalM;
|
||||||
cSatipServers *serversM;
|
cSatipServers serversM;
|
||||||
void Activate(void);
|
void Activate(void);
|
||||||
void Deactivate(void);
|
void Deactivate(void);
|
||||||
void Janitor(void);
|
|
||||||
void Probe(void);
|
|
||||||
void Read(void);
|
|
||||||
void AddServer(const char *addrP, const char *modelP, const char *descP);
|
void AddServer(const char *addrP, const char *modelP, const char *descP);
|
||||||
|
void Fetch(const char *urlP);
|
||||||
// constructor
|
// constructor
|
||||||
cSatipDiscover();
|
cSatipDiscover();
|
||||||
// to prevent copy constructor and assignment
|
// to prevent copy constructor and assignment
|
||||||
@ -74,6 +71,7 @@ public:
|
|||||||
static bool Initialize(cSatipDiscoverServers *serversP);
|
static bool Initialize(cSatipDiscoverServers *serversP);
|
||||||
static void Destroy(void);
|
static void Destroy(void);
|
||||||
virtual ~cSatipDiscover();
|
virtual ~cSatipDiscover();
|
||||||
|
void Probe(const char *urlP);
|
||||||
void TriggerScan(void) { probeIntervalM.Set(0); }
|
void TriggerScan(void) { probeIntervalM.Set(0); }
|
||||||
int GetServerCount(void);
|
int GetServerCount(void);
|
||||||
cSatipServer *GetServer(int sourceP, int transponderP = 0, int systemP = -1);
|
cSatipServer *GetServer(int sourceP, int transponderP = 0, int systemP = -1);
|
||||||
|
94
msearch.c
Normal file
94
msearch.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* msearch.c: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "discover.h"
|
||||||
|
#include "poller.h"
|
||||||
|
#include "msearch.h"
|
||||||
|
|
||||||
|
const char *cSatipMsearch::bcastAddressS = "239.255.255.250";
|
||||||
|
const char *cSatipMsearch::bcastMessageS = "M-SEARCH * HTTP/1.1\r\n" \
|
||||||
|
"HOST: 239.255.255.250:1900\r\n" \
|
||||||
|
"MAN: \"ssdp:discover\"\r\n" \
|
||||||
|
"ST: urn:ses-com:device:SatIPServer:1\r\n" \
|
||||||
|
"MX: 2\r\n\r\n";
|
||||||
|
|
||||||
|
cSatipMsearch::cSatipMsearch(void)
|
||||||
|
: bufferLenM(eProbeBufferSize),
|
||||||
|
bufferM(MALLOC(unsigned char, bufferLenM)),
|
||||||
|
registeredM(false)
|
||||||
|
{
|
||||||
|
if (bufferM)
|
||||||
|
memset(bufferM, 0, bufferLenM);
|
||||||
|
else
|
||||||
|
error("Cannot create Msearch buffer!");
|
||||||
|
if (!Open(eDiscoveryPort))
|
||||||
|
error("Cannot open Msearch port!");
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipMsearch::~cSatipMsearch()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipMsearch::Probe(void)
|
||||||
|
{
|
||||||
|
debug("cSatipMsearch::%s()", __FUNCTION__);
|
||||||
|
if (!registeredM) {
|
||||||
|
cSatipPoller::GetInstance()->Register(*this);
|
||||||
|
registeredM = true;
|
||||||
|
}
|
||||||
|
Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipMsearch::GetFd(void)
|
||||||
|
{
|
||||||
|
return Fd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipMsearch::Process(int fdP)
|
||||||
|
{
|
||||||
|
//debug("cSatipMsearch::%s()", __FUNCTION__);
|
||||||
|
if (bufferM) {
|
||||||
|
int length = Read(bufferM, bufferLenM);
|
||||||
|
if (length > 0) {
|
||||||
|
bufferM[min(length, int(bufferLenM - 1))] = 0;
|
||||||
|
//debug("cSatipMsearch::%s(): len=%d buf=%s", __FUNCTION__, length, bufferM);
|
||||||
|
bool status = false, valid = false;
|
||||||
|
char *s, *p = reinterpret_cast<char *>(bufferM), *location = NULL;
|
||||||
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
while (r) {
|
||||||
|
//debug("cSatipMsearch::%s(): %s", __FUNCTION__, r);
|
||||||
|
// Check the status code
|
||||||
|
// HTTP/1.1 200 OK
|
||||||
|
if (!status && startswith(r, "HTTP/1.1 200 OK"))
|
||||||
|
status = true;
|
||||||
|
if (status) {
|
||||||
|
// Check the location data
|
||||||
|
// LOCATION: http://192.168.0.115:8888/octonet.xml
|
||||||
|
if (startswith(r, "LOCATION:")) {
|
||||||
|
location = compactspace(r + 9);
|
||||||
|
debug("cSatipMsearch::%s(): location='%s'", __FUNCTION__, location);
|
||||||
|
}
|
||||||
|
// Check the source type
|
||||||
|
// ST: urn:ses-com:device:SatIPServer:1
|
||||||
|
else if (startswith(r, "ST:")) {
|
||||||
|
char *st = compactspace(r + 3);
|
||||||
|
if (strstr(st, "urn:ses-com:device:SatIPServer:1"))
|
||||||
|
valid = true;
|
||||||
|
debug("cSatipMsearch::%s(): st='%s'", __FUNCTION__, st);
|
||||||
|
}
|
||||||
|
// Check whether all the required data is found
|
||||||
|
if (valid && !isempty(location)) {
|
||||||
|
cSatipDiscover::GetInstance()->Probe(location);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
msearch.h
Normal file
37
msearch.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* msearch.h: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SATIP_MSEARCH_H_
|
||||||
|
#define __SATIP_MSEARCH_H_
|
||||||
|
|
||||||
|
#include "socket.h"
|
||||||
|
#include "pollerif.h"
|
||||||
|
|
||||||
|
class cSatipMsearch : public cSatipSocket, public cSatipPollerIf {
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
eProbeBufferSize = 1024, // in bytes
|
||||||
|
eDiscoveryPort = 1900,
|
||||||
|
};
|
||||||
|
static const char *bcastAddressS;
|
||||||
|
static const char *bcastMessageS;
|
||||||
|
unsigned int bufferLenM;
|
||||||
|
unsigned char *bufferM;
|
||||||
|
bool registeredM;
|
||||||
|
|
||||||
|
public:
|
||||||
|
cSatipMsearch(void);
|
||||||
|
virtual ~cSatipMsearch();
|
||||||
|
void Probe(void);
|
||||||
|
|
||||||
|
// for internal poller interface
|
||||||
|
public:
|
||||||
|
virtual int GetFd(void);
|
||||||
|
virtual void Process(int fdP);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __SATIP_MSEARCH_H_ */
|
@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 0.3.4\n"
|
"Project-Id-Version: vdr-satip 1.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-11-11 11:11+0200\n"
|
"POT-Creation-Date: 2014-11-22 11:22+0200\n"
|
||||||
"PO-Revision-Date: 2014-11-11 11:11+0200\n"
|
"PO-Revision-Date: 2014-11-22 11:22+0200\n"
|
||||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||||
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
||||||
"Language: ca\n"
|
"Language: ca\n"
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 0.3.4\n"
|
"Project-Id-Version: vdr-satip 1.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-11-11 11:11+0200\n"
|
"POT-Creation-Date: 2014-11-22 11:22+0200\n"
|
||||||
"PO-Revision-Date: 2014-11-11 11:11+0200\n"
|
"PO-Revision-Date: 2014-11-22 11:22+0200\n"
|
||||||
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
|
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
|
||||||
"Language-Team: German <vdr@linuxtv.org>\n"
|
"Language-Team: German <vdr@linuxtv.org>\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 0.3.4\n"
|
"Project-Id-Version: vdr-satip 1.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-11-11 11:11+0200\n"
|
"POT-Creation-Date: 2014-11-22 11:22+0200\n"
|
||||||
"PO-Revision-Date: 2014-11-11 11:11+0200\n"
|
"PO-Revision-Date: 2014-11-22 11:22+0200\n"
|
||||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||||
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
||||||
"Language: es\n"
|
"Language: es\n"
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 0.3.4\n"
|
"Project-Id-Version: vdr-satip 1.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-11-11 11:11+0200\n"
|
"POT-Creation-Date: 2014-11-22 11:22+0200\n"
|
||||||
"PO-Revision-Date: 2014-11-11 11:11+0200\n"
|
"PO-Revision-Date: 2014-11-22 11:22+0200\n"
|
||||||
"Last-Translator: Rolf Ahrenberg\n"
|
"Last-Translator: Rolf Ahrenberg\n"
|
||||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
||||||
"Language: fi\n"
|
"Language: fi\n"
|
||||||
|
109
poller.c
Normal file
109
poller.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* poller.c: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "poller.h"
|
||||||
|
|
||||||
|
cSatipPoller *cSatipPoller::instanceS = NULL;
|
||||||
|
|
||||||
|
cSatipPoller *cSatipPoller::GetInstance(void)
|
||||||
|
{
|
||||||
|
if (!instanceS)
|
||||||
|
instanceS = new cSatipPoller();
|
||||||
|
return instanceS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipPoller::Initialize(void)
|
||||||
|
{
|
||||||
|
debug("cSatipPoller::%s()", __FUNCTION__);
|
||||||
|
if (instanceS)
|
||||||
|
instanceS->Activate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipPoller::Destroy(void)
|
||||||
|
{
|
||||||
|
debug("cSatipPoller::%s()", __FUNCTION__);
|
||||||
|
if (instanceS)
|
||||||
|
instanceS->Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipPoller::cSatipPoller()
|
||||||
|
: cThread("SAT>IP poller"),
|
||||||
|
mutexM(),
|
||||||
|
fdM(epoll_create(eMaxFileDescriptors))
|
||||||
|
{
|
||||||
|
debug("cSatipPoller::%s()", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipPoller::~cSatipPoller()
|
||||||
|
{
|
||||||
|
debug("cSatipPoller::%s()", __FUNCTION__);
|
||||||
|
Deactivate();
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
close(fdM);
|
||||||
|
// Free allocated memory
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipPoller::Activate(void)
|
||||||
|
{
|
||||||
|
// Start the thread
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipPoller::Deactivate(void)
|
||||||
|
{
|
||||||
|
debug("cSatipPoller::%s()", __FUNCTION__);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
if (Running())
|
||||||
|
Cancel(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipPoller::Action(void)
|
||||||
|
{
|
||||||
|
debug("cSatipPoller::%s(): entering", __FUNCTION__);
|
||||||
|
struct epoll_event events[eMaxFileDescriptors];
|
||||||
|
// Increase priority
|
||||||
|
SetPriority(-1);
|
||||||
|
// Do the thread loop
|
||||||
|
while (Running()) {
|
||||||
|
int nfds = epoll_wait(fdM, events, eMaxFileDescriptors, -1);
|
||||||
|
ERROR_IF_FUNC((nfds == -1), "epoll_wait() failed", break, ;);
|
||||||
|
for (int i = 0; i < nfds; ++i) {
|
||||||
|
cSatipPollerIf* poll = reinterpret_cast<cSatipPollerIf *>(events[i].data.ptr);
|
||||||
|
if (poll)
|
||||||
|
poll->Process(events[i].events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug("cSatipPoller::%s(): exiting", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipPoller::Register(cSatipPollerIf &pollerP)
|
||||||
|
{
|
||||||
|
debug("cSatipPoller::%s(%d)", __FUNCTION__, pollerP.GetFd());
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
|
||||||
|
struct epoll_event ev;
|
||||||
|
ev.events = EPOLLIN | EPOLLET;
|
||||||
|
ev.data.ptr = &pollerP;
|
||||||
|
ERROR_IF_RET(epoll_ctl(fdM, EPOLL_CTL_ADD, pollerP.GetFd(), &ev) == -1, "epoll_ctl(EPOLL_CTL_ADD) failed", return false);
|
||||||
|
debug("cSatipPoller::%s(%d): Added interface", __FUNCTION__, pollerP.GetFd());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipPoller::Unregister(cSatipPollerIf &pollerP)
|
||||||
|
{
|
||||||
|
debug("cSatipPoller::%s(%d)", __FUNCTION__, pollerP.GetFd());
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
ERROR_IF_RET((epoll_ctl(fdM, EPOLL_CTL_DEL, pollerP.GetFd(), NULL) == -1), "epoll_ctl(EPOLL_CTL_DEL) failed", return false);
|
||||||
|
debug("cSatipPoller::%s(%d): Removed interface", __FUNCTION__, pollerP.GetFd());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
44
poller.h
Normal file
44
poller.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* poller.h: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SATIP_POLLER_H
|
||||||
|
#define __SATIP_POLLER_H
|
||||||
|
|
||||||
|
#include <vdr/thread.h>
|
||||||
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
|
#include "pollerif.h"
|
||||||
|
|
||||||
|
class cSatipPoller : public cThread {
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
eMaxFileDescriptors = SATIP_MAX_DEVICES * 2, // Data + Application
|
||||||
|
};
|
||||||
|
static cSatipPoller *instanceS;
|
||||||
|
cMutex mutexM;
|
||||||
|
int fdM;
|
||||||
|
void Activate(void);
|
||||||
|
void Deactivate(void);
|
||||||
|
// constructor
|
||||||
|
cSatipPoller();
|
||||||
|
// to prevent copy constructor and assignment
|
||||||
|
cSatipPoller(const cSatipPoller&);
|
||||||
|
cSatipPoller& operator=(const cSatipPoller&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void Action(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static cSatipPoller *GetInstance(void);
|
||||||
|
static bool Initialize(void);
|
||||||
|
static void Destroy(void);
|
||||||
|
virtual ~cSatipPoller();
|
||||||
|
bool Register(cSatipPollerIf &pollerP);
|
||||||
|
bool Unregister(cSatipPollerIf &pollerP);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __SATIP_POLLER_H
|
23
pollerif.h
Normal file
23
pollerif.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* pollerif.h: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SATIP_POLLERIF_H
|
||||||
|
#define __SATIP_POLLERIF_H
|
||||||
|
|
||||||
|
class cSatipPollerIf {
|
||||||
|
public:
|
||||||
|
cSatipPollerIf() {}
|
||||||
|
virtual ~cSatipPollerIf() {}
|
||||||
|
virtual int GetFd(void) = 0;
|
||||||
|
virtual void Process(int fdP) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
cSatipPollerIf(const cSatipPollerIf&);
|
||||||
|
cSatipPollerIf& operator=(const cSatipPollerIf&);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __SATIP_POLLERIF_H
|
88
rtcp.c
Normal file
88
rtcp.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* rtcp.c: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "rtcp.h"
|
||||||
|
|
||||||
|
cSatipRtcp::cSatipRtcp(cSatipTunerIf &tunerP, unsigned int bufferLenP)
|
||||||
|
: tunerM(tunerP),
|
||||||
|
bufferLenM(bufferLenP),
|
||||||
|
bufferM(MALLOC(unsigned char, bufferLenM))
|
||||||
|
{
|
||||||
|
if (bufferM)
|
||||||
|
memset(bufferM, 0, bufferLenM);
|
||||||
|
else
|
||||||
|
error("Cannot create RTCP buffer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipRtcp::~cSatipRtcp()
|
||||||
|
{
|
||||||
|
DELETE_POINTER(bufferM);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipRtcp::GetFd(void)
|
||||||
|
{
|
||||||
|
return Fd();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipRtcp::GetApplicationOffset(int *lengthP)
|
||||||
|
{
|
||||||
|
//debug("cSatipRtcp::%s()", __FUNCTION__);
|
||||||
|
if (!lengthP)
|
||||||
|
return -1;
|
||||||
|
int offset = 0;
|
||||||
|
int total = *lengthP;
|
||||||
|
while (total > 0) {
|
||||||
|
// Version
|
||||||
|
unsigned int v = (bufferM[offset] >> 6) & 0x03;
|
||||||
|
// Padding
|
||||||
|
//unsigned int p = (bufferM[offset] >> 5) & 0x01;
|
||||||
|
// Subtype
|
||||||
|
//unsigned int st = bufferM[offset] & 0x1F;
|
||||||
|
// Payload type
|
||||||
|
unsigned int pt = bufferM[offset + 1] & 0xFF;
|
||||||
|
// Lenght
|
||||||
|
unsigned int length = ((bufferM[offset + 2] & 0xFF) << 8) | (bufferM[offset + 3] & 0xFF);
|
||||||
|
// Convert it to bytes
|
||||||
|
length = (length + 1) * 4;
|
||||||
|
// V=2, APP = 204
|
||||||
|
if ((v == 2) && (pt == 204)) {
|
||||||
|
// SSCR/CSCR
|
||||||
|
//unsigned int ssrc = ((bufferM[offset + 4] & 0xFF) << 24) | ((bufferM[offset + 5] & 0xFF) << 16) |
|
||||||
|
// ((bufferM[offset + 6] & 0xFF) << 8) | (bufferM[offset + 7] & 0xFF);
|
||||||
|
// Name
|
||||||
|
if ((bufferM[offset + 8] == 'S') && (bufferM[offset + 9] == 'E') &&
|
||||||
|
(bufferM[offset + 10] == 'S') && (bufferM[offset + 11] == '1')) {
|
||||||
|
// Identifier
|
||||||
|
//unsigned int id = ((bufferM[offset + 12] & 0xFF) << 8) | (bufferM[offset + 13] & 0xFF);
|
||||||
|
// String length
|
||||||
|
int string_length = ((bufferM[offset + 14] & 0xFF) << 8) | (bufferM[offset + 15] & 0xFF);
|
||||||
|
if (string_length > 0) {
|
||||||
|
*lengthP = string_length;
|
||||||
|
return (offset + 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset += length;
|
||||||
|
total -= length;
|
||||||
|
}
|
||||||
|
*lengthP = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipRtcp::Process(int fdP)
|
||||||
|
{
|
||||||
|
//debug("cSatipRtcp::%s(%d)", __FUNCTION__, fdP);
|
||||||
|
if (bufferM) {
|
||||||
|
int length = Read(bufferM, bufferLenM);
|
||||||
|
if (length > 0) {
|
||||||
|
int offset = GetApplicationOffset(&length);
|
||||||
|
if (offset >= 0)
|
||||||
|
tunerM.ProcessApplicationData(bufferM + offset, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
rtcp.h
Normal file
32
rtcp.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* rtcp.h: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SATIP_RTCP_H_
|
||||||
|
#define __SATIP_RTCP_H_
|
||||||
|
|
||||||
|
#include "socket.h"
|
||||||
|
#include "tunerif.h"
|
||||||
|
#include "pollerif.h"
|
||||||
|
|
||||||
|
class cSatipRtcp : public cSatipSocket, public cSatipPollerIf {
|
||||||
|
private:
|
||||||
|
cSatipTunerIf &tunerM;
|
||||||
|
unsigned int bufferLenM;
|
||||||
|
unsigned char *bufferM;
|
||||||
|
int GetApplicationOffset(int *lenghtP);
|
||||||
|
|
||||||
|
public:
|
||||||
|
cSatipRtcp(cSatipTunerIf &tunerP, unsigned int bufferLenP);
|
||||||
|
virtual ~cSatipRtcp();
|
||||||
|
|
||||||
|
// for internal poller interface
|
||||||
|
public:
|
||||||
|
virtual int GetFd(void);
|
||||||
|
virtual void Process(int fdP);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __SATIP_RTCP_H_ */
|
114
rtp.c
Normal file
114
rtp.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* rtp.c: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "rtp.h"
|
||||||
|
|
||||||
|
cSatipRtp::cSatipRtp(cSatipTunerIf &tunerP, unsigned int bufferLenP)
|
||||||
|
: tunerM(tunerP),
|
||||||
|
bufferLenM(bufferLenP),
|
||||||
|
bufferM(MALLOC(unsigned char, bufferLenM)),
|
||||||
|
lastErrorReportM(0),
|
||||||
|
packetErrorsM(0),
|
||||||
|
sequenceNumberM(-1)
|
||||||
|
{
|
||||||
|
if (bufferM)
|
||||||
|
memset(bufferM, 0, bufferLenM);
|
||||||
|
else
|
||||||
|
error("Cannot create RTP buffer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipRtp::~cSatipRtp()
|
||||||
|
{
|
||||||
|
DELETE_POINTER(bufferM);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipRtp::GetFd(void)
|
||||||
|
{
|
||||||
|
return Fd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipRtp::Close(void)
|
||||||
|
{
|
||||||
|
debug("cSatipRtp::%s(%d)", __FUNCTION__, GetFd());
|
||||||
|
|
||||||
|
cSatipSocket::Close();
|
||||||
|
|
||||||
|
sequenceNumberM = -1;
|
||||||
|
if (packetErrorsM) {
|
||||||
|
info("Detected %d RTP packet errors", packetErrorsM);
|
||||||
|
packetErrorsM = 0;
|
||||||
|
lastErrorReportM = time(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipRtp::GetHeaderLenght(int lengthP)
|
||||||
|
{
|
||||||
|
//debug("cSatipRtp::%s()", __FUNCTION__);
|
||||||
|
unsigned int headerlen = 0;
|
||||||
|
|
||||||
|
if (lengthP > 0) {
|
||||||
|
if (bufferM[0] == TS_SYNC_BYTE)
|
||||||
|
return headerlen;
|
||||||
|
else if (lengthP > 3) {
|
||||||
|
// http://tools.ietf.org/html/rfc3550
|
||||||
|
// http://tools.ietf.org/html/rfc2250
|
||||||
|
// Version
|
||||||
|
unsigned int v = (bufferM[0] >> 6) & 0x03;
|
||||||
|
// Extension bit
|
||||||
|
unsigned int x = (bufferM[0] >> 4) & 0x01;
|
||||||
|
// CSCR count
|
||||||
|
unsigned int cc = bufferM[0] & 0x0F;
|
||||||
|
// Payload type: MPEG2 TS = 33
|
||||||
|
//unsigned int pt = bufferAddrP[1] & 0x7F;
|
||||||
|
// Sequence number
|
||||||
|
int seq = ((bufferM[2] & 0xFF) << 8) | (bufferM[3] & 0xFF);
|
||||||
|
if ((((sequenceNumberM + 1) % 0xFFFF) == 0) && (seq == 0xFFFF))
|
||||||
|
sequenceNumberM = -1;
|
||||||
|
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
|
||||||
|
packetErrorsM++;
|
||||||
|
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
|
||||||
|
info("Detected %d RTP packet errors", packetErrorsM);
|
||||||
|
packetErrorsM = 0;
|
||||||
|
lastErrorReportM = time(NULL);
|
||||||
|
}
|
||||||
|
sequenceNumberM = seq;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sequenceNumberM = seq;
|
||||||
|
// Header lenght
|
||||||
|
headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
||||||
|
// Check if extension
|
||||||
|
if (x) {
|
||||||
|
// Extension header length
|
||||||
|
unsigned int ehl = (((bufferM[headerlen + 2] & 0xFF) << 8) | (bufferM[headerlen + 3] & 0xFF));
|
||||||
|
// 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
|
||||||
|
if ((v != 2) || (((lengthP - headerlen) % TS_SIZE) != 0) || (bufferM[headerlen] != TS_SYNC_BYTE)) {
|
||||||
|
debug("cSatipRtp::%s(%d): Received incorrect RTP packet", __FUNCTION__, lengthP);
|
||||||
|
headerlen = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return headerlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipRtp::Process(int fdP)
|
||||||
|
{
|
||||||
|
//debug("cSatipRtp::%s(%d)", __FUNCTION__, fdP);
|
||||||
|
if (bufferM) {
|
||||||
|
int length = Read(bufferM, min(tunerM.GetVideoDataSize(), bufferLenM));
|
||||||
|
if (length > 0) {
|
||||||
|
int headerlen = GetHeaderLenght(length);
|
||||||
|
if ((headerlen >= 0) && (headerlen < length))
|
||||||
|
tunerM.ProcessVideoData(bufferM + headerlen, length - headerlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
rtp.h
Normal file
39
rtp.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* rtp.h: SAT>IP plugin for the Video Disk Recorder
|
||||||
|
*
|
||||||
|
* See the README file for copyright information and how to reach the author.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SATIP_RTP_H_
|
||||||
|
#define __SATIP_RTP_H_
|
||||||
|
|
||||||
|
#include "socket.h"
|
||||||
|
#include "tunerif.h"
|
||||||
|
#include "pollerif.h"
|
||||||
|
|
||||||
|
class cSatipRtp : public cSatipSocket, public cSatipPollerIf {
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
eReportIntervalS = 300 // in seconds
|
||||||
|
};
|
||||||
|
cSatipTunerIf &tunerM;
|
||||||
|
unsigned int bufferLenM;
|
||||||
|
unsigned char *bufferM;
|
||||||
|
time_t lastErrorReportM;
|
||||||
|
int packetErrorsM;
|
||||||
|
int sequenceNumberM;
|
||||||
|
int GetHeaderLenght(int lengthP);
|
||||||
|
|
||||||
|
public:
|
||||||
|
cSatipRtp(cSatipTunerIf &tunerP, unsigned int bufferLenP);
|
||||||
|
virtual ~cSatipRtp();
|
||||||
|
virtual void Close(void);
|
||||||
|
|
||||||
|
// for internal poller interface
|
||||||
|
public:
|
||||||
|
virtual int GetFd(void);
|
||||||
|
virtual void Process(int fdP);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __SATIP_RTP_H_ */
|
29
rtsp.c
29
rtsp.c
@ -9,7 +9,7 @@
|
|||||||
#include "rtsp.h"
|
#include "rtsp.h"
|
||||||
|
|
||||||
cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
||||||
: tunerM(&tunerP),
|
: tunerM(tunerP),
|
||||||
tunerIdM(tunerP.GetId()),
|
tunerIdM(tunerP.GetId()),
|
||||||
handleM(curl_easy_init()),
|
handleM(curl_easy_init()),
|
||||||
headerListM(NULL)
|
headerListM(NULL)
|
||||||
@ -59,21 +59,21 @@ size_t cSatipRtsp::HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void
|
|||||||
char *s, *p = (char *)ptrP;
|
char *s, *p = (char *)ptrP;
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
|
||||||
while (obj && obj->tunerM && r) {
|
while (obj && r) {
|
||||||
//debug("cSatipRtsp::%s(%zu): %s", __FUNCTION__, len, r);
|
//debug("cSatipRtsp::%s(%zu): %s", __FUNCTION__, len, r);
|
||||||
r = skipspace(r);
|
r = skipspace(r);
|
||||||
if (strstr(r, "com.ses.streamID")) {
|
if (strstr(r, "com.ses.streamID")) {
|
||||||
int streamid = -1;
|
int streamid = -1;
|
||||||
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
|
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
|
||||||
obj->tunerM->SetStreamId(streamid);
|
obj->tunerM.SetStreamId(streamid);
|
||||||
}
|
}
|
||||||
else if (strstr(r, "Session:")) {
|
else if (strstr(r, "Session:")) {
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
char *session = NULL;
|
char *session = NULL;
|
||||||
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
|
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
|
||||||
obj->tunerM->SetSessionTimeout(skipspace(session), timeout * 1000);
|
obj->tunerM.SetSessionTimeout(skipspace(session), timeout * 1000);
|
||||||
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
|
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
|
||||||
obj->tunerM->SetSessionTimeout(skipspace(session), -1);
|
obj->tunerM.SetSessionTimeout(skipspace(session), -1);
|
||||||
FREE_POINTER(session);
|
FREE_POINTER(session);
|
||||||
}
|
}
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
@ -88,11 +88,8 @@ size_t cSatipRtsp::WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *
|
|||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
//debug("cSatipRtsp::%s(%zu)", __FUNCTION__, len);
|
//debug("cSatipRtsp::%s(%zu)", __FUNCTION__, len);
|
||||||
|
|
||||||
if (obj && obj->tunerM && (len > 0)) {
|
if (obj && (len > 0))
|
||||||
char *data = strndup((char*)ptrP, len);
|
obj->tunerM.ProcessApplicationData((u_char*)ptrP, len);
|
||||||
obj->tunerM->ParseReceptionParameters(data);
|
|
||||||
FREE_POINTER(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -101,22 +98,22 @@ int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, s
|
|||||||
{
|
{
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(userPtrP);
|
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(userPtrP);
|
||||||
|
|
||||||
if (obj && obj->tunerM) {
|
if (obj) {
|
||||||
switch (typeP) {
|
switch (typeP) {
|
||||||
case CURLINFO_TEXT:
|
case CURLINFO_TEXT:
|
||||||
debug("cSatipTuner::%s(%d): RTSP INFO %.*s", __FUNCTION__, obj->tunerM->GetId(), (int)sizeP, dataP);
|
debug("cSatipTuner::%s(%d): RTSP INFO %.*s", __FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
||||||
break;
|
break;
|
||||||
case CURLINFO_HEADER_IN:
|
case CURLINFO_HEADER_IN:
|
||||||
debug("cSatipTuner::%s(%d): RTSP HEAD <<< %.*s", __FUNCTION__, obj->tunerM->GetId(), (int)sizeP, dataP);
|
debug("cSatipTuner::%s(%d): RTSP HEAD <<< %.*s", __FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
||||||
break;
|
break;
|
||||||
case CURLINFO_HEADER_OUT:
|
case CURLINFO_HEADER_OUT:
|
||||||
debug("cSatipTuner::%s(%d): RTSP HEAD >>>\n%.*s", __FUNCTION__, obj->tunerM->GetId(), (int)sizeP, dataP);
|
debug("cSatipTuner::%s(%d): RTSP HEAD >>>\n%.*s", __FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
||||||
break;
|
break;
|
||||||
case CURLINFO_DATA_IN:
|
case CURLINFO_DATA_IN:
|
||||||
debug("cSatipTuner::%s(%d): RTSP DATA <<< %.*s", __FUNCTION__, obj->tunerM->GetId(), (int)sizeP, dataP);
|
debug("cSatipTuner::%s(%d): RTSP DATA <<< %.*s", __FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
||||||
break;
|
break;
|
||||||
case CURLINFO_DATA_OUT:
|
case CURLINFO_DATA_OUT:
|
||||||
debug("cSatipTuner::%s(%d): RTSP DATA >>>\n%.*s", __FUNCTION__, obj->tunerM->GetId(), (int)sizeP, dataP);
|
debug("cSatipTuner::%s(%d): RTSP DATA >>>\n%.*s", __FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
2
rtsp.h
2
rtsp.h
@ -27,7 +27,7 @@ private:
|
|||||||
eConnectTimeoutMs = 1500, // in milliseconds
|
eConnectTimeoutMs = 1500, // in milliseconds
|
||||||
};
|
};
|
||||||
|
|
||||||
cSatipTunerIf* tunerM;
|
cSatipTunerIf &tunerM;
|
||||||
int tunerIdM;
|
int tunerIdM;
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
struct curl_slist *headerListM;
|
struct curl_slist *headerListM;
|
||||||
|
5
satip.c
5
satip.c
@ -11,6 +11,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "discover.h"
|
#include "discover.h"
|
||||||
|
#include "poller.h"
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
|
||||||
#if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x072400
|
#if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x072400
|
||||||
@ -25,7 +26,7 @@
|
|||||||
#define GITVERSION ""
|
#define GITVERSION ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char VERSION[] = "0.3.4" GITVERSION;
|
const char VERSION[] = "1.0.0" GITVERSION;
|
||||||
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
|
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
|
||||||
|
|
||||||
class cPluginSatip : public cPlugin {
|
class cPluginSatip : public cPlugin {
|
||||||
@ -116,6 +117,7 @@ bool cPluginSatip::Initialize(void)
|
|||||||
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
|
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
|
||||||
error("Unable to initialize CURL");
|
error("Unable to initialize CURL");
|
||||||
SatipConfig.SetConfigDirectory(cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
|
SatipConfig.SetConfigDirectory(cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
|
||||||
|
cSatipPoller::GetInstance()->Initialize();
|
||||||
cSatipDiscover::GetInstance()->Initialize(serversM);
|
cSatipDiscover::GetInstance()->Initialize(serversM);
|
||||||
return cSatipDevice::Initialize(deviceCountM);
|
return cSatipDevice::Initialize(deviceCountM);
|
||||||
}
|
}
|
||||||
@ -141,6 +143,7 @@ void cPluginSatip::Stop(void)
|
|||||||
// Stop any background activities the plugin is performing.
|
// Stop any background activities the plugin is performing.
|
||||||
cSatipDevice::Shutdown();
|
cSatipDevice::Shutdown();
|
||||||
cSatipDiscover::GetInstance()->Destroy();
|
cSatipDiscover::GetInstance()->Destroy();
|
||||||
|
cSatipPoller::GetInstance()->Destroy();
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
109
socket.c
109
socket.c
@ -20,10 +20,7 @@
|
|||||||
|
|
||||||
cSatipSocket::cSatipSocket()
|
cSatipSocket::cSatipSocket()
|
||||||
: socketPortM(0),
|
: socketPortM(0),
|
||||||
socketDescM(-1),
|
socketDescM(-1)
|
||||||
lastErrorReportM(0),
|
|
||||||
packetErrorsM(0),
|
|
||||||
sequenceNumberM(-1)
|
|
||||||
{
|
{
|
||||||
debug("cSatipSocket::%s()", __FUNCTION__);
|
debug("cSatipSocket::%s()", __FUNCTION__);
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
@ -75,14 +72,8 @@ void cSatipSocket::Close(void)
|
|||||||
close(socketDescM);
|
close(socketDescM);
|
||||||
socketDescM = -1;
|
socketDescM = -1;
|
||||||
socketPortM = 0;
|
socketPortM = 0;
|
||||||
sequenceNumberM = -1;
|
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
}
|
}
|
||||||
if (packetErrorsM) {
|
|
||||||
info("detected %d RTP packet errors", packetErrorsM);
|
|
||||||
packetErrorsM = 0;
|
|
||||||
lastErrorReportM = time(NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipSocket::Flush(void)
|
bool cSatipSocket::Flush(void)
|
||||||
@ -141,104 +132,6 @@ int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipSocket::ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
|
||||||
{
|
|
||||||
//debug("cSatipSocket::%s()", __FUNCTION__);
|
|
||||||
int len = Read(bufferAddrP, bufferLenP);
|
|
||||||
if (len > 0) {
|
|
||||||
if (bufferAddrP[0] == TS_SYNC_BYTE)
|
|
||||||
return len;
|
|
||||||
else if (len > 3) {
|
|
||||||
// http://tools.ietf.org/html/rfc3550
|
|
||||||
// http://tools.ietf.org/html/rfc2250
|
|
||||||
// Version
|
|
||||||
unsigned int v = (bufferAddrP[0] >> 6) & 0x03;
|
|
||||||
// Extension bit
|
|
||||||
unsigned int x = (bufferAddrP[0] >> 4) & 0x01;
|
|
||||||
// CSCR count
|
|
||||||
unsigned int cc = bufferAddrP[0] & 0x0F;
|
|
||||||
// Payload type: MPEG2 TS = 33
|
|
||||||
//unsigned int pt = bufferAddrP[1] & 0x7F;
|
|
||||||
// Sequence number
|
|
||||||
int seq = ((bufferAddrP[2] & 0xFF) << 8) | (bufferAddrP[3] & 0xFF);
|
|
||||||
if ((((sequenceNumberM + 1) % 0xFFFF) == 0) && (seq == 0xFFFF))
|
|
||||||
sequenceNumberM = -1;
|
|
||||||
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
|
|
||||||
packetErrorsM++;
|
|
||||||
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
|
|
||||||
info("detected %d RTP packet errors", packetErrorsM);
|
|
||||||
packetErrorsM = 0;
|
|
||||||
lastErrorReportM = time(NULL);
|
|
||||||
}
|
|
||||||
sequenceNumberM = seq;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sequenceNumberM = seq;
|
|
||||||
// Header lenght
|
|
||||||
unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
|
||||||
// Check if extension
|
|
||||||
if (x) {
|
|
||||||
// Extension header length
|
|
||||||
unsigned int ehl = (((bufferAddrP[headerlen + 2] & 0xFF) << 8) |
|
|
||||||
(bufferAddrP[headerlen + 3] & 0xFF));
|
|
||||||
// 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
|
|
||||||
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) &&
|
|
||||||
(bufferAddrP[headerlen] == TS_SYNC_BYTE)) {
|
|
||||||
// Set argument point to payload in read buffer
|
|
||||||
memmove(bufferAddrP, &bufferAddrP[headerlen], (len - headerlen));
|
|
||||||
return (len - headerlen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipSocket::ReadApplication(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
|
||||||
{
|
|
||||||
//debug("cSatipSocket::%s()", __FUNCTION__);
|
|
||||||
int len = Read(bufferAddrP, bufferLenP);
|
|
||||||
int offset = 0;
|
|
||||||
while (len > 0) {
|
|
||||||
// Version
|
|
||||||
unsigned int v = (bufferAddrP[offset] >> 6) & 0x03;
|
|
||||||
// Padding
|
|
||||||
//unsigned int p = (bufferAddrP[offset] >> 5) & 0x01;
|
|
||||||
// Subtype
|
|
||||||
//unsigned int st = bufferAddrP[offset] & 0x1F;
|
|
||||||
// Payload type
|
|
||||||
unsigned int pt = bufferAddrP[offset + 1] & 0xFF;
|
|
||||||
// Lenght
|
|
||||||
unsigned int length = ((bufferAddrP[offset + 2] & 0xFF) << 8) | (bufferAddrP[offset + 3] & 0xFF);
|
|
||||||
// Convert it to bytes
|
|
||||||
length = (length + 1) * 4;
|
|
||||||
// V=2, APP = 204
|
|
||||||
if ((v == 2) && (pt == 204)) {
|
|
||||||
// SSCR/CSCR
|
|
||||||
//unsigned int ssrc = ((bufferAddrP[offset + 4] & 0xFF) << 24) | ((bufferAddrP[offset + 5] & 0xFF) << 16) |
|
|
||||||
// ((bufferAddrP[offset + 6] & 0xFF) << 8) | (bufferAddrP[offset + 7] & 0xFF);
|
|
||||||
// Name
|
|
||||||
if ((bufferAddrP[offset + 8] == 'S') && (bufferAddrP[offset + 9] == 'E') &&
|
|
||||||
(bufferAddrP[offset + 10] == 'S') && (bufferAddrP[offset + 11] == '1')) {
|
|
||||||
// Identifier
|
|
||||||
//unsigned int id = ((bufferAddrP[offset + 12] & 0xFF) << 8) | (bufferAddrP[offset + 13] & 0xFF);
|
|
||||||
// String length
|
|
||||||
int string_length = ((bufferAddrP[offset + 14] & 0xFF) << 8) | (bufferAddrP[offset + 15] & 0xFF);
|
|
||||||
if (string_length > 0) {
|
|
||||||
// Set argument point to payload in read buffer
|
|
||||||
memmove(bufferAddrP, &bufferAddrP[offset + 16], string_length);
|
|
||||||
bufferAddrP[string_length] = 0;
|
|
||||||
return string_length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
offset += length;
|
|
||||||
len -= length;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipSocket::Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP)
|
bool cSatipSocket::Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||||
{
|
{
|
||||||
|
12
socket.h
12
socket.h
@ -12,28 +12,20 @@
|
|||||||
|
|
||||||
class cSatipSocket {
|
class cSatipSocket {
|
||||||
private:
|
private:
|
||||||
enum {
|
|
||||||
eReportIntervalS = 300 // in seconds
|
|
||||||
};
|
|
||||||
int socketPortM;
|
int socketPortM;
|
||||||
int socketDescM;
|
int socketDescM;
|
||||||
struct sockaddr_in sockAddrM;
|
struct sockaddr_in sockAddrM;
|
||||||
time_t lastErrorReportM;
|
|
||||||
int packetErrorsM;
|
|
||||||
int sequenceNumberM;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipSocket();
|
cSatipSocket();
|
||||||
~cSatipSocket();
|
virtual ~cSatipSocket();
|
||||||
bool Open(const int portP = 0);
|
bool Open(const int portP = 0);
|
||||||
void Close(void);
|
virtual void Close(void);
|
||||||
int Fd(void) { return socketDescM; }
|
int Fd(void) { return socketDescM; }
|
||||||
int Port(void) { return socketPortM; }
|
int Port(void) { return socketPortM; }
|
||||||
bool IsOpen(void) { return (socketDescM >= 0); }
|
bool IsOpen(void) { return (socketDescM >= 0); }
|
||||||
bool Flush(void);
|
bool Flush(void);
|
||||||
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
||||||
int ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
|
||||||
int ReadApplication(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
|
||||||
bool Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP);
|
bool Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
255
tuner.c
255
tuner.c
@ -5,11 +5,10 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "discover.h"
|
#include "discover.h"
|
||||||
|
#include "poller.h"
|
||||||
#include "tuner.h"
|
#include "tuner.h"
|
||||||
|
|
||||||
cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
||||||
@ -17,21 +16,21 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
|||||||
sleepM(),
|
sleepM(),
|
||||||
deviceM(&deviceP),
|
deviceM(&deviceP),
|
||||||
deviceIdM(deviceP.GetId()),
|
deviceIdM(deviceP.GetId()),
|
||||||
packetBufferLenM(packetLenP),
|
rtspM(*this),
|
||||||
rtspM(new cSatipRtsp(*this)),
|
rtpM(*this, packetLenP),
|
||||||
rtpSocketM(new cSatipSocket()),
|
rtcpM(*this, eApplicationMaxSizeB),
|
||||||
rtcpSocketM(new cSatipSocket()),
|
|
||||||
streamAddrM(""),
|
streamAddrM(""),
|
||||||
streamParamM(""),
|
streamParamM(""),
|
||||||
currentServerM(NULL),
|
currentServerM(NULL),
|
||||||
nextServerM(NULL),
|
nextServerM(NULL),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
|
reConnectM(),
|
||||||
keepAliveM(),
|
keepAliveM(),
|
||||||
statusUpdateM(),
|
statusUpdateM(),
|
||||||
pidUpdateCacheM(),
|
pidUpdateCacheM(),
|
||||||
sessionM(""),
|
sessionM(""),
|
||||||
tunerStatusM(tsIdle),
|
currentStateM(tsIdle),
|
||||||
fdM(epoll_create(eMaxFileDescriptors)),
|
nextStateM(tsIdle),
|
||||||
timeoutM(eMinKeepAliveIntervalMs),
|
timeoutM(eMinKeepAliveIntervalMs),
|
||||||
hasLockM(false),
|
hasLockM(false),
|
||||||
signalStrengthM(-1),
|
signalStrengthM(-1),
|
||||||
@ -41,45 +40,22 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
|||||||
delPidsM(),
|
delPidsM(),
|
||||||
pidsM()
|
pidsM()
|
||||||
{
|
{
|
||||||
debug("cSatipTuner::%s(%d) [device %d]", __FUNCTION__, packetBufferLenM, deviceIdM);
|
debug("cSatipTuner::%s(%d) [device %d]", __FUNCTION__, packetLenP, deviceIdM);
|
||||||
// Allocate packet buffer
|
|
||||||
packetBufferM = MALLOC(unsigned char, packetBufferLenM);
|
|
||||||
if (packetBufferM)
|
|
||||||
memset(packetBufferM, 0, packetBufferLenM);
|
|
||||||
else
|
|
||||||
error("MALLOC() failed for packet buffer [device %d]", deviceIdM);
|
|
||||||
|
|
||||||
// Open sockets
|
// Open sockets
|
||||||
int i = 100;
|
int i = 100;
|
||||||
while (i-- > 0) {
|
while (i-- > 0) {
|
||||||
if (rtpSocketM->Open(0) && rtcpSocketM->Open(rtpSocketM->Port() + 1))
|
if (rtpM.Open(0) && rtcpM.Open(rtpM.Port() + 1))
|
||||||
break;
|
break;
|
||||||
rtpSocketM->Close();
|
rtpM.Close();
|
||||||
rtcpSocketM->Close();
|
rtcpM.Close();
|
||||||
}
|
}
|
||||||
if ((rtpSocketM->Port() <= 0) || (rtcpSocketM->Port() <= 0)) {
|
if ((rtpM.Port() <= 0) || (rtcpM.Port() <= 0)) {
|
||||||
error("Cannot open required RTP/RTCP ports [device %d]", deviceIdM);
|
error("Cannot open required RTP/RTCP ports [device %d]", deviceIdM);
|
||||||
}
|
}
|
||||||
|
// Must be done after socket initialization!
|
||||||
// Setup epoll
|
cSatipPoller::GetInstance()->Register(rtpM);
|
||||||
if (fdM >= 0) {
|
cSatipPoller::GetInstance()->Register(rtcpM);
|
||||||
if (rtpSocketM->Fd() >= 0) {
|
|
||||||
struct epoll_event ev;
|
|
||||||
ev.events = EPOLLIN | EPOLLET;
|
|
||||||
ev.data.fd = rtpSocketM->Fd();
|
|
||||||
if (epoll_ctl(fdM, EPOLL_CTL_ADD, rtpSocketM->Fd(), &ev) == -1) {
|
|
||||||
error("Cannot add RTP socket into epoll [device %d]", deviceIdM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rtcpSocketM->Fd() >= 0) {
|
|
||||||
struct epoll_event ev;
|
|
||||||
ev.events = EPOLLIN | EPOLLET;
|
|
||||||
ev.data.fd = rtcpSocketM->Fd();
|
|
||||||
if (epoll_ctl(fdM, EPOLL_CTL_ADD, rtcpSocketM->Fd(), &ev) == -1) {
|
|
||||||
error("Cannot add RTP socket into epoll [device %d]", deviceIdM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start thread
|
// Start thread
|
||||||
Start();
|
Start();
|
||||||
@ -89,7 +65,8 @@ cSatipTuner::~cSatipTuner()
|
|||||||
{
|
{
|
||||||
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
||||||
|
|
||||||
tunerStatusM = tsIdle;
|
currentStateM = tsIdle;
|
||||||
|
nextStateM = tsIdle;
|
||||||
|
|
||||||
// Stop thread
|
// Stop thread
|
||||||
sleepM.Signal();
|
sleepM.Signal();
|
||||||
@ -97,84 +74,48 @@ cSatipTuner::~cSatipTuner()
|
|||||||
Cancel(3);
|
Cancel(3);
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
// Cleanup epoll
|
|
||||||
if (fdM >= 0) {
|
|
||||||
if ((rtpSocketM->Fd() >= 0) && (epoll_ctl(fdM, EPOLL_CTL_DEL, rtpSocketM->Fd(), NULL) == -1)) {
|
|
||||||
error("Cannot remove RTP socket from epoll [device %d]", deviceIdM);
|
|
||||||
}
|
|
||||||
if ((rtcpSocketM->Fd() >= 0) && (epoll_ctl(fdM, EPOLL_CTL_DEL, rtcpSocketM->Fd(), NULL) == -1)) {
|
|
||||||
error("Cannot remove RTP socket from epoll [device %d]", deviceIdM);
|
|
||||||
}
|
|
||||||
close(fdM);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the listening sockets
|
// Close the listening sockets
|
||||||
rtpSocketM->Close();
|
cSatipPoller::GetInstance()->Unregister(rtcpM);
|
||||||
rtcpSocketM->Close();
|
cSatipPoller::GetInstance()->Unregister(rtpM);
|
||||||
|
rtcpM.Close();
|
||||||
// Free allocated memory
|
rtpM.Close();
|
||||||
free(packetBufferM);
|
|
||||||
DELETENULL(rtcpSocketM);
|
|
||||||
DELETENULL(rtpSocketM);
|
|
||||||
DELETENULL(rtspM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipTuner::Action(void)
|
void cSatipTuner::Action(void)
|
||||||
{
|
{
|
||||||
debug("cSatipTuner::%s(): entering [device %d]", __FUNCTION__, deviceIdM);
|
debug("cSatipTuner::%s(): entering [device %d]", __FUNCTION__, deviceIdM);
|
||||||
cTimeMs reconnection(eConnectTimeoutMs);
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
// Increase priority
|
|
||||||
SetPriority(-1);
|
|
||||||
// Do the thread loop
|
// Do the thread loop
|
||||||
while (packetBufferM && rtpSocketM && rtcpSocketM && Running()) {
|
while (Running()) {
|
||||||
struct epoll_event events[eMaxFileDescriptors];
|
mutexM.Lock();
|
||||||
int nfds = epoll_wait(fdM, events, eMaxFileDescriptors, eReadTimeoutMs);
|
if (StateRequested())
|
||||||
switch (nfds) {
|
currentStateM = nextStateM;
|
||||||
default:
|
mutexM.Unlock();
|
||||||
reconnection.Set(eConnectTimeoutMs);
|
switch (currentStateM) {
|
||||||
for (int i = 0; i < nfds; ++i) {
|
|
||||||
if (events[i].data.fd == rtpSocketM->Fd()) {
|
|
||||||
// Read data
|
|
||||||
int length = rtpSocketM->ReadVideo(packetBufferM, min(deviceM->CheckData(), packetBufferLenM));
|
|
||||||
if (length > 0) {
|
|
||||||
AddTunerStatistic(length);
|
|
||||||
deviceM->WriteData(packetBufferM, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (events[i].data.fd == rtcpSocketM->Fd()) {
|
|
||||||
unsigned char buf[1450];
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
if (rtcpSocketM->ReadApplication(buf, sizeof(buf)) > 0)
|
|
||||||
ParseReceptionParameters((const char *)buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// fall through into epoll timeout
|
|
||||||
case 0:
|
|
||||||
switch (tunerStatusM) {
|
|
||||||
case tsIdle:
|
case tsIdle:
|
||||||
//debug("cSatipTuner::%s(): tsIdle [device %d]", __FUNCTION__, deviceIdM);
|
//debug("cSatipTuner::%s(): tsIdle [device %d]", __FUNCTION__, deviceIdM);
|
||||||
break;
|
break;
|
||||||
case tsRelease:
|
case tsRelease:
|
||||||
//debug("cSatipTuner::%s(): tsRelease [device %d]", __FUNCTION__, deviceIdM);
|
//debug("cSatipTuner::%s(): tsRelease [device %d]", __FUNCTION__, deviceIdM);
|
||||||
Disconnect();
|
Disconnect();
|
||||||
tunerStatusM = tsIdle;
|
RequestState(tsIdle);
|
||||||
break;
|
break;
|
||||||
case tsSet:
|
case tsSet:
|
||||||
//debug("cSatipTuner::%s(): tsSet [device %d]", __FUNCTION__, deviceIdM);
|
//debug("cSatipTuner::%s(): tsSet [device %d]", __FUNCTION__, deviceIdM);
|
||||||
reconnection.Set(eConnectTimeoutMs);
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
Disconnect();
|
Disconnect();
|
||||||
if (Connect()) {
|
if (Connect()) {
|
||||||
tunerStatusM = tsTuned;
|
RequestState(tsTuned);
|
||||||
UpdatePids(true);
|
UpdatePids(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
error("Tuning failed - re-tuning [device %d]", deviceIdM);
|
error("Tuning failed - re-tuning [device %d]", deviceIdM);
|
||||||
tunerStatusM = tsIdle;
|
RequestState(tsIdle);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case tsTuned:
|
case tsTuned:
|
||||||
//debug("cSatipTuner::%s(): tsTuned [device %d]", __FUNCTION__, deviceIdM);
|
//debug("cSatipTuner::%s(): tsTuned [device %d]", __FUNCTION__, deviceIdM);
|
||||||
reconnection.Set(eConnectTimeoutMs);
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
// Read reception statistics via DESCRIBE and RTCP
|
// Read reception statistics via DESCRIBE and RTCP
|
||||||
if (hasLockM || ReadReceptionStatus()) {
|
if (hasLockM || ReadReceptionStatus()) {
|
||||||
// Quirk for devices without valid reception data
|
// Quirk for devices without valid reception data
|
||||||
@ -184,37 +125,33 @@ void cSatipTuner::Action(void)
|
|||||||
signalQualityM = eDefaultSignalQuality;
|
signalQualityM = eDefaultSignalQuality;
|
||||||
}
|
}
|
||||||
if (hasLockM)
|
if (hasLockM)
|
||||||
tunerStatusM = tsLocked;
|
RequestState(tsLocked);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case tsLocked:
|
case tsLocked:
|
||||||
//debug("cSatipTuner::%s(): tsLocked [device %d]", __FUNCTION__, deviceIdM);
|
//debug("cSatipTuner::%s(): tsLocked [device %d]", __FUNCTION__, deviceIdM);
|
||||||
tunerStatusM = tsLocked;
|
|
||||||
if (!UpdatePids()) {
|
if (!UpdatePids()) {
|
||||||
error("Pid update failed - re-tuning [device %d]", deviceIdM);
|
error("Pid update failed - re-tuning [device %d]", deviceIdM);
|
||||||
tunerStatusM = tsSet;
|
RequestState(tsSet);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!KeepAlive()) {
|
if (!KeepAlive()) {
|
||||||
error("Keep-alive failed - re-tuning [device %d]", deviceIdM);
|
error("Keep-alive failed - re-tuning [device %d]", deviceIdM);
|
||||||
tunerStatusM = tsSet;
|
RequestState(tsSet);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (reconnection.TimedOut()) {
|
if (reConnectM.TimedOut()) {
|
||||||
error("Connection timeout - re-tuning [device %d]", deviceIdM);
|
error("Connection timeout - re-tuning [device %d]", deviceIdM);
|
||||||
tunerStatusM = tsSet;
|
RequestState(tsSet);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("Unknown tuner status %d [device %d]", tunerStatusM, deviceIdM);
|
error("Unknown tuner status %d [device %d]", currentStateM, deviceIdM);
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
ERROR_IF((nfds == -1), "epoll_wait() failed");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!StateRequested())
|
||||||
|
sleepM.Wait(eSleepTimeoutMs); // to avoid busy loop and reduce cpu load
|
||||||
}
|
}
|
||||||
debug("cSatipTuner::%s(): exiting [device %d]", __FUNCTION__, deviceIdM);
|
debug("cSatipTuner::%s(): exiting [device %d]", __FUNCTION__, deviceIdM);
|
||||||
}
|
}
|
||||||
@ -223,7 +160,10 @@ bool cSatipTuner::Open(void)
|
|||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
||||||
tunerStatusM = tsSet;
|
|
||||||
|
RequestState(tsSet);
|
||||||
|
|
||||||
|
// return always true
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +171,10 @@ bool cSatipTuner::Close(void)
|
|||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
||||||
tunerStatusM = tsRelease;
|
|
||||||
|
RequestState(tsRelease);
|
||||||
|
|
||||||
|
// return always true
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,18 +187,18 @@ bool cSatipTuner::Connect(void)
|
|||||||
cString connectionUri = cString::sprintf("rtsp://%s", *streamAddrM);
|
cString connectionUri = cString::sprintf("rtsp://%s", *streamAddrM);
|
||||||
cString uri = cString::sprintf("%s/?%s", *connectionUri, *streamParamM);
|
cString uri = cString::sprintf("%s/?%s", *connectionUri, *streamParamM);
|
||||||
// Just retune
|
// Just retune
|
||||||
if ((tunerStatusM >= tsTuned) && (streamIdM >= 0) && rtpSocketM && rtcpSocketM) {
|
if (streamIdM >= 0) {
|
||||||
debug("cSatipTuner::%s(): retune [device %d]", __FUNCTION__, deviceIdM);
|
debug("cSatipTuner::%s(): retune [device %d]", __FUNCTION__, deviceIdM);
|
||||||
KeepAlive(true);
|
KeepAlive(true);
|
||||||
// Flush any old content
|
// Flush any old content
|
||||||
rtpSocketM->Flush();
|
rtpM.Flush();
|
||||||
return rtspM->Setup(*uri, rtpSocketM->Port(), rtcpSocketM->Port());
|
return rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port());
|
||||||
}
|
}
|
||||||
keepAliveM.Set(timeoutM);
|
keepAliveM.Set(timeoutM);
|
||||||
if (rtspM->Options(*connectionUri)) {
|
if (rtspM.Options(*connectionUri)) {
|
||||||
if (nextServerM && nextServerM->Quirk(cSatipServer::eSatipQuirkSessionId))
|
if (nextServerM && nextServerM->Quirk(cSatipServer::eSatipQuirkSessionId))
|
||||||
rtspM->SetSession(SkipZeroes(*sessionM));
|
rtspM.SetSession(SkipZeroes(*sessionM));
|
||||||
if (rtspM->Setup(*uri, rtpSocketM->Port(), rtcpSocketM->Port())) {
|
if (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port())) {
|
||||||
if (nextServerM) {
|
if (nextServerM) {
|
||||||
cSatipDiscover::GetInstance()->UseServer(nextServerM, true);
|
cSatipDiscover::GetInstance()->UseServer(nextServerM, true);
|
||||||
currentServerM = nextServerM;
|
currentServerM = nextServerM;
|
||||||
@ -275,11 +218,12 @@ bool cSatipTuner::Disconnect(void)
|
|||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
||||||
|
|
||||||
if ((tunerStatusM >= tsTuned) && !isempty(*streamAddrM) && (streamIdM >= 0)) {
|
if (!isempty(*streamAddrM) && (streamIdM >= 0)) {
|
||||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
||||||
rtspM->Teardown(*uri);
|
rtspM.Teardown(*uri);
|
||||||
}
|
}
|
||||||
tunerStatusM = tsIdle;
|
currentStateM = tsIdle;
|
||||||
|
nextStateM = tsIdle;
|
||||||
|
|
||||||
// Reset signal parameters
|
// Reset signal parameters
|
||||||
hasLockM = false;
|
hasLockM = false;
|
||||||
@ -297,15 +241,33 @@ bool cSatipTuner::Disconnect(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipTuner::ParseReceptionParameters(const char *paramP)
|
unsigned int cSatipTuner::GetVideoDataSize(void)
|
||||||
{
|
{
|
||||||
//debug("cSatipTuner::%s(%s) [device %d]", __FUNCTION__, paramP, deviceIdM);
|
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
||||||
|
return deviceM->CheckData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipTuner::ProcessVideoData(u_char *bufferP, int lengthP)
|
||||||
|
{
|
||||||
|
//debug("cSatipTuner::%s(%d) [device %d]", __FUNCTION__, lengthP, deviceIdM);
|
||||||
|
if (lengthP > 0) {
|
||||||
|
AddTunerStatistic(lengthP);
|
||||||
|
deviceM->WriteData(bufferP, lengthP);
|
||||||
|
}
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
||||||
|
{
|
||||||
|
//debug("cSatipTuner::%s(%d) [device %d]", __FUNCTION__, lengthP, deviceIdM);
|
||||||
// DVB-S2:
|
// DVB-S2:
|
||||||
// ver=<major>.<minor>;src=<srcID>;tuner=<feID>,<level>,<lock>,<quality>,<frequency>,<polarisation>,<system>,<type>,<pilots>,<roll_off>,<symbol_rate>,<fec_inner>;pids=<pid0>,...,<pidn>
|
// ver=<major>.<minor>;src=<srcID>;tuner=<feID>,<level>,<lock>,<quality>,<frequency>,<polarisation>,<system>,<type>,<pilots>,<roll_off>,<symbol_rate>,<fec_inner>;pids=<pid0>,...,<pidn>
|
||||||
// DVB-T2:
|
// DVB-T2:
|
||||||
// ver=1.1;tuner=<feID>,<level>,<lock>,<quality>,<freq>,<bw>,<msys>,<tmode>,<mtype>,<gi>,<fec>,<plp>,<t2id>,<sm>;pids=<pid0>,...,<pidn>
|
// ver=1.1;tuner=<feID>,<level>,<lock>,<quality>,<freq>,<bw>,<msys>,<tmode>,<mtype>,<gi>,<fec>,<plp>,<t2id>,<sm>;pids=<pid0>,...,<pidn>
|
||||||
if (!isempty(paramP)) {
|
if (lengthP > 0) {
|
||||||
char *s = strdup(paramP);
|
char *s = strndup((char *)bufferP, lengthP);
|
||||||
|
//debug("cSatipTuner::%s(%s) [device %d]", __FUNCTION__, s, deviceIdM);
|
||||||
char *c = strstr(s, ";tuner=");
|
char *c = strstr(s, ";tuner=");
|
||||||
if (c) {
|
if (c) {
|
||||||
int value;
|
int value;
|
||||||
@ -370,15 +332,16 @@ bool cSatipTuner::SetSource(cSatipServer *serverP, const char *parameterP, const
|
|||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (serverP) {
|
if (serverP) {
|
||||||
nextServerM = cSatipDiscover::GetInstance()->GetServer(serverP);
|
nextServerM = cSatipDiscover::GetInstance()->GetServer(serverP);
|
||||||
if (rtspM && nextServerM && !isempty(nextServerM->Address()) && !isempty(parameterP)) {
|
if (nextServerM && !isempty(nextServerM->Address()) && !isempty(parameterP)) {
|
||||||
// Update stream address and parameter
|
// Update stream address and parameter
|
||||||
streamAddrM = rtspM->RtspUnescapeString(nextServerM->Address());
|
streamAddrM = rtspM.RtspUnescapeString(nextServerM->Address());
|
||||||
streamParamM = rtspM->RtspUnescapeString(parameterP);
|
streamParamM = rtspM.RtspUnescapeString(parameterP);
|
||||||
tunerStatusM = tsSet;
|
RequestState(tsSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tunerStatusM = tsRelease;
|
RequestState(tsRelease);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,14 +360,16 @@ bool cSatipTuner::SetPid(int pidP, int typeP, bool onP)
|
|||||||
addPidsM.RemovePid(pidP);
|
addPidsM.RemovePid(pidP);
|
||||||
}
|
}
|
||||||
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
||||||
|
sleepM.Signal();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipTuner::UpdatePids(bool forceP)
|
bool cSatipTuner::UpdatePids(bool forceP)
|
||||||
{
|
{
|
||||||
//debug("cSatipTuner::%s(%d) tunerStatus=%s [device %d]", __FUNCTION__, forceP, TunerStatusString(tunerStatusM), deviceIdM);
|
//debug("cSatipTuner::%s(%d) tunerState=%s [device %d]", __FUNCTION__, forceP, TunerStateString(currentStateM), deviceIdM);
|
||||||
if (((forceP && pidsM.Size()) || (pidUpdateCacheM.TimedOut() && (addPidsM.Size() || delPidsM.Size()))) &&
|
if (((forceP && pidsM.Size()) || (pidUpdateCacheM.TimedOut() && (addPidsM.Size() || delPidsM.Size()))) &&
|
||||||
(tunerStatusM >= tsTuned) && !isempty(*streamAddrM) && (streamIdM > 0)) {
|
!isempty(*streamAddrM) && (streamIdM > 0)) {
|
||||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
||||||
bool usedummy = !!(currentServerM && currentServerM->Quirk(cSatipServer::eSatipQuirkPlayPids));
|
bool usedummy = !!(currentServerM && currentServerM->Quirk(cSatipServer::eSatipQuirkPlayPids));
|
||||||
if (forceP || usedummy) {
|
if (forceP || usedummy) {
|
||||||
@ -428,7 +393,7 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
|||||||
uri = cString::sprintf("%s%d%s", *uri, delPidsM[i], (i == (delPidsM.Size() - 1)) ? "" : ",");
|
uri = cString::sprintf("%s%d%s", *uri, delPidsM[i], (i == (delPidsM.Size() - 1)) ? "" : ",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!rtspM->Play(*uri))
|
if (!rtspM.Play(*uri))
|
||||||
return false;
|
return false;
|
||||||
addPidsM.Clear();
|
addPidsM.Clear();
|
||||||
delPidsM.Clear();
|
delPidsM.Clear();
|
||||||
@ -439,7 +404,7 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
|||||||
|
|
||||||
bool cSatipTuner::KeepAlive(bool forceP)
|
bool cSatipTuner::KeepAlive(bool forceP)
|
||||||
{
|
{
|
||||||
//debug("cSatipTuner::%s(%d) tunerStatus=%s [device %d]", __FUNCTION__, forceP, TunerStatusString(tunerStatusM), deviceIdM);
|
//debug("cSatipTuner::%s(%d) tunerState=%s [device %d]", __FUNCTION__, forceP, TunerStateString(currentStateM), deviceIdM);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (keepAliveM.TimedOut()) {
|
if (keepAliveM.TimedOut()) {
|
||||||
keepAliveM.Set(timeoutM);
|
keepAliveM.Set(timeoutM);
|
||||||
@ -447,7 +412,7 @@ bool cSatipTuner::KeepAlive(bool forceP)
|
|||||||
}
|
}
|
||||||
if (forceP && !isempty(*streamAddrM) && (streamIdM > 0)) {
|
if (forceP && !isempty(*streamAddrM) && (streamIdM > 0)) {
|
||||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
||||||
if (!rtspM->Options(*uri))
|
if (!rtspM.Options(*uri))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +421,7 @@ bool cSatipTuner::KeepAlive(bool forceP)
|
|||||||
|
|
||||||
bool cSatipTuner::ReadReceptionStatus(bool forceP)
|
bool cSatipTuner::ReadReceptionStatus(bool forceP)
|
||||||
{
|
{
|
||||||
//debug("cSatipTuner::%s(%d) tunerStatus=%s [device %d]", __FUNCTION__, forceP, TunerStatusString(tunerStatusM), deviceIdM);
|
//debug("cSatipTuner::%s(%d) tunerState=%s [device %d]", __FUNCTION__, forceP, TunerStateString(currentStateM), deviceIdM);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (statusUpdateM.TimedOut()) {
|
if (statusUpdateM.TimedOut()) {
|
||||||
statusUpdateM.Set(eStatusUpdateTimeoutMs);
|
statusUpdateM.Set(eStatusUpdateTimeoutMs);
|
||||||
@ -464,16 +429,35 @@ bool cSatipTuner::ReadReceptionStatus(bool forceP)
|
|||||||
}
|
}
|
||||||
if (forceP && !isempty(*streamAddrM) && (streamIdM > 0)) {
|
if (forceP && !isempty(*streamAddrM) && (streamIdM > 0)) {
|
||||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
||||||
if (rtspM->Describe(*uri))
|
if (rtspM.Describe(*uri))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *cSatipTuner::TunerStatusString(eTunerStatus statusP)
|
bool cSatipTuner::StateRequested(void)
|
||||||
{
|
{
|
||||||
switch (statusP) {
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
//debug("cSatipTuner::%s(%s <> %s) [device %d]", __FUNCTION__, TunerStateString(currentStateM), TunerStateString(nextStateM), deviceIdM);
|
||||||
|
|
||||||
|
return (currentStateM != nextStateM);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipTuner::RequestState(eTunerState stateP)
|
||||||
|
{
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
debug("cSatipTuner::%s(%s) [device %d]", __FUNCTION__, TunerStateString(stateP), deviceIdM);
|
||||||
|
|
||||||
|
nextStateM = stateP;
|
||||||
|
|
||||||
|
// validate legal state changes
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cSatipTuner::TunerStateString(eTunerState stateP)
|
||||||
|
{
|
||||||
|
switch (stateP) {
|
||||||
case tsIdle:
|
case tsIdle:
|
||||||
return "tsIdle";
|
return "tsIdle";
|
||||||
case tsRelease:
|
case tsRelease:
|
||||||
@ -487,6 +471,7 @@ const char *cSatipTuner::TunerStatusString(eTunerStatus statusP)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "---";
|
return "---";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +490,7 @@ int cSatipTuner::SignalQuality(void)
|
|||||||
bool cSatipTuner::HasLock(void)
|
bool cSatipTuner::HasLock(void)
|
||||||
{
|
{
|
||||||
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
||||||
return (tunerStatusM >= tsTuned) && hasLockM;
|
return (currentStateM >= tsTuned) && hasLockM;
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipTuner::GetSignalStatus(void)
|
cString cSatipTuner::GetSignalStatus(void)
|
||||||
@ -517,5 +502,5 @@ cString cSatipTuner::GetSignalStatus(void)
|
|||||||
cString cSatipTuner::GetInformation(void)
|
cString cSatipTuner::GetInformation(void)
|
||||||
{
|
{
|
||||||
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceIdM);
|
||||||
return (tunerStatusM >= tsTuned) ? cString::sprintf("rtsp://%s/?%s [stream=%d]", *streamAddrM, *streamParamM, streamIdM) : "connection failed";
|
return (currentStateM >= tsTuned) ? cString::sprintf("rtsp://%s/?%s [stream=%d]", *streamAddrM, *streamParamM, streamIdM) : "connection failed";
|
||||||
}
|
}
|
||||||
|
35
tuner.h
35
tuner.h
@ -12,10 +12,11 @@
|
|||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
#include "deviceif.h"
|
#include "deviceif.h"
|
||||||
|
#include "rtp.h"
|
||||||
|
#include "rtcp.h"
|
||||||
#include "rtsp.h"
|
#include "rtsp.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
#include "socket.h"
|
|
||||||
|
|
||||||
class cSatipPid : public cVector<int> {
|
class cSatipPid : public cVector<int> {
|
||||||
private:
|
private:
|
||||||
@ -43,40 +44,40 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class cSatipTuner : public cThread, public cSatipTunerStatistics, public cSatipTunerIf {
|
class cSatipTuner : public cThread, public cSatipTunerStatistics, public cSatipTunerIf
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
eMaxFileDescriptors = 2, // RTP + RTCP
|
|
||||||
eDummyPid = 100,
|
eDummyPid = 100,
|
||||||
eDefaultSignalStrength = 15,
|
eDefaultSignalStrength = 15,
|
||||||
eDefaultSignalQuality = 224,
|
eDefaultSignalQuality = 224,
|
||||||
eReadTimeoutMs = 500, // in milliseconds
|
eApplicationMaxSizeB = 1500,
|
||||||
|
eSleepTimeoutMs = 500, // in milliseconds
|
||||||
eStatusUpdateTimeoutMs = 1000, // in milliseconds
|
eStatusUpdateTimeoutMs = 1000, // in milliseconds
|
||||||
ePidUpdateIntervalMs = 250, // in milliseconds
|
ePidUpdateIntervalMs = 250, // in milliseconds
|
||||||
eConnectTimeoutMs = 5000, // in milliseconds
|
eConnectTimeoutMs = 5000, // in milliseconds
|
||||||
eMinKeepAliveIntervalMs = 30000 // in milliseconds
|
eMinKeepAliveIntervalMs = 30000 // in milliseconds
|
||||||
};
|
};
|
||||||
enum eTunerStatus { tsIdle, tsRelease, tsSet, tsTuned, tsLocked };
|
enum eTunerState { tsIdle, tsRelease, tsSet, tsTuned, tsLocked };
|
||||||
|
|
||||||
cCondWait sleepM;
|
cCondWait sleepM;
|
||||||
cSatipDeviceIf* deviceM;
|
cSatipDeviceIf* deviceM;
|
||||||
int deviceIdM;
|
int deviceIdM;
|
||||||
unsigned char* packetBufferM;
|
cSatipRtsp rtspM;
|
||||||
unsigned int packetBufferLenM;
|
cSatipRtp rtpM;
|
||||||
cSatipRtsp *rtspM;
|
cSatipRtcp rtcpM;
|
||||||
cSatipSocket *rtpSocketM;
|
|
||||||
cSatipSocket *rtcpSocketM;
|
|
||||||
cString streamAddrM;
|
cString streamAddrM;
|
||||||
cString streamParamM;
|
cString streamParamM;
|
||||||
cSatipServer *currentServerM;
|
cSatipServer *currentServerM;
|
||||||
cSatipServer *nextServerM;
|
cSatipServer *nextServerM;
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
|
cTimeMs reConnectM;
|
||||||
cTimeMs keepAliveM;
|
cTimeMs keepAliveM;
|
||||||
cTimeMs statusUpdateM;
|
cTimeMs statusUpdateM;
|
||||||
cTimeMs pidUpdateCacheM;
|
cTimeMs pidUpdateCacheM;
|
||||||
cString sessionM;
|
cString sessionM;
|
||||||
eTunerStatus tunerStatusM;
|
eTunerState currentStateM;
|
||||||
int fdM;
|
eTunerState nextStateM;
|
||||||
int timeoutM;
|
int timeoutM;
|
||||||
bool hasLockM;
|
bool hasLockM;
|
||||||
int signalStrengthM;
|
int signalStrengthM;
|
||||||
@ -91,7 +92,9 @@ private:
|
|||||||
bool KeepAlive(bool forceP = false);
|
bool KeepAlive(bool forceP = false);
|
||||||
bool ReadReceptionStatus(bool forceP = false);
|
bool ReadReceptionStatus(bool forceP = false);
|
||||||
bool UpdatePids(bool forceP = false);
|
bool UpdatePids(bool forceP = false);
|
||||||
const char *TunerStatusString(eTunerStatus statusP);
|
bool StateRequested(void);
|
||||||
|
bool RequestState(eTunerState stateP);
|
||||||
|
const char *TunerStateString(eTunerState stateP);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
@ -99,7 +102,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
|
cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
|
||||||
virtual ~cSatipTuner();
|
virtual ~cSatipTuner();
|
||||||
bool IsTuned(void) const { return tunerStatusM > tsIdle; }
|
bool IsTuned(void) const { return currentStateM > tsIdle; }
|
||||||
bool SetSource(cSatipServer *serverP, const char *parameterP, const int indexP);
|
bool SetSource(cSatipServer *serverP, const char *parameterP, const int indexP);
|
||||||
bool SetPid(int pidP, int typeP, bool onP);
|
bool SetPid(int pidP, int typeP, bool onP);
|
||||||
bool Open(void);
|
bool Open(void);
|
||||||
@ -112,7 +115,9 @@ public:
|
|||||||
|
|
||||||
// for internal tuner interface
|
// for internal tuner interface
|
||||||
public:
|
public:
|
||||||
virtual void ParseReceptionParameters(const char *paramP);
|
virtual unsigned int GetVideoDataSize(void);
|
||||||
|
virtual void ProcessVideoData(u_char *bufferP, int lengthP);
|
||||||
|
virtual void ProcessApplicationData(u_char *bufferP, int lengthP);
|
||||||
virtual void SetStreamId(int streamIdP);
|
virtual void SetStreamId(int streamIdP);
|
||||||
virtual void SetSessionTimeout(const char *sessionP, int timeoutP);
|
virtual void SetSessionTimeout(const char *sessionP, int timeoutP);
|
||||||
virtual int GetId(void);
|
virtual int GetId(void);
|
||||||
|
@ -12,7 +12,9 @@ class cSatipTunerIf {
|
|||||||
public:
|
public:
|
||||||
cSatipTunerIf() {}
|
cSatipTunerIf() {}
|
||||||
virtual ~cSatipTunerIf() {}
|
virtual ~cSatipTunerIf() {}
|
||||||
virtual void ParseReceptionParameters(const char *paramP) = 0;
|
virtual unsigned int GetVideoDataSize(void) = 0;
|
||||||
|
virtual void ProcessVideoData(u_char *bufferP, int lenghtP) = 0;
|
||||||
|
virtual void ProcessApplicationData(u_char *bufferP, int lenghtP) = 0;
|
||||||
virtual void SetStreamId(int streamIdP) = 0;
|
virtual void SetStreamId(int streamIdP) = 0;
|
||||||
virtual void SetSessionTimeout(const char *sessionP, int timeoutP) = 0;
|
virtual void SetSessionTimeout(const char *sessionP, int timeoutP) = 0;
|
||||||
virtual int GetId(void) = 0;
|
virtual int GetId(void) = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user