CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxImageReceiverThread.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxImageReceiverThread.h"
13 
14 #include "cxCyclicActionLogger.h"
15 #include "cxXmlOptionItem.h"
16 #include "cxStreamer.h"
17 #include "cxStreamerService.h"
18 #include "cxDirectlyLinkedSender.h"
19 #include "cxLogger.h"
20 #include "cxProfile.h"
21 
22 namespace cx
23 {
24 
25 ImageReceiverThread::ImageReceiverThread(StreamerServicePtr streamerInterface, QObject* parent) :
26  QObject(parent),
27  mStreamerInterface(streamerInterface)
28 {
29  this->setObjectName("imagereceiver worker");
30 }
31 
33 {
34  if (!this->attemptInitialize())
35  {
36  // cleanup here in order to do less in the destructor... ??
37  mImageStreamer.reset();
38  mSender.reset();
39 
40  emit finished();
41  }
42 }
43 
44 bool ImageReceiverThread::attemptInitialize()
45 {
46  XmlOptionFile xmlFile = profile()->getXmlSettings().descend("video");
47  QDomElement element = xmlFile.getElement("video");
48  mImageStreamer = mStreamerInterface->createStreamer(element);
49 
50  if(!mImageStreamer)
51  {
52  return false;
53  }
54 
55  report(QString("Starting streamer: [%1]").arg(this->hostDescription()));
56 
57  mSender.reset(new DirectlyLinkedSender());
58 
59  connect(mSender.get(), &DirectlyLinkedSender::newImage, this, &ImageReceiverThread::addImageToQueueSlot, Qt::DirectConnection);
60  connect(mSender.get(), &DirectlyLinkedSender::newUSStatus, this, &ImageReceiverThread::addSonixStatusToQueueSlot, Qt::DirectConnection);
61 
62  mImageStreamer->startStreaming(mSender);
63 
64  return true;
65 }
66 
68 {
69  if (mImageStreamer)
70  {
71  report(QString("Stopping streamer: [%1]...").arg(this->hostDescription()));
72  mImageStreamer->stopStreaming();
73  report(QString("Stopped streamer: [%1]").arg(this->hostDescription()));
74  mImageStreamer.reset();
75  mSender.reset();
76  }
77 
78  emit finished();
79 }
80 
81 void ImageReceiverThread::addImageToQueueSlot()
82 {
83  this->addImageToQueue(mSender->popImage());
84 }
85 
86 void ImageReceiverThread::addSonixStatusToQueueSlot()
87 {
88  this->addSonixStatusToQueue(mSender->popUSStatus());
89 }
90 
91 
93 {
94  this->reportFPS(imgMsg->getUid());
95 
96 // bool needToCalibrateMsgTimeStamp = this->imageComesFromSonix(imgMsg);
97 
98 // moved to IGTLinkClientStreamer
99 // //Should only be needed if time stamp is set on another computer that is
100 // //not synched with the one running this code: e.g. The Ultrasonix scanner
101 // if (needToCalibrateMsgTimeStamp)
102 // mStreamSynchronizer.syncToCurrentTime(imgMsg);
103 
104  QMutexLocker sentry(&mImageMutex);
105  mMutexedImageMessageQueue.push_back(imgMsg);
106  sentry.unlock();
107 
108  emit imageReceived(); // emit signal outside lock, catch possibly in another thread
109 }
110 
112 {
113  QMutexLocker sentry(&mSonixStatusMutex);
114  mMutexedSonixStatusMessageQueue.push_back(msg);
115  sentry.unlock();
116  emit sonixStatusReceived(); // emit signal outside lock, catch possibly in another thread
117 }
118 
120 {
121  QMutexLocker sentry(&mImageMutex);
122  if (mMutexedImageMessageQueue.empty())
123  return ImagePtr();
124  ImagePtr retval = mMutexedImageMessageQueue.front();
125  mMutexedImageMessageQueue.pop_front();
126 
127  return retval;
128 }
129 
131 {
132  QMutexLocker sentry(&mSonixStatusMutex);
133  if (mMutexedSonixStatusMessageQueue.empty())
134  return ProbeDefinitionPtr();
135  ProbeDefinitionPtr retval = mMutexedSonixStatusMessageQueue.front();
136  mMutexedSonixStatusMessageQueue.pop_front();
137  return retval;
138 }
139 
140 void ImageReceiverThread::reportFPS(QString streamUid)
141 {
142  int timeout = 2000;
143  if (!mFPSTimer.count(streamUid))
144  {
145  mFPSTimer[streamUid].reset(new CyclicActionLogger());
146  mFPSTimer[streamUid]->reset(timeout);
147  }
148 
149  CyclicActionLoggerPtr logger = mFPSTimer[streamUid];
150 
151  logger->begin();
152  if (logger->intervalPassed())
153  {
154  emit fps(streamUid, logger->getFPS());
155  logger->reset(timeout);
156  }
157 }
158 
159 //bool ImageReceiverThread::imageComesFromSonix(ImagePtr imgMsg)
160 //{
161 // return imgMsg->getUid().contains("Sonix", Qt::CaseInsensitive);
162 //}
163 
165 {
166  if (!mStreamerInterface)
167  return "none";
168  return mStreamerInterface->getName();
169 }
170 
171 
172 } /* namespace cx */
boost::shared_ptr< class CyclicActionLogger > CyclicActionLoggerPtr
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
void fps(QString, double)
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
QDomElement getElement()
return the current element
virtual ImagePtr getLastImageMessage()
void addSonixStatusToQueue(ProbeDefinitionPtr msg)
add the message to a thread-safe queue
virtual QString hostDescription() const
ImageReceiverThread(StreamerServicePtr streamerInterface, QObject *parent=NULL)
void report(QString msg)
Definition: cxLogger.cpp:69
virtual ProbeDefinitionPtr getLastSonixStatusMessage()
boost::shared_ptr< class StreamerService > StreamerServicePtr
void addImageToQueue(ImagePtr imgMsg)
boost::shared_ptr< class ProbeDefinition > ProbeDefinitionPtr
Helper class for xml files used to store ssc/cx data.
Namespace for all CustusX production code.