00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
00123 uri.scheme = "file";
00124 uri.url = str_uri;
00125 return uri;
00126 }
00127
00128
00129 size_t nurl = str_uri.find("//",ns+1);
00130 if(nurl != string::npos)
00131 {
00132
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
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
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
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
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 }