SequenceFileStream.C

Go to the documentation of this file.
00001 /*!@file Media/SequenceFileStream.C Read frames from .seq video files */
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: Rand Voorhies <voorhies at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Media/SequenceFileStream.C $
00035 // $Id: SequenceFileStream.C 12962 2010-03-06 02:13:53Z irock $
00036 //
00037 
00038 #include "Media/SequenceFileStream.H"
00039 #include "Component/ModelOptionDef.H"
00040 #include "Raster/DeBayer.H"
00041 #include "Image/Image.H"
00042 #include "Image/Pixels.H"
00043 #include "Raster/GenericFrame.H"
00044 #include "Transport/TransportOpts.H"   // for MOC_INPUT
00045 #include "Util/log.H"
00046 #include "rutz/trace.h"
00047 
00048 #include <stdio.h>
00049 #include <fcntl.h>
00050 
00051 const ModelOptionDef OPT_SequenceFileStreamUseMmap =
00052   { MODOPT_ARG(bool), "SequenceFileStreamUseMmap", &MOC_INPUT, OPTEXP_CORE,
00053     "Whether to use mmap() instead of read() to stream data from disk. The"
00054     "default is to use mmap(), which may be significantly faster, but may"
00055     "be somewhat less portable.",
00056     "seqfile-use-mmap", '\0', "<true|false>", "false" };
00057 
00058 // ######################################################################
00059 SequenceFileStream::SequenceFileStream(OptionManager& mgr,
00060     const std::string& descrName, const std::string& tagName) :
00061   FrameIstream(mgr, descrName, tagName),
00062   itsUseMmap(&OPT_SequenceFileStreamUseMmap, this),
00063   itsFrame(), itsFrameSpec(), itsFrameSpecValid(false), itsFileHandle(-1),
00064   itsMmapFile()
00065 { }
00066 
00067 // ######################################################################
00068 SequenceFileStream::~SequenceFileStream()
00069 { }
00070 
00071 // ######################################################################
00072 void SequenceFileStream::setConfigInfo(const std::string& filename)
00073 {
00074   this->setFileName(filename);
00075 }
00076 
00077 
00078 // ######################################################################
00079 GenericFrameSpec SequenceFileStream::peekFrameSpec()
00080 {
00081 GVX_TRACE(__PRETTY_FUNCTION__);
00082 
00083   if (!itsFrameSpecValid)
00084   {
00085     if (itsFrame.initialized() == false) itsFrame = readFrame();
00086 
00087     itsFrameSpec = itsFrame.frameSpec();
00088     itsFrameSpecValid = true;
00089   }
00090 
00091   return itsFrameSpec;
00092 }
00093 
00094 // ######################################################################
00095 void SequenceFileStream::setFileName(const std::string& fname)
00096 {
00097 GVX_TRACE(__PRETTY_FUNCTION__);
00098 
00099   // Open the file
00100   if (itsFileHandle != -1) close(itsFileHandle);
00101 
00102 #ifdef HAVE_O_LARGEFILE
00103   itsFileHandle = open(fname.c_str(), O_LARGEFILE | O_RDONLY);
00104 #else
00105   itsFileHandle = open(fname.c_str(), O_RDONLY);
00106 #endif
00107 
00108   if(itsFileHandle == -1) PLFATAL("Could Not Open File %s", fname.c_str());
00109 
00110   int32_t header[146];
00111   ssize_t headerSize;
00112 
00113   // Read and parse the file header
00114   headerSize = read(itsFileHandle, &header, (size_t)(sizeof(int32_t) * 146) );
00115 
00116   // Make sure then entire header was read
00117   if (headerSize != size_t(sizeof(int32_t) * 146) )
00118     LFATAL("Could not fully read .seq file header. File: %s", fname.c_str());
00119 
00120   // Check the version number on the header
00121   if(header[7] != 3)
00122     LFATAL("Wrong version number found in .seq file header (%d != 3).", header[7]);
00123 
00124   // Check the magic number on the header
00125   if(header[0] != 0xfeed)
00126     LFATAL("Missing magic number from .seq file header (%x != 0xfeed).", header[0]);
00127 
00128   if(header[139] != 8 || header[140] != 8 || (header[142] != 100 && header[142] != 101))
00129     LFATAL("seq file in a format other than 8-bit bayer\n");
00130 
00131   itsDataOffset      = header[8];    // need for seek
00132   itsWidth           = header[137];  // stored image dimensions, for read
00133   itsHeight          = header[138];
00134   itsFrameCount      = header[143];  // number of frames
00135   itsFirstFrame      = header[144];  // start number, always 0?
00136   itsTrueImageSize   = header[145];  // need for seek
00137   itsImageSizeBytes  = header[141];  // amount to read
00138 
00139   LINFO("Opening Sequence File with %d Frames", itsFrameCount);
00140 
00141   // do we want to use mmap'd I/O?
00142   if (itsUseMmap.getVal()) {
00143     // close the file and instead get a mapped_file going:
00144     close(itsFileHandle); itsFileHandle = -1;
00145     itsMmapFile.reset(new rutz::mapped_infile(fname.c_str()));
00146   }
00147 }
00148 
00149 bool SequenceFileStream::setFrameNumber(int n)
00150 {
00151   if ((unsigned int)n > itsFrameCount) return false;
00152 
00153   itsFrameOffset = n;
00154   return true;
00155 }
00156 
00157 // ######################################################################
00158 GenericFrame SequenceFileStream::readFrame()
00159 {
00160 GVX_TRACE(__PRETTY_FUNCTION__);
00161 
00162   if (itsUseMmap.getVal()) { if (itsMmapFile.is_invalid()) LFATAL("File not mmap'd"); }
00163   else { if (itsFileHandle == -1) LFATAL("File not open"); }
00164 
00165   GenericFrame ret;
00166 
00167   // do we already have a frame because we peeked its specs?
00168   if (itsFrame.initialized()) {
00169     ret = itsFrame;
00170     itsFrame = GenericFrame();
00171   } else {
00172     // Calculate the desired seek position
00173     off_t seekPosition = itsDataOffset + (itsFirstFrame + itsFrameOffset) * itsTrueImageSize;
00174 
00175     if (itsUseMmap.getVal()) {
00176       // use mmap I/O. In fact, we don't read anything proper until we
00177       // call deBayer() which will automatically swap in data as it
00178       // processes the pixels. Yeah the attach() below is hacky with
00179       // the casting, we need to remember that the mmap'd memory is
00180       // read-only so we should not try to modify any pixel in that
00181       // temporary image:
00182 
00183       //FIXME: this has issues:
00184       //      Image<byte> img;
00185       //      img.attach(const_cast<byte*>(reinterpret_cast<const byte *>(itsMmapFile->memory())) +
00186       //                 seekPosition, itsWidth, itsHeight);
00187 
00188       //FIXME: I believe this makes a deep copy...
00189       Image<byte> img(reinterpret_cast<const byte *>(itsMmapFile->memory()) + seekPosition, itsWidth, itsHeight);
00190 
00191       // Debayer the image to make it RGB; this will swap in the
00192       // necessary pages as the memory is being accessed by the
00193       // dBayer function:
00194       Image<PixRGB<byte> > frame = deBayer(img, BAYER_GRBG);
00195       ret = GenericFrame(frame);
00196 
00197       //img.detach();
00198     } else {
00199       // use regular I/O; Seek to the desired frame
00200 #ifdef HAVE_O_LARGEFILE
00201       lseek64(itsFileHandle, seekPosition, SEEK_SET);
00202 #else
00203       lseek(itsFileHandle, seekPosition, SEEK_SET);
00204 #endif
00205 
00206       // Read the frame as raw bytes
00207       Image<byte> tempImage(itsWidth, itsHeight, NO_INIT);
00208 
00209       size_t numRead = read(itsFileHandle, tempImage.getArrayPtr(), itsWidth * itsHeight);
00210 
00211       if (numRead <= 0) { LERROR("Frame Not Read From Sequence File"); return GenericFrame(); }
00212 
00213       // Debayer the image to make it RGB
00214       Image<PixRGB<byte> > frame = deBayer(tempImage, BAYER_GRBG);
00215       ret = GenericFrame(frame);
00216     }
00217     // ready for next frame:
00218     ++itsFrameOffset;
00219   }
00220 
00221   return ret;
00222 }
00223 
00224 
Generated on Sun May 8 08:41:01 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3