ATV Modulator: camera support

This commit is contained in:
f4exb 2017-03-11 08:21:26 +01:00
parent 41fac50526
commit 5baaacb2ed
5 changed files with 126 additions and 8 deletions

View File

@ -84,6 +84,7 @@ void ATVMod::configure(MessageQueue* messageQueue,
ATVModulation atvModulation,
bool videoPlayLoop,
bool videoPlay,
bool cameraPlay,
bool channelMute)
{
Message* cmd = MsgConfigureATVMod::create(
@ -93,7 +94,8 @@ void ATVMod::configure(MessageQueue* messageQueue,
uniformLevel,
atvModulation,
videoPlayLoop,
videoPlay);
videoPlay,
cameraPlay);
messageQueue->push(cmd);
}
@ -245,6 +247,44 @@ void ATVMod::pullVideo(Real& sample)
m_videoFPSCount = m_videoFPSq;
}
}
else if ((m_running.m_atvModInput == ATVModInputCamera) && (m_running.m_cameraPlay))
{
ATVCamera& camera = m_cameras[m_cameraIndex]; // currently selected canera
int grabOK;
int fpsIncrement = (int) camera.m_videoFPSCount - camera.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 = camera.m_camera.grab();
if (!grabOK) break;
}
if (grabOK)
{
cv::Mat colorFrame;
camera.m_camera.retrieve(colorFrame);
if (!colorFrame.empty()) // some frames may not come out properly
{
cv::cvtColor(colorFrame, camera.m_videoframeOriginal, CV_BGR2GRAY);
resizeCamera();
}
if (camera.m_videoFPSCount < camera.m_videoFPS)
{
camera.m_videoPrevFPSCount = (int) camera.m_videoFPSCount;
camera.m_videoFPSCount += camera.m_videoFPSq;
}
else
{
camera.m_videoPrevFPSCount = 0;
camera.m_videoFPSCount = camera.m_videoFPSq;
}
}
}
}
m_horizontalCount = 0;
@ -308,6 +348,7 @@ bool ATVMod::handleMessage(const Message& cmd)
m_config.m_atvModulation = cfg.getModulation();
m_config.m_videoPlayLoop = cfg.getVideoPlayLoop();
m_config.m_videoPlay = cfg.getVideoPlay();
m_config.m_cameraPlay = cfg.getCameraPlay();
apply();
@ -318,7 +359,8 @@ bool ATVMod::handleMessage(const Message& cmd)
<< " m_uniformLevel: " << m_config.m_uniformLevel
<< " m_atvModulation: " << (int) m_config.m_atvModulation
<< " m_videoPlayLoop: " << m_config.m_videoPlayLoop
<< " m_videoPlay: " << m_config.m_videoPlay;
<< " m_videoPlay: " << m_config.m_videoPlay
<< " m_cameraPlay: " << m_config.m_cameraPlay;
return true;
}
@ -424,6 +466,7 @@ void ATVMod::apply(bool force)
m_running.m_atvModulation = m_config.m_atvModulation;
m_running.m_videoPlayLoop = m_config.m_videoPlayLoop;
m_running.m_videoPlay = m_config.m_videoPlay;
m_running.m_cameraPlay = m_config.m_cameraPlay;
}
int ATVMod::getSampleRateUnits(ATVStd std)
@ -500,6 +543,8 @@ void ATVMod::applyStandard()
calculateVideoSizes();
resizeVideo();
}
calculateCamerasSizes();
}
void ATVMod::openImage(const QString& fileName)
@ -582,6 +627,9 @@ void ATVMod::calculateCamerasSizes()
it->m_videoFy = (m_nbImageLines - 2*m_nbBlankLines) / (float) it->m_videoHeight;
it->m_videoFx = m_pointsPerImgLine / (float) it->m_videoWidth;
it->m_videoFPSq = it->m_videoFPS / m_fps;
it->m_videoFPSCount = it->m_videoFPSq;
it->m_videoPrevFPSCount = 0;
qDebug("ATVMod::calculateCamerasSizes: [%d] factors: %f x %f FPSq: %f", (int) (it - m_cameras.begin()), it->m_videoFx, it->m_videoFy, it->m_videoFPSq);
}
}
@ -596,6 +644,15 @@ void ATVMod::resizeCameras()
}
}
void ATVMod::resizeCamera()
{
ATVCamera& camera = m_cameras[m_cameraIndex];
if (!camera.m_videoframeOriginal.empty()) {
cv::resize(camera.m_videoframeOriginal, camera.m_videoFrame, cv::Size(), camera.m_videoFx, camera.m_videoFy); // resize current frame
}
}
void ATVMod::seekVideoFileStream(int seekPercentage)
{
QMutexLocker mutexLocker(&m_settingsMutex);
@ -641,6 +698,7 @@ void ATVMod::scanCameras()
if (m_cameras.size() > 0)
{
calculateCamerasSizes();
m_cameraIndex = 0;
}
}

View File

