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 <qvcore/qvworker.h>
00040 #include <qvcameras/qvmplayercamera.h>
00041
00042
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
00077
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
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
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
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
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
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
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
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
00287 emit sendCommandSignal();
00288
00289
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
00297
00298
00299 if (isYUV)
00300 getNewFrame(tempY = img_auxY, tempU = img_auxU, tempV = img_auxV);
00301 else
00302 getNewFrame(tempRGB = img_auxRGB);
00303
00304
00305
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
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();
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
00354
00355
00356
00357
00358
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);
00368 debug_in_memcpy = true;
00369
00370
00371
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
00438
00439 finished = TRUE;
00440 qDebug() << "QVMPlayerFrameGrabber::readNewFrame(): error -" << fifoInput->errorString();
00441 break;
00442 }
00443 }
00444 }
00445
00446
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
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
00471
00472
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
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
00510
00511
00512 if (url.scheme() != "")
00513 schema = url.scheme();
00514 else if (urlString.startsWith("/dev/video"))
00515 schema = "v4l";
00516 else if (urlString.startsWith("/dev/dv"))
00517 schema = "dv";
00518 else if (urlString.contains("*"))
00519 schema = "mf";
00520 else if (urlString.startsWith("www."))
00521 schema = "http";
00522 else if (urlString.startsWith("ftp."))
00523 schema = "ftp";
00524
00525 qDebug() << "QVMPlayerCamera::initMPlayerArgs(): scheme" << schema;
00526
00527 live_camera = TRUE;
00528
00529
00530 if ((schema == "v4l") or (schema == "v4l2") or (schema == "analog"))
00531 {
00532
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
00543 mplayer_args << path << "-demuxer" << "rawdv" << "-cache" << "400";
00544 else if (schema == "iidc")
00545
00546
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
00551 qFatal("tv URL: Still not implemented\n");
00552 else if (schema == "dvb")
00553
00554 qFatal("dvb URL: Still not implemented\n");
00555 else
00556 {
00557
00558 live_camera = FALSE;
00559 if (schema != "")
00560 mplayer_args << QString(schema + "://" + path);
00561 else
00562 mplayer_args << path;
00563 }
00564
00565
00566
00567 QString aux;
00568
00569
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
00583 if(not (open_options & RealTime))
00584 {
00585 if(not live_camera)
00586 mplayer_args << "-benchmark";
00587 else
00588
00589
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
00597 mplayer_args << "-slave" << "-quiet" << "-nosound" << "-vo" << QString("yuv4mpeg:file=%1").arg(namedPipe->getInputFilePath());
00598
00599
00600
00601
00602
00603
00604
00605
00606 qDebug() << "QVMPlayerCamera::initMPlayerArgs() <- return";
00607 }
00608
00609
00610
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
00624 bool QVMPlayerCamera::openCam(const QString & urlstring,OpenOptions opts)
00625 { return openCam(urlstring,0,0,opts); }
00626
00627
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
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
00656
00657
00658
00659
00660
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
00672
00673
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
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
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
00702
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
00747
00748
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
00759
00760 return TRUE;
00761 }
00762
00763
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
00781 emit sendCommandSignal();
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
00851
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
00863
00864
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
00875
00876 bool newImages = performGrab();
00877
00878 if (newImages)
00879 mplayerFrameGrabber->getQVImageRGB(imageRGB);
00880
00881 setPropertyValue< QVImage<uChar,3> >("RGB image", imageRGB);
00882
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
00892
00893
00894 bool newImages = performGrab();
00895
00896 if (newImages)
00897 mplayerFrameGrabber->getQVImageGray(imageGray);
00898
00899
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
00909 qDebug() << "QVMPlayerCamera::performGrab()";
00910
00911 if (isClosed()) return false;
00912
00913 qDebug() << "QVMPlayerCamera::performGrab(): status != Closed";
00914
00915 bool newFrameGrabbed = false;
00916
00917
00918
00919
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
00938
00939
00940
00941
00942
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
00961
00962
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;
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