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 frames_grabbed = 0;
00451 rgbMode = false;
00452 setStatus(Closed);
00453 live_camera = FALSE;
00454
00455
00456 addProperty<int>("Rows", inputFlag, 0, "Rows to open the camera");
00457 addProperty<int>("Cols", inputFlag, 0, "Columns to open the camera");
00458 addProperty<bool>("RealTime", inputFlag, FALSE,"If the camera should be opened in real time mode");
00459 addProperty<bool>("Deinterlaced", inputFlag, FALSE,"If the camera should be opened in deinterlaced mode");
00460 addProperty<bool>("NoLoop", inputFlag, FALSE,"If the camera should be opened in no loop mode");
00461 addProperty<bool>("RGBMEncoder", inputFlag, FALSE,"If the camera should be opened in RGB using mencoder");
00462 addProperty<QString>("URL", inputFlag, QString(""),"URL of the video source");
00463
00464
00465
00466 addProperty< QVImage<uChar,3> >("RGB image", outputFlag, QVImage<uChar,3>(), "Last grabbed RGB image");
00467 addProperty< QVImage<uChar,1> >("Y channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed Y channel image");
00468 addProperty< QVImage<uChar,1> >("U channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed U channel image");
00469 addProperty< QVImage<uChar,1> >("V channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed V channel image");
00470
00471 qDebug() << "QVMPlayerCamera::QVMPlayerCamera() <- return";
00472 }
00473
00474 QVMPlayerCamera::~QVMPlayerCamera()
00475 {
00476 qDebug() << "QVMPlayerCamera::~QVMPlayerCamera()";
00477 if (status != Closed) closeCam();
00478 qDebug() << "QVMPlayerCamera::~QVMPlayerCamera() <- deleting image";
00479 setImageBuffer(NULL);
00480 qDebug() << "QVMPlayerCamera::~QVMPlayerCamera() <- return";
00481 }
00482
00483 void QVMPlayerCamera::initMPlayerArgs(QString urlString, uInt rows, uInt cols)
00484 {
00485 qDebug() << "QVMPlayerCamera::initMPlayerArgs()";
00486 qDebug() << "QVMPlayerCamera::initMPlayerArgs(): url string =" << urlString;
00487
00488 QUrl url(urlString);
00489
00490 if (url.host() != "")
00491 path = url.host() + "/";
00492
00493 path += url.path();
00494
00495 qDebug() << "QVMPlayerCamera::initMPlayerArgs(): path" << path;
00496
00497
00498
00499
00500 if (url.scheme() != "")
00501 schema = url.scheme();
00502 else if (urlString.startsWith("/dev/video"))
00503 schema = "v4l";
00504 else if (urlString.startsWith("/dev/dv"))
00505 schema = "dv";
00506 else if (urlString.contains("*"))
00507 schema = "mf";
00508 else if (urlString.startsWith("www."))
00509 schema = "http";
00510 else if (urlString.startsWith("ftp."))
00511 schema = "ftp";
00512
00513 qDebug() << "QVMPlayerCamera::initMPlayerArgs(): scheme" << schema;
00514
00515 live_camera = TRUE;
00516
00517
00518 if ((schema == "v4l") or (schema == "v4l2") or (schema == "analog"))
00519 {
00520
00521 QString urlQueryValues = QString("driver=%1:device=%2").arg(schema).arg(path);
00522
00523 QList<QPair<QString, QString> > queryItems = url.queryItems();
00524 for (int i = 0; i < queryItems.size(); ++i)
00525 urlQueryValues += ":" + queryItems.at(i).first + "=" + queryItems.at(i).second;
00526
00527 mplayer_args << "tv://" << "-tv" << urlQueryValues;
00528 }
00529 else if (schema == "dv")
00530
00531 mplayer_args << path << "-demuxer" << "rawdv" << "-cache" << "400";
00532 else if (schema == "iidc")
00533
00534
00535 qFatal("Currently this driver does not work (apparently with\n"
00536 "vloopback writing and then reading from a fifo with mplayer\ndoes not work).\n");
00537 else if (schema == "tv")
00538
00539 qFatal("tv URL: Still not implemented\n");
00540 else if (schema == "dvb")
00541
00542 qFatal("dvb URL: Still not implemented\n");
00543 else
00544 {
00545
00546 live_camera = FALSE;
00547 if (schema != "")
00548 mplayer_args << QString(schema + "://" + path);
00549 else
00550 mplayer_args << path;
00551 }
00552
00553
00554
00555 QString aux;
00556
00557
00558 if(open_options & Deinterlaced) aux = "pp=md";
00559
00560 if(rows != 0 or cols != 0)
00561 {
00562 if(aux != QString())
00563 aux += QString(",scale=%1:%2").arg(cols).arg(rows);
00564 else
00565 aux = QString("scale=%1:%2").arg(cols).arg(rows);
00566 }
00567
00568 if (aux != QString()) mplayer_args << "-vf" << aux;
00569
00570
00571 if(not (open_options & RealTime))
00572 {
00573 if(not live_camera)
00574 mplayer_args << "-benchmark";
00575 else
00576
00577
00578 qWarning("Warning: opening live cameras in continuous mode "
00579 "wastes less CPU time, but it is prone to delays in "
00580 "the pipe of images if your process is slower than "
00581 "the camera.");
00582 }
00583
00584
00585 if(not (open_options & NoLoop)) mplayer_args << "-loop" << "0";
00586
00587
00588 mplayer_args << "-slave" << "-quiet" << "-nosound" << "-vo" << QString("yuv4mpeg:file=%1").arg(namedPipe->getInputFilePath());
00589
00590 qDebug() << "QVMPlayerCamera::initMPlayerArgs() <- return";
00591 }
00592
00593
00594
00595 bool QVMPlayerCamera::openCam()
00596 {
00597 OpenOptions optsProp = Default;
00598
00599 if (getPropertyValue<bool>("RealTime")) optsProp |= RealTime;
00600 if (getPropertyValue<bool>("Deinterlaced")) optsProp |= Deinterlaced;
00601 if (getPropertyValue<bool>("NoLoop")) optsProp |= NoLoop;
00602 if (rgbMode) optsProp |= RGBMEncoder;
00603
00604 return openCam(getPropertyValue<QString>("URL"), getPropertyValue<int>("Rows"), getPropertyValue<int>("Cols"), optsProp);
00605 }
00606
00607
00608 bool QVMPlayerCamera::openCam(const QString & urlstring,OpenOptions opts)
00609 { return openCam(urlstring,0,0,opts); }
00610
00611
00612 bool QVMPlayerCamera::openCam(const QString & urlstring, uInt rows, uInt cols, OpenOptions opts)
00613 {
00614 qDebug() << "QVMPlayerCamera::openCam(" << urlstring << "," << rows << "," << cols << "," << opts << ")";
00615
00616 setStatus(Closed);
00617
00618 open_options = opts;
00619
00620
00621 namedPipe = new QNamedPipe(QString("mplayer"));
00622 fifo_file.setFileName(namedPipe->getOutputFilePath());
00623
00624 if(open_options & QVMPlayerCamera::RGBMEncoder)
00625 {
00626 namedPipeAux = new QNamedPipe(QString("mplayer-aux"));
00627 fifo_file_2.setFileName(namedPipeAux->getOutputFilePath());
00628 }
00629
00630 initMPlayerArgs(urlstring, rows, cols);
00631
00632 qDebug() << "QVMPlayerCamera::openCam(): MPlayer args ->" << mplayer_args;
00633 mplayer.start("mplayer",mplayer_args);
00634 qDebug() << "QVMPlayerCamera::openCam(): after mplayer.start()";
00635 if(not mplayer.waitForStarted(1000))
00636 qFatal("Mplayer failed to start: Are you sure it is installed and in the correct PATH?");
00637 qDebug() << "QVMPlayerCamera::openCam(): after mplayer.waitForstarted()";
00638
00639
00640
00641
00642
00643
00644
00645 QVCheckOKMplayerCamera *check_thread;
00646 if (schema == "http" or schema == "ftp" or schema == "rtsp" or schema == "dvd" or schema == "vcd")
00647 check_thread = new QVCheckOKMplayerCamera(fifo_file, 10000);
00648 else
00649 check_thread = new QVCheckOKMplayerCamera(fifo_file, 2000);
00650
00651 check_thread->moveToThread(check_thread);
00652 check_thread->start();
00653 qDebug() << "QVMPlayerCamera::openCam(): after starting QVCheckOKMplayerCamera thread";
00654
00655
00656
00657
00658 qDebug() << "QVMPlayerCamera::openCam(): opening fifo_file";
00659 if((fifo_file.open(QIODevice::ReadWrite|QIODevice::Unbuffered)) == -1)
00660 qFatal("Error opening fifo %s\n", qPrintable(namedPipe->getPipeName()));
00661 qDebug() << "QVMPlayerCamera::openCam(): reading fifo_file";
00662
00663
00664 char buf[1024];
00665 int len;
00666 if ((len = fifo_file.readLine(buf, sizeof(buf))) == -1) return FALSE;
00667 if (QString(buf) == QString("MPLAYER ERROR\n")) {
00668 std::cerr << "QVMPlayerCamera::openCam(): Warning: Mplayer could not open the requested video source (" << qPrintable(urlstring) << ") of type " << qPrintable(schema) <<std::endl;
00669 check_thread->quit();
00670 check_thread->wait();
00671 delete check_thread;
00672
00673
00674 mplayer.terminate();
00675 if (not mplayer.waitForFinished(500)) mplayer.kill();
00676 fifo_file.close();
00677 delete namedPipe;
00678 if(open_options & QVMPlayerCamera::RGBMEncoder)
00679 delete namedPipeAux;
00680
00681 qDebug() << "QVMPlayerCamera::openCam(): QVCheckOKMplayerCamera thread deleted after detecting an error; returning FALSE";
00682 return FALSE;
00683 }
00684
00685
00686
00687 if(open_options & QVMPlayerCamera::RGBMEncoder)
00688 {
00689 fifo_file.write(buf,len);
00690 mencoder.start("mencoder", QStringList() << namedPipe->getOutputFilePath() << "-nosound" << "-o" << namedPipeAux->getInputFilePath() <<
00691 "-ovc" << "raw" << "-of" << "rawvideo" << "-vf" << "format=rgb24");
00692 qDebug() << "QVMPlayerCamera::openCam(): mencoder started";
00693 if(not mencoder.waitForStarted(1000))
00694 qFatal("Mencoder failed to start: Are you sure it is installed and in the correct PATH?");
00695 qDebug() << "QVMPlayerCamera::openCam(): opening fifo_file_2";
00696 if((fifo_file_2.open(QIODevice::ReadOnly|QIODevice::Unbuffered))==-1)
00697 qFatal("Error opening fifo %s\n", qPrintable(namedPipeAux->getPipeName()));
00698 }
00699
00700 check_thread->quit();
00701 check_thread->wait();
00702
00703 delete check_thread;
00704 qDebug() << "QVMPlayerCamera::openCam(): QVCheckOKMplayerCamera thread deleted after correct launch of mplayer";
00705
00706 qDebug() << "QVMPlayerCamera::openCam(): going to create QVMPlayerIOProcessor...";
00707 mplayerIOProcessor = new QVMPlayerIOProcessor(&mplayer);
00708
00709 qDebug() << "QVMPlayerCamera::openCam(): waiting for initialization.";
00710 while(getRows() == 0 || getCols() == 0)
00711 mplayerIOProcessor->interpretMPlayerOutput();
00712
00713 qDebug() << "QVMPlayerCamera::openCam(): video dims (" << getCols() << "," << getRows() << ")";
00714 qDebug() << "QVMPlayerCamera::openCam(): fps " << getFPS();
00715
00716 mplayerIOProcessor->queueCommandToMPlayer("get_time_length");
00717
00718 if (open_options & QVMPlayerCamera::RGBMEncoder)
00719 {
00720 setImageBuffer(new QVImage<uChar,3>(getRows(), getCols(), 3*getCols()));
00721 mplayerFrameGrabber = new QVMPlayerFrameGrabber(mplayerIOProcessor, &fifo_file_2, getRows(), getCols(), true, open_options & QVMPlayerCamera::RealTime);
00722 }
00723 else {
00724 setImageBuffer(new QVImage<uChar,1>(getRows(), getCols(), getCols()));
00725 mplayerFrameGrabber = new QVMPlayerFrameGrabber(mplayerIOProcessor, &fifo_file, getRows(), getCols(), false, open_options & QVMPlayerCamera::RealTime);
00726 }
00727
00728 connect(mplayerFrameGrabber,SIGNAL(newReadFrameGrabber()),this,SIGNAL(newRead()));
00729
00730
00731
00732
00733 connect(mplayerFrameGrabber,SIGNAL(sendCommandSignal()),mplayerIOProcessor,SLOT(sendCommandToMPlayer()));
00734 connect(this,SIGNAL(sendCommandSignal()),mplayerIOProcessor,SLOT(sendCommandToMPlayer()));
00735
00736 setStatus(Running);
00737
00738 qDebug() << "QVMPlayerCamera::openCam() <- return";
00739
00740 emit camOpened();
00741
00742
00743
00744 return TRUE;
00745 }
00746
00747
00748 void QVMPlayerCamera::closeCam()
00749 {
00750 qDebug() << "QVMPlayerCamera::closeCam()";
00751
00752 if (status == Closed)
00753 {
00754 qDebug() << "QVMPlayerCamera::closeCam(): camera already closed. Returning";
00755 qDebug() << "QVMPlayerCamera::closeCam() <- return";
00756 return;
00757 }
00758
00759 setStatus(Closed);
00760
00761 emit camClosed();
00762
00763 mplayerIOProcessor->queueCommandToMPlayer("quit");
00764
00765 emit sendCommandSignal();
00766
00767 delete mplayerFrameGrabber;
00768 qDebug() << "QVMPlayerCamera::closeCam(): mplayerFrameGrabber deleted";
00769
00770 delete mplayerIOProcessor;
00771 qDebug() << "QVMPlayerCamera::closeCam(): mplayerIOProcessor deleted";
00772
00773 mplayer.terminate();
00774 while (not mplayer.waitForFinished(500)) mplayer.kill();
00775 qDebug() << "QVMPlayerCamera::closeCam(): mplayer terminated";
00776
00777 if (open_options & QVMPlayerCamera::RGBMEncoder)
00778 {
00779 mencoder.terminate();
00780 while (not mencoder.waitForFinished(500)) mencoder.kill();
00781 }
00782
00783 qDebug() << "QVMPlayerCamera::closeCam(): mencoder terminated";
00784
00785 fifo_file.close();
00786 qDebug() << "QVMPlayerCamera::closeCam(): closed fifo_file";
00787
00788 if(open_options & QVMPlayerCamera::RGBMEncoder)
00789 fifo_file_2.close();
00790 qDebug() << "QVMPlayerCamera::closeCam(): closed fifo_file2";
00791
00792 delete namedPipe;
00793 qDebug() << "mplayercamera2::closecam(): deleted namedpipe";
00794
00795 if(open_options & QVMPlayerCamera::RGBMEncoder)
00796 delete namedPipeAux;
00797 qDebug() << "QVMPlayerCamera::closeCam(): deleted namedPipeAux";
00798
00799 qDebug() << "QVMPlayerCamera::closeCam() <- return";
00800 }
00801
00802 bool QVMPlayerCamera::grab()
00803 {
00804 qDebug() << "QVMPlayerCamera::grab()";
00805
00806 if(!performGrab())
00807 return false;
00808
00809 if (open_options & QVMPlayerCamera::RGBMEncoder)
00810 {
00811 QVImage<uChar,3> grabbedRGBImage;
00812 mplayerFrameGrabber->getQVImageRGB(grabbedRGBImage);
00813 setPropertyValue< QVImage<uChar,3> >("RGB image", grabbedRGBImage);
00814 }
00815 else {
00816 QVImage<uChar> grabbedYImage, grabbedUImage, grabbedVImage;
00817 mplayerFrameGrabber->getQVImageYUV(grabbedYImage, grabbedUImage, grabbedVImage);
00818
00819 setPropertyValue< QVImage<uChar,1> >("Y channel image", grabbedYImage);
00820 setPropertyValue< QVImage<uChar,1> >("U channel image", grabbedUImage);
00821 setPropertyValue< QVImage<uChar,1> >("V channel image", grabbedVImage);
00822 }
00823
00824 writeOutputProperties();
00825
00826 qDebug() << "QVMPlayerCamera::grab() <~ return";
00827
00828 return true;
00829 }
00830
00831 bool QVMPlayerCamera::grab(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV)
00832 {
00833 qDebug() << "QVMPlayerCamera::grab(imageY, imageU, imageV)";
00834
00835
00836
00837 bool newImages = performGrab();
00838
00839 if (newImages)
00840 mplayerFrameGrabber->getQVImageYUV(imgY, imgU, imgV);
00841
00842 setPropertyValue< QVImage<uChar,1> >("Y channel image", imgY);
00843 setPropertyValue< QVImage<uChar,1> >("U channel image", imgU);
00844 setPropertyValue< QVImage<uChar,1> >("V channel image", imgV);
00845
00846
00847
00848
00849
00850 qDebug() << "QVMPlayerCamera::grab() <~ return";
00851
00852 return newImages;
00853 }
00854
00855 bool QVMPlayerCamera::grab(QVImage<uChar,3> & imageRGB)
00856 {
00857 qDebug() << "QVMPlayerCamera::grab(imageRGB)";
00858
00859
00860 bool newImages = performGrab();
00861
00862 if (newImages)
00863 mplayerFrameGrabber->getQVImageRGB(imageRGB);
00864
00865 setPropertyValue< QVImage<uChar,3> >("RGB image", imageRGB);
00866
00867
00868 qDebug() << "QVMPlayerCamera::grab() <~ return";
00869 return newImages;
00870 }
00871
00872 bool QVMPlayerCamera::grab(QVImage<uChar,1> & imageGray)
00873 {
00874 qDebug() << "QVMPlayerCamera::grab(imageGray)";
00875
00876
00877
00878 bool newImages = performGrab();
00879
00880 if (newImages)
00881 mplayerFrameGrabber->getQVImageGray(imageGray);
00882
00883
00884 setPropertyValue< QVImage<uChar,1> >("Y channel image", imageGray);
00885
00886 qDebug() << "QVMPlayerCamera::grab() <~ return";
00887 return newImages;
00888 }
00889
00890 bool QVMPlayerCamera::performGrab()
00891 {
00892
00893 qDebug() << "QVMPlayerCamera::performGrab()";
00894
00895 if (isClosed()) return false;
00896
00897 qDebug() << "QVMPlayerCamera::performGrab(): status != Closed";
00898
00899 bool newFrameGrabbed = false;
00900
00901
00902
00903
00904
00905 switch(status)
00906 {
00907 case RunningOneStep:
00908 qDebug() << "QVMPlayerCamera::performGrab(): status == RunningOneStep";
00909 setStatus(Paused);
00910 case Running:
00911 qDebug() << "QVMPlayerCamera::performGrab(): status == Running";
00912 mplayerFrameGrabber->updateFrameBuffer();
00913 frames_grabbed++;
00914 newFrameGrabbed = true;
00915 qDebug() << "QVMPlayerCamera::performGrab(): frames grabbed" << getFramesGrabbed();
00916 break;
00917
00918 case Paused:
00919 qDebug() << "QVMPlayerCamera::performGrab(): status == Paused";
00920
00921
00922
00923
00924
00925
00926
00927 break;
00928
00929 default:
00930 break;
00931 }
00932 qDebug() << "QVMPlayerCamera::performGrab(): checking finished";
00933
00934 if (mplayerFrameGrabber->finished)
00935 closeCam();
00936 else
00937 emit newGrab();
00938
00939 qDebug() << "QVMPlayerCamera::performGrab() <- return";
00940
00941 return newFrameGrabbed;
00942 }
00943
00944
00945
00946
00947 void QVMPlayerCamera::pauseCam()
00948 {
00949 qDebug() << "QVMPlayerCamera::pauseCam()";
00950 if(status == Closed) return;
00951 setStatus(Paused);
00952 qDebug() << "QVMPlayerCamera::pauseCam() <- return";
00953 }
00954
00955 void QVMPlayerCamera::unpauseCam()
00956 {
00957 qDebug() << "QVMPlayerCamera::unpauseCam()";
00958 if(status == Closed) return;
00959 setStatus(Running);
00960 qDebug() << "QVMPlayerCamera::unpauseCam() <~ return";
00961 }
00962
00963 void QVMPlayerCamera::nextFrameCam()
00964 {
00965 qDebug() << "QVMPlayerCamera::nextFrameCam()";
00966 if(status == Closed) return;
00967 setStatus(RunningOneStep);
00968 qDebug() << "QVMPlayerCamera::nextFrameCam() <~ return";
00969 }
00970
00971 void QVMPlayerCamera::setSpeedCam(double d)
00972 {
00973 qDebug() << "QVMPlayerCamera::setSpeedCam()";
00974 if(status == Closed) return;
00975 mplayerIOProcessor->queueCommandToMPlayer(QString("pausing_keep speed_set ") + QString::number(d));
00976 mplayerIOProcessor->queueCommandToMPlayer("get_property speed");
00977 qDebug() << "QVMPlayerCamera::setSpeedCam() <~ return";
00978 }
00979
00980 void QVMPlayerCamera::seekCam(TSeekType seek,double d)
00981 {
00982 qDebug() << "QVMPlayerCamera::seekCam()";
00983 if(status == Closed) return;
00984 if(status == Paused)
00985 setStatus(RunningOneStep);
00986 QString command = QString("pausing_keep seek ") + QString::number(d) + " " + QString::number(seek);
00987 mplayerIOProcessor->queueCommandToMPlayer(command);
00988 qDebug() << "QVMPlayerCamera::seekCam() <~ return";
00989 }
00990
00991 bool QVMPlayerCamera::link(QVWorker* worker, const QString imageName)
00992 {
00993 connect(worker, SIGNAL(startIteration()), this, SLOT(grab()), Qt::DirectConnection);
00994
00995 if(worker->isType<QVImage<uChar,1> >(imageName))
00996 return this->linkProperty("Y channel image",worker,imageName,AsynchronousLink);
00997 else if(worker->isType<QVImage<uChar,3> >(imageName))
00998 {
00999 rgbMode = true;
01000 return this->linkProperty("RGB image",worker,imageName,AsynchronousLink);
01001 }
01002 else
01003 {
01004 disconnect(worker, SIGNAL(startIteration()), this, SLOT(grab()));
01005 std::cerr << "Warning: QVMPlayerCamera::link(): unsupported property type: property " << qPrintable(imageName)
01006 << " in holder " << qPrintable(worker->getName()) << "is not a QVImage<uChar,1> or QVImage<uChar,3>" << std::endl;
01007 return FALSE;
01008 }
01009 }
01010
01011 bool QVMPlayerCamera::link(QVWorker* worker, const QString imageNameY, const QString imageNameU, const QString imageNameV)
01012 {
01013 if(!worker->isType< QVImage<uChar,1> >(imageNameY))
01014 {
01015 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameY) << "is not of type QVImage<uChar,1> in holder "
01016 << qPrintable(worker->getName()) << std::endl;
01017 return FALSE;
01018 }
01019
01020 if(!worker->isType< QVImage<uChar,1> >(imageNameU))
01021 {
01022 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameU) << "is not of type QVImage<uChar,1> in holder "
01023 << qPrintable(worker->getName()) << std::endl;
01024 return FALSE;
01025 }
01026
01027 if(!worker->isType< QVImage<uChar,1> >(imageNameV))
01028 {
01029 std::cerr << "Warning: QVMPlayerCamera::link(): image " << qPrintable(imageNameV) << "is not of type QVImage<uChar,1> in holder "
01030 << qPrintable(worker->getName()) << std::endl;
01031 return FALSE;
01032 }
01033
01034 connect(worker, SIGNAL(startIteration()), this, SLOT(grab()), Qt::DirectConnection);
01035 return this->linkProperty("Y channel image", worker, imageNameY, AsynchronousLink) &&
01036 this->linkProperty("U channel image", worker, imageNameU, AsynchronousLink) &&
01037 this->linkProperty("V channel image", worker, imageNameV, AsynchronousLink);
01038 }
01039