Generating an SDP offer with datachannel

I am trying to generate an SDP offer to establish an audio only connection. I am creating the pipeline, linking it, creating a datachannel and then attempting to generate the SDP offer to send on. However, at present the offer turns off the datachannel (m=application 0 UDP/DTLS/SCTP webrtc-datachannel)

I create the pipeline objects, set properties, link the pipeline, bind signals, and then set the pipeline to READY and create the datachannel. I then generate the offer, which I use to set the local description, but then wait until ICE gathering is complete (the other end doesn’t seem to do trickle, it wants the candidates in the SDP). At this point I get the local description for transmitting to the other end (code excerpts below):

GstElement * _webrtc{nullptr};
_webrtc = gst_element_factory_make("webrtcbin", "webrtcbin");
g_object_set(G_OBJECT(_webrtc),
				 "bundle-policy", GST_WEBRTC_BUNDLE_POLICY_MAX_BUNDLE,
				 "latency", _latency, NULL);

g_signal_connect_data(_webrtc, "on-negotiation-needed", G_CALLBACK(on_negotiation_static), make_callback_name(_registry_name), destroy_callback_name, GConnectFlags(0));
g_signal_connect_data(_webrtc, "on-ice-candidate", G_CALLBACK(on_ice_static), make_callback_name(_registry_name), destroy_callback_name, GConnectFlags(0));
g_signal_connect_data(_webrtc, "notify::ice-gathering-state", G_CALLBACK(gather_ice_static), make_callback_name(_registry_name), destroy_callback_name, GConnectFlags(0));
g_signal_connect_data(_webrtc, "notify::ice-connection-state", G_CALLBACK(on_ice_state_static), make_callback_name(_registry_name), destroy_callback_name, GConnectFlags(0));
g_signal_connect_data(_webrtc, "notify::connection-state", G_CALLBACK(on_connection_state_static), make_callback_name(_registry_name), destroy_callback_name, GConnectFlags(0));


GstWebRTCDataChannel * _data_sender{nullptr};
gst_element_set_state(_pipeline, GST_STATE_READY);
g_signal_emit_by_name(_webrtc, "create-data-channel", "oai-event", NULL, &_data_sender);

if (_data_sender && GST_IS_WEBRTC_DATA_CHANNEL(_data_sender))
{
	bind_data_receiver_signals(_data_sender);
	Q_EMIT qlog_write("Created sending data channel", log_level::debug);
	g_object_ref_sink(_data_sender);
}

// Time passes, "ice-gathering-state" signal fires...

GstWebRTCICEGatheringState state;
g_object_get(G_OBJECT(webrtc), "ice-gathering-state", &state, NULL);

if (state == GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE)
{
	GstWebRTCSessionDescription * offer{nullptr};
	g_object_get(G_OBJECT(webrtc), "local-description", &offer, NULL);

	if (offer)
	{
		auto data = gst_sdp_message_as_text(offer->sdp);
		Q_EMIT qlog_write("notify sdp " + QString::fromUtf8(data).replace("\r\n", "\\r\\n"));
		gst_webrtc_session_description_free(offer);
	}
}

However, the resulting SDP is:

v=0
o=- 5657636778875196994 0 IN IP4 0.0.0.0
s=-
t=0 0
a=ice-options:trickle
a=group:BUNDLE audio0 application1
m=audio 9 UDP/TLS/RTP/SAVPF 111
<Audio stuff>
<List of ICE candidates>
a=end-of-candidates
m=application 0 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=setup:actpass
a=ice-ufrag:DTc7bCHofH5jmyP1aN7L2dAVPar00pnN
a=ice-pwd:sciN9MY8YDV6TZ5IKxwxlpS0MwC7sKM1
a=bundle-only
a=mid:application1
a=sctp-port:5000
a=fingerprint:sha-256 7A:B5:4D:D4:16:42:FC:7E:69:91:5E:22:34:0C:83:70:43:85:A9:9F:64:67:EA:3A:F9:C1:75:75:9F:A1:0B:C1

Looking in the code (subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c) I see in _add_data_channel_offer the port is set to 0 (turning it off) because of the boolean bundle_only being set to true. Am I doing something wrong with my setup? I don’t understand bundling well enough to feel confident in hacking around the source code…

The ‘0’ in m=application 0 UDP/DTLS/SCTP webrtc-datachannel is for the second m-line which in a bundled SDP (your case) could still mean that the media is accepted. When bundling, you also have to consult the a=group:BUNDLE attribute which in your case contains the mid of the data channel media (application1).

In short, the SDP is fine and both audio and data channel are offered.

Oh, my understanding of SDP offers is even less complete than I thought! Thank you very much!