#pragma once

//#include "mux_ts.h"

#include "TLock.h"

#include "common.h"
#include "iso_lang.h"
#include "mtime.h"
#include "bits.h"
#include "es.h"
#include "pes.h"
#include "block.h"
#include "buffer_chain.h"

#include "dvbpsi.h"
#include "demux.h"
#include "descriptor.h"
#include "tables/pat.h"
#include "tables/pmt.h"
#include "tables/sdt.h"
#include "descriptors/dr.h"
#include "psi.h"
#include "csa.h"

#ifdef HAVE_BSEARCH
#   define MAX_PMT 64       /* Maximum number of programs. FIXME: I just chose an arbitary number. Where is the maximum in the spec? */
#else
#   define MAX_PMT 1
#endif
#define MAX_PMT_PID 64   /* Maximum pids in each pmt.  FIXME: I just chose an arbitary number. Where is the maximum in the spec? */

struct pmt_map_t   /* Holds the mapping between the pmt-pid/pmt table */
{
	int i_pid;
	unsigned long i_prog;
} ;

struct sdt_desc_t
{
	char *psz_provider;
	char *psz_service_name;  /* name of program */
} ;

struct ts_stream_t
{
	int             i_pid;
	fourcc_t		i_codec;

	int             i_stream_type;
	int             i_stream_id;
	int             i_continuity_counter;
	bool_t			b_discontinuity;

	/* to be used for carriege of DIV3 */
	fourcc_t		i_bih_codec;
	int             i_bih_width, i_bih_height;

	/* Specific to mpeg4 in mpeg2ts */
	int             i_es_id;

	int             i_decoder_specific_info;
	uint8_t         *p_decoder_specific_info;

	/* language is iso639-2T */
	int             i_langs;
	uint8_t         *lang;

	buffer_chain_t  chain_pes;

	mtime_t         i_pes_dts;
	mtime_t         i_pes_length;
	int             i_pes_used;
	bool_t			b_key_frame;
} ;

struct input_t
{
	block_fifo_t   *p_fifo;

	es_format_t    *p_fmt;
	ts_stream_t    *p_sys;
};

struct mux_sys_t
{
	TsMuxParam_t* p_param;

	int             i_pcr_pid;
	input_t			*p_pcr_input;

	TLock			*csa_lock;

	int             i_audio_bound;
	int             i_video_bound;

	bool_t			b_es_id_pid;
	bool_t			b_sdt;
	int             i_pid_video;
	int             i_pid_audio;
	int             i_pid_spu;
	int             i_pid_free; /* first usable pid */

	int             i_tsid;
	int             i_netid;
	int             i_num_pmt;
	int             i_pmtslots;
	int             i_pat_version_number;
	ts_stream_t     pat;

	int             i_pmt_version_number;
	ts_stream_t     pmt[MAX_PMT];
	pmt_map_t       pmtmap[MAX_PMT_PID];
	int             i_pmt_program_number[MAX_PMT];
	sdt_desc_t      sdt_descriptors[MAX_PMT];
	bool_t			b_data_alignment;

	int             i_mpeg4_streams;

	int             i_null_continuity_counter;  /* Needed ? */
	ts_stream_t     sdt;
	dvbpsi_pmt_t    *dvbpmt;

	/* for TS building */
	int64_t             i_bitrate_min;
	int64_t             i_bitrate_max;

	int64_t             i_shaping_delay;
	int64_t             i_pcr_delay;

	int64_t             i_dts_delay;

	bool_t				b_use_key_frames;

	mtime_t             i_pcr;  /* last PCR emited */

	csa_t               *csa;
	int                 i_csa_pkt_size;
	bool_t				b_crypt_audio;
	bool_t				b_crypt_video;
};

/** Muxer structure */
struct  mux_t
{
	//module_t            *p_module;

	//sout_instance_t     *p_sout;

	//char                *psz_mux;
	//config_chain_t          *p_cfg;

	GetTsDataCBFun		  p_access;
	void				  *p_access_user_data;
	//sout_access_out_t   *p_access;

	//int                 (*pf_addstream)( sout_mux_t *, sout_input_t * );
	//int                 (*pf_delstream)( sout_mux_t *, sout_input_t * );
	//int                 (*pf_mux)      ( sout_mux_t * );
	//int                 (*pf_control)  ( sout_mux_t *, int, va_list );

	/* here are all inputs accepted by muxer */
	int            i_nb_inputs;
	input_t        *pp_inputs[10];

	/* mux private */
	mux_sys_t      *p_sys;

	/* XXX private to stream_output.c */
	/* if muxer doesn't support adding stream at any time then we first wait
	*  for stream then we refuse all stream and start muxing */
	//bool  b_add_stream_any_time;
	//bool  b_waiting_stream;
	/* we wait one second after first stream added */
	//mtime_t     i_add_stream_start;
};
