CtSaving.cpp 48 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//###########################################################################
// This file is part of LImA, a Library for Image Acquisition
//
// Copyright (C) : 2009-2011
// European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//###########################################################################
22
#include <cmath>
23
#include <sstream>
24
25
#include <sys/types.h>
#include <sys/stat.h>
seb's avatar
seb committed
26
27
28
#include <unistd.h>

#ifdef __linux__ 
Roberto Arturo Homs Regojo's avatar
.    
Roberto Arturo Homs Regojo committed
29
#include <dirent.h>
seb's avatar
seb committed
30
#include <sys/statvfs.h>
31
32
#else
#include <direct.h>
seb's avatar
seb committed
33
#endif
34
35

#include "CtSaving.h"
seb's avatar
seb committed
36
#include "CtSaving_Edf.h"
37
#include "CtAcquisition.h"
38
#include "CtBuffer.h"
39
40
41
42

#ifdef WITH_NXS_SAVING
#include "CtSaving_Nxs.h"
#endif
seb's avatar
seb committed
43
44
45
46

#ifdef WITH_CBF_SAVING
#include "CtSaving_Cbf.h"
#endif
47

48
49
50
51
#ifdef WITH_FITS_SAVING
#include "CtSaving_Fits.h"
#endif

52
#include "TaskMgr.h"
53
54
55
56
57
58
59
60
#include "SinkTask.h"

using namespace lima;

static const char DIR_SEPARATOR = '/';

/** @brief save task class
 */
61
class CtSaving::Stream::_SaveTask : public SinkTaskBase
62
{
63
    DEB_CLASS_NAMESPC(DebModControl,"CtSaving::Stream::_SaveTask","Control");
64
public:
65
66
67
  _SaveTask(CtSaving::Stream& stream) 
    : SinkTaskBase(), m_stream(stream) {}

68
69
  virtual void process(Data &aData)
  {
seb's avatar
seb committed
70
71
72
    DEB_MEMBER_FUNCT();
    DEB_PARAM() << DEB_VAR1(aData);

73
    m_stream.writeFile(aData, m_header);
74
75
76
77
  }

  CtSaving::HeaderMap	 m_header;
private:
78
  CtSaving::Stream& m_stream;
79
80
81
};
/** @brief save callback
 */
82
class CtSaving::Stream::_SaveCBK : public TaskEventCallback
83
{
84
    DEB_CLASS_NAMESPC(DebModControl,"CtSaving::Stream::_SaveCBK","Control");
85
public:
86
  _SaveCBK(Stream& stream) : m_stream(stream) {}
seb's avatar
seb committed
87
  virtual void finished(Data &aData)
88
  {
seb's avatar
seb committed
89
90
91
    DEB_MEMBER_FUNCT();
    DEB_PARAM() << DEB_VAR1(aData);

92
    m_stream.saveFinished(aData);
93
94
  }
private:
95
  Stream& m_stream;
96
};
97
98
/** @brief compression callback
 */
99
class CtSaving::Stream::_CompressionCBK : public TaskEventCallback
100
{
101
    DEB_CLASS_NAMESPC(DebModControl,"CtSaving::_CompressionCBK","Control");
102
public:
103
  _CompressionCBK(Stream& stream) : m_stream(stream) {}
104
105
106
107
  virtual void finished(Data &aData)
  {
    DEB_MEMBER_FUNCT();
    DEB_PARAM() << DEB_VAR1(aData);
108

109
    m_stream.compressionFinished(aData);
110
111
  }
private:
112
  Stream &m_stream;
113
};
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/** @brief manual background saving
 */
class CtSaving::_ManualBackgroundSaveTask : public SinkTaskBase
{
public:
  _ManualBackgroundSaveTask(CtSaving& ct_saving,
			    HeaderMap &aHeader) :
    m_saving(ct_saving),
    m_header(aHeader)
  {
  }

  ~_ManualBackgroundSaveTask()
  {
    AutoMutex lock(m_saving.m_cond.mutex());
    m_saving.m_ready_flag = true;
    m_saving.m_cond.broadcast();
  }

  virtual void process(Data &aData)
  {
    m_saving._synchronousSaving(aData,m_header);
  }
private:
  CtSaving &m_saving;
  HeaderMap m_header;
};
141
142
143
144
/** @brief Parameters default constructor
 */
CtSaving::Parameters::Parameters()
  : nextNumber(0), fileFormat(RAW), savingMode(Manual), 
145
    overwritePolicy(Abort),
146
    indexFormat("%04d"),framesPerFile(1)
