aboutsummaryrefslogtreecommitdiff
path: root/talk
diff options
context:
space:
mode:
authorpthatcher@webrtc.org <pthatcher@webrtc.org>2014-12-19 22:29:55 +0000
committerpthatcher@webrtc.org <pthatcher@webrtc.org>2014-12-19 22:29:55 +0000
commit4c0544ab07987fa080a832123bee5e61750fd815 (patch)
treec580014d84b99397167bc8522e3633c3c0ff96e5 /talk
parented1a48b0cd405b0e6c76450f422e1a1c8b95421f (diff)
downloadwebrtc-4c0544ab07987fa080a832123bee5e61750fd815.tar.gz
Move Jingle-specific files from talk/session/media to webrtc/libjingle/session/media. This is part of an ongoing effort to remove Jingle-specific files from the WebRTC repository.
Also, fix the includes and header guards of examples/call. R=juberti@webrtc.org, pbos@webrtc.org Review URL: https://webrtc-codereview.appspot.com/34559004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7972 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'talk')
-rwxr-xr-xtalk/libjingle.gyp7
-rwxr-xr-xtalk/libjingle_tests.gyp2
-rw-r--r--talk/session/media/call.cc1132
-rw-r--r--talk/session/media/call.h307
-rw-r--r--talk/session/media/currentspeakermonitor_unittest.cc51
-rw-r--r--talk/session/media/mediamessages.cc333
-rw-r--r--talk/session/media/mediamessages.h98
-rw-r--r--talk/session/media/mediamessages_unittest.cc363
-rw-r--r--talk/session/media/mediasessionclient.cc1161
-rw-r--r--talk/session/media/mediasessionclient.h175
-rw-r--r--talk/session/media/mediasessionclient_unittest.cc3324
11 files changed, 22 insertions, 6931 deletions
diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp
index d12affbf45..56d29af12e 100755
--- a/talk/libjingle.gyp
+++ b/talk/libjingle.gyp
@@ -575,7 +575,6 @@
'<(DEPTH)/third_party/libsrtp/libsrtp.gyp:libsrtp',
'libjingle',
'libjingle_media',
- '<(webrtc_root)/libjingle/libjingle.gyp:jingle_session',
],
'include_dirs': [
'<(DEPTH)/testing/gtest/include',
@@ -590,24 +589,18 @@
'session/media/audiomonitor.h',
'session/media/bundlefilter.cc',
'session/media/bundlefilter.h',
- 'session/media/call.cc',
- 'session/media/call.h',
'session/media/channel.cc',
'session/media/channel.h',
'session/media/channelmanager.cc',
'session/media/channelmanager.h',
'session/media/currentspeakermonitor.cc',
'session/media/currentspeakermonitor.h',
- 'session/media/mediamessages.cc',
- 'session/media/mediamessages.h',
'session/media/mediamonitor.cc',
'session/media/mediamonitor.h',
'session/media/mediarecorder.cc',
'session/media/mediarecorder.h',
'session/media/mediasession.cc',
'session/media/mediasession.h',
- 'session/media/mediasessionclient.cc',
- 'session/media/mediasessionclient.h',
'session/media/mediasink.h',
'session/media/rtcpmuxfilter.cc',
'session/media/rtcpmuxfilter.h',
diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp
index 3410737788..b59a7ef463 100755
--- a/talk/libjingle_tests.gyp
+++ b/talk/libjingle_tests.gyp
@@ -167,9 +167,7 @@
'session/media/channelmanager_unittest.cc',
'session/media/currentspeakermonitor_unittest.cc',
'session/media/mediarecorder_unittest.cc',
- 'session/media/mediamessages_unittest.cc',
'session/media/mediasession_unittest.cc',
- 'session/media/mediasessionclient_unittest.cc',
'session/media/rtcpmuxfilter_unittest.cc',
'session/media/srtpfilter_unittest.cc',
],
diff --git a/talk/session/media/call.cc b/talk/session/media/call.cc
deleted file mode 100644
index 784be9422c..0000000000
--- a/talk/session/media/call.cc
+++ /dev/null
@@ -1,1132 +0,0 @@
-/*
- * 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.
- */
-
-#include <string>
-#include "talk/media/base/constants.h"
-#include "talk/media/base/screencastid.h"
-#include "webrtc/p2p/base/parsing.h"
-#include "talk/session/media/call.h"
-#include "talk/session/media/currentspeakermonitor.h"
-#include "talk/session/media/mediasessionclient.h"
-#include "webrtc/base/helpers.h"
-#include "webrtc/base/logging.h"
-#include "webrtc/base/thread.h"
-#include "webrtc/base/window.h"
-
-namespace cricket {
-
-const uint32 MSG_CHECKAUTODESTROY = 1;
-const uint32 MSG_TERMINATECALL = 2;
-const uint32 MSG_PLAYDTMF = 3;
-
-namespace {
-const int kDTMFDelay = 300; // msec
-const size_t kMaxDTMFDigits = 30;
-const int kSendToVoicemailTimeout = 1000*20;
-const int kNoVoicemailTimeout = 1000*180;
-const int kMediaMonitorInterval = 1000*15;
-// In order to be the same as the server-side switching, this must be 100.
-const int kAudioMonitorPollPeriodMillis = 100;
-
-// V is a pointer type.
-template<class K, class V>
-V FindOrNull(const std::map<K, V>& map,
- const K& key) {
- typename std::map<K, V>::const_iterator it = map.find(key);
- return (it != map.end()) ? it->second : NULL;
-}
-
-
-bool ContentContainsCrypto(const cricket::ContentInfo* content) {
- if (content != NULL) {
- const cricket::MediaContentDescription* desc =
- static_cast<const cricket::MediaContentDescription*>(
- content->description);
- if (!desc || desc->cryptos().empty()) {
- return false;
- }
- }
- return true;
-}
-
-}
-
-AudioSourceProxy::AudioSourceProxy(Call* call)
- : call_(call) {
- call_->SignalAudioMonitor.connect(this, &AudioSourceProxy::OnAudioMonitor);
- call_->SignalMediaStreamsUpdate.connect(
- this, &AudioSourceProxy::OnMediaStreamsUpdate);
-}
-
-void AudioSourceProxy::OnAudioMonitor(Call* call, const AudioInfo& info) {
- SignalAudioMonitor(this, info);
-}
-
-void AudioSourceProxy::OnMediaStreamsUpdate(Call* call, Session* session,
- const MediaStreams& added, const MediaStreams& removed) {
- SignalMediaStreamsUpdate(this, session, added, removed);
-}
-
-Call::Call(MediaSessionClient* session_client)
- : id_(rtc::CreateRandomId()),
- session_client_(session_client),
- has_video_(false),
- has_data_(false),
- muted_(false),
- video_muted_(false),
- send_to_voicemail_(true),
- playing_dtmf_(false) {
- audio_source_proxy_.reset(new AudioSourceProxy(this));
-}
-
-Call::~Call() {
- while (media_session_map_.begin() != media_session_map_.end()) {
- Session* session = media_session_map_.begin()->second.session;
- RemoveSession(session);
- session_client_->session_manager()->DestroySession(session);
- }
- rtc::Thread::Current()->Clear(this);
-}
-
-Session* Call::InitiateSession(const buzz::Jid& to,
- const buzz::Jid& initiator,
- const CallOptions& options) {
- std::string id;
- std::string initiator_name = initiator.Str();
- return InternalInitiateSession(id, to, initiator_name, options);
-}
-
-Session *Call::InitiateSession(const std::string& id,
- const buzz::Jid& to,
- const CallOptions& options) {
- std::string initiator_name;
- return InternalInitiateSession(id, to, initiator_name, options);
-}
-
-void Call::IncomingSession(Session* session, const SessionDescription* offer) {
- AddSession(session, offer);
-
- // Make sure the session knows about the incoming ssrcs. This needs to be done
- // prior to the SignalSessionState call, because that may trigger handling of
- // these new SSRCs, so they need to be registered before then.
- UpdateRemoteMediaStreams(session, offer->contents(), false);
-
- // Missed the first state, the initiate, which is needed by
- // call_client.
- SignalSessionState(this, session, Session::STATE_RECEIVEDINITIATE);
-}
-
-void Call::AcceptSession(Session* session,
- const cricket::CallOptions& options) {
- MediaSessionMap::iterator it = media_session_map_.find(session->id());
- if (it != media_session_map_.end()) {
- const SessionDescription* answer = session_client_->CreateAnswer(
- session->remote_description(), options);
- it->second.session->Accept(answer);
- }
-}
-
-void Call::RejectSession(Session* session) {
- // Assume polite decline.
- MediaSessionMap::iterator it = media_session_map_.find(session->id());
- if (it != media_session_map_.end())
- it->second.session->Reject(STR_TERMINATE_DECLINE);
-}
-
-void Call::TerminateSession(Session* session) {
- MediaSessionMap::iterator it = media_session_map_.find(session->id());
- if (it != media_session_map_.end()) {
- // Assume polite terminations.
- it->second.session->Terminate();
- }
-}
-
-void Call::Terminate() {
- // Copy the list so that we can iterate over it in a stable way
- std::vector<Session*> sessions = this->sessions();
-
- // There may be more than one session to terminate
- std::vector<Session*>::iterator it;
- for (it = sessions.begin(); it != sessions.end(); ++it) {
- TerminateSession(*it);
- }
-}
-
-bool Call::SendViewRequest(Session* session,
- const ViewRequest& view_request) {
- StaticVideoViews::const_iterator it;
- for (it = view_request.static_video_views.begin();
- it != view_request.static_video_views.end(); ++it) {
- StreamParams found_stream;
- bool found = false;
- MediaStreams* recv_streams = GetMediaStreams(session);
- if (recv_streams)
- found = recv_streams->GetVideoStream(it->selector, &found_stream);
- if (!found) {
- LOG(LS_WARNING) << "Trying to send view request for ("
- << it->selector.ssrc << ", '"
- << it->selector.groupid << "', '"
- << it->selector.streamid << "'"
- << ") is not in the local streams.";
- return false;
- }
- }
-
- XmlElements elems;
- WriteError error;
- if (!WriteJingleViewRequest(CN_VIDEO, view_request, &elems, &error)) {
- LOG(LS_ERROR) << "Couldn't write out view request: " << error.text;
- return false;
- }
-
- return session->SendInfoMessage(elems, session->remote_name());
-}
-
-void Call::SetVideoRenderer(Session* session, uint32 ssrc,
- VideoRenderer* renderer) {
- VideoChannel* video_channel = GetVideoChannel(session);
- if (video_channel) {
- video_channel->SetRenderer(ssrc, renderer);
- LOG(LS_INFO) << "Set renderer of ssrc " << ssrc
- << " to " << renderer << ".";
- } else {
- LOG(LS_INFO) << "Failed to set renderer of ssrc " << ssrc << ".";
- }
-}
-
-void Call::OnMessage(rtc::Message* message) {
- switch (message->message_id) {
- case MSG_CHECKAUTODESTROY:
- // If no more sessions for this call, delete it
- if (media_session_map_.empty())
- session_client_->DestroyCall(this);
- break;
- case MSG_TERMINATECALL:
- // Signal to the user that a timeout has happened and the call should
- // be sent to voicemail.
- if (send_to_voicemail_) {
- SignalSetupToCallVoicemail();
- }
-
- // Callee didn't answer - terminate call
- Terminate();
- break;
- case MSG_PLAYDTMF:
- ContinuePlayDTMF();
- }
-}
-
-std::vector<Session*> Call::sessions() {
- std::vector<Session*> sessions;
- MediaSessionMap::iterator it;
- for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it)
- sessions.push_back(it->second.session);
-
- return sessions;
-}
-
-bool Call::AddSession(Session* session, const SessionDescription* offer) {
- bool succeeded = true;
- MediaSession media_session;
- media_session.session = session;
- media_session.voice_channel = NULL;
- media_session.video_channel = NULL;
- media_session.data_channel = NULL;
- media_session.recv_streams = NULL;
-
- const ContentInfo* audio_offer = GetFirstAudioContent(offer);
- const ContentInfo* video_offer = GetFirstVideoContent(offer);
- const ContentInfo* data_offer = GetFirstDataContent(offer);
- has_video_ = (video_offer != NULL);
- has_data_ = (data_offer != NULL);
-
- ASSERT(audio_offer != NULL);
- // Create voice channel and start a media monitor.
- media_session.voice_channel =
- session_client_->channel_manager()->CreateVoiceChannel(
- session, audio_offer->name, has_video_);
- // voice_channel can be NULL in case of NullVoiceEngine.
- if (media_session.voice_channel) {
- media_session.voice_channel->SignalMediaMonitor.connect(
- this, &Call::OnMediaMonitor);
- media_session.voice_channel->StartMediaMonitor(kMediaMonitorInterval);
- } else {
- succeeded = false;
- }
-
- // If desired, create video channel and start a media monitor.
- if (has_video_ && succeeded) {
- media_session.video_channel =
- session_client_->channel_manager()->CreateVideoChannel(
- session,
- video_offer->name,
- true,
- VideoOptions(),
- media_session.voice_channel);
- // video_channel can be NULL in case of NullVideoEngine.
- if (media_session.video_channel) {
- media_session.video_channel->SignalMediaMonitor.connect(
- this, &Call::OnMediaMonitor);
- media_session.video_channel->StartMediaMonitor(kMediaMonitorInterval);
- } else {
- succeeded = false;
- }
- }
-
- // If desired, create data channel.
- if (has_data_ && succeeded) {
- const DataContentDescription* data = GetFirstDataContentDescription(offer);
- if (data == NULL) {
- succeeded = false;
- } else {
- DataChannelType data_channel_type = DCT_RTP;
- if ((data->protocol() == kMediaProtocolSctp) ||
- (data->protocol() == kMediaProtocolDtlsSctp)) {
- data_channel_type = DCT_SCTP;
- }
-
- bool rtcp = false;
- media_session.data_channel =
- session_client_->channel_manager()->CreateDataChannel(
- session, data_offer->name, rtcp, data_channel_type);
- if (media_session.data_channel) {
- media_session.data_channel->SignalDataReceived.connect(
- this, &Call::OnDataReceived);
- } else {
- succeeded = false;
- }
- }
- }
-
- if (succeeded) {
- // Add session to list, create channels for this session.
- media_session.recv_streams = new MediaStreams;
- media_session_map_[session->id()] = media_session;
- session->SignalState.connect(this, &Call::OnSessionState);
- session->SignalError.connect(this, &Call::OnSessionError);
- session->SignalInfoMessage.connect(
- this, &Call::OnSessionInfoMessage);
- session->SignalRemoteDescriptionUpdate.connect(
- this, &Call::OnRemoteDescriptionUpdate);
- session->SignalReceivedTerminateReason
- .connect(this, &Call::OnReceivedTerminateReason);
-
- // If this call has the focus, enable this session's channels.
- if (session_client_->GetFocus() == this) {
- EnableSessionChannels(session, true);
- }
-
- // Signal client.
- SignalAddSession(this, session);
- }
-
- return succeeded;
-}
-
-void Call::RemoveSession(Session* session) {
- MediaSessionMap::iterator it = media_session_map_.find(session->id());
- if (it == media_session_map_.end())
- return;
-
- // Remove all the screencasts, if they haven't been already.
- while (!it->second.started_screencasts.empty()) {
- uint32 ssrc = it->second.started_screencasts.begin()->first;
- if (!StopScreencastWithoutSendingUpdate(it->second.session, ssrc)) {
- LOG(LS_ERROR) << "Unable to stop screencast with ssrc " << ssrc;
- ASSERT(false);
- }
- }
-
- // Destroy video channel
- VideoChannel* video_channel = it->second.video_channel;
- if (video_channel != NULL)
- session_client_->channel_manager()->DestroyVideoChannel(video_channel);
-
- // Destroy voice channel
- VoiceChannel* voice_channel = it->second.voice_channel;
- if (voice_channel != NULL)
- session_client_->channel_manager()->DestroyVoiceChannel(voice_channel);
-
- // Destroy data channel
- DataChannel* data_channel = it->second.data_channel;
- if (data_channel != NULL)
- session_client_->channel_manager()->DestroyDataChannel(data_channel);
-
- delete it->second.recv_streams;
- media_session_map_.erase(it);
-
- // Destroy speaker monitor
- StopSpeakerMonitor(session);
-
- // Signal client
- SignalRemoveSession(this, session);
-
- // The call auto destroys when the last session is removed
- rtc::Thread::Current()->Post(this, MSG_CHECKAUTODESTROY);
-}
-
-VoiceChannel* Call::GetVoiceChannel(Session* session) const {
- MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
- return (it != media_session_map_.end()) ? it->second.voice_channel : NULL;
-}
-
-VideoChannel* Call::GetVideoChannel(Session* session) const {
- MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
- return (it != media_session_map_.end()) ? it->second.video_channel : NULL;
-}
-
-DataChannel* Call::GetDataChannel(Session* session) const {
- MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
- return (it != media_session_map_.end()) ? it->second.data_channel : NULL;
-}
-
-MediaStreams* Call::GetMediaStreams(Session* session) const {
- MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
- return (it != media_session_map_.end()) ? it->second.recv_streams : NULL;
-}
-
-void Call::EnableChannels(bool enable) {
- MediaSessionMap::iterator it;
- for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
- EnableSessionChannels(it->second.session, enable);
- }
-}
-
-void Call::EnableSessionChannels(Session* session, bool enable) {
- MediaSessionMap::iterator it = media_session_map_.find(session->id());
- if (it == media_session_map_.end())
- return;
-
- VoiceChannel* voice_channel = it->second.voice_channel;
- VideoChannel* video_channel = it->second.video_channel;
- DataChannel* data_channel = it->second.data_channel;
- if (voice_channel != NULL)
- voice_channel->Enable(enable);
- if (video_channel != NULL)
- video_channel->Enable(enable);
- if (data_channel != NULL)
- data_channel->Enable(enable);
-}
-
-void Call::Mute(bool mute) {
- muted_ = mute;
- MediaSessionMap::iterator it;
- for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
- if (it->second.voice_channel != NULL)
- it->second.voice_channel->MuteStream(0, mute);
- }
-}
-
-void Call::MuteVideo(bool mute) {
- video_muted_ = mute;
- MediaSessionMap::iterator it;
- for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
- if (it->second.video_channel != NULL)
- it->second.video_channel->MuteStream(0, mute);
- }
-}
-
-bool Call::SendData(Session* session,
- const SendDataParams& params,
- const rtc::Buffer& payload,
- SendDataResult* result) {
- DataChannel* data_channel = GetDataChannel(session);
- if (!data_channel) {
- LOG(LS_WARNING) << "Could not send data: no data channel.";
- return false;
- }
-
- return data_channel->SendData(params, payload, result);
-}
-
-void Call::PressDTMF(int event) {
- // Queue up this digit
- if (queued_dtmf_.size() < kMaxDTMFDigits) {
- LOG(LS_INFO) << "Call::PressDTMF(" << event << ")";
-
- queued_dtmf_.push_back(event);
-
- if (!playing_dtmf_) {
- ContinuePlayDTMF();
- }
- }
-}
-
-cricket::VideoFormat ScreencastFormatFromFps(int fps) {
- // The capturer pretty much ignore this, but just in case we give it
- // a resolution big enough to cover any expected desktop. In any
- // case, it can't be 0x0, or the CaptureManager will fail to use it.
- return cricket::VideoFormat(
- 1, 1,
- cricket::VideoFormat::FpsToInterval(fps),
- cricket::FOURCC_ANY);
-}
-
-bool Call::StartScreencast(Session* session,
- const std::string& streamid, uint32 ssrc,
- const ScreencastId& screenid, int fps) {
- MediaSessionMap::iterator it = media_session_map_.find(session->id());
- if (it == media_session_map_.end()) {
- return false;
- }
-
- VideoChannel *video_channel = GetVideoChannel(session);
- if (!video_channel) {
- LOG(LS_WARNING) << "Cannot add screencast"
- << " because there is no video channel.";
- return false;
- }
-
- VideoCapturer* capturer = session_client_->channel_manager()->
- CreateScreenCapturer(screenid);
- if (!capturer) {
- LOG(LS_WARNING) << "Could not create screencast capturer.";
- return false;
- }
-
- if (!video_channel->AddScreencast(ssrc, capturer)) {
- delete capturer;
- LOG(LS_WARNING) << "Could not add screencast capturer.";
- return false;
- }
-
- VideoFormat format = ScreencastFormatFromFps(fps);
- if (!session_client_->channel_manager()->StartVideoCapture(
- capturer, format)) {
- LOG(LS_WARNING) << "Could not start video capture.";
- video_channel->RemoveScreencast(ssrc);
- return false;
- }
-
- if (!video_channel->SetCapturer(ssrc, capturer)) {
- LOG(LS_WARNING) << "Could not start sending screencast.";
- session_client_->channel_manager()->StopVideoCapture(
- capturer, ScreencastFormatFromFps(fps));
- video_channel->RemoveScreencast(ssrc);
- }
-
- // TODO(pthatcher): Once the CaptureManager has a nicer interface
- // for removing captures (such as having StartCapture return a
- // handle), remove this StartedCapture stuff.
- it->second.started_screencasts.insert(
- std::make_pair(ssrc, StartedCapture(capturer, format)));
-
- // TODO(pthatcher): Verify we aren't re-using an existing id or
- // ssrc.
- StreamParams stream;
- stream.id = streamid;
- stream.ssrcs.push_back(ssrc);
- VideoContentDescription* video = CreateVideoStreamUpdate(stream);
-
- // TODO(pthatcher): Wait until view request before sending video.
- video_channel->SetLocalContent(video, CA_UPDATE, NULL);
- SendVideoStreamUpdate(session, video);
- return true;
-}
-
-bool Call::StopScreencast(Session* session,
- const std::string& streamid, uint32 ssrc) {
- if (!StopScreencastWithoutSendingUpdate(session, ssrc)) {
- return false;
- }
-
- VideoChannel *video_channel = GetVideoChannel(session);
- if (!video_channel) {
- LOG(LS_WARNING) << "Cannot add screencast"
- << " because there is no video channel.";
- return false;
- }
-
- StreamParams stream;
- stream.id = streamid;
- // No ssrcs
- VideoContentDescription* video = CreateVideoStreamUpdate(stream);
-
- video_channel->SetLocalContent(video, CA_UPDATE, NULL);
- SendVideoStreamUpdate(session, video);
- return true;
-}
-
-bool Call::StopScreencastWithoutSendingUpdate(
- Session* session, uint32 ssrc) {
- MediaSessionMap::iterator it = media_session_map_.find(session->id());
- if (it == media_session_map_.end()) {
- return false;
- }
-
- VideoChannel *video_channel = GetVideoChannel(session);
- if (!video_channel) {
- LOG(LS_WARNING) << "Cannot remove screencast"
- << " because there is no video channel.";
- return false;
- }
-
- StartedScreencastMap::const_iterator screencast_iter =
- it->second.started_screencasts.find(ssrc);
- if (screencast_iter == it->second.started_screencasts.end()) {
- LOG(LS_WARNING) << "Could not stop screencast " << ssrc
- << " because there is no capturer.";
- return false;
- }
-
- VideoCapturer* capturer = screencast_iter->second.capturer;
- VideoFormat format = screencast_iter->second.format;
- video_channel->SetCapturer(ssrc, NULL);
- if (!session_client_->channel_manager()->StopVideoCapture(
- capturer, format)) {
- LOG(LS_WARNING) << "Could not stop screencast " << ssrc
- << " because could not stop capture.";
- return false;
- }
- video_channel->RemoveScreencast(ssrc);
- it->second.started_screencasts.erase(ssrc);
- return true;
-}
-
-VideoContentDescription* Call::CreateVideoStreamUpdate(
- const StreamParams& stream) {
- VideoContentDescription* video = new VideoContentDescription();
- video->set_multistream(true);
- video->set_partial(true);
- video->AddStream(stream);
- return video;
-}
-
-void Call::SendVideoStreamUpdate(
- Session* session, VideoContentDescription* video) {
- // Takes the ownership of |video|.
- rtc::scoped_ptr<VideoContentDescription> description(video);
- const ContentInfo* video_info =
- GetFirstVideoContent(session->local_description());
- if (video_info == NULL) {
- LOG(LS_WARNING) << "Cannot send stream update for video.";
- return;
- }
-
- std::vector<ContentInfo> contents;
- contents.push_back(
- ContentInfo(video_info->name, video_info->type, description.get()));
-
- session->SendDescriptionInfoMessage(contents);
-}
-
-void Call::ContinuePlayDTMF() {
- playing_dtmf_ = false;
-
- // Check to see if we have a queued tone
- if (queued_dtmf_.size() > 0) {
- playing_dtmf_ = true;
-
- int tone = queued_dtmf_.front();
- queued_dtmf_.pop_front();
-
- LOG(LS_INFO) << "Call::ContinuePlayDTMF(" << tone << ")";
- for (MediaSessionMap::iterator it = media_session_map_.begin();
- it != media_session_map_.end(); ++it) {
- if (it->second.voice_channel != NULL) {
- it->second.voice_channel->PressDTMF(tone, true);
- }
- }
-
- // Post a message to play the next tone or at least clear the playing_dtmf_
- // bit.
- rtc::Thread::Current()->PostDelayed(kDTMFDelay, this, MSG_PLAYDTMF);
- }
-}
-
-void Call::Join(Call* call, bool enable) {
- for (MediaSessionMap::iterator it = call->media_session_map_.begin();
- it != call->media_session_map_.end(); ++it) {
- // Shouldn't already exist.
- ASSERT(media_session_map_.find(it->first) == media_session_map_.end());
- media_session_map_[it->first] = it->second;
-
- it->second.session->SignalState.connect(this, &Call::OnSessionState);
- it->second.session->SignalError.connect(this, &Call::OnSessionError);
- it->second.session->SignalReceivedTerminateReason
- .connect(this, &Call::OnReceivedTerminateReason);
-
- EnableSessionChannels(it->second.session, enable);
- }
-
- // Moved all the sessions over, so the other call should no longer have any.
- call->media_session_map_.clear();
-}
-
-void Call::StartConnectionMonitor(Session* session, int cms) {
- VoiceChannel* voice_channel = GetVoiceChannel(session);
- if (voice_channel) {
- voice_channel->SignalConnectionMonitor.connect(this,
- &Call::OnConnectionMonitor);
- voice_channel->StartConnectionMonitor(cms);
- }
-
- VideoChannel* video_channel = GetVideoChannel(session);
- if (video_channel) {
- video_channel->SignalConnectionMonitor.connect(this,
- &Call::OnConnectionMonitor);
- video_channel->StartConnectionMonitor(cms);
- }
-}
-
-void Call::StopConnectionMonitor(Session* session) {
- VoiceChannel* voice_channel = GetVoiceChannel(session);
- if (voice_channel) {
- voice_channel->StopConnectionMonitor();
- voice_channel->SignalConnectionMonitor.disconnect(this);
- }
-
- VideoChannel* video_channel = GetVideoChannel(session);
- if (video_channel) {
- video_channel->StopConnectionMonitor();
- video_channel->SignalConnectionMonitor.disconnect(this);
- }
-}
-
-void Call::StartAudioMonitor(Session* session, int cms) {
- VoiceChannel* voice_channel = GetVoiceChannel(session);
- if (voice_channel) {
- voice_channel->SignalAudioMonitor.connect(this, &Call::OnAudioMonitor);
- voice_channel->StartAudioMonitor(cms);
- }
-}
-
-void Call::StopAudioMonitor(Session* session) {
- VoiceChannel* voice_channel = GetVoiceChannel(session);
- if (voice_channel) {
- voice_channel->StopAudioMonitor();
- voice_channel->SignalAudioMonitor.disconnect(this);
- }
-}
-
-bool Call::IsAudioMonitorRunning(Session* session) {
- VoiceChannel* voice_channel = GetVoiceChannel(session);
- if (voice_channel) {
- return voice_channel->IsAudioMonitorRunning();
- } else {
- return false;
- }
-}
-
-void Call::StartSpeakerMonitor(Session* session) {
- if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
- if (!IsAudioMonitorRunning(session)) {
- StartAudioMonitor(session, kAudioMonitorPollPeriodMillis);
- }
- CurrentSpeakerMonitor* speaker_monitor =
- new cricket::CurrentSpeakerMonitor(
- audio_source_proxy_.get(), session);
- speaker_monitor->SignalUpdate.connect(this, &Call::OnSpeakerMonitor);
- speaker_monitor->Start();
- speaker_monitor_map_[session->id()] = speaker_monitor;
- } else {
- LOG(LS_WARNING) << "Already started speaker monitor for session "
- << session->id() << ".";
- }
-}
-
-void Call::StopSpeakerMonitor(Session* session) {
- if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
- LOG(LS_WARNING) << "Speaker monitor for session "
- << session->id() << " already stopped.";
- } else {
- CurrentSpeakerMonitor* monitor = speaker_monitor_map_[session->id()];
- monitor->Stop();
- speaker_monitor_map_.erase(session->id());
- delete monitor;
- }
-}
-
-void Call::OnConnectionMonitor(VoiceChannel* channel,
- const std::vector<ConnectionInfo> &infos) {
- SignalConnectionMonitor(this, infos);
-}
-
-void Call::OnMediaMonitor(VoiceChannel* channel, const VoiceMediaInfo& info) {
- last_voice_media_info_ = info;
- SignalMediaMonitor(this, info);
-}
-
-void Call::OnAudioMonitor(VoiceChannel* channel, const AudioInfo& info) {
- SignalAudioMonitor(this, info);
-}
-
-void Call::OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc) {
- Session* session = static_cast<Session*>(monitor->session());
- MediaStreams* recv_streams = GetMediaStreams(session);
- if (recv_streams) {
- StreamParams stream;
- recv_streams->GetAudioStream(StreamSelector(ssrc), &stream);
- SignalSpeakerMonitor(this, session, stream);
- }
-}
-
-void Call::OnConnectionMonitor(VideoChannel* channel,
- const std::vector<ConnectionInfo> &infos) {
- SignalVideoConnectionMonitor(this, infos);
-}
-
-void Call::OnMediaMonitor(VideoChannel* channel, const VideoMediaInfo& info) {
- SignalVideoMediaMonitor(this, info);
-}
-
-void Call::OnDataReceived(DataChannel* channel,
- const ReceiveDataParams& params,
- const rtc::Buffer& payload) {
- SignalDataReceived(this, params, payload);
-}
-
-uint32 Call::id() {
- return id_;
-}
-
-void Call::OnSessionState(BaseSession* base_session, BaseSession::State state) {
- Session* session = static_cast<Session*>(base_session);
- switch (state) {
- case Session::STATE_RECEIVEDACCEPT:
- UpdateRemoteMediaStreams(session,
- session->remote_description()->contents(), false);
- session_client_->session_manager()->signaling_thread()->Clear(this,
- MSG_TERMINATECALL);
- break;
- case Session::STATE_RECEIVEDREJECT:
- case Session::STATE_RECEIVEDTERMINATE:
- session_client_->session_manager()->signaling_thread()->Clear(this,
- MSG_TERMINATECALL);
- break;
- default:
- break;
- }
- SignalSessionState(this, session, state);
-}
-
-void Call::OnSessionError(BaseSession* base_session, Session::Error error) {
- session_client_->session_manager()->signaling_thread()->Clear(this,
- MSG_TERMINATECALL);
- SignalSessionError(this, static_cast<Session*>(base_session), error);
-}
-
-void Call::OnSessionInfoMessage(Session* session,
- const buzz::XmlElement* action_elem) {
- if (!IsJingleViewRequest(action_elem)) {
- return;
- }
-
- ViewRequest view_request;
- ParseError error;
- if (!ParseJingleViewRequest(action_elem, &view_request, &error)) {
- LOG(LS_WARNING) << "Failed to parse view request: " << error.text;
- return;
- }
-
- VideoChannel* video_channel = GetVideoChannel(session);
- if (video_channel == NULL) {
- LOG(LS_WARNING) << "Ignore view request since we have no video channel.";
- return;
- }
-
- if (!video_channel->ApplyViewRequest(view_request)) {
- LOG(LS_WARNING) << "Failed to ApplyViewRequest.";
- }
-}
-
-void Call::OnRemoteDescriptionUpdate(BaseSession* base_session,
- const ContentInfos& updated_contents) {
- Session* session = static_cast<Session*>(base_session);
-
- const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
- if (audio_content) {
- const AudioContentDescription* audio_update =
- static_cast<const AudioContentDescription*>(audio_content->description);
- if (!audio_update->codecs().empty()) {
- UpdateVoiceChannelRemoteContent(session, audio_update);
- }
- }
-
- const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
- if (video_content) {
- const VideoContentDescription* video_update =
- static_cast<const VideoContentDescription*>(video_content->description);
- if (!video_update->codecs().empty()) {
- UpdateVideoChannelRemoteContent(session, video_update);
- }
- }
-
- const ContentInfo* data_content = GetFirstDataContent(updated_contents);
- if (data_content) {
- const DataContentDescription* data_update =
- static_cast<const DataContentDescription*>(data_content->description);
- if (!data_update->codecs().empty()) {
- UpdateDataChannelRemoteContent(session, data_update);
- }
- }
-
- UpdateRemoteMediaStreams(session, updated_contents, true);
-}
-
-bool Call::UpdateVoiceChannelRemoteContent(
- Session* session, const AudioContentDescription* audio) {
- VoiceChannel* voice_channel = GetVoiceChannel(session);
- if (!voice_channel->SetRemoteContent(audio, CA_UPDATE, NULL)) {
- const std::string error_desc =
- "Failure in audio SetRemoteContent with CA_UPDATE";
- LOG(LS_ERROR) << error_desc;
- session->SetError(BaseSession::ERROR_CONTENT, error_desc);
- return false;
- }
- return true;
-}
-
-bool Call::UpdateVideoChannelRemoteContent(
- Session* session, const VideoContentDescription* video) {
- VideoChannel* video_channel = GetVideoChannel(session);
- if (!video_channel->SetRemoteContent(video, CA_UPDATE, NULL)) {
- const std::string error_desc =
- "Failure in video SetRemoteContent with CA_UPDATE";
- LOG(LS_ERROR) << error_desc;
- session->SetError(BaseSession::ERROR_CONTENT, error_desc);
- return false;
- }
- return true;
-}
-
-bool Call::UpdateDataChannelRemoteContent(
- Session* session, const DataContentDescription* data) {
- DataChannel* data_channel = GetDataChannel(session);
- if (!data_channel->SetRemoteContent(data, CA_UPDATE, NULL)) {
- const std::string error_desc =
- "Failure in data SetRemoteContent with CA_UPDATE";
- LOG(LS_ERROR) << error_desc;
- session->SetError(BaseSession::ERROR_CONTENT, error_desc);
- return false;
- }
- return true;
-}
-
-void Call::UpdateRemoteMediaStreams(Session* session,
- const ContentInfos& updated_contents,
- bool update_channels) {
- MediaStreams* recv_streams = GetMediaStreams(session);
- if (!recv_streams)
- return;
-
- cricket::MediaStreams added_streams;
- cricket::MediaStreams removed_streams;
-
- const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
- if (audio_content) {
- const AudioContentDescription* audio_update =
- static_cast<const AudioContentDescription*>(audio_content->description);
- UpdateRecvStreams(audio_update->streams(),
- update_channels ? GetVoiceChannel(session) : NULL,
- recv_streams->mutable_audio(),
- added_streams.mutable_audio(),
- removed_streams.mutable_audio());
- }
-
- const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
- if (video_content) {
- const VideoContentDescription* video_update =
- static_cast<const VideoContentDescription*>(video_content->description);
- UpdateRecvStreams(video_update->streams(),
- update_channels ? GetVideoChannel(session) : NULL,
- recv_streams->mutable_video(),
- added_streams.mutable_video(),
- removed_streams.mutable_video());
- }
-
- const ContentInfo* data_content = GetFirstDataContent(updated_contents);
- if (data_content) {
- const DataContentDescription* data_update =
- static_cast<const DataContentDescription*>(data_content->description);
- UpdateRecvStreams(data_update->streams(),
- update_channels ? GetDataChannel(session) : NULL,
- recv_streams->mutable_data(),
- added_streams.mutable_data(),
- removed_streams.mutable_data());
- }
-
- if (!added_streams.empty() || !removed_streams.empty()) {
- SignalMediaStreamsUpdate(this, session, added_streams, removed_streams);
- }
-}
-
-void FindStreamChanges(const std::vector<StreamParams>& streams,
- const std::vector<StreamParams>& updates,
- std::vector<StreamParams>* added_streams,
- std::vector<StreamParams>* removed_streams) {
- for (std::vector<StreamParams>::const_iterator update = updates.begin();
- update != updates.end(); ++update) {
- StreamParams stream;
- if (GetStreamByIds(streams, update->groupid, update->id, &stream)) {
- if (!update->has_ssrcs()) {
- removed_streams->push_back(stream);
- }
- } else {
- // There's a bug on reflector that will send <stream>s even
- // though there is not ssrc (which means there isn't really a
- // stream). To work around it, we simply ignore new <stream>s
- // that don't have any ssrcs.
- if (update->has_ssrcs()) {
- added_streams->push_back(*update);
- }
- }
- }
-}
-
-void Call::UpdateRecvStreams(const std::vector<StreamParams>& update_streams,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams,
- std::vector<StreamParams>* added_streams,
- std::vector<StreamParams>* removed_streams) {
- FindStreamChanges(*recv_streams,
- update_streams, added_streams, removed_streams);
- AddRecvStreams(*added_streams,
- channel, recv_streams);
- RemoveRecvStreams(*removed_streams,
- channel, recv_streams);
-}
-
-void Call::AddRecvStreams(const std::vector<StreamParams>& added_streams,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams) {
- std::vector<StreamParams>::const_iterator stream;
- for (stream = added_streams.begin();
- stream != added_streams.end();
- ++stream) {
- AddRecvStream(*stream, channel, recv_streams);
- }
-}
-
-void Call::AddRecvStream(const StreamParams& stream,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams) {
- if (channel && stream.has_ssrcs()) {
- channel->AddRecvStream(stream);
- }
- recv_streams->push_back(stream);
-}
-
-void Call::RemoveRecvStreams(const std::vector<StreamParams>& removed_streams,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams) {
- std::vector<StreamParams>::const_iterator stream;
- for (stream = removed_streams.begin();
- stream != removed_streams.end();
- ++stream) {
- RemoveRecvStream(*stream, channel, recv_streams);
- }
-}
-
-void Call::RemoveRecvStream(const StreamParams& stream,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams) {
- if (channel && stream.has_ssrcs()) {
- // TODO(pthatcher): Change RemoveRecvStream to take a stream argument.
- channel->RemoveRecvStream(stream.first_ssrc());
- }
- RemoveStreamByIds(recv_streams, stream.groupid, stream.id);
-}
-
-void Call::OnReceivedTerminateReason(Session* session,
- const std::string& reason) {
- session_client_->session_manager()->signaling_thread()->Clear(this,
- MSG_TERMINATECALL);
- SignalReceivedTerminateReason(this, session, reason);
-}
-
-// TODO(mdodd): Get ride of this method since all Hangouts are using a secure
-// connection.
-bool Call::secure() const {
- if (session_client_->secure() == SEC_DISABLED) {
- return false;
- }
-
- bool ret = true;
- int i = 0;
-
- MediaSessionMap::const_iterator it;
- for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
- LOG_F(LS_VERBOSE) << "session[" << i
- << "], check local and remote descriptions";
- i++;
-
- if (!SessionDescriptionContainsCrypto(
- it->second.session->local_description()) ||
- !SessionDescriptionContainsCrypto(
- it->second.session->remote_description())) {
- ret = false;
- break;
- }
- }
-
- LOG_F(LS_VERBOSE) << "secure=" << ret;
- return ret;
-}
-
-bool Call::SessionDescriptionContainsCrypto(
- const SessionDescription* sdesc) const {
- if (sdesc == NULL) {
- LOG_F(LS_VERBOSE) << "sessionDescription is NULL";
- return false;
- }
-
- return ContentContainsCrypto(sdesc->GetContentByName(CN_AUDIO)) &&
- ContentContainsCrypto(sdesc->GetContentByName(CN_VIDEO));
-}
-
-Session* Call::InternalInitiateSession(const std::string& id,
- const buzz::Jid& to,
- const std::string& initiator_name,
- const CallOptions& options) {
- const SessionDescription* offer = session_client_->CreateOffer(options);
-
- Session* session = session_client_->CreateSession(id, this);
- // Only override the initiator_name if it was manually supplied. Otherwise,
- // session_client_ will supply the local jid as initiator in CreateOffer.
- if (!initiator_name.empty()) {
- session->set_initiator_name(initiator_name);
- }
-
- AddSession(session, offer);
- session->Initiate(to.Str(), offer);
-
- // After this timeout, terminate the call because the callee isn't
- // answering
- session_client_->session_manager()->signaling_thread()->Clear(this,
- MSG_TERMINATECALL);
- session_client_->session_manager()->signaling_thread()->PostDelayed(
- send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout,
- this, MSG_TERMINATECALL);
- return session;
-}
-
-AudioSourceProxy* Call::GetAudioSourceProxy() {
- return audio_source_proxy_.get();
-}
-
-} // namespace cricket
diff --git a/talk/session/media/call.h b/talk/session/media/call.h
deleted file mode 100644
index 6f682b2e81..0000000000
--- a/talk/session/media/call.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * 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 <deque>
-#include <map>
-#include <string>
-#include <vector>
-
-#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 "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/base/messagequeue.h"
-#include "webrtc/libjingle/session/sessionmanager.h"
-#include "webrtc/libjingle/xmpp/jid.h"
-#include "webrtc/p2p/client/socketmonitor.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&);
-
- 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<Session*> 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<StreamParams>* GetDataRecvStreams(Session* session) const {
- MediaStreams* recv_streams = GetMediaStreams(session);
- return recv_streams ? &recv_streams->data() : NULL;
- }
- const std::vector<StreamParams>* GetVideoRecvStreams(Session* session) const {
- MediaStreams* recv_streams = GetMediaStreams(session);
- return recv_streams ? &recv_streams->video() : NULL;
- }
- const std::vector<StreamParams>* 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<Call*, Session*> SignalAddSession;
- sigslot::signal2<Call*, Session*> SignalRemoveSession;
- sigslot::signal3<Call*, Session*, Session::State>
- SignalSessionState;
- sigslot::signal3<Call*, Session*, Session::Error>
- SignalSessionError;
- sigslot::signal3<Call*, Session*, const std::string &>
- SignalReceivedTerminateReason;
- sigslot::signal2<Call*, const std::vector<ConnectionInfo> &>
- SignalConnectionMonitor;
- sigslot::signal2<Call*, const VoiceMediaInfo&> SignalMediaMonitor;
- sigslot::signal2<Call*, const AudioInfo&> SignalAudioMonitor;
- // Empty nick on StreamParams means "unknown".
- // No ssrcs in StreamParams means "no current speaker".
- sigslot::signal3<Call*,
- Session*,
- const StreamParams&> SignalSpeakerMonitor;
- sigslot::signal2<Call*, const std::vector<ConnectionInfo> &>
- SignalVideoConnectionMonitor;
- sigslot::signal2<Call*, const VideoMediaInfo&> SignalVideoMediaMonitor;
- // Gives added streams and removed streams, in that order.
- sigslot::signal4<Call*,
- Session*,
- const MediaStreams&,
- const MediaStreams&> SignalMediaStreamsUpdate;
- sigslot::signal3<Call*,
- const ReceiveDataParams&,
- const rtc::Buffer&> SignalDataReceived;
-
- AudioSourceProxy* GetAudioSourceProxy();
-
- private:
- void OnMessage(rtc::Message* message);
- void OnSessionState(BaseSession* base_session, BaseSession::State state);
- void OnSessionError(BaseSession* base_session, BaseSession::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<ConnectionInfo> &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<ConnectionInfo> &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<StreamParams>& update_streams,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams,
- std::vector<StreamParams>* added_streams,
- std::vector<StreamParams>* removed_streams);
- void AddRecvStreams(const std::vector<StreamParams>& added_streams,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams);
- void AddRecvStream(const StreamParams& stream,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams);
- void RemoveRecvStreams(const std::vector<StreamParams>& removed_streams,
- BaseChannel* channel,
- std::vector<StreamParams>* recv_streams);
- void RemoveRecvStream(const StreamParams& stream,
- BaseChannel* channel,
- std::vector<StreamParams>* 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<uint32, StartedCapture> 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<std::string, MediaSession> MediaSessionMap;
- MediaSessionMap media_session_map_;
-
- std::map<std::string, CurrentSpeakerMonitor*> 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<int> queued_dtmf_;
- bool playing_dtmf_;
-
- VoiceMediaInfo last_voice_media_info_;
-
- rtc::scoped_ptr<AudioSourceProxy> audio_source_proxy_;
-
- friend class MediaSessionClient;
-};
-
-} // namespace cricket
-
-#endif // TALK_SESSION_MEDIA_CALL_H_
diff --git a/talk/session/media/currentspeakermonitor_unittest.cc b/talk/session/media/currentspeakermonitor_unittest.cc
index 63676f982e..6a99973f96 100644
--- a/talk/session/media/currentspeakermonitor_unittest.cc
+++ b/talk/session/media/currentspeakermonitor_unittest.cc
@@ -25,7 +25,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "talk/session/media/call.h"
+#include "talk/session/media/audiomonitor.h"
#include "talk/session/media/currentspeakermonitor.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/thread.h"
@@ -42,21 +42,11 @@ static const uint32 kMinTimeBetweenSwitches = 10;
// I am assuming system clocks do not have a coarser resolution than 90 ms.
static const uint32 kSleepTimeBetweenSwitches = 100;
-class MockCall : public Call {
- public:
- MockCall() : Call(NULL) {}
-
- void EmitAudioMonitor(const AudioInfo& info) {
- GetAudioSourceProxy()->SignalAudioMonitor(GetAudioSourceProxy(), info);
- }
-};
-
class CurrentSpeakerMonitorTest : public testing::Test,
public sigslot::has_slots<> {
public:
CurrentSpeakerMonitorTest() {
- call_ = new MockCall();
- monitor_ = new CurrentSpeakerMonitor(call_->GetAudioSourceProxy(), NULL);
+ monitor_ = new CurrentSpeakerMonitor(&source_, NULL);
// Shrink the minimum time betweeen switches to 10 ms so we don't have to
// slow down our tests.
monitor_->set_min_time_between_switches(kMinTimeBetweenSwitches);
@@ -68,11 +58,14 @@ class CurrentSpeakerMonitorTest : public testing::Test,
~CurrentSpeakerMonitorTest() {
delete monitor_;
- delete call_;
+ }
+
+ void SignalAudioMonitor(const AudioInfo& info) {
+ source_.SignalAudioMonitor(&source_, info);
}
protected:
- MockCall* call_;
+ AudioSourceContext source_;
CurrentSpeakerMonitor* monitor_;
int num_changes_;
uint32 current_speaker_;
@@ -91,7 +84,7 @@ static void InitAudioInfo(AudioInfo* info, int input_level, int output_level) {
TEST_F(CurrentSpeakerMonitorTest, NoActiveStreams) {
AudioInfo info;
InitAudioInfo(&info, 0, 0);
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, 0U);
EXPECT_EQ(num_changes_, 0);
@@ -103,7 +96,7 @@ TEST_F(CurrentSpeakerMonitorTest, MultipleActiveStreams) {
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
// No speaker recognized because the initial sample is treated as possibly
// just noise and disregarded.
@@ -112,7 +105,7 @@ TEST_F(CurrentSpeakerMonitorTest, MultipleActiveStreams) {
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, kSsrc2);
EXPECT_EQ(num_changes_, 1);
@@ -125,21 +118,21 @@ TEST_F(CurrentSpeakerMonitorTest, DISABLED_RapidSpeakerChange) {
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, 0U);
EXPECT_EQ(num_changes_, 0);
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, kSsrc2);
EXPECT_EQ(num_changes_, 1);
info.active_streams.push_back(std::make_pair(kSsrc1, 9));
info.active_streams.push_back(std::make_pair(kSsrc2, 1));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
// We expect no speaker change because of the rapid change.
EXPECT_EQ(current_speaker_, kSsrc2);
@@ -152,14 +145,14 @@ TEST_F(CurrentSpeakerMonitorTest, SpeakerChange) {
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, 0U);
EXPECT_EQ(num_changes_, 0);
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, kSsrc2);
EXPECT_EQ(num_changes_, 1);
@@ -169,7 +162,7 @@ TEST_F(CurrentSpeakerMonitorTest, SpeakerChange) {
info.active_streams.push_back(std::make_pair(kSsrc1, 9));
info.active_streams.push_back(std::make_pair(kSsrc2, 1));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, kSsrc1);
EXPECT_EQ(num_changes_, 2);
@@ -181,21 +174,21 @@ TEST_F(CurrentSpeakerMonitorTest, InterwordSilence) {
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, 0U);
EXPECT_EQ(num_changes_, 0);
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, kSsrc2);
EXPECT_EQ(num_changes_, 1);
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 7));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
EXPECT_EQ(current_speaker_, kSsrc2);
EXPECT_EQ(num_changes_, 1);
@@ -205,7 +198,7 @@ TEST_F(CurrentSpeakerMonitorTest, InterwordSilence) {
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 0));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
// Current speaker shouldn't have changed because we treat this as an inter-
// word silence.
@@ -214,7 +207,7 @@ TEST_F(CurrentSpeakerMonitorTest, InterwordSilence) {
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 0));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
// Current speaker shouldn't have changed because we treat this as an inter-
// word silence.
@@ -223,7 +216,7 @@ TEST_F(CurrentSpeakerMonitorTest, InterwordSilence) {
info.active_streams.push_back(std::make_pair(kSsrc1, 3));
info.active_streams.push_back(std::make_pair(kSsrc2, 0));
- call_->EmitAudioMonitor(info);
+ SignalAudioMonitor(info);
// At this point, we should have concluded that SSRC2 stopped speaking.
EXPECT_EQ(current_speaker_, kSsrc1);
diff --git a/talk/session/media/mediamessages.cc b/talk/session/media/mediamessages.cc
deleted file mode 100644
index 455a8d84fa..0000000000
--- a/talk/session/media/mediamessages.cc
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * libjingle
- * Copyright 2010 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.
- */
-
-/*
- * Documentation is in mediamessages.h.
- */
-
-#include "talk/session/media/mediamessages.h"
-
-#include "webrtc/p2p/base/constants.h"
-#include "webrtc/p2p/base/parsing.h"
-#include "talk/session/media/mediasessionclient.h"
-#include "webrtc/libjingle/xmllite/xmlelement.h"
-#include "webrtc/base/logging.h"
-#include "webrtc/base/stringencode.h"
-
-namespace cricket {
-
-namespace {
-
-bool ParseSsrc(const std::string& string, uint32* ssrc) {
- return rtc::FromString(string, ssrc);
-}
-
-// Builds a <view> element according to the following spec:
-// goto/jinglemuc
-buzz::XmlElement* CreateViewElem(const std::string& name,
- const std::string& type) {
- buzz::XmlElement* view_elem =
- new buzz::XmlElement(QN_JINGLE_DRAFT_VIEW, true);
- view_elem->AddAttr(QN_NAME, name);
- view_elem->SetAttr(QN_TYPE, type);
- return view_elem;
-}
-
-buzz::XmlElement* CreateVideoViewElem(const std::string& content_name,
- const std::string& type) {
- return CreateViewElem(content_name, type);
-}
-
-buzz::XmlElement* CreateNoneVideoViewElem(const std::string& content_name) {
- return CreateVideoViewElem(content_name, STR_JINGLE_DRAFT_VIEW_TYPE_NONE);
-}
-
-buzz::XmlElement* CreateStaticVideoViewElem(const std::string& content_name,
- const StaticVideoView& view) {
- buzz::XmlElement* view_elem =
- CreateVideoViewElem(content_name, STR_JINGLE_DRAFT_VIEW_TYPE_STATIC);
- AddXmlAttr(view_elem, QN_SSRC, view.selector.ssrc);
-
- buzz::XmlElement* params_elem = new buzz::XmlElement(QN_JINGLE_DRAFT_PARAMS);
- AddXmlAttr(params_elem, QN_WIDTH, view.width);
- AddXmlAttr(params_elem, QN_HEIGHT, view.height);
- AddXmlAttr(params_elem, QN_FRAMERATE, view.framerate);
- AddXmlAttr(params_elem, QN_PREFERENCE, view.preference);
- view_elem->AddElement(params_elem);
-
- return view_elem;
-}
-
-} // namespace
-
-bool IsJingleViewRequest(const buzz::XmlElement* action_elem) {
- return action_elem->FirstNamed(QN_JINGLE_DRAFT_VIEW) != NULL;
-}
-
-bool ParseStaticVideoView(const buzz::XmlElement* view_elem,
- StaticVideoView* view,
- ParseError* error) {
- uint32 ssrc;
- if (!ParseSsrc(view_elem->Attr(QN_SSRC), &ssrc)) {
- return BadParse("Invalid or missing view ssrc.", error);
- }
- view->selector = StreamSelector(ssrc);
-
- const buzz::XmlElement* params_elem =
- view_elem->FirstNamed(QN_JINGLE_DRAFT_PARAMS);
- if (params_elem) {
- view->width = GetXmlAttr(params_elem, QN_WIDTH, 0);
- view->height = GetXmlAttr(params_elem, QN_HEIGHT, 0);
- view->framerate = GetXmlAttr(params_elem, QN_FRAMERATE, 0);
- view->preference = GetXmlAttr(params_elem, QN_PREFERENCE, 0);
- } else {
- return BadParse("Missing view params.", error);
- }
-
- return true;
-}
-
-bool ParseJingleViewRequest(const buzz::XmlElement* action_elem,
- ViewRequest* view_request,
- ParseError* error) {
- for (const buzz::XmlElement* view_elem =
- action_elem->FirstNamed(QN_JINGLE_DRAFT_VIEW);
- view_elem != NULL;
- view_elem = view_elem->NextNamed(QN_JINGLE_DRAFT_VIEW)) {
- std::string type = view_elem->Attr(QN_TYPE);
- if (STR_JINGLE_DRAFT_VIEW_TYPE_NONE == type) {
- view_request->static_video_views.clear();
- return true;
- } else if (STR_JINGLE_DRAFT_VIEW_TYPE_STATIC == type) {
- StaticVideoView static_video_view(StreamSelector(0), 0, 0, 0);
- if (!ParseStaticVideoView(view_elem, &static_video_view, error)) {
- return false;
- }
- view_request->static_video_views.push_back(static_video_view);
- } else {
- LOG(LS_INFO) << "Ingnoring unknown view type: " << type;
- }
- }
- return true;
-}
-
-bool WriteJingleViewRequest(const std::string& content_name,
- const ViewRequest& request,
- XmlElements* elems,
- WriteError* error) {
- if (request.static_video_views.empty()) {
- elems->push_back(CreateNoneVideoViewElem(content_name));
- } else {
- for (StaticVideoViews::const_iterator view =
- request.static_video_views.begin();
- view != request.static_video_views.end(); ++view) {
- elems->push_back(CreateStaticVideoViewElem(content_name, *view));
- }
- }
- return true;
-}
-
-bool ParseSsrcAsLegacyStream(const buzz::XmlElement* desc_elem,
- std::vector<StreamParams>* streams,
- ParseError* error) {
- const std::string ssrc_str = desc_elem->Attr(QN_SSRC);
- if (!ssrc_str.empty()) {
- uint32 ssrc;
- if (!ParseSsrc(ssrc_str, &ssrc)) {
- return BadParse("Missing or invalid ssrc.", error);
- }
-
- streams->push_back(StreamParams::CreateLegacy(ssrc));
- }
- return true;
-}
-
-bool ParseSsrcs(const buzz::XmlElement* parent_elem,
- std::vector<uint32>* ssrcs,
- ParseError* error) {
- for (const buzz::XmlElement* ssrc_elem =
- parent_elem->FirstNamed(QN_JINGLE_DRAFT_SSRC);
- ssrc_elem != NULL;
- ssrc_elem = ssrc_elem->NextNamed(QN_JINGLE_DRAFT_SSRC)) {
- uint32 ssrc;
- if (!ParseSsrc(ssrc_elem->BodyText(), &ssrc)) {
- return BadParse("Missing or invalid ssrc.", error);
- }
-
- ssrcs->push_back(ssrc);
- }
- return true;
-}
-
-bool ParseSsrcGroups(const buzz::XmlElement* parent_elem,
- std::vector<SsrcGroup>* ssrc_groups,
- ParseError* error) {
- for (const buzz::XmlElement* group_elem =
- parent_elem->FirstNamed(QN_JINGLE_DRAFT_SSRC_GROUP);
- group_elem != NULL;
- group_elem = group_elem->NextNamed(QN_JINGLE_DRAFT_SSRC_GROUP)) {
- std::string semantics = group_elem->Attr(QN_SEMANTICS);
- std::vector<uint32> ssrcs;
- if (!ParseSsrcs(group_elem, &ssrcs, error)) {
- return false;
- }
- ssrc_groups->push_back(SsrcGroup(semantics, ssrcs));
- }
- return true;
-}
-
-bool ParseJingleStream(const buzz::XmlElement* stream_elem,
- std::vector<StreamParams>* streams,
- ParseError* error) {
- StreamParams stream;
- // We treat the nick as a stream groupid.
- stream.groupid = stream_elem->Attr(QN_NICK);
- stream.id = stream_elem->Attr(QN_NAME);
- stream.type = stream_elem->Attr(QN_TYPE);
- stream.display = stream_elem->Attr(QN_DISPLAY);
- stream.cname = stream_elem->Attr(QN_CNAME);
- if (!ParseSsrcs(stream_elem, &(stream.ssrcs), error)) {
- return false;
- }
- std::vector<SsrcGroup> ssrc_groups;
- if (!ParseSsrcGroups(stream_elem, &(stream.ssrc_groups), error)) {
- return false;
- }
- streams->push_back(stream);
- return true;
-}
-
-bool ParseJingleRtpHeaderExtensions(const buzz::XmlElement* parent_elem,
- std::vector<RtpHeaderExtension>* hdrexts,
- ParseError* error) {
- for (const buzz::XmlElement* hdrext_elem =
- parent_elem->FirstNamed(QN_JINGLE_RTP_HDREXT);
- hdrext_elem != NULL;
- hdrext_elem = hdrext_elem->NextNamed(QN_JINGLE_RTP_HDREXT)) {
- std::string uri = hdrext_elem->Attr(QN_URI);
- int id = GetXmlAttr(hdrext_elem, QN_ID, 0);
- if (id <= 0) {
- return BadParse("Invalid RTP header extension id.", error);
- }
- hdrexts->push_back(RtpHeaderExtension(uri, id));
- }
- return true;
-}
-
-bool HasJingleStreams(const buzz::XmlElement* desc_elem) {
- const buzz::XmlElement* streams_elem =
- desc_elem->FirstNamed(QN_JINGLE_DRAFT_STREAMS);
- return (streams_elem != NULL);
-}
-
-bool ParseJingleStreams(const buzz::XmlElement* desc_elem,
- std::vector<StreamParams>* streams,
- ParseError* error) {
- const buzz::XmlElement* streams_elem =
- desc_elem->FirstNamed(QN_JINGLE_DRAFT_STREAMS);
- if (streams_elem == NULL) {
- return BadParse("Missing streams element.", error);
- }
- for (const buzz::XmlElement* stream_elem =
- streams_elem->FirstNamed(QN_JINGLE_DRAFT_STREAM);
- stream_elem != NULL;
- stream_elem = stream_elem->NextNamed(QN_JINGLE_DRAFT_STREAM)) {
- if (!ParseJingleStream(stream_elem, streams, error)) {
- return false;
- }
- }
- return true;
-}
-
-void WriteSsrcs(const std::vector<uint32>& ssrcs,
- buzz::XmlElement* parent_elem) {
- for (std::vector<uint32>::const_iterator ssrc = ssrcs.begin();
- ssrc != ssrcs.end(); ++ssrc) {
- buzz::XmlElement* ssrc_elem =
- new buzz::XmlElement(QN_JINGLE_DRAFT_SSRC, false);
- SetXmlBody(ssrc_elem, *ssrc);
-
- parent_elem->AddElement(ssrc_elem);
- }
-}
-
-void WriteSsrcGroups(const std::vector<SsrcGroup>& groups,
- buzz::XmlElement* parent_elem) {
- for (std::vector<SsrcGroup>::const_iterator group = groups.begin();
- group != groups.end(); ++group) {
- buzz::XmlElement* group_elem =
- new buzz::XmlElement(QN_JINGLE_DRAFT_SSRC_GROUP, false);
- AddXmlAttrIfNonEmpty(group_elem, QN_SEMANTICS, group->semantics);
- WriteSsrcs(group->ssrcs, group_elem);
-
- parent_elem->AddElement(group_elem);
- }
-}
-
-void WriteJingleStream(const StreamParams& stream,
- buzz::XmlElement* parent_elem) {
- buzz::XmlElement* stream_elem =
- new buzz::XmlElement(QN_JINGLE_DRAFT_STREAM, false);
- // We treat the nick as a stream groupid.
- AddXmlAttrIfNonEmpty(stream_elem, QN_NICK, stream.groupid);
- AddXmlAttrIfNonEmpty(stream_elem, QN_NAME, stream.id);
- AddXmlAttrIfNonEmpty(stream_elem, QN_TYPE, stream.type);
- AddXmlAttrIfNonEmpty(stream_elem, QN_DISPLAY, stream.display);
- AddXmlAttrIfNonEmpty(stream_elem, QN_CNAME, stream.cname);
- WriteSsrcs(stream.ssrcs, stream_elem);
- WriteSsrcGroups(stream.ssrc_groups, stream_elem);
-
- parent_elem->AddElement(stream_elem);
-}
-
-void WriteJingleStreams(const std::vector<StreamParams>& streams,
- buzz::XmlElement* parent_elem) {
- buzz::XmlElement* streams_elem =
- new buzz::XmlElement(QN_JINGLE_DRAFT_STREAMS, true);
- for (std::vector<StreamParams>::const_iterator stream = streams.begin();
- stream != streams.end(); ++stream) {
- WriteJingleStream(*stream, streams_elem);
- }
-
- parent_elem->AddElement(streams_elem);
-}
-
-void WriteJingleRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& hdrexts,
- buzz::XmlElement* parent_elem) {
- for (std::vector<RtpHeaderExtension>::const_iterator hdrext = hdrexts.begin();
- hdrext != hdrexts.end(); ++hdrext) {
- buzz::XmlElement* hdrext_elem =
- new buzz::XmlElement(QN_JINGLE_RTP_HDREXT, false);
- AddXmlAttr(hdrext_elem, QN_URI, hdrext->uri);
- AddXmlAttr(hdrext_elem, QN_ID, hdrext->id);
- parent_elem->AddElement(hdrext_elem);
- }
-}
-
-
-} // namespace cricket
diff --git a/talk/session/media/mediamessages.h b/talk/session/media/mediamessages.h
deleted file mode 100644
index e64eaef4fc..0000000000
--- a/talk/session/media/mediamessages.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * libjingle
- * Copyright 2010 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.
- */
-
-/*
- * A collection of functions and types for serializing and
- * deserializing Jingle session messages related to media.
- * Specificially, the <notify> and <view> messages. They are not yet
- * standardized, but their current documentation can be found at:
- * goto/jinglemuc
- */
-
-#ifndef TALK_SESSION_MEDIA_MEDIAMESSAGES_H_
-#define TALK_SESSION_MEDIA_MEDIAMESSAGES_H_
-
-#include <string>
-#include <vector>
-
-#include "talk/media/base/mediachannel.h" // For RtpHeaderExtension
-#include "talk/media/base/streamparams.h"
-#include "webrtc/p2p/base/parsing.h"
-#include "webrtc/p2p/base/sessiondescription.h"
-#include "webrtc/base/basictypes.h"
-
-namespace cricket {
-
-// If the parent element (usually <jingle>) is a jingle view.
-bool IsJingleViewRequest(const buzz::XmlElement* action_elem);
-
-// Parses a view request from the parent element (usually
-// <jingle>). If it fails, it returns false and fills an error
-// message.
-bool ParseJingleViewRequest(const buzz::XmlElement* action_elem,
- ViewRequest* view_request,
- ParseError* error);
-
-// Serializes a view request to XML. If it fails, returns false and
-// fills in an error message.
-bool WriteJingleViewRequest(const std::string& content_name,
- const ViewRequest& view,
- XmlElements* elems,
- WriteError* error);
-
-// TODO(pthatcher): Get rid of legacy source notify and replace with
-// description-info as soon as reflector is capable of sending it.
-bool IsSourcesNotify(const buzz::XmlElement* action_elem);
-
-// If the given elem has <streams>.
-bool HasJingleStreams(const buzz::XmlElement* desc_elem);
-
-// Parses streams from a jingle <description>. If it fails, returns
-// false and fills an error message.
-bool ParseJingleStreams(const buzz::XmlElement* desc_elem,
- std::vector<StreamParams>* streams,
- ParseError* error);
-
-// Write a <streams> element to the parent_elem.
-void WriteJingleStreams(const std::vector<StreamParams>& streams,
- buzz::XmlElement* parent_elem);
-
-// Parses rtp header extensions from a jingle <description>. If it
-// fails, returns false and fills an error message.
-bool ParseJingleRtpHeaderExtensions(
- const buzz::XmlElement* desc_elem,
- std::vector<RtpHeaderExtension>* hdrexts,
- ParseError* error);
-
-// Writes <rtp-hdrext> elements to the parent_elem.
-void WriteJingleRtpHeaderExtensions(
- const std::vector<RtpHeaderExtension>& hdrexts,
- buzz::XmlElement* parent_elem);
-
-} // namespace cricket
-
-#endif // TALK_SESSION_MEDIA_MEDIAMESSAGES_H_
diff --git a/talk/session/media/mediamessages_unittest.cc b/talk/session/media/mediamessages_unittest.cc
deleted file mode 100644
index a9f00e47d9..0000000000
--- a/talk/session/media/mediamessages_unittest.cc
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * 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.
- */
-
-#include "talk/session/media/mediamessages.h"
-
-#include <string>
-#include <vector>
-
-#include "webrtc/p2p/base/constants.h"
-#include "talk/session/media/mediasessionclient.h"
-#include "webrtc/libjingle/xmllite/xmlelement.h"
-#include "webrtc/base/gunit.h"
-#include "webrtc/base/scoped_ptr.h"
-
-// Unit tests for mediamessages.cc.
-
-namespace cricket {
-
-namespace {
-
-static const char kViewVideoNoneXml[] =
- "<view xmlns='google:jingle'"
- " name='video1'"
- " type='none'"
- "/>";
-
-class MediaMessagesTest : public testing::Test {
- public:
- // CreateMediaSessionDescription uses a static variable cricket::NS_JINGLE_RTP
- // defined in another file and cannot be used to initialize another static
- // variable (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14)
- MediaMessagesTest()
- : remote_description_(CreateMediaSessionDescription("audio1", "video1")) {
- }
-
- protected:
- static std::string ViewVideoStaticVgaXml(const std::string& ssrc) {
- return "<view xmlns='google:jingle'"
- " name='video1'"
- " type='static'"
- " ssrc='" + ssrc + "'"
- ">"
- "<params"
- " width='640'"
- " height='480'"
- " framerate='30'"
- " preference='0'"
- " />"
- "</view>";
- }
-
- static cricket::StreamParams CreateStream(const std::string& nick,
- const std::string& name,
- uint32 ssrc1,
- uint32 ssrc2,
- const std::string& semantics,
- const std::string& type,
- const std::string& display) {
- StreamParams stream;
- stream.groupid = nick;
- stream.id = name;
- stream.ssrcs.push_back(ssrc1);
- stream.ssrcs.push_back(ssrc2);
- stream.ssrc_groups.push_back(
- cricket::SsrcGroup(semantics, stream.ssrcs));
- stream.type = type;
- stream.display = display;
- return stream;
- }
-
- static std::string StreamsXml(const std::string& stream1,
- const std::string& stream2) {
- return "<streams xmlns='google:jingle'>"
- + stream1
- + stream2 +
- "</streams>";
- }
-
-
- static std::string StreamXml(const std::string& nick,
- const std::string& name,
- const std::string& ssrc1,
- const std::string& ssrc2,
- const std::string& semantics,
- const std::string& type,
- const std::string& display) {
- return "<stream"
- " nick='" + nick + "'"
- " name='" + name + "'"
- " type='" + type + "'"
- " display='" + display + "'"
- ">"
- "<ssrc>" + ssrc1 + "</ssrc>"
- "<ssrc>" + ssrc2 + "</ssrc>"
- "<ssrc-group"
- " semantics='" + semantics + "'"
- ">"
- "<ssrc>" + ssrc1 + "</ssrc>"
- "<ssrc>" + ssrc2 + "</ssrc>"
- "</ssrc-group>"
- "</stream>";
- }
-
- static std::string HeaderExtensionsXml(const std::string& hdrext1,
- const std::string& hdrext2) {
- return "<rtp:description xmlns:rtp=\"urn:xmpp:jingle:apps:rtp:1\">"
- + hdrext1
- + hdrext2 +
- "</rtp:description>";
- }
-
- static std::string HeaderExtensionXml(const std::string& uri,
- const std::string& id) {
- return "<rtp:rtp-hdrext"
- " uri='" + uri + "'"
- " id='" + id + "'"
- "/>";
- }
-
- static cricket::SessionDescription* CreateMediaSessionDescription(
- const std::string& audio_content_name,
- const std::string& video_content_name) {
- cricket::SessionDescription* desc = new cricket::SessionDescription();
- desc->AddContent(audio_content_name, cricket::NS_JINGLE_RTP,
- new cricket::AudioContentDescription());
- desc->AddContent(video_content_name, cricket::NS_JINGLE_RTP,
- new cricket::VideoContentDescription());
- return desc;
- }
-
- size_t ClearXmlElements(cricket::XmlElements* elements) {
- size_t size = elements->size();
- for (size_t i = 0; i < size; i++) {
- delete elements->at(i);
- }
- elements->clear();
- return size;
- }
-
- rtc::scoped_ptr<cricket::SessionDescription> remote_description_;
-};
-
-} // anonymous namespace
-
-// Test serializing/deserializing an empty <view> message.
-TEST_F(MediaMessagesTest, ViewNoneToFromXml) {
- buzz::XmlElement* expected_view_elem =
- buzz::XmlElement::ForStr(kViewVideoNoneXml);
- rtc::scoped_ptr<buzz::XmlElement> action_elem(
- new buzz::XmlElement(QN_JINGLE));
-
- EXPECT_FALSE(cricket::IsJingleViewRequest(action_elem.get()));
- action_elem->AddElement(expected_view_elem);
- EXPECT_TRUE(cricket::IsJingleViewRequest(action_elem.get()));
-
- cricket::ViewRequest view_request;
- cricket::XmlElements actual_view_elems;
- cricket::WriteError error;
-
- ASSERT_TRUE(cricket::WriteJingleViewRequest(
- "video1", view_request, &actual_view_elems, &error));
-
- ASSERT_EQ(1U, actual_view_elems.size());
- EXPECT_EQ(expected_view_elem->Str(), actual_view_elems[0]->Str());
- ClearXmlElements(&actual_view_elems);
-
- cricket::ParseError parse_error;
- EXPECT_TRUE(cricket::IsJingleViewRequest(action_elem.get()));
- ASSERT_TRUE(cricket::ParseJingleViewRequest(
- action_elem.get(), &view_request, &parse_error));
- EXPECT_EQ(0U, view_request.static_video_views.size());
-}
-
-// Test serializing/deserializing an a simple vga <view> message.
-TEST_F(MediaMessagesTest, ViewVgaToFromXml) {
- rtc::scoped_ptr<buzz::XmlElement> action_elem(
- new buzz::XmlElement(QN_JINGLE));
- buzz::XmlElement* expected_view_elem1 =
- buzz::XmlElement::ForStr(ViewVideoStaticVgaXml("1234"));
- buzz::XmlElement* expected_view_elem2 =
- buzz::XmlElement::ForStr(ViewVideoStaticVgaXml("2468"));
- action_elem->AddElement(expected_view_elem1);
- action_elem->AddElement(expected_view_elem2);
-
- cricket::ViewRequest view_request;
- cricket::XmlElements actual_view_elems;
- cricket::WriteError error;
-
- view_request.static_video_views.push_back(cricket::StaticVideoView(
- cricket::StreamSelector(1234), 640, 480, 30));
- view_request.static_video_views.push_back(cricket::StaticVideoView(
- cricket::StreamSelector(2468), 640, 480, 30));
-
- ASSERT_TRUE(cricket::WriteJingleViewRequest(
- "video1", view_request, &actual_view_elems, &error));
-
- ASSERT_EQ(2U, actual_view_elems.size());
- EXPECT_EQ(expected_view_elem1->Str(), actual_view_elems[0]->Str());
- EXPECT_EQ(expected_view_elem2->Str(), actual_view_elems[1]->Str());
- ClearXmlElements(&actual_view_elems);
-
- view_request.static_video_views.clear();
- cricket::ParseError parse_error;
- EXPECT_TRUE(cricket::IsJingleViewRequest(action_elem.get()));
- ASSERT_TRUE(cricket::ParseJingleViewRequest(
- action_elem.get(), &view_request, &parse_error));
- EXPECT_EQ(2U, view_request.static_video_views.size());
- EXPECT_EQ(1234U, view_request.static_video_views[0].selector.ssrc);
- EXPECT_EQ(640, view_request.static_video_views[0].width);
- EXPECT_EQ(480, view_request.static_video_views[0].height);
- EXPECT_EQ(30, view_request.static_video_views[0].framerate);
- EXPECT_EQ(2468U, view_request.static_video_views[1].selector.ssrc);
-}
-
-// Test deserializing bad view XML.
-TEST_F(MediaMessagesTest, ParseBadViewXml) {
- rtc::scoped_ptr<buzz::XmlElement> action_elem(
- new buzz::XmlElement(QN_JINGLE));
- buzz::XmlElement* view_elem =
- buzz::XmlElement::ForStr(ViewVideoStaticVgaXml("not-an-ssrc"));
- action_elem->AddElement(view_elem);
-
- cricket::ViewRequest view_request;
- cricket::ParseError parse_error;
- ASSERT_FALSE(cricket::ParseJingleViewRequest(
- action_elem.get(), &view_request, &parse_error));
-}
-
-
-// Test serializing/deserializing typical streams xml.
-TEST_F(MediaMessagesTest, StreamsToFromXml) {
- rtc::scoped_ptr<buzz::XmlElement> expected_streams_elem(
- buzz::XmlElement::ForStr(
- StreamsXml(
- StreamXml("nick1", "stream1", "101", "102",
- "semantics1", "type1", "display1"),
- StreamXml("nick2", "stream2", "201", "202",
- "semantics2", "type2", "display2"))));
-
- std::vector<cricket::StreamParams> expected_streams;
- expected_streams.push_back(CreateStream("nick1", "stream1", 101U, 102U,
- "semantics1", "type1", "display1"));
- expected_streams.push_back(CreateStream("nick2", "stream2", 201U, 202U,
- "semantics2", "type2", "display2"));
-
- rtc::scoped_ptr<buzz::XmlElement> actual_desc_elem(
- new buzz::XmlElement(QN_JINGLE_RTP_CONTENT));
- cricket::WriteJingleStreams(expected_streams, actual_desc_elem.get());
-
- const buzz::XmlElement* actual_streams_elem =
- actual_desc_elem->FirstNamed(QN_JINGLE_DRAFT_STREAMS);
- ASSERT_TRUE(actual_streams_elem != NULL);
- EXPECT_EQ(expected_streams_elem->Str(), actual_streams_elem->Str());
-
- rtc::scoped_ptr<buzz::XmlElement> expected_desc_elem(
- new buzz::XmlElement(QN_JINGLE_RTP_CONTENT));
- expected_desc_elem->AddElement(new buzz::XmlElement(
- *expected_streams_elem));
- std::vector<cricket::StreamParams> actual_streams;
- cricket::ParseError parse_error;
-
- EXPECT_TRUE(cricket::HasJingleStreams(expected_desc_elem.get()));
- ASSERT_TRUE(cricket::ParseJingleStreams(
- expected_desc_elem.get(), &actual_streams, &parse_error));
- EXPECT_EQ(2U, actual_streams.size());
- EXPECT_EQ(expected_streams[0], actual_streams[0]);
- EXPECT_EQ(expected_streams[1], actual_streams[1]);
-}
-
-// Test deserializing bad streams xml.
-TEST_F(MediaMessagesTest, StreamsFromBadXml) {
- rtc::scoped_ptr<buzz::XmlElement> streams_elem(
- buzz::XmlElement::ForStr(
- StreamsXml(
- StreamXml("nick1", "name1", "101", "not-an-ssrc",
- "semantics1", "type1", "display1"),
- StreamXml("nick2", "name2", "202", "not-an-ssrc",
- "semantics2", "type2", "display2"))));
- rtc::scoped_ptr<buzz::XmlElement> desc_elem(
- new buzz::XmlElement(QN_JINGLE_RTP_CONTENT));
- desc_elem->AddElement(new buzz::XmlElement(*streams_elem));
-
- std::vector<cricket::StreamParams> actual_streams;
- cricket::ParseError parse_error;
- ASSERT_FALSE(cricket::ParseJingleStreams(
- desc_elem.get(), &actual_streams, &parse_error));
-}
-
-// Test serializing/deserializing typical RTP Header Extension xml.
-TEST_F(MediaMessagesTest, HeaderExtensionsToFromXml) {
- rtc::scoped_ptr<buzz::XmlElement> expected_desc_elem(
- buzz::XmlElement::ForStr(
- HeaderExtensionsXml(
- HeaderExtensionXml("abc", "123"),
- HeaderExtensionXml("def", "456"))));
-
- std::vector<cricket::RtpHeaderExtension> expected_hdrexts;
- expected_hdrexts.push_back(RtpHeaderExtension("abc", 123));
- expected_hdrexts.push_back(RtpHeaderExtension("def", 456));
-
- rtc::scoped_ptr<buzz::XmlElement> actual_desc_elem(
- new buzz::XmlElement(QN_JINGLE_RTP_CONTENT));
- cricket::WriteJingleRtpHeaderExtensions(expected_hdrexts, actual_desc_elem.get());
-
- ASSERT_TRUE(actual_desc_elem != NULL);
- EXPECT_EQ(expected_desc_elem->Str(), actual_desc_elem->Str());
-
- std::vector<cricket::RtpHeaderExtension> actual_hdrexts;
- cricket::ParseError parse_error;
- ASSERT_TRUE(cricket::ParseJingleRtpHeaderExtensions(
- expected_desc_elem.get(), &actual_hdrexts, &parse_error));
- EXPECT_EQ(2U, actual_hdrexts.size());
- EXPECT_EQ(expected_hdrexts[0], actual_hdrexts[0]);
- EXPECT_EQ(expected_hdrexts[1], actual_hdrexts[1]);
-}
-
-// Test deserializing bad RTP header extension xml.
-TEST_F(MediaMessagesTest, HeaderExtensionsFromBadXml) {
- std::vector<cricket::RtpHeaderExtension> actual_hdrexts;
- cricket::ParseError parse_error;
-
- rtc::scoped_ptr<buzz::XmlElement> desc_elem(
- buzz::XmlElement::ForStr(
- HeaderExtensionsXml(
- HeaderExtensionXml("abc", "123"),
- HeaderExtensionXml("def", "not-an-id"))));
- ASSERT_FALSE(cricket::ParseJingleRtpHeaderExtensions(
- desc_elem.get(), &actual_hdrexts, &parse_error));
-
- desc_elem.reset(
- buzz::XmlElement::ForStr(
- HeaderExtensionsXml(
- HeaderExtensionXml("abc", "123"),
- HeaderExtensionXml("def", "-1"))));
- ASSERT_FALSE(cricket::ParseJingleRtpHeaderExtensions(
- desc_elem.get(), &actual_hdrexts, &parse_error));
-}
-
-} // namespace cricket
diff --git a/talk/session/media/mediasessionclient.cc b/talk/session/media/mediasessionclient.cc
deleted file mode 100644
index 5cb79175d8..0000000000
--- a/talk/session/media/mediasessionclient.cc
+++ /dev/null
@@ -1,1161 +0,0 @@
-/*
- * 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.
- */
-
-#include <string>
-
-#include "talk/session/media/mediasessionclient.h"
-
-#include "talk/media/base/capturemanager.h"
-#include "talk/media/base/cryptoparams.h"
-#include "talk/media/sctp/sctpdataengine.h"
-#include "webrtc/p2p/base/constants.h"
-#include "webrtc/p2p/base/parsing.h"
-#include "talk/session/media/mediamessages.h"
-#include "talk/session/media/srtpfilter.h"
-#include "webrtc/libjingle/xmllite/qname.h"
-#include "webrtc/libjingle/xmllite/xmlconstants.h"
-#include "webrtc/libjingle/xmpp/constants.h"
-#include "webrtc/base/helpers.h"
-#include "webrtc/base/logging.h"
-#include "webrtc/base/stringencode.h"
-#include "webrtc/base/stringutils.h"
-
-namespace cricket {
-
-#if !defined(DISABLE_MEDIA_ENGINE_FACTORY)
-MediaSessionClient::MediaSessionClient(
- const buzz::Jid& jid, SessionManager *manager)
- : jid_(jid),
- session_manager_(manager),
- focus_call_(NULL),
- channel_manager_(new ChannelManager(session_manager_->worker_thread())),
- desc_factory_(channel_manager_,
- session_manager_->transport_desc_factory()),
- multisession_enabled_(false) {
- Construct();
-}
-#endif
-
-MediaSessionClient::MediaSessionClient(
- const buzz::Jid& jid, SessionManager *manager,
- MediaEngineInterface* media_engine,
- DataEngineInterface* data_media_engine,
- DeviceManagerInterface* device_manager)
- : jid_(jid),
- session_manager_(manager),
- focus_call_(NULL),
- channel_manager_(new ChannelManager(
- media_engine, data_media_engine,
- device_manager, new CaptureManager(),
- session_manager_->worker_thread())),
- desc_factory_(channel_manager_,
- session_manager_->transport_desc_factory()),
- multisession_enabled_(false) {
- Construct();
-}
-
-void MediaSessionClient::Construct() {
- // Register ourselves as the handler of audio and video sessions.
- session_manager_->AddClient(NS_JINGLE_RTP, this);
- // Forward device notifications.
- SignalDevicesChange.repeat(channel_manager_->SignalDevicesChange);
- // Bring up the channel manager.
- // In previous versions of ChannelManager, this was done automatically
- // in the constructor.
- channel_manager_->Init();
-}
-
-MediaSessionClient::~MediaSessionClient() {
- // Destroy all calls
- std::map<uint32, Call *>::iterator it;
- while (calls_.begin() != calls_.end()) {
- std::map<uint32, Call *>::iterator it = calls_.begin();
- DestroyCall((*it).second);
- }
-
- // Delete channel manager. This will wait for the channels to exit
- delete channel_manager_;
-
- // Remove ourselves from the client map.
- session_manager_->RemoveClient(NS_JINGLE_RTP);
-}
-
-Call *MediaSessionClient::CreateCall() {
- Call *call = new Call(this);
- calls_[call->id()] = call;
- SignalCallCreate(call);
- return call;
-}
-
-void MediaSessionClient::OnSessionCreate(Session *session,
- bool received_initiate) {
- if (received_initiate) {
- session->SignalState.connect(this, &MediaSessionClient::OnSessionState);
- }
-}
-
-void MediaSessionClient::OnSessionState(BaseSession* base_session,
- BaseSession::State state) {
- // MediaSessionClient can only be used with a Session*, so it's
- // safe to cast here.
- Session* session = static_cast<Session*>(base_session);
-
- if (state == Session::STATE_RECEIVEDINITIATE) {
- // The creation of the call must happen after the session has
- // processed the initiate message because we need the
- // remote_description to know what content names to use in the
- // call.
-
- // If our accept would have no codecs, then we must reject this call.
- const SessionDescription* offer = session->remote_description();
- const SessionDescription* accept = CreateAnswer(offer, CallOptions());
- const ContentInfo* audio_content = GetFirstAudioContent(accept);
- bool audio_rejected = (!audio_content) ? true : audio_content->rejected;
- const AudioContentDescription* audio_desc = (!audio_content) ? NULL :
- static_cast<const AudioContentDescription*>(audio_content->description);
-
- // For some reason, we need a call even if we reject. So, either find a
- // matching call or create a new one.
- // The matching of existing calls is used to support the multi-session mode
- // required for p2p handoffs: ie. once a MUC call is established, a new
- // session may be established for the same call but is direct between the
- // clients. To indicate that this is the case, the initiator of the incoming
- // session is set to be the same as the remote name of the MUC for the
- // existing session, thus the client can know that this is a new session for
- // the existing call, rather than a whole new call.
- Call* call = NULL;
- if (multisession_enabled_) {
- call = FindCallByRemoteName(session->initiator_name());
- }
-
- if (call == NULL) {
- // Could not find a matching call, so create a new one.
- call = CreateCall();
- }
-
- session_map_[session->id()] = call;
- call->IncomingSession(session, offer);
-
- if (audio_rejected || !audio_desc || audio_desc->codecs().size() == 0) {
- session->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
- }
- delete accept;
- }
-}
-
-void MediaSessionClient::DestroyCall(Call *call) {
- // Change focus away, signal destruction
-
- if (call == focus_call_)
- SetFocus(NULL);
- SignalCallDestroy(call);
-
- // Remove it from calls_ map and delete
-
- std::map<uint32, Call *>::iterator it = calls_.find(call->id());
- if (it != calls_.end())
- calls_.erase(it);
-
- delete call;
-}
-
-void MediaSessionClient::OnSessionDestroy(Session *session) {
- // Find the call this session is in, remove it
- SessionMap::iterator it = session_map_.find(session->id());
- ASSERT(it != session_map_.end());
- if (it != session_map_.end()) {
- Call *call = (*it).second;
- session_map_.erase(it);
- call->RemoveSession(session);
- }
-}
-
-Call *MediaSessionClient::GetFocus() {
- return focus_call_;
-}
-
-void MediaSessionClient::SetFocus(Call *call) {
- Call *old_focus_call = focus_call_;
- if (focus_call_ != call) {
- if (focus_call_ != NULL)
- focus_call_->EnableChannels(false);
- focus_call_ = call;
- if (focus_call_ != NULL)
- focus_call_->EnableChannels(true);
- SignalFocus(focus_call_, old_focus_call);
- }
-}
-
-void MediaSessionClient::JoinCalls(Call *call_to_join, Call *call) {
- // Move all sessions from call to call_to_join, delete call.
- // If call_to_join has focus, added sessions should have enabled channels.
-
- if (focus_call_ == call)
- SetFocus(NULL);
- call_to_join->Join(call, focus_call_ == call_to_join);
- DestroyCall(call);
-}
-
-Session *MediaSessionClient::CreateSession(Call *call) {
- std::string id;
- return CreateSession(id, call);
-}
-
-Session *MediaSessionClient::CreateSession(const std::string& id, Call* call) {
- const std::string& type = NS_JINGLE_RTP;
- Session *session = session_manager_->CreateSession(id, jid().Str(), type);
- session_map_[session->id()] = call;
- return session;
-}
-
-Call *MediaSessionClient::FindCallByRemoteName(const std::string &remote_name) {
- SessionMap::const_iterator call;
- for (call = session_map_.begin(); call != session_map_.end(); ++call) {
- std::vector<Session *> sessions = call->second->sessions();
- std::vector<Session *>::const_iterator session;
- for (session = sessions.begin(); session != sessions.end(); ++session) {
- if (remote_name == (*session)->remote_name()) {
- return call->second;
- }
- }
- }
-
- return NULL;
-}
-
-// TODO(pthatcher): Move all of the parsing and writing functions into
-// mediamessages.cc, with unit tests.
-bool ParseGingleAudioCodec(const buzz::XmlElement* element, AudioCodec* out) {
- int id = GetXmlAttr(element, QN_ID, -1);
- if (id < 0)
- return false;
-
- std::string name = GetXmlAttr(element, QN_NAME, buzz::STR_EMPTY);
- int clockrate = GetXmlAttr(element, QN_CLOCKRATE, 0);
- int bitrate = GetXmlAttr(element, QN_BITRATE, 0);
- int channels = GetXmlAttr(element, QN_CHANNELS, 1);
- *out = AudioCodec(id, name, clockrate, bitrate, channels, 0);
- return true;
-}
-
-bool ParseGingleVideoCodec(const buzz::XmlElement* element, VideoCodec* out) {
- int id = GetXmlAttr(element, QN_ID, -1);
- if (id < 0)
- return false;
-
- std::string name = GetXmlAttr(element, QN_NAME, buzz::STR_EMPTY);
- int width = GetXmlAttr(element, QN_WIDTH, 0);
- int height = GetXmlAttr(element, QN_HEIGHT, 0);
- int framerate = GetXmlAttr(element, QN_FRAMERATE, 0);
-
- *out = VideoCodec(id, name, width, height, framerate, 0);
- return true;
-}
-
-// Parses an ssrc string as a legacy stream. If it fails, returns
-// false and fills an error message.
-bool ParseSsrcAsLegacyStream(const std::string& ssrc_str,
- std::vector<StreamParams>* streams,
- ParseError* error) {
- if (!ssrc_str.empty()) {
- uint32 ssrc;
- if (!rtc::FromString(ssrc_str, &ssrc)) {
- return BadParse("Missing or invalid ssrc.", error);
- }
-
- streams->push_back(StreamParams::CreateLegacy(ssrc));
- }
- return true;
-}
-
-void ParseGingleSsrc(const buzz::XmlElement* parent_elem,
- const buzz::QName& name,
- MediaContentDescription* media) {
- const buzz::XmlElement* ssrc_elem = parent_elem->FirstNamed(name);
- if (ssrc_elem) {
- ParseError error;
- ParseSsrcAsLegacyStream(
- ssrc_elem->BodyText(), &(media->mutable_streams()), &error);
- }
-}
-
-bool ParseCryptoParams(const buzz::XmlElement* element,
- CryptoParams* out,
- ParseError* error) {
- if (!element->HasAttr(QN_CRYPTO_SUITE)) {
- return BadParse("crypto: crypto-suite attribute missing ", error);
- } else if (!element->HasAttr(QN_CRYPTO_KEY_PARAMS)) {
- return BadParse("crypto: key-params attribute missing ", error);
- } else if (!element->HasAttr(QN_CRYPTO_TAG)) {
- return BadParse("crypto: tag attribute missing ", error);
- }
-
- const std::string& crypto_suite = element->Attr(QN_CRYPTO_SUITE);
- const std::string& key_params = element->Attr(QN_CRYPTO_KEY_PARAMS);
- const int tag = GetXmlAttr(element, QN_CRYPTO_TAG, 0);
- const std::string& session_params =
- element->Attr(QN_CRYPTO_SESSION_PARAMS); // Optional.
-
- *out = CryptoParams(tag, crypto_suite, key_params, session_params);
- return true;
-}
-
-
-// Parse the first encryption element found with a matching 'usage'
-// element.
-// <usage/> is specific to Gingle. In Jingle, <crypto/> is already
-// scoped to a content.
-// Return false if there was an encryption element and it could not be
-// parsed.
-bool ParseGingleEncryption(const buzz::XmlElement* desc,
- const buzz::QName& usage,
- MediaContentDescription* media,
- ParseError* error) {
- for (const buzz::XmlElement* encryption = desc->FirstNamed(QN_ENCRYPTION);
- encryption != NULL;
- encryption = encryption->NextNamed(QN_ENCRYPTION)) {
- if (encryption->FirstNamed(usage) != NULL) {
- if (GetXmlAttr(encryption, QN_ENCRYPTION_REQUIRED, false)) {
- media->set_crypto_required(CT_SDES);
- }
- for (const buzz::XmlElement* crypto = encryption->FirstNamed(QN_CRYPTO);
- crypto != NULL;
- crypto = crypto->NextNamed(QN_CRYPTO)) {
- CryptoParams params;
- if (!ParseCryptoParams(crypto, &params, error)) {
- return false;
- }
- media->AddCrypto(params);
- }
- break;
- }
- }
- return true;
-}
-
-void ParseBandwidth(const buzz::XmlElement* parent_elem,
- MediaContentDescription* media) {
- const buzz::XmlElement* bw_elem = GetXmlChild(parent_elem, LN_BANDWIDTH);
- int bandwidth_kbps = -1;
- if (bw_elem && rtc::FromString(bw_elem->BodyText(), &bandwidth_kbps)) {
- if (bandwidth_kbps >= 0) {
- media->set_bandwidth(bandwidth_kbps * 1000);
- }
- }
-}
-
-bool ParseGingleAudioContent(const buzz::XmlElement* content_elem,
- ContentDescription** content,
- ParseError* error) {
- AudioContentDescription* audio = new AudioContentDescription();
-
- int preference = kMaxPayloadId;
- if (content_elem->FirstElement()) {
- for (const buzz::XmlElement* codec_elem =
- content_elem->FirstNamed(QN_GINGLE_AUDIO_PAYLOADTYPE);
- codec_elem != NULL;
- codec_elem = codec_elem->NextNamed(QN_GINGLE_AUDIO_PAYLOADTYPE)) {
- AudioCodec codec;
- if (ParseGingleAudioCodec(codec_elem, &codec)) {
- codec.preference = preference--;
- audio->AddCodec(codec);
- }
- }
- } else {
- // For backward compatibility, we can assume the other client is
- // an old version of Talk if it has no audio payload types at all.
- audio->AddCodec(AudioCodec(103, "ISAC", 16000, -1, 1, 1));
- audio->AddCodec(AudioCodec(0, "PCMU", 8000, 64000, 1, 0));
- }
-
- ParseGingleSsrc(content_elem, QN_GINGLE_AUDIO_SRCID, audio);
-
- if (!ParseGingleEncryption(content_elem, QN_GINGLE_AUDIO_CRYPTO_USAGE,
- audio, error)) {
- return false;
- }
-
- *content = audio;
- return true;
-}
-
-bool ParseGingleVideoContent(const buzz::XmlElement* content_elem,
- ContentDescription** content,
- ParseError* error) {
- VideoContentDescription* video = new VideoContentDescription();
-
- int preference = kMaxPayloadId;
- for (const buzz::XmlElement* codec_elem =
- content_elem->FirstNamed(QN_GINGLE_VIDEO_PAYLOADTYPE);
- codec_elem != NULL;
- codec_elem = codec_elem->NextNamed(QN_GINGLE_VIDEO_PAYLOADTYPE)) {
- VideoCodec codec;
- if (ParseGingleVideoCodec(codec_elem, &codec)) {
- codec.preference = preference--;
- video->AddCodec(codec);
- }
- }
-
- ParseGingleSsrc(content_elem, QN_GINGLE_VIDEO_SRCID, video);
- ParseBandwidth(content_elem, video);
-
- if (!ParseGingleEncryption(content_elem, QN_GINGLE_VIDEO_CRYPTO_USAGE,
- video, error)) {
- return false;
- }
-
- *content = video;
- return true;
-}
-
-void ParsePayloadTypeParameters(const buzz::XmlElement* element,
- std::map<std::string, std::string>* paramap) {
- for (const buzz::XmlElement* param = element->FirstNamed(QN_PARAMETER);
- param != NULL; param = param->NextNamed(QN_PARAMETER)) {
- std::string name = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_NAME,
- buzz::STR_EMPTY);
- std::string value = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_VALUE,
- buzz::STR_EMPTY);
- if (!name.empty() && !value.empty()) {
- paramap->insert(make_pair(name, value));
- }
- }
-}
-
-void ParseFeedbackParams(const buzz::XmlElement* element,
- FeedbackParams* params) {
- for (const buzz::XmlElement* param = element->FirstNamed(QN_JINGLE_RTCP_FB);
- param != NULL; param = param->NextNamed(QN_JINGLE_RTCP_FB)) {
- std::string type = GetXmlAttr(param, QN_TYPE, buzz::STR_EMPTY);
- std::string subtype = GetXmlAttr(param, QN_SUBTYPE, buzz::STR_EMPTY);
- if (!type.empty()) {
- params->Add(FeedbackParam(type, subtype));
- }
- }
-}
-
-void AddFeedbackParams(const FeedbackParams& additional_params,
- FeedbackParams* params) {
- for (size_t i = 0; i < additional_params.params().size(); ++i) {
- params->Add(additional_params.params()[i]);
- }
-}
-
-int FindWithDefault(const std::map<std::string, std::string>& map,
- const std::string& key, const int def) {
- std::map<std::string, std::string>::const_iterator iter = map.find(key);
- return (iter == map.end()) ? def : atoi(iter->second.c_str());
-}
-
-
-// Parse the first encryption element found.
-// Return false if there was an encryption element and it could not be
-// parsed.
-bool ParseJingleEncryption(const buzz::XmlElement* content_elem,
- MediaContentDescription* media,
- ParseError* error) {
- const buzz::XmlElement* encryption =
- content_elem->FirstNamed(QN_ENCRYPTION);
- if (encryption == NULL) {
- return true;
- }
-
- if (GetXmlAttr(encryption, QN_ENCRYPTION_REQUIRED, false)) {
- media->set_crypto_required(CT_SDES);
- }
-
- for (const buzz::XmlElement* crypto = encryption->FirstNamed(QN_CRYPTO);
- crypto != NULL;
- crypto = crypto->NextNamed(QN_CRYPTO)) {
- CryptoParams params;
- if (!ParseCryptoParams(crypto, &params, error)) {
- return false;
- }
- media->AddCrypto(params);
- }
- return true;
-}
-
-bool ParseJingleAudioCodec(const buzz::XmlElement* elem, AudioCodec* codec) {
- int id = GetXmlAttr(elem, QN_ID, -1);
- if (id < 0)
- return false;
-
- std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY);
- int clockrate = GetXmlAttr(elem, QN_CLOCKRATE, 0);
- int channels = GetXmlAttr(elem, QN_CHANNELS, 1);
-
- std::map<std::string, std::string> paramap;
- ParsePayloadTypeParameters(elem, &paramap);
- int bitrate = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_BITRATE, 0);
-
- *codec = AudioCodec(id, name, clockrate, bitrate, channels, 0);
- ParseFeedbackParams(elem, &codec->feedback_params);
- return true;
-}
-
-bool ParseJingleVideoCodec(const buzz::XmlElement* elem, VideoCodec* codec) {
- int id = GetXmlAttr(elem, QN_ID, -1);
- if (id < 0)
- return false;
-
- std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY);
-
- std::map<std::string, std::string> paramap;
- ParsePayloadTypeParameters(elem, &paramap);
- int width = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_WIDTH, 0);
- int height = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_HEIGHT, 0);
- int framerate = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_FRAMERATE, 0);
-
- *codec = VideoCodec(id, name, width, height, framerate, 0);
- codec->params = paramap;
- ParseFeedbackParams(elem, &codec->feedback_params);
- return true;
-}
-
-bool ParseJingleDataCodec(const buzz::XmlElement* elem, DataCodec* codec) {
- int id = GetXmlAttr(elem, QN_ID, -1);
- if (id < 0)
- return false;
-
- std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY);
-
- *codec = DataCodec(id, name, 0);
- ParseFeedbackParams(elem, &codec->feedback_params);
- return true;
-}
-
-bool ParseJingleStreamsOrLegacySsrc(const buzz::XmlElement* desc_elem,
- MediaContentDescription* media,
- ParseError* error) {
- if (HasJingleStreams(desc_elem)) {
- if (!ParseJingleStreams(desc_elem, &(media->mutable_streams()), error)) {
- return false;
- }
- } else {
- const std::string ssrc_str = desc_elem->Attr(QN_SSRC);
- if (!ParseSsrcAsLegacyStream(
- ssrc_str, &(media->mutable_streams()), error)) {
- return false;
- }
- }
- return true;
-}
-
-bool ParseJingleAudioContent(const buzz::XmlElement* content_elem,
- ContentDescription** content,
- ParseError* error) {
- rtc::scoped_ptr<AudioContentDescription> audio(
- new AudioContentDescription());
-
- FeedbackParams content_feedback_params;
- ParseFeedbackParams(content_elem, &content_feedback_params);
-
- int preference = kMaxPayloadId;
- for (const buzz::XmlElement* payload_elem =
- content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE);
- payload_elem != NULL;
- payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) {
- AudioCodec codec;
- if (ParseJingleAudioCodec(payload_elem, &codec)) {
- AddFeedbackParams(content_feedback_params, &codec.feedback_params);
- codec.preference = preference--;
- audio->AddCodec(codec);
- }
- }
-
- if (!ParseJingleStreamsOrLegacySsrc(content_elem, audio.get(), error)) {
- return false;
- }
-
- if (!ParseJingleEncryption(content_elem, audio.get(), error)) {
- return false;
- }
-
- audio->set_rtcp_mux(content_elem->FirstNamed(QN_JINGLE_RTCP_MUX) != NULL);
-
- RtpHeaderExtensions hdrexts;
- if (!ParseJingleRtpHeaderExtensions(content_elem, &hdrexts, error)) {
- return false;
- }
- audio->set_rtp_header_extensions(hdrexts);
-
- *content = audio.release();
- return true;
-}
-
-bool ParseJingleVideoContent(const buzz::XmlElement* content_elem,
- ContentDescription** content,
- ParseError* error) {
- rtc::scoped_ptr<VideoContentDescription> video(
- new VideoContentDescription());
-
- FeedbackParams content_feedback_params;
- ParseFeedbackParams(content_elem, &content_feedback_params);
-
- int preference = kMaxPayloadId;
- for (const buzz::XmlElement* payload_elem =
- content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE);
- payload_elem != NULL;
- payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) {
- VideoCodec codec;
- if (ParseJingleVideoCodec(payload_elem, &codec)) {
- AddFeedbackParams(content_feedback_params, &codec.feedback_params);
- codec.preference = preference--;
- video->AddCodec(codec);
- }
- }
-
- if (!ParseJingleStreamsOrLegacySsrc(content_elem, video.get(), error)) {
- return false;
- }
- ParseBandwidth(content_elem, video.get());
-
- if (!ParseJingleEncryption(content_elem, video.get(), error)) {
- return false;
- }
-
- video->set_rtcp_mux(content_elem->FirstNamed(QN_JINGLE_RTCP_MUX) != NULL);
-
- RtpHeaderExtensions hdrexts;
- if (!ParseJingleRtpHeaderExtensions(content_elem, &hdrexts, error)) {
- return false;
- }
- video->set_rtp_header_extensions(hdrexts);
-
- *content = video.release();
- return true;
-}
-
-bool ParseJingleSctpDataContent(const buzz::XmlElement* content_elem,
- ContentDescription** content,
- ParseError* error) {
- rtc::scoped_ptr<DataContentDescription> data(
- new DataContentDescription());
- data->set_protocol(kMediaProtocolSctp);
-
- for (const buzz::XmlElement* stream_elem =
- content_elem->FirstNamed(QN_JINGLE_DRAFT_SCTP_STREAM);
- stream_elem != NULL;
- stream_elem = stream_elem->NextNamed(QN_JINGLE_DRAFT_SCTP_STREAM)) {
- StreamParams stream;
- stream.groupid = stream_elem->Attr(QN_NICK);
- stream.id = stream_elem->Attr(QN_NAME);
- uint32 sid;
- if (!rtc::FromString(stream_elem->Attr(QN_SID), &sid)) {
- return BadParse("Missing or invalid sid.", error);
- }
- if (sid > kMaxSctpSid) {
- return BadParse("SID is greater than max value.", error);
- }
-
- stream.ssrcs.push_back(sid);
- data->mutable_streams().push_back(stream);
- }
-
- *content = data.release();
- return true;
-}
-
-bool ParseJingleRtpDataContent(const buzz::XmlElement* content_elem,
- ContentDescription** content,
- ParseError* error) {
- DataContentDescription* data = new DataContentDescription();
-
- FeedbackParams content_feedback_params;
- ParseFeedbackParams(content_elem, &content_feedback_params);
-
- int preference = kMaxPayloadId;
- for (const buzz::XmlElement* payload_elem =
- content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE);
- payload_elem != NULL;
- payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) {
- DataCodec codec;
- if (ParseJingleDataCodec(payload_elem, &codec)) {
- AddFeedbackParams(content_feedback_params, &codec.feedback_params);
- codec.preference = preference--;
- data->AddCodec(codec);
- }
- }
-
- if (!ParseJingleStreamsOrLegacySsrc(content_elem, data, error)) {
- return false;
- }
- ParseBandwidth(content_elem, data);
-
- if (!ParseJingleEncryption(content_elem, data, error)) {
- return false;
- }
-
- data->set_rtcp_mux(content_elem->FirstNamed(QN_JINGLE_RTCP_MUX) != NULL);
-
- *content = data;
- return true;
-}
-
-bool MediaSessionClient::ParseContent(SignalingProtocol protocol,
- const buzz::XmlElement* content_elem,
- ContentDescription** content,
- ParseError* error) {
- if (protocol == PROTOCOL_GINGLE) {
- const std::string& content_type = content_elem->Name().Namespace();
- if (NS_GINGLE_AUDIO == content_type) {
- return ParseGingleAudioContent(content_elem, content, error);
- } else if (NS_GINGLE_VIDEO == content_type) {
- return ParseGingleVideoContent(content_elem, content, error);
- } else {
- return BadParse("Unknown content type: " + content_type, error);
- }
- } else {
- const std::string& content_type = content_elem->Name().Namespace();
- // We use the XMLNS of the <description> element to determine if
- // it's RTP or SCTP.
- if (content_type == NS_JINGLE_DRAFT_SCTP) {
- return ParseJingleSctpDataContent(content_elem, content, error);
- }
-
- std::string media;
- if (!RequireXmlAttr(content_elem, QN_JINGLE_CONTENT_MEDIA, &media, error))
- return false;
-
- if (media == JINGLE_CONTENT_MEDIA_AUDIO) {
- return ParseJingleAudioContent(content_elem, content, error);
- } else if (media == JINGLE_CONTENT_MEDIA_VIDEO) {
- return ParseJingleVideoContent(content_elem, content, error);
- } else if (media == JINGLE_CONTENT_MEDIA_DATA) {
- return ParseJingleRtpDataContent(content_elem, content, error);
- } else {
- return BadParse("Unknown media: " + media, error);
- }
- }
-}
-
-buzz::XmlElement* CreateGingleAudioCodecElem(const AudioCodec& codec) {
- buzz::XmlElement* payload_type =
- new buzz::XmlElement(QN_GINGLE_AUDIO_PAYLOADTYPE, true);
- AddXmlAttr(payload_type, QN_ID, codec.id);
- payload_type->AddAttr(QN_NAME, codec.name);
- if (codec.clockrate > 0)
- AddXmlAttr(payload_type, QN_CLOCKRATE, codec.clockrate);
- if (codec.bitrate > 0)
- AddXmlAttr(payload_type, QN_BITRATE, codec.bitrate);
- if (codec.channels > 1)
- AddXmlAttr(payload_type, QN_CHANNELS, codec.channels);
- return payload_type;
-}
-
-buzz::XmlElement* CreateGingleVideoCodecElem(const VideoCodec& codec) {
- buzz::XmlElement* payload_type =
- new buzz::XmlElement(QN_GINGLE_VIDEO_PAYLOADTYPE, true);
- AddXmlAttr(payload_type, QN_ID, codec.id);
- payload_type->AddAttr(QN_NAME, codec.name);
- AddXmlAttr(payload_type, QN_WIDTH, codec.width);
- AddXmlAttr(payload_type, QN_HEIGHT, codec.height);
- AddXmlAttr(payload_type, QN_FRAMERATE, codec.framerate);
- return payload_type;
-}
-
-buzz::XmlElement* CreateGingleSsrcElem(const buzz::QName& name, uint32 ssrc) {
- buzz::XmlElement* elem = new buzz::XmlElement(name, true);
- if (ssrc) {
- SetXmlBody(elem, ssrc);
- }
- return elem;
-}
-
-buzz::XmlElement* CreateBandwidthElem(const buzz::QName& name, int bps) {
- int kbps = bps / 1000;
- buzz::XmlElement* elem = new buzz::XmlElement(name);
- elem->AddAttr(buzz::QN_TYPE, "AS");
- SetXmlBody(elem, kbps);
- return elem;
-}
-
-// For Jingle, usage_qname is empty.
-buzz::XmlElement* CreateJingleEncryptionElem(const CryptoParamsVec& cryptos,
- bool required) {
- buzz::XmlElement* encryption_elem = new buzz::XmlElement(QN_ENCRYPTION);
-
- if (required) {
- encryption_elem->SetAttr(QN_ENCRYPTION_REQUIRED, "true");
- }
-
- for (CryptoParamsVec::const_iterator i = cryptos.begin();
- i != cryptos.end();
- ++i) {
- buzz::XmlElement* crypto_elem = new buzz::XmlElement(QN_CRYPTO);
-
- AddXmlAttr(crypto_elem, QN_CRYPTO_TAG, i->tag);
- crypto_elem->AddAttr(QN_CRYPTO_SUITE, i->cipher_suite);
- crypto_elem->AddAttr(QN_CRYPTO_KEY_PARAMS, i->key_params);
- if (!i->session_params.empty()) {
- crypto_elem->AddAttr(QN_CRYPTO_SESSION_PARAMS, i->session_params);
- }
- encryption_elem->AddElement(crypto_elem);
- }
- return encryption_elem;
-}
-
-buzz::XmlElement* CreateGingleEncryptionElem(const CryptoParamsVec& cryptos,
- const buzz::QName& usage_qname,
- bool required) {
- buzz::XmlElement* encryption_elem =
- CreateJingleEncryptionElem(cryptos, required);
-
- if (required) {
- encryption_elem->SetAttr(QN_ENCRYPTION_REQUIRED, "true");
- }
-
- buzz::XmlElement* usage_elem = new buzz::XmlElement(usage_qname);
- encryption_elem->AddElement(usage_elem);
-
- return encryption_elem;
-}
-
-buzz::XmlElement* CreateGingleAudioContentElem(
- const AudioContentDescription* audio,
- bool crypto_required) {
- buzz::XmlElement* elem =
- new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT, true);
-
- for (AudioCodecs::const_iterator codec = audio->codecs().begin();
- codec != audio->codecs().end(); ++codec) {
- elem->AddElement(CreateGingleAudioCodecElem(*codec));
- }
- if (audio->has_ssrcs()) {
- elem->AddElement(CreateGingleSsrcElem(
- QN_GINGLE_AUDIO_SRCID, audio->first_ssrc()));
- }
-
- const CryptoParamsVec& cryptos = audio->cryptos();
- if (!cryptos.empty()) {
- elem->AddElement(CreateGingleEncryptionElem(cryptos,
- QN_GINGLE_AUDIO_CRYPTO_USAGE,
- crypto_required));
- }
- return elem;
-}
-
-buzz::XmlElement* CreateGingleVideoContentElem(
- const VideoContentDescription* video,
- bool crypto_required) {
- buzz::XmlElement* elem =
- new buzz::XmlElement(QN_GINGLE_VIDEO_CONTENT, true);
-
- for (VideoCodecs::const_iterator codec = video->codecs().begin();
- codec != video->codecs().end(); ++codec) {
- elem->AddElement(CreateGingleVideoCodecElem(*codec));
- }
- if (video->has_ssrcs()) {
- elem->AddElement(CreateGingleSsrcElem(
- QN_GINGLE_VIDEO_SRCID, video->first_ssrc()));
- }
- if (video->bandwidth() != kAutoBandwidth) {
- elem->AddElement(CreateBandwidthElem(QN_GINGLE_VIDEO_BANDWIDTH,
- video->bandwidth()));
- }
-
- const CryptoParamsVec& cryptos = video->cryptos();
- if (!cryptos.empty()) {
- elem->AddElement(CreateGingleEncryptionElem(cryptos,
- QN_GINGLE_VIDEO_CRYPTO_USAGE,
- crypto_required));
- }
-
- return elem;
-}
-
-template <class T>
-buzz::XmlElement* CreatePayloadTypeParameterElem(
- const std::string& name, T value) {
- buzz::XmlElement* elem = new buzz::XmlElement(QN_PARAMETER);
-
- elem->AddAttr(QN_PAYLOADTYPE_PARAMETER_NAME, name);
- AddXmlAttr(elem, QN_PAYLOADTYPE_PARAMETER_VALUE, value);
-
- return elem;
-}
-
-void AddRtcpFeedbackElem(buzz::XmlElement* elem,
- const FeedbackParams& feedback_params) {
- std::vector<FeedbackParam>::const_iterator it;
- for (it = feedback_params.params().begin();
- it != feedback_params.params().end(); ++it) {
- buzz::XmlElement* fb_elem = new buzz::XmlElement(QN_JINGLE_RTCP_FB);
- fb_elem->AddAttr(QN_TYPE, it->id());
- fb_elem->AddAttr(QN_SUBTYPE, it->param());
- elem->AddElement(fb_elem);
- }
-}
-
-buzz::XmlElement* CreateJingleAudioCodecElem(const AudioCodec& codec) {
- buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE);
-
- AddXmlAttr(elem, QN_ID, codec.id);
- elem->AddAttr(QN_NAME, codec.name);
- if (codec.clockrate > 0) {
- AddXmlAttr(elem, QN_CLOCKRATE, codec.clockrate);
- }
- if (codec.bitrate > 0) {
- elem->AddElement(CreatePayloadTypeParameterElem(
- PAYLOADTYPE_PARAMETER_BITRATE, codec.bitrate));
- }
- if (codec.channels > 1) {
- AddXmlAttr(elem, QN_CHANNELS, codec.channels);
- }
-
- AddRtcpFeedbackElem(elem, codec.feedback_params);
-
- return elem;
-}
-
-buzz::XmlElement* CreateJingleVideoCodecElem(const VideoCodec& codec) {
- buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE);
-
- AddXmlAttr(elem, QN_ID, codec.id);
- elem->AddAttr(QN_NAME, codec.name);
- elem->AddElement(CreatePayloadTypeParameterElem(
- PAYLOADTYPE_PARAMETER_WIDTH, codec.width));
- elem->AddElement(CreatePayloadTypeParameterElem(
- PAYLOADTYPE_PARAMETER_HEIGHT, codec.height));
- elem->AddElement(CreatePayloadTypeParameterElem(
- PAYLOADTYPE_PARAMETER_FRAMERATE, codec.framerate));
-
- AddRtcpFeedbackElem(elem, codec.feedback_params);
-
- CodecParameterMap::const_iterator param_iter;
- for (param_iter = codec.params.begin(); param_iter != codec.params.end();
- ++param_iter) {
- elem->AddElement(CreatePayloadTypeParameterElem(param_iter->first,
- param_iter->second));
- }
-
- return elem;
-}
-
-buzz::XmlElement* CreateJingleDataCodecElem(const DataCodec& codec) {
- buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE);
-
- AddXmlAttr(elem, QN_ID, codec.id);
- elem->AddAttr(QN_NAME, codec.name);
-
- AddRtcpFeedbackElem(elem, codec.feedback_params);
-
- return elem;
-}
-
-void WriteLegacyJingleSsrc(const MediaContentDescription* media,
- buzz::XmlElement* elem) {
- if (media->has_ssrcs()) {
- AddXmlAttr(elem, QN_SSRC, media->first_ssrc());
- }
-}
-
-void WriteJingleStreamsOrLegacySsrc(const MediaContentDescription* media,
- buzz::XmlElement* desc_elem) {
- if (!media->multistream()) {
- WriteLegacyJingleSsrc(media, desc_elem);
- } else {
- WriteJingleStreams(media->streams(), desc_elem);
- }
-}
-
-buzz::XmlElement* CreateJingleAudioContentElem(
- const AudioContentDescription* audio, bool crypto_required) {
- buzz::XmlElement* elem =
- new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true);
-
- elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_AUDIO);
- WriteJingleStreamsOrLegacySsrc(audio, elem);
-
- for (AudioCodecs::const_iterator codec = audio->codecs().begin();
- codec != audio->codecs().end(); ++codec) {
- elem->AddElement(CreateJingleAudioCodecElem(*codec));
- }
-
- const CryptoParamsVec& cryptos = audio->cryptos();
- if (!cryptos.empty()) {
- elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required));
- }
-
- if (audio->rtcp_mux()) {
- elem->AddElement(new buzz::XmlElement(QN_JINGLE_RTCP_MUX));
- }
-
- WriteJingleRtpHeaderExtensions(audio->rtp_header_extensions(), elem);
-
- return elem;
-}
-
-buzz::XmlElement* CreateJingleVideoContentElem(
- const VideoContentDescription* video, bool crypto_required) {
- buzz::XmlElement* elem =
- new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true);
-
- elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_VIDEO);
- WriteJingleStreamsOrLegacySsrc(video, elem);
-
- for (VideoCodecs::const_iterator codec = video->codecs().begin();
- codec != video->codecs().end(); ++codec) {
- elem->AddElement(CreateJingleVideoCodecElem(*codec));
- }
-
- const CryptoParamsVec& cryptos = video->cryptos();
- if (!cryptos.empty()) {
- elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required));
- }
-
- if (video->rtcp_mux()) {
- elem->AddElement(new buzz::XmlElement(QN_JINGLE_RTCP_MUX));
- }
-
- if (video->bandwidth() != kAutoBandwidth) {
- elem->AddElement(CreateBandwidthElem(QN_JINGLE_RTP_BANDWIDTH,
- video->bandwidth()));
- }
-
- WriteJingleRtpHeaderExtensions(video->rtp_header_extensions(), elem);
-
- return elem;
-}
-
-buzz::XmlElement* CreateJingleSctpDataContentElem(
- const DataContentDescription* data) {
- buzz::XmlElement* content_elem =
- new buzz::XmlElement(QN_JINGLE_DRAFT_SCTP_CONTENT, true);
- for (std::vector<StreamParams>::const_iterator
- stream = data->streams().begin();
- stream != data->streams().end(); ++stream) {
- buzz::XmlElement* stream_elem =
- new buzz::XmlElement(QN_JINGLE_DRAFT_SCTP_STREAM, false);
- AddXmlAttrIfNonEmpty(stream_elem, QN_NICK, stream->groupid);
- AddXmlAttrIfNonEmpty(stream_elem, QN_NAME, stream->id);
- if (!stream->ssrcs.empty()) {
- AddXmlAttr(stream_elem, QN_SID, stream->ssrcs[0]);
- }
- content_elem->AddElement(stream_elem);
- }
- return content_elem;;
-}
-
-buzz::XmlElement* CreateJingleRtpDataContentElem(
- const DataContentDescription* data, bool crypto_required) {
-
- buzz::XmlElement* elem =
- new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true);
-
- elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_DATA);
- WriteJingleStreamsOrLegacySsrc(data, elem);
-
- for (DataCodecs::const_iterator codec = data->codecs().begin();
- codec != data->codecs().end(); ++codec) {
- elem->AddElement(CreateJingleDataCodecElem(*codec));
- }
-
- const CryptoParamsVec& cryptos = data->cryptos();
- if (!cryptos.empty()) {
- elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required));
- }
-
- if (data->rtcp_mux()) {
- elem->AddElement(new buzz::XmlElement(QN_JINGLE_RTCP_MUX));
- }
-
- if (data->bandwidth() != kAutoBandwidth) {
- elem->AddElement(CreateBandwidthElem(QN_JINGLE_RTP_BANDWIDTH,
- data->bandwidth()));
- }
-
- return elem;
-}
-
-bool IsSctp(const DataContentDescription* data) {
- return (data->protocol() == kMediaProtocolSctp ||
- data->protocol() == kMediaProtocolDtlsSctp);
-}
-
-buzz::XmlElement* CreateJingleDataContentElem(
- const DataContentDescription* data, bool crypto_required) {
- if (IsSctp(data)) {
- return CreateJingleSctpDataContentElem(data);
- } else {
- return CreateJingleRtpDataContentElem(data, crypto_required);
- }
-}
-
-bool MediaSessionClient::IsWritable(SignalingProtocol protocol,
- const ContentDescription* content) {
- const MediaContentDescription* media =
- static_cast<const MediaContentDescription*>(content);
- if (protocol == PROTOCOL_GINGLE &&
- media->type() == MEDIA_TYPE_DATA) {
- return false;
- }
- return true;
-}
-
-bool MediaSessionClient::WriteContent(SignalingProtocol protocol,
- const ContentDescription* content,
- buzz::XmlElement** elem,
- WriteError* error) {
- const MediaContentDescription* media =
- static_cast<const MediaContentDescription*>(content);
- bool crypto_required = secure() == SEC_REQUIRED;
-
- if (media->type() == MEDIA_TYPE_AUDIO) {
- const AudioContentDescription* audio =
- static_cast<const AudioContentDescription*>(media);
- if (protocol == PROTOCOL_GINGLE) {
- *elem = CreateGingleAudioContentElem(audio, crypto_required);
- } else {
- *elem = CreateJingleAudioContentElem(audio, crypto_required);
- }
- } else if (media->type() == MEDIA_TYPE_VIDEO) {
- const VideoContentDescription* video =
- static_cast<const VideoContentDescription*>(media);
- if (protocol == PROTOCOL_GINGLE) {
- *elem = CreateGingleVideoContentElem(video, crypto_required);
- } else {
- *elem = CreateJingleVideoContentElem(video, crypto_required);
- }
- } else if (media->type() == MEDIA_TYPE_DATA) {
- const DataContentDescription* data =
- static_cast<const DataContentDescription*>(media);
- if (protocol == PROTOCOL_GINGLE) {
- return BadWrite("Data channel not supported with Gingle.", error);
- } else {
- *elem = CreateJingleDataContentElem(data, crypto_required);
- }
- } else {
- return BadWrite("Unknown content type: " +
- rtc::ToString<int>(media->type()), error);
- }
-
- return true;
-}
-
-} // namespace cricket
diff --git a/talk/session/media/mediasessionclient.h b/talk/session/media/mediasessionclient.h
deleted file mode 100644
index 4d29987a16..0000000000
--- a/talk/session/media/mediasessionclient.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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_MEDIASESSIONCLIENT_H_
-#define TALK_SESSION_MEDIA_MEDIASESSIONCLIENT_H_
-
-#include <algorithm>
-#include <map>
-#include <string>
-#include <vector>
-#include "talk/media/base/cryptoparams.h"
-#include "talk/session/media/call.h"
-#include "talk/session/media/channelmanager.h"
-#include "talk/session/media/mediasession.h"
-#include "webrtc/base/messagequeue.h"
-#include "webrtc/base/sigslot.h"
-#include "webrtc/base/sigslotrepeater.h"
-#include "webrtc/base/thread.h"
-#include "webrtc/libjingle/session/sessionmanager.h"
-#include "webrtc/p2p/base/session.h"
-#include "webrtc/p2p/base/sessionclient.h"
-#include "webrtc/p2p/base/sessiondescription.h"
-
-namespace cricket {
-
-class Call;
-
-class MediaSessionClient : public SessionClient, public sigslot::has_slots<> {
- public:
-#if !defined(DISABLE_MEDIA_ENGINE_FACTORY)
- MediaSessionClient(const buzz::Jid& jid, SessionManager *manager);
-#endif
- // Alternative constructor, allowing injection of media_engine
- // and device_manager.
- MediaSessionClient(const buzz::Jid& jid, SessionManager *manager,
- MediaEngineInterface* media_engine,
- DataEngineInterface* data_media_engine,
- DeviceManagerInterface* device_manager);
- ~MediaSessionClient();
-
- const buzz::Jid &jid() const { return jid_; }
- SessionManager* session_manager() const { return session_manager_; }
- ChannelManager* channel_manager() const { return channel_manager_; }
-
- // Return mapping of call ids to Calls.
- const std::map<uint32, Call *>& calls() const { return calls_; }
-
- // The settings below combine with the settings on SessionManager to choose
-
- // whether SDES-SRTP, DTLS-SRTP, or no security should be used. The possible
- // combinations are shown in the following table. Note that where either DTLS
- // or SDES is possible, DTLS is preferred. Thus to require either SDES or
- // DTLS, but not mandate DTLS, set SDES to require and DTLS to enable.
- //
- // | SDES:Disable | SDES:Enable | SDES:Require |
- // ----------------------------------------------------------------|
- // DTLS:Disable | No SRTP | SDES Optional | SDES Mandatory |
- // DTLS:Enable | DTLS Optional | DTLS/SDES Opt | DTLS/SDES Mand |
- // DTLS:Require | DTLS Mandatory | DTLS Mandatory | DTLS Mandatory |
-
- // Control use of SDES-SRTP.
- SecurePolicy secure() const { return desc_factory_.secure(); }
- void set_secure(SecurePolicy s) { desc_factory_.set_secure(s); }
-
- // Control use of multiple sessions in a call.
- void set_multisession_enabled(bool multisession_enabled) {
- multisession_enabled_ = multisession_enabled;
- }
-
- int GetCapabilities() { return channel_manager_->GetCapabilities(); }
-
- Call *CreateCall();
- void DestroyCall(Call *call);
-
- Call *GetFocus();
- void SetFocus(Call *call);
-
- void JoinCalls(Call *call_to_join, Call *call);
-
- bool GetAudioInputDevices(std::vector<std::string>* names) {
- return channel_manager_->GetAudioInputDevices(names);
- }
- bool GetAudioOutputDevices(std::vector<std::string>* names) {
- return channel_manager_->GetAudioOutputDevices(names);
- }
- bool GetVideoCaptureDevices(std::vector<std::string>* names) {
- return channel_manager_->GetVideoCaptureDevices(names);
- }
-
- bool SetAudioOptions(const std::string& in_name, const std::string& out_name,
- const AudioOptions& options) {
- return channel_manager_->SetAudioOptions(in_name, out_name, options);
- }
- bool SetOutputVolume(int level) {
- return channel_manager_->SetOutputVolume(level);
- }
- bool SetCaptureDevice(const std::string& cam_device) {
- return channel_manager_->SetCaptureDevice(cam_device);
- }
-
- SessionDescription* CreateOffer(const CallOptions& options) {
- return desc_factory_.CreateOffer(options, NULL);
- }
- SessionDescription* CreateAnswer(const SessionDescription* offer,
- const CallOptions& options) {
- return desc_factory_.CreateAnswer(offer, options, NULL);
- }
-
- sigslot::signal2<Call *, Call *> SignalFocus;
- sigslot::signal1<Call *> SignalCallCreate;
- sigslot::signal1<Call *> SignalCallDestroy;
- sigslot::repeater0<> SignalDevicesChange;
-
- virtual bool ParseContent(SignalingProtocol protocol,
- const buzz::XmlElement* elem,
- ContentDescription** content,
- ParseError* error);
- virtual bool IsWritable(SignalingProtocol protocol,
- const ContentDescription* content);
- virtual bool WriteContent(SignalingProtocol protocol,
- const ContentDescription* content,
- buzz::XmlElement** elem,
- WriteError* error);
-
- private:
- void Construct();
- void OnSessionCreate(Session *session, bool received_initiate);
- void OnSessionState(BaseSession *session, BaseSession::State state);
- void OnSessionDestroy(Session *session);
- Session *CreateSession(Call *call);
- Session *CreateSession(const std::string& id, Call* call);
- Call *FindCallByRemoteName(const std::string &remote_name);
-
- buzz::Jid jid_;
- SessionManager* session_manager_;
- Call *focus_call_;
- ChannelManager *channel_manager_;
- MediaSessionDescriptionFactory desc_factory_;
- bool multisession_enabled_;
- std::map<uint32, Call *> calls_;
-
- // Maintain a mapping of session id to call.
- typedef std::map<std::string, Call *> SessionMap;
- SessionMap session_map_;
-
- friend class Call;
-};
-
-} // namespace cricket
-
-#endif // TALK_SESSION_MEDIA_MEDIASESSIONCLIENT_H_
diff --git a/talk/session/media/mediasessionclient_unittest.cc b/talk/session/media/mediasessionclient_unittest.cc
deleted file mode 100644
index eb052ef86a..0000000000
--- a/talk/session/media/mediasessionclient_unittest.cc
+++ /dev/null
@@ -1,3324 +0,0 @@
-/*
- * 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.
- */
-
-#include <string>
-#include <vector>
-
-#include "talk/media/base/fakemediaengine.h"
-#include "talk/media/base/testutils.h"
-#include "talk/media/devices/fakedevicemanager.h"
-#include "webrtc/p2p/base/constants.h"
-#include "webrtc/p2p/client/basicportallocator.h"
-#include "talk/session/media/mediasessionclient.h"
-#include "webrtc/libjingle/xmllite/xmlbuilder.h"
-#include "webrtc/libjingle/xmllite/xmlelement.h"
-#include "webrtc/libjingle/xmllite/xmlprinter.h"
-#include "webrtc/libjingle/xmpp/constants.h"
-#include "webrtc/base/gunit.h"
-#include "webrtc/base/logging.h"
-#include "webrtc/base/scoped_ptr.h"
-#include "webrtc/base/ssladapter.h"
-
-using cricket::AudioCodec;
-using cricket::AudioContentDescription;
-using cricket::Codec;
-using cricket::DataCodec;
-using cricket::DataContentDescription;
-using cricket::FeedbackParam;
-using cricket::FeedbackParams;
-using cricket::VideoCodec;
-using cricket::VideoContentDescription;
-
-// The codecs that our FakeMediaEngine will support. Order is important, since
-// the tests check that our messages have codecs in the correct order.
-static const cricket::AudioCodec kAudioCodecs[] = {
- cricket::AudioCodec(103, "ISAC", 16000, -1, 1, 18),
- cricket::AudioCodec(104, "ISAC", 32000, -1, 1, 17),
- cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16),
- cricket::AudioCodec(99, "speex", 16000, 22000, 1, 15),
- cricket::AudioCodec(97, "IPCMWB", 16000, 80000, 1, 14),
- cricket::AudioCodec(9, "G722", 8000, 64000, 1, 13),
- cricket::AudioCodec(102, "iLBC", 8000, 13300, 1, 12),
- cricket::AudioCodec(98, "speex", 8000, 11000, 1, 11),
- cricket::AudioCodec(3, "GSM", 8000, 13000, 1, 10),
- cricket::AudioCodec(100, "EG711U", 8000, 64000, 1, 9),
- cricket::AudioCodec(101, "EG711A", 8000, 64000, 1, 8),
- cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 7),
- cricket::AudioCodec(8, "PCMA", 8000, 64000, 1, 6),
- cricket::AudioCodec(126, "CN", 32000, 0, 1, 5),
- cricket::AudioCodec(105, "CN", 16000, 0, 1, 4),
- cricket::AudioCodec(13, "CN", 8000, 0, 1, 3),
- cricket::AudioCodec(117, "red", 8000, 0, 1, 2),
- cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1)
-};
-
-// The codecs that our FakeMediaEngine will support with a different order of
-// supported codecs.
-static const cricket::AudioCodec kAudioCodecsDifferentPreference[] = {
- cricket::AudioCodec(104, "ISAC", 32000, -1, 1, 17),
- cricket::AudioCodec(97, "IPCMWB", 16000, 80000, 1, 14),
- cricket::AudioCodec(9, "G722", 8000, 64000, 1, 13),
- cricket::AudioCodec(119, "ISACLC", 16000, 40000, 1, 16),
- cricket::AudioCodec(103, "ISAC", 16000, -1, 1, 18),
- cricket::AudioCodec(99, "speex", 16000, 22000, 1, 15),
- cricket::AudioCodec(100, "EG711U", 8000, 64000, 1, 9),
- cricket::AudioCodec(101, "EG711A", 8000, 64000, 1, 8),
- cricket::AudioCodec(0, "PCMU", 8000, 64000, 1, 7),
- cricket::AudioCodec(8, "PCMA", 8000, 64000, 1, 6),
- cricket::AudioCodec(102, "iLBC", 8000, 13300, 1, 12),
- cricket::AudioCodec(3, "GSM", 8000, 13000, 1, 10),
- cricket::AudioCodec(98, "speex", 8000, 11000, 1, 11),
- cricket::AudioCodec(126, "CN", 32000, 0, 1, 5),
- cricket::AudioCodec(105, "CN", 16000, 0, 1, 4),
- cricket::AudioCodec(13, "CN", 8000, 0, 1, 3),
- cricket::AudioCodec(117, "red", 8000, 0, 1, 2),
- cricket::AudioCodec(106, "telephone-event", 8000, 0, 1, 1)
-};
-
-static const cricket::VideoCodec kVideoCodecs[] = {
- cricket::VideoCodec(96, "H264-SVC", 320, 200, 30, 1)
-};
-
-static const cricket::DataCodec kDataCodecs[] = {
- cricket::DataCodec(127, "google-data", 0)
-};
-
-const std::string kGingleCryptoOffer = \
- "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
- " <usage/> " \
- " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
- " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
- " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
- " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
- "</rtp:encryption> ";
-
-// Jingle offer does not have any <usage> element.
-const std::string kJingleCryptoOffer = \
- "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
- " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
- " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
- " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
- " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
- "</rtp:encryption> ";
-
-
-const std::string kGingleRequiredCryptoOffer = \
- "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\
- " <usage/> " \
- " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
- " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
- " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
- " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
- "</rtp:encryption> ";
-
-const std::string kJingleRequiredCryptoOffer = \
- "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'> "\
- " <rtp:crypto tag='145' crypto-suite='AES_CM_128_HMAC_SHA1_32'" \
- " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
- " <rtp:crypto tag='51' crypto-suite='AES_CM_128_HMAC_SHA1_80'" \
- " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
- "</rtp:encryption> ";
-
-
-const std::string kGingleUnsupportedCryptoOffer = \
- "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
- " <usage/> " \
- " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
- " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
- " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
- " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
- "</rtp:encryption> ";
-
-const std::string kJingleUnsupportedCryptoOffer = \
- "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1'> " \
- " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
- " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
- " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
- " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
- "</rtp:encryption> ";
-
-
-// With unsupported but with required="true"
-const std::string kGingleRequiredUnsupportedCryptoOffer = \
- "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \
- " <usage/> " \
- " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1'" \
- " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/>" \
- " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2'" \
- " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
- "</rtp:encryption> ";
-
-const std::string kJingleRequiredUnsupportedCryptoOffer = \
- "<rtp:encryption xmlns:rtp='urn:xmpp:jingle:apps:rtp:1' required='true'>" \
- " <rtp:crypto tag='145' crypto-suite='NOT_SUPPORTED_1' " \
- " key-params='inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9'/> " \
- " <rtp:crypto tag='51' crypto-suite='NOT_SUPPORTED_2' " \
- " key-params='inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy'/>" \
- "</rtp:encryption> ";
-
-const std::string kGingleInitiate(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='103' name='ISAC' clockrate='16000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='104' name='ISAC' clockrate='32000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='119' name='ISACLC' clockrate='16000' bitrate='40000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='99' name='speex' clockrate='16000' bitrate='22000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='97' name='IPCMWB' clockrate='16000' bitrate='80000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='9' name='G722' clockrate='8000' bitrate='64000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='102' name='iLBC' clockrate='8000' bitrate='13300' />" \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='98' name='speex' clockrate='8000' bitrate='11000' />" \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='3' name='GSM' clockrate='8000' bitrate='13000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='100' name='EG711U' clockrate='8000' bitrate='64000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='101' name='EG711A' clockrate='8000' bitrate='64000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='0' name='PCMU' clockrate='8000' bitrate='64000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='8' name='PCMA' clockrate='8000' bitrate='64000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='126' name='CN' clockrate='32000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='105' name='CN' clockrate='16000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='13' name='CN' clockrate='8000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='117' name='red' clockrate='8000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='106' name='telephone-event' clockrate='8000' /> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiate(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
- " <payload-type " \
- " id='119' name='ISACLC' clockrate='16000'> " \
- " <parameter name='bitrate' value='40000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='99' name='speex' clockrate='16000'> " \
- " <parameter name='bitrate' value='22000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='97' name='IPCMWB' clockrate='16000'> " \
- " <parameter name='bitrate' value='80000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='9' name='G722' clockrate='8000'> " \
- " <parameter name='bitrate' value='64000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='102' name='iLBC' clockrate='8000'> " \
- " <parameter name='bitrate' value='13300'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='98' name='speex' clockrate='8000'> " \
- " <parameter name='bitrate' value='11000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='3' name='GSM' clockrate='8000'> " \
- " <parameter name='bitrate' value='13000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='100' name='EG711U' clockrate='8000'> " \
- " <parameter name='bitrate' value='64000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='101' name='EG711A' clockrate='8000'> " \
- " <parameter name='bitrate' value='64000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='0' name='PCMU' clockrate='8000'> " \
- " <parameter name='bitrate' value='64000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='8' name='PCMA' clockrate='8000'> " \
- " <parameter name='bitrate' value='64000'/> " \
- " </payload-type> " \
- " <payload-type " \
- " id='126' name='CN' clockrate='32000' /> " \
- " <payload-type " \
- " id='105' name='CN' clockrate='16000' /> " \
- " <payload-type " \
- " id='13' name='CN' clockrate='8000' /> " \
- " <payload-type " \
- " id='117' name='red' clockrate='8000' /> " \
- " <payload-type " \
- " id='106' name='telephone-event' clockrate='8000' /> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kJingleInitiateWithRtcpFb(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'> " \
- " <rtcp-fb type='nack'/> " \
- " </payload-type> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
- " <rtcp-fb type='nack'/> " \
- " <payload-type id='99' name='H264-SVC'> " \
- " <rtcp-fb type='ccm' subtype='fir'/> " \
- " <parameter name='height' value='200'/> " \
- " <parameter name='width' value='320'/> " \
- " <parameter name='framerate' value='30'/> " \
- " </payload-type> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test data'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \
- " <rtcp-fb type='nack'/> " \
- " <payload-type id='127' name='google-data'> " \
- " </payload-type> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kGingleVideoInitiate(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/video'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='103' name='ISAC' clockrate='16000' /> " \
- " <payload-type xmlns='http://www.google.com/session/video' " \
- " id='99' name='H264-SVC' framerate='30' " \
- " height='200' width='320'/> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleVideoInitiate(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
- " <payload-type id='99' name='H264-SVC'> " \
- " <parameter name='height' value='200'/> " \
- " <parameter name='width' value='320'/> " \
- " <parameter name='framerate' value='30'/> " \
- " </payload-type> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kJingleVideoInitiateWithRtpData(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
- " <payload-type id='99' name='H264-SVC'> " \
- " <parameter name='height' value='200'/> " \
- " <parameter name='width' value='320'/> " \
- " <parameter name='framerate' value='30'/> " \
- " </payload-type> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test data'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='data'> " \
- " <payload-type id='127' name='google-data'/> " \
- " <rtcp-mux/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kJingleVideoInitiateWithSctpData(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
- " <payload-type id='99' name='H264-SVC'> " \
- " <parameter name='height' value='200'/> " \
- " <parameter name='width' value='320'/> " \
- " <parameter name='framerate' value='30'/> " \
- " </payload-type> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test data'> " \
- " <description xmlns='google:jingle:sctp' media='data'> " \
- " <stream sid='1'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kJingleVideoInitiateWithBandwidth(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
- " <payload-type id='99' name='H264-SVC'> " \
- " <parameter name='height' value='200'/> " \
- " <parameter name='width' value='320'/> " \
- " <parameter name='framerate' value='30'/> " \
- " </payload-type> " \
- " <bandwidth type='AS'>42</bandwidth> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kJingleVideoInitiateWithRtcpMux(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " <content name='test video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='video'> " \
- " <payload-type id='99' name='H264-SVC'> " \
- " <parameter name='height' value='200'/> " \
- " <parameter name='width' value='320'/> " \
- " <parameter name='framerate' value='30'/> " \
- " </payload-type> " \
- " <rtcp-mux/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-// Initiate string with a combination of supported and unsupported codecs
-// Should accept the supported ones
-const std::string kGingleInitiateSomeUnsupported(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='103' name='ISAC' clockrate='16000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='97' name='ASDFDS' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='102' name='1010' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='107' name='DFAS' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='100' name='EG711U' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='101' name='EG711A' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='0' name='PCMU' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='110' name=':)' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='13' name='CN' /> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateSomeUnsupported(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'> " \
- " <payload-type " \
- " id='103' name='ISAC' clockrate='16000' /> " \
- " <payload-type " \
- " id='97' name='ASDFDS' /> " \
- " <payload-type " \
- " id='102' name='1010' /> " \
- " <payload-type " \
- " id='107' name='DFAS' /> " \
- " <payload-type " \
- " id='100' name='EG711U' /> " \
- " <payload-type " \
- " id='101' name='EG711A' /> " \
- " <payload-type " \
- " id='0' name='PCMU' /> " \
- " <payload-type " \
- " id='110' name=':)' /> " \
- " <payload-type " \
- " id='13' name='CN' /> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kGingleVideoInitiateWithBandwidth(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/video'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='103' name='ISAC' clockrate='16000' /> " \
- " <payload-type xmlns='http://www.google.com/session/video' " \
- " id='99' name='H264-SVC' framerate='30' " \
- " height='200' width='320'/> " \
- " <bandwidth type='AS'>42</bandwidth> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-// Initiate string without any supported codecs. Should send a reject.
-const std::string kGingleInitiateNoSupportedAudioCodecs(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='123' name='Supercodec6000' /> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateNoSupportedAudioCodecs(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
- " <payload-type " \
- " id='123' name='Supercodec6000' /> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-// Initiate string without any codecs. Assumes ancient version of Cricket
-// and tries a session with ISAC and PCMU
-const std::string kGingleInitiateNoAudioCodecs(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateNoAudioCodecs(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-// The codecs are supported, but not at the given clockrates. Should send
-// a reject.
-const std::string kGingleInitiateWrongClockrates(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='103' name='ISAC' clockrate='8000'/> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='97' name='IPCMWB' clockrate='1337'/> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='102' name='iLBC' clockrate='1982' /> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateWrongClockrates(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
- " <payload-type " \
- " id='103' name='ISAC' clockrate='8000'/> " \
- " <payload-type " \
- " id='97' name='IPCMWB' clockrate='1337'/> " \
- " <payload-type " \
- " id='102' name='iLBC' clockrate='1982' /> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-// The codecs are supported, but not with the given number of channels.
-// Should send a reject.
-const std::string kGingleInitiateWrongChannels(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='103' name='ISAC' channels='2'/> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='97' name='IPCMWB' channels='3'/> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateWrongChannels(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
- " <payload-type " \
- " id='103' name='ISAC' channels='2'/> " \
- " <payload-type " \
- " id='97' name='IPCMWB' channels='3'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-// Initiate with a dynamic codec not using webrtc default payload id. Should
-// accept with provided payload id.
-const std::string kGingleInitiateDynamicAudioCodecs(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='123' name='speex' clockrate='16000'/> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateDynamicAudioCodecs(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
- " <payload-type " \
- " id='123' name='speex' clockrate='16000'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-// Initiate string with nothing but static codec id's. Should accept.
-const std::string kGingleInitiateStaticAudioCodecs(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='3' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='0' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='8' /> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateStaticAudioCodecs(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
- " <payload-type id='3' /> " \
- " <payload-type id='0' /> " \
- " <payload-type id='8' /> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-// Initiate with payload type-less codecs. Should reject.
-const std::string kGingleInitiateNoPayloadTypes(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " name='ISAC' clockrate='16000'/> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateNoPayloadTypes(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
- " <payload-type name='ISAC' clockrate='16000'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-// Initiate with unnamed dynamic codces. Should reject.
-const std::string kGingleInitiateDynamicWithoutNames(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <session xmlns='http://www.google.com/session' type='initiate'" \
- " id='abcdef' initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/phone'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='100' clockrate='16000'/> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleInitiateDynamicWithoutNames(
- "<iq xmlns='jabber:client' from='me@domain.com/resource' " \
- " to='user@domain.com/resource' type='set' id='123'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-initiate'> " \
- " sid='abcdef' initiator='me@domain.com/resource'> " \
- " <content name='test audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>" \
- " <payload-type id='100' clockrate='16000'/> " \
- " </description> " \
- " <transport xmlns=\"http://www.google.com/transport/p2p\"/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const uint32 kAudioSsrc = 4294967295U;
-const uint32 kVideoSsrc = 87654321;
-const uint32 kDataSsrc = 1010101;
-// Note that this message does not specify a session ID. It must be populated
-// before use.
-const std::string kGingleAcceptWithSsrcs(
- "<iq xmlns='jabber:client' from='me@mydomain.com' " \
- " to='user@domain.com/resource' type='set' id='150'> " \
- " <session xmlns='http://www.google.com/session' type='accept' " \
- " initiator='me@domain.com/resource'> " \
- " <description xmlns='http://www.google.com/session/video'> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='103' name='ISAC' clockrate='16000' /> " \
- " <payload-type xmlns='http://www.google.com/session/phone' " \
- " id='104' name='ISAC' clockrate='32000' /> " \
- " <src-id xmlns='http://www.google.com/session/phone'> " \
- " 4294967295</src-id> " \
- " <src-id>87654321</src-id> " \
- " </description> " \
- " </session> " \
- "</iq> ");
-
-const std::string kJingleAcceptWithSsrcs(
- "<iq xmlns='jabber:client' from='me@mydomain.com' " \
- " to='user@domain.com/resource' type='set' id='150'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
- " initiator='me@domain.com/resource'> " \
- " <content name='audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
- " media='audio' ssrc='4294967295'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
- " </description> " \
- " <transport xmlns='http://www.google.com/transport/p2p'/> " \
- " </content> " \
- " <content name='video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
- " media='video' ssrc='87654321'> " \
- " </description> " \
- " <transport xmlns='http://www.google.com/transport/p2p'/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kJingleAcceptWithRtpDataSsrcs(
- "<iq xmlns='jabber:client' from='me@mydomain.com' " \
- " to='user@domain.com/resource' type='set' id='150'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
- " initiator='me@domain.com/resource'> " \
- " <content name='audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
- " media='audio' ssrc='4294967295'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
- " </description> " \
- " <transport xmlns='http://www.google.com/transport/p2p'/> " \
- " </content> " \
- " <content name='video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
- " media='video' ssrc='87654321'> " \
- " </description> " \
- " <transport xmlns='http://www.google.com/transport/p2p'/> " \
- " </content> " \
- " <content name='data'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
- " media='data' ssrc='1010101'> " \
- " </description> " \
- " <transport xmlns='http://www.google.com/transport/p2p'/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-const std::string kJingleAcceptWithSctpData(
- "<iq xmlns='jabber:client' from='me@mydomain.com' " \
- " to='user@domain.com/resource' type='set' id='150'> " \
- " <jingle xmlns='urn:xmpp:jingle:1' action='session-accept' " \
- " initiator='me@domain.com/resource'> " \
- " <content name='audio'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
- " media='audio' ssrc='4294967295'> " \
- " <payload-type id='103' name='ISAC' clockrate='16000'/> " \
- " <payload-type id='104' name='ISAC' clockrate='32000'/> " \
- " </description> " \
- " <transport xmlns='http://www.google.com/transport/p2p'/> " \
- " </content> " \
- " <content name='video'> " \
- " <description xmlns='urn:xmpp:jingle:apps:rtp:1' " \
- " media='video' ssrc='87654321'> " \
- " </description> " \
- " <transport xmlns='http://www.google.com/transport/p2p'/> " \
- " </content> " \
- " <content name='data'> " \
- " <description xmlns='google:jingle:sctp'> " \
- " <stream sid='1'/> " \
- " </description> " \
- " <transport xmlns='http://www.google.com/transport/p2p'/> " \
- " </content> " \
- " </jingle> " \
- "</iq> ");
-
-std::string JingleView(const std::string& ssrc,
- const std::string& width,
- const std::string& height,
- const std::string& framerate) {
- // We have some slightly weird whitespace formatting to make the
- // actual XML generated match the expected XML here.
- return \
- "<cli:iq"
- " to='me@mydomain.com'"
- " type='set'"
- " xmlns:cli='jabber:client'>"
- "<jingle"
- " xmlns='urn:xmpp:jingle:1'"
- " action='session-info'"
- " sid=''>"
- "<view xmlns='google:jingle'"
- " name='video'"
- " type='static'"
- " ssrc='" + ssrc + "'>"
- "<params"
- " width='" + width + "'"
- " height='" + height + "'"
- " framerate='" + framerate + "'"
- " preference='0'/>"
- "</view>"
- "</jingle>"
- "</cli:iq>";
-}
-
-std::string JingleStreamAdd(const std::string& content_name,
- const std::string& nick,
- const std::string& name,
- const std::string& ssrc) {
- return \
- "<iq"
- " xmlns='jabber:client'"
- " from='me@mydomain.com'"
- " to='user@domain.com/resource'"
- " type='set'"
- " id='150'>"
- " <jingle"
- " xmlns='urn:xmpp:jingle:1'"
- " action='description-info'>"
- " <content"
- " xmlns='urn:xmpp:jingle:1'"
- " name='" + content_name + "'>"
- " <description"
- " xmlns='urn:xmpp:jingle:apps:rtp:1'"
- " media='" + content_name + "'>"
- " <streams"
- " xmlns='google:jingle'>"
- " <stream"
- " nick='" + nick + "'"
- " name='" + name + "'>"
- " <ssrc>" + ssrc + "</ssrc>"
- " </stream>"
- " </streams>"
- " </description>"
- " </content>"
- " </jingle>"
- "</iq>";
-}
-
-std::string JingleOutboundStreamRemove(const std::string& sid,
- const std::string& content_name,
- const std::string& name) {
- return \
- "<cli:iq"
- " to='me@mydomain.com'"
- " type='set'"
- " xmlns:cli='jabber:client'>"
- "<jingle"
- " xmlns='urn:xmpp:jingle:1'"
- " action='description-info'"
- " sid='" + sid + "'>"
- "<content"
- " name='" + content_name + "'"
- " creator='initiator'>"
- "<description"
- " xmlns='urn:xmpp:jingle:apps:rtp:1'"
- " media='" + content_name + "'>"
- "<streams"
- " xmlns='google:jingle'>"
- "<stream"
- " name='" + name + "'>"
- "</stream>"
- "</streams>"
- "</description>"
- "</content>"
- "</jingle>"
- "</cli:iq>";
-}
-
-std::string JingleOutboundStreamAdd(const std::string& sid,
- const std::string& content_name,
- const std::string& name,
- const std::string& ssrc) {
- return \
- "<cli:iq"
- " to='me@mydomain.com'"
- " type='set'"
- " xmlns:cli='jabber:client'>"
- "<jingle"
- " xmlns='urn:xmpp:jingle:1'"
- " action='description-info'"
- " sid='" + sid + "'>"
- "<content"
- " name='" + content_name + "'"
- " creator='initiator'>"
- "<description"
- " xmlns='urn:xmpp:jingle:apps:rtp:1'"
- " media='" + content_name + "'>"
- "<streams"
- " xmlns='google:jingle'>"
- "<stream"
- " name='" + name + "'>"
- "<ssrc>" + ssrc + "</ssrc>"
- "</stream>"
- "</streams>"
- "</description>"
- "</content>"
- "</jingle>"
- "</cli:iq>";
-}
-
-std::string JingleStreamAddWithoutSsrc(const std::string& content_name,
- const std::string& nick,
- const std::string& name) {
- return \
- "<iq"
- " xmlns='jabber:client'"
- " from='me@mydomain.com'"
- " to='user@domain.com/resource'"
- " type='set'"
- " id='150'>"
- " <jingle"
- " xmlns='urn:xmpp:jingle:1'"
- " action='description-info'>"
- " <content"
- " xmlns='urn:xmpp:jingle:1'"
- " name='" + content_name + "'>"
- " <description"
- " xmlns='urn:xmpp:jingle:apps:rtp:1'"
- " media='" + content_name + "'>"
- " <streams"
- " xmlns='google:jingle'>"
- " <stream"
- " nick='" + nick + "'"
- " name='" + name + "'>"
- " </stream>"
- " </streams>"
- " </description>"
- " </content>"
- " </jingle>"
- "</iq>";
-}
-
-std::string JingleStreamRemove(const std::string& content_name,
- const std::string& nick,
- const std::string& name) {
- return \
- "<iq"
- " xmlns='jabber:client'"
- " from='me@mydomain.com'"
- " to='user@domain.com/resource'"
- " type='set'"
- " id='150'>"
- " <jingle"
- " xmlns='urn:xmpp:jingle:1'"
- " action='description-info'>"
- " <content"
- " xmlns='urn:xmpp:jingle:1'"
- " name='" + content_name + "'>"
- " <description"
- " xmlns='urn:xmpp:jingle:apps:rtp:1'"
- " media='" + content_name + "'>"
- " <streams"
- " xmlns='google:jingle'>"
- " <stream"
- " nick='" + nick + "'"
- " name='" + name + "'/>"
- " </streams>"
- " </description>"
- " </content>"
- " </jingle>"
- "</iq>";
-}
-
-// Convenience function to get CallOptions that have audio enabled,
-// but not video or data.
-static cricket::CallOptions AudioCallOptions() {
- cricket::CallOptions options;
- options.recv_audio = true;
- options.recv_video = false;
- options.data_channel_type = cricket::DCT_NONE;
- return options;
-}
-
-// Convenience function to get CallOptions that have audio and video
-// enabled, but not data.
-static cricket::CallOptions VideoCallOptions() {
- cricket::CallOptions options;
- options.recv_audio = true;
- options.recv_video = true;
- options.data_channel_type = cricket::DCT_NONE;
- return options;
-}
-
-static buzz::XmlElement* CopyElement(const buzz::XmlElement* elem) {
- return new buzz::XmlElement(*elem);
-}
-
-static std::string AddEncryption(std::string stanza, std::string encryption) {
- std::string::size_type pos = stanza.find("</description>");
- while (pos != std::string::npos) {
- stanza = stanza.insert(pos, encryption);
- pos = stanza.find("</description>", pos + encryption.length() + 1);
- }
- return stanza;
-}
-
-static int IntFromJingleCodecParameter(const buzz::XmlElement* parameter,
- const std::string& expected_name) {
- if (parameter) {
- const std::string& actual_name =
- parameter->Attr(cricket::QN_PAYLOADTYPE_PARAMETER_NAME);
-
- EXPECT_EQ(expected_name, actual_name)
- << "wrong parameter name. Expected '"
- << expected_name << "'. Actually '"
- << actual_name << "'.";
-
- return atoi(parameter->Attr(
- cricket::QN_PAYLOADTYPE_PARAMETER_VALUE).c_str());
- }
- return 0;
-}
-
-template <class CodecClass, class DescriptionClass>
-static void VerifyCodecFbParams(const FeedbackParams& expected,
- const DescriptionClass* desc) {
- if (!expected.params().empty()) {
- ASSERT_TRUE(desc != NULL);
- const std::vector<CodecClass> codecs = desc->codecs();
- for (size_t i = 0; i < codecs.size(); ++i) {
- EXPECT_EQ(expected, codecs[i].feedback_params);
- }
- }
-}
-
-// Parses and extracts payload and codec info from test XML. Since
-// that XML will be in various contents (Gingle and Jingle), we need an
-// abstract parser with one concrete implementation per XML content.
-class MediaSessionTestParser {
- public:
- virtual buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) = 0;
- virtual buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) = 0;
- virtual buzz::XmlElement* NextContent(buzz::XmlElement* content) = 0;
- virtual buzz::XmlElement* PayloadTypeFromContent(
- buzz::XmlElement* content) = 0;
- virtual buzz::XmlElement* NextFromPayloadType(
- buzz::XmlElement* payload_type) = 0;
- virtual cricket::AudioCodec AudioCodecFromPayloadType(
- const buzz::XmlElement* payload_type) = 0;
- virtual cricket::VideoCodec VideoCodecFromPayloadType(
- const buzz::XmlElement* payload_type) = 0;
- virtual cricket::DataCodec DataCodecFromPayloadType(
- const buzz::XmlElement* payload_type) = 0;
- virtual buzz::XmlElement* EncryptionFromContent(
- buzz::XmlElement* content) = 0;
- virtual buzz::XmlElement* NextFromEncryption(
- buzz::XmlElement* encryption) = 0;
- virtual const buzz::XmlElement* BandwidthFromContent(
- buzz::XmlElement* content) = 0;
- virtual const buzz::XmlElement* RtcpMuxFromContent(
- buzz::XmlElement* content) = 0;
- virtual bool ActionIsTerminate(const buzz::XmlElement* action) = 0;
- virtual ~MediaSessionTestParser() {}
-};
-
-class JingleSessionTestParser : public MediaSessionTestParser {
- public:
- JingleSessionTestParser() {}
-
- ~JingleSessionTestParser() {
- }
-
- buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
- return stanza->FirstNamed(cricket::QN_JINGLE);
- }
-
- buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
- // We need to be able to use multiple contents, but the action
- // gets deleted before we can call NextContent, so we need to
- // stash away a copy.
- action_.reset(CopyElement(action));
- return action_->FirstNamed(cricket::QN_JINGLE_CONTENT);
- }
-
- buzz::XmlElement* NextContent(buzz::XmlElement* content) {
- // For some reason, content->NextNamed(cricket::QN_JINGLE_CONTENT)
- // doesn't work.
- return action_->FirstNamed(cricket::QN_JINGLE_CONTENT)
- ->NextNamed(cricket::QN_JINGLE_CONTENT);
- }
-
- buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
- buzz::XmlElement* content_desc =
- content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
- if (!content_desc)
- return NULL;
-
- return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
- }
-
- buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
- return payload_type->NextNamed(cricket::QN_JINGLE_RTP_PAYLOADTYPE);
- }
-
- void ParsePayloadTypeFeedbackParameters(const buzz::XmlElement* element,
- FeedbackParams* params) {
- const buzz::XmlElement* param =
- element->FirstNamed(cricket::QN_JINGLE_RTCP_FB);
- for (; param != NULL;
- param = param->NextNamed(cricket::QN_JINGLE_RTCP_FB)) {
- std::string type = param->Attr(cricket::QN_TYPE);
- std::string subtype = param->Attr(cricket::QN_SUBTYPE);
- if (!type.empty()) {
- params->Add(FeedbackParam(type, subtype));
- }
- }
- }
-
- cricket::AudioCodec AudioCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- int id = 0;
- if (payload_type->HasAttr(cricket::QN_ID))
- id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
-
- std::string name;
- if (payload_type->HasAttr(cricket::QN_NAME))
- name = payload_type->Attr(cricket::QN_NAME);
-
- int clockrate = 0;
- if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
- clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
-
- int bitrate = IntFromJingleCodecParameter(
- payload_type->FirstNamed(cricket::QN_PARAMETER), "bitrate");
-
- int channels = 1;
- if (payload_type->HasAttr(cricket::QN_CHANNELS))
- channels = atoi(payload_type->Attr(
- cricket::QN_CHANNELS).c_str());
-
- AudioCodec codec = AudioCodec(id, name, clockrate, bitrate, channels, 0);
- ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
- return codec;
- }
-
- cricket::VideoCodec VideoCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- int id = 0;
- if (payload_type->HasAttr(cricket::QN_ID))
- id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
-
- std::string name;
- if (payload_type->HasAttr(cricket::QN_NAME))
- name = payload_type->Attr(cricket::QN_NAME);
-
- int width = 0;
- int height = 0;
- int framerate = 0;
- const buzz::XmlElement* param =
- payload_type->FirstNamed(cricket::QN_PARAMETER);
- if (param) {
- width = IntFromJingleCodecParameter(param, "width");
- param = param->NextNamed(cricket::QN_PARAMETER);
- if (param) {
- height = IntFromJingleCodecParameter(param, "height");
- param = param->NextNamed(cricket::QN_PARAMETER);
- if (param) {
- framerate = IntFromJingleCodecParameter(param, "framerate");
- }
- }
- }
- VideoCodec codec = VideoCodec(id, name, width, height, framerate, 0);
- ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
- return codec;
- }
-
- cricket::DataCodec DataCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- int id = 0;
- if (payload_type->HasAttr(cricket::QN_ID))
- id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
-
- std::string name;
- if (payload_type->HasAttr(cricket::QN_NAME))
- name = payload_type->Attr(cricket::QN_NAME);
-
- DataCodec codec = DataCodec(id, name, 0);
- ParsePayloadTypeFeedbackParameters(payload_type, &codec.feedback_params);
- return codec;
- }
-
- bool ActionIsTerminate(const buzz::XmlElement* action) {
- return (action->HasAttr(cricket::QN_ACTION) &&
- action->Attr(cricket::QN_ACTION) == "session-terminate");
- }
-
- buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
- buzz::XmlElement* content_desc =
- content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
- if (!content_desc)
- return NULL;
-
- return content_desc->FirstNamed(cricket::QN_ENCRYPTION);
- }
-
- buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
- return encryption->NextNamed(cricket::QN_ENCRYPTION);
- }
-
- const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
- buzz::XmlElement* content_desc =
- content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
- if (!content_desc)
- return NULL;
-
- return content_desc->FirstNamed(cricket::QN_JINGLE_RTP_BANDWIDTH);
- }
-
- const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
- return content->FirstNamed(cricket::QN_JINGLE_RTCP_MUX);
- }
-
- private:
- rtc::scoped_ptr<buzz::XmlElement> action_;
-};
-
-class GingleSessionTestParser : public MediaSessionTestParser {
- public:
- GingleSessionTestParser() : found_content_count_(0) {}
-
- buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
- return stanza->FirstNamed(cricket::QN_GINGLE_SESSION);
- }
-
- buzz::XmlElement* ContentFromAction(buzz::XmlElement* session) {
- buzz::XmlElement* content =
- session->FirstNamed(cricket::QN_GINGLE_AUDIO_CONTENT);
- if (content == NULL)
- content = session->FirstNamed(cricket::QN_GINGLE_VIDEO_CONTENT);
- return content;
- }
-
- // Assumes contents are in order of audio, and then video.
- buzz::XmlElement* NextContent(buzz::XmlElement* content) {
- found_content_count_++;
- return content;
- }
-
- buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* content) {
- if (found_content_count_ > 0) {
- return content->FirstNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
- } else {
- return content->FirstNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
- }
- }
-
- buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
- if (found_content_count_ > 0) {
- return payload_type->NextNamed(cricket::QN_GINGLE_VIDEO_PAYLOADTYPE);
- } else {
- return payload_type->NextNamed(cricket::QN_GINGLE_AUDIO_PAYLOADTYPE);
- }
- }
-
- cricket::AudioCodec AudioCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- int id = 0;
- if (payload_type->HasAttr(cricket::QN_ID))
- id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
-
- std::string name;
- if (payload_type->HasAttr(cricket::QN_NAME))
- name = payload_type->Attr(cricket::QN_NAME);
-
- int clockrate = 0;
- if (payload_type->HasAttr(cricket::QN_CLOCKRATE))
- clockrate = atoi(payload_type->Attr(cricket::QN_CLOCKRATE).c_str());
-
- int bitrate = 0;
- if (payload_type->HasAttr(cricket::QN_BITRATE))
- bitrate = atoi(payload_type->Attr(cricket::QN_BITRATE).c_str());
-
- int channels = 1;
- if (payload_type->HasAttr(cricket::QN_CHANNELS))
- channels = atoi(payload_type->Attr(cricket::QN_CHANNELS).c_str());
-
- return cricket::AudioCodec(id, name, clockrate, bitrate, channels, 0);
- }
-
- cricket::VideoCodec VideoCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- int id = 0;
- if (payload_type->HasAttr(cricket::QN_ID))
- id = atoi(payload_type->Attr(cricket::QN_ID).c_str());
-
- std::string name;
- if (payload_type->HasAttr(cricket::QN_NAME))
- name = payload_type->Attr(cricket::QN_NAME);
-
- int width = 0;
- if (payload_type->HasAttr(cricket::QN_WIDTH))
- width = atoi(payload_type->Attr(cricket::QN_WIDTH).c_str());
-
- int height = 0;
- if (payload_type->HasAttr(cricket::QN_HEIGHT))
- height = atoi(payload_type->Attr(cricket::QN_HEIGHT).c_str());
-
- int framerate = 1;
- if (payload_type->HasAttr(cricket::QN_FRAMERATE))
- framerate = atoi(payload_type->Attr(cricket::QN_FRAMERATE).c_str());
-
- return cricket::VideoCodec(id, name, width, height, framerate, 0);
- }
-
- cricket::DataCodec DataCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- // Gingle can't do data codecs.
- return cricket::DataCodec(0, "", 0);
- }
-
- buzz::XmlElement* EncryptionFromContent(
- buzz::XmlElement* content) {
- return content->FirstNamed(cricket::QN_ENCRYPTION);
- }
-
- buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
- return encryption->NextNamed(cricket::QN_ENCRYPTION);
- }
-
- const buzz::XmlElement* BandwidthFromContent(buzz::XmlElement* content) {
- return content->FirstNamed(cricket::QN_GINGLE_VIDEO_BANDWIDTH);
- }
-
- const buzz::XmlElement* RtcpMuxFromContent(buzz::XmlElement* content) {
- return NULL;
- }
-
- bool ActionIsTerminate(const buzz::XmlElement* session) {
- return (session->HasAttr(buzz::QN_TYPE) &&
- session->Attr(buzz::QN_TYPE) == "terminate");
- }
-
- int found_content_count_;
-};
-
-class MediaSessionClientTest : public sigslot::has_slots<> {
- public:
- explicit MediaSessionClientTest(MediaSessionTestParser* parser,
- cricket::SignalingProtocol initial_protocol) {
- nm_ = new rtc::BasicNetworkManager();
- pa_ = new cricket::BasicPortAllocator(nm_);
- sm_ = new cricket::SessionManager(pa_, NULL);
- fme_ = new cricket::FakeMediaEngine();
- fdme_ = new cricket::FakeDataEngine();
-
- FeedbackParams params_nack_fir;
- params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
- cricket::kRtcpFbCcmParamFir));
- params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
- FeedbackParams params_nack;
- params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
-
- std::vector<cricket::AudioCodec>
- audio_codecs(kAudioCodecs, kAudioCodecs + ARRAY_SIZE(kAudioCodecs));
- SetCodecFeedbackParams(&audio_codecs, params_nack);
- fme_->SetAudioCodecs(audio_codecs);
- std::vector<cricket::VideoCodec>
- video_codecs(kVideoCodecs, kVideoCodecs + ARRAY_SIZE(kVideoCodecs));
- SetCodecFeedbackParams(&video_codecs, params_nack_fir);
- fme_->SetVideoCodecs(video_codecs);
- std::vector<cricket::DataCodec>
- data_codecs(kDataCodecs, kDataCodecs + ARRAY_SIZE(kDataCodecs));
- SetCodecFeedbackParams(&data_codecs, params_nack);
- fdme_->SetDataCodecs(data_codecs);
-
- client_ = new cricket::MediaSessionClient(
- buzz::Jid("user@domain.com/resource"), sm_,
- fme_, fdme_, new cricket::FakeDeviceManager());
- client_->session_manager()->SignalOutgoingMessage.connect(
- this, &MediaSessionClientTest::OnSendStanza);
- client_->session_manager()->SignalSessionCreate.connect(
- this, &MediaSessionClientTest::OnSessionCreate);
- client_->SignalCallCreate.connect(
- this, &MediaSessionClientTest::OnCallCreate);
- client_->SignalCallDestroy.connect(
- this, &MediaSessionClientTest::OnCallDestroy);
-
- call_ = NULL;
- parser_ = parser;
- initial_protocol_ = initial_protocol;
- expect_incoming_crypto_ = false;
- expect_outgoing_crypto_ = false;
- expected_video_bandwidth_ = cricket::kAutoBandwidth;
- expected_video_rtcp_mux_ = false;
- }
-
- ~MediaSessionClientTest() {
- delete client_;
- delete sm_;
- delete pa_;
- delete nm_;
- delete parser_;
- ClearStanzas();
- }
-
- buzz::XmlElement* ActionFromStanza(buzz::XmlElement* stanza) {
- return parser_->ActionFromStanza(stanza);
- }
-
- buzz::XmlElement* ContentFromAction(buzz::XmlElement* action) {
- return parser_->ContentFromAction(action);
- }
-
- buzz::XmlElement* PayloadTypeFromContent(buzz::XmlElement* payload) {
- return parser_->PayloadTypeFromContent(payload);
- }
-
- buzz::XmlElement* NextFromPayloadType(buzz::XmlElement* payload_type) {
- return parser_->NextFromPayloadType(payload_type);
- }
-
- buzz::XmlElement* EncryptionFromContent(buzz::XmlElement* content) {
- return parser_->EncryptionFromContent(content);
- }
-
- buzz::XmlElement* NextFromEncryption(buzz::XmlElement* encryption) {
- return parser_->NextFromEncryption(encryption);
- }
-
- cricket::AudioCodec AudioCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- return parser_->AudioCodecFromPayloadType(payload_type);
- }
-
- cricket::VideoCodec VideoCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- return parser_->VideoCodecFromPayloadType(payload_type);
- }
-
- cricket::DataCodec DataCodecFromPayloadType(
- const buzz::XmlElement* payload_type) {
- return parser_->DataCodecFromPayloadType(payload_type);
- }
-
- const AudioContentDescription* GetFirstAudioContentDescription(
- const cricket::SessionDescription* sdesc) {
- const cricket::ContentInfo* content =
- cricket::GetFirstAudioContent(sdesc);
- if (content == NULL)
- return NULL;
- return static_cast<const AudioContentDescription*>(content->description);
- }
-
- const cricket::VideoContentDescription* GetFirstVideoContentDescription(
- const cricket::SessionDescription* sdesc) {
- const cricket::ContentInfo* content =
- cricket::GetFirstVideoContent(sdesc);
- if (content == NULL)
- return NULL;
- return static_cast<const cricket::VideoContentDescription*>(
- content->description);
- }
-
- void CheckCryptoFromGoodIncomingInitiate(const cricket::Session* session) {
- ASSERT_TRUE(session != NULL);
- const AudioContentDescription* content =
- GetFirstAudioContentDescription(session->remote_description());
- ASSERT_TRUE(content != NULL);
- ASSERT_EQ(2U, content->cryptos().size());
- ASSERT_EQ(145, content->cryptos()[0].tag);
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
- ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
- content->cryptos()[0].key_params);
- ASSERT_EQ(51, content->cryptos()[1].tag);
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", content->cryptos()[1].cipher_suite);
- ASSERT_EQ("inline:J4lfdUL8W1F7TNJKcbuygaQuA429SJy2e9JctPUy",
- content->cryptos()[1].key_params);
- }
-
- void CheckCryptoForGoodOutgoingAccept(const cricket::Session* session) {
- const AudioContentDescription* content =
- GetFirstAudioContentDescription(session->local_description());
- ASSERT_EQ(1U, content->cryptos().size());
- ASSERT_EQ(145, content->cryptos()[0].tag);
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", content->cryptos()[0].cipher_suite);
- ASSERT_EQ(47U, content->cryptos()[0].key_params.size());
- }
-
- void CheckBadCryptoFromIncomingInitiate(const cricket::Session* session) {
- const AudioContentDescription* content =
- GetFirstAudioContentDescription(session->remote_description());
- ASSERT_EQ(1U, content->cryptos().size());
- ASSERT_EQ(145, content->cryptos()[0].tag);
- ASSERT_EQ("NOT_SUPPORTED", content->cryptos()[0].cipher_suite);
- ASSERT_EQ("inline:hsWuSQJxx7przmb8HM+ZkeNcG3HezSNID7LmfDa9",
- content->cryptos()[0].key_params);
- }
-
- void CheckNoCryptoForOutgoingAccept(const cricket::Session* session) {
- const AudioContentDescription* content =
- GetFirstAudioContentDescription(session->local_description());
- ASSERT_TRUE(content->cryptos().empty());
- }
-
- void CheckRtcpFb(const cricket::SessionDescription* sdesc) {
- VerifyCodecFbParams<AudioCodec>(expected_audio_fb_params_,
- GetFirstAudioContentDescription(sdesc));
-
- VerifyCodecFbParams<VideoCodec>(expected_video_fb_params_,
- GetFirstVideoContentDescription(sdesc));
-
- VerifyCodecFbParams<DataCodec>(expected_data_fb_params_,
- GetFirstDataContentDescription(sdesc));
- }
-
- void CheckVideoBandwidth(int expected_bandwidth,
- const cricket::SessionDescription* sdesc) {
- const cricket::VideoContentDescription* video =
- GetFirstVideoContentDescription(sdesc);
- if (video != NULL) {
- ASSERT_EQ(expected_bandwidth, video->bandwidth());
- }
- }
-
- void CheckVideoRtcpMux(bool expected_video_rtcp_mux,
- const cricket::SessionDescription* sdesc) {
- const cricket::VideoContentDescription* video =
- GetFirstVideoContentDescription(sdesc);
- if (video != NULL) {
- ASSERT_EQ(expected_video_rtcp_mux, video->rtcp_mux());
- }
- }
-
- virtual void CheckRtpDataContent(buzz::XmlElement* content) {
- if (initial_protocol_) {
- // Gingle can not write out data content.
- return;
- }
-
- buzz::XmlElement* e = PayloadTypeFromContent(content);
- ASSERT_TRUE(e != NULL);
- cricket::DataCodec codec = DataCodecFromPayloadType(e);
- EXPECT_EQ(127, codec.id);
- EXPECT_EQ("google-data", codec.name);
- EXPECT_EQ(expected_data_fb_params_, codec.feedback_params);
-
- CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
- CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
- if (expect_outgoing_crypto_) {
- content = parser_->NextContent(content);
- buzz::XmlElement* encryption = EncryptionFromContent(content);
- ASSERT_TRUE(encryption != NULL);
- // TODO(pthatcher): Check encryption parameters?
- }
- }
-
- virtual void CheckSctpDataContent(buzz::XmlElement* content) {
- if (initial_protocol_) {
- // Gingle can not write out data content.
- return;
- }
-
- buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
- ASSERT_TRUE(payload_type == NULL);
- buzz::XmlElement* encryption = EncryptionFromContent(content);
- ASSERT_TRUE(encryption == NULL);
- // TODO(pthatcher): Check for <streams>.
- }
-
- void CheckDataRtcpMux(bool expected_data_rtcp_mux,
- const cricket::SessionDescription* sdesc) {
- const cricket::DataContentDescription* data =
- GetFirstDataContentDescription(sdesc);
- if (data != NULL) {
- ASSERT_EQ(expected_data_rtcp_mux, data->rtcp_mux());
- }
- }
-
- void CheckAudioSsrcForIncomingAccept(const cricket::Session* session) {
- const AudioContentDescription* audio =
- GetFirstAudioContentDescription(session->remote_description());
- ASSERT_TRUE(audio != NULL);
- ASSERT_EQ(kAudioSsrc, audio->first_ssrc());
- }
-
- void CheckVideoSsrcForIncomingAccept(const cricket::Session* session) {
- const cricket::VideoContentDescription* video =
- GetFirstVideoContentDescription(session->remote_description());
- ASSERT_TRUE(video != NULL);
- ASSERT_EQ(kVideoSsrc, video->first_ssrc());
- }
-
- void CheckDataSsrcForIncomingAccept(const cricket::Session* session) {
- const cricket::DataContentDescription* data =
- GetFirstDataContentDescription(session->remote_description());
- ASSERT_TRUE(data != NULL);
- ASSERT_EQ(kDataSsrc, data->first_ssrc());
- }
-
- void TestGoodIncomingInitiate(const std::string& initiate_string,
- const cricket::CallOptions& options,
- buzz::XmlElement** element) {
- *element = NULL;
-
- rtc::scoped_ptr<buzz::XmlElement> el(
- buzz::XmlElement::ForStr(initiate_string));
- client_->session_manager()->OnIncomingMessage(el.get());
- ASSERT_TRUE(call_ != NULL);
- ASSERT_TRUE(call_->sessions()[0] != NULL);
- ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
- ClearStanzas();
- CheckVideoBandwidth(expected_video_bandwidth_,
- call_->sessions()[0]->remote_description());
- CheckVideoRtcpMux(expected_video_rtcp_mux_,
- call_->sessions()[0]->remote_description());
- CheckRtcpFb(call_->sessions()[0]->remote_description());
- if (expect_incoming_crypto_) {
- CheckCryptoFromGoodIncomingInitiate(call_->sessions()[0]);
- }
-
- // TODO(pthatcher): Add tests for sending <bandwidth> in accept.
- call_->AcceptSession(call_->sessions()[0], options);
- ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
-
- buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
- ASSERT_TRUE(e != NULL);
- ASSERT_TRUE(ContentFromAction(e) != NULL);
- *element = CopyElement(ContentFromAction(e));
- ASSERT_TRUE(*element != NULL);
- ClearStanzas();
- if (expect_outgoing_crypto_) {
- CheckCryptoForGoodOutgoingAccept(call_->sessions()[0]);
- }
-
- if (options.data_channel_type == cricket::DCT_RTP) {
- CheckDataRtcpMux(true, call_->sessions()[0]->local_description());
- CheckDataRtcpMux(true, call_->sessions()[0]->remote_description());
- // TODO(pthatcher): Check rtcpmux and crypto?
- }
-
- call_->Terminate();
- ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
- e = ActionFromStanza(stanzas_[0]);
- ASSERT_TRUE(e != NULL);
- ASSERT_TRUE(parser_->ActionIsTerminate(e));
- ClearStanzas();
- }
-
- void TestRejectOffer(const std::string &initiate_string,
- const cricket::CallOptions& options,
- buzz::XmlElement** element) {
- *element = NULL;
-
- rtc::scoped_ptr<buzz::XmlElement> el(
- buzz::XmlElement::ForStr(initiate_string));
- client_->session_manager()->OnIncomingMessage(el.get());
- ASSERT_TRUE(call_ != NULL);
- ASSERT_TRUE(call_->sessions()[0] != NULL);
- ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
- ClearStanzas();
-
- call_->AcceptSession(call_->sessions()[0], options);
- ASSERT_EQ(cricket::Session::STATE_SENTACCEPT,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
-
- buzz::XmlElement* e = ActionFromStanza(stanzas_[0]);
- ASSERT_TRUE(e != NULL);
- ASSERT_TRUE(ContentFromAction(e) != NULL);
- *element = CopyElement(ContentFromAction(e));
- ASSERT_TRUE(*element != NULL);
- ClearStanzas();
-
- buzz::XmlElement* content = *element;
- // The NextContent method actually returns the second content. So we
- // can't handle the case when audio, video and data are all enabled. But
- // since we are testing rejection, it won't be the case.
- if (options.has_audio()) {
- ASSERT_TRUE(content != NULL);
- ASSERT_EQ("test audio", content->Attr(buzz::QName("", "name")));
- content = parser_->NextContent(content);
- }
-
- if (options.has_video()) {
- ASSERT_TRUE(content != NULL);
- ASSERT_EQ("test video", content->Attr(buzz::QName("", "name")));
- content = parser_->NextContent(content);
- }
-
- if (options.has_data()) {
- ASSERT_TRUE(content != NULL);
- ASSERT_EQ("test data", content->Attr(buzz::QName("", "name")));
- content = parser_->NextContent(content);
- }
-
- call_->Terminate();
- ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
- e = ActionFromStanza(stanzas_[0]);
- ASSERT_TRUE(e != NULL);
- ASSERT_TRUE(parser_->ActionIsTerminate(e));
- ClearStanzas();
- }
-
- void TestBadIncomingInitiate(const std::string& initiate_string) {
- rtc::scoped_ptr<buzz::XmlElement> el(
- buzz::XmlElement::ForStr(initiate_string));
- client_->session_manager()->OnIncomingMessage(el.get());
- ASSERT_TRUE(call_ != NULL);
- ASSERT_TRUE(call_->sessions()[0] != NULL);
- ASSERT_EQ(cricket::Session::STATE_SENTREJECT,
- call_->sessions()[0]->state());
- ASSERT_EQ(2U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[1]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[1]->Attr(buzz::QN_TYPE));
- ClearStanzas();
- }
-
- void VerifyAudioCodec(const AudioCodec& codec, int id,
- const std::string& name, int clockrate,
- int bitrate, int channels) {
- ASSERT_EQ(id, codec.id);
- ASSERT_EQ(name, codec.name);
- ASSERT_EQ(clockrate, codec.clockrate);
- ASSERT_EQ(bitrate, codec.bitrate);
- ASSERT_EQ(channels, codec.channels);
- ASSERT_EQ(expected_audio_fb_params_, codec.feedback_params);
- }
-
- void TestGoodOutgoingInitiate(const cricket::CallOptions& options) {
- if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
- // rtcp fb is only implemented for jingle.
- ExpectRtcpFb();
- }
-
- client_->CreateCall();
- ASSERT_TRUE(call_ != NULL);
- call_->InitiateSession(buzz::Jid("me@mydomain.com"),
- buzz::Jid("me@mydomain.com"), options);
- ASSERT_TRUE(call_->sessions()[0] != NULL);
- ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
- buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
- ASSERT_TRUE(action != NULL);
- buzz::XmlElement* content = ContentFromAction(action);
- ASSERT_TRUE(content != NULL);
-
- buzz::XmlElement* e = PayloadTypeFromContent(content);
- ASSERT_TRUE(e != NULL);
- cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 103, "ISAC", 16000, 0, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 104, "ISAC", 32000, 0, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 119, "ISACLC", 16000, 40000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 99, "speex", 16000, 22000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 97, "IPCMWB", 16000, 80000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 9, "G722", 8000, 64000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 102, "iLBC", 8000, 13300, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 98, "speex", 8000, 11000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 3, "GSM", 8000, 13000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 100, "EG711U", 8000, 64000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 101, "EG711A", 8000, 64000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 0, "PCMU", 8000, 64000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 8, "PCMA", 8000, 64000, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 126, "CN", 32000, 0, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 105, "CN", 16000, 0, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 13, "CN", 8000, 0, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 117, "red", 8000, 0, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- VerifyAudioCodec(codec, 106, "telephone-event", 8000, 0, 1);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e == NULL);
-
- if (expect_outgoing_crypto_) {
- buzz::XmlElement* encryption = EncryptionFromContent(content);
- ASSERT_TRUE(encryption != NULL);
-
- if (client_->secure() == cricket::SEC_REQUIRED) {
- ASSERT_TRUE(cricket::GetXmlAttr(
- encryption, cricket::QN_ENCRYPTION_REQUIRED, false));
- }
-
- if (content->Name().Namespace() == cricket::NS_GINGLE_AUDIO) {
- e = encryption->FirstNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE);
- ASSERT_TRUE(e != NULL);
- ASSERT_TRUE(
- e->NextNamed(cricket::QN_GINGLE_AUDIO_CRYPTO_USAGE) == NULL);
- ASSERT_TRUE(
- e->FirstNamed(cricket::QN_GINGLE_VIDEO_CRYPTO_USAGE) == NULL);
- }
-
- e = encryption->FirstNamed(cricket::QN_CRYPTO);
- ASSERT_TRUE(e != NULL);
- ASSERT_EQ("0", e->Attr(cricket::QN_CRYPTO_TAG));
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_32", e->Attr(cricket::QN_CRYPTO_SUITE));
- std::string key_0 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
- ASSERT_EQ(47U, key_0.length());
- ASSERT_EQ("inline:", key_0.substr(0, 7));
-
- e = e->NextNamed(cricket::QN_CRYPTO);
- ASSERT_TRUE(e != NULL);
- ASSERT_EQ("1", e->Attr(cricket::QN_CRYPTO_TAG));
- ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", e->Attr(cricket::QN_CRYPTO_SUITE));
- std::string key_1 = e->Attr(cricket::QN_CRYPTO_KEY_PARAMS);
- ASSERT_EQ(47U, key_1.length());
- ASSERT_EQ("inline:", key_1.substr(0, 7));
- ASSERT_NE(key_0, key_1);
-
- encryption = NextFromEncryption(encryption);
- ASSERT_TRUE(encryption == NULL);
- }
-
- if (options.has_video()) {
- CheckVideoBandwidth(options.video_bandwidth,
- call_->sessions()[0]->local_description());
- CheckVideoRtcpMux(expected_video_rtcp_mux_,
- call_->sessions()[0]->remote_description());
- content = parser_->NextContent(content);
- const buzz::XmlElement* bandwidth =
- parser_->BandwidthFromContent(content);
- if (options.video_bandwidth == cricket::kAutoBandwidth) {
- ASSERT_TRUE(bandwidth == NULL);
- } else {
- ASSERT_TRUE(bandwidth != NULL);
- ASSERT_EQ("AS", bandwidth->Attr(buzz::QName("", "type")));
- ASSERT_EQ(rtc::ToString(options.video_bandwidth / 1000),
- bandwidth->BodyText());
- }
-
- buzz::XmlElement* e = PayloadTypeFromContent(content);
- ASSERT_TRUE(e != NULL);
- VideoCodec codec = VideoCodecFromPayloadType(e);
- VideoCodec expected_codec = kVideoCodecs[0];
- expected_codec.preference = codec.preference;
- expected_codec.feedback_params = expected_video_fb_params_;
- EXPECT_EQ(expected_codec, codec);
- }
-
- if (options.data_channel_type == cricket::DCT_RTP) {
- content = parser_->NextContent(content);
- CheckRtpDataContent(content);
- }
-
- if (options.data_channel_type == cricket::DCT_SCTP) {
- content = parser_->NextContent(content);
- CheckSctpDataContent(content);
- }
-
- ClearStanzas();
- }
-
- void TestHasAllSupportedAudioCodecs(buzz::XmlElement* e) {
- ASSERT_TRUE(e != NULL);
-
- e = PayloadTypeFromContent(e);
- ASSERT_TRUE(e != NULL);
- cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(103, codec.id);
- ASSERT_EQ("ISAC", codec.name);
- ASSERT_EQ(16000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(104, codec.id);
- ASSERT_EQ("ISAC", codec.name);
- ASSERT_EQ(32000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(119, codec.id);
- ASSERT_EQ("ISACLC", codec.name);
- ASSERT_EQ(16000, codec.clockrate);
- ASSERT_EQ(40000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(99, codec.id);
- ASSERT_EQ("speex", codec.name);
- ASSERT_EQ(16000, codec.clockrate);
- ASSERT_EQ(22000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(97, codec.id);
- ASSERT_EQ("IPCMWB", codec.name);
- ASSERT_EQ(16000, codec.clockrate);
- ASSERT_EQ(80000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(9, codec.id);
- ASSERT_EQ("G722", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(64000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(102, codec.id);
- ASSERT_EQ("iLBC", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(13300, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(98, codec.id);
- ASSERT_EQ("speex", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(11000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(3, codec.id);
- ASSERT_EQ("GSM", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(13000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(100, codec.id);
- ASSERT_EQ("EG711U", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(64000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(101, codec.id);
- ASSERT_EQ("EG711A", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(64000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(0, codec.id);
- ASSERT_EQ("PCMU", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(64000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(8, codec.id);
- ASSERT_EQ("PCMA", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(64000, codec.bitrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(126, codec.id);
- ASSERT_EQ("CN", codec.name);
- ASSERT_EQ(32000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(105, codec.id);
- ASSERT_EQ("CN", codec.name);
- ASSERT_EQ(16000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(13, codec.id);
- ASSERT_EQ("CN", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(117, codec.id);
- ASSERT_EQ("red", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(106, codec.id);
- ASSERT_EQ("telephone-event", codec.name);
- ASSERT_EQ(8000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e == NULL);
- }
-
- void TestCodecsOfVideoInitiate(buzz::XmlElement* content) {
- ASSERT_TRUE(content != NULL);
- buzz::XmlElement* payload_type = PayloadTypeFromContent(content);
- ASSERT_TRUE(payload_type != NULL);
- cricket::AudioCodec codec = AudioCodecFromPayloadType(payload_type);
- ASSERT_EQ(103, codec.id);
- ASSERT_EQ("ISAC", codec.name);
- ASSERT_EQ(16000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- content = parser_->NextContent(content);
- ASSERT_TRUE(content != NULL);
- payload_type = PayloadTypeFromContent(content);
- ASSERT_TRUE(payload_type != NULL);
- cricket::VideoCodec vcodec =
- parser_->VideoCodecFromPayloadType(payload_type);
- ASSERT_EQ(99, vcodec.id);
- ASSERT_EQ("H264-SVC", vcodec.name);
- ASSERT_EQ(320, vcodec.width);
- ASSERT_EQ(200, vcodec.height);
- ASSERT_EQ(30, vcodec.framerate);
- }
-
- void TestHasAudioCodecsFromInitiateSomeUnsupported(buzz::XmlElement* e) {
- ASSERT_TRUE(e != NULL);
- e = PayloadTypeFromContent(e);
- ASSERT_TRUE(e != NULL);
-
- cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(103, codec.id);
- ASSERT_EQ("ISAC", codec.name);
- ASSERT_EQ(16000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(100, codec.id);
- ASSERT_EQ("EG711U", codec.name);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(101, codec.id);
- ASSERT_EQ("EG711A", codec.name);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(0, codec.id);
- ASSERT_EQ("PCMU", codec.name);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(13, codec.id);
- ASSERT_EQ("CN", codec.name);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e == NULL);
- }
-
- void TestHasAudioCodecsFromInitiateDynamicAudioCodecs(
- buzz::XmlElement* e) {
- ASSERT_TRUE(e != NULL);
- e = PayloadTypeFromContent(e);
- ASSERT_TRUE(e != NULL);
-
- cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(123, codec.id);
- ASSERT_EQ(16000, codec.clockrate);
- ASSERT_EQ(1, codec.channels);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e == NULL);
- }
-
- void TestHasDefaultAudioCodecs(buzz::XmlElement* e) {
- ASSERT_TRUE(e != NULL);
- e = PayloadTypeFromContent(e);
- ASSERT_TRUE(e != NULL);
-
- cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(103, codec.id);
- ASSERT_EQ("ISAC", codec.name);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(0, codec.id);
- ASSERT_EQ("PCMU", codec.name);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e == NULL);
- }
-
- void TestHasAudioCodecsFromInitiateStaticAudioCodecs(
- buzz::XmlElement* e) {
- ASSERT_TRUE(e != NULL);
- e = PayloadTypeFromContent(e);
- ASSERT_TRUE(e != NULL);
-
- cricket::AudioCodec codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(3, codec.id);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(0, codec.id);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e != NULL);
- codec = AudioCodecFromPayloadType(e);
- ASSERT_EQ(8, codec.id);
-
- e = NextFromPayloadType(e);
- ASSERT_TRUE(e == NULL);
- }
-
- void TestGingleInitiateWithUnsupportedCrypto(
- const std::string &initiate_string,
- buzz::XmlElement** element) {
- *element = NULL;
-
- rtc::scoped_ptr<buzz::XmlElement> el(
- buzz::XmlElement::ForStr(initiate_string));
- client_->session_manager()->OnIncomingMessage(el.get());
-
- ASSERT_EQ(cricket::Session::STATE_RECEIVEDINITIATE,
- call_->sessions()[0]->state());
- ClearStanzas();
- CheckBadCryptoFromIncomingInitiate(call_->sessions()[0]);
-
- call_->AcceptSession(call_->sessions()[0], cricket::CallOptions());
- ClearStanzas();
- CheckNoCryptoForOutgoingAccept(call_->sessions()[0]);
-
- call_->Terminate();
- ASSERT_EQ(cricket::Session::STATE_SENTTERMINATE,
- call_->sessions()[0]->state());
- ClearStanzas();
- }
-
- void TestIncomingAcceptWithSsrcs(
- const std::string& accept_string,
- cricket::CallOptions& options) {
- client_->CreateCall();
- ASSERT_TRUE(call_ != NULL);
-
- call_->InitiateSession(buzz::Jid("me@mydomain.com"),
- buzz::Jid("me@mydomain.com"), options);
- ASSERT_TRUE(call_->sessions()[0] != NULL);
- ASSERT_EQ(cricket::Session::STATE_SENTINITIATE,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_SET), stanzas_[0]->Attr(buzz::QN_TYPE));
- buzz::XmlElement* action = ActionFromStanza(stanzas_[0]);
- ASSERT_TRUE(action != NULL);
- buzz::XmlElement* content = ContentFromAction(action);
- ASSERT_TRUE(content != NULL);
- if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
- buzz::XmlElement* content_desc =
- content->FirstNamed(cricket::QN_JINGLE_RTP_CONTENT);
- ASSERT_TRUE(content_desc != NULL);
- ASSERT_EQ("", content_desc->Attr(cricket::QN_SSRC));
- }
- ClearStanzas();
-
- // We need to insert the session ID into the session accept message.
- rtc::scoped_ptr<buzz::XmlElement> el(
- buzz::XmlElement::ForStr(accept_string));
- const std::string sid = call_->sessions()[0]->id();
- if (initial_protocol_ == cricket::PROTOCOL_JINGLE) {
- buzz::XmlElement* jingle = el->FirstNamed(cricket::QN_JINGLE);
- jingle->SetAttr(cricket::QN_SID, sid);
- } else {
- buzz::XmlElement* session = el->FirstNamed(cricket::QN_GINGLE_SESSION);
- session->SetAttr(cricket::QN_ID, sid);
- }
-
- client_->session_manager()->OnIncomingMessage(el.get());
-
- ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_TRUE(buzz::QN_IQ == stanzas_[0]->Name());
- ASSERT_TRUE(stanzas_[0]->HasAttr(buzz::QN_TYPE));
- ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
- ClearStanzas();
-
- CheckAudioSsrcForIncomingAccept(call_->sessions()[0]);
- CheckVideoSsrcForIncomingAccept(call_->sessions()[0]);
- if (options.data_channel_type == cricket::DCT_RTP) {
- CheckDataSsrcForIncomingAccept(call_->sessions()[0]);
- }
- // TODO(pthatcher): Check kDataSid if DCT_SCTP.
- // const uint32 kDataSid = 0;
- }
-
- size_t ClearStanzas() {
- size_t size = stanzas_.size();
- for (size_t i = 0; i < size; i++) {
- delete stanzas_[i];
- }
- stanzas_.clear();
- return size;
- }
-
- buzz::XmlElement* SetJingleSid(buzz::XmlElement* stanza) {
- buzz::XmlElement* jingle =
- stanza->FirstNamed(cricket::QN_JINGLE);
- jingle->SetAttr(cricket::QN_SID, call_->sessions()[0]->id());
- return stanza;
- }
-
- void TestSendVideoStreamUpdate() {
- cricket::CallOptions options = VideoCallOptions();
- options.is_muc = true;
-
- client_->CreateCall();
- call_->InitiateSession(buzz::Jid("me@mydomain.com"),
- buzz::Jid("me@mydomain.com"), options);
- ClearStanzas();
-
- cricket::StreamParams stream;
- stream.id = "test-stream";
- stream.ssrcs.push_back(1001);
- rtc::scoped_ptr<buzz::XmlElement> expected_stream_add(
- buzz::XmlElement::ForStr(
- JingleOutboundStreamAdd(
- call_->sessions()[0]->id(),
- "video", stream.id, "1001")));
- rtc::scoped_ptr<buzz::XmlElement> expected_stream_remove(
- buzz::XmlElement::ForStr(
- JingleOutboundStreamRemove(
- call_->sessions()[0]->id(),
- "video", stream.id)));
-
- call_->SendVideoStreamUpdate(call_->sessions()[0],
- call_->CreateVideoStreamUpdate(stream));
- ASSERT_EQ(1U, stanzas_.size());
- EXPECT_EQ(expected_stream_add->Str(), stanzas_[0]->Str());
- ClearStanzas();
-
- stream.ssrcs.clear();
- call_->SendVideoStreamUpdate(call_->sessions()[0],
- call_->CreateVideoStreamUpdate(stream));
- ASSERT_EQ(1U, stanzas_.size());
- EXPECT_EQ(expected_stream_remove->Str(), stanzas_[0]->Str());
- ClearStanzas();
- }
-
- void TestStreamsUpdateAndViewRequests() {
- cricket::CallOptions options = VideoCallOptions();
- options.is_muc = true;
-
- client_->CreateCall();
- call_->InitiateSession(buzz::Jid("me@mydomain.com"),
- buzz::Jid("me@mydomain.com"), options);
- ASSERT_EQ(1U, ClearStanzas());
- ASSERT_EQ(0U, last_streams_added_.audio().size());
- ASSERT_EQ(0U, last_streams_added_.video().size());
- ASSERT_EQ(0U, last_streams_removed_.audio().size());
- ASSERT_EQ(0U, last_streams_removed_.video().size());
-
- rtc::scoped_ptr<buzz::XmlElement> accept_stanza(
- buzz::XmlElement::ForStr(kJingleAcceptWithSsrcs));
- SetJingleSid(accept_stanza.get());
- client_->session_manager()->OnIncomingMessage(accept_stanza.get());
- ASSERT_EQ(cricket::Session::STATE_RECEIVEDACCEPT,
- call_->sessions()[0]->state());
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_EQ(std::string(buzz::STR_RESULT), stanzas_[0]->Attr(buzz::QN_TYPE));
- ClearStanzas();
- // Need to clear the added streams, because they are populated when
- // receiving an accept message now.
- last_streams_added_.mutable_video()->clear();
- last_streams_added_.mutable_audio()->clear();
-
- call_->sessions()[0]->SetState(cricket::Session::STATE_INPROGRESS);
-
- rtc::scoped_ptr<buzz::XmlElement> streams_stanza(
- buzz::XmlElement::ForStr(
- JingleStreamAdd("video", "Bob", "video1", "ABC")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- // First one is ignored because of bad syntax.
- ASSERT_EQ(1U, stanzas_.size());
- // TODO(pthatcher): Figure out how to make this an ERROR rather than RESULT.
- ASSERT_EQ(std::string(buzz::STR_ERROR), stanzas_[0]->Attr(buzz::QN_TYPE));
- ClearStanzas();
- ASSERT_EQ(0U, last_streams_added_.audio().size());
- ASSERT_EQ(0U, last_streams_added_.video().size());
- ASSERT_EQ(0U, last_streams_removed_.audio().size());
- ASSERT_EQ(0U, last_streams_removed_.video().size());
-
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamAdd("audio", "Bob", "audio1", "1234")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(1U, last_streams_added_.audio().size());
- ASSERT_EQ("Bob", last_streams_added_.audio()[0].groupid);
- ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
- ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
-
- // Ignores adds without ssrcs.
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamAddWithoutSsrc("audio", "Bob", "audioX")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(1U, last_streams_added_.audio().size());
- ASSERT_EQ(1234U, last_streams_added_.audio()[0].first_ssrc());
-
- // Ignores stream updates with unknown content names. (Don't terminate).
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamAddWithoutSsrc("foo", "Bob", "foo")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
-
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamAdd("audio", "Joe", "audio1", "2468")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(1U, last_streams_added_.audio().size());
- ASSERT_EQ("Joe", last_streams_added_.audio()[0].groupid);
- ASSERT_EQ(1U, last_streams_added_.audio()[0].ssrcs.size());
- ASSERT_EQ(2468U, last_streams_added_.audio()[0].first_ssrc());
-
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamAdd("video", "Bob", "video1", "5678")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(1U, last_streams_added_.video().size());
- ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
- ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
- ASSERT_EQ(5678U, last_streams_added_.video()[0].first_ssrc());
-
- // We're testing that a "duplicate" is effectively ignored.
- last_streams_added_.mutable_video()->clear();
- last_streams_removed_.mutable_video()->clear();
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamAdd("video", "Bob", "video1", "5678")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(0U, last_streams_added_.video().size());
- ASSERT_EQ(0U, last_streams_removed_.video().size());
-
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamAdd("video", "Bob", "video2", "5679")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(1U, last_streams_added_.video().size());
- ASSERT_EQ("Bob", last_streams_added_.video()[0].groupid);
- ASSERT_EQ(1U, last_streams_added_.video()[0].ssrcs.size());
- ASSERT_EQ(5679U, last_streams_added_.video()[0].first_ssrc());
-
- cricket::FakeVoiceMediaChannel* voice_channel = fme_->GetVoiceChannel(0);
- ASSERT_TRUE(voice_channel != NULL);
- ASSERT_TRUE(voice_channel->HasRecvStream(1234U));
- ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
- cricket::FakeVideoMediaChannel* video_channel = fme_->GetVideoChannel(0);
- ASSERT_TRUE(video_channel != NULL);
- ASSERT_TRUE(video_channel->HasRecvStream(5678U));
- ClearStanzas();
-
- cricket::ViewRequest viewRequest;
- cricket::StaticVideoView staticVideoView(
- cricket::StreamSelector(5678U), 640, 480, 30);
- viewRequest.static_video_views.push_back(staticVideoView);
- rtc::scoped_ptr<buzz::XmlElement> expected_view_elem(
- buzz::XmlElement::ForStr(JingleView("5678", "640", "480", "30")));
- SetJingleSid(expected_view_elem.get());
-
- ASSERT_TRUE(
- call_->SendViewRequest(call_->sessions()[0], viewRequest));
- ASSERT_EQ(1U, stanzas_.size());
- ASSERT_EQ(expected_view_elem->Str(), stanzas_[0]->Str());
- ClearStanzas();
-
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamRemove("audio", "Bob", "audio1")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(1U, last_streams_removed_.audio().size());
- ASSERT_EQ(1U, last_streams_removed_.audio()[0].ssrcs.size());
- EXPECT_EQ(1234U, last_streams_removed_.audio()[0].first_ssrc());
-
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamRemove("video", "Bob", "video1")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(1U, last_streams_removed_.video().size());
- ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
- EXPECT_EQ(5678U, last_streams_removed_.video()[0].first_ssrc());
-
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamRemove("video", "Bob", "video2")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(1U, last_streams_removed_.video().size());
- ASSERT_EQ(1U, last_streams_removed_.video()[0].ssrcs.size());
- EXPECT_EQ(5679U, last_streams_removed_.video()[0].first_ssrc());
-
- // Duplicate removal: should be ignored.
- last_streams_removed_.mutable_audio()->clear();
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamRemove("audio", "Bob", "audio1")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(0U, last_streams_removed_.audio().size());
-
- // Duplicate removal: should be ignored.
- last_streams_removed_.mutable_video()->clear();
- streams_stanza.reset(buzz::XmlElement::ForStr(
- JingleStreamRemove("video", "Bob", "video1")));
- SetJingleSid(streams_stanza.get());
- client_->session_manager()->OnIncomingMessage(streams_stanza.get());
- ASSERT_EQ(0U, last_streams_removed_.video().size());
-
- voice_channel = fme_->GetVoiceChannel(0);
- ASSERT_TRUE(voice_channel != NULL);
- ASSERT_FALSE(voice_channel->HasRecvStream(1234U));
- ASSERT_TRUE(voice_channel->HasRecvStream(2468U));
- video_channel = fme_->GetVideoChannel(0);
- ASSERT_TRUE(video_channel != NULL);
- ASSERT_FALSE(video_channel->HasRecvStream(5678U));
-
- // Fails because ssrc is now invalid.
- ASSERT_FALSE(
- call_->SendViewRequest(call_->sessions()[0], viewRequest));
-
- ClearStanzas();
- }
-
- void MakeSignalingSecure(cricket::SecurePolicy secure) {
- client_->set_secure(secure);
- }
-
- void ExpectCrypto(cricket::SecurePolicy secure) {
- MakeSignalingSecure(secure);
- expect_incoming_crypto_ = true;
-#ifdef HAVE_SRTP
- expect_outgoing_crypto_ = true;
-#endif
- }
-
- void ExpectVideoBandwidth(int bandwidth) {
- expected_video_bandwidth_ = bandwidth;
- }
-
- void ExpectVideoRtcpMux(bool rtcp_mux) {
- expected_video_rtcp_mux_ = rtcp_mux;
- }
-
- template <class C>
- void SetCodecFeedbackParams(std::vector<C>* codecs,
- const FeedbackParams& fb_params) {
- for (size_t i = 0; i < codecs->size(); ++i) {
- codecs->at(i).feedback_params = fb_params;
- }
- }
-
- void ExpectRtcpFb() {
- FeedbackParams params_nack_fir;
- params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamCcm,
- cricket::kRtcpFbCcmParamFir));
- params_nack_fir.Add(FeedbackParam(cricket::kRtcpFbParamNack));
-
- FeedbackParams params_nack;
- params_nack.Add(FeedbackParam(cricket::kRtcpFbParamNack));
-
- expected_audio_fb_params_ = params_nack;
- expected_video_fb_params_ = params_nack_fir;
- expected_data_fb_params_ = params_nack;
- }
-
- cricket::FakeMediaEngine* fme() { return fme_; }
-
- private:
- void OnSendStanza(cricket::SessionManager* manager,
- const buzz::XmlElement* stanza) {
- LOG(LS_INFO) << stanza->Str();
- stanzas_.push_back(new buzz::XmlElement(*stanza));
- }
-
- void OnSessionCreate(cricket::Session* session, bool initiate) {
- session->set_current_protocol(initial_protocol_);
- }
-
- void OnCallCreate(cricket::Call *call) {
- call_ = call;
- call->SignalMediaStreamsUpdate.connect(
- this, &MediaSessionClientTest::OnMediaStreamsUpdate);
- }
-
- void OnCallDestroy(cricket::Call *call) {
- call_ = NULL;
- }
-
- void OnMediaStreamsUpdate(cricket::Call *call,
- cricket::Session *session,
- const cricket::MediaStreams& added,
- const cricket::MediaStreams& removed) {
- last_streams_added_.CopyFrom(added);
- last_streams_removed_.CopyFrom(removed);
- }
-
- rtc::NetworkManager* nm_;
- cricket::PortAllocator* pa_;
- cricket::SessionManager* sm_;
- cricket::FakeMediaEngine* fme_;
- cricket::FakeDataEngine* fdme_;
- cricket::MediaSessionClient* client_;
-
- cricket::Call* call_;
- std::vector<buzz::XmlElement* > stanzas_;
- MediaSessionTestParser* parser_;
- cricket::SignalingProtocol initial_protocol_;
- bool expect_incoming_crypto_;
- bool expect_outgoing_crypto_;
- int expected_video_bandwidth_;
- bool expected_video_rtcp_mux_;
- FeedbackParams expected_audio_fb_params_;
- FeedbackParams expected_video_fb_params_;
- FeedbackParams expected_data_fb_params_;
- cricket::MediaStreams last_streams_added_;
- cricket::MediaStreams last_streams_removed_;
-};
-
-MediaSessionClientTest* GingleTest() {
- return new MediaSessionClientTest(new GingleSessionTestParser(),
- cricket::PROTOCOL_GINGLE);
-}
-
-MediaSessionClientTest* JingleTest() {
- return new MediaSessionClientTest(new JingleSessionTestParser(),
- cricket::PROTOCOL_JINGLE);
-}
-
-class MediaSessionTest : public ::testing::Test {};
-
-TEST_F(MediaSessionTest, JingleGoodInitiateWithRtcpFb) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
-
- cricket::CallOptions options = VideoCallOptions();
- options.data_channel_type = cricket::DCT_SCTP;
- test->ExpectRtcpFb();
- test->TestGoodIncomingInitiate(
- kJingleInitiateWithRtcpFb, options, elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleGoodVideoInitiate) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestGoodIncomingInitiate(
- kJingleVideoInitiate, VideoCallOptions(), elem.use());
- test->TestCodecsOfVideoInitiate(elem.get());
-}
-
-TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithBandwidth) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->ExpectVideoBandwidth(42000);
- test->TestGoodIncomingInitiate(
- kJingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithRtcpMux) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->ExpectVideoRtcpMux(true);
- test->TestGoodIncomingInitiate(
- kJingleVideoInitiateWithRtcpMux, VideoCallOptions(), elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithRtpData) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- cricket::CallOptions options = VideoCallOptions();
- options.data_channel_type = cricket::DCT_RTP;
- test->TestGoodIncomingInitiate(
- AddEncryption(kJingleVideoInitiateWithRtpData, kJingleCryptoOffer),
- options,
- elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleGoodVideoInitiateWithSctpData) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- cricket::CallOptions options = VideoCallOptions();
- options.data_channel_type = cricket::DCT_SCTP;
- test->TestGoodIncomingInitiate(kJingleVideoInitiateWithSctpData,
- options,
- elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleRejectAudio) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- cricket::CallOptions options = VideoCallOptions();
- options.recv_audio = false;
- options.data_channel_type = cricket::DCT_RTP;
- test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleRejectVideo) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- cricket::CallOptions options = AudioCallOptions();
- options.data_channel_type = cricket::DCT_RTP;
- test->TestRejectOffer(kJingleVideoInitiateWithRtpData, options, elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleRejectData) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestRejectOffer(
- kJingleVideoInitiateWithRtpData, VideoCallOptions(), elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleRejectVideoAndData) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestRejectOffer(
- kJingleVideoInitiateWithRtpData, AudioCallOptions(), elem.use());
-}
-
-TEST_F(MediaSessionTest, JingleGoodInitiateAllSupportedAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestGoodIncomingInitiate(
- kJingleInitiate, AudioCallOptions(), elem.use());
- test->TestHasAllSupportedAudioCodecs(elem.get());
-}
-
-// Changes the codecs that our FakeMediaEngine will support with a different
-// preference order than the incoming offer.
-// Verifies the answer accepts the preference order of the remote peer.
-TEST_F(MediaSessionTest, JingleGoodInitiateDifferentPreferenceAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->fme()->SetAudioCodecs(MAKE_VECTOR(kAudioCodecsDifferentPreference));
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestGoodIncomingInitiate(
- kJingleInitiate, AudioCallOptions(), elem.use());
- test->TestHasAllSupportedAudioCodecs(elem.get());
-}
-
-TEST_F(MediaSessionTest, JingleGoodInitiateSomeUnsupportedAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestGoodIncomingInitiate(
- kJingleInitiateSomeUnsupported, AudioCallOptions(), elem.use());
- test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get());
-}
-
-TEST_F(MediaSessionTest, JingleGoodInitiateDynamicAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestGoodIncomingInitiate(
- kJingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use());
- test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get());
-}
-
-TEST_F(MediaSessionTest, JingleGoodInitiateStaticAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestGoodIncomingInitiate(
- kJingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use());
- test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get());
-}
-
-TEST_F(MediaSessionTest, JingleBadInitiateNoAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestBadIncomingInitiate(kJingleInitiateNoAudioCodecs);
-}
-
-TEST_F(MediaSessionTest, JingleBadInitiateNoSupportedAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestBadIncomingInitiate(kJingleInitiateNoSupportedAudioCodecs);
-}
-
-TEST_F(MediaSessionTest, JingleBadInitiateWrongClockrates) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestBadIncomingInitiate(kJingleInitiateWrongClockrates);
-}
-
-TEST_F(MediaSessionTest, JingleBadInitiateWrongChannels) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestBadIncomingInitiate(kJingleInitiateWrongChannels);
-}
-
-TEST_F(MediaSessionTest, JingleBadInitiateNoPayloadTypes) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestBadIncomingInitiate(kJingleInitiateNoPayloadTypes);
-}
-
-TEST_F(MediaSessionTest, JingleBadInitiateDynamicWithoutNames) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestBadIncomingInitiate(kJingleInitiateDynamicWithoutNames);
-}
-
-TEST_F(MediaSessionTest, JingleGoodOutgoingInitiate) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestGoodOutgoingInitiate(AudioCallOptions());
-}
-
-TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithBandwidth) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- cricket::CallOptions options = VideoCallOptions();
- options.video_bandwidth = 42000;
- test->TestGoodOutgoingInitiate(options);
-}
-
-TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithRtcpMux) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- cricket::CallOptions options = VideoCallOptions();
- options.rtcp_mux_enabled = true;
- test->TestGoodOutgoingInitiate(options);
-}
-
-TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithRtpData) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- cricket::CallOptions options;
- options.data_channel_type = cricket::DCT_RTP;
- test->ExpectCrypto(cricket::SEC_ENABLED);
- test->TestGoodOutgoingInitiate(options);
-}
-
-TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithSctpData) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- cricket::CallOptions options;
- options.data_channel_type = cricket::DCT_SCTP;
- test->TestGoodOutgoingInitiate(options);
-}
-
-// Crypto related tests.
-
-// Offer has crypto but the session is not secured, just ignore it.
-TEST_F(MediaSessionTest, JingleInitiateWithCryptoIsIgnoredWhenNotSecured) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestGoodIncomingInitiate(
- AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
- VideoCallOptions(),
- elem.use());
-}
-
-// Offer has crypto required but the session is not secure, fail.
-TEST_F(MediaSessionTest, JingleInitiateWithCryptoRequiredWhenNotSecured) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestBadIncomingInitiate(AddEncryption(kJingleVideoInitiate,
- kJingleRequiredCryptoOffer));
-}
-
-// Offer has no crypto but the session is secure required, fail.
-TEST_F(MediaSessionTest, JingleInitiateWithNoCryptoFailsWhenSecureRequired) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->ExpectCrypto(cricket::SEC_REQUIRED);
- test->TestBadIncomingInitiate(kJingleInitiate);
-}
-
-// Offer has crypto and session is secure, expect crypto in the answer.
-TEST_F(MediaSessionTest, JingleInitiateWithCryptoWhenSecureEnabled) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->ExpectCrypto(cricket::SEC_ENABLED);
- test->TestGoodIncomingInitiate(
- AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
- VideoCallOptions(),
- elem.use());
-}
-
-// Offer has crypto and session is secure required, expect crypto in
-// the answer.
-TEST_F(MediaSessionTest, JingleInitiateWithCryptoWhenSecureRequired) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->ExpectCrypto(cricket::SEC_REQUIRED);
- test->TestGoodIncomingInitiate(
- AddEncryption(kJingleVideoInitiate, kJingleCryptoOffer),
- VideoCallOptions(),
- elem.use());
-}
-
-// Offer has unsupported crypto and session is secure, no crypto in
-// the answer.
-TEST_F(MediaSessionTest, JingleInitiateWithUnsupportedCrypto) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->MakeSignalingSecure(cricket::SEC_ENABLED);
- test->TestGoodIncomingInitiate(
- AddEncryption(kJingleInitiate, kJingleUnsupportedCryptoOffer),
- VideoCallOptions(),
- elem.use());
-}
-
-// Offer has unsupported REQUIRED crypto and session is not secure, fail.
-TEST_F(MediaSessionTest, JingleInitiateWithRequiredUnsupportedCrypto) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestBadIncomingInitiate(
- AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
-}
-
-// Offer has unsupported REQUIRED crypto and session is secure, fail.
-TEST_F(MediaSessionTest,
- JingleInitiateWithRequiredUnsupportedCryptoWhenSecure) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->MakeSignalingSecure(cricket::SEC_ENABLED);
- test->TestBadIncomingInitiate(
- AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
-}
-
-// Offer has unsupported REQUIRED crypto and session is required secure, fail.
-TEST_F(MediaSessionTest,
- JingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->MakeSignalingSecure(cricket::SEC_REQUIRED);
- test->TestBadIncomingInitiate(
- AddEncryption(kJingleInitiate, kJingleRequiredUnsupportedCryptoOffer));
-}
-
-TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithCrypto) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->ExpectCrypto(cricket::SEC_ENABLED);
- test->TestGoodOutgoingInitiate(AudioCallOptions());
-}
-
-TEST_F(MediaSessionTest, JingleGoodOutgoingInitiateWithCryptoRequired) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->ExpectCrypto(cricket::SEC_REQUIRED);
- test->TestGoodOutgoingInitiate(AudioCallOptions());
-}
-
-TEST_F(MediaSessionTest, JingleIncomingAcceptWithSsrcs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- cricket::CallOptions options = VideoCallOptions();
- options.is_muc = true;
- test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSsrcs, options);
-}
-
-TEST_F(MediaSessionTest, JingleIncomingAcceptWithRtpDataSsrcs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- cricket::CallOptions options = VideoCallOptions();
- options.is_muc = true;
- options.data_channel_type = cricket::DCT_RTP;
- test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithRtpDataSsrcs, options);
-}
-
-TEST_F(MediaSessionTest, JingleIncomingAcceptWithSctpData) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- cricket::CallOptions options = VideoCallOptions();
- options.is_muc = true;
- options.data_channel_type = cricket::DCT_SCTP;
- test->TestIncomingAcceptWithSsrcs(kJingleAcceptWithSctpData, options);
-}
-
-TEST_F(MediaSessionTest, JingleStreamsUpdateAndView) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestStreamsUpdateAndViewRequests();
-}
-
-TEST_F(MediaSessionTest, JingleSendVideoStreamUpdate) {
- rtc::scoped_ptr<MediaSessionClientTest> test(JingleTest());
- test->TestSendVideoStreamUpdate();
-}
-
-// Gingle tests
-
-TEST_F(MediaSessionTest, GingleGoodVideoInitiate) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestGoodIncomingInitiate(
- kGingleVideoInitiate, VideoCallOptions(), elem.use());
- test->TestCodecsOfVideoInitiate(elem.get());
-}
-
-TEST_F(MediaSessionTest, GingleGoodVideoInitiateWithBandwidth) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->ExpectVideoBandwidth(42000);
- test->TestGoodIncomingInitiate(
- kGingleVideoInitiateWithBandwidth, VideoCallOptions(), elem.use());
-}
-
-TEST_F(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecs) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestGoodIncomingInitiate(
- kGingleInitiate, AudioCallOptions(), elem.use());
- test->TestHasAllSupportedAudioCodecs(elem.get());
-}
-
-TEST_F(MediaSessionTest, GingleGoodInitiateAllSupportedAudioCodecsWithCrypto) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->ExpectCrypto(cricket::SEC_ENABLED);
- test->TestGoodIncomingInitiate(
- AddEncryption(kGingleInitiate, kGingleCryptoOffer),
- AudioCallOptions(),
- elem.use());
- test->TestHasAllSupportedAudioCodecs(elem.get());
-}
-
-// Changes the codecs that our FakeMediaEngine will support with a different
-// preference order than the incoming offer.
-// Verifies the answer accepts the preference order of the remote peer.
-TEST_F(MediaSessionTest, GingleGoodInitiateDifferentPreferenceAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->fme()->SetAudioCodecs(MAKE_VECTOR(kAudioCodecsDifferentPreference));
- rtc::scoped_ptr<buzz::XmlElement> elem;
- test->TestGoodIncomingInitiate(
- kGingleInitiate, AudioCallOptions(), elem.use());
- test->TestHasAllSupportedAudioCodecs(elem.get());
-}
-
-TEST_F(MediaSessionTest, GingleGoodInitiateSomeUnsupportedAudioCodecs) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestGoodIncomingInitiate(
- kGingleInitiateSomeUnsupported, AudioCallOptions(), elem.use());
- test->TestHasAudioCodecsFromInitiateSomeUnsupported(elem.get());
-}
-
-TEST_F(MediaSessionTest, GingleGoodInitiateDynamicAudioCodecs) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestGoodIncomingInitiate(
- kGingleInitiateDynamicAudioCodecs, AudioCallOptions(), elem.use());
- test->TestHasAudioCodecsFromInitiateDynamicAudioCodecs(elem.get());
-}
-
-TEST_F(MediaSessionTest, GingleGoodInitiateStaticAudioCodecs) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestGoodIncomingInitiate(
- kGingleInitiateStaticAudioCodecs, AudioCallOptions(), elem.use());
- test->TestHasAudioCodecsFromInitiateStaticAudioCodecs(elem.get());
-}
-
-TEST_F(MediaSessionTest, GingleGoodInitiateNoAudioCodecs) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestGoodIncomingInitiate(
- kGingleInitiateNoAudioCodecs, AudioCallOptions(), elem.use());
- test->TestHasDefaultAudioCodecs(elem.get());
-}
-
-TEST_F(MediaSessionTest, GingleBadInitiateNoSupportedAudioCodecs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestBadIncomingInitiate(kGingleInitiateNoSupportedAudioCodecs);
-}
-
-TEST_F(MediaSessionTest, GingleBadInitiateWrongClockrates) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestBadIncomingInitiate(kGingleInitiateWrongClockrates);
-}
-
-TEST_F(MediaSessionTest, GingleBadInitiateWrongChannels) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestBadIncomingInitiate(kGingleInitiateWrongChannels);
-}
-
-TEST_F(MediaSessionTest, GingleBadInitiateNoPayloadTypes) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestBadIncomingInitiate(kGingleInitiateNoPayloadTypes);
-}
-
-TEST_F(MediaSessionTest, GingleBadInitiateDynamicWithoutNames) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestBadIncomingInitiate(kGingleInitiateDynamicWithoutNames);
-}
-
-TEST_F(MediaSessionTest, GingleGoodOutgoingInitiate) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestGoodOutgoingInitiate(AudioCallOptions());
-}
-
-TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithBandwidth) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- cricket::CallOptions options = VideoCallOptions();
- options.video_bandwidth = 42000;
- test->TestGoodOutgoingInitiate(options);
-}
-
-// Crypto related tests.
-
-// Offer has crypto but the session is not secured, just ignore it.
-TEST_F(MediaSessionTest, GingleInitiateWithCryptoIsIgnoredWhenNotSecured) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestGoodIncomingInitiate(
- AddEncryption(kGingleInitiate, kGingleCryptoOffer),
- VideoCallOptions(),
- elem.use());
-}
-
-// Offer has crypto required but the session is not secure, fail.
-TEST_F(MediaSessionTest, GingleInitiateWithCryptoRequiredWhenNotSecured) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestBadIncomingInitiate(AddEncryption(kGingleInitiate,
- kGingleRequiredCryptoOffer));
-}
-
-// Offer has no crypto but the session is secure required, fail.
-TEST_F(MediaSessionTest, GingleInitiateWithNoCryptoFailsWhenSecureRequired) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->ExpectCrypto(cricket::SEC_REQUIRED);
- test->TestBadIncomingInitiate(kGingleInitiate);
-}
-
-// Offer has crypto and session is secure, expect crypto in the answer.
-TEST_F(MediaSessionTest, GingleInitiateWithCryptoWhenSecureEnabled) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->ExpectCrypto(cricket::SEC_ENABLED);
- test->TestGoodIncomingInitiate(
- AddEncryption(kGingleInitiate, kGingleCryptoOffer),
- VideoCallOptions(),
- elem.use());
-}
-
-// Offer has crypto and session is secure required, expect crypto in
-// the answer.
-TEST_F(MediaSessionTest, GingleInitiateWithCryptoWhenSecureRequired) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->ExpectCrypto(cricket::SEC_REQUIRED);
- test->TestGoodIncomingInitiate(
- AddEncryption(kGingleInitiate, kGingleCryptoOffer),
- VideoCallOptions(),
- elem.use());
-}
-
-// Offer has unsupported crypto and session is secure, no crypto in
-// the answer.
-TEST_F(MediaSessionTest, GingleInitiateWithUnsupportedCrypto) {
- rtc::scoped_ptr<buzz::XmlElement> elem;
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->MakeSignalingSecure(cricket::SEC_ENABLED);
- test->TestGoodIncomingInitiate(
- AddEncryption(kGingleInitiate, kGingleUnsupportedCryptoOffer),
- VideoCallOptions(),
- elem.use());
-}
-
-// Offer has unsupported REQUIRED crypto and session is not secure, fail.
-TEST_F(MediaSessionTest, GingleInitiateWithRequiredUnsupportedCrypto) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->TestBadIncomingInitiate(
- AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
-}
-
-// Offer has unsupported REQUIRED crypto and session is secure, fail.
-TEST_F(MediaSessionTest,
- GingleInitiateWithRequiredUnsupportedCryptoWhenSecure) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->MakeSignalingSecure(cricket::SEC_ENABLED);
- test->TestBadIncomingInitiate(
- AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
-}
-
-// Offer has unsupported REQUIRED crypto and session is required secure, fail.
-TEST_F(MediaSessionTest,
- GingleInitiateWithRequiredUnsupportedCryptoWhenSecureRequired) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->MakeSignalingSecure(cricket::SEC_REQUIRED);
- test->TestBadIncomingInitiate(
- AddEncryption(kGingleInitiate, kGingleRequiredUnsupportedCryptoOffer));
-}
-
-TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithCrypto) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->ExpectCrypto(cricket::SEC_ENABLED);
- test->TestGoodOutgoingInitiate(AudioCallOptions());
-}
-
-TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithCryptoRequired) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- test->ExpectCrypto(cricket::SEC_REQUIRED);
- test->TestGoodOutgoingInitiate(AudioCallOptions());
-}
-
-TEST_F(MediaSessionTest, GingleIncomingAcceptWithSsrcs) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- cricket::CallOptions options = VideoCallOptions();
- options.is_muc = true;
- test->TestIncomingAcceptWithSsrcs(kGingleAcceptWithSsrcs, options);
-}
-
-TEST_F(MediaSessionTest, GingleGoodOutgoingInitiateWithRtpData) {
- rtc::scoped_ptr<MediaSessionClientTest> test(GingleTest());
- cricket::CallOptions options;
- options.data_channel_type = cricket::DCT_RTP;
- test->ExpectCrypto(cricket::SEC_ENABLED);
- test->TestGoodOutgoingInitiate(options);
-}