seq_compress.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:16k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. *
  3. * $Id: seq_compress.cpp,v 1.2 2005/01/30 05:11:41 gabest Exp $ $Name:  $
  4. *
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License
  8. * Version 1.1 (the "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  14. * the specific language governing rights and limitations under the License.
  15. *
  16. * The Original Code is BBC Research and Development code.
  17. *
  18. * The Initial Developer of the Original Code is the British Broadcasting
  19. * Corporation.
  20. * Portions created by the Initial Developer are Copyright (C) 2004.
  21. * All Rights Reserved.
  22. *
  23. * Contributor(s): Thomas Davies (Original Author),
  24. *                 Scott R Ladd,
  25. *                 Anuradha Suraparaju
  26. *
  27. * Alternatively, the contents of this file may be used under the terms of
  28. * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
  29. * Public License Version 2.1 (the "LGPL"), in which case the provisions of
  30. * the GPL or the LGPL are applicable instead of those above. If you wish to
  31. * allow use of your version of this file only under the terms of the either
  32. * the GPL or LGPL and not to allow others to use your version of this file
  33. * under the MPL, indicate your decision by deleting the provisions above
  34. * and replace them with the notice and other provisions required by the GPL
  35. * or LGPL. If you do not delete the provisions above, a recipient may use
  36. * your version of this file under the terms of any one of the MPL, the GPL
  37. * or the LGPL.
  38. * ***** END LICENSE BLOCK ***** */
  39. #include <libdirac_encoder/seq_compress.h>
  40. #include <libdirac_common/dirac_assertions.h>
  41. #include <libdirac_common/golomb.h>
  42. using namespace dirac;
  43. SequenceCompressor::SequenceCompressor( StreamPicInput* pin , 
  44.                                         std::ostream* outfile ,
  45.                                         EncoderParams& encp
  46.                                         ): 
  47.     m_all_done(false),
  48.     m_just_finished(true),
  49.     m_encparams(encp),
  50.     m_pic_in(pin),
  51.     m_current_display_fnum(-1),
  52.     m_current_code_fnum(0),
  53.     m_show_fnum(-1),m_last_frame_read(-1), 
  54.     m_delay(1),
  55.     m_qmonitor( m_encparams , m_pic_in->GetSeqParams() ),
  56.     m_fcoder( m_encparams )
  57. {
  58.     // Set up the compression of the sequence
  59.     const SeqParams& sparams=m_pic_in->GetSeqParams();
  60.     //TBD: put into the constructor for EncoderParams
  61.     m_encparams.SetEntropyFactors( new EntropyCorrector(4) );
  62.     m_encparams.SetBitsOut( new SequenceOutputManager( outfile ) );
  63.     WriteStreamHeader();
  64.     //We have to set up the block parameters and file padding. This needs to take into
  65.     //account both blocks for motion compensation and also wavelet transforms
  66.     //Amount of horizontal padding for Y,U and V components
  67.     int xpad_luma,xpad_chroma;
  68.     //Amount of vertical padding for Y,U and V components
  69.     int ypad_luma,ypad_chroma;
  70.     //scaling factors for chroma based on chroma format
  71.     int x_chroma_fac,y_chroma_fac;    
  72.     //First, we need to have sufficient padding to take account of the blocksizes.
  73.     //It's sufficient to check for chroma
  74.     
  75.     if (sparams.CFormat() == format411)
  76.     {
  77.         x_chroma_fac = 4; 
  78.         y_chroma_fac = 1;
  79.     }
  80.     else if (sparams.CFormat()==format420)
  81.     {
  82.         x_chroma_fac = 2;
  83.         y_chroma_fac = 2;
  84.     }
  85.     else if (sparams.CFormat() == format422)
  86.     {
  87.         x_chroma_fac = 2;
  88.         y_chroma_fac = 1;
  89.     }
  90.     else
  91.     {
  92.         x_chroma_fac = 1;
  93.         y_chroma_fac = 1;
  94.     }
  95.     int xl_chroma = sparams.Xl() / x_chroma_fac;
  96.     int yl_chroma = sparams.Yl() / y_chroma_fac;
  97.     // Make sure we have enough macroblocks to cover the pictures
  98.     m_encparams.SetXNumMB( xl_chroma/m_encparams.ChromaBParams(0).Xbsep() );
  99.     m_encparams.SetYNumMB( yl_chroma/m_encparams.ChromaBParams(0).Ybsep() );
  100.     if ( m_encparams.XNumMB() * m_encparams.ChromaBParams(0).Xbsep() < xl_chroma )
  101.     {
  102.         m_encparams.SetXNumMB( m_encparams.XNumMB() + 1 );
  103.         xpad_chroma = m_encparams.XNumMB()*m_encparams.ChromaBParams(0).Xbsep()-xl_chroma;
  104.     }
  105.     else
  106.         xpad_chroma = 0;
  107.     if ( m_encparams.YNumMB() * m_encparams.ChromaBParams(0).Ybsep() < yl_chroma )
  108.     {
  109.         m_encparams.SetYNumMB( m_encparams.YNumMB() + 1 );
  110.         ypad_chroma = m_encparams.YNumMB() * m_encparams.ChromaBParams(0).Ybsep() - yl_chroma;
  111.     }
  112.     else
  113.         ypad_chroma = 0;
  114.     // Now we have an integral number of macroblocks in a picture and we set the number of blocks
  115.     m_encparams.SetXNumBlocks( 4 * m_encparams.XNumMB() );
  116.     m_encparams.SetYNumBlocks( 4 * m_encparams.YNumMB() );
  117.     // Next we work out the additional padding due to the wavelet transform
  118.     // For the moment, we'll fix the transform depth to be 4, so we need divisibility by 16.
  119.     // In the future we'll want arbitrary transform depths. It's sufficient to check for
  120.     // chroma only
  121.     int xpad_len = xl_chroma+xpad_chroma;
  122.     int ypad_len = yl_chroma+ypad_chroma;
  123.     if ( xpad_len%16 != 0 )
  124.         xpad_chroma = ( (xpad_len/16)+1 ) *16 - xl_chroma;
  125.     if ( ypad_len%16 != 0 )
  126.         ypad_chroma = ( (ypad_len/16)+1 ) * 16 - yl_chroma;
  127.     xpad_luma = xpad_chroma * x_chroma_fac;
  128.     ypad_luma = ypad_chroma * y_chroma_fac;
  129.     //Set the resulting padding values
  130.     m_pic_in->SetPadding(xpad_luma,ypad_luma);
  131.     // Set up the frame buffers with the PADDED picture sizes
  132.     m_fbuffer = new FrameBuffer( sparams.CFormat() , m_encparams.NumL1() , m_encparams.L1Sep() , 
  133.             sparams.Xl() + xpad_luma , sparams.Yl() + ypad_luma );
  134.     m_origbuffer = new FrameBuffer( sparams.CFormat() , m_encparams.NumL1() , m_encparams.L1Sep() , 
  135.             sparams.Xl() + xpad_luma , sparams.Yl() + ypad_luma );
  136. }
  137. SequenceCompressor::~SequenceCompressor()
  138. {
  139.     if ( m_encparams.Verbose())
  140.         MakeSequenceReport();
  141.     //TBD: put into the destructor for EncoderParams 
  142.     delete &m_encparams.BitsOut();
  143.     delete &m_encparams.EntropyFactors();
  144.     delete m_fbuffer;
  145.     delete m_origbuffer;
  146. }
  147. bool SequenceCompressor::LoadNextFrame()
  148. {
  149.     m_fbuffer->PushFrame( m_pic_in , m_last_frame_read+1 );
  150.     if ( m_pic_in->End() )
  151.     {
  152.         m_all_done = true;
  153.         return false;
  154.     }
  155.     m_last_frame_read++;
  156.     m_origbuffer->PushFrame( m_fbuffer->GetFrame( m_last_frame_read ) );
  157.     return true;
  158. }
  159. Frame& SequenceCompressor::CompressNextFrame()
  160. {
  161.     // This function codes the next frame in coding order and returns the next frame in display order
  162.     // In general these will differ, and because of re-ordering there is a m_delay which needs to be imposed.
  163.     // This creates problems at the start and at the end of the sequence which must be dealt with.
  164.     // At the start we just keep outputting frame 0. At the end you will need to loop for longer to get all
  165.     // the frames out. It's up to the calling function to do something with the decoded frames as they
  166.     // come out - write them to screen or to file, or whatever. TJD 13Feb04.
  167.     // current_fnum is the number of the current frame being coded in display order
  168.     // m_current_code_fnum is the number of the current frame in coding order. This function increments
  169.     // m_current_code_fnum by 1 each time and works out what the number is in display order.
  170.     // m_show_fnum is the index of the frame number that can be shown when current_fnum has been coded.
  171.     // Var m_delay is the m_delay caused by reordering (as distinct from buffering)
  172.     TESTM (m_last_frame_read >= 0, "Data loaded before calling CompressNextFrame");
  173.     m_current_display_fnum = CodedToDisplay( m_current_code_fnum );
  174.     // If we're not at the beginning, clean the buffer
  175.     if ( m_current_code_fnum != 0 )
  176.     {
  177.         m_fbuffer->Clean( m_show_fnum );
  178.         m_origbuffer->Clean( m_show_fnum );
  179.     }
  180.     m_show_fnum = std::max( m_current_code_fnum - m_delay , 0 );
  181.     bool can_encode = false;
  182.     if (m_last_frame_read >= m_current_display_fnum )
  183.         can_encode = true;
  184.     if ( can_encode )
  185.     {   // We haven't coded everything, so compress the next frame
  186.         // True if we need to recode
  187.         bool recode = false;
  188.         if ( m_encparams.Verbose() )
  189.         {
  190.              std::cerr<<std::endl<<std::endl<<"Compressing frame "<<m_current_code_fnum<<", ";
  191.             std::cerr<<m_current_display_fnum<<" in display order";
  192.         }
  193.  
  194.         // A count of how many times we've recoded
  195.         int count = 0;
  196.         int max_count = 3;
  197.         do
  198.         {
  199.       
  200.             // Compress the frame//
  201.             ///////////////////////
  202.             m_fcoder.Compress( *m_fbuffer , *m_origbuffer , m_current_display_fnum );
  203.             // Adjust the Lagrangian parameters and check if we need to re-do the frame
  204.             recode = m_qmonitor.UpdateModel( m_fbuffer->GetFrame( m_current_display_fnum ) , 
  205.                                              m_origbuffer->GetFrame( m_current_display_fnum ) , count );
  206.             ++count;
  207.             if ( recode && count<max_count )
  208.             {
  209.                 if ( m_encparams.Verbose() )
  210.                     std::cerr<<std::endl<<"Recoding!";
  211.                 // Copy the original data back in
  212.                 m_fbuffer->GetFrame( m_current_display_fnum ) = m_origbuffer->GetFrame( m_current_display_fnum );
  213.                 // Reset the output
  214.                 m_encparams.BitsOut().ResetFrame();
  215.             }
  216.         }
  217.         while ( recode && count <max_count );
  218.        // Finish by writing the compressed data out to file ...
  219.        m_encparams.BitsOut().WriteFrameData();
  220.        if ( m_encparams.Verbose() )
  221.        {
  222.            MakeFrameReport();
  223.        }
  224.     
  225.         // Increment our position
  226.         m_current_code_fnum++;
  227.     }
  228.     // Return the latest frame that can be shown
  229.     return m_fbuffer->GetFrame(m_show_fnum);
  230. }
  231. const Frame *SequenceCompressor::GetFrameEncoded()
  232. {
  233.     if (m_current_display_fnum >= 0)
  234.         return &m_fbuffer->GetFrame( m_current_display_fnum );
  235.     return 0;
  236. }
  237. const MEData *SequenceCompressor::GetMEData()
  238. {
  239.     if ( m_fcoder.IsMEDataAvail())
  240.         return m_fcoder.GetMEData();
  241.     return 0;
  242. }
  243. void SequenceCompressor::EndSequence()
  244. {
  245.     if (m_just_finished)
  246.     {
  247.         //Write end of sequence
  248.         unsigned char seq_end[5] = { START_CODE_PREFIX_BYTE0, 
  249.                                      START_CODE_PREFIX_BYTE1, 
  250.                                      START_CODE_PREFIX_BYTE2, 
  251.                                      START_CODE_PREFIX_BYTE3, 
  252.                                      SEQ_END_CODE };
  253.         m_encparams.BitsOut().TrailerOutput().OutputBytes((char *)seq_end, 5);
  254.         m_encparams.BitsOut().WriteSeqTrailerToFile();
  255.         m_just_finished = false;
  256.         m_all_done = true;
  257.     }
  258. }
  259. void SequenceCompressor::MakeSequenceReport()
  260. {
  261.     std::cerr<<"Total bits for sequence="<<m_encparams.BitsOut().SequenceBytes() * 8;
  262.     std::cerr<<" ( "<<m_encparams.BitsOut().SequenceHeadBytes() * 8<<" header )";
  263.     
  264.     std::cerr<<std::endl<<"Of these: "<<std::endl<<std::endl;
  265.     std::cerr<<m_encparams.BitsOut().ComponentBytes( Y_COMP ) * 8<<" were Y, ";
  266.     std::cerr<<std::endl<<m_encparams.BitsOut().ComponentBytes( U_COMP ) * 8<<" were U, ";
  267.     std::cerr<<std::endl<<m_encparams.BitsOut().ComponentBytes( V_COMP ) * 8<<" were V, and ";
  268.     std::cerr<<std::endl<<m_encparams.BitsOut().MVBytes() * 8<<" were motion vector data.";
  269.     std::cerr<<std::endl<<std::endl<<"The resulting bit-rate at "<<m_pic_in->GetSeqParams().FrameRate()<<"Hz is ";
  270.     std::cerr<<m_encparams.BitsOut().SequenceBytes() * 8 * ( m_pic_in->GetSeqParams().FrameRate() )
  271.                                                          /  m_current_code_fnum <<" bits/sec.";
  272.     std::cerr<<std::endl;
  273. }
  274. void SequenceCompressor::MakeFrameReport()
  275. {
  276.     // Write out to screen a report of the number of bits written
  277.     const FrameOutputManager& foutput = m_encparams.BitsOut().FrameOutput();
  278.     unsigned int unit_bits = foutput.MVBytes() * 8;            
  279.     unsigned int unit_head_bits = foutput.MVHeadBytes() * 8;
  280.     std::cerr<<std::endl<<"Number of MV bits="<<unit_bits;
  281.     std::cerr<<" ( "<<unit_head_bits<<" header bits)";
  282.     unit_bits = foutput.ComponentBytes( Y_COMP ) * 8;
  283.     unit_head_bits = foutput.ComponentHeadBytes( Y_COMP ) * 8;
  284.     std::cerr<<std::endl<<"Number of bits for Y="<<unit_bits;
  285.     std::cerr<<" ( "<<unit_head_bits<<" header bits)";
  286.     unit_bits = foutput.ComponentBytes( U_COMP ) * 8;
  287.     unit_head_bits = foutput.ComponentHeadBytes( U_COMP ) * 8;
  288.     std::cerr<<std::endl<<"Number of bits for U="<<unit_bits;
  289.     std::cerr<<" ( "<<unit_head_bits<<" header bits)";
  290.     unit_bits = foutput.ComponentBytes( V_COMP ) * 8;
  291.     unit_head_bits = foutput.ComponentHeadBytes( V_COMP ) * 8;
  292.     std::cerr<<std::endl<<"Number of bits for V="<<unit_bits;
  293.     std::cerr<<" ( "<<unit_head_bits<<" header bits)";
  294.     unit_bits = foutput.FrameBytes() * 8;
  295.     unit_head_bits = foutput.FrameHeadBytes() * 8;
  296.     std::cerr<<std::endl<<std::endl<<"Total frame bits="<<unit_bits;
  297.     std::cerr<<" ( "<<unit_head_bits<<" header bits)"<<std::endl<<std::endl;
  298. }
  299. void SequenceCompressor::WriteStreamHeader()
  300. {
  301.      // Write out all the header data
  302.     BasicOutputManager& stream_header = m_encparams.BitsOut().HeaderOutput();
  303.         // Begin with the ID of the codec
  304.      stream_header.OutputBytes("KW-DIRAC");
  305.     
  306.     unsigned char seq_start[5] = { START_CODE_PREFIX_BYTE0,
  307.                                    START_CODE_PREFIX_BYTE1,
  308.                                    START_CODE_PREFIX_BYTE2,
  309.                                    START_CODE_PREFIX_BYTE3,
  310.                                    RAP_START_CODE };
  311.     
  312.     stream_header.OutputBytes((char *)seq_start, 5);
  313.     // bit stream version
  314.     stream_header.OutputByte((char)BITSTREAM_VERSION);
  315.         // Picture dimensions
  316.      UnsignedGolombCode( stream_header ,(unsigned int) m_pic_in->GetSeqParams().Xl() );
  317.      UnsignedGolombCode( stream_header ,(unsigned int) m_pic_in->GetSeqParams().Yl() );
  318.      // Picture rate
  319.      UnsignedGolombCode( stream_header , (unsigned int) m_pic_in->GetSeqParams().FrameRate());
  320.      // Block parameters
  321.      UnsignedGolombCode( stream_header ,(unsigned int) m_encparams.LumaBParams(2).Xblen() );
  322.      UnsignedGolombCode( stream_header ,(unsigned int) m_encparams.LumaBParams(2).Yblen() );
  323.      UnsignedGolombCode( stream_header ,(unsigned int) m_encparams.LumaBParams(2).Xbsep() );
  324.      UnsignedGolombCode( stream_header ,(unsigned int) m_encparams.LumaBParams(2).Ybsep() );
  325.      // Also send the number of blocks horizontally and vertically
  326.      UnsignedGolombCode( stream_header ,(unsigned int) m_encparams.XNumBlocks() );
  327.      UnsignedGolombCode( stream_header ,(unsigned int) m_encparams.YNumBlocks() );
  328.      // Chroma format
  329.      UnsignedGolombCode( stream_header ,(unsigned int) m_pic_in->GetSeqParams().CFormat() );
  330.      // Interlace marker
  331.      stream_header.OutputBit(m_pic_in->GetSeqParams().Interlace() );
  332.      m_encparams.BitsOut().WriteSeqHeaderToFile();
  333. }
  334. int SequenceCompressor::CodedToDisplay( const int fnum )
  335. {
  336.     int div;
  337.     if (m_encparams.L1Sep()>0)
  338.     {
  339.         // We have L1 and L2 frames
  340.         if (fnum==0)
  341.             return 0;
  342.         else if ((fnum-1)% m_encparams.L1Sep()==0)
  343.         {//we have L1 or subsequent I frames
  344.             div=(fnum-1)/m_encparams.L1Sep();
  345.             return fnum+m_encparams.L1Sep()-1;
  346.         }
  347.         else//we have L2 frames
  348.             return fnum-1;
  349.     }
  350.     else
  351.     {//we just have I-frames, so no re-ordering
  352.         return fnum;
  353.     }
  354. }