1
0
mirror of https://github.com/rofafor/vdr-plugin-femon.git synced 2023-10-10 13:36:53 +02:00

Removed bitstream parsing from Receive() method.

Refactored the error logging from unimplemented ioctl functions.
This commit is contained in:
Rolf Ahrenberg 2009-09-22 08:44:30 +03:00
parent 080f390a75
commit 21d9c20beb
6 changed files with 237 additions and 118 deletions

View File

@ -381,3 +381,4 @@ VDR Plugin 'femon' Revision History
- Changed H.264 parser to show display aspect ratio.
- Removed error logging from unimplemented ioctl functions.
- Removed bitstream parsing from Receive() method.

View File

@ -28,6 +28,7 @@
#define OSDSPACING 5
#define OSDROUNDING 10
#define IS_OSDROUNDING (femonConfig.skin == eFemonSkinElchi)
#define IS_OSDRESOLUTION(r1, r2) (abs(r1 - r2) < 20)
#define OSDINFOWIN_Y(offset) (femonConfig.position ? (OSDHEIGHT - OSDINFOHEIGHT + offset) : offset)
#define OSDINFOWIN_X(col) ((col == 4) ? int(round(OSDWIDTH * 0.76)) : \
(col == 3) ? int(round(OSDWIDTH * 0.51)) : \
@ -66,7 +67,7 @@
#define OSDDRAWSTATUSBAR(value) \
if (value > 0) { \
int32_t barvalue = OSDBARWIDTH(value); \
int barvalue = OSDBARWIDTH(value); \
m_Osd->DrawRectangle(0, OSDSTATUSWIN_Y(offset) + 3, min(OSDBARWIDTH(femonConfig.redlimit), barvalue), OSDSTATUSWIN_Y(offset) + OSDROWHEIGHT - 3, femonTheme[femonConfig.theme].clrRed); \
if (barvalue > OSDBARWIDTH(femonConfig.redlimit)) \
m_Osd->DrawRectangle(OSDBARWIDTH(femonConfig.redlimit), OSDSTATUSWIN_Y(offset) + 3, min((OSDWIDTH * femonConfig.greenlimit / 100), barvalue), OSDSTATUSWIN_Y(offset) + OSDROWHEIGHT - 3, femonTheme[femonConfig.theme].clrYellow); \
@ -168,10 +169,15 @@ cFemonOsd::cFemonOsd()
m_SvdrpPlugin(NULL),
m_Number(0),
m_OldNumber(0),
m_SNR(-1),
m_Signal(-1),
m_BER(-1),
m_UNC(-1),
m_SNR(0),
m_SNRValid(false),
m_Signal(0),
m_SignalValid(false),
m_BER(0),
m_BERValid(false),
m_UNC(0),
m_UNCValid(false),
m_FrontendStatusValid(false),
m_DisplayMode(femonConfig.displaymode),
m_OsdWidth(cOsd::OsdWidth()),
m_OsdHeight(cOsd::OsdHeight()),
@ -181,8 +187,8 @@ cFemonOsd::cFemonOsd()
{
int tmp;
Dprintf("%s()\n", __PRETTY_FUNCTION__);
memset(&m_FrontendInfo, 0, sizeof(m_FrontendInfo));
memset(&m_FrontendStatus, 0, sizeof(m_FrontendStatus));
memset(&m_FrontendInfo, 0, sizeof(m_FrontendInfo));
m_SvdrpConnection.handle = -1;
m_Font = cFont::CreateFont(Setup.FontSml, min(max(Setup.FontSmlSize, MINFONTSIZE), MAXFONTSIZE));
if (!m_Font || !m_Font->Height()) {
@ -284,13 +290,13 @@ void cFemonOsd::DrawStatusWindow(void)
OSDDRAWSTATUSBM(OSDSPACING);
}
if (m_Receiver) {
if (abs(m_Receiver->VideoVerticalSize() - 1080) < 20)
if (IS_OSDRESOLUTION(m_Receiver->VideoVerticalSize(), 1080))
bm = &bmSymbol[SYMBOL_FORMAT_1080];
else if (abs(m_Receiver->VideoVerticalSize() - 720) < 20)
else if (IS_OSDRESOLUTION(m_Receiver->VideoVerticalSize(), 720))
bm = &bmSymbol[SYMBOL_FORMAT_720];
else if (abs(m_Receiver->VideoVerticalSize() - 576) < 20)
else if (IS_OSDRESOLUTION(m_Receiver->VideoVerticalSize(), 576))
bm = &bmSymbol[SYMBOL_FORMAT_576];
else if (abs(m_Receiver->VideoVerticalSize() - 480) < 20)
else if (IS_OSDRESOLUTION(m_Receiver->VideoVerticalSize(), 480))
bm = &bmSymbol[SYMBOL_FORMAT_480];
else
bm = NULL;
@ -321,28 +327,30 @@ void cFemonOsd::DrawStatusWindow(void)
OSDDRAWSTATUSBM(OSDSPACING);
}
offset += OSDROWHEIGHT;
if (m_Signal >= 0)
if (m_SignalValid)
OSDDRAWSTATUSBAR(m_Signal / 655);
offset += OSDROWHEIGHT;
if (m_SNR >= 0)
if (m_SNRValid)
OSDDRAWSTATUSBAR(m_SNR / 655);
offset += OSDROWHEIGHT;
OSDDRAWSTATUSVALUES("STR:", (m_Signal >= 0) ? *cString::sprintf("%04" PRIu32, m_Signal) : "---", (m_Signal >= 0) ? *cString::sprintf("(%2d%%)", m_Signal / 655) : "",
"BER:", (m_BER >= 0) ? *cString::sprintf("%08" PRIx64, m_BER) : "---", *cString::sprintf("%s:", tr("Video")),
OSDDRAWSTATUSVALUES("STR:", m_SignalValid ? *cString::sprintf("%04x", m_Signal) : "", m_SignalValid ? *cString::sprintf("(%2d%%)", m_Signal / 655) : "",
"BER:", m_BERValid ? *cString::sprintf("%08x", m_BER) : "", *cString::sprintf("%s:", tr("Video")),
*getBitrateMbits(m_Receiver ? m_Receiver->VideoBitrate() : (m_SvdrpFrontend >= 0 ? m_SvdrpVideoBitrate : -1.0)));
offset += OSDROWHEIGHT;
OSDDRAWSTATUSVALUES("SNR:", (m_SNR >= 0) ? *cString::sprintf("%04" PRIu32, m_SNR) : "---", (m_SNR >= 0) ? *cString::sprintf("(%2d%%)", m_SNR / 655) : "",
"UNC:", (m_UNC >= 0) ? *cString::sprintf("%08" PRIx64, m_UNC) : "---",
OSDDRAWSTATUSVALUES("SNR:", m_SNRValid ? *cString::sprintf("%04x", m_SNR) : "", m_SNRValid ? *cString::sprintf("(%2d%%)", m_SNR / 655) : "",
"UNC:", m_UNCValid ? *cString::sprintf("%08x", m_UNC) : "",
*cString::sprintf("%s:", (m_Receiver && m_Receiver->AC3Valid() && IS_DOLBY_TRACK(track)) ? tr("AC-3") : tr("Audio")),
*getBitrateKbits(m_Receiver ? ((m_Receiver->AC3Valid() && IS_DOLBY_TRACK(track)) ? m_Receiver->AC3Bitrate() : m_Receiver->AudioBitrate()) : (m_SvdrpFrontend >= 0 ? m_SvdrpAudioBitrate : -1.0)));
offset += OSDROWHEIGHT;
x = bmSymbol[SYMBOL_LOCK].Width();
y = (OSDROWHEIGHT - bmSymbol[SYMBOL_LOCK].Height()) / 2;
if (m_FrontendStatusValid) {
OSDDRAWSTATUSFRONTEND(1, bmSymbol[SYMBOL_LOCK], FE_HAS_LOCK);
OSDDRAWSTATUSFRONTEND(2, bmSymbol[SYMBOL_SIGNAL], FE_HAS_SIGNAL);
OSDDRAWSTATUSFRONTEND(3, bmSymbol[SYMBOL_CARRIER], FE_HAS_CARRIER);
OSDDRAWSTATUSFRONTEND(4, bmSymbol[SYMBOL_VITERBI], FE_HAS_VITERBI);
OSDDRAWSTATUSFRONTEND(5, bmSymbol[SYMBOL_SYNC], FE_HAS_SYNC);
}
OSDDRAWSTATUSBOTTOMBAR();
m_Osd->Flush();
}
@ -505,16 +513,11 @@ void cFemonOsd::Action(void)
m_SvdrpVideoBitrate = -1.0;
m_SvdrpAudioBitrate = -1.0;
if (m_Frontend != -1) {
if (ioctl(m_Frontend, FE_READ_STATUS, &m_FrontendStatus) < 0)
memset(&m_FrontendStatus, 0, sizeof(m_FrontendStatus));
if (ioctl(m_Frontend, FE_READ_SIGNAL_STRENGTH, &m_Signal) < 0)
m_Signal = -1;
if (ioctl(m_Frontend, FE_READ_SNR, &m_SNR) < 0)
m_SNR = -1;
if (ioctl(m_Frontend, FE_READ_BER, &m_BER) < 0)
m_BER = -1;
if (ioctl(m_Frontend, FE_READ_UNCORRECTED_BLOCKS, &m_UNC) < 0)
m_UNC = -1;
m_FrontendStatusValid = (ioctl(m_Frontend, FE_READ_STATUS, &m_FrontendStatus) >= 0);
m_SignalValid = (ioctl(m_Frontend, FE_READ_SIGNAL_STRENGTH, &m_Signal) >= 0);
m_SNRValid = (ioctl(m_Frontend, FE_READ_SNR, &m_SNR) >= 0);
m_BERValid = (ioctl(m_Frontend, FE_READ_BER, &m_BER) >= 0);
m_UNCValid = (ioctl(m_Frontend, FE_READ_UNCORRECTED_BLOCKS, &m_UNC) >= 0);
DrawInfoWindow();
DrawStatusWindow();
}
@ -522,24 +525,40 @@ void cFemonOsd::Action(void)
cmd.handle = m_SvdrpConnection.handle;
m_SvdrpPlugin->Service("SvdrpCommand-v1.0", &cmd);
if (cmd.responseCode == 900) {
m_FrontendStatusValid = false;
m_SignalValid = false;
m_SNRValid = false;
m_BERValid = false;
m_UNCValid = false;
for (cLine *line = cmd.reply.First(); line; line = cmd.reply.Next(line)) {
const char *s = line->Text();
if (!strncasecmp(s, "CARD:", 5))
m_SvdrpFrontend = (int)strtol(s + 5, NULL, 10);
else if (!strncasecmp(s, "TYPE:", 5))
m_FrontendInfo.type = (fe_type_t)strtol(s + 5, NULL, 10);
else if (!strncasecmp(s, "NAME:", 5))
else if (!strncasecmp(s, "NAME:", 5)) {
strn0cpy(m_FrontendInfo.name, s + 5, sizeof(m_FrontendInfo.name));
else if (!strncasecmp(s, "STAT:", 5))
}
else if (!strncasecmp(s, "STAT:", 5)) {
m_FrontendStatus = (fe_status_t)strtol(s + 5, NULL, 16);
else if (!strncasecmp(s, "SGNL:", 5))
m_Signal = (int32_t)strtol(s + 5, NULL, 16);
else if (!strncasecmp(s, "SNRA:", 5))
m_SNR = (int32_t)strtol(s + 5, NULL, 16);
else if (!strncasecmp(s, "BERA:", 5))
m_BER = (int64_t)strtol(s + 5, NULL, 16);
else if (!strncasecmp(s, "UNCB:", 5))
m_UNC = (int64_t)strtol(s + 5, NULL, 16);
m_FrontendStatusValid = true;
}
else if (!strncasecmp(s, "SGNL:", 5)) {
m_Signal = (uint16_t)strtol(s + 5, NULL, 16);
m_SignalValid = true;
}
else if (!strncasecmp(s, "SNRA:", 5)) {
m_SNR = (uint16_t)strtol(s + 5, NULL, 16);
m_SNRValid = true;
}
else if (!strncasecmp(s, "BERA:", 5)) {
m_BER = (uint32_t)strtol(s + 5, NULL, 16);
m_BERValid = true;
}
else if (!strncasecmp(s, "UNCB:", 5)) {
m_UNC = (uint32_t)strtol(s + 5, NULL, 16);
m_UNCValid = true;
}
else if (!strncasecmp(s, "VIBR:", 5))
m_SvdrpVideoBitrate = (double)strtol(s + 5, NULL, 10);
else if (!strncasecmp(s, "AUBR:", 5))

View File

@ -34,14 +34,19 @@ private:
double m_SvdrpAudioBitrate;
SvdrpConnection_v1_0 m_SvdrpConnection;
cPlugin *m_SvdrpPlugin;
dvb_frontend_info m_FrontendInfo;
int m_Number;
int m_OldNumber;
int32_t m_SNR;
int32_t m_Signal;
int64_t m_BER;
int64_t m_UNC;
uint16_t m_SNR;
bool m_SNRValid;
uint16_t m_Signal;
bool m_SignalValid;
uint32_t m_BER;
bool m_BERValid;
uint32_t m_UNC;
bool m_UNCValid;
fe_status_t m_FrontendStatus;
bool m_FrontendStatusValid;
dvb_frontend_info m_FrontendInfo;
int m_DisplayMode;
int m_OsdWidth;
int m_OsdHeight;

View File

@ -20,15 +20,18 @@ cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vtype, int Vpid
m_DetectMPEG(this, this),
m_DetectAAC(this),
m_DetectAC3(this),
m_VideoBuffer(KILOBYTE(256), TS_SIZE, false, "Femon video"),
m_VideoType(Vtype),
m_VideoPid(Vpid),
m_VideoPacketCount(0),
m_VideoBitrate(0.0),
m_VideoValid(false),
m_AudioBuffer(KILOBYTE(256), TS_SIZE, false, "Femon audio"),
m_AudioPid(Apid[0]),
m_AudioPacketCount(0),
m_AudioBitrate(0.0),
m_AudioValid(false),
m_AC3Buffer(KILOBYTE(256), TS_SIZE, false, "Femon AC3"),
m_AC3Pid(Dpid[0]),
m_AC3PacketCount(0),
m_AC3Bitrate(0),
@ -36,6 +39,10 @@ cFemonReceiver::cFemonReceiver(tChannelID ChannelID, int Ca, int Vtype, int Vpid
{
Dprintf("%s()\n", __PRETTY_FUNCTION__);
m_VideoBuffer.SetTimeouts(0, 0);
m_AudioBuffer.SetTimeouts(0, 0);
m_AC3Buffer.SetTimeouts(0, 0);
m_VideoInfo.codec = VIDEO_CODEC_INVALID;
m_VideoInfo.format = VIDEO_FORMAT_INVALID;
m_VideoInfo.scan = VIDEO_SCAN_INVALID;
@ -89,10 +96,63 @@ void cFemonReceiver::Activate(bool On)
void cFemonReceiver::Receive(uchar *Data, int Length)
{
// TS packet length: TS_SIZE
if (Length == TS_SIZE) {
if ((*Data == TS_SYNC_BYTE) || (Length == TS_SIZE)) {
int len, pid = TsPid(Data);
if (pid == m_VideoPid) {
m_VideoPacketCount++;
++m_VideoPacketCount;
len = m_VideoBuffer.Put(Data, Length);
if (len != Length) {
m_VideoBuffer.ReportOverflow(Length - len);
m_VideoBuffer.Clear();
}
}
else if (pid == m_AudioPid) {
++m_AudioPacketCount;
len = m_AudioBuffer.Put(Data, Length);
if (len != Length) {
m_AudioBuffer.ReportOverflow(Length - len);
m_AudioBuffer.Clear();
}
}
else if (pid == m_AC3Pid) {
++m_AC3PacketCount;
len = m_AC3Buffer.Put(Data, Length);
if (len != Length) {
m_AC3Buffer.ReportOverflow(Length - len);
m_AC3Buffer.Clear();
}
}
}
}
void cFemonReceiver::Action(void)
{
Dprintf("%s()\n", __PRETTY_FUNCTION__);
cTimeMs calcPeriod(0);
m_Active = true;
while (Running() && m_Active) {
uint8_t *Data;
double timeout;
int len, Length;
bool processed = false;
// process available video data
while (Data = m_VideoBuffer.Get(Length)) {
if (!m_Active || (Length < TS_SIZE))
break;
Length = TS_SIZE;
if (*Data != TS_SYNC_BYTE) {
for (int i = 1; i < Length; ++i) {
if (Data[i] == TS_SYNC_BYTE) {
Length = i;
break;
}
}
m_VideoBuffer.Del(Length);
continue;
}
processed = true;
if (TsPayloadStart(Data)) {
while (const uint8_t *p = m_VideoAssembler.GetPes(len)) {
if (m_VideoType == 0x1B) { // MPEG4
@ -111,42 +171,73 @@ void cFemonReceiver::Receive(uchar *Data, int Length)
m_VideoAssembler.Reset();
}
m_VideoAssembler.PutTs(Data, Length);
m_VideoBuffer.Del(Length);
}
else if (pid == m_AudioPid) {
m_AudioPacketCount++;
// process available audio data
while (Data = m_AudioBuffer.Get(Length)) {
if (!m_Active || (Length < TS_SIZE))
break;
Length = TS_SIZE;
if (*Data != TS_SYNC_BYTE) {
for (int i = 1; i < Length; ++i) {
if (Data[i] == TS_SYNC_BYTE) {
Length = i;
break;
}
}
m_AudioBuffer.Del(Length);
continue;
}
processed = true;
if (const uint8_t *p = m_AudioAssembler.GetPes(len)) {
if (m_DetectAAC.processAudio(p, len) || m_DetectMPEG.processAudio(p, len))
m_AudioValid = true;
m_AudioAssembler.Reset();
}
m_AudioAssembler.PutTs(Data, Length);
m_AudioBuffer.Del(Length);
}
else if (pid == m_AC3Pid) {
m_AC3PacketCount++;
// process available dolby data
while (Data = m_AC3Buffer.Get(Length)) {
if (!m_Active || (Length < TS_SIZE))
break;
Length = TS_SIZE;
if (*Data != TS_SYNC_BYTE) {
for (int i = 1; i < Length; ++i) {
if (Data[i] == TS_SYNC_BYTE) {
Length = i;
break;
}
}
m_AC3Buffer.Del(Length);
continue;
}
processed = true;
if (const uint8_t *p = m_AC3Assembler.GetPes(len)) {
if (m_DetectAC3.processAudio(p, len))
m_AC3Valid = true;
m_AC3Assembler.Reset();
}
m_AC3Assembler.PutTs(Data, Length);
m_AudioBuffer.Del(Length);
}
}
}
void cFemonReceiver::Action(void)
{
Dprintf("%s()\n", __PRETTY_FUNCTION__);
cTimeMs t;
m_Active = true;
while (Running() && m_Active) {
t.Set(0);
// calculate bitrates
timeout = double(calcPeriod.Elapsed());
if (m_Active && (timeout >= (100.0 * femonConfig.calcinterval))) {
// TS packet 188 bytes - 4 byte header; MPEG standard defines 1Mbit = 1000000bit
m_VideoBitrate = (10.0 * 8.0 * 184.0 * m_VideoPacketCount) / femonConfig.calcinterval;
m_VideoBitrate = (1000.0 * 8.0 * 184.0 * m_VideoPacketCount) / timeout;
m_VideoPacketCount = 0;
m_AudioBitrate = (10.0 * 8.0 * 184.0 * m_AudioPacketCount) / femonConfig.calcinterval;
m_AudioBitrate = (1000.0 * 8.0 * 184.0 * m_AudioPacketCount) / timeout;
m_AudioPacketCount = 0;
m_AC3Bitrate = (10.0 * 8.0 * 184.0 * m_AC3PacketCount) / femonConfig.calcinterval;
m_AC3Bitrate = (1000.0 * 8.0 * 184.0 * m_AC3PacketCount) / timeout;
m_AC3PacketCount = 0;
m_Sleep.Wait(max((int)(100 * femonConfig.calcinterval - t.Elapsed()), 3));
calcPeriod.Set(0);
}
if (!processed)
m_Sleep.Wait(10); // to avoid busy loop and reduce cpu load
}
}

View File

@ -30,6 +30,7 @@ private:
cFemonAAC m_DetectAAC;
cFemonAC3 m_DetectAC3;
cRingBufferLinear m_VideoBuffer;
cTsToPes m_VideoAssembler;
int m_VideoType;
int m_VideoPid;
@ -38,6 +39,7 @@ private:
bool m_VideoValid;
video_info_t m_VideoInfo;
cRingBufferLinear m_AudioBuffer;
cTsToPes m_AudioAssembler;
int m_AudioPid;
int m_AudioPacketCount;
@ -45,6 +47,7 @@ private:
bool m_AudioValid;
audio_info_t m_AudioInfo;
cRingBufferLinear m_AC3Buffer;
cTsToPes m_AC3Assembler;
int m_AC3Pid;
int m_AC3PacketCount;

View File

@ -99,13 +99,13 @@ cString getFrontendInfo(int cardIndex)
if (ioctl(fe, FE_READ_STATUS, &status) >= 0)
info = cString::sprintf("%s\nSTAT:%02X", *info, status);
if (ioctl(fe, FE_READ_SIGNAL_STRENGTH, &signal) >= 0)
info = cString::sprintf("%s\nSGNL:%04" PRIX16, *info, signal);
info = cString::sprintf("%s\nSGNL:%04X", *info, signal);
if (ioctl(fe, FE_READ_SNR, &snr) >= 0)
info = cString::sprintf("%s\nSNRA:%04" PRIX16, *info, snr);
info = cString::sprintf("%s\nSNRA:%04X", *info, snr);
if (ioctl(fe, FE_READ_BER, &ber) >= 0)
info = cString::sprintf("%s\nBERA:%08" PRIX32, *info, ber);
info = cString::sprintf("%s\nBERA:%08X", *info, ber);
if (ioctl(fe, FE_READ_UNCORRECTED_BLOCKS, &unc) >= 0)
info = cString::sprintf("%s\nUNCB:%08" PRIX32, *info, unc);
info = cString::sprintf("%s\nUNCB:%08X", *info, unc);
close(fe);
if (cFemonOsd::Instance())