9using namespace resipgst;
15#define RESIPROCATE_SUBSYSTEM resip::GstSubsystem::GSTREAMER
22 mMediaBin = Bin::create();
25GstRtpSession::~GstRtpSession()
31GstRtpSession::getLocalAddress()
const
37GstRtpSession::allocatePort()
40 return mRTPManager.getPortManager().allocateRTPPort();
43std::shared_ptr<SdpContents>
44GstRtpSession::buildOffer(
bool audio,
bool video)
46 std::shared_ptr<SdpContents>
offer;
60 "o=- 3838180699 3838180699 IN IP4 " +
localAddress +
"\r\n"
64 "a=ice-pwd:da9801364d7cd7d3a87f7f2f\r\n"
65 "a=ice-ufrag:91f7ed7e\r\n"
66 "a=rtcp-xr:rcvr-rtt=all:10000 stat-summary=loss,dup,jitt,TTL voip-metrics\r\n"
81 Mime type(
"application",
"sdp");
101 else if(!m.
codecs().empty())
103 o << m.
codecs().front().payloadType();
113std::shared_ptr<SdpContents>
114GstRtpSession::buildAnswer(std::shared_ptr<resip::SdpContents>
remoteOffer)
122 "o=- 3838180699 3838180699 IN IP4 " +
localAddress +
"\r\n"
126 "a=rtcp-xr:rcvr-rtt=all:10000 stat-summary=loss,dup,jitt,TTL voip-metrics\r\n";
131 unsigned int entry = 0;
138 caps->get_structure(0).get_field(
"encoding-name",
codecName);
142 caps->get_structure(0).get_field<
gint>(
"payload", pt);
151 stream <<
"m=" << m.
name() <<
" " <<
localPort <<
" RTP/AVP " << pt <<
"\r\n"
153 stream <<
"a=rtpmap:" << pt <<
" " << cc.mName <<
"/" << cc.mRate <<
"\r\n";
154 if(m.
name() ==
"video")
156 stream <<
"a=fmtp:" << pt <<
" " << cc.mFmtp <<
"\r\n";
161 DebugLog(<<
"didn't find supported codec");
167 DebugLog(<<
"unsupported media type");
175 Mime type(
"application",
"sdp");
185GstRtpSession::processAnswer(std::shared_ptr<resip::SdpContents>
remoteAnswer)
194 unsigned int entry = 0;
201 caps->get_structure(0).get_field(
"encoding-name",
codecName);
205 caps->get_structure(0).get_field<
gint>(
"payload", pt);
221 DebugLog(<<
"didn't find supported codec");
227 DebugLog(<<
"unsupported media type");
241 DebugLog(<<
"going to STATE_PLAYING");
245 ErrLog(<<
"pipeline fail");
249Glib::RefPtr<Gst::Caps>
262 return Gst::Caps::create_simple(
"application/x-rtp",
264 "encoding-name",
c.getName().c_str(),
265 "clock-rate",
c.getRate(),
266 "payload",
c.payloadType());
269Glib::RefPtr<Gst::Caps>
272 std::list<std::reference_wrapper<SdpContents::Session::Medium>> media =
274 if(media.size() == 0)
286 DebugLog(<<
"creating outgoing bin for caps: " <<
caps->to_string());
297 if(
caps->get_structure(0).has_field(
"media"))
303 if(
caps->get_structure(0).has_field(
"encoding-name"))
311 Glib::RefPtr<Gst::Caps>
v_caps;
326 enc = Gst::ElementFactory::create_element(
"vp8enc");
327 v_caps = Gst::Caps::create_simple(
"video/x-vp8",
333 enc->property<
gint>(
"token-partitions", 3);
334 enc->property<
gint>(
"keyframe-max-dist", 2000);
336 payloader = Gst::ElementFactory::create_element(
"rtpvp8pay");
342 enc = Gst::ElementFactory::create_element(
"openh264enc");
343 v_caps = Gst::Caps::create_simple(
"video/x-h264",
344 "profile",
"baseline");
345 enc->property<
guint>(
"bitrate", 90000);
347 enc->property<
gint64>(
"rate-control", 1);
367 payloader = Gst::ElementFactory::create_element(
"rtph264pay");
387 enc = Gst::ElementFactory::create_element(
"opusenc");
389 v_caps = Gst::Caps::create_simple(
"audio/x-opus",
391 "encoding-name",
"OPUS",
394 enc->property<
gint>(
"bitrate", 48000);
395 payloader = Gst::ElementFactory::create_element(
"rtpopuspay");
401 enc = Gst::ElementFactory::create_element(
"alawenc");
402 v_caps = Gst::Caps::create_simple(
"audio/x-alaw",
405 payloader = Gst::ElementFactory::create_element(
"rtppcmapay");
416 ErrLog(<<
"unhandled mediaType");
517Glib::RefPtr<Gst::Bin>
532 depay = Gst::ElementFactory::create_element(
"rtpvp8depay");
533 parse = Gst::ElementFactory::create_element(
"vp8parse");
534 dec = Gst::ElementFactory::create_element(
"vp8dec");
539 depay = Gst::ElementFactory::create_element(
"rtph264depay");
540 parse = Gst::ElementFactory::create_element(
"h264parse");
541 dec = Gst::ElementFactory::create_element(
"openh264dec");
555 depay = Gst::ElementFactory::create_element(
"rtpopusdepay");
556 dec = Gst::ElementFactory::create_element(
"opusdec");
560 depay = Gst::ElementFactory::create_element(
"rtppcmadepay");
561 dec = Gst::ElementFactory::create_element(
"alawdec");
574 RefPtr<Pad> sink = GhostPad::create(queue->get_static_pad(
"sink"),
"sink");
592 StackLog(<<
"src pad already added");
616#define P_CLIENTS(a,p) (a + ":" + Data(p))
619GstRtpSession::initRtpRxPorts()
625 DebugLog(<<
"mRtpTransportBin not ready yet");
638 DebugLog(<<
"udpsrc0 already present");
649 SdpContents::Session::MediumContainer::iterator
local =
mLocal->session().media().begin();
658 if(
local->name() ==
"audio" ||
local->name() ==
"video")
664 Glib::RefPtr<Gst::Element>
udpSource = Gst::ElementFactory::create_element(
"udpsrc");
668 Glib::RefPtr<Gst::Element>
udpSourceRtcp = Gst::ElementFactory::create_element(
"udpsrc");
754GstRtpSession::initRtpTxPorts()
760 DebugLog(<<
"mRtpTransportBin not ready yet");
773 DebugLog(<<
"multiudpsink0 already present");
790 SdpContents::Session::MediumContainer::iterator
local =
mLocal->session().media().begin();
791 SdpContents::Session::MediumContainer::const_iterator
remote =
mRemote->session().media().cbegin();
799 if(
local->name() ==
"audio" ||
local->name() ==
"video")
814 Glib::RefPtr<Gst::Element>
udpSink = Gst::ElementFactory::create_element(
"multiudpsink");
829 udpSink->set_property(
"sync",
false);
830 udpSink->set_property(
"async",
false);
835 Glib::RefPtr<Gst::Element>
udpSinkRtcp = Gst::ElementFactory::create_element(
"multiudpsink");
901GstRtpSession::createRtpTransportBin()
905 WarningLog(<<
"mRtpTransportBin already initialized");
910 mRtpTransportBin = RefPtr<Bin>::cast_dynamic(ElementFactory::create_element(
"webrtcbin"));
923 Glib::RefPtr<Gst::Element>
rtpBin = Gst::ElementFactory::create_element(
"rtpbin");
929 DebugLog(<<
"Dynamic pad created. Linking demuxer/decoder " <<
padName);
938 std::regex r(
"recv_rtp_src_(\\d+)_(\\d+)_(\\d+)");
940 const std::string&
s =
padName.raw();
941 if(std::regex_search(
s.begin(),
s.end(),
match, r))
950 r =
"send_rtp_src_(\\d+)";
951 if(std::regex_search(
s.begin(),
s.end(),
match, r))
958 Glib::RefPtr<Gst::Caps>
rtcp_caps = Gst::Caps::create_simple(
959 "application/x-rtcp");
989 if (std::regex_search(
s.begin(),
s.end(),
match, r))
992 auto& ssrc =
match[2];
1010 <<
sinkPad->get_name() <<
" failed.");
1037 const Glib::ustring
padName =
pad->get_name();
1040 StackLog(<<
"trying to extract pt from pad name: " << padName);
1041 std::regex r1(
"recv_rtp_src_(\\d+)_(\\d+)_(\\d+)");
1042 std::regex r2(
"src_(\\d+)");
1044 const std::string& s = padName.raw();
1046 if (std::regex_search(s.begin(), s.end(), match, r1))
1048 unsigned int streamId = atoi(match[1].str().c_str());
1049 unsigned long ssrc = atoi(match[2].str().c_str());
1050 unsigned int pt = atoi(match[3].str().c_str());
1051 StackLog(<<
"found stream " << streamId
1052 <<
" SSRC: " << ssrc
1053 <<
" payload type: " << pt);
1055 createDecodeBinForStream(pad, streamId, pt);
1057 else if (std::regex_search(
s.begin(),
s.end(),
match,
r2))
1059 unsigned int streamId = atoi(match[1].str().c_str());
1060 StackLog(<<
"found stream " << streamId);
1061 createDecodeBinForStream(pad, streamId, -1);
1065 ErrLog(<<
"unrecognized src pad: " << padName);
1079GstRtpSession::getRtpTransportBin()
1099 ErrLog(<<
"no local SDP, new pad is not expected and can't be handled");
1124 ErrLog(<<
"no payload format matches pt: " << pt);
1132 if(!
caps->get_structure(0).has_field(
"encoding-name"))
1134 CritLog(<<
"can't find encoding-name");
1163 std::shared_ptr<CodecConfig> cc =
codecRegIt->second;
1177 if(!cc->mParse.empty())
1221 DebugLog(<<
"all incoming streams connected to decoders");
1224 DebugLog(<<
"all pads ready, trying to setup HOMER HEP RTCP");
1240GstRtpSession::onPlaying()
1245 DebugLog(<<
"onPlaying: adding pad " <<
pad->get_name());
1251GstRtpSession::initCaps(std::shared_ptr<SdpContents>
sdp, std::vector<Glib::RefPtr<Caps>>& sessionCaps)
1255 ErrLog(<<
"initCaps: we don't have valid SDP");
1261 sessionCaps.clear();
1262 sessionCaps.resize(
sdp->session().media().size());
1264 unsigned int entry = 0;
1265 for(
const auto& m :
sdp->session().media())
1274 std::map<int, SdpContents::Session::Codec>
codecMap;
1275 for(
const auto&
c : m.codecs())
1279 StackLog(<<
"found " <<
codecMap.size() <<
" codec(s) and " <<
formats.size() <<
" format(s) in the SDP offer");
1284 if(!
caps &&
f !=
"webrtc-datachannel" &&
f !=
"*")
1286 int pt =
f.convertInt();
1301 caps = Gst::Caps::create_simple(
"application/x-rtp",
1304 "clock-rate",
c.getRate(),
1305 "payload",
c.payloadType());
1314 WarningLog(<<
"format " << pt <<
" not found in codecMap");
1328GstRtpSession::initOutgoingBins()
1347GstRtpSession::addStream(Glib::RefPtr<Gst::Caps>
caps)
1355GstRtpSession::setRemoteSdp(std::shared_ptr<resip::SdpContents>
remote)
1365GstRtpSession::getStreamCount()
static const Data pad("\0\0\0\0\0\0\0", 7)
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
An iostream that operates on an existing Data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Data & uppercase()
Converts this Data to uppercase.
const char * c_str() const
Returns a null-terminated string representing.
Data & lowercase()
Converts this Data to lowercase.
size_type find(const Data &match, size_type start=0) const
Finds a specified sequence of bytes in this Data.
Represents the "media-type" element in the RFC 3261 grammar.
parameters for a specific codec are stored in this class.
process m= (media announcement) blocks
const std::list< Data > & getFormats() const
return a list of codec formats
const CodecContainer & codecs() const
preferred codec/format interface
const Data & protocol() const
return the transport protocol
const Data & name() const
return the media type
Provides an interface to process and generate SDP bodies (MIME content-type application/sdp).
dcm! – add UnusedChecking(_enum) below;