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 // PAS 17/6/04 (revised 16/2/05) 00022 #ifndef CVD_INCLUDE_DEINTERLACEBUFFER_H 00023 #define CVD_INCLUDE_DEINTERLACEBUFFER_H 00024 00025 #include <cvd/videobuffer.h> 00026 #include <cvd/deinterlaceframe.h> 00027 00028 namespace CVD 00029 { 00031 // DEINTERLACE BUFFER EXCEPTIONS 00032 // 00033 namespace Exceptions 00034 { 00037 namespace DeinterlaceBuffer 00038 { 00041 struct All: public CVD::Exceptions::VideoBuffer::All { }; 00042 00045 struct OddNumberOfLines: public All { OddNumberOfLines(); }; 00046 } 00047 } 00048 00049 00051 // DEINTERLACE BUFFER 00052 // 00053 00075 00077 struct DeinterlaceBufferFields 00078 { 00079 enum Fields{ 00080 OddOnly, 00081 EvenOnly, 00082 OddEven, 00083 EvenOdd 00084 }; 00085 }; 00086 00087 template <typename T> 00088 class DeinterlaceBuffer : public VideoBuffer<T> 00089 { 00090 public: 00091 typedef DeinterlaceBufferFields Fields; 00095 DeinterlaceBuffer(CVD::VideoBuffer<T>& buf, Fields::Fields fields = Fields::OddEven, bool line_double=false); 00096 00099 ImageRef size(); 00100 00101 CVD::VideoFrame<T>* get_frame(); 00102 00103 void put_frame(CVD::VideoFrame<T>* f); 00104 00105 virtual bool frame_pending() 00106 {return m_vidbuf.frame_pending();} 00107 00108 virtual void seek_to(double t) 00109 {return m_vidbuf.seek_to(t);} 00110 00114 virtual double frame_rate() 00115 { 00116 if(m_fields == Fields::OddOnly || m_fields == Fields::EvenOnly) 00117 return m_vidbuf.frame_rate(); 00118 else 00119 return m_vidbuf.frame_rate() * 2.0; 00120 } 00121 00122 private: 00123 CVD::VideoFrame<T>* my_realframe; 00124 CVD::VideoBuffer<T>& m_vidbuf; 00125 Fields::Fields m_fields; 00126 bool m_loadnewframe; 00127 ImageRef m_size; 00128 unsigned int m_linebytes; 00129 bool line_double; 00130 }; 00131 00132 // 00133 // CONSTRUCTOR 00134 // 00135 template <typename T> 00136 DeinterlaceBuffer<T>::DeinterlaceBuffer(CVD::VideoBuffer<T>& vidbuf, Fields::Fields fields, bool l) : 00137 VideoBuffer<T>(vidbuf.type()), 00138 m_vidbuf(vidbuf), 00139 m_fields(fields), 00140 m_loadnewframe(true), 00141 line_double(l) 00142 { 00143 // Check it has an even number of lines 00144 if(m_vidbuf.size().y % 2 != 0) 00145 throw Exceptions::DeinterlaceBuffer::OddNumberOfLines(); 00146 00147 if(line_double == false) 00148 m_size = ImageRef(m_vidbuf.size().x, m_vidbuf.size().y / 2); 00149 else 00150 m_size = m_vidbuf.size(); 00151 00152 m_linebytes = sizeof(T) * m_size.x; 00153 } 00154 00155 // 00156 // GET FRAME 00157 // 00158 template <typename T> 00159 VideoFrame<T>* DeinterlaceBuffer<T>::get_frame() 00160 { 00161 if(m_loadnewframe) 00162 { 00163 // Get a new frame from the real videobuffer 00164 my_realframe = m_vidbuf.get_frame(); 00165 } 00166 00167 // Now return the deinterlaced image 00168 // First sort out the time 00169 double time = my_realframe->timestamp(); 00170 00171 // If we're giving the second frame of a pair, make its time half-way to the next frame 00172 if(!m_loadnewframe) 00173 time += frame_rate(); 00174 00175 Image<T> im(size()); 00176 DeinterlaceFrame<T>* frame = new DeinterlaceFrame<T>(time, im); 00177 00178 00179 if(m_fields == Fields::OddOnly || 00180 (m_fields == Fields::OddEven && m_loadnewframe) || 00181 (m_fields == Fields::EvenOdd && !m_loadnewframe)) 00182 { 00183 00184 // We want the odd field 00185 if(line_double) 00186 { 00187 //Copy line 0 from line 1, and copy over line 1 to line 1 00188 for(int y=0; y < 2; y++) 00189 for(int x=0; x < m_size.x; x++) 00190 (*frame)[y][x] = (*my_realframe)[0][x]; 00191 00192 //Done 0, 1. next 2, 3 00193 00194 for(int y=3; y < m_size.y; y+=2) 00195 for(int x=0; x < m_size.x; x++) 00196 { 00197 (*frame)[y][x] = (*my_realframe)[y][x]; 00198 (*frame)[y-1][x] = ((*my_realframe)[y][x] + (*my_realframe)[y-2][x])/2; 00199 } 00200 } 00201 else 00202 { 00203 for(int y=0; y < m_size.y; y++) 00204 for(int x=0; x < m_size.x; x++) 00205 (*frame)[y][x] = (*my_realframe)[2*y+1][x]; 00206 } 00207 00208 } 00209 else 00210 { 00211 // We want the even field 00212 // We want the odd field 00213 if(line_double) 00214 { 00215 //Copy over and double the first set of lines 00216 for(int y=0; y < m_size.y-2; y+=2) 00217 for(int x=0; x < m_size.x; x++) 00218 { 00219 (*frame)[y][x] = (*my_realframe)[y][x]; 00220 (*frame)[y+1][x] = ((*my_realframe)[y][x] + (*my_realframe)[y+2][x])/2; 00221 } 00222 00223 //Copy the last line. 00224 for(int y=m_size.y-2; y < m_size.y; y++) 00225 for(int x=0; x < m_size.x; x++) 00226 (*frame)[y][x] = (*my_realframe)[m_size.y-2][x]; 00227 } 00228 else 00229 { 00230 for(int y=0; y < m_size.y; y++) 00231 for(int x=0; x < m_size.x; x++) 00232 (*frame)[y][x] = (*my_realframe)[2*y][x]; 00233 } 00234 } 00235 frame->real_frame = my_realframe; 00236 00237 if(m_fields == Fields::OddEven || m_fields == Fields::EvenOdd) 00238 { 00239 // If we're taking both fields, we only load a frame every other field 00240 m_loadnewframe = !m_loadnewframe; 00241 } 00242 00243 return frame; 00244 } 00245 00246 // 00247 // SIZE 00248 // 00249 template <typename T> 00250 ImageRef DeinterlaceBuffer<T>::size() 00251 { 00252 return m_size; 00253 } 00254 00255 // 00256 // PUT FRAME 00257 // 00258 template <typename T> 00259 void DeinterlaceBuffer<T>::put_frame(CVD::VideoFrame<T>* frame) 00260 { 00261 if(m_loadnewframe) 00262 { 00263 // Next time we'll be getting a new real frame, so put back the current real frame 00264 m_vidbuf.put_frame(my_realframe); 00265 } 00266 00267 // And delete the data for my current deinterlaced frame 00268 delete dynamic_cast<DeinterlaceFrame<T>*>(frame); 00269 } 00270 00271 } // CVD 00272 #endif