- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 }