#ifndef _GF_IETF_DEV_H_
#define _GF_IETF_DEV_H_
#include <gpac/ietf.h>
#ifndef GPAC_DISABLE_STREAMING
#include <gpac/thread.h>
typedef struct
{
        
        u8 Version;
        
        u8 Padding;
        
        u8 Count;
        
        u8 PayloadType;
        
        u16 Length;
        
        u32 SSRC;
} GF_RTCPHeader;
typedef struct __PRO_item
{
        struct __PRO_item *next;
        u32 pck_seq_num;
        void *pck;
        u32 size;
} GF_POItem;
typedef struct __PO
{
        struct __PRO_item *in;
        u32 head_seqnum;
        u32 Count;
        u32 MaxCount;
        u32 IsInit;
        u32 MaxDelay, LastTime;
} GF_RTPReorder;
GF_RTPReorder *gf_rtp_reorderer_new(u32 MaxCount, u32 MaxDelay);
void gf_rtp_reorderer_del(GF_RTPReorder *po);
void gf_rtp_reorderer_reset(GF_RTPReorder *po);
GF_Err gf_rtp_reorderer_add(GF_RTPReorder *po, const void * pck, u32 pck_size, u32 pck_seqnum);
void *gf_rtp_reorderer_get(GF_RTPReorder *po, u32 *pck_size);
struct __tag_rtp_channel
{
        
        GF_RTSPTransport net_info;
        
        GF_Socket *rtp;
        
        GF_Socket *rtcp;
        
        GF_RTPReorder *po;
        
        u32 last_report_time;
        u32 next_report_time;
        
        u32 last_nat_keepalive_time, nat_keepalive_time_period;
        
        u32 rtp_first_SN;
        
        u32 rtp_time;
        
        u32 CurrentTime;
        
        u32 num_sn_loops;
        
        u8 PayloadType;
        u32 TimeScale;
        
        char *send_buffer;
        u32 send_buffer_size;
        u32 pck_sent_since_last_sr;
        u32 last_pck_ts;
        u32 last_pck_ntp_sec, last_pck_ntp_frac;
        u32 num_pck_sent, num_payload_bytes;
        u32 forced_ntp_sec, forced_ntp_frac;
        Bool no_auto_rtcp;
        
        char *s_name, *s_email, *s_location, *s_phone, *s_tool, *s_note, *s_priv;
        s8 first_SR;
        u32 SSRC;
        u32 SenderSSRC;
        u32 last_pck_sn;
        
        Bool packet_loss;
        char *CName;
        u32 rtcp_bytes_sent;
        
        u32 tot_num_pck_rcv, tot_num_pck_expected;
        
        u32 last_num_pck_rcv, last_num_pck_expected, last_num_pck_loss;
        
        u32 Jitter, ntp_init;
        s32 last_deviance;
        
        u32 last_SR_NTP_sec, last_SR_NTP_frac;
        
        u32 last_SR_rtp_time;
        
        u32 total_pck, total_bytes;
};
u32 gf_rtp_channel_time(GF_RTPChannel *ch);
u32 gf_rtp_get_report_time();
void gf_rtp_get_next_report_time(GF_RTPChannel *ch);
#define GF_RTSP_DEFAULT_BUFFER          2048
#define GF_RTSP_VERSION         "RTSP/1.0"
#define RTSP_WRITE_STEPALLOC    250
#define RTSP_WRITE_ALLOC_STR_WITHOUT_CHECK(buf, buf_size, pos, str)             \
        if (strlen((const char *) str)+pos >= buf_size) {       \
                buf_size += RTSP_WRITE_STEPALLOC;       \
                buf = (char *) gf_realloc(buf, buf_size);               \
        }       \
        strcpy(buf+pos, (const char *) str);            \
        pos += (u32) strlen((const char *) str); \
 
#define RTSP_WRITE_ALLOC_STR(buf, buf_size, pos, str)           \
        if (str){       \
                RTSP_WRITE_ALLOC_STR_WITHOUT_CHECK(buf, buf_size, pos, str);    \
        }       \
        
#define RTSP_WRITE_HEADER(buf, buf_size, pos, type, str)                \
        if( str ) {     \
        RTSP_WRITE_ALLOC_STR(buf, buf_size, pos, type);         \
        RTSP_WRITE_ALLOC_STR(buf, buf_size, pos, ": ");         \
        RTSP_WRITE_ALLOC_STR(buf, buf_size, pos, str);          \
        RTSP_WRITE_ALLOC_STR(buf, buf_size, pos, "\r\n");       \
        }       \
 