@ -261,6 +261,7 @@ public:
ATVModulation atvModulation,
bool videoPlayLoop,
bool videoPlay,
bool cameraPLay,
bool channelMute);
virtual void pull(Sample& sample);
@ -297,6 +298,7 @@ private:
ATVModulation getModulation() const { return m_atvModulation; }
bool getVideoPlayLoop() const { return m_videoPlayLoop; }
bool getVideoPlay() const { return m_videoPlay; }
bool getCameraPlay() const { return m_cameraPlay; }
static MsgConfigureATVMod* create(
Real rfBandwidth,
@ -305,7 +307,8 @@ private:
Real uniformLevel,
ATVModulation atvModulation,
bool videoPlayLoop,
bool videoPlay)
bool videoPlay,
bool cameraPlay)
{
return new MsgConfigureATVMod(
rfBandwidth,
@ -314,7 +317,8 @@ private:
uniformLevel,
atvModulation,
videoPlayLoop,
videoPlay);
videoPlay,
cameraPlay);
}
private:
@ -325,6 +329,7 @@ private:
ATVModulation m_atvModulation;
bool m_videoPlayLoop;
bool m_videoPlay;
bool m_cameraPlay;
MsgConfigureATVMod(
Real rfBandwidth,
@ -333,7 +338,8 @@ private:
Real uniformLevel,
ATVModulation atvModulation,
bool videoPlayLoop,
bool videoPlay) :
bool videoPlay,
bool cameraPlay) :
Message(),
m_rfBandwidth(rfBandwidth),
m_atvStd(atvStd),
@ -341,7 +347,8 @@ private:
m_uniformLevel(uniformLevel),
m_atvModulation(atvModulation),
m_videoPlayLoop(videoPlayLoop),
m_videoPlay(videoPlay)
m_videoPlay(videoPlay),
m_cameraPlay(cameraPlay)
{ }
};
@ -357,6 +364,8 @@ private:
float m_videoFx; //!< camera horizontal scaling factor
float m_videoFy; //!< camera vertictal scaling factor
float m_videoFPSq; //!< camera FPS sacaling factor
float m_videoFPSCount; //!< camera FPS fractional counter
int m_videoPrevFPSCount; //!< camera FPS previous integer counter
ATVCamera() :
m_cameraNumber(-1),
@ -365,7 +374,9 @@ private:
m_videoHeight(1),
m_videoFx(1.0f),
m_videoFy(1.0f),
m_videoFPSq(1.0f)
m_videoFPSq(1.0f),
m_videoFPSCount(0.0f),
m_videoPrevFPSCount(0)
{}
};
@ -380,6 +391,7 @@ private:
ATVModulation m_atvModulation; //!< RF modulation type
bool m_videoPlayLoop; //!< Play video in a loop
bool m_videoPlay; //!< True to play video and false to pause
bool m_cameraPlay; //!< True to play camera video and false to pause
Config() :
m_outputSampleRate(-1),
@ -390,7 +402,8 @@ private:
m_uniformLevel(0.5f),
m_atvModulation(ATVModulationAM),
m_videoPlayLoop(false),
m_videoPlay(false)
m_videoPlay(false),
m_cameraPlay(false)
{ }
};
@ -476,6 +489,7 @@ private:
void releaseCameras();
void calculateCamerasSizes();
void resizeCameras();
void resizeCamera();
inline void pullImageLine(Real& sample)
{
@ -547,6 +561,33 @@ private:
sample = (pixv / 256.0f) * m_spanLevel + m_blackLevel;
}
break;
case ATVModInputCamera:
if ((iLineImage < 0) || (m_cameraIndex < 0))
{
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;
}
else
{
ATVCamera& camera = m_cameras[m_cameraIndex];
if (camera.m_videoFrame.empty())
{
sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel;
}
else
{
unsigned char pixv;
if (m_interlaced) {
pixv = camera.m_videoFrame.at<unsigned char>(2*iLineImage + oddity, pointIndex); // row (y), col (x)
} else {
pixv = camera.m_videoFrame.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;

View File

@ -290,6 +290,16 @@ void ATVModGUI::on_navTimeSlider_valueChanged(int value)
}
}
void ATVModGUI::on_playCamera_toggled(bool checked)
{
applySettings();
}
void ATVModGUI::on_camSelect_currentIndexChanged(int index)
{
ATVMod::MsgConfigureCameraIndex* message = ATVMod::MsgConfigureCameraIndex::create(index);
m_atvMod->getInputMessageQueue()->push(message);
}
void ATVModGUI::configureImageFileName()
{
@ -410,6 +420,7 @@ void ATVModGUI::applySettings()
(ATVMod::ATVModulation) ui->modulation->currentIndex(),
ui->playLoop->isChecked(),
ui->playVideo->isChecked(),
ui->playCamera->isChecked(),
ui->channelMute->isChecked());
}
}

View File

@ -72,6 +72,9 @@ private slots:
void on_playLoop_toggled(bool checked);
void on_navTimeSlider_valueChanged(int value);
void on_playCamera_toggled(bool checked);
void on_camSelect_currentIndexChanged(int index);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDoubleClicked();

View File

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