00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef CVD_DISKBUFFER2_H
00022 #define CVD_DISKBUFFER2_H
00023
00024 #include <vector>
00025 #include <string>
00026 #include <fstream>
00027 #include <errno.h>
00028
00029 #include <cvd/localvideobuffer.h>
00030 #include <cvd/videobufferflags.h>
00031 #include <cvd/diskbuffer2_frame.h>
00032 #include <cvd/image_io.h>
00033 #include <cvd/config.h>
00034
00035 namespace CVD
00036 {
00037
00038
00044 #ifdef CVD_HAVE_GLOB
00045 std::vector<std::string> globlist(const std::string& gl);
00046 #endif
00047
00048 namespace Exceptions
00049 {
00052 namespace DiskBuffer2
00053 {
00056 struct All: public CVD::Exceptions::VideoBuffer::All { };
00059 struct NoFiles: public All { NoFiles(); };
00062 struct BadFile: public All { BadFile(const std::string&, int);
00063 };
00066 struct BadImage: public All { BadImage(const std::string& file, const std::string& error);
00067 };
00070 struct BadImageSize: public All { BadImageSize(const std::string& file);
00071 };
00074 struct EndOfBuffer: public All { EndOfBuffer(); };
00077 struct BadSeek: public All { BadSeek(double t);
00078 };
00079
00080 }
00081 }
00082
00090 template<typename T>
00091 class DiskBuffer2: public CVD::LocalVideoBuffer<T>
00092 {
00093 public:
00100 DiskBuffer2(const std::vector<std::string>& names, double fps, VideoBufferFlags::OnEndOfBuffer eob = VideoBufferFlags::RepeatLastFrame);
00101
00102 virtual ImageRef size() {return my_size;}
00103
00107 virtual bool frame_pending() {return frame_ready;}
00108
00109 virtual DiskBuffer2Frame<T>* get_frame();
00110 virtual void put_frame(VideoFrame<T>* f);
00111 virtual void seek_to(double t);
00112
00115 virtual void on_end_of_buffer(VideoBufferFlags::OnEndOfBuffer eob)
00116 {end_of_buffer_behaviour = eob;}
00117
00118 virtual double frame_rate()
00119 {
00120 return frames_per_sec;
00121 }
00122
00123 protected:
00124 ImageRef my_size;
00125 int next_frame;
00126 double start_time;
00127 double time_per_frame, frames_per_sec;
00128 bool frame_ready;
00129 std::vector<std::string> file_names;
00130 VideoBufferFlags::OnEndOfBuffer end_of_buffer_behaviour;
00131 };
00132
00133
00134
00135
00136 template<typename T>
00137 inline DiskBuffer2<T>::DiskBuffer2(const std::vector<std::string>& names, double fps, VideoBufferFlags::OnEndOfBuffer eob)
00138 :LocalVideoBuffer<T>(VideoBufferType::NotLive),end_of_buffer_behaviour(eob)
00139 {
00140 frames_per_sec = fps;
00141
00142 start_time = 0;
00143 next_frame=0;
00144 time_per_frame = 1/fps;
00145
00146 file_names = names;
00147
00148 if(file_names.size() == 0)
00149 throw Exceptions::DiskBuffer2::NoFiles();
00150
00151 Image<T> foo;
00152 std::ifstream im;
00153 im.open(names[0].c_str(), std::ios::in|std::ios::binary);
00154
00155 if(!im.good())
00156 throw Exceptions::DiskBuffer2::BadFile(names[0], errno);
00157
00158 try
00159 {
00160 img_load(foo, im);
00161 }
00162 catch(Exceptions::Image_IO::All err)
00163 {
00164 throw Exceptions::DiskBuffer2::BadImage(names[0], err.what);
00165 }
00166
00167 my_size = foo.size();
00168 frame_ready = true;
00169 }
00170
00171
00172
00173
00174 template<typename T>
00175 inline DiskBuffer2Frame<T>* DiskBuffer2<T>::get_frame()
00176 {
00177 if(next_frame < 0)
00178 next_frame = 0;
00179
00180 if(!frame_pending())
00181 throw Exceptions::DiskBuffer2::EndOfBuffer();
00182
00183 Image<T> foo(my_size);
00184
00185 std::ifstream im_file(file_names[next_frame].c_str(), std::ios::in|std::ios::binary);
00186
00187 if(!im_file.good())
00188 throw Exceptions::DiskBuffer2::BadFile(file_names[next_frame], errno);
00189
00190 try{
00191 img_load(foo, im_file);
00192 }
00193 catch(CVD::Exceptions::Image_IO::All err)
00194 {
00195 throw Exceptions::DiskBuffer2::BadImage(file_names[next_frame], err.what);
00196 }
00197
00198 DiskBuffer2Frame<T>* vf = new DiskBuffer2Frame<T>(next_frame * time_per_frame + start_time, foo, file_names[next_frame]);
00199
00200 next_frame++;
00201
00202 if(next_frame > (int)file_names.size()-1)
00203 {
00204 switch(end_of_buffer_behaviour)
00205 {
00206 case VideoBufferFlags::RepeatLastFrame:
00207 next_frame = file_names.size()-1;
00208 break;
00209
00210 case VideoBufferFlags::UnsetPending:
00211 frame_ready = false;
00212 break;
00213
00214 case VideoBufferFlags::Loop:
00215 next_frame = 0;
00216 break;
00217 }
00218 }
00219
00220 return vf;
00221 }
00222
00223
00224
00225
00226 template<typename T>
00227 inline void DiskBuffer2<T>::put_frame(VideoFrame<T>* f)
00228 {
00229
00230 DiskBuffer2Frame<T>* db2f = dynamic_cast<DiskBuffer2Frame<T>*>(f);
00231
00232 if(db2f == NULL)
00233 throw CVD::Exceptions::VideoBuffer::BadPutFrame();
00234 else
00235 delete db2f;
00236 }
00237
00238
00239
00240
00241 template<typename T>
00242 inline void DiskBuffer2<T>::seek_to(double t)
00243 {
00244
00245
00246 int frameno = static_cast<int>((t - start_time) / time_per_frame + 0.5);
00247 if(frameno < 0 || static_cast<unsigned int>(frameno) > (file_names.size() - 1))
00248 throw Exceptions::DiskBuffer2::BadSeek(t);
00249 next_frame = frameno;
00250 frame_ready = true;
00251 }
00252 }
00253
00254
00255 #endif