mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 13:37:42 +02:00
Add preliminary support for DVBViewer CI.
This commit is contained in:
parent
f65dca2910
commit
4c45787541
7
device.c
7
device.c
@ -479,6 +479,13 @@ int cSatipDevice::GetCISlot(void)
|
||||
return slot;
|
||||
}
|
||||
|
||||
cString cSatipDevice::GetTnrParameterString(void)
|
||||
{
|
||||
if (channelM.Ca())
|
||||
return GetTnrUrlParameters(&channelM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cSatipDevice::IsIdle(void)
|
||||
{
|
||||
return !Receiving();
|
||||
|
1
device.h
1
device.h
@ -110,6 +110,7 @@ public:
|
||||
virtual int GetId(void);
|
||||
virtual int GetPmtPid(void);
|
||||
virtual int GetCISlot(void);
|
||||
virtual cString GetTnrParameterString(void);
|
||||
virtual bool IsIdle(void);
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,7 @@ public:
|
||||
virtual int GetId(void) = 0;
|
||||
virtual int GetPmtPid(void) = 0;
|
||||
virtual int GetCISlot(void) = 0;
|
||||
virtual cString GetTnrParameterString(void) = 0;
|
||||
virtual bool IsIdle(void) = 0;
|
||||
|
||||
private:
|
||||
|
310
param.c
310
param.c
@ -194,3 +194,313 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cString GetTnrUrlParameters(const cChannel *channelP)
|
||||
{
|
||||
if (channelP) {
|
||||
cDvbTransponderParameters dtp(channelP->Parameters());
|
||||
eTrackType track = cDevice::PrimaryDevice()->GetCurrentAudioTrack();
|
||||
|
||||
// TunerType: Byte;
|
||||
// 0 = cable, 1 = satellite, 2 = terrestrial, 3 = atsc, 4 = iptv, 5 = stream (URL, DVBViewer GE)
|
||||
int TunerType = 0;
|
||||
if (channelP->IsCable())
|
||||
TunerType = 0;
|
||||
else if (channelP->IsSat())
|
||||
TunerType = 1;
|
||||
else if (channelP->IsTerr())
|
||||
TunerType = 2;
|
||||
else if (channelP->IsAtsc())
|
||||
TunerType = 3;
|
||||
|
||||
// Frequency: DWord;
|
||||
// DVB-S: MHz if < 1000000, kHz if >= 1000000
|
||||
// DVB-T/C, ATSC: kHz
|
||||
// IPTV: IP address Byte3.Byte2.Byte1.Byte0
|
||||
int Frequency = channelP->Frequency() / 1000;
|
||||
|
||||
// Symbolrate: DWord;
|
||||
// DVB S/C: in kSym/s
|
||||
// DVB-T, ATSC: 0
|
||||
// IPTV: Port
|
||||
int Symbolrate = (channelP->IsSat() || channelP->IsCable()) ? channelP->Srate() : 0;
|
||||
|
||||
// LNB_LOF: Word;
|
||||
// DVB-S: Local oscillator frequency of the LNB
|
||||
// DVB-T/C, ATSC: 0
|
||||
// IPTV: Byte0 and Byte1 of Source IP
|
||||
int LNB_LOF = channelP->IsSat() ? Setup.LnbSLOF : 0;
|
||||
|
||||
// Tone: Byte;
|
||||
// 0 = off, 1 = 22 khz
|
||||
int Tone = (channelP->Frequency() < Setup.LnbSLOF) ? 0 : 1;
|
||||
|
||||
// Polarity: Byte;
|
||||
// DVB-S polarity: 0 = horizontal, 1 = vertical, 2 = circular left, 3 = circular right
|
||||
// DVB-C modulation: 0 = Auto, 1 = 16QAM, 2 = 32QAM, 3 = 64QAM, 4 = 128QAM, 5 = 256 QAM
|
||||
// DVB-T bandwidth: 0 = 6 MHz, 1 = 7 MHz, 2 = 8 MHz
|
||||
// IPTV: Byte3 of SourceIP
|
||||
int Polarity = 0;
|
||||
if (channelP->IsSat()) {
|
||||
switch (tolower(dtp.Polarization())) {
|
||||
case 'h':
|
||||
Polarity = 0;
|
||||
break;
|
||||
case 'v':
|
||||
Polarity = 1;
|
||||
break;
|
||||
case 'l':
|
||||
Polarity = 2;
|
||||
break;
|
||||
case 'r':
|
||||
Polarity = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (channelP->IsCable()) {
|
||||
switch (dtp.Modulation()) {
|
||||
case 999:
|
||||
Polarity = 0;
|
||||
break;
|
||||
case 16:
|
||||
Polarity = 1;
|
||||
break;
|
||||
case 32:
|
||||
Polarity = 2;
|
||||
break;
|
||||
case 64:
|
||||
Polarity = 3;
|
||||
break;
|
||||
case 128:
|
||||
Polarity = 4;
|
||||
break;
|
||||
case 256:
|
||||
Polarity = 5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (channelP->IsTerr()) {
|
||||
switch (dtp.Bandwidth()) {
|
||||
case 6:
|
||||
Polarity = 0;
|
||||
break;
|
||||
case 7:
|
||||
Polarity = 1;
|
||||
break;
|
||||
case 8:
|
||||
Polarity = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// DiSEqC: Byte;
|
||||
// 0 = None
|
||||
// 1 = Pos A (mostly translated to PosA/OptA)
|
||||
// 2 = Pos B (mostly translated to PosB/OptA)
|
||||
// 3 = PosA/OptA
|
||||
// 4 = PosB/OptA
|
||||
// 5 = PosA/OptB
|
||||
// 6 = PosB/OptB
|
||||
// 7 = Preset Position (DiSEqC 1.2, see DiSEqCExt)
|
||||
// 8 = Angular Position (DiSEqC 1.2, see DiSEqCExt)
|
||||
// 9 = DiSEqC Command Sequence (see DiSEqCExt)
|
||||
int DiSEqC = 0;
|
||||
|
||||
// FEC: Byte;
|
||||
// 0 = Auto
|
||||
// 1 = 1/2
|
||||
// 2 = 2/3
|
||||
// 3 = 3/4
|
||||
// 4 = 5/6
|
||||
// 5 = 7/8
|
||||
// 6 = 8/9
|
||||
// 7 = 3/5
|
||||
// 8 = 4/5
|
||||
// 9 = 9/10
|
||||
// IPTV: Byte2 of SourceIP
|
||||
// DVB C/T, ATSC: 0
|
||||
int FEC = 0;
|
||||
if (channelP->IsSat()) {
|
||||
switch (dtp.CoderateH()) {
|
||||
case 999:
|
||||
FEC = 0;
|
||||
break;
|
||||
case 12:
|
||||
FEC = 1;
|
||||
break;
|
||||
case 23:
|
||||
FEC = 2;
|
||||
break;
|
||||
case 34:
|
||||
FEC = 3;
|
||||
break;
|
||||
case 56:
|
||||
FEC = 4;
|
||||
break;
|
||||
case 78:
|
||||
FEC = 5;
|
||||
break;
|
||||
case 89:
|
||||
FEC = 6;
|
||||
break;
|
||||
case 35:
|
||||
FEC = 7;
|
||||
break;
|
||||
case 45:
|
||||
FEC = 8;
|
||||
break;
|
||||
case 910:
|
||||
FEC = 9;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Audio_PID: Word;
|
||||
int Audio_PID = channelP->Apid(0);
|
||||
if (IS_AUDIO_TRACK(track))
|
||||
Audio_PID = channelP->Apid(int(track - ttAudioFirst));
|
||||
else if (IS_DOLBY_TRACK(track))
|
||||
Audio_PID = channelP->Dpid(int(track - ttDolbyFirst));
|
||||
|
||||
// Video_PID: Word;
|
||||
int Video_PID = channelP->Vpid();
|
||||
|
||||
// PMT_PID: Word;
|
||||
int PMT_PID = channelP->Ppid();
|
||||
|
||||
// Service_ID: Word;
|
||||
int Service_ID = channelP->Sid();
|
||||
|
||||
// SatModulation: Byte;
|
||||
// Bit 0..1: satellite modulation. 0 = Auto, 1 = QPSK, 2 = 8PSK, 3 = 16QAM or APSK for DVB-S2
|
||||
// Bit 2: modulation system. 0 = DVB-S/T/C, 1 = DVB-S2/T2/C2
|
||||
// Bit 3..4: DVB-S2: roll-off. 0 = 0.35, 1 = 0.25, 2 = 0.20, 3 = reserved
|
||||
// Bit 5..6: spectral inversion, 0 = undefined, 1 = auto, 2 = normal, 3 = inverted
|
||||
// Bit 7: DVB-S2: pilot symbols, 0 = off, 1 = on
|
||||
// DVB-T2: DVB-T2 Lite, 0 = off, 1 = on
|
||||
int SatModulation = 0;
|
||||
if (channelP->IsSat() && dtp.System()) {
|
||||
switch (dtp.Modulation()) {
|
||||
case 999:
|
||||
SatModulation |= (0 & 0x3) << 0;
|
||||
break;
|
||||
case 2:
|
||||
SatModulation |= (1 & 0x3) << 0;
|
||||
break;
|
||||
case 5:
|
||||
SatModulation |= (2 & 0x3) << 0;
|
||||
break;
|
||||
case 6:
|
||||
SatModulation |= (3 & 0x3) << 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
SatModulation |= (dtp.System() & 0x1) << 2;
|
||||
if (channelP->IsSat() && dtp.System()) {
|
||||
switch (dtp.RollOff()) {
|
||||
case 35:
|
||||
SatModulation |= (0 & 0x3) << 3;
|
||||
break;
|
||||
case 25:
|
||||
SatModulation |= (1 & 0x3) << 3;
|
||||
break;
|
||||
case 20:
|
||||
SatModulation |= (2 & 0x3) << 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (dtp.Inversion()) {
|
||||
case 999:
|
||||
SatModulation |= (1 & 0x3) << 5;
|
||||
break;
|
||||
case 0:
|
||||
SatModulation |= (2 & 0x3) << 5;
|
||||
break;
|
||||
case 1:
|
||||
SatModulation |= (3 & 0x3) << 5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (channelP->IsSat() && dtp.System()) {
|
||||
switch (dtp.Pilot()) {
|
||||
case 0:
|
||||
SatModulation |= (0 & 0x1) << 7;
|
||||
break;
|
||||
case 1:
|
||||
SatModulation |= (1 & 0x1) << 7;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// DiSEqCExt: Word;
|
||||
// DiSEqC Extension, meaning depends on DiSEqC
|
||||
// DiSEqC = 0..6: 0
|
||||
// DiSEqC = 7: Preset Position (DiSEqC 1.2)
|
||||
// DiSEqC = 8: Orbital Position (DiSEqC 1.2, USALS, for calculating motor angle)
|
||||
// Same format as OrbitalPos above
|
||||
// DiSEQC = 9: Orbital Position referencing DiSEqC sequence defined in DiSEqC.xml/ini
|
||||
// Same format as OrbitalPos above
|
||||
int DiSEqCExt = 0;
|
||||
|
||||
// Flags: Byte;
|
||||
// Bit 0: 1 = encrypted channel
|
||||
// Bit 1: reserved, set to 0
|
||||
// Bit 2: 1 = channel broadcasts RDS data
|
||||
// Bit 3: 1 = channel is a video service (even if the Video PID is temporarily = 0)
|
||||
// Bit 4: 1 = channel is an audio service (even if the Audio PID is temporarily = 0)
|
||||
// Bit 5: 1 = audio has a different samplerate than 48 KHz
|
||||
// Bit 6: 1 = bandstacking, internally polarisation is always set to H
|
||||
// Bit 7: 1 = channel entry is an additional audio track of the preceding
|
||||
// channel with bit 7 = 0
|
||||
int Flags = (channelP->Ca() > 0xFF) ? 1 : 0;
|
||||
|
||||
// ChannelGroup: Byte;
|
||||
// 0 = Group A, 1 = Group B, 2 = Group C etc.
|
||||
int ChannelGroup = 0;
|
||||
|
||||
// TransportStream_ID: Word;
|
||||
int TransportStream_ID = channelP->Tid();
|
||||
|
||||
// OriginalNetwork_ID: Word;
|
||||
int OriginalNetwork_ID = channelP->Nid();
|
||||
|
||||
// Substream: Word;
|
||||
// DVB-S/C/T, ATSC, IPTV: 0
|
||||
// DVB-T2: 0 = PLP_ID not set, 1..256: PLP_ID + 1, 257... reserved
|
||||
int Substream = (channelP->IsTerr() && dtp.System()) ? dtp.StreamId() - 1 : 0;
|
||||
|
||||
// OrbitalPos: Word;
|
||||
// DVB-S: orbital position x 10, 0 = undefined, 1..1800 east, 1801..3599 west (1°W = 3599)
|
||||
// DVB-C: 4000..4999
|
||||
// DVB-T: 5000..5999
|
||||
// ATSC: 6000..6999
|
||||
// IPTV: 7000..7999
|
||||
// Stream: 8000..8999
|
||||
int OrbitalPos = 0;
|
||||
if (channelP->IsSat()) {
|
||||
OrbitalPos = cSource::Position(channelP->Source());
|
||||
if (OrbitalPos != 3600)
|
||||
OrbitalPos += 1800;
|
||||
}
|
||||
|
||||
return cString::sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
TunerType, Frequency, Symbolrate, LNB_LOF, Tone, Polarity, DiSEqC, FEC, Audio_PID, Video_PID, PMT_PID, Service_ID,
|
||||
SatModulation, DiSEqCExt, Flags, ChannelGroup, TransportStream_ID, OriginalNetwork_ID, Substream, OrbitalPos);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
1
param.h
1
param.h
@ -11,5 +11,6 @@
|
||||
#include "common.h"
|
||||
|
||||
cString GetTransponderUrlParameters(const cChannel *channelP);
|
||||
cString GetTnrUrlParameters(const cChannel *channelP);
|
||||
|
||||
#endif // __SATIP_PARAM_H
|
||||
|
18
server.c
18
server.c
@ -146,11 +146,25 @@ cSatipServer::cSatipServer(const char *addressP, const int portP, const char *mo
|
||||
quirkM |= eSatipQuirkForceLock;
|
||||
quirksM = cString::sprintf("%s%sForceLock", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
}
|
||||
// These devices support the X_PMT protocol extension
|
||||
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
||||
strstr(*descriptionM, "minisatip") // minisatip server
|
||||
) {
|
||||
quirkM |= eSatipQuirkCiXpmt;
|
||||
quirksM = cString::sprintf("%s%sCiXpmt", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
}
|
||||
// These devices support the TNR protocol extension
|
||||
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||
) {
|
||||
quirkM |= eSatipQuirkCiTnr;
|
||||
quirksM = cString::sprintf("%s%sCiTnr", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
}
|
||||
debug3("%s description=%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM, *quirksM);
|
||||
}
|
||||
// These devices support the X_PMT protocol extension
|
||||
// These devices support external CI
|
||||
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
||||
strstr(*descriptionM, "minisatip") // minisatip server
|
||||
strstr(*descriptionM, "minisatip") || // minisatip server
|
||||
strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||
) {
|
||||
hasCiM = true;
|
||||
}
|
||||
|
4
server.h
4
server.h
@ -79,7 +79,9 @@ public:
|
||||
eSatipQuirkPlayPids = 0x02,
|
||||
eSatipQuirkForceLock = 0x04,
|
||||
eSatipQuirkRtpOverTcp = 0x08,
|
||||
eSatipQuirkMask = 0x0F
|
||||
eSatipQuirkCiXpmt = 0x10,
|
||||
eSatipQuirkCiTnr = 0x20,
|
||||
eSatipQuirkMask = 0xFF
|
||||
};
|
||||
cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP);
|
||||
virtual ~cSatipServer();
|
||||
|
38
tuner.c
38
tuner.c
@ -25,6 +25,7 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
||||
rtcpM(*this),
|
||||
streamAddrM(""),
|
||||
streamParamM(""),
|
||||
tnrParamM(""),
|
||||
streamPortM(SATIP_DEFAULT_RTSP_PORT),
|
||||
currentServerM(NULL, deviceP.GetId(), 0),
|
||||
nextServerM(NULL, deviceP.GetId(), 0),
|
||||
@ -210,6 +211,7 @@ bool cSatipTuner::Connect(void)
|
||||
|
||||
if (!isempty(*streamAddrM)) {
|
||||
cString connectionUri = GetBaseUrl(*streamAddrM, streamPortM);
|
||||
tnrParamM = "";
|
||||
// Just retune
|
||||
if (streamIdM >= 0) {
|
||||
cString uri = cString::sprintf("%sstream=%d?%s", *connectionUri, streamIdM, *streamParamM);
|
||||
@ -445,20 +447,30 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
||||
uri = cString::sprintf("%s%sdelpids=%s", *uri, addPidsM.Size() ? "&" : "?", *delPidsM.ListPids());
|
||||
}
|
||||
if (useci) {
|
||||
// CI extension parameters:
|
||||
// - x_pmt : specifies the PMT of the service you want the CI to decode
|
||||
// - x_ci : specfies which CI slot (1..n) to use
|
||||
// value 0 releases the CI slot
|
||||
// CI slot released automatically if the stream is released,
|
||||
// but not when used retuning to another channel
|
||||
int pid = deviceM->GetPmtPid();
|
||||
if ((pid > 0) && (pid != pmtPidM)) {
|
||||
int slot = deviceM->GetCISlot();
|
||||
uri = cString::sprintf("%s&x_pmt=%d", *uri, pid);
|
||||
if (slot > 0)
|
||||
uri = cString::sprintf("%s&x_ci=%d", *uri, slot);
|
||||
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiXpmt)) {
|
||||
// CI extension parameters:
|
||||
// - x_pmt : specifies the PMT of the service you want the CI to decode
|
||||
// - x_ci : specfies which CI slot (1..n) to use
|
||||
// value 0 releases the CI slot
|
||||
// CI slot released automatically if the stream is released,
|
||||
// but not when used retuning to another channel
|
||||
int pid = deviceM->GetPmtPid();
|
||||
if ((pid > 0) && (pid != pmtPidM)) {
|
||||
int slot = deviceM->GetCISlot();
|
||||
uri = cString::sprintf("%s&x_pmt=%d", *uri, pid);
|
||||
if (slot > 0)
|
||||
uri = cString::sprintf("%s&x_ci=%d", *uri, slot);
|
||||
}
|
||||
pmtPidM = pid;
|
||||
}
|
||||
else if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiTnr)) {
|
||||
// CI extension parameters:
|
||||
// - tnr : specifies a channel config entry
|
||||
cString param = deviceM->GetTnrParameterString();
|
||||
if (!isempty(*param) && strcmp(*tnrParamM, *param) != 0)
|
||||
uri = cString::sprintf("%s&tnr=%s", *uri, *param);
|
||||
tnrParamM = param;
|
||||
}
|
||||
pmtPidM = pid;
|
||||
}
|
||||
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
||||
if (!rtspM.Play(*uri))
|
||||
|
Loading…
Reference in New Issue
Block a user