BobDeinterlacer.C

Go to the documentation of this file.
00001 /*!@file Transport/BobDeinterlacer.C Deinterlace frames with the "bob" method */
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/Transport/BobDeinterlacer.C $
00035 // $Id: BobDeinterlacer.C 14290 2010-12-01 21:44:03Z itti $
00036 //
00037 
00038 #ifndef TRANSPORT_BOBDEINTERLACER_C_DEFINED
00039 #define TRANSPORT_BOBDEINTERLACER_C_DEFINED
00040 
00041 #include "Transport/BobDeinterlacer.H"
00042 
00043 #include "Raster/GenericFrame.H"
00044 #include "Util/SimTime.H"
00045 
00046 // ######################################################################
00047 BobDeinterlacer::BobDeinterlacer(OptionManager& mgr)
00048   :
00049   Deinterlacer(mgr),
00050   itsFieldTime(SimTime::ZERO()),
00051   itsFrameNumber(-1),
00052   itsCurFullFrame(),
00053   itsLastFrameTime(),
00054   itsLastBottomTime(),
00055   itsUsleepAdjustment(0.0),
00056   itsDeinterlacing(false),
00057   itsInBottomField(false)
00058 {}
00059 
00060 // ######################################################################
00061 BobDeinterlacer::~BobDeinterlacer()
00062 {}
00063 
00064 // ######################################################################
00065 void BobDeinterlacer::setListener(rutz::shared_ptr<FrameListener> listener)
00066 {
00067   getDelegate().setListener(listener);
00068 }
00069 
00070 // ######################################################################
00071 GenericFrameSpec BobDeinterlacer::peekFrameSpec()
00072 {
00073   GenericFrameSpec result = getDelegate().peekFrameSpec();
00074 
00075   switch (result.nativeType)
00076     {
00077     case GenericFrame::NONE:
00078       ASSERT(0);
00079       break;
00080 
00081     case GenericFrame::RGB_U8:
00082     case GenericFrame::RGBD:
00083       result.nativeType = GenericFrame::VIDEO;
00084       result.videoFormat = VIDFMT_RGB24;
00085       result.videoByteSwap = false;
00086       break;
00087 
00088     case GenericFrame::RGB_F32:
00089       result.nativeType = GenericFrame::VIDEO;
00090       result.videoFormat = VIDFMT_RGB24;
00091       result.videoByteSwap = false;
00092       break;
00093 
00094     case GenericFrame::GRAY_U8:
00095       result.nativeType = GenericFrame::VIDEO;
00096       result.videoFormat = VIDFMT_GREY;
00097       result.videoByteSwap = false;
00098       break;
00099 
00100     case GenericFrame::GRAY_F32:
00101       result.nativeType = GenericFrame::VIDEO;
00102       result.videoFormat = VIDFMT_GREY;
00103       result.videoByteSwap = false;
00104       break;
00105 
00106     case GenericFrame::RGB_U16:
00107       break;
00108 
00109     case GenericFrame::GRAY_U16:
00110       break;
00111 
00112     case GenericFrame::VIDEO:
00113       // no changes
00114       break;
00115     }
00116 
00117   return result;
00118 }
00119 
00120 // ######################################################################
00121 SimTime BobDeinterlacer::getNaturalFrameTime() const
00122 {
00123   return itsFieldTime;
00124 }
00125 
00126 // ######################################################################
00127 bool BobDeinterlacer::setFrameNumber(int n)
00128 {
00129   ASSERT(n >= 0);
00130 
00131   bool ret = true;
00132 
00133   if (itsFrameNumber < 0
00134       || itsFrameNumber/2 != n/2)
00135     ret = getDelegate().setFrameNumber(n/2);
00136 
00137   itsFrameNumber = n;
00138 
00139   return ret;
00140 }
00141 
00142 // ######################################################################
00143 void BobDeinterlacer::startStream()
00144 {
00145   getDelegate().startStream();
00146 
00147   itsInBottomField = false;
00148 }
00149 
00150 // ######################################################################
00151 GenericFrame BobDeinterlacer::readFrame()
00152 {
00153   if (!itsDeinterlacing)
00154     // we're not deinterlacing, just just return the raw buffer:
00155     return getDelegate().readFrame();
00156 
00157   // else: OK, we're deinterlacing
00158 
00159   if (itsInBottomField)
00160     {
00161       VideoFrame bottomfield = itsCurFullFrame.makeBobDeinterlaced(1);
00162 
00163       // if we have a non-zero half-field time, then let's try a
00164       // combination of usleep() and a busy loop to get to that time
00165       // exactly:
00166       if (itsFieldTime > SimTime::ZERO())
00167         {
00168           const double elapsed =
00169             (rutz::time::wall_clock_now() - itsLastFrameTime).usec();
00170 
00171           if (elapsed < 0)
00172             LFATAL("Hey, time is moving backwards!");
00173 
00174           const double fieldusec = itsFieldTime.usecs();
00175 
00176           const int sleepusec =
00177             int(fieldusec - elapsed - itsUsleepAdjustment - 1000);
00178 
00179           // we do a usleep() for most of the delay, but then finish
00180           // the delay with a hard busy loop to get more precise
00181           // timing
00182 
00183           // not sure why we aren't getting better timing from
00184           // usleep()
00185 
00186           if (sleepusec > 0)
00187             usleep(sleepusec);
00188 
00189           while ((rutz::time::wall_clock_now() - itsLastFrameTime).usec()
00190                  < fieldusec)
00191             {
00192               // hard busy loop
00193             }
00194         }
00195 
00196       // switch to the other field for next time:
00197       itsInBottomField = false;
00198 
00199       itsLastBottomTime = rutz::time::wall_clock_now();
00200 
00201       const double half_delay =
00202         (itsLastBottomTime - itsLastFrameTime).usec();
00203 
00204       itsUsleepAdjustment += 0.5 * (half_delay - itsFieldTime.usecs());
00205 
00206       // and return the deinterlaced bottom field:
00207       return GenericFrame(bottomfield);
00208     }
00209 
00210   // else, we're waiting for a top field, so we need to grab a new
00211   // frame:
00212 
00213   itsCurFullFrame = getDelegate().readFrame().asVideo();
00214 
00215   if (!itsCurFullFrame.initialized())
00216     // ok, we got an empty frame from our delegate (probably means the
00217     // stream is exhausted), so just return an empty frame
00218     return GenericFrame();
00219 
00220   VideoFrame topfield = itsCurFullFrame.makeBobDeinterlaced(0);
00221 
00222   itsLastFrameTime = rutz::time::wall_clock_now();
00223 
00224   // switch to the other field for next time:
00225   itsInBottomField = true;
00226 
00227   // and return the deinterlaced top field:
00228   return GenericFrame(topfield);
00229 }
00230 
00231 // ######################################################################
00232 void BobDeinterlacer::start2()
00233 {
00234   Deinterlacer::start2();
00235 
00236   itsCurFullFrame = VideoFrame();
00237 
00238   // is this a deinterlaceable format?
00239   VideoFormat vidfmt = getDelegate().peekFrameSpec().videoFormat;
00240 
00241   itsDeinterlacing = isSimplePackedMode(vidfmt) || vidfmt == VIDFMT_YUV420P;
00242 
00243   if (!itsDeinterlacing)
00244     LFATAL("bob-deinterlacing is not supported for video mode %s "
00245            "(bob-deinterlacing requires a simple packed pixel format)",
00246            convertToString(vidfmt).c_str());
00247 
00248   itsInBottomField = false;
00249 
00250   const SimTime frametime = getDelegate().getNaturalFrameTime();
00251   itsFieldTime = frametime * 0.5;
00252 
00253   // NTSC: ((1.0/29.97Hz)/2.0) * (1000000.0 usec/sec) = 16683.35usec
00254   LINFO("using a half-field time of %.2fus [%.2fHz] "
00255         "(full frame time is %.2fus [%.2fHz])",
00256         itsFieldTime.usecs(), itsFieldTime.hertz(),
00257         frametime.usecs(), frametime.hertz());
00258 }
00259 
00260 // ######################################################################
00261 void BobDeinterlacer::stop2()
00262 {
00263   itsCurFullFrame = VideoFrame();
00264   itsDeinterlacing = false;
00265   itsInBottomField = false;
00266 
00267   Deinterlacer::stop2();
00268 }
00269 
00270 // ######################################################################
00271 /* So things look consistent in everyone's emacs... */
00272 /* Local Variables: */
00273 /* mode: c++ */
00274 /* indent-tabs-mode: nil */
00275 /* End: */
00276 
00277 #endif // TRANSPORT_BOBDEINTERLACER_C_DEFINED
Generated on Sun May 8 08:42:24 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3