/*
* GPAC - Multimedia Framework C SDK
*
* Authors: Jean Le Feuvre
* Copyright (c) Telecom ParisTech 2000-2012
* All rights reserved
*
* This file is part of GPAC / RTP input module
*
* GPAC is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* GPAC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef RTP_IN_H
#define RTP_IN_H
/*module interface*/
#include <gpac/modules/service.h>
#ifndef GPAC_DISABLE_STREAMING
#include <gpac/thread.h>
#include <gpac/constants.h>
#include <gpac/base_coding.h>
/*IETF lib*/
#include <gpac/ietf.h>
#define RTP_BUFFER_SIZE 0x100000ul
#define RTSP_BUFFER_SIZE 5000
#define RTSP_TCP_BUFFER_SIZE 0x100000ul
#define RTSP_LANGUAGE "English"
/*the rtsp/rtp client*/
typedef struct
{
/*the service we're responsible for*/
GF_ClientService *service;
/*the one and only IOD*/
GF_Descriptor *session_desc;
/*RTSP sessions*/
GF_List *sessions;
/*RTP/RTCP media channels*/
GF_List *channels;
/*sdp downloader*/
GF_DownloadSession * dnload;
/*initial sdp download if any (temp storage)*/
struct _sdp_fetch *sdp_temp;
/*RTSP communication/deinterleaver thread*/
GF_Mutex *mx;
GF_Thread *th;
u32 th_state;
/*RTSP config*/
/*transport mode. 0 is udp, 1 is tcp, 3 is tcp if unreliable media */
u32 transport_mode;
/*default RTSP port*/
u16 default_port;
/*signaling timeout in msec*/
u32 time_out;
/*udp timeout in msec*/
u32 udp_time_out;
/*packet drop emulation*/
u32 first_packet_drop;
u32 frequency_drop;
/*for single-object control*/
u32 media_type;
/*session state data, formatyed as "data:application/sdp;SDPDATA"*/
char *session_state_data;
/*if set ANNOUNCE (sent by server) will be handled*/
// Bool handle_announce;
Double last_ntp;
Bool session_migration;
Bool is_scalable;
u32 cur_mid;
} RTPClient;
enum
{
RTSP_AGG_CONTROL = 1,
RTSP_TCP_FLUSH = 1<<1,
RTSP_FORCE_INTER = 1<<2,
RTSP_WAIT_REPLY = 1<<3,
RTSP_DSS_SERVER = 1<<4,
RTSP_AGG_ONLY = 1<<5,
};
/*rtsp session*/
typedef struct _rtp_session
{
u32 flags;
/*owner*/
RTPClient *owner;
/*RTSP session object*/
GF_RTSPSession *session;
/*session ID for aggregated stream control*/
char *session_id;
/*session control string*/
char *control;
/*response object*/
GF_RTSPResponse *rtsp_rsp;
Double last_range;
u32 command_time;
GF_List *rtsp_commands;
GF_Err connect_error;
/*SAT>IP uses a non-conformant version of RTSP*/
Bool satip;
char *satip_server;
} RTSPSession;
/*creates new RTSP session handler*/
RTSPSession *RP_NewSession(RTPClient *rtp, char *session_control);
/*disconnects and destroy RTSP session handler - if immediate_shutdown do not wait for response*/
void RP_DelSession(RTSPSession *sess);
/*check session by control string*/
RTSPSession *RP_CheckSession(RTPClient *rtp, char *control);
void RP_SetupObjects(RTPClient *rtp);
void RP_ProcessCommands(RTSPSession *sess);
void RP_SendMessage(GF_ClientService *service, GF_Err e, const char *message);
/*RTP channel state*/
enum
{
/*channel is setup and waits for connection request*/
RTP_Setup,
/*waiting for server reply*/
RTP_WaitingForAck,
/*connection OK*/
RTP_Connected,
/*data exchange on this service/channel*/
RTP_Running,
/*deconnection OK - a download channel can automatically disconnect when download is done*/
RTP_Disconnected,
/*service/channel is not (no longer) available/found and should be removed*/
RTP_Unavailable,
RTP_SessionResume
};
/*rtp channel flags*/
enum
{
/*static RTP channel flags*/
/*set if sending RTCP reports is enabled (default)*/
RTP_ENABLE_RTCP = 1,
/*set if stream control possible*/
RTP_HAS_RANGE = (1<<1),
/*set if RTP over RTSP*/
RTP_INTERLEAVED = (1<<2),
/*broadcast emultaion is on (no time control for stream)*/
RTP_FORCE_BROADCAST = (1<<3),
/*RTP channel runtime flags*/
/*set if next command (PLAY/PAUSE) is to be skipped (aggregation control)*/
RTP_SKIP_NEXT_COM = (1<<4),
/*indicates whether channel creation has been acknowledged or not
this is needed to filter real channel_connect calls from RTSP re-setup (after STOP) ones*/
RTP_CONNECTED = (1<<5),
/*EOS signaled (RTCP or range-based)*/
RTP_EOS = (1<<6),
/*RTP stream is using mobileIP - this will disable RTP over RTSP*/
RTP_MOBILEIP = (1<<7),
};
enum
{
RTP_SET_TIME_NONE = 0,
RTP_SET_TIME_RTP,
RTP_SET_TIME_RTP_SEEK,
};
#define RTCP_DEFAULT_TIMEOUT_MS 5000
/*rtp channel*/
typedef struct
{
/*module*/
RTPClient *owner;
/*channel flags*/
u32 flags;
/*control session (may be null)*/
RTSPSession *rtsp;
/*session ID for independent stream control*/
char *session_id;
/*RTP channel*/
GF_RTPChannel *rtp_ch;
/*depacketizer*/
GF_RTPDepacketizer *depacketizer;
/*logical app channel*/
LPNETCHANNEL channel;
u32 status;
u32 ES_ID, OD_ID;
char *control;
/*rtp receive buffer*/
char buffer[RTP_BUFFER_SIZE];
/*set at play/seek stages to sync app NPT to RTP time (RTSP) or NTP to RTP (RTCP)
*/
u32 check_rtp_time;
/*can we control the stream ?*/
Double range_start, range_end;
/*current start time in npt (for pause/resume)*/
Double current_start;
Bool paused;
Bool rtcp_init;
/*UDP time-out detection*/
u32 last_udp_time;
/*RTP stats*/
u32 rtp_bytes, rtcp_bytes, stat_start_time, stat_stop_time;
u32 ts_res;
/*stream id*/
u32 mid;
u32 prev_stream;
u32 next_stream;
u32 base_stream;
u32 rtcp_check_start;
u64 ts_offset;
/*SAT>IP M2TS demux*/
GF_InputService *satip_m2ts_ifce;
Bool satip_m2ts_service_connected;
} RTPStream;
GF_Err RP_ConnectServiceEx(GF_InputService *plug, GF_ClientService *serv, const char *url, Bool skip_migration);
/*creates new RTP stream from SDP info*/
RTPStream *RP_NewStream(RTPClient *rtp, GF_SDPMedia *media, GF_SDPInfo *sdp, RTPStream *input_stream);
/*creates new SAT>IP stream*/
RTPStream *RP_NewSatipStream(RTPClient *rtp, const char *server_ip);
/*destroys RTP stream */
void RP_DeleteStream(RTPStream *ch);
/*resets stream state and inits RTP sockets if ResetOnly is false*/
GF_Err RP_InitStream(RTPStream *ch, Bool ResetOnly);
/*RTSP -> RTP de-interleaving callback*/
GF_Err RP_DataOnTCP(GF_RTSPSession *sess, void *cbck, char *buffer, u32 bufferSize, Bool IsRTCP);
/*send confirmation of connection - if no error, also setup SL based on payload*/
void RP_ConfirmChannelConnect(RTPStream *ch, GF_Err e);
/*fetch sdp file - stream is the RTP channel this sdp describes, or NULL if session sdp*/
void RP_FetchSDP(RTPClient *rtp, char *url, RTPStream *stream, char *original_url);
/*locate RTP stream by channel or ES_ID or control*/
RTPStream *RP_FindChannel(RTPClient *rtp, LPNETCHANNEL ch, u32 ES_ID, char *es_control, Bool remove_stream);
/*adds channel to session identified by session_control. If no session exists, the session is created if needed*/
GF_Err RP_AddStream(RTPClient *rtp, RTPStream *stream, char *session_control);
/*removes stream from session*/
void RP_RemoveStream(RTPClient *rtp, RTPStream *ch);
/*reads input socket and process*/
void RP_ReadStream(RTPStream *ch);
/*parse RTP payload for MPEG4*/
void RP_ParsePayloadMPEG4(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size);
/*parse RTP payload for MPEG12*/
void RP_ParsePayloadMPEG12(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size);
/*parse RTP payload for AMR*/
void RP_ParsePayloadAMR(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size);
/*parse RTP payload for H263+*/
void RP_ParsePayloadH263(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size);
/*parse RTP payload for 3GPP Text*/
void RP_ParsePayloadText(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size);
/*parse RTP payload for H264/AVC*/
void RP_ParsePayloadH264(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size);
/*parse RTP payload for LATM audio*/
void RP_ParsePayloadLATM(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size);
/*load SDP and setup described media in SDP. If stream is null this is the root
SDP and IOD will be extracted, otherwise this a channel SDP*/
void RP_LoadSDP(RTPClient *rtp, char *sdp, u32 sdp_len, RTPStream *stream);
/*returns 1 if payload type is supported*/
u32 payt_get_type(RTPClient *rtp, GF_RTPMap *map, GF_SDPMedia *media);
/*setup payload type, returns 1 if success, 0 otherwise (in which case the stream will be deleted)*/
Bool payt_setup(RTPStream *st, GF_RTPMap *map, GF_SDPMedia *media);
/*RTSP signaling is handled by stacking commands and processing them
in the main session thread. Each RTSP command has an associated private stack as follows*/
/*describe stack for single channel (not for session)*/
typedef struct
{
u32 ES_ID;
LPNETCHANNEL channel;
char *esd_url;
} ChannelDescribe;
typedef struct
{
RTPStream *ch;
GF_NetworkCommand com;
} ChannelControl;
/*RTSP signaling */
Bool RP_PreprocessDescribe(RTSPSession *sess, GF_RTSPCommand *com);
GF_Err RP_ProcessDescribe(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e);
void RP_ProcessSetup(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e);
void RP_ProcessTeardown(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e);
Bool RP_PreprocessUserCom(RTSPSession *sess, GF_RTSPCommand *com);
void RP_ProcessUserCommand(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e);
/*send describe - if esd_url is given, this is a describe on es*/
void RP_Describe(RTSPSession *sess, char *esd_url, LPNETCHANNEL channel);
/*send setup for stream*/
void RP_Setup(RTPStream *ch);
/*filter setup if no session (rtp only), otherwise setup channel - ch_desc may be NULL
if channel association is already done*/
GF_Err RP_SetupChannel(RTPStream *ch, ChannelDescribe *ch_desc);
/*send command for stream - handles aggregation*/
void RP_UserCommand(RTSPSession *sess, RTPStream *ch, GF_NetworkCommand *command);
/*disconnect the session - if @ch, only the channel is teardown*/
void RP_Teardown(RTSPSession *sess, RTPStream *ch);
/*emulate IOD*/
GF_Descriptor *RP_EmulateIOD(RTPClient *rtp, const char *sub_url);
/*sdp file downloader*/
typedef struct _sdp_fetch
{
RTPClient *client;
/*when loading a channel from SDP*/
RTPStream *chan;
char *remote_url;
char *original_url;
} SDPFetch;
void RP_SaveSessionState(RTPClient *rtp);
#endif /*GPAC_DISABLE_STREAMING*/
#endif