FrameSeries.C

Go to the documentation of this file.
00001 /*!@file Media/FrameSeries.C a series of frames */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
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@klab.caltech.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Media/FrameSeries.C $
00035 // $Id: FrameSeries.C 14559 2011-03-01 22:02:47Z ehu $
00036 //
00037 
00038 #include <cstddef>
00039 #include <vector>
00040 
00041 #include "Component/GlobalOpts.H" // for OPT_TestMode
00042 #include "Component/ModelOptionDef.H"
00043 #include "Component/OptionManager.H"
00044 #include "Component/Plugin.H"
00045 #include "Devices/DC1394Grabber2.H"
00046 #include "Devices/DiskDataStream.H"
00047 #include "Devices/IEEE1394grabber.H"
00048 #include "Devices/QuickTimeGrabber.H"
00049 #include "Devices/RTSPGrabber.H"
00050 #include "Devices/V4L2grabber.H"
00051 #include "Devices/V4Lgrabber.H"
00052 #include "Devices/KinectGrabber.H"
00053 #include "Devices/OpenNIGrabber.H"
00054 #include "GUI/ImageDisplayStream.H"
00055 
00056 #include "Devices/XCgrabber.H"
00057 #include "Devices/XCgrabberFlex.H"
00058 #include "Media/FrameSeries.H"
00059 
00060 #ifdef INVT_HAVE_QT4
00061 #  include "GUI/QtDisplayStream4.H" // use the Qt4 version of QtDisplayStream if we have Qt4 installed
00062 #else
00063 #ifdef INVT_HAVE_QT3
00064 #  include "GUI/QtDisplayStream.H"
00065 #endif
00066 #endif
00067 
00068 #include "GUI/SDLdisplayStream.H"
00069 #include "Image/CutPaste.H"   // for inplaceEmbed()
00070 #include "Image/Image.H"
00071 #include "Image/Layout.H"
00072 #include "Image/Pixels.H"
00073 #include "Image/ShapeOps.H"   // for rescale()
00074 #include "Media/FrameCounter.H"
00075 #include "Media/MediaOpts.H"
00076 #include "Media/MgzInputStream.H"
00077 #include "Media/MgzJInputStream.H"
00078 #include "Media/MgzOutputStream.H"
00079 #include "Media/MgzJOutputStream.H"
00080 #include "Media/MpegInputStream.H"
00081 #include "Media/MpegOutputStream.H"
00082 #include "Media/HttpOutputStream.H"
00083 #include "Media/MrawvInputStream.H"
00084 #include "Media/MrawvOutputStream.H"
00085 #include "Media/NullOutputStream.H"
00086 #include "Media/SequenceFileStream.H"
00087 #include "Media/UcbMpegOutputStream.H"
00088 #include "Raster/GenericFrame.H"
00089 #include "Transport/BobDeinterlacer.H"
00090 #include "Transport/BufferedFrameIstream.H"
00091 #include "Transport/CoerceVideoFormatOfilt.H"
00092 #include "Transport/ColorbarsInput.H"
00093 #include "Transport/ColorizeOfilt.H"
00094 #include "Transport/FrameInfo.H"
00095 #include "Transport/FrameIstreamFactory.H"
00096 #include "Transport/FrameOstreamFactory.H"
00097 #include "Transport/GameOfLifeInput.H"
00098 #include "Transport/HalfFieldDeinterlacer.H"
00099 #include "Transport/HashOutputSeries.H"
00100 #include "Transport/InfoOutputSeries.H"
00101 #include "Transport/LuminanceOfilt.H"
00102 #include "Transport/RandomInput.H"
00103 #include "Transport/DotStimuli.H"
00104 #include "Transport/BarStimuli.H"
00105 #include "Transport/ShiftedImage.H"
00106 #include "Transport/RasterInputSeries.H"
00107 #include "Transport/RasterOutputSeries.H"
00108 #include "Transport/RasterlistInputSeries.H"
00109 #include "Transport/SplitRgbOfilt.H"
00110 #include "Transport/StatsOutputSeries.H"
00111 #include "Transport/TransportOpts.H"
00112 #include "Transport/World2DInput.H"
00113 #include "Transport/World3DInput.H"
00114 #include "Transport/XMLInput.H"
00115 #include "Transport/Stimulus2D.H"
00116 #include "Util/AllocAux.H" // for invt_allocation_set_stats_units()
00117 #include "Util/TextLog.H"
00118 #include "Util/log.H"
00119 #include "Util/sformat.H"
00120 
00121 // Private command-line option defs
00122 
00123 namespace
00124 {
00125   bool isRectEmpty(const Rectangle& rect)
00126   {
00127     return
00128       (rect.isValid() == false)
00129       ||
00130       (rect.area() == 0);
00131   }
00132 
00133   template <class T>
00134   Image<T> doResizeImage(const Image<T>& input,
00135                          const Rectangle& rect,
00136                          const Dims& dims,
00137                          const int zoom,
00138                          const bool preserveAspect)
00139   {
00140     // if we got an empty image, that means we're at the end of our
00141     // input stream and so we just pass along the empty image as is:
00142     if (!input.initialized()) return input;
00143 
00144     if (dims.isEmpty() && zoom == 0) return input;
00145 
00146     Image<T> cropped = input;
00147 
00148     if (!isRectEmpty(rect))
00149       {
00150         cropped = crop(input, rect, true);
00151       }
00152 
00153     if (zoom < 0)
00154       {
00155         const Dims zoomout(std::max(cropped.getWidth() >> (-zoom), 1),
00156                            std::max(cropped.getHeight() >> (-zoom), 1));
00157 
00158         cropped = rescale(cropped, zoomout);
00159       }
00160     else if (zoom > 0)
00161       {
00162         cropped = zoomXY(cropped, 1 << zoom, 1 << zoom);
00163       }
00164 
00165     if (preserveAspect)
00166       {
00167         Image<T> res(dims, ZEROS);
00168         T bg = T(); bg += 64;
00169         inplaceEmbed(res, cropped, res.getBounds(), bg, true);
00170         return res;
00171       }
00172 
00173     if (dims.isNonEmpty())
00174       return rescale(cropped, dims);
00175 
00176     return cropped;
00177   }
00178 
00179   GenericFrame doResizeFrame(const GenericFrame& input,
00180                              const Rectangle& rect,
00181                              const Dims& dims,
00182                              const int zoom,
00183                              const bool preserveAspect)
00184   {
00185     /* Check if we can skip resizing altogether and just return a copy
00186        of the original image.
00187 
00188        NOTE that this check is critical in allowing efficient
00189        optimizations based on representations that would are lost when
00190        we are forced to resize. For example, SDLdisplayStream is
00191        optimized for displaying YUV VideoFrame objects, and
00192        ImageDisplayStream is optimized for displaying Layout
00193        objects. When we are forced to resize a VideoFrame or Layout,
00194        those optimizations are lost because the frame has to be
00195        rendered as a plain Image before resizing.
00196     */
00197     if (zoom == 0
00198         && (dims.isEmpty() || dims == input.getDims())
00199         && !preserveAspect)
00200       return input;
00201 
00202     switch (input.nativeType())
00203       {
00204       case GenericFrame::NONE:
00205         return GenericFrame();
00206 
00207       case GenericFrame::RGB_U8:
00208         return GenericFrame(doResizeImage(input.asRgbU8(),
00209                                           rect, dims, zoom, preserveAspect));
00210 
00211       case GenericFrame::RGBD:
00212         return GenericFrame(doResizeImage(input.asRgbU8(), rect, dims, zoom, preserveAspect),
00213                             doResizeImage(input.asGrayU16(), rect, dims, zoom, preserveAspect));
00214 
00215       case GenericFrame::RGB_F32:
00216         return GenericFrame(doResizeImage(input.asRgbF32(),
00217                                           rect, dims, zoom, preserveAspect),
00218                             input.floatFlags());
00219 
00220       case GenericFrame::GRAY_U8:
00221         return GenericFrame(doResizeImage(input.asGrayU8(),
00222                                           rect, dims, zoom, preserveAspect));
00223 
00224       case GenericFrame::GRAY_F32:
00225         return GenericFrame(doResizeImage(input.asGrayF32(),
00226                                           rect, dims, zoom, preserveAspect),
00227                             input.floatFlags());
00228 
00229       case GenericFrame::VIDEO:
00230         // NOTE: if we are going to resize a VideoFrame, we'll first
00231         // have to convert it to rgb and do the resizing in that
00232         // format
00233         return GenericFrame(doResizeImage(input.asRgb(),
00234                                           rect, dims, zoom, preserveAspect));
00235 
00236       case GenericFrame::RGB_U16:
00237         return GenericFrame();  break;
00238       case GenericFrame::GRAY_U16:
00239         return GenericFrame();  break;
00240 
00241       }
00242 
00243     ASSERT(0); /* can't happen */ return GenericFrame();
00244   }
00245 
00246   // this is a file-global variable that is needed when we use
00247   // pthread_once() to initialize the factories with istream_init()
00248   // and ostream_init(); those init functions need an OptionManager to
00249   // do the initialization but pthread_once() doesn't allow any args
00250   // to be passed to the init function, thus we have to communicate
00251   // the args through an outside variable
00252   OptionManager* init_manager = 0;
00253 
00254   pthread_once_t istream_init_once = PTHREAD_ONCE_INIT;
00255 
00256   void istream_init()
00257   {
00258     ASSERT(init_manager != 0);
00259 
00260     OptionManager& mgr = *init_manager;
00261 
00262     ComponentFactory<FrameIstream>& inTypeFactory = getFrameIstreamTypeFactory();
00263 
00264     // NOTE: If you add input sources or otherwise modify the
00265     // inTypeFactory, then please also update the documentation of the
00266     // main "--in" option in the definition of OPT_InputFrameSource in
00267     // Media/MediaOpts.C so that your changes will be visible to
00268     // users.
00269 
00270     inTypeFactory.registerType<RasterInputSeries>("raster", mgr);
00271     inTypeFactory.registerType<RasterlistInputSeries>("rasterlist", mgr);
00272     inTypeFactory.registerType<InputMPEGStream>("mpeg", mgr);
00273     inTypeFactory.registerType<InputMPEGStream>("movie", mgr);
00274     inTypeFactory.registerType<RandomInput>("random", mgr);
00275     inTypeFactory.registerType<DotStimuli>("dots", mgr);
00276     inTypeFactory.registerType<BarStimuli>("bars", mgr);
00277     inTypeFactory.registerType<ShiftedImage>("shiftedImage", mgr);
00278     inTypeFactory.registerType<GameOfLifeInput>("life", mgr);
00279     inTypeFactory.registerType<World2DInput>("World2D", mgr);
00280     inTypeFactory.registerType<World3DInput>("World3D", mgr);
00281     inTypeFactory.registerType<Stimulus2D>("stimulus2D", mgr);
00282     inTypeFactory.registerType<XMLInput>("xmlfile", mgr);
00283 #ifdef HAVE_LINUX_VIDEODEV_H
00284     inTypeFactory.registerType<V4Lgrabber>("v4l", mgr);
00285 #endif
00286 #ifdef HAVE_LINUX_VIDEODEV2_H
00287     inTypeFactory.registerType<V4L2grabber>("v4l2", mgr);
00288 #endif
00289     inTypeFactory.registerType<IEEE1394grabber>("ieee1394", mgr);
00290 #ifdef HAVE_XCLIB
00291     inTypeFactory.registerType<XCgrabber>("XC", mgr);
00292 #endif
00293 #ifdef HAVE_XCLIB
00294     inTypeFactory.registerType<XCgrabberFlex>("XCFLEX", mgr);
00295 #endif
00296     inTypeFactory.registerType<DC1394Grabber2>("dc1394v2", mgr);
00297     inTypeFactory.registerType<QuickTimeGrabber>("qtgrab", mgr);
00298 #ifdef INVT_HAVE_LIBFREENECT
00299     inTypeFactory.registerType<KinectGrabber>("kinect", mgr);
00300 #endif
00301 #ifdef INVT_HAVE_OPENNI
00302     inTypeFactory.registerType<OpenNIGrabber>("openni", mgr);
00303 #endif
00304     inTypeFactory.registerType<RTSPGrabber>("rtsp", mgr);
00305     inTypeFactory.registerType<ColorbarsInput>("colorbars", mgr);
00306     inTypeFactory.registerType<BobDeinterlacer>("bob", mgr);
00307     inTypeFactory.registerType<HalfFieldDeinterlacer<true> >("bhf", mgr);
00308     inTypeFactory.registerType<HalfFieldDeinterlacer<false> >("thf", mgr);
00309     inTypeFactory.registerType<MgzInputStream>("mgz", mgr);
00310     inTypeFactory.registerType<MgzJInputStream>("mgzJ", mgr);
00311     inTypeFactory.registerType<BufferedFrameIstream>("buf", mgr);
00312     inTypeFactory.registerType<MrawvInputStream>("mraw", mgr);
00313 
00314     inTypeFactory.set_fallback
00315       (rutz::make_shared(new PluginFallback(init_manager, "FrameIstream")));
00316 
00317     ComponentFactory<FrameIstream>& inExtFactory = getFrameIstreamExtFactory();
00318 
00319     // NOTE: If you add input sources or otherwise modify the
00320     // inExtFactory, then please also update the documentation of the
00321     // main "--in" option in the definition of OPT_InputFrameSource in
00322     // Media/MediaOpts.C so that your changes will be visible to
00323     // users.
00324 
00325     inExtFactory.registerType<RasterInputSeries>("pnm", mgr);     // RASFMT_PNM
00326     inExtFactory.registerType<RasterInputSeries>("pgm", mgr);     // RASFMT_PNM
00327     inExtFactory.registerType<RasterInputSeries>("ppm", mgr);     // RASFMT_PNM
00328     inExtFactory.registerType<RasterInputSeries>("pbm", mgr);     // RASFMT_PNM
00329     inExtFactory.registerType<RasterInputSeries>("pfm", mgr);     // RASFMT_PFM
00330     inExtFactory.registerType<RasterInputSeries>("png", mgr);     // RASFMT_PNG
00331     inExtFactory.registerType<RasterInputSeries>("jpeg", mgr);    // RASFMT_JPEG
00332     inExtFactory.registerType<RasterInputSeries>("jpg", mgr);     // RASFMT_JPEG
00333     inExtFactory.registerType<RasterInputSeries>("dpx", mgr);     // RASFMT_DPX
00334 
00335     inExtFactory.registerType<RasterInputSeries>("grey", mgr);    // RASFMT_RAW_VIDEO
00336     inExtFactory.registerType<RasterInputSeries>("rgb555", mgr);  // RASFMT_RAW_VIDEO
00337     inExtFactory.registerType<RasterInputSeries>("rgb565", mgr);  // RASFMT_RAW_VIDEO
00338     inExtFactory.registerType<RasterInputSeries>("rgb24", mgr);   // RASFMT_RAW_VIDEO
00339     inExtFactory.registerType<RasterInputSeries>("rgb32", mgr);   // RASFMT_RAW_VIDEO
00340     inExtFactory.registerType<RasterInputSeries>("yuv24", mgr);   // RASFMT_RAW_VIDEO
00341     inExtFactory.registerType<RasterInputSeries>("yuyv", mgr);    // RASFMT_RAW_VIDEO
00342     inExtFactory.registerType<RasterInputSeries>("uyvy", mgr);    // RASFMT_RAW_VIDEO
00343     inExtFactory.registerType<RasterInputSeries>("yuv444", mgr);  // RASFMT_RAW_VIDEO
00344     inExtFactory.registerType<RasterInputSeries>("yuv422", mgr);  // RASFMT_RAW_VIDEO
00345     inExtFactory.registerType<RasterInputSeries>("yuv411", mgr);  // RASFMT_RAW_VIDEO
00346     inExtFactory.registerType<RasterInputSeries>("yuv420", mgr);  // RASFMT_RAW_VIDEO
00347     inExtFactory.registerType<RasterInputSeries>("yuv410", mgr);  // RASFMT_RAW_VIDEO
00348     inExtFactory.registerType<RasterInputSeries>("yuv444p", mgr); // RASFMT_RAW_VIDEO
00349     inExtFactory.registerType<RasterInputSeries>("yuv422p", mgr); // RASFMT_RAW_VIDEO
00350     inExtFactory.registerType<RasterInputSeries>("yuv411p", mgr); // RASFMT_RAW_VIDEO
00351     inExtFactory.registerType<RasterInputSeries>("yuv420p", mgr); // RASFMT_RAW_VIDEO
00352     inExtFactory.registerType<RasterInputSeries>("yuv410p", mgr); // RASFMT_RAW_VIDEO
00353 
00354     inExtFactory.registerType<RasterInputSeries>("grey.gz", mgr);    // RASFMT_RAW_VIDEO
00355     inExtFactory.registerType<RasterInputSeries>("rgb555.gz", mgr);  // RASFMT_RAW_VIDEO
00356     inExtFactory.registerType<RasterInputSeries>("rgb565.gz", mgr);  // RASFMT_RAW_VIDEO
00357     inExtFactory.registerType<RasterInputSeries>("rgb24.gz", mgr);   // RASFMT_RAW_VIDEO
00358     inExtFactory.registerType<RasterInputSeries>("rgb32.gz", mgr);   // RASFMT_RAW_VIDEO
00359     inExtFactory.registerType<RasterInputSeries>("yuv24.gz", mgr);   // RASFMT_RAW_VIDEO
00360     inExtFactory.registerType<RasterInputSeries>("yuyv.gz", mgr);    // RASFMT_RAW_VIDEO
00361     inExtFactory.registerType<RasterInputSeries>("uyvy.gz", mgr);    // RASFMT_RAW_VIDEO
00362     inExtFactory.registerType<RasterInputSeries>("yuv444.gz", mgr);  // RASFMT_RAW_VIDEO
00363     inExtFactory.registerType<RasterInputSeries>("yuv422.gz", mgr);  // RASFMT_RAW_VIDEO
00364     inExtFactory.registerType<RasterInputSeries>("yuv411.gz", mgr);  // RASFMT_RAW_VIDEO
00365     inExtFactory.registerType<RasterInputSeries>("yuv420.gz", mgr);  // RASFMT_RAW_VIDEO
00366     inExtFactory.registerType<RasterInputSeries>("yuv410.gz", mgr);  // RASFMT_RAW_VIDEO
00367     inExtFactory.registerType<RasterInputSeries>("yuv444p.gz", mgr); // RASFMT_RAW_VIDEO
00368     inExtFactory.registerType<RasterInputSeries>("yuv422p.gz", mgr); // RASFMT_RAW_VIDEO
00369     inExtFactory.registerType<RasterInputSeries>("yuv411p.gz", mgr); // RASFMT_RAW_VIDEO
00370     inExtFactory.registerType<RasterInputSeries>("yuv420p.gz", mgr); // RASFMT_RAW_VIDEO
00371     inExtFactory.registerType<RasterInputSeries>("yuv410p.gz", mgr); // RASFMT_RAW_VIDEO
00372 
00373     inExtFactory.registerType<RasterInputSeries>("grey.bz2", mgr);    // RASFMT_RAW_VIDEO
00374     inExtFactory.registerType<RasterInputSeries>("rgb555.bz2", mgr);  // RASFMT_RAW_VIDEO
00375     inExtFactory.registerType<RasterInputSeries>("rgb565.bz2", mgr);  // RASFMT_RAW_VIDEO
00376     inExtFactory.registerType<RasterInputSeries>("rgb24.bz2", mgr);   // RASFMT_RAW_VIDEO
00377     inExtFactory.registerType<RasterInputSeries>("rgb32.bz2", mgr);   // RASFMT_RAW_VIDEO
00378     inExtFactory.registerType<RasterInputSeries>("yuv24.bz2", mgr);   // RASFMT_RAW_VIDEO
00379     inExtFactory.registerType<RasterInputSeries>("yuyv.bz2", mgr);    // RASFMT_RAW_VIDEO
00380     inExtFactory.registerType<RasterInputSeries>("uyvy.bz2", mgr);    // RASFMT_RAW_VIDEO
00381     inExtFactory.registerType<RasterInputSeries>("yuv444.bz2", mgr);  // RASFMT_RAW_VIDEO
00382     inExtFactory.registerType<RasterInputSeries>("yuv422.bz2", mgr);  // RASFMT_RAW_VIDEO
00383     inExtFactory.registerType<RasterInputSeries>("yuv411.bz2", mgr);  // RASFMT_RAW_VIDEO
00384     inExtFactory.registerType<RasterInputSeries>("yuv420.bz2", mgr);  // RASFMT_RAW_VIDEO
00385     inExtFactory.registerType<RasterInputSeries>("yuv410.bz2", mgr);  // RASFMT_RAW_VIDEO
00386     inExtFactory.registerType<RasterInputSeries>("yuv444p.bz2", mgr); // RASFMT_RAW_VIDEO
00387     inExtFactory.registerType<RasterInputSeries>("yuv422p.bz2", mgr); // RASFMT_RAW_VIDEO
00388     inExtFactory.registerType<RasterInputSeries>("yuv411p.bz2", mgr); // RASFMT_RAW_VIDEO
00389     inExtFactory.registerType<RasterInputSeries>("yuv420p.bz2", mgr); // RASFMT_RAW_VIDEO
00390     inExtFactory.registerType<RasterInputSeries>("yuv410p.bz2", mgr); // RASFMT_RAW_VIDEO
00391 
00392     inExtFactory.registerType<InputMPEGStream>("avi", mgr);
00393     inExtFactory.registerType<InputMPEGStream>("mpg", mgr);
00394     inExtFactory.registerType<InputMPEGStream>("mpeg", mgr);
00395     inExtFactory.registerType<InputMPEGStream>("m4v", mgr);
00396     inExtFactory.registerType<InputMPEGStream>("mov", mgr);
00397     inExtFactory.registerType<InputMPEGStream>("flv", mgr);  // Flash video, supported by ffmpeg
00398     inExtFactory.registerType<InputMPEGStream>("dv", mgr);
00399     inExtFactory.registerType<InputMPEGStream>("asf", mgr);
00400     inExtFactory.registerType<InputMPEGStream>("wmv", mgr);
00401     inExtFactory.registerType<InputMPEGStream>("m2ts", mgr);
00402 
00403     inExtFactory.registerType<MgzInputStream>("mgz", mgr);
00404     inExtFactory.registerType<MgzJInputStream>("mgzJ", mgr);
00405 
00406     inExtFactory.registerType<MrawvInputStream>("mgrey", mgr);
00407     inExtFactory.registerType<MrawvInputStream>("mrgb555", mgr);
00408     inExtFactory.registerType<MrawvInputStream>("mrgb565", mgr);
00409     inExtFactory.registerType<MrawvInputStream>("mrgb24", mgr);
00410     inExtFactory.registerType<MrawvInputStream>("mrgb32", mgr);
00411     inExtFactory.registerType<MrawvInputStream>("myuv24", mgr);
00412     inExtFactory.registerType<MrawvInputStream>("myuyv", mgr);
00413     inExtFactory.registerType<MrawvInputStream>("muyvy", mgr);
00414     inExtFactory.registerType<MrawvInputStream>("myuv444", mgr);
00415     inExtFactory.registerType<MrawvInputStream>("myuv422", mgr);
00416     inExtFactory.registerType<MrawvInputStream>("myuv411", mgr);
00417     inExtFactory.registerType<MrawvInputStream>("myuv420", mgr);
00418     inExtFactory.registerType<MrawvInputStream>("myuv410", mgr);
00419     inExtFactory.registerType<MrawvInputStream>("myuv444p", mgr);
00420     inExtFactory.registerType<MrawvInputStream>("myuv422p", mgr);
00421     inExtFactory.registerType<MrawvInputStream>("myuv411p", mgr);
00422     inExtFactory.registerType<MrawvInputStream>("myuv420p", mgr);
00423     inExtFactory.registerType<MrawvInputStream>("myuv410p", mgr);
00424 
00425     inExtFactory.registerType<MrawvInputStream>("mgrey.gz", mgr);
00426     inExtFactory.registerType<MrawvInputStream>("mrgb555.gz", mgr);
00427     inExtFactory.registerType<MrawvInputStream>("mrgb565.gz", mgr);
00428     inExtFactory.registerType<MrawvInputStream>("mrgb24.gz", mgr);
00429     inExtFactory.registerType<MrawvInputStream>("mrgb32.gz", mgr);
00430     inExtFactory.registerType<MrawvInputStream>("myuv24.gz", mgr);
00431     inExtFactory.registerType<MrawvInputStream>("myuyv.gz", mgr);
00432     inExtFactory.registerType<MrawvInputStream>("muyvy.gz", mgr);
00433     inExtFactory.registerType<MrawvInputStream>("myuv444.gz", mgr);
00434     inExtFactory.registerType<MrawvInputStream>("myuv422.gz", mgr);
00435     inExtFactory.registerType<MrawvInputStream>("myuv411.gz", mgr);
00436     inExtFactory.registerType<MrawvInputStream>("myuv420.gz", mgr);
00437     inExtFactory.registerType<MrawvInputStream>("myuv410.gz", mgr);
00438     inExtFactory.registerType<MrawvInputStream>("myuv444p.gz", mgr);
00439     inExtFactory.registerType<MrawvInputStream>("myuv422p.gz", mgr);
00440     inExtFactory.registerType<MrawvInputStream>("myuv411p.gz", mgr);
00441     inExtFactory.registerType<MrawvInputStream>("myuv420p.gz", mgr);
00442     inExtFactory.registerType<MrawvInputStream>("myuv410p.gz", mgr);
00443 
00444     inExtFactory.registerType<MrawvInputStream>("mgrey.bz2", mgr);
00445     inExtFactory.registerType<MrawvInputStream>("mrgb555.bz2", mgr);
00446     inExtFactory.registerType<MrawvInputStream>("mrgb565.bz2", mgr);
00447     inExtFactory.registerType<MrawvInputStream>("mrgb24.bz2", mgr);
00448     inExtFactory.registerType<MrawvInputStream>("mrgb32.bz2", mgr);
00449     inExtFactory.registerType<MrawvInputStream>("myuv24.bz2", mgr);
00450     inExtFactory.registerType<MrawvInputStream>("myuyv.bz2", mgr);
00451     inExtFactory.registerType<MrawvInputStream>("muyvy.bz2", mgr);
00452     inExtFactory.registerType<MrawvInputStream>("myuv444.bz2", mgr);
00453     inExtFactory.registerType<MrawvInputStream>("myuv422.bz2", mgr);
00454     inExtFactory.registerType<MrawvInputStream>("myuv411.bz2", mgr);
00455     inExtFactory.registerType<MrawvInputStream>("myuv420.bz2", mgr);
00456     inExtFactory.registerType<MrawvInputStream>("myuv410.bz2", mgr);
00457     inExtFactory.registerType<MrawvInputStream>("myuv444p.bz2", mgr);
00458     inExtFactory.registerType<MrawvInputStream>("myuv422p.bz2", mgr);
00459     inExtFactory.registerType<MrawvInputStream>("myuv411p.bz2", mgr);
00460     inExtFactory.registerType<MrawvInputStream>("myuv420p.bz2", mgr);
00461     inExtFactory.registerType<MrawvInputStream>("myuv410p.bz2", mgr);
00462 
00463     inExtFactory.registerType<XMLInput>("xml", mgr);
00464     inExtFactory.registerType<SequenceFileStream>("seq", mgr);
00465     inExtFactory.registerType<Stimulus2D>("stim2d", mgr);
00466   }
00467 
00468   pthread_once_t ostream_init_once = PTHREAD_ONCE_INIT;
00469 
00470   void ostream_init()
00471   {
00472     ASSERT(init_manager != 0);
00473 
00474     OptionManager& mgr = *init_manager;
00475 
00476     ComponentFactory<FrameOstream>& outTypeFactory = getFrameOstreamTypeFactory();
00477 
00478     // NOTE: If you add output destinations or otherwise modify the
00479     // outTypeFactory, then please also update the documentation of
00480     // the main "--out" option in the definition of
00481     // OPT_OutputFrameSink in Media/MediaOpts.C so that your changes
00482     // will be visible to users.
00483 
00484     outTypeFactory.registerType<GenericRasterOutputSeries>("raster", mgr);
00485     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_PNM> >("pnm", mgr);
00486     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_PNM> >("pgm", mgr);
00487     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_PNM> >("ppm", mgr);
00488     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_PNM> >("pbm", mgr);
00489     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_PFM> >("pfm", mgr);
00490     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_PNG> >("png", mgr);
00491     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_RAW_VIDEO> >("rawvideo", mgr);
00492     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_TXT> >("txt", mgr);
00493     outTypeFactory.registerType<FixedRasterOutputSeries<RASFMT_CCODE> >("ccode", mgr);
00494 
00495     outTypeFactory.registerType<DiskDataStream>("bkg-rawvideo", mgr);
00496 
00497     outTypeFactory.registerType<ImageDisplayStream>("display", mgr);
00498 #ifdef HAVE_SDL_SDL_H
00499     outTypeFactory.registerType<SDLdisplayStream>("sdl", mgr);
00500 #endif
00501 #if defined(INVT_HAVE_QT3) || defined(INVT_HAVE_QT4)
00502     outTypeFactory.registerType<QtDisplayStream>("qt", mgr);
00503 #endif
00504 #ifdef INVT_HAVE_AVCODEC
00505     outTypeFactory.registerType<OutputMPEGStream>("mpeg", mgr);
00506     outTypeFactory.registerType<OutputMPEGStream>("movie", mgr);
00507     outTypeFactory.registerType<OutputHttpStream>("http", mgr);
00508 #endif
00509 #ifdef MPEGENCODE_PROG
00510     outTypeFactory.registerType<UcbMpegOutputStream>("ucbmpeg", mgr);
00511 #endif
00512     outTypeFactory.registerType<HashOutputSeries>("hash", mgr);
00513     outTypeFactory.registerType<InfoOutputSeries>("info", mgr);
00514     outTypeFactory.registerType<StatsOutputSeries>("stats", mgr);
00515     outTypeFactory.registerType<MgzOutputStream>("mgz", mgr);
00516     outTypeFactory.registerType<MgzJOutputStream>("mgzJ", mgr);
00517     outTypeFactory.registerType<MrawvOutputStream>("mraw", mgr);
00518     outTypeFactory.registerType<NullOutputStream>("null", mgr);
00519     outTypeFactory.registerType<SplitRgbOfilt>("splitrgb", mgr);
00520     outTypeFactory.registerType<LuminanceOfilt>("luminance", mgr);
00521     outTypeFactory.registerType<ColorizeOfilt>("colorize", mgr);
00522 
00523     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_GREY> >("coerce-grey", mgr);
00524     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_RGB555> >("coerce-rgb555", mgr);
00525     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_RGB565> >("coerce-rgb565", mgr);
00526     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_RGB24> >("coerce-rgb24", mgr);
00527     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_RGB32> >("coerce-rgb32", mgr);
00528     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV24> >("coerce-yuv24", mgr);
00529     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUYV> >("coerce-yuyv", mgr);
00530     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_UYVY> >("coerce-uyvy", mgr);
00531     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV444> >("coerce-yuv444", mgr);
00532     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV422> >("coerce-yuv422", mgr);
00533     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV411> >("coerce-yuv411", mgr);
00534     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV444P> >("coerce-yuv444p", mgr);
00535     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV422P> >("coerce-yuv422p", mgr);
00536     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV411P> >("coerce-yuv411p", mgr);
00537     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV420P> >("coerce-yuv420p", mgr);
00538     outTypeFactory.registerType<TCoerceVideoFormatOfilt<VIDFMT_YUV410P> >("coerce-yuv410p", mgr);
00539 
00540     outTypeFactory.set_fallback
00541       (rutz::make_shared(new PluginFallback(init_manager, "FrameOstream")));
00542 
00543     ComponentFactory<FrameOstream>& outExtFactory = getFrameOstreamExtFactory();
00544 
00545     // NOTE: If you add output destinations or otherwise modify the
00546     // outExtFactory, then please also update the documentation of the
00547     // main "--out" option in the definition of OPT_OutputFrameSink in
00548     // Media/MediaOpts.C so that your changes will be visible to
00549     // users.
00550 
00551     outExtFactory.registerType<FixedRasterOutputSeries<RASFMT_PNM> >("pnm", mgr);
00552     outExtFactory.registerType<FixedRasterOutputSeries<RASFMT_PNM> >("pgm", mgr);
00553     outExtFactory.registerType<FixedRasterOutputSeries<RASFMT_PNM> >("ppm", mgr);
00554     outExtFactory.registerType<FixedRasterOutputSeries<RASFMT_PNM> >("pbm", mgr);
00555     outExtFactory.registerType<FixedRasterOutputSeries<RASFMT_PFM> >("pfm", mgr);
00556     outExtFactory.registerType<FixedRasterOutputSeries<RASFMT_PNG> >("png", mgr);
00557     outExtFactory.registerType<FixedRasterOutputSeries<RASFMT_TXT> >("txt", mgr);
00558     outExtFactory.registerType<FixedRasterOutputSeries<RASFMT_CCODE> >("C", mgr);
00559 
00560 #ifdef INVT_HAVE_AVCODEC
00561     outExtFactory.registerType<OutputMPEGStream>("mpg", mgr);
00562     outExtFactory.registerType<OutputMPEGStream>("mpeg", mgr);
00563     outExtFactory.registerType<OutputMPEGStream>("m4v", mgr);
00564 #endif
00565 
00566     outExtFactory.registerType<MgzOutputStream>("mgz", mgr);
00567     outExtFactory.registerType<MgzJOutputStream>("mgzJ", mgr);
00568   }
00569 }
00570 
00571 // ######################################################################
00572 // #################### InputFrameSeries
00573 // ######################################################################
00574 
00575 struct InputFrameSeries::Impl
00576 {
00577   Impl(OptionManager& mgr, const FrameRange& range, bool wrap=false)
00578     :
00579     source(),
00580     sourceDescription(),
00581     echoes(),
00582     numEchoed(0),
00583     inputEof(false),
00584     lastUpdateTime(SimTime::ZERO()),
00585     counter(range, wrap)
00586   { 
00587   }
00588 
00589   nub::soft_ref<FrameIstream> source;
00590   std::string sourceDescription;
00591   std::vector<nub::ref<FrameOstream> > echoes;
00592 
00593   int numEchoed;
00594 
00595   bool inputEof;
00596 
00597   SimTime lastUpdateTime;
00598 
00599   FrameCounter counter;
00600 
00601   bool setFrameNumber(int n)
00602   {
00603     //If our source doesn't allow us to seek, then don't mess
00604     //around with anything - just return false to the user.
00605     if(!this->source->supportsSeek() && this->counter.currentFrame() > n) return false;
00606 
00607     return this->counter.setCurrent(n);
00608   }
00609 
00610   // auxiliary implementation function around which readRGB(),
00611   // readGray(), readFloat() are thin wrappers
00612   GenericFrame readFrame(InputFrameSeries* self)
00613   {
00614     // double check we have a valid source
00615     ASSERT(this->source.is_valid());
00616 
00617     const int fnum = this->counter.currentFrame();
00618     if (this->source->setFrameNumber(fnum))
00619       {
00620         const GenericFrame ima =
00621           doResizeFrame(this->source->readFrame(),
00622                         self->itsCropRect.getVal(),
00623                         self->itsDims.getVal(),
00624                         /* zoom */ 0,
00625                         self->itsPreserveAspect.getVal());
00626 
00627         if (ima.initialized())
00628           {
00629             LDEBUG("%s frame %d at %.2fms",
00630                    self->tagName().c_str(), fnum,
00631                    this->lastUpdateTime.msecs());
00632 
00633             textLog(self->itsLogFile.getVal(),
00634                     self->tagName().c_str(),
00635                     sformat("frame %d", fnum),
00636                     this->lastUpdateTime);
00637 
00638             // send the image out to all echo destinations:
00639             for (uint i = 0; i < this->echoes.size(); ++i)
00640               {
00641                 this->echoes[i]->setFrameNumber(fnum);
00642                 this->echoes[i]->writeFrame
00643                   (ima, "input-echo",
00644                    FrameInfo("copy of input frame", SRC_POS));
00645                 ++this->numEchoed;
00646               }
00647 
00648             // set the default stats units so that it will be
00649             // available for later display of memory stats:
00650             invt_allocation_set_stats_units(ima.frameSpec().dims.sz());
00651 
00652             return ima;
00653           }
00654         else
00655           LINFO("input exhausted (readFrame() returned empty)");
00656       }
00657     else
00658       LINFO("input exhausted (setFrameNumber() returned false)");
00659 
00660     // something failed, so we're at eof; now keep track of whether
00661     // we've hit eof, so that we can use that information in update()
00662     this->inputEof = true;
00663 
00664     return GenericFrame();
00665   }
00666 };
00667 
00668 InputFrameSeries::InputFrameSeries(OptionManager& mgr,
00669                                    const std::string& descrName,
00670                                    const std::string& tag) :
00671   FrameIstream(mgr, "Input "+descrName, "Input"+tag),
00672   itsLogFile(&OPT_TextLogFile, this),
00673   itsTestMode(&OPT_TestMode, this),
00674   itsFrameRange(&OPT_InputFrameRange, this),
00675   itsFrameWrap(&OPT_InputFramesWrap, this),
00676   itsCropRect(&OPT_InputFrameCrop, this),
00677   itsDims(&OPT_InputFrameDims, this),
00678   itsPreserveAspect(&OPT_InputPreserveAspect, this),
00679   itsZeroNumberFrames(&OPT_ZeroNumberFrames, this),
00680   itsFrameSource(&OPT_InputFrameSource, this),
00681   itsInOut(&OPT_InputOutputComboSpec, this),
00682   itsInputEcho(&OPT_InputEchoDest, this),
00683   itsWaitForUser(&OPT_WaitForUser, this),
00684   itsKeepGoing(&OPT_KeepGoing, this),
00685   rep(new Impl(mgr, itsFrameRange.getVal(), itsFrameWrap.getVal()))
00686 {
00687   init_manager = &mgr;
00688   pthread_once(&istream_init_once, &istream_init);
00689   pthread_once(&ostream_init_once, &ostream_init);
00690 }
00691 
00692 // ######################################################################
00693 InputFrameSeries::~InputFrameSeries()
00694 {
00695   delete rep;
00696 }
00697 
00698 // ######################################################################
00699 void InputFrameSeries::reset1()
00700 {
00701   // reset some stuff for FrameSeries
00702   rep->counter.reset(itsFrameRange.getVal(), false, itsFrameWrap.getVal());
00703   rep->numEchoed = 0;
00704   rep->inputEof = false;
00705 
00706   // propagate to our base class:
00707   FrameIstream::reset1();
00708 }
00709 
00710 
00711 // ######################################################################
00712 void InputFrameSeries::setFrameDims(Dims d)
00713 {
00714   OptionManager& mgr = getManager();
00715   mgr.setOptionValString(&OPT_InputFrameDims,
00716                          convertToString(d));
00717 }
00718 
00719 // ######################################################################
00720 Dims InputFrameSeries::getFrameDims()
00721 {
00722   return itsDims.getVal();
00723 }
00724 
00725 
00726 
00727 // ######################################################################
00728 void InputFrameSeries::paramChanged(ModelParamBase* const param,
00729                                     const bool valueChanged,
00730                                     ParamClient::ChangeStatus* status)
00731 {
00732   FrameIstream::paramChanged(param, valueChanged, status);
00733 
00734   if (param == &itsFrameSource)
00735     {
00736       if (itsFrameSource.getVal() != "")
00737         this->setFrameSource(itsFrameSource.getVal());
00738     }
00739   else if (param == &itsInOut)
00740     {
00741       if (itsInOut.getVal() != "")
00742         this->setFrameSource(itsInOut.getVal());
00743     }
00744   else if (param == &itsInputEcho)
00745     {
00746       OptionManager& mgr = getManager();
00747 
00748       if (itsInputEcho.getVal() == "")
00749         {
00750           // ignore
00751         }
00752       else if (itsInputEcho.getVal() == "none")
00753         {
00754           rep->echoes.clear();
00755         }
00756       else
00757         {
00758           nub::ref<FrameOstream> f = makeFrameOstream(itsInputEcho.getVal(), mgr);
00759 
00760           rep->echoes.push_back(f);
00761           this->addSubComponent(f);
00762           f->exportOptions(MC_RECURSE);
00763         }
00764     }
00765   else if (param == &itsFrameRange)
00766     {
00767       rep->counter.reset(itsFrameRange.getVal(), false);
00768     }
00769 }
00770 
00771 // ######################################################################
00772 FrameState InputFrameSeries::update(const SimTime& stime)
00773 {
00774 
00775   // check if we've hit eof, and handle it accordingly
00776   if (rep->inputEof)
00777     {
00778       if (itsKeepGoing.getVal())
00779         // ok, user wants to keep going even though we're out of input
00780         return FRAME_SAME;
00781       else
00782         // default case is to quit when we're out of input
00783         return FRAME_COMPLETE;
00784     }
00785 
00786   rep->numEchoed = 0;
00787 
00788   rep->lastUpdateTime = stime;
00789 
00790   const FrameState result = rep->counter.update(stime);
00791 
00792   if (result != FRAME_SAME)
00793     {
00794       const int fnum = rep->counter.currentFrame();
00795 
00796       LDEBUG("%s frame %d at %.2fms",
00797             rep->source->tagName().c_str(), fnum, stime.msecs());
00798     }
00799 
00800   return result;
00801 }
00802 
00803 // ######################################################################
00804 FrameState InputFrameSeries::updateNext()
00805 {
00806   return rep->counter.updateNext();
00807 }
00808 
00809 // ######################################################################
00810 bool InputFrameSeries::shouldWait() const
00811 {
00812   return rep->numEchoed > 0
00813     && itsWaitForUser.getVal() == true
00814     && !itsTestMode.getVal();
00815 }
00816 
00817 // ######################################################################
00818 void InputFrameSeries::start1()
00819 {
00820   if (!rep->source.is_valid())
00821     {
00822       LFATAL("\n\tOops, you didn't specify an input frame source.\n"
00823              "\tFor example, you can use --in=raster:path/to/filestem,\n"
00824              "\tor --in=mpeg:path/to/file.mpg, or --in=random:256x256.");
00825     }
00826 
00827   rep->counter.reset(itsFrameRange.getVal(), false, itsFrameWrap.getVal());
00828 
00829   const int fnum = rep->counter.currentFrame();
00830   if (!rep->source->setFrameNumber(fnum))
00831     LFATAL("couldn't initialize frame source %s to frame number %d",
00832            rep->sourceDescription.c_str(), fnum);
00833 
00834   rep->inputEof = false;
00835 }
00836 
00837 // ######################################################################
00838 void InputFrameSeries::start2()
00839 {
00840   FrameIstream::start2();
00841 
00842   // get the fully cooked input frame dims (after possible resizing
00843   // and framing):
00844   const Dims indims = this->peekDims();
00845 
00846   OptionManager& mgr = getManager();
00847 
00848 
00849   // Setting the command line option of dim-size here is hacky because 
00850   // the dim size is now assumed to come from the user even *after* a 
00851   // change of setFrameSource().  The dims from peekDims() should be used, 
00852   // and NOT this option... However, I don't know exactly where this is 
00853   // used yet, so I have an externally controlled fix of calling 
00854   // setFrameDims(Dims()) before setFrameSource() to destroy 
00855   // the value (and thus ignoring any user requests)
00856   // In reality this option must never be touched and peekDims()
00857   // exclusively used.  -DFP 10152010
00858   // set the input dims if someone wants them but they are not set:
00859   Dims idim(0, 0);
00860   convertFromString(mgr.getOptionValString(&OPT_InputFrameDims), idim);
00861   if (idim.isEmpty())
00862     mgr.setOptionValString(&OPT_InputFrameDims,
00863                            convertToString(indims));
00864 
00865   ASSERT(rep->source.is_valid());
00866 
00867   //Grab a copy of the FrameRange from our actual input source to see if it
00868   //has any hard restrictions on the frames it can retrieve.  If it does, then
00869   //create a union of the most restrictive of each of the parameters from the user
00870   //and the source.
00871   FrameRange repRng = rep->source->getFrameRange();
00872   FrameRange usrRng = this->getFrameRange();
00873   if(repRng != FrameRange())
00874   {
00875     std::vector<SimTime> delayTimes(usrRng.numDelayTimes());
00876     for(size_t i=0; i<usrRng.numDelayTimes(); i++)
00877       delayTimes.at(i) = usrRng.getDelayTime(i);
00878 
00879     FrameRange newRange(
00880           repRng.getFirst() > usrRng.getFirst() ? repRng.getFirst() : usrRng.getFirst(),
00881           usrRng.getStep(),
00882           repRng.getLast() < usrRng.getLast() ?   repRng.getLast()  : usrRng.getLast(),
00883           delayTimes,
00884           usrRng.isEventTriggered()
00885         );
00886 
00887     rep->counter.reset(newRange, true);
00888     itsFrameRange.setVal(newRange);
00889   }
00890 
00891 
00892 
00893 
00894   const GenericFrameSpec origspec = rep->source->peekFrameSpec();
00895   const GenericFrameSpec finalspec = this->peekFrameSpec();
00896 
00897   const std::string description =
00898     origspec == finalspec
00899     ? origspec.getDescription()
00900     : sformat("originally %s; converted to %s",
00901               origspec.getDescription().c_str(),
00902               finalspec.getDescription().c_str());
00903 
00904   LINFO("input frames: %s", description.c_str());
00905   textLog(itsLogFile.getVal(),
00906           "InputDims", sformat("%dx%d", indims.w(), indims.h()));
00907 }
00908 
00909 // ######################################################################
00910 GenericFrameSpec InputFrameSeries::peekFrameSpec()
00911 {
00912   // double check we have a valid source
00913   ASSERT(rep->source.is_valid());
00914 
00915   const int fnum = rep->counter.currentFrame();
00916 
00917   if (!rep->source->setFrameNumber(fnum))
00918     LFATAL("couldn't initialize frame source %s to frame number %d",
00919            rep->sourceDescription.c_str(), fnum);
00920 
00921   const GenericFrameSpec origspec = rep->source->peekFrameSpec();
00922 
00923   GenericFrameSpec result = origspec;
00924 
00925   // if we are doing resizing, our dims are the resized dims:
00926   if (itsDims.getVal().isNonEmpty())
00927     result.dims = itsDims.getVal();
00928 
00929   // otherwise if we are cropping, our dims are the cropped dims:
00930   else if (!isRectEmpty(itsCropRect.getVal()))
00931     result.dims = itsCropRect.getVal().dims();
00932 
00933   // now, if the dims have changed, then a VideoFrame will decay to
00934   // Image<PixRGB<byte> >
00935   if (result.dims != origspec.dims
00936       && origspec.nativeType == GenericFrame::VIDEO)
00937     result.nativeType = GenericFrame::RGB_U8;
00938 
00939   return result;
00940 }
00941 
00942 // ######################################################################
00943 void InputFrameSeries::startStream()
00944 {
00945   if (!this->started())
00946     LFATAL("startStream() must not be called until after start()");
00947 
00948   // double check we have a valid source
00949   ASSERT(rep->source.is_valid());
00950 
00951   rep->source->startStream();
00952 }
00953 
00954 // ######################################################################
00955 GenericFrame InputFrameSeries::readFrame()
00956 {
00957   if (!this->started())
00958     LFATAL("readFrame() must not be called until after start()");
00959 
00960   return rep->readFrame(this);
00961 }
00962 
00963 // ######################################################################
00964 void InputFrameSeries::setFrameSource(const std::string& source)
00965 {
00966   nub::soft_ref<FrameIstream> in =
00967     makeFrameIstream(source);
00968 
00969   if (!in.is_valid())
00970     {
00971       LFATAL("unknown value for %s: '%s'\n\tvalid values are %s",
00972              itsFrameSource.getOptionDef()->longoptname,
00973              source.c_str(),
00974              itsFrameSource.getOptionDef()->validvals);
00975     }
00976 
00977   if (rep->source.is_valid())
00978     this->removeSubComponent(*rep->source);
00979   rep->source = in;
00980   rep->sourceDescription = source;
00981   this->addSubComponent(rep->source);
00982   rep->source->exportOptions(MC_RECURSE);
00983 }
00984 
00985 // ######################################################################
00986 int InputFrameSeries::frame() const
00987 {
00988   return rep->counter.currentFrame();
00989 }
00990 
00991 // ######################################################################
00992 nub::ref<FrameIstream> InputFrameSeries::getFrameSource() const
00993 {
00994   if (!rep->source.is_valid())
00995     LFATAL("Oops! I don't have any frame source");
00996 
00997   return rep->source;
00998 }
00999 
01000 // ######################################################################
01001 FrameRange InputFrameSeries::getFrameRange() const
01002 {
01003   return itsFrameRange.getVal();
01004 }
01005 
01006 // ######################################################################
01007 bool InputFrameSeries::setFrameNumber(int n)
01008 {
01009   return rep->setFrameNumber(n);
01010 }
01011 
01012 
01013 // ######################################################################
01014 // #################### OutputFrameSeries
01015 // ######################################################################
01016 
01017 struct OutputFrameSeries::Impl
01018 {
01019   Impl(OptionManager& mgr, const FrameRange& range)
01020     :
01021     vec(),
01022     explicitNone(false),
01023     counter(range),
01024     wasNonvoidAtStart(false)
01025   {}
01026 
01027   typedef std::vector<nub::ref<FrameOstream> > VecType;
01028 
01029   VecType vec;
01030 
01031   // by default, we will treat an empty destination list as an error
01032   // (to prevent somebody spending lots of CPU time only to find out
01033   // that their results haven't gone anywhere); but, if the user
01034   // explicitly specifies --out=none, then we'll allow an empty
01035   // destination list
01036   bool explicitNone;
01037 
01038   FrameCounter counter;
01039 
01040   bool wasNonvoidAtStart;
01041 };
01042 
01043 OutputFrameSeries::OutputFrameSeries(OptionManager& mgr,
01044                                      const std::string& descrName,
01045                                      const std::string& tag) :
01046   FrameOstream(mgr, "Output " + descrName, "Output"+tag),
01047   itsLogFile(&OPT_TextLogFile, this),
01048   itsTestMode(&OPT_TestMode, this),
01049   itsFrameRange(&OPT_OutputFrameRange, this),
01050   itsDims(&OPT_OutputFrameDims, this),
01051   itsPreserveAspect(&OPT_OutputPreserveAspect, this),
01052   itsZoom(&OPT_OutputZoom, this),
01053   itsZeroNumberFrames(&OPT_ZeroNumberFrames, this),
01054   itsFrameSink(&OPT_OutputFrameSink, this),
01055   itsInOut(&OPT_InputOutputComboSpec, this),
01056   itsWaitForUser(&OPT_WaitForUser, this),
01057   itsOutputReplicate(&OPT_OutputReplicate, this),
01058   itsNumWritten(0),
01059   rep(new Impl(mgr, itsFrameRange.getVal()))
01060 {
01061   init_manager = &mgr;
01062   pthread_once(&istream_init_once, &istream_init);
01063   pthread_once(&ostream_init_once, &ostream_init);
01064 }
01065 
01066 // ######################################################################
01067 OutputFrameSeries::~OutputFrameSeries()
01068 {
01069   delete rep;
01070 }
01071 
01072 // ######################################################################
01073 void OutputFrameSeries::reset1()
01074 {
01075   // reset some stuff for FrameSeries
01076   rep->counter.reset(itsFrameRange.getVal(), true);
01077   itsNumWritten = 0;
01078 
01079   rep->explicitNone = false;
01080   rep->vec.clear();
01081 
01082   // propagate to our base class:
01083   FrameOstream::reset1();
01084 }
01085 
01086 // ######################################################################
01087 void OutputFrameSeries::paramChanged(ModelParamBase* const param,
01088                                      const bool valueChanged,
01089                                      ParamClient::ChangeStatus* status)
01090 {
01091   FrameOstream::paramChanged(param, valueChanged, status);
01092 
01093   if (param == &itsFrameSink)
01094     {
01095       this->addFrameDest(itsFrameSink.getVal());
01096     }
01097   else if (param == &itsInOut)
01098     {
01099       this->addFrameDest(itsInOut.getVal());
01100     }
01101   else if (param == &itsFrameRange)
01102     {
01103       rep->counter.reset(itsFrameRange.getVal(), false);
01104     }
01105 }
01106 
01107 // ######################################################################
01108 FrameState OutputFrameSeries::update(const SimTime& stime,
01109                                      bool new_event)
01110 {
01111   // reset our itsNumWritten:
01112   itsNumWritten = 0;
01113 
01114   const FrameState result = rep->counter.update(stime, new_event);
01115 
01116   if (result != FRAME_SAME)
01117     {
01118       const int fnum = rep->counter.currentFrame();
01119 
01120       LDEBUG("%-20s frame %d at %.2fms",
01121             this->tagName().c_str(), fnum, stime.msecs());
01122 
01123       textLog(itsLogFile.getVal(),
01124               this->tagName().c_str(),
01125               sformat("frame %d", fnum), stime);
01126     }
01127 
01128   return result;
01129 }
01130 
01131 // ######################################################################
01132 FrameState OutputFrameSeries::updateNext()
01133 {
01134   return rep->counter.updateNext();
01135 }
01136 
01137 // ######################################################################
01138 bool OutputFrameSeries::shouldWait() const
01139 {
01140   return itsNumWritten > 0
01141     && itsWaitForUser.getVal() == true
01142     && !itsTestMode.getVal();
01143 }
01144 
01145 // ######################################################################
01146 void OutputFrameSeries::writeFrame(const GenericFrame& orig,
01147                                    const std::string& shortname,
01148                                    const FrameInfo& auxinfo)
01149 {
01150   int fnum;
01151   if(itsZeroNumberFrames.getVal())
01152     fnum = 0;
01153   else
01154     fnum = rep->counter.currentFrame();
01155 
01156   const GenericFrame frame =
01157     doResizeFrame(orig, Rectangle(), itsDims.getVal(),
01158                   itsZoom.getVal(), itsPreserveAspect.getVal());
01159 
01160   // double-check that we avoid a silently empty output vector
01161   ASSERT(rep->vec.size() > 0 || rep->explicitNone);
01162 
01163   for (size_t i = 0; i < rep->vec.size(); ++i)
01164     {
01165       for (size_t k = 0; k < itsOutputReplicate.getVal(); ++k)
01166         {
01167           rep->vec[i]->setFrameNumber(k + fnum * itsOutputReplicate.getVal());
01168           rep->vec[i]->writeFrame(frame, shortname, auxinfo);
01169         }
01170       ++itsNumWritten;
01171     }
01172 }
01173 
01174 // ######################################################################
01175 bool OutputFrameSeries::isVoid() const
01176 {
01177   // look for any non-void child streams:
01178   for (size_t i = 0; i < rep->vec.size(); ++i)
01179     if (!rep->vec[i]->isVoid())
01180       return false;
01181 
01182   // no child streams were non-void, so we are void:
01183   return true;
01184 }
01185 
01186 // ######################################################################
01187 bool OutputFrameSeries::becameVoid() const
01188 {
01189   return rep->wasNonvoidAtStart && this->isVoid();
01190 }
01191 
01192 // ######################################################################
01193 void OutputFrameSeries::closeStream(const std::string& shortname)
01194 {
01195   for (size_t i = 0; i < rep->vec.size(); ++i)
01196     rep->vec[i]->closeStream(shortname);
01197 }
01198 
01199 // ######################################################################
01200 void OutputFrameSeries::addFrameDest(const std::string& source)
01201 {
01202   if (source == "")
01203     return;
01204 
01205   OptionManager& mgr = getManager();
01206 
01207   if (source == "none")
01208     {
01209       // get rid of any output destinations we may have already
01210       // created:
01211       while (rep->vec.size() != 0)
01212         {
01213           nub::ref<FrameOstream> f = rep->vec.back();
01214           rep->vec.pop_back();
01215           this->removeSubComponent(*f);
01216         }
01217       rep->explicitNone = true;
01218     }
01219   else
01220     {
01221       nub::ref<FrameOstream> f = makeFrameOstream(source, mgr);
01222 
01223       rep->vec.push_back(f);
01224       this->addSubComponent(f);
01225       f->exportOptions(MC_RECURSE);
01226     }
01227 }
01228 
01229 // ######################################################################
01230 size_t OutputFrameSeries::getNumFrameDests() const
01231 {
01232   return rep->vec.size();
01233 }
01234 
01235 // ######################################################################
01236 nub::ref<FrameOstream> OutputFrameSeries::getFrameDest(size_t n) const
01237 {
01238   ASSERT(n < rep->vec.size());
01239 
01240   return rep->vec[n];
01241 }
01242 
01243 // ######################################################################
01244 void OutputFrameSeries::start2()
01245 {
01246   rep->counter.reset(itsFrameRange.getVal(), true);
01247 
01248   if (rep->vec.empty() && !rep->explicitNone)
01249     LFATAL("\n\tOops, you didn't specify an output destination with\n"
01250            "\tan --out option. If this is actually the behavior\n"
01251            "\tyou want, you can do an explicit --out=none to avoid\n"
01252            "\tthis error message. Otherwise, you can use an option\n"
01253            "\tlike --out=raster:path/to/filestem or --out=mpeg:\n"
01254            "\tor --out=display: to request particular output format.");
01255 
01256   rep->wasNonvoidAtStart = !this->isVoid();
01257 }
01258 
01259 // ######################################################################
01260 int OutputFrameSeries::frame() const
01261 {
01262   if(itsZeroNumberFrames.getVal())
01263     return 0;
01264   else
01265     return rep->counter.currentFrame();
01266 }
01267 
01268 
01269 // ######################################################################
01270 /* So things look consistent in everyone's emacs... */
01271 /* Local Variables: */
01272 /* indent-tabs-mode: nil */
01273 /* End: */
Generated on Sun May 8 08:41:01 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3