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