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_horizontalCount(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");
|
||||
|
||||
|
@ -59,6 +63,7 @@ ATVMod::ATVMod() :
|
|||
|
||||
ATVMod::~ATVMod()
|
||||
{
|
||||
if (m_video.isOpened()) m_video.release();
|
||||
}
|
||||
|
||||
void ATVMod::configure(MessageQueue* messageQueue,
|
||||
|
@ -171,10 +176,48 @@ void ATVMod::pullVideo(Real& sample)
|
|||
m_lineCount++;
|
||||
if (m_lineCount > (m_nbLines/2)) m_evenImage = !m_evenImage;
|
||||
}
|
||||
else
|
||||
else // new image
|
||||
{
|
||||
m_lineCount = 0;
|
||||
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;
|
||||
|
@ -342,7 +385,7 @@ void ATVMod::applyStandard()
|
|||
m_nbImageLines2 = 255;
|
||||
m_interlaced = true;
|
||||
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
|
||||
m_nbSyncLinesH = 5;
|
||||
m_nbSyncLinesHead = 5;
|
||||
m_nbBlankLines = 15; // yields 480 lines (255 - 15) * 2
|
||||
m_pointsPerHBar = m_pointsPerImgLine / m_nbBars;
|
||||
m_linesPerVBar = m_nbImageLines2 / m_nbBars;
|
||||
|
@ -364,7 +407,7 @@ void ATVMod::applyStandard()
|
|||
m_nbImageLines2 = 305;
|
||||
m_interlaced = true;
|
||||
m_nbHorizPoints = 64 * m_pointsPerTU; // full line
|
||||
m_nbSyncLinesH = 5;
|
||||
m_nbSyncLinesHead = 5;
|
||||
m_nbBlankLines = 17; // yields 576 lines (305 - 17) * 2
|
||||
m_pointsPerHBar = m_pointsPerImgLine / m_nbBars;
|
||||
m_linesPerVBar = m_nbImageLines2 / m_nbBars;
|
||||
|
@ -377,6 +420,12 @@ void ATVMod::applyStandard()
|
|||
{
|
||||
resizeImage();
|
||||
}
|
||||
|
||||
if (m_videoOK)
|
||||
{
|
||||
calculateVideoSizes();
|
||||
resizeVideo();
|
||||
}
|
||||
}
|
||||
|
||||
void ATVMod::openImage(const QString& fileName)
|
||||
|
@ -392,6 +441,8 @@ void ATVMod::openImage(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));
|
||||
|
||||
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_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);
|
||||
calculateVideoSizes();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,3 +462,19 @@ void ATVMod::resizeImage()
|
|||
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);
|
||||
}
|
||||
|
||||
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_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_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
|
||||
float m_hBarIncrement; //!< video level increment at each horizontal bar increment
|
||||
float m_vBarIncrement; //!< video level increment at each vertical bar increment
|
||||
|
@ -240,10 +240,16 @@ private:
|
|||
bool m_imageOK;
|
||||
|
||||
cv::VideoCapture m_video; //!< current video capture
|
||||
cv::Mat m_frame; //!< current frame
|
||||
float m_videoFPS;
|
||||
int m_videoWidth;
|
||||
int m_videoHeight;
|
||||
cv::Mat m_frameOriginal; //!< current frame from video
|
||||
cv::Mat m_frame; //!< current displayable video frame
|
||||
float m_videoFPS; //!< current video FPS rate
|
||||
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;
|
||||
|
||||
static const float m_blackLevel;
|
||||
|
@ -260,6 +266,8 @@ private:
|
|||
void openImage(const QString& fileName);
|
||||
void openVideo(const QString& fileName);
|
||||
void resizeImage();
|
||||
void calculateVideoSizes();
|
||||
void resizeVideo();
|
||||
|
||||
inline void pullImageLine(Real& sample)
|
||||
{
|
||||
|
@ -276,7 +284,7 @@ private:
|
|||
int pointIndex = m_horizontalCount - (m_pointsPerSync + m_pointsPerBP);
|
||||
int iLine = m_lineCount % m_nbLines2;
|
||||
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)
|
||||
{
|
||||
|
@ -296,13 +304,38 @@ private:
|
|||
sample = ((iLine -5) / (float) m_nbImageLines2) * m_spanLevel + m_blackLevel;
|
||||
break;
|
||||
case ATVModInputImage:
|
||||
if (!m_imageOK || (iLineImage < 0))
|
||||
if (!m_imageOK || (iLineImage < 0) || m_image.empty())
|
||||
{
|
||||
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -69,7 +69,7 @@ void ATVModGUI::resetToDefaults()
|
|||
{
|
||||
blockApplySettings(true);
|
||||
|
||||
ui->rfBW->setValue(12);
|
||||
ui->rfBW->setValue(10);
|
||||
ui->uniformLevel->setValue(35);
|
||||
ui->volume->setValue(10);
|
||||
ui->standard->setCurrentIndex(0);
|
||||
|
|
|
@ -390,6 +390,11 @@
|
|||
<string>Image</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Video</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
Ładowanie…
Reference in New Issue