SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
atvmod.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include <time.h>
19 
20 #include <QDebug>
21 #include <QNetworkAccessManager>
22 #include <QNetworkReply>
23 #include <QBuffer>
24 
25 #include "SWGChannelSettings.h"
26 #include "SWGChannelReport.h"
27 #include "SWGATVModReport.h"
28 
29 #include "opencv2/imgproc/imgproc.hpp"
30 
31 #include "dsp/upchannelizer.h"
33 #include "dsp/dspcommands.h"
34 #include "device/deviceapi.h"
35 #include "util/db.h"
36 
37 #include "atvmod.h"
38 
51 
52 const QString ATVMod::m_channelIdURI = "sdrangel.channeltx.modatv";
53 const QString ATVMod::m_channelId = "ATVMod";
54 const float ATVMod::m_blackLevel = 0.3f;
55 const float ATVMod::m_spanLevel = 0.7f;
56 const int ATVMod::m_levelNbSamples = 10000; // every 10ms
57 const int ATVMod::m_nbBars = 6;
58 const int ATVMod::m_cameraFPSTestNbFrames = 100;
59 const int ATVMod::m_ssbFftLen = 1024;
60 
62  ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
63  m_deviceAPI(deviceAPI),
64  m_outputSampleRate(1000000),
65  m_inputFrequencyOffset(0),
66  m_modPhasor(0.0f),
67  m_tvSampleRate(1000000),
68  m_evenImage(true),
69  m_settingsMutex(QMutex::Recursive),
70  m_horizontalCount(0),
71  m_lineCount(0),
72  m_imageOK(false),
73  m_videoFPSq(1.0f),
74  m_videoFPSCount(0.0f),
75  m_videoPrevFPSCount(0),
76  m_videoEOF(false),
77  m_videoOK(false),
78  m_cameraIndex(-1),
79  //m_showOverlayText(false),
80  m_SSBFilter(0),
81  m_SSBFilterBuffer(0),
82  m_SSBFilterBufferIndex(0),
83  m_DSBFilter(0),
84  m_DSBFilterBuffer(0),
85  m_DSBFilterBufferIndex(0)
86 {
87  setObjectName(m_channelId);
88  scanCameras();
89 
91  m_SSBFilterBuffer = new Complex[m_ssbFftLen>>1]; // filter returns data exactly half of its size
92  memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
93 
96  memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
97 
100 
102  applySettings(m_settings, true); // does applyStandard() too;
103 
104  m_channelizer = new UpChannelizer(this);
108 
109  m_networkManager = new QNetworkAccessManager();
110  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
111 }
112 
114 {
115  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
116  delete m_networkManager;
117 
118  if (m_video.isOpened()) {
119  m_video.release();
120  }
121 
122  releaseCameras();
125  delete m_threadedChannelizer;
126  delete m_channelizer;
127  delete m_SSBFilter;
128  delete m_DSBFilter;
129  delete[] m_SSBFilterBuffer;
130  delete[] m_DSBFilterBuffer;
131 }
132 
133 void ATVMod::pullAudio(int nbSamples)
134 {
135  (void) nbSamples;
136 }
137 
138 void ATVMod::pull(Sample& sample)
139 {
141  {
142  sample.m_real = 0.0f;
143  sample.m_imag = 0.0f;
144  return;
145  }
146 
147  Complex ci;
148 
149  m_settingsMutex.lock();
150 
151  if ((m_tvSampleRate == m_outputSampleRate) && (!m_settings.m_forceDecimator)) // no interpolation nor decimation
152  {
153  modulateSample();
154  pullFinalize(m_modSample, sample);
155  }
156  else
157  {
158  if (m_interpolatorDistance > 1.0f) // decimate
159  {
160  modulateSample();
161 
163  {
164  modulateSample();
165  }
166  }
167  else
168  {
170  {
171  modulateSample();
172  }
173  }
174 
176  pullFinalize(ci, sample);
177  }
178 }
179 
181 {
182  ci *= m_carrierNco.nextIQ(); // shift to carrier frequency
183 
184  m_settingsMutex.unlock();
185 
186  double magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
187  magsq /= (SDR_TX_SCALED*SDR_TX_SCALED);
188  m_movingAverage(magsq);
189 
190  sample.m_real = (FixReal) ci.real();
191  sample.m_imag = (FixReal) ci.imag();
192 }
193 
195 {
196  Real t;
197 
198  pullVideo(t);
199  calculateLevel(t);
200 
201  t = m_settings.m_invertedVideo ? 1.0f - t : t;
202 
203  switch (m_settings.m_atvModulation)
204  {
205  case ATVModSettings::ATVModulationFM: // FM half bandwidth deviation
206  m_modPhasor += (t - 0.5f) * m_settings.m_fmExcursion * 2.0f * M_PI;
207  if (m_modPhasor > 2.0f * M_PI) m_modPhasor -= 2.0f * M_PI; // limit growth
208  if (m_modPhasor < 2.0f * M_PI) m_modPhasor += 2.0f * M_PI; // limit growth
211  break;
216  break;
221  break;
222  case ATVModSettings::ATVModulationAM: // AM 90%
223  default:
224  m_modSample.real((t*1.8f + 0.1f) * (m_settings.m_rfScalingFactor/2.0f)); // modulate and scale zero frequency carrier
225  m_modSample.imag(0.0f);
226  }
227 }
228 
230 {
231  int n_out;
232  Complex ci(sample, 0.0f);
233  fftfilt::cmplx *filtered;
234 
236 
237  if (n_out > 0)
238  {
239  memcpy((void *) m_SSBFilterBuffer, (const void *) filtered, n_out*sizeof(Complex));
241  }
242 
244 
246 }
247 
249 {
250  int n_out;
251  Complex ci(sample, 0.0f);
252  fftfilt::cmplx *filtered;
253 
255 
256  if (n_out > 0)
257  {
258  memcpy((void *) m_DSBFilterBuffer, (const void *) filtered, n_out*sizeof(Complex));
260  }
261 
263 
265 }
266 
267 void ATVMod::pullVideo(Real& sample)
268 {
269  if ((m_settings.m_atvStd == ATVModSettings::ATVStdHSkip) && (m_lineCount == m_nbLines2)) // last line in skip mode
270  {
271  pullImageLine(sample, true); // pull image line without sync
272  }
273  else if (m_lineCount < m_nbLines2 + 1) // even image or non interlaced
274  {
275  int iLine = m_lineCount;
276 
277  if (iLine < m_nbSyncLinesHeadE + m_nbBlankLines)
278  {
279  pullVSyncLine(sample);
280  }
281  else if (iLine > m_nbLines2 - m_nbSyncLinesBottom)
282  {
283  pullVSyncLine(sample);
284  }
285  else
286  {
287  pullImageLine(sample);
288  }
289  }
290  else // odd image
291  {
292  int iLine = m_lineCount - m_nbLines2 - 1;
293 
294  if (iLine < m_nbSyncLinesHeadO + m_nbBlankLines)
295  {
296  pullVSyncLine(sample);
297  }
298  else if (iLine > m_nbLines2 - 1 - m_nbSyncLinesBottom)
299  {
300  pullVSyncLine(sample);
301  }
302  else
303  {
304  pullImageLine(sample);
305  }
306  }
307 
309  {
311  }
312  else
313  {
314  if (m_lineCount < m_nbLines - 1)
315  {
316  m_lineCount++;
318  }
319  else // new image
320  {
321  m_lineCount = 0;
323 
325  {
326  int grabOK = 0;
327  int fpsIncrement = (int) m_videoFPSCount - m_videoPrevFPSCount;
328 
329  // move a number of frames according to increment
330  // use grab to test for EOF then retrieve to preserve last valid frame as the current original frame
331  // TODO: handle pause (no move)
332  for (int i = 0; i < fpsIncrement; i++)
333  {
334  grabOK = m_video.grab();
335  if (!grabOK) break;
336  }
337 
338  if (grabOK)
339  {
340  cv::Mat colorFrame;
341  m_video.retrieve(colorFrame);
342 
343  if (!colorFrame.empty()) // some frames may not come out properly
344  {
346  mixImageAndText(colorFrame);
347  }
348 
349  cv::cvtColor(colorFrame, m_videoframeOriginal, CV_BGR2GRAY);
350  resizeVideo();
351  }
352  }
353  else
354  {
355  if (m_settings.m_videoPlayLoop) { // play loop
357  } else { // stops
358  m_videoEOF = true;
359  }
360  }
361 
363  {
366  }
367  else
368  {
371  }
372  }
374  {
375  ATVCamera& camera = m_cameras[m_cameraIndex]; // currently selected canera
376 
377  if (camera.m_videoFPS < 0.0f) // default frame rate when it could not be obtained via get
378  {
379  time_t start, end;
380  cv::Mat frame;
381 
382  if (getMessageQueueToGUI())
383  {
384  MsgReportCameraData *report;
386  camera.m_cameraNumber,
387  0.0f,
388  camera.m_videoFPSManual,
389  camera.m_videoFPSManualEnable,
390  camera.m_videoWidth,
391  camera.m_videoHeight,
392  1); // open splash screen on GUI side
393  getMessageQueueToGUI()->push(report);
394  }
395 
396  int nbFrames = 0;
397 
398  time(&start);
399 
400  for (int i = 0; i < m_cameraFPSTestNbFrames; i++)
401  {
402  camera.m_camera >> frame;
403  if (!frame.empty()) nbFrames++;
404  }
405 
406  time(&end);
407 
408  double seconds = difftime (end, start);
409  // take a 10% guard and divide bandwidth between all cameras as a hideous hack
410  camera.m_videoFPS = ((nbFrames / seconds) * 0.9) / m_cameras.size();
411  camera.m_videoFPSq = camera.m_videoFPS / m_fps;
412  camera.m_videoFPSCount = camera.m_videoFPSq;
413  camera.m_videoPrevFPSCount = 0;
414 
415  if (getMessageQueueToGUI())
416  {
417  MsgReportCameraData *report;
419  camera.m_cameraNumber,
420  camera.m_videoFPS,
421  camera.m_videoFPSManual,
422  camera.m_videoFPSManualEnable,
423  camera.m_videoWidth,
424  camera.m_videoHeight,
425  2); // close splash screen on GUI side
426  getMessageQueueToGUI()->push(report);
427  }
428  }
429  else if (camera.m_videoFPS == 0.0f) // Hideous hack for windows
430  {
431  camera.m_videoFPS = 5.0f;
432  camera.m_videoFPSq = camera.m_videoFPS / m_fps;
433  camera.m_videoFPSCount = camera.m_videoFPSq;
434  camera.m_videoPrevFPSCount = 0;
435 
436  if (getMessageQueueToGUI())
437  {
438  MsgReportCameraData *report;
440  camera.m_cameraNumber,
441  camera.m_videoFPS,
442  camera.m_videoFPSManual,
443  camera.m_videoFPSManualEnable,
444  camera.m_videoWidth,
445  camera.m_videoHeight,
446  0);
447  getMessageQueueToGUI()->push(report);
448  }
449  }
450 
451  int fpsIncrement = (int) camera.m_videoFPSCount - camera.m_videoPrevFPSCount;
452 
453  // move a number of frames according to increment
454  // use grab to test for EOF then retrieve to preserve last valid frame as the current original frame
455  cv::Mat colorFrame;
456 
457  for (int i = 0; i < fpsIncrement; i++)
458  {
459  camera.m_camera >> colorFrame;
460  if (colorFrame.empty()) break;
461  }
462 
463  if (!colorFrame.empty()) // some frames may not come out properly
464  {
466  mixImageAndText(colorFrame);
467  }
468 
469  cv::cvtColor(colorFrame, camera.m_videoframeOriginal, CV_BGR2GRAY);
470  resizeCamera();
471  }
472 
473  if (camera.m_videoFPSCount < (camera.m_videoFPSManualEnable ? camera.m_videoFPSManual : camera.m_videoFPS))
474  {
475  camera.m_videoPrevFPSCount = (int) camera.m_videoFPSCount;
476  camera.m_videoFPSCount += (camera.m_videoFPSManualEnable ? camera.m_videoFPSqManual : camera.m_videoFPSq);
477  }
478  else
479  {
480  camera.m_videoPrevFPSCount = 0;
481  camera.m_videoFPSCount = (camera.m_videoFPSManualEnable ? camera.m_videoFPSqManual : camera.m_videoFPSq);
482  }
483  }
484  }
485 
486  m_horizontalCount = 0;
487  }
488 }
489 
491 {
493  {
494  m_peakLevel = std::max(std::fabs(m_peakLevel), sample);
495  m_levelSum += sample * sample;
497  }
498  else
499  {
500  qreal rmsLevel = std::sqrt(m_levelSum / m_levelNbSamples);
501  //qDebug("NFMMod::calculateLevel: %f %f", rmsLevel, m_peakLevel);
502  emit levelChanged(rmsLevel, m_peakLevel, m_levelNbSamples);
503  m_peakLevel = 0.0f;
504  m_levelSum = 0.0f;
505  m_levelCalcCount = 0;
506  }
507 }
508 
510 {
511  qDebug() << "ATVMod::start: m_outputSampleRate: " << m_outputSampleRate
512  << " m_inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset;
514 }
515 
517 {
518 }
519 
521 {
523  {
525  qDebug() << "ATVMod::handleMessage: MsgChannelizerNotification:"
526  << " outputSampleRate: " << notif.getSampleRate()
527  << " inputFrequencyOffset: " << notif.getFrequencyOffset();
528 
530 
531  return true;
532  }
533  else if (MsgConfigureChannelizer::match(cmd))
534  {
536  qDebug() << "SSBMod::handleMessage: MsgConfigureChannelizer: sampleRate: " << m_channelizer->getOutputSampleRate()
537  << " centerFrequency: " << cfg.getCenterFrequency();
538 
541  cfg.getCenterFrequency());
542 
543  return true;
544  }
545  else if (MsgConfigureATVMod::match(cmd))
546  {
548  qDebug() << "ATVMod::handleMessage: MsgConfigureATVMod";
549 
550  applySettings(cfg.getSettings(), cfg.getForce());
551 
552  return true;
553  }
554  else if (MsgConfigureImageFileName::match(cmd))
555  {
557  openImage(conf.getFileName());
558  return true;
559  }
560  else if (MsgConfigureVideoFileName::match(cmd))
561  {
563  openVideo(conf.getFileName());
564  return true;
565  }
567  {
569  int seekPercentage = conf.getPercentage();
570  seekVideoFileStream(seekPercentage);
571  return true;
572  }
574  {
575  int framesCount;
576 
577  if (m_videoOK && m_video.isOpened())
578  {
579  framesCount = m_video.get(CV_CAP_PROP_POS_FRAMES);;
580  } else {
581  framesCount = 0;
582  }
583 
584  if (getMessageQueueToGUI())
585  {
587  report = MsgReportVideoFileSourceStreamTiming::create(framesCount);
588  getMessageQueueToGUI()->push(report);
589  }
590 
591  return true;
592  }
593  else if (MsgConfigureCameraIndex::match(cmd))
594  {
596  uint32_t index = cfg.getIndex() & 0x7FFFFFF;
597 
598  if (index < m_cameras.size())
599  {
600  m_cameraIndex = index;
601 
602  if (getMessageQueueToGUI())
603  {
604  MsgReportCameraData *report;
606  m_cameras[m_cameraIndex].m_cameraNumber,
608  m_cameras[m_cameraIndex].m_videoFPSManual,
609  m_cameras[m_cameraIndex].m_videoFPSManualEnable,
612  0);
613  getMessageQueueToGUI()->push(report);
614  }
615  }
616 
617  return true;
618  }
619  else if (MsgConfigureCameraData::match(cmd))
620  {
622  uint32_t index = cfg.getIndex() & 0x7FFFFFF;
623  float mnaualFPS = cfg.getManualFPS();
624  bool manualFPSEnable = cfg.getManualFPSEnable();
625 
626  if (index < m_cameras.size())
627  {
628  m_cameras[index].m_videoFPSManual = mnaualFPS;
629  m_cameras[index].m_videoFPSManualEnable = manualFPSEnable;
630  }
631 
632  return true;
633  }
634  else if (DSPSignalNotification::match(cmd))
635  {
636  return true;
637  }
638  else
639  {
640  return false;
641  }
642 }
643 
644 void ATVMod::getBaseValues(int outputSampleRate, int linesPerSecond, int& sampleRateUnits, uint32_t& nbPointsPerRateUnit)
645 {
646  int maxPoints = outputSampleRate / linesPerSecond;
647  int i = maxPoints;
648 
649  for (; i > 0; i--)
650  {
651  if ((i * linesPerSecond) % 10 == 0)
652  break;
653  }
654 
655  nbPointsPerRateUnit = i == 0 ? maxPoints : i;
656  sampleRateUnits = nbPointsPerRateUnit * linesPerSecond;
657 }
658 
660 {
661  switch(modulation)
662  {
667  return 1.05f;
668  break;
671  default:
672  return 2.2f;
673  }
674 }
675 
677 {
678  m_pointsPerSync = (uint32_t) ((4.7f / 64.0f) * m_pointsPerLine);
679  m_pointsPerBP = (uint32_t) ((4.7f / 64.0f) * m_pointsPerLine);
680  m_pointsPerFP = (uint32_t) ((2.6f / 64.0f) * m_pointsPerLine);
681  m_pointsPerFSync = (uint32_t) ((2.3f / 64.0f) * m_pointsPerLine);
682 
685 
689 
691  m_nbLines2 = m_nbLines / 2;
692  m_fps = m_settings.m_fps * 1.0f;
693 
694 // qDebug() << "ATVMod::applyStandard: "
695 // << " m_nbLines: " << m_config.m_nbLines
696 // << " m_fps: " << m_config.m_fps
697 // << " rateUnits: " << rateUnits
698 // << " nbPointsPerRateUnit: " << nbPointsPerRateUnit
699 // << " m_tvSampleRate: " << m_tvSampleRate
700 // << " m_pointsPerTU: " << m_pointsPerTU;
701 
702  switch(m_settings.m_atvStd)
703  {
705  m_nbImageLines = m_nbLines; // lines less the total number of sync lines
706  m_nbImageLines2 = m_nbImageLines; // force non interleaved for vbars
707  m_interleaved = false;
708  m_nbSyncLinesHeadE = 0; // number of sync lines on the top of a frame even
709  m_nbSyncLinesHeadO = 0; // number of sync lines on the top of a frame odd
710  m_nbSyncLinesBottom = -1; // force no vsync in even block
711  m_nbLongSyncLines = 0;
712  m_nbHalfLongSync = 0;
713  m_nbWholeEqLines = 0;
714  m_singleLongSync = true;
715  m_nbBlankLines = 0;
716  m_blankLineLvel = 0.7f;
717  m_nbLines2 = m_nbLines - 1;
718  break;
720  m_nbImageLines = m_nbLines - 2; // lines less the total number of sync lines
721  m_nbImageLines2 = m_nbImageLines; // force non interleaved for vbars
722  m_interleaved = false;
723  m_nbSyncLinesHeadE = 1; // number of sync lines on the top of a frame even
724  m_nbSyncLinesHeadO = 1; // number of sync lines on the top of a frame odd
726  m_nbLongSyncLines = 1;
727  m_nbHalfLongSync = 0;
728  m_nbWholeEqLines = 0;
729  m_singleLongSync = true;
730  m_nbBlankLines = 1;
731  m_blankLineLvel = 0.7f;
732  m_nbLines2 = m_nbLines; // force non interleaved => treated as even for all lines
733  break;
735  m_nbImageLines = m_nbLines - 2; // lines less the total number of sync lines
737  m_interleaved = true;
738  m_nbSyncLinesHeadE = 1; // number of sync lines on the top of a frame even
739  m_nbSyncLinesHeadO = 1; // number of sync lines on the top of a frame odd
741  m_nbLongSyncLines = 1;
742  m_nbHalfLongSync = 0;
743  m_nbWholeEqLines = 0;
744  m_singleLongSync = true;
745  m_nbBlankLines = 1;
746  m_blankLineLvel = 0.7f;
747  break;
748  case ATVModSettings::ATVStd405: // Follows loosely the 405 lines standard
749  m_nbImageLines = m_nbLines - 15; // lines less the total number of sync lines
751  m_interleaved = true;
752  m_nbSyncLinesHeadE = 5; // number of sync lines on the top of a frame even
753  m_nbSyncLinesHeadO = 4; // number of sync lines on the top of a frame odd
755  m_nbLongSyncLines = 2;
756  m_nbHalfLongSync = 1;
757  m_nbWholeEqLines = 2;
758  m_singleLongSync = false;
759  m_nbBlankLines = 7; // yields 376 lines (195 - 7) * 2
761  break;
762  case ATVModSettings::ATVStdPAL525: // Follows PAL-M standard
763  m_nbImageLines = m_nbLines - 15;
765  m_interleaved = true;
766  m_nbSyncLinesHeadE = 5;
767  m_nbSyncLinesHeadO = 4; // number of sync lines on the top of a frame odd
769  m_nbLongSyncLines = 2;
770  m_nbHalfLongSync = 1;
771  m_nbWholeEqLines = 2;
772  m_singleLongSync = false;
773  m_nbBlankLines = 15; // yields 480 lines (255 - 15) * 2
775  break;
776  case ATVModSettings::ATVStdPAL625: // Follows PAL-B/G/H standard
777  default:
778  m_nbImageLines = m_nbLines - 15;
780  m_interleaved = true;
781  m_nbSyncLinesHeadE = 5;
782  m_nbSyncLinesHeadO = 4; // number of sync lines on the top of a frame odd
784  m_nbLongSyncLines = 2;
785  m_nbHalfLongSync = 1;
786  m_nbWholeEqLines = 2;
787  m_singleLongSync = false;
788  m_nbBlankLines = 17; // yields 576 lines (305 - 17) * 2
790  }
791 
793 
794  if (m_imageOK)
795  {
796  resizeImage();
797  }
798 
799  if (m_videoOK)
800  {
802  resizeVideo();
803  }
804 
806 }
807 
808 void ATVMod::openImage(const QString& fileName)
809 {
810  m_imageFromFile = cv::imread(qPrintable(fileName), CV_LOAD_IMAGE_GRAYSCALE);
811  m_imageOK = m_imageFromFile.data != 0;
812 
813  if (m_imageOK)
814  {
815  m_imageFileName = fileName;
817 
820  }
821 
822  resizeImage();
823  }
824  else
825  {
826  m_imageFileName.clear();
827  qDebug("ATVMod::openImage: cannot open image file %s", qPrintable(fileName));
828  }
829 }
830 
831 void ATVMod::openVideo(const QString& fileName)
832 {
833  //if (m_videoOK && m_video.isOpened()) m_video.release(); should be done by OpenCV in open method
834 
835  m_videoOK = m_video.open(qPrintable(fileName));
836 
837  if (m_videoOK)
838  {
839  m_videoFileName = fileName;
840  m_videoFPS = m_video.get(CV_CAP_PROP_FPS);
841  m_videoWidth = (int) m_video.get(CV_CAP_PROP_FRAME_WIDTH);
842  m_videoHeight = (int) m_video.get(CV_CAP_PROP_FRAME_HEIGHT);
843  m_videoLength = (int) m_video.get(CV_CAP_PROP_FRAME_COUNT);
844  int ex = static_cast<int>(m_video.get(CV_CAP_PROP_FOURCC));
845  char ext[] = {(char)(ex & 0XFF),(char)((ex & 0XFF00) >> 8),(char)((ex & 0XFF0000) >> 16),(char)((ex & 0XFF000000) >> 24),0};
846 
847  qDebug("ATVMod::openVideo: %s FPS: %f size: %d x %d #frames: %d codec: %s",
848  m_video.isOpened() ? "OK" : "KO",
849  m_videoFPS,
850  m_videoWidth,
853  ext);
854 
856  m_videoEOF = false;
857 
858  if (getMessageQueueToGUI())
859  {
862  getMessageQueueToGUI()->push(report);
863  }
864  }
865  else
866  {
867  m_videoFileName.clear();
868  qDebug("ATVMod::openVideo: cannot open video file %s", qPrintable(fileName));
869  }
870 }
871 
873 {
874  float fy = (m_nbImageLines - 2*m_nbBlankLines) / (float) m_imageOriginal.rows;
875  float fx = m_pointsPerImgLine / (float) m_imageOriginal.cols;
876  cv::resize(m_imageOriginal, m_image, cv::Size(), fx, fy);
877  qDebug("ATVMod::resizeImage: %d x %d -> %d x %d", m_imageOriginal.cols, m_imageOriginal.rows, m_image.cols, m_image.rows);
878 }
879 
881 {
887 
888  qDebug("ATVMod::calculateVideoSizes: factors: %f x %f FPSq: %f", m_videoFx, m_videoFy, m_videoFPSq);
889 }
890 
892 {
893  if (!m_videoframeOriginal.empty()) {
894  cv::resize(m_videoframeOriginal, m_videoFrame, cv::Size(), m_videoFx, m_videoFy); // resize current frame
895  }
896 }
897 
899 {
900  for (std::vector<ATVCamera>::iterator it = m_cameras.begin(); it != m_cameras.end(); ++it)
901  {
902  it->m_videoFy = (m_nbImageLines - 2*m_nbBlankLines) / (float) it->m_videoHeight;
903  it->m_videoFx = m_pointsPerImgLine / (float) it->m_videoWidth;
904  it->m_videoFPSq = it->m_videoFPS / m_fps;
905  it->m_videoFPSqManual = it->m_videoFPSManual / m_fps;
906  it->m_videoFPSCount = 0; //it->m_videoFPSq;
907  it->m_videoPrevFPSCount = 0;
908 
909  qDebug("ATVMod::calculateCamerasSizes: [%d] factors: %f x %f FPSq: %f", (int) (it - m_cameras.begin()), it->m_videoFx, it->m_videoFy, it->m_videoFPSq);
910  }
911 }
912 
914 {
915  for (std::vector<ATVCamera>::iterator it = m_cameras.begin(); it != m_cameras.end(); ++it)
916  {
917  if (!it->m_videoframeOriginal.empty()) {
918  cv::resize(it->m_videoframeOriginal, it->m_videoFrame, cv::Size(), it->m_videoFx, it->m_videoFy); // resize current frame
919  }
920  }
921 }
922 
924 {
925  ATVCamera& camera = m_cameras[m_cameraIndex];
926 
927  if (!camera.m_videoframeOriginal.empty()) {
928  cv::resize(camera.m_videoframeOriginal, camera.m_videoFrame, cv::Size(), camera.m_videoFx, camera.m_videoFy); // resize current frame
929  }
930 }
931 
932 void ATVMod::seekVideoFileStream(int seekPercentage)
933 {
934  QMutexLocker mutexLocker(&m_settingsMutex);
935 
936  if ((m_videoOK) && m_video.isOpened())
937  {
938  int seekPoint = ((m_videoLength * seekPercentage) / 100);
939  m_video.set(CV_CAP_PROP_POS_FRAMES, seekPoint);
942  m_videoEOF = false;
943  }
944 }
945 
947 {
948  for (int i = 0; i < 4; i++)
949  {
950  ATVCamera newCamera;
951  m_cameras.push_back(newCamera);
952  m_cameras.back().m_cameraNumber = i;
953  m_cameras.back().m_camera.open(i);
954 
955  if (m_cameras.back().m_camera.isOpened())
956  {
957  m_cameras.back().m_videoFPS = m_cameras.back().m_camera.get(CV_CAP_PROP_FPS);
958  m_cameras.back().m_videoWidth = (int) m_cameras.back().m_camera.get(CV_CAP_PROP_FRAME_WIDTH);
959  m_cameras.back().m_videoHeight = (int) m_cameras.back().m_camera.get(CV_CAP_PROP_FRAME_HEIGHT);
960 
961  //m_cameras.back().m_videoFPS = m_cameras.back().m_videoFPS < 0 ? 16.3f : m_cameras.back().m_videoFPS;
962 
963  qDebug("ATVMod::scanCameras: [%d] FPS: %f %dx%d",
964  i,
965  m_cameras.back().m_videoFPS,
966  m_cameras.back().m_videoWidth ,
967  m_cameras.back().m_videoHeight);
968  }
969  else
970  {
971  m_cameras.pop_back();
972  }
973  }
974 
975  if (m_cameras.size() > 0)
976  {
978  m_cameraIndex = 0;
979  }
980 }
981 
983 {
984  for (std::vector<ATVCamera>::iterator it = m_cameras.begin(); it != m_cameras.end(); ++it)
985  {
986  if (it->m_camera.isOpened()) it->m_camera.release();
987  }
988 }
989 
990 void ATVMod::getCameraNumbers(std::vector<int>& numbers)
991 {
992  for (std::vector<ATVCamera>::iterator it = m_cameras.begin(); it != m_cameras.end(); ++it) {
993  numbers.push_back(it->m_cameraNumber);
994  }
995 
996  if (m_cameras.size() > 0)
997  {
998  m_cameraIndex = 0;
999 
1000  if (getMessageQueueToGUI())
1001  {
1002  MsgReportCameraData *report;
1003  report = MsgReportCameraData::create(
1004  m_cameras[0].m_cameraNumber,
1005  m_cameras[0].m_videoFPS,
1006  m_cameras[0].m_videoFPSManual,
1007  m_cameras[0].m_videoFPSManualEnable,
1010  0);
1011  getMessageQueueToGUI()->push(report);
1012  }
1013  }
1014 }
1015 
1016 void ATVMod::mixImageAndText(cv::Mat& image)
1017 {
1018  int fontFace = cv::FONT_HERSHEY_PLAIN;
1019  double fontScale = image.rows / 100.0;
1020  int thickness = image.cols / 160;
1021  int baseline=0;
1022 
1023  fontScale = fontScale < 4.0f ? 4.0f : fontScale; // minimum size
1024  cv::Size textSize = cv::getTextSize(m_settings.m_overlayText.toStdString(), fontFace, fontScale, thickness, &baseline);
1025  baseline += thickness;
1026 
1027  // position the text in the top left corner
1028  cv::Point textOrg(6, textSize.height+10);
1029  // then put the text itself
1030  cv::putText(image, m_settings.m_overlayText.toStdString(), textOrg, fontFace, fontScale, cv::Scalar::all(255*m_settings.m_uniformLevel), thickness, CV_AA);
1031 }
1032 
1033 void ATVMod::applyChannelSettings(int outputSampleRate, int inputFrequencyOffset, bool force)
1034 {
1035  qDebug() << "AMMod::applyChannelSettings:"
1036  << " outputSampleRate: " << outputSampleRate
1037  << " inputFrequencyOffset: " << inputFrequencyOffset;
1038 
1039  if ((inputFrequencyOffset != m_inputFrequencyOffset) ||
1040  (outputSampleRate != m_outputSampleRate) || force)
1041  {
1042  m_settingsMutex.lock();
1043  m_carrierNco.setFreq(inputFrequencyOffset, outputSampleRate);
1044  m_settingsMutex.unlock();
1045  }
1046 
1047  if ((outputSampleRate != m_outputSampleRate) || force)
1048  {
1050 
1051  m_settingsMutex.lock();
1052 
1053  if (m_tvSampleRate > 0)
1054  {
1056  m_interpolatorDistance = (Real) m_tvSampleRate / (Real) outputSampleRate;
1060  3.0);
1061  }
1062  else
1063  {
1064  m_tvSampleRate = outputSampleRate;
1065  }
1066 
1068  memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
1070 
1071  applyStandard(); // set all timings
1072  m_settingsMutex.unlock();
1073 
1074  if (getMessageQueueToGUI())
1075  {
1078  getMessageQueueToGUI()->push(report);
1079  }
1080  }
1081 
1082  m_outputSampleRate = outputSampleRate;
1083  m_inputFrequencyOffset = inputFrequencyOffset;
1084 }
1085 
1086 void ATVMod::applySettings(const ATVModSettings& settings, bool force)
1087 {
1088  qDebug() << "ATVMod::applySettings:"
1089  << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
1090  << " m_rfBandwidth: " << settings.m_rfBandwidth
1091  << " m_rfOppBandwidth: " << settings.m_rfOppBandwidth
1092  << " m_atvStd: " << (int) settings.m_atvStd
1093  << " m_nbLines: " << settings.m_nbLines
1094  << " m_fps: " << settings.m_fps
1095  << " m_atvModInput: " << (int) settings.m_atvModInput
1096  << " m_uniformLevel: " << settings.m_uniformLevel
1097  << " m_atvModulation: " << (int) settings.m_atvModulation
1098  << " m_videoPlayLoop: " << settings.m_videoPlayLoop
1099  << " m_videoPlay: " << settings.m_videoPlay
1100  << " m_cameraPlay: " << settings.m_cameraPlay
1101  << " m_channelMute: " << settings.m_channelMute
1102  << " m_invertedVideo: " << settings.m_invertedVideo
1103  << " m_rfScalingFactor: " << settings.m_rfScalingFactor
1104  << " m_fmExcursion: " << settings.m_fmExcursion
1105  << " m_forceDecimator: " << settings.m_forceDecimator
1106  << " m_showOverlayText: " << settings.m_showOverlayText
1107  << " m_overlayText: " << settings.m_overlayText
1108  << " force: " << force;
1109 
1110  QList<QString> reverseAPIKeys;
1111 
1112  if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) {
1113  reverseAPIKeys.append("inputFrequencyOffset");
1114  }
1115  if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) {
1116  reverseAPIKeys.append("rfBandwidth");
1117  }
1118  if ((settings.m_rfOppBandwidth != m_settings.m_rfOppBandwidth) || force) {
1119  reverseAPIKeys.append("rfOppBandwidth");
1120  }
1121  if ((settings.m_atvStd != m_settings.m_atvStd) || force) {
1122  reverseAPIKeys.append("atvStd");
1123  }
1124  if ((settings.m_nbLines != m_settings.m_nbLines) || force) {
1125  reverseAPIKeys.append("nbLines");
1126  }
1127  if ((settings.m_fps != m_settings.m_fps) || force) {
1128  reverseAPIKeys.append("fps");
1129  }
1130  if ((settings.m_atvModInput != m_settings.m_atvModInput) || force) {
1131  reverseAPIKeys.append("atvModInput");
1132  }
1133  if ((settings.m_uniformLevel != m_settings.m_uniformLevel) || force) {
1134  reverseAPIKeys.append("uniformLevel");
1135  }
1136  if ((settings.m_uniformLevel != m_settings.m_uniformLevel) || force) {
1137  reverseAPIKeys.append("uniformLevel");
1138  }
1139  if ((settings.m_atvModulation != m_settings.m_atvModulation) || force) {
1140  reverseAPIKeys.append("atvModulation");
1141  }
1142  if ((settings.m_videoPlayLoop != m_settings.m_videoPlayLoop) || force) {
1143  reverseAPIKeys.append("videoPlayLoop");
1144  }
1145  if ((settings.m_videoPlay != m_settings.m_videoPlay) || force) {
1146  reverseAPIKeys.append("videoPlay");
1147  }
1148  if ((settings.m_cameraPlay != m_settings.m_cameraPlay) || force) {
1149  reverseAPIKeys.append("cameraPlay");
1150  }
1151  if ((settings.m_channelMute != m_settings.m_channelMute) || force) {
1152  reverseAPIKeys.append("channelMute");
1153  }
1154  if ((settings.m_invertedVideo != m_settings.m_invertedVideo) || force) {
1155  reverseAPIKeys.append("invertedVideo");
1156  }
1157  if ((settings.m_rfScalingFactor != m_settings.m_rfScalingFactor) || force) {
1158  reverseAPIKeys.append("rfScalingFactor");
1159  }
1160  if ((settings.m_fmExcursion != m_settings.m_fmExcursion) || force) {
1161  reverseAPIKeys.append("fmExcursion");
1162  }
1163  if ((settings.m_forceDecimator != m_settings.m_forceDecimator) || force) {
1164  reverseAPIKeys.append("forceDecimator");
1165  }
1166  if ((settings.m_showOverlayText != m_settings.m_showOverlayText) || force) {
1167  reverseAPIKeys.append("showOverlayText");
1168  }
1169  if ((settings.m_overlayText != m_settings.m_overlayText) || force) {
1170  reverseAPIKeys.append("overlayText");
1171  }
1172 
1173  if ((settings.m_atvStd != m_settings.m_atvStd)
1174  || (settings.m_nbLines != m_settings.m_nbLines)
1175  || (settings.m_fps != m_settings.m_fps)
1176  || (settings.m_rfBandwidth != m_settings.m_rfBandwidth)
1177  || (settings.m_atvModulation != m_settings.m_atvModulation) || force)
1178  {
1180 
1181  m_settingsMutex.lock();
1182 
1183  if (m_tvSampleRate > 0)
1184  {
1190  3.0);
1191  }
1192 
1194  memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
1196 
1197  applyStandard(); // set all timings
1198  m_settingsMutex.unlock();
1199 
1200  if (getMessageQueueToGUI())
1201  {
1204  getMessageQueueToGUI()->push(report);
1205  }
1206  }
1207 
1208  if ((settings.m_rfOppBandwidth != m_settings.m_rfOppBandwidth)
1209  || (settings.m_rfBandwidth != m_settings.m_rfBandwidth)
1210  || (settings.m_nbLines != m_settings.m_nbLines) // difference in line period may have changed TV sample rate
1211  || (settings.m_fps != m_settings.m_fps) //
1212  || force)
1213  {
1214  m_settingsMutex.lock();
1215 
1217  memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
1219 
1220  m_settingsMutex.unlock();
1221  }
1222 
1223  if ((settings.m_showOverlayText != m_settings.m_showOverlayText) || force)
1224  {
1225  if (!m_imageFromFile.empty())
1226  {
1228 
1229  if (settings.m_showOverlayText) {
1230  qDebug("ATVMod::applySettings: set overlay text");
1232  } else{
1233  qDebug("ATVMod::applySettings: clear overlay text");
1234  }
1235 
1236  resizeImage();
1237  }
1238  }
1239 
1240  if (settings.m_useReverseAPI)
1241  {
1242  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
1247  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
1248  }
1249 
1250  m_settings = settings;
1251 }
1252 
1253 QByteArray ATVMod::serialize() const
1254 {
1255  return m_settings.serialize();
1256 }
1257 
1258 bool ATVMod::deserialize(const QByteArray& data)
1259 {
1260  if (m_settings.deserialize(data))
1261  {
1264  return true;
1265  }
1266  else
1267  {
1271  return false;
1272  }
1273 }
1274 
1277  QString& errorMessage)
1278 {
1279  (void) errorMessage;
1281  response.getAtvModSettings()->init();
1283  return 200;
1284 }
1285 
1287  bool force,
1288  const QStringList& channelSettingsKeys,
1290  QString& errorMessage)
1291 {
1292  (void) errorMessage;
1293  ATVModSettings settings = m_settings;
1294  bool frequencyOffsetChanged = false;
1295 
1296  if (channelSettingsKeys.contains("inputFrequencyOffset"))
1297  {
1299  frequencyOffsetChanged = true;
1300  }
1301  if (channelSettingsKeys.contains("rfBandwidth")) {
1302  settings.m_rfBandwidth = response.getAtvModSettings()->getRfBandwidth();
1303  }
1304  if (channelSettingsKeys.contains("rfOppBandwidth")) {
1305  settings.m_rfOppBandwidth = response.getAtvModSettings()->getRfOppBandwidth();
1306  }
1307  if (channelSettingsKeys.contains("atvStd")) {
1308  settings.m_atvStd = (ATVModSettings::ATVStd) response.getAtvModSettings()->getAtvStd();
1309  }
1310  if (channelSettingsKeys.contains("nbLines")) {
1311  settings.m_nbLines = response.getAtvModSettings()->getNbLines();
1312  }
1313  if (channelSettingsKeys.contains("fps")) {
1314  settings.m_fps = response.getAtvModSettings()->getFps();
1315  }
1316  if (channelSettingsKeys.contains("atvModInput")) {
1318  }
1319  if (channelSettingsKeys.contains("uniformLevel")) {
1320  settings.m_uniformLevel = response.getAtvModSettings()->getUniformLevel();
1321  }
1322  if (channelSettingsKeys.contains("atvModulation")) {
1324  }
1325  if (channelSettingsKeys.contains("videoPlayLoop")) {
1326  settings.m_videoPlayLoop = response.getAtvModSettings()->getVideoPlayLoop() != 0;
1327  }
1328  if (channelSettingsKeys.contains("videoPlay")) {
1329  settings.m_videoPlay = response.getAtvModSettings()->getVideoPlay() != 0;
1330  }
1331  if (channelSettingsKeys.contains("cameraPlay")) {
1332  settings.m_cameraPlay = response.getAtvModSettings()->getCameraPlay() != 0;
1333  }
1334  if (channelSettingsKeys.contains("channelMute")) {
1335  settings.m_channelMute = response.getAtvModSettings()->getChannelMute() != 0;
1336  }
1337  if (channelSettingsKeys.contains("invertedVideo")) {
1338  settings.m_invertedVideo = response.getAtvModSettings()->getInvertedVideo() != 0;
1339  }
1340  if (channelSettingsKeys.contains("rfScalingFactor")) {
1341  settings.m_rfScalingFactor = response.getAtvModSettings()->getRfScalingFactor();
1342  }
1343  if (channelSettingsKeys.contains("fmExcursion")) {
1344  settings.m_fmExcursion = response.getAtvModSettings()->getFmExcursion();
1345  }
1346  if (channelSettingsKeys.contains("forceDecimator")) {
1347  settings.m_forceDecimator = response.getAtvModSettings()->getForceDecimator() != 0;
1348  }
1349  if (channelSettingsKeys.contains("showOverlayText")) {
1350  settings.m_showOverlayText = response.getAtvModSettings()->getShowOverlayText() != 0;
1351  }
1352  if (channelSettingsKeys.contains("overlayText")) {
1353  settings.m_overlayText = *response.getAtvModSettings()->getOverlayText();
1354  }
1355  if (channelSettingsKeys.contains("rgbColor")) {
1356  settings.m_rgbColor = response.getAtvModSettings()->getRgbColor();
1357  }
1358  if (channelSettingsKeys.contains("title")) {
1359  settings.m_title = *response.getAtvModSettings()->getTitle();
1360  }
1361  if (channelSettingsKeys.contains("useReverseAPI")) {
1362  settings.m_useReverseAPI = response.getAtvModSettings()->getUseReverseApi() != 0;
1363  }
1364  if (channelSettingsKeys.contains("reverseAPIAddress")) {
1366  }
1367  if (channelSettingsKeys.contains("reverseAPIPort")) {
1368  settings.m_reverseAPIPort = response.getAtvModSettings()->getReverseApiPort();
1369  }
1370  if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
1372  }
1373  if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
1375  }
1376  if (frequencyOffsetChanged)
1377  {
1379  settings.m_inputFrequencyOffset);
1380  m_inputMessageQueue.push(msgChan);
1381  }
1382 
1383  MsgConfigureATVMod *msg = MsgConfigureATVMod::create(settings, force);
1385 
1386  if (m_guiMessageQueue) // forward to GUI if any
1387  {
1388  MsgConfigureATVMod *msgToGUI = MsgConfigureATVMod::create(settings, force);
1389  m_guiMessageQueue->push(msgToGUI);
1390  }
1391 
1392  if (channelSettingsKeys.contains("imageFileName"))
1393  {
1395  *response.getAtvModSettings()->getImageFileName());
1397 
1398  if (m_guiMessageQueue) // forward to GUI if any
1399  {
1401  *response.getAtvModSettings()->getImageFileName());
1402  m_guiMessageQueue->push(msgToGUI);
1403  }
1404  }
1405 
1406  if (channelSettingsKeys.contains("videoFileName"))
1407  {
1409  *response.getAtvModSettings()->getVideoFileName());
1411 
1412  if (m_guiMessageQueue) // forward to GUI if any
1413  {
1415  *response.getAtvModSettings()->getVideoFileName());
1416  m_guiMessageQueue->push(msgToGUI);
1417  }
1418  }
1419 
1420  webapiFormatChannelSettings(response, settings);
1421 
1422  return 200;
1423 }
1424 
1427  QString& errorMessage)
1428 {
1429  (void) errorMessage;
1431  response.getAtvModReport()->init();
1432  webapiFormatChannelReport(response);
1433  return 200;
1434 }
1435 
1437 {
1439  response.getAtvModSettings()->setRfBandwidth(settings.m_rfBandwidth);
1441  response.getAtvModSettings()->setAtvStd(settings.m_atvStd);
1442  response.getAtvModSettings()->setNbLines(settings.m_nbLines);
1443  response.getAtvModSettings()->setFps(settings.m_fps);
1444  response.getAtvModSettings()->setAtvModInput(settings.m_atvModInput);
1445  response.getAtvModSettings()->setUniformLevel(settings.m_uniformLevel);
1446  response.getAtvModSettings()->setAtvModulation(settings.m_atvModulation);
1447  response.getAtvModSettings()->setVideoPlayLoop(settings.m_videoPlayLoop ? 1 : 0);
1448  response.getAtvModSettings()->setVideoPlay(settings.m_videoPlay ? 1 : 0);
1449  response.getAtvModSettings()->setCameraPlay(settings.m_cameraPlay ? 1 : 0);
1450  response.getAtvModSettings()->setChannelMute(settings.m_channelMute ? 1 : 0);
1451  response.getAtvModSettings()->setInvertedVideo(settings.m_invertedVideo ? 1 : 0);
1453  response.getAtvModSettings()->setFmExcursion(settings.m_fmExcursion);
1454  response.getAtvModSettings()->setForceDecimator(settings.m_forceDecimator ? 1 : 0);
1455  response.getAtvModSettings()->setShowOverlayText(settings.m_showOverlayText ? 1 : 0);
1456 
1457  if (response.getAtvModSettings()->getOverlayText()) {
1458  *response.getAtvModSettings()->getOverlayText() = settings.m_overlayText;
1459  } else {
1460  response.getAtvModSettings()->setOverlayText(new QString(settings.m_overlayText));
1461  }
1462 
1463  response.getAtvModSettings()->setRgbColor(settings.m_rgbColor);
1464 
1465  if (response.getAtvModSettings()->getTitle()) {
1466  *response.getAtvModSettings()->getTitle() = settings.m_title;
1467  } else {
1468  response.getAtvModSettings()->setTitle(new QString(settings.m_title));
1469  }
1470 
1471  if (response.getAtvModSettings()->getImageFileName()) {
1473  } else {
1474  response.getAtvModSettings()->setImageFileName(new QString(m_imageFileName));
1475  }
1476 
1477  if (response.getAtvModSettings()->getVideoFileName()) {
1479  } else {
1480  response.getAtvModSettings()->setVideoFileName(new QString(m_videoFileName));
1481  }
1482 
1483  response.getAtvModSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
1484 
1485  if (response.getAtvModSettings()->getReverseApiAddress()) {
1487  } else {
1488  response.getAtvModSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
1489  }
1490 
1494 }
1495 
1497 {
1500 }
1501 
1502 void ATVMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const ATVModSettings& settings, bool force)
1503 {
1505  swgChannelSettings->setDirection(1); // single source (Tx)
1506  swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
1507  swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
1508  swgChannelSettings->setChannelType(new QString("ATVMod"));
1509  swgChannelSettings->setAtvModSettings(new SWGSDRangel::SWGATVModSettings());
1510  SWGSDRangel::SWGATVModSettings *swgATVModSettings = swgChannelSettings->getAtvModSettings();
1511 
1512  // transfer data that has been modified. When force is on transfer all data except reverse API data
1513 
1514  if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
1515  swgATVModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
1516  }
1517  if (channelSettingsKeys.contains("rfBandwidth") || force) {
1518  swgATVModSettings->setRfBandwidth(settings.m_rfBandwidth);
1519  }
1520  if (channelSettingsKeys.contains("rfOppBandwidth") || force) {
1521  swgATVModSettings->setRfOppBandwidth(settings.m_rfOppBandwidth);
1522  }
1523  if (channelSettingsKeys.contains("atvStd") || force) {
1524  swgATVModSettings->setAtvStd((int) settings.m_atvStd);
1525  }
1526  if (channelSettingsKeys.contains("nbLines") || force) {
1527  swgATVModSettings->setNbLines(settings.m_nbLines);
1528  }
1529  if (channelSettingsKeys.contains("fps") || force) {
1530  swgATVModSettings->setFps(settings.m_fps);
1531  }
1532  if (channelSettingsKeys.contains("atvModInput") || force) {
1533  swgATVModSettings->setAtvModInput((int) settings.m_atvModInput);
1534  }
1535  if (channelSettingsKeys.contains("uniformLevel") || force) {
1536  swgATVModSettings->setUniformLevel(settings.m_uniformLevel);
1537  }
1538  if (channelSettingsKeys.contains("atvModulation") || force) {
1539  swgATVModSettings->setAtvModulation((int) settings.m_atvModulation);
1540  }
1541  if (channelSettingsKeys.contains("videoPlayLoop") || force) {
1542  swgATVModSettings->setVideoPlayLoop(settings.m_videoPlayLoop ? 1 : 0);
1543  }
1544  if (channelSettingsKeys.contains("videoPlay") || force) {
1545  swgATVModSettings->setVideoPlay(settings.m_videoPlay ? 1 : 0);
1546  }
1547  if (channelSettingsKeys.contains("cameraPlay") || force) {
1548  swgATVModSettings->setCameraPlay(settings.m_cameraPlay ? 1 : 0);
1549  }
1550  if (channelSettingsKeys.contains("channelMute") || force) {
1551  swgATVModSettings->setChannelMute(settings.m_channelMute ? 1 : 0);
1552  }
1553  if (channelSettingsKeys.contains("invertedVideo") || force) {
1554  swgATVModSettings->setInvertedVideo(settings.m_invertedVideo ? 1 : 0);
1555  }
1556  if (channelSettingsKeys.contains("rfScalingFactor") || force) {
1557  swgATVModSettings->setRfScalingFactor(settings.m_rfScalingFactor);
1558  }
1559  if (channelSettingsKeys.contains("fmExcursion") || force) {
1560  swgATVModSettings->setFmExcursion(settings.m_fmExcursion);
1561  }
1562  if (channelSettingsKeys.contains("forceDecimator") || force) {
1563  swgATVModSettings->setForceDecimator(settings.m_forceDecimator ? 1 : 0);
1564  }
1565  if (channelSettingsKeys.contains("showOverlayText") || force) {
1566  swgATVModSettings->setShowOverlayText(settings.m_showOverlayText ? 1 : 0);
1567  }
1568  if (channelSettingsKeys.contains("overlayText") || force) {
1569  swgATVModSettings->setOverlayText(new QString(settings.m_overlayText));
1570  }
1571  if (channelSettingsKeys.contains("rgbColor") || force) {
1572  swgATVModSettings->setRgbColor(settings.m_rgbColor);
1573  }
1574  if (channelSettingsKeys.contains("title") || force) {
1575  swgATVModSettings->setTitle(new QString(settings.m_title));
1576  }
1577 
1578  QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1579  .arg(settings.m_reverseAPIAddress)
1580  .arg(settings.m_reverseAPIPort)
1581  .arg(settings.m_reverseAPIDeviceIndex)
1582  .arg(settings.m_reverseAPIChannelIndex);
1583  m_networkRequest.setUrl(QUrl(channelSettingsURL));
1584  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
1585 
1586  QBuffer *buffer=new QBuffer();
1587  buffer->open((QBuffer::ReadWrite));
1588  buffer->write(swgChannelSettings->asJson().toUtf8());
1589  buffer->seek(0);
1590 
1591  // Always use PATCH to avoid passing reverse API settings
1592  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
1593 
1594  delete swgChannelSettings;
1595 }
1596 
1597 void ATVMod::networkManagerFinished(QNetworkReply *reply)
1598 {
1599  QNetworkReply::NetworkError replyError = reply->error();
1600 
1601  if (replyError)
1602  {
1603  qWarning() << "ATVMod::networkManagerFinished:"
1604  << " error(" << (int) replyError
1605  << "): " << replyError
1606  << ": " << reply->errorString();
1607  return;
1608  }
1609 
1610  QString answer = reply->readAll();
1611  answer.chop(1); // remove last \n
1612  qDebug("ATVMod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
1613 }
uint32_t m_pointsPerFP
number of line points for the front porch
Definition: atvmod.h:475
void setOriginatorChannelIndex(qint32 originator_channel_index)
float m_videoFPSCount
camera FPS fractional counter
Definition: atvmod.h:437
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
Definition: atvmod.cpp:1286
float m_videoFPSqManual
camera FPS sacaling factor manually set
Definition: atvmod.h:436
static const QString m_channelIdURI
Definition: atvmod.h:406
uint32_t m_pointsPerLine
Number of points per full line.
Definition: atvmod.h:471
float m_rfScalingFactor
Scaling factor from +/-1 to +/-2^15.
static MsgConfigureVideoFileName * create(const QString &fileName)
Definition: atvmod.h:124
void setUseReverseApi(qint32 use_reverse_api)
cv::Mat m_videoFrame
displayable camera frame
Definition: atvmod.h:426
void setInvertedVideo(qint32 inverted_video)
float m_videoFPSq
camera FPS sacaling factor
Definition: atvmod.h:435
DeviceAPI * m_deviceAPI
Definition: atvmod.h:456
std::vector< ATVCamera > m_cameras
vector of available cameras
Definition: atvmod.h:528
bool m_evenImage
in interlaced mode true if this is an even image
Definition: atvmod.h:497
Complex nextIQ()
Return next complex sample.
Definition: nco.cpp:61
bool decimate(Real *distance, const Complex &next, Complex *result)
Definition: interpolator.h:38
ATVMod(DeviceAPI *deviceAPI)
Definition: atvmod.cpp:61
void setCameraPlay(qint32 camera_play)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
static MsgReportCameraData * create(int deviceNumber, float fps, float fpsManual, bool fpsManualEnable, int width, int height, int status)
Definition: atvmod.h:285
ATVModulation m_atvModulation
RF modulation type.
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2271
uint16_t m_reverseAPIDeviceIndex
int m_pointsPerSync
number of line points for the horizontal sync
Definition: atvmod.h:472
void removeChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:181
int m_nbLines
number of lines per complete frame
Definition: atvmod.h:480
static double dbPower(double magsq, double floor=1e-12)
Definition: db.cpp:22
~ATVMod()
Definition: atvmod.cpp:113
int m_DSBFilterBufferIndex
Definition: atvmod.h:543
float m_videoFPS
current video FPS rate
Definition: atvmod.h:516
void resizeCameras()
Definition: atvmod.cpp:913
int m_nbLines
Number of lines per full frame.
bool m_videoFPSManualEnable
Enable camera FPS rate manual set value.
Definition: atvmod.h:430
QString m_videoFileName
Definition: atvmod.h:533
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
void pullFinalize(Complex &ci, Sample &sample)
Definition: atvmod.cpp:180
static MsgReportVideoFileSourceStreamData * create(int frameRate, quint32 recordLength)
Definition: atvmod.h:204
int m_cameraIndex
curent camera index in list of available cameras
Definition: atvmod.h:529
bool interpolate(Real *distance, const Complex &next, Complex *result)
Definition: interpolator.h:53
void setAtvModInput(qint32 atv_mod_input)
uint32_t m_linesPerVBar
number of lines for a bar of the bar chart
Definition: atvmod.h:478
float m_videoFy
current video vertictal scaling factor
Definition: atvmod.h:520
void setOverlayText(QString *overlay_text)
int getDeviceSetIndex() const
Definition: channelapi.h:89
Complex & modulateVestigialSSB(Real &sample)
Definition: atvmod.cpp:248
static MsgConfigureImageFileName * create(const QString &fileName)
Definition: atvmod.h:103
const ATVModSettings & getSettings() const
Definition: atvmod.h:57
QByteArray serialize() const
void setChannelSampleRate(qint32 channel_sample_rate)
void setReverseApiAddress(QString *reverse_api_address)
void removeChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Remove a channel source (Tx)
Definition: deviceapi.cpp:147
void setFmExcursion(float fm_excursion)
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
Definition: atvmod.cpp:1425
int m_nbWholeEqLines
number of whole equalizing lines
Definition: atvmod.h:490
void setUniformLevel(float uniform_level)
int m_videoLength
current video length in frames
Definition: atvmod.h:524
void setVideoPlay(qint32 video_play)
float m_hBarIncrement
video level increment at each horizontal bar increment
Definition: atvmod.h:494
int m_videoPrevFPSCount
current video FPS previous integer counter
Definition: atvmod.h:523
static const int m_cameraFPSTestNbFrames
number of frames for camera FPS test
Definition: atvmod.h:553
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
void setShowOverlayText(qint32 show_overlay_text)
fftfilt * m_SSBFilter
Definition: atvmod.h:536
void setForceDecimator(qint32 force_decimator)
static const QString m_channelId
Definition: atvmod.h:407
quint32 m_rgbColor
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
void setVideoFileName(QString *video_file_name)
void resizeVideo()
Definition: atvmod.cpp:891
int m_pointsPerFSync
number of line points for the field first sync
Definition: atvmod.h:476
float m_videoFx
camera horizontal scaling factor
Definition: atvmod.h:433
void setRfOppBandwidth(float rf_opp_bandwidth)
int m_nbSyncLinesHeadO
number of header sync lines on odd frame
Definition: atvmod.h:486
void setRfBandwidth(float rf_bandwidth)
int getOutputSampleRate() const
Definition: upchannelizer.h:89
int getCenterFrequency() const
Definition: atvmod.h:80
static const int m_ssbFftLen
Definition: atvmod.h:548
#define M_PI
Definition: rdsdemod.cpp:27
void modulateSample()
Definition: atvmod.cpp:194
void setChannelType(QString *channel_type)
void addChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Add a channel source (Tx)
Definition: deviceapi.cpp:138
qint64 m_inputFrequencyOffset
offset from baseband center frequency
int m_nbSyncLinesBottom
number of sync lines at bottom
Definition: atvmod.h:487
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
void openImage(const QString &fileName)
Definition: atvmod.cpp:808
int m_cameraNumber
camera device number
Definition: atvmod.h:427
float m_videoFx
current video horizontal scaling factor
Definition: atvmod.h:519
std::complex< float > cmplx
Definition: fftfilt.h:21
int m_nbHorizPoints
number of line points per horizontal line
Definition: atvmod.h:484
unsigned int uint32_t
Definition: rtptypes_win.h:46
static const int m_nbBars
number of bars in bar or chessboard patterns
Definition: atvmod.h:552
QString m_overlayText
void applySettings(const ATVModSettings &settings, bool force=false)
Definition: atvmod.cpp:1086
virtual QByteArray serialize() const
Definition: atvmod.cpp:1253
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
Definition: atvmod.cpp:520
float m_modPhasor
For FM modulation.
Definition: atvmod.h:466
QMutex m_settingsMutex
Definition: atvmod.h:498
const QString & getFileName() const
Definition: atvmod.h:122
bool m_channelMute
Mute channel baseband output.
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples)
QNetworkAccessManager * m_networkManager
Definition: atvmod.h:545
bool m_forceDecimator
Forces decimator even when channel and source sample rates are equal.
void calculateCamerasSizes()
Definition: atvmod.cpp:898
void openVideo(const QString &fileName)
Definition: atvmod.cpp:831
virtual void pullAudio(int nbSamples)
Definition: atvmod.cpp:133
UpChannelizer * m_channelizer
Definition: atvmod.h:458
void setImageFileName(QString *image_file_name)
int m_videoHeight
camera frame height
Definition: atvmod.h:432
ThreadedBasebandSampleSource * m_threadedChannelizer
Definition: atvmod.h:457
uint32_t m_nbImageLines2
same number as above (non interlaced) or half the number above (interlaced)
Definition: atvmod.h:483
void setAtvModReport(SWGATVModReport *atv_mod_report)
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
void setVideoPlayLoop(qint32 video_play_loop)
void create_filter(float f1, float f2)
Definition: fftfilt.cpp:107
static MsgReportVideoFileSourceStreamTiming * create(int frameCount)
Definition: atvmod.h:183
float m_videoFy
camera vertictal scaling factor
Definition: atvmod.h:434
cv::Mat m_imageOriginal
original not resized image
Definition: atvmod.h:509
void pullVSyncLine(Real &sample)
Definition: atvmod.h:767
Complex * m_SSBFilterBuffer
Definition: atvmod.h:537
cv::VideoCapture m_video
current video capture
Definition: atvmod.h:513
float m_videoFPS
camera FPS rate
Definition: atvmod.h:428
FixReal m_real
Definition: dsptypes.h:64
float m_vBarIncrement
video level increment at each vertical bar increment
Definition: atvmod.h:495
QNetworkRequest m_networkRequest
Definition: atvmod.h:546
void resizeImage()
Definition: atvmod.cpp:872
void getCameraNumbers(std::vector< int > &numbers)
Definition: atvmod.cpp:990
int m_videoHeight
current video frame height
Definition: atvmod.h:518
void pullImageLine(Real &sample, bool noHSync=false)
Definition: atvmod.h:581
int m_fps
Number of frames per second.
uint16_t m_reverseAPIChannelIndex
ATVModSettings m_settings
Definition: atvmod.h:462
uint32_t m_pointsPerHBar
number of line points for a bar of the bar chart
Definition: atvmod.h:477
Fixed< IntType, IntBits > sin(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2265
SWGATVModSettings * getAtvModSettings()
void setRgbColor(qint32 rgb_color)
int32_t i
Definition: decimators.h:244
QString m_reverseAPIAddress
static bool match(const Message *message)
Definition: message.cpp:45
int m_SSBFilterBufferIndex
Definition: atvmod.h:538
int m_nbHalfLongSync
number of half long sync / equalization lines
Definition: atvmod.h:489
int m_tvSampleRate
sample rate for generating signal
Definition: atvmod.h:470
void setFreq(Real freq, Real sampleRate)
Definition: nco.cpp:49
static float getRFBandwidthDivisor(ATVModSettings::ATVModulation modulation)
Definition: atvmod.cpp:659
Real m_interpolatorDistanceRemain
Definition: atvmod.h:469
int m_videoPrevFPSCount
camera FPS previous integer counter
Definition: atvmod.h:438
MovingAverageUtil< double, double, 16 > m_movingAverage
Definition: atvmod.h:503
cv::Mat m_videoFrame
current displayable video frame
Definition: atvmod.h:515
void setInputFrequencyOffset(qint64 input_frequency_offset)
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
Definition: atvmod.cpp:1496
cv::Mat m_imageFromFile
original image not resized not overlaid by text
Definition: atvmod.h:508
float m_fmExcursion
FM excursion factor relative to full bandwidth.
bool m_showOverlayText
Show overlay text on image.
bool m_invertedVideo
True if video signal is inverted before modulation.
Fixed< IntType, IntBits > sqrt(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2283
void networkManagerFinished(QNetworkReply *reply)
Definition: atvmod.cpp:1597
bool m_imageOK
Definition: atvmod.h:511
void setChannelMute(qint32 channel_mute)
cv::Mat m_videoframeOriginal
camera non resized image
Definition: atvmod.h:425
Real m_interpolatorDistance
Definition: atvmod.h:468
NCO m_carrierNco
Definition: atvmod.h:464
virtual void stop()
Definition: atvmod.cpp:516
ATVStd m_atvStd
Standard.
Real m_peakLevel
Definition: atvmod.h:505
virtual QString asJson() override
void setAtvModulation(qint32 atv_modulation)
static MsgConfigureATVMod * create(const ATVModSettings &settings, bool force)
Definition: atvmod.h:60
virtual void start()
Definition: atvmod.cpp:509
ATVModInput m_atvModInput
Input source type.
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
Definition: atvmod.cpp:1275
cv::Mat m_videoframeOriginal
current frame from video
Definition: atvmod.h:514
int m_pointsPerImgLine
number of line points for the image line
Definition: atvmod.h:474
float m_videoFPSCount
current video FPS fractional counter
Definition: atvmod.h:522
int m_nbBlankLines
number of lines in a frame (full or half) that are blanked (black) at the top of the image ...
Definition: atvmod.h:492
static const int m_levelNbSamples
Definition: atvmod.h:551
cv::VideoCapture m_camera
camera object
Definition: atvmod.h:424
bool m_videoEOF
current video has reached end of file
Definition: atvmod.h:525
QString m_imageFileName
Definition: atvmod.h:532
int m_videoWidth
current video frame width
Definition: atvmod.h:517
bool m_videoPlay
True to play video and false to pause.
Interpolator m_interpolator
Definition: atvmod.h:467
SWGATVModReport * getAtvModReport()
Real m_levelSum
Definition: atvmod.h:506
void applyStandard()
Definition: atvmod.cpp:676
bool m_videoOK
Definition: atvmod.h:526
void scanCameras()
Definition: atvmod.cpp:946
uint32_t m_nbImageLines
number of image lines excluding synchronization lines
Definition: atvmod.h:482
bool m_cameraPlay
True to play camera video and false to pause.
MessageQueue * getMessageQueueToGUI()
bool m_interleaved
true if image is interlaced (2 half frames per frame)
Definition: atvmod.h:496
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
void releaseCameras()
Definition: atvmod.cpp:982
Real m_uniformLevel
Percentage between black and white for uniform screen display.
static MsgReportEffectiveSampleRate * create(int sampleRate, uint32_t nbPointsPerLine)
Definition: atvmod.h:340
void setRfScalingFactor(float rf_scaling_factor)
int m_horizontalCount
current point index on line
Definition: atvmod.h:499
float m_videoFPSManual
camera FPS rate manually set
Definition: atvmod.h:429
int runSSB(const cmplx &in, cmplx **out, bool usb, bool getDC=true)
Definition: fftfilt.cpp:284
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const ATVModSettings &settings, bool force)
Definition: atvmod.cpp:1502
virtual bool deserialize(const QByteArray &data)
Definition: atvmod.cpp:1258
void calculateVideoSizes()
Definition: atvmod.cpp:880
Complex & modulateSSB(Real &sample)
Definition: atvmod.cpp:229
virtual void pull(Sample &sample)
Definition: atvmod.cpp:138
float m_blankLineLvel
video level of blank lines
Definition: atvmod.h:493
cv::Mat m_image
resized image for transmission at given rate
Definition: atvmod.h:510
int m_videoWidth
camera frame width
Definition: atvmod.h:431
FixReal m_imag
Definition: dsptypes.h:65
double getMagSq() const
Definition: atvmod.h:400
void setAtvModSettings(SWGATVModSettings *atv_mod_settings)
static void getBaseValues(int outputSampleRate, int linesPerSecond, int &sampleRateUnits, uint32_t &nbPointsPerRateUnit)
Definition: atvmod.cpp:644
void create_asym_filter(float fopp, float fin)
two different filters for in band and opposite band
Definition: fftfilt.cpp:174
Real m_rfBandwidth
Bandwidth of modulated signal or direct sideband for SSB / vestigial SSB.
float m_fps
resulting frames per second
Definition: atvmod.h:501
static const float m_spanLevel
Definition: atvmod.h:550
void addChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:174
bool m_singleLongSync
single or double long sync per long sync line
Definition: atvmod.h:491
bool getForce() const
Definition: atvmod.h:58
quint32 m_levelCalcCount
Definition: atvmod.h:504
int m_lineCount
current line index in frame
Definition: atvmod.h:500
int m_pointsPerBP
number of line points for the back porch
Definition: atvmod.h:473
int getIndexInDeviceSet() const
Definition: channelapi.h:87
std::complex< Real > Complex
Definition: dsptypes.h:43
bool getManualFPSEnable() const
Definition: atvmod.h:250
void setReverseApiPort(qint32 reverse_api_port)
uint16_t m_reverseAPIPort
static MsgConfigureChannelizer * create(int centerFrequency)
Definition: atvmod.h:82
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
int m_outputSampleRate
Definition: atvmod.h:460
int m_nbSyncLinesHeadE
number of header sync lines on even frame
Definition: atvmod.h:485
Real m_rfOppBandwidth
Bandwidth of opposite sideband for vestigial SSB.
void applyChannelSettings(int outputSampleRate, int inputFrequencyOffset, bool force=false)
Definition: atvmod.cpp:1033
float Real
Definition: dsptypes.h:42
void seekVideoFileStream(int seekPercentage)
Definition: atvmod.cpp:932
#define SDR_TX_SCALED
Definition: dsptypes.h:40
void pullVideo(Real &sample)
Definition: atvmod.cpp:267
void resizeCamera()
Definition: atvmod.cpp:923
void mixImageAndText(cv::Mat &image)
Definition: atvmod.cpp:1016
const QString & getFileName() const
Definition: atvmod.h:101
bool deserialize(const QByteArray &data)
qint16 FixReal
Definition: dsptypes.h:35
float getManualFPS() const
Definition: atvmod.h:249
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const ATVModSettings &settings)
Definition: atvmod.cpp:1436
T max(const T &x, const T &y)
Definition: framework.h:446
fftfilt * m_DSBFilter
Definition: atvmod.h:541
static const float m_blackLevel
Definition: atvmod.h:549
float m_videoFPSq
current video FPS sacaling factor
Definition: atvmod.h:521
void setChannelPowerDb(float channel_power_db)
bool m_videoPlayLoop
Play video in a loop.
int m_inputFrequencyOffset
Definition: atvmod.h:461
int m_nbLines2
same number as above (non interlaced) or half the number above (interlaced)
Definition: atvmod.h:481
int runAsym(const cmplx &in, cmplx **out, bool usb)
Asymmetrical fitering can be used for vestigial sideband.
Definition: fftfilt.cpp:360
Complex * m_DSBFilterBuffer
Definition: atvmod.h:542
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
int m_nbLongSyncLines
number of whole long sync lines for vertical synchronization
Definition: atvmod.h:488
Complex m_modSample
Definition: atvmod.h:465
void calculateLevel(Real &sample)
Definition: atvmod.cpp:490