147
148
149
{
}

150
151
152
153
154
155
156
157
158
159
160
void CtSaving::Parameters::checkValid() const
{
  switch(fileFormat)
    {
#ifdef WITH_CBF_SAVING
    case CBFFormat :
      if(framesPerFile > 1)
	throw LIMA_CTL_EXC(InvalidValue, "CBF file format does not support "
			                 "multi frame per file");
      break;
#endif
161
#ifndef __unix
162
#pragma message ( "--- WARNING / TODO - no cases???" )
163
#endif
164
165
166
167
168
    default:
      break;
    }
}

169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
//@brief constructor
CtSaving::Stream::Stream(CtSaving& aCtSaving, int idx)
  : m_saving(aCtSaving), m_idx(idx),
    m_save_cnt(NULL),
    m_pars_dirty_flag(false),
    m_active(false),
    m_compression_cbk(NULL)
{
  DEB_CONSTRUCTOR();

  createSaveContainer();
  m_saving_cbk = new _SaveCBK(*this);
  m_compression_cbk = new _CompressionCBK(*this);
}

//@brief destructor
CtSaving::Stream::~Stream()
{
  DEB_DESTRUCTOR();

  delete m_save_cnt;
  m_saving_cbk->unref();
  m_compression_cbk->unref();
}

const 
CtSaving::Parameters& CtSaving::Stream::getParameters(ParameterType type) const
{ 
  bool from_acq = (type == Acq) || ((type == Auto) && !m_pars_dirty_flag);
  return *(from_acq ? &m_acquisition_pars : &m_pars); 
}

CtSaving::Parameters& CtSaving::Stream::getParameters(ParameterType type)
{ 
  bool from_acq = (type == Acq) || ((type == Auto) && !m_pars_dirty_flag);
  return *(from_acq ? &m_acquisition_pars : &m_pars); 
}

void CtSaving::Stream::setParameters(const CtSaving::Parameters& pars)
{ 
  DEB_MEMBER_FUNCT();

212
213
214
  if (pars.nextNumber == m_acquisition_pars.nextNumber)
    m_pars.nextNumber = pars.nextNumber;

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  if (pars == m_pars)
    return;

  pars.checkValid(); 
  m_pars_dirty_flag = true; 
  m_pars = pars; 

  DEB_TRACE() << "pars changed";
}

void CtSaving::Stream::setActive(bool active)
{
  DEB_MEMBER_FUNCT();

  if (active == m_active)
    return;
  
  if (!active)
    m_save_cnt->close();

  m_active = active;
}

void CtSaving::Stream::prepare()
{
  DEB_MEMBER_FUNCT();

  if (hasAutoSaveMode())
243
244
245
246
247
    {
      m_save_cnt->close();
      updateParameters();
      checkWriteAccess();
    }
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
}

void CtSaving::Stream::updateParameters()
{
  DEB_MEMBER_FUNCT();

  if (!m_pars_dirty_flag)
    return;

  if (m_pars.fileFormat != m_acquisition_pars.fileFormat)
    createSaveContainer();

  m_acquisition_pars = m_pars;
  m_pars_dirty_flag = false;
}

void CtSaving::Stream::createSaveContainer()
{
  DEB_MEMBER_FUNCT();

  switch (m_pars.fileFormat) {
  case CBFFormat :
#ifndef WITH_CBF_SAVING
    THROW_CTL_ERROR(NotSupported) << "Lima is not compiled with the cbf "
                                     "saving option, not managed";  
#endif
274
275
    goto common;

276
277
278
279
  case NXS:
#ifndef WITH_NXS_SAVING
    THROW_CTL_ERROR(NotSupported) << "Lima is not compiled with the nxs "
                                     "saving option, not managed";  
280
#endif        
281
282
    goto common;

283
284
285
286
  case FITS:
#ifndef WITH_FITS_SAVING
    THROW_CTL_ERROR(NotSupported) << "Lima is not compiled with the fits "
                                     "saving option, not managed";  
287
#endif        
288
    goto common;
289
290
291
292
293
294
  case EDFGZ:
#ifndef WITH_EDFGZ_SAVING
    THROW_CTL_ERROR(NotSupported) << "Lima is not compiled with the edf gzip "
                                     "saving option, not managed"; 
#endif
    goto common;
295
296
  case RAW:
  case EDF:
297
298

  common:
299
300
301
302
303
304
305
306
307
308
309
310
311
312
    if (m_save_cnt) {
      m_save_cnt->close();
      delete m_save_cnt;
    }
    break;

  default:
    THROW_CTL_ERROR(NotSupported) << "File format not yet managed";
  }

  switch(m_pars.fileFormat)
  {
  case RAW:
  case EDF:
313
314
  case EDFGZ:
    m_save_cnt = new SaveContainerEdf(*this,m_pars.fileFormat);
315
316
317
318
319
320
321
322
323
324
325
    break;
#ifdef WITH_CBF_SAVING
  case CBFFormat:
    m_save_cnt = new SaveContainerCbf(*this);
    m_pars.framesPerFile = 1;
    break;
#endif
#ifdef WITH_NXS_SAVING
  case NXS:
    m_save_cnt = new SaveContainerNxs(*this);
    break;
326
327
328
329
330
#endif
#ifdef WITH_FITS_SAVING
  case FITS:
    m_save_cnt = new SaveContainerFits(*this);
    break;
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
#endif
  default:
    break;
  }
}

