UcbMpegEncoder.C

Go to the documentation of this file.
00001 /*!@file Media/UcbMpegEncoder.C Thin c++ wrapper around mpeg_encode/ppmtompeg */
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/Media/UcbMpegEncoder.C $
00035 // $Id: UcbMpegEncoder.C 8903 2007-10-25 22:56:57Z rjpeters $
00036 //
00037 
00038 #ifndef MEDIA_UCBMPEGENCODER_C_DEFINED
00039 #define MEDIA_UCBMPEGENCODER_C_DEFINED
00040 
00041 #include "Media/UcbMpegEncoder.H"
00042 
00043 #include "Image/Image.H"
00044 #include "Image/Pixels.H"
00045 #include "Raster/GenericFrame.H"
00046 #include "Raster/PnmWriter.H"
00047 #include "Util/log.H"
00048 #include "Util/sformat.H"
00049 #include "Video/VideoFrame.H"
00050 #include "rutz/pipe.h"
00051 #include "rutz/trace.h"
00052 
00053 #include <fstream>
00054 
00055 UcbMpegParams UcbMpegParams::basic()
00056 {
00057 GVX_TRACE(__PRETTY_FUNCTION__);
00058   UcbMpegParams parms;
00059 
00060   parms.PATTERN = "IBBPBBPBBPBBPBB";
00061   parms.GOP_SIZE = 30;
00062   parms.SLICES_PER_FRAME = 1;
00063   parms.PIXEL = "HALF";
00064   parms.RANGE = 10;
00065   parms.PSEARCH_ALG = "LOGARITHMIC";
00066   parms.BSEARCH_ALG = "CROSS2";
00067   parms.IQSCALE = 8;
00068   parms.PQSCALE = 10;
00069   parms.BQSCALE = 25;
00070   parms.REFERENCE_FRAME = "ORIGINAL";
00071 
00072   return parms;
00073 }
00074 
00075 UcbMpegParams UcbMpegParams::hq()
00076 {
00077 GVX_TRACE(__PRETTY_FUNCTION__);
00078   UcbMpegParams parms;
00079 
00080   parms.PATTERN = "IBBPBBPBBPBBPBB";
00081   parms.GOP_SIZE = 30;
00082   parms.SLICES_PER_FRAME = 1;
00083   parms.PIXEL = "HALF";
00084   parms.RANGE = 10;
00085   parms.PSEARCH_ALG = "LOGARITHMIC";
00086   parms.BSEARCH_ALG = "CROSS2";
00087   parms.IQSCALE = 1;
00088   parms.PQSCALE = 1;
00089   parms.BQSCALE = 1;
00090   parms.REFERENCE_FRAME = "DECODED";
00091 
00092   return parms;
00093 }
00094 
00095 UcbMpegParams UcbMpegParams::superhq()
00096 {
00097 GVX_TRACE(__PRETTY_FUNCTION__);
00098   UcbMpegParams parms;
00099 
00100   parms.PATTERN = "I";
00101   parms.GOP_SIZE = 1;
00102   parms.SLICES_PER_FRAME = 1;
00103   parms.PIXEL = "HALF";
00104   parms.RANGE = 10;
00105   parms.PSEARCH_ALG = "LOGARITHMIC";
00106   parms.BSEARCH_ALG = "CROSS2";
00107   parms.IQSCALE = 1;
00108   parms.PQSCALE = 1;
00109   parms.BQSCALE = 1;
00110   parms.REFERENCE_FRAME = "DECODED";
00111 
00112   return parms;
00113 }
00114 
00115 UcbMpegEncoder::UcbMpegEncoder(const std::string& exename,
00116                                const std::string& outname,
00117                                const UcbMpegParams& params,
00118                                const double framerate) :
00119   itsExeName(exename),
00120   itsOutFname(outname),
00121   itsParams(params),
00122   itsParamFname(),
00123   itsFrameRate(framerate),
00124   itsVideoFormat(VIDFMT_AUTO),
00125   itsSubprocess(0),
00126   itsDims()
00127 {
00128 GVX_TRACE(__PRETTY_FUNCTION__);
00129 }
00130 
00131 UcbMpegEncoder::~UcbMpegEncoder()
00132 {
00133 GVX_TRACE(__PRETTY_FUNCTION__);
00134   this->close();
00135 
00136   delete itsSubprocess;
00137 }
00138 
00139 int UcbMpegEncoder::close()
00140 {
00141 GVX_TRACE(__PRETTY_FUNCTION__);
00142   int result = 0;
00143 
00144   if (itsSubprocess != 0)
00145     {
00146       itsSubprocess->close_out();
00147 
00148       result = itsSubprocess->exit_status();
00149 
00150       LINFO("%s exited with status %d", itsExeName.c_str(), result);
00151 
00152       delete itsSubprocess;
00153       itsSubprocess = 0;
00154     }
00155 
00156   if (itsParamFname.length() > 0)
00157     {
00158       remove(itsParamFname.c_str());
00159       itsParamFname = std::string();
00160     }
00161 
00162   return result;
00163 }
00164 
00165 void UcbMpegEncoder::makeParmsFile(const VideoFrame& f)
00166 {
00167 GVX_TRACE(__PRETTY_FUNCTION__);
00168   static int counter = 0;
00169 
00170   if (f.getDims().w() % 16 != 0)
00171     LFATAL("%s requires the image width to be a multiple of 16, "
00172            "but the actual image width was %d",
00173            itsExeName.c_str(), f.getDims().w());
00174 
00175   if (f.getDims().h() % 16 != 0)
00176     LFATAL("%s requires the image height to be a multiple of 16, "
00177            "but the actual image height was %d",
00178            itsExeName.c_str(), f.getDims().h());
00179 
00180   itsDims = f.getDims();
00181 
00182   itsParamFname = sformat("/tmp/mpegencode-params-%d-%d.txt",
00183                          int(getpid()), counter++);
00184 
00185   FILE* pf = fopen(itsParamFname.c_str(), "w");
00186 
00187   if (pf == 0)
00188     LFATAL("couldn't open %s for writing", itsParamFname.c_str());
00189 
00190   fprintf(pf, "PATTERN                 %s\n", itsParams.PATTERN);
00191   fprintf(pf, "GOP_SIZE                %d\n", itsParams.GOP_SIZE);
00192   fprintf(pf, "SLICES_PER_FRAME        %d\n", itsParams.SLICES_PER_FRAME);
00193   fprintf(pf, "PIXEL                   %s\n", itsParams.PIXEL);
00194   fprintf(pf, "RANGE                   %d\n", itsParams.RANGE);
00195   fprintf(pf, "PSEARCH_ALG             %s\n", itsParams.PSEARCH_ALG);
00196   fprintf(pf, "BSEARCH_ALG             %s\n", itsParams.BSEARCH_ALG);
00197   fprintf(pf, "IQSCALE                 %d\n", itsParams.IQSCALE);
00198   fprintf(pf, "PQSCALE                 %d\n", itsParams.PQSCALE);
00199   fprintf(pf, "BQSCALE                 %d\n", itsParams.BQSCALE);
00200   fprintf(pf, "REFERENCE_FRAME         %s\n", itsParams.REFERENCE_FRAME);
00201 
00202   fprintf(pf, "FORCE_ENCODE_LAST_FRAME 1\n");
00203   fprintf(pf, "FRAME_RATE              %.2f\n", itsFrameRate);
00204   fprintf(pf, "OUTPUT                  %s\n", itsOutFname.c_str());
00205   fprintf(pf, "SIZE                    %dx%d\n", f.getDims().w(), f.getDims().h());
00206 
00207   switch (f.getMode())
00208     {
00209     case VIDFMT_UYVY:
00210     case VIDFMT_YUV422:
00211       fprintf(pf, "BASE_FILE_FORMAT        YUV\n");
00212       fprintf(pf, "YUV_FORMAT              ABEKAS\n");
00213       itsVideoFormat = f.getMode();
00214       LINFO("writing frames in YUV/ABEKAS format");
00215       break;
00216 
00217       // NOTE: "YUV_FORMAT PHILLIPS" would be YVYU, but we don't have
00218       // a VIDFMT code for that layout
00219 
00220     case VIDFMT_YUV420P:
00221       fprintf(pf, "BASE_FILE_FORMAT        YUV\n");
00222       fprintf(pf, "YUV_FORMAT              UCB\n");
00223       itsVideoFormat = f.getMode();
00224       LINFO("writing frames in YUV/UCB format");
00225       break;
00226 
00227     default:
00228       fprintf(pf, "BASE_FILE_FORMAT        PPM\n");
00229       itsVideoFormat = VIDFMT_AUTO; // just convert through toRgb()
00230       LINFO("writing frames in PPM format");
00231       break;
00232     }
00233 
00234   fprintf(pf, "INPUT_DIR               stdin\n");
00235   fprintf(pf, "INPUT_CONVERT           *\n");
00236   fprintf(pf, "INPUT\n");
00237   fprintf(pf, "END_INPUT\n");
00238 
00239   fclose(pf);
00240 
00241   // now echo the params file back to the user for debugging:
00242   {
00243     std::ifstream ifs(itsParamFname.c_str());
00244     int lineno = 0;
00245     std::string line;
00246     while (std::getline(ifs, line))
00247       {
00248         LDEBUG("params:%02d: %s", ++lineno, line.c_str());
00249       }
00250   }
00251 }
00252 
00253 void UcbMpegEncoder::writeVideoFrame(const VideoFrame& f)
00254 {
00255 GVX_TRACE(__PRETTY_FUNCTION__);
00256 
00257   if (itsSubprocess == 0)
00258     {
00259       this->makeParmsFile(f);
00260       itsSubprocess = new rutz::bidir_pipe;
00261 
00262       itsSubprocess->block_child_sigint();
00263 
00264       itsSubprocess->init(itsExeName.c_str(),
00265                           "-realquiet",
00266                           itsParamFname.c_str(),
00267                           0);
00268 
00269       LDEBUG("initialized subprocess '%s -realquiet %s'",
00270              itsExeName.c_str(), itsParamFname.c_str());
00271     }
00272 
00273   if (f.getDims() != itsDims)
00274     LFATAL("invalid image dimensions (got %dx%d, expected %dx%d)",
00275            f.getDims().w(), f.getDims().h(), itsDims.w(), itsDims.h());
00276 
00277   switch (itsVideoFormat)
00278     {
00279     case VIDFMT_UYVY:
00280     case VIDFMT_YUV422:
00281     case VIDFMT_YUV420P:
00282       if (f.getMode() != itsVideoFormat)
00283         LFATAL("input frame in wrong format (expected %s, got %s)",
00284                convertToString(itsVideoFormat).c_str(),
00285                convertToString(f.getMode()).c_str());
00286 
00287       itsSubprocess->out_stream()
00288         .write(reinterpret_cast<const char*>(f.getBuffer()),
00289                f.getBufSize());
00290 
00291       break;
00292 
00293     default:
00294       {
00295         const Image<PixRGB<byte> > rgb = f.toRgb();
00296         PnmWriter::writeRGB(rgb, itsSubprocess->out_stream());
00297       }
00298     }
00299 
00300   if (itsSubprocess->out_stream().fail())
00301     LFATAL("pipe stream error while sending frame");
00302 }
00303 
00304 void UcbMpegEncoder::writeFrame(const GenericFrame& f)
00305 {
00306   this->writeVideoFrame(f.asVideo());
00307 }
00308 
00309 // ######################################################################
00310 /* So things look consistent in everyone's emacs... */
00311 /* Local Variables: */
00312 /* mode: c++ */
00313 /* indent-tabs-mode: nil */
00314 /* End: */
00315 
00316 #endif // MEDIA_UCBMPEGENCODER_C_DEFINED
Generated on Sun May 8 08:41:01 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3