/* * libjingle * Copyright 2004 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TALK_SESSION_MEDIA_CALL_H_ #define TALK_SESSION_MEDIA_CALL_H_ #include #include #include #include #include "talk/media/base/mediachannel.h" #include "talk/media/base/screencastid.h" #include "talk/media/base/streamparams.h" #include "talk/media/base/videocommon.h" #include "webrtc/p2p/base/session.h" #include "webrtc/p2p/client/socketmonitor.h" #include "talk/session/media/audiomonitor.h" #include "talk/session/media/currentspeakermonitor.h" #include "talk/session/media/mediamessages.h" #include "talk/session/media/mediasession.h" #include "webrtc/libjingle/xmpp/jid.h" #include "webrtc/base/messagequeue.h" namespace cricket { struct AudioInfo; class Call; class MediaSessionClient; class BaseChannel; class VoiceChannel; class VideoChannel; class DataChannel; // Can't typedef this easily since it's forward declared as struct elsewhere. struct CallOptions : public MediaSessionOptions { }; // CurrentSpeakerMonitor used to have a dependency on Call. To remove this // dependency, we create AudioSourceContext. CurrentSpeakerMonitor depends on // AudioSourceContext. // AudioSourceProxy acts as a proxy so that when SignalAudioMonitor // in Call is triggered, SignalAudioMonitor in AudioSourceContext is triggered. // Likewise, when OnMediaStreamsUpdate in Call is triggered, // OnMediaStreamsUpdate in AudioSourceContext is triggered. class AudioSourceProxy: public AudioSourceContext, public sigslot::has_slots<> { public: explicit AudioSourceProxy(Call* call); private: void OnAudioMonitor(Call* call, const AudioInfo& info); void OnMediaStreamsUpdate(Call* call, cricket::Session*, const cricket::MediaStreams&, const cricket::MediaStreams&); AudioSourceContext* audio_source_context_; Call* call_; }; class Call : public rtc::MessageHandler, public sigslot::has_slots<> { public: explicit Call(MediaSessionClient* session_client); ~Call(); // |initiator| can be empty. Session* InitiateSession(const buzz::Jid& to, const buzz::Jid& initiator, const CallOptions& options); Session* InitiateSession(const std::string& id, const buzz::Jid& to, const CallOptions& options); void AcceptSession(Session* session, const CallOptions& options); void RejectSession(Session* session); void TerminateSession(Session* session); void Terminate(); bool SendViewRequest(Session* session, const ViewRequest& view_request); void SetVideoRenderer(Session* session, uint32 ssrc, VideoRenderer* renderer); void StartConnectionMonitor(Session* session, int cms); void StopConnectionMonitor(Session* session); void StartAudioMonitor(Session* session, int cms); void StopAudioMonitor(Session* session); bool IsAudioMonitorRunning(Session* session); void StartSpeakerMonitor(Session* session); void StopSpeakerMonitor(Session* session); void Mute(bool mute); void MuteVideo(bool mute); bool SendData(Session* session, const SendDataParams& params, const rtc::Buffer& payload, SendDataResult* result); void PressDTMF(int event); bool StartScreencast(Session* session, const std::string& stream_name, uint32 ssrc, const ScreencastId& screenid, int fps); bool StopScreencast(Session* session, const std::string& stream_name, uint32 ssrc); std::vector sessions(); uint32 id(); bool has_video() const { return has_video_; } bool has_data() const { return has_data_; } bool muted() const { return muted_; } bool video() const { return has_video_; } bool secure() const; bool video_muted() const { return video_muted_; } const std::vector* GetDataRecvStreams(Session* session) const { MediaStreams* recv_streams = GetMediaStreams(session); return recv_streams ? &recv_streams->data() : NULL; } const std::vector* GetVideoRecvStreams(Session* session) const { MediaStreams* recv_streams = GetMediaStreams(session); return recv_streams ? &recv_streams->video() : NULL; } const std::vector* GetAudioRecvStreams(Session* session) const { MediaStreams* recv_streams = GetMediaStreams(session); return recv_streams ? &recv_streams->audio() : NULL; } VoiceChannel* GetVoiceChannel(Session* session) const; VideoChannel* GetVideoChannel(Session* session) const; DataChannel* GetDataChannel(Session* session) const; // Public just for unit tests VideoContentDescription* CreateVideoStreamUpdate(const StreamParams& stream); // Takes ownership of video. void SendVideoStreamUpdate(Session* session, VideoContentDescription* video); // Setting this to false will cause the call to have a longer timeout and // for the SignalSetupToCallVoicemail to never fire. void set_send_to_voicemail(bool send_to_voicemail) { send_to_voicemail_ = send_to_voicemail; } bool send_to_voicemail() { return send_to_voicemail_; } const VoiceMediaInfo& last_voice_media_info() const { return last_voice_media_info_; } // Sets a flag on the chatapp that will redirect the call to voicemail once // the call has been terminated sigslot::signal0<> SignalSetupToCallVoicemail; sigslot::signal2 SignalAddSession; sigslot::signal2 SignalRemoveSession; sigslot::signal3 SignalSessionState; sigslot::signal3 SignalSessionError; sigslot::signal3 SignalReceivedTerminateReason; sigslot::signal2 &> SignalConnectionMonitor; sigslot::signal2 SignalMediaMonitor; sigslot::signal2 SignalAudioMonitor; // Empty nick on StreamParams means "unknown". // No ssrcs in StreamParams means "no current speaker". sigslot::signal3 SignalSpeakerMonitor; sigslot::signal2 &> SignalVideoConnectionMonitor; sigslot::signal2 SignalVideoMediaMonitor; // Gives added streams and removed streams, in that order. sigslot::signal4 SignalMediaStreamsUpdate; sigslot::signal3 SignalDataReceived; AudioSourceProxy* GetAudioSourceProxy(); private: void OnMessage(rtc::Message* message); void OnSessionState(BaseSession* base_session, BaseSession::State state); void OnSessionError(BaseSession* base_session, Session::Error error); void OnSessionInfoMessage( Session* session, const buzz::XmlElement* action_elem); void OnViewRequest( Session* session, const ViewRequest& view_request); void OnRemoteDescriptionUpdate( BaseSession* base_session, const ContentInfos& updated_contents); void OnReceivedTerminateReason(Session* session, const std::string &reason); void IncomingSession(Session* session, const SessionDescription* offer); // Returns true on success. bool AddSession(Session* session, const SessionDescription* offer); void RemoveSession(Session* session); void EnableChannels(bool enable); void EnableSessionChannels(Session* session, bool enable); void Join(Call* call, bool enable); void OnConnectionMonitor(VoiceChannel* channel, const std::vector &infos); void OnMediaMonitor(VoiceChannel* channel, const VoiceMediaInfo& info); void OnAudioMonitor(VoiceChannel* channel, const AudioInfo& info); void OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc); void OnConnectionMonitor(VideoChannel* channel, const std::vector &infos); void OnMediaMonitor(VideoChannel* channel, const VideoMediaInfo& info); void OnDataReceived(DataChannel* channel, const ReceiveDataParams& params, const rtc::Buffer& payload); MediaStreams* GetMediaStreams(Session* session) const; void UpdateRemoteMediaStreams(Session* session, const ContentInfos& updated_contents, bool update_channels); bool UpdateVoiceChannelRemoteContent(Session* session, const AudioContentDescription* audio); bool UpdateVideoChannelRemoteContent(Session* session, const VideoContentDescription* video); bool UpdateDataChannelRemoteContent(Session* session, const DataContentDescription* data); void UpdateRecvStreams(const std::vector& update_streams, BaseChannel* channel, std::vector* recv_streams, std::vector* added_streams, std::vector* removed_streams); void AddRecvStreams(const std::vector& added_streams, BaseChannel* channel, std::vector* recv_streams); void AddRecvStream(const StreamParams& stream, BaseChannel* channel, std::vector* recv_streams); void RemoveRecvStreams(const std::vector& removed_streams, BaseChannel* channel, std::vector* recv_streams); void RemoveRecvStream(const StreamParams& stream, BaseChannel* channel, std::vector* recv_streams); void ContinuePlayDTMF(); bool StopScreencastWithoutSendingUpdate(Session* session, uint32 ssrc); bool StopAllScreencastsWithoutSendingUpdate(Session* session); bool SessionDescriptionContainsCrypto(const SessionDescription* sdesc) const; Session* InternalInitiateSession(const std::string& id, const buzz::Jid& to, const std::string& initiator_name, const CallOptions& options); uint32 id_; MediaSessionClient* session_client_; struct StartedCapture { StartedCapture(cricket::VideoCapturer* capturer, const cricket::VideoFormat& format) : capturer(capturer), format(format) { } cricket::VideoCapturer* capturer; cricket::VideoFormat format; }; typedef std::map StartedScreencastMap; struct MediaSession { Session* session; VoiceChannel* voice_channel; VideoChannel* video_channel; DataChannel* data_channel; MediaStreams* recv_streams; StartedScreencastMap started_screencasts; }; // Create a map of media sessions, keyed off session->id(). typedef std::map MediaSessionMap; MediaSessionMap media_session_map_; std::map speaker_monitor_map_; bool has_video_; bool has_data_; bool muted_; bool video_muted_; bool send_to_voicemail_; // DTMF tones have to be queued up so that we don't flood the call. We // keep a deque (doubely ended queue) of them around. While one is playing we // set the playing_dtmf_ bit and schedule a message in XX msec to clear that // bit or start the next tone playing. std::deque queued_dtmf_; bool playing_dtmf_; VoiceMediaInfo last_voice_media_info_; rtc::scoped_ptr audio_source_proxy_; friend class MediaSessionClient; }; } // namespace cricket #endif // TALK_SESSION_MEDIA_CALL_H_