NorMIT-nav  2023.01.05-dev+develop.0da12
An IGT application
cxSavingVideoRecorder.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 "cxSavingVideoRecorder.h"
13 
14 #include <QDir>
15 #include <QFile>
16 #include <QFileInfo>
17 #include <QTextStream>
18 
19 #include <vtkImageChangeInformation.h>
20 #include <vtkImageLuminance.h>
21 #include <vtkImageData.h>
22 #include "vtkImageAppend.h"
23 #include "vtkMetaImageWriter.h"
24 
25 #include "cxTypeConversions.h"
26 #include "cxLogger.h"
27 #include "cxSettings.h"
28 #include "cxXmlOptionItem.h"
29 #include "cxImageDataContainer.h"
30 #include "cxVideoSource.h"
31 
32 namespace cx
33 {
34 
35 VideoRecorderSaveThread::VideoRecorderSaveThread(QObject* parent, QString saveFolder, QString prefix, bool compressed, bool writeColor) :
36  QThread(parent),
37  mSaveFolder(saveFolder),
38  mPrefix(prefix),
39  mImageIndex(0),
40  mMutex(QMutex::Recursive),
41  mStop(false),
42  mCancel(false),
43  mTimestampsFile(saveFolder+"/"+prefix+".fts"),
44  mCompressed(compressed),
45  mWriteColor(writeColor)
46 {
47  this->setObjectName("org.custusx.resource.videorecordersave"); // becomes the thread name
48 }
49 
51 {
52 }
53 
55 {
56  if (!image)
57  return "";
58 
59  DataType data;
60  data.mTimestamp = timestamp;
61  data.mImage = vtkImageDataPtr::New();
62  data.mImage->DeepCopy(image);
63  data.mImageFilename = QString("%1/%2_%3.mhd").arg(mSaveFolder).arg(mPrefix).arg(mImageIndex++);
64 
65  {
66  QMutexLocker sentry(&mMutex);
67  mPendingData.push_back(data);
68  }
69 
70  return data.mImageFilename;
71 }
72 
74 {
75  mStop = true;
76 }
77 
79 {
80  mCancel = true;
81  mStop = true;
82 }
83 
85 {
86  if(!mTimestampsFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
87  {
88  reportError("Cannot open "+mTimestampsFile.fileName());
89  return false;
90  }
91  return true;
92 }
93 
94 
96 {
97  mTimestampsFile.close();
98 
99 // QFileInfo info(mTimestampsFile);
100 // if (!mCancel)
101 // {
102 // report(QString("Saved %1 timestamps to file %2")
103 // .arg(mImageIndex)
104 // .arg(info.fileName()));
105 // }
106  return true;
107 }
108 
110 {
111  this->writeTimeStampsFile(data.mTimestamp);
112 
113  // convert to 8 bit data if applicable.
114  if (!mWriteColor && data.mImage->GetNumberOfScalarComponents()>2)
115  {
116  vtkSmartPointer<vtkImageLuminance> luminance = vtkSmartPointer<vtkImageLuminance>::New();
117  luminance->SetInputData(data.mImage);
118  luminance->Update();
119  data.mImage = luminance->GetOutput();
120 // data.mImage->Update();
121  }
122 
123  // write image
124  vtkMetaImageWriterPtr writer = vtkMetaImageWriterPtr::New();
125  writer->SetInputData(data.mImage);
126  writer->SetFileName(cstring_cast(data.mImageFilename));
127  writer->SetCompression(mCompressed);
128  writer->Write();
129 }
130 
132 {
133  QTextStream stream(&mTimestampsFile);
134  stream << qstring_cast(timeStamps.getAcquisitionTime());
135  stream << endl;
136 }
137 
142 {
143  while(!mPendingData.empty())
144  {
145  if (mCancel)
146  return;
147 
148  DataType current;
149 
150  {
151  QMutexLocker sentry(&mMutex);
152  current = mPendingData.front();
153  mPendingData.pop_front();
154  }
155 
156  this->write(current);
157  }
158 }
159 
161 {
162  this->openTimestampsFile();
163  while (!mStop)
164  {
165  this->writeQueue();
166  this->msleep(20);
167  }
168 
169  this->writeQueue();
170  this->closeTimestampsFile();
171 }
172 
173 //---------------------------------------------------------
174 //---------------------------------------------------------
175 //---------------------------------------------------------
176 
177 
178 SavingVideoRecorder::SavingVideoRecorder(VideoSourcePtr source, QString saveFolder, QString prefix, bool compressed, bool writeColor, FileManagerServicePtr filemanagerservice) :
179 // mLastPurgedImageIndex(-1),
180  mSource(source)
181 {
182  mImages.reset(new cx::CachedImageDataContainer(filemanagerservice));
183  mImages->setDeleteFilesOnRelease(true);
184 
185  mPrefix = prefix;
186  mSaveFolder = saveFolder;
187  mSaveThread.reset(new VideoRecorderSaveThread(NULL, saveFolder, prefix, compressed, writeColor));
188  mSaveThread->start();
189 }
190 
192 {
193  mSaveThread->cancel();
194  mSaveThread->wait(); // wait indefinitely for thread to finish
195 }
196 
198 {
199  connect(mSource.get(), &VideoSource::newFrame, this, &SavingVideoRecorder::newFrameSlot);
200 }
201 
203 {
204  disconnect(mSource.get(), &VideoSource::newFrame, this, &SavingVideoRecorder::newFrameSlot);
205 }
206 
207 void SavingVideoRecorder::newFrameSlot()
208 {
209  if (!mSource->validData())
210  return;
211 
212  vtkImageDataPtr image = mSource->getVtkImageData();
213  TimeInfo timestamp = mSource->getAdvancedTimeInfo();
214  QString filename = mSaveThread->addData(timestamp, image);
215 
216  mImages->append(filename);
217  mTimestamps.push_back(timestamp);
218 }
219 
221 {
222  return mImages;
223 }
224 
225 std::vector<TimeInfo> SavingVideoRecorder::getTimestamps()
226 {
227  return mTimestamps;
228 }
229 
231 {
232  this->stopRecord();
233 
234  mSaveThread->cancel();
235  mSaveThread->wait(); // wait indefinitely for thread to finish
236 
237  this->deleteFolder(mSaveFolder);
238 }
239 
242 void SavingVideoRecorder::deleteFolder(QString folder)
243 {
244  QStringList filters;
245  filters << "*.fts" << "*.mhd" << "*.raw" << "*.zraw";
246  for (int i=0; i<filters.size(); ++i) // prepend prefix, ensuring files from other savers are not deleted.
247  filters[i] = mPrefix + filters[i];
248 
249  QDir dir(folder);
250  QStringList files = dir.entryList(filters);
251 
252  for (int i=0; i<files.size(); ++i)
253  dir.remove(files[i]);
254  dir.rmdir(folder);
255 }
256 
258 {
259  mSaveThread->stop();
260  mSaveThread->wait(); // wait indefinitely for thread to finish
261 }
262 
263 } // namespace cx
264 
265 
cx::VideoSource::newFrame
void newFrame()
emitted when a new frame has arrived (getVtkImageData() returns something new). info/status/name/vali...
cx::VideoRecorderSaveThread
Definition: cxSavingVideoRecorder.h:48
cxLogger.h
qstring_cast
QString qstring_cast(const T &val)
Definition: cxTypeConversions.h:46
cx::VideoRecorderSaveThread::mStop
bool mStop
Definition: cxSavingVideoRecorder.h:76
cx::VideoRecorderSaveThread::mCompressed
bool mCompressed
Definition: cxSavingVideoRecorder.h:79
cx::VideoRecorderSaveThread::mSaveFolder
QString mSaveFolder
Definition: cxSavingVideoRecorder.h:71
cx::VideoRecorderSaveThread::writeTimeStampsFile
void writeTimeStampsFile(TimeInfo timeStamps)
Definition: cxSavingVideoRecorder.cpp:131
cx::VideoRecorderSaveThread::DataType::mTimestamp
TimeInfo mTimestamp
Definition: cxSavingVideoRecorder.h:67
cx::VideoRecorderSaveThread::addData
QString addData(TimeInfo timestamp, vtkImageDataPtr data)
Definition: cxSavingVideoRecorder.cpp:54
cx::VideoRecorderSaveThread::VideoRecorderSaveThread
VideoRecorderSaveThread(QObject *parent, QString saveFolder, QString prefix, bool compressed, bool writeColor)
Definition: cxSavingVideoRecorder.cpp:35
cx
Namespace for all CustusX production code.
Definition: cx_dev_group_definitions.h:13
cx::SavingVideoRecorder::getImageData
CachedImageDataContainerPtr getImageData()
Definition: cxSavingVideoRecorder.cpp:220
cx::VideoRecorderSaveThread::mPendingData
std::list< DataType > mPendingData
Definition: cxSavingVideoRecorder.h:74
cx::VideoRecorderSaveThread::~VideoRecorderSaveThread
virtual ~VideoRecorderSaveThread()
Definition: cxSavingVideoRecorder.cpp:50
cx::VideoRecorderSaveThread::stop
void stop()
Definition: cxSavingVideoRecorder.cpp:73
cx::VideoRecorderSaveThread::cancel
void cancel()
Definition: cxSavingVideoRecorder.cpp:78
cx::SavingVideoRecorder::SavingVideoRecorder
SavingVideoRecorder(VideoSourcePtr source, QString saveFolder, QString prefix, bool compressed, bool writeColor, FileManagerServicePtr filemanagerservice)
Definition: cxSavingVideoRecorder.cpp:178
cx::VideoRecorderSaveThread::mCancel
bool mCancel
Definition: cxSavingVideoRecorder.h:77
cx::SavingVideoRecorder::startRecord
virtual void startRecord()
Definition: cxSavingVideoRecorder.cpp:197
cxXmlOptionItem.h
cstring_cast
cstring_cast_Placeholder cstring_cast(const T &val)
Definition: cxTypeConversions.h:69
vtkImageDataPtr
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
Definition: cxVideoConnectionWidget.h:30
cx::SavingVideoRecorder::~SavingVideoRecorder
virtual ~SavingVideoRecorder()
Definition: cxSavingVideoRecorder.cpp:191
cx::VideoRecorderSaveThread::DataType::mImage
vtkImageDataPtr mImage
Definition: cxSavingVideoRecorder.h:69
cx::VideoRecorderSaveThread::write
void write(DataType data)
Definition: cxSavingVideoRecorder.cpp:109
cx::FileManagerServicePtr
boost::shared_ptr< class FileManagerService > FileManagerServicePtr
Definition: cxLogicManager.h:31
cx::VideoSourcePtr
boost::shared_ptr< class VideoSource > VideoSourcePtr
Definition: cxForwardDeclarations.h:109
cxVideoSource.h
cx::TimeInfo::getAcquisitionTime
double getAcquisitionTime() const
Definition: cxData.h:62
cx::CachedImageDataContainer
Definition: cxImageDataContainer.h:83
cx::SavingVideoRecorder::stopRecord
virtual void stopRecord()
Definition: cxSavingVideoRecorder.cpp:202
cx::SavingVideoRecorder::completeSave
void completeSave()
Definition: cxSavingVideoRecorder.cpp:257
cx::VideoRecorderSaveThread::openTimestampsFile
bool openTimestampsFile()
Definition: cxSavingVideoRecorder.cpp:84
cx::TimeInfo
Definition: cxData.h:43
cxTypeConversions.h
cx::SavingVideoRecorder::getTimestamps
std::vector< TimeInfo > getTimestamps()
Definition: cxSavingVideoRecorder.cpp:225
cxImageDataContainer.h
cx::VideoRecorderSaveThread::mTimestampsFile
QFile mTimestampsFile
Definition: cxSavingVideoRecorder.h:78
cxSettings.h
cx::VideoRecorderSaveThread::run
virtual void run()
Definition: cxSavingVideoRecorder.cpp:160
cx::SavingVideoRecorder::cancel
void cancel()
Definition: cxSavingVideoRecorder.cpp:230
cx::VideoRecorderSaveThread::DataType
Definition: cxSavingVideoRecorder.h:65
cx::VideoRecorderSaveThread::writeQueue
void writeQueue()
Definition: cxSavingVideoRecorder.cpp:141
cx::CachedImageDataContainerPtr
boost::shared_ptr< class CachedImageDataContainer > CachedImageDataContainerPtr
Definition: cxSavingVideoRecorder.h:27
cx::VideoRecorderSaveThread::mImageIndex
int mImageIndex
Definition: cxSavingVideoRecorder.h:73
cxSavingVideoRecorder.h
cx::VideoRecorderSaveThread::mWriteColor
bool mWriteColor
Definition: cxSavingVideoRecorder.h:80
cx::VideoRecorderSaveThread::DataType::mImageFilename
QString mImageFilename
Definition: cxSavingVideoRecorder.h:68
cx::reportError
void reportError(QString msg)
Definition: cxLogger.cpp:71
cx::VideoRecorderSaveThread::mPrefix
QString mPrefix
Definition: cxSavingVideoRecorder.h:72
cx::VideoRecorderSaveThread::mMutex
QMutex mMutex
protects the mPendingData
Definition: cxSavingVideoRecorder.h:75
vtkMetaImageWriterPtr
vtkSmartPointer< class vtkMetaImageWriter > vtkMetaImageWriterPtr
Definition: vtkForwardDeclarations.h:98
cx::VideoRecorderSaveThread::closeTimestampsFile
bool closeTimestampsFile()
Definition: cxSavingVideoRecorder.cpp:95