/* * $Id$ * * Copyright (C) 2002-2003 Fhg Fokus * * This file is part of sems, a free SIP media server. * * sems is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * sems 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RtpStream_h_ #define _RtpStream_h_ #include "AmSdp.h" #include "AmThread.h" #include "SampleArray.h" #include "AmRtpPacket.h" #include "AmEvent.h" #include #include #include #include using std::string; using std::map; using std::auto_ptr; #define DEAD_RTP_TIME (5*60) /* 5 minutes */ // return values of AmRtpStream::receive #define RTP_EMPTY 0 // no rtp packet available #define RTP_PARSE_ERROR -1 // error while parsing rtp packet #define RTP_TIMEOUT -2 // last received packet is too old #define RTP_DTMF -3 // dtmf packet has been received #define RTP_BUFFER_SIZE -4 // buffer overrun #define RTP_UNKNOWN_PL -5 // unknown payload struct amci_payload_t; class AmAudio; class AmSession; class SdpPayload; class AmJitterBuffer; /** * \brief RTP implementation * * Rtp stream high level interface. */ class AmRtpStream { protected: static int next_port; static AmMutex port_mut; static int getNextPort(); AmSharedVar runcond; AmMutex runmutex; /** Internal payload (only different from payload if using dynamic payloads). */ int int_payload; /** Remote payload (only different from int_payload if using dynamic payloads) */ int payload; unsigned int sequence; /** Payload of last received packet. Usefull to detect talk spurt, looking for comfort noise packets. */ int last_payload; string format_parameters; string r_host; unsigned short r_port; #ifdef SUPPORT_IPV6 struct sockaddr_storage r_saddr; struct sockaddr_storage l_saddr; #else struct sockaddr_in r_saddr; struct sockaddr_in l_saddr; #endif unsigned short l_port; int l_sd; struct timeval last_recv_time; /** the offset RTP receive TS <-> audio_buffer TS */ unsigned int recv_offset; /** the recv_offset initialized ? */ bool recv_offset_i; // unsigned int l_ssrc; unsigned int r_ssrc; bool r_ssrc_i; /** symmetric RTP */ bool passive; // passive mode ? AmSharedVar first_recved; // first packet received ? /** Payload type for telephone event */ auto_ptr telephone_event_pt; AmJitterBuffer *m_main_jb; AmJitterBuffer *m_telephone_event_jb; AmSession* session; /** Initializes a new random local port, and sets own attributes properly. */ void setLocalPort(); /* get next packet in buffer */ int nextAudioPacket(AmRtpPacket& p, unsigned int ts, unsigned int ms); public: /** Mute */ bool mute; bool begin_talk; int send( unsigned int ts, unsigned char* buffer, unsigned int size ); int receive( unsigned char* buffer, unsigned int size, unsigned int *ts, unsigned int audio_buffer_ts, unsigned int ms); /** Allocates resources for future use of RTP. */ AmRtpStream(AmSession* _s=0); /** Stops the stream and frees all resources. */ virtual ~AmRtpStream(); /** * This function must be called before setLocalPort, because * setLocalPort will bind the socket and it will be not * possible to change the IP later */ void setLocalIP(const string& ip); /** * Gets RTP port number. If no RTP port in assigned, assigns a new one. * @return local RTP port. */ int getLocalPort(); /** * Gets remote RTP port. * @return remote RTP port. */ int getRPort(); /** * Gets remote host IP. * @return remote host IP. */ string getRHost(); /** * Set remote IP & port. */ void setRAddr(const string& addr, unsigned short port); /** Symmetric RTP: passive mode ? */ void setPassiveMode(bool p) { passive = p; } /** * Set remote telephone event * payload type */ void setTelephoneEventPT(const SdpPayload *pt) { telephone_event_pt.reset(pt); } int getTelephoneEventRate(); /** * Enables RTP stream. * @param sdp_payload payload from the SDP message. * @warning start() must have been called so that play and record work. * @warning It should be called only if the stream has been completly initialized, * @warning and only once per session. Use resume() then. */ virtual void init(const SdpPayload* sdp_payload); /** * Stops RTP stream. */ void pause(); /** * Resume a paused RTP stream. */ void resume(); /** * Report an ICMP error. */ void icmpError(); /** * Insert an RTP packet to the buffer. * Note: memory is owned by this instance. */ void bufferPacket(const AmRtpPacket* p); virtual unsigned int bytes2samples(unsigned int) const = 0; }; /** \brief represents info about an \ref AmRtpStream */ struct AmRtpStreamInfo { enum StreamType { ST_Receive=1, ST_Send=2, ST_Duplex=3 }; StreamType type; AmAudio* audio_play; AmAudio* audio_rec; bool ts_offset_i; unsigned int ts_offset; AmRtpStreamInfo(StreamType type, AmAudio* audio_play = NULL, AmAudio* audio_rec = NULL); }; class AmRtpTimeoutEvent : public AmEvent { public: AmRtpTimeoutEvent() : AmEvent(0) { } ~AmRtpTimeoutEvent() { } }; #endif // Local Variables: // mode:C++ // End: