00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
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
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
00148
00149 template <typename T>
00150 VideoFrame<T>* DeinterlaceBuffer<T>::get_frame()
00151 {
00152 if(m_loadnewframe)
00153 {
00154
00155 my_realframe = m_vidbuf.get_frame();
00156 }
00157
00158
00159
00160 double time = my_realframe->timestamp();
00161
00162
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
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
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
00199 m_loadnewframe = !m_loadnewframe;
00200 }
00201
00202 return frame;
00203 }
00204
00205
00206
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
00217
00218 template <typename T>
00219 void DeinterlaceBuffer<T>::put_frame(CVD::VideoFrame<T>* frame)
00220 {
00221 if(m_loadnewframe)
00222 {
00223
00224 m_vidbuf.put_frame(my_realframe);
00225 }
00226
00227
00228 delete[] frame->data();
00229 delete dynamic_cast<DeinterlaceFrame<T>*>(frame);
00230 }
00231
00232 }
00233 #endif