ATV Modulator: transmit video interim state (1)

pull/27/head
f4exb 2017-03-09 19:07:45 +01:00
rodzic 870f44a51b
commit 2a64878d7f
4 zmienionych plików z 119 dodań i 13 usunięć

Wyświetl plik

@ -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
}
}

Wyświetl plik

@ -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,16 +304,41 @@ 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;
case ATVModInputUniform:
default:
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;

Wyświetl plik

@ -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);

Wyświetl plik

@ -390,6 +390,11 @@
<string>Image</string>
</property>
</item>
<item>
<property name="text">
<string>Video</string>
</property>
</item>
</widget>
</item>
<item>