/*
   File: mpeg2buff.hh

   By: Alex Theo de Jong
   Created: February 1996

   Description:
   "Multi-Threading Save" read/write buffer
*/


#ifndef __mpeg2buff_hh
#define __mpeg2buff_hh

#ifdef __GNUG__
#pragma interface
#endif

#include <unistd.h>
#include <sys/time.h>

class Memory {
 private:
  // Normal memory space
  unsigned char *mem_min, *mem_max, *mem_begin, *mem_end;
  short end_ahead;
 protected:
  int mem_size;
 protected:
  Memory(int size);
  ~Memory();
  int unused();
  int put(unsigned char* data, int size);
  int get(unsigned char* data, int size);
  int reset();
  unsigned char getchr() ;
  int mem_skip(int bytes);
 public:
  int used();
  // USE THESE IN COMBINATION WITH waitforbytes!!!!
  unsigned int getbyte();
#if defined(IRIX) && !defined(__GNUG__)
  // Only with Native SGI C++ Compiler
  unsigned int value; // used in getbits32
  unsigned int getbits32(){ 
    return (((((value=getchr()<<24)) |= (getchr()<<16)) |= (getchr()<<8)) |= getchr());
  }
#else
  // unsigned int getword(){ return ((getchr() << 8) | getchr()); }
  // unsigned int getbits24(){ return ((getchr() << 16) | (getchr() << 8) | getchar()); }
  unsigned int getbits32();
#endif
};


class Mpeg2Buffer : public Memory {
 private:
  int rsize;  // variable to be used in waitforbytes
  Condition memory_in_cond, memory_out_cond;
  MutexLock mem_lock;
 protected:
  void lock();
  void unlock();
  void wait_write();
  void wait_read();
  void signal_write();
  void signal_read();
  int completed;
 public:
  Mpeg2Buffer(int size);
  ~Mpeg2Buffer();
  int close();
  int waitforbytes(int size);
  int available();
  int maximum() ;
  void signal_buffer();
  // Normal read/write operations
  int read(unsigned char* data, int size);
  int write(unsigned char* data, int size);
  int skipbytes(int size);
};


class Mpeg2Input : public Mpeg2Buffer {
  int fd;
  int buffer_size, bitrate;
  athr_t id;
 public:
  Mpeg2Input(const char* filename, int size, int bitrate=0);
  ~Mpeg2Input(){ athr_join(id); ::close(fd); }
  static void* filereader(Mpeg2Input*);
};


class Mpeg2Timer {
  MutexLock timer_lock;
  Condition timer_cond;
  timespec time;
  timeval time_new;
  timeval time_out;
 protected:
  void lock();
  void unlock();
 public:
  Mpeg2Timer();
  ~Mpeg2Timer();
  int wait(int interval_usec);     // use while and yield
  int waitcond(int interval_usec); // use condition
};

#endif // __mpeg2buff_hh
