video.cpp
Go to the documentation of this file.
00001 /* This file is part of the Pangolin Project.
00002  * http://github.com/stevenlovegrove/Pangolin
00003  *
00004  * Copyright (c) 2011 Steven Lovegrove
00005  *
00006  * Permission is hereby granted, free of charge, to any person
00007  * obtaining a copy of this software and associated documentation
00008  * files (the "Software"), to deal in the Software without
00009  * restriction, including without limitation the rights to use,
00010  * copy, modify, merge, publish, distribute, sublicense, and/or sell
00011  * copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following
00013  * conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be
00016  * included in all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00019  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00020  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00021  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00022  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00023  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00024  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00025  * OTHER DEALINGS IN THE SOFTWARE.
00026  */
00027 
00028 #include "video.h"
00029 
00030 #ifdef HAVE_DC1394
00031 #include "video/firewire.h"
00032 #endif
00033 
00034 #ifdef HAVE_V4L
00035 #include "video/v4l.h"
00036 #endif
00037 
00038 #ifdef HAVE_FFMPEG
00039 #include "video/ffmpeg.h"
00040 #endif
00041 
00042 #ifdef HAVE_OPENNI
00043 #include "video/openni.h"
00044 #endif
00045 
00046 #include "video/pvn_video.h"
00047 
00048 #include <boost/algorithm/string.hpp>
00049 #include <boost/algorithm/string/trim.hpp>
00050 #include <boost/algorithm/string/case_conv.hpp>
00051 #include <boost/algorithm/string/predicate.hpp>
00052 #include <boost/foreach.hpp>
00053 #define foreach BOOST_FOREACH
00054 
00055 using namespace std;
00056 using namespace boost;
00057 
00058 namespace pangolin
00059 {
00060 
00061 const VideoPixelFormat SupportedVideoPixelFormats[] =
00062 {
00063     {"GRAY8", 1, {8}, 8, false},
00064     {"GRAY16LE", 1, {16}, 16, false},
00065     {"RGB24", 3, {8,8,8}, 24, false},
00066     {"BGR24", 3, {8,8,8}, 24, false},
00067     {"YUYV422", 3, {4,2,2}, 16, false},
00068     {"",0,{0,0,0,0},0,0}
00069 };
00070 
00071 VideoPixelFormat VideoFormatFromString(const std::string& format)
00072 {
00073     for(int i=0; !SupportedVideoPixelFormats[i].format.empty(); ++i)
00074         if(!format.compare(SupportedVideoPixelFormats[i].format))
00075             return SupportedVideoPixelFormats[i];
00076     throw VideoException("Unknown Format",format);
00077 }
00078 
00079 ostream& operator<< (ostream &out, Uri &uri)
00080 {
00081     out << "scheme: " << uri.scheme << endl;
00082     out << "url:    " << uri.url << endl;
00083     out << "params:" << endl;
00084     typedef pair<string,string> Param;
00085     foreach( Param p, uri.params)
00086     {
00087         cout << "\t" << p.first << " = " << p.second << endl;
00088     }
00089 
00090     return out;
00091 }
00092 
00093 
00094 VideoInput::VideoInput()
00095     : uri(""), video(0)
00096 {
00097 }
00098 
00099 VideoInput::VideoInput(std::string uri)
00100     : video(0)
00101 {
00102     Open(uri);
00103 }
00104 
00105 VideoInput::~VideoInput()
00106 {
00107     if(video) delete video;
00108 }
00109 
00110 Uri ParseUri(string str_uri)
00111 {
00112     Uri uri;
00113 
00114     // Find Scheme delimiter
00115     size_t ns = str_uri.find_first_of(':');
00116     if( ns != string::npos )
00117     {
00118         uri.scheme = str_uri.substr(0,ns);
00119     }
00120     else
00121     {
00122 //        throw VideoException("Bad video URI","no device scheme specified");
00123         uri.scheme = "file";
00124         uri.url = str_uri;
00125         return uri;
00126     }
00127 
00128     // Find url delimiter
00129     size_t nurl = str_uri.find("//",ns+1);
00130     if(nurl != string::npos)
00131     {
00132         // If there is space between the delimiters, extract protocol arguments
00133         if( nurl-ns > 1)
00134         {
00135             if( str_uri[ns+1] == '[' && str_uri[nurl-1] == ']' )
00136             {
00137                 string queries = str_uri.substr(ns+2, nurl-1 - (ns+2) );
00138                 vector<string> params;
00139                 split(params, queries, boost::is_any_of(","));
00140                 foreach(string p, params)
00141                 {
00142                     vector<string> args;
00143                     split(args, p, boost::is_any_of("=") );
00144                     if( args.size() == 2 )
00145                     {
00146                         boost::trim(args[0]);
00147                         boost::trim(args[1]);
00148                         uri.params[args[0]] = args[1];
00149                     }
00150                 }
00151             }
00152             else
00153             {
00154                 throw VideoException("Bad video URI");
00155             }
00156         }
00157 
00158         uri.url = str_uri.substr(nurl+2);
00159 
00160 //        // Find parameter delimiter
00161 //        size_t nq = str_uri.find_first_of('?',nurl+2);
00162 //        if(nq == string::npos)
00163 //        {
00164 //            uri.url = str_uri.substr(nurl+2);
00165 //        }else{
00166 //            string queries = str_uri.substr(nq+1);
00167 //            uri.url = str_uri.substr(nurl+2,nq-(nurl+2));
00168 //            vector<string> params;
00169 //            split(params, queries, boost::is_any_of("&"));
00170 //            foreach(string p, params)
00171 //            {
00172 //                vector<string> args;
00173 //                split(args, p, boost::is_any_of("=") );
00174 //                if( args.size() == 2 )
00175 //                {
00176 //                    uri.params[args[0]] = args[1];
00177 //                }
00178 //            }
00179 //        }
00180     }
00181 
00182     return uri;
00183 }
00184 
00185 #ifdef HAVE_DC1394
00186 
00187 dc1394video_mode_t get_firewire_format7_mode(const string fmt)
00188 {
00189     const string FMT7_prefix = "FORMAT7_";
00190 
00191     if( algorithm::starts_with(fmt, FMT7_prefix) )
00192     {
00193         int fmt7_mode = 0;
00194         std::istringstream iss( fmt.substr(FMT7_prefix.size()) );
00195         iss >> fmt7_mode;
00196         if( !iss.fail() )
00197         {
00198             return (dc1394video_mode_t)(DC1394_VIDEO_MODE_FORMAT7_0 + fmt7_mode);
00199         }
00200     }
00201 
00202     throw VideoException("Unknown video mode");
00203 }
00204 
00205 dc1394video_mode_t get_firewire_mode(unsigned width, unsigned height, const string fmt)
00206 {
00207     for( dc1394video_mode_t video_mode=DC1394_VIDEO_MODE_MIN; video_mode<DC1394_VIDEO_MODE_MAX; video_mode = (dc1394video_mode_t)(video_mode +1) )
00208     {
00209         unsigned w,h;
00210         string format;
00211         Dc1394ModeDetails(video_mode,w,h,format);
00212 
00213         if( w == width && h==height && !fmt.compare(format) )
00214             return video_mode;
00215     }
00216 
00217     throw VideoException("Unknown video mode");
00218 }
00219 
00220 dc1394framerate_t get_firewire_framerate(float framerate)
00221 {
00222     if(framerate==1.875)     return DC1394_FRAMERATE_1_875;
00223     else if(framerate==3.75) return DC1394_FRAMERATE_3_75;
00224     else if(framerate==7.5)  return DC1394_FRAMERATE_7_5;
00225     else if(framerate==15)   return DC1394_FRAMERATE_15;
00226     else if(framerate==30)   return DC1394_FRAMERATE_30;
00227     else if(framerate==60)   return DC1394_FRAMERATE_60;
00228     else if(framerate==120)  return DC1394_FRAMERATE_120;
00229     else if(framerate==240)  return DC1394_FRAMERATE_240;
00230     else throw VideoException("Invalid framerate");
00231 }
00232 
00233 #endif
00234 
00235 VideoInterface* OpenVideo(std::string str_uri)
00236 {
00237     VideoInterface* video = 0;
00238 
00239     Uri uri = ParseUri(str_uri);
00240 
00241     if(!uri.scheme.compare("file") && algorithm::ends_with(uri.url,"pvn") )
00242     {
00243         bool realtime = true;
00244         if(uri.params.find("realtime")!=uri.params.end())
00245         {
00246             std::istringstream iss(uri.params["realtime"]);
00247             iss >> realtime;
00248         }
00249         video = new PvnVideo(uri.url.c_str(), realtime);
00250     }
00251     else
00252 #ifdef HAVE_FFMPEG
00253         if(!uri.scheme.compare("ffmpeg") || !uri.scheme.compare("file") || !uri.scheme.compare("files") )
00254         {
00255             string outfmt = "RGB24";
00256             if(uri.params.find("fmt")!=uri.params.end())
00257             {
00258                 outfmt = uri.params["fmt"];
00259             }
00260             int video_stream = -1;
00261             if(uri.params.find("stream")!=uri.params.end())
00262             {
00263                 std::istringstream iss(uri.params["stream"]);
00264                 iss >> video_stream;
00265             }
00266             video = new FfmpegVideo(uri.url.c_str(), outfmt, "", false, video_stream);
00267         }
00268         else if( !uri.scheme.compare("mjpeg"))
00269         {
00270             video = new FfmpegVideo(uri.url.c_str(),"RGB24", "MJPEG" );
00271         }
00272         else if( !uri.scheme.compare("convert") )
00273         {
00274             string outfmt = "RGB24";
00275             if(uri.params.find("fmt")!=uri.params.end())
00276             {
00277                 outfmt = uri.params["fmt"];
00278             }
00279             VideoInterface* subvid = OpenVideo(uri.url);
00280             video = new FfmpegConverter(subvid,outfmt,FFMPEG_POINT);
00281         }
00282         else
00283 #endif //HAVE_FFMPEG
00284 #ifdef HAVE_V4L
00285             if(!uri.scheme.compare("v4l"))
00286             {
00287                 video = new V4lVideo(uri.url.c_str());
00288             }
00289             else
00290 #endif // HAVE_V4L
00291 #ifdef HAVE_DC1394
00292                 if(!uri.scheme.compare("firewire") || !uri.scheme.compare("dc1394") )
00293                 {
00294                     // Default parameters
00295                     int desired_x = 0;
00296                     int desired_y = 0;
00297                     int desired_width = 640;
00298                     int desired_height = 480;
00299                     int desired_dma = 10;
00300                     int desired_iso = 400;
00301                     float desired_fps = 30;
00302                     string desired_format = "RGB24";
00303 
00304                     // Parse parameters
00305                     if(uri.params.find("fmt")!=uri.params.end())
00306                     {
00307                         desired_format = uri.params["fmt"];
00308                         boost::to_upper(desired_format);
00309                     }
00310                     if(uri.params.find("size")!=uri.params.end())
00311                     {
00312                         std::istringstream iss(uri.params["size"]);
00313                         iss >> desired_width;
00314                         iss.get();
00315                         iss >> desired_height;
00316                     }
00317                     if(uri.params.find("pos")!=uri.params.end())
00318                     {
00319                         std::istringstream iss(uri.params["pos"]);
00320                         iss >> desired_x;
00321                         iss.get();
00322                         iss >> desired_y;
00323                     }
00324                     if(uri.params.find("dma")!=uri.params.end())
00325                     {
00326                         std::istringstream iss(uri.params["dma"]);
00327                         iss >> desired_dma;
00328                     }
00329                     if(uri.params.find("iso")!=uri.params.end())
00330                     {
00331                         std::istringstream iss(uri.params["iso"]);
00332                         iss >> desired_iso;
00333                     }
00334                     if(uri.params.find("fps")!=uri.params.end())
00335                     {
00336                         std::istringstream iss(uri.params["fps"]);
00337                         iss >> desired_fps;
00338                     }
00339 
00340                     Guid guid = 0;
00341                     unsigned deviceid = 0;
00342                     dc1394framerate_t framerate = get_firewire_framerate(desired_fps);
00343                     dc1394speed_t iso_speed = (dc1394speed_t)(log(desired_iso/100) / log(2));
00344                     int dma_buffers = desired_dma;
00345 
00346                     if( algorithm::starts_with(desired_format, "FORMAT7") )
00347                     {
00348                         dc1394video_mode_t video_mode = get_firewire_format7_mode(desired_format);
00349                         if( guid.guid == 0 )
00350                         {
00351                             video = new FirewireVideo(deviceid,video_mode,FirewireVideo::MAX_FR,desired_width, desired_height, desired_x, desired_y, iso_speed, dma_buffers,true);
00352                         }
00353                         else
00354                         {
00355                             video = new FirewireVideo(guid,video_mode,FirewireVideo::MAX_FR,desired_width, desired_height, desired_x, desired_y, iso_speed, dma_buffers,true);
00356                         }
00357                     }
00358                     else
00359                     {
00360                         dc1394video_mode_t video_mode = get_firewire_mode(desired_width,desired_height,desired_format);
00361                         if( guid.guid == 0 )
00362                         {
00363                             video = new FirewireVideo(deviceid,video_mode,framerate,iso_speed,dma_buffers);
00364                         }
00365                         else
00366                         {
00367                             video = new FirewireVideo(guid,video_mode,framerate,iso_speed,dma_buffers);
00368                         }
00369                     }
00370                 }
00371                 else
00372 #endif //HAVE_DC1394
00373 #ifdef HAVE_OPENNI
00374                     if(!uri.scheme.compare("openni") || !uri.scheme.compare("kinect"))
00375                     {
00376                         OpenNiSensorType img1 = OpenNiRgb;
00377                         OpenNiSensorType img2 = OpenNiUnassigned;
00378 
00379                         if(uri.params.find("img1")!=uri.params.end())
00380                         {
00381                             std::istringstream iss(uri.params["img1"]);
00382 
00383                             if( boost::iequals(iss.str(),"rgb") )
00384                             {
00385                                 img1 = OpenNiRgb;
00386                             }
00387                             else if( boost::iequals(iss.str(),"ir") )
00388                             {
00389                                 img1 = OpenNiIr;
00390                             }
00391                             else if( boost::iequals(iss.str(),"depth") )
00392                             {
00393                                 img1 = OpenNiDepth;
00394                             }
00395                         }
00396 
00397                         if(uri.params.find("img2")!=uri.params.end())
00398                         {
00399                             std::istringstream iss(uri.params["img2"]);
00400 
00401                             if( boost::iequals(iss.str(),"rgb") )
00402                             {
00403                                 img2 = OpenNiRgb;
00404                             }
00405                             else if( boost::iequals(iss.str(),"ir") )
00406                             {
00407                                 img2 = OpenNiIr;
00408                             }
00409                             else if( boost::iequals(iss.str(),"depth") )
00410                             {
00411                                 img2 = OpenNiDepth;
00412                             }
00413                         }
00414 
00415                         video = new OpenNiVideo(img1,img2);
00416                     }
00417                     else
00418 #endif
00419                     {
00420                         throw VideoException("Unable to open video URI");
00421                     }
00422 
00423     return video;
00424 }
00425 
00426 void VideoInput::Open(std::string uri)
00427 {
00428     this->uri = uri;
00429 
00430     if(video)
00431     {
00432         delete video;
00433         video = 0;
00434     }
00435     video = OpenVideo(uri);
00436 }
00437 
00438 void VideoInput::Reset()
00439 {
00440     Open(uri);
00441 }
00442 
00443 unsigned VideoInput::Width() const
00444 {
00445     if( !video ) throw VideoException("No video source open");
00446     return video->Width();
00447 }
00448 
00449 unsigned VideoInput::Height() const
00450 {
00451     if( !video ) throw VideoException("No video source open");
00452     return video->Height();
00453 }
00454 
00455 size_t VideoInput::SizeBytes() const
00456 {
00457     if( !video ) throw VideoException("No video source open");
00458     return video->SizeBytes();
00459 }
00460 
00461 std::string VideoInput::PixFormat() const
00462 {
00463     if( !video ) throw VideoException("No video source open");
00464     return video->PixFormat();
00465 }
00466 
00467 void VideoInput::Start()
00468 {
00469     if( !video ) throw VideoException("No video source open");
00470     video->Start();
00471 }
00472 
00473 void VideoInput::Stop()
00474 {
00475     if( !video ) throw VideoException("No video source open");
00476     video->Stop();
00477 }
00478 
00479 bool VideoInput::GrabNext( unsigned char* image, bool wait )
00480 {
00481     if( !video ) throw VideoException("No video source open");
00482     return video->GrabNext(image,wait);
00483 }
00484 
00485 bool VideoInput::GrabNewest( unsigned char* image, bool wait )
00486 {
00487     if( !video ) throw VideoException("No video source open");
00488     return video->GrabNext(image,wait);
00489 }
00490 
00491 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


pangolin_wrapper
Author(s): Todor Stoyanov
autogenerated on Wed Feb 13 2013 14:03:25