00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 <qvipp.h>
00040
00041 #include <QVWorker>
00042 #include <QVMPlayerCamera>
00043
00044
00045 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)
00046 {
00047 qDebug() << "QVCheckOKMplayerCamera::QVCheckOKMplayerCamera()";
00048 qDebug() << "QVCheckOKMplayerCamera::QVCheckOKMplayerCamera() <- return";
00049 }
00050
00051 QVCheckOKMplayerCamera::~QVCheckOKMplayerCamera()
00052 {
00053 qDebug() << "QVCheckOKMplayerCamera::~QVCheckOKMplayerCamera()";
00054 quit();
00055 wait();
00056 qDebug() << "QVCheckOKMplayerCamera::~QVCheckOKMplayerCamera: thread finished";
00057 qDebug() << "QVCheckOKMplayerCamera::~QVCheckOKMplayerCamera() <- return";
00058 }
00059
00060 void QVCheckOKMplayerCamera::run()
00061 {
00062 qDebug() << "QVCheckOKMplayerCamera::run()";
00063 QTimer::singleShot(_max_time_ms_to_wait_for_open, this, SLOT(writeErrorInFifo()));
00064 qDebug() << "QVCheckOKMplayerCamera::run() <- entering event loop";
00065 exec();
00066 qDebug() << "QVCheckOKMplayerCamera::run() <- back from event loop";
00067 qDebug() << "QVCheckOKMplayerCamera::run() <- return";
00068 }
00069
00070
00071 void QVCheckOKMplayerCamera::writeErrorInFifo()
00072 {
00073 qDebug() << "QVCheckOKMplayerCamera::writeErrorInFifo()";
00074 _fifo_file.write("MPLAYER ERROR\n");
00075 qDebug() << "QVCheckOKMplayerCamera::writeErrorInFifo() -> return";
00076 };
00077
00078
00079 QVCameraThread::QVCameraThread(QObject *object,char *slot): QThread(), _object(object), _slot(slot)
00080 {
00081 qDebug() << "QVCameraThread::QVCameraThread()";
00082 _object->moveToThread(this);
00083 qDebug() << "QVCameraThread::QVCameraThread(): object moved to thread";
00084 qDebug() << "QVCameraThread::QVCameraThread() <- return";
00085 }
00086
00087 QVCameraThread::~QVCameraThread()
00088 {
00089 qDebug() << "QVCameraThread::~QVCameraThread()";
00090 disconnect();
00091 quit();
00092 qDebug() << "QVCameraThread::~QVCameraThread(): sent quit to thread";
00093 wait();
00094 qDebug() << "QVCameraThread::~QVCameraThread(): thread finished";
00095 qDebug() << "QVCameraThread::~QVCameraThread() <- return";
00096 }
00097
00098 void QVCameraThread::run()
00099 {
00100 qDebug() << "QVCameraThread::run()";
00101 QTimer *timer = new QTimer();
00102 timer->start(0);
00103 connect(timer, SIGNAL(timeout()),_object,_slot);
00104 qDebug() << "QVCameraThread::run(): timer created, started and connected";
00105 qDebug() << "QVCameraThread::run(): entering event processing loop";
00106 exec();
00107 qDebug() << "QVCameraThread::run(): back from event processing loop";
00108 delete timer;
00109 qDebug() << "QVCameraThread::run(): timer deleted";
00110 qDebug() << "QVCameraThread::run() <- return";
00111 }
00112
00113
00114 QVMPlayerIOProcessor::QVMPlayerIOProcessor(QProcess * mplayer): QObject(), command_queue(), command_queue_mutex()
00115 {
00116 qDebug() << "QVMPlayerIOProcessor::QVMPlayerIOProcessor()";
00117 rows = cols = 0;
00118 fps = time_length = time_pos = 0;
00119 speed = 1;
00120 this->mplayer = mplayer;
00121 mplayer->waitForReadyRead();
00122 qDebug() << "QVMPlayerIOProcessor::QVMPlayerIOProcessor() <- return";
00123 }
00124
00125 QVMPlayerIOProcessor::~QVMPlayerIOProcessor()
00126 {
00127 qDebug() << "QVMPlayerIOProcessor::~QVMPlayerIOProcessor()";
00128 qDebug() << "QVMPlayerIOProcessor::~QVMPlayerIOProcessor() <- return";
00129 }
00130
00131 void QVMPlayerIOProcessor::queueCommandToMPlayer(const QString &com_str, bool ifEmpty)
00132 {
00133 qDebug() << "QVMPlayerIOProcessor::queueCommand("<< com_str <<")";
00134 qDebug() << "QVMPlayerIOProcessor::queueCommand(): command_queue.size() = "
00135 << command_queue.size();
00136 command_queue_mutex.lock();
00137 if(!ifEmpty || command_queue.size()==0)
00138 command_queue << com_str + '\n';
00139 command_queue_mutex.unlock();
00140 qDebug() << "QVMPlayerIOProcessor::queueCommand() <- return";
00141 }
00142
00143 void QVMPlayerIOProcessor::sendCommandToMPlayer()
00144 {
00145 qDebug() << "QVMPlayerIOProcessor::sendCommandToMPlayer()";
00146 command_queue_mutex.lock();
00147 if (command_queue.size() > 0)
00148 {
00149 qDebug() << "QVMPlayerIOProcessor::sendCommandToMPlayer(): sending command:" << command_queue.head();
00150 mplayer->write(qPrintable(command_queue.dequeue()));
00151 }
00152 command_queue_mutex.unlock();
00153 qDebug() << "QVMPlayerIOProcessor::sendCommandToMPlayer(): wait for bytes written";
00154
00155 #ifdef unix
00156 mplayer->waitForBytesWritten();
00157 #endif
00158 qDebug() << "QVMPlayerIOProcessor::sendCommandToMPlayer() <- return";
00159 }
00160
00161 int QVMPlayerIOProcessor::interpretMPlayerOutput()
00162 {
00163 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput()";
00164 int length = -1;
00165 char buf[1024];
00166
00167 length = mplayer->readLine(buf, sizeof(buf));
00168
00169 if (length == -1)
00170 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): length == -1";
00171 else {
00172 QString str(buf);
00173 QStringList variables = str.simplified().split("=");
00174 QStringList palabras = str.simplified().split(" ");
00175
00176 if(variables[0] == "ANS_speed")
00177 {
00178 speed = variables[1].toDouble();
00179 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating speed =" << speed;
00180 }
00181 else if(variables[0] == "ANS_LENGTH")
00182 {
00183 time_length = variables[1].toDouble();
00184 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating time_length =" << time_length;
00185 }
00186 else if(variables[0] == "ANS_TIME_POSITION")
00187 {
00188 time_pos = variables[1].toDouble();
00189 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating time_pos =" << time_pos;
00190 }
00191 else if (palabras[0] == "VIDEO:")
00192 {
00193
00194 for (int i = 0; i < palabras.size(); ++i)
00195 if (palabras[i] == "fps")
00196 fps = palabras[i-1].toDouble();
00197
00198 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating fps" << fps;
00199 }
00200 else if (palabras[0] == "VO:")
00201 {
00202
00203 QStringList dimensiones = palabras[2].split("x");
00204 cols = dimensiones[0].toInt();
00205 rows = dimensiones[1].toInt();
00206 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating cols" << cols;
00207 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): updating rows" << rows;
00208 }
00209 else
00210 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput(): uninterpreted mplayer output:" << str;
00211 }
00212 qDebug() << "QVMPlayerIOProcessor::interpretMPlayerOutput() <- return" << length;
00213 return length;
00214 }
00215
00216
00217 QVMPlayerFrameGrabber::QVMPlayerFrameGrabber(QVMPlayerIOProcessor *mplayerIOProcessor, QFile *fifoInput, uInt rows, uInt cols, bool realTime): QObject()
00218 {
00219 qDebug() << "QVMPlayerFrameGrabber::QVMPlayerFrameGrabber(fifoInput," << mplayerIOProcessor->rows << "," << mplayerIOProcessor->cols
00220 << "," << realTime <<")";
00221
00222 this->mplayerIOProcessor = mplayerIOProcessor;
00223 this->fifoInput = fifoInput;
00224 this->realTime = realTime;
00225 this->finished = false;
00226 this->frames_read = 0;
00227
00228 debug_in_memcpy = debug_in_updateSlot = false;
00229
00230 imgY = QVImage<uChar>(cols, rows, cols);
00231 img_auxY = QVImage<uChar>(cols, rows, cols);
00232 img_auxU = QVImage<uChar>(cols/2, rows/2, cols/2);
00233 img_auxV = QVImage<uChar>(cols/2, rows/2, cols/2);
00234
00235 buf_size = rows*cols + rows*cols/4 + rows*cols/4;
00236
00237 if (realTime)
00238 {
00239 qvcamerathread = new QVCameraThread(this,SLOT(updateSlot()));
00240 qvcamerathread->start(QThread::NormalPriority);
00241 }
00242
00243 qDebug() << "QVMPlayerFrameGrabber::QVMPlayerFrameGrabber() <- return";
00244 };
00245
00246 QVMPlayerFrameGrabber::~QVMPlayerFrameGrabber()
00247 {
00248 qDebug() << "QVMPlayerFrameGrabber::~QVMPlayerFrameGrabber()";
00249 finished = true;
00250 if (realTime) delete qvcamerathread;
00251 qDebug() << "QVMPlayerFrameGrabber::~QVMPlayerFrameGrabber(): thread deleted.";
00252 qDebug() << "QVMPlayerFrameGrabber::~QVMPlayerFrameGrabber() <- return";
00253 }
00254
00255 void QVMPlayerFrameGrabber::getNewFrame(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV)
00256 {
00257 qDebug() << "QVMPlayerFrameGrabber::getNewFrame(): reading YUV header";
00258 char buf[1024];
00259 fifoInput->readLine(buf, sizeof(buf));
00260 readToBuffer(imgY.getWriteData(), 2*buf_size/3);
00261 readToBuffer(imgU.getWriteData(), buf_size/6);
00262 readToBuffer(imgV.getWriteData(), buf_size/6);
00263 qDebug() << "QVMPlayerFrameGrabber::getNewFrame() <- return";
00264 }
00265
00266 void QVMPlayerFrameGrabber::updateSlot()
00267 {
00268 qDebug() << "QVMPlayerFrameGrabber::updateSlot()";
00269
00270 qDebug() << "QVMPlayerFrameGrabber::updateSlot(): sent command to mplayer: get_time_pos";
00271 mplayerIOProcessor->queueCommandToMPlayer("pausing_keep get_time_pos\n",true);
00272
00273
00274 emit sendCommandSignal();
00275
00276
00277 qDebug() << "QVMPlayerFrameGrabber::updateSlot(): reading frame";
00278 QVImage<uChar, 1> tempY;
00279 QVImage<uChar, 1> tempU;
00280 QVImage<uChar, 1> tempV;
00281
00282
00283
00284
00285 getNewFrame(tempY = img_auxY, tempU = img_auxU, tempV = img_auxV);
00286
00287
00288
00289 if(realTime)
00290 {
00291 mutex.lock();
00292 debug_in_updateSlot = true;
00293 if (debug_in_memcpy)
00294 {
00295 std::cerr << "(BUG1) entered frameUpdate while memcpying!";
00296 exit(0);
00297 }
00298 }
00299
00300 img_auxY = tempY;
00301 img_auxU = tempU;
00302 img_auxV = tempV;
00303
00304
00305 if(realTime)
00306 {
00307 if (debug_in_memcpy) {
00308 std::cerr << "(BUG2) entered frameUpdate while memcpying!";
00309 exit(0);
00310 }
00311 debug_in_updateSlot = false;
00312 condition.wakeAll();
00313 mutex.unlock();
00314 }
00315
00316 qDebug() << "QVMPlayerFrameGrabber::updateSlot(): finished" << finished;
00317 frames_read++;
00318 qDebug() << "QVMPlayerFrameGrabber::updateSlot(): frames read" << frames_read;
00319
00320 mplayerIOProcessor->interpretMPlayerOutput();
00321
00322 qDebug() << "QVMPlayerFrameGrabber::updateSlot() <- return";
00323
00324 emit newReadFrameGrabber();
00325 }
00326
00327 void QVMPlayerFrameGrabber::updateFrameBuffer()
00328 {
00329 qDebug() << "QVMPlayerFrameGrabber::updateFrameBuffer()";
00330
00331
00332
00333
00334
00335
00336
00337 mutex.lock();
00338 if (debug_in_updateSlot)
00339 {
00340 std::cerr << "(BUG3) entered memcpy while frameUpdating!";
00341 exit(0);
00342 }
00343
00344 if(realTime)
00345 condition.wait(&mutex);
00346 debug_in_memcpy = true;
00347
00348
00349
00350 if(not realTime)
00351 updateSlot();
00352
00353 imgY = img_auxY;
00354 imgU = img_auxU;
00355 imgV = img_auxV;
00356
00357
00358 if (debug_in_updateSlot)
00359 {
00360 std::cerr << "(BUG4) entered memcpy while frameUpdating!";
00361 exit(0);
00362 }
00363 debug_in_memcpy = false;
00364 mutex.unlock();
00365
00366 qDebug() << "QVMPlayerFrameGrabber::updateFrameBuffer() <- return";
00367 }
00368
00369 void QVMPlayerFrameGrabber::getQVImageYUV(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV) const
00370 {
00371 qDebug() << "QVMPlayerFrameGrabber::getQVImageYUV()";
00372 imgY = this->imgY;
00373 imgU = this->imgU;
00374 imgV = this->imgV;
00375 qDebug() << "QVMPlayerFrameGrabber::getQVImageYUV() <- return";
00376 }
00377
00378 void QVMPlayerFrameGrabber::getQVImageGray(QVImage<uChar> &imgGray) const
00379 {
00380 qDebug() << "QVMPlayerFrameGrabber::getQVImageYUV()";
00381 imgGray = imgY;
00382 qDebug() << "QVMPlayerFrameGrabber::getQVImageYUV() <- return";
00383 }
00384
00385 void QVMPlayerFrameGrabber::readToBuffer(uChar *buf_img_aux, uInt buf_size)
00386 {
00387 uInt totbytes = 0;
00388 while (totbytes != buf_size and not finished)
00389 {
00390 int nbytes = fifoInput->read((char *)(buf_img_aux+totbytes), buf_size-totbytes);
00391
00392 totbytes += nbytes;
00393 qDebug() << "QVMPlayerFrameGrabber::readNewFrame(): read" << nbytes << "bytes";
00394
00395 if(nbytes == 0)
00396 {
00397 finished = TRUE;
00398 qDebug() << "QVMPlayerFrameGrabber::readNewFrame(): read 0 bytes, finishing" << finished;
00399 break;
00400 }
00401
00402 if(nbytes == -1)
00403 {
00404
00405
00406 finished = TRUE;
00407 qDebug() << "QVMPlayerFrameGrabber::readNewFrame(): error -" << fifoInput->errorString();
00408 break;
00409 }
00410 }
00411 }
00412
00413
00414 QVMPlayerCamera::QVMPlayerCamera(QString name):QVCamera(name), open_options(Default)
00415 {
00416 qDebug() << "QVMPlayerCamera::QVMPlayerCamera()";
00417 if (qvApp == NULL)
00418 {
00419 QString str = "QVWorker::QVWorker(): the QVWorker cannot be created before the QVApplication instance. Aborting now.";
00420 std::cerr << qPrintable(str) << std::endl;
00421 exit(1);
00422 }
00423
00424 frames_grabbed = 0;
00425 rgbMode = false;
00426 setStatus(Closed);
00427 live_camera = FALSE;
00428
00429
00430 addProperty<int>("Rows", inputFlag, 0, "Rows to open the camera");
00431 addProperty<int>("Cols", inputFlag, 0, "Columns to open the camera");
00432 addProperty<bool>("RealTime", inputFlag, FALSE,"If the camera should be opened in real time mode");
00433 addProperty<bool>("Deinterlaced", inputFlag, FALSE,"If the camera should be opened in deinterlaced mode");
00434 addProperty<bool>("NoLoop", inputFlag, FALSE,"If the camera should be opened in no loop mode");
00435 addProperty<bool>("RGBMEncoder", inputFlag, FALSE,"If the camera should be opened in RGB using mencoder");
00436 addProperty<QString>("URL", inputFlag, QString(""),"URL of the video source");
00437
00438
00439
00440 addProperty< QVImage<uChar,3> >("RGB image", outputFlag, QVImage<uChar,3>(), "Last grabbed RGB image");
00441 addProperty< QVImage<uChar,1> >("Y channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed Y channel image");
00442 addProperty< QVImage<uChar,1> >("U channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed U channel image");
00443 addProperty< QVImage<uChar,1> >("V channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed V channel image");
00444
00445 qDebug() << "QVMPlayerCamera::QVMPlayerCamera() <- return";
00446 }
00447
00448 QVMPlayerCamera::~QVMPlayerCamera()
00449 {
00450 qDebug() << "QVMPlayerCamera::~QVMPlayerCamera()";
00451 if (status != Closed) closeCam();
00452 qDebug() << "QVMPlayerCamera::~QVMPlayerCamera() <- deleting image";
00453 setImageBuffer(NULL);
00454 qDebug() << "QVMPlayerCamera::~QVMPlayerCamera() <- return";
00455 }
00456
00457 void QVMPlayerCamera::initMPlayerArgs(QString urlString, uInt rows, uInt cols)
00458 {
00459 qDebug() << "QVMPlayerCamera::initMPlayerArgs()";
00460 qDebug() << "QVMPlayerCamera::initMPlayerArgs(): url string =" << urlString;
00461
00462
00463 if(not (open_options & NoLoop)) mplayer_args << "-loop" << "0";
00464
00465 mplayer_args << "-fixed-vo";
00466
00467 QUrl url(urlString);
00468
00469 if (url.host() != "")
00470 path = url.host() + "/";
00471
00472 path += url.path();
00473
00474 qDebug() << "QVMPlayerCamera::initMPlayerArgs(): path" << path;
00475
00476
00477
00478
00479 if (url.scheme() != "")
00480 schema = url.scheme();
00481 else if (urlString.startsWith("/dev/video"))
00482 schema = "v4l";
00483 else if (urlString.startsWith("/dev/dv"))
00484 schema = "dv";
00485 else if (urlString.contains("*"))
00486 schema = "mf";
00487 else if (urlString.startsWith("www."))
00488 schema = "http";
00489 else if (urlString.startsWith("ftp."))
00490 schema = "ftp";
00491
00492 qDebug() << "QVMPlayerCamera::initMPlayerArgs(): scheme" << schema;
00493
00494 live_camera = TRUE;
00495
00496
00497 if ((schema == "v4l") or (schema == "v4l2") or (schema == "analog"))
00498 {
00499
00500 QString urlQueryValues = QString("driver=%1:device=%2").arg(schema).arg(path);
00501
00502 QList<QPair<QString, QString> > queryItems = url.queryItems();
00503 for (int i = 0; i < queryItems.size(); ++i)
00504 urlQueryValues += ":" + queryItems.at(i).first + "=" + queryItems.at(i).second;
00505
00506 mplayer_args << "tv://" << "-tv" << urlQueryValues;
00507 }
00508 else if (schema == "dv")
00509
00510 mplayer_args << path << "-demuxer" << "rawdv" << "-cache" << "400";
00511 else if (schema == "iidc")
00512
00513
00514 qFatal("Currently this driver does not work (apparently with\n"
00515 "vloopback writing and then reading from a fifo with mplayer\ndoes not work).\n");
00516 else if (schema == "tv")
00517
00518 qFatal("tv URL: Still not implemented\n");
00519 else if (schema == "dvb")
00520
00521 qFatal("dvb URL: Still not implemented\n");
00522 else
00523 {
00524
00525 live_camera = FALSE;
00526 if (schema != "")
00527 mplayer_args << QString(schema + "://" + path);
00528 else
00529 mplayer_args << path;
00530 }
00531
00532
00533
00534 QString aux;
00535
00536
00537 if(open_options & Deinterlaced) aux = "pp=md";
00538
00539 if(rows != 0 or cols != 0)
00540 {
00541 if(aux != QString())
00542 aux += QString(",scale=%1:%2").arg(cols).arg(rows);
00543 else
00544 aux = QString("scale=%1:%2").arg(cols).arg(rows);
00545 }
00546
00547 if (aux != QString()) mplayer_args << "-vf" << aux;
00548
00549
00550 if(not (open_options & RealTime))
00551 {
00552 if(not live_camera)
00553 mplayer_args << "-benchmark";
00554 else
00555
00556
00557 qWarning("Warning: opening live cameras in continuous mode "
00558 "wastes less CPU time, but it is prone to delays in "
00559 "the pipe of images if your process is slower than "
00560 "the camera.");
00561 }
00562
00563
00564 mplayer_args << "-slave" << "-quiet" << "-nosound" << "-vo" << QString("yuv4mpeg:file=%1").arg(namedPipe->getInputFilePath());
00565
00566 qDebug() << "QVMPlayerCamera::initMPlayerArgs() <- return";
00567 }
00568
00569
00570
00571 bool QVMPlayerCamera::openCam()
00572 {
00573 OpenOptions optsProp = Default;
00574
00575 readInputProperties();
00576
00577 if (getPropertyValue<bool>("RealTime")) optsProp |= RealTime;
00578 if (getPropertyValue<bool>("Deinterlaced")) optsProp |= Deinterlaced;
00579 if (getPropertyValue<bool>("NoLoop")) optsProp |= NoLoop;
00580 if (rgbMode) optsProp |= RGBMEncoder;
00581
00582 return openCam(getPropertyValue<QString>("URL"), getPropertyValue<int>("Rows"), getPropertyValue<int>("Cols"), optsProp);
00583 }
00584
00585
00586 bool QVMPlayerCamera::openCam(const QString & urlstring,OpenOptions opts)
00587 { return openCam(urlstring,0,0,opts); }
00588
00589
00590 bool QVMPlayerCamera::openCam(const QString & urlstring, uInt rows, uInt cols, OpenOptions opts)
00591 {
00592 qDebug() << "QVMPlayerCamera::openCam(" << urlstring << "," << rows << "," << cols << "," << opts << ")";
00593
00594 setStatus(Closed);
00595
00596 open_options = opts;
00597
00598
00599 namedPipe = new QNamedPipe(QString("mplayer"));
00600 fifo_file.setFileName(namedPipe->getOutputFilePath());
00601
00602 initMPlayerArgs(urlstring, rows, cols);
00603
00604 qDebug() << "QVMPlayerCamera::openCam(): MPlayer args ->" << mplayer_args;
00605 mplayer.start(MPLAYER_BINARY_PATH,mplayer_args);
00606 qDebug() << "QVMPlayerCamera::openCam(): after mplayer.start()";
00607 if(not mplayer.waitForStarted(1000))
00608 qFatal("Mplayer failed to start: Are you sure it is installed and in the correct PATH?");
00609 qDebug() << "QVMPlayerCamera::openCam(): after mplayer.waitForstarted()";
00610
00611
00612
00613
00614
00615
00616
00617 QVCheckOKMplayerCamera *check_thread;
00618 if (schema == "http" or schema == "ftp" or schema == "rtsp" or schema == "dvd" or schema == "vcd")
00619 check_thread = new QVCheckOKMplayerCamera(fifo_file, 10000);
00620 else
00621 check_thread = new QVCheckOKMplayerCamera(fifo_file, 2000);
00622
00623 check_thread->moveToThread(check_thread);
00624 check_thread->start();
00625 qDebug() << "QVMPlayerCamera::openCam(): after starting QVCheckOKMplayerCamera thread";
00626
00627
00628
00629
00630 qDebug() << "QVMPlayerCamera::openCam(): opening fifo_file";
00631 if((fifo_file.open(QIODevice::ReadWrite|QIODevice::Unbuffered)) == -1)
00632 qFatal("Error opening fifo %s\n", qPrintable(namedPipe->getPipeName()));
00633 qDebug() << "QVMPlayerCamera::openCam(): reading fifo_file";
00634
00635
00636 char buf[1024];
00637 int len;
00638 if ((len = fifo_file.readLine(buf, sizeof(buf))) == -1) return FALSE;
00639 if (QString(buf) == QString("MPLAYER ERROR\n")) {
00640 std::cerr << "QVMPlayerCamera::openCam(): Warning: Mplayer could not open the requested video source (" << qPrintable(urlstring) << ") of type " << qPrintable(schema) <<std::endl;
00641 check_thread->quit();
00642 check_thread->wait();
00643 delete check_thread;
00644
00645
00646 mplayer.terminate();
00647 if (not mplayer.waitForFinished(500)) mplayer.kill();
00648 fifo_file.close();
00649 delete namedPipe;
00650
00651 qDebug() << "QVMPlayerCamera::openCam(): QVCheckOKMplayerCamera thread deleted after detecting an error; returning FALSE";
00652 return FALSE;
00653 }
00654
00655 check_thread->quit();
00656 check_thread->wait();
00657
00658 delete check_thread;
00659 qDebug() << "QVMPlayerCamera::openCam(): QVCheckOKMplayerCamera thread deleted after correct launch of mplayer";
00660
00661 qDebug() << "QVMPlayerCamera::openCam(): going to create QVMPlayerIOProcessor...";
00662 mplayerIOProcessor = new QVMPlayerIOProcessor(&mplayer);
00663
00664 qDebug() << "QVMPlayerCamera::openCam(): waiting for initialization.";
00665 while(getRows() == 0 || getCols() == 0)
00666 mplayerIOProcessor->interpretMPlayerOutput();
00667
00668 qDebug() << "QVMPlayerCamera::openCam(): video dims (" << getCols() << "," << getRows() << ")";
00669 qDebug() << "QVMPlayerCamera::openCam(): fps " << getFPS();
00670
00671 mplayerIOProcessor->queueCommandToMPlayer("get_time_length");
00672
00673 setImageBuffer(new QVImage<uChar,1>(getRows(), getCols(), getCols()));
00674 mplayerFrameGrabber = new QVMPlayerFrameGrabber(mplayerIOProcessor, &fifo_file, getRows(), getCols(), open_options & QVMPlayerCamera::RealTime);
00675
00676 connect(mplayerFrameGrabber,SIGNAL(newReadFrameGrabber()),this,SIGNAL(newRead()));
00677
00678
00679
00680
00681 connect(mplayerFrameGrabber,SIGNAL(sendCommandSignal()),mplayerIOProcessor,SLOT(sendCommandToMPlayer()));
00682 connect(this,SIGNAL(sendCommandSignal()),mplayerIOProcessor,SLOT(sendCommandToMPlayer()));
00683
00684 setStatus(Running);
00685
00686 qDebug() << "QVMPlayerCamera::openCam() <- return";
00687
00688 emit camOpened();
00689
00690
00691
00692 return TRUE;
00693 }
00694
00695
00696 void QVMPlayerCamera::closeCam()
00697 {
00698 qDebug() << "QVMPlayerCamera::closeCam()";
00699
00700 if (status == Closed)
00701 {
00702 qDebug() << "QVMPlayerCamera::closeCam(): camera already closed. Returning";
00703 qDebug() << "QVMPlayerCamera::closeCam() <- return";
00704 return;
00705 }
00706
00707 setStatus(Closed);
00708
00709 emit camClosed();
00710
00711 mplayerIOProcessor->queueCommandToMPlayer("quit");
00712
00713 emit sendCommandSignal();
00714
00715 delete mplayerFrameGrabber;
00716 qDebug() << "QVMPlayerCamera::closeCam(): mplayerFrameGrabber deleted";
00717
00718 delete mplayerIOProcessor;
00719 qDebug() << "QVMPlayerCamera::closeCam(): mplayerIOProcessor deleted";
00720
00721 mplayer.terminate();
00722 while (not mplayer.waitForFinished(500)) mplayer.kill();
00723 qDebug() << "QVMPlayerCamera::closeCam(): mplayer terminated";
00724
00725 fifo_file.close();
00726 qDebug() << "QVMPlayerCamera::closeCam(): closed fifo_file";
00727
00728 delete namedPipe;
00729 qDebug() << "QVMPlayerCamera::closecam(): deleted namedpipe";
00730
00731 qDebug() << "QVMPlayerCamera::closeCam() <- return";
00732 }
00733
00734 bool QVMPlayerCamera::grab()
00735 {
00736 qDebug() << "QVMPlayerCamera::grab()";
00737
00738 if(!performGrab())
00739 return false;
00740
00741 QVImage<uChar> grabbedYImage, grabbedUImage, grabbedVImage;
00742 mplayerFrameGrabber->getQVImageYUV(grabbedYImage, grabbedUImage, grabbedVImage);
00743
00744 setPropertyValue< QVImage<uChar,1> >("Y channel image", grabbedYImage);
00745 setPropertyValue< QVImage<uChar,1> >("U channel image", grabbedUImage);
00746 setPropertyValue< QVImage<uChar,1> >("V channel image", grabbedVImage);
00747
00748 if (open_options & QVMPlayerCamera::RGBMEncoder)
00749 {
00750 QVImage<uChar,3> grabbedRGBImage(grabbedYImage.getCols(),grabbedYImage.getRows());
00751 YUV420ToRGB(grabbedYImage, grabbedUImage, grabbedVImage, grabbedRGBImage);
00752 setPropertyValue< QVImage<uChar,3> >("RGB image", grabbedRGBImage);
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762 writeOutputProperties();
00763
00764 qDebug() << "QVMPlayerCamera::grab() <~ return";
00765
00766 return true;
00767 }
00768
00769 bool QVMPlayerCamera::grab(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV)
00770 {
00771 qDebug() << "QVMPlayerCamera::grab(imageY, imageU, imageV)";
00772
00773 bool newImages = performGrab();
00774
00775 if (newImages)
00776 mplayerFrameGrabber->getQVImageYUV(imgY, imgU, imgV);
00777
00778 setPropertyValue< QVImage<uChar,1> >("Y channel image", imgY);
00779 setPropertyValue< QVImage<uChar,1> >("U channel image", imgU);
00780 setPropertyValue< QVImage<uChar,1> >("V channel image", imgV);
00781
00782 qDebug() << "QVMPlayerCamera::grab() <~ return";
00783
00784 return newImages;
00785 }
00786
00787 bool QVMPlayerCamera::grab(QVImage<uChar,3> & imageRGB)
00788 {
00789 qDebug() << "QVMPlayerCamera::grab(imageRGB)";
00790 bool newImages = performGrab();
00791
00792 QVImage<uChar> grabbedYImage, grabbedUImage, grabbedVImage;
00793
00794 if (newImages)
00795 {
00796 mplayerFrameGrabber->getQVImageYUV(grabbedYImage, grabbedUImage, grabbedVImage);
00797
00798 imageRGB = QVImage<uChar,3>(grabbedYImage.getCols(),grabbedYImage.getRows());
00799 YUV420ToRGB(grabbedYImage, grabbedUImage, grabbedVImage, imageRGB);
00800 }
00801
00802 setPropertyValue< QVImage<uChar,3> >("RGB image", imageRGB);
00803
00804 qDebug() << "QVMPlayerCamera::grab() <~ return";
00805 return newImages;
00806 }
00807
00808 bool QVMPlayerCamera::grab(QVImage<uChar,1> & imageGray)
00809 {
00810 qDebug() << "QVMPlayerCamera::grab(imageGray)";
00811
00812 bool newImages = performGrab();
00813
00814 if (newImages)
00815 mplayerFrameGrabber->getQVImageGray(imageGray);
00816
00817 setPropertyValue< QVImage<uChar,1> >("Y channel image", imageGray);
00818
00819 qDebug() << "QVMPlayerCamera::grab() <~ return";
00820 return newImages;
00821 }
00822
00823 bool QVMPlayerCamera::performGrab()
00824 {
00825
00826 qDebug() << "QVMPlayerCamera::performGrab()";
00827
00828 if (isClosed()) return false;
00829
00830 qDebug() << "QVMPlayerCamera::performGrab(): status != Closed";
00831
00832 bool newFrameGrabbed = false;
00833
00834
00835
00836
00837
00838 switch(status)
00839 {
00840 case RunningOneStep:
00841 qDebug() << "QVMPlayerCamera::performGrab(): status == RunningOneStep";
00842 setStatus(Paused);
00843 case Running:
00844 qDebug() << "QVMPlayerCamera::performGrab(): status == Running";
00845 mplayerFrameGrabber->updateFrameBuffer();
00846 frames_grabbed++;
00847 newFrameGrabbed = true;
00848 qDebug() << "QVMPlayerCamera::performGrab(): frames grabbed" << getFramesGrabbed();
00849 break;
00850
00851 case Paused:
00852 qDebug() << "QVMPlayerCamera::performGrab(): status == Paused";
00853
00854
00855
00856
00857
00858
00859
00860 break;
00861
00862 default:
00863 break;
00864 }
00865 qDebug() << "QVMPlayerCamera::performGrab(): checking finished";
00866
00867 if (mplayerFrameGrabber->finished)
00868 closeCam();
00869 else
00870 emit newGrab();
00871
00872 qDebug() << "QVMPlayerCamera::performGrab() <- return";
00873
00874 return newFrameGrabbed;
00875 }
00876
00877
00878
00879
00880 void QVMPlayerCamera::pauseCam()
00881 {
00882 qDebug() << "QVMPlayerCamera::pauseCam()";
00883 if(status == Closed) return;
00884 setStatus(Paused);
00885 qDebug() << "QVMPlayerCamera::pauseCam() <- return";
00886 }
00887
00888 void QVMPlayerCamera::unpauseCam()
00889 {
00890 qDebug() << "QVMPlayerCamera::unpauseCam()";
00891 if(status == Closed) return;
00892 setStatus(Running);
00893 qDebug() << "QVMPlayerCamera::unpauseCam() <~ return";
00894 }
00895
00896 void QVMPlayerCamera::nextFrameCam()
00897 {
00898 qDebug() << "QVMPlayerCamera::nextFrameCam()";
00899 if(status == Closed) return;
00900 setStatus(RunningOneStep);
00901 qDebug() << "QVMPlayerCamera::nextFrameCam() <~ return";
00902 }
00903
00904 void QVMPlayerCamera::setSpeedCam(double d)
00905 {
00906 qDebug() << "QVMPlayerCamera::setSpeedCam()";
00907 if(status == Closed) return;
00908 mplayerIOProcessor->queueCommandToMPlayer(QString("pausing_keep speed_set ") + QString::number(d));
00909 mplayerIOProcessor->queueCommandToMPlayer("get_property speed");
00910 qDebug() << "QVMPlayerCamera::setSpeedCam() <~ return";
00911 }
00912
00913 void QVMPlayerCamera::seekCam(TSeekType seek,double d)
00914 {
00915 qDebug() << "QVMPlayerCamera::seekCam()";
00916 if(status == Closed) return;
00917 if(status == Paused)
00918 setStatus(RunningOneStep);
00919 QString command = QString("pausing_keep seek ") + QString::number(d) + " " + QString::number(seek);
00920 mplayerIOProcessor->queueCommandToMPlayer(command);
00921 qDebug() << "QVMPlayerCamera::seekCam() <~ return";
00922 }
00923
00924 bool QVMPlayerCamera::link(QVWorker* worker, const QString imageName)
00925 {
00926 if(worker->isType<QVImage<uChar,1> >(imageName))
00927 {
00928 connect(worker, SIGNAL(startIteration()), this, SLOT(grab()), Qt::DirectConnection);
00929 return this->linkProperty("Y channel image", worker, imageName, AsynchronousLink);
00930 }
00931 else if(worker->isType<QVImage<uChar,3> >(imageName))
00932 {
00933 rgbMode = true;
00934 connect(worker, SIGNAL(startIteration()), this, SLOT(grab()), Qt::DirectConnection);
00935 return this->linkProperty("RGB image", worker, imageName, AsynchronousLink);
00936 }
00937 else
00938 {
00939 std::cerr << "Warning: QVMPlayerCamera::link(): unsupported property type: property " << qPrintable(imageName)
00940 << " in holder " << qPrintable(worker->getName()) << "is not a QVImage<uChar,1> or QVImage<uChar,3>" << std::endl;
00941 return FALSE;
00942 }
00943 }
00944
00945 bool QVMPlayerCamera::link(QVWorker* worker, const QString imageNameY, const QString imageNameU, const QString imageNameV)
00946 {
00947 if(!worker->isType< QVImage<uChar,1> >(imageNameY))
00948 {
00949 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameY) << "is not of type QVImage<uChar,1> in holder "
00950 << qPrintable(worker->getName()) << std::endl;
00951 return FALSE;
00952 }
00953
00954 if(!worker->isType< QVImage<uChar,1> >(imageNameU))
00955 {
00956 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameU) << "is not of type QVImage<uChar,1> in holder "
00957 << qPrintable(worker->getName()) << std::endl;
00958 return FALSE;
00959 }
00960
00961 if(!worker->isType< QVImage<uChar,1> >(imageNameV))
00962 {
00963 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameV) << "is not of type QVImage<uChar,1> in holder "
00964 << qPrintable(worker->getName()) << std::endl;
00965 return FALSE;
00966 }
00967
00968 connect(worker, SIGNAL(startIteration()), this, SLOT(grab()), Qt::DirectConnection);
00969 return this->linkProperty("Y channel image", worker, imageNameY, AsynchronousLink) &&
00970 this->linkProperty("U channel image", worker, imageNameU, AsynchronousLink) &&
00971 this->linkProperty("V channel image", worker, imageNameV, AsynchronousLink);
00972 }
00973
00974 bool QVMPlayerCamera::unlink(QVWorker* worker, const QString imageName)
00975 {
00976 disconnect(worker, SIGNAL(startIteration()), this, SLOT(grab()));
00977
00978 if (rgbMode) {
00979 return unlinkProperty("RGB image", worker, imageName);
00980 }
00981 else {
00982 return unlinkProperty("Y channel image", worker, imageName);
00983 }
00984 }
00985