Variant SDP::GetAudioTrack(uint32_t index, string uri) { //1. Find the track Variant track = GetTrack(index, "audio"); if (track == V_NULL) { FATAL("Audio track index %u not found", index); return Variant(); } //2. Prepare the info Variant result; SDP_AUDIO_SERVER_IP(result) = (*this)[SDP_SESSION][SDP_O]["address"]; string control = track[SDP_A].GetValue("control", false); if (control.find("rtsp") == 0) SDP_AUDIO_CONTROL_URI(result) = control; else SDP_AUDIO_CONTROL_URI(result) = uri + "/" + control; SDP_AUDIO_CODEC(result) = track[SDP_A].GetValue("rtpmap", false)["encodingName"]; if ((uint64_t) SDP_AUDIO_CODEC(result) != CODEC_AUDIO_AAC) { FATAL("The only supported audio codec is aac"); return Variant(); } SDP_AUDIO_CODEC_SETUP(result) = track[SDP_A] .GetValue("fmtp", false) .GetValue("config", false); SDP_TRACK_GLOBAL_INDEX(result) = SDP_TRACK_GLOBAL_INDEX(track); SDP_TRACK_IS_AUDIO(result) = (bool)true; //3. Done return result; }
Variant SDP::GetVideoTrack(uint32_t index, string uri) { //1. Find the track Variant track = GetTrack(index, "video"); if (track == V_NULL) { FATAL("Video track index %u not found", index); return Variant(); } //2. Prepare the info Variant result; SDP_VIDEO_SERVER_IP(result) = (*this)[SDP_SESSION][SDP_O]["address"]; string control = track[SDP_A].GetValue("control", false); if (control.find("rtsp") == 0) SDP_VIDEO_CONTROL_URI(result) = control; else SDP_VIDEO_CONTROL_URI(result) = uri + "/" + control; SDP_VIDEO_CODEC(result) = track[SDP_A].GetValue("rtpmap", false)["encodingName"]; if ((uint64_t) SDP_VIDEO_CODEC(result) != CODEC_VIDEO_AVC) { FATAL("The only supported video codec is h264"); return Variant(); } SDP_VIDEO_CODEC_H264_SPS(result) = track[SDP_A] .GetValue("fmtp", false) .GetValue("sprop-parameter-sets", false)["SPS"]; SDP_VIDEO_CODEC_H264_PPS(result) = track[SDP_A] .GetValue("fmtp", false) .GetValue("sprop-parameter-sets", false)["PPS"]; SDP_TRACK_GLOBAL_INDEX(result) = SDP_TRACK_GLOBAL_INDEX(track); SDP_TRACK_IS_AUDIO(result) = (bool)false; //3. Done return result; }
Variant SDP::GetVideoTrack(uint32_t index, string contentBase) { //1. Find the track Variant track = GetTrack(index, "video"); if (track == V_NULL) { FATAL("Video track index %u not found", index); return Variant(); } //2. Prepare the info Variant result; SDP_VIDEO_SERVER_IP(result) = (*this)[SDP_SESSION][SDP_O]["address"]; string control = track[SDP_A].GetValue("control", false); if (control.find("rtsp") == 0) { SDP_VIDEO_CONTROL_URI(result) = control; } else { if ((contentBase != "") && (contentBase[contentBase.size() - 1] != '/')) { contentBase += "/"; } SDP_VIDEO_CONTROL_URI(result) = contentBase + control; } SDP_VIDEO_CODEC(result) = track[SDP_A].GetValue("rtpmap", false)["encodingName"]; if ((uint64_t) SDP_VIDEO_CODEC(result) != CODEC_VIDEO_H264) { FATAL("The only supported video codec is h264"); return Variant(); } SDP_VIDEO_CODEC_H264_SPS(result) = track[SDP_A] .GetValue("fmtp", false) .GetValue("sprop-parameter-sets", false)["SPS"]; SDP_VIDEO_CODEC_H264_PPS(result) = track[SDP_A] .GetValue("fmtp", false) .GetValue("sprop-parameter-sets", false)["PPS"]; SDP_TRACK_GLOBAL_INDEX(result) = SDP_TRACK_GLOBAL_INDEX(track); SDP_TRACK_IS_AUDIO(result) = (bool)false; if (track.HasKeyChain(V_UINT32, false, 1, SDP_B)) SDP_TRACK_BANDWIDTH(result) = track[SDP_B]; else SDP_TRACK_BANDWIDTH(result) = (uint32_t) 0; SDP_TRACK_CLOCKRATE(result) = track[SDP_A].GetValue("rtpmap", false)["clockRate"]; //3. Done return result; }
bool InboundConnectivity::AddTrack(Variant& track, bool isAudio) { Variant &_track = isAudio ? _audioTrack : _videoTrack; Variant &_oppositeTrack = isAudio ? _videoTrack : _audioTrack; InboundRTPProtocol **ppRTP = isAudio ? &_pRTPAudio : &_pRTPVideo; RTCPProtocol **ppRTCP = isAudio ? &_pRTCPAudio : &_pRTCPVideo; uint8_t *pRR = isAudio ? _audioRR : _videoRR; if (_track != V_NULL) return false; BaseClientApplication *pApplication = _pRTSP->GetApplication(); if (pApplication == NULL) { FATAL("RTSP protocol not yet assigned to an application"); return false; } _track = track; if (_oppositeTrack != V_NULL) { if (_oppositeTrack["isTcp"] != _track["isTcp"]) return false; } _forceTcp = (bool)_track["isTcp"]; Variant dummy; *ppRTP = (InboundRTPProtocol *) ProtocolFactoryManager::CreateProtocolChain( CONF_PROTOCOL_INBOUND_UDP_RTP, dummy); if (*ppRTP == NULL) { FATAL("Unable to create the protocol chain"); Cleanup(); return false; } *ppRTCP = (RTCPProtocol *) ProtocolFactoryManager::CreateProtocolChain( CONF_PROTOCOL_UDP_RTCP, dummy); if (*ppRTCP == NULL) { FATAL("Unable to create the protocol chain"); Cleanup(); return false; } if ((bool)_track["isTcp"]) { uint16_t dataIdx = 0; uint16_t rtcpIdx = 0; //2. Add them in the fast-pickup array if ((_track.HasKeyChain(V_UINT16, true, 2, "portsOrChannels", "data")) && (_track.HasKeyChain(V_UINT16, true, 2, "portsOrChannels", "rtcp"))) { dataIdx = (uint16_t) _track["portsOrChannels"]["data"]; rtcpIdx = (uint16_t) _track["portsOrChannels"]["rtcp"]; } else { uint8_t idx = (uint8_t) ((uint32_t) SDP_TRACK_GLOBAL_INDEX(_track)*2); dataIdx = idx; rtcpIdx = idx + 1; } if ((dataIdx >= 256) || (rtcpIdx >= 256)) { FATAL("Invalid channel numbers"); return false; } if ((_pProtocols[dataIdx] != NULL) || (_pProtocols[rtcpIdx] != NULL)) { FATAL("Invalid channel numbers"); return false; } _pProtocols[dataIdx] = *ppRTP; _pProtocols[rtcpIdx] = *ppRTCP; EHTONLP(pRR + 8, (*ppRTCP)->GetSSRC()); //SSRC of packet sender EHTONLP(pRR + 40, (*ppRTCP)->GetSSRC()); //SSRC of packet sender pRR[1] = (uint8_t) rtcpIdx; } else { if (!CreateCarriers(*ppRTP, *ppRTCP)) { FATAL("Unable to create carriers"); return false; } } (*ppRTP)->SetApplication(pApplication); (*ppRTCP)->SetApplication(pApplication); return true; }