frame_buffer.cpp

00001 /* ***** BEGIN LICENSE BLOCK *****
00002 *
00003 * $Id: frame_buffer.cpp,v 1.2 2005/01/30 05:11:40 gabest Exp $ $Name:  $
00004 *
00005 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006 *
00007 * The contents of this file are subject to the Mozilla Public License
00008 * Version 1.1 (the "License"); you may not use this file except in compliance
00009 * with the License. You may obtain a copy of the License at
00010 * http://www.mozilla.org/MPL/
00011 *
00012 * Software distributed under the License is distributed on an "AS IS" basis,
00013 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
00014 * the specific language governing rights and limitations under the License.
00015 *
00016 * The Original Code is BBC Research and Development code.
00017 *
00018 * The Initial Developer of the Original Code is the British Broadcasting
00019 * Corporation.
00020 * Portions created by the Initial Developer are Copyright (C) 2004.
00021 * All Rights Reserved.
00022 *
00023 * Contributor(s): Thomas Davies (Original Author), Scott R Ladd
00024 *
00025 * Alternatively, the contents of this file may be used under the terms of
00026 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
00027 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
00028 * the GPL or the LGPL are applicable instead of those above. If you wish to
00029 * allow use of your version of this file only under the terms of the either
00030 * the GPL or LGPL and not to allow others to use your version of this file
00031 * under the MPL, indicate your decision by deleting the provisions above
00032 * and replace them with the notice and other provisions required by the GPL
00033 * or LGPL. If you do not delete the provisions above, a recipient may use
00034 * your version of this file under the terms of any one of the MPL, the GPL
00035 * or the LGPL.
00036 * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <libdirac_common/frame_buffer.h>
00039 #include <algorithm>
00040 using namespace dirac;
00041 
00042 //Simple constructor for general operation
00043 FrameBuffer::FrameBuffer(ChromaFormat cf,int xlen,int ylen): 
00044     m_fparams(cf,xlen,ylen),
00045     m_num_L1(0),
00046     m_L1_sep(1),
00047     m_gop_len(0)
00048 {}    
00049 
00050 //Constructor for coding with an initial I-frame only    
00051 FrameBuffer::FrameBuffer(ChromaFormat cf,int L1sep, int xlen, int ylen):
00052     m_fparams(cf,xlen,ylen),
00053     m_num_L1(0),
00054     m_L1_sep(L1sep),
00055     m_gop_len(0)
00056 {}
00057 
00058 //Constructor setting GOP parameters for use with a standard GOP
00059 FrameBuffer::FrameBuffer(ChromaFormat cf,int numL1,int L1sep,int xlen,int ylen): 
00060     m_fparams(cf,xlen,ylen),
00061     m_num_L1(numL1),
00062     m_L1_sep(L1sep)
00063 {    
00064     if (m_num_L1>0)
00065     {// conventional GOP coding
00066         m_gop_len = (m_num_L1+1)*m_L1_sep;
00067     }
00068     else if (m_num_L1==0)
00069     {// I-frame only coding
00070         m_gop_len = 1;
00071         m_L1_sep = 0;
00072     }
00073     else
00074     {// don't have a proper GOP, only an initial I-frame
00075         m_gop_len = 0;
00076     }    
00077 }    
00078 
00079 //Copy constructor. Why anyone would need this I don't know.
00080 FrameBuffer::FrameBuffer(const FrameBuffer& cpy)
00081     {
00082     // first delete all frames in the current buffer
00083     for (size_t i=0 ; i<m_frame_data.size() ; ++i)
00084     {
00085         delete m_frame_data[i];
00086     }//i
00087 
00088     // next create new arrays, copying from the initialising buffer
00089     m_frame_data.resize(cpy.m_frame_data.size());
00090     for (size_t i=0 ; i<m_frame_data.size() ; ++i){
00091         m_frame_data[i] = new Frame( *(cpy.m_frame_data[i]) );
00092     }//i
00093 
00094     // now copy the map
00095     m_fnum_map = cpy.m_fnum_map;
00096 
00097     // and the internal frame parameters
00098     m_fparams = cpy.m_fparams;
00099 }
00100 
00101 //Assignment=. Not sure why this would be used either.
00102 FrameBuffer& FrameBuffer::operator=(const FrameBuffer& rhs){
00103     if (&rhs!=this)
00104     {
00105         // delete all the frames in the lhs buffer
00106         for (size_t i=0 ; i<m_frame_data.size() ; ++i)
00107         {
00108             delete m_frame_data[i];
00109         }//i
00110 
00111         // next create new arrays, copying from the rhs
00112         m_frame_data.resize(rhs.m_frame_data.size());
00113         for (size_t i=0 ; i<m_frame_data.size() ; ++i)
00114         {
00115             m_frame_data[i] = new Frame( *(rhs.m_frame_data[i]) );
00116         }//i
00117 
00118         // now copy the map
00119         m_fnum_map = rhs.m_fnum_map;
00120 
00121         // and the internal frame parameters
00122         m_fparams = rhs.m_fparams;
00123     }
00124     return *this;
00125 }
00126 
00127 //Destructor
00128 FrameBuffer::~FrameBuffer()
00129 {
00130     for (size_t i=0 ; i<m_frame_data.size() ;++i)
00131         delete m_frame_data[i];
00132 
00133 }
00134 
00135 Frame& FrameBuffer::GetFrame( unsigned int fnum )
00136 {//get frame with a given frame number, NOT with a given position in the buffer.
00137  //If the frame number does not occur, the first frame in the buffer is returned.
00138 
00139     std::map<unsigned int,unsigned int>::iterator it = m_fnum_map.find(fnum);
00140 
00141     unsigned int pos = 0;    
00142     if (it != m_fnum_map.end()) 
00143         pos = it->second;    
00144 
00145     return *(m_frame_data[pos]);
00146 }
00147 
00148 const Frame& FrameBuffer::GetFrame( unsigned int fnum ) const
00149 {    //as above, but const version
00150 
00151     std::map<unsigned int,unsigned int>::const_iterator it = m_fnum_map.find(fnum);
00152 
00153     unsigned int pos=0;
00154     if (it != m_fnum_map.end()) 
00155         pos = it->second;
00156 
00157     return *(m_frame_data[pos]);
00158 }
00159 
00160 PicArray& FrameBuffer::GetComponent( unsigned int fnum , CompSort c)
00161 {//as GetFrame, but returns corresponding component
00162 
00163     std::map<unsigned int,unsigned int>::iterator it = m_fnum_map.find(fnum);
00164 
00165     unsigned int pos = 0;
00166     if (it!=m_fnum_map.end()) 
00167         pos = it->second;
00168 
00169     if (c == U_COMP) 
00170         return m_frame_data[pos]->Udata();
00171     else if (c == V_COMP) 
00172         return m_frame_data[pos]->Vdata();
00173     else 
00174         return m_frame_data[pos]->Ydata();
00175 }
00176 
00177 const PicArray& FrameBuffer::GetComponent( unsigned int fnum , CompSort c ) const 
00178 {//as above, but const version
00179  
00180     std::map<unsigned int,unsigned int>::const_iterator it = m_fnum_map.find(fnum);
00181 
00182     unsigned int pos;
00183     if (it!=m_fnum_map.end()) 
00184         pos = it->second;
00185 
00186     if (c==U_COMP) 
00187         return m_frame_data[pos]->Udata();
00188     else if (c==V_COMP) 
00189         return m_frame_data[pos]->Vdata();
00190     else 
00191         return m_frame_data[pos]->Ydata();
00192 }
00193 
00194 // as GetFrame, but returns corresponding upconverted component
00195 PicArray& FrameBuffer::GetUpComponent(unsigned int fnum, CompSort c){
00196     std::map<unsigned int,unsigned int>::iterator it = m_fnum_map.find(fnum);
00197 
00198     unsigned int pos = 0;
00199     if (it!=m_fnum_map.end())
00200         pos = it->second;
00201 
00202     if (c == U_COMP) 
00203         return m_frame_data[pos]->UpUdata();
00204     else if (c == V_COMP) 
00205         return m_frame_data[pos]->UpVdata();
00206     else 
00207         return m_frame_data[pos]->UpYdata();
00208 
00209 }
00210 
00211 const PicArray& FrameBuffer::GetUpComponent(unsigned int fnum, CompSort c) const {//as above, but const version
00212     std::map<unsigned int,unsigned int>::const_iterator it=m_fnum_map.find(fnum);
00213 
00214     unsigned int pos = 0;
00215     if (it!=m_fnum_map.end())
00216         pos = it->second;
00217 
00218     if (c == U_COMP) 
00219         return m_frame_data[pos]->UpUdata();
00220     else if (c == V_COMP) 
00221         return m_frame_data[pos]->UpVdata();
00222     else 
00223         return m_frame_data[pos]->UpYdata();
00224 
00225 }
00226 
00227 void FrameBuffer::PushFrame(unsigned int frame_num)
00228 {// Put a new frame onto the top of the stack using built-in frame parameters
00229  // with frame number frame_num
00230     m_fparams.SetFrameNum(frame_num);
00231     Frame* fptr = new Frame(m_fparams);
00232 
00233     // add the frame to the buffer
00234     m_frame_data.push_back(fptr);
00235     
00236     // put the frame number into the index table
00237     std::pair<unsigned int,unsigned int> temp_pair(m_fparams.FrameNum() , m_frame_data.size()-1);
00238     m_fnum_map.insert(temp_pair);
00239 }
00240 
00241 void FrameBuffer::PushFrame( const FrameParams& fp )
00242 {// Put a new frame onto the top of the stack
00243 
00244     Frame* fptr = new Frame(fp);
00245 
00246     // add the frame to the buffer
00247     m_frame_data.push_back(fptr);
00248 
00249     // put the frame number into the index table
00250     std::pair<unsigned int,unsigned int> temp_pair(fp.FrameNum() , m_frame_data.size()-1);
00251     m_fnum_map.insert(temp_pair);
00252 }
00253 
00254 void FrameBuffer::PushFrame( const Frame& frame )
00255 {
00256     // Put a copy of a new frame onto the top of the stack
00257 
00258     Frame* fptr = new Frame( frame );
00259 
00260     // Add the frame to the buffer
00261     m_frame_data.push_back(fptr);
00262 
00263     // Put the frame number into the index table
00264     std::pair<unsigned int,unsigned int> tmp_pair(frame.GetFparams().FrameNum() ,
00265                                                    m_frame_data.size()-1);
00266     m_fnum_map.insert(tmp_pair);
00267 }
00268 
00269 void FrameBuffer::PushFrame(StreamPicInput* picin,const FrameParams& fp)
00270 {
00271     //Read a frame onto the top of the stack
00272 
00273     PushFrame(fp);
00274     picin->ReadNextFrame( *(m_frame_data[m_frame_data.size()-1]) );
00275 }
00276 
00277 void FrameBuffer::PushFrame(StreamPicInput* picin, unsigned int fnum)
00278 {
00279    //Read a frame onto the top of the stack    
00280     SetFrameParams( fnum );
00281     PushFrame( picin , m_fparams );
00282 }
00283 
00284 void FrameBuffer::Remove(unsigned int pos)
00285 {//remove frame fnum from the buffer, shifting everything above down
00286 
00287     std::pair<unsigned int,unsigned int>* tmp_pair;
00288 
00289     if (pos<m_frame_data.size())
00290     {
00291 
00292         delete m_frame_data[pos];
00293 
00294         m_frame_data.erase(m_frame_data.begin()+pos,m_frame_data.begin()+pos+1);
00295 
00296          //make a new map
00297         m_fnum_map.clear();
00298         for (size_t i=0 ; i<m_frame_data.size() ; ++i)
00299         {
00300             tmp_pair = new std::pair<unsigned int,unsigned int>( m_frame_data[i]->GetFparams().FrameNum() , i);
00301             m_fnum_map.insert(*tmp_pair);
00302             delete tmp_pair;
00303         }//i
00304 
00305     }
00306 }
00307 
00308 void FrameBuffer::Clean(int fnum)
00309 {// clean out all frames that have expired
00310 
00311     for (size_t i=0 ; i<m_frame_data.size() ; ++i)
00312     {
00313         if ((m_frame_data[i]->GetFparams().FrameNum() + m_frame_data[i]->GetFparams().ExpiryTime() ) <= fnum)
00314             Remove(i);
00315     }//i
00316 }
00317 
00318 void FrameBuffer::SetFrameParams( unsigned int fnum )
00319 {    
00320     // Set the frame parameters, given the GOP set-up and the frame number in display order
00321     // This function can be ignored by setting the frame parameters directly if required
00322 
00323     m_fparams.SetFrameNum( fnum );
00324     m_fparams.Refs().clear();    
00325 
00326     if ( m_gop_len>0 )
00327     {
00328 
00329         if ( fnum % m_gop_len == 0)
00330         {
00331             m_fparams.SetFSort( I_frame );
00332 
00333             // I frame expires after we've coded the next I frame
00334             m_fparams.SetExpiryTime( m_gop_len );
00335         }
00336         else if (fnum % m_L1_sep == 0)
00337         {
00338             m_fparams.SetFSort( L1_frame );
00339 
00340             // Ref the previous I or L1 frame
00341             m_fparams.Refs().push_back( fnum - m_L1_sep );
00342 
00343             // if we don't have the first L1 frame ...
00344             if ((fnum-m_L1_sep) % m_gop_len>0)
00345                 // ... other ref is the prior I frame
00346                 m_fparams.Refs().push_back( ( fnum/m_gop_len ) * m_gop_len  );
00347 
00348             // Expires after the next L1 or I frame            
00349             m_fparams.SetExpiryTime( m_L1_sep );
00350         }
00351         else
00352         {
00353             m_fparams.SetFSort( L2_frame );
00354             // Refs are the next or previous I or L1 frame
00355             m_fparams.Refs().push_back((fnum/m_L1_sep)*m_L1_sep);
00356             m_fparams.Refs().push_back(((fnum/m_L1_sep)+1)*m_L1_sep);
00357 
00358             m_fparams.SetExpiryTime( 1 );  
00359             // ( L2 frames could expire directly after being coded, but putting in a delay of 1
00360             // allows for frame-skipping to be done, since the frame will still be around to
00361             // be used if the next frame is skipped. )
00362         }
00363     }    
00364     else{        
00365         if (fnum==0)
00366         {
00367             m_fparams.SetFSort( I_frame );
00368             m_fparams.SetExpiryTime( 1<<30 );//ie never
00369         }
00370         else if (fnum % m_L1_sep==0)
00371         {
00372             m_fparams.SetFSort( L1_frame );
00373             m_fparams.Refs().push_back(0);//frame 0 is the I frame
00374 
00375             if (fnum != m_L1_sep)//we don't have the first L1 frame    
00376                 m_fparams.Refs().push_back(fnum-m_L1_sep);//other ref is the prior L1 frame
00377 
00378             //expires after the next L1 or I frame                        
00379             m_fparams.SetExpiryTime( m_L1_sep );
00380         }
00381         else
00382         {
00383             m_fparams.SetFSort( L2_frame );
00384             m_fparams.Refs().push_back((fnum/m_L1_sep)*m_L1_sep);
00385             m_fparams.Refs().push_back(((fnum/m_L1_sep)+1)*m_L1_sep);
00386             m_fparams.SetExpiryTime( 1 );    //L2 frames could expire directly after being coded, but putting in a delay of 1
00387                                         //allows for frame-skipping to be done, since the frame will still be around to
00388                                         //be used if the next frame is skipped.
00389         }
00390     }
00391 }

Generated on Tue Dec 13 14:47:13 2005 for guliverkli by  doxygen 1.4.5