/* getbits.c, bit level routines                                            */

/* Copyright (C) 1994, MPEG Software Simulation Group. All Rights Reserved. */

/*
 * Disclaimer of Warranty
 *
 * These software programs are available to the user without any license fee or
 * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
 * any and all warranties, whether express, implied, or statuary, including any
 * implied warranties or merchantability or of fitness for a particular
 * purpose.  In no event shall the copyright-holder be liable for any
 * incidental, punitive, or consequential damages of any kind whatsoever
 * arising from the use of these programs.
 *
 * This disclaimer of warranty extends to the user of these programs and user's
 * customers, employees, agents, transferees, successors, and assigns.
 *
 * The MPEG Software Simulation Group does not represent or warrant that the
 * programs furnished hereunder are free of infringement of any third-party
 * patents.
 *
 * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
 * are subject to royalty fees to patent holders.  Many of these patents are
 * general enough such that they are unavoidable regardless of implementation
 * design.
 *
 */

#include <stdlib.h>

#include "config.h"
#include "global.h"


/* to mask the n least significant bits of an integer */

static unsigned int msk[33] =
{
  0x00000000,0x00000001,0x00000003,0x00000007,
  0x0000000f,0x0000001f,0x0000003f,0x0000007f,
  0x000000ff,0x000001ff,0x000003ff,0x000007ff,
  0x00000fff,0x00001fff,0x00003fff,0x00007fff,
  0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
  0x000fffff,0x001fffff,0x003fffff,0x007fffff,
  0x00ffffff,0x01ffffff,0x03ffffff,0x07ffffff,
  0x0fffffff,0x1fffffff,0x3fffffff,0x7fffffff,
  0xffffffff
};


/* initialize buffer, call once before first getbits or showbits */

void initbits()
{
  ld->incnt = 0;
  ld->rdptr = ld->rdbfr + 2048;
  ld->bitcnt = 0;
}

void fillbfr()
{
  int l;

  ld->inbfr[0] = ld->inbfr[8];
  ld->inbfr[1] = ld->inbfr[9];
  ld->inbfr[2] = ld->inbfr[10];
  ld->inbfr[3] = ld->inbfr[11];

  if (ld->rdptr>=ld->rdbfr+2048)
  {
    l = read(ld->infile,ld->rdbfr,2048);
    ld->rdptr = ld->rdbfr;
    if (l<2048)
    {
      if (l<0)
        l = 0;

      while (l & 3)
        ld->rdbfr[l++] = 0;

      while (l<2048)
      {
        ld->rdbfr[l++] = SEQ_END_CODE>>24;
        ld->rdbfr[l++] = SEQ_END_CODE>>16;
        ld->rdbfr[l++] = SEQ_END_CODE>>8;
        ld->rdbfr[l++] = SEQ_END_CODE&0xff;
      }
    }
  }

  for (l=0; l<8; l++)
    ld->inbfr[l+4] = ld->rdptr[l];

  ld->rdptr+= 8;
  ld->incnt+= 64;
}


/* return next n bits (right adjusted) without advancing */

unsigned int showbits(n)
int n;
{
  unsigned char *v;
  unsigned int b;
  int c;

  if (ld->incnt<n)
    fillbfr();

  v = ld->inbfr + ((96 - ld->incnt)>>3);
  b = (v[0]<<24) | (v[1]<<16) | (v[2]<<8) | v[3];
  c = ((ld->incnt-1) & 7) + 25;
  return (b>>(c-n)) & msk[n];
}


/* return next bit (could be made faster than getbits(1)) */

unsigned int getbits1()
{
  return getbits(1);
}


/* advance by n bits */

void flushbits(n)
int n;
{

  ld->bitcnt+= n;
  ld->incnt-= n;
  if (ld->incnt < 0)
    fillbfr();
}


/* return next n bits (right adjusted) */

unsigned int getbits(n)
int n;
{
  unsigned int l;

  l = showbits(n);
  flushbits(n);

  return l;
}
