From 29506a1d6564beba93dea5fe0405b30235b057b7 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 28 Mar 2021 18:40:43 +0200 Subject: [PATCH] DATV: fixes to improve stability (1) --- plugins/channelrx/demoddatv/datvdemod.h | 4 +- plugins/channelrx/demoddatv/datvdemodgui.cpp | 9 ++- plugins/channelrx/demoddatv/datvdemodgui.ui | 35 ++++++++++- plugins/channelrx/demoddatv/datvdemodsink.cpp | 63 ++++++++++++------- .../demoddatv/datvdvbs2constellation.h | 10 +-- .../channelrx/demoddatv/datvideorender.cpp | 16 ++++- plugins/channelrx/demoddatv/datvideorender.h | 19 +++++- plugins/channelrx/demoddatv/leansdr/dvbs2.h | 24 +++---- 8 files changed, 134 insertions(+), 46 deletions(-) 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