

#ifndef VALIB_PARSER_H
#define VALIB_PARSER_H

#include "spk.h"
#include "data.h"

struct HeaderInfo;
class HeaderParser;
class FrameParser;

class StreamBuffer;










































































































































struct HeaderInfo
{
  Speakers spk;
  size_t   frame_size;
  size_t   scan_size;
  size_t   nsamples;
  int      bs_type;
  uint16_t spdif_type;

  HeaderInfo(): 
    spk(spk_unknown),
    frame_size(0),
    scan_size(0),
    nsamples(0),
    bs_type(0),
    spdif_type(0)
    {};

  inline void drop()
  {
    spk        = spk_unknown;
    frame_size = 0;
    scan_size  = 0;
    nsamples   = 0;
    bs_type    = BITSTREAM_NONE;
    spdif_type = 0;
  }
};

class HeaderParser
{
public:
  HeaderParser() {};
  virtual ~HeaderParser() {};

  virtual size_t   header_size() const = 0;
  virtual size_t   min_frame_size() const = 0;
  virtual size_t   max_frame_size() const = 0;
  virtual bool     can_parse(int format) const = 0;

  virtual bool     parse_header(const uint8_t *hdr, HeaderInfo *h = 0) const = 0;
  virtual bool     compare_headers(const uint8_t *hdr1, const uint8_t *hdr2) const = 0;
  virtual size_t   header_info(const uint8_t *hdr, char *buf, size_t size) const;
};











































































class FrameParser
{
public:
  FrameParser() {};
  virtual ~FrameParser() {};

  virtual const HeaderParser *header_parser() const = 0;

  
  

  virtual void reset() = 0;
  virtual bool parse_frame(uint8_t *frame, size_t size) = 0;

  
  

  virtual Speakers  get_spk() const = 0;

  virtual samples_t get_samples() const = 0;
  virtual size_t    get_nsamples() const = 0;

  virtual uint8_t  *get_rawdata() const = 0;
  virtual size_t    get_rawsize() const = 0;

  
  

  virtual size_t stream_info(char *buf, size_t size) const = 0;
  virtual size_t frame_info(char *buf, size_t size) const = 0;
};
















































































































































class StreamBuffer
{
protected:
  

  const HeaderParser *parser;    
  size_t header_size;            
  size_t min_frame_size;         
  size_t max_frame_size;         

  
  
  
  
  

  DataBuf  buf;

  uint8_t *header_buf;           
  HeaderInfo hinfo;              

  uint8_t *sync_buf;             
  size_t   sync_size;            
  size_t   sync_data;            

  

  uint8_t   *debris;             
  size_t     debris_size;        

  uint8_t   *frame;              
  size_t     frame_size;         
  size_t     frame_interval;     

  

  bool in_sync;                  
  bool new_stream;               
  int  frames;                   

  bool sync(uint8_t **data, uint8_t *data_end);

public:
  StreamBuffer();
  StreamBuffer(const HeaderParser *hparser);
  virtual ~StreamBuffer();

  
  

  bool set_parser(const HeaderParser *parser);
  const HeaderParser *get_parser() const { return parser; }
  void release_parser();

  
  

  void reset();
  bool load(uint8_t **data, uint8_t *end);
  bool load_frame(uint8_t **data, uint8_t *end);
  bool flush();

  
  

  bool is_in_sync()             const { return in_sync;         }
  bool is_new_stream()          const { return new_stream;      }
  bool is_frame_loaded()        const { return frame_size  > 0; }
  bool is_debris_exists()       const { return debris_size > 0; }

  
  

  const uint8_t *get_buffer()   const { return sync_buf;       }
  size_t   get_buffer_size()    const { return sync_data;      }

  uint8_t *get_debris()         const { return debris;         }
  size_t   get_debris_size()    const { return debris_size;    }

  Speakers get_spk()            const { return hinfo.spk;      }
  uint8_t *get_frame()          const { return frame;          }
  size_t   get_frame_size()     const { return frame_size;     }
  size_t   get_frame_interval() const { return frame_interval; }

  int get_frames() const { return frames; }
  size_t stream_info(char *buf, size_t size) const;
  HeaderInfo header_info() const { return hinfo; }
};

#endif
