diff --git a/local/owr_video_renderer.c b/local/owr_video_renderer.c index d8898deb..767aeb3e 100644 --- a/local/owr_video_renderer.c +++ b/local/owr_video_renderer.c @@ -393,7 +393,10 @@ static GstCaps *owr_video_renderer_get_caps(OwrMediaRenderer *renderer) static GstElement *owr_video_renderer_get_sink(OwrMediaRenderer *renderer) { OWR_UNUSED(renderer); - return gst_element_factory_make(VIDEO_SINK, "video-renderer-sink"); + GstElement *result; + result = gst_element_factory_make(VIDEO_SINK, "video-renderer-sink"); + g_object_set(result, "sync", FALSE, NULL); + return result; } void _owr_video_renderer_notify_tag_changed(OwrVideoRenderer *video_renderer, const gchar *tag, gboolean have_handle, guintptr new_handle) diff --git a/tests/test_send_receive.c b/tests/test_send_receive.c index 35fb0c77..7afd6352 100644 --- a/tests/test_send_receive.c +++ b/tests/test_send_receive.c @@ -46,6 +46,10 @@ #include +typedef struct{ + OwrTransportAgent *snd, *rcv; +}TransportAgents; + static OwrTransportAgent *recv_transport_agent = NULL; static OwrMediaSession *recv_session_audio = NULL; static OwrMediaSession *recv_session_video = NULL; @@ -341,6 +345,15 @@ static gboolean dump_cb(gpointer *user_data) return G_SOURCE_REMOVE; } +static gboolean add_subflow(gpointer *user_data) +{ + g_print("Add subflow to the pipeline!\n"); + TransportAgents *agents = user_data; + owr_transport_agent_join_rcv_subflow(agents->rcv, 5720); + owr_transport_agent_join_snd_subflow(agents->snd, "127.0.0.1", 5720); + return G_SOURCE_REMOVE; +} + static const gchar *message_origin_name_func(gpointer origin) { if (!origin) { @@ -378,11 +391,11 @@ static const gchar *message_origin_name_func(gpointer origin) } } - int main(int argc, char **argv) { GOptionContext *options; GError *error = NULL; + TransportAgents agents; options = g_option_context_new(NULL); g_option_context_add_main_entries(options, entries, NULL); @@ -412,7 +425,7 @@ int main(int argc, char **argv) owr_bus_add_message_origin(bus, OWR_MESSAGE_ORIGIN(owr_window_registry_get())); - recv_transport_agent = owr_transport_agent_new(FALSE); + agents.rcv = recv_transport_agent = owr_transport_agent_new(FALSE); g_assert(OWR_IS_TRANSPORT_AGENT(recv_transport_agent)); owr_bus_add_message_origin(bus, OWR_MESSAGE_ORIGIN(recv_transport_agent)); @@ -423,7 +436,7 @@ int main(int argc, char **argv) owr_transport_agent_add_local_address(recv_transport_agent, local_addr); // SEND - send_transport_agent = owr_transport_agent_new(TRUE); + agents.snd = send_transport_agent = owr_transport_agent_new(TRUE); g_assert(OWR_IS_TRANSPORT_AGENT(send_transport_agent)); owr_bus_add_message_origin(bus, OWR_MESSAGE_ORIGIN(send_transport_agent)); @@ -503,6 +516,10 @@ int main(int argc, char **argv) g_timeout_add_seconds(10, (GSourceFunc)dump_cb, NULL); + //Todo: transport agent into one pointer. + g_timeout_add_seconds(10, (GSourceFunc)add_subflow, &agents); + + owr_run(); g_free(remote_addr); diff --git a/transport/owr_transport_agent.c b/transport/owr_transport_agent.c index 21e88cc6..b917eb64 100644 --- a/transport/owr_transport_agent.c +++ b/transport/owr_transport_agent.c @@ -97,6 +97,15 @@ static void owr_message_origin_interface_init(OwrMessageOriginInterface *interfa G_DEFINE_TYPE_WITH_CODE(OwrTransportAgent, owr_transport_agent, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(OWR_TYPE_MESSAGE_ORIGIN, owr_message_origin_interface_init)) + +typedef struct{ + guint8 id; + NiceAgent *agent; + GstElement *sink; + GstElement *src; + OwrTransportAgent *parent; +}Subflow; + typedef struct { OwrDataChannelState state; GstElement *data_sink, *data_src; @@ -123,6 +132,7 @@ typedef struct { typedef struct { GstElement *nice_src_rtp, *dtls_dec_rtp; + GstElement *mprtp_rcv; gulong nice_src_block_rtp; GstElement *nice_src_rtcp, *dtls_dec_rtcp; @@ -163,6 +173,14 @@ struct _OwrTransportAgentPrivate { GRWLock data_channels_rw_mutex; gboolean data_session_added, data_session_established; OwrMessageOriginBusSet *message_origin_bus_set; + + GstElement *mprtp_sch; + GstElement *mprtp_snd; + GstElement *mprtp_rcv; + GstElement *mprtp_ply; + GHashTable *subflows; + guint mprtp_actual_subflow_id_index; + gboolean mprtp_subflow_id_overflow_detected; }; typedef struct { @@ -360,7 +378,7 @@ static void owr_message_origin_interface_init(OwrMessageOriginInterface *interfa interface->get_bus_set = owr_transport_agent_get_bus_set; } -/* FIXME: Copy from owr/orw.c without any error handling whatsoever */ +/* _FIXME: Copy from owr/orw.c without any error handling whatsoever */ static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer user_data) { gboolean ret, is_warning = FALSE; @@ -510,6 +528,209 @@ static void owr_transport_agent_init(OwrTransportAgent *transport_agent) priv->send_bins = g_hash_table_new_full(NULL, NULL, NULL, g_free); priv->message_origin_bus_set = owr_message_origin_bus_set_new(); + priv->subflows = g_hash_table_new_full(NULL, NULL, NULL, g_free); +} + + + +static guint8 get_new_subflow_id(OwrTransportAgent *transport_agent) +{ + Subflow *subflow; + gpointer val,key; + gboolean reserved[255]; + guint result,i; + GHashTableIter iter; + + if(transport_agent->priv->mprtp_actual_subflow_id_index == 255){ + transport_agent->priv->mprtp_subflow_id_overflow_detected = TRUE; + } + + if(!transport_agent->priv->mprtp_subflow_id_overflow_detected){ + if(transport_agent->priv->mprtp_actual_subflow_id_index == 0){ + transport_agent->priv->mprtp_actual_subflow_id_index = 2; + } + result = transport_agent->priv->mprtp_actual_subflow_id_index++; + goto done; + } + + g_hash_table_iter_init (&iter, transport_agent->priv->subflows); + while (g_hash_table_iter_next (&iter, (gpointer) & key, (gpointer) & val)) { + subflow = (Subflow *) val; + reserved[subflow->id] = TRUE; + } + + for(i=2; i<255; ++i){ + if(reserved[i] == FALSE){ + result = i; + goto done; + } + } + result = 0; +done: + return result; +} + + +guint8 owr_transport_agent_join_snd_subflow(OwrTransportAgent *transport_agent, + const gchar *remote_address, + guint port) +{ + + Subflow *subflow; + GstElement *udpsink; + gchar *padname; + gchar *element_name; + gboolean synced_ok; + OwrTransportAgentPrivate *priv; + guint8 subflow_id = 0; + + g_return_val_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent), 0); + g_return_val_if_fail(remote_address, 0); + + subflow_id = get_new_subflow_id(transport_agent); + g_return_val_if_fail(subflow_id > 0, 0); + + priv = transport_agent->priv; + + + subflow = (Subflow*) g_hash_table_lookup(priv->subflows, GUINT_TO_POINTER(subflow_id)); + if(subflow == NULL){ + subflow = g_malloc0(sizeof(Subflow)); + g_hash_table_insert(transport_agent->priv->subflows, + GINT_TO_POINTER(subflow_id), subflow); + + } + + element_name = g_strdup_printf("subflow-rtc-udpsink-%hhu", subflow_id); + subflow->sink = udpsink = gst_element_factory_make("udpsink", element_name); + g_free(element_name); + + if (!gst_bin_add(GST_BIN(transport_agent->priv->transport_bin), + udpsink)) { + GST_WARNING("Failed to add udpsrc-rtc to parent bin"); + return subflow_id; + } + + g_object_set (udpsink, "port", port, "host", remote_address, "sync", + FALSE, "async", FALSE, NULL); + + padname = g_strdup_printf("src_%hhu", subflow_id); + gst_element_link_pads(priv->mprtp_snd, padname, udpsink, "sink"); + g_free(padname); + + g_object_set(priv->mprtp_sch, "join-subflow", subflow_id, NULL); + + synced_ok = gst_element_sync_state_with_parent(udpsink); + g_warn_if_fail(synced_ok); + + return subflow_id; +} + + +void owr_transport_agent_detach_snd_subflow(OwrTransportAgent *transport_agent, + guint8 subflow_id) +{ + + Subflow *subflow; + OwrTransportAgentPrivate *priv; + + g_return_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent)); + + priv = transport_agent->priv; + + subflow = (Subflow*) g_hash_table_lookup(priv->subflows, GUINT_TO_POINTER(subflow_id)); + if(subflow == NULL){ + GST_WARNING("Not existed subflow (%d) requested to detach at sending part", subflow_id); + return; + } + + g_object_set(priv->mprtp_sch, "detach-subflow", subflow_id, NULL); + gst_element_set_state(subflow->sink, GST_STATE_NULL); + if (!gst_bin_remove(GST_BIN(transport_agent->priv->transport_bin), subflow->sink)) { + GST_WARNING("Failed to remove sink for subflow %d", subflow_id); + } + subflow->sink = NULL; + if(subflow->src == NULL){ + g_hash_table_remove(priv->subflows, GUINT_TO_POINTER(subflow_id)); + } +} + +guint8 owr_transport_agent_join_rcv_subflow(OwrTransportAgent *transport_agent, + guint port) +{ + Subflow *subflow; + GstElement *udpsrc; + gchar *padname; + gchar *element_name; + gboolean synced_ok; + OwrTransportAgentPrivate *priv; + guint8 subflow_id = 0; + + g_return_val_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent), 0); + subflow_id = get_new_subflow_id(transport_agent); + g_return_val_if_fail(subflow_id > 0, 0); + + priv = transport_agent->priv; + + subflow = (Subflow*) g_hash_table_lookup(priv->subflows, GUINT_TO_POINTER(subflow_id)); + if(subflow == NULL){ + subflow = g_malloc0(sizeof(Subflow)); + g_hash_table_insert(transport_agent->priv->subflows, + GINT_TO_POINTER(subflow_id), subflow); + } + + element_name = g_strdup_printf("subflow-udpsrc-%hhu", subflow_id); + subflow->src = udpsrc = gst_element_factory_make("udpsrc", element_name); + g_free(element_name); + + if (!gst_bin_add(GST_BIN(transport_agent->priv->transport_bin), + udpsrc)) { + GST_WARNING("Failed to add udpsrc-rtc to parent bin"); + return subflow_id; + } + + g_object_set (udpsrc, "port", port, NULL); + + padname = g_strdup_printf("sink_%hhu", subflow_id); + gst_element_link_pads(udpsrc, "src", priv->mprtp_rcv, padname); + g_free(padname); + + g_object_set(priv->mprtp_ply, "join-subflow", subflow_id, NULL); + + synced_ok = gst_element_sync_state_with_parent(udpsrc); + g_warn_if_fail(synced_ok); + + return subflow_id; +} + + +void owr_transport_agent_detach_rcv_subflow(OwrTransportAgent *transport_agent, + guint8 subflow_id) +{ + + Subflow *subflow; + OwrTransportAgentPrivate *priv; + + g_return_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent)); + + priv = transport_agent->priv; + + subflow = (Subflow*) g_hash_table_lookup(priv->subflows, GUINT_TO_POINTER(subflow_id)); + if(subflow == NULL){ + GST_WARNING("Not existed subflow (%d) requested to detach at sending part", subflow_id); + return; + } + + g_object_set(priv->mprtp_ply, "detach-subflow", subflow_id, NULL); + gst_element_set_state(subflow->src, GST_STATE_NULL); + if (!gst_bin_remove(GST_BIN(transport_agent->priv->transport_bin), subflow->src)) { + GST_WARNING("Failed to remove src for subflow %d", subflow_id); + } + + subflow->src = NULL; + if(subflow->sink == NULL){ + g_hash_table_remove(priv->subflows, GUINT_TO_POINTER(subflow_id)); + } } @@ -816,7 +1037,7 @@ static void handle_new_send_source(OwrTransportAgent *transport_agent, return; } - /* FIXME - communicate what codec types are supported by the source + /* _FIXME - communicate what codec types are supported by the source * and if one is reusable, use it, else raw? g_object_get(send_payload, "codec-type", &codec_type, NULL); */ @@ -1381,6 +1602,118 @@ static void on_bitrate_change(GstElement *scream_queue, guint bitrate, guint ssr _owr_schedule_with_hash_table((GSourceFunc)emit_bitrate_change, args); } + +static GstElement *add_mprtp_scheduler_element( + OwrTransportAgent *transport_agent, + guint stream_id, + gboolean for_datastream, + GstElement *bin) +{ + GstElement *mprtp_sch = NULL; + gchar *element_name; + gboolean added_ok; + + g_return_val_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent), NULL); + + element_name = g_strdup_printf("mprtp_sch_%s_%d", + for_datastream ? "datastr" : "rtcstr", + stream_id); + + mprtp_sch = gst_element_factory_make("mprtpscheduler", element_name); + + g_object_set(mprtp_sch, "join-subflow", 1, NULL); + + added_ok = gst_bin_add(GST_BIN(bin), mprtp_sch); + g_warn_if_fail(added_ok); + + g_free(element_name); + + return mprtp_sch; +} + + +static GstElement *add_mprtp_plaoyouter_element( + OwrTransportAgent *transport_agent, + guint stream_id, + gboolean for_datastream, + GstElement *bin) +{ + GstElement *mprtp_sch = NULL; + gchar *element_name; + gboolean added_ok; + + g_return_val_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent), NULL); + + element_name = g_strdup_printf("mprtp_ply_%s_%d", + for_datastream ? "datastr" : "rtcstr", + stream_id); + + mprtp_sch = gst_element_factory_make("mprtpplayouter", element_name); + + g_object_set(mprtp_sch, "join-subflow", 1, NULL); + + added_ok = gst_bin_add(GST_BIN(bin), mprtp_sch); + g_warn_if_fail(added_ok); + + g_free(element_name); + + return mprtp_sch; +} + + +static GstElement *add_mprtp_receiver_element(OwrTransportAgent *transport_agent, + guint stream_id, + gboolean for_datastream, + GstElement *bin) +{ + GstElement *mprtp_rcv = NULL; + gchar *element_name; + gboolean added_ok; + + g_return_val_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent), NULL); + + element_name = g_strdup_printf("mprtp_rcv_%s_%d", + for_datastream ? "datastr" : "rtcstr", + stream_id); + + mprtp_rcv = gst_element_factory_make("mprtpreceiver", element_name); + + added_ok = gst_bin_add(GST_BIN(bin), mprtp_rcv); + g_warn_if_fail(added_ok); + + g_free(element_name); + + return mprtp_rcv; +} + + + +static GstElement *add_mprtp_sender_element( + OwrTransportAgent *transport_agent, + guint stream_id, + gboolean for_datastream, + GstElement *bin) +{ + GstElement *mprtp_snd = NULL; + gchar *element_name; + gboolean added_ok; + + g_return_val_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent), NULL); + + element_name = g_strdup_printf("mprtp_snd_%s_%d", + for_datastream ? "datastr" : "rtcstr", + stream_id); + + mprtp_snd = gst_element_factory_make("mprtpsender", element_name); + + added_ok = gst_bin_add(GST_BIN(bin), mprtp_snd); + g_warn_if_fail(added_ok); + + g_free(element_name); + + return mprtp_snd; +} + static void link_rtpbin_to_send_output_bin(OwrTransportAgent *transport_agent, guint stream_id, gboolean rtp, gboolean rtcp) { gchar *rtpbin_pad_name, *dtls_srtp_pad_name; @@ -1413,7 +1746,7 @@ static void link_rtpbin_to_send_output_bin(OwrTransportAgent *transport_agent, g g_assert(scream_queue); g_signal_connect_object(scream_queue, "on-bitrate-change", G_CALLBACK(on_bitrate_change), media_session, 0); - /* TODO: Move connect to prepare_transport_bin_send_elements */ + /* _TODO: Move connect to prepare_transport_bin_send_elements */ /* RTP */ if (rtp) { @@ -1500,6 +1833,7 @@ static void prepare_transport_bin_send_elements(OwrTransportAgent *transport_age gchar *bin_name, *dtls_srtp_pad_name; OwrMediaSession *media_session; AgentAndSessionIdPair *agent_and_session_id_pair; + GstElement* mprtp_sch, *mprtp_snd; g_return_if_fail(OWR_IS_TRANSPORT_AGENT(transport_agent)); @@ -1520,14 +1854,22 @@ static void prepare_transport_bin_send_elements(OwrTransportAgent *transport_age media_session = OWR_MEDIA_SESSION(get_session(transport_agent, stream_id)); scream_queue = gst_element_factory_make("screamqueue", "screamqueue"); g_assert(scream_queue); + mprtp_sch = add_mprtp_scheduler_element(transport_agent, stream_id, FALSE, send_output_bin); + g_assert(mprtp_sch); + mprtp_snd = add_mprtp_sender_element(transport_agent, stream_id, FALSE, send_output_bin); + g_assert(mprtp_snd); + g_object_set(scream_queue, "scream-controller-id", transport_agent->priv->agent_id, NULL); g_signal_connect(scream_queue, "on-payload-adaptation-request", (GCallback)on_payload_adaptation_request, media_session); gst_bin_add(GST_BIN(send_output_bin), scream_queue); + //Todo: Add mprtp sender here. <-Theoretically done. pending_session_info->nice_sink_rtp = nice_element = add_nice_element(transport_agent, stream_id, TRUE, FALSE, send_output_bin); pending_session_info->dtls_enc_rtp = dtls_srtp_bin_rtp = add_dtls_srtp_bin(transport_agent, stream_id, TRUE, FALSE, send_output_bin); - linked_ok = gst_element_link(dtls_srtp_bin_rtp, nice_element); + linked_ok = gst_element_link_pads(dtls_srtp_bin_rtp, "src", mprtp_snd, "mprtp_sink"); + g_warn_if_fail(linked_ok); + linked_ok = gst_element_link_pads(mprtp_snd, "src_1", nice_element, "sink"); g_warn_if_fail(linked_ok); agent_and_session_id_pair = g_new0(AgentAndSessionIdPair, 1); @@ -1535,11 +1877,21 @@ static void prepare_transport_bin_send_elements(OwrTransportAgent *transport_age agent_and_session_id_pair->session_id = stream_id; g_signal_connect_data(dtls_srtp_bin_rtp, "on-key-set", G_CALLBACK(on_dtls_enc_key_set), agent_and_session_id_pair, (GClosureNotify) g_free, 0); + //Todo: Link mprtp scheduler here. <-Theoretically done. dtls_srtp_pad_name = g_strdup_printf("rtp_sink_%u", stream_id); - linked_ok = gst_element_link_pads(scream_queue, "src", dtls_srtp_bin_rtp, dtls_srtp_pad_name); + linked_ok = gst_element_link_pads(scream_queue, "src", + mprtp_sch, "rtp_sink"); + linked_ok = gst_element_link_pads(mprtp_sch, "mprtp_src", + dtls_srtp_bin_rtp, dtls_srtp_pad_name); g_free(dtls_srtp_pad_name); g_warn_if_fail(linked_ok); + //Todo: Sync mprtp scheduler here. <-Theoretically done. + g_warn_if_fail(linked_ok); + synced_ok = gst_element_sync_state_with_parent(mprtp_snd); + g_warn_if_fail(synced_ok); + synced_ok = gst_element_sync_state_with_parent(mprtp_sch); + g_warn_if_fail(synced_ok); synced_ok = gst_element_sync_state_with_parent(nice_element); g_warn_if_fail(synced_ok); synced_ok = gst_element_sync_state_with_parent(scream_queue); @@ -1566,6 +1918,9 @@ static void prepare_transport_bin_send_elements(OwrTransportAgent *transport_age send_bin_info->send_output_bin = send_output_bin; send_bin_info->linked_rtcp = FALSE; + transport_agent->priv->mprtp_sch = mprtp_sch; + transport_agent->priv->mprtp_snd = mprtp_snd; + g_hash_table_insert(transport_agent->priv->send_bins, GINT_TO_POINTER(stream_id), send_bin_info); } @@ -1588,6 +1943,7 @@ static void prepare_transport_bin_receive_elements(OwrTransportAgent *transport_ gboolean linked_ok, synced_ok; GstElement *receive_input_bin; ScreamRx *scream_rx; + GstElement *mprtp_ply, *mprtp_rcv; #ifdef TEST_RTX GstElement *identity; #endif @@ -1610,6 +1966,9 @@ static void prepare_transport_bin_receive_elements(OwrTransportAgent *transport_ return; } + transport_agent->priv->mprtp_rcv = mprtp_rcv = add_mprtp_receiver_element(transport_agent, stream_id, FALSE, receive_input_bin); + transport_agent->priv->mprtp_ply = mprtp_ply = add_mprtp_plaoyouter_element(transport_agent, stream_id, FALSE, receive_input_bin); + pending_session_info->mprtp_rcv = transport_agent->priv->mprtp_rcv; pending_session_info->nice_src_rtp = nice_element = add_nice_element(transport_agent, stream_id, FALSE, FALSE, receive_input_bin); pending_session_info->dtls_dec_rtp = dtls_srtp_bin = add_dtls_srtp_bin(transport_agent, stream_id, FALSE, FALSE, receive_input_bin); @@ -1620,10 +1979,20 @@ static void prepare_transport_bin_receive_elements(OwrTransportAgent *transport_ pending_session_info->nice_src_block_rtp = gst_pad_add_probe(nice_src_pad, GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST, (GstPadProbeCallback)nice_src_pad_block, agent_and_session_id_pair, (GDestroyNotify) g_free); gst_object_unref(nice_src_pad); + //Todo: Sync mprtp_rcv, mprtp_ply here. //<- Theoretically done synced_ok = gst_element_sync_state_with_parent(nice_element); g_warn_if_fail(synced_ok); + synced_ok = gst_element_sync_state_with_parent(mprtp_rcv); + g_warn_if_fail(synced_ok); + synced_ok = gst_element_sync_state_with_parent(mprtp_ply); + g_warn_if_fail(synced_ok); - rtp_src_pad = gst_element_get_static_pad(dtls_srtp_bin, "rtp_src"); + // +// rtp_src_pad = gst_element_get_static_pad(dtls_srtp_bin, "rtp_src"); +// ghost_pad_and_add_to_bin(rtp_src_pad, receive_input_bin, "rtp_src"); +// gst_object_unref(rtp_src_pad); + gst_element_link_pads(dtls_srtp_bin, "rtp_src", mprtp_ply, "mprtp_sink"); + rtp_src_pad = gst_element_get_static_pad(mprtp_ply, "mprtp_src"); ghost_pad_and_add_to_bin(rtp_src_pad, receive_input_bin, "rtp_src"); gst_object_unref(rtp_src_pad); @@ -2011,7 +2380,10 @@ static void on_new_selected_pair(NiceAgent *nice_agent, GstPad *pad; gboolean sync_ok, link_ok; - link_ok = gst_element_link(pending_session_info->nice_src_rtp, pending_session_info->dtls_dec_rtp); +// link_ok = gst_element_link(pending_session_info->nice_src_rtp, pending_session_info->dtls_dec_rtp); + link_ok = gst_element_link_pads(pending_session_info->nice_src_rtp, "src", pending_session_info->mprtp_rcv, "sink_1"); + g_warn_if_fail(link_ok); + link_ok = gst_element_link_pads(pending_session_info->mprtp_rcv, "mprtp_src", pending_session_info->dtls_dec_rtp, "sink"); g_warn_if_fail(link_ok); gst_element_set_locked_state(pending_session_info->dtls_dec_rtp, FALSE); @@ -2089,7 +2461,7 @@ on_dtls_enc_key_set(GstElement *dtls_srtp_enc, AgentAndSessionIdPair *data) */ g_mutex_lock(&transport_agent->priv->sessions_lock); pending_session_info = g_hash_table_lookup(transport_agent->priv->pending_sessions, GUINT_TO_POINTER(stream_id)); - /* FIXME: What to do about RTCP? It's not guaranteed to ever be enabled if + /* _FIXME: What to do about RTCP? It's not guaranteed to ever be enabled if * RTCP muxing is used but the usage wasn't known beforehand */ if (pending_session_info && dtls_srtp_enc == pending_session_info->dtls_enc_rtp) { @@ -2829,7 +3201,7 @@ static GstElement * on_rtpbin_request_aux_receiver(G_GNUC_UNUSED GstElement *rtp g_object_set(rtxrecv, "payload-type-map", pt_map, NULL); gst_structure_free(pt_map); - /* FIXME: how do we get rtx-time? */ + /* _FIXME: how do we get rtx-time? */ return create_aux_bin("rtprtxrecv", rtxrecv, session_id); @@ -3488,7 +3860,7 @@ static GstFlowReturn new_data_callback(GstAppSink *appsink, OwrTransportAgent *t break; case OWR_DATA_CHANNEL_PPID_BINARY_PARTIAL: g_warning("PPID: DATA_CHANNEL_PPID_BINARY_PARTIAL - Deprecated - Not supported"); - /* TODO: Seems like chrome is using this.. maybe it should be supported to at least receive + /* _TODO: Seems like chrome is using this.. maybe it should be supported to at least receive * this kind of messages even if it is deprecated?. */ break; case OWR_DATA_CHANNEL_PPID_BINARY: @@ -3496,7 +3868,7 @@ static GstFlowReturn new_data_callback(GstAppSink *appsink, OwrTransportAgent *t break; case OWR_DATA_CHANNEL_PPID_STRING_PARTIAL: g_warning("PPID: DATA_CHANNEL_PPID_STRING_PARTIAL - Deprecated - Not supported"); - /* TODO: Seems like chrome is using this.. maybe it should be supported to at least receive + /* _TODO: Seems like chrome is using this.. maybe it should be supported to at least receive * this kind of messages even if it is deprecated? */ break; default: @@ -4199,7 +4571,7 @@ static void on_feedback_rtcp(GObject *session, guint type, guint fbtype, guint s n_loss = GST_READ_UINT8(fci_buf + 2); n_ecn = GST_READ_UINT8(fci_buf + 3); timestamp = GST_READ_UINT32_BE(fci_buf + 4); - /* TODO: Fix qbit */ + /* _TODO: Fix qbit */ gst_buffer_unmap(fci, &info); g_signal_emit_by_name(scream_queue, "incoming-feedback", media_ssrc, timestamp, highest_seq, n_loss, n_ecn, qbit); diff --git a/transport/owr_transport_agent.h b/transport/owr_transport_agent.h index 950e4b4b..88fd4e0e 100644 --- a/transport/owr_transport_agent.h +++ b/transport/owr_transport_agent.h @@ -77,6 +77,15 @@ void owr_transport_agent_set_local_port_range(OwrTransportAgent *transport_agent void owr_transport_agent_add_session(OwrTransportAgent *agent, OwrSession *session); gchar * owr_transport_agent_get_dot_data(OwrTransportAgent *transport_agent); +guint8 owr_transport_agent_join_snd_subflow(OwrTransportAgent *transport_agent, + const gchar *remote_address, + guint port); +void owr_transport_agent_detach_snd_subflow(OwrTransportAgent *transport_agent, + guint8 subflow_id); +guint8 owr_transport_agent_join_rcv_subflow(OwrTransportAgent *transport_agent, + guint port); +void owr_transport_agent_detach_rcv_subflow(OwrTransportAgent *transport_agent, + guint8 subflow_id); G_END_DECLS #endif /* __OWR_TRANSPORT_AGENT_H__ */