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