diff --git a/plugins/channelrx/demoddatv/datvdemod.h b/plugins/channelrx/demoddatv/datvdemod.h
index a28406f4a..4283ffcab 100644
--- a/plugins/channelrx/demoddatv/datvdemod.h
+++ b/plugins/channelrx/demoddatv/datvdemod.h
@@ -66,10 +66,12 @@ public:
return m_settings.m_centerFrequency;
}
- void setMessageQueueToGUI(MessageQueue* queue) override {
+ void setMessageQueueToGUI(MessageQueue* queue) override
+ {
ChannelAPI::setMessageQueueToGUI(queue);
m_basebandSink->setMessageQueueToGUI(queue);
}
+
void SetTVScreen(TVScreen *objScreen) { m_basebandSink->setTVScreen(objScreen); }
void setMERLabel(QLabel *merLabel) { m_basebandSink->setMERLabel(merLabel); }
void setCNRLabel(QLabel *cnrLabel) { m_basebandSink->setCNRLabel(cnrLabel); }
diff --git a/plugins/channelrx/demoddatv/datvdemodgui.cpp b/plugins/channelrx/demoddatv/datvdemodgui.cpp
index 8ff914732..fb36bf707 100644
--- a/plugins/channelrx/demoddatv/datvdemodgui.cpp
+++ b/plugins/channelrx/demoddatv/datvdemodgui.cpp
@@ -261,6 +261,7 @@ DATVDemodGUI::DATVDemodGUI(PluginAPI* objPluginAPI, DeviceUISet *deviceUISet, Ba
ui->softLDPC->setStyleSheet("QCheckBox { color: gray }");
#endif
+ ui->playerIndicator->setStyleSheet("QLabel { background-color: gray; border-radius: 8px; }");
resetToDefaults(); // does applySettings()
}
@@ -547,7 +548,13 @@ void DATVDemodGUI::tick()
m_intPreviousDecodedData = m_intLastDecodedData;
//Try to start video rendering
- m_objDATVDemod->playVideo();
+ bool success = m_objDATVDemod->playVideo();
+
+ if (success) {
+ ui->playerIndicator->setStyleSheet("QLabel { background-color: rgb(85, 232, 85); border-radius: 8px; }"); // green
+ } else {
+ ui->playerIndicator->setStyleSheet("QLabel { background-color: gray; border-radius: 8px; }");
+ }
return;
}
diff --git a/plugins/channelrx/demoddatv/datvdemodgui.ui b/plugins/channelrx/demoddatv/datvdemodgui.ui
index 36c4f7593..a8ead08e6 100644
--- a/plugins/channelrx/demoddatv/datvdemodgui.ui
+++ b/plugins/channelrx/demoddatv/datvdemodgui.ui
@@ -779,6 +779,37 @@
+
+
+
+ 10
+ 250
+ 16
+ 16
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16
+ 16
+
+
+
+ Player thread running indicator
+
+
+ QLabel { background-color: gray; border-radius: 8px; }
+
+
+
+
+
@@ -911,7 +942,7 @@
- SNR estimation
+ MER estimation
@@ -971,7 +1002,7 @@
- SNR estimation
+ CNR estimation
diff --git a/plugins/channelrx/demoddatv/datvdemodsink.cpp b/plugins/channelrx/demoddatv/datvdemodsink.cpp
index 3825e2ac8..9dd3e9c12 100644
--- a/plugins/channelrx/demoddatv/datvdemodsink.cpp
+++ b/plugins/channelrx/demoddatv/datvdemodsink.cpp
@@ -176,11 +176,12 @@ bool DATVDemodSink::playVideo()
{
m_objRenderThread->setStreamAndRenderer(m_objRegisteredVideoRender, m_objVideoStream);
m_objVideoStream->MultiThreaded = true;
- m_objVideoStream->ThreadTimeOut = 5000; //5000 ms
+ m_objVideoStream->ThreadTimeOut = DATVideoRenderThread::videoThreadTimeoutMs;
m_objRenderThread->start();
+ return true;
}
- return true;
+ return false;
}
void DATVDemodSink::CleanUpDATVFramework()
@@ -1013,29 +1014,29 @@ void DATVDemodSink::InitDATVS2Framework()
switch (m_objCfg.sampler)
{
case DATVDemodSettings::SAMP_NEAREST:
- sampler = new leansdr::nearest_sampler();
- break;
+ sampler = new leansdr::nearest_sampler();
+ break;
case DATVDemodSettings::SAMP_LINEAR:
- sampler = new leansdr::linear_sampler();
- break;
+ sampler = new leansdr::linear_sampler();
+ break;
case DATVDemodSettings::SAMP_RRC:
{
- if (m_objCfg.rrc_steps == 0)
- {
- // At least 64 discrete sampling points between symbols
- m_objCfg.rrc_steps = std::max(1, (int)(64*m_objCfg.Fm / m_objCfg.Fs));
- }
+ if (m_objCfg.rrc_steps == 0)
+ {
+ // At least 64 discrete sampling points between symbols
+ m_objCfg.rrc_steps = std::max(1, (int)(64*m_objCfg.Fm / m_objCfg.Fs));
+ }
- float Frrc = m_objCfg.Fs * m_objCfg.rrc_steps; // Sample freq of the RRC filter
- float transition = (m_objCfg.Fm/2) * m_objCfg.rolloff;
- int order = m_objCfg.rrc_rej * Frrc / (22*transition);
- ncoeffs_sampler = leansdr::filtergen::root_raised_cosine(order, m_objCfg.Fm/Frrc, m_objCfg.rolloff, &coeffs_sampler);
- sampler = new leansdr::fir_sampler(ncoeffs_sampler, coeffs_sampler, m_objCfg.rrc_steps);
- break;
+ float Frrc = m_objCfg.Fs * m_objCfg.rrc_steps; // Sample freq of the RRC filter
+ float transition = (m_objCfg.Fm/2) * m_objCfg.rolloff;
+ int order = m_objCfg.rrc_rej * Frrc / (22*transition);
+ ncoeffs_sampler = leansdr::filtergen::root_raised_cosine(order, m_objCfg.Fm/Frrc, m_objCfg.rolloff, &coeffs_sampler);
+ sampler = new leansdr::fir_sampler(ncoeffs_sampler, coeffs_sampler, m_objCfg.rrc_steps);
+ break;
}
default:
- qCritical("DATVDemodSink::InitDATVS2Framework: Interpolator not implemented");
- return;
+ qCritical("DATVDemodSink::InitDATVS2Framework: Interpolator not implemented");
+ return;
}
p_slots_dvbs2 = new leansdr::pipebuf< leansdr::plslot > (m_objScheduler, "PL slots", BUF_SLOTS);
@@ -1268,7 +1269,7 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
if (m_blnNeedConfigUpdate)
{
qDebug("DATVDemodSink::feed: Settings applied. Standard : %d...", m_settings.m_standard);
- m_blnNeedConfigUpdate=false;
+ m_blnNeedConfigUpdate = false;
if(m_settings.m_standard==DATVDemodSettings::DVB_S2)
{
@@ -1297,8 +1298,8 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
objRF ++;
if (m_blnDVBInitialized
- && (p_rawiq_writer!=nullptr)
- && (m_objScheduler!=nullptr))
+ && (p_rawiq_writer!=nullptr)
+ && (m_objScheduler!=nullptr))
{
p_rawiq_writer->write(objIQ);
m_lngReadIQ++;
@@ -1321,7 +1322,7 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
} // Samples for loop
// DVBS2: Track change of constellation via MODCOD
- if (m_settings.m_standard==DATVDemodSettings::DVB_S2)
+ if (m_settings.m_standard == DATVDemodSettings::DVB_S2)
{
leansdr::s2_frame_receiver * objDemodulatorDVBS2 = (leansdr::s2_frame_receiver *) m_objDemodulatorDVBS2;
@@ -1342,6 +1343,22 @@ void DATVDemodSink::feed(const SampleVector::const_iterator& begin, const Sample
getMessageQueueToGUI()->push(msg);
}
+
+ if (
+ (
+ (m_modcodModulation != objDemodulatorDVBS2->m_modcodType) &&
+ (m_modcodModulation >= 0) &&
+ (objDemodulatorDVBS2->m_modcodType >= 0)
+ ) ||
+ (
+ (m_modcodCodeRate != objDemodulatorDVBS2->m_modcodRate) &&
+ (m_modcodCodeRate >= 0) &&
+ (objDemodulatorDVBS2->m_modcodRate >= 0)
+ )
+ )
+ {
+ m_blnNeedConfigUpdate = true;
+ }
}
m_cstlnSetByModcod = objDemodulatorDVBS2->cstln->m_setByModcod;
diff --git a/plugins/channelrx/demoddatv/datvdvbs2constellation.h b/plugins/channelrx/demoddatv/datvdvbs2constellation.h
index 0d9b2bd1c..a389a5b0a 100644
--- a/plugins/channelrx/demoddatv/datvdvbs2constellation.h
+++ b/plugins/channelrx/demoddatv/datvdvbs2constellation.h
@@ -29,8 +29,10 @@ namespace leansdr {
static const int DEFAULT_GUI_DVBS2_DECIMATION = 64;
-static inline cstln_lut * make_dvbs2_constellation(cstln_lut::predef c,
- code_rate r)
+static inline cstln_lut * make_dvbs2_constellation(
+ cstln_lut::predef c,
+ code_rate r
+)
{
float gamma1 = 1, gamma2 = 1, gamma3 = 1;
@@ -104,8 +106,8 @@ static inline cstln_lut * make_dvbs2_constellation(cstln_lut *newCstln = new cstln_lut(c, 10, gamma1, gamma2, gamma3);
- newCstln->m_rateCode = (int) r;
- newCstln->m_typeCode = (int) c;
+ newCstln->m_rateCode = r < code_rate::FEC_COUNT ? r : -1;
+ newCstln->m_typeCode = c < cstln_lut::predef::COUNT ? c : -1;
newCstln->m_setByModcod = false;
return newCstln;
}
diff --git a/plugins/channelrx/demoddatv/datvideorender.cpp b/plugins/channelrx/demoddatv/datvideorender.cpp
index 1b67ab4e7..618eb1ca2 100644
--- a/plugins/channelrx/demoddatv/datvideorender.cpp
+++ b/plugins/channelrx/demoddatv/datvideorender.cpp
@@ -29,7 +29,8 @@ extern "C"
#include "audio/audiofifo.h"
#include "datvideorender.h"
-DATVideoRender::DATVideoRender(QWidget *parent) : TVScreen(true, parent), m_parentWidget(parent)
+DATVideoRender::DATVideoRender(QWidget *parent) :
+ TVScreen(true, parent), m_parentWidget(parent)
{
installEventFilter(this);
m_isFullScreen = false;
@@ -229,7 +230,7 @@ bool DATVideoRender::PreprocessStream()
avcodec_free_context(&m_videoDecoderCtx);
}
- m_videoDecoderCtx = avcodec_alloc_context3(NULL);
+ m_videoDecoderCtx = avcodec_alloc_context3(nullptr);
avcodec_parameters_to_context(m_videoDecoderCtx, parms);
// m_videoDecoderCtx = m_formatCtx->streams[m_videoStreamIndex]->codec; // old style
@@ -311,6 +312,10 @@ bool DATVideoRender::PreprocessStream()
m_metaData.CodecDescription = QString("%1").arg(videoCodec->long_name);
m_metaData.OK_VideoStream = true;
+ QString metaStr;
+ m_metaData.formatString(metaStr);
+ qDebug() << "DATVideoRender::PreprocessStream: video: " << metaStr;
+
emit onMetaDataChanged(new DataTSMetaData2(m_metaData));
// Prepare Audio Codec
@@ -704,6 +709,13 @@ bool DATVideoRender::CloseStream(QIODevice *device)
m_videoDecoderCtx = nullptr;
}
+ if (m_audioDecoderCtx)
+ {
+ avcodec_free_context(&m_audioDecoderCtx);
+ avcodec_close(m_audioDecoderCtx);
+ m_audioDecoderCtx = nullptr;
+ }
+
if (m_frame)
{
av_frame_unref(m_frame);
diff --git a/plugins/channelrx/demoddatv/datvideorender.h b/plugins/channelrx/demoddatv/datvideorender.h
index fec726df2..6ac6ae90c 100644
--- a/plugins/channelrx/demoddatv/datvideorender.h
+++ b/plugins/channelrx/demoddatv/datvideorender.h
@@ -86,6 +86,20 @@ struct DataTSMetaData2
OK_TransportStream = false;
OK_VideoStream = false;
}
+
+ void formatString(QString &s)
+ {
+ QTextStream out(&s);
+ out << " CodecID:" << CodecID
+ << " PID:" << PID
+ << " Program:" << Program
+ << " Stream:" << Stream
+ << " Width:" << Width
+ << " Height:" << Height
+ << " BitRate:" << BitRate
+ << " Channels:" << Channels
+ << " CodecDescription:" << CodecDescription;
+ }
};
class DATVideoRender : public TVScreen
@@ -98,11 +112,11 @@ class DATVideoRender : public TVScreen
void SetFullScreen(bool blnFullScreen);
+ void setAudioFIFO(AudioFifo *fifo) { m_audioFifo = fifo; }
bool OpenStream(DATVideostream *objDevice);
bool RenderStream();
bool CloseStream(QIODevice *objDevice);
- void setAudioFIFO(AudioFifo *fifo) { m_audioFifo = fifo; }
int getVideoStreamIndex() const { return m_videoStreamIndex; }
int getAudioStreamIndex() const { return m_audioStreamIndex; }
@@ -114,6 +128,7 @@ class DATVideoRender : public TVScreen
bool getVideoDecodeOK() const { return m_videoDecodeOK; }
private:
+
struct DataTSMetaData2 m_metaData;
QWidget *m_parentWidget;
Qt::WindowFlags m_originalWindowFlags;
@@ -224,6 +239,8 @@ class DATVideoRenderThread : public QThread
m_renderingVideo = false;
}
+ static const int videoThreadTimeoutMs = 2000;
+
private:
DATVideoRender *m_renderer;
DATVideostream *m_stream;
diff --git a/plugins/channelrx/demoddatv/leansdr/dvbs2.h b/plugins/channelrx/demoddatv/leansdr/dvbs2.h
index b9f4fe0e1..e05bf61e7 100644
--- a/plugins/channelrx/demoddatv/leansdr/dvbs2.h
+++ b/plugins/channelrx/demoddatv/leansdr/dvbs2.h
@@ -769,7 +769,7 @@ struct s2_frame_receiver : runnable
opt_write(state_out, 0);
if (sch->debug) {
- fprintf(stderr, "DETECT\n");
+ fprintf(stderr, "enter_frame_detect\n");
}
if (fastlock || first_run)
@@ -960,7 +960,7 @@ struct s2_frame_receiver : runnable
if (plscode_errors >= S2_MAX_ERR_PLSCODE)
{
if (sch->debug2) {
- fprintf(stderr, "Too many errors in plscode (%u)\n", plscode_errors);
+ fprintf(stderr, "Too many errors in plscode (%u/%lu)\n", plscode_errors, S2_MAX_ERR_PLSCODE);
}
in.read(ss.p-in.rd());
@@ -1040,13 +1040,16 @@ struct s2_frame_receiver : runnable
if (mer < mcinfo->esn0_nf - 1.0f)
{
// False positive from PLHEADER detection.
- if ( sch->debug ) fprintf(stderr, "Insufficient MER\n");
+ if (sch->debug) {
+ fprintf(stderr, "Insufficient MER (%f/%f)\n", mer, mcinfo->esn0_nf - 1.0f);
+ }
+
in.read(ss.p-in.rd());
enter_frame_detect();
return;
}
- if (pls.sf && mcinfo->rate==FEC910)
+ if (pls.sf && mcinfo->rate == FEC910)
{ // TBD use fec_infos
fprintf(stderr, "Unsupported or corrupted FEC\n");
in.read(ss.p-in.rd());
@@ -1056,19 +1059,19 @@ struct s2_frame_receiver : runnable
// Store current MODCOD info
if (mcinfo->c != m_modcodType) {
- m_modcodType = mcinfo->c;
+ m_modcodType = mcinfo->c < cstln_base::predef::COUNT ? mcinfo->c : -1;
}
if (mcinfo->rate != m_modcodRate) {
- m_modcodRate = mcinfo->rate;
+ m_modcodRate = mcinfo->rate < code_rate::FEC_COUNT ? mcinfo->rate : -1;
}
S = pls.sf ? mcinfo->nslots_nf/4 : mcinfo->nslots_nf;
// Constellation for data slots.
dcstln = get_cstln(pls.modcod);
cstln = dcstln; // Used by GUI
- cstln->m_rateCode = (int) mcinfo->rate;
- cstln->m_typeCode = (int) mcinfo->c;
+ cstln->m_rateCode = mcinfo->rate < code_rate::FEC_COUNT ? mcinfo->rate : -1;
+ cstln->m_typeCode = mcinfo->c < cstln_base::predef::COUNT ? mcinfo->c : -1;
cstln->m_setByModcod = true;
// Output special slot with PLS information.
pout->is_pls = true;
@@ -1324,10 +1327,7 @@ struct s2_frame_receiver : runnable
if (ss_cache.fw16max_freqw16)
{
- if (sch->debug) {
- fprintf(stderr, "Carrier out of bounds\n");
- }
-
+ fprintf(stderr, "Carrier out of bounds\n");
enter_frame_detect();
}
} // run_frame_probe_locked