1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkVideoStream_h
19 #define itkVideoStream_h
20 
21 #include "itkTemporalDataObject.h"
22 #include "itkImage.h"
23 
24 namespace itk
25 {
26 
27 /** \class VideoStream
28  * \brief A DataObject that holds a buffered portion of a video
29  *
30  * The function of VideoStream is to provide an Image-specific subclass of
31  * TemporalDataObject. It provides several convenient typedefs to get common
32  * attributes of the frames. Additionally, the VideoStream caches meta
33  * information (lagest/requested/buffered spatial regions, origin, spacing,
34  * and direction) about all frames in the video, even those not currently
35  * buffered. This is done primarily in order to allow the meta data to be set
36  * before the frame is buffered.
37  *
38  * \ingroup ITKVideoCore
39  */
40 template<typename TFrameType>
41 class ITK_TEMPLATE_EXPORT VideoStream : public TemporalDataObject
42 {
43 public:
44   ITK_DISALLOW_COPY_AND_ASSIGN(VideoStream);
45 
46   /** Standard class type aliases */
47   using Self = VideoStream;
48   using Superclass = TemporalDataObject;
49   using Pointer = SmartPointer< Self >;
50   using ConstPointer = SmartPointer< const Self >;
51   using ConstWeakPointer = WeakPointer< const Self >;
52 
53   using FrameType = TFrameType;
54   using FramePointer = typename FrameType::Pointer;
55   using FrameConstPointer = typename FrameType::ConstPointer;
56   using BufferType = typename Superclass::BufferType;
57 
58   using SpatialRegionType = typename FrameType::RegionType;
59   using IndexType = typename FrameType::IndexType;
60   using PixelType = typename FrameType::PixelType;
61   using PointType = typename FrameType::PointType;
62   using SpacingType = typename FrameType::SpacingType;
63   using SizeType = typename FrameType::SizeType;
64   using DirectionType = typename FrameType::DirectionType;
65 
66   /** Types used to store map between frame numbers and frame meta data */
67   using SpatialRegionMapType = typename std::map<SizeValueType, SpatialRegionType>;
68   using PointMapType = typename std::map<SizeValueType, PointType>;
69   using DirectionMapType = typename std::map<SizeValueType, DirectionType>;
70   using SpacingMapType = typename std::map<SizeValueType, SpacingType>;
71 
72   /** Access the spacial dimensionality of the frames */
73   static constexpr unsigned int FrameDimension = FrameType::ImageDimension;
GetFrameDimension()74   static unsigned int GetFrameDimension()
75   {
76     return FrameType::ImageDimension;
77   }
78 
79   itkNewMacro(Self);
80 
81   /** Run-time type information (and related methods). */
82   itkTypeMacro(VideoStream, TemporalDataObject);
83 
84   /** Safely expand the internal ring buffer. */
85   void SetMinimumBufferSize(SizeValueType minimumNumberOfFrames);
86 
87   /** Initialize any empty frames. This method makes sure that the frame buffer
88    * is large enough to hold the number of frames needed for the buffered
89    * temporal region. It goes through the necessary number of frames making
90    * sure that each one has been initialized. When allocating space for frames,
91    * this method should be called first, followed by setting the spatial
92    * regions on each frame, before Allocate is called. */
93   void InitializeEmptyFrames();
94 
95   /** Provide access to the internal frame buffer object */
GetFrameBuffer()96   BufferType* GetFrameBuffer()
97   {
98     return reinterpret_cast<BufferType*>(m_DataObjectBuffer.GetPointer() );
99   }
GetFrameBuffer()100   const BufferType* GetFrameBuffer() const
101   {
102     return reinterpret_cast<BufferType*>(m_DataObjectBuffer.GetPointer() );
103   }
104 
105   /** Set the internal pixel buffer */
106   void SetFrameBuffer(BufferType* buffer);
107 
108   /** Provide access to the internal caches for the meta data */
GetLargestPossibleSpatialRegionCache()109   const SpatialRegionMapType & GetLargestPossibleSpatialRegionCache() const
110   {
111     return m_LargestPossibleSpatialRegionCache;
112   }
SetLargestPossibleSpatialRegionCache(SpatialRegionMapType map)113   void SetLargestPossibleSpatialRegionCache(SpatialRegionMapType map)
114   {
115     m_LargestPossibleSpatialRegionCache = map;
116   }
117 
GetRequestedSpatialRegionCache()118   const SpatialRegionMapType & GetRequestedSpatialRegionCache() const
119   {
120     return m_RequestedSpatialRegionCache;
121   }
SetRequestedSpatialRegionCache(SpatialRegionMapType map)122   void SetRequestedSpatialRegionCache(SpatialRegionMapType map)
123   {
124     m_RequestedSpatialRegionCache = map;
125   }
126 
GetBufferedSpatialRegionCache()127   const SpatialRegionMapType & GetBufferedSpatialRegionCache() const
128   {
129     return m_BufferedSpatialRegionCache;
130   }
SetBufferedSpatialRegionCache(SpatialRegionMapType map)131   void SetBufferedSpatialRegionCache(SpatialRegionMapType map)
132   {
133     m_BufferedSpatialRegionCache = map;
134   }
135 
GetSpacingCache()136   const SpacingMapType & GetSpacingCache() const
137   {
138     return m_SpacingCache;
139   }
SetSpacingCache(SpacingMapType map)140   void SetSpacingCache(SpacingMapType map)
141   {
142     m_SpacingCache = map;
143   }
144 
GetOriginCache()145   const PointMapType & GetOriginCache() const
146   {
147     return m_OriginCache;
148   }
SetOriginCache(PointMapType map)149   void SetOriginCache(PointMapType map)
150   {
151     m_OriginCache = map;
152   }
153 
GetDirectionCache()154   const DirectionMapType & GetDirectionCache() const
155   {
156     return m_DirectionCache;
157   }
SetDirectionCache(DirectionMapType map)158   void SetDirectionCache(DirectionMapType map)
159   {
160     m_DirectionCache = map;
161   }
162 
163   /** Set the contents of the frame at a given frame number */
164   void SetFrame(SizeValueType frameNumber, FramePointer frame);
165 
166   /** Get the frame for the given frame number. Internally, we always leave the
167    * Head of the ring buffer in place and just use the frame number as an
168    * offset. This allows all references to frames to be processed by an
169    * explicit frame number rather than a potentially confusing offset. */
170   FramePointer GetFrame(SizeValueType frameNumber);
171   FrameConstPointer GetFrame(SizeValueType frameNumber) const;
172 
173   /** Get/Set the LargestPossibleRegion of a frame */
174   void SetFrameLargestPossibleSpatialRegion(SizeValueType frameNumber,
175                                             SpatialRegionType region);
176 
177   const SpatialRegionType &
178   GetFrameLargestPossibleSpatialRegion(SizeValueType frameNumber) const;
179 
180   /** Get/Set the RequestedRegion of a frame */
181   void SetFrameRequestedSpatialRegion(SizeValueType frameNumber,
182                                       SpatialRegionType region);
183 
184   const SpatialRegionType &
185   GetFrameRequestedSpatialRegion(SizeValueType frameNumber) const;
186 
187   /** Get/Set the BufferedRegion of a frame */
188   void SetFrameBufferedSpatialRegion(SizeValueType frameNumber,
189                                      SpatialRegionType region);
190 
191   const SpatialRegionType &
192   GetFrameBufferedSpatialRegion(SizeValueType frameNumber) const;
193 
194   /** Get/Set the Spacing of a frame */
195   void SetFrameSpacing(SizeValueType frameNumber, SpacingType spacing);
196 
197   const SpacingType & GetFrameSpacing(SizeValueType frameNumber) const;
198 
199   /** Get/Set the Origin of a frame */
200   void SetFrameOrigin(SizeValueType frameNumber, PointType origin);
201 
202   const PointType & GetFrameOrigin(SizeValueType frameNumber) const;
203 
204   /** Get/Set the Direction of a frame */
205   void SetFrameDirection(SizeValueType frameNumber, DirectionType direction);
206 
207   const DirectionType & GetFrameDirection(SizeValueType frameNumber) const;
208 
209   /** Set the LargestPossibleRegion on all frames. This assumes that all frames
210    * in the buffered temporal region have been initialized (should be called
211    * after InitializeEmptyFrames). */
212   void SetAllLargestPossibleSpatialRegions(SpatialRegionType region);
213 
214   /** Set the RequestedRegion on all frames. This assumes that all frames in
215    * the buffered temporal region have been initialized (should be called
216    * after InitializeEmptyFrames). */
217   void SetAllRequestedSpatialRegions(SpatialRegionType region);
218 
219   /** Set the BufferedRegion on all frames. This assumes that all frames in the
220    * buffered temporal region have been initialized (should be called after
221    * InitializeEmptyFrames). */
222   void SetAllBufferedSpatialRegions(SpatialRegionType region);
223 
224   /** Set the Spacing of all frames. This assumes that all frames in the
225    * buffered temporal region have been initialized (should be called after
226    * InitializeEmptyFrames). */
227   void SetAllFramesSpacing(SpacingType spacing);
228 
229   /** Set the Origin of all frames. This assumes that all frames in the
230    * buffered temporal region have been initialized (should be called after
231    * InitializeEmptyFrames). */
232   void SetAllFramesOrigin(PointType origin);
233 
234   /** Set the Direction of all frames. This assumes that all frames in the
235    * buffered temporal region have been initialized (should be called after
236    * InitializeEmptyFrames). */
237   void SetAllFramesDirection(DirectionType direction);
238 
239   /** Allocate memory for the buffered spatial region of each frame in the
240    * buffered temporal region. This assumes that all frames in the buffered
241    * temporal region have been initialized and that the buffered spatial region
242    * has been set for each of these frames. A typical setup would look like:
243    *
244      \code
245         // Set the temporal regions
246         TemporalRegionType temporalRegion;
247         temporalRegion.SetFrameStart( 0 );
248         temporalRegion.SetFrameDuration( 3 );
249         video->SetLargestPossibleTemporalRegion( temporalRegion );
250         video->SetRequestedTemporalRegion( temporalRegion );
251         video->SetBufferedTemporalRegion( temporalRegion );
252 
253         // Initialize all frames in the buffered temporal region
254         video->InitializeEmptyFrames();
255 
256         // Set the buffered spatial region for each frame
257         SpatialRegionType bufferedSpatialRegion;
258         SpatialRegionType::SizeType size;
259         SpatialRegionType::IndexType start;
260         size[0] = 50;
261         size[1] = 40;
262         start.Fill( 0 );
263         bufferedSpatialRegion.SetSize( size );
264         bufferedSpatialRegion.SetIndex( start );
265         video->SetAllBufferedSpatialRegions( bufferedSpatialRegion );
266 
267         // Allocate memory for the frames
268         video->Allocate();
269      \endcode
270    */
271   void Allocate();
272 
273   /** Graft the data and information from one VideoStream to this one. This
274    * just copies the meta information using TemporalProcessObject's Graft then
275    * sets the internal RingBuffer pointer to point to the same buffer used by
276    * the other VideoStream. */
277   void Graft(const DataObject* data) override;
278 
279 protected:
280   VideoStream() = default;
281   ~VideoStream() override = default;
282 
PrintSelf(std::ostream & os,Indent indent)283   void PrintSelf(std::ostream & os, Indent indent) const override
284   {
285     Superclass::Print(os, indent);
286   }
287 
288   /** These maps are used to cache a mapping between frame number and spatial
289    * region. This is done because frames will often not be in actual existence
290    * at the time when the region gets set. */
291   SpatialRegionMapType m_LargestPossibleSpatialRegionCache;
292   SpatialRegionMapType m_RequestedSpatialRegionCache;
293   SpatialRegionMapType m_BufferedSpatialRegionCache;
294 
295   /** These maps cache a mapping between frame number and the meta data for
296    * origin, spacing, and direction */
297   SpacingMapType       m_SpacingCache;
298   DirectionMapType     m_DirectionCache;
299   PointMapType         m_OriginCache;
300 }; // end class VideoStream
301 
302 } // end namespace itk
303 
304 #ifndef ITK_MANUAL_INSTANTIATION
305 #include "itkVideoStream.hxx"
306 #endif
307 
308 #endif
309