void CtSaving::Stream::writeFile(Data& data, HeaderMap& header)
{
  DEB_MEMBER_FUNCT();

  m_save_cnt->writeFile(data, header);
}


SinkTaskBase *CtSaving::Stream::getTask(TaskType type, const HeaderMap& header)
{
  DEB_MEMBER_FUNCT();

  SinkTaskBase *save_task;

  if (type == Compression) {
    if (!needCompression())
      return NULL;
    save_task = m_save_cnt->getCompressionTask(header);
    save_task->setEventCallback(m_compression_cbk);
  } else {
    _SaveTask *real_task = new _SaveTask(*this);
    real_task->m_header = header;
    save_task = real_task;
    save_task->setEventCallback(m_saving_cbk);
  }

  return save_task;
}

void CtSaving::Stream::compressionFinished(Data& data)
{
  DEB_MEMBER_FUNCT();
  m_saving._compressionFinished(data, *this);
}

void CtSaving::Stream::saveFinished(Data& data)
{
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR2(data, getIndex());

  m_saving._saveFinished(data, *this);
}

380
381
382
383
384
385
386
class CtSaving::_NewFrameSaveCBK : public HwSavingCtrlObj::Callback
{
public:
  _NewFrameSaveCBK(CtSaving &ct_saving) :
    m_saving(ct_saving)
  {
  }
387
  bool newFrameWritten(int frame_id)
388
389
390
391
392
393
  {
    return m_saving._newFrameWrite(frame_id);
  }
private:
  CtSaving&	m_saving;
};
394

395
396
397
//@brief constructor
CtSaving::CtSaving(CtControl &aCtrl) :
  m_ctrl(aCtrl),
398
  m_stream(NULL),
399
  m_ready_flag(true),
400
401
  m_need_compression(false),
  m_nb_save_cbk(0),
402
403
  m_end_cbk(NULL),
  m_managed_mode(Software)
404
{
seb's avatar
seb committed
405
406
  DEB_CONSTRUCTOR();

407
408
409
410
411
412
413
  m_nb_stream = 5;
  m_stream = new Stream *[m_nb_stream];
  for (int s = 0; s < m_nb_stream; ++s)
    m_stream[s] = new Stream(*this, s);

  m_stream[0]->setActive(true);

414
  resetLastFrameNb();
415
416
417
418
419
420
421
422
423
424

  HwInterface *hw = aCtrl.hwInterface();
  m_has_hwsaving = hw->getHwCtrlObj(m_hwsaving);
  if(m_has_hwsaving)
    {
      m_new_frame_save_cbk = new _NewFrameSaveCBK(*this);
      m_hwsaving->registerCallback(m_new_frame_save_cbk);
    }
  else
    m_new_frame_save_cbk = NULL;
425
426
427
428
429
}

//@brief destructor
CtSaving::~CtSaving()
{
seb's avatar
seb committed
430
431
  DEB_DESTRUCTOR();

432
433
434
435
  for (int s = 0; s < m_nb_stream; ++s)
    delete m_stream[s];
  delete [] m_stream;

436
  setEndCallback(NULL);
437
438
439
440
441
  if(m_has_hwsaving)
    {
      m_hwsaving->unregisterCallback(m_new_frame_save_cbk);
      delete m_new_frame_save_cbk;
    }
442
443
}

444
445
446
447
448
449
CtSaving::Stream& CtSaving::getStreamExc(int stream_idx) const
{
  DEB_MEMBER_FUNCT();
  THROW_CTL_ERROR(InvalidValue) << "Invalid " << DEB_VAR1(stream_idx);
}

