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     }