/* 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-2016, 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 AnnexBread.h \brief reading functions for Annex B byte streams */ #pragma once #ifndef __ANNEXBREAD__ #define __ANNEXBREAD__ #include #include #include #include "TLibCommon/CommonDef.h" //! \ingroup TLibDecoder //! \{ class InputByteStream { public: /** * Create a bytestream reader that will extract bytes from * istream. * * NB, it isn't safe to access istream while in use by a * InputByteStream. * * Side-effects: the exception mask of istream is set to eofbit */ InputByteStream(std::istream& istream) : m_NumFutureBytes(0) , m_FutureBytes(0) , m_Input(istream) { istream.exceptions(std::istream::eofbit | std::istream::badbit); } /** * Reset the internal state. Must be called if input stream is * modified externally to this class */ Void reset() { m_NumFutureBytes = 0; m_FutureBytes = 0; } /** * returns true if an EOF will be encountered within the next * n bytes. */ Bool eofBeforeNBytes(UInt n) { assert(n <= 4); if (m_NumFutureBytes >= n) { return false; } n -= m_NumFutureBytes; try { for (UInt i = 0; i < n; i++) { m_FutureBytes = (m_FutureBytes << 8) | m_Input.get(); m_NumFutureBytes++; } } catch (...) { return true; } return false; } /** * return the next n bytes in the stream without advancing * the stream pointer. * * Returns: an unsigned integer representing an n byte bigendian * word. * * If an attempt is made to read past EOF, an n-byte word is * returned, but the portion that required input bytes beyond EOF * is undefined. * */ uint32_t peekBytes(UInt n) { eofBeforeNBytes(n); return m_FutureBytes >> 8*(m_NumFutureBytes - n); } /** * consume and return one byte from the input. * * If bytestream is already at EOF prior to a call to readByte(), * an exception std::ios_base::failure is thrown. */ uint8_t readByte() { if (!m_NumFutureBytes) { uint8_t byte = m_Input.get(); return byte; } m_NumFutureBytes--; uint8_t wanted_byte = m_FutureBytes >> 8*m_NumFutureBytes; m_FutureBytes &= ~(0xff << 8*m_NumFutureBytes); return wanted_byte; } /** * consume and return n bytes from the input. n bytes from * bytestream are interpreted as bigendian when assembling * the return value. */ uint32_t readBytes(UInt n) { uint32_t val = 0; for (UInt i = 0; i < n; i++) { val = (val << 8) | readByte(); } return val; } #if RExt__DECODER_DEBUG_BIT_STATISTICS UInt GetNumBufferedBytes() const { return m_NumFutureBytes; } #endif private: UInt m_NumFutureBytes; /* number of valid bytes in m_FutureBytes */ uint32_t m_FutureBytes; /* bytes that have been peeked */ std::istream& m_Input; /* Input stream to read from */ }; /** * Statistics associated with AnnexB bytestreams */ struct AnnexBStats { UInt m_numLeadingZero8BitsBytes; UInt m_numZeroByteBytes; UInt m_numStartCodePrefixBytes; UInt m_numBytesInNALUnit; UInt m_numTrailingZero8BitsBytes; AnnexBStats& operator+=(const AnnexBStats& rhs) { this->m_numLeadingZero8BitsBytes += rhs.m_numLeadingZero8BitsBytes; this->m_numZeroByteBytes += rhs.m_numZeroByteBytes; this->m_numStartCodePrefixBytes += rhs.m_numStartCodePrefixBytes; this->m_numBytesInNALUnit += rhs.m_numBytesInNALUnit; this->m_numTrailingZero8BitsBytes += rhs.m_numTrailingZero8BitsBytes; return *this; } }; Bool byteStreamNALUnit(InputByteStream& bs, std::vector& nalUnit, AnnexBStats& stats); //! \} #endif