diff --git a/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.cpp b/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.cpp index 1b9f47f0ee..2b6c80a529 100644 --- a/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.cpp +++ b/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.cpp @@ -1,435 +1,448 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkOpenCVVideoControls.h" #include #include #include #include class QmitkOpenCVVideoControlsPrivate { public: QmitkOpenCVVideoControlsPrivate(QmitkOpenCVVideoControls* q, const std::string& id) : q(q) , m_Id(id) {} /// /// muellerm: persitence service implementation /// PERSISTENCE_GET_SERVICE_METHOD_MACRO QmitkOpenCVVideoControls* q; /// /// muellerm: a unique id for the prop list /// std::string m_Id; void ToPropertyList(); void FromPropertyList(); }; QmitkOpenCVVideoControls::QmitkOpenCVVideoControls(QmitkVideoBackground* _VideoBackground , QmitkRenderWindow* _RenderWindow , QWidget * parent, Qt::WindowFlags f) : QWidget(parent, f) , m_VideoBackground(nullptr) , m_RenderWindow(nullptr) , m_VideoSource(nullptr) , m_Controls(new Ui::QmitkOpenCVVideoControls) , m_SliderCurrentlyMoved(false) , d(new QmitkOpenCVVideoControlsPrivate(this, "QmitkOpenCVVideoControls")) { m_Controls->setupUi(this); m_Controls->FileChooser->SetFileMustExist(true); m_Controls->FileChooser->SetSelectDir(false); this->SetRenderWindow(_RenderWindow); this->SetVideoBackground(_VideoBackground); d->FromPropertyList(); mitk::IPersistenceService* persistenceService = d->GetPersistenceService(); if (persistenceService != nullptr) { persistenceService->AddPropertyListReplacedObserver(this); } else { MITK_WARN << "No Persistence Service available in constructor"; } } QmitkOpenCVVideoControls::~QmitkOpenCVVideoControls() { if(m_VideoSource != 0 && m_VideoSource->IsCapturingEnabled()) { this->Stop(); // emulate stop } mitk::IPersistenceService* persistenceService = d->GetPersistenceService(); if (persistenceService != nullptr) { persistenceService->RemovePropertyListReplacedObserver(this); } else { MITK_WARN << "No Persistence Service available in destructor"; } d->ToPropertyList(); } void QmitkOpenCVVideoControls::on_UseGrabbingDeviceButton_clicked(bool /*checked=false*/) { m_Controls->GrabbingDevicePanel->setEnabled(true); m_Controls->VideoFilePanel->setEnabled(false); } void QmitkOpenCVVideoControls::on_UseVideoFileButton_clicked(bool /*checked=false*/) { m_Controls->GrabbingDevicePanel->setEnabled(false); m_Controls->VideoFilePanel->setEnabled(true); m_Controls->FileChooser->setEnabled(true); } //void QmitkOpenCVVideoControls::on_VideoProgressSlider_sliderMoved( int value ) //{ // MITK_DEBUG << "progress bar slider clicked"; // double progressRatio = static_cast(value)/static_cast(m_Controls->VideoProgressSlider->maximum()); // MITK_DEBUG << "progressRatio" << progressRatio; // m_VideoSource->SetVideoCaptureProperty(CV_CAP_PROP_POS_AVI_RATIO, progressRatio); //} void QmitkOpenCVVideoControls::on_VideoProgressSlider_sliderPressed() { m_SliderCurrentlyMoved = true; // temporary pause the video while sliding if (!m_VideoSource->GetCapturePaused()) m_VideoSource->PauseCapturing(); MITK_DEBUG << "freezing video with old pos ratio: " << m_VideoSource->GetVideoCaptureProperty(CV_CAP_PROP_POS_AVI_RATIO); } void QmitkOpenCVVideoControls::on_VideoProgressSlider_sliderReleased() { double progressRatio = static_cast(m_Controls->VideoProgressSlider->value()) / static_cast(m_Controls->VideoProgressSlider->maximum()); m_VideoSource->SetVideoCaptureProperty(CV_CAP_PROP_POS_AVI_RATIO, progressRatio); MITK_DEBUG << "resuming video with new pos ratio: " << progressRatio; // resume the video ( if it was not paused by the user) if (m_VideoSource->GetCapturePaused() && m_Controls->PlayButton->isChecked()) m_VideoSource->PauseCapturing(); m_SliderCurrentlyMoved = false; } void QmitkOpenCVVideoControls::on_RepeatVideoButton_clicked(bool checked) { MITK_INFO << "repeat video clicked"; m_VideoSource->SetRepeatVideo(checked); } void QmitkOpenCVVideoControls::on_PlayButton_clicked(bool checked) { MITK_INFO << "play button clicked"; if (checked) { this->Play(); } else { // show pause button this->SwitchPlayButton(true); m_VideoSource->PauseCapturing(); } } void QmitkOpenCVVideoControls::on_StopButton_clicked(bool /*checked=false*/) { this->Stop(); } void QmitkOpenCVVideoControls::Play() { if (m_VideoSource->GetCapturePaused()) { this->SwitchPlayButton(false); m_VideoSource->PauseCapturing(); } else { if (m_Controls->UseGrabbingDeviceButton->isChecked()) { m_VideoSource->SetVideoCameraInput(m_Controls->GrabbingDeviceNumber->text().toInt(), false); m_Controls->VideoFileControls->setEnabled(false); } else { m_VideoSource->SetVideoFileInput(m_Controls->FileChooser->GetFile().c_str(), m_Controls->RepeatVideoButton->isChecked(), false); m_VideoSource->SetRepeatVideo(m_Controls->RepeatVideoButton->isChecked()); m_Controls->VideoProgressSlider->setValue(0); } m_VideoSource->StartCapturing(); if (!m_VideoSource->IsCapturingEnabled()) { MITK_ERROR << "Video could not be initialized!"; m_Controls->PlayButton->setChecked(false); } else { int hertz = m_Controls->UpdateRate->text().toInt(); int updateTime = itk::Math::Round(1000.0 / hertz); // resets the whole background m_VideoBackground->SetTimerDelay(updateTime); m_VideoBackground->AddRenderWindow(m_RenderWindow->GetVtkRenderWindow()); this->connect(m_VideoBackground, SIGNAL(NewFrameAvailable(mitk::VideoSource*)) , this, SLOT(NewFrameAvailable(mitk::VideoSource*))); this->connect(m_VideoBackground, SIGNAL(EndOfVideoSourceReached(mitk::VideoSource*)) , this, SLOT(EndOfVideoSourceReached(mitk::VideoSource*))); m_VideoBackground->Enable(); this->m_Controls->StopButton->setEnabled(true); // show video file controls if (m_Controls->UseVideoFileButton->isChecked()) { m_Controls->VideoFileControls->setEnabled(true); m_Controls->RepeatVideoButton->setEnabled(true); m_Controls->VideoProgressSlider->setEnabled(true); } // show pause button this->SwitchPlayButton(false); // disable other controls m_Controls->GrabbingDevicePanel->setEnabled(false); m_Controls->VideoFilePanel->setEnabled(false); m_Controls->UseGrabbingDeviceButton->setEnabled(false); m_Controls->UseVideoFileButton->setEnabled(false); m_Controls->UpdateRatePanel->setEnabled(false); } } } void QmitkOpenCVVideoControls::Stop() { // disable video file controls, stop button and show play button again m_Controls->UseGrabbingDeviceButton->setEnabled(true); m_Controls->UseVideoFileButton->setEnabled(true); if (m_Controls->UseGrabbingDeviceButton->isChecked()) on_UseGrabbingDeviceButton_clicked(true); else on_UseVideoFileButton_clicked(true); m_Controls->UpdateRatePanel->setEnabled(true); m_Controls->VideoFileControls->setEnabled(false); this->m_Controls->StopButton->setEnabled(false); this->SwitchPlayButton(true); if (m_VideoBackground) { m_VideoBackground->Disable(); if (m_RenderWindow) m_VideoBackground->RemoveRenderWindow(m_RenderWindow->GetVtkRenderWindow()); this->disconnect(m_VideoBackground, SIGNAL(NewFrameAvailable(mitk::VideoSource*)) , this, SLOT(NewFrameAvailable(mitk::VideoSource*))); } if (m_VideoSource != 0) m_VideoSource->StopCapturing(); } void QmitkOpenCVVideoControls::Reset() { this->Stop(); } void QmitkOpenCVVideoControls::SwitchPlayButton(bool paused) { if (paused) { m_Controls->PlayButton->setText("Play"); m_Controls->PlayButton->setIcon(QIcon(":/OpenCVVideoSupportUI/media-playback-start.png")); m_Controls->PlayButton->setChecked(false); } else { m_Controls->PlayButton->setText("Pause"); m_Controls->PlayButton->setIcon(QIcon(":/OpenCVVideoSupportUI/media-playback-pause.png")); m_Controls->PlayButton->setChecked(true); } } void QmitkOpenCVVideoControls::NewFrameAvailable(mitk::VideoSource* /*videoSource*/) { emit NewOpenCVFrameAvailable(m_VideoSource->GetCurrentFrame()); if (!m_SliderCurrentlyMoved) m_Controls->VideoProgressSlider->setValue(itk::Math::Round(m_VideoSource->GetVideoCaptureProperty(CV_CAP_PROP_POS_AVI_RATIO) *m_Controls->VideoProgressSlider->maximum())); } +void QmitkOpenCVVideoControls::EndOfVideoSourceReached(mitk::VideoSource* /*videoSource*/) +{ + if (m_Controls->RepeatVideoButton->isChecked()) + { + this->Reset(); + this->Play(); + } + else + { + this->Stop(); + } +} + void QmitkOpenCVVideoControls::SetRenderWindow(QmitkRenderWindow* _RenderWindow) { if (m_RenderWindow == _RenderWindow) return; // In Reset() m_MultiWidget is used, set it to 0 now for avoiding errors if (_RenderWindow == 0) m_RenderWindow = 0; this->Reset(); m_RenderWindow = _RenderWindow; if (m_RenderWindow == 0) { this->setEnabled(false); } else { this->setEnabled(true); } } QmitkRenderWindow* QmitkOpenCVVideoControls::GetRenderWindow() const { return m_RenderWindow; } void QmitkOpenCVVideoControls::SetVideoBackground(QmitkVideoBackground* _VideoBackground) { if (m_VideoBackground == _VideoBackground) return; if (m_VideoBackground != nullptr) this->disconnect(m_VideoBackground, SIGNAL(destroyed(QObject*)) , this, SLOT(QObjectDestroyed(QObject*))); this->Reset(); m_VideoBackground = _VideoBackground; if (m_VideoBackground == nullptr) { m_VideoSource = 0; MITK_WARN << "m_MultiWidget is 0"; this->setEnabled(false); } else { this->setEnabled(true); m_VideoSource = dynamic_cast(m_VideoBackground->GetVideoSource()); // preset form entries if (m_VideoSource != nullptr) { if (!m_VideoSource->GetVideoFileName().empty()) { m_Controls->FileChooser->SetFile(m_VideoSource->GetVideoFileName()); on_UseGrabbingDeviceButton_clicked(false); } else if (m_VideoSource->GetGrabbingDeviceNumber() >= 0) m_Controls->GrabbingDeviceNumber->setValue(m_VideoSource->GetGrabbingDeviceNumber()); m_Controls->UpdateRate->setValue(m_VideoBackground->GetTimerDelay()); this->connect(m_VideoBackground, SIGNAL(destroyed(QObject*)) , this, SLOT(QObjectDestroyed(QObject*))); } else { MITK_WARN << "m_VideoSource is 0"; this->setEnabled(false); } } } QmitkVideoBackground* QmitkOpenCVVideoControls::GetVideoBackground() const { return m_VideoBackground; } void QmitkOpenCVVideoControls::QObjectDestroyed(QObject * obj /*= 0 */) { if (m_VideoBackground == obj) { m_VideoSource = nullptr; this->SetVideoBackground(nullptr); } } void QmitkOpenCVVideoControlsPrivate::ToPropertyList() { mitk::IPersistenceService* persistenceService = this->GetPersistenceService(); if (persistenceService != nullptr) { mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(m_Id); propList->Set("deviceType", q->m_Controls->UseGrabbingDeviceButton->isChecked() ? 0 : 1); propList->Set("grabbingDeviceNumber", q->m_Controls->GrabbingDeviceNumber->value()); propList->Set("updateRate", q->m_Controls->UpdateRate->value()); propList->Set("repeatVideo", q->m_Controls->RepeatVideoButton->isChecked()); } else { MITK_WARN << "Persistence Service not available."; } } void QmitkOpenCVVideoControlsPrivate::FromPropertyList() { mitk::IPersistenceService* persistenceService = this->GetPersistenceService(); if (persistenceService != nullptr) { mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(m_Id); bool repeatVideo = false; propList->Get("repeatVideo", repeatVideo); q->m_Controls->RepeatVideoButton->setChecked(repeatVideo); int updateRate = 25; propList->Get("updateRate", updateRate); q->m_Controls->UpdateRate->setValue(updateRate); int grabbingDeviceNumber = 0; propList->Get("grabbingDeviceNumber", grabbingDeviceNumber); q->m_Controls->GrabbingDeviceNumber->setValue(grabbingDeviceNumber); int deviceType = 0; propList->Get("deviceType", deviceType); if (deviceType == 0) { q->m_Controls->UseGrabbingDeviceButton->setChecked(true); } else { q->m_Controls->UseVideoFileButton->setChecked(true); } } else { MITK_WARN << "Persistence Service not available."; } } void QmitkOpenCVVideoControls::AfterPropertyListReplaced(const std::string& id, mitk::PropertyList* /*propertyList*/) { if (id == d->m_Id) d->FromPropertyList(); } diff --git a/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.h b/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.h index 82f509b22c..17fc693eeb 100644 --- a/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.h +++ b/Modules/OpenCVVideoSupport/UI/QmitkOpenCVVideoControls.h @@ -1,117 +1,119 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkOpenCVVideoControls_h #define QmitkOpenCVVideoControls_h #include #include #include #include class QmitkRenderWindow; class QmitkVideoBackground; namespace mitk { class VideoSource; class OpenCVVideoSource; } class QmitkOpenCVVideoControlsPrivate; /// /// \brief Offers widgets to play/pause/stop a video on a certain render window with /// the use of an !initialized! QmitkVideoBackground. The QmitkVideoBackground should /// contain an OpenCVVideoSource is then owned by this widget (and deleted) /// class MITKOPENCVVIDEOSUPPORTUI_EXPORT QmitkOpenCVVideoControls : public QWidget, public mitk::PropertyListReplacedObserver { Q_OBJECT public: /// /// Construct the widget with the given render window and the given preset values /// QmitkOpenCVVideoControls(QmitkVideoBackground* _VideoBackground, QmitkRenderWindow* _RenderWindow , QWidget* parent = 0, Qt::WindowFlags f = 0); /// /// call reset if video playback is enabled here /// virtual ~QmitkOpenCVVideoControls(); /// /// sets the render window for this video player /// void SetRenderWindow(QmitkRenderWindow* _RenderWindow); /// /// returns the current render window /// QmitkRenderWindow* GetRenderWindow() const; /// /// sets the qmitkvideobackground for this /// void SetVideoBackground(QmitkVideoBackground* _VideoBackground); /// /// returns the current QmitkVideoBackground /// QmitkVideoBackground* GetVideoBackground() const; /// /// calls FromPropertyList /// void AfterPropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) override; signals: /// /// When playback is started this informs when a new frame was grabbed /// void NewOpenCVFrameAvailable(const IplImage*); protected slots: void on_UseGrabbingDeviceButton_clicked(bool checked=false); void on_UseVideoFileButton_clicked(bool checked=false); void on_VideoProgressSlider_sliderPressed(); void on_VideoProgressSlider_sliderReleased(); void on_RepeatVideoButton_clicked( bool checked=false ); void on_PlayButton_clicked(bool checked=false); void on_StopButton_clicked(bool checked=false); void Play(); void Stop(); void Reset(); void SwitchPlayButton(bool paused); void QObjectDestroyed( QObject * obj = 0 ); void NewFrameAvailable(mitk::VideoSource* videoSource); + void EndOfVideoSourceReached(mitk::VideoSource* videoSource); + protected: QmitkVideoBackground* m_VideoBackground; QmitkRenderWindow* m_RenderWindow; mitk::OpenCVVideoSource* m_VideoSource; Ui::QmitkOpenCVVideoControls* m_Controls; bool m_SliderCurrentlyMoved; private: friend class QmitkOpenCVVideoControlsPrivate; QScopedPointer d; }; #endif diff --git a/Modules/QtWidgetsExt/include/QmitkVideoBackground.h b/Modules/QtWidgetsExt/include/QmitkVideoBackground.h index 9e5682353d..5c4d43ecc3 100644 --- a/Modules/QtWidgetsExt/include/QmitkVideoBackground.h +++ b/Modules/QtWidgetsExt/include/QmitkVideoBackground.h @@ -1,207 +1,209 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _Qmitk_Video_Background_h_ #define _Qmitk_Video_Background_h_ // MITK #include "mitkVideoSource.h" #include "MitkQtWidgetsExtExports.h" // Qt #include class QTimer; // vtk class vtkRenderer; class vtkRenderWindow; class vtkImageActor; class vtkImageImport; class vtkActor2D; class vtkVideoSizeCallback; class vtkObject; /** * Displays a 3-channel (!) video data in the background * of one or more vtkRenderWindow(s). * The video is provided by a mitkVideoSource / GetVideoTexture(). * Caution: As the texture data is not being copied, the user is responsible for a valid * pointer to the data. Also the image dimensions needs to be set correctly before enabling the * background. */ class MITKQTWIDGETSEXT_EXPORT QmitkVideoBackground : public QObject { Q_OBJECT public: /// /// default ctor, TimerDelay is 40 by default /// you must SetVideoSource() and AddRenderWindow() afterwards /// explicit QmitkVideoBackground(QObject* parent = nullptr); /// /// constructs a video background with the given video source /// no parent is set here, dont forget to delete the object or /// call setParent() /// TimerDelay = refresh rate of video in ms (25 ms = 40 Hz). /// you must call AddRenderWindow() afterwards /// explicit QmitkVideoBackground(mitk::VideoSource* v, int TimerDelay = 25); /// /// disables all video backgrounds /// virtual ~QmitkVideoBackground(); /// /// \brief add a RenderWindow in which the video is displayed. /// -> must be initialized before enabling the background. /// if the renderwindow was previously inserted it will get /// re-inserted (restarted videobackground) /// *ATTENTION*: to size the renderwindow correctly GetImageWidth() of the video /// source will be called and if *no size is returned: FetchFrame() /// on the video source will be called to get the first frame and /// the corresponding size* /// void AddRenderWindow(vtkRenderWindow* renderWindow); /// /// \brief removes a renderwindow = disables video background there /// void RemoveRenderWindow(vtkRenderWindow* renderWindow); /// /// \return true if "renderWindow" is currently connected to the video /// background or not /// bool IsRenderWindowIncluded(vtkRenderWindow* renderWindow); /// /// \brief sets the update rate of the video in milli seconds, by default 25. /// void SetTimerDelay(int ms); /// /// visualizes the video. Requires image dimensions and an active videosource to be set. /// void Enable(); /// /// \brief disables visualization of the video. /// void Disable(); /// /// \brief Checks, if the Video background is currently enabled (visible). /// bool IsEnabled(); /// /// Returns the videosource attached to this background /// mitk::VideoSource* GetVideoSource(); /// /// Returns the timer delay /// int GetTimerDelay(); /// /// pauses the playback (stops the update timer) /// void Pause(); /// /// resumes the playback (restarts the update timer) /// void Resume(); /// /// sets a *new* video source (if previously enabled, this will stop /// the video background if it was previously enabled /// void SetVideoSource(mitk::VideoSource* videoSource); /// /// receive renderwindow delete events /// static void OnRenderWindowDelete(vtkObject*, unsigned long eid , void* clientdata, void* /*calldata*/); /// /// receive VideoSource delete event /// void OnVideoSourceDelete(const itk::Object* caller , const itk::EventObject &event); public slots: /// /// update all video backgrounds. (called by the timer or manually /// by the user) /// void UpdateVideo(); signals: /// /// emitted after all video backgrounds are filled with the new /// video frame /// void NewFrameAvailable(mitk::VideoSource*); + void EndOfVideoSourceReached(mitk::VideoSource*); + protected: /// /// class for holding all vtk dependencies /// needed to do background image rendering /// struct VideoBackgroundVectorInfo { vtkRenderWindow* renWin; vtkRenderer* videoRenderer; vtkImageActor* videoActor; vtkImageImport* videoImport; unsigned long renderWindowObserverTag; }; /// /// removes the renderwindow and also removes the observer if the flag is set /// void RemoveRenderWindow(vtkRenderWindow* renderWindow, bool removeObserver); /// /// reset all video backgrounds /// void ResetVideoBackground(); /// /// inits all renderwindows with default values, called before video rendering is started /// void Modified(); /// /// the class has to store a list of renderwindows /// typedef std::vector RenderWindowVectorInfoType; protected: /// /// a list of renderwindows and associated renderers and actors and imageimporters /// RenderWindowVectorInfoType m_renderWindowVectorInfo; /// /// calls updatevideo repeateadly for framegrabbing /// QTimer* m_QTimer; /// /// must implement GetVideoTexture() correctly (must return an OpenGL texture) /// mitk::VideoSource* m_VideoSource; /// /// the observer tag for the video source /// unsigned long m_VideoSourceObserverTag; }; #endif diff --git a/Modules/QtWidgetsExt/src/QmitkVideoBackground.cpp b/Modules/QtWidgetsExt/src/QmitkVideoBackground.cpp index 386b8acdf4..3a305549b6 100644 --- a/Modules/QtWidgetsExt/src/QmitkVideoBackground.cpp +++ b/Modules/QtWidgetsExt/src/QmitkVideoBackground.cpp @@ -1,303 +1,314 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkVideoBackground.h" // MITK includes #include "mitkVtkLayerController.h" #include "mitkRenderingManager.h" // QT includes #include // itk includes #include // VTK includes #include #include #include #include #include #include #include #include #include #include #include #include QmitkVideoBackground::QmitkVideoBackground( QObject *parent ) : QObject(parent) , m_QTimer(new QTimer(this)) , m_VideoSource(nullptr) , m_VideoSourceObserverTag(0) { this->ResetVideoBackground(); } QmitkVideoBackground::QmitkVideoBackground(mitk::VideoSource* v, int) : QObject(nullptr) , m_QTimer(new QTimer(this)) , m_VideoSource(nullptr) , m_VideoSourceObserverTag(0) { this->SetVideoSource( v ); this->ResetVideoBackground(); } void QmitkVideoBackground::ResetVideoBackground() { m_QTimer->setInterval(25); connect( m_QTimer, SIGNAL(timeout()), SLOT(UpdateVideo()) ); m_renderWindowVectorInfo.clear(); } QmitkVideoBackground::~QmitkVideoBackground() { this->Disable(); } void QmitkVideoBackground::AddRenderWindow(vtkRenderWindow* renderWindow ) { if(!renderWindow || !m_VideoSource) { MITK_WARN << "No Renderwindow or VideoSource set!"; return; } this->RemoveRenderWindow(renderWindow); vtkRenderer* videoRenderer = vtkRenderer::New(); vtkImageActor* videoActor = vtkImageActor::New(); vtkImageImport* videoImport = vtkImageImport::New(); videoImport->SetDataScalarTypeToUnsignedChar(); videoImport->SetNumberOfScalarComponents(3); if(m_VideoSource->GetImageWidth() == 0) m_VideoSource->FetchFrame(); videoImport->SetWholeExtent(0, m_VideoSource->GetImageWidth()-1, 0, m_VideoSource->GetImageHeight()-1, 0, 1-1); videoImport->SetDataExtentToWholeExtent(); VideoBackgroundVectorInfo v; v.renWin = renderWindow; v.videoRenderer = videoRenderer; v.videoActor = videoActor; v.videoImport = videoImport; // callback for the deletion of the renderwindow vtkSmartPointer deleteCallback = vtkSmartPointer::New(); deleteCallback->SetCallback ( QmitkVideoBackground::OnRenderWindowDelete ); deleteCallback->SetClientData(this); v.renderWindowObserverTag = renderWindow->AddObserver( vtkCommand::DeleteEvent, deleteCallback ); m_renderWindowVectorInfo.push_back(v); // completes the initialization this->Modified(); } void QmitkVideoBackground::RemoveRenderWindow( vtkRenderWindow* renderWindow ) { this->RemoveRenderWindow(renderWindow, true); } void QmitkVideoBackground::RemoveRenderWindow( vtkRenderWindow* renderWindow, bool removeObserver ) { // search for renderwindow and remove it for(auto it = m_renderWindowVectorInfo.begin(); it != m_renderWindowVectorInfo.end(); it++) { if((*it).renWin == renderWindow) { mitk::VtkLayerController* layerController = mitk::VtkLayerController::GetInstance((*it).renWin); // unregister video backround renderer from renderwindow if( layerController ) layerController->RemoveRenderer((*it).videoRenderer); (*it).videoRenderer->Delete(); (*it).videoActor->Delete(); (*it).videoImport->Delete(); // remove listener if(removeObserver) renderWindow->RemoveObserver( (*it).renderWindowObserverTag ); m_renderWindowVectorInfo.erase(it); break; } } } bool QmitkVideoBackground::IsRenderWindowIncluded(vtkRenderWindow* renderWindow ) { for(auto it = m_renderWindowVectorInfo.begin(); it != m_renderWindowVectorInfo.end(); it++) { if((*it).renWin == renderWindow) return true; } return false; } void QmitkVideoBackground::Pause() { m_QTimer->stop(); } void QmitkVideoBackground::Resume() { m_QTimer->start(); } /** * Enables drawing of the color Video background. * If you want to disable it, call the Disable() function. */ void QmitkVideoBackground::Enable() { UpdateVideo(); Modified(); m_QTimer->start(); } /** * Disables drawing of the color Video background. * If you want to enable it, call the Enable() function. */ void QmitkVideoBackground::Disable() { if ( this->IsEnabled() ) { mitk::VtkLayerController* layerController = nullptr; for(auto it = m_renderWindowVectorInfo.begin(); it != m_renderWindowVectorInfo.end(); it++) { layerController = mitk::VtkLayerController::GetInstance((*it).renWin); if(layerController) layerController->RemoveRenderer((*it).videoRenderer); } m_QTimer->stop(); } } bool QmitkVideoBackground::IsEnabled() { return m_QTimer->isActive(); } void QmitkVideoBackground::UpdateVideo() { if( m_renderWindowVectorInfo.size() > 0 ) { unsigned char *src = nullptr; - src = m_VideoSource->GetVideoTexture(); + + try + { + src = m_VideoSource->GetVideoTexture(); + } + catch (const std::logic_error& error) + { + MITK_DEBUG << error.what(); + emit EndOfVideoSourceReached(m_VideoSource); + return; + } + if(src) { for(auto it = m_renderWindowVectorInfo.begin(); it != m_renderWindowVectorInfo.end(); it++) { (*it).videoImport->SetImportVoidPointer(src); (*it).videoImport->Modified(); (*it).videoImport->Update(); mitk::RenderingManager::GetInstance()->RequestUpdate((*it).renWin); } emit NewFrameAvailable ( m_VideoSource ); } else MITK_WARN << "No video texture available"; } } void QmitkVideoBackground::Modified() { // ensures registration of video backrounds in each renderwindow for(auto it = m_renderWindowVectorInfo.begin(); it != m_renderWindowVectorInfo.end(); it++) { (*it).videoImport->Update(); (*it).videoActor->SetInputData((*it).videoImport->GetOutput()); (*it).videoRenderer->AddActor2D((*it).videoActor); (*it).videoRenderer->ResetCamera(); (*it).videoRenderer->InteractiveOff(); (*it).videoRenderer->GetActiveCamera()->ParallelProjectionOn(); (*it).videoRenderer->GetActiveCamera()->SetParallelScale(m_VideoSource->GetImageHeight()/2); mitk::VtkLayerController* layerController = mitk::VtkLayerController::GetInstance((*it).renWin); if( layerController && !layerController->IsRendererInserted((*it).videoRenderer) ) layerController->InsertBackgroundRenderer((*it).videoRenderer,true); } } void QmitkVideoBackground::SetVideoSource( mitk::VideoSource* videoSource ) { if( m_VideoSource == videoSource ) return; if( m_VideoSource ) m_VideoSource->RemoveObserver( m_VideoSourceObserverTag ); m_VideoSource = videoSource; if( m_VideoSource ) { itk::MemberCommand::Pointer _ModifiedCommand = itk::MemberCommand::New(); _ModifiedCommand->SetCallbackFunction(this, &QmitkVideoBackground::OnVideoSourceDelete); m_VideoSourceObserverTag = m_VideoSource->AddObserver(itk::DeleteEvent(), _ModifiedCommand); } } void QmitkVideoBackground::SetTimerDelay( int ms ) { m_QTimer->setInterval( ms ); } mitk::VideoSource* QmitkVideoBackground::GetVideoSource() { return m_VideoSource; } int QmitkVideoBackground::GetTimerDelay() { return m_QTimer->interval(); } void QmitkVideoBackground::OnVideoSourceDelete(const itk::Object*, const itk::EventObject&) { this->Disable(); // will only disable if enabled m_VideoSource = nullptr; } void QmitkVideoBackground::OnRenderWindowDelete( vtkObject * object, unsigned long, void* clientdata, void*) { QmitkVideoBackground* instance = static_cast( clientdata ); instance->RemoveRenderWindow( static_cast(object), false ); }