/*
   File: vstream.hh

   By: Alex Theo de Jong
   Created: Fabruary 1996
*/

#ifdef HAVE_MMX
#include <mmx.h>
#endif

#ifndef __vstream_hh
#define __vstream_hh

#ifdef __GNUG__
#pragma interface
#endif

class VideoStream {
  Mpeg2Buffer* inputstream;
  Synchronization* sync;
  unsigned int bfr, value;  // bfr = buffer for integer, value=temporary storage for getbits
  int bytes, bytes_available, chunksize;  // chunk of data to be read from buffer
  int incnt;
  bool file;                // reading from file?
 protected:
#ifndef DEBUG
  void fill(){ if (!incnt) bfr=0; for (; incnt<=24; incnt+=8) bfr|=(getbyte() << (24 - incnt)); }
#else
  void fill();
#endif
//  void refill(){ for (bfr=0, incnt=0; incnt<=24; incnt+=8) bfr|=(getbyte() << (24 - incnt));  }
  void refill() {
    if (bytes > 4) {
       bfr = inputstream->getbits32(); incnt = 32; bytes -= 4;
    } else {
      for (bfr=0, incnt=0; incnt<=24; incnt+=8) bfr|=(getbyte() << (24 - incnt));
    }
  }
  unsigned int getNewByte();
  unsigned int getbyte(void){ return (--bytes<0) ? getNewByte() : inputstream->getbyte(); }
 public:
  VideoStream(const char* filename, int bitrate=0);
  VideoStream(Mpeg2Buffer* input, Synchronization* s);
  ~VideoStream();
  void flushbits(int n){
    if (incnt<n){ n-=incnt; refill(); }
    incnt-=n; 
    bfr<<=n;
  }
  unsigned int showbits(int n);
  unsigned int startcode();
  unsigned int getbits(int n);
  int getposition() const { return (8*(bytes_available-bytes)); }
  int set_read_block_size(int size){ return (size>0) ? (chunksize=size) : -1; }
};

#ifndef DEBUG

inline unsigned int VideoStream::startcode(){
  if (incnt&7){ bfr<<=(incnt&7); incnt-=(incnt&7); }     // Byte align & fill bfr
  fill();
  for (; ((bfr >> 8)!=Packet_start_code_prefix); ){ bfr<<=8; bfr|=getbyte(); }  // search
  return bfr;
}
#endif

inline unsigned int VideoStream::showbits(int n){
  fill();
  return (n==32) ? bfr : (bfr >> (32-n));
}

inline unsigned int VideoStream::getbits(int n){ 
  value = 0;
  if (incnt<n){
    if (incnt){
      n-=incnt;
      value=((bfr >> (32 - incnt)) << n);
    }
    refill();
  }
  value|=(bfr >> (32-n));
  incnt-=n;
  bfr<<=n;
  return value;
}

#endif  // __vstream_hh
