/*************************************************************************
    bbDMUX by Brent Beyeler, beyeler@home.com
*************************************************************************/

#include <vector>
#include "bits.h"

#undef SHOW_RESYNCHS

#define MPEG_PROGRAM_END_CODE    0x000001B9
#define PACK_START_CODE          0x000001BA
#define SYSTEM_HEADER_START_CODE 0x000001BB
#define PACKET_START_CODE_PREFIX 0x000001

#define PROGRAM_ASSOCIATION_TABLE 0x0000
#define CONDITIONAL_ACCESS_TABLE  0x0001
#define NULL_PACKET               0x1FFF

#define TRANSPORT_SYNC_BYTE      0x47
#define PROGRAM_STREAM_MAP       0xBC
#define PRIVATE_STREAM_1         0xBD
#define PADDING_STREAM           0xBE
#define PRIVATE_STREAM_2         0xBF
#define ECM_STREAM               0xF0
#define EMM_STREAM               0xF1
#define PROGRAM_STREAM_DIRECTORY 0xFF
#define DSMCC_STREAM             0xF2
#define ITUTRECH222TYPEE_STREAM  0xF8

#define SUBSTREAM_AC3_0          0x80
#define SUBSTREAM_AC3_8          0x87
#define SUBSTREAM_DTS_0          0x88
#define SUBSTREAM_DTS_8          0x8F
#define SUBSTREAM_PCM_0          0xA0
#define SUBSTREAM_PCM_F          0xAF
#define SUBSTREAM_SUBPIC_0       0x20
#define SUBSTREAM_SUBPIC_1F      0x3F

namespace Mpeg2
{

class Demux
{
  const unsigned int BufferSize;
public:
  enum enVideoType {
    UndefVideo=0,
    VOB,
    MPEG2,
    MPEG1,
    AVI
  };
  enum enAudioType {
    UndefAudio=0,
    mp2,
    ac3,
    pcm
  };
  enum enAspectRatio {
    UndefAspect=0,
    Letterbox, // 4:3
    Widescreen // 16/9
  };
  enum enContainerType {
    UndefConainer=0,
    TransportStream,
    ProgramStream
  };
  template < class Type > class Base {
    unsigned int iStreamID;
    unsigned int iSubstreamID;
    Type         type;
  };
  class Video : public Base<enVideoType> {
    unsigned int  iWidth;
    unsigned int  iHeight;
    enAspectRatio ratio;
  };
  class Audio : public Base<enAudioType>{
  };
  class Subtitle : Base<char>{
  };
  class Stream {
    public:
     Stream ( );
    ~Stream ( );
    void setLastMessage ( const char * );

    unsigned long   iFileSize;
    char           *pFileName;
    enContainerType type;

    // the fllowing two lines are for reporting.
    char *pLastMessage;
    in    iErrorCode; // 0 == Ok
    std::vector<Video>     videoStreams;
    std::vector<Audio>     audioStreams;
    std::vector<Subtitle>  subtitleStreams;
  };

   Demux ( );
  ~Demux ( );

  int demuxAllStreams   ( );
  Stream *getStreamInfo ( );
    
  const char *main ( int, char ** );

protected:
  void debugOut ( const char *, ... );

  struct stream_entry {
    unsigned long stream_id;
    unsigned long substream_id;
    unsigned long stream_packets;
    unsigned long stream_bytes;
    int stream_encrypted;
    int stream_found;
    int pcm_bytes;
    int subpic_bytes;
    int ac3_bytes;
    int dts_bytes;
  };
  bool writeBuffer ( );
  bool flushBuffer ( );
  const char *transportStream ( char *, int, int );

  Bits   m_bitStream;
  Stream m_streamInfo;

  unsigned char *m_pBuffer; // [ const BufferSize = 32768 ]
  int   m_iBufferIdx;
  FILE *m_pOutputFile;
  char *m_pOutputFileName;
  bool  m_bVobFlag;
};

}; // End namespace Mpeg2


