cvd/readaheadvideobuffer.h

00001 /*                       
00002     This file is part of the CVD Library.
00003 
00004     Copyright (C) 2005 The Authors
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public
00017     License along with this library; if not, write to the Free Software
00018     Foundation, Inc., 
00019     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 
00022 #ifndef CVD_READAHEADVIDEOBUFFER_H
00023 #define CVD_READAHEADVIDEOBUFFER_H
00024 
00025 #include <cvd/config.h>
00026 #include <cvd/videobuffer.h>
00027 
00028 #ifdef CVD_HAVE_PTHREAD
00029 #include <deque>
00030 #include <cvd/thread.h>
00031 #include <cvd/synchronized.h>
00032 #include <cvd/eventobject.h>
00033 #endif
00034 
00035 namespace CVD {
00036     #ifndef CVD_HAVE_PTHREAD
00037     #warning ReadAheadVideoBuffer will not do any read-ahead because threads are not supported in this build
00038     template <class T> 
00039     class ReadAheadVideoBuffer : public VideoBuffer<T>
00040     {
00041     private:
00042     VideoBuffer<T>& vbuffer;
00043     public:
00044     virtual ~ReadAheadVideoBuffer() {}
00045     ReadAheadVideoBuffer(VideoBuffer<T>& vb, size_t maxReadAhead=10) 
00046     : VideoBuffer<T>(vb.type()),vbuffer(vb) {}
00048     ImageRef size() { return vbuffer.size(); }
00050     VideoFrame<T>* get_frame() { return vbuffer.get_frame(); }
00053     void put_frame(VideoFrame<T>* f) { vbuffer.put_frame(f); }
00055     bool frame_pending() { return vbuffer.frame_pending(); }
00057     double frame_rate() { return vbuffer.frame_rate(); }
00060     void seek_to(double t){ vbuffer.seek_to(t); }
00061     };
00062 #else    
00069     template <class T> 
00070     class ReadAheadVideoBuffer : public VideoBuffer<T>, public Runnable
00071     {
00072     private:
00073     VideoBuffer<T>& vbuffer;
00074     size_t maxRA;
00075     std::deque<VideoFrame<T>*> q, putq;
00076     Synchronized vblock;
00077     EventObject qevent;
00078     Thread thread;
00079 
00080 
00081     static VideoBufferType::Type type_update(VideoBufferType::Type t)
00082     {
00083         if(t== VideoBufferType::NotLive)
00084             return t; 
00085         else
00086             return VideoBufferType::Flushable;
00087     }
00088 
00089     public:
00090     virtual ~ReadAheadVideoBuffer() {
00091         qevent.lock();
00092         thread.stop();
00093         qevent.trigger();
00094         qevent.unlock();
00095         thread.join();      
00096     }
00097     ReadAheadVideoBuffer(VideoBuffer<T>& vb, size_t maxReadAhead=10) 
00098     : VideoBuffer<T>(type_update(vb.type())), vbuffer(vb), maxRA(maxReadAhead) {
00099         thread.start(this);     
00100     }
00101 
00102     void run() {
00103         while (!thread.shouldStop()) 
00104         {
00105         // lock queue
00106         { Lock l(qevent);
00107             for (size_t i=0; i<putq.size(); i++)
00108             vbuffer.put_frame(putq[i]);
00109             putq.resize(0);
00110             while (q.size() >= maxRA) {         
00111             qevent.wait();
00112             if (thread.shouldStop())
00113                 return;
00114             }
00115         }
00116         // lock videobuffer
00117         { Lock l(vblock);
00118             VideoFrame<T>* frame = vbuffer.get_frame();
00119             // lock queue
00120             { Lock l(qevent);
00121             q.push_back(frame);
00122             qevent.trigger();
00123             }
00124         }
00125         }
00126     }
00128     ImageRef size() { return vbuffer.size(); }
00130     VideoFrame<T>* get_frame() {
00131         VideoFrame<T>* frame = 0;
00132         Lock l(qevent);
00133         while (q.empty())
00134         qevent.wait();
00135         frame = q.front();
00136         q.pop_front();
00137         qevent.trigger(); 
00138         return frame;
00139     }
00142     void put_frame(VideoFrame<T>* f) { Lock l(qevent); putq.push_back(f); }
00144     bool frame_pending() {
00145         return !q.empty();
00146     }
00148     double frame_rate() { return vbuffer.frame_rate(); }
00151     void seek_to(double t){
00152         Lock vbl(vblock);
00153         Lock ql(qevent);
00154         for (size_t i=0; i<q.size(); i++)
00155         putq.push_back(q[i]);
00156         q.resize(0);
00157         qevent.triggerAll();
00158         vbuffer.seek_to(t);
00159     }
00160     };
00161     #endif
00162 }
00163 
00164 #endif

Generated on Wed Feb 18 10:23:01 2009 for CVD by  doxygen 1.5.3