Fraxinus  18.10
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  report(QString("Starting streamer: [%1]").arg(this->hostDescription()));
50 
51  if(!mImageStreamer)
52  {
53  return false;
54  }
55  mSender.reset(new DirectlyLinkedSender());
56 
57  connect(mSender.get(), &DirectlyLinkedSender::newImage, this, &ImageReceiverThread::addImageToQueueSlot, Qt::DirectConnection);
58  connect(mSender.get(), &DirectlyLinkedSender::newUSStatus, this, &ImageReceiverThread::addSonixStatusToQueueSlot, Qt::DirectConnection);
59 
60  mImageStreamer->startStreaming(mSender);
61 
62  return true;
63 }
64 
66 {
67  if (mImageStreamer)
68  {
69  report(QString("Stopping streamer: [%1]...").arg(this->hostDescription()));
70  mImageStreamer->stopStreaming();
71  report(QString("Stopped streamer: [%1]").arg(this->hostDescription()));
72  mImageStreamer.reset();
73  mSender.reset();
74  }
75 
76  emit finished();
77 }
78 
79 void ImageReceiverThread::addImageToQueueSlot()
80 {
81  this->addImageToQueue(mSender->popImage());
82 }
83 
84 void ImageReceiverThread::addSonixStatusToQueueSlot()
85 {
86  this->addSonixStatusToQueue(mSender->popUSStatus());
87 }
88 
89 
91 {
92  this->reportFPS(imgMsg->getUid());
93 
94 // bool needToCalibrateMsgTimeStamp = this->imageComesFromSonix(imgMsg);
95 
96 // moved to IGTLinkClientStreamer
97 // //Should only be needed if time stamp is set on another computer that is
98 // //not synched with the one running this code: e.g. The Ultrasonix scanner
99 // if (needToCalibrateMsgTimeStamp)
100 // mStreamSynchronizer.syncToCurrentTime(imgMsg);
101 
102  QMutexLocker sentry(&mImageMutex);
103  mMutexedImageMessageQueue.push_back(imgMsg);
104  sentry.unlock();
105 
106  emit imageReceived(); // emit signal outside lock, catch possibly in another thread
107 }
108 
110 {
111  QMutexLocker sentry(&mSonixStatusMutex);
112  mMutexedSonixStatusMessageQueue.push_back(msg);
113  sentry.unlock();
114  emit sonixStatusReceived(); // emit signal outside lock, catch possibly in another thread
115 }
116 
118 {
119  QMutexLocker sentry(&mImageMutex);
120  if (mMutexedImageMessageQueue.empty())
121  return ImagePtr();
122  ImagePtr retval = mMutexedImageMessageQueue.front();
123  mMutexedImageMessageQueue.pop_front();
124 
125  return retval;
126 }
127 
129 {
130  QMutexLocker sentry(&mSonixStatusMutex);
131  if (mMutexedSonixStatusMessageQueue.empty())
132  return ProbeDefinitionPtr();
133  ProbeDefinitionPtr retval = mMutexedSonixStatusMessageQueue.front();
134  mMutexedSonixStatusMessageQueue.pop_front();
135  return retval;
136 }
137 
138 void ImageReceiverThread::reportFPS(QString streamUid)
139 {
140  int timeout = 2000;
141  if (!mFPSTimer.count(streamUid))
142  {
143  mFPSTimer[streamUid].reset(new CyclicActionLogger());
144  mFPSTimer[streamUid]->reset(timeout);
145  }
146 
147  CyclicActionLoggerPtr logger = mFPSTimer[streamUid];
148 
149  logger->begin();
150  if (logger->intervalPassed())
151  {
152  emit fps(streamUid, logger->getFPS());
153  logger->reset(timeout);
154  }
155 }
156 
157 //bool ImageReceiverThread::imageComesFromSonix(ImagePtr imgMsg)
158 //{
159 // return imgMsg->getUid().contains("Sonix", Qt::CaseInsensitive);
160 //}
161 
163 {
164  if (!mStreamerInterface)
165  return "none";
166  return mStreamerInterface->getName();
167 }
168 
169 
170 } /* 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.