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