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_VIDEOFILEBUFFER_H 00023 #define CVD_VIDEOFILEBUFFER_H 00024 00025 #include <vector> 00026 #include <string> 00027 #include <fstream> 00028 #include <errno.h> 00029 00030 #include <cvd/localvideobuffer.h> 00031 #include <cvd/videobufferflags.h> 00032 #include <cvd/videofilebuffer_frame.h> 00033 #include <cvd/image_io.h> 00034 00035 #include <cvd/byte.h> 00036 #include <cvd/rgb.h> 00037 00038 #include <cvd/config.h> 00039 00040 extern "C" { 00041 #ifdef CVD_INTERNAL_HAVE_FFMPEG_OLD_HEADERS 00042 #include <ffmpeg/avcodec.h> 00043 #include <ffmpeg/avformat.h> 00044 #include <ffmpeg/swscale.h> 00045 #else 00046 #include <libavcodec/avcodec.h> 00047 #include <libavformat/avformat.h> 00048 #include <libswscale/swscale.h> 00049 #endif 00050 } 00051 00052 struct AVFormatContext; 00053 struct AVFrame; 00054 00055 namespace CVD 00056 { 00057 namespace Exceptions 00058 { 00061 namespace VideoFileBuffer 00062 { 00065 struct All: public CVD::Exceptions::VideoBuffer::All { }; 00068 struct FileOpen: public All { FileOpen(const std::string& file, const std::string& error); 00069 }; 00072 struct BadFrameAlloc: public All { BadFrameAlloc(); }; 00075 struct BadDecode: public All { BadDecode(double t); 00076 }; 00079 struct EndOfFile: public All { EndOfFile(); }; 00082 struct BadSeek: public All { BadSeek(double t); 00083 }; 00084 } 00085 } 00086 00088 namespace VFB 00089 { 00090 00091 #ifndef DOXYGEN_IGNORE_INTERNAL 00092 template<class C> struct rgb 00093 { 00094 static const bool p=C::Error__type_not_valid___Use_byte_or_rgb_of_byte; 00095 }; 00096 00097 template<> struct rgb<CVD::byte> 00098 { 00099 static const bool p=false; 00100 }; 00101 00102 template<> struct rgb<CVD::Rgb<CVD::byte> > 00103 { 00104 static const bool p=true; 00105 }; 00106 #endif 00107 00108 00109 class A_Frame; 00110 00113 class RawVideoFileBuffer 00114 { 00115 public: 00119 RawVideoFileBuffer(const std::string& file, bool is_rgb); 00120 ~RawVideoFileBuffer(); 00121 00123 ImageRef size() 00124 { 00125 return my_size; 00126 } 00127 00129 void* get_frame(); 00132 void put_frame(void* f); 00133 00135 bool frame_pending() 00136 { 00137 return frame_ready; 00138 } 00139 00142 void seek_to(double t); 00143 00146 void on_end_of_buffer(VideoBufferFlags::OnEndOfBuffer behaviour) 00147 { 00148 end_of_buffer_behaviour = behaviour; 00149 } 00150 00152 double frames_per_second() 00153 { 00154 #if LIBAVCODEC_BUILD >= 4754 00155 return pCodecContext->time_base.den / static_cast<double>(pCodecContext->time_base.num); 00156 #else 00157 return pCodecContext->frame_rate / static_cast<double>(pCodecContext->frame_rate_base); 00158 #endif 00159 }; 00160 00162 std::string file_name() 00163 { 00164 return pFormatContext->filename; 00165 } 00166 00168 std::string codec_name() 00169 { 00170 return pCodecContext->codec_name; 00171 } 00172 00173 private: 00174 bool read_next_frame(); 00175 00176 private: 00177 ImageRef my_size; 00178 VideoBufferFlags::OnEndOfBuffer end_of_buffer_behaviour; 00179 double start_time; 00180 bool frame_ready; 00181 00182 AVFormatContext* pFormatContext; 00183 int video_stream; 00184 AVCodecContext* pCodecContext; 00185 AVFrame* pFrame; 00186 AVFrame* pFrameRGB; 00187 SwsContext *img_convert_ctx; 00188 00189 CVD::Image<CVD::Rgb<byte> > next_frame_rgb; 00190 CVD::Image<CVD::byte> next_frame; 00191 00192 double frame_time; 00193 bool is_rgb; 00194 }; 00195 } 00196 00206 template<typename T> 00207 class VideoFileBuffer : public CVD::LocalVideoBuffer<T> 00208 { 00209 private: 00210 VFB::RawVideoFileBuffer vf; 00211 00212 00213 public: 00216 VideoFileBuffer(const std::string& file) 00217 :LocalVideoBuffer<T>(VideoBufferType::NotLive),vf(file, VFB::rgb<T>::p) 00218 { 00219 } 00220 00221 ~VideoFileBuffer() 00222 { 00223 } 00224 00225 virtual ImageRef size() 00226 { 00227 return vf.size(); 00228 } 00229 00230 virtual bool frame_pending() 00231 { 00232 return vf.frame_pending(); 00233 } 00234 00237 virtual void on_end_of_buffer(VideoBufferFlags::OnEndOfBuffer behaviour) 00238 { 00239 vf.on_end_of_buffer(behaviour); 00240 } 00241 00242 virtual void seek_to(double t) 00243 { 00244 vf.seek_to(t); 00245 } 00246 00247 virtual VideoFileFrame<T> * get_frame() 00248 { 00249 return reinterpret_cast<VideoFileFrame<T>*>(vf.get_frame()); 00250 } 00251 00252 virtual void put_frame(VideoFrame<T>* f) 00253 { 00254 vf.put_frame(f); 00255 } 00256 00257 // This class additions 00258 00259 double frame_rate() 00260 { 00261 return vf.frames_per_second(); 00262 } 00263 00265 std::string file_name() 00266 { 00267 return vf.file_name(); 00268 } 00269 00271 std::string codec_name() 00272 { 00273 return vf.codec_name(); 00274 } 00275 00276 private: 00277 }; 00278 } 00279 00280 #endif