- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# dirac_cppparser.cpp

    00001 /* ***** BEGIN LICENSE BLOCK *****
    00002 *
    00003 * $Id: dirac_cppparser.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): Anuradha Suraparaju (Original Author)
    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 <sstream>
    00039 #include <cstdio>
    00040 #include <cstring>
    00041 #include <libdirac_common/dirac_assertions.h>
    00042 #include <libdirac_decoder/dirac_cppparser.h>
    00043 #include <libdirac_decoder/seq_decompress.h>
    00044 #include <libdirac_common/frame.h>
    00045 using namespace dirac;
    00046
    00047
    00048 InputStreamBuffer::InputStreamBuffer()
    00049 {
    00050     m_chunk_buffer = new char[m_buffer_size];
    00051
    00052     setg (m_chunk_buffer,  //beginning of read area
    00053           m_chunk_buffer,  //read position
    00054           m_chunk_buffer); //end position
    00055 }
    00056
    00057 std::ios::pos_type InputStreamBuffer::Rewind()
    00058 {
    00059     return Seek(0, std::ios::beg);
    00060 }
    00061
    00062 std::ios::pos_type InputStreamBuffer::Tell()
    00063 {
    00064     return gptr() - eback();
    00065 }
    00066
    00067 std::ios::pos_type InputStreamBuffer::Seek(std::ios::pos_type bytes, std::ios::seekdir dir)
    00068 {
    00069     char *new_pos;
    00070
    00071     switch (dir)
    00072     {
    00073     case std::ios::beg:
    00074         new_pos  = eback() + bytes;
    00075         break;
    00076     case std::ios::end:
    00077         new_pos  = egptr() + bytes;
    00078         break;
    00079     default:
    00080         new_pos  = gptr() + bytes;
    00081         break;
    00082     }
    00083     if (new_pos > egptr() || new_pos < eback())
    00084         return -1;
    00085
    00086     setg(eback(), //start of read
    00087         new_pos, //current read position
    00088         egptr()); //end of stream positon
    00089
    00090     return 0;
    00091 }
    00092
    00093 void InputStreamBuffer::Copy(char *start, int bytes)
    00094 {
    00095     //std::cerr << "eback=" << m_chunk_buffer - eback()
    00096      //         << "gptr=" << gptr() -m_chunk_buffer
    00097       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
    00098
    00099     int bytes_left = m_buffer_size - (egptr() - m_chunk_buffer);
    00100     if (bytes_left < bytes)
    00101     {
    00102         char *temp =  new char [m_buffer_size + bytes];
    00103         memcpy (temp, m_chunk_buffer, m_buffer_size);
    00104         setg (temp, temp+(gptr()-m_chunk_buffer), temp + (egptr() - m_chunk_buffer));
    00105         delete [] m_chunk_buffer;
    00106         m_chunk_buffer = temp;
    00107     }
    00108     //std::cerr << "eback=" << m_chunk_buffer - eback()
    00109      //         << "gptr=" << gptr() -m_chunk_buffer
    00110       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
    00111
    00112     memcpy (egptr(), start, bytes);
    00113     setg(m_chunk_buffer, gptr(), egptr()+bytes);
    00114
    00115     //std::cerr << "eback=" << m_chunk_buffer - eback()
    00116      //         << "gptr=" << gptr() -m_chunk_buffer
    00117       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
    00118 }
    00119
    00120 void InputStreamBuffer::PurgeProcessedData()
    00121 {
    00122     //std::cerr << "eback=" << m_chunk_buffer - eback()
    00123      //         << "gptr=" << gptr() -m_chunk_buffer
    00124       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
    00125
    00126     if (gptr() != m_chunk_buffer)
    00127     {
    00128         memmove (m_chunk_buffer, gptr(), egptr() - gptr());
    00129         setg(m_chunk_buffer, m_chunk_buffer, m_chunk_buffer+(egptr() - gptr()));
    00130     }
    00131     //std::cerr << "eback=" << m_chunk_buffer - eback()
    00132      //         << "gptr=" << gptr() -m_chunk_buffer
    00133       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
    00134 }
    00135
    00136 InputStreamBuffer::~InputStreamBuffer()
    00137 {
    00138     delete [] m_chunk_buffer;
    00139 }
    00140
    00141
    00142 DiracParser::DiracParser(bool verbose) :
    00143     m_state(STATE_BUFFER),
    00144     m_next_state(STATE_SEQUENCE),
    00145     m_show_fnum(-1),
    00146     m_decomp(0),
    00147     m_skip(false),
    00148     m_skip_type(L2_frame),
    00149     m_verbose(verbose),
    00150     m_found_start(false),
    00151     m_found_end(false),
    00152     m_shift (0xffffffff)
    00153 {
    00154     m_istr = new std::istream(&m_sbuf);
    00155 }
    00156
    00157 DiracParser::~DiracParser()
    00158 {
    00159     delete m_istr;
    00160     delete m_decomp;
    00161 }
    00162
    00163 void DiracParser::SetBuffer (char *start, char *end)
    00164 {
    00165     TEST (end > start);
    00166     m_sbuf.Copy(start, end - start);
    00167
    00168 }
    00169
    00170 DecoderState DiracParser::Parse()
    00171 {
    00172
    00173     while(true)
    00174     {
    00175         m_state = SeekChunk();
    00176         switch (m_state)
    00177         {
    00178         case STATE_BUFFER:
    00179                 return m_state;
    00180
    00181         case STATE_SEQUENCE:
    00182             if (m_next_state == m_state)
    00183             {
    00184                 if (m_decomp)
    00185                     delete m_decomp;
    00186
    00187                 m_decomp = new SequenceDecompressor (m_istr, m_verbose);
    00188                 if (m_decomp->GetSeqParams().BitstreamVersion() != BITSTREAM_VERSION)
    00189                 {
    00190                     std::ostringstream errstr;
    00191                     errstr << "Input Bitstream version " << m_decomp->GetSeqParams().BitstreamVersion() << " supported";
    00192                     REPORTM(false, errstr.str().c_str());
    00193                     return STATE_INVALID;
    00194                 }
    00195                 InitStateVars();
    00196                 return m_state;
    00197             }
    00198             else
    00199                 m_state = STATE_BUFFER;
    00200
    00201             break;
    00202
    00203         case STATE_PICTURE_START:
    00204             if (m_next_state == m_state)
    00205             {
    00206                 m_decomp->ReadNextFrameHeader();
    00207                 m_next_state = STATE_PICTURE_DECODE;
    00208                 m_sbuf.PurgeProcessedData();
    00209                 return m_state;
    00210             }
    00211             else
    00212             {
    00213                 m_state = STATE_BUFFER;
    00214             }
    00215             break;
    00216
    00217         case STATE_PICTURE_DECODE:
    00218         {
    00219             Frame &my_frame = m_decomp->DecompressNextFrame(m_skip);
    00220             if (m_skip)
    00221             {
    00222                 // Go pass start code so that we skip frame
    00223                 m_sbuf.Seek(5);
    00224             }
    00225             else
    00226             {
    00227                 int framenum_decoded = my_frame.GetFparams().FrameNum();
    00228                 if (framenum_decoded != m_show_fnum)
    00229                 {
    00230                     m_show_fnum = my_frame.GetFparams().FrameNum();
    00231                     if (m_verbose)
    00232                     {
    00233                         std::cerr << "Frame " << m_show_fnum << " available" << std::endl;
    00234                     }
    00235                     m_state = STATE_PICTURE_AVAIL;
    00236                 }
    00237             }
    00238             InitStateVars();
    00239             if (m_state == STATE_PICTURE_AVAIL)
    00240                 return m_state;
    00241
    00242             break;
    00243         }
    00244         case STATE_SEQUENCE_END:
    00245         {
    00246             //push last frame in sequence out
    00247             m_sbuf.Seek(5);
    00248             Frame &my_frame = m_decomp->DecompressNextFrame(m_skip);
    00249             if (!m_skip)
    00250             {
    00251                 if (my_frame.GetFparams().FrameNum() != m_show_fnum)
    00252                 {
    00253                     m_show_fnum = my_frame.GetFparams().FrameNum();
    00254                     if (m_verbose)
    00255                     {
    00256                         std::cerr << "Frame " << m_show_fnum << " available" << std::endl;
    00257                     }
    00258                     m_state = STATE_PICTURE_AVAIL;
    00259                     m_next_state = STATE_SEQUENCE_END;
    00260                 }
    00261                 else
    00262                 {
    00263                     InitStateVars();
    00264                 }
    00265             }
    00266             else
    00267             {
    00268                 InitStateVars();
    00269             }
    00270             return m_state;
    00271
    00272             break;
    00273         }
    00274         default:
    00275             return STATE_INVALID;
    00276         }
    00277     }
    00278     return m_state;
    00279 }
    00280
    00281 const SeqParams& DiracParser::GetSeqParams() const
    00282 {
    00283     return m_decomp->GetSeqParams();
    00284 }
    00285
    00286 const FrameParams& DiracParser::GetNextFrameParams() const
    00287 {
    00288     return m_decomp->GetNextFrameParams();
    00289 }
    00290
    00291 const Frame& DiracParser::GetNextFrame() const
    00292 {
    00293     return m_decomp->GetNextFrame();
    00294 }
    00295
    00296 const Frame& DiracParser::GetLastFrame() const
    00297 {
    00298     return  m_decomp->DecompressNextFrame();
    00299 }
    00300
    00301 void DiracParser::SetSkip(bool skip)
    00302 {
    00303     const FrameParams& fparams = m_decomp->GetNextFrameParams();
    00304     // FIXME: need to change this logic once bitstream is finalised. so that
    00305     // we skip to next RAP when an L1 frame is skipped
    00306     if (skip == false)
    00307     {
    00308         if (m_skip_type == L2_frame)
    00309             m_skip = false;
    00310
    00311         else if (m_skip_type == L1_frame || m_skip_type == I_frame)
    00312         {
    00313             if (fparams.FSort() == L2_frame || fparams.FSort() == L1_frame)
    00314                 m_skip = true;
    00315             else
    00316             {
    00317                 m_skip_type = L2_frame;
    00318                 m_skip = false;
    00319             }
    00320         }
    00321     }
    00322     else
    00323     {
    00324         m_skip = true;
    00325         if (m_skip_type != fparams.FSort())
    00326         {
    00327             switch (fparams.FSort())
    00328             {
    00329             case L2_frame:
    00330                 break;
    00331
    00332             case L1_frame:
    00333                 if (m_skip_type != I_frame)
    00334                     m_skip_type = L1_frame;
    00335                 break;
    00336             case I_frame:
    00337                 m_skip_type = I_frame;
    00338                 break;
    00339
    00340             default:
    00341                 dirac_ASSERTM(false, "Frame type must be I or L1 or L2");
    00342                 break;
    00343             }
    00344         }
    00345     }
    00346 }
    00347
    00348
    00349 DecoderState DiracParser::SeekChunk()
    00350 {
    00351     char byte;
    00352     if (!m_found_start)
    00353     {
    00354         while (m_sbuf.sgetn(&byte, 1))
    00355         {
    00356             //Find start of next chunk to be processed
    00357             if (m_shift == START_CODE_PREFIX)
    00358             {
    00359                 switch ((unsigned char)byte)
    00360                 {
    00361                 case NOT_START_CODE:
    00362                     m_shift = 0xffffffff;
    00363                     continue;
    00364
    00365                 case RAP_START_CODE:
    00366                     m_next_state = STATE_SEQUENCE;
    00367                     break;
    00368
    00369                 case IFRAME_START_CODE:
    00370                 case L1FRAME_START_CODE:
    00371                 case L2FRAME_START_CODE:
    00372                     m_next_state = STATE_PICTURE_START;
    00373                     break;
    00374
    00375                 case SEQ_END_CODE:
    00376                     m_next_state = STATE_SEQUENCE_END;
    00377                     break;
    00378                 default:
    00379                     dirac_ASSERTM (false, "Should never have reached here!!!");
    00380                     break;
    00381                 }
    00382                 m_found_start = true;
    00383                 m_sbuf.Seek(-5);
    00384                 m_sbuf.PurgeProcessedData();
    00385                 m_sbuf.Seek(5);
    00386                 m_shift = 0xffffffff;
    00387                 break;
    00388             }
    00389             m_shift = (m_shift << 8) | byte;
    00390         }
    00391
    00392         if (!m_found_start)
    00393         {
    00394             m_next_state =  STATE_BUFFER;
    00395         }
    00396     }
    00397
    00398     if (m_found_start && !m_found_end && m_next_state != STATE_SEQUENCE_END)
    00399     {
    00400         while (m_sbuf.sgetn(&byte, 1))
    00401         {
    00402             //Find start of next chunk to be processed
    00403             if (m_shift == START_CODE_PREFIX)
    00404             {
    00405                 switch ((unsigned char)byte)
    00406                 {
    00407                 case NOT_START_CODE:
    00408                     m_shift = 0xffffffff;
    00409                     continue;
    00410
    00411                 case RAP_START_CODE:
    00412                     break;
    00413
    00414                 case IFRAME_START_CODE:
    00415                 case L1FRAME_START_CODE:
    00416                 case L2FRAME_START_CODE:
    00417                     break;
    00418
    00419                 case SEQ_END_CODE:
    00420                     break;
    00421
    00422                 default:
    00423                     dirac_ASSERTM (false, "Should never have reached here!!!");
    00424                     break;
    00425                 }
    00426                 m_found_end = true;
    00427                 break;
    00428
    00429             }
    00430             m_shift = (m_shift << 8) | byte;
    00431         }
    00432
    00433         if (!m_found_end)
    00434         {
    00435             if (m_next_state != STATE_SEQUENCE_END)
    00436                 return STATE_BUFFER;
    00437         }
    00438     }
    00439
    00440     if (m_found_start && m_found_end)
    00441     {
    00442         m_sbuf.Rewind();
    00443         m_shift = 0xffffffff;
    00444     }
    00445     return m_next_state;
    00446 }
    00447
    00448 void DiracParser::InitStateVars()
    00449 {
    00450     m_shift = 0xffffffff;
    00451     m_found_start = false;
    00452     m_found_end = false;
    00453 }