CVD 0.8
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     #ifndef _WIN32
00038     #warning ReadAheadVideoBuffer will not do any read-ahead because threads are not supported in this build
00039     #endif
00040     template <class T> 
00041     class ReadAheadVideoBuffer : public VideoBuffer<T>
00042     {
00043     private:
00044     VideoBuffer<T>& vbuffer;
00045     public:
00046     virtual ~ReadAheadVideoBuffer() {}
00047     ReadAheadVideoBuffer(VideoBuffer<T>& vb, size_t maxReadAhead=10) 
00048     : VideoBuffer<T>(vb.type()),vbuffer(vb) {}
00050     ImageRef size() { return vbuffer.size(); }
00052     VideoFrame<T>* get_frame() { return vbuffer.get_frame(); }
00055     void put_frame(VideoFrame<T>* f) { vbuffer.put_frame(f); }
00057     bool frame_pending() { return vbuffer.frame_pending(); }
00059     double frame_rate() { return vbuffer.frame_rate(); }
00062     void seek_to(double t){ vbuffer.seek_to(t); }
00063     };
00064 #else    
00065 
00066 
00067 
00068 
00069 
00070 
00071     template <class T> 
00072     class ReadAheadVideoBuffer : public VideoBuffer<T>, public Runnable
00073     {
00074     private:
00075     VideoBuffer<T>& vbuffer;
00076     size_t maxRA;
00077     std::deque<VideoFrame<T>*> q, putq;
00078     Synchronized vblock;
00079     EventObject qevent;
00080     Thread thread;
00081 
00082 
00083     static VideoBufferType::Type type_update(VideoBufferType::Type t)
00084     {
00085         if(t== VideoBufferType::NotLive)
00086             return t; 
00087         else
00088             return VideoBufferType::Flushable;
00089     }
00090 
00091     public:
00092     virtual ~ReadAheadVideoBuffer() {
00093         qevent.lock();
00094         thread.stop();
00095         qevent.trigger();
00096         qevent.unlock();
00097         thread.join();      
00098     }
00099     ReadAheadVideoBuffer(VideoBuffer<T>& vb, size_t maxReadAhead=10) 
00100     : VideoBuffer<T>(type_update(vb.type())), vbuffer(vb), maxRA(maxReadAhead) {
00101         thread.start(this);     
00102     }
00103 
00104     void run() {
00105         while (!thread.shouldStop()) 
00106         {
00107         // lock queue
00108         { Lock l(qevent);
00109             for (size_t i=0; i<putq.size(); i++)
00110             vbuffer.put_frame(putq[i]);
00111             putq.resize(0);
00112             while (q.size() >= maxRA) {         
00113             qevent.wait();
00114             if (thread.shouldStop())
00115                 return;
00116             }
00117         }
00118         // lock videobuffer
00119         { Lock l(vblock);
00120             VideoFrame<T>* frame = vbuffer.get_frame();
00121             // lock queue
00122             { Lock l(qevent);
00123             q.push_back(frame);
00124             qevent.trigger();
00125             }
00126         }
00127         }
00128     }
00130     ImageRef size() { return vbuffer.size(); }
00132     VideoFrame<T>* get_frame() {
00133         VideoFrame<T>* frame = 0;
00134         Lock l(qevent);
00135         while (q.empty())
00136         qevent.wait();
00137         frame = q.front();
00138         q.pop_front();
00139         qevent.trigger(); 
00140         return frame;
00141     }
00144     void put_frame(VideoFrame<T>* f) { Lock l(qevent); putq.push_back(f); }
00146     bool frame_pending() {
00147         return !q.empty();
00148     }
00150     double frame_rate() { return vbuffer.frame_rate(); }
00153     void seek_to(double t){
00154         Lock vbl(vblock);
00155         Lock ql(qevent);
00156         for (size_t i=0; i<q.size(); i++)
00157         putq.push_back(q[i]);
00158         q.resize(0);
00159         qevent.triggerAll();
00160         vbuffer.seek_to(t);
00161     }
00162     };
00163     #endif
00164 }
00165 
00166 #endif