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 #ifdef QVIPP
00028 #include <qvipp.h>
00029 #endif
00030
00031 #ifdef QVOPENCV
00032 #include <opencv/cv.h>
00033 #endif
00034
00035 #include <QVImage>
00036 #include <QVVideoReaderBlock>
00037
00038 #define DEFAULT_IMAGE_SIZE 128
00039
00040 QVVideoReaderBlock::QVVideoReaderBlock(QString name): QVProcessingBlock(name)
00041 {
00042
00043 addProperty<bool>("NoLoop", inputFlag, FALSE,"If the camera should be opened in no loop mode");
00044 addProperty<bool>("Deinterlaced", inputFlag, FALSE,"If input image should be deinterlaced");
00045 addProperty<QString>("URL", inputFlag, QString("#0"),"URL of the video source to read");
00046 addProperty<int>("Cols", inputFlag, 0, "Suggested number of columns of the video");
00047 addProperty<int>("Rows", inputFlag, 0, "Suggested number of rows of the video");
00048
00049
00050 addProperty<bool>("RealTime", inputFlag|guiInvisible, FALSE, "If the camera should be opened in real time mode");
00051
00052
00053 addProperty<bool>("Opened", outputFlag, FALSE, "If the camera is correctly opened and working");
00054 addProperty<int>("FPS", outputFlag, 0, "FPS of the video");
00055 addProperty<int>("Frames", outputFlag, 0, "Number of read frames");
00056 addProperty<int>("ColsR", outputFlag, 0, "Actual number of columns of the video");
00057 addProperty<int>("RowsR", outputFlag, 0, "Actual number of rows of the video");
00058 addProperty<int>("Pos", outputFlag, 0.0, "Current position on the video");
00059 addProperty<int>("Length", outputFlag, 0.0, "Length of the video (0 if not available)");
00060
00061
00062 addProperty< QVImage<uChar,3> >("RGB image", outputFlag, QVImage<uChar,3>(), "Last grabbed RGB image");
00063 addProperty< QVImage<uChar,1> >("Y channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed Y channel image");
00064 addProperty< QVImage<uChar,1> >("U channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed U channel image");
00065 addProperty< QVImage<uChar,1> >("V channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed V channel image");
00066 addProperty< QVImage<uChar,1> >("R channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed R channel image");
00067 addProperty< QVImage<uChar,1> >("G channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed G channel image");
00068 addProperty< QVImage<uChar,1> >("B channel image",outputFlag, QVImage<uChar,1>(), "Last grabbed B channel image");
00069
00070
00071 imageR = QVImage<uChar>(DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE);
00072 imageG = QVImage<uChar>(DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE);
00073 imageB = QVImage<uChar>(DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE);
00074 imageY = QVImage<uChar>(DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE);
00075 imageU = QVImage<uChar>(DEFAULT_IMAGE_SIZE/2,DEFAULT_IMAGE_SIZE/2,DEFAULT_IMAGE_SIZE/2);
00076 imageV = QVImage<uChar>(DEFAULT_IMAGE_SIZE/2,DEFAULT_IMAGE_SIZE/2,DEFAULT_IMAGE_SIZE/2);
00077 Set(128,imageY);
00078 Set(128,imageU);
00079 Set(128,imageV);
00080 Set(128,imageR);
00081 Set(128,imageG);
00082 Set(128,imageB);
00083 setPropertyValue< QVImage<uChar, 1> >("Y channel image", imageY);
00084 setPropertyValue< QVImage<uChar, 1> >("U channel image", imageU);
00085 setPropertyValue< QVImage<uChar, 1> >("V channel image", imageV);
00086 setPropertyValue< QVImage<uChar, 1> >("R channel image", imageR);
00087 setPropertyValue< QVImage<uChar, 1> >("G channel image", imageG);
00088 setPropertyValue< QVImage<uChar, 1> >("B channel image", imageB);
00089 imageRGB = QVImage<uChar,3>(DEFAULT_IMAGE_SIZE,DEFAULT_IMAGE_SIZE);
00090 uchar value[3] = {128,128,128};
00091 Set(value,imageRGB);
00092 setPropertyValue< QVImage<uChar, 3> >("RGB image", imageRGB);
00093
00094
00095 flush_pending_images = FALSE;
00096 }
00097
00098 QVVideoReaderBlock::~QVVideoReaderBlock()
00099 {
00100 video_reader.close();
00101 }
00102
00103 static inline int iRoundUp(int a, int b)
00104 {
00105 return (a % b == 0) ? a : b*(a / b + 1) ;
00106 }
00107
00108 void QVVideoReaderBlock::tryOpeningCam()
00109 {
00110
00111 unsigned int cols, rows, fps;
00112
00113
00114
00115 realTime = getPropertyValue<bool>("RealTime");
00116 noLoop = getPropertyValue<bool>("NoLoop");
00117 deinterlaced = getPropertyValue<bool>("Deinterlaced");
00118 urlName = getPropertyValue<QString>("URL");
00119 cols = getPropertyValue<int>("Cols");
00120 rows = getPropertyValue<int>("Rows");
00121
00122
00123
00124 QVVideoReader::OpenOptions opts;
00125 QVVideoReader::TSourceMode source_mode;
00126 if(realTime) opts |= QVVideoReader::RealTime;
00127 if(noLoop) opts |= QVVideoReader::NoLoop;
00128 if(deinterlaced) opts |= QVVideoReader::Deinterlaced;
00129 if(video_reader.open(urlName,cols,rows,fps,opts,source_mode))
00130 {
00131 setPropertyValue<bool>("Opened",TRUE);
00132 setPropertyValue<int>("ColsR",cols);
00133 setPropertyValue<int>("RowsR",rows);
00134 setPropertyValue<int>("FPS",fps);
00135 setPropertyValue<int>("Frames",0);
00136 setPropertyValue<double>("Pos",video_reader.getPos());
00137 setPropertyValue<double>("Length",video_reader.getLength());
00138
00139 const int default_size=128;
00140 imageY = QVImage<uChar>(default_size, default_size, iRoundUp(default_size,8));
00141 imageU = QVImage<uChar>(default_size/2, default_size/2, iRoundUp(default_size/2,8));
00142 imageV = QVImage<uChar>(default_size/2, default_size/2, iRoundUp(default_size/2,8));
00143 imageR = QVImage<uChar>(default_size, default_size, iRoundUp(default_size,8));
00144 imageG = QVImage<uChar>(default_size, default_size, iRoundUp(default_size,8));
00145 imageB = QVImage<uChar>(default_size, default_size, iRoundUp(default_size,8));
00146 imageRGB = QVImage<uChar,3>(default_size, default_size, iRoundUp(3*default_size,8));
00147
00148 setPropertyValue< QVImage<uChar, 1> >("Y channel image", imageY);
00149 setPropertyValue< QVImage<uChar, 1> >("U channel image", imageU);
00150 setPropertyValue< QVImage<uChar, 1> >("V channel image", imageV);
00151 setPropertyValue< QVImage<uChar, 1> >("R channel image", imageR);
00152 setPropertyValue< QVImage<uChar, 1> >("G channel image", imageG);
00153 setPropertyValue< QVImage<uChar, 1> >("B channel image", imageB);
00154 setPropertyValue< QVImage<uChar, 3> >("RGB image", imageRGB);
00155
00156
00157
00158
00159 if (realTime)
00160 QTimer::singleShot(0, this, SLOT(grabFrame()));
00161
00162
00163 unPause();
00164
00165
00166 if (realTime)
00167 connectOrDisconnectLinkedBlocks(TRUE);
00168
00169 emit opened();
00170 }
00171 else
00172 reset();
00173 }
00174
00175 void QVVideoReaderBlock::connectOrDisconnectLinkedBlocks(bool connect_disconnect)
00176 {
00177 QList<QVPropertyContainer*> list_linked_qvps = getDestinyContainers("RGB image");
00178 list_linked_qvps << getDestinyContainers("Y channel image");
00179 list_linked_qvps << getDestinyContainers("U channel image");
00180 list_linked_qvps << getDestinyContainers("V channel image");
00181 list_linked_qvps << getDestinyContainers("R channel image");
00182 list_linked_qvps << getDestinyContainers("G channel image");
00183 list_linked_qvps << getDestinyContainers("B channel image");
00184 QSet<QVPropertyContainer*> set_linked_qvps = list_linked_qvps.toSet();
00185 QVProcessingBlock *block;
00186 foreach (QVPropertyContainer *qvp, set_linked_qvps)
00187 if((block = dynamic_cast<QVProcessingBlock*>(qvp)) != NULL) {
00188 if(connect_disconnect)
00189 connect(block,SIGNAL(endIteration(uint,int)),this,SLOT(nothing()),Qt::BlockingQueuedConnection);
00190 else
00191 disconnect(block,SIGNAL(endIteration(uint,int)),this,SLOT(nothing()));
00192 }
00193 }
00194
00195 void QVVideoReaderBlock::reset()
00196 {
00197
00198 if(realTime)
00199 connectOrDisconnectLinkedBlocks(FALSE);
00200
00201
00202 flush_pending_images = TRUE;
00203 while(qApp->hasPendingEvents ()) qApp->processEvents();
00204 flush_pending_images = FALSE;
00205
00206
00207 video_reader.close();
00208
00209
00210 setPropertyValue<bool>("Opened",FALSE);
00211 setPropertyValue<int>("FPS",0);
00212 setPropertyValue<int>("Frames",0);
00213 setPropertyValue<int>("Pos",0);
00214 setPropertyValue<int>("Length",0);
00215
00216
00217 stop();
00218
00219 emit closed();
00220 }
00221
00222
00223 bool QVVideoReaderBlock::linkProperty(QVPropertyContainer *destinyContainer, QString destinyPropertyName)
00224 {
00225
00226 LinkType linkType = getPropertyValue<bool>("RealTime") ? AsynchronousLink : SynchronousLink;
00227
00228
00229 if (destinyContainer->isType< QVImage<uChar, 3> >(destinyPropertyName))
00230 return QVProcessingBlock::linkProperty("RGB image", destinyContainer, destinyPropertyName, linkType);
00231 else if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName))
00232 return QVProcessingBlock::linkProperty("Y channel image", destinyContainer, destinyPropertyName, linkType);
00233 else
00234 {
00235 qWarning() << "QVVideoReaderBlock::link(): error, can't link property " << qPrintable(destinyPropertyName) << ".";
00236 return false;
00237 }
00238 }
00239
00240 bool QVVideoReaderBlock::linkProperty(QVPropertyContainer *destinyContainer, QString destinyPropertyName1, QString destinyPropertyName2, QString destinyPropertyName3, bool YUV_RGB)
00241 {
00242
00243 LinkType linkType = getPropertyValue<bool>("RealTime") ? AsynchronousLink : SynchronousLink;
00244
00245 bool ok = TRUE;
00246
00247
00248 if(YUV_RGB)
00249 {
00250 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName1))
00251 if(not QVProcessingBlock::linkProperty("R channel image", destinyContainer, destinyPropertyName1, linkType))
00252 {
00253 ok = FALSE;
00254 qWarning() << "QVVideoReaderBlock::linkProperty(): error, can't link R property " << qPrintable(destinyPropertyName1) ;
00255 }
00256 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName2))
00257 if(not QVProcessingBlock::linkProperty("G channel image", destinyContainer, destinyPropertyName2, linkType))
00258 {
00259 ok = FALSE;
00260 qWarning() << "QVVideoReaderBlock::linkProperty(): error, can't link G property " << qPrintable(destinyPropertyName2) ;
00261 }
00262 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName3))
00263 if(not QVProcessingBlock::linkProperty("B channel image", destinyContainer, destinyPropertyName3, linkType))
00264 {
00265 ok = FALSE;
00266 qWarning() << "QVVideoReaderBlock::linkProperty(): error, can't link B property " << qPrintable(destinyPropertyName3) ;
00267 }
00268 }
00269 else
00270 {
00271 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName1))
00272 if(not QVProcessingBlock::linkProperty("Y channel image", destinyContainer, destinyPropertyName1, linkType))
00273 {
00274 ok = FALSE;
00275 qWarning() << "QVVideoReaderBlock::linkProperty(): error, can't link Y property " << qPrintable(destinyPropertyName1) ;
00276 }
00277 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName2))
00278 if(not QVProcessingBlock::linkProperty("U channel image", destinyContainer, destinyPropertyName2, linkType))
00279 {
00280 ok = FALSE;
00281 qWarning() << "QVVideoReaderBlock::linkProperty(): error, can't link U property " << qPrintable(destinyPropertyName2) ;
00282 }
00283 if (destinyContainer->isType< QVImage<uChar, 1> >(destinyPropertyName3))
00284 if(not QVProcessingBlock::linkProperty("V channel image", destinyContainer, destinyPropertyName3, linkType))
00285 {
00286 ok = FALSE;
00287 qWarning() << "QVVideoReaderBlock::linkProperty(): error, can't link V property " << qPrintable(destinyPropertyName3) ;
00288 }
00289 }
00290 return ok;
00291 }
00292
00293 void QVVideoReaderBlock::grabFrame()
00294 {
00295
00296 if(video_reader.grab())
00297 {
00298 if (isLinkedOutput("RGB image"))
00299 video_reader.getRGBImage(imageRGB);
00300 if (isLinkedOutput("Y channel image") and not isLinkedOutput("U channel image") and not isLinkedOutput("V channel image"))
00301 video_reader.getGrayImage(imageY);
00302 else if(isLinkedOutput("Y channel image") and (isLinkedOutput("U channel image") or isLinkedOutput("V channel image")))
00303 video_reader.getYUVImage(imageY,imageU,imageV);
00304 if (isLinkedOutput("R channel image") or isLinkedOutput("G channel image") or isLinkedOutput("B channel image"))
00305 video_reader.getRGBImage(imageR,imageG,imageB);
00306 setPropertyValue<int>("Frames",getPropertyValue<int>("Frames")+1);
00307 setPropertyValue<int>("Pos",video_reader.getPos());
00308
00309 setPropertyValue<int>("Length",video_reader.getLength());
00310
00311
00312 static QTime t;
00313 if(getPropertyValue<int>("Frames")==1)
00314 t.start();
00315 else
00316 {
00317 int ms = t.elapsed();
00318 if(ms>0) setPropertyValue<int>("FPS",1000/ms);
00319 t.restart();
00320 }
00321
00322 setPropertyValue<int>("ColsR",video_reader.getCols());
00323 setPropertyValue<int>("RowsR",video_reader.getRows());
00324
00325 if(realTime) writeOutputProperties();
00326
00327 emit grabbed();
00328
00329
00330 if(realTime and not flush_pending_images)
00331 QTimer::singleShot(0, this, SLOT(grabFrame()));
00332 }
00333 else
00334 reset();
00335 }
00336
00337 void QVVideoReaderBlock::iterate()
00338 {
00339
00340
00341 if(getIteration()==0)
00342 tryOpeningCam();
00343
00344
00345 if(isStopped()) return;
00346
00347
00348
00349 if (not realTime)
00350 grabFrame();
00351
00352 if (isLinkedOutput("RGB image"))
00353 setPropertyValue< QVImage<uChar,3> >("RGB image", imageRGB);
00354 if (isLinkedOutput("R channel image"))
00355 setPropertyValue< QVImage<uChar,1> >("R channel image", imageR);
00356 if (isLinkedOutput("G channel image"))
00357 setPropertyValue< QVImage<uChar,1> >("G channel image", imageG);
00358 if (isLinkedOutput("B channel image"))
00359 setPropertyValue< QVImage<uChar,1> >("B channel image", imageB);
00360 if (isLinkedOutput("Y channel image"))
00361 setPropertyValue< QVImage<uChar,1> >("Y channel image", imageY);
00362 if (isLinkedOutput("U channel image"))
00363 setPropertyValue< QVImage<uChar,1> >("U channel image", imageU);
00364 if (isLinkedOutput("V channel image"))
00365 setPropertyValue< QVImage<uChar,1> >("V channel image", imageV);
00366
00367 }
00368
00369 void QVVideoReaderBlock::reopen()
00370 {
00371
00372
00373 if(flush_pending_images) return;
00374
00375
00376 reset();
00377
00378 readInputProperties();
00379 tryOpeningCam();
00380 }