- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# frame_compress.cpp

    00001 /* ***** BEGIN LICENSE BLOCK *****
    00002 *
    00003 * $Id: frame_compress.cpp,v 1.2 2005/01/30 05:11:41 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),
    00024 *                 Scott R Ladd,
    00025 *                 Chris Bowley,
    00026 *                 Anuradha Suraparaju
    00027 *
    00028 * Alternatively, the contents of this file may be used under the terms of
    00029 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
    00030 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
    00031 * the GPL or the LGPL are applicable instead of those above. If you wish to
    00032 * allow use of your version of this file only under the terms of the either
    00033 * the GPL or LGPL and not to allow others to use your version of this file
    00034 * under the MPL, indicate your decision by deleting the provisions above
    00035 * and replace them with the notice and other provisions required by the GPL
    00036 * or LGPL. If you do not delete the provisions above, a recipient may use
    00037 * your version of this file under the terms of any one of the MPL, the GPL
    00038 * or the LGPL.
    00039 * ***** END LICENSE BLOCK ***** */
    00040
    00041 //Compression of frames//
    00043
    00044 #include <libdirac_encoder/frame_compress.h>
    00045 #include <libdirac_encoder/comp_compress.h>
    00046 #include <libdirac_common/mot_comp.h>
    00047 #include <libdirac_motionest/motion_estimate.h>
    00048 #include <libdirac_common/mv_codec.h>
    00049 #include <libdirac_common/golomb.h>
    00050 #include <libdirac_common/bit_manager.h>
    00051 #include <libdirac_common/dirac_assertions.h>
    00052 using namespace dirac;
    00053
    00054 #include <iostream>
    00055 #include <sstream>
    00056
    00057 FrameCompressor::FrameCompressor( EncoderParams& encp ) :
    00058     m_encparams(encp),
    00059     m_me_data(0),
    00060     m_skipped(false),
    00061     m_use_global(false),
    00062     m_use_block_mv(true),
    00063     m_global_pred_mode(REF1_ONLY),
    00064     m_medata_avail(false)
    00065 {
    00066 }
    00067
    00068 FrameCompressor::~FrameCompressor()
    00069 {
    00070     if (m_me_data)
    00071         delete m_me_data;
    00072 }
    00073
    00074 void FrameCompressor::Compress( FrameBuffer& my_buffer, const FrameBuffer& orig_buffer , int fnum )
    00075 {
    00076     FrameOutputManager& foutput = m_encparams.BitsOut().FrameOutput();
    00077
    00078     Frame& my_frame = my_buffer.GetFrame( fnum );
    00079     const FrameParams& fparams = my_frame.GetFparams();
    00080     const FrameSort& fsort = fparams.FSort();
    00081     const ChromaFormat cformat = fparams.CFormat();
    00082
    00083     // number of bits written, without byte alignment
    00084     unsigned int num_mv_bits;
    00085     m_medata_avail = false;
    00086
    00087     CompCompressor my_compcoder(m_encparams , fparams );
    00088
    00089     if (m_me_data)
    00090     {
    00091         delete m_me_data;
    00092         m_me_data = 0;
    00093     }
    00094
    00095     if ( fsort != I_frame )
    00096     {
    00097
    00098         m_me_data = new MEData( m_encparams.XNumMB() , m_encparams.YNumMB());
    00099
    00100         // Motion estimate first
    00101         MotionEstimator my_motEst( m_encparams );
    00102         bool is_a_cut = my_motEst.DoME( orig_buffer , fnum , *m_me_data );
    00103
    00104         // If we have a cut, and an L1 frame, then turn into an I-frame
    00105         if ( is_a_cut )
    00106         {
    00107             my_frame.SetFrameSort( I_frame );
    00108             if ( m_encparams.Verbose() )
    00109                 std::cerr<<std::endl<<"Cut detected and I-frame inserted!";
    00110         }
    00111
    00112     }
    00113
    00114
    00115     // Write the frame header. We wait until after motion estimation, since
    00116     // this allows us to do cut-detection and (possibly) to decide whether
    00117     // or not to skip a frame before actually encoding anything. However we
    00118     // can do this at any point prior to actually writing any frame data.
    00119     WriteFrameHeader( my_frame.GetFparams() );
    00120
    00121
    00122     if ( !m_skipped )
    00123     {    // If not skipped we continue with the coding ...
    00124
    00125         if ( fsort != I_frame)
    00126         {
    00127              // Code the MV data
    00128
    00129             // If we're using global motion parameters, code them
    00130             if (m_use_global)
    00131             {
    00132                 /*
    00133                     Code the global motion parameters
    00134                     TBC ....
    00135                 */
    00136             }
    00137
    00138             // If we're using block motion vectors, code them
    00139             if ( m_use_block_mv )
    00140             {
    00141                 MvDataCodec my_mv_coder( &( foutput.MVOutput().Data() ) , 50 , cformat);
    00142
    00143                 my_mv_coder.InitContexts();//may not be necessary
    00144                 num_mv_bits = my_mv_coder.Compress( *m_me_data );
    00145
    00146                 UnsignedGolombCode( foutput.MVOutput().Header() , num_mv_bits);
    00147             }
    00148
    00149              // Then motion compensate
    00150
    00151             MotionCompensator mycomp( m_encparams , SUBTRACT);
    00152             mycomp.CompensateFrame( my_buffer , fnum , *m_me_data );
    00153
    00154         }//?fsort
    00155
    00156         //code component data
    00157         my_compcoder.Compress( my_buffer.GetComponent( fnum , Y_COMP) );
    00158         if (cformat != Yonly)
    00159         {
    00160             my_compcoder.Compress( my_buffer.GetComponent( fnum , U_COMP) );
    00161             my_compcoder.Compress( my_buffer.GetComponent( fnum , V_COMP) );
    00162         }
    00163
    00164         //motion compensate again if necessary
    00165         if ( fsort != I_frame )
    00166         {
    00167             MotionCompensator mycomp( m_encparams , ADD);
    00168             mycomp.CompensateFrame( my_buffer , fnum , *m_me_data );
    00169             // Set me data available flag
    00170             m_medata_avail = true;
    00171         }//?fsort
    00172
    00173          //finally clip the data to keep it in range
    00174         my_buffer.GetFrame(fnum).Clip();
    00175
    00176     }//?m_skipped
    00177 }
    00178
    00179 void FrameCompressor::WriteFrameHeader( const FrameParams& fparams )
    00180 {
    00181     BasicOutputManager& frame_header_op = m_encparams.BitsOut().FrameOutput().HeaderOutput();
    00182
    00183     // Write the frame start code
    00184     unsigned char frame_start[5] = { START_CODE_PREFIX_BYTE0,
    00185                                      START_CODE_PREFIX_BYTE1,
    00186                                      START_CODE_PREFIX_BYTE2,
    00187                                      START_CODE_PREFIX_BYTE3,
    00188                                      IFRAME_START_CODE };
    00189     switch(fparams.FSort())
    00190     {
    00191     case I_frame:
    00192         frame_start[4] = IFRAME_START_CODE;
    00193         break;
    00194
    00195     case L1_frame:
    00196         frame_start[4] = L1FRAME_START_CODE;
    00197         break;
    00198
    00199     case L2_frame:
    00200         frame_start[4] = L2FRAME_START_CODE;
    00201          break;
    00202
    00203     default:
    00204 //         dirac_ASSERTM (false, "Frame type is I_frame or L1_frame or L2_frame");
    00205          break;
    00206     }
    00207     frame_header_op.OutputBytes((char *)frame_start, 5);
    00208
    00209     // Write the frame number
    00210     UnsignedGolombCode(frame_header_op , fparams.FrameNum());
    00211
    00212     //write whether the frame is m_skipped or not
    00213     frame_header_op.OutputBit( m_skipped );
    00214
    00215     if (!m_skipped)
    00216     {// If we're not m_skipped, then we write the rest of the metadata
    00217
    00218         // Write the expiry time relative to the frame number
    00219         UnsignedGolombCode( frame_header_op , fparams.ExpiryTime() );
    00220
    00221         // Write the frame sort
    00222         UnsignedGolombCode( frame_header_op , (unsigned int) fparams.FSort() );
    00223         if (fparams.FSort() != I_frame)
    00224         {
    00225             // If not an I-frame, write how many references there are
    00226             UnsignedGolombCode( frame_header_op , (unsigned int) fparams.Refs().size() );
    00227
    00228             // For each reference, write the reference number relative to the frame number
    00229             for ( size_t i=0 ; i<fparams.Refs().size() ; ++i )
    00230                 GolombCode( frame_header_op , fparams.Refs()[i]-fparams.FrameNum() );
    00231
    00232             // Indicate whether or not there is global motion vector data
    00233             frame_header_op.OutputBit( m_use_global );
    00234
    00235             // Indicate whether or not there is block motion vector data
    00236             frame_header_op.OutputBit( m_use_block_mv );
    00237
    00238             // If there is global but no block motion vector data, indicate the
    00239             // prediction mode to use for the whole frame
    00240             if ( m_use_global && !m_use_block_mv )
    00241             {
    00242                 UnsignedGolombCode( frame_header_op , (unsigned int) m_global_pred_mode );
    00243             }
    00244         }
    00245
    00246     }// ?m_skipped
    00247 }
    00248
    00249 const MEData* FrameCompressor::GetMEData() const
    00250 {
    00251     TESTM (m_me_data != NULL, "m_medata allocated");
    00252     TESTM (m_medata_avail == true, "ME Data available");
    00253
    00254     return m_me_data;
    00255 }