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