src/qvcameras/qvmplayercamera.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 #include <unistd.h>
00028 #include <stdlib.h>
00029 #include <fcntl.h>
00030 #include <stdio.h>
00031 
00032 #include <QApplication>
00033 #include <QDebug>
00034 #include <QObject>
00035 #include <QStringList>
00036 #include <QRegExp>
00037 #include <QMutex>
00038 
00039 #include <qvcore/qvworker.h>
00040 #include <qvcameras/qvmplayercamera.h>
00041 
00042 /******************* Auxiliary QVCheckOKMPlayerCamera Class *******************/
00043 QVCheckOKMplayerCamera::QVCheckOKMplayerCamera(QFile & fifo_file,int max_time_ms_to_wait_for_open) : QThread(), _fifo_file(fifo_file), _max_time_ms_to_wait_for_open(max_time_ms_to_wait_for_open)
00044         {
00045         qDebug() << "QVCheckOKMplayerCamera::QVCheckOKMplayerCamera()";
00046         qDebug() << "QVCheckOKMplayerCamera::QVCheckOKMplayerCamera() <- return";
00047         }
00048 
00049 QVCheckOKMplayerCamera::~QVCheckOKMplayerCamera()
00050         {
00051         qDebug() << "QVCheckOKMplayerCamera::~QVCheckOKMplayerCamera()";
00052         quit();
00053         wait();
00054         qDebug() << "QVCheckOKMplayerCamera::~QVCheckOKMplayerCamera: thread finished";
00055         qDebug() << "QVCheckOKMplayerCamera::~QVCheckOKMplayerCamera() <- return";
00056         }
00057 
00058 void QVCheckOKMplayerCamera::run()
00059         {
00060         qDebug() << "QVCheckOKMplayerCamera::run()";
00061         QTimer::singleShot(_max_time_ms_to_wait_for_open, this, SLOT(writeErrorInFifo()));
00062         qDebug() << "QVCheckOKMplayerCamera::run() <- entering event loop";
00063         exec();
00064         qDebug() << "QVCheckOKMplayerCamera::run() <- back from event loop";
00065         qDebug() << "QVCheckOKMplayerCamera::run() <- return";
00066         }
00067 
00068 
00069 void QVCheckOKMplayerCamera::writeErrorInFifo()
00070         {
00071         qDebug() << "QVCheckOKMplayerCamera::writeErrorInFifo()";
00072         _fifo_file.write("MPLAYER ERROR\n"); 
00073         qDebug() << "QVCheckOKMplayerCamera::writeErrorInFifo() -> return";
00074         };
00075 
00076 /********************* Auxiliary QVCameraThread Class *************************/
00077 //QVCameraThread::QVCameraThread(): QThread(), objectList(), slotList(), timer(NULL)
00078 QVCameraThread::QVCameraThread(QObject *object,char *slot): QThread(), _object(object), _slot(slot)
00079         {
00080         qDebug() << "QVCameraThread::QVCameraThread()";
00081         _object->moveToThread(this);
00082         qDebug() << "QVCameraThread::QVCameraThread(): object moved to thread";
00083         qDebug() << "QVCameraThread::QVCameraThread() <- return";
00084         }
00085 
00086 QVCameraThread::~QVCameraThread()
00087         {
00088         qDebug() << "QVCameraThread::~QVCameraThread()";
00089         disconnect();
00090         quit();
00091         qDebug() << "QVCameraThread::~QVCameraThread(): sent quit to thread";
00092         wait();
00093         qDebug() << "QVCameraThread::~QVCameraThread(): thread finished";
00094         qDebug() << "QVCameraThread::~QVCameraThread() <- return";
00095         }
00096 
00097 void QVCameraThread::run()
00098         {
00099         qDebug() << "QVCameraThread::run()";
00100         QTimer *timer = new QTimer();
00101         timer->start(0);
00102         connect(timer, SIGNAL(timeout()),_object,_slot);
00103         qDebug() << "QVCameraThread::run(): timer created, started and connected";
00104         qDebug() << "QVCameraThread::run(): entering event processing loop";
00105         exec();
00106         qDebug() << "QVCameraThread::run(): back from event processing loop";
00107         delete timer;
00108         qDebug() << "QVCameraThread::run(): timer deleted";
00109         qDebug() << "QVCameraThread::run() <- return";
00110         }
00111 
00112 /********************* Auxiliary QVMPlayerIOProcessor class *******************/
00113 QVMPlayerIOProcessor::QVMPlayerIOProcessor(QProcess * mplayer): QObject(), command_queue(), command_queue_mutex()
00114         {
00115         qDebug() << "QVMPlayerIOProcessor::QVMPlayerIOProcessor()";
00116         rows = cols = 0;
00117         fps = time_length = time_pos = 0;
00118         speed = 1;
00119         this->mplayer = mplayer;
00120         mplayer->waitForReadyRead();
00121         qDebug() << "QVMPlayerIOProcessor::QVMPlayerIOProcessor() <- return";
00122         }
00123 
00124 QVMPlayerIOProcessor::~QVMPlayerIOProcessor()
00125         {
00126         qDebug() << "QVMPlayerIOProcessor::~QVMPlayerIOProcessor()";
00127         qDebug() << "QVMPlayerIOProcessor::~QVMPlayerIOProcessor() <- return";
00128         }
00129 
00130 void QVMPlayerIOProcessor::queueCommandToMPlayer(const QString &com_str, bool ifEmpty)
00131         {
00132         qDebug() << "QVMPlayerIOProcessor::queueCommand("<< com_str <<")";
00133         qDebug() << "QVMPlayerIOProcessor::queueCommand(): command_queue.size() = "
00134                 << command_queue.size();
00135         command_queue_mutex.lock();
00136         if(!ifEmpty || command_queue.size()==0)
00137                 command_queue << com_str + '\n';
00138         command_queue_mutex.unlock();
00139         qDebug() << "QVMPlayerIOProcessor::queueCommand() <- return";
00140         }
00141 
00142 void QVMPlayerIOProcessor::sendCommandToMPlayer()
00143         {
00144         qDebug() << "QVMPlayerIOProcessor::sendCommandToMPlayer()";
00145         command_queue_mutex.lock();
00146         if (command_queue.size() > 0)
00147                 {
00148                 qDebug() << "QVMPlayerIOProcessor::sendCommandToMPlayer(): sending command:" << command_queue.head();
00149                 mplayer->write(qPrintable(command_queue.dequeue()));
00150                 }
00151         command_queue_mutex.unlock();
00152         qDebug() << "QVMPlayerIOProcessor::sendCommandToMPlayer(): wait for bytes written";
00153         // BUG: In Windows this hangs?
00154         #ifdef unix
00155         mplayer->waitForBytesWritten();
00156         #endif
00157         qDebug() << "QVMPlayerIOProcessor::sendCommandToMPlayer() <- return";
00158         }
00159 
00160 int QVMPlayerIOProcessor::interpretMPlayerOutput()
00161         {
00162         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput()";
00163         int length = -1;
00164         char buf[1024];
00165 
00166         length = mplayer->readLine(buf, sizeof(buf));
00167 
00168         if (length == -1)
00169                 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): length == -1";
00170         else    {
00171                 QString str(buf);
00172                 QStringList variables = str.simplified().split("=");
00173                 QStringList palabras = str.simplified().split(" ");
00174 
00175                 if(variables[0] == "ANS_speed")
00176                         {
00177                         speed = variables[1].toDouble();
00178                         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating speed =" << speed;
00179                         }
00180                 else if(variables[0] == "ANS_LENGTH")
00181                         {
00182                         time_length = variables[1].toDouble();
00183                         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating time_length =" << time_length;
00184                         }
00185                 else if(variables[0] == "ANS_TIME_POSITION")
00186                         {
00187                         time_pos = variables[1].toDouble();
00188                         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating time_pos =" << time_pos;
00189                         }
00190                 else if (palabras[0] == "VIDEO:")
00191                         {
00192                         // ya tenemos las especificaciones de fps
00193                         for (int i = 0; i < palabras.size(); ++i)
00194                                 if (palabras[i] == "fps")
00195                                         fps = palabras[i-1].toDouble();
00196 
00197                         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating fps" << fps;
00198                         }
00199                 else if (palabras[0] == "VO:")
00200                         {
00201                         // ya tenemos las especificaciones del video y dimensiones
00202                         QStringList dimensiones = palabras[2].split("x");
00203                         cols = dimensiones[0].toInt();
00204                         rows = dimensiones[1].toInt();
00205                         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating cols" << cols;
00206                         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating rows" << rows;
00207                         }
00208                 else
00209                         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): uninterpreted mplayer output:" << str;
00210                 }
00211         qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput() <- return" << length;
00212         return length;
00213         }
00214 
00215 /******************* Auxiliary QVMPlayerFrameGrabber Class ********************/
00216 QVMPlayerFrameGrabber::QVMPlayerFrameGrabber(QVMPlayerIOProcessor *mplayerIOProcessor, QFile *fifoInput, uInt rows, uInt cols, bool isRGB, bool realTime): QObject()
00217         {
00218         qDebug() << "QVMPlayerFrameGrabber::QVMPlayerFrameGrabber(fifoInput," << mplayerIOProcessor->rows << "," << mplayerIOProcessor->cols << "," << isRGB << "," << realTime <<")";
00219         
00220         this->mplayerIOProcessor = mplayerIOProcessor;
00221         this->fifoInput = fifoInput;
00222         this->realTime = realTime;
00223         this->isYUV = not isRGB;
00224         this->finished = false;
00225         this->frames_read = 0;
00226 
00227         debug_in_memcpy = debug_in_updateSlot = false;
00228 
00229         if(isYUV)
00230                 {
00231                 imgY = QVImage<uChar>(cols, rows, cols);
00232                 img_auxY = QVImage<uChar>(cols, rows, cols);
00233                 img_auxU = QVImage<uChar>(cols/2, rows/2, cols/2);
00234                 img_auxV = QVImage<uChar>(cols/2, rows/2, cols/2);
00235                 // ...a YUV420 rows x cols image:
00236                 buf_size = rows*cols + rows*cols/4 + rows*cols/4;
00237                 }
00238         else    {
00239                 imgRGB = QVImage<uChar,3>(cols, rows, 3*cols);
00240                 img_auxRGB = QVImage<uChar,3>(cols, rows, 3*cols);
00241                 // ...or a RGB rows x cols image:
00242                 buf_size = 3*rows*cols;
00243                 }
00244 
00245         if (realTime)
00246                 {
00247                 qvcamerathread = new QVCameraThread(this,SLOT(updateSlot()));
00248                 qvcamerathread->start(QThread::NormalPriority);
00249                 }
00250 
00251         qDebug() << "QVMPlayerFrameGrabber::QVMPlayerFrameGrabber() <- return";
00252         };
00253 
00254 QVMPlayerFrameGrabber::~QVMPlayerFrameGrabber()
00255         {
00256         qDebug() << "QVMPlayerFrameGrabber::~QVMPlayerFrameGrabber()";
00257         finished = true;
00258         if (realTime) delete qvcamerathread;
00259         qDebug() << "QVMPlayerFrameGrabber::~QVMPlayerFrameGrabber(): thread deleted.";
00260         qDebug() << "QVMPlayerFrameGrabber::~QVMPlayerFrameGrabber() <- return";
00261         }
00262 
00263 void QVMPlayerFrameGrabber::getNewFrame(QVImage<uChar,3> &img)
00264         {
00265         readToBuffer(img.getWriteData(), buf_size);
00266         }
00267 
00268 void QVMPlayerFrameGrabber::getNewFrame(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV)
00269         {
00270         qDebug() << "QVMPlayerFrameGrabber::getNewFrame(): reading YUV header";
00271         char buf[1024];
00272         fifoInput->readLine(buf, sizeof(buf));
00273         readToBuffer(imgY.getWriteData(), 2*buf_size/3);
00274         readToBuffer(imgU.getWriteData(), buf_size/6);
00275         readToBuffer(imgV.getWriteData(), buf_size/6);
00276         qDebug() << "QVMPlayerFrameGrabber::getNewFrame() <- return";
00277         }
00278 
00279 void QVMPlayerFrameGrabber::updateSlot()
00280         {
00281         qDebug() << "QVMPlayerFrameGrabber::updateSlot()";
00282 
00283         qDebug() << "QVMPlayerFrameGrabber::updateSlot(): sent command to mplayer: get_time_pos";
00284         mplayerIOProcessor->queueCommandToMPlayer("pausing_keep get_time_pos\n",true);
00285 
00286         // Avoid QSocketNotifier annoying message, by deferring call:
00287         emit sendCommandSignal(); // NOT mplayerIOProcessor->sendCommandToMPlayer();
00288 
00289         // New frame read:
00290         qDebug() << "QVMPlayerFrameGrabber::updateSlot(): reading frame";
00291         QVImage<uChar, 1> tempY;
00292         QVImage<uChar, 1> tempU;
00293         QVImage<uChar, 1> tempV;
00294         QVImage<uChar, 3> tempRGB;
00295 
00296         // We always read in temporal images, that are later safely copied:
00297         // There is no copy overhead because QVImage uses QSharedData (reference
00298         // counting).
00299         if (isYUV)
00300                 getNewFrame(tempY = img_auxY, tempU = img_auxU, tempV = img_auxV);
00301         else    
00302                 getNewFrame(tempRGB = img_auxRGB);
00303 
00304         // If in real time, we lock, to avoid collision with the thread that is
00305         // grabbing from the camera:
00306         if(realTime)
00307                 {
00308                 mutex.lock();
00309                 debug_in_updateSlot = true;
00310                 if (debug_in_memcpy)
00311                         {
00312                         std::cerr << "(BUG1) entered frameUpdate while memcpying!";
00313                         exit(0);
00314                         }
00315                 }
00316 
00317         if (isYUV)
00318                 {
00319                 img_auxY = tempY;
00320                 img_auxU = tempU;
00321                 img_auxV = tempV;
00322                 }
00323         else
00324                 img_auxRGB = tempRGB;
00325 
00326         // Unlock (if in real time):
00327         if(realTime)
00328                 {
00329                 if (debug_in_memcpy) {
00330                         std::cerr << "(BUG2) entered frameUpdate while memcpying!";
00331                         exit(0);
00332                 }
00333                 debug_in_updateSlot = false;
00334                 condition.wakeAll(); // Wake possible waiting grabs.
00335                 mutex.unlock();
00336                 }
00337 
00338         qDebug() << "QVMPlayerFrameGrabber::updateSlot(): finished" << finished;
00339         frames_read++;
00340         qDebug() << "QVMPlayerFrameGrabber::updateSlot(): frames read" << frames_read;
00341 
00342         mplayerIOProcessor->interpretMPlayerOutput();
00343 
00344         qDebug() << "QVMPlayerFrameGrabber::updateSlot() <- return";
00345 
00346         emit newReadFrameGrabber();
00347         }
00348 
00349 void QVMPlayerFrameGrabber::updateFrameBuffer()
00350         {
00351         qDebug() << "QVMPlayerFrameGrabber::updateFrameBuffer()";
00352 
00353         // Here we come from a grab, so we always lock (if in real time, it is 
00354         // obviously needed, but also if not in real time, to make non-real-cameras
00355         // grabbing also thread-safe (won't be used normally, but who knows...
00356         // maybe the programmer wish to read different frames from different
00357         // threads, without discarding any frame as could happen with real time
00358         // cameras).
00359         mutex.lock();
00360         if (debug_in_updateSlot) 
00361                 {
00362                 std::cerr << "(BUG3) entered memcpy while frameUpdating!";
00363                 exit(0);
00364                 }
00365 
00366         if(realTime)
00367                 condition.wait(&mutex); // If in real time, wait for next fresh frame.
00368         debug_in_memcpy = true;
00369 
00370         // If in real time, updateSlot is asynchronously called by a dedicated
00371         // thread, otherwise we have to call it explicitly.
00372         if(not realTime)
00373                 updateSlot();
00374 
00375         if (isYUV)
00376                 {
00377                 imgY = img_auxY;
00378                 imgU = img_auxU;
00379                 imgV = img_auxV;
00380                 }
00381         else
00382                 imgRGB = img_auxRGB;
00383 
00384         if (debug_in_updateSlot) 
00385                 {
00386                 std::cerr << "(BUG4) entered memcpy while frameUpdating!";
00387                 exit(0);
00388                 }
00389         debug_in_memcpy = false;
00390         mutex.unlock();
00391 
00392         qDebug() << "QVMPlayerFrameGrabber::updateFrameBuffer() <- return";
00393         }
00394 
00395 void QVMPlayerFrameGrabber::getQVImageYUV(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV) const
00396         {
00397         qDebug() << "QVMPlayerFrameGrabber::getQVImageYUV()";
00398         imgY = this->imgY;
00399         imgU = this->imgU;
00400         imgV = this->imgV;
00401         qDebug() << "QVMPlayerFrameGrabber::getQVImageYUV() <- return";
00402         }
00403 
00404 void QVMPlayerFrameGrabber::getQVImageGray(QVImage<uChar> &imgGray) const
00405         {
00406         qDebug() << "QVMPlayerFrameGrabber::getQVImageYUV()";
00407         imgGray = imgY;
00408         qDebug() << "QVMPlayerFrameGrabber::getQVImageYUV() <- return";
00409         }
00410 
00411 void QVMPlayerFrameGrabber::getQVImageRGB(QVImage<uChar,3> &img) const
00412         {
00413         qDebug() << "QVMPlayerFrameGrabber::getQVImageRGB()";
00414         img = imgRGB;
00415         qDebug() << "QVMPlayerFrameGrabber::getQVImageRGB() <- return";
00416         }
00417 
00418 void QVMPlayerFrameGrabber::readToBuffer(uChar *buf_img_aux, uInt buf_size)
00419         {
00420         uInt totbytes = 0;
00421         while (totbytes != buf_size and not finished)
00422                 {
00423                 int nbytes = fifoInput->read((char *)(buf_img_aux+totbytes), buf_size-totbytes);
00424 
00425                 totbytes += nbytes;
00426                 qDebug() << "QVMPlayerFrameGrabber::readNewFrame(): read" << nbytes << "bytes";
00427 
00428                 if(nbytes == 0)
00429                         {
00430                         finished = TRUE;
00431                         qDebug() << "QVMPlayerFrameGrabber::readNewFrame(): read 0 bytes, finishing" << finished;
00432                         break;
00433                         }
00434 
00435                 if(nbytes == -1)
00436                         {
00437                         // BUG: problem in Windows, suddenly pipe can not be read ?!!?
00438                         // errorString() -> "Device did not accept the command."
00439                         finished = TRUE;
00440                         qDebug() << "QVMPlayerFrameGrabber::readNewFrame(): error -" << fifoInput->errorString();
00441                         break;
00442                         }                       
00443                 }
00444         }
00445 
00446 /***************************** QVMPlayerCamera Class **************************/
00447 QVMPlayerCamera::QVMPlayerCamera(QString name):QVCamera(name), open_options(Default)
00448         {
00449         qDebug() << "QVMPlayerCamera::QVMPlayerCamera()";
00450         if (qvApp == NULL)
00451                 {
00452                 QString str = "QVWorker::QVWorker(): the QVWorker cannot be created before the QVApplication instance. Aborting now.";
00453                 std::cerr << qPrintable(str) << std::endl;
00454                 exit(1);
00455                 }
00456 
00457         frames_grabbed = 0;
00458         rgbMode = false;
00459         setStatus(Closed);
00460         live_camera = FALSE;
00461 
00462         // Properties (to allow reading from argc and argv):
00463         addProperty<int>("Rows", inputFlag, 0, "Rows to open the camera");
00464         addProperty<int>("Cols", inputFlag, 0, "Columns to open the camera");
00465         addProperty<bool>("RealTime", inputFlag, FALSE,"If the camera should be opened in real time mode");
00466         addProperty<bool>("Deinterlaced", inputFlag, FALSE,"If the camera should be opened in deinterlaced mode");
00467         addProperty<bool>("NoLoop", inputFlag, FALSE,"If the camera should be opened in no loop mode");
00468         addProperty<bool>("RGBMEncoder", inputFlag, FALSE,"If the camera should be opened in RGB using mencoder");
00469         addProperty<QString>("URL", inputFlag, QString(""),"URL of the video source");
00470         //addProperty<int>("Count",0,"Test param");
00471 
00472         // QVImage's
00473         addProperty< QVImage<uChar,3> >("RGB image", outputFlag, QVImage<uChar,3>(), "Last grabbed RGB image");
00474         addProperty< QVImage<uChar,1> >("Y channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed Y channel image");
00475         addProperty< QVImage<uChar,1> >("U channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed U channel image");
00476         addProperty< QVImage<uChar,1> >("V channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed V channel image");
00477 
00478         qDebug() << "QVMPlayerCamera::QVMPlayerCamera() <- return";
00479         }
00480 
00481 QVMPlayerCamera::~QVMPlayerCamera()
00482         {
00483         qDebug() << "QVMPlayerCamera::~QVMPlayerCamera()";
00484         if (status != Closed) closeCam();
00485         qDebug() << "QVMPlayerCamera::~QVMPlayerCamera() <- deleting image";
00486         setImageBuffer(NULL);
00487         qDebug() << "QVMPlayerCamera::~QVMPlayerCamera() <- return";
00488         }
00489 
00490 void QVMPlayerCamera::initMPlayerArgs(QString urlString, uInt rows, uInt cols)
00491         {
00492         qDebug() << "QVMPlayerCamera::initMPlayerArgs()";
00493         qDebug() << "QVMPlayerCamera::initMPlayerArgs(): url string =" << urlString;
00494 
00495         // Loop option and fixed-vo must go first:
00496         if(not (open_options & NoLoop)) mplayer_args << "-loop" << "0";
00497 
00498         mplayer_args << "-fixed-vo";
00499 
00500         QUrl url(urlString);
00501 
00502         if (url.host() != "")
00503                 path = url.host() + "/";
00504 
00505         path += url.path();
00506 
00507         qDebug() << "QVMPlayerCamera::initMPlayerArgs(): path" << path;
00508 
00509         // Here we infer the type of the video source from the url.
00510         // If it is not specified in the schema of it, certain match rules are
00511         // applied to guess it out.
00512         if (url.scheme() != "")                         // schema specified by the user
00513                 schema = url.scheme();
00514         else if (urlString.startsWith("/dev/video"))    // a v4l device
00515                 schema = "v4l";
00516         else if (urlString.startsWith("/dev/dv"))       // a dv device
00517                 schema = "dv";
00518         else if (urlString.contains("*"))               // a multifile
00519                 schema = "mf";
00520         else if (urlString.startsWith("www."))          // a http file
00521                 schema = "http";
00522         else if (urlString.startsWith("ftp."))          // a ftp file
00523                 schema = "ftp";
00524 
00525         qDebug() << "QVMPlayerCamera::initMPlayerArgs(): scheme" << schema;
00526 
00527         live_camera = TRUE;     // default configuration
00528 
00529         // Different mplayer args for different kind of image sources:
00530         if ((schema == "v4l") or (schema == "v4l2") or (schema == "analog"))
00531                 {
00532                 // Video for Linux cameras:
00533                 QString urlQueryValues = QString("driver=%1:device=%2").arg(schema).arg(path);
00534 
00535                 QList<QPair<QString, QString> > queryItems = url.queryItems();
00536                 for (int i = 0; i < queryItems.size(); ++i)
00537                         urlQueryValues += ":" + queryItems.at(i).first + "=" + queryItems.at(i).second;
00538 
00539                 mplayer_args << "tv://" << "-tv" << urlQueryValues;
00540                 }
00541         else if (schema == "dv")
00542                 // DV cameras (connected through firewire):
00543                 mplayer_args << path << "-demuxer" << "rawdv" << "-cache" << "400";
00544         else if (schema == "iidc")
00545                 // IIDC cameras (connected through firewire):
00546                 // For example, iidc:///dev/video1394/0?from=/dev/video0:to=/dev/video1
00547                 qFatal("Currently this driver does not work (apparently with\n"
00548                         "vloopback writing and then reading from a fifo with mplayer\ndoes not work).\n");
00549         else if (schema == "tv")
00550                 // Analog TV input:
00551                 qFatal("tv URL: Still not implemented\n");
00552         else if (schema == "dvb")
00553                 // Digital TV input:
00554                 qFatal("dvb URL: Still not implemented\n");
00555         else    // Format can be rtsp:// http://, ftp://, dvd://, vcd://, mf:// or file://
00556                 { 
00557                 //  We pass the url it directly to mplayer:
00558                 live_camera = FALSE;
00559                 if (schema != "")
00560                         mplayer_args << QString(schema + "://" + path);
00561                 else
00562                         mplayer_args << path;
00563                 }
00564 
00565         // IMPORTANT!! All -vf filters MUST be together, separated by commas, and in
00566         // the right order. By now, we only use deinterlacing and scale, and in that order:
00567         QString aux;
00568 
00569         // Deinterlace option:
00570         if(open_options & Deinterlaced) aux = "pp=md";
00571 
00572         if(rows != 0 or cols != 0)
00573                 {
00574                 if(aux != QString())
00575                         aux += QString(",scale=%1:%2").arg(cols).arg(rows);
00576                 else
00577                         aux = QString("scale=%1:%2").arg(cols).arg(rows);
00578                 }
00579 
00580         if (aux != QString()) mplayer_args << "-vf" << aux;
00581 
00582         // Real time option:
00583         if(not (open_options & RealTime))
00584                 {
00585                 if(not live_camera)
00586                         mplayer_args << "-benchmark";
00587                 else
00588                         // The user attempted to open a live camera in continuous mode.
00589                         // We issue a warning:
00590                         qWarning("Warning: opening live cameras in continuous mode "
00591                                          "wastes less CPU time, but it is prone to delays in "
00592                                          "the pipe of images if your process is slower than "
00593                                          "the camera.");
00594                 }
00595 
00596         // Additional arguments (slave, quiet, nosound & yuv4mpeg output):
00597         mplayer_args << "-slave" << "-quiet" << "-nosound" << "-vo" << QString("yuv4mpeg:file=%1").arg(namedPipe->getInputFilePath());
00598 
00599         /* for(QStringList::Iterator it=mplayer_args.begin(); it != mplayer_args.end();++it )
00600                    printf( "%s \n", qPrintable(*it) );*/
00601         
00602         /*std::cout << "MPlayer args:" << std::endl;
00603         foreach(QString arg, mplayer_args)
00604                 std::cout << "\t" << qPrintable(arg) << std::endl;*/
00605 
00606         qDebug() << "QVMPlayerCamera::initMPlayerArgs() <- return";
00607         }
00608 
00609 // (Implicit) default open method for a camera (uses introspection to read 
00610 // parameters, allowing initialization from argc and argv):
00611 bool QVMPlayerCamera::openCam()
00612         {
00613         OpenOptions optsProp = Default;
00614 
00615         if (getPropertyValue<bool>("RealTime"))         optsProp |= RealTime;
00616         if (getPropertyValue<bool>("Deinterlaced"))     optsProp |= Deinterlaced;
00617         if (getPropertyValue<bool>("NoLoop"))           optsProp |= NoLoop;
00618         if (rgbMode)                                    optsProp |= RGBMEncoder;
00619 
00620         return openCam(getPropertyValue<QString>("URL"), getPropertyValue<int>("Rows"), getPropertyValue<int>("Cols"), optsProp);
00621         }
00622 
00623 // Explicit open url (and possible options) method:
00624 bool QVMPlayerCamera::openCam(const QString & urlstring,OpenOptions opts)
00625         { return openCam(urlstring,0,0,opts); }
00626 
00627 // Main method to open a camera:
00628 bool QVMPlayerCamera::openCam(const QString & urlstring, uInt rows, uInt cols, OpenOptions opts)
00629         {
00630         qDebug() << "QVMPlayerCamera::openCam(" << urlstring << "," << rows << "," << cols << "," << opts << ")";
00631 
00632         setStatus(Closed);
00633 
00634         open_options = opts;
00635 
00636         // Pipe initialization
00637         namedPipe = new QNamedPipe(QString("mplayer"));
00638         fifo_file.setFileName(namedPipe->getOutputFilePath());
00639 
00640         if(open_options & QVMPlayerCamera::RGBMEncoder)
00641                 {
00642                 namedPipeAux = new QNamedPipe(QString("mplayer-aux"));
00643                 fifo_file_2.setFileName(namedPipeAux->getOutputFilePath());
00644                 }
00645 
00646         initMPlayerArgs(urlstring, rows, cols);
00647 
00648         qDebug() << "QVMPlayerCamera::openCam(): MPlayer args ->" << mplayer_args;
00649         mplayer.start(MPLAYER_BINARY_PATH,mplayer_args);
00650         qDebug() << "QVMPlayerCamera::openCam(): after mplayer.start()";
00651         if(not mplayer.waitForStarted(1000))
00652                 qFatal("Mplayer failed to start: Are you sure it is installed and in the correct PATH?");
00653         qDebug() << "QVMPlayerCamera::openCam(): after mplayer.waitForstarted()";
00654         
00655         // We create a guarding thread that will unblock the subsequent
00656         // fifo_file.readLine in the case that mplayer does not start OK (due,
00657         // for example, to a wrong URL, an incorrect file format, or whatever).
00658         // If mplayer starts OK before two seconds (for local videos) or ten
00659         // seconds (for DVD, VCD and remote videos), this thread silently stops and
00660         // is deleted.
00661         QVCheckOKMplayerCamera *check_thread;
00662         if (schema == "http" or schema == "ftp" or schema == "rtsp" or schema == "dvd" or schema == "vcd")
00663                 check_thread = new QVCheckOKMplayerCamera(fifo_file, 10000);
00664         else
00665                 check_thread = new QVCheckOKMplayerCamera(fifo_file, 2000);
00666 
00667         check_thread->moveToThread(check_thread);
00668         check_thread->start();
00669         qDebug() << "QVMPlayerCamera::openCam(): after starting QVCheckOKMplayerCamera thread";
00670 
00671         // Important to open in ReadWrite mode, to avoid infinite waiting if
00672         // mplayer did not start OK, and because perhaps the former guarding
00673         // thread will write in the FIFO.
00674         qDebug() << "QVMPlayerCamera::openCam(): opening fifo_file";
00675         if((fifo_file.open(QIODevice::ReadWrite|QIODevice::Unbuffered)) == -1)
00676                 qFatal("Error opening fifo %s\n", qPrintable(namedPipe->getPipeName()));
00677         qDebug() << "QVMPlayerCamera::openCam(): reading fifo_file";
00678 
00679         // Now we read YUV header:
00680         char buf[1024];
00681         int len;
00682         if ((len = fifo_file.readLine(buf, sizeof(buf))) == -1) return FALSE;
00683         if (QString(buf) == QString("MPLAYER ERROR\n")) { 
00684                 std::cerr << "QVMPlayerCamera::openCam(): Warning: Mplayer could not open the requested video source (" << qPrintable(urlstring) << ") of type " << qPrintable(schema) <<std::endl;
00685                 check_thread->quit();
00686                 check_thread->wait();
00687                 delete check_thread;
00688 
00689                 // Cleaning: mplayer.waitForFinished();
00690                 mplayer.terminate();
00691                 if (not mplayer.waitForFinished(500)) mplayer.kill();   
00692                 fifo_file.close();
00693                 delete namedPipe;
00694                 if(open_options & QVMPlayerCamera::RGBMEncoder)
00695                         delete namedPipeAux;
00696 
00697                 qDebug() << "QVMPlayerCamera::openCam(): QVCheckOKMplayerCamera thread deleted after detecting an error; returning FALSE";
00698                 return FALSE;
00699         }
00700 
00701         // If in RGBMEncoder mode, we also launch mencoder (previously writing
00702         // the read line back to the pipe, because mencoder will need it):
00703         if(open_options & QVMPlayerCamera::RGBMEncoder)
00704                 {
00705                 fifo_file.write(buf,len);
00706                 mencoder.start(MENCODER_BINARY_PATH, QStringList() << namedPipe->getOutputFilePath() << "-nosound" << "-o" << namedPipeAux->getInputFilePath() <<
00707                                                         "-ovc" << "raw" << "-of" << "rawvideo" << "-vf" << "format=rgb24");
00708                 qDebug() << "QVMPlayerCamera::openCam(): mencoder started";
00709                 if(not mencoder.waitForStarted(1000))
00710                         qFatal("Mencoder failed to start: Are you sure it is installed and in the correct PATH?");
00711                 qDebug() << "QVMPlayerCamera::openCam(): opening fifo_file_2";
00712                 if((fifo_file_2.open(QIODevice::ReadOnly|QIODevice::Unbuffered))==-1)
00713                         qFatal("Error opening fifo %s\n", qPrintable(namedPipeAux->getPipeName()));
00714                 }
00715 
00716         check_thread->quit();
00717         check_thread->wait();
00718 
00719         delete check_thread;
00720         qDebug() << "QVMPlayerCamera::openCam(): QVCheckOKMplayerCamera thread deleted after correct launch of mplayer";
00721 
00722         qDebug() << "QVMPlayerCamera::openCam(): going to create QVMPlayerIOProcessor...";
00723         mplayerIOProcessor = new QVMPlayerIOProcessor(&mplayer);
00724 
00725         qDebug() << "QVMPlayerCamera::openCam(): waiting for initialization.";
00726         while(getRows() == 0 || getCols() == 0)
00727                 mplayerIOProcessor->interpretMPlayerOutput();
00728 
00729         qDebug() << "QVMPlayerCamera::openCam(): video dims (" << getCols() << "," << getRows() << ")";
00730         qDebug() << "QVMPlayerCamera::openCam(): fps " << getFPS();
00731 
00732         mplayerIOProcessor->queueCommandToMPlayer("get_time_length");
00733 
00734         if (open_options & QVMPlayerCamera::RGBMEncoder)
00735                 {
00736                 setImageBuffer(new QVImage<uChar,3>(getRows(), getCols(), 3*getCols()));
00737                 mplayerFrameGrabber = new QVMPlayerFrameGrabber(mplayerIOProcessor, &fifo_file_2, getRows(), getCols(), true, open_options & QVMPlayerCamera::RealTime);
00738                 }
00739         else    {
00740                 setImageBuffer(new QVImage<uChar,1>(getRows(), getCols(), getCols()));
00741                 mplayerFrameGrabber = new QVMPlayerFrameGrabber(mplayerIOProcessor, &fifo_file, getRows(), getCols(), false, open_options & QVMPlayerCamera::RealTime);
00742                 }
00743 
00744         connect(mplayerFrameGrabber,SIGNAL(newReadFrameGrabber()),this,SIGNAL(newRead()));
00745 
00746         // These signals are to defer the call to sendCommandToMplayer, and avoid
00747         // the "QSocketNotifier:: socket notifier cannot be enabled from another
00748         // thread" warning.
00749         connect(mplayerFrameGrabber,SIGNAL(sendCommandSignal()),mplayerIOProcessor,SLOT(sendCommandToMPlayer()));
00750         connect(this,SIGNAL(sendCommandSignal()),mplayerIOProcessor,SLOT(sendCommandToMPlayer()));
00751 
00752         setStatus(Running);
00753 
00754         qDebug() << "QVMPlayerCamera::openCam() <- return";
00755 
00756         emit camOpened();
00757 
00758         //grab();
00759 
00760         return TRUE;
00761         }
00762 
00763 // Close camera method:
00764 void QVMPlayerCamera::closeCam()
00765         {
00766         qDebug() << "QVMPlayerCamera::closeCam()";
00767 
00768         if (status == Closed)
00769                 {
00770                 qDebug() << "QVMPlayerCamera::closeCam(): camera already closed. Returning";
00771                 qDebug() << "QVMPlayerCamera::closeCam() <- return";
00772                 return;
00773                 }
00774 
00775         setStatus(Closed);
00776 
00777         emit camClosed();
00778 
00779         mplayerIOProcessor->queueCommandToMPlayer("quit");      
00780         // Avoid QSocketNotifier annoying message, by deferring call:
00781         emit sendCommandSignal(); // NOT mplayerIOProcessor->sendCommandToMPlayer();
00782 
00783         delete mplayerFrameGrabber;
00784         qDebug() << "QVMPlayerCamera::closeCam(): mplayerFrameGrabber deleted";
00785 
00786         delete mplayerIOProcessor;
00787         qDebug() << "QVMPlayerCamera::closeCam(): mplayerIOProcessor deleted";
00788 
00789         mplayer.terminate();
00790         while (not mplayer.waitForFinished(500)) mplayer.kill();
00791         qDebug() << "QVMPlayerCamera::closeCam(): mplayer terminated";
00792         
00793         if (open_options & QVMPlayerCamera::RGBMEncoder)
00794                 {
00795                 mencoder.terminate();
00796                 while (not mencoder.waitForFinished(500)) mencoder.kill();
00797                 }
00798 
00799         qDebug() << "QVMPlayerCamera::closeCam(): mencoder terminated";
00800         
00801         fifo_file.close();
00802         qDebug() << "QVMPlayerCamera::closeCam(): closed fifo_file";
00803         
00804         if(open_options & QVMPlayerCamera::RGBMEncoder)
00805                 fifo_file_2.close();
00806         qDebug() << "QVMPlayerCamera::closeCam(): closed fifo_file2";
00807         
00808         delete namedPipe;
00809         qDebug() << "mplayercamera2::closecam(): deleted namedpipe";
00810 
00811         if(open_options & QVMPlayerCamera::RGBMEncoder)
00812                 delete namedPipeAux;
00813         qDebug() << "QVMPlayerCamera::closeCam(): deleted namedPipeAux";
00814 
00815         qDebug() << "QVMPlayerCamera::closeCam() <- return";
00816         }
00817 
00818 bool QVMPlayerCamera::grab()
00819         {
00820         qDebug() << "QVMPlayerCamera::grab()";
00821 
00822         if(!performGrab())
00823                 return false;
00824 
00825         if (open_options & QVMPlayerCamera::RGBMEncoder)
00826                 {
00827                 QVImage<uChar,3> grabbedRGBImage;
00828                 mplayerFrameGrabber->getQVImageRGB(grabbedRGBImage);
00829                 setPropertyValue< QVImage<uChar,3> >("RGB image", grabbedRGBImage);
00830                 }
00831         else    {
00832                 QVImage<uChar> grabbedYImage, grabbedUImage, grabbedVImage;
00833                 mplayerFrameGrabber->getQVImageYUV(grabbedYImage, grabbedUImage, grabbedVImage);
00834 
00835                 setPropertyValue< QVImage<uChar,1> >("Y channel image", grabbedYImage);
00836                 setPropertyValue< QVImage<uChar,1> >("U channel image", grabbedUImage);
00837                 setPropertyValue< QVImage<uChar,1> >("V channel image", grabbedVImage);
00838                 }
00839 
00840         writeOutputProperties();
00841 
00842         qDebug() << "QVMPlayerCamera::grab() <~ return";
00843 
00844         return true;
00845         }
00846 
00847 bool QVMPlayerCamera::grab(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV)
00848         {
00849         qDebug() << "QVMPlayerCamera::grab(imageY, imageU, imageV)";
00850         //QVImage<uChar> grabbedYImage, grabbedUImage, grabbedVImage;
00851         //QVImage<uChar,3> grabbedRGBImage;
00852 
00853         bool newImages = performGrab();
00854 
00855         if (newImages)
00856                 mplayerFrameGrabber->getQVImageYUV(imgY, imgU, imgV);
00857 
00858         setPropertyValue< QVImage<uChar,1> >("Y channel image", imgY);
00859         setPropertyValue< QVImage<uChar,1> >("U channel image", imgU);
00860         setPropertyValue< QVImage<uChar,1> >("V channel image", imgV);
00861 
00862         /*imgY = grabbedYImage;
00863         imgU = grabbedUImage;
00864         imgV = grabbedVImage;*/
00865 
00866         qDebug() << "QVMPlayerCamera::grab() <~ return";
00867 
00868         return newImages;
00869         }
00870 
00871 bool QVMPlayerCamera::grab(QVImage<uChar,3> & imageRGB)
00872         {
00873         qDebug() << "QVMPlayerCamera::grab(imageRGB)";
00874         //QVImage<uChar> grabbedYImage, grabbedUImage, grabbedVImage;
00875         //QVImage<uChar,3> grabbedRGBImage;
00876         bool newImages = performGrab();
00877 
00878         if (newImages)
00879                 mplayerFrameGrabber->getQVImageRGB(imageRGB);
00880 
00881         setPropertyValue< QVImage<uChar,3> >("RGB image", imageRGB);
00882         //imageRGB = grabbedRGBImage;
00883         
00884         qDebug() << "QVMPlayerCamera::grab() <~ return";
00885         return newImages;
00886         }
00887 
00888 bool QVMPlayerCamera::grab(QVImage<uChar,1> & imageGray)
00889         {
00890         qDebug() << "QVMPlayerCamera::grab(imageGray)";
00891         //QVImage<uChar> grabbedYImage, grabbedUImage, grabbedVImage;
00892         //QVImage<uChar,3> grabbedRGBImage;
00893 
00894         bool newImages = performGrab();
00895 
00896         if (newImages)
00897                 mplayerFrameGrabber->getQVImageGray(imageGray);
00898 
00899         //imageGray = grabbedYImage;
00900         setPropertyValue< QVImage<uChar,1> >("Y channel image", imageGray);
00901 
00902         qDebug() << "QVMPlayerCamera::grab() <~ return";
00903         return newImages;
00904         }
00905 
00906 bool QVMPlayerCamera::performGrab()
00907         {
00908         // First, if there are any pending commands, we send them to mplayer:
00909         qDebug() << "QVMPlayerCamera::performGrab()";
00910 
00911         if (isClosed()) return false;
00912 
00913         qDebug() << "QVMPlayerCamera::performGrab(): status != Closed";
00914 
00915         bool newFrameGrabbed = false;
00916         // This is for when the camera is paused; it will return the same frames
00917         // over and over, but not immediately, but at a maximum fps rate (to avoid
00918         // intense CPU usage, that will slow the rest of the application and the
00919         // GUI.
00920 
00921         switch(status)
00922                 {
00923                 case RunningOneStep:
00924                         qDebug() << "QVMPlayerCamera::performGrab(): status == RunningOneStep";
00925                         setStatus(Paused);
00926                 case Running:
00927                         qDebug() << "QVMPlayerCamera::performGrab(): status == Running";
00928                         mplayerFrameGrabber->updateFrameBuffer();
00929                         frames_grabbed++;
00930                         newFrameGrabbed = true;
00931                         qDebug() << "QVMPlayerCamera::performGrab(): frames grabbed" << getFramesGrabbed();
00932                         break;
00933 
00934                 case Paused:
00935                         qDebug() << "QVMPlayerCamera::performGrab(): status == Paused";
00936                         /*
00937                         mutexJustToSleepMiliseconds.lock();
00938                         qDebug() << "QVMPlayerCamera::performGrab(): pausing" << milisecsToWait
00939                                 << "milisecs (video is "<< getFPS() <<" FPS's)";
00940                         conditionJustToSleepMiliseconds.wait(&mutexJustToSleepMiliseconds,milisecsToWait);
00941                         qDebug() << "QVMPlayerCamera::performGrab(): unlocking";
00942                         mutexJustToSleepMiliseconds.unlock(); */
00943                         break;
00944 
00945                 default:
00946                         break;
00947                 }
00948         qDebug() << "QVMPlayerCamera::performGrab(): checking finished";
00949 
00950         if (mplayerFrameGrabber->finished)
00951                 closeCam();
00952         else
00953                 emit newGrab();
00954 
00955         qDebug() << "QVMPlayerCamera::performGrab() <- return";
00956 
00957         return newFrameGrabbed;
00958         }
00959 
00960 // Pause, unpause, next frame, set speed, seek and close camer slots:
00961 // In all of them, the corresponding command is sent to the shared command queue
00962 // data structure, so access is accordingly protected .
00963 void QVMPlayerCamera::pauseCam()
00964         {
00965         qDebug() << "QVMPlayerCamera::pauseCam()";
00966         if(status == Closed) return;
00967         setStatus(Paused);
00968         qDebug() << "QVMPlayerCamera::pauseCam() <- return";
00969         }
00970 
00971 void QVMPlayerCamera::unpauseCam()
00972         {
00973         qDebug() << "QVMPlayerCamera::unpauseCam()";
00974         if(status == Closed) return;
00975         setStatus(Running);
00976         qDebug() << "QVMPlayerCamera::unpauseCam() <~ return";
00977         }
00978 
00979 void QVMPlayerCamera::nextFrameCam()
00980         {
00981         qDebug() << "QVMPlayerCamera::nextFrameCam()";
00982         if(status == Closed) return;
00983         setStatus(RunningOneStep);
00984         qDebug() << "QVMPlayerCamera::nextFrameCam() <~ return";
00985         }
00986 
00987 void QVMPlayerCamera::setSpeedCam(double d)
00988         {
00989         qDebug() << "QVMPlayerCamera::setSpeedCam()";
00990         if(status == Closed) return;
00991         mplayerIOProcessor->queueCommandToMPlayer(QString("pausing_keep speed_set ") + QString::number(d));
00992         mplayerIOProcessor->queueCommandToMPlayer("get_property speed");
00993         qDebug() << "QVMPlayerCamera::setSpeedCam() <~ return";
00994         }
00995 
00996 void QVMPlayerCamera::seekCam(TSeekType seek,double d)
00997         {
00998         qDebug() << "QVMPlayerCamera::seekCam()";
00999         if(status == Closed) return;
01000         if(status == Paused)
01001                 setStatus(RunningOneStep);
01002         QString command = QString("pausing_keep seek ") + QString::number(d) + " " + QString::number(seek);
01003         mplayerIOProcessor->queueCommandToMPlayer(command);
01004         qDebug() << "QVMPlayerCamera::seekCam() <~ return";
01005         }
01006 
01007 bool QVMPlayerCamera::link(QVWorker* worker, const QString imageName)
01008         {
01009         connect(worker, SIGNAL(startIteration()), this, SLOT(grab()), Qt::DirectConnection);
01010 
01011         if(worker->isType<QVImage<uChar,1> >(imageName))
01012                 return this->linkProperty("Y channel image",worker,imageName,AsynchronousLink);
01013         else if(worker->isType<QVImage<uChar,3> >(imageName))
01014                 {
01015                 rgbMode = true;
01016                 return this->linkProperty("RGB image",worker,imageName,AsynchronousLink);
01017                 }
01018         else
01019                 {
01020                 disconnect(worker, SIGNAL(startIteration()), this, SLOT(grab()));
01021                 std::cerr << "Warning: QVMPlayerCamera::link(): unsupported property type: property " << qPrintable(imageName)
01022                         << " in holder " << qPrintable(worker->getName()) << "is not a QVImage<uChar,1> or QVImage<uChar,3>" << std::endl;
01023                 return FALSE; //Should never get here;
01024                 }
01025         }
01026 
01027 bool QVMPlayerCamera::link(QVWorker* worker, const QString imageNameY, const QString imageNameU, const QString imageNameV)
01028         {
01029         if(!worker->isType< QVImage<uChar,1> >(imageNameY))
01030                 {
01031                 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameY) << "is not of type QVImage<uChar,1> in holder "
01032                         << qPrintable(worker->getName()) << std::endl;
01033                 return FALSE;
01034                 }
01035 
01036         if(!worker->isType< QVImage<uChar,1> >(imageNameU))
01037                 {
01038                 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameU) << "is not of type QVImage<uChar,1> in holder "
01039                         << qPrintable(worker->getName()) << std::endl;
01040                 return FALSE;
01041                 }
01042 
01043         if(!worker->isType< QVImage<uChar,1> >(imageNameV))
01044                 {
01045                 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameV) << "is not of type QVImage<uChar,1> in holder "
01046                         << qPrintable(worker->getName()) << std::endl;
01047                 return FALSE;
01048                 }
01049 
01050         connect(worker, SIGNAL(startIteration()), this, SLOT(grab()), Qt::DirectConnection);
01051         return  this->linkProperty("Y channel image", worker, imageNameY, AsynchronousLink) &&
01052                 this->linkProperty("U channel image", worker, imageNameU, AsynchronousLink) &&
01053                 this->linkProperty("V channel image", worker, imageNameV, AsynchronousLink);
01054         }
01055 

Generated on Thu Jul 17 17:23:27 2008 for QVision by  doxygen 1.5.3