450
451
452
453
454
/** @brief set saving parameter for a saving stream

    @param pars parameters for the saving stream
    @param stream_idx the id of the saving stream
 */
455
void CtSaving::setParameters(const CtSaving::Parameters &pars, int stream_idx)
456
{
seb's avatar
seb committed
457
  DEB_MEMBER_FUNCT();
458
  DEB_PARAM() << DEB_VAR2(pars, stream_idx);
seb's avatar
seb committed
459

460
  AutoMutex aLock(m_cond.mutex());
461
462
  Stream& stream = getStream(stream_idx);
  stream.setParameters(pars);
463
464
}

465
466
467
468
469
/** @brief get the saving stream parameters

    @param pars the return parameters
    @param stream_idx the stream id
 */
470
void CtSaving::getParameters(CtSaving::Parameters &pars, int stream_idx) const
471
{
seb's avatar
seb committed
472
  DEB_MEMBER_FUNCT();
473
  DEB_PARAM() << DEB_VAR1(stream_idx);
seb's avatar
seb committed
474

475
  AutoMutex aLock(m_cond.mutex());
476
477
  const Stream& stream = getStream(stream_idx);
  pars = stream.getParameters(Auto);
seb's avatar
seb committed
478
479

  DEB_RETURN() << DEB_VAR1(pars);
480
}
481
482
/** @brief set the saving directory for a saving stream
 */
483
void CtSaving::setDirectory(const std::string &directory, int stream_idx)
484
{
seb's avatar
seb committed
485
  DEB_MEMBER_FUNCT();
486
  DEB_PARAM() << DEB_VAR2(directory, stream_idx);
seb's avatar
seb committed
487

488
  AutoMutex aLock(m_cond.mutex());
489
490
491
492
  Stream& stream = getStream(stream_idx);
  Parameters pars = stream.getParameters(Auto);
  pars.directory = directory;
  stream.setParameters(pars);
493
}
494
495
/** @brief get the saving directory for a saving stream
 */
496
void CtSaving::getDirectory(std::string& directory, int stream_idx) const
497
{
seb's avatar
seb committed
498
  DEB_MEMBER_FUNCT();
499
  DEB_PARAM() << DEB_VAR1(stream_idx);
seb's avatar
seb committed
500

501
  AutoMutex aLock(m_cond.mutex());
502
503
504
  const Stream& stream = getStream(stream_idx);
  const Parameters& pars = stream.getParameters(Auto);
  directory = pars.directory;
seb's avatar
seb committed
505
506

  DEB_RETURN() << DEB_VAR1(directory);
507
}
508
509
/** @brief set the filename prefix for a saving stream
 */
510
void CtSaving::setPrefix(const std::string &prefix, int stream_idx)
511
{
seb's avatar
seb committed
512
  DEB_MEMBER_FUNCT();
513
  DEB_PARAM() << DEB_VAR2(prefix, stream_idx);
seb's avatar
seb committed
514

515
  AutoMutex aLock(m_cond.mutex());
516
517
518
519
  Stream& stream = getStream(stream_idx);
  Parameters pars = stream.getParameters(Auto);
  pars.prefix = prefix;
  stream.setParameters(pars);
520
}
521
522
/** @brief get the filename prefix for a saving stream
 */
523
void CtSaving::getPrefix(std::string& prefix, int stream_idx) const
524
{
seb's avatar
seb committed
525
  DEB_MEMBER_FUNCT();
526
  DEB_PARAM() << DEB_VAR1(stream_idx);
seb's avatar
seb committed
527

528
  AutoMutex aLock(m_cond.mutex());
529
530
531
  const Stream& stream = getStream(stream_idx);
  const Parameters& pars = stream.getParameters(Auto);
  prefix = pars.prefix;
seb's avatar
seb committed
532
533

  DEB_RETURN() << DEB_VAR1(prefix);
534
}
535
536
/** @brief set the filename suffix for a saving stream
 */
537
void CtSaving::setSuffix(const std::string &suffix, int stream_idx)
538
{
seb's avatar
seb committed
539
  DEB_MEMBER_FUNCT();
540
  DEB_PARAM() << DEB_VAR2(suffix, stream_idx);
seb's avatar
seb committed
541

542
  AutoMutex aLock(m_cond.mutex());
543
544
545
546
  Stream& stream = getStream(stream_idx);
  Parameters pars = stream.getParameters(Auto);
  pars.suffix = suffix;
  stream.setParameters(pars);
547
}
548
549
/** @brief get the filename suffix for a saving stream
 */
