00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <QTimer>
00026
00027 #include <QVImage>
00028 #include <qvio/qvcameraworker.h>
00029 #include <qvip/qvipp/qvipp.h>
00030
00031 #define DEFAULT_IMAGE_SIZE 128
00032
00033 QVCameraWorker::QVCameraWorker(QString name): QVWorker(name)
00034 {
00035
00036 addProperty<bool>("NoLoop", inputFlag, FALSE,"If the camera should be opened in no loop mode");
00037 addProperty<QString>("URL", inputFlag, QString(""),"URL of the video source to read");
00038 addProperty<int>("Cols", inputFlag, 0, "Suggested number of columns of the video");
00039 addProperty<int>("Rows", inputFlag, 0, "Suggested number of rows of the video");
00040
00041
00042 addProperty<bool>("RealTime", inputFlag|guiInvisible, FALSE, "If the camera should be opened in real time mode");
00043
00044
00045 addProperty<bool>("Opened", outputFlag, FALSE, "If the camera is correctly opened and working");
00046 addProperty<int>("FPS", outputFlag, 0, "FPS of the video");
00047 addProperty<int>("Frames", outputFlag, 0, "Number of read frames");
00048 addProperty<int>("ColsR", outputFlag, 0, "Actual number of columns of the video");
00049 addProperty<int>("RowsR", outputFlag, 0, "Actual number of rows of the video");
00050 addProperty<double>("Pos", outputFlag, 0.0, "Current time position of the video");
00051 addProperty<double>("Length", outputFlag, 0.0, "Length of the video (0.0 if not available)");
00052
00053
00054 addProperty< QVImage<uChar,3> >("RGB image", outputFlag, QVImage<uChar,3>(), "Last grabbed RGB image");
00055 addProperty< QVImage<uChar,1> >("Y channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed Y channel image");
00056 addProperty< QVImage<uChar,1> >("U channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed U channel image");
00057 addProperty< QVImage<uChar,1> >("V channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed V channel image");
00058
00059
00060 imageY = QVImage<uChar>(DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE);
00061 imageU = QVImage<uChar>(DEFAULT_IMAGE_SIZE/2,DEFAULT_IMAGE_SIZE/2,DEFAULT_IMAGE_SIZE/2);
00062 imageV = QVImage<uChar>(DEFAULT_IMAGE_SIZE/2,DEFAULT_IMAGE_SIZE/2,DEFAULT_IMAGE_SIZE/2);
00063 Set(128,imageY);
00064 Set(128,imageU);
00065 Set(128,imageV);
00066 setPropertyValue< QVImage<uChar, 1> >("Y channel image", imageY);
00067 setPropertyValue< QVImage<uChar, 1> >("U channel image", imageU);
00068 setPropertyValue< QVImage<uChar, 1> >("V channel image", imageV);
00069 QVImage<uChar, 3> imageRGB(DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE);
00070 YUV420ToRGB(imageY, imageU, imageV, imageRGB);
00071 setPropertyValue< QVImage<uChar, 3> >("RGB image", imageRGB);
00072
00073
00074 flush_pending_images = FALSE;
00075
00076 }
00077
00078 QVCameraWorker::~QVCameraWorker()
00079 {
00080
00081
00082 }
00083
00084 static inline int iRoundUp(int a, int b) {
00085 return (a % b == 0) ? a : b*(a / b + 1) ;
00086 }
00087
00088 void QVCameraWorker::tryOpeningCam()
00089 {
00090
00091 int cols, rows, fps;
00092
00093
00094 realTime = getPropertyValue<bool>("RealTime");
00095 noLoop = getPropertyValue<bool>("NoLoop");
00096 urlName = getPropertyValue<QString>("URL");
00097 cols = getPropertyValue<int>("Cols");
00098 rows = getPropertyValue<int>("Rows");
00099
00100
00101 if(this->openCam(urlName,cols,rows,fps))
00102 {
00103 setPropertyValue<bool>("Opened",TRUE);
00104 setPropertyValue<int>("ColsR",cols);
00105 setPropertyValue<int>("RowsR",rows);
00106 setPropertyValue<int>("FPS",fps);
00107 setPropertyValue<int>("Frames",0);
00108 setPropertyValue<double>("Pos",this->currentPos());
00109 setPropertyValue<double>("Length",this->lengthOfVideo());
00110
00111 imageY = QVImage<uChar>(cols, rows, iRoundUp(cols,8));
00112 imageU = QVImage<uChar>(cols/2, rows/2, iRoundUp(cols/2,8));
00113 imageV = QVImage<uChar>(cols/2, rows/2, iRoundUp(cols/2,8));
00114 setPropertyValue< QVImage<uChar, 1> >("Y channel image", imageY);
00115 setPropertyValue< QVImage<uChar, 1> >("U channel image", imageU);
00116 setPropertyValue< QVImage<uChar, 1> >("V channel image", imageV);
00117 setPropertyValue< QVImage<uChar, 3> >("RGB image", QVImage<uChar,3>(cols, rows, iRoundUp(3*cols,8)));
00118
00119
00120
00121
00122 if (realTime)
00123 QTimer::singleShot(0, this, SLOT(grabFrame()));
00124
00125
00126 unPause();
00127
00128
00129 if (realTime)
00130 connectOrDisconnectLinkedWorkers(TRUE);
00131
00132 emit opened();
00133 }
00134 else
00135 resetCameraWorker();
00136 }
00137
00138 void QVCameraWorker::connectOrDisconnectLinkedWorkers(bool connect_disconnect)
00139 {
00140 QList<QVPropertyContainer*> list_linked_qvps = getDestinyContainers("RGB image");
00141 list_linked_qvps << getDestinyContainers("Y channel image");
00142 list_linked_qvps << getDestinyContainers("U channel image");
00143 list_linked_qvps << getDestinyContainers("V channel image");
00144 QSet<QVPropertyContainer*> set_linked_qvps = list_linked_qvps.toSet();
00145 QVWorker *worker;
00146 foreach (QVPropertyContainer *qvp, set_linked_qvps)
00147 if((worker = dynamic_cast<QVWorker*>(qvp)) != NULL)
00148 if(connect_disconnect)
00149 connect(worker,SIGNAL(endIteration(uint,int)),this,SLOT(nothing()),Qt::BlockingQueuedConnection);
00150 else
00151 disconnect(worker,SIGNAL(endIteration(uint,int)),this,SLOT(nothing()));
00152 }
00153
00154 void QVCameraWorker::resetCameraWorker()
00155 {
00156
00157 if(realTime)
00158 connectOrDisconnectLinkedWorkers(FALSE);
00159
00160
00161 flush_pending_images = TRUE;
00162 while(qApp->hasPendingEvents ()) qApp->processEvents();
00163 flush_pending_images = FALSE;
00164
00165
00166 this->closeCam();
00167
00168
00169 setPropertyValue<bool>("Opened",FALSE);
00170 setPropertyValue<int>("FPS",0);
00171 setPropertyValue<int>("Frames",0);
00172 setPropertyValue<double>("Pos",0.0);
00173 setPropertyValue<double>("Length",0.0);
00174
00175
00176 stop();
00177
00178 emit closed();
00179 }
00180
00181
00182 bool QVCameraWorker::linkProperty(QVPropertyContainer *destinyContainer, QString destinyPropertyName)
00183 {
00184
00185 LinkType linkType = getPropertyValue<bool>("RealTime") ? AsynchronousLink : SynchronousLink;
00186
00187
00188 if (destinyContainer->isType< QVImage<uChar, 3> >(destinyPropertyName))
00189 return QVWorker::linkProperty("RGB image", destinyContainer, destinyPropertyName, linkType);
00190 else if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName))
00191 return QVWorker::linkProperty("Y channel image", destinyContainer, destinyPropertyName, linkType);
00192 else
00193 {
00194 qWarning() << "QVCameraWorker::link(): error, can't link property " << qPrintable(destinyPropertyName) << ".";
00195 return false;
00196 }
00197 }
00198
00199 bool QVCameraWorker::linkProperty(QVPropertyContainer *destinyContainer, QString destinyPropertyName1, QString destinyPropertyName2, QString destinyPropertyName3)
00200 {
00201
00202 LinkType linkType = getPropertyValue<bool>("RealTime") ? AsynchronousLink : SynchronousLink;
00203
00204 bool ok = TRUE;
00205
00206
00207 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName1))
00208 if(not QVWorker::linkProperty("Y channel image", destinyContainer, destinyPropertyName1, linkType))
00209 {
00210 ok = FALSE;
00211 qWarning() << "QVCameraWorker::linkProperty(): error, can't link Y property " << qPrintable(destinyPropertyName1) ;
00212 }
00213 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName2))
00214 if(not QVWorker::linkProperty("U channel image", destinyContainer, destinyPropertyName2, linkType))
00215 {
00216 ok = FALSE;
00217 qWarning() << "QVCameraWorker::linkProperty(): error, can't link U property " << qPrintable(destinyPropertyName2) ;
00218 }
00219 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName3))
00220 if(not QVWorker::linkProperty("V channel image", destinyContainer, destinyPropertyName3, linkType))
00221 {
00222 ok = FALSE;
00223 qWarning() << "QVCameraWorker::linkProperty(): error, can't link V property " << qPrintable(destinyPropertyName3) ;
00224 }
00225
00226 return ok;
00227 }
00228
00229 void QVCameraWorker::grabFrame()
00230 {
00231
00232 if(this->grab(imageY,imageU,imageV))
00233 {
00234 setPropertyValue<int>("Frames",getPropertyValue<int>("Frames")+1);
00235 setPropertyValue<double>("Pos",this->currentPos());
00236
00237 setPropertyValue<double>("Length",this->lengthOfVideo());
00238
00239 static QTime t;
00240 if(getPropertyValue<int>("Frames")==1)
00241 t.start();
00242 else
00243 {
00244 int ms = t.elapsed();
00245 if(ms>0) setPropertyValue<int>("FPS",1000/ms);
00246 t.restart();
00247 }
00248
00249 if(realTime) writeOutputProperties();
00250
00251 emit grabbed();
00252
00253
00254 if(realTime and not flush_pending_images)
00255 QTimer::singleShot(0, this, SLOT(grabFrame()));
00256 }
00257 else
00258 resetCameraWorker();
00259 }
00260
00261 void QVCameraWorker::iterate()
00262 {
00263
00264
00265 if(getIteration()==0)
00266 tryOpeningCam();
00267
00268
00269 if(isStoped()) return;
00270
00271
00272
00273 if (not realTime)
00274 grabFrame();
00275
00276 setPropertyValue< QVImage<uChar, 1> >("Y channel image", imageY);
00277 setPropertyValue< QVImage<uChar, 1> >("U channel image", imageU);
00278 setPropertyValue< QVImage<uChar, 1> >("V channel image", imageV);
00279
00280 if (isLinkedOutput("RGB image"))
00281 {
00282 QVImage<uChar, 3> imageRGB(imageY.getCols(),imageY.getRows());
00283 YUV420ToRGB(imageY, imageU, imageV, imageRGB);
00284 setPropertyValue< QVImage<uChar, 3> >("RGB image", imageRGB);
00285 }
00286
00287 }
00288
00289 void QVCameraWorker::reopen()
00290 {
00291
00292
00293 if(flush_pending_images) return;
00294
00295
00296 resetCameraWorker();
00297
00298 readInputProperties();
00299 tryOpeningCam();
00300 }