00001 /*!@file Video/VideoFrame.H Handle generic video frames in a multitude of formats */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Video/VideoFrame.H $ 00035 // $Id: VideoFrame.H 10348 2008-10-15 22:45:29Z ilab24 $ 00036 // 00037 00038 #ifndef VIDEO_VIDEOFRAME_H_DEFINED 00039 #define VIDEO_VIDEOFRAME_H_DEFINED 00040 00041 #include "Image/ArrayData.H" 00042 #include "Image/Dims.H" 00043 #include "Util/Types.H" 00044 #include "Video/VideoFormat.H" 00045 #include "rutz/scopedptr.h" 00046 00047 #include <iosfwd> 00048 #include <string> 00049 00050 template <class T> class Image; 00051 template <class T> class PixRGB; 00052 template <class T> class PixVideoYUV; 00053 00054 /// Simple class that encpasulates information about a video frame. 00055 /** This includes information about the format in which the frame is 00056 encoded, its size, and of course the raw framebuffer data 00057 itself. 00058 00059 NOTE: The purpose of this class is to take the place of just 00060 passing raw buffer pointers around; instead, we wrap the buffer 00061 pointer along with associated descriptive information. However, 00062 BEWARE that we have no strong safeguards to ensure that the 00063 internal buffer pointer stays "live" for very long. If you want to 00064 keep a VideoFrame object around for a "long" time (say, holding it 00065 for longer than the function call in which you received it in the 00066 first place), then you should call deepCopyOf() on it to get a 00067 safe VideoFrame; that way the VideoFrame will make an internal 00068 private copy of the frame buffer which can live as long as the 00069 object lives without becoming corrupted. 00070 */ 00071 class VideoFrame 00072 { 00073 public: 00074 /// Default constructor; be sure to initialize before use, though! 00075 VideoFrame(); 00076 00077 /// Construct by borrowing 'data' buffer. 00078 /** The caller is responsible for ensuring that 'data' points to 00079 valid memory for as long as the VideoFrame object lives, and for 00080 freeing/deleting 'data' afterwards. If you need to hold on to 00081 the frame for a long time, then call deepCopyOf() to get a 00082 VideoFrame that can be safely held. */ 00083 VideoFrame(const byte* data, const size_t length, const Dims& dims, 00084 const VideoFormat mode, const bool byteswap, 00085 const bool strictLength); 00086 00087 /// Construct with all information needed to convert to RGB, save to disk, etc. 00088 VideoFrame(const ArrayHandle<byte>& hdl, const Dims& dims, 00089 const VideoFormat mode, const bool byteswap); 00090 00091 /// Construct from a grayscale image (using VIDFMT_GREY) 00092 explicit VideoFrame(const Image<byte>& gray); 00093 00094 /// Construct from an RGB image (using VIDFMT_RGB24) 00095 explicit VideoFrame(const Image<PixRGB<byte> >& rgb); 00096 00097 /// Construct from a VideoYUV image (using VIDFMT_YUV24) 00098 explicit VideoFrame(const Image<PixVideoYUV<byte> >& yuv); 00099 00100 /// Destructor 00101 ~VideoFrame(); 00102 00103 /// Copy constructor 00104 VideoFrame(const VideoFrame& that); 00105 00106 /// Assignment operator 00107 VideoFrame& operator=(const VideoFrame& that); 00108 00109 /// Pseudo-constructor that builds a VideoFrame from a raw file 00110 /** @param strictLength if true, then we will throw an error if the 00111 data length of the file is larger the length that would be 00112 expected based on the given Dims and VideoFormat; if the file 00113 length is too small, we will unconditionally throw an error 00114 regardless of whether strictLength is true */ 00115 static VideoFrame fromFile(const char* fname, const Dims& dims, 00116 const VideoFormat mode, const bool byteswap, 00117 const bool strictLength = false); 00118 00119 /// Pseudo-constructor that builds a VideoFrame from an input stream 00120 static VideoFrame fromStream(std::istream& strm, const Dims& dims, 00121 const VideoFormat mode, const bool byteswap, 00122 const bool fail_is_fatal = true); 00123 00124 /// Make a new VideoFrame object with an internal private copy of the frame data 00125 /** This allows the returned VideoFrame object to be long-lived (on 00126 the other hand, the original VideoFrame's buffer is prone to 00127 being eventually overwritten by the frame grabber or movie 00128 stream that originally produced it). 00129 */ 00130 static VideoFrame deepCopyOf(const VideoFrame& original); 00131 00132 /// Check if we have any data 00133 bool initialized() const { return itsDims.isNonEmpty(); } 00134 00135 /// Get the raw buffer pointer 00136 const byte* getBuffer() const { return itsData; } 00137 00138 /// Get the length of the buffer 00139 size_t getBufSize() const; 00140 00141 /// Get the dimensions of the frame 00142 const Dims& getDims() const { return itsDims; } 00143 00144 /// Get the video mode 00145 VideoFormat getMode() const { return itsMode; } 00146 00147 /// Get the byteswap state 00148 bool getByteSwap() const { return itsByteSwap; } 00149 00150 /// Deinterlace the frame using the "bob" method 00151 /** @param in_bottom_field determines whether to return the rescaled 00152 top field or rescaled bottom field */ 00153 VideoFrame makeBobDeinterlaced(int in_bottom_field) const; 00154 00155 /// Flip the frame in the horizontal direction 00156 /** For now, this only works with VIDFMT_YUV420P frames (which are 00157 typically read from ffmpeg and displayed in SDL). */ 00158 VideoFrame getFlippedHoriz() const; 00159 00160 /// Dump the frame to a disk file using mmap() 00161 /** A filename extension appropriate to the frame's VideoFormat 00162 will be added to the given filename stem. 00163 00164 Returns the full filename of the file that was actually written. 00165 00166 @param flush if true, then do an fsync() on the file before returning 00167 */ 00168 std::string diskDumpMmap(const char* fstem, bool flush = false) const; 00169 00170 /// Dump the frame to a disk file using posix io functions 00171 /** A filename extension appropriate to the frame's VideoFormat 00172 will be added to the given filename stem. 00173 00174 Returns the full filename of the file that was actually written. 00175 00176 @param flush if true, then do an fsync() on the file before returning 00177 */ 00178 std::string diskDumpStdio(const char* fstem, bool flush = false) const; 00179 00180 /// Convert the buffer to RGB, according to its video mode 00181 Image<PixRGB<byte> > toRgb() const; 00182 00183 // Conver the 16 bit format type buffer to RGB, according to its video mode 00184 Image<PixRGB<uint16> > toRgbU16() const; 00185 00186 /// Extract individual Y/U/V component images from the buffer, if possible 00187 /** This function will LFATAL() if the VideoFrame data is in a 00188 non-YUV mode (such as RGB or grayscale), so you need to check 00189 the data mode is appropriate before trying to call this 00190 function. 00191 00192 Depending on the data mode, the individual component images may 00193 not be all the same size; in particular, the y component is 00194 likely to be at the full image size, while the u and v 00195 components may be downscaled by a factor of 2 or 4. So, you will 00196 need to check the Dims of the result images before doing further 00197 processing with them. 00198 */ 00199 void toYuvComponents(Image<byte>& y, 00200 Image<byte>& u, 00201 Image<byte>& v) const; 00202 00203 /// Abstract base class for various storage back-ends 00204 class Storage 00205 { 00206 public: 00207 /// Virtual destructor for safe inheritance 00208 virtual ~Storage(); 00209 00210 virtual Storage* clone() const = 0; 00211 }; 00212 00213 private: 00214 rutz::scoped_ptr<Storage> itsStorage; 00215 const byte* itsData; 00216 size_t itsDataLength; 00217 Dims itsDims; 00218 VideoFormat itsMode; 00219 bool itsByteSwap; 00220 }; 00221 00222 // ###################################################################### 00223 /* So things look consistent in everyone's emacs... */ 00224 /* Local Variables: */ 00225 /* mode: c++ */ 00226 /* indent-tabs-mode: nil */ 00227 /* End: */ 00228 00229 #endif // VIDEO_VIDEOFRAME_H_DEFINED