/* Copyright (C) 2005-2009 Michel de Boer This program 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. This program 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, see . */ #ifndef _AUDIO_TX_H #define _AUDIO_TX_H // Receive RTP and send audio to soundcard #include #include #include "audio_codecs.h" #include "audio_decoder.h" #include "audio_rx.h" #include "media_buffer.h" #include "rtp_telephone_event.h" #include "user.h" #include "threads/mutex.h" #include "audio_device.h" #include "twinkle_rtp_session.h" #include "twinkle_config.h" #ifdef HAVE_GSM #include #else #include "gsm/inc/gsm.h" #endif using namespace std; using namespace ost; // Forward declarations class t_audio_session; class t_line; class t_audio_tx { private: // audio_session owning this audio transmitter t_audio_session *audio_session; // User profile of user using the line // This is a pointer to the user_config owned by a phone user. // So this pointer should never be deleted. t_user *user_config; // file descriptor audio capture device t_audio_io *playback_device; t_twinkle_rtp_session *rtp_session; // Indicates if this transmitter is part of a 3-way conference bool is_3way; // Indicates if this transmitter is the mixer in a 3-way conference. // The mixer will mix this audio stream with the audio from the other // party and send it to the soundcard. // If the transmitter is part of a 3-way conference, but not the // mixer, then it simply has to send its audio payload to the mixer. bool is_3way_mixer; // Media buffer for media from the other far-end. This buffer is // used by the mixer. t_media_buffer *media_3way_peer_tx; // The peer audio transmitter in a 3-way conference t_audio_tx *peer_tx_3way; // The audio receiver that needs input from this transmitter in // a 3-way conference. t_audio_rx *peer_rx_3way; // Buffer for mixing purposes in 3-way conference. unsigned char *mix_buf_3way; // Mutex to protect 3-way resources t_mutex mtx_3way; // Codec information t_audio_codec codec; map payload2codec; unsigned short ptime; // in milliseconds // Sample rate of sound card. // The sample rate of the sound card is set to the sample rate // used for the initial codec. The far end may dynamically switch // to a codec with another sample rate. This will not change the // sample rate of the sound card! (capture and playback cannot // be done at different sampling rates). unsigned short sc_sample_rate; // Mapping from codecs to decoders map map_audio_decoder; // Buffer to store PCM samples of a received RTP packet unsigned char *sample_buf; // Jitter buffer (PCM). // jitter_buf_len indicates the number of bytes in the jitter buffer. // At the start of playing the samples are stored in the jitter buffer. // Once the buffer is full, all samples are copied to the memory of // the soundcard. From that point the soundcard itself is the jitter // buffer. unsigned char *jitter_buf; unsigned short jitter_buf_len; bool load_jitter_buf; // Buffer to keep last played packets for concealment. unsigned char *conceal_buf[MAX_CONCEALMENT]; unsigned short conceal_buflen[MAX_CONCEALMENT]; // length of packet short conceal_pos; // points to the oldest packet. short conceal_num; // number of retained packets. unsigned short soundcard_buf_size; // Payload type for telephone-event payload. // Some endpoints ignore the payload type that was sent in an // outgoing INVITE and simply sends it with the payload type, // they indicated in the 200 OK. Accept both payloads for // interoperability. int pt_telephone_event; int pt_telephone_event_alt; // Timestamp of previous DTMF tone unsigned long dtmf_previous_timestamp; // Inidicates if the playing thread is running volatile bool is_running; // The thread exits when this indicator is set to true volatile bool stop_running; // Retain a packet (PCM encoded) for possible concealment. void retain_for_concealment(unsigned char *buf, unsigned short len); // Play last num packets again. void conceal(short num); // Erase concealment buffers. void clear_conceal_buf(void); // Play PCM encoded samples // - only_3rd_party indicates if there is only 3rd_party audio available, // i.e. due to jitter, packet loss or silence suppression void play_pcm(unsigned char *buf, unsigned short len, bool only_3rd_party = false); public: // Create the audio transmitter // _fd file descriptor of capture device // _rtp_session RTP socket tp send the RTP stream // _codec audio codec to use // _ptime length of the audio packets in ms // _ptime = 0 means use default ptime value for the codec t_audio_tx(t_audio_session *_audio_session, t_audio_io *_playback_device, t_twinkle_rtp_session *_rtp_session, t_audio_codec _codec, const map &_payload2codec, unsigned short _ptime = 0); ~t_audio_tx(); // Set the is running flag void set_running(bool running); void run(void); // Set the dynamic payload type for telephone events void set_pt_telephone_event(int pt, int pt_alt); // Get phone line belonging to this audio transmitter t_line *get_line(void) const; // Join this transmitter in a 3way conference. // mixer indicates if this transmitter must be the mixer. // - peer_tx is the peer transmitter in a 3-way // - audio_rx is the audio receiver needing the output from this // transmitter for mixing. void join_3way(bool mixer, t_audio_tx *peer_tx, t_audio_rx *peer_rx); // Change the peer rx/tx (NULL to erase) void set_peer_tx_3way(t_audio_tx *peer_tx); void set_peer_rx_3way(t_audio_rx *peer_rx); // Change the mixer role void set_mixer_3way(bool mixer); // Stop the 3-way conference and make it a 1-on-1 call again. void stop_3way(void); // Post media from the peer transmitter for a 3-way mixer. void post_media_peer_tx_3way(unsigned char *media, int len, unsigned short peer_sample_rate); // Returns if this transmitter is the mixer in a 3-way bool get_is_3way_mixer(void) const; }; #endif