/** Hook called when an SDP offer is required */ bool AmSession::getSdpOffer(AmSdp& offer) { DBG("AmSession::getSdpOffer(...) ...\n"); offer.version = 0; offer.origin.user = "******"; //offer.origin.sessId = 1; //offer.origin.sessV = 1; offer.sessionName = "sems"; offer.conn.network = NT_IN; offer.conn.addrType = AT_V4; offer.conn.address = advertisedIP(); // TODO: support mutiple media types (needs multiples RTP streams) // TODO: support update instead of clearing everything if(RTPStream()->getSdpMediaIndex() < 0) offer.media.clear(); unsigned int media_idx = 0; if(!offer.media.size()) { offer.media.push_back(SdpMedia()); offer.media.back().type=MT_AUDIO; } else { media_idx = RTPStream()->getSdpMediaIndex(); } RTPStream()->setLocalIP(localMediaIP()); RTPStream()->getSdpOffer(media_idx,offer.media.back()); return true; }
void AmSession::setOnHold(bool hold) { lockAudio(); bool old_hold = RTPStream()->getOnHold(); RTPStream()->setOnHold(hold); if (hold != old_hold) sendReinvite(); unlockAudio(); }
string AmSession::sid4dbg() { string dbg; dbg = dlg->getCallid() + "/" + dlg->getLocalTag() + "/" + dlg->getRemoteTag() + "/" + int2str(RTPStream()->getLocalPort()) + "/" + RTPStream()->getRHost() + ":" + int2str(RTPStream()->getRPort()); return dbg; }
CallBackDialog::CallBackDialog(AmPromptCollection& prompts, UACAuthCred* cred) : play_list(this), prompts(prompts), cred(cred), state(CBNone) { // set configured playout type RTPStream()->setPlayoutType(CallBackFactory::m_PlayoutType); }
CallBackCalleeDialog::CallBackCalleeDialog(const string& other_tag, AmSessionAudioConnector* connector, UACAuthCred* cred) : AmB2ABCalleeSession(other_tag, connector), cred(cred) { // set configured playout type RTPStream()->setPlayoutType(CallBackFactory::m_PlayoutType); setDtmfDetectionEnabled(false); }
int AmSession::onSdpCompleted(const AmSdp& local_sdp, const AmSdp& remote_sdp) { DBG("AmSession::onSdpCompleted(...) ...\n"); if(local_sdp.media.empty() || remote_sdp.media.empty()) { ERROR("Invalid SDP"); string debug_str; local_sdp.print(debug_str); ERROR("Local SDP:\n%s", debug_str.empty() ? "<empty>" : debug_str.c_str()); remote_sdp.print(debug_str); ERROR("Remote SDP:\n%s", debug_str.empty() ? "<empty>" : debug_str.c_str()); return -1; } bool set_on_hold = false; if (!remote_sdp.media.empty()) { vector<SdpAttribute>::const_iterator pos = std::find(remote_sdp.media[0].attributes.begin(), remote_sdp.media[0].attributes.end(), SdpAttribute("sendonly")); set_on_hold = pos != remote_sdp.media[0].attributes.end(); } lockAudio(); // TODO: // - get the right media ID // - check if the stream coresponding to the media ID // should be created or updated // int ret = 0; try { ret = RTPStream()->init(local_sdp, remote_sdp, AmConfig::ForceSymmetricRtp); } catch (const string& s) { ERROR("Error while initializing RTP stream: '%s'\n", s.c_str()); ret = -1; } catch (...) { ERROR("Error while initializing RTP stream (unknown exception in AmRTPStream::init)\n"); ret = -1; } unlockAudio(); if (!isProcessingMedia()) { setInbandDetector(AmConfig::DefaultDTMFDetector); } return ret; }
WebConferenceDialog::WebConferenceDialog(AmPromptCollection& prompts, WebConferenceFactory* my_f, UACAuthCred* cred) : play_list(this), separator(this, 0), prompts(prompts), state(None), factory(my_f), cred(cred), muted(false), connect_ts(-1), disconnect_ts(-1) { is_dialout = (cred != NULL); accept_early_session = is_dialout; // set configured playout type RTPStream()->setPlayoutType(WebConferenceFactory::m_PlayoutType); }
WebConferenceDialog::WebConferenceDialog(AmPromptCollection& prompts, WebConferenceFactory* my_f, const string& room) : play_list(this), separator(this, 0), prompts(prompts), state(None), factory(my_f), muted(false), connect_ts(-1), disconnect_ts(-1) { conf_id = room; DBG("set conf_id to %s\n", conf_id.c_str()); is_dialout = false; // set configured playout type RTPStream()->setPlayoutType(WebConferenceFactory::m_PlayoutType); }
/* 循环产生一个能唯一标识该RTPSession的RTPStream数组中新的RTPStream的随机数(作为SSRC),搭建一个新的RTPStream,放入RTPStream的数组 */ QTSS_Error RTPSession::AddStream(RTSPRequestInterface* request, RTPStream** outStream, QTSS_AddStreamFlags inFlags) { Assert(outStream != NULL); // Create a new SSRC for this stream. This should just be a random number unique // to all the streams in the session /* 循环产生一个能唯一标识该RTPSession的RTPStream数组中新的RTPStream的随机数,作为SSRC(它和该数组中现存的每个RTPStream的SSRC都不同) */ UInt32 theSSRC = 0; while (theSSRC == 0) { /* 产生随机数,它在该RTPSession的RTPStream数组中唯一标识一个RTPSream */ theSSRC = (SInt32)::rand(); RTPStream** theStream = NULL; UInt32 theLen = 0; /* 遍历RTPSession中的每个RTPStream,若它的SSRC恰和theSSRC相同,就将theSSRC置0,使得该循环继续 */ for (int x = 0; this->GetValuePtr(qtssCliSesStreamObjects, x, (void**)&theStream, &theLen) == QTSS_NoErr; x++) { Assert(theStream != NULL); Assert(theLen == sizeof(RTPStream*)); if (*theStream != NULL) if ((*theStream)->GetSSRC() == theSSRC) theSSRC = 0; } } /***************** 新建一个RTPStream对象,它有唯一标识它的SSRC(随机数) *************/ *outStream = NEW RTPStream(theSSRC, this); /***************** 新建一个RTPStream对象 *************/ /* 以指定加入方式搭建该RTSP Request的RTPStream */ QTSS_Error theErr = (*outStream)->Setup(request, inFlags); /* 假如搭建不成功,就删去新建RTPStream对象 */ if (theErr != QTSS_NoErr) // If we couldn't setup the stream, make sure not to leak memory! delete *outStream; /* 假如搭建成功,将其放入RTPStream Array中,注意下面qtssCliSesStreamObjects是个多值索引的属性 */ else { // If the stream init succeeded, then put it into the array of setup streams theErr = this->SetValue(qtssCliSesStreamObjects, this->GetNumValues(qtssCliSesStreamObjects), outStream, sizeof(RTPStream*), QTSSDictionary::kDontObeyReadOnly); Assert(theErr == QTSS_NoErr); fHasAnRTPStream = true;/* 现在有一个RTPStream */ } return theErr; }
int AmSession::writeStreams(unsigned long long ts, unsigned char *buffer) { int res = 0; lockAudio(); AmRtpAudio *stream = RTPStream(); if (stream->sendIntReached()) { // FIXME: shouldn't depend on checkInterval call before! unsigned int f_size = stream->getFrameSize(); int got = 0; if (output) got = output->get(ts, buffer, stream->getSampleRate(), f_size); if (got < 0) res = -1; if (got > 0) res = stream->put(ts, buffer, stream->getSampleRate(), got); } unlockAudio(); return res; }
QTSS_Error RTPSession::AddStream(RTSPRequestInterface* request, RTPStream** outStream, QTSS_AddStreamFlags inFlags) { Assert(outStream != NULL); // Create a new SSRC for this stream. This should just be a random number unique // to all the streams in the session UInt32 theSSRC = 0; while (theSSRC == 0) { theSSRC = (SInt32)::rand(); RTPStream** theStream = NULL; UInt32 theLen = 0; for (int x = 0; this->GetValuePtr(qtssCliSesStreamObjects, x, (void**)&theStream, &theLen) == QTSS_NoErr; x++) { Assert(theStream != NULL); Assert(theLen == sizeof(RTPStream*)); if (*theStream != NULL) if ((*theStream)->GetSSRC() == theSSRC) theSSRC = 0; } } *outStream = NEW RTPStream(theSSRC, this); QTSS_Error theErr = (*outStream)->Setup(request, inFlags); if (theErr != QTSS_NoErr) // If we couldn't setup the stream, make sure not to leak memory! delete *outStream; else { // If the stream init succeeded, then put it into the array of setup streams theErr = this->SetValue(qtssCliSesStreamObjects, this->GetNumValues(qtssCliSesStreamObjects), outStream, sizeof(RTPStream*), QTSSDictionary::kDontObeyReadOnly); Assert(theErr == QTSS_NoErr); fHasAnRTPStream = true; } return theErr; }
int AmSession::readStreams(unsigned long long ts, unsigned char *buffer) { int res = 0; lockAudio(); AmRtpAudio *stream = RTPStream(); unsigned int f_size = stream->getFrameSize(); if (stream->checkInterval(ts)) { int got = stream->get(ts, buffer, stream->getSampleRate(), f_size); if (got < 0) res = -1; if (got > 0) { if (isDtmfDetectionEnabled()) putDtmfAudio(buffer, got, ts); if (input) res = input->put(ts, buffer, stream->getSampleRate(), got); } } unlockAudio(); return res; }
int AmB2BSession::onSdpCompleted(const AmSdp& local_sdp, const AmSdp& remote_sdp) { if (rtp_relay_mode != RTP_Direct) { if (!media_session) { // report missing media session (here we get for rtp_relay_mode == RTP_Relay) ERROR("BUG: media session is missing, can't update SDP\n"); } else { media_session->updateStreams(a_leg, local_sdp, remote_sdp, this); } } if(hasRtpStream() && RTPStream()->getSdpMediaIndex() >= 0) { if(!sip_relay_only){ return AmSession::onSdpCompleted(local_sdp,remote_sdp); } DBG("sip_relay_only = true: doing nothing!\n"); } return 0; }
/** Hook called when an SDP answer is required */ bool AmSession::getSdpAnswer(const AmSdp& offer, AmSdp& answer) { DBG("AmSession::getSdpAnswer(...) ...\n"); answer.version = 0; answer.origin.user = "******"; //answer.origin.sessId = 1; //answer.origin.sessV = 1; answer.sessionName = "sems"; answer.conn.network = NT_IN; if (offer.conn.address.empty()) answer.conn.addrType = AT_V4; // or use first stream connection? else answer.conn.addrType = offer.conn.addrType; answer.conn.address = advertisedIP(answer.conn.addrType); answer.media.clear(); bool audio_1st_stream = true; unsigned int media_index = 0; for(vector<SdpMedia>::const_iterator m_it = offer.media.begin(); m_it != offer.media.end(); ++m_it) { answer.media.push_back(SdpMedia()); SdpMedia& answer_media = answer.media.back(); if( m_it->type == MT_AUDIO && m_it->transport == TP_RTPAVP && audio_1st_stream && (m_it->port != 0) ) { RTPStream()->setLocalIP(localMediaIP(answer.conn.addrType)); RTPStream()->getSdpAnswer(media_index,*m_it,answer_media); if(answer_media.payloads.empty() || ((answer_media.payloads.size() == 1) && (answer_media.payloads[0].encoding_name == "telephone-event")) ){ // no compatible media found throw Exception(488,"no compatible payload"); } audio_1st_stream = false; } else { answer_media.type = m_it->type; answer_media.port = 0; answer_media.nports = 0; answer_media.transport = m_it->transport; answer_media.send = false; answer_media.recv = false; answer_media.payloads.clear(); if(!m_it->payloads.empty()) { SdpPayload dummy_pl = m_it->payloads.front(); dummy_pl.encoding_name.clear(); dummy_pl.sdp_format_parameters.clear(); answer_media.payloads.push_back(dummy_pl); } answer_media.attributes.clear(); } // sort payload type in the answer according to the priority given in the codec_order configuration key std::stable_sort(answer_media.payloads.begin(),answer_media.payloads.end(),codec_priority_cmp()); media_index++; } return true; }
Click2TransSession::Click2TransSession(Click2TransDialog* parentDialog) : dialog(parentDialog),ringTone(new AmRingTone(0,2000,4000,440,480)) { RTPStream()->setPlayoutType(ADAPTIVE_PLAYOUT); setCallgroup(dialog->getID()); }
void AmSession::sendDtmf(int event, unsigned int duration_ms) { RTPStream()->sendDtmf(event, duration_ms); }
void AmSession::setInbandDetector(Dtmf::InbandDetectorType t) { m_dtmfDetector.setInbandDetector(t, RTPStream()->getSampleRate()); }
int AmSession::getRPort() { return RTPStream()->getRPort(); }
PinAuthConferenceDialog::PinAuthConferenceDialog(AmPromptCollection& prompts) : play_list(this), separator(this, 0), prompts(prompts), state(None) { // set configured playout type RTPStream()->setPlayoutType(PinAuthConferenceFactory::m_PlayoutType); }