00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025
00026 #include <QUrl>
00027 #include <QFile>
00028 #include <QDir>
00029 #include <QThread>
00030 #include <QTime>
00031
00032 #ifdef QVIPP
00033 #include <qvipp.h>
00034 #endif // QVIPP
00035
00036 #include <QVImage>
00037 #include <QVVideoReader>
00038
00039 #ifdef QVMPLAYER
00040 #include <QVMPlayerReader>
00041 #endif // QVMPLAYER
00042
00043 #ifdef QVOPENCV
00044 #include <QVOpenCVReader>
00045 #endif // QVOPENCV
00046
00047 #include <QVYUV4MPEG2Reader>
00048 #include <QVDirReader>
00049
00050
00051 class SleeperThread : public QThread
00052 {
00053 public:
00054 static void msleep(unsigned long msecs)
00055 {
00056 QThread::msleep(msecs);
00057 }
00058 };
00059
00060 void simulateDelay(int fps)
00061 {
00062 static QTime last_time;
00063
00064 int msecs_to_wait = (int)(1000/(double)fps) - last_time.elapsed();
00065
00066
00067
00068
00069
00070 if((msecs_to_wait > 0) and (msecs_to_wait < (int)(1000/(double)fps)))
00071 SleeperThread::msleep(msecs_to_wait);
00072
00073 last_time.start();
00074 }
00075
00076 QVVideoReader::QVVideoReader():
00077 url(QString()), scheme(QString()),changing_size(false),cols(0), rows(0), fps(0), frames_grabbed(0),
00078 camera_opened(FALSE), live_camera(FALSE), end_of_video(FALSE),
00079 availableGray(false), availableRGB3(false), availableYUV(false), availableRGB(false),
00080 imgGray(QVImage<uChar>()), imgRGB(QVImage<uChar,3>()),
00081 imgY(QVImage<uChar>()), imgU(QVImage<uChar>()), imgV(QVImage<uChar>()),
00082 imgR(QVImage<uChar>()), imgG(QVImage<uChar>()), imgB(QVImage<uChar>()),
00083 open_options(QVVideoReader::Default), source_mode(QVVideoReader::YUVMode), base_reader(0)
00084 {
00085 };
00086
00087 QVVideoReader::~QVVideoReader()
00088 {
00089 if (camera_opened)
00090 close();
00091
00092 if (base_reader != 0)
00093 delete base_reader;
00094 }
00095
00096
00097 bool QVVideoReader::open(const QString & url_string, unsigned int & suggested_cols,
00098 unsigned int & suggested_rows , unsigned int & suggested_fps,
00099 QVVideoReader::OpenOptions & suggested_opts,
00100 QVVideoReader::TSourceMode & suggested_source_mode)
00101 {
00102 if (base_reader != 0)
00103 delete base_reader;
00104
00105
00106
00107
00108 QUrl URL(url_string);
00109 bool modify_url = true;
00110 QString mod_url_string;
00111 scheme = URL.scheme();
00112 if (scheme != "") {
00113
00114 modify_url = false;
00115 } else if (url_string.startsWith("/dev/video")) {
00116
00117 scheme = "v4l2";
00118 } else if (url_string.startsWith("/dev/dv")) {
00119
00120 scheme = "dv";
00121 } else if (url_string.contains("*")) {
00122
00123 scheme = "dir";
00124 } else if (url_string.startsWith("www.")) {
00125
00126 scheme = "http";
00127 } else if (url_string.startsWith("ftp.")) {
00128
00129 scheme = "ftp";
00130 } else if (url_string.startsWith("#")) {
00131
00132 scheme = "cvc";
00133 } else if (QDir(url_string).exists()) {
00134
00135 scheme = "dir";
00136 } else if (QFile::exists(url_string)) {
00137
00138 if (url_string.endsWith(".yuv")) {
00139
00140 scheme = "yuv4mpeg";
00141 } else if (url_string.endsWith(".jpg") or url_string.endsWith(".png") or url_string.endsWith(".bmp") or
00142 url_string.endsWith(".pgm") or url_string.endsWith(".gif") or url_string.endsWith(".jpeg") or
00143 url_string.endsWith(".pbm") or url_string.endsWith(".ppm") or url_string.endsWith(".tiff") or
00144 url_string.endsWith(".xbm") or url_string.endsWith(".xpm") ) {
00145
00146 scheme = "dir";
00147 } else {
00148
00149 scheme = "file";
00150 }
00151 } else {
00152 std::cout << "QVVideoReader::open(): Error: do not know how to open URL " << qPrintable (url_string) << std::endl;
00153 goto end_with_fail;
00154 }
00155
00156 if(modify_url)
00157 mod_url_string = scheme + QString("://") + url_string;
00158 else
00159 mod_url_string = url_string;
00160
00161
00162
00163
00164 if (scheme == "dir")
00165 {
00166 base_reader = new QVDirReader();
00167 live_camera = false;
00168 }
00169 else if (scheme == "yuv4mpeg")
00170 {
00171 base_reader = new QVYUV4MPEG2Reader();
00172 live_camera = false;
00173 }
00174 #ifdef QVMPLAYER
00175 else if(scheme == "file")
00176 {
00177 base_reader = new QVMPlayerReader();
00178 live_camera = false;
00179 }
00180 else if (scheme == "v4l2")
00181 {
00182 base_reader = new QVMPlayerReader();
00183 live_camera = true;
00184 }
00185 else if (scheme == "dvb")
00186 {
00187 base_reader = new QVMPlayerReader();
00188 live_camera = true;
00189 }
00190 else if (scheme == "rtsp")
00191 {
00192 base_reader = new QVMPlayerReader();
00193 live_camera = false;
00194 }
00195 else if (scheme == "http")
00196 {
00197 base_reader = new QVMPlayerReader();
00198 live_camera = false;
00199 }
00200 else if (scheme == "ftp")
00201 {
00202 base_reader = new QVMPlayerReader();
00203 live_camera = false;
00204 }
00205 else if (scheme == "dvd")
00206 {
00207 base_reader = new QVMPlayerReader();
00208 live_camera = false;
00209 }
00210 else if (scheme == "vcd")
00211 {
00212 base_reader = new QVMPlayerReader();
00213 live_camera = false;
00214 }
00215 else if (scheme == "mf")
00216 {
00217 base_reader = new QVMPlayerReader();
00218 live_camera = false;
00219 }
00220 #else
00221 else if ( (scheme == "file") or
00222 (scheme == "v4l2") or
00223 (scheme == "dvb") or
00224 (scheme == "rtsp") or
00225 (scheme == "http") or
00226 (scheme == "ftp") or
00227 (scheme == "dvd") or
00228 (scheme == "vcd") or
00229 (scheme == "mf") )
00230 {
00231 std::cout << "QVVideoReader::open(): Error: tried to open video with MPlayer, while QVision was not configured to use it. See file 'config.pri'." << std::endl;
00232 goto end_with_fail;
00233 }
00234 #endif // QVMPLAYER
00235 #ifdef QVOPENCV
00236 else if (scheme == "cvf")
00237 {
00238 base_reader = new QVOpenCVReader();
00239 live_camera = false;
00240 }
00241 else if (scheme == "cvc")
00242 {
00243 base_reader = new QVOpenCVReader();
00244 live_camera = true;
00245 }
00246 #else
00247 else if ( (scheme == "cvf") or (scheme == "cvc") )
00248 {
00249 std::cout << "QVVideoReader::open(): Error: tried to open video with OpenCV functionality, while QVision was not configured to use it. See file 'config.pri'." << std::endl;
00250 goto end_with_fail;
00251 }
00252 #endif // QVOPENCV
00253
00254 cols = suggested_cols;
00255 rows = suggested_rows;
00256
00257 if(base_reader != 0)
00258 {
00259 if(base_reader->open(mod_url_string,suggested_cols,suggested_rows,suggested_fps,
00260 suggested_opts,suggested_source_mode))
00261 {
00262 url = mod_url_string;
00263
00264
00265
00266 if ((cols == 0) or (rows == 0)) {
00267 cols = suggested_cols;
00268 rows = suggested_rows;
00269 }
00270
00271 cols = cols & 0xfffffffe;
00272 rows = rows & 0xfffffffe;
00273 changing_size = (cols == 0 or rows == 0);
00274
00275
00276
00277
00278 fps = suggested_fps;
00279 frames_grabbed = 0;
00280 camera_opened = true;
00281
00282 end_of_video = false;
00283 availableGray = availableRGB3 = availableYUV = availableRGB = false;
00284 open_options = suggested_opts;
00285 source_mode = suggested_source_mode;
00286
00287 emit sourceOpened();
00288 return true;
00289 }
00290 }
00291 else
00292 {
00293 std::cout << "Error:: do not know how to open " << qPrintable (mod_url_string) << " in QVVideoReader::open() method\n";
00294 }
00295
00296 end_with_fail:
00297 url = QString();
00298 scheme = QString();
00299 changing_size = false;
00300 cols = 0;
00301 rows = 0;
00302 fps = 0;
00303 frames_grabbed = 0;
00304 camera_opened = false;
00305 live_camera = false;
00306 end_of_video = true;
00307 availableGray = availableRGB3 = availableYUV = availableRGB = false;
00308 open_options = QVVideoReader::Default;
00309 source_mode = suggested_source_mode;
00310 delete base_reader;
00311 base_reader = 0;
00312 return false;
00313 }
00314
00315 bool QVVideoReader::grab()
00316 {
00317 availableGray = availableRGB3 = availableYUV = availableRGB = false;
00318
00319 if(source_mode == QVVideoReader::GrayOnlyMode)
00320 {
00321 QVImage<uChar> imgDummy1,imgDummy2;
00322 if(base_reader->grab(imgGray, imgDummy1, imgDummy2))
00323 {
00324 availableGray = true;
00325 frames_grabbed++;
00326 emit newGrab();
00327 if(fps != 0) simulateDelay(fps);
00328
00329
00330
00331 if((imgGray.getCols()%2==1) or (imgGray.getRows()%2==1)) {
00332 QVImage<uChar> inter = QVImage<uChar>(imgGray.getCols() & 0xfffffffe,imgGray.getRows() & 0xfffffffe);
00333 Resize(imgGray,inter);
00334 imgGray = inter;
00335 }
00336 if(changing_size) {
00337 cols = imgGray.getCols();
00338 rows = imgGray.getRows();
00339 }
00340 return true;
00341 }
00342 else
00343 {
00344 end_of_video = true;
00345 if(fps != 0) simulateDelay(fps);
00346 return false;
00347 }
00348 }
00349 else if(source_mode == QVVideoReader::YUVMode)
00350 {
00351 if(base_reader->grab(imgY, imgU, imgV))
00352 {
00353 availableYUV = true;
00354 frames_grabbed++;
00355 emit newGrab();
00356 if(fps != 0) simulateDelay(fps);
00357
00358
00359
00360 if((imgY.getCols()%2==1) or (imgY.getRows()%2==1)) {
00361 QVImage<uChar> inter = QVImage<uChar>(imgY.getCols() & 0xfffffffe,imgY.getRows() & 0xfffffffe);
00362 Resize(imgY,inter);
00363 imgY = inter;
00364 }
00365 if(changing_size) {
00366 cols = imgY.getCols();
00367 rows = imgY.getRows();
00368 }
00369 if(imgU.getRows() != imgY.getRows()/2 or imgU.getCols() != imgY.getCols()/2 or
00370 imgV.getRows() != imgY.getRows()/2 or imgV.getCols() != imgY.getCols()/2 ) {
00371 std::cout << "ERROR in QVVideoReader::grab(): Y, U and U channels have not a correct size!\n";
00372 exit(1);
00373 }
00374 return true;
00375 }
00376 else
00377 {
00378 end_of_video = true;
00379 if(fps != 0) simulateDelay(fps);
00380 return false;
00381 }
00382 }
00383 else
00384 {
00385 if(base_reader->grab(imgR, imgG, imgB))
00386 {
00387 availableRGB = true;
00388 frames_grabbed++;
00389 emit newGrab();
00390 if(fps != 0) simulateDelay(fps);
00391
00392
00393
00394 if((imgR.getCols()%2==1) or (imgR.getRows()%2==1)) {
00395 QVImage<uChar> inter = QVImage<uChar>(imgR.getCols() & 0xfffffffe,imgR.getRows() & 0xfffffffe);
00396 Resize(imgR,inter);
00397 imgR = inter;
00398 Resize(imgG,inter);
00399 imgG = inter;
00400 Resize(imgB,inter);
00401 imgB = inter;
00402 }
00403 if(changing_size) {
00404 cols = imgR.getCols();
00405 rows = imgR.getRows();
00406 }
00407 if(imgG.getRows() != imgR.getRows() or imgG.getCols() != imgR.getCols() or
00408 imgB.getRows() != imgR.getRows() or imgB.getCols() != imgR.getCols() ) {
00409 std::cout << "ERROR in QVVideoReader::grab(): R, G and B channels are not of the same size!\n";
00410 exit(1);
00411 }
00412 return true;
00413 }
00414 else
00415 {
00416 end_of_video = true;
00417 if(fps != 0) simulateDelay(fps);
00418 return false;
00419 }
00420 }
00421 }
00422
00423 void QVVideoReader::getGrayImage(QVImage<uChar> &imageGray)
00424 {
00425 if(not availableGray)
00426 {
00427 if(availableYUV) {
00428 imgGray = imgY;
00429 availableGray = true;
00430 }
00431 else if(availableRGB)
00432 {
00433 imgRGB = QVImage<uChar,3>(imgR,imgG,imgB);
00434 imgGray = QVImage<uChar>(imgRGB.getCols(),imgRGB.getRows());
00435 RGBToGray(imgRGB,imgGray);
00436 availableGray = true;
00437 availableRGB3 = true;
00438 }
00439 else if(availableRGB3)
00440 {
00441 imgGray = QVImage<uChar>(imgRGB.getCols(),imgRGB.getRows());
00442 RGBToGray(imgRGB,imgGray);
00443 availableGray = true;
00444 }
00445 }
00446
00447 if( ( (imgGray.getRows() != rows) or (imgGray.getCols() != cols) ) )
00448 {
00449 imageGray = QVImage<uChar>(cols,rows);
00450 Resize(imgGray,imageGray);
00451 }
00452 else
00453 imageGray = imgGray;
00454 }
00455
00456 void QVVideoReader::getRGBImage(QVImage<uChar,3> & imageRGB)
00457 {
00458 if(not availableRGB3)
00459 {
00460 if(availableRGB)
00461 {
00462 imgRGB = QVImage<uChar,3>(imgR,imgG,imgB);
00463 availableRGB3 = true;
00464 }
00465 else if(availableYUV)
00466 {
00467 imgRGB = QVImage<uChar,3>(imgY.getCols(),imgY.getRows());
00468 YUV420ToRGB(imgY,imgU,imgV,imgRGB);
00469 availableRGB3 = true;
00470 }
00471 else if (availableGray)
00472 {
00473 imgRGB = QVImage<uChar,3>(imgGray,imgGray,imgGray);
00474 }
00475 }
00476
00477 if( ( (imgRGB.getRows() != rows) or (imgRGB.getCols() != cols) ) )
00478 {
00479 imageRGB = QVImage<uChar,3>(cols,rows);
00480 Resize(imgRGB,imageRGB);
00481 }
00482 else
00483 imageRGB = imgRGB;
00484 }
00485
00486 void QVVideoReader::getRGBImage(QVImage<uChar> &imageR, QVImage<uChar> &imageG, QVImage<uChar> &imageB)
00487 {
00488 if(not availableRGB)
00489 {
00490 if(availableRGB3)
00491 {
00492 imgR = imgG = imgB = QVImage<uChar>(imgRGB.getCols(),imgRGB.getRows());
00493 Copy(imgRGB,0,imgR);
00494 Copy(imgRGB,1,imgG);
00495 Copy(imgRGB,2,imgB);
00496 availableRGB = true;
00497 }
00498 else if(availableYUV)
00499 {
00500 imgRGB = QVImage<uChar,3>(imgY.getCols(),imgY.getRows());
00501 YUV420ToRGB(imgY,imgU,imgV,imgRGB);
00502 imgR = imgG = imgB = QVImage<uChar>(imgRGB.getCols(),imgRGB.getRows());
00503 Copy(imgRGB,0,imgR);
00504 Copy(imgRGB,1,imgG);
00505 Copy(imgRGB,2,imgB);
00506 availableRGB = true;
00507 availableRGB3 = true;
00508 }
00509 else if (availableGray)
00510 {
00511 imgR = imgGray;
00512 imgG = imgGray;
00513 imgB = imgGray;
00514 availableRGB = true;
00515 }
00516 }
00517
00518 if( ( (imgR.getRows() != rows) or (imgR.getCols() != cols) or
00519 (imgG.getRows() != rows) or (imgG.getCols() != cols) or
00520 (imgB.getRows() != rows) or (imgB.getCols() != cols) ) )
00521 {
00522 imageR = QVImage<uChar>(cols,rows);
00523 imageG = QVImage<uChar>(cols,rows);
00524 imageB = QVImage<uChar>(cols,rows);
00525 Resize(imgR,imageR);
00526 Resize(imgG,imageG);
00527 Resize(imgB,imageB);
00528 }
00529 else
00530 {
00531 imageR = imgR;
00532 imageG = imgG;
00533 imageB = imgB;
00534 }
00535 }
00536
00537 void QVVideoReader::getYUVImage(QVImage<uChar> &imageY, QVImage<uChar> &imageU, QVImage<uChar> &imageV)
00538 {
00539 if(not availableYUV)
00540 {
00541 if(availableRGB3)
00542 {
00543 imgY = QVImage<uChar>(imgRGB.getCols(),imgRGB.getRows());
00544 imgU = imgV = QVImage<uChar>(imgRGB.getCols()/2,imgRGB.getRows()/2);
00545 RGBToYUV420(imgRGB,imgY,imgU,imgV);
00546 availableYUV = true;
00547 }
00548 else if(availableRGB)
00549 {
00550 imgRGB = QVImage<uChar,3>(imgR,imgG,imgB);
00551 imgY = QVImage<uChar>(imgRGB.getCols(),imgRGB.getRows());
00552 imgU = imgV = QVImage<uChar>(imgRGB.getCols()/2,imgRGB.getRows()/2);
00553 RGBToYUV420(imgRGB,imgY,imgU,imgV);
00554 availableYUV = true;
00555 availableRGB3 = true;
00556 }
00557 else if (availableGray)
00558 {
00559 imgRGB = QVImage<uChar,3>(imgGray,imgGray,imgGray);
00560 imgY = QVImage<uChar>(imgRGB.getCols(),imgRGB.getRows());
00561 imgU = imgV = QVImage<uChar>(imgRGB.getCols()/2,imgRGB.getRows()/2);
00562 RGBToYUV420(imgRGB,imgY,imgU,imgV);
00563 availableRGB3 = true;
00564 availableYUV = true;
00565 }
00566 }
00567
00568 if( ( (imgY.getRows() != rows) or (imgY.getCols() != cols) or
00569 (imgU.getRows() != rows/2) or (imgU.getCols() != cols/2) or
00570 (imgV.getRows() != rows/2) or (imgV.getCols() != cols/2) ) )
00571 {
00572 imageY = QVImage<uChar>(cols,rows);
00573 imageU = QVImage<uChar>(cols/2,rows/2);
00574 imageV = QVImage<uChar>(cols/2,rows/2);
00575 Resize(imgY,imageY);
00576 Resize(imgU,imageU);
00577 Resize(imgV,imageV);
00578 }
00579 else
00580 {
00581 imageY = imgY;
00582 imageU = imgU;
00583 imageV = imgV;
00584 }
00585 }
00586
00587 bool QVVideoReader::close()
00588 {
00589 if(base_reader != 0)
00590 {
00591 if(base_reader->close())
00592 {
00593 url = QString();
00594 scheme = QString();
00595 cols = 0;
00596 rows = 0;
00597 fps = 0;
00598 frames_grabbed = 0;
00599 camera_opened = false;
00600 live_camera = false;
00601 end_of_video = true;
00602 availableGray = availableRGB3 = availableYUV = availableRGB = false;
00603 open_options = Default;
00604 source_mode = YUVMode;
00605 delete base_reader;
00606 base_reader = 0;
00607 emit sourceClosed();
00608 return true;
00609 }
00610 }
00611 return false;
00612 }
00613
00614 bool QVVideoReader::seek(int pos)
00615 {
00616 return base_reader->seek(pos);
00617 }
00618
00619 int QVVideoReader::getLength() const
00620 {
00621 return base_reader->getLength();
00622 }
00623
00624 int QVVideoReader::getPos() const
00625 {
00626 return base_reader->getPos();
00627 }
00628