Skip to content
Snippets Groups Projects
BitStream.h 8.08 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* The copyright in this software is being made available under the BSD
     * License, included below. This software may be subject to other third party
     * and contributor rights, including patent rights, and no such rights are
     * granted under this license.
     *
    
     * Copyright (c) 2010-2020, ITU/ISO/IEC
    
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     *  * Redistributions of source code must retain the above copyright notice,
     *    this list of conditions and the following disclaimer.
     *  * Redistributions in binary form must reproduce the above copyright notice,
     *    this list of conditions and the following disclaimer in the documentation
     *    and/or other materials provided with the distribution.
     *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
     *    be used to endorse or promote products derived from this software without
     *    specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     * THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /** \file     BitStream.h
        \brief    class for handling bitstream (header)
    */
    
    #ifndef __BITSTREAM__
    #define __BITSTREAM__
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    #include <stdint.h>
    #include <vector>
    #include <stdio.h>
    #include "CommonDef.h"
    
    //! \ingroup CommonLib
    //! \{
    
    // ====================================================================================================================
    // Class definition
    // ====================================================================================================================
    /**
     * Model of a writable bitstream that accumulates bits to produce a
     * bytestream.
     */
    class OutputBitstream
    {
      /**
       * FIFO for storage of bytes.  Use:
       *  - fifo.push_back(x) to append words
       *  - fifo.clear() to empty the FIFO
       *  - &fifo.front() to get a pointer to the data array.
       *    NB, this pointer is only valid until the next push_back()/clear()
       */
      std::vector<uint8_t> m_fifo;
    
      uint32_t m_num_held_bits; /// number of bits not flushed to bytestream.
      uint8_t m_held_bits; /// the bits held and not flushed to bytestream.
                                 /// this value is always msb-aligned, bigendian.
    public:
      // create / destroy
      OutputBitstream();
      ~OutputBitstream();
    
      // interface for encoding
      /**
       * append uiNumberOfBits least significant bits of uiBits to
       * the current bitstream
       */
      void        write           ( uint32_t uiBits, uint32_t uiNumberOfBits );
    
      /** insert one bits until the bitstream is byte-aligned */
      void        writeAlignOne   ();
    
      /** insert zero bits until the bitstream is byte-aligned */
      void        writeAlignZero  ();
    
      // utility functions
    
      /**
       * Return a pointer to the start of the byte-stream buffer.
       * Pointer is valid until the next write/flush/reset call.
       * NB, data is arranged such that subsequent bytes in the
       * bytestream are stored in ascending addresses.
       */
      uint8_t* getByteStream() const;
    
      /**
       * Return the number of valid bytes available from  getByteStream()
       */
      uint32_t getByteStreamLength();
    
      /**
       * Reset all internal state.
       */
      void clear();
    
      /**
       * returns the number of bits that need to be written to
       * achieve byte alignment.
       */
      int getNumBitsUntilByteAligned() const { return (8 - m_num_held_bits) & 0x7; }
    
      /**
       * Return the number of bits that have been written since the last clear()
       */
      uint32_t getNumberOfWrittenBits() const { return uint32_t(m_fifo.size()) * 8 + m_num_held_bits; }
    
      void insertAt(const OutputBitstream& src, uint32_t pos);
    
      /**
       * Return a reference to the internal fifo
       */
      std::vector<uint8_t>& getFIFO() { return m_fifo; }
    
      uint8_t getHeldBits  ()          { return m_held_bits;          }
    
      //OutputBitstream& operator= (const OutputBitstream& src);
      /** Return a reference to the internal fifo */
      const std::vector<uint8_t>& getFIFO() const { return m_fifo; }
    
      void          addSubstream    ( OutputBitstream* pcSubstream );
      void writeByteAlignment();
    
      //! returns the number of start code emulations contained in the current buffer
      int countStartCodeEmulations();
    };
    
    /**
     * Model of an input bitstream that extracts bits from a predefined
     * bytestream.
     */
    class InputBitstream
    {
    protected:
      std::vector<uint8_t> m_fifo; /// FIFO for storage of complete bytes
      std::vector<uint32_t>    m_emulationPreventionByteLocation;
    
      uint32_t m_fifo_idx; /// Read index into m_fifo
    
      uint32_t m_num_held_bits;
      uint8_t m_held_bits;
      uint32_t  m_numBitsRead;
    
    public:
      /**
       * Create a new bitstream reader object that reads from buf.
       */
      InputBitstream();
      virtual ~InputBitstream() { }
      InputBitstream(const InputBitstream &src);
    
      void resetToStart();
    
      // interface for decoding
      void        pseudoRead      ( uint32_t uiNumberOfBits, uint32_t& ruiBits );
      void        read            ( uint32_t uiNumberOfBits, uint32_t& ruiBits );
      void        readByte        ( uint32_t &ruiBits )
      {
        CHECK( m_fifo_idx >= m_fifo.size(), "FIFO exceeded" );
        ruiBits = m_fifo[m_fifo_idx++];
    #if ENABLE_TRACING
        m_numBitsRead += 8;
    #endif
      }
    
      void        peekPreviousByte( uint32_t &byte )
      {
        CHECK( m_fifo_idx == 0, "FIFO empty" );
        byte = m_fifo[m_fifo_idx - 1];
      }
    
      uint32_t        readOutTrailingBits ();
      uint8_t getHeldBits  ()          { return m_held_bits;          }
      OutputBitstream& operator= (const OutputBitstream& src);
      uint32_t  getByteLocation              ( )                     { return m_fifo_idx                    ; }
    
      // Peek at bits in word-storage. Used in determining if we have completed reading of current bitstream and therefore slice in LCEC.
      uint32_t        peekBits (uint32_t uiBits) { uint32_t tmp; pseudoRead(uiBits, tmp); return tmp; }
    
      // utility functions
      uint32_t read(uint32_t numberOfBits)      { uint32_t tmp; read(numberOfBits, tmp); return tmp; }
      uint32_t readByte()                   { uint32_t tmp; readByte( tmp ); return tmp; }
      uint32_t getNumBitsUntilByteAligned() { return m_num_held_bits & (0x7); }
      uint32_t getNumBitsLeft()             { return 8*((uint32_t)m_fifo.size() - m_fifo_idx) + m_num_held_bits; }
      InputBitstream *extractSubstream( uint32_t uiNumBits ); // Read the nominated number of bits, and return as a bitstream.
      uint32_t  getNumBitsRead()            { return m_numBitsRead; }
      uint32_t  readByteAlignment();
    
      void      pushEmulationPreventionByteLocation ( uint32_t pos )                         { m_emulationPreventionByteLocation.push_back( pos ); }
      uint32_t      numEmulationPreventionBytesRead     ()                                   { return (uint32_t) m_emulationPreventionByteLocation.size();    }
      const std::vector<uint32_t> &getEmulationPreventionByteLocation  () const              { return m_emulationPreventionByteLocation;           }
      uint32_t      getEmulationPreventionByteLocation  ( uint32_t idx )                         { return m_emulationPreventionByteLocation[ idx ];    }
      void      clearEmulationPreventionByteLocation()                                   { m_emulationPreventionByteLocation.clear();          }
      void      setEmulationPreventionByteLocation  ( const std::vector<uint32_t> &vec )     { m_emulationPreventionByteLocation = vec;            }
    
      const std::vector<uint8_t> &getFifo() const { return m_fifo; }
            std::vector<uint8_t> &getFifo()       { return m_fifo; }
    };
    
    //! \}
    
    #endif