550
void CtSaving::getSuffix(std::string& suffix, int stream_idx) const
551
{
seb's avatar
seb committed
552
  DEB_MEMBER_FUNCT();
553
  DEB_PARAM() << DEB_VAR1(stream_idx);
seb's avatar
seb committed
554

555
  AutoMutex aLock(m_cond.mutex());
556
557
558
  const Stream& stream = getStream(stream_idx);
  const Parameters& pars = stream.getParameters(Auto);
  suffix = pars.suffix;
seb's avatar
seb committed
559
560

  DEB_RETURN() << DEB_VAR1(suffix);
561
}
562
563
/** @brief set the next number for the filename for a saving stream
 */
564
void CtSaving::setNextNumber(long number, int stream_idx)
565
{
seb's avatar
seb committed
566
  DEB_MEMBER_FUNCT();
567
  DEB_PARAM() << DEB_VAR2(number, stream_idx);
seb's avatar
seb committed
568

569
  AutoMutex aLock(m_cond.mutex());
570
571
572
573
  Stream& stream = getStream(stream_idx);
  Parameters pars = stream.getParameters(Auto);
  pars.nextNumber = number;
  stream.setParameters(pars);
574
}
575
576
/** @brief get the next number for the filename for a saving stream
 */
577
void CtSaving::getNextNumber(long& number, int stream_idx) const
578
{
seb's avatar
seb committed
579
  DEB_MEMBER_FUNCT();
580
  DEB_PARAM() << DEB_VAR1(stream_idx);
seb's avatar
seb committed
581
  
582
  AutoMutex aLock(m_cond.mutex());
583
584
585
  const Stream& stream = getStream(stream_idx);
  const Parameters& pars = stream.getParameters(Auto);
  number = pars.nextNumber;
seb's avatar
seb committed
586
587

  DEB_RETURN() << DEB_VAR1(number);
588
}
589
590
/** @brief set the saving format for a saving stream
 */
591
void CtSaving::setFormat(FileFormat format, int stream_idx)
592
{
seb's avatar
seb committed
593
594
  DEB_MEMBER_FUNCT();

595
  AutoMutex aLock(m_cond.mutex());
596
597
598
599
  Stream& stream = getStream(stream_idx);
  Parameters pars = stream.getParameters(Auto);
  pars.fileFormat = format;
  stream.setParameters(pars);
seb's avatar
seb committed
600
}
601
602
/** @brief get the saving format for a saving stream
 */
603
void CtSaving::getFormat(FileFormat& format, int stream_idx) const
604
{
seb's avatar
seb committed
605
  DEB_MEMBER_FUNCT();
606
  DEB_PARAM() << DEB_VAR1(stream_idx);
seb's avatar
seb committed
607

608
  AutoMutex aLock(m_cond.mutex());
609
610
611
  const Stream& stream = getStream(stream_idx);
  const Parameters& pars = stream.getParameters(Auto);
  format = pars.fileFormat;
seb's avatar
seb committed
612
613

  DEB_RETURN() << DEB_VAR1(format);
614
}
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
/** @brief return a list of hardware possible saving format
 */
void CtSaving::getHardwareFormatList(std::list<std::string> &format_list) const
{
  DEB_MEMBER_FUNCT();

  if(!m_has_hwsaving)
    THROW_CTL_ERROR(NotSupported) << "No hardware saving for this camera";
  
  m_hwsaving->getPossibleSaveFormat(format_list);
}

void CtSaving::setHardwareFormat(const std::string &format)
{
  DEB_MEMBER_FUNCT();

  if(!m_has_hwsaving)
    THROW_CTL_ERROR(NotSupported) << "No hardware saving for this camera";

  bool found = _checkHwFileFormat(format);
  
  if(!found)
    {
      THROW_CTL_ERROR(NotSupported) << 
	"Hardware does not support" << DEB_VAR1(format);
    }

  m_specific_hardware_format = format;
}

bool CtSaving::_checkHwFileFormat(const std::string &format) const
{
  std::list<std::string> format_list;
  m_hwsaving->getPossibleSaveFormat(format_list);
  bool found = false;
  for(std::list<std::string>::const_iterator i = format_list.begin();
      !found && i != format_list.end();++i)
    found = *i == format;
  return found;
}

