12 #define PCLOSE _pclose
13 #define POPEN_MODE_WRITE "wb"
18 #define POPEN_MODE_WRITE "w"
28 const std::string & _identifier,
31 const std::string & _metaData,
32 int _framesPerFileCycle,
37 s_identifier(_identifier),
42 totalFramesWritten(0),
43 maxFrames(_maxFrames),
44 framesPerFileCycle(_framesPerFileCycle),
45 cumulative(_cumulative),
50 accQuadratic(nullptr),
52 storageManager = &_storageManager;
68 return {filename, metaData,
keepGoing?
"active":
"done",
SSTR(0),
SSTR(totalFramesWritten)};
73 void FileStorageExtractor::extractSetup() {
77 void FileStorageExtractor::extractImpl(
unsigned int _width,
79 unsigned int _bytesPerPixel,
82 zmq::message_t * sourceImage) {
86 if(wallTimes.size() == 0) {
89 bytesPerPixel = _bytesPerPixel;
91 tmpdata =
new uint16_t[width*height];
94 if(width != _width || height != _height || bytesPerPixel != _bytesPerPixel) {
95 cout <<
"ERROR: image size changed during capture!" << endl;
100 highResTimes.push_back(highResTime);
101 wallTimes.push_back(wallTime);
105 uint16_t * data = (uint16_t*)sourceImage->data();
106 for(
unsigned int i=0; i<height; ++i) {
107 for(
unsigned int j=0; j<width; ++j) {
108 tmpdata[(i*width)+j] = data[((2*i)*width)+j] + data[(((2*i)+1)*width)+j];
111 size_t actuallyWritten = fwrite(tmpdata, 1, sourceImage->size()/2, fil);
112 if(actuallyWritten != sourceImage->size()/2) {
113 cerr <<
"could only write " << actuallyWritten <<
" bytes of " << sourceImage->size()/2 <<
" bytes" << endl;
114 perror(
"WRITE ERROR");
117 size_t actuallyWritten = fwrite(sourceImage->data(), 1, sourceImage->size(), fil);
118 if(actuallyWritten != sourceImage->size()) {
119 cerr <<
"could only write " << actuallyWritten <<
" bytes of " << sourceImage->size() <<
" bytes" << endl;
120 perror(
"WRITE ERROR");
125 unsigned int count = width * height;
127 if(accLinear ==
nullptr) {
128 accLinear =
new float[count]();
130 if(accQuadratic ==
nullptr) {
131 accQuadratic =
new float[count]();
133 switch(_bytesPerPixel) {
136 uint8_t * data =
static_cast<uint8_t*
>(sourceImage->data());
137 for(i = 0; i < count; ++i) {
138 element = (float)(data[i]);
139 accLinear[i] += element;
140 accQuadratic[i] += element*element;
146 uint16_t * data =
static_cast<uint16_t*
>(sourceImage->data());
147 for(i = 0; i < count; ++i) {
148 element = (float)(data[i]);
149 accLinear[i] += element;
150 accQuadratic[i] += element*element;
156 uint32_t * data =
static_cast<uint32_t*
>(sourceImage->data());
157 for(i = 0; i < count; ++i) {
158 element = (float)(data[i]);
159 accLinear[i] += element;
160 accQuadratic[i] += element*element;
165 cout <<
"ERROR: " << _bytesPerPixel <<
" bytesPerPixel are not implemented!" << endl;
173 ++totalFramesWritten;
174 if(maxFrames >= 0 && totalFramesWritten >= maxFrames) {
178 if(framesPerFileCycle > 0 && !cumulative && framesWritten >= framesPerFileCycle) {
183 highResTimes.clear();
188 void FileStorageExtractor::extractTeardown() {
189 if(cumulative && accLinear !=
nullptr) {
190 size_t size = width * height *
sizeof(float);
191 size_t actuallyWritten = fwrite((
void*)accLinear, 1, size, fil);
192 if(actuallyWritten != size) {
193 cerr <<
"could only write " << actuallyWritten <<
" bytes of " << size <<
" bytes" << endl;
194 perror(
"WRITE ERROR");
196 actuallyWritten = fwrite((
void*)accQuadratic, 1, size, fil);
197 if(actuallyWritten != size) {
198 cerr <<
"could only write " << actuallyWritten <<
" bytes of " << size <<
" bytes" << endl;
199 perror(
"WRITE ERROR");
202 delete[] accQuadratic;
204 if(tmpdata !=
nullptr)
delete[] tmpdata;
207 unique_lock<mutex> _(lastHeaderWriterThreadMutex);
208 if(lastHeaderWriterThread !=
nullptr && lastHeaderWriterThread->joinable()) {
209 lastHeaderWriterThread->join();
214 void FileStorageExtractor::openFile() {
216 std::string filename_tmp =
SSTR(storageDir,
"/tmp_recordXXXXXX");
218 strcpy_s(filename,
sizeof(filename), filename_tmp.c_str());
220 strcpy(filename, filename_tmp.c_str());
222 int fd = mkstemp(filename);
224 fil = _fdopen(fd,
"wb");
226 fil = fdopen(fd,
"wb");
228 cout <<
"opened file " << filename << endl;
231 void FileStorageExtractor::closeFile() {
232 cout <<
"start closing " << fil << endl;
235 cout <<
"closed file " << filename << endl;
237 cout <<
"there was an error during file creation, removing " << filename <<
"!" << endl;
239 }
else if(framesWritten == 0) {
240 cout <<
"no frames written in current cycle, removing " << filename <<
"!" << endl;
243 stringstream sswalltimes;
245 for(
const auto & t: wallTimes) {
250 sswalltimes <<
"," << t;
253 stringstream sshighrestimes;
255 for(
const auto & t: highResTimes) {
260 sshighrestimes <<
"," << t;
264 if((pPipe = POPEN(
"python -m runmacs.spec.io.streamed_header", POPEN_MODE_WRITE)) !=
nullptr) {
270 fwriteString(pPipe,
SSTR(
"\"highRes_times\":[", sshighrestimes.str(),
"],"));
287 unique_lock<mutex> _(lastHeaderWriterThreadMutex);
288 thread * prevHeaderWriterThread = lastHeaderWriterThread;
289 lastHeaderWriterThread =
new thread([=](){
290 (void) PCLOSE(pPipe);
291 if(prevHeaderWriterThread !=
nullptr && prevHeaderWriterThread->joinable()) {
292 prevHeaderWriterThread->join();
298 cout <<
"could not call header-writer" << endl;
std::string getPreferredStorageLocation()
Ask for a good location to store data.
Handles storage locations.
size_t fwriteString(FILE *stream, const std::string &str)
std::string SSTR(Args &&...components)
Creates a temporary string stream for string concatenation.