mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
webrtcbin: implement support for group: BUNDLE
This commit is contained in:
parent
51d5db3f47
commit
9f684a2f81
7 changed files with 912 additions and 221 deletions
File diff suppressed because it is too large
Load diff
|
@ -83,6 +83,7 @@ struct _GstWebRTCBin
|
||||||
GstBin parent;
|
GstBin parent;
|
||||||
|
|
||||||
GstElement *rtpbin;
|
GstElement *rtpbin;
|
||||||
|
GstElement *rtpfunnel;
|
||||||
|
|
||||||
GstWebRTCSignalingState signaling_state;
|
GstWebRTCSignalingState signaling_state;
|
||||||
GstWebRTCICEGatheringState ice_gathering_state;
|
GstWebRTCICEGatheringState ice_gathering_state;
|
||||||
|
@ -94,6 +95,8 @@ struct _GstWebRTCBin
|
||||||
GstWebRTCSessionDescription *current_remote_description;
|
GstWebRTCSessionDescription *current_remote_description;
|
||||||
GstWebRTCSessionDescription *pending_remote_description;
|
GstWebRTCSessionDescription *pending_remote_description;
|
||||||
|
|
||||||
|
GstWebRTCBundlePolicy bundle_policy;
|
||||||
|
|
||||||
GstWebRTCBinPrivate *priv;
|
GstWebRTCBinPrivate *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,7 @@ transport_stream_finalize (GObject * object)
|
||||||
TransportStream *stream = TRANSPORT_STREAM (object);
|
TransportStream *stream = TRANSPORT_STREAM (object);
|
||||||
|
|
||||||
g_array_free (stream->ptmap, TRUE);
|
g_array_free (stream->ptmap, TRUE);
|
||||||
|
g_array_free (stream->remote_ssrcmap, TRUE);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -238,6 +239,7 @@ transport_stream_init (TransportStream * stream)
|
||||||
{
|
{
|
||||||
stream->ptmap = g_array_new (FALSE, TRUE, sizeof (PtMapItem));
|
stream->ptmap = g_array_new (FALSE, TRUE, sizeof (PtMapItem));
|
||||||
g_array_set_clear_func (stream->ptmap, (GDestroyNotify) clear_ptmap_item);
|
g_array_set_clear_func (stream->ptmap, (GDestroyNotify) clear_ptmap_item);
|
||||||
|
stream->remote_ssrcmap = g_array_new (FALSE, TRUE, sizeof (SsrcMapItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
TransportStream *
|
TransportStream *
|
||||||
|
|
|
@ -37,6 +37,12 @@ typedef struct
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
} PtMapItem;
|
} PtMapItem;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
guint32 ssrc;
|
||||||
|
guint media_idx;
|
||||||
|
} SsrcMapItem;
|
||||||
|
|
||||||
struct _TransportStream
|
struct _TransportStream
|
||||||
{
|
{
|
||||||
GstObject parent;
|
GstObject parent;
|
||||||
|
@ -54,6 +60,7 @@ struct _TransportStream
|
||||||
GstWebRTCDTLSTransport *rtcp_transport;
|
GstWebRTCDTLSTransport *rtcp_transport;
|
||||||
|
|
||||||
GArray *ptmap; /* array of PtMapItem's */
|
GArray *ptmap; /* array of PtMapItem's */
|
||||||
|
GArray *remote_ssrcmap; /* array of SsrcMapItem's */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _TransportStreamClass
|
struct _TransportStreamClass
|
||||||
|
|
|
@ -281,11 +281,9 @@ gboolean
|
||||||
validate_sdp (GstWebRTCBin * webrtc, SDPSource source,
|
validate_sdp (GstWebRTCBin * webrtc, SDPSource source,
|
||||||
GstWebRTCSessionDescription * sdp, GError ** error)
|
GstWebRTCSessionDescription * sdp, GError ** error)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
const gchar *group, *bundle_ice_ufrag = NULL, *bundle_ice_pwd = NULL;
|
const gchar *group, *bundle_ice_ufrag = NULL, *bundle_ice_pwd = NULL;
|
||||||
gchar **group_members = NULL;
|
gchar **group_members = NULL;
|
||||||
gboolean is_bundle = FALSE;
|
gboolean is_bundle = FALSE;
|
||||||
#endif
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!_check_valid_state_for_sdp_change (webrtc, source, sdp->type, error))
|
if (!_check_valid_state_for_sdp_change (webrtc, source, sdp->type, error))
|
||||||
|
@ -294,30 +292,21 @@ validate_sdp (GstWebRTCBin * webrtc, SDPSource source,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
/* not explicitly required
|
/* not explicitly required
|
||||||
if (ICE && !_check_trickle_ice (sdp->sdp))
|
if (ICE && !_check_trickle_ice (sdp->sdp))
|
||||||
return FALSE;
|
return FALSE;*/
|
||||||
group = gst_sdp_message_get_attribute_val (sdp->sdp, "group");
|
group = gst_sdp_message_get_attribute_val (sdp->sdp, "group");
|
||||||
is_bundle = g_str_has_prefix (group, "BUNDLE");
|
is_bundle = group && g_str_has_prefix (group, "BUNDLE");
|
||||||
if (is_bundle)
|
if (is_bundle)
|
||||||
group_members = g_strsplit (&group[6], " ", -1);*/
|
group_members = g_strsplit (&group[6], " ", -1);
|
||||||
|
|
||||||
for (i = 0; i < gst_sdp_message_medias_len (sdp->sdp); i++) {
|
for (i = 0; i < gst_sdp_message_medias_len (sdp->sdp); i++) {
|
||||||
const GstSDPMedia *media = gst_sdp_message_get_media (sdp->sdp, i);
|
const GstSDPMedia *media = gst_sdp_message_get_media (sdp->sdp, i);
|
||||||
#if 0
|
|
||||||
const gchar *mid;
|
const gchar *mid;
|
||||||
gboolean media_in_bundle = FALSE, first_media_in_bundle = FALSE;
|
gboolean media_in_bundle = FALSE;
|
||||||
gboolean bundle_only = FALSE;
|
|
||||||
#endif
|
|
||||||
if (!_media_has_mid (media, i, error))
|
if (!_media_has_mid (media, i, error))
|
||||||
goto fail;
|
goto fail;
|
||||||
#if 0
|
|
||||||
mid = gst_sdp_media_get_attribute_val (media, "mid");
|
mid = gst_sdp_media_get_attribute_val (media, "mid");
|
||||||
media_in_bundle = is_bundle && g_strv_contains (group_members, mid);
|
media_in_bundle = is_bundle
|
||||||
if (media_in_bundle)
|
&& g_strv_contains ((const gchar **) group_members, mid);
|
||||||
bundle_only =
|
|
||||||
gst_sdp_media_get_attribute_val (media, "bundle-only") != NULL;
|
|
||||||
first_media_in_bundle = media_in_bundle
|
|
||||||
&& g_strcmp0 (mid, group_members[0]) == 0;
|
|
||||||
#endif
|
|
||||||
if (!_media_get_ice_ufrag (sdp->sdp, i)) {
|
if (!_media_get_ice_ufrag (sdp->sdp, i)) {
|
||||||
g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_BAD_SDP,
|
g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_BAD_SDP,
|
||||||
"media %u is missing or contains an empty \'ice-ufrag\' attribute",
|
"media %u is missing or contains an empty \'ice-ufrag\' attribute",
|
||||||
|
@ -331,7 +320,6 @@ validate_sdp (GstWebRTCBin * webrtc, SDPSource source,
|
||||||
}
|
}
|
||||||
if (!_media_has_setup (media, i, error))
|
if (!_media_has_setup (media, i, error))
|
||||||
goto fail;
|
goto fail;
|
||||||
#if 0
|
|
||||||
/* check paramaters in bundle are the same */
|
/* check paramaters in bundle are the same */
|
||||||
if (media_in_bundle) {
|
if (media_in_bundle) {
|
||||||
const gchar *ice_ufrag =
|
const gchar *ice_ufrag =
|
||||||
|
@ -339,7 +327,7 @@ validate_sdp (GstWebRTCBin * webrtc, SDPSource source,
|
||||||
const gchar *ice_pwd = gst_sdp_media_get_attribute_val (media, "ice-pwd");
|
const gchar *ice_pwd = gst_sdp_media_get_attribute_val (media, "ice-pwd");
|
||||||
if (!bundle_ice_ufrag)
|
if (!bundle_ice_ufrag)
|
||||||
bundle_ice_ufrag = ice_ufrag;
|
bundle_ice_ufrag = ice_ufrag;
|
||||||
else if (!g_strcmp0 (bundle_ice_ufrag, ice_ufrag) != 0) {
|
else if (g_strcmp0 (bundle_ice_ufrag, ice_ufrag) != 0) {
|
||||||
g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_BAD_SDP,
|
g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_BAD_SDP,
|
||||||
"media %u has different ice-ufrag values in bundle. "
|
"media %u has different ice-ufrag values in bundle. "
|
||||||
"%s != %s", i, bundle_ice_ufrag, ice_ufrag);
|
"%s != %s", i, bundle_ice_ufrag, ice_ufrag);
|
||||||
|
@ -347,22 +335,21 @@ validate_sdp (GstWebRTCBin * webrtc, SDPSource source,
|
||||||
}
|
}
|
||||||
if (!bundle_ice_pwd) {
|
if (!bundle_ice_pwd) {
|
||||||
bundle_ice_pwd = ice_pwd;
|
bundle_ice_pwd = ice_pwd;
|
||||||
} else if (g_strcmp0 (bundle_ice_pwd, ice_pwd) == 0) {
|
} else if (g_strcmp0 (bundle_ice_pwd, ice_pwd) != 0) {
|
||||||
g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_BAD_SDP,
|
g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_BAD_SDP,
|
||||||
"media %u has different ice-ufrag values in bundle. "
|
"media %u has different ice-pwd values in bundle. "
|
||||||
"%s != %s", i, bundle_ice_ufrag, ice_ufrag);
|
"%s != %s", i, bundle_ice_pwd, ice_pwd);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// g_strv_free (group_members);
|
g_strfreev (group_members);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
// g_strv_free (group_members);
|
g_strfreev (group_members);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -321,4 +321,22 @@ typedef enum /*< underscore_name=gst_webrtc_data_channel_state >*/
|
||||||
GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED,
|
GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED,
|
||||||
} GstWebRTCDataChannelState;
|
} GstWebRTCDataChannelState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstWebRTCBundlePolicy:
|
||||||
|
* GST_WEBRTC_BUNDLE_POLICY_NONE: none
|
||||||
|
* GST_WEBRTC_BUNDLE_POLICY_BALANCED: balanced
|
||||||
|
* GST_WEBRTC_BUNDLE_POLICY_MAX_COMPAT: max-compat
|
||||||
|
* GST_WEBRTC_BUNDLE_POLICY_MAX_BUNDLE: max-bundle
|
||||||
|
*
|
||||||
|
* See https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-4.1.1
|
||||||
|
* for more information.
|
||||||
|
*/
|
||||||
|
typedef enum /*<underscore_name=gst_webrtc_bundle_policy>*/
|
||||||
|
{
|
||||||
|
GST_WEBRTC_BUNDLE_POLICY_NONE,
|
||||||
|
GST_WEBRTC_BUNDLE_POLICY_BALANCED,
|
||||||
|
GST_WEBRTC_BUNDLE_POLICY_MAX_COMPAT,
|
||||||
|
GST_WEBRTC_BUNDLE_POLICY_MAX_BUNDLE,
|
||||||
|
} GstWebRTCBundlePolicy;
|
||||||
|
|
||||||
#endif /* __GST_WEBRTC_FWD_H__ */
|
#endif /* __GST_WEBRTC_FWD_H__ */
|
||||||
|
|
|
@ -2070,6 +2070,336 @@ GST_START_TEST (test_data_channel_pre_negotiated)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
guint num_media;
|
||||||
|
guint num_active_media;
|
||||||
|
const gchar **bundled;
|
||||||
|
const gchar **bundled_only;
|
||||||
|
} BundleCheckData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_parse_bundle (GstSDPMessage * sdp, GStrv * bundled)
|
||||||
|
{
|
||||||
|
const gchar *group;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
group = gst_sdp_message_get_attribute_val (sdp, "group");
|
||||||
|
|
||||||
|
if (group && g_str_has_prefix (group, "BUNDLE ")) {
|
||||||
|
*bundled = g_strsplit (group + strlen ("BUNDLE "), " ", 0);
|
||||||
|
|
||||||
|
if (!(*bundled)[0]) {
|
||||||
|
GST_ERROR
|
||||||
|
("Invalid format for BUNDLE group, expected at least one mid (%s)",
|
||||||
|
group);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = TRUE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_media_has_attribute_key (const GstSDPMedia * media, const gchar * key)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < gst_sdp_media_attributes_len (media); i++) {
|
||||||
|
const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i);
|
||||||
|
|
||||||
|
if (g_strcmp0 (attr->key, key) == 0)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_check_bundled_sdp_media (struct test_webrtc *t, GstElement * element,
|
||||||
|
GstWebRTCSessionDescription * sd, gpointer user_data)
|
||||||
|
{
|
||||||
|
gchar **bundled = NULL;
|
||||||
|
BundleCheckData *data = (BundleCheckData *) user_data;
|
||||||
|
guint i;
|
||||||
|
guint active_media;
|
||||||
|
|
||||||
|
fail_unless_equals_int (gst_sdp_message_medias_len (sd->sdp),
|
||||||
|
data->num_media);
|
||||||
|
|
||||||
|
fail_unless (_parse_bundle (sd->sdp, &bundled));
|
||||||
|
|
||||||
|
if (!bundled) {
|
||||||
|
fail_unless_equals_int (g_strv_length ((GStrv) data->bundled), 0);
|
||||||
|
} else {
|
||||||
|
fail_unless_equals_int (g_strv_length (bundled),
|
||||||
|
g_strv_length ((GStrv) data->bundled));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; data->bundled[i]; i++) {
|
||||||
|
fail_unless (g_strv_contains ((const gchar **) bundled, data->bundled[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
active_media = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < gst_sdp_message_medias_len (sd->sdp); i++) {
|
||||||
|
const GstSDPMedia *media = gst_sdp_message_get_media (sd->sdp, i);
|
||||||
|
const gchar *mid = gst_sdp_media_get_attribute_val (media, "mid");
|
||||||
|
|
||||||
|
if (g_strv_contains ((const gchar **) data->bundled_only, mid))
|
||||||
|
fail_unless (_media_has_attribute_key (media, "bundle-only"));
|
||||||
|
|
||||||
|
if (gst_sdp_media_get_port (media) != 0)
|
||||||
|
active_media += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail_unless_equals_int (active_media, data->num_active_media);
|
||||||
|
|
||||||
|
if (bundled)
|
||||||
|
g_strfreev (bundled);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_START_TEST (test_bundle_audio_video_max_bundle_max_bundle)
|
||||||
|
{
|
||||||
|
struct test_webrtc *t = create_audio_video_test ();
|
||||||
|
const gchar *bundle[] = { "audio0", "video1", NULL };
|
||||||
|
const gchar *offer_bundle_only[] = { "video1", NULL };
|
||||||
|
const gchar *answer_bundle_only[] = { NULL };
|
||||||
|
/* We set a max-bundle policy on the offering webrtcbin,
|
||||||
|
* this means that all the offered medias should be part
|
||||||
|
* of the group:BUNDLE attribute, and they should be marked
|
||||||
|
* as bundle-only
|
||||||
|
*/
|
||||||
|
BundleCheckData offer_data = {
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
bundle,
|
||||||
|
offer_bundle_only,
|
||||||
|
};
|
||||||
|
/* We also set a max-bundle policy on the answering webrtcbin,
|
||||||
|
* this means that all the offered medias should be part
|
||||||
|
* of the group:BUNDLE attribute, but need not be marked
|
||||||
|
* as bundle-only.
|
||||||
|
*/
|
||||||
|
BundleCheckData answer_data = {
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
bundle,
|
||||||
|
answer_bundle_only,
|
||||||
|
};
|
||||||
|
struct validate_sdp offer = { _check_bundled_sdp_media, &offer_data };
|
||||||
|
struct validate_sdp answer = { _check_bundled_sdp_media, &answer_data };
|
||||||
|
|
||||||
|
gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
|
||||||
|
"max-bundle");
|
||||||
|
gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
|
||||||
|
"max-bundle");
|
||||||
|
|
||||||
|
t->on_negotiation_needed = NULL;
|
||||||
|
t->offer_data = &offer;
|
||||||
|
t->on_offer_created = validate_sdp;
|
||||||
|
t->answer_data = &answer;
|
||||||
|
t->on_answer_created = validate_sdp;
|
||||||
|
t->on_ice_candidate = NULL;
|
||||||
|
|
||||||
|
fail_if (gst_element_set_state (t->webrtc1,
|
||||||
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
||||||
|
fail_if (gst_element_set_state (t->webrtc2,
|
||||||
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
||||||
|
|
||||||
|
test_webrtc_create_offer (t, t->webrtc1);
|
||||||
|
|
||||||
|
test_webrtc_wait_for_answer_error_eos (t);
|
||||||
|
fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
|
||||||
|
|
||||||
|
test_webrtc_free (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_bundle_audio_video_max_compat_max_bundle)
|
||||||
|
{
|
||||||
|
struct test_webrtc *t = create_audio_video_test ();
|
||||||
|
const gchar *bundle[] = { "audio0", "video1", NULL };
|
||||||
|
const gchar *bundle_only[] = { NULL };
|
||||||
|
/* We set a max-compat policy on the offering webrtcbin,
|
||||||
|
* this means that all the offered medias should be part
|
||||||
|
* of the group:BUNDLE attribute, and they should *not* be marked
|
||||||
|
* as bundle-only
|
||||||
|
*/
|
||||||
|
BundleCheckData offer_data = {
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
bundle,
|
||||||
|
bundle_only,
|
||||||
|
};
|
||||||
|
/* We set a max-bundle policy on the answering webrtcbin,
|
||||||
|
* this means that all the offered medias should be part
|
||||||
|
* of the group:BUNDLE attribute, but need not be marked
|
||||||
|
* as bundle-only.
|
||||||
|
*/
|
||||||
|
BundleCheckData answer_data = {
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
bundle,
|
||||||
|
bundle_only,
|
||||||
|
};
|
||||||
|
struct validate_sdp offer = { _check_bundled_sdp_media, &offer_data };
|
||||||
|
struct validate_sdp answer = { _check_bundled_sdp_media, &answer_data };
|
||||||
|
|
||||||
|
gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
|
||||||
|
"max-compat");
|
||||||
|
gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
|
||||||
|
"max-bundle");
|
||||||
|
|
||||||
|
t->on_negotiation_needed = NULL;
|
||||||
|
t->offer_data = &offer;
|
||||||
|
t->on_offer_created = validate_sdp;
|
||||||
|
t->answer_data = &answer;
|
||||||
|
t->on_answer_created = validate_sdp;
|
||||||
|
t->on_ice_candidate = NULL;
|
||||||
|
|
||||||
|
fail_if (gst_element_set_state (t->webrtc1,
|
||||||
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
||||||
|
fail_if (gst_element_set_state (t->webrtc2,
|
||||||
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
||||||
|
|
||||||
|
test_webrtc_create_offer (t, t->webrtc1);
|
||||||
|
|
||||||
|
test_webrtc_wait_for_answer_error_eos (t);
|
||||||
|
fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
|
||||||
|
|
||||||
|
test_webrtc_free (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_bundle_audio_video_max_bundle_none)
|
||||||
|
{
|
||||||
|
struct test_webrtc *t = create_audio_video_test ();
|
||||||
|
const gchar *offer_bundle[] = { "audio0", "video1", NULL };
|
||||||
|
const gchar *offer_bundle_only[] = { "video1", NULL };
|
||||||
|
const gchar *answer_bundle[] = { NULL };
|
||||||
|
const gchar *answer_bundle_only[] = { NULL };
|
||||||
|
/* We set a max-bundle policy on the offering webrtcbin,
|
||||||
|
* this means that all the offered medias should be part
|
||||||
|
* of the group:BUNDLE attribute, and they should be marked
|
||||||
|
* as bundle-only
|
||||||
|
*/
|
||||||
|
BundleCheckData offer_data = {
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
offer_bundle,
|
||||||
|
offer_bundle_only,
|
||||||
|
};
|
||||||
|
/* We set a none policy on the answering webrtcbin,
|
||||||
|
* this means that the answer should contain no bundled
|
||||||
|
* medias, and as the bundle-policy of the offering webrtcbin
|
||||||
|
* is set to max-bundle, only one media should be active.
|
||||||
|
*/
|
||||||
|
BundleCheckData answer_data = {
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
answer_bundle,
|
||||||
|
answer_bundle_only,
|
||||||
|
};
|
||||||
|
struct validate_sdp offer = { _check_bundled_sdp_media, &offer_data };
|
||||||
|
struct validate_sdp answer = { _check_bundled_sdp_media, &answer_data };
|
||||||
|
|
||||||
|
gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
|
||||||
|
"max-bundle");
|
||||||
|
gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy", "none");
|
||||||
|
|
||||||
|
t->on_negotiation_needed = NULL;
|
||||||
|
t->offer_data = &offer;
|
||||||
|
t->on_offer_created = validate_sdp;
|
||||||
|
t->answer_data = &answer;
|
||||||
|
t->on_answer_created = validate_sdp;
|
||||||
|
t->on_ice_candidate = NULL;
|
||||||
|
|
||||||
|
fail_if (gst_element_set_state (t->webrtc1,
|
||||||
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
||||||
|
fail_if (gst_element_set_state (t->webrtc2,
|
||||||
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
||||||
|
|
||||||
|
test_webrtc_create_offer (t, t->webrtc1);
|
||||||
|
|
||||||
|
test_webrtc_wait_for_answer_error_eos (t);
|
||||||
|
fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
|
||||||
|
|
||||||
|
test_webrtc_free (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_bundle_audio_video_data)
|
||||||
|
{
|
||||||
|
struct test_webrtc *t = create_audio_video_test ();
|
||||||
|
const gchar *bundle[] = { "audio0", "video1", "application2", NULL };
|
||||||
|
const gchar *offer_bundle_only[] = { "video1", "application2", NULL };
|
||||||
|
const gchar *answer_bundle_only[] = { NULL };
|
||||||
|
GObject *channel = NULL;
|
||||||
|
/* We set a max-bundle policy on the offering webrtcbin,
|
||||||
|
* this means that all the offered medias should be part
|
||||||
|
* of the group:BUNDLE attribute, and they should be marked
|
||||||
|
* as bundle-only
|
||||||
|
*/
|
||||||
|
BundleCheckData offer_data = {
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
bundle,
|
||||||
|
offer_bundle_only,
|
||||||
|
};
|
||||||
|
/* We also set a max-bundle policy on the answering webrtcbin,
|
||||||
|
* this means that all the offered medias should be part
|
||||||
|
* of the group:BUNDLE attribute, but need not be marked
|
||||||
|
* as bundle-only.
|
||||||
|
*/
|
||||||
|
BundleCheckData answer_data = {
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
bundle,
|
||||||
|
answer_bundle_only,
|
||||||
|
};
|
||||||
|
struct validate_sdp offer = { _check_bundled_sdp_media, &offer_data };
|
||||||
|
struct validate_sdp answer = { _check_bundled_sdp_media, &answer_data };
|
||||||
|
|
||||||
|
gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
|
||||||
|
"max-bundle");
|
||||||
|
gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
|
||||||
|
"max-bundle");
|
||||||
|
|
||||||
|
t->on_negotiation_needed = NULL;
|
||||||
|
t->offer_data = &offer;
|
||||||
|
t->on_offer_created = validate_sdp;
|
||||||
|
t->answer_data = &answer;
|
||||||
|
t->on_answer_created = validate_sdp;
|
||||||
|
t->on_ice_candidate = NULL;
|
||||||
|
|
||||||
|
fail_if (gst_element_set_state (t->webrtc1,
|
||||||
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
||||||
|
fail_if (gst_element_set_state (t->webrtc2,
|
||||||
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
|
||||||
|
|
||||||
|
g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
|
||||||
|
&channel);
|
||||||
|
|
||||||
|
test_webrtc_create_offer (t, t->webrtc1);
|
||||||
|
|
||||||
|
test_webrtc_wait_for_answer_error_eos (t);
|
||||||
|
fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
|
||||||
|
|
||||||
|
g_object_unref (channel);
|
||||||
|
test_webrtc_free (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
webrtcbin_suite (void)
|
webrtcbin_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -2101,6 +2431,9 @@ webrtcbin_suite (void)
|
||||||
tcase_add_test (tc, test_add_recvonly_transceiver);
|
tcase_add_test (tc, test_add_recvonly_transceiver);
|
||||||
tcase_add_test (tc, test_recvonly_sendonly);
|
tcase_add_test (tc, test_recvonly_sendonly);
|
||||||
tcase_add_test (tc, test_payload_types);
|
tcase_add_test (tc, test_payload_types);
|
||||||
|
tcase_add_test (tc, test_bundle_audio_video_max_bundle_max_bundle);
|
||||||
|
tcase_add_test (tc, test_bundle_audio_video_max_bundle_none);
|
||||||
|
tcase_add_test (tc, test_bundle_audio_video_max_compat_max_bundle);
|
||||||
if (sctpenc && sctpdec) {
|
if (sctpenc && sctpdec) {
|
||||||
tcase_add_test (tc, test_data_channel_create);
|
tcase_add_test (tc, test_data_channel_create);
|
||||||
tcase_add_test (tc, test_data_channel_remote_notify);
|
tcase_add_test (tc, test_data_channel_remote_notify);
|
||||||
|
@ -2110,6 +2443,7 @@ webrtcbin_suite (void)
|
||||||
tcase_add_test (tc, test_data_channel_low_threshold);
|
tcase_add_test (tc, test_data_channel_low_threshold);
|
||||||
tcase_add_test (tc, test_data_channel_max_message_size);
|
tcase_add_test (tc, test_data_channel_max_message_size);
|
||||||
tcase_add_test (tc, test_data_channel_pre_negotiated);
|
tcase_add_test (tc, test_data_channel_pre_negotiated);
|
||||||
|
tcase_add_test (tc, test_bundle_audio_video_data);
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING ("Some required elements were not found. "
|
GST_WARNING ("Some required elements were not found. "
|
||||||
"All datachannel are disabled. sctpenc %p, sctpdec %p", sctpenc,
|
"All datachannel are disabled. sctpenc %p, sctpdec %p", sctpenc,
|
||||||
|
|
Loading…
Reference in a new issue