kopia lustrzana https://github.com/f4exb/sdrangel
ATV Modulator: transmit video interim state (1)
rodzic
870f44a51b
commit
2a64878d7f
|
@ -37,7 +37,11 @@ ATVMod::ATVMod() :
|
||||||
m_settingsMutex(QMutex::Recursive),
|
m_settingsMutex(QMutex::Recursive),
|
||||||
m_horizontalCount(0),
|
m_horizontalCount(0),
|
||||||
m_lineCount(0),
|
m_lineCount(0),
|
||||||
m_imageOK(false)
|
m_imageOK(false),
|
||||||
|
m_videoFPSq(1.0f),
|
||||||
|
m_videoFPSCount(0.0f),
|
||||||
|
m_videoPrevFPSCount(0),
|
||||||
|
m_videoOK(false)
|
||||||
{
|
{
|
||||||
setObjectName("ATVMod");
|
setObjectName("ATVMod");
|
||||||
|
|
||||||
|
@ -59,6 +63,7 @@ ATVMod::ATVMod() :
|
||||||
|
|
||||||
ATVMod::~ATVMod()
|
ATVMod::~ATVMod()
|
||||||
{
|
{
|
||||||
|
if (m_video.isOpened()) m_video.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATVMod::configure(MessageQueue* messageQueue,
|
void ATVMod::configure(MessageQueue* messageQueue,
|
||||||
|
@ -171,10 +176,48 @@ void ATVMod::pullVideo(Real& sample)
|
||||||
m_lineCount++;
|
m_lineCount++;
|
||||||
if (m_lineCount > (m_nbLines/2)) m_evenImage = !m_evenImage;
|
if (m_lineCount > (m_nbLines/2)) m_evenImage = !m_evenImage;
|
||||||
}
|
}
|
||||||
else
|
else // new image
|
||||||
{
|
{
|
||||||
m_lineCount = 0;
|
m_lineCount = 0;
|
||||||
m_evenImage = !m_evenImage;
|
m_evenImage = !m_evenImage;
|
||||||
|
|
||||||
|
if (m_running.m_atvModInput == ATVModInputVideo)
|
||||||
|
{
|
||||||
|
int grabOK;
|
||||||
|
int fpsIncrement = (int) m_videoFPSCount - m_videoPrevFPSCount;
|
||||||
|
|
||||||
|
// move a number of frames according to increment
|
||||||
|
// use grab to test for EOF then retrieve to preserve last valid frame as the current original frame
|
||||||
|
// TODO: handle pause (no move)
|
||||||
|
for (int i = 0; i < fpsIncrement; i++)
|
||||||
|
{
|
||||||
|
grabOK = m_video.grab();
|
||||||
|
if (!grabOK) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grabOK)
|
||||||
|
{
|
||||||
|
cv::Mat colorFrame;
|
||||||
|
m_video.retrieve(colorFrame);
|
||||||
|
cv::cvtColor(colorFrame, m_frameOriginal, CV_BGR2GRAY);
|
||||||
|
resizeVideo();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: handle play loop
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_videoFPSCount < m_videoFPS)
|
||||||
|
{
|
||||||
|
m_videoPrevFPSCount = (int) m_videoFPSCount;
|
||||||
|
m_videoFPSCount += m_videoFPSq;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_videoPrevFPSCount = 0;
|
||||||
|
m_videoFPSCount = m_videoFPSq;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_horizontalCount = 0;
|
m_horizontalCount = 0;
|
||||||
|
@ -342,7 +385,7 @@ void ATVMod::applyStandard()
|
||||||
m_nbImageLines2 = 255;
|
m_nbImageLines2 = 255;
|
||||||
m_interlaced = true;
|
m_interlaced = true;
|
||||||
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
|
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
|
||||||
m_nbSyncLinesH = 5;
|
m_nbSyncLinesHead = 5;
|
||||||
m_nbBlankLines = 15; // yields 480 lines (255 - 15) * 2
|
m_nbBlankLines = 15; // yields 480 lines (255 - 15) * 2
|
||||||
m_pointsPerHBar = m_pointsPerImgLine / m_nbBars;
|
m_pointsPerHBar = m_pointsPerImgLine / m_nbBars;
|
||||||
m_linesPerVBar = m_nbImageLines2 / m_nbBars;
|
m_linesPerVBar = m_nbImageLines2 / m_nbBars;
|
||||||
|
@ -364,7 +407,7 @@ void ATVMod::applyStandard()
|
||||||
m_nbImageLines2 = 305;
|
m_nbImageLines2 = 305;
|
||||||
m_interlaced = true;
|
m_interlaced = true;
|
||||||
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
|
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
|
||||||
m_nbSyncLinesH = 5;
|
m_nbSyncLinesHead = 5;
|
||||||
m_nbBlankLines = 17; // yields 576 lines (305 - 17) * 2
|
m_nbBlankLines = 17; // yields 576 lines (305 - 17) * 2
|
||||||
m_pointsPerHBar = m_pointsPerImgLine / m_nbBars;
|
m_pointsPerHBar = m_pointsPerImgLine / m_nbBars;
|
||||||
m_linesPerVBar = m_nbImageLines2 / m_nbBars;
|
m_linesPerVBar = m_nbImageLines2 / m_nbBars;
|
||||||
|
@ -377,6 +420,12 @@ void ATVMod::applyStandard()
|
||||||
{
|
{
|
||||||
resizeImage();
|
resizeImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_videoOK)
|
||||||
|
{
|
||||||
|
calculateVideoSizes();
|
||||||
|
resizeVideo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATVMod::openImage(const QString& fileName)
|
void ATVMod::openImage(const QString& fileName)
|
||||||
|
@ -392,6 +441,8 @@ void ATVMod::openImage(const QString& fileName)
|
||||||
|
|
||||||
void ATVMod::openVideo(const QString& fileName)
|
void ATVMod::openVideo(const QString& fileName)
|
||||||
{
|
{
|
||||||
|
//if (m_videoOK && m_video.isOpened()) m_video.release(); should be done by OpenCV in open method
|
||||||
|
|
||||||
m_videoOK = m_video.open(qPrintable(fileName));
|
m_videoOK = m_video.open(qPrintable(fileName));
|
||||||
|
|
||||||
if (m_videoOK)
|
if (m_videoOK)
|
||||||
|
@ -400,6 +451,7 @@ void ATVMod::openVideo(const QString& fileName)
|
||||||
m_videoWidth = (int) m_video.get(CV_CAP_PROP_FRAME_WIDTH);
|
m_videoWidth = (int) m_video.get(CV_CAP_PROP_FRAME_WIDTH);
|
||||||
m_videoHeight = (int) m_video.get(CV_CAP_PROP_FRAME_HEIGHT);
|
m_videoHeight = (int) m_video.get(CV_CAP_PROP_FRAME_HEIGHT);
|
||||||
qDebug("ATVMod::openVideo(: FPS: %f size: %d x %d", m_videoFPS, m_videoWidth, m_videoHeight);
|
qDebug("ATVMod::openVideo(: FPS: %f size: %d x %d", m_videoFPS, m_videoWidth, m_videoHeight);
|
||||||
|
calculateVideoSizes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,3 +462,19 @@ void ATVMod::resizeImage()
|
||||||
cv::resize(m_imageOriginal, m_image, cv::Size(), fx, fy);
|
cv::resize(m_imageOriginal, m_image, cv::Size(), fx, fy);
|
||||||
qDebug("ATVMod::resizeImage: %d x %d -> %d x %d", m_imageOriginal.cols, m_imageOriginal.rows, m_image.cols, m_image.rows);
|
qDebug("ATVMod::resizeImage: %d x %d -> %d x %d", m_imageOriginal.cols, m_imageOriginal.rows, m_image.cols, m_image.rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ATVMod::calculateVideoSizes()
|
||||||
|
{
|
||||||
|
m_videoFy = (m_nbImageLines - 2*m_nbBlankLines) / (float) m_videoHeight;
|
||||||
|
m_videoFx = m_pointsPerImgLine / (float) m_videoWidth;
|
||||||
|
m_videoFPSq = m_videoFPS / m_fps;
|
||||||
|
|
||||||
|
qDebug("ATVMod::resizeVideo: factors: %f x %f FPSq: %f", m_videoFx, m_videoFy, m_videoFPSq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ATVMod::resizeVideo()
|
||||||
|
{
|
||||||
|
if (!m_frameOriginal.empty()) {
|
||||||
|
cv::resize(m_frameOriginal, m_frame, cv::Size(), m_videoFx, m_videoFy); // resize current frame
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -219,7 +219,7 @@ private:
|
||||||
uint32_t m_nbImageLines; //!< number of image lines excluding synchronization lines
|
uint32_t m_nbImageLines; //!< number of image lines excluding synchronization lines
|
||||||
uint32_t m_nbImageLines2; //!< same number as above (non interlaced) or half the number above (interlaced)
|
uint32_t m_nbImageLines2; //!< same number as above (non interlaced) or half the number above (interlaced)
|
||||||
uint32_t m_nbHorizPoints; //!< number of line points per horizontal line
|
uint32_t m_nbHorizPoints; //!< number of line points per horizontal line
|
||||||
uint32_t m_nbSyncLinesH; //!< number of header sync lines
|
uint32_t m_nbSyncLinesHead; //!< number of header sync lines
|
||||||
uint32_t m_nbBlankLines; //!< number of lines in a frame (full or half) that are blanked (black) at the top of the image
|
uint32_t m_nbBlankLines; //!< number of lines in a frame (full or half) that are blanked (black) at the top of the image
|
||||||
float m_hBarIncrement; //!< video level increment at each horizontal bar increment
|
float m_hBarIncrement; //!< video level increment at each horizontal bar increment
|
||||||
float m_vBarIncrement; //!< video level increment at each vertical bar increment
|
float m_vBarIncrement; //!< video level increment at each vertical bar increment
|
||||||
|
@ -240,10 +240,16 @@ private:
|
||||||
bool m_imageOK;
|
bool m_imageOK;
|
||||||
|
|
||||||
cv::VideoCapture m_video; //!< current video capture
|
cv::VideoCapture m_video; //!< current video capture
|
||||||
cv::Mat m_frame; //!< current frame
|
cv::Mat m_frameOriginal; //!< current frame from video
|
||||||
float m_videoFPS;
|
cv::Mat m_frame; //!< current displayable video frame
|
||||||
int m_videoWidth;
|
float m_videoFPS; //!< current video FPS rate
|
||||||
int m_videoHeight;
|
int m_videoWidth; //!< current video frame width
|
||||||
|
int m_videoHeight; //!< current video frame height
|
||||||
|
float m_videoFx; //!< current video horizontal scaling factor
|
||||||
|
float m_videoFy; //!< current video vertictal scaling factor
|
||||||
|
float m_videoFPSq; //!< current video FPS sacaling factor
|
||||||
|
float m_videoFPSCount; //!< current video FPS fractional counter
|
||||||
|
int m_videoPrevFPSCount; //!< current video FPS previous integer counter
|
||||||
bool m_videoOK;
|
bool m_videoOK;
|
||||||
|
|
||||||
static const float m_blackLevel;
|
static const float m_blackLevel;
|
||||||
|
@ -260,6 +266,8 @@ private:
|
||||||
void openImage(const QString& fileName);
|
void openImage(const QString& fileName);
|
||||||
void openVideo(const QString& fileName);
|
void openVideo(const QString& fileName);
|
||||||
void resizeImage();
|
void resizeImage();
|
||||||
|
void calculateVideoSizes();
|
||||||
|
void resizeVideo();
|
||||||
|
|
||||||
inline void pullImageLine(Real& sample)
|
inline void pullImageLine(Real& sample)
|
||||||
{
|
{
|
||||||
|
@ -276,7 +284,7 @@ private:
|
||||||
int pointIndex = m_horizontalCount - (m_pointsPerSync + m_pointsPerBP);
|
int pointIndex = m_horizontalCount - (m_pointsPerSync + m_pointsPerBP);
|
||||||
int iLine = m_lineCount % m_nbLines2;
|
int iLine = m_lineCount % m_nbLines2;
|
||||||
int oddity = m_lineCount < m_nbLines2 ? 0 : 1;
|
int oddity = m_lineCount < m_nbLines2 ? 0 : 1;
|
||||||
int iLineImage = iLine - m_nbSyncLinesH - m_nbBlankLines;
|
int iLineImage = iLine - m_nbSyncLinesHead - m_nbBlankLines;
|
||||||
|
|
||||||
switch(m_running.m_atvModInput)
|
switch(m_running.m_atvModInput)
|
||||||
{
|
{
|
||||||
|
@ -296,16 +304,41 @@ private:
|
||||||
sample = ((iLine -5) / (float) m_nbImageLines2) * m_spanLevel + m_blackLevel;
|
sample = ((iLine -5) / (float) m_nbImageLines2) * m_spanLevel + m_blackLevel;
|
||||||
break;
|
break;
|
||||||
case ATVModInputImage:
|
case ATVModInputImage:
|
||||||
if (!m_imageOK || (iLineImage < 0))
|
if (!m_imageOK || (iLineImage < 0) || m_image.empty())
|
||||||
{
|
{
|
||||||
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;
|
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned char pixv = m_image.at<unsigned char>(2*iLineImage+ oddity, pointIndex); // row (y), col (x)
|
unsigned char pixv;
|
||||||
|
|
||||||
|
if (m_interlaced) {
|
||||||
|
pixv = m_image.at<unsigned char>(2*iLineImage + oddity, pointIndex); // row (y), col (x)
|
||||||
|
} else {
|
||||||
|
pixv = m_image.at<unsigned char>(iLineImage, pointIndex); // row (y), col (x)
|
||||||
|
}
|
||||||
|
|
||||||
sample = (pixv / 256.0f) * m_spanLevel + m_blackLevel;
|
sample = (pixv / 256.0f) * m_spanLevel + m_blackLevel;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ATVModInputVideo:
|
||||||
|
if (!m_videoOK || (iLineImage < 0) || m_frame.empty())
|
||||||
|
{
|
||||||
|
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char pixv;
|
||||||
|
|
||||||
|
if (m_interlaced) {
|
||||||
|
pixv = m_frame.at<unsigned char>(2*iLineImage + oddity, pointIndex); // row (y), col (x)
|
||||||
|
} else {
|
||||||
|
pixv = m_frame.at<unsigned char>(iLineImage, pointIndex); // row (y), col (x)
|
||||||
|
}
|
||||||
|
|
||||||
|
sample = (pixv / 256.0f) * m_spanLevel + m_blackLevel;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ATVModInputUniform:
|
case ATVModInputUniform:
|
||||||
default:
|
default:
|
||||||
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;
|
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;
|
||||||
|
|
|
@ -69,7 +69,7 @@ void ATVModGUI::resetToDefaults()
|
||||||
{
|
{
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
|
|
||||||
ui->rfBW->setValue(12);
|
ui->rfBW->setValue(10);
|
||||||
ui->uniformLevel->setValue(35);
|
ui->uniformLevel->setValue(35);
|
||||||
ui->volume->setValue(10);
|
ui->volume->setValue(10);
|
||||||
ui->standard->setCurrentIndex(0);
|
ui->standard->setCurrentIndex(0);
|
||||||
|
|
|
@ -390,6 +390,11 @@
|
||||||
<string>Image</string>
|
<string>Image</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Video</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
Ładowanie…
Reference in New Issue