#define RTSP_WRITE_INT(buf, buf_size, pos, d, sig)              \
        if (sig < 0) { \
                sprintf(temp, "%d", d);         \
        } else { \
                sprintf(temp, "%d", d);         \
        }       \
        RTSP_WRITE_ALLOC_STR_WITHOUT_CHECK(buf, buf_size, pos, temp);
#define RTSP_WRITE_FLOAT_WITHOUT_CHECK(buf, buf_size, pos, d)           \
        sprintf(temp, "%.4f", d);               \
        RTSP_WRITE_ALLOC_STR_WITHOUT_CHECK(buf, buf_size, pos, temp);
#define RTSP_WRITE_FLOAT(buf, buf_size, pos, d)         \
        sprintf(temp, "%.4f", d);               \
        RTSP_WRITE_ALLOC_STR(buf, buf_size, pos, temp);
#define RTSP_PCK_SIZE                   6000
#define RTSP_TCP_BUF_SIZE               0x10000ul
typedef struct
{
        u8 rtpID;
        u8 rtcpID;
        void *ch_ptr;
} GF_TCPChan;
struct _tag_rtsp_session
{
        
        char *Service;
        
        char *Server;
        
        u16 Port;
        
        u8 ConnectionType;
        
        u8 InterID;
        
        Bool HasTunnel;
        GF_Socket *http;
        char HTTP_Cookie[30];
        u32 CookieRadLen;
        
        GF_Socket *connection;
        u32 SockBufferSize;
        
        u32 NeedConnection;
        
        u32 CSeq;
        
        u32 NbPending;
        
        const char *last_session_id;
        
        u32 RTSP_State;
        char RTSPLastRequest[40];
        
        char TCPBuffer[RTSP_TCP_BUF_SIZE];
        u32 CurrentSize, CurrentPos;
        
        GF_Err (*RTSP_SignalData)(GF_RTSPSession *sess, void *chan, char *buffer, u32 bufferSize, Bool IsRTCP);
        
        char *rtsp_pck_buf;
        u32 rtsp_pck_size;
        u32 pck_start, payloadSize;
        
        GF_List *TCPChannels;
        
        GF_Mutex *mx;
        char *MobileIP;
};
GF_RTSPSession *gf_rtsp_session_new(char *sURL, u16 DefaultPort);
GF_Err gf_rtsp_check_connection(GF_RTSPSession *sess);
GF_Err gf_rtsp_send_data(GF_RTSPSession *sess, char *buffer, u32 Size);
void gf_rtsp_get_body_info(GF_RTSPSession *sess, u32 *body_start, u32 *body_size);
GF_Err gf_rtsp_read_reply(GF_RTSPSession *sess);
GF_Err gf_rtsp_fill_buffer(GF_RTSPSession *sess);
GF_Err gf_rtsp_refill_buffer(GF_RTSPSession *sess);
GF_RTSPTransport *gf_rtsp_transport_parse(char *buffer);
GF_Err gf_rtsp_parse_header(char *buffer, u32 BufferSize, u32 BodyStart, GF_RTSPCommand *com, GF_RTSPResponse *rsp);
void gf_rtsp_set_command_value(GF_RTSPCommand *com, char *Header, char *Value);
void gf_rtsp_set_response_value(GF_RTSPResponse *rsp, char *Header, char *Value);
GF_Err gf_rtsp_set_deinterleave(GF_RTSPSession *sess);
GF_Err gf_rtsp_http_tunnel_start(GF_RTSPSession *sess, char *UserAgent);
GF_Err gp_rtp_builder_do_mpeg4(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
GF_Err gp_rtp_builder_do_h263(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
GF_Err gp_rtp_builder_do_amr(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
#ifndef GPAC_DISABLE_AV_PARSERS
GF_Err gp_rtp_builder_do_mpeg12_video(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
#endif
GF_Err gp_rtp_builder_do_mpeg12_audio(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
GF_Err gp_rtp_builder_do_tx3g(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration, u8 descIndex);
GF_Err gp_rtp_builder_do_avc(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
GF_Err gp_rtp_builder_do_qcelp(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
GF_Err gp_rtp_builder_do_smv(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
GF_Err gp_rtp_builder_do_latm(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration);
GF_Err gp_rtp_builder_do_dims(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration);
GF_Err gp_rtp_builder_do_ac3(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
GF_Err gp_rtp_builder_do_hevc(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize);
#endif 
#endif