⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skl_bits.h

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 H
字号:
/********************************************************
 * Some code. Copyright (C) 2003 by Pascal Massimino.   *
 * All Rights Reserved.      (http://skal.planet-d.net) *
 * For Educational/Academic use ONLY. See 'LICENSE.TXT'.*
 ********************************************************/
/*
 * skl_bits.h
 *
 *  bitstream I/O + masking utils
 ********************************************************/

#ifndef _SKL_BITS_H_
#define _SKL_BITS_H_

//////////////////////////////////////////////////////////
// Bit-masking utils
//////////////////////////////////////////////////////////

class SKL_BMASKS {
  public:
    static const SKL_UINT32 And[33];    // (1<<n)-1
    static const SKL_UINT32 Or[33];     // 1<<(n-1)

    static int Is_Power_Of_2(int Value)
      { return (!(Value & (Value-1))); }  // wow!

    static const SKL_BYTE Bit_Sizes[256];
    static int Get_Size(int Value) {
      int Size = 0;
      while (Value>=256) { Value>>=8; Size+=8; }
      return Size + Bit_Sizes[Value];
    }
    // Get_Size() actually returns 'ceil(log2(Value))'
    // So here's a wrapper:
    static int Log2(int Value) { return Get_Size(Value); }
      // and even faster, using IEEE float representation:
    static SKL_INT32 fLog2(float v) {
      SKL_INT32 I = (SKL_INT32&)v;
      return ((I&0x7f800000)>>23) - 127; // extract un-biased 8-bit exponent
    }
    static SKL_INT32 fLog2(SKL_INT32 v) { return fLog2((float)v); }

    static const SKL_BYTE First_Bit_Set[256];
    static int Get_First_Bit_Set_16(int V) {
      SKL_ASSERT(V>0 && V<=0xffff);
      if (V>>8) return First_Bit_Set[(V>>8)];
      else return First_Bit_Set[V]+8;
    }
    static int Get_First_Bit_Set_8(int V) {
      SKL_ASSERT(V>0 && V<=0xff);
      return First_Bit_Set[V];
    }
};

//////////////////////////////////////////////////////////
// These are fast, inlined, MSBF bitstream.
// It heavily supposes you know what you're doing.
// Read/write overflow is *NOT* checked.
//////////////////////////////////////////////////////////

struct SKL_FBB {
  SKL_BYTE  *Buf;
  SKL_INT32  Bits_Left;
  SKL_UINT32 Bits;

  SKL_FBB() {}
  SKL_FBB(const SKL_BYTE *buf) { Init(buf); } // read
  SKL_FBB(SKL_BYTE *buf) { Init(buf); }       // write


  inline void Init(const SKL_BYTE *buf) {
    SKL_ASSERT(buf!=0);
    Buf       = (SKL_BYTE*)buf;
    Bits_Left = 0;
    Bits      = 0x0;
  }
  inline void Copy(const SKL_FBB *In) {
    Buf       = In->Buf;
    Bits_Left = In->Bits_Left;
    Bits      = In->Bits;
  }


    // -- loading bytes/words

  inline SKL_UINT32 Next_Byte() { return *Buf++; }
  inline SKL_UINT32 Next_Word() {
    SKL_UINT32 Val = (Buf[0]<<8) | (Buf[1]);
    Buf += 2;
    return Val;
  }
  inline void Load() {
    SKL_ASSERT(Bits_Left<=24);
    Bits_Left += 8;
    Bits |= Next_Byte() << (32-Bits_Left);
  }
  inline void Load_Word() {
    SKL_ASSERT(Bits_Left<=24);
    Bits_Left += 16;
    Bits |= Next_Word() << (32-Bits_Left);
  }

  inline void Check_Bits(int Nb) {  // unsigned
    SKL_ASSERT(Nb<=24);
    while (Bits_Left<Nb) Load();
  }
  inline void Check_Bits_Word(int Nb) {  // unsigned
    SKL_ASSERT(Nb<=16);
    if (Bits_Left<Nb) Load_Word();  // only load 1 word
  }

  inline SKL_UINT32 Get_Bits(int Nb) {  // unsigned
    Check_Bits(Nb);
    SKL_INT32 Val = Bits >> (32-Nb);
    Bits <<= Nb;
    Bits_Left -= Nb;
    return Val;
  }
  inline SKL_UINT32 Get_Bits_Word(int Nb) {  // unsigned
    Check_Bits_Word(Nb);
    SKL_INT32 Val = Bits >> (32-Nb);
    Bits <<= Nb;
    Bits_Left -= Nb;
    return Val;
  }

    // -- checking forthcoming bits

  inline SKL_UINT32 See_Bits_Safe(int Nb) const {
    SKL_ASSERT(Bits_Left>=Nb);
    return (Bits >> (32-Nb));
  }
  inline SKL_UINT32 See_Bits(int Nb) {  // unsigned
    Check_Bits(Nb);
    return (Bits >> (32-Nb));
  }
  inline SKL_UINT32 See_Bits_Word(int Nb) {  // unsigned
    Check_Bits_Word(Nb);
    return (Bits >> (32-Nb));
  }

