From 5d9a1c7c5679b927d517eb380a882bef910f87d9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 9 Mar 2017 23:17:14 +0100 Subject: [PATCH] ATV Modulator: report video file straming to GUI --- plugins/channeltx/modatv/atvmod.cpp | 50 ++++++++++++++- plugins/channeltx/modatv/atvmod.h | 86 ++++++++++++++++++++++++++ plugins/channeltx/modatv/atvmodgui.cpp | 67 ++++++++++++++++++-- plugins/channeltx/modatv/atvmodgui.h | 8 ++- 4 files changed, 203 insertions(+), 8 deletions(-) diff --git a/plugins/channeltx/modatv/atvmod.cpp b/plugins/channeltx/modatv/atvmod.cpp index 0df38fba5..031f29f7b 100644 --- a/plugins/channeltx/modatv/atvmod.cpp +++ b/plugins/channeltx/modatv/atvmod.cpp @@ -24,6 +24,10 @@ MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureATVMod, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureImageFileName, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureVideoFileName, Message) +MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureVideoFileSourceSeek, Message) +MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureVideoFileSourceStreamTiming, Message) +MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportVideoFileSourceStreamTiming, Message) +MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportVideoFileSourceStreamData, Message) const float ATVMod::m_blackLevel = 0.3f; const float ATVMod::m_spanLevel = 0.7f; @@ -307,6 +311,30 @@ bool ATVMod::handleMessage(const Message& cmd) openVideo(conf.getFileName()); return true; } + else if (MsgConfigureVideoFileSourceSeek::match(cmd)) + { + MsgConfigureVideoFileSourceSeek& conf = (MsgConfigureVideoFileSourceSeek&) cmd; + int seekPercentage = conf.getPercentage(); + seekVideoFileStream(seekPercentage); + return true; + } + else if (MsgConfigureVideoFileSourceStreamTiming::match(cmd)) + { + int framesCount; + + if (m_videoOK && m_video.isOpened()) + { + framesCount = m_video.get(CV_CAP_PROP_POS_FRAMES);; + } else { + framesCount = 0; + } + + MsgReportVideoFileSourceStreamTiming *report; + report = MsgReportVideoFileSourceStreamTiming::create(framesCount); + getOutputMessageQueue()->push(report); + + return true; + } else { return false; @@ -454,15 +482,22 @@ void ATVMod::openVideo(const QString& fileName) m_videoFPS = m_video.get(CV_CAP_PROP_FPS); m_videoWidth = (int) m_video.get(CV_CAP_PROP_FRAME_WIDTH); m_videoHeight = (int) m_video.get(CV_CAP_PROP_FRAME_HEIGHT); + m_videoLength = (int) m_video.get(CV_CAP_PROP_FRAME_COUNT); int ex = static_cast(m_video.get(CV_CAP_PROP_FOURCC)); char ext[] = {(char)(ex & 0XFF),(char)((ex & 0XFF00) >> 8),(char)((ex & 0XFF0000) >> 16),(char)((ex & 0XFF000000) >> 24),0}; - qDebug("ATVMod::openVideo: %s FPS: %f size: %d x %d codec: %s", + + qDebug("ATVMod::openVideo: %s FPS: %f size: %d x %d #frames: %d codec: %s", m_video.isOpened() ? "OK" : "KO", m_videoFPS, m_videoWidth, m_videoHeight, + m_videoLength, ext); calculateVideoSizes(); + + MsgReportVideoFileSourceStreamData *report; + report = MsgReportVideoFileSourceStreamData::create(m_videoFPS, m_videoLength); + getOutputMessageQueue()->push(report); } else { @@ -493,3 +528,16 @@ void ATVMod::resizeVideo() cv::resize(m_frameOriginal, m_frame, cv::Size(), m_videoFx, m_videoFy); // resize current frame } } + +void ATVMod::seekVideoFileStream(int seekPercentage) +{ + QMutexLocker mutexLocker(&m_settingsMutex); + + if ((m_videoOK) && m_video.isOpened()) + { + int seekPoint = ((m_videoLength * seekPercentage) / 100); + m_video.set(CV_CAP_PROP_POS_FRAMES, seekPoint); + } +} + + diff --git a/plugins/channeltx/modatv/atvmod.h b/plugins/channeltx/modatv/atvmod.h index bcf9a520d..acbe6396f 100644 --- a/plugins/channeltx/modatv/atvmod.h +++ b/plugins/channeltx/modatv/atvmod.h @@ -101,6 +101,90 @@ public: { } }; + class MsgConfigureVideoFileSourceSeek : public Message + { + MESSAGE_CLASS_DECLARATION + + public: + int getPercentage() const { return m_seekPercentage; } + + static MsgConfigureVideoFileSourceSeek* create(int seekPercentage) + { + return new MsgConfigureVideoFileSourceSeek(seekPercentage); + } + + protected: + int m_seekPercentage; //!< percentage of seek position from the beginning 0..100 + + MsgConfigureVideoFileSourceSeek(int seekPercentage) : + Message(), + m_seekPercentage(seekPercentage) + { } + }; + + class MsgConfigureVideoFileSourceStreamTiming : public Message { + MESSAGE_CLASS_DECLARATION + + public: + + static MsgConfigureVideoFileSourceStreamTiming* create() + { + return new MsgConfigureVideoFileSourceStreamTiming(); + } + + private: + + MsgConfigureVideoFileSourceStreamTiming() : + Message() + { } + }; + + class MsgReportVideoFileSourceStreamTiming : public Message + { + MESSAGE_CLASS_DECLARATION + + public: + int getFrameCount() const { return m_frameCount; } + + static MsgReportVideoFileSourceStreamTiming* create(int frameCount) + { + return new MsgReportVideoFileSourceStreamTiming(frameCount); + } + + protected: + int m_frameCount; + + MsgReportVideoFileSourceStreamTiming(int frameCount) : + Message(), + m_frameCount(frameCount) + { } + }; + + class MsgReportVideoFileSourceStreamData : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getFrameRate() const { return m_frameRate; } + quint32 getVideoLength() const { return m_videoLength; } + + static MsgReportVideoFileSourceStreamData* create(int frameRate, + quint32 recordLength) + { + return new MsgReportVideoFileSourceStreamData(frameRate, recordLength); + } + + protected: + int m_frameRate; + int m_videoLength; //!< Video length in frames + + MsgReportVideoFileSourceStreamData(int frameRate, + int videoLength) : + Message(), + m_frameRate(frameRate), + m_videoLength(videoLength) + { } + }; + ATVMod(); ~ATVMod(); @@ -250,6 +334,7 @@ private: 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 + int m_videoLength; //!< current video length in frames bool m_videoOK; static const float m_blackLevel; @@ -268,6 +353,7 @@ private: void resizeImage(); void calculateVideoSizes(); void resizeVideo(); + void seekVideoFileStream(int seekPercentage); inline void pullImageLine(Real& sample) { diff --git a/plugins/channeltx/modatv/atvmodgui.cpp b/plugins/channeltx/modatv/atvmodgui.cpp index a0c758c33..d9985d732 100644 --- a/plugins/channeltx/modatv/atvmodgui.cpp +++ b/plugins/channeltx/modatv/atvmodgui.cpp @@ -152,7 +152,24 @@ bool ATVModGUI::deserialize(const QByteArray& data) bool ATVModGUI::handleMessage(const Message& message) { - return false; + if (ATVMod::MsgReportVideoFileSourceStreamData::match(message)) + { + m_videoFrameRate = ((ATVMod::MsgReportVideoFileSourceStreamData&)message).getFrameRate(); + m_videoLength = ((ATVMod::MsgReportVideoFileSourceStreamData&)message).getVideoLength(); + m_frameCount = 0; + updateWithStreamData(); + return true; + } + else if (ATVMod::MsgReportVideoFileSourceStreamTiming::match(message)) + { + m_frameCount = ((ATVMod::MsgReportVideoFileSourceStreamTiming&)message).getFrameCount(); + updateWithStreamTime(); + return true; + } + else + { + return false; + } } void ATVModGUI::viewChanged() @@ -289,9 +306,9 @@ ATVModGUI::ATVModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa m_basicSettingsShown(false), m_doApplySettings(true), m_channelPowerDbAvg(20,0), - m_recordLength(0), - m_recordSampleRate(48000), - m_samplesCount(0), + m_videoLength(0), + m_videoFrameRate(48000), + m_frameCount(0), m_tickCount(0), m_enableNavTime(false) { @@ -386,4 +403,46 @@ void ATVModGUI::tick() Real powDb = CalcDb::dbPower(m_atvMod->getMagSq()); m_channelPowerDbAvg.feed(powDb); ui->channelPower->setText(QString::number(m_channelPowerDbAvg.average(), 'f', 1)); + + if (((++m_tickCount & 0xf) == 0) && (ui->inputSelect->currentIndex() == (int) ATVMod::ATVModInputVideo)) + { + ATVMod::MsgConfigureVideoFileSourceStreamTiming* message = ATVMod::MsgConfigureVideoFileSourceStreamTiming::create(); + m_atvMod->getInputMessageQueue()->push(message); + } } + +void ATVModGUI::updateWithStreamData() +{ + QTime recordLength(0, 0, 0, 0); + recordLength = recordLength.addSecs(m_videoLength / m_videoFrameRate); + QString s_time = recordLength.toString("hh:mm:ss"); + ui->recordLengthText->setText(s_time); + updateWithStreamTime(); +} + +void ATVModGUI::updateWithStreamTime() +{ + int t_sec = 0; + int t_msec = 0; + + if (m_videoFrameRate > 0.0f) + { + float secs = m_frameCount / m_videoFrameRate; + t_sec = (int) secs; + t_msec = (int) ((secs - t_sec) * 1000.0f); + } + + QTime t(0, 0, 0, 0); + t = t.addSecs(t_sec); + t = t.addMSecs(t_msec); + QString s_timems = t.toString("hh:mm:ss.zzz"); + QString s_time = t.toString("hh:mm:ss"); + ui->relTimeText->setText(s_timems); + + if (!m_enableNavTime) + { + float posRatio = (t_sec * m_videoFrameRate) / m_videoLength; + ui->navTimeSlider->setValue((int) (posRatio * 100.0)); + } +} + diff --git a/plugins/channeltx/modatv/atvmodgui.h b/plugins/channeltx/modatv/atvmodgui.h index 61f1caa6b..2e79a9575 100644 --- a/plugins/channeltx/modatv/atvmodgui.h +++ b/plugins/channeltx/modatv/atvmodgui.h @@ -91,9 +91,9 @@ private: QString m_imageFileName; QString m_videoFileName; - quint32 m_recordLength; - int m_recordSampleRate; - int m_samplesCount; + quint32 m_videoLength; //!< video file length in seconds + float m_videoFrameRate; //!< video file frame rate + int m_frameCount; std::size_t m_tickCount; bool m_enableNavTime; @@ -102,6 +102,8 @@ private: void blockApplySettings(bool block); void applySettings(); + void updateWithStreamData(); + void updateWithStreamTime(); void leaveEvent(QEvent*); void enterEvent(QEvent*);