1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Implemented getting and logging DVB API 5 signal statistics

This commit is contained in:
Klaus Schmidinger 2017-04-17 15:02:44 +02:00
parent 1f541487e0
commit 6132a46768
6 changed files with 154 additions and 5 deletions

View File

@ -3388,6 +3388,8 @@ Dietmar Spingler <d_spingler@gmx.de>
for suggesting that the -V and -h options should list the plugins in alphabetical order
for suggesting to implement the setup option "Recording/Record key handling"
for suggesting to cache the channel/CAM relations in the file 'cam.data'
for suggesting to log signal statistics whenever the tuner of a cDvbDevice acquires
a lock, and DVB API 5 signal statistics are available
Stefan Schallenberg <infos@nafets.de>
for adding the functions IndexOf(), InsertUnique(), AppendUnique() and RemoveElement()

View File

@ -8925,7 +8925,7 @@ Video Disk Recorder Revision History
- Now stopping any ongoing recordings before stopping the plugins, to avoid
a crash when stopping VDR while recording.
2017-04-15: Version 2.3.4
2017-04-17: Version 2.3.4
- The functionality of HandleRemoteModifications(), which synchronizes changes to
timers between peer VDR machines, has been moved to timers.[ch] and renamed to
@ -8978,3 +8978,7 @@ Video Disk Recorder Revision History
is called, but the actual TS packet returned (pointed to by Data) may well be
(and typically is, unless the CAM copies the data) in the area of the buffer that
would be deleted by Skip().
- The new function cDevice::SignalStats() (if implemented by an actual device) returns
statistics about the currently received signal.
- If DVB API 5 signal statistics are available for a cDvbDevice, it now logs them
whenever the tuner acquires a lock (suggested by Dietmar Spingler).

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.c 4.14 2017/04/15 09:44:50 kls Exp $
* $Id: device.c 4.15 2017/04/17 14:47:42 kls Exp $
*/
#include "device.h"
@ -749,6 +749,11 @@ const cPositioner *cDevice::Positioner(void) const
return NULL;
}
bool cDevice::SignalStats(int &Valid, double *Strength, double *Cnr, double *BerPre, double *BerPost, double *Per) const
{
return false;
}
int cDevice::SignalStrength(void) const
{
return -1;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.h 4.7 2017/04/15 09:41:34 kls Exp $
* $Id: device.h 4.8 2017/04/17 14:46:57 kls Exp $
*/
#ifndef __DEVICE_H
@ -106,6 +106,13 @@ public:
/// The cDevice class is the base from which actual devices can be derived.
#define DTV_STAT_VALID_NONE 0x0000
#define DTV_STAT_VALID_STRENGTH 0x0001
#define DTV_STAT_VALID_CNR 0x0002
#define DTV_STAT_VALID_BERPRE 0x0004
#define DTV_STAT_VALID_BERPOST 0x0008
#define DTV_STAT_VALID_PER 0x0010
class cDevice : public cThread {
friend class cLiveSubtitle;
friend class cDeviceHook;
@ -284,6 +291,22 @@ public:
///< move the satellite dish to the requested position (only applies to DVB-S
///< devices). If no positioner is involved, or this is not a DVB-S device,
///< NULL will be returned.
virtual bool SignalStats(int &Valid, double *Strength = NULL, double *Cnr = NULL, double *BerPre = NULL, double *BerPost = NULL, double *Per = NULL) const;
///< Returns statistics about the currently received signal (if available).
///< Strength is the signal strength in dBm (typical range -100dBm...0dBm).
///< Cnr is the carrier to noise ratio in dB (typical range 0dB...40dB).
///< BerPre is the bit error rate before the forward error correction (FEC).
///< BerPost is the bit error rate after the forward error correction (FEC).
///< Per is the block error rate after the forward error correction (FEC).
///< Typical range for BerPre, BerPost and Per is 0...1.
///< If any of the given pointers is not NULL, the value of the respective signal
///< statistic is returned in it. Upon return, Valid holds a combination of
///< DTV_STAT_VALID_* flags, indicating which of the returned values are actually
///< valid. If the flag for a particular parameter in Valid is 0, the returned
///< value is undefined. It depends on the device which of these parameters
///< (if any) are available.
///< Returns true if any of the requested parameters is valid.
///< If false is returned, the value in Valid is undefined.
virtual int SignalStrength(void) const;
///< Returns the "strength" of the currently received signal.
///< This is a value in the range 0 (no signal at all) through

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbdevice.c 4.6 2017/04/14 10:05:15 kls Exp $
* $Id: dvbdevice.c 4.7 2017/04/17 15:02:44 kls Exp $
*/
#include "dvbdevice.h"
@ -346,6 +346,7 @@ public:
void SetChannel(const cChannel *Channel);
bool Locked(int TimeoutMs = 0);
const cPositioner *Positioner(void) const { return positioner; }
bool GetSignalStats(int &Valid, double *Strength = NULL, double *Cnr = NULL, double *BerPre = NULL, double *BerPost = NULL, double *Per = NULL) const;
int GetSignalStrength(void) const;
int GetSignalQuality(void) const;
};
@ -554,6 +555,7 @@ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
return false;
}
//#define DEBUG_SIGNALSTATS
//#define DEBUG_SIGNALSTRENGTH
//#define DEBUG_SIGNALQUALITY
@ -566,6 +568,101 @@ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
}\
}
bool cDvbTuner::GetSignalStats(int &Valid, double *Strength, double *Cnr, double *BerPre, double *BerPost, double *Per) const
{
ClearEventQueue();
dtv_property Props[MAXFRONTENDCMDS];
dtv_properties CmdSeq;
memset(&Props, 0, sizeof(Props));
memset(&CmdSeq, 0, sizeof(CmdSeq));
CmdSeq.props = Props;
if (Strength) SETCMD(DTV_STAT_SIGNAL_STRENGTH, 0);
if (Cnr) SETCMD(DTV_STAT_CNR, 0);
if (BerPre) { SETCMD(DTV_STAT_PRE_ERROR_BIT_COUNT, 0);
SETCMD(DTV_STAT_PRE_TOTAL_BIT_COUNT, 0); }
if (BerPost) { SETCMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0);
SETCMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0); }
if (Per) { SETCMD(DTV_STAT_ERROR_BLOCK_COUNT, 0);
SETCMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0); }
if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
return false;
}
Valid = DTV_STAT_VALID_NONE;
int i = 0;
if (Strength) {
if (Props[i].u.st.len > 0) {
switch (Props[i].u.st.stat[0].scale) {
case FE_SCALE_DECIBEL: *Strength = double(Props[i].u.st.stat[0].svalue) / 1000;
Valid |= DTV_STAT_VALID_STRENGTH;
break;
default: ;
}
}
i++;
}
if (Cnr) {
if (Props[i].u.st.len > 0) {
switch (Props[i].u.st.stat[0].scale) {
case FE_SCALE_DECIBEL: *Cnr = double(Props[i].u.st.stat[0].svalue) / 1000;
Valid |= DTV_STAT_VALID_CNR;
break;
default: ;
}
}
i++;
}
if (BerPre) {
if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
uint64_t ebc = Props[i].u.st.stat[0].uvalue; // error bit count
uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue; // total bit count
if (tbc > 0) {
*BerPre = double(ebc) / tbc;
Valid |= DTV_STAT_VALID_BERPRE;
}
}
}
i += 2;
}
if (BerPost) {
if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
uint64_t ebc = Props[i].u.st.stat[0].uvalue; // error bit count
uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue; // total bit count
if (tbc > 0) {
*BerPost = double(ebc) / tbc;
Valid |= DTV_STAT_VALID_BERPOST;
}
}
}
i += 2;
}
if (Per) {
if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
uint64_t ebc = Props[i].u.st.stat[0].uvalue; // error block count
uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue; // total block count
if (tbc > 0) {
*Per = double(ebc) / tbc;
Valid |= DTV_STAT_VALID_PER;
}
}
}
i += 2;
}
#ifdef DEBUG_SIGNALSTATS
fprintf(stderr, "FE %d/%d: API5 %04X", adapter, frontend, Valid);
if ((Valid & DTV_STAT_VALID_STRENGTH) != 0) fprintf(stderr, " STR=%1.1fdBm", *Strength);
if ((Valid & DTV_STAT_VALID_CNR) != 0) fprintf(stderr, " CNR=%1.1fdB", *Cnr);
if ((Valid & DTV_STAT_VALID_BERPRE) != 0) fprintf(stderr, " BERPRE=%1.1e", *BerPre);
if ((Valid & DTV_STAT_VALID_BERPOST) != 0) fprintf(stderr, " BERPOST=%1.1e", *BerPost);
if ((Valid & DTV_STAT_VALID_PER) != 0) fprintf(stderr, " PER=%1.1e", *Per);
fprintf(stderr, "\n");
#endif
return Valid != DTV_STAT_VALID_NONE;
}
int dB1000toPercent(int dB1000, int Low, int High)
{
// Convert the given value, which is in 1/1000 dBm, to a percentage in the
@ -1058,6 +1155,18 @@ void cDvbTuner::Action(void)
isyslog("frontend %d/%d regained lock on channel %d (%s), tp %d", adapter, frontend, channel.Number(), channel.Name(), channel.Transponder());
LostLock = false;
}
if (tunerStatus == tsTuned) {
if (SysLogLevel >= 3) {
int Valid;
double Strength, Cnr;
if (GetSignalStats(Valid, &Strength, &Cnr)) {
cString s = cString::sprintf("frontend %d/%d locked with signal", adapter, frontend);
if ((Valid & DTV_STAT_VALID_STRENGTH) != 0) s = cString::sprintf("%s STR=%1.1fdBm", *s, Strength);
if ((Valid & DTV_STAT_VALID_CNR) != 0) s = cString::sprintf("%s CNR=%1.1fdB", *s, Cnr);
dsyslog("%s", *s);
}
}
}
tunerStatus = tsLocked;
locked.Broadcast();
lastTimeoutReport = 0;
@ -1697,6 +1806,11 @@ const cPositioner *cDvbDevice::Positioner(void) const
return dvbTuner ? dvbTuner->Positioner() : NULL;
}
bool cDvbDevice::SignalStats(int &Valid, double *Strength, double *Cnr, double *BerPre, double *BerPost, double *Per) const
{
return dvbTuner ? dvbTuner->GetSignalStats(Valid, Strength, Cnr, BerPre, BerPost, Per) : false;
}
int cDvbDevice::SignalStrength(void) const
{
return dvbTuner ? dvbTuner->GetSignalStrength() : -1;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbdevice.h 4.2 2017/04/14 09:31:29 kls Exp $
* $Id: dvbdevice.h 4.3 2017/04/17 14:44:43 kls Exp $
*/
#ifndef __DVBDEVICE_H
@ -244,6 +244,7 @@ public:
virtual bool ProvidesEIT(void) const;
virtual int NumProvidedSystems(void) const;
virtual const cPositioner *Positioner(void) const;
virtual bool SignalStats(int &Valid, double *Strength = NULL, double *Cnr = NULL, double *BerPre = NULL, double *BerPost = NULL, double *Per = NULL) const;
virtual int SignalStrength(void) const;
virtual int SignalQuality(void) const;
virtual const cChannel *GetCurrentlyTunedTransponder(void) const;