cvd/deinterlacebuffer.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 // PAS 17/6/04 (revised 16/2/05)
00022 
00023 #ifndef __CVD_DEINTERLACEBUFFER_H
00024 #define __CVD_DEINTERLACEBUFFER_H
00025 
00026 #include <cvd/videobuffer.h>
00027 #include <cvd/deinterlaceframe.h>
00028 
00029 namespace CVD
00030 {
00032 // DEINTERLACE BUFFER EXCEPTIONS
00033 //
00034 namespace Exceptions
00035 {
00038     namespace DeinterlaceBuffer
00039     {   
00042         struct All: public CVD::Exceptions::VideoBuffer::All { }; 
00043         
00046         struct OddNumberOfLines: public All { OddNumberOfLines(); }; 
00047     }
00048 }
00049 
00050 
00052 // DEINTERLACE BUFFER
00053 //
00054 
00076 template <typename T>
00077 class DeinterlaceBuffer : public VideoBuffer<T>
00078 {
00079     public:
00081         enum Fields{
00082             OddOnly, 
00083             EvenOnly, 
00084             OddEven, 
00085             EvenOdd 
00086         }; 
00087         
00088     public:
00092         DeinterlaceBuffer(CVD::VideoBuffer<T>& buf, Fields fields = OddEven);
00093  
00096         ImageRef size();
00097         
00098         CVD::VideoFrame<T>* get_frame();
00099         
00100         void put_frame(CVD::VideoFrame<T>* f);
00101         
00102         virtual bool frame_pending()
00103             {return m_vidbuf.frame_pending();}
00104             
00105         virtual void seek_to(double t)
00106             {return m_vidbuf.seek_to(t);}
00107             
00111         virtual double frame_rate()
00112         {
00113             if(m_fields == OddOnly || m_fields == EvenOnly)
00114                 return m_vidbuf.frame_rate();
00115             else
00116                 return m_vidbuf.frame_rate() * 2.0;
00117         }
00118       
00119    private:
00120         CVD::VideoFrame<T>* my_realframe;
00121         CVD::VideoBuffer<T>& m_vidbuf;
00122         Fields m_fields;
00123         bool m_loadnewframe;
00124         ImageRef m_size;
00125         unsigned int m_linebytes;
00126 };
00127 
00128 //
00129 // CONSTRUCTOR
00130 //
00131 template <typename T>
00132 DeinterlaceBuffer<T>::DeinterlaceBuffer(CVD::VideoBuffer<T>& vidbuf, Fields fields) :
00133     VideoBuffer<T>(vidbuf.type()),
00134     m_vidbuf(vidbuf),
00135     m_fields(fields),
00136     m_loadnewframe(true)
00137 {
00138     // Check it has an even number of lines
00139     if(m_vidbuf.size().y % 2 != 0)
00140         throw Exceptions::DeinterlaceBuffer::OddNumberOfLines();
00141     
00142     m_size = ImageRef(m_vidbuf.size().x, m_vidbuf.size().y / 2);
00143     m_linebytes = sizeof(T) * m_size.x;
00144 }
00145 
00146 //
00147 // GET FRAME
00148 //
00149 template <typename T>
00150 VideoFrame<T>* DeinterlaceBuffer<T>::get_frame()
00151 {
00152     if(m_loadnewframe)
00153     {
00154         // Get a new frame from the real videobuffer
00155         my_realframe = m_vidbuf.get_frame();
00156     }
00157         
00158     // Now return the deinterlaced image
00159     // First sort out the time
00160     double time = my_realframe->timestamp();
00161     
00162     // If we're giving the second frame of a pair, make its time half-way to the next frame
00163     if(!m_loadnewframe)
00164         time += frame_rate(); 
00165     
00166     T* data = new T[m_size.x * m_size.y];
00167     DeinterlaceFrame<T>* frame = new DeinterlaceFrame<T>(time, data, m_size);
00168     if(m_fields == OddOnly || 
00169         (m_fields == OddEven && m_loadnewframe) ||
00170         (m_fields == EvenOdd && !m_loadnewframe))
00171     {
00172         // We want the odd field
00173         CVD::byte* podd = reinterpret_cast<CVD::byte*>(frame->data());
00174         const CVD::byte* pframe = reinterpret_cast<const CVD::byte*>(my_realframe->data());
00175         for(int i = 0; i < m_size.y; i++)
00176         {
00177             memcpy(podd, pframe, m_linebytes);
00178             pframe += 2 * m_linebytes;
00179             podd += m_linebytes;
00180         }
00181     }
00182     else
00183     {
00184         // We want the even field
00185         CVD::byte* peven = reinterpret_cast<CVD::byte*>(frame->data());
00186         const CVD::byte* pframe = reinterpret_cast<const CVD::byte*>(my_realframe->data()) + m_linebytes;
00187         for(int i = 0; i < m_size.y; i++)
00188         {
00189             memcpy(peven, pframe, m_linebytes);
00190             pframe += 2 * m_linebytes;
00191             peven += m_linebytes;
00192         }
00193     }
00194     frame->real_frame = my_realframe;
00195     
00196     if(m_fields == OddEven || m_fields == EvenOdd)
00197     {
00198         // If we're taking both fields, we only load a frame every other field
00199         m_loadnewframe = !m_loadnewframe;
00200     }
00201 
00202   return frame;
00203 }
00204 
00205 //
00206 // SIZE
00207 //
00208 template <typename T>
00209 ImageRef DeinterlaceBuffer<T>::size()
00210 {
00211     ImageRef size = m_vidbuf.size();
00212     return ImageRef(size.x, size.y / 2);
00213 }
00214 
00215 //
00216 // PUT FRAME
00217 //
00218 template <typename T>
00219 void DeinterlaceBuffer<T>::put_frame(CVD::VideoFrame<T>* frame)
00220 {
00221     if(m_loadnewframe)
00222     {
00223         // Next time we'll be getting a new real frame, so put back the current real frame
00224         m_vidbuf.put_frame(my_realframe);
00225     }
00226     
00227     // And delete the data for my current deinterlaced frame
00228     delete[] frame->data();
00229     delete dynamic_cast<DeinterlaceFrame<T>*>(frame);
00230 }
00231 
00232 } // CVD
00233 #endif

Generated on Wed Feb 18 10:23:00 2009 for CVD by  doxygen 1.5.3