void CtSaving::_ReadImage(Data &image,int frameNumber)
{
  DEB_MEMBER_FUNCT();

  if(m_hwsaving->getCapabilities() & HwSavingCtrlObj::MANUAL_READ)
    {
      HwFrameInfoType frame;
      m_hwsaving->readFrame(frame,frameNumber);
      CtBuffer::transformHwFrameInfoToData(image,frame);
    }
  else
    THROW_CTL_ERROR(NotSupported) << "Image read is not supported for this hardware";
}
void CtSaving::getHardwareFormat(std::string &format) const
{
  DEB_MEMBER_FUNCT();

  if(!m_has_hwsaving)
    THROW_CTL_ERROR(NotSupported) << "No hardware saving for this camera";
  
  format = m_specific_hardware_format;
}

679
680
/** @brief set the saving mode for a saving stream
 */
681
682
void CtSaving::setSavingMode(SavingMode mode)
{
seb's avatar
seb committed
683
684
685
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(mode);

686
  AutoMutex aLock(m_cond.mutex());
687
688
689
690
691
692
  for (int s = 0; s < m_nb_stream; ++s) {
    Stream& stream = getStream(s);
    Parameters pars = stream.getParameters(Auto);
    pars.savingMode = mode;
    stream.setParameters(pars);
  }
693
}
694
695
/** @brief get the saving mode for a saving stream
 */
696
697
void CtSaving::getSavingMode(SavingMode& mode) const
{ 
seb's avatar
seb committed
698
699
  DEB_MEMBER_FUNCT();
  
700
  AutoMutex aLock(m_cond.mutex());
701
702
703
  const Stream& stream = getStream(0);
  const Parameters& pars = stream.getParameters(Auto);
  mode = pars.savingMode;
seb's avatar
seb committed
704
705
  
  DEB_RETURN() << DEB_VAR1(mode);
706
}
707
708
/** @brief set the overwrite policy for a saving stream
 */
709
void CtSaving::setOverwritePolicy(OverwritePolicy policy, int stream_idx)
710
{
seb's avatar
seb committed
711
  DEB_MEMBER_FUNCT();
712
  DEB_PARAM() << DEB_VAR2(policy, stream_idx);
seb's avatar
seb committed
713

714
  AutoMutex aLock(m_cond.mutex());
715
716
717
718
  Stream& stream = getStream(stream_idx);
  Parameters pars = stream.getParameters(Auto);
  pars.overwritePolicy = policy;
  stream.setParameters(pars);
719
}
720
721
/** @brief get the overwrite policy for a saving stream
 */
722
723
void CtSaving::getOverwritePolicy(OverwritePolicy& policy, 
				  int stream_idx) const
724
{
seb's avatar
seb committed
725
  DEB_MEMBER_FUNCT();
726
  DEB_PARAM() << DEB_VAR1(stream_idx);
seb's avatar
seb committed
727
  
728
  AutoMutex aLock(m_cond.mutex());
729
730
731
  const Stream& stream = getStream(stream_idx);
  const Parameters& pars = stream.getParameters(Auto);
  policy = pars.overwritePolicy;
seb's avatar
seb committed
732
733

  DEB_RETURN() << DEB_VAR1(policy);
734
}
735
736
/** @brief set the number of frame saved per file for a saving stream
 */
737
void CtSaving::setFramesPerFile(unsigned long frames_per_file, int stream_idx)
738
{
seb's avatar
seb committed
739
  DEB_MEMBER_FUNCT();
740
  DEB_PARAM() << DEB_VAR2(frames_per_file, stream_idx);
seb's avatar
seb committed
741

742
  AutoMutex aLock(m_cond.mutex());
743
744
745
746
  Stream& stream = getStream(stream_idx);
  Parameters pars = stream.getParameters(Auto);
  pars.framesPerFile = frames_per_file;
  stream.setParameters(pars);
747
}
748
749
/** @brief get the number of frame saved per file for a saving stream
 */
750
751
void CtSaving::getFramePerFile(unsigned long& frames_per_file, 
			       int stream_idx) const
752
{
seb's avatar
seb committed
753
  DEB_MEMBER_FUNCT();
754
  DEB_PARAM() << DEB_VAR1(stream_idx);
seb's avatar
seb committed
755

756
  AutoMutex aLock(m_cond.mutex());
757
758
759
  const Stream& stream = getStream(stream_idx);
  const Parameters& pars = stream.getParameters(Auto);
  frames_per_file = pars.framesPerFile;
seb's avatar
seb committed
760
761

  DEB_RETURN() << DEB_VAR1(frames_per_file);
762
763
}

