PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
PlusBkProFocusCameraLinkReceiver.cxx
Go to the documentation of this file.
1 #include "PlusConfigure.h"
2 
5 
6 #include "ResearchInterface.h"
7 
9 
10 const int BYTES_PER_SAMPLE = 2; // One sample is one I or Q value, stored on 16 bits
11 
12 const int HEADER_SIZE_BYTES = 4; // The header consists of two 16 bit fields
13 
14 //----------------------------------------------------------------------------
16 {
18 
19  m_Frame = NULL;
20 
21  m_Decimation = 1;
22 
25 }
26 
27 //----------------------------------------------------------------------------
29 {
30 }
31 
32 //----------------------------------------------------------------------------
33 bool PlusBkProFocusCameraLinkReceiver::Prepare(int samples, int lines, int pitch)
34 {
35  LOG_DEBUG("Prepare: samples" << samples << ", lines=" << lines << ", pitch=" << pitch);
36 
37  if (lines < 0)
38  {
39  LOG_ERROR("Invalid lines argument sent to Prepare. Cannot process negative values.");
40  return false;
41  }
42 
43  unsigned int maxNumberOfLines = static_cast<unsigned int>(lines);
44  // maxNumberOfRfSamples refers to the number of available 16-bit data samples (without the header)
45  // need to subtract the the line header length, because the input "samples" includes the line header as well
46  int numberOfRfSamplesPerLine = (samples - HEADER_SIZE_BYTES / BYTES_PER_SAMPLE) / m_Decimation;
47 
48  if (maxNumberOfLines == m_MaxNumberOfLines && numberOfRfSamplesPerLine == m_NumberOfRfSamplesPerLine && m_Frame != NULL)
49  {
50  // frame buffer already allocated
51  return true;
52  }
53 
54  // initialize parameters
55  m_MaxNumberOfLines = maxNumberOfLines;
56  // adding 6 fixes the issue of mismatch between the prepared and received buffers. Perhaps this is
57  // due to a header that is not accounted for.
58  if (numberOfRfSamplesPerLine + 6 < 0)
59  {
60  LOG_ERROR("numberOfRfSamplesPerLine is negative. Cannot continue.");
61  return false;
62  }
63  m_NumberOfRfSamplesPerLine = static_cast<unsigned int>(numberOfRfSamplesPerLine + 6);
64 
65  if (m_Frame != NULL)
66  {
67  _aligned_free(m_Frame);
68  }
69  m_Frame = reinterpret_cast<unsigned char*>(_aligned_malloc(m_MaxNumberOfLines * m_NumberOfRfSamplesPerLine * BYTES_PER_SAMPLE, 16u));
70  if (m_Frame == NULL)
71  {
72  LOG_ERROR("PlusBkProFocusCameraLinkReceiver::Prepare: Failed to allocate memory for m_Frame");
73  return false;
74  }
75 
76  return true;
77 }
78 
79 //----------------------------------------------------------------------------
81 {
82  if (m_Frame != NULL)
83  {
84  _aligned_free(m_Frame);
85  m_Frame = NULL;
86  }
89  return true;
90 }
91 
92 //----------------------------------------------------------------------------
93 bool PlusBkProFocusCameraLinkReceiver::DataAvailable(int lines, int pitch, void const* frameData)
94 {
95  if (frameData == NULL)
96  {
97  LOG_DEBUG("DataAvailable received empty m_Frame");
98  return false;
99  }
100  if (m_Frame == NULL)
101  {
102  LOG_ERROR("Frame buffer is not initialized");
103  return false;
104  }
105  if (m_CallbackVideoSource == NULL)
106  {
107  LOG_ERROR("No video source callback is set");
108  return false;
109  }
110 
111  const ResearchInterfaceLineHeader* header = reinterpret_cast<const ResearchInterfaceLineHeader*>(frameData);
112  const unsigned char* inputFrame = reinterpret_cast<const unsigned char*>(frameData);
113 
114  // Copy as many sample pairs (2x16 bits) as available in the input and allocated in the output
115  // pitch size is in 1x8 bits, not in samples (2x8 bits).
116  // Note the inconsistency: in Prepare(), pitch is defined in 2x8 samples!
117  unsigned int numberOfSamplesInInput = (pitch - HEADER_SIZE_BYTES) / BYTES_PER_SAMPLE / m_Decimation;
118  unsigned int numberOfSamplePairsInInput = numberOfSamplesInInput / 2;
119  unsigned int numberOfSamplePairsInOutput = m_NumberOfRfSamplesPerLine / 2;
120  unsigned int numberOfSamplePairsToCopy = 0;
121  if (numberOfSamplePairsInOutput == numberOfSamplePairsInInput)
122  {
123  numberOfSamplePairsToCopy = numberOfSamplePairsInOutput;
124  }
125  else if (numberOfSamplePairsInOutput < numberOfSamplePairsInInput)
126  {
127  LOG_WARNING("Not enough space allocated to store all the RF samples. Input: " << numberOfSamplePairsInInput << ", output: " << numberOfSamplePairsInOutput);
128  numberOfSamplePairsToCopy = numberOfSamplePairsInOutput;
129  }
130  else // numberOfSamplePairsInInput < numberOfSamplePairsInOutput
131  {
132  LOG_WARNING("Not enough samples are available in the acquired frame, the end of the RF lines will be undefined");
133  numberOfSamplePairsToCopy = numberOfSamplePairsInInput;
134  }
135 
136  unsigned int numBmodeLines = 0; // number of bmode lines in this m_Frame
137  for (int inputLineIndex = 0; inputLineIndex < lines; ++inputLineIndex)
138  {
139  // Each RF line has a header (two 16-bit fields, see ResearchInterfaceLineHeader), then data values, then some undefined values (padding) till the next line
140  // Pitch is the total number of bytes of the RF line (including header, data, and padding)
141  header = reinterpret_cast<const ResearchInterfaceLineHeader*>(inputFrame + inputLineIndex * pitch);
142 
143  if (header->ModelID != 0 || header->CFM != 0 || header->FFT != 0)
144  {
145  // Only process lines that refer to lines that can be converted to brightness lines,
146  // so skip special lines (CFM, FFT, ...)
147  continue;
148  }
149 
150  if (numBmodeLines >= m_MaxNumberOfLines)
151  {
152  LOG_WARNING("Not enough lines are available in the frame buffer, ignore the acquired line");
153  continue;
154  }
155 
156  // TODO: check if header->LineLength can be used to make the numberOfSamplePairsToCopy computation more accurate
157  // (now there might be junk pixels at the end of the line if the line length is different for different lines)
158 
159  // 32 bit, one sample pair
160  const int32_t* currentInputPosition = reinterpret_cast<const int32_t*>(inputFrame + inputLineIndex * pitch + HEADER_SIZE_BYTES);
161  // Fill the output from the last line, because RF data is expected in FM orientation, so first scanline on the unmarked side of the transducer, but the first scanline in the BK buffer is the one on the marked side
162  int32_t* currentOutputPosition = reinterpret_cast<int32_t*>(m_Frame + (m_MaxNumberOfLines - 1 - numBmodeLines) * m_NumberOfRfSamplesPerLine * BYTES_PER_SAMPLE);
163 
164  for (int samplePairIndex = 0; samplePairIndex < numberOfSamplePairsToCopy; ++samplePairIndex)
165  {
166  *currentOutputPosition = *currentInputPosition;
167  currentInputPosition += m_Decimation; // copy every N-th sample pair (N=m_Decimation), ignore the rest
168  ++currentOutputPosition;
169  }
170 
171  ++numBmodeLines;
172  }
173 
174  // compute bmode
175  if (numBmodeLines == 0)
176  {
177  LOG_DEBUG("No B-mode compatible image lines were found");
178  return false;
179  }
180 
181  switch (m_ImagingMode)
182  {
184  {
185  LOG_ERROR("B-mode imaging is not supported");
186  break;
187  }
189  {
190  if (m_CallbackVideoSource != NULL)
191  {
192  // AF: each sample in m_RfFrame is twice as large as in bmode, and we do not decimate
193  FrameSizeType frameSizeInPix = {m_NumberOfRfSamplesPerLine, numBmodeLines, 1}; // each I and Q value is a sample (there are numRfSamples/2 IQ pairs in one line)
194  m_CallbackVideoSource->NewFrameCallback(m_Frame + (m_MaxNumberOfLines - numBmodeLines)*m_NumberOfRfSamplesPerLine * BYTES_PER_SAMPLE, frameSizeInPix, VTK_SHORT, US_IMG_RF_IQ_LINE);
195  }
196  break;
197  }
198  default:
199  LOG_ERROR("Invalid imaging mode requested: " << m_ImagingMode);
200  return false;
201  }
202 
203  return true;
204 }
205 
206 //----------------------------------------------------------------------------
208 {
209  m_CallbackVideoSource = videoSource;
210 }
211 
212 //----------------------------------------------------------------------------
214 {
215  m_ImagingMode = imagingMode;
216 }
217 
218 //----------------------------------------------------------------------------
220 {
221  m_Decimation = decimation;
222 }
virtual void SetImagingMode(vtkPlusBkProFocusCameraLinkVideoSource::ImagingModeType imagingMode)
virtual bool DataAvailable(int lines, int pitch, void const *frameData)
vtkPlusBkProFocusCameraLinkVideoSource::ImagingModeType m_ImagingMode
const int HEADER_SIZE_BYTES
vtkPlusBkProFocusCameraLinkVideoSource * m_CallbackVideoSource
void NewFrameCallback(void *pixelDataPtr, const FrameSizeType &frameSizeInPix, igsioCommon::VTKScalarPixelType pixelType, US_IMAGE_TYPE imageType)
Class for acquiring ultrasound images from BK ProFocus scanners.
virtual bool Prepare(int samples, int lines, int pitch)
virtual void SetPlusVideoSource(vtkPlusBkProFocusCameraLinkVideoSource *videoSource)
const int BYTES_PER_SAMPLE