CVD 0.8
|
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 #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 // GLOBLIST 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 // CONSTRUCTOR 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 // GET FRAME 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 // PUT FRAME 00225 // 00226 template<typename T> 00227 inline void DiskBuffer2<T>::put_frame(VideoFrame<T>* f) 00228 { 00229 //Check that the type is correct... 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 // SEEK TO 00240 // 00241 template<typename T> 00242 inline void DiskBuffer2<T>::seek_to(double t) 00243 { 00244 // t is in ms, but work in seconds 00245 // round the answer to the nearest whole frame 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