10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/* 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004 Google Inc. 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer. 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * and/or other materials provided with the distribution. 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * derived from this software without specific prior written permission. 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */ 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string> 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/session/media/mediasessionclient.h" 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/capturemanager.h" 33cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/cryptoparams.h" 34391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org#include "talk/media/sctp/sctpdataengine.h" 350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/constants.h" 360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/parsing.h" 370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/session/media/mediamessages.h" 380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/session/media/srtpfilter.h" 3913b2d035e2e7f2f18e3a4d3377bc1a09f43a4ff9buildbot@webrtc.org#include "webrtc/libjingle/xmllite/qname.h" 4013b2d035e2e7f2f18e3a4d3377bc1a09f43a4ff9buildbot@webrtc.org#include "webrtc/libjingle/xmllite/xmlconstants.h" 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/constants.h" 42cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/helpers.h" 43cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/logging.h" 44cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/stringencode.h" 45cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/stringutils.h" 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket { 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(DISABLE_MEDIA_ENGINE_FACTORY) 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgMediaSessionClient::MediaSessionClient( 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::Jid& jid, SessionManager *manager) 520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : jid_(jid), 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session_manager_(manager), 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org focus_call_(NULL), 550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_manager_(new ChannelManager(session_manager_->worker_thread())), 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desc_factory_(channel_manager_, 577162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org session_manager_->transport_desc_factory()), 587162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org multisession_enabled_(false) { 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Construct(); 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgMediaSessionClient::MediaSessionClient( 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::Jid& jid, SessionManager *manager, 650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaEngineInterface* media_engine, 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DataEngineInterface* data_media_engine, 670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DeviceManagerInterface* device_manager) 680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : jid_(jid), 690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session_manager_(manager), 700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org focus_call_(NULL), 710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_manager_(new ChannelManager( 720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org media_engine, data_media_engine, 730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org device_manager, new CaptureManager(), 740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session_manager_->worker_thread())), 750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desc_factory_(channel_manager_, 767162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org session_manager_->transport_desc_factory()), 777162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org multisession_enabled_(false) { 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Construct(); 790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid MediaSessionClient::Construct() { 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Register ourselves as the handler of audio and video sessions. 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session_manager_->AddClient(NS_JINGLE_RTP, this); 840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Forward device notifications. 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalDevicesChange.repeat(channel_manager_->SignalDevicesChange); 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Bring up the channel manager. 870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // In previous versions of ChannelManager, this was done automatically 880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // in the constructor. 890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_manager_->Init(); 900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgMediaSessionClient::~MediaSessionClient() { 930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Destroy all calls 940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::map<uint32, Call *>::iterator it; 950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (calls_.begin() != calls_.end()) { 960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::map<uint32, Call *>::iterator it = calls_.begin(); 970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DestroyCall((*it).second); 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Delete channel manager. This will wait for the channels to exit 1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delete channel_manager_; 1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Remove ourselves from the client map. 1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session_manager_->RemoveClient(NS_JINGLE_RTP); 1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgCall *MediaSessionClient::CreateCall() { 1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Call *call = new Call(this); 1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org calls_[call->id()] = call; 1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalCallCreate(call); 1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return call; 1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid MediaSessionClient::OnSessionCreate(Session *session, 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool received_initiate) { 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (received_initiate) { 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session->SignalState.connect(this, &MediaSessionClient::OnSessionState); 1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid MediaSessionClient::OnSessionState(BaseSession* base_session, 1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org BaseSession::State state) { 1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // MediaSessionClient can only be used with a Session*, so it's 1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // safe to cast here. 1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Session* session = static_cast<Session*>(base_session); 1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (state == Session::STATE_RECEIVEDINITIATE) { 1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The creation of the call must happen after the session has 1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // processed the initiate message because we need the 1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // remote_description to know what content names to use in the 1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // call. 1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If our accept would have no codecs, then we must reject this call. 1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const SessionDescription* offer = session->remote_description(); 1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const SessionDescription* accept = CreateAnswer(offer, CallOptions()); 1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const ContentInfo* audio_content = GetFirstAudioContent(accept); 1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool audio_rejected = (!audio_content) ? true : audio_content->rejected; 1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const AudioContentDescription* audio_desc = (!audio_content) ? NULL : 1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<const AudioContentDescription*>(audio_content->description); 1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // For some reason, we need a call even if we reject. So, either find a 1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // matching call or create a new one. 1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The matching of existing calls is used to support the multi-session mode 1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // required for p2p handoffs: ie. once a MUC call is established, a new 1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // session may be established for the same call but is direct between the 1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // clients. To indicate that this is the case, the initiator of the incoming 1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // session is set to be the same as the remote name of the MUC for the 1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // existing session, thus the client can know that this is a new session for 1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the existing call, rather than a whole new call. 1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Call* call = NULL; 1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (multisession_enabled_) { 1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org call = FindCallByRemoteName(session->initiator_name()); 1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (call == NULL) { 1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Could not find a matching call, so create a new one. 1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org call = CreateCall(); 1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session_map_[session->id()] = call; 1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org call->IncomingSession(session, offer); 1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (audio_rejected || !audio_desc || audio_desc->codecs().size() == 0) { 1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session->Reject(STR_TERMINATE_INCOMPATIBLE_PARAMETERS); 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delete accept; 1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid MediaSessionClient::DestroyCall(Call *call) { 1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Change focus away, signal destruction 1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (call == focus_call_) 1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetFocus(NULL); 1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalCallDestroy(call); 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Remove it from calls_ map and delete 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::map<uint32, Call *>::iterator it = calls_.find(call->id()); 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (it != calls_.end()) 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org calls_.erase(it); 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delete call; 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid MediaSessionClient::OnSessionDestroy(Session *session) { 1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Find the call this session is in, remove it 1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SessionMap::iterator it = session_map_.find(session->id()); 1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(it != session_map_.end()); 1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (it != session_map_.end()) { 1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Call *call = (*it).second; 1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session_map_.erase(it); 1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org call->RemoveSession(session); 1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgCall *MediaSessionClient::GetFocus() { 1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return focus_call_; 1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid MediaSessionClient::SetFocus(Call *call) { 2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Call *old_focus_call = focus_call_; 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (focus_call_ != call) { 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (focus_call_ != NULL) 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org focus_call_->EnableChannels(false); 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org focus_call_ = call; 2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (focus_call_ != NULL) 2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org focus_call_->EnableChannels(true); 2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalFocus(focus_call_, old_focus_call); 2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid MediaSessionClient::JoinCalls(Call *call_to_join, Call *call) { 2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Move all sessions from call to call_to_join, delete call. 2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If call_to_join has focus, added sessions should have enabled channels. 2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (focus_call_ == call) 2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetFocus(NULL); 2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org call_to_join->Join(call, focus_call_ == call_to_join); 2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DestroyCall(call); 2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSession *MediaSessionClient::CreateSession(Call *call) { 224f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org std::string id; 225f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org return CreateSession(id, call); 226f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org} 227f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org 228f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgSession *MediaSessionClient::CreateSession(const std::string& id, Call* call) { 2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& type = NS_JINGLE_RTP; 230f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org Session *session = session_manager_->CreateSession(id, jid().Str(), type); 2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org session_map_[session->id()] = call; 2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return session; 2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgCall *MediaSessionClient::FindCallByRemoteName(const std::string &remote_name) { 2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SessionMap::const_iterator call; 2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (call = session_map_.begin(); call != session_map_.end(); ++call) { 2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<Session *> sessions = call->second->sessions(); 2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<Session *>::const_iterator session; 2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (session = sessions.begin(); session != sessions.end(); ++session) { 2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (remote_name == (*session)->remote_name()) { 2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return call->second; 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return NULL; 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TODO(pthatcher): Move all of the parsing and writing functions into 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// mediamessages.cc, with unit tests. 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleAudioCodec(const buzz::XmlElement* element, AudioCodec* out) { 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int id = GetXmlAttr(element, QN_ID, -1); 2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (id < 0) 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string name = GetXmlAttr(element, QN_NAME, buzz::STR_EMPTY); 2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int clockrate = GetXmlAttr(element, QN_CLOCKRATE, 0); 2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int bitrate = GetXmlAttr(element, QN_BITRATE, 0); 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channels = GetXmlAttr(element, QN_CHANNELS, 1); 2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *out = AudioCodec(id, name, clockrate, bitrate, channels, 0); 2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleVideoCodec(const buzz::XmlElement* element, VideoCodec* out) { 2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int id = GetXmlAttr(element, QN_ID, -1); 2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (id < 0) 2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string name = GetXmlAttr(element, QN_NAME, buzz::STR_EMPTY); 2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int width = GetXmlAttr(element, QN_WIDTH, 0); 2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int height = GetXmlAttr(element, QN_HEIGHT, 0); 2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int framerate = GetXmlAttr(element, QN_FRAMERATE, 0); 2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *out = VideoCodec(id, name, width, height, framerate, 0); 2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Parses an ssrc string as a legacy stream. If it fails, returns 2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// false and fills an error message. 2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseSsrcAsLegacyStream(const std::string& ssrc_str, 2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<StreamParams>* streams, 2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ssrc_str.empty()) { 2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 ssrc; 2862a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org if (!rtc::FromString(ssrc_str, &ssrc)) { 2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadParse("Missing or invalid ssrc.", error); 2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org streams->push_back(StreamParams::CreateLegacy(ssrc)); 2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid ParseGingleSsrc(const buzz::XmlElement* parent_elem, 2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::QName& name, 2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaContentDescription* media) { 2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::XmlElement* ssrc_elem = parent_elem->FirstNamed(name); 2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ssrc_elem) { 3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError error; 3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseSsrcAsLegacyStream( 3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ssrc_elem->BodyText(), &(media->mutable_streams()), &error); 3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseCryptoParams(const buzz::XmlElement* element, 3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CryptoParams* out, 3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!element->HasAttr(QN_CRYPTO_SUITE)) { 3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadParse("crypto: crypto-suite attribute missing ", error); 3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (!element->HasAttr(QN_CRYPTO_KEY_PARAMS)) { 3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadParse("crypto: key-params attribute missing ", error); 3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (!element->HasAttr(QN_CRYPTO_TAG)) { 3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadParse("crypto: tag attribute missing ", error); 3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& crypto_suite = element->Attr(QN_CRYPTO_SUITE); 3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& key_params = element->Attr(QN_CRYPTO_KEY_PARAMS); 3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const int tag = GetXmlAttr(element, QN_CRYPTO_TAG, 0); 3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& session_params = 3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org element->Attr(QN_CRYPTO_SESSION_PARAMS); // Optional. 3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *out = CryptoParams(tag, crypto_suite, key_params, session_params); 3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Parse the first encryption element found with a matching 'usage' 3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// element. 3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// <usage/> is specific to Gingle. In Jingle, <crypto/> is already 3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// scoped to a content. 3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Return false if there was an encryption element and it could not be 3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// parsed. 3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleEncryption(const buzz::XmlElement* desc, 3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::QName& usage, 3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaContentDescription* media, 3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* encryption = desc->FirstNamed(QN_ENCRYPTION); 3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org encryption != NULL; 3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org encryption = encryption->NextNamed(QN_ENCRYPTION)) { 3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (encryption->FirstNamed(usage) != NULL) { 342ac5a3e5f1e59174797dc60641cba617c1bf0c279henrike@webrtc.org if (GetXmlAttr(encryption, QN_ENCRYPTION_REQUIRED, false)) { 343ac5a3e5f1e59174797dc60641cba617c1bf0c279henrike@webrtc.org media->set_crypto_required(CT_SDES); 344ac5a3e5f1e59174797dc60641cba617c1bf0c279henrike@webrtc.org } 3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* crypto = encryption->FirstNamed(QN_CRYPTO); 3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto != NULL; 3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto = crypto->NextNamed(QN_CRYPTO)) { 3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CryptoParams params; 3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseCryptoParams(crypto, ¶ms, error)) { 3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org media->AddCrypto(params); 3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid ParseBandwidth(const buzz::XmlElement* parent_elem, 3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaContentDescription* media) { 3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::XmlElement* bw_elem = GetXmlChild(parent_elem, LN_BANDWIDTH); 3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int bandwidth_kbps = -1; 3642a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org if (bw_elem && rtc::FromString(bw_elem->BodyText(), &bandwidth_kbps)) { 3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (bandwidth_kbps >= 0) { 3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org media->set_bandwidth(bandwidth_kbps * 1000); 3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleAudioContent(const buzz::XmlElement* content_elem, 3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ContentDescription** content, 3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AudioContentDescription* audio = new AudioContentDescription(); 3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 376daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org int preference = kMaxPayloadId; 3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (content_elem->FirstElement()) { 3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* codec_elem = 3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org content_elem->FirstNamed(QN_GINGLE_AUDIO_PAYLOADTYPE); 3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec_elem != NULL; 3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec_elem = codec_elem->NextNamed(QN_GINGLE_AUDIO_PAYLOADTYPE)) { 3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AudioCodec codec; 3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ParseGingleAudioCodec(codec_elem, &codec)) { 384daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org codec.preference = preference--; 3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org audio->AddCodec(codec); 3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // For backward compatibility, we can assume the other client is 3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // an old version of Talk if it has no audio payload types at all. 3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org audio->AddCodec(AudioCodec(103, "ISAC", 16000, -1, 1, 1)); 3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org audio->AddCodec(AudioCodec(0, "PCMU", 8000, 64000, 1, 0)); 3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseGingleSsrc(content_elem, QN_GINGLE_AUDIO_SRCID, audio); 3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseGingleEncryption(content_elem, QN_GINGLE_AUDIO_CRYPTO_USAGE, 3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org audio, error)) { 3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *content = audio; 4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleVideoContent(const buzz::XmlElement* content_elem, 4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ContentDescription** content, 4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VideoContentDescription* video = new VideoContentDescription(); 4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 411daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org int preference = kMaxPayloadId; 4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* codec_elem = 4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org content_elem->FirstNamed(QN_GINGLE_VIDEO_PAYLOADTYPE); 4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec_elem != NULL; 4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec_elem = codec_elem->NextNamed(QN_GINGLE_VIDEO_PAYLOADTYPE)) { 4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VideoCodec codec; 4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ParseGingleVideoCodec(codec_elem, &codec)) { 418daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org codec.preference = preference--; 4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video->AddCodec(codec); 4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseGingleSsrc(content_elem, QN_GINGLE_VIDEO_SRCID, video); 4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseBandwidth(content_elem, video); 4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseGingleEncryption(content_elem, QN_GINGLE_VIDEO_CRYPTO_USAGE, 4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video, error)) { 4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *content = video; 4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid ParsePayloadTypeParameters(const buzz::XmlElement* element, 4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::map<std::string, std::string>* paramap) { 4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* param = element->FirstNamed(QN_PARAMETER); 4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org param != NULL; param = param->NextNamed(QN_PARAMETER)) { 4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string name = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_NAME, 4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::STR_EMPTY); 4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string value = GetXmlAttr(param, QN_PAYLOADTYPE_PARAMETER_VALUE, 4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::STR_EMPTY); 4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!name.empty() && !value.empty()) { 4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org paramap->insert(make_pair(name, value)); 4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4495aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.orgvoid ParseFeedbackParams(const buzz::XmlElement* element, 4505aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org FeedbackParams* params) { 4515aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org for (const buzz::XmlElement* param = element->FirstNamed(QN_JINGLE_RTCP_FB); 4525aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org param != NULL; param = param->NextNamed(QN_JINGLE_RTCP_FB)) { 4535aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org std::string type = GetXmlAttr(param, QN_TYPE, buzz::STR_EMPTY); 4545aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org std::string subtype = GetXmlAttr(param, QN_SUBTYPE, buzz::STR_EMPTY); 4555aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org if (!type.empty()) { 4565aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org params->Add(FeedbackParam(type, subtype)); 4575aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org } 4585aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org } 4595aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org} 4605aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 4615aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.orgvoid AddFeedbackParams(const FeedbackParams& additional_params, 4625aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org FeedbackParams* params) { 4635aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org for (size_t i = 0; i < additional_params.params().size(); ++i) { 4645aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org params->Add(additional_params.params()[i]); 4655aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org } 4665aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org} 4675aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint FindWithDefault(const std::map<std::string, std::string>& map, 4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& key, const int def) { 4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::map<std::string, std::string>::const_iterator iter = map.find(key); 4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (iter == map.end()) ? def : atoi(iter->second.c_str()); 4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Parse the first encryption element found. 4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Return false if there was an encryption element and it could not be 4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// parsed. 4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleEncryption(const buzz::XmlElement* content_elem, 4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaContentDescription* media, 4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::XmlElement* encryption = 4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org content_elem->FirstNamed(QN_ENCRYPTION); 4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (encryption == NULL) { 4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 487ac5a3e5f1e59174797dc60641cba617c1bf0c279henrike@webrtc.org if (GetXmlAttr(encryption, QN_ENCRYPTION_REQUIRED, false)) { 488ac5a3e5f1e59174797dc60641cba617c1bf0c279henrike@webrtc.org media->set_crypto_required(CT_SDES); 489ac5a3e5f1e59174797dc60641cba617c1bf0c279henrike@webrtc.org } 4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* crypto = encryption->FirstNamed(QN_CRYPTO); 4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto != NULL; 4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto = crypto->NextNamed(QN_CRYPTO)) { 4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CryptoParams params; 4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseCryptoParams(crypto, ¶ms, error)) { 4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org media->AddCrypto(params); 4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleAudioCodec(const buzz::XmlElement* elem, AudioCodec* codec) { 5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int id = GetXmlAttr(elem, QN_ID, -1); 5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (id < 0) 5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY); 5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int clockrate = GetXmlAttr(elem, QN_CLOCKRATE, 0); 5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int channels = GetXmlAttr(elem, QN_CHANNELS, 1); 5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::map<std::string, std::string> paramap; 5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParsePayloadTypeParameters(elem, ¶map); 5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int bitrate = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_BITRATE, 0); 5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *codec = AudioCodec(id, name, clockrate, bitrate, channels, 0); 5175aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org ParseFeedbackParams(elem, &codec->feedback_params); 5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleVideoCodec(const buzz::XmlElement* elem, VideoCodec* codec) { 5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int id = GetXmlAttr(elem, QN_ID, -1); 5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (id < 0) 5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY); 5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::map<std::string, std::string> paramap; 5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParsePayloadTypeParameters(elem, ¶map); 5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int width = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_WIDTH, 0); 5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int height = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_HEIGHT, 0); 5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int framerate = FindWithDefault(paramap, PAYLOADTYPE_PARAMETER_FRAMERATE, 0); 5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *codec = VideoCodec(id, name, width, height, framerate, 0); 5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec->params = paramap; 5365aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org ParseFeedbackParams(elem, &codec->feedback_params); 5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleDataCodec(const buzz::XmlElement* elem, DataCodec* codec) { 5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int id = GetXmlAttr(elem, QN_ID, -1); 5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (id < 0) 5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string name = GetXmlAttr(elem, QN_NAME, buzz::STR_EMPTY); 5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *codec = DataCodec(id, name, 0); 5485aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org ParseFeedbackParams(elem, &codec->feedback_params); 5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleStreamsOrLegacySsrc(const buzz::XmlElement* desc_elem, 5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaContentDescription* media, 5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (HasJingleStreams(desc_elem)) { 5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseJingleStreams(desc_elem, &(media->mutable_streams()), error)) { 5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string ssrc_str = desc_elem->Attr(QN_SSRC); 5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseSsrcAsLegacyStream( 5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ssrc_str, &(media->mutable_streams()), error)) { 5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleAudioContent(const buzz::XmlElement* content_elem, 5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ContentDescription** content, 5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 5722a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<AudioContentDescription> audio( 5737162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org new AudioContentDescription()); 5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5755aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org FeedbackParams content_feedback_params; 5765aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org ParseFeedbackParams(content_elem, &content_feedback_params); 5775aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 578daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org int preference = kMaxPayloadId; 5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* payload_elem = 5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE); 5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org payload_elem != NULL; 5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) { 5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AudioCodec codec; 5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ParseJingleAudioCodec(payload_elem, &codec)) { 5855aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org AddFeedbackParams(content_feedback_params, &codec.feedback_params); 586daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org codec.preference = preference--; 5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org audio->AddCodec(codec); 5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5917162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (!ParseJingleStreamsOrLegacySsrc(content_elem, audio.get(), error)) { 5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5957162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (!ParseJingleEncryption(content_elem, audio.get(), error)) { 5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org audio->set_rtcp_mux(content_elem->FirstNamed(QN_JINGLE_RTCP_MUX) != NULL); 6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org RtpHeaderExtensions hdrexts; 6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseJingleRtpHeaderExtensions(content_elem, &hdrexts, error)) { 6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org audio->set_rtp_header_extensions(hdrexts); 6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6077162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org *content = audio.release(); 6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleVideoContent(const buzz::XmlElement* content_elem, 6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ContentDescription** content, 6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 6142a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<VideoContentDescription> video( 6157162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org new VideoContentDescription()); 6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6175aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org FeedbackParams content_feedback_params; 6185aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org ParseFeedbackParams(content_elem, &content_feedback_params); 6195aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 620daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org int preference = kMaxPayloadId; 6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* payload_elem = 6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE); 6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org payload_elem != NULL; 6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) { 6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VideoCodec codec; 6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ParseJingleVideoCodec(payload_elem, &codec)) { 6275aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org AddFeedbackParams(content_feedback_params, &codec.feedback_params); 628daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org codec.preference = preference--; 6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video->AddCodec(codec); 6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6337162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (!ParseJingleStreamsOrLegacySsrc(content_elem, video.get(), error)) { 6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6367162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org ParseBandwidth(content_elem, video.get()); 6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6387162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org if (!ParseJingleEncryption(content_elem, video.get(), error)) { 6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video->set_rtcp_mux(content_elem->FirstNamed(QN_JINGLE_RTCP_MUX) != NULL); 6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org RtpHeaderExtensions hdrexts; 6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseJingleRtpHeaderExtensions(content_elem, &hdrexts, error)) { 6460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video->set_rtp_header_extensions(hdrexts); 6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6507162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org *content = video.release(); 6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleSctpDataContent(const buzz::XmlElement* content_elem, 6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ContentDescription** content, 6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 6572a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<DataContentDescription> data( 6587162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org new DataContentDescription()); 6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data->set_protocol(kMediaProtocolSctp); 6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* stream_elem = 6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org content_elem->FirstNamed(QN_JINGLE_DRAFT_SCTP_STREAM); 6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream_elem != NULL; 6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream_elem = stream_elem->NextNamed(QN_JINGLE_DRAFT_SCTP_STREAM)) { 6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org StreamParams stream; 6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream.groupid = stream_elem->Attr(QN_NICK); 6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream.id = stream_elem->Attr(QN_NAME); 6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 sid; 6692a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org if (!rtc::FromString(stream_elem->Attr(QN_SID), &sid)) { 6700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadParse("Missing or invalid sid.", error); 6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (sid > kMaxSctpSid) { 6730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadParse("SID is greater than max value.", error); 6740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream.ssrcs.push_back(sid); 6770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data->mutable_streams().push_back(stream); 6780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6807162d28d68ad58802a5a52eca0df59150ee7b9d4henrike@webrtc.org *content = data.release(); 6810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 6820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleRtpDataContent(const buzz::XmlElement* content_elem, 6850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ContentDescription** content, 6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DataContentDescription* data = new DataContentDescription(); 6880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6895aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org FeedbackParams content_feedback_params; 6905aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org ParseFeedbackParams(content_elem, &content_feedback_params); 6915aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 692daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org int preference = kMaxPayloadId; 6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const buzz::XmlElement* payload_elem = 6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org content_elem->FirstNamed(QN_JINGLE_RTP_PAYLOADTYPE); 6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org payload_elem != NULL; 6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org payload_elem = payload_elem->NextNamed(QN_JINGLE_RTP_PAYLOADTYPE)) { 6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DataCodec codec; 6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ParseJingleDataCodec(payload_elem, &codec)) { 6995aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org AddFeedbackParams(content_feedback_params, &codec.feedback_params); 700daf1d14b6fd8a1d962ae9b238172c4bc327f3776wu@webrtc.org codec.preference = preference--; 7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data->AddCodec(codec); 7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseJingleStreamsOrLegacySsrc(content_elem, data, error)) { 7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseBandwidth(content_elem, data); 7090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ParseJingleEncryption(content_elem, data, error)) { 7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data->set_rtcp_mux(content_elem->FirstNamed(QN_JINGLE_RTCP_MUX) != NULL); 7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *content = data; 7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool MediaSessionClient::ParseContent(SignalingProtocol protocol, 7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::XmlElement* content_elem, 7220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ContentDescription** content, 7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ParseError* error) { 7240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (protocol == PROTOCOL_GINGLE) { 7250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& content_type = content_elem->Name().Namespace(); 7260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (NS_GINGLE_AUDIO == content_type) { 7270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ParseGingleAudioContent(content_elem, content, error); 7280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (NS_GINGLE_VIDEO == content_type) { 7290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ParseGingleVideoContent(content_elem, content, error); 7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadParse("Unknown content type: " + content_type, error); 7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& content_type = content_elem->Name().Namespace(); 7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // We use the XMLNS of the <description> element to determine if 7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // it's RTP or SCTP. 7370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (content_type == NS_JINGLE_DRAFT_SCTP) { 7380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ParseJingleSctpDataContent(content_elem, content, error); 7390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string media; 7420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!RequireXmlAttr(content_elem, QN_JINGLE_CONTENT_MEDIA, &media, error)) 7430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 7440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (media == JINGLE_CONTENT_MEDIA_AUDIO) { 7460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ParseJingleAudioContent(content_elem, content, error); 7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (media == JINGLE_CONTENT_MEDIA_VIDEO) { 7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ParseJingleVideoContent(content_elem, content, error); 7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (media == JINGLE_CONTENT_MEDIA_DATA) { 7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ParseJingleRtpDataContent(content_elem, content, error); 7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 7520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadParse("Unknown media: " + media, error); 7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateGingleAudioCodecElem(const AudioCodec& codec) { 7580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* payload_type = 7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_GINGLE_AUDIO_PAYLOADTYPE, true); 7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(payload_type, QN_ID, codec.id); 7610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org payload_type->AddAttr(QN_NAME, codec.name); 7620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec.clockrate > 0) 7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(payload_type, QN_CLOCKRATE, codec.clockrate); 7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec.bitrate > 0) 7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(payload_type, QN_BITRATE, codec.bitrate); 7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec.channels > 1) 7670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(payload_type, QN_CHANNELS, codec.channels); 7680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return payload_type; 7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateGingleVideoCodecElem(const VideoCodec& codec) { 7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* payload_type = 7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_GINGLE_VIDEO_PAYLOADTYPE, true); 7740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(payload_type, QN_ID, codec.id); 7750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org payload_type->AddAttr(QN_NAME, codec.name); 7760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(payload_type, QN_WIDTH, codec.width); 7770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(payload_type, QN_HEIGHT, codec.height); 7780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(payload_type, QN_FRAMERATE, codec.framerate); 7790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return payload_type; 7800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateGingleSsrcElem(const buzz::QName& name, uint32 ssrc) { 7830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = new buzz::XmlElement(name, true); 7840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ssrc) { 7850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetXmlBody(elem, ssrc); 7860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 7880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateBandwidthElem(const buzz::QName& name, int bps) { 7910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int kbps = bps / 1000; 7920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = new buzz::XmlElement(name); 7930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddAttr(buzz::QN_TYPE, "AS"); 7940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetXmlBody(elem, kbps); 7950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 7960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// For Jingle, usage_qname is empty. 7990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleEncryptionElem(const CryptoParamsVec& cryptos, 8000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool required) { 8010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* encryption_elem = new buzz::XmlElement(QN_ENCRYPTION); 8020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (required) { 8040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org encryption_elem->SetAttr(QN_ENCRYPTION_REQUIRED, "true"); 8050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (CryptoParamsVec::const_iterator i = cryptos.begin(); 8080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org i != cryptos.end(); 8090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ++i) { 8100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* crypto_elem = new buzz::XmlElement(QN_CRYPTO); 8110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(crypto_elem, QN_CRYPTO_TAG, i->tag); 8130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto_elem->AddAttr(QN_CRYPTO_SUITE, i->cipher_suite); 8140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto_elem->AddAttr(QN_CRYPTO_KEY_PARAMS, i->key_params); 8150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!i->session_params.empty()) { 8160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto_elem->AddAttr(QN_CRYPTO_SESSION_PARAMS, i->session_params); 8170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org encryption_elem->AddElement(crypto_elem); 8190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return encryption_elem; 8210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 8220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateGingleEncryptionElem(const CryptoParamsVec& cryptos, 8240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const buzz::QName& usage_qname, 8250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool required) { 8260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* encryption_elem = 8270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CreateJingleEncryptionElem(cryptos, required); 8280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (required) { 8300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org encryption_elem->SetAttr(QN_ENCRYPTION_REQUIRED, "true"); 8310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* usage_elem = new buzz::XmlElement(usage_qname); 8340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org encryption_elem->AddElement(usage_elem); 8350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return encryption_elem; 8370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 8380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateGingleAudioContentElem( 8400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const AudioContentDescription* audio, 8410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool crypto_required) { 8420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = 8430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT, true); 8440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (AudioCodecs::const_iterator codec = audio->codecs().begin(); 8460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec != audio->codecs().end(); ++codec) { 8470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateGingleAudioCodecElem(*codec)); 8480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (audio->has_ssrcs()) { 8500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateGingleSsrcElem( 8510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org QN_GINGLE_AUDIO_SRCID, audio->first_ssrc())); 8520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const CryptoParamsVec& cryptos = audio->cryptos(); 8550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!cryptos.empty()) { 8560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateGingleEncryptionElem(cryptos, 8570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org QN_GINGLE_AUDIO_CRYPTO_USAGE, 8580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto_required)); 8590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 8610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 8620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateGingleVideoContentElem( 8640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const VideoContentDescription* video, 8650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool crypto_required) { 8660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = 8670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_GINGLE_VIDEO_CONTENT, true); 8680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (VideoCodecs::const_iterator codec = video->codecs().begin(); 8700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec != video->codecs().end(); ++codec) { 8710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateGingleVideoCodecElem(*codec)); 8720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (video->has_ssrcs()) { 8740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateGingleSsrcElem( 8750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org QN_GINGLE_VIDEO_SRCID, video->first_ssrc())); 8760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (video->bandwidth() != kAutoBandwidth) { 8780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateBandwidthElem(QN_GINGLE_VIDEO_BANDWIDTH, 8790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video->bandwidth())); 8800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const CryptoParamsVec& cryptos = video->cryptos(); 8830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!cryptos.empty()) { 8840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateGingleEncryptionElem(cryptos, 8850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org QN_GINGLE_VIDEO_CRYPTO_USAGE, 8860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org crypto_required)); 8870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 8880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 8900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 8910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgtemplate <class T> 8930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreatePayloadTypeParameterElem( 8940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& name, T value) { 8950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = new buzz::XmlElement(QN_PARAMETER); 8960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 8970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddAttr(QN_PAYLOADTYPE_PARAMETER_NAME, name); 8980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(elem, QN_PAYLOADTYPE_PARAMETER_VALUE, value); 8990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 9010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 9020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9035aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.orgvoid AddRtcpFeedbackElem(buzz::XmlElement* elem, 9045aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org const FeedbackParams& feedback_params) { 9055aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org std::vector<FeedbackParam>::const_iterator it; 9065aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org for (it = feedback_params.params().begin(); 9075aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org it != feedback_params.params().end(); ++it) { 9085aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org buzz::XmlElement* fb_elem = new buzz::XmlElement(QN_JINGLE_RTCP_FB); 9095aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org fb_elem->AddAttr(QN_TYPE, it->id()); 9105aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org fb_elem->AddAttr(QN_SUBTYPE, it->param()); 9115aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org elem->AddElement(fb_elem); 9125aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org } 9135aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org} 9145aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 9150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleAudioCodecElem(const AudioCodec& codec) { 9160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE); 9170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(elem, QN_ID, codec.id); 9190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddAttr(QN_NAME, codec.name); 9200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec.clockrate > 0) { 9210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(elem, QN_CLOCKRATE, codec.clockrate); 9220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec.bitrate > 0) { 9240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreatePayloadTypeParameterElem( 9250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org PAYLOADTYPE_PARAMETER_BITRATE, codec.bitrate)); 9260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (codec.channels > 1) { 9280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(elem, QN_CHANNELS, codec.channels); 9290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9315aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org AddRtcpFeedbackElem(elem, codec.feedback_params); 9325aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 9330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 9340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 9350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleVideoCodecElem(const VideoCodec& codec) { 9370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE); 9380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(elem, QN_ID, codec.id); 9400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddAttr(QN_NAME, codec.name); 9410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreatePayloadTypeParameterElem( 9420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org PAYLOADTYPE_PARAMETER_WIDTH, codec.width)); 9430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreatePayloadTypeParameterElem( 9440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org PAYLOADTYPE_PARAMETER_HEIGHT, codec.height)); 9450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreatePayloadTypeParameterElem( 9460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org PAYLOADTYPE_PARAMETER_FRAMERATE, codec.framerate)); 9475aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 9485aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org AddRtcpFeedbackElem(elem, codec.feedback_params); 9495aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 9500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CodecParameterMap::const_iterator param_iter; 9510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (param_iter = codec.params.begin(); param_iter != codec.params.end(); 9520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ++param_iter) { 9530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreatePayloadTypeParameterElem(param_iter->first, 9540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org param_iter->second)); 9550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 9580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 9590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleDataCodecElem(const DataCodec& codec) { 9610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = new buzz::XmlElement(QN_JINGLE_RTP_PAYLOADTYPE); 9620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(elem, QN_ID, codec.id); 9640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddAttr(QN_NAME, codec.name); 9650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9665aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org AddRtcpFeedbackElem(elem, codec.feedback_params); 9675aed3bb9fb287faecd773b88bb68732c31579590wu@webrtc.org 9680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 9690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 9700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WriteLegacyJingleSsrc(const MediaContentDescription* media, 9720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem) { 9730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (media->has_ssrcs()) { 9740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(elem, QN_SSRC, media->first_ssrc()); 9750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 9770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WriteJingleStreamsOrLegacySsrc(const MediaContentDescription* media, 9790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* desc_elem) { 9800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!media->multistream()) { 9810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WriteLegacyJingleSsrc(media, desc_elem); 9820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 9830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WriteJingleStreams(media->streams(), desc_elem); 9840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 9860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleAudioContentElem( 9880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const AudioContentDescription* audio, bool crypto_required) { 9890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = 9900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true); 9910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_AUDIO); 9930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WriteJingleStreamsOrLegacySsrc(audio, elem); 9940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (AudioCodecs::const_iterator codec = audio->codecs().begin(); 9960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec != audio->codecs().end(); ++codec) { 9970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateJingleAudioCodecElem(*codec)); 9980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 9990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const CryptoParamsVec& cryptos = audio->cryptos(); 10010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!cryptos.empty()) { 10020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required)); 10030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (audio->rtcp_mux()) { 10060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(new buzz::XmlElement(QN_JINGLE_RTCP_MUX)); 10070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WriteJingleRtpHeaderExtensions(audio->rtp_header_extensions(), elem); 10100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 10120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 10130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleVideoContentElem( 10150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const VideoContentDescription* video, bool crypto_required) { 10160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = 10170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true); 10180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_VIDEO); 10200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WriteJingleStreamsOrLegacySsrc(video, elem); 10210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (VideoCodecs::const_iterator codec = video->codecs().begin(); 10230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec != video->codecs().end(); ++codec) { 10240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateJingleVideoCodecElem(*codec)); 10250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const CryptoParamsVec& cryptos = video->cryptos(); 10280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!cryptos.empty()) { 10290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required)); 10300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (video->rtcp_mux()) { 10330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(new buzz::XmlElement(QN_JINGLE_RTCP_MUX)); 10340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (video->bandwidth() != kAutoBandwidth) { 10370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateBandwidthElem(QN_JINGLE_RTP_BANDWIDTH, 10380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video->bandwidth())); 10390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WriteJingleRtpHeaderExtensions(video->rtp_header_extensions(), elem); 10420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 10440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 10450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleSctpDataContentElem( 10470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const DataContentDescription* data) { 10480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* content_elem = 10490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_JINGLE_DRAFT_SCTP_CONTENT, true); 10500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::vector<StreamParams>::const_iterator 10510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream = data->streams().begin(); 10520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream != data->streams().end(); ++stream) { 10530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* stream_elem = 10540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_JINGLE_DRAFT_SCTP_STREAM, false); 10550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttrIfNonEmpty(stream_elem, QN_NICK, stream->groupid); 10560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttrIfNonEmpty(stream_elem, QN_NAME, stream->id); 10570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!stream->ssrcs.empty()) { 10580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddXmlAttr(stream_elem, QN_SID, stream->ssrcs[0]); 10590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org content_elem->AddElement(stream_elem); 10610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return content_elem;; 10630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 10640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleRtpDataContentElem( 10660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const DataContentDescription* data, bool crypto_required) { 10670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement* elem = 10690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org new buzz::XmlElement(QN_JINGLE_RTP_CONTENT, true); 10700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->SetAttr(QN_JINGLE_CONTENT_MEDIA, JINGLE_CONTENT_MEDIA_DATA); 10720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WriteJingleStreamsOrLegacySsrc(data, elem); 10730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (DataCodecs::const_iterator codec = data->codecs().begin(); 10750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org codec != data->codecs().end(); ++codec) { 10760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateJingleDataCodecElem(*codec)); 10770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const CryptoParamsVec& cryptos = data->cryptos(); 10800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!cryptos.empty()) { 10810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateJingleEncryptionElem(cryptos, crypto_required)); 10820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (data->rtcp_mux()) { 10850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(new buzz::XmlElement(QN_JINGLE_RTCP_MUX)); 10860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (data->bandwidth() != kAutoBandwidth) { 10890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elem->AddElement(CreateBandwidthElem(QN_JINGLE_RTP_BANDWIDTH, 10900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data->bandwidth())); 10910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 10920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return elem; 10940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 10950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 10960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool IsSctp(const DataContentDescription* data) { 10970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (data->protocol() == kMediaProtocolSctp || 10980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data->protocol() == kMediaProtocolDtlsSctp); 10990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* CreateJingleDataContentElem( 11020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const DataContentDescription* data, bool crypto_required) { 11030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (IsSctp(data)) { 11040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return CreateJingleSctpDataContentElem(data); 11050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 11060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return CreateJingleRtpDataContentElem(data, crypto_required); 11070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool MediaSessionClient::IsWritable(SignalingProtocol protocol, 11110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const ContentDescription* content) { 11120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const MediaContentDescription* media = 11130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<const MediaContentDescription*>(content); 11140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (protocol == PROTOCOL_GINGLE && 11150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org media->type() == MEDIA_TYPE_DATA) { 11160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 11170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 11190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool MediaSessionClient::WriteContent(SignalingProtocol protocol, 11220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const ContentDescription* content, 11230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org buzz::XmlElement** elem, 11240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WriteError* error) { 11250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const MediaContentDescription* media = 11260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<const MediaContentDescription*>(content); 11270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool crypto_required = secure() == SEC_REQUIRED; 11280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (media->type() == MEDIA_TYPE_AUDIO) { 11300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const AudioContentDescription* audio = 11310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<const AudioContentDescription*>(media); 11320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (protocol == PROTOCOL_GINGLE) { 11330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *elem = CreateGingleAudioContentElem(audio, crypto_required); 11340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 11350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *elem = CreateJingleAudioContentElem(audio, crypto_required); 11360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (media->type() == MEDIA_TYPE_VIDEO) { 11380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const VideoContentDescription* video = 11390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<const VideoContentDescription*>(media); 11400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (protocol == PROTOCOL_GINGLE) { 11410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *elem = CreateGingleVideoContentElem(video, crypto_required); 11420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 11430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *elem = CreateJingleVideoContentElem(video, crypto_required); 11440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (media->type() == MEDIA_TYPE_DATA) { 11460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const DataContentDescription* data = 11470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<const DataContentDescription*>(media); 11480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (protocol == PROTOCOL_GINGLE) { 11490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadWrite("Data channel not supported with Gingle.", error); 11500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 11510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *elem = CreateJingleDataContentElem(data, crypto_required); 11520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 11540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return BadWrite("Unknown content type: " + 11552a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::ToString<int>(media->type()), error); 11560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 11590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 11600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 11610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace cricket 1162