src/qvcameras/qvmplayercamera.h

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #ifndef MPLAYERCAMERA_H
00026 #define MPLAYERCAMERA_H
00027 
00028 #include <QObject>
00029 #include <QProcess>
00030 #include <QString>
00031 #include <QList>
00032 #include <QUrl>
00033 #include <QThread>
00034 #include <QMutex>
00035 #include <QWaitCondition>
00036 #include <QFile>
00037 #include <QTimer>
00038 #include <QQueue>
00039 
00040 #include <QVCamera>
00041 #include <qvutils/qnamedpipe.h>
00042 
00043 #ifndef DOXYGEN_IGNORE_THIS
00044 // Auxiliary QVCheckOKMPlayerCamera Class.
00045 // This is an internal convenience thread used only to unblock the open function
00046 // when it is waiting for mplayer to read from the fifo, in the case when
00047 // mplayer aborted when starting (due to bad URL, or wrong file format, for
00048 // example).
00049 
00050 class QVCheckOKMplayerCamera: public QThread
00051 {
00052         Q_OBJECT
00053         public:
00054                 QVCheckOKMplayerCamera(QFile & fifo_file,int max_time_ms_to_wait_for_open);
00055                 ~QVCheckOKMplayerCamera();
00056                 void run();
00057         private slots:
00058                 void writeErrorInFifo();
00059         private:
00060                 QFile & _fifo_file;
00061                 int _max_time_ms_to_wait_for_open;
00062 };
00063 
00064 // Auxiliary QVCameraThread Class.
00065 // This is an internal convenience thread used in real time cameras to keep
00066 // updating the frames from mplayer independently of the user grabs.
00067 
00068 class QVCameraThread: public QThread
00069         {
00070         Q_OBJECT
00071         public:
00072                 QVCameraThread(QObject *object,char *slot);
00073                 ~QVCameraThread();
00074                 void run();
00075         private:
00076                 QObject *_object;
00077                 char *_slot;
00078         };
00079 
00080 // Auxiliary QVMPlayerIOProcessor class.
00081 // Auxiliary class to communicate through stdin and stdout with mplayer, and
00082 // read data such as the number of rows and cols of the video, the fps, and also
00083 // to send commands such as pausing, ask for current position, and so on.
00084 
00085 class QVMPlayerIOProcessor: public QObject
00086         {
00087         Q_OBJECT
00088         public:
00089                 QVMPlayerIOProcessor(QProcess *mplayer);
00090                 ~QVMPlayerIOProcessor();
00091                 void queueCommandToMPlayer(const QString &, bool ifEmpty = false);
00092                 double fps, speed, time_length, time_pos;
00093                 uInt cols, rows;
00094         public slots:
00095                 int interpretMPlayerOutput();
00096         private slots:
00097                 void sendCommandToMPlayer();
00098         private:
00099                 QQueue<QString> command_queue;
00100                 QMutex command_queue_mutex;
00101                 QProcess *mplayer;
00102         };
00103 
00104 // Auxiliary QVMPlayerFrameGrabber Class.
00105 class QVMPlayerFrameGrabber: public QObject
00106         {
00107         Q_OBJECT
00108 
00109         public:
00110                 QVMPlayerFrameGrabber(QVMPlayerIOProcessor *, QFile *, uInt rows, uInt cols, bool realTime);
00111                 ~QVMPlayerFrameGrabber();
00112                 uInt getFrameSize() const { return buf_size; };
00113 
00114                 void getQVImageGray(QVImage<uChar> &imgGray) const;
00115                 void getQVImageYUV(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV) const;
00116 
00117                 void updateFrameBuffer();
00118                 uInt frames_read;
00119                 bool finished;
00120                 QMutex mutex;
00121                 QWaitCondition condition;
00122 
00123         public slots:
00124                 void updateSlot();
00125 
00126         signals:
00127                 void newReadFrameGrabber();
00128                 // This signal is to defer the call to sendCommandToMplayer, and avoid
00129                 // the "QSocketNotifier:: socket notifier cannot be enabled from another
00130                 // thread" warning:
00131                 void sendCommandSignal();
00132 
00133         private:
00134                 QVCameraThread *qvcamerathread;
00135                 QFile *fifoInput;       
00136                 QVMPlayerIOProcessor *mplayerIOProcessor;
00137 
00138                 bool debug_in_memcpy, debug_in_updateSlot;
00139                 bool realTime;
00140                 uInt buf_size;
00141 
00142                 QVImage<uChar> imgY, img_auxY, imgU, img_auxU,  imgV, img_auxV;
00143                 void readToBuffer(uChar *buf_img_aux, uInt buf_size);
00144                 void getNewFrame(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV);
00145         };
00146 #endif
00147 
00148 // This is for doxygen get the detailed description for QVMPlayerCamera correctly.
00149 class QVWorker;
00150 class QVMPlayerIOProcessor;
00151 
00239 class QVMPlayerCamera : public QVCamera
00240         {
00241         Q_OBJECT
00242 
00243         public:
00245                 QVMPlayerCamera(QString name = QString());
00247                 ~QVMPlayerCamera();
00248 
00249                 // Camera opening options as flags. Combine using | operator to create
00250                 // an OpenOptions flags (observe plural) object:
00252                 enum OpenOption {
00254                         Default = 0x0,
00256                         RealTime = 0x1,
00258                         Deinterlaced = 0x2,
00260                         NoLoop = 0x4,
00262                         RGBMEncoder = 0x8
00263                 };
00264 
00265                 Q_DECLARE_FLAGS(OpenOptions,OpenOption);
00266 
00271                 bool openCam(const QString & url,OpenOptions opts = Default);
00272 
00281                 bool openCam(const QString & urlstring, unsigned int r, unsigned int c, OpenOptions opts = Default);
00282 
00283                 #ifndef DOXYGEN_IGNORE_THIS
00302                 bool openCam();
00303                 #endif
00304 
00310                 bool grab(QVImage<uChar,3> &image);
00311 
00317                 bool grab(QVImage<uChar,1> &image);
00318 
00330                 bool grab(QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV);
00331 
00335                 const QString getUrlBase() const { return path.split("/").last(); }
00336 
00339                 OpenOptions getOptions() const          { return open_options; };
00340 
00343                 int getBufferSize() const               { return mplayerFrameGrabber->getFrameSize(); };
00344 
00347                 unsigned int getFramesUpdated() const   { return mplayerFrameGrabber->frames_read; }
00348 
00351                 unsigned int getRows() const            { return mplayerIOProcessor->rows; };
00352 
00355                 unsigned int getCols() const            { return mplayerIOProcessor->cols; };
00356 
00359                 double getFPS() const                   { return mplayerIOProcessor->fps; };
00360 
00363                 double getTimeLength() const            { return mplayerIOProcessor->time_length; };
00364 
00367                 double getTimePos() const               { return mplayerIOProcessor->time_pos; };
00368 
00371                 double getSpeed() const                 { return mplayerIOProcessor->speed; };
00372 
00375                 unsigned int getFramesGrabbed() const           { return frames_grabbed; };
00376 
00379                 unsigned int getFramesRead() const              { return mplayerFrameGrabber->frames_read; };
00380 
00383                 bool isLiveCamera() const               { return live_camera; };
00384 
00393                 static bool getFrame(const QString uri, QVImage<uChar,3> &img, int frame = 0)
00394                         {
00395                         QVMPlayerCamera camera;
00396                         if(camera.openCam(uri, QVMPlayerCamera::RGBMEncoder) == -1)
00397                                 return false;
00398                         bool result;
00399                         for (int i=-1; i < frame; i++)
00400                                 result = camera.grab(img);
00401                         camera.closeCam();
00402                         return result;
00403                         }
00404 
00413                 static bool getFrame(const QString uri, QVImage<uChar,1> &img, int frame = 0)
00414                         {
00415                         QVMPlayerCamera camera;
00416                         if(camera.openCam(uri, QVMPlayerCamera::Default) == -1)
00417                                 return false;
00418 
00419                         for (int i=-1; i < frame; i++)
00420                                 if (!camera.grab(img))
00421                                         return false;
00422 
00423                         camera.closeCam();
00424 
00425                         return true;
00426                         }
00427 
00438                 static bool getFrame(const QString uri, QVImage<uChar> &imgY, QVImage<uChar> &imgU, QVImage<uChar> &imgV,
00439                                 int frame = 0)
00440                         {
00441                         QVMPlayerCamera camera;
00442                         if(camera.openCam(uri, QVMPlayerCamera::Default) == -1)
00443                                 return false;
00444                         bool result;
00445                         for (int i=-1; i < frame; i++)
00446                                 result = camera.grab(imgY, imgU, imgV);
00447                         camera.closeCam();
00448                         return result;
00449                         }
00450 
00451         public slots:
00458                 bool grab();
00459 
00461                 void pauseCam();
00463                 void unpauseCam();
00465                 void nextFrameCam();
00468                 void setSpeedCam(double d);
00475                 void seekCam(QVCamera::TSeekType type, double pos);     
00477                 void closeCam();
00478 
00479                 bool link(QVWorker *, const QString imageName);
00480                 bool link(QVWorker *, const QString imageY, const QString imageU, const QString imageV);
00481                 bool unlink(QVWorker *, const QString imageName);
00482 
00483         signals:
00484                 // This signal is to defer the call to sendCommandToMplayer, and avoid
00485                 // the "QSocketNotifier:: socket notifier cannot be enabled from another
00486                 // thread" warning:
00487                 void sendCommandSignal();
00488 
00489         private:
00490                 // this boolean value becomes true if any RGB image is linked to the camera, from a worker.
00491                 bool rgbMode;
00492 
00493                 QWaitCondition conditionJustToSleepMiliseconds;
00494 
00495                 OpenOptions open_options;
00496                 QVMPlayerFrameGrabber * mplayerFrameGrabber;
00497                 QVMPlayerIOProcessor * mplayerIOProcessor;
00498 
00499                 QNamedPipe *namedPipe;                  // The named fifo;
00500                 QFile fifo_file;                        // Named fifo;
00501                 QProcess mplayer;                       // mplayer and mencoder processes;
00502 
00503                 void initMPlayerArgs(QString urlString, unsigned int rows, unsigned int cols);
00504                 bool performGrab();
00505 
00506                 QStringList mplayer_args;               // MPlayer arguments
00507                 QString path, schema;                   // path and schema extracted from the URL
00508                 
00509                 bool live_camera;
00510                 int frames_grabbed;
00511         };
00512 
00513 // Camera opening flags | operator:
00514 Q_DECLARE_OPERATORS_FOR_FLAGS(QVMPlayerCamera::OpenOptions)
00515 
00516 #endif
00517 
00518 
00519 
00520