From 2adf6da86da57818fceaf91370b930edaa700052 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 10 Mar 2017 19:06:51 +0100 Subject: [PATCH] ATV Modulator: camera device handling (no streaming yet) --- plugins/channeltx/modatv/atvmod.cpp | 71 ++++++++++++++-- plugins/channeltx/modatv/atvmod.h | 108 ++++++++++++++++++++++--- plugins/channeltx/modatv/atvmodgui.cpp | 5 ++ 3 files changed, 166 insertions(+), 18 deletions(-) diff --git a/plugins/channeltx/modatv/atvmod.cpp b/plugins/channeltx/modatv/atvmod.cpp index b062ce50f..77a4e7a80 100644 --- a/plugins/channeltx/modatv/atvmod.cpp +++ b/plugins/channeltx/modatv/atvmod.cpp @@ -28,6 +28,8 @@ MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureVideoFileSourceSeek, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureVideoFileSourceStreamTiming, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportVideoFileSourceStreamTiming, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportVideoFileSourceStreamData, Message) +MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureCameraIndex, Message) +MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportCameraData, Message) const float ATVMod::m_blackLevel = 0.3f; const float ATVMod::m_spanLevel = 0.7f; @@ -46,7 +48,8 @@ ATVMod::ATVMod() : m_videoFPSCount(0.0f), m_videoPrevFPSCount(0), m_videoEOF(false), - m_videoOK(false) + m_videoOK(false), + m_cameraIndex(-1) { setObjectName("ATVMod"); scanCameras(); @@ -218,7 +221,7 @@ void ATVMod::pullVideo(Real& sample) if (!colorFrame.empty()) // some frames may not come out properly { - cv::cvtColor(colorFrame, m_frameOriginal, CV_BGR2GRAY); + cv::cvtColor(colorFrame, m_videoframeOriginal, CV_BGR2GRAY); resizeVideo(); } } @@ -355,6 +358,23 @@ bool ATVMod::handleMessage(const Message& cmd) return true; } + else if (MsgConfigureCameraIndex::match(cmd)) + { + MsgConfigureCameraIndex& cfg = (MsgConfigureCameraIndex&) cmd; + int index = cfg.getIndex(); + + if (index < m_cameras.size()) + { + m_cameraIndex = index; + MsgReportCameraData *report; + report = MsgReportCameraData::create( + m_cameras[m_cameraIndex].m_cameraNumber, + m_cameras[m_cameraIndex].m_videoFPS, + m_cameras[m_cameraIndex].m_videoWidth, + m_cameras[m_cameraIndex].m_videoHeight); + getOutputMessageQueue()->push(report); + } + } else { return false; @@ -545,13 +565,34 @@ void ATVMod::calculateVideoSizes() m_videoFPSCount = m_videoFPSq; m_videoPrevFPSCount = 0; - qDebug("ATVMod::resizeVideo: factors: %f x %f FPSq: %f", m_videoFx, m_videoFy, m_videoFPSq); + qDebug("ATVMod::calculateVideoSizes: 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 + if (!m_videoframeOriginal.empty()) { + cv::resize(m_videoframeOriginal, m_videoFrame, cv::Size(), m_videoFx, m_videoFy); // resize current frame + } +} + +void ATVMod::calculateCamerasSizes() +{ + for (std::vector::iterator it = m_cameras.begin(); it != m_cameras.end(); ++it) + { + 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; + qDebug("ATVMod::calculateCamerasSizes: [%d] factors: %f x %f FPSq: %f", (int) (it - m_cameras.begin()), it->m_videoFx, it->m_videoFy, it->m_videoFPSq); + } +} + +void ATVMod::resizeCameras() +{ + for (std::vector::iterator it = m_cameras.begin(); it != m_cameras.end(); ++it) + { + if (!it->m_videoframeOriginal.empty()) { + cv::resize(it->m_videoframeOriginal, it->m_videoFrame, cv::Size(), it->m_videoFx, it->m_videoFy); // resize current frame + } } } @@ -578,11 +619,29 @@ void ATVMod::scanCameras() m_cameras.back().m_cameraNumber = i; m_cameras.back().m_camera.open(i); - if (!m_cameras.back().m_camera.isOpened()) + if (m_cameras.back().m_camera.isOpened()) + { + m_cameras.back().m_videoFPS = m_cameras.back().m_camera.get(CV_CAP_PROP_FPS); + m_cameras.back().m_videoWidth = (int) m_cameras.back().m_camera.get(CV_CAP_PROP_FRAME_WIDTH); + m_cameras.back().m_videoHeight = (int) m_cameras.back().m_camera.get(CV_CAP_PROP_FRAME_HEIGHT); + } + else { m_cameras.pop_back(); } } + + if (m_cameras.size() > 0) + { + m_cameraIndex = 0; + MsgReportCameraData *report; + report = MsgReportCameraData::create( + m_cameras[0].m_cameraNumber, + m_cameras[0].m_videoFPS, + m_cameras[0].m_videoWidth, + m_cameras[0].m_videoHeight); + getOutputMessageQueue()->push(report); + } } void ATVMod::releaseCameras() diff --git a/plugins/channeltx/modatv/atvmod.h b/plugins/channeltx/modatv/atvmod.h index 0e98cb86e..5778e54fc 100644 --- a/plugins/channeltx/modatv/atvmod.h +++ b/plugins/channeltx/modatv/atvmod.h @@ -52,7 +52,8 @@ public: ATVModInputHGradient, ATVModInputVGradient, ATVModInputImage, - ATVModInputVideo + ATVModInputVideo, + ATVModInputCamera } ATVModInput; typedef enum @@ -61,12 +62,6 @@ public: ATVModulationFM } ATVModulation; - typedef struct - { - cv::VideoCapture m_camera; - int m_cameraNumber; - } ATVCamera; - class MsgConfigureImageFileName : public Message { MESSAGE_CLASS_DECLARATION @@ -193,6 +188,68 @@ public: { } }; + class MsgConfigureCameraIndex : public Message + { + MESSAGE_CLASS_DECLARATION + + public: + int getIndex() const { return m_index; } + + static MsgConfigureCameraIndex* create(int index) + { + return new MsgConfigureCameraIndex(index); + } + + private: + int m_index; + + MsgConfigureCameraIndex(int index) : + Message(), + m_index(index) + { } + }; + + class MsgReportCameraData : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getdeviceNumber() const { return m_deviceNumber; } + int getFPS() const { return m_fps; } + int getWidth() const { return m_width; } + int getHeight() const { return m_height; } + + static MsgReportCameraData* create( + int deviceNumber, + int fps, + int width, + int height) + { + return new MsgReportCameraData( + deviceNumber, + fps, + width, + height); + } + + protected: + int m_deviceNumber; + int m_fps; + int m_width; + int m_height; + + MsgReportCameraData( + int deviceNumber, + int fps, + int width, + int height) : + Message(), + m_deviceNumber(deviceNumber), + m_fps(fps), + m_width(width), + m_height(height) + { } + }; + ATVMod(); ~ATVMod(); @@ -292,6 +349,30 @@ private: { } }; + typedef struct ATVCamera + { + cv::VideoCapture m_camera; //!< camera object + cv::Mat m_videoframeOriginal; //!< camera non resized image + cv::Mat m_videoFrame; //!< displayable camera frame + int m_cameraNumber; //!< camera device number + float m_videoFPS; //!< camera FPS rate + int m_videoWidth; //!< camera frame width + int m_videoHeight; //!< camera frame height + float m_videoFx; //!< camera horizontal scaling factor + float m_videoFy; //!< camera vertictal scaling factor + float m_videoFPSq; //!< camera FPS sacaling factor + + ATVCamera() : + m_cameraNumber(-1), + m_videoFPS(25), + m_videoWidth(1), + m_videoHeight(1), + m_videoFx(1.0f), + m_videoFy(1.0f), + m_videoFPSq(1.0f) + {} + }; + struct Config { int m_outputSampleRate; //!< sample rate from channelizer @@ -361,8 +442,8 @@ private: bool m_imageOK; cv::VideoCapture m_video; //!< current video capture - cv::Mat m_frameOriginal; //!< current frame from video - cv::Mat m_frame; //!< current displayable video frame + cv::Mat m_videoframeOriginal; //!< current frame from video + cv::Mat m_videoFrame; //!< 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 @@ -376,6 +457,7 @@ private: bool m_videoOK; std::vector m_cameras; //!< vector of available cameras + int m_cameraIndex; //!< curent camera index in list of available cameras static const float m_blackLevel; static const float m_spanLevel; @@ -396,6 +478,8 @@ private: void seekVideoFileStream(int seekPercentage); void scanCameras(); void releaseCameras(); + void calculateCamerasSizes(); + void resizeCameras(); inline void pullImageLine(Real& sample) { @@ -450,7 +534,7 @@ private: } break; case ATVModInputVideo: - if (!m_videoOK || (iLineImage < 0) || m_frame.empty()) + if (!m_videoOK || (iLineImage < 0) || m_videoFrame.empty()) { sample = m_spanLevel * m_running.m_uniformLevel + m_blackLevel; } @@ -459,9 +543,9 @@ private: unsigned char pixv; if (m_interlaced) { - pixv = m_frame.at(2*iLineImage + oddity, pointIndex); // row (y), col (x) + pixv = m_videoFrame.at(2*iLineImage + oddity, pointIndex); // row (y), col (x) } else { - pixv = m_frame.at(iLineImage, pointIndex); // row (y), col (x) + pixv = m_videoFrame.at(iLineImage, pointIndex); // row (y), col (x) } sample = (pixv / 256.0f) * m_spanLevel + m_blackLevel; diff --git a/plugins/channeltx/modatv/atvmodgui.cpp b/plugins/channeltx/modatv/atvmodgui.cpp index a3cff2652..3a5c2653e 100644 --- a/plugins/channeltx/modatv/atvmodgui.cpp +++ b/plugins/channeltx/modatv/atvmodgui.cpp @@ -162,6 +162,11 @@ bool ATVModGUI::handleMessage(const Message& message) updateWithStreamTime(); return true; } + else if (ATVMod::MsgReportCameraData::match(message)) + { + // TODO + return true; + } else { return false;