764
765
766
767
768
769
770
771
772
773
774
775
776
777
/** @brief set who will manage the saving.
 *
 *  with this methode you can choose who will do the saving
 *   - if mode is set to Software, the saving will be managed by Lima core
 *   - if mode is set to Hardware then it's the sdk or the hardware of the camera that will manage the saving.
 *  @param mode can be either Software or Hardware
*/
void CtSaving::setManagedMode(CtSaving::ManagedMode mode)
{
  DEB_MEMBER_FUNCT();
  if(mode == Hardware && !m_has_hwsaving)
    THROW_CTL_ERROR(InvalidValue) << DEB_VAR1(mode) << "Not supported";

  AutoMutex aLock(m_cond.mutex());
778
  if(mode == Hardware)
779
    {
780
781
782
783
784
785
786
787
788
789
790
      if(!m_has_hwsaving)
	THROW_CTL_ERROR(NotSupported) << "Hardware saving is not supported";

      int hw_cap = m_hwsaving->getCapabilities();
      if(hw_cap & HwSavingCtrlObj::COMMON_HEADER)
	m_hwsaving->setCommonHeader(m_common_header);
      else if(!m_common_header.empty())
	{
	  THROW_CTL_ERROR(Error) << "Hardware saving do not manage common header"
				 << ", clear it first";
	}
791
    }
792
  m_managed_mode = mode;
793
794
795
796
797
798
799
}

void CtSaving::getManagedMode(CtSaving::ManagedMode &mode) const
{
  DEB_MEMBER_FUNCT();

  AutoMutex aLock(m_cond.mutex());
800
  mode = m_managed_mode;
801
802
}

803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
void CtSaving::_getTaskList(TaskType type, long frame_nr, 
			    const HeaderMap& header, TaskList& task_list)
{
  DEB_MEMBER_FUNCT();

  task_list.clear();
  for (int s = 0; s < m_nb_stream; ++s) {
    Stream& stream = getStream(s);
    if (stream.isActive()) {
      SinkTaskBase *save_task = stream.getTask(type, header);
      if (save_task)
	task_list.push_back(save_task);
    }
  }
  int nb_cbk = task_list.size();
  DEB_TRACE() << DEB_VAR1(nb_cbk);
  if (type == Compression) {
    FrameCbkCountMap::value_type map_pair(frame_nr, nb_cbk);
    m_nb_compression_cbk.insert(map_pair);
  } else
    m_nb_save_cbk = nb_cbk;
}
825
826
/** @brief clear the common header
 */
827
828
void CtSaving::resetCommonHeader()
{
seb's avatar
seb committed
829
830
  DEB_MEMBER_FUNCT();

831
  AutoMutex aLock(m_cond.mutex());
832
  ManagedMode managed_mode = getManagedMode();
833
  if(managed_mode == Hardware)
834
835
836
837
838
839
840
    {
      int hw_cap = m_hwsaving->getCapabilities();
      if(hw_cap & HwSavingCtrlObj::COMMON_HEADER)
	m_hwsaving->resetCommonHeader();
      else
	THROW_CTL_ERROR(NotSupported) << "Common header is not supported";
    }
841
  m_common_header.clear();
842
}
843
844
845
/** @brief set the common header.
    This is the header which will be write for all frame for this acquisition
 */
846
847
void CtSaving::setCommonHeader(const HeaderMap &header)
{
seb's avatar
seb committed
848
849
850
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(header);

851
  AutoMutex aLock(m_cond.mutex());
852
  ManagedMode managed_mode = getManagedMode();
853
  if(managed_mode == Hardware)
854
855
856
857
858
859
860
    {
      int hw_cap = m_hwsaving->getCapabilities();
      if(hw_cap & HwSavingCtrlObj::COMMON_HEADER)
	m_hwsaving->setCommonHeader(header);
      else
	THROW_CTL_ERROR(NotSupported) << "Common header is not supported";
    }
861
  m_common_header = header;
862
}
863
864
/** @brief replace/add field in the common header
 */
865
866
void CtSaving::updateCommonHeader(const HeaderMap &header)
{
seb's avatar
seb committed
867
868
869
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(header);

870
  AutoMutex aLock(m_cond.mutex());
871
872
873
874
875
876
877
878
879
880
  //Update
  for(HeaderMap::const_iterator i = header.begin();
      i != header.end();++i)
    {
      std::pair<HeaderMap::iterator,bool> result= 
	m_common_header.insert(HeaderMap::value_type(i->first,i->second));
      //if it exist, update
      if(!result.second)
	result.first->second = i->second;
    }
881
}
882
883
/** @brief get the current common header
 */
884
885
void CtSaving::getCommonHeader(HeaderMap& header) const
{
seb's avatar
seb committed
886
887
  DEB_MEMBER_FUNCT();

888
889
  AutoMutex aLock(m_cond.mutex());
  header = HeaderMap(m_common_header);
seb's avatar
seb committed
890
891

  DEB_RETURN() << DEB_VAR1(header);
892
}
893
894
/** @brief add/replace a header value in the current common header
 */
895
896
void CtSaving::addToCommonHeader(const HeaderValue &value)
{
seb's avatar
seb committed
897
898
899
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(value);

900
901
902
  AutoMutex aLock(m_cond.mutex());
  m_common_header.insert(value);
}
903
904
/** @brief add/replace a header value in the current frame header
 */
905
906
void CtSaving::addToFrameHeader(long frame_nr,const HeaderValue &value)
{
seb's avatar
seb committed
907
908
909
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR2(frame_nr,value);

910
911
912
  AutoMutex aLock(m_cond.mutex());
  m_frame_headers[frame_nr].insert(value);
}
913
914
/** @brief add/replace several value in the current frame header
 */
915
916
void CtSaving::updateFrameHeader(long frame_nr,const HeaderMap &header)
{
seb's avatar
seb committed
917
918
919
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR2(frame_nr,header);

920
921
  AutoMutex aLock(m_cond.mutex());
  HeaderMap &frameHeader = m_frame_headers[frame_nr];
922
923
924
925
926
927
928
929
930
  for(HeaderMap::const_iterator i = header.begin();
      i != header.end();++i)
    {
      std::pair<HeaderMap::iterator,bool> result= 
	frameHeader.insert(HeaderMap::value_type(i->first,i->second));
      //if it exist, update
      if(!result.second)
	result.first->second = i->second;
    }
931
}
932
933
934
935
/** @brief validate a header for a frame.
    this mean that the header is ready and can now be save.
    If you are in AutoHeader this will trigger the saving if the data frame is available
 */
936
void CtSaving::validateFrameHeader(long frame_nr)
937
{
seb's avatar
seb committed
938
939
940
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(frame_nr);

941
  AutoMutex aLock(m_cond.mutex());
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
  SavingMode saving_mode = getAcqSavingMode();
  if (saving_mode != CtSaving::AutoHeader)
    return;

  FrameMap::iterator frame_iter = m_frame_datas.find(frame_nr);
  bool data_available = (frame_iter != m_frame_datas.end());
  bool can_save = (m_ready_flag && (m_last_frameid_saved == frame_nr - 1));
  if (!data_available || !(m_need_compression || can_save))
    return;
  Data aData = frame_iter->second;

  HeaderMap task_header;
  FrameHeaderMap::iterator aHeaderIter;
  aHeaderIter = m_frame_headers.find(frame_nr);
  bool keep_header = m_need_compression;
  _takeHeader(aHeaderIter, task_header, keep_header);

  TaskType task_type = m_need_compression ? Compression : Save;
  TaskList task_list;
  _getTaskList(task_type, frame_nr, task_header, task_list);
  if (!m_need_compression) {
    m_frame_datas.erase(frame_iter);
    m_ready_flag = false, m_last_frameid_saved = frame_nr;
  }
  aLock.unlock();
  _postTaskList(aData, task_list);
968
}
969
/** @brief get the frame header.
970

971
972
973
    @param frame_nr the frame id
    @param header the current frame header
 */
974
975
void CtSaving::getFrameHeader(long frame_nr, HeaderMap& header) const
{
seb's avatar
seb committed
976
977
978
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(frame_nr);

979
  AutoMutex aLock(m_cond.mutex());
980
  FrameHeaderMap::const_iterator i = m_frame_headers.find(frame_nr);
981
982
  if(i != m_frame_headers.end())
    header.insert(i->second.begin(),i->second.end());
seb's avatar
seb committed
983
984

  DEB_RETURN() << DEB_VAR1(header);
985
986
}

987
988
/** @brief get the frame header and remove it from the container
 */
989
990
void CtSaving::takeFrameHeader(long frame_nr, HeaderMap& header)
{
seb's avatar
seb committed
991
992
993
  DEB_MEMBER_FUNCT();
  DEB_PARAM() << DEB_VAR1(frame_nr);

994
  AutoMutex aLock(m_cond.mutex());
995
  FrameHeaderMap::iterator i = m_frame_headers.find(frame_nr);
996
997
998
999
1000
  if(i != m_frame_headers.end())
    {
      header = i->second;
      m_frame_headers.erase(i);
    }