    // -- discard, forward and backward

  inline void Discard(int Nb) {
    Check_Bits(Nb);
    Bits <<= Nb;
    Bits_Left -= Nb;
  }
  inline void Discard_Word(int Nb) {
    Check_Bits_Word(Nb);
    Bits <<= Nb;
    Bits_Left -= Nb;
  }
  inline void Discard_Safe(int Nb) {
    SKL_ASSERT(Bits_Left>=Nb);
    Bits <<= Nb;
    Bits_Left -= Nb;
  }

  inline void Rewind(int Nb)
  {
    SKL_ASSERT(Nb>=0);
    Nb += Bits_Left + 7;
    Buf -= Nb/8;
    Nb = 1 + (Nb&7);
    Bits = Next_Byte()<<(32-Nb);
    Bits_Left = Nb;
  }
  inline void Forward(int Nb)
  {
    SKL_ASSERT(Nb>=0);
    if (Nb>=Bits_Left) {
      Nb -= Bits_Left;
      Buf += Nb/8;
      Bits_Left = 8-(Nb&7);
      Bits = Next_Byte()<<(32-Nb);
    }
    else {
      Bits_Left -= Nb;
      Bits <<= Nb;
    }
  }
  inline void Skip_Bytes(int Nb) {   // warning! unsafe!
    SKL_ASSERT(Is_Aligned());
    Buf += Nb;
  }

  inline int Is_Aligned() const { return !(Bits_Left&7); }
  inline void Align() { if (Bits_Left&7) Discard_Safe( Bits_Left&7 ); }

    // -- positioning

  inline SKL_BYTE *Pos() const { return Buf - Bits_Left/8; }
  inline SKL_SAFE_INT Bit_Pos() const
    { return ((SKL_SAFE_INT)Buf)*8 - Bits_Left; }

    // Safely storing the offset in *bits* would theoretically
    // require 32+8 bits. Using a known reference (Pos0) not far
    // from current position helps avoiding overflow.
    // Note that overflow can only happen if you use a bit buffer
    // bigger than 16.7 Mo :)
  inline SKL_SAFE_INT Safe_Bit_Pos(SKL_BYTE *Pos0) const
    { return ((SKL_SAFE_INT)(Buf-Pos0)*8 - Bits_Left); }


    // -- Writing bits

  inline void Put_Bits(SKL_UINT32 Val, int Nb)
  {
    SKL_ASSERT(Nb<32 && !(Val&~SKL_BMASKS::And[Nb]));
    Bits_Left += Nb;
    if (Bits_Left>32) {
      Bits_Left -= 32;
      Bits |= Val >> Bits_Left;
      *Buf++ = ( Bits>>24 ) & 0xff;
      *Buf++ = ( Bits>>16 ) & 0xff;
      *Buf++ = ( Bits>> 8 ) & 0xff;
      *Buf++ = ( Bits>> 0 ) & 0xff;
      Bits = Val<<(32-Bits_Left);
    }
    else Bits |= Val<<(32-Bits_Left);
  }

  inline void Put_Bits0(int Nb) // emits the bit '0' Nb times
  {
    SKL_ASSERT(Nb>=0);
    Bits_Left += Nb;
    while (Bits_Left>32) {
      Bits_Left -= 32;
      *Buf++ = ( Bits>>24 ) & 0xff;
      *Buf++ = ( Bits>>16 ) & 0xff;
      *Buf++ = ( Bits>> 8 ) & 0xff;
      *Buf++ = ( Bits>> 0 ) & 0xff;
      Bits = 0;
    }
  }
  inline void Put_Bits1(int Nb) // emits the bit '1' Nb times
  {
    SKL_ASSERT(Nb>=0);
    Bits |= SKL_BMASKS::And[32-Bits_Left];
    Bits_Left += Nb;
    while (Bits_Left>32) {
      Bits_Left -= 32;
      *Buf++ = ( Bits>>24 ) & 0xff;
      *Buf++ = ( Bits>>16 ) & 0xff;
      *Buf++ = ( Bits>> 8 ) & 0xff;
      *Buf++ = ( Bits>> 0 ) & 0xff;
      Bits = 0xffffffff;
    }
    Bits &= ~SKL_BMASKS::And[32-Bits_Left];
  }

  inline void Put_Word(SKL_UINT32 Val)
  {
    SKL_ASSERT(Is_Flushed());
    *Buf++ = ( Val>>8 ) & 0xff;
    *Buf++ = ( Val>>0 ) & 0xff;
  }

  inline void Put_DWord(SKL_UINT32 Val)
  {
    SKL_ASSERT(Is_Flushed());
    *Buf++ = ( Val>>24 ) & 0xff;
    *Buf++ = ( Val>>16 ) & 0xff;
    *Buf++ = ( Val>> 8 ) & 0xff;
    *Buf++ = ( Val>> 0 ) & 0xff;
  }

  inline SKL_BYTE *Write_Pos() const { return Buf + Bits_Left/8; }
  inline SKL_SAFE_INT Write_Bit_Pos() const
    { return ((SKL_SAFE_INT)Buf)*8 + Bits_Left; }
  inline SKL_SAFE_INT Safe_Write_Bit_Pos(SKL_BYTE *Pos0) const
    { return ((SKL_SAFE_INT)(Buf-Pos0)*8 + Bits_Left); }

   // -- sync pending bits and align to byte

  inline void Flush_Write() {
    while (Bits_Left>0) {
      *Buf++ = (Bits >> 24) & 0xff;
      Bits <<= 8;
      Bits_Left -= 8;
    }
    Bits_Left = 0;
    SKL_ASSERT(Bits==0);
  }
  inline int Is_Flushed() const { return (Bits_Left==0); }


    // exponential Golomb codes

#if 1

    // Table-based not inlined version

  static const SKL_BYTE  EG_Len[512-16];
  static const SKL_UINT8 UEG_Val[512-16];
  static const SKL_INT8  SEG_Val[512-16];

  SKL_UINT32 UEG();               // unsigned
  SKL_INT32  SEG();               // signed

  static const SKL_UINT16 UEG_Tab[256][2];
  static const SKL_UINT16 SEG_Tab[256][2];

  void Put_UEG(SKL_UINT32 v);   // unsigned
  void Put_SEG(SKL_INT32 v);    // signed

#else

      // Reference, slow but robust, versions

  inline SKL_UINT32 UEG()              // unsigned
  {
    int Len = 0;
    while (!Get_Bits(1)) Len++;
    return (Len==0) ? 0 : (1<<Len)-1 + Get_Bits(Len);
  }

  inline SKL_INT32 SEG()               // signed
  {
    int Len = 0;
    while (!Get_Bits(1)) Len++;
    if (Len==0) return 0;
    SKL_INT32 Val = (1<<Len) | Get_Bits(Len);
    return (Val&1) ? -(Val>>1) : (Val>>1);
  }

  inline void Put_UEG(SKL_UINT32 v)              // unsigned
  {
    if (v) {
      v += 1;
      const int Len = SKL_BMASKS::Log2(v);
      //  Put_Bits(v, 2*Len-1);   <- this could overflow if 2*Len-1>24
      Put_Bits(0, Len-1);
      Put_Bits(v, Len  );
    }
    else Put_Bits(1,1);
  }

  inline void Put_SEG(SKL_INT32 v)               // signed
  {
    if (v) {
      int Len;
      if (v<0) v = 1-2*v;
      else     v = 2*v;
      Len = SKL_BMASKS::Log2(v);
      //  Put_Bits(v, 2*Len-1);   <- this could overflow if 2*Len-1>24
      Put_Bits(0, Len-1);
      Put_Bits(v, Len  );
    }
    else Put_Bits(1,1);
  }

#endif

    // computes code length

  static int UEG_Len(SKL_UINT32 v)              // unsigned
  {
    return 2*SKL_BMASKS::Log2(v+1) - 1;
  }

  static int SEG_Len(SKL_INT32 v)               // signed
  {
    if (v==0) return 1;
    if (v<0) v = 1-2*v;
    else     v = 2*v;
    return 2*SKL_BMASKS::Log2(v) - 1;
  }
};

//////////////////////////////////////////////////////////
// MACRO-ized version
//////////////////////////////////////////////////////////

#define SKL_FBB_DECL             SKL_BYTE *Buf; SKL_INT32 Bits_Left; SKL_UINT32 Bits
#define SKL_FBB_START(FBB)       Buf = (FBB).Buf; Bits_Left = (FBB).Bits_Left; Bits = (FBB).Bits
#define SKL_FBB_STOP(FBB)        (FBB).Buf = Buf; (FBB).Bits_Left = Bits_Left; (FBB).Bits = Bits
#define SKL_FBB_NEXT_WORD        do { Bits_Left+=16; Bits |= ((Buf[0]<<8) | Buf[1])<<(32-Bits_Left); Buf+=2; } while(0)
#define SKL_FBB_LOAD_WORD(NB)    if (Bits_Left<NB) SKL_FBB_NEXT_WORD
#define SKL_FBB_NEXT_BYTE        do { Bits_Left+=16; Bits |= Buf[1]<<(32-Bits_Left); Buf+=1; } while(0)
#define SKL_FBB_LOAD_BYTE(NB)    if (Bits_Left<NB) SKL_FBB_NEXT_BYTE
#define SKL_FBB_BITS(NB)         (Bits>>(32-NB))
#define SKL_FBB_BITS_SIGNED(NB)  (((SKL_INT32)Bits)>>(32-NB))
#define SKL_FBB_CHECK(NB)        while (Bits_Left<NB) SKL_FBB_NEXT_BYTE
#define SKL_FBB_DISCARD(NB)      do { SKL_FBB_CHECK(NB); Bits<<=NB; Bits_Left-= NB; } while(0)
#define SKL_FBB_DISCARD_SAFE(NB) do { Bits<<=NB; Bits_Left-= NB; } while(0)

//////////////////////////////////////////////////////////

#endif  /* _SKL_BITS_H_ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -