From fdd710fa5d225df0f1df5a1e8b9d84913558fd29 Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Wed, 18 May 2016 14:03:03 +0900 Subject: [PATCH 01/16] Inherit code for start_preroll/start_prepare - change function name (start_preroll -> default_start_preroll, start_prepare -> default_start_prepare) - add vmethod named start_preroll/start_prepare - lastly, link between default function and vmethod like other vmethod. Signed-off-by: SeokHoon Lee Change-Id: I53fe20ed0a0f4b0e0adf8f09d23baf65e6b0d765 --- gst/rtsp-server/rtsp-media.c | 29 +++++++++++++++++++++-------- gst/rtsp-server/rtsp-media.h | 2 ++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 5a6f758..f659091 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -196,6 +196,7 @@ static gboolean default_handle_message (GstRTSPMedia * media, GstMessage * message); static void finish_unprepare (GstRTSPMedia * media); static gboolean default_prepare (GstRTSPMedia * media, GstRTSPThread * thread); +static gboolean default_start_preroll (GstRTSPMedia * media); static gboolean default_unprepare (GstRTSPMedia * media); static gboolean default_suspend (GstRTSPMedia * media); static gboolean default_unsuspend (GstRTSPMedia * media); @@ -208,6 +209,7 @@ static GstElement *default_create_rtpbin (GstRTSPMedia * media); static gboolean default_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp, GstSDPInfo * info); static gboolean default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp); +static gboolean default_start_prepare (GstRTSPMedia * media); static gboolean wait_preroll (GstRTSPMedia * media); @@ -364,6 +366,7 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass) klass->handle_message = default_handle_message; klass->prepare = default_prepare; + klass->start_preroll = default_start_preroll; klass->unprepare = default_unprepare; klass->suspend = default_suspend; klass->unsuspend = default_unsuspend; @@ -373,6 +376,7 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass) klass->create_rtpbin = default_create_rtpbin; klass->setup_sdp = default_setup_sdp; klass->handle_sdp = default_handle_sdp; + klass->start_prepare = default_start_prepare; } static void @@ -2394,7 +2398,7 @@ struct _DynPaySignalHandlers }; static gboolean -start_preroll (GstRTSPMedia * media) +default_start_preroll (GstRTSPMedia * media) { GstRTSPMediaPrivate *priv = media->priv; GstStateChangeReturn ret; @@ -2481,12 +2485,15 @@ request_aux_sender (GstElement * rtpbin, guint sessid, GstRTSPMedia * media) } static gboolean -start_prepare (GstRTSPMedia * media) +default_start_prepare (GstRTSPMedia * media) { GstRTSPMediaPrivate *priv = media->priv; + GstRTSPMediaClass *klass; guint i; GList *walk; + klass = GST_RTSP_MEDIA_GET_CLASS (media); + /* link streams we already have, other streams might appear when we have * dynamic elements */ for (i = 0; i < priv->streams->len; i++) { @@ -2532,8 +2539,9 @@ start_prepare (GstRTSPMedia * media) } } - if (!start_preroll (media)) - goto preroll_failed; + if (klass->start_preroll) + if(!klass->start_preroll (media)) + goto preroll_failed; return FALSE; @@ -2603,8 +2611,9 @@ default_prepare (GstRTSPMedia * media, GstRTSPThread * thread) /* do remainder in context */ source = g_idle_source_new (); - g_source_set_callback (source, (GSourceFunc) start_prepare, - g_object_ref (media), (GDestroyNotify) g_object_unref); + if(klass->start_prepare) + g_source_set_callback (source, (GSourceFunc) klass->start_prepare, + g_object_ref (media), (GDestroyNotify) g_object_unref); g_source_attach (source, context); g_source_unref (source); @@ -3821,6 +3830,9 @@ static gboolean default_unsuspend (GstRTSPMedia * media) { GstRTSPMediaPrivate *priv = media->priv; + GstRTSPMediaClass *klass; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); switch (priv->suspend_mode) { case GST_RTSP_SUSPEND_MODE_NONE: @@ -3832,8 +3844,9 @@ default_unsuspend (GstRTSPMedia * media) case GST_RTSP_SUSPEND_MODE_RESET: { gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING); - if (!start_preroll (media)) - goto start_failed; + if (klass->start_preroll) + if(!klass->start_preroll (media)) + goto start_failed; g_rec_mutex_unlock (&priv->state_lock); if (!wait_preroll (media)) diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index f1be13c..26d38d5 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -142,6 +142,7 @@ struct _GstRTSPMediaClass { /* vmethods */ gboolean (*handle_message) (GstRTSPMedia *media, GstMessage *message); gboolean (*prepare) (GstRTSPMedia *media, GstRTSPThread *thread); + gboolean (*start_preroll) (GstRTSPMedia *media); gboolean (*unprepare) (GstRTSPMedia *media); gboolean (*suspend) (GstRTSPMedia *media); gboolean (*unsuspend) (GstRTSPMedia *media); @@ -152,6 +153,7 @@ struct _GstRTSPMediaClass { GstElement * (*create_rtpbin) (GstRTSPMedia *media); gboolean (*setup_rtpbin) (GstRTSPMedia *media, GstElement *rtpbin); gboolean (*setup_sdp) (GstRTSPMedia *media, GstSDPMessage *sdp, GstSDPInfo *info); + gboolean (*start_prepare) (GstRTSPMedia *media); /* signals */ void (*new_stream) (GstRTSPMedia *media, GstRTSPStream * stream); -- 2.7.4 From 454ddee8481bf499e91a3597a79421a7f98522fe Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Fri, 27 May 2016 09:36:43 +0900 Subject: [PATCH 02/16] change function name - set_target_state -> gst_rtsp_media_set_target_state - delete static in function gst_rtsp_media_set_target_state, set_rtsp_media_set_status Signed-off-by: SeokHoon Lee Change-Id: I681092d03e9071831e5b0010818457c68b1446b1 --- gst/rtsp-server/rtsp-media.c | 16 ++++++++-------- gst/rtsp-server/rtsp-media.h | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 5a6f758..0b8c821 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -1811,7 +1811,7 @@ media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked) g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media); } -static void +void gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status) { GstRTSPMediaPrivate *priv = media->priv; @@ -2061,8 +2061,8 @@ set_state (GstRTSPMedia * media, GstState state) return ret; } -static GstStateChangeReturn -set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state) +GstStateChangeReturn +gst_rtsp_media_set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state) { GstRTSPMediaPrivate *priv = media->priv; GstStateChangeReturn ret; @@ -2401,7 +2401,7 @@ start_preroll (GstRTSPMedia * media) GST_INFO ("setting pipeline to PAUSED for media %p", media); /* first go to PAUSED */ - ret = set_target_state (media, GST_STATE_PAUSED, TRUE); + ret = gst_rtsp_media_set_target_state (media, GST_STATE_PAUSED, TRUE); switch (ret) { case GST_STATE_CHANGE_SUCCESS: @@ -2875,7 +2875,7 @@ gst_rtsp_media_unprepare (GstRTSPMedia * media) GST_INFO ("unprepare media %p", media); if (priv->blocked) media_streams_set_blocked (media, FALSE); - set_target_state (media, GST_STATE_NULL, FALSE); + gst_rtsp_media_set_target_state (media, GST_STATE_NULL, FALSE); success = TRUE; if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARED) { @@ -3722,14 +3722,14 @@ default_suspend (GstRTSPMedia * media) break; case GST_RTSP_SUSPEND_MODE_PAUSE: GST_DEBUG ("media %p suspend to PAUSED", media); - ret = set_target_state (media, GST_STATE_PAUSED, TRUE); + ret = gst_rtsp_media_set_target_state (media, GST_STATE_PAUSED, TRUE); if (ret == GST_STATE_CHANGE_FAILURE) goto state_failed; unblock = TRUE; break; case GST_RTSP_SUSPEND_MODE_RESET: GST_DEBUG ("media %p suspend to NULL", media); - ret = set_target_state (media, GST_STATE_NULL, TRUE); + ret = gst_rtsp_media_set_target_state (media, GST_STATE_NULL, TRUE); if (ret == GST_STATE_CHANGE_FAILURE) goto state_failed; /* Because payloader needs to set the sequence number as @@ -3912,7 +3912,7 @@ media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state) gst_rtsp_media_unprepare (media); } else { GST_INFO ("state %s media %p", gst_element_state_get_name (state), media); - set_target_state (media, state, FALSE); + gst_rtsp_media_set_target_state (media, state, FALSE); /* when we are buffering, don't update the state yet, this will be done * when buffering finishes */ if (priv->buffering) { diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index f1be13c..10988f8 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -257,6 +257,8 @@ gboolean gst_rtsp_media_set_state (GstRTSPMedia *media, GstS GPtrArray *transports); void gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstState state); +GstStateChangeReturn gst_rtsp_media_set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state); +void gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status); G_END_DECLS -- 2.7.4 From eb5a99fb87006febc7793376e6da60d6d47968f4 Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Tue, 31 May 2016 14:01:52 +0900 Subject: [PATCH 03/16] code integration - add RTCP_STATS signal - midification for create socket code - add gst_rtsp_client_set_watch_flushing function Signed-off-by: SeokHoon Lee Change-Id: I0ce3273d9399f580f4035e9c6d752ccdb120a970 --- gst/rtsp-server/gstwfdmessage.h | 0 gst/rtsp-server/rtsp-client.c | 23 +++++++++++++++++++++++ gst/rtsp-server/rtsp-client.h | 1 + gst/rtsp-server/rtsp-server.c | 9 +++++++-- gst/rtsp-server/rtsp-server.h | 1 + gst/rtsp-server/rtsp-stream.c | 10 ++++++++++ 6 files changed, 42 insertions(+), 2 deletions(-) mode change 100755 => 100644 gst/rtsp-server/gstwfdmessage.h diff --git a/gst/rtsp-server/gstwfdmessage.h b/gst/rtsp-server/gstwfdmessage.h old mode 100755 new mode 100644 diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index 4f3212d..a600537 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -3944,3 +3944,26 @@ restart: return result; } + +/** + * gst_rtsp_client_set_watch_flushing: + * @client: a #GstRTSPClient + * @val: a boolean value + * + * sets watch flushing to @val on watch to accet/ignore new messages. + */ +void +gst_rtsp_client_set_watch_flushing (GstRTSPClient * client, gboolean val) +{ + GstRTSPClientPrivate *priv = NULL; + g_return_if_fail (GST_IS_RTSP_CLIENT (client)); + + priv = GST_RTSP_CLIENT_GET_PRIVATE (client); + + /* make sure we unblock/block the backlog and accept/don't accept new messages on the watch */ + if (priv->watch != NULL) + { + GST_INFO("Set watch flushing as %d", val); + gst_rtsp_watch_set_flushing (priv->watch, val); + } +} diff --git a/gst/rtsp-server/rtsp-client.h b/gst/rtsp-server/rtsp-client.h index 13fa2d1..2e6bbf7 100644 --- a/gst/rtsp-server/rtsp-client.h +++ b/gst/rtsp-server/rtsp-client.h @@ -171,6 +171,7 @@ GstRTSPResult gst_rtsp_client_handle_message (GstRTSPClient *client, GstRTSPResult gst_rtsp_client_send_message (GstRTSPClient * client, GstRTSPSession *session, GstRTSPMessage *message); +void gst_rtsp_client_set_watch_flushing (GstRTSPClient * client, gboolean val); /** * GstRTSPClientSessionFilterFunc: * @client: a #GstRTSPClient object diff --git a/gst/rtsp-server/rtsp-server.c b/gst/rtsp-server/rtsp-server.c index 45ae9db..144cb3a 100644 --- a/gst/rtsp-server/rtsp-server.c +++ b/gst/rtsp-server/rtsp-server.c @@ -230,6 +230,7 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass) GST_TYPE_RTSP_CLIENT); klass->create_client = default_create_client; + klass->create_socket = gst_rtsp_server_create_socket; GST_DEBUG_CATEGORY_INIT (rtsp_server_debug, "rtspserver", 0, "GstRTSPServer"); } @@ -1256,14 +1257,18 @@ gst_rtsp_server_create_source (GstRTSPServer * server, GCancellable * cancellable, GError ** error) { GstRTSPServerPrivate *priv; - GSocket *socket, *old; + GstRTSPServerClass *klass; + GSocket *socket = NULL, *old; GSource *source; g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); priv = server->priv; + klass = GST_RTSP_SERVER_GET_CLASS (server); + + if (klass->create_socket) + socket = klass->create_socket (server, NULL, error); - socket = gst_rtsp_server_create_socket (server, NULL, error); if (socket == NULL) goto no_socket; diff --git a/gst/rtsp-server/rtsp-server.h b/gst/rtsp-server/rtsp-server.h index 9a6f9d4..4cb0495 100644 --- a/gst/rtsp-server/rtsp-server.h +++ b/gst/rtsp-server/rtsp-server.h @@ -85,6 +85,7 @@ struct _GstRTSPServerClass { GObjectClass parent_class; GstRTSPClient * (*create_client) (GstRTSPServer *server); + GSocket * (*create_socket) (GstRTSPServer * server, GCancellable * cancellable, GError ** error); /* signals */ void (*client_connected) (GstRTSPServer *server, GstRTSPClient *client); diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c index a015346..ce2f5a4 100644 --- a/gst/rtsp-server/rtsp-stream.c +++ b/gst/rtsp-server/rtsp-stream.c @@ -184,6 +184,7 @@ enum { SIGNAL_NEW_RTP_ENCODER, SIGNAL_NEW_RTCP_ENCODER, + SIGNAL_RTCP_STATS, SIGNAL_LAST }; @@ -241,6 +242,11 @@ gst_rtsp_stream_class_init (GstRTSPStreamClass * klass) G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT); + gst_rtsp_stream_signals[SIGNAL_RTCP_STATS] = + g_signal_new ("rtcp-statistics", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_STRUCTURE); + GST_DEBUG_CATEGORY_INIT (rtsp_stream_debug, "rtspstream", 0, "GstRTSPStream"); ssrc_stream_map_key = g_quark_from_static_string ("GstRTSPServer.stream"); @@ -1594,6 +1600,8 @@ check_transport (GObject * source, GstRTSPStream * stream) dump_structure (stats); + g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_RTCP_STATS], 0, stats); + rtcp_from = gst_structure_get_string (stats, "rtcp-from"); if ((trans = find_transport (stream, rtcp_from))) { GST_INFO ("%p: found transport %p for source %p", stream, trans, @@ -1643,6 +1651,8 @@ on_ssrc_active (GObject * session, GObject * source, GstRTSPStream * stream) GstStructure *stats; g_object_get (source, "stats", &stats, NULL); if (stats) { + g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_RTCP_STATS], 0, stats); + dump_structure (stats); gst_structure_free (stats); } -- 2.7.4 From 348befdfd2e731a38c8638dc8ab96a7734c5692d Mon Sep 17 00:00:00 2001 From: "Hyunsoo, Park" Date: Fri, 28 Oct 2016 15:53:11 +0900 Subject: [PATCH 04/16] Add AL-FEC feature [Version] 1.6.1 [Profile] Common [Issue Type] Add feature [Dependency module] N/A [Depends-on] https://review.tizen.org/gerrit/#/c/94313/(Change-Id: Iec3ba16bd8b61b96415e39126e25c4286cd02dc4) [Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161025.2] Change-Id: I534d3acf3aa5f0114c2282b3ea80a7b0f51216cc Signed-off-by: Hyunsoo, Park --- gst/rtsp-server/Makefile.am | 8 +- gst/rtsp-server/gstwfdmessage-ext.c | 525 ++++++++++++++++++ gst/rtsp-server/gstwfdmessage-ext.h | 123 +++++ gst/rtsp-server/gstwfdmessage.c | 241 ++++---- gst/rtsp-server/rtsp-client-ext.c | 922 +++++++++++++++++++++++++++++++ gst/rtsp-server/rtsp-client-ext.h | 73 +++ gst/rtsp-server/rtsp-client-wfd.c | 441 +++++++++------ gst/rtsp-server/rtsp-client-wfd.h | 12 + gst/rtsp-server/rtsp-client.c | 7 +- gst/rtsp-server/rtsp-media-ext.c | 773 ++++++++++++++++++++++++++ gst/rtsp-server/rtsp-media-ext.h | 115 ++++ gst/rtsp-server/rtsp-media-factory-wfd.c | 210 +++++-- gst/rtsp-server/rtsp-media-factory-wfd.h | 9 + gst/rtsp-server/rtsp-media.c | 74 ++- gst/rtsp-server/rtsp-media.h | 5 + gst/rtsp-server/rtsp-server-wfd.c | 28 +- gst/rtsp-server/rtsp-stream.c | 8 +- packaging/gst-rtsp-server.spec | 2 +- 18 files changed, 3237 insertions(+), 339 deletions(-) create mode 100755 gst/rtsp-server/gstwfdmessage-ext.c create mode 100755 gst/rtsp-server/gstwfdmessage-ext.h create mode 100755 gst/rtsp-server/rtsp-client-ext.c create mode 100755 gst/rtsp-server/rtsp-client-ext.h mode change 100644 => 100755 gst/rtsp-server/rtsp-client-wfd.c create mode 100755 gst/rtsp-server/rtsp-media-ext.c create mode 100755 gst/rtsp-server/rtsp-media-ext.h mode change 100644 => 100755 gst/rtsp-server/rtsp-media-factory-wfd.c diff --git a/gst/rtsp-server/Makefile.am b/gst/rtsp-server/Makefile.am index 60eaf3e..aac53f0 100644 --- a/gst/rtsp-server/Makefile.am +++ b/gst/rtsp-server/Makefile.am @@ -5,6 +5,7 @@ public_headers = \ rtsp-params.h \ rtsp-sdp.h \ rtsp-thread-pool.h \ + rtsp-media-ext.h \ rtsp-media.h \ rtsp-media-factory.h \ rtsp-media-factory-wfd.h \ @@ -17,10 +18,12 @@ public_headers = \ rtsp-session-media.h \ rtsp-session-pool.h \ rtsp-token.h \ + rtsp-client-ext.h \ rtsp-client-wfd.h \ rtsp-client.h \ rtsp-server-wfd.h \ rtsp-server.h \ + gstwfdmessage-ext.h \ gstwfdmessage.h c_sources = \ @@ -30,6 +33,7 @@ c_sources = \ rtsp-params.c \ rtsp-sdp.c \ rtsp-thread-pool.c \ + rtsp-media-ext.c \ rtsp-media.c \ rtsp-media-factory.c \ rtsp-media-factory-wfd.c \ @@ -42,13 +46,15 @@ c_sources = \ rtsp-session-media.c \ rtsp-session-pool.c \ rtsp-token.c \ + gstwfdmessage-ext.c \ gstwfdmessage.c \ + rtsp-client-ext.c \ rtsp-client-wfd.c \ rtsp-client.c \ rtsp-server-wfd.c \ rtsp-server.c -noinst_HEADERS = +noinst_HEADERS = lib_LTLIBRARIES = \ libgstrtspserver-@GST_API_VERSION@.la diff --git a/gst/rtsp-server/gstwfdmessage-ext.c b/gst/rtsp-server/gstwfdmessage-ext.c new file mode 100755 index 0000000..d7d1ed4 --- /dev/null +++ b/gst/rtsp-server/gstwfdmessage-ext.c @@ -0,0 +1,525 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* + * Unless otherwise indicated, Source Code is licensed under MIT license. + * See further explanation attached in License Statement (distributed in the file + * LICENSE). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * SECTION:gstwfdmessage + * @short_description: Helper methods for dealing with WFD messages + * + * + * + * The GstWFDMessage helper functions makes it easy to parse and create WFD + * messages. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +//#include + +#include "gstwfdmessage-ext.h" + +#define FREE_STRING(field) g_free (field); (field) = NULL +#define REPLACE_STRING(field, val) FREE_STRING(field); (field) = g_strdup (val) + +G_DEFINE_BOXED_TYPE (GstWFDExtMessage, gst_wfd_ext_message, NULL, NULL); + +/** + * gst_wfd_ext_message_new: + * @msg: (out) (transfer full): pointer to new #GstWFDExtMessage + * + * Allocate a new GstWFDExtMessage and store the result in @msg. + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_ext_message_new (GstWFDExtMessage ** msg) +{ + GstWFDExtMessage *newmsg; + + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + newmsg = g_new0 (GstWFDExtMessage, 1); + + *msg = newmsg; + + return gst_wfd_ext_message_init (newmsg); +} + +/** + * gst_wfd_ext_message_init: + * @msg: a #GstWFDExtMessage + * + * Initialize @msg so that its contents are as if it was freshly allocated + * with gst_wfd_ext_message_new(). This function is mostly used to initialize a message + * allocated on the stack. gst_wfd_ext_message_uninit() undoes this operation. + * + * When this function is invoked on newly allocated data (with malloc or on the + * stack), its contents should be set to 0 before calling this function. + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_ext_message_init (GstWFDExtMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + return GST_WFD_OK; +} + +/** + * gst_wfd_ext_message_uninit: + * @msg: a #GstWFDExtMessage + * + * Free all resources allocated in @msg. @msg should not be used anymore after + * this function. This function should be used when @msg was allocated on the + * stack and initialized with gst_wfd_ext_message_init(). + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_ext_message_uninit (GstWFDExtMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (msg->tizen_retransmission) { + FREE_STRING (msg->tizen_retransmission); + } + + if (msg->tizen_fec) { + FREE_STRING (msg->tizen_fec); + } + + if (msg->tizen_latency_mode) { + FREE_STRING (msg->tizen_latency_mode); + } + + return GST_WFD_OK; +} + +static void +_read_string_space_ended (gchar * dest, guint size, gchar * src) +{ + guint idx = 0; + + while (!g_ascii_isspace (*src) && *src != '\0') { + if (idx < size - 1) + dest[idx++] = *src; + src++; + } + + if (size > 0) + dest[idx] = '\0'; + + return; +} + + +static void +_read_string_attr_and_value (gchar * attr, gchar * value, guint tsize, + guint vsize, gchar del, gchar * src) +{ + guint idx; + + idx = 0; + + while (*src != del && *src != '\0') { + if (idx < tsize - 1) + attr[idx++] = *src; + src++; + } + + if (tsize > 0) + attr[idx] = '\0'; + + src++; + idx = 0; + + while (*src != '\0') { + if (idx < vsize - 1) + value[idx++] = *src; + src++; + } + + if (vsize > 0) + value[idx] = '\0'; + + return; +} + +static void +gst_wfd_parse_attribute (gchar * buffer, GstWFDExtMessage * msg) +{ + gchar attr[8192] = { 0 }; + gchar value[8192] = { 0 }; + gchar temp[8192] = { 0 }; + gchar *p = buffer; + gchar *v = value; + +#define WFD_SKIP_SPACE(q) if (*q && g_ascii_isspace (*q)) q++ +#define WFD_SKIP_EQUAL(q) if (*q && *q == '=') q++ +#define WFD_SKIP_COMMA(q) if (*q && g_ascii_ispunct (*q)) q++ +#define WFD_READ_STRING(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); REPLACE_STRING (field, temp) +#define WFD_READ_UINT32(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 16) +#define WFD_READ_UINT32_DIGIT(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 10) + + _read_string_attr_and_value (attr, value, sizeof (attr), sizeof (value), ':', + p); + + if (!g_strcmp0 (attr, GST_STRING_TIZEN_WFD_RESTRANSMISSION)) { + msg->tizen_retransmission = g_new0 (GstWFDTizenRetransmission, 1); + if (strlen (v)) { + if (!strstr (v, "none")) { + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->tizen_retransmission->rtp_port); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->tizen_retransmission->rtcp_port); + } + } + } + else if (!g_strcmp0 (attr, GST_STRING_TIZEN_WFD_FEC)) { + msg->tizen_fec = g_new0 (GstWFDTizenFec, 1); + if (strlen (v)) { + if (!strstr (v, "none")) { + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->tizen_fec->t_max); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->tizen_fec->p_max); + } + } + } else if (!g_strcmp0 (attr, GST_STRING_TIZEN_WFD_LATENCY_MODE)) { + msg->tizen_latency_mode = g_new0 (GstWFDTizenLatencyMode, 1); + if (strlen (v)) { + if (strstr (v, GST_STRING_TIZEN_WFD_LATENCY_LOW)) { + msg->tizen_latency_mode->latency_mode = GST_WFD_TIZEN_LATENCY_LOW; + } else if (strstr (v, GST_STRING_TIZEN_WFD_LATENCY_MID)) { + msg->tizen_latency_mode->latency_mode = GST_WFD_TIZEN_LATENCY_MID; + } else if (strstr (v, GST_STRING_TIZEN_WFD_LATENCY_HIGH)) { + msg->tizen_latency_mode->latency_mode = GST_WFD_TIZEN_LATENCY_HIGH; + } else { + msg->tizen_latency_mode->latency_mode = GST_WFD_TIZEN_LATENCY_NONE; + } + } + } + + return; +} + +/** + * gst_wfd_ext_message_parse_buffer: + * @data: the start of the buffer + * @size: the size of the buffer + * @msg: the result #GstSDPMessage + * + * Parse the contents of @size bytes pointed to by @data and store the result in + * @msg. + * + * Returns: #GST_SDP_OK on success. + */ +GstWFDResult +gst_wfd_ext_message_parse_buffer (const guint8 * data, guint size, + GstWFDExtMessage * msg) +{ + gchar *p; + gchar buffer[255] = { 0 }; + guint idx = 0; + + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (data != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (size != 0, GST_WFD_EINVAL); + + p = (gchar *) data; + while (TRUE) { + + if (*p == '\0') + break; + + idx = 0; + while (*p != '\n' && *p != '\r' && *p != '\0') { + if (idx < sizeof (buffer) - 1) + buffer[idx++] = *p; + p++; + } + buffer[idx] = '\0'; + gst_wfd_parse_attribute (buffer, msg); + + if (*p == '\0') + break; + p += 2; + } + return GST_WFD_OK; +} + +/** + * gst_wfd_ext_message_free: + * @msg: a #GstWFDExtMessage + * + * Free all resources allocated by @msg. @msg should not be used anymore after + * this function. This function should be used when @msg was dynamically + * allocated with gst_wfd_ext_message_new(). + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_ext_message_free (GstWFDExtMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + gst_wfd_ext_message_uninit (msg); + g_free (msg); + + return GST_WFD_OK; +} + +/** + * gst_wfd_ext_message_as_text: + * @msg: a #GstWFDExtMessage + * + * Convert the contents of @msg to a text string. + * + * Returns: A dynamically allocated string representing the WFD description. + */ +gchar * +gst_wfd_ext_message_as_text (const GstWFDExtMessage * msg) +{ + /* change all vars so they match rfc? */ + GString *lines; + + g_return_val_if_fail (msg != NULL, NULL); + + lines = g_string_new (""); + + if (msg->tizen_retransmission) { + g_string_append_printf (lines, GST_STRING_TIZEN_WFD_RESTRANSMISSION); + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %d", msg->tizen_retransmission->rtp_port); + g_string_append_printf (lines, " %d", msg->tizen_retransmission->rtcp_port); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->tizen_fec) { + g_string_append_printf (lines, GST_STRING_TIZEN_WFD_FEC); + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %d", msg->tizen_fec->t_max); + g_string_append_printf (lines, " %d", msg->tizen_fec->p_max); + g_string_append_printf (lines, "\r\n"); + } + + if (msg->tizen_latency_mode) { + g_string_append_printf (lines, GST_STRING_TIZEN_WFD_LATENCY_MODE); + g_string_append_printf (lines, ":"); + + if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_LOW) + g_string_append_printf (lines, " " GST_STRING_TIZEN_WFD_LATENCY_LOW); + else if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_MID) + g_string_append_printf (lines, " " GST_STRING_TIZEN_WFD_LATENCY_MID); + else if (msg->tizen_latency_mode->latency_mode == + GST_WFD_TIZEN_LATENCY_HIGH) + g_string_append_printf (lines, " " GST_STRING_TIZEN_WFD_LATENCY_HIGH); + else + g_string_append_printf (lines, " none"); + + g_string_append_printf (lines, "\r\n"); + } + + return g_string_free (lines, FALSE); +} + +gchar * +gst_wfd_ext_message_param_names_as_text (const GstWFDExtMessage * msg) +{ + /* change all vars so they match rfc? */ + GString *lines; + g_return_val_if_fail (msg != NULL, NULL); + + lines = g_string_new (""); + + if (msg->tizen_retransmission) { + g_string_append_printf (lines, GST_STRING_TIZEN_WFD_RESTRANSMISSION); + g_string_append_printf (lines, "\r\n"); + } + if (msg->tizen_fec) { + g_string_append_printf (lines, GST_STRING_TIZEN_WFD_FEC); + g_string_append_printf (lines, "\r\n"); + } + if (msg->tizen_latency_mode) { + g_string_append_printf (lines, GST_STRING_TIZEN_WFD_LATENCY_MODE); + g_string_append_printf (lines, "\r\n"); + } + + return g_string_free (lines, FALSE); +} + +/** + * gst_wfd_ext_message_dump: + * @msg: a #GstWFDExtMessage + * + * Dump the parsed contents of @msg to stdout. + * + * Returns: a #GstWFDResult. + */ +GstWFDResult +gst_wfd_ext_message_dump (const GstWFDExtMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (msg->tizen_retransmission) { + g_print ("tizen_wfd_retransmission: %d %d", + msg->tizen_retransmission->rtp_port, + msg->tizen_retransmission->rtcp_port); + g_print ("\r\n"); + } + + if (msg->tizen_fec) { + g_print ("tizen_wfd_fec: %d %d", msg->tizen_fec->t_max, msg->tizen_fec->p_max); + g_print ("\r\n"); + } + + if (msg->tizen_latency_mode) { + g_print ("tizen_wfd_latency_mode:"); + + if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_LOW) + g_print (" low"); + else if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_MID) + g_print (" mid"); + else if (msg->tizen_latency_mode->latency_mode == GST_WFD_TIZEN_LATENCY_HIGH) + g_print (" high"); + else + g_print (" none"); + + g_print ("\r\n"); + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_ext_message_set_tizen_retransmission (GstWFDExtMessage * msg, + guint rtp_port, guint rtcp_port) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->tizen_retransmission) + msg->tizen_retransmission = g_new0 (GstWFDTizenRetransmission, 1); + + msg->tizen_retransmission->rtp_port = rtp_port; + msg->tizen_retransmission->rtcp_port = rtcp_port; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_ext_message_get_tizen_retransmission (GstWFDExtMessage * msg, + guint * rtp_port, guint * rtcp_port) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->tizen_retransmission != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (rtp_port != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (rtcp_port != NULL, GST_WFD_EINVAL); + + *rtp_port = msg->tizen_retransmission->rtp_port; + *rtcp_port = msg->tizen_retransmission->rtcp_port; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_ext_message_set_tizen_fec (GstWFDExtMessage * msg, guint t_max, + guint p_max) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->tizen_fec) + msg->tizen_fec = g_new0 (GstWFDTizenFec, 1); + + msg->tizen_fec->t_max = t_max; + msg->tizen_fec->p_max = p_max; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_ext_message_get_tizen_fec (GstWFDExtMessage * msg, guint * t_max, + guint * p_max) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->tizen_fec != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (t_max != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (p_max != NULL, GST_WFD_EINVAL); + + *t_max = msg->tizen_fec->t_max; + *p_max = msg->tizen_fec->p_max; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_ext_message_set_tizen_latency_mode (GstWFDExtMessage * msg, + guint latency_mode) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->tizen_latency_mode) + msg->tizen_latency_mode = g_new0 (GstWFDTizenLatencyMode, 1); + + msg->tizen_latency_mode->latency_mode = latency_mode; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_ext_message_get_tizen_latency_mode (GstWFDExtMessage * msg, + guint * latency_mode) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->tizen_latency_mode != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (latency_mode != NULL, GST_WFD_EINVAL); + + *latency_mode = msg->tizen_latency_mode->latency_mode; + + return GST_WFD_OK; +} diff --git a/gst/rtsp-server/gstwfdmessage-ext.h b/gst/rtsp-server/gstwfdmessage-ext.h new file mode 100755 index 0000000..347a487 --- /dev/null +++ b/gst/rtsp-server/gstwfdmessage-ext.h @@ -0,0 +1,123 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* + * Unless otherwise indicated, Source Code is licensed under MIT license. + * See further explanation attached in License Statement (distributed in the file + * LICENSE). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __GST_WFD_EXT_MESSAGE_H__ +#define __GST_WFD_EXT_MESSAGE_H__ + +#include +#include "gstwfdmessage.h" + +G_BEGIN_DECLS + +#define GST_STRING_TIZEN_WFD_RESTRANSMISSION "tizen_wfd_retransmission" +#define GST_STRING_TIZEN_WFD_FEC "tizen_wfd_fec" +#define GST_STRING_TIZEN_WFD_LATENCY_MODE "tizen_wfd_latency_mode" +#define GST_STRING_TIZEN_WFD_LATENCY_LOW "low" +#define GST_STRING_TIZEN_WFD_LATENCY_MID "mid" +#define GST_STRING_TIZEN_WFD_LATENCY_HIGH "high" + +typedef enum { + GST_WFD_TIZEN_LATENCY_NONE, + GST_WFD_TIZEN_LATENCY_LOW, + GST_WFD_TIZEN_LATENCY_MID, + GST_WFD_TIZEN_LATENCY_HIGH +} GstWFDTizenLatencyEnum; + +typedef struct { + guint rtp_port; + guint rtcp_port; +} GstWFDTizenRetransmission; + +typedef struct { + guint t_max; /*TMAX is the maximum number of source symbols in a block*/ + guint p_max; /*PMAX is the maximum number of parity symbols in a block*/ +} GstWFDTizenFec; + +typedef struct { + guint latency_mode; +} GstWFDTizenLatencyMode; + +typedef struct { + GstWFDTizenRetransmission *tizen_retransmission; + GstWFDTizenFec *tizen_fec; + GstWFDTizenLatencyMode *tizen_latency_mode; +} GstWFDExtMessage; + +GType gst_wfd_ext_message_get_type (void); + +#define GST_TYPE_WFD_EXT_MESSAGE (gst_wfd_ext_message_get_type()) +#define GST_WFD_EXT_MESSAGE_CAST(object) ((GstWFDExtMessage *)(object)) +#define GST_WFD_EXT_MESSAGE(object) (GST_WFD_EXT_MESSAGE_CAST(object)) + +/* Session descriptions */ +GstWFDResult gst_wfd_ext_message_new (GstWFDExtMessage **msg); +GstWFDResult gst_wfd_ext_message_init (GstWFDExtMessage *msg); +GstWFDResult gst_wfd_ext_message_uninit (GstWFDExtMessage *msg); +GstWFDResult gst_wfd_ext_message_free (GstWFDExtMessage *msg); + +GstWFDResult gst_wfd_ext_message_parse_buffer (const guint8 *data, guint size, GstWFDExtMessage *msg); +gchar* gst_wfd_ext_message_as_text (const GstWFDExtMessage *msg); +gchar* gst_wfd_ext_message_param_names_as_text (const GstWFDExtMessage *msg); +GstWFDResult gst_wfd_ext_message_dump (const GstWFDExtMessage *msg); + +GstWFDResult gst_wfd_ext_message_set_tizen_retransmission (GstWFDExtMessage *msg, + guint rtp_port, + guint rtcp_port); +GstWFDResult gst_wfd_ext_message_get_tizen_retransmission (GstWFDExtMessage *msg, + guint *rtp_port, + guint *rtcp_port); + +GstWFDResult gst_wfd_ext_message_set_tizen_fec (GstWFDExtMessage *msg, + guint t_max, + guint p_max); +GstWFDResult gst_wfd_ext_message_get_tizen_fec (GstWFDExtMessage *msg, + guint *t_max, + guint *p_max); + +GstWFDResult gst_wfd_ext_message_set_tizen_latency_mode (GstWFDExtMessage *msg, + guint latency_mode); +GstWFDResult gst_wfd_ext_message_get_tizen_latency_mode (GstWFDExtMessage *msg, + guint *latency_mode); + +G_END_DECLS + +#endif /* __GST_WFD_EXT_MESSAGE_H__ */ diff --git a/gst/rtsp-server/gstwfdmessage.c b/gst/rtsp-server/gstwfdmessage.c index fc81a9c..0e1f7dd 100644 --- a/gst/rtsp-server/gstwfdmessage.c +++ b/gst/rtsp-server/gstwfdmessage.c @@ -243,96 +243,96 @@ gst_wfd_message_uninit (GstWFDMessage * msg) guint i = 0; if (msg->audio_codecs->list) { for (; i < msg->audio_codecs->count; i++) { - FREE_STRING(msg->audio_codecs->list[i].audio_format); + FREE_STRING (msg->audio_codecs->list[i].audio_format); msg->audio_codecs->list[i].modes = 0; msg->audio_codecs->list[i].latency = 0; } - FREE_STRING(msg->audio_codecs->list); + FREE_STRING (msg->audio_codecs->list); } - FREE_STRING(msg->audio_codecs); + FREE_STRING (msg->audio_codecs); } if (msg->video_formats) { - FREE_STRING(msg->video_formats->list); - FREE_STRING(msg->video_formats); + FREE_STRING (msg->video_formats->list); + FREE_STRING (msg->video_formats); } if (msg->video_3d_formats) { - FREE_STRING(msg->video_3d_formats->list); - FREE_STRING(msg->video_3d_formats); + FREE_STRING (msg->video_3d_formats->list); + FREE_STRING (msg->video_3d_formats); } if (msg->content_protection) { if (msg->content_protection->hdcp2_spec) { - FREE_STRING(msg->content_protection->hdcp2_spec->hdcpversion); - FREE_STRING(msg->content_protection->hdcp2_spec->TCPPort); - FREE_STRING(msg->content_protection->hdcp2_spec); + FREE_STRING (msg->content_protection->hdcp2_spec->hdcpversion); + FREE_STRING (msg->content_protection->hdcp2_spec->TCPPort); + FREE_STRING (msg->content_protection->hdcp2_spec); } - FREE_STRING(msg->content_protection); + FREE_STRING (msg->content_protection); } if (msg->display_edid) { if (msg->display_edid->edid_payload) - FREE_STRING(msg->display_edid->edid_payload); - FREE_STRING(msg->display_edid); + FREE_STRING (msg->display_edid->edid_payload); + FREE_STRING (msg->display_edid); } if (msg->coupled_sink) { if (msg->coupled_sink->coupled_sink_cap) { - FREE_STRING(msg->coupled_sink->coupled_sink_cap->sink_address); - FREE_STRING(msg->coupled_sink->coupled_sink_cap); + FREE_STRING (msg->coupled_sink->coupled_sink_cap->sink_address); + FREE_STRING (msg->coupled_sink->coupled_sink_cap); } - FREE_STRING(msg->coupled_sink); + FREE_STRING (msg->coupled_sink); } if (msg->trigger_method) { - FREE_STRING(msg->trigger_method->wfd_trigger_method); - FREE_STRING(msg->trigger_method); + FREE_STRING (msg->trigger_method->wfd_trigger_method); + FREE_STRING (msg->trigger_method); } if (msg->presentation_url) { - FREE_STRING(msg->presentation_url->wfd_url0); - FREE_STRING(msg->presentation_url->wfd_url1); - FREE_STRING(msg->presentation_url); + FREE_STRING (msg->presentation_url->wfd_url0); + FREE_STRING (msg->presentation_url->wfd_url1); + FREE_STRING (msg->presentation_url); } if (msg->client_rtp_ports) { - FREE_STRING(msg->client_rtp_ports->profile); - FREE_STRING(msg->client_rtp_ports->mode); - FREE_STRING(msg->client_rtp_ports); + FREE_STRING (msg->client_rtp_ports->profile); + FREE_STRING (msg->client_rtp_ports->mode); + FREE_STRING (msg->client_rtp_ports); } if (msg->route) { - FREE_STRING(msg->route->destination); - FREE_STRING(msg->route); + FREE_STRING (msg->route->destination); + FREE_STRING (msg->route); } if (msg->I2C) { - FREE_STRING(msg->I2C); + FREE_STRING (msg->I2C); } if (msg->av_format_change_timing) { - FREE_STRING(msg->av_format_change_timing); + FREE_STRING (msg->av_format_change_timing); } if (msg->preferred_display_mode) { - FREE_STRING(msg->preferred_display_mode); + FREE_STRING (msg->preferred_display_mode); } if (msg->standby_resume_capability) { - FREE_STRING(msg->standby_resume_capability); + FREE_STRING (msg->standby_resume_capability); } if (msg->standby) { - FREE_STRING(msg->standby); + FREE_STRING (msg->standby); } if (msg->connector_type) { - FREE_STRING(msg->connector_type); + FREE_STRING (msg->connector_type); } if (msg->idr_request) { - FREE_STRING(msg->idr_request); + FREE_STRING (msg->idr_request); } return GST_WFD_OK; @@ -473,33 +473,33 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg) WFD_SKIP_SPACE (v); WFD_READ_UINT32 (msg->video_formats->list->native); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats-> - list->preferred_display_mode_supported); + WFD_READ_UINT32 (msg->video_formats->list-> + preferred_display_mode_supported); WFD_SKIP_SPACE (v); WFD_READ_UINT32 (msg->video_formats->list->H264_codec.profile); WFD_SKIP_SPACE (v); WFD_READ_UINT32 (msg->video_formats->list->H264_codec.level); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec. - misc_params.CEA_Support); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + CEA_Support); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec. - misc_params.VESA_Support); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + VESA_Support); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec. - misc_params.HH_Support); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + HH_Support); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec. - misc_params.latency); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + latency); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec. - misc_params.min_slice_size); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + min_slice_size); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec. - misc_params.slice_enc_params); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + slice_enc_params); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec. - misc_params.frame_rate_control_support); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + frame_rate_control_support); WFD_SKIP_SPACE (v); if (msg->video_formats->list->preferred_display_mode_supported == 1) { WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_hres); @@ -516,27 +516,27 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg) WFD_SKIP_SPACE (v); WFD_READ_UINT32 (msg->video_3d_formats->list->native); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_3d_formats-> - list->preferred_display_mode_supported); + WFD_READ_UINT32 (msg->video_3d_formats->list-> + preferred_display_mode_supported); WFD_SKIP_SPACE (v); WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.profile); WFD_SKIP_SPACE (v); WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.level); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. - misc_params.video_3d_capability); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params. + video_3d_capability); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. - misc_params.latency); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params. + latency); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. - misc_params.min_slice_size); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params. + min_slice_size); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. - misc_params.slice_enc_params); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params. + slice_enc_params); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec. - misc_params.frame_rate_control_support); + WFD_READ_UINT32 (msg->video_3d_formats->list->H264_codec.misc_params. + frame_rate_control_support); WFD_SKIP_SPACE (v); if (msg->video_formats->list->preferred_display_mode_supported == 1) { WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_hres); @@ -694,26 +694,26 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg) WFD_SKIP_SPACE (v); WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.level); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. - misc_params.CEA_Support); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params. + CEA_Support); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. - misc_params.VESA_Support); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params. + VESA_Support); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. - misc_params.HH_Support); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params. + HH_Support); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. - misc_params.latency); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params. + latency); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. - misc_params.min_slice_size); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params. + min_slice_size); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. - misc_params.slice_enc_params); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params. + slice_enc_params); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec. - misc_params.frame_rate_control_support); + WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.misc_params. + frame_rate_control_support); WFD_SKIP_SPACE (v); WFD_READ_UINT32 (msg->preferred_display_mode->H264_codec.max_hres); WFD_SKIP_SPACE (v); @@ -876,8 +876,8 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) g_string_append_printf (lines, " %04x", msg->video_formats->list->H264_codec.misc_params.slice_enc_params); g_string_append_printf (lines, " %02x", - msg->video_formats->list->H264_codec. - misc_params.frame_rate_control_support); + msg->video_formats->list->H264_codec.misc_params. + frame_rate_control_support); if (msg->video_formats->list->H264_codec.max_hres) g_string_append_printf (lines, " %04x", @@ -908,8 +908,8 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) g_string_append_printf (lines, " %02x", msg->video_3d_formats->list->H264_codec.level); g_string_append_printf (lines, " %16x", - msg->video_3d_formats->list->H264_codec. - misc_params.video_3d_capability); + msg->video_3d_formats->list->H264_codec.misc_params. + video_3d_capability); g_string_append_printf (lines, " %02x", msg->video_3d_formats->list->H264_codec.misc_params.latency); g_string_append_printf (lines, " %04x", @@ -917,8 +917,8 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) g_string_append_printf (lines, " %04x", msg->video_3d_formats->list->H264_codec.misc_params.slice_enc_params); g_string_append_printf (lines, " %02x", - msg->video_3d_formats->list->H264_codec. - misc_params.frame_rate_control_support); + msg->video_3d_formats->list->H264_codec.misc_params. + frame_rate_control_support); if (msg->video_3d_formats->list->H264_codec.max_hres) g_string_append_printf (lines, " %04x", msg->video_3d_formats->list->H264_codec.max_hres); @@ -959,8 +959,9 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) if (msg->display_edid->edid_supported) { if (msg->display_edid->edid_block_count > 0 && msg->display_edid->edid_block_count <= EDID_BLOCK_COUNT_MAX_SIZE) { - g_string_append_printf (lines," %04x", msg->display_edid->edid_block_count); - g_string_append_printf(lines, " %s", msg->display_edid->edid_payload); + g_string_append_printf (lines, " %04x", + msg->display_edid->edid_block_count); + g_string_append_printf (lines, " %s", msg->display_edid->edid_payload); } else g_string_append_printf (lines, " none"); } else { @@ -1261,26 +1262,26 @@ gst_wfd_message_dump (const GstWFDMessage * msg) nativeindex = msg->video_formats->list->native >> 3; g_print (" Resolution: %d\n", (1 << nativeindex)); - if (msg->video_formats->list-> - H264_codec.profile & GST_WFD_H264_BASE_PROFILE) { + if (msg->video_formats->list->H264_codec. + profile & GST_WFD_H264_BASE_PROFILE) { g_print (" Profile: BASE\n"); - } else if (msg->video_formats->list-> - H264_codec.profile & GST_WFD_H264_HIGH_PROFILE) { + } else if (msg->video_formats->list->H264_codec. + profile & GST_WFD_H264_HIGH_PROFILE) { g_print (" Profile: HIGH\n"); } if (msg->video_formats->list->H264_codec.level & GST_WFD_H264_LEVEL_3_1) { g_print (" Level: 3.1\n"); - } else if (msg->video_formats->list-> - H264_codec.level & GST_WFD_H264_LEVEL_3_2) { + } else if (msg->video_formats->list->H264_codec. + level & GST_WFD_H264_LEVEL_3_2) { g_print (" Level: 3.2\n"); - } else if (msg->video_formats->list-> - H264_codec.level & GST_WFD_H264_LEVEL_4) { + } else if (msg->video_formats->list->H264_codec. + level & GST_WFD_H264_LEVEL_4) { g_print (" Level: 4\n"); - } else if (msg->video_formats->list-> - H264_codec.level & GST_WFD_H264_LEVEL_4_1) { + } else if (msg->video_formats->list->H264_codec. + level & GST_WFD_H264_LEVEL_4_1) { g_print (" Level: 4.1\n"); - } else if (msg->video_formats->list-> - H264_codec.level & GST_WFD_H264_LEVEL_4_2) { + } else if (msg->video_formats->list->H264_codec. + level & GST_WFD_H264_LEVEL_4_2) { g_print (" Level: 4.2\n"); } g_print (" Latency: %d\n", @@ -1290,8 +1291,8 @@ gst_wfd_message_dump (const GstWFDMessage * msg) g_print (" slice_enc_params: %x\n", msg->video_formats->list->H264_codec.misc_params.slice_enc_params); g_print (" frame_rate_control_support: %x\n", - msg->video_formats->list->H264_codec. - misc_params.frame_rate_control_support); + msg->video_formats->list->H264_codec.misc_params. + frame_rate_control_support); if (msg->video_formats->list->H264_codec.max_hres) { g_print (" Max Height: %04d\n", msg->video_formats->list->H264_codec.max_hres); @@ -1578,8 +1579,8 @@ gst_wfd_message_set_supported_video_format (GstWFDMessage * msg, min_slice_size; msg->video_formats->list->H264_codec.misc_params.slice_enc_params = slice_enc_params; - msg->video_formats->list->H264_codec. - misc_params.frame_rate_control_support = frame_rate_control; + msg->video_formats->list->H264_codec.misc_params. + frame_rate_control_support = frame_rate_control; } return GST_WFD_OK; } @@ -1681,8 +1682,8 @@ gst_wfd_message_get_supported_video_format (GstWFDMessage * msg, *slice_enc_params = msg->video_formats->list->H264_codec.misc_params.slice_enc_params; *frame_rate_control = - msg->video_formats->list->H264_codec. - misc_params.frame_rate_control_support; + msg->video_formats->list->H264_codec.misc_params. + frame_rate_control_support; return GST_WFD_OK; } @@ -1725,8 +1726,8 @@ gst_wfd_message_get_prefered_video_format (GstWFDMessage * msg, *slice_enc_params = msg->video_formats->list->H264_codec.misc_params.slice_enc_params; *frame_rate_control = - msg->video_formats->list->H264_codec. - misc_params.frame_rate_control_support; + msg->video_formats->list->H264_codec.misc_params. + frame_rate_control_support; return GST_WFD_OK; } @@ -1742,9 +1743,11 @@ gst_wfd_message_set_display_edid (GstWFDMessage * msg, return GST_WFD_OK; if (edid_blockcount > 0 && edid_blockcount <= EDID_BLOCK_COUNT_MAX_SIZE) { msg->display_edid->edid_block_count = edid_blockcount; - msg->display_edid->edid_payload = g_malloc(EDID_BLOCK_SIZE * edid_blockcount); + msg->display_edid->edid_payload = + g_malloc (EDID_BLOCK_SIZE * edid_blockcount); if (msg->display_edid->edid_payload) - memcpy(msg->display_edid->edid_payload, edid_playload, EDID_BLOCK_SIZE * edid_blockcount); + memcpy (msg->display_edid->edid_payload, edid_playload, + EDID_BLOCK_SIZE * edid_blockcount); else msg->display_edid->edid_supported = FALSE; } else @@ -1767,11 +1770,14 @@ gst_wfd_message_get_display_edid (GstWFDMessage * msg, if (msg->display_edid) { if (msg->display_edid->edid_supported) { *edid_blockcount = msg->display_edid->edid_block_count; - if (msg->display_edid->edid_block_count > 0 && msg->display_edid->edid_block_count <= EDID_BLOCK_COUNT_MAX_SIZE) { + if (msg->display_edid->edid_block_count > 0 + && msg->display_edid->edid_block_count <= EDID_BLOCK_COUNT_MAX_SIZE) { char *temp; - temp = g_malloc0(EDID_BLOCK_SIZE * msg->display_edid->edid_block_count); + temp = + g_malloc0 (EDID_BLOCK_SIZE * msg->display_edid->edid_block_count); if (temp) { - memcpy(temp, msg->display_edid->edid_payload, EDID_BLOCK_SIZE * msg->display_edid->edid_block_count); + memcpy (temp, msg->display_edid->edid_payload, + EDID_BLOCK_SIZE * msg->display_edid->edid_block_count); *edid_playload = temp; *edid_supported = TRUE; } @@ -1830,7 +1836,8 @@ gst_wfd_message_get_contentprotection_type (GstWFDMessage * msg, } if (msg->content_protection->hdcp2_spec->TCPPort) { - result = strtok_r (msg->content_protection->hdcp2_spec->TCPPort, "=", &ptr); + result = + strtok_r (msg->content_protection->hdcp2_spec->TCPPort, "=", &ptr); while (result != NULL && ptr != NULL) { result = strtok_r (NULL, "=", &ptr); *TCPPort = atoi (result); @@ -1947,12 +1954,13 @@ gst_wfd_message_get_presentation_url (GstWFDMessage * msg, gchar ** wfd_url0, } GstWFDResult -gst_wfd_message_set_av_format_change_timing(GstWFDMessage *msg, guint64 PTS, guint64 DTS) +gst_wfd_message_set_av_format_change_timing (GstWFDMessage * msg, guint64 PTS, + guint64 DTS) { - g_return_val_if_fail(msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); if (!msg->av_format_change_timing) - msg->av_format_change_timing = g_new0(GstWFDAVFormatChangeTiming, 1); + msg->av_format_change_timing = g_new0 (GstWFDAVFormatChangeTiming, 1); msg->av_format_change_timing->PTS = PTS; msg->av_format_change_timing->DTS = DTS; @@ -1960,11 +1968,12 @@ gst_wfd_message_set_av_format_change_timing(GstWFDMessage *msg, guint64 PTS, gui } GstWFDResult -gst_wfd_message_get_av_format_change_timing(GstWFDMessage *msg, guint64 *PTS, guint64 *DTS) +gst_wfd_message_get_av_format_change_timing (GstWFDMessage * msg, guint64 * PTS, + guint64 * DTS) { - g_return_val_if_fail(msg != NULL, GST_WFD_EINVAL); - g_return_val_if_fail(PTS != NULL, GST_WFD_EINVAL); - g_return_val_if_fail(DTS != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (PTS != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (DTS != NULL, GST_WFD_EINVAL); if (msg->av_format_change_timing) { *PTS = msg->av_format_change_timing->PTS; diff --git a/gst/rtsp-server/rtsp-client-ext.c b/gst/rtsp-server/rtsp-client-ext.c new file mode 100755 index 0000000..5f73c99 --- /dev/null +++ b/gst/rtsp-server/rtsp-client-ext.c @@ -0,0 +1,922 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:rtsp-client + * @short_description: A client connection state + * @see_also: #GstRTSPServer, #GstRTSPThreadPool + * + * The client object handles the connection with a client for as long as a TCP + * connection is open. + * + * A #GstRTSPWFDClient is created by #GstRTSPServer when a new connection is + * accepted and it inherits the #GstRTSPMountPoints, #GstRTSPSessionPool, + * #GstRTSPAuth and #GstRTSPThreadPool from the server. + * + * The client connection should be configured with the #GstRTSPConnection using + * gst_rtsp_wfd_client_set_connection() before it can be attached to a #GMainContext + * using gst_rtsp_wfd_client_attach(). From then on the client will handle requests + * on the connection. + * + * Use gst_rtsp_wfd_client_session_filter() to iterate or modify all the + * #GstRTSPSession objects managed by the client object. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include +#include + +#include "rtsp-client-ext.h" +#include "rtsp-media-factory-wfd.h" +#include "rtsp-sdp.h" +#include "rtsp-params.h" +#include "rtsp-media-ext.h" +#include "gstwfdmessage-ext.h" + +#define GST_RTSP_EXT_CLIENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_EXT_CLIENT, GstRTSPExtClientPrivate)) + +struct _GstRTSPExtClientPrivate +{ + GstRTSPMediaExt *media; + guint resend_packets; + guint prev_max_seqnum; + guint prev_fraction_lost; + guint32 prev_max_packets_lost; + gboolean first_rtcp; + guint consecutive_low_bitrate_count; + + guint tizen_retransmission_rtp_port; + guint tizen_retransmission_rtcp_port; + guint tizen_fec_t_max; + guint tizen_fec_p_max; + guint tizen_latency_mode; +}; + +#define WFD_MOUNT_POINT "/wfd1.0/streamid=0" +#define UNSTABLE_NETWORK_INTERVAL 15 +#define MIN_PORT_NUM 1024 +#define MAX_PORT_NUM 65535 +#define TIZEN_RETRANSMISSION_RTP_PORT_NONE 0 +#define TIZEN_RETRANSMISSION_RTCP_PORT_NONE 0 +#define MIN_FEC_T_NUM 2 +#define MAX_FEC_T_NUM 100 +#define MIN_FEC_P_NUM 2 +#define MAX_FEC_P_NUM 100 +#define TIZEN_T_MAX_NONE 0 +#define TIZEN_P_MAX_NONE 0 +#define TIZEN_USER_AGENT "TIZEN" +#define DEFAULT_WFD_TIMEOUT 60 + +GST_DEBUG_CATEGORY_STATIC (rtsp_ext_client_debug); +#define GST_CAT_DEFAULT rtsp_ext_client_debug + +static gboolean ext_configure_client_media (GstRTSPClient * client, + GstRTSPMedia * media, GstRTSPStream * stream, GstRTSPContext * ctx); +static void handle_ext_stats (GstRTSPWFDClient * client, GstStructure * stats); +static gchar* handle_ext_m3_req_msg (GstRTSPWFDClient * client, gchar * data); +static void handle_ext_set_param_msg (GstRTSPWFDClient * client, gchar * data); + +static void handle_ext_m3_res_msg (GstRTSPWFDClient * client, gchar * data); +static gchar* handle_ext_m4_req_msg (GstRTSPWFDClient * client, gchar * data); + +static void gst_rtsp_ext_client_finalize (GObject * obj); + +G_DEFINE_TYPE (GstRTSPExtClient, gst_rtsp_ext_client, GST_TYPE_RTSP_WFD_CLIENT); + +static void +gst_rtsp_ext_client_class_init (GstRTSPExtClientClass * klass) +{ + GObjectClass *gobject_class; + GstRTSPClientClass *rtsp_client_class; + GstRTSPWFDClientClass *wfd_client_class; + + g_type_class_add_private (klass, sizeof (GstRTSPExtClientPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + rtsp_client_class = GST_RTSP_CLIENT_CLASS (klass); + wfd_client_class = GST_RTSP_WFD_CLIENT_CLASS (klass); + + gobject_class->finalize = gst_rtsp_ext_client_finalize; + + rtsp_client_class->configure_client_media = ext_configure_client_media; + wfd_client_class->wfd_rtp_stats = handle_ext_stats; + wfd_client_class->wfd_handle_m3_req_msg = handle_ext_m3_req_msg; + wfd_client_class->wfd_handle_m3_res_msg = handle_ext_m3_res_msg; + wfd_client_class->wfd_handle_m4_req_msg = handle_ext_m4_req_msg; + wfd_client_class->wfd_handle_set_param_msg = handle_ext_set_param_msg; + + GST_DEBUG_CATEGORY_INIT (rtsp_ext_client_debug, "rtspextclient", 0, + "GstRTSPExtClient"); +} + +static void +gst_rtsp_ext_client_init (GstRTSPExtClient * client) +{ + GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (client); + + client->priv = priv; + priv->resend_packets = 0; + priv->prev_max_seqnum = 0; + priv->prev_fraction_lost = 0; + priv->prev_max_packets_lost = 0; + priv->first_rtcp = FALSE; + priv->consecutive_low_bitrate_count = 0; + priv->tizen_retransmission_rtp_port = TIZEN_RETRANSMISSION_RTP_PORT_NONE; + priv->tizen_retransmission_rtcp_port = TIZEN_RETRANSMISSION_RTCP_PORT_NONE; + priv->tizen_fec_t_max = TIZEN_T_MAX_NONE; + priv->tizen_fec_p_max = TIZEN_P_MAX_NONE; + priv->tizen_latency_mode = GST_WFD_TIZEN_LATENCY_NONE; + + GST_INFO_OBJECT (client, "Client is initialized"); + + return; +} + +/* A client is finalized when the connection is broken */ +static void +gst_rtsp_ext_client_finalize (GObject * obj) +{ + GstRTSPExtClient *client = GST_RTSP_EXT_CLIENT (obj); +// GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (client); + + GST_INFO ("finalize client %p", client); + + G_OBJECT_CLASS (gst_rtsp_ext_client_parent_class)->finalize (obj); +} + +/** + * gst_rtsp_ext_client_new: + * + * Create a new #GstRTSPExtClient instance. + * + * Returns: a new #GstRTSPExtClient + */ +GstRTSPExtClient * +gst_rtsp_ext_client_new (void) +{ + GstRTSPExtClient *result; + + result = g_object_new (GST_TYPE_RTSP_EXT_CLIENT, NULL); + + return result; +} + +static gboolean +ext_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media, + GstRTSPStream * stream, GstRTSPContext * ctx) +{ + GstRTSPMediaExt* _media = NULL; + GstRTSPExtClient *_client = GST_RTSP_EXT_CLIENT (client); + GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (_client); + + _media = GST_RTSP_MEDIA_EXT (media); + + if (GST_IS_RTSP_MEDIA_EXT (_media)) { + if (_media != priv->media) { + GST_ERROR_OBJECT (client, "Different media!"); + priv->media = _media; + } + } + + return GST_RTSP_WFD_CLIENT_CLASS (gst_rtsp_ext_client_parent_class)-> + configure_client_media (client, media, stream, ctx); +} + +static gboolean +_set_venc_bitrate (GstRTSPWFDClient * client, gint bitrate) +{ + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + GstRTSPMediaFactory *factory = NULL; + GstRTSPMountPoints *mount_points = NULL; + gchar *path = NULL; + gint matched = 0; + gboolean ret = TRUE; + + if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { + ret = FALSE; + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no mount points..."); + goto no_mount_points; + } + + path = g_strdup (WFD_MOUNT_POINT); + if (!path) { + ret = FALSE; + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no path..."); + goto no_path; + } + + if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no factory..."); + ret = FALSE; + goto no_factory; + } + + gst_rtsp_media_factory_wfd_set_venc_bitrate (factory, bitrate); + ret = TRUE; + + g_object_unref (factory); + +no_factory: + g_free (path); +no_path: + g_object_unref (mount_points); +no_mount_points: + return ret; +} + +static gboolean +_get_venc_bitrate (GstRTSPWFDClient * client, gint * bitrate) +{ + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + GstRTSPMediaFactory *factory = NULL; + GstRTSPMountPoints *mount_points = NULL; + gchar *path = NULL; + gint matched = 0; + gboolean ret = TRUE; + + if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { + ret = FALSE; + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no mount points..."); + goto no_mount_points; + } + + path = g_strdup (WFD_MOUNT_POINT); + if (!path) { + ret = FALSE; + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no path..."); + goto no_path; + } + + if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no factory..."); + ret = FALSE; + goto no_factory; + } + + gst_rtsp_media_factory_wfd_get_venc_bitrate (factory, bitrate); + ret = TRUE; + + g_object_unref (factory); + +no_factory: + g_free (path); +no_path: + g_object_unref (mount_points); +no_mount_points: + return ret; +} + +static gboolean +_get_config_bitrate (GstRTSPWFDClient * client, guint32 * min, guint32 * max) +{ + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + GstRTSPMediaFactory *factory = NULL; + GstRTSPMountPoints *mount_points = NULL; + gchar *path = NULL; + gint matched = 0; + gboolean ret = TRUE; + + if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { + ret = FALSE; + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no mount points..."); + goto no_mount_points; + } + + path = g_strdup (WFD_MOUNT_POINT); + if (!path) { + ret = FALSE; + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no path..."); + goto no_path; + } + + if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no factory..."); + ret = FALSE; + goto no_factory; + } + + gst_rtsp_media_factory_wfd_get_config_bitrate (factory, min, max); + ret = TRUE; + + g_object_unref (factory); + +no_factory: + g_free (path); +no_path: + g_object_unref (mount_points); +no_mount_points: + return ret; +} + +static gboolean +_bitrate_config (GstRTSPWFDClient * client, gint bitrate, guint32 min_bitrate) +{ + GstRTSPExtClient *_client = GST_RTSP_EXT_CLIENT (client); + GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (_client); + gint prev_bitrate; + + _get_venc_bitrate (client, &prev_bitrate); + + if (prev_bitrate != bitrate) { + _set_venc_bitrate (client, bitrate); + GST_INFO_OBJECT (client, "[UDP] New Bitrate value [%d]", bitrate); + } + + if (prev_bitrate == min_bitrate && prev_bitrate == bitrate) + priv->consecutive_low_bitrate_count++; + else + priv->consecutive_low_bitrate_count = 0; + + if (priv->consecutive_low_bitrate_count >= UNSTABLE_NETWORK_INTERVAL) { + /* Network congestion happens. Add logic for popup warning or something else */ + GST_WARNING_OBJECT (client, "Network unstable"); + priv->consecutive_low_bitrate_count = 0; + } + + return TRUE; +} + +static void +handle_ext_stats (GstRTSPWFDClient * client, GstStructure * stats) +{ + GstRTSPExtClient *_client = GST_RTSP_EXT_CLIENT (client); + GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (_client); + guint latest_resend_packets = 0; + + g_return_val_if_fail (priv != NULL, FALSE); + + latest_resend_packets = gst_rtsp_media_ext_get_resent_packets (priv->media); + + GST_INFO_OBJECT (client, "Re-sent RTP packets : %d", latest_resend_packets); + + /* calculation to decide bitrate */ + { + static gint32 next_k = 40; + static gint32 next_p = 0; + guint32 min_bitrate = 0; + guint32 max_bitrate = 0; + guint fraction_lost = 0; + guint max_seqnum = 0; + gint packetslost; + gint bitrate = 0; + gint temp_fraction_lost = 0; + gint statistics_fraction_lost = 0; + gfloat thretholdValue = 0; + static gint fraction_lost_MA = 0; + + gst_structure_get_uint (stats, "rb-fractionlost", &fraction_lost); + gst_structure_get_uint (stats, "rb-exthighestseq", &max_seqnum); + gst_structure_get_int (stats, "rb-packetslost", &packetslost); + + _get_venc_bitrate (client, &bitrate); + GST_INFO_OBJECT (client, "[UDP] Current Bitrate value [%d]", bitrate); + + _get_config_bitrate (client, &min_bitrate, &max_bitrate); + GST_INFO_OBJECT (client, "[UDP] min [%d], max [%d]", min_bitrate, + max_bitrate); + + if (priv->resend_packets == latest_resend_packets) + fraction_lost = 0; + priv->resend_packets = latest_resend_packets; + + if (priv->prev_max_seqnum == max_seqnum) + goto config; + + if (priv->first_rtcp == FALSE) { + GST_DEBUG_OBJECT (client, "Ignoring first receiver report"); + priv->prev_fraction_lost = 0; + priv->prev_max_packets_lost = packetslost; + priv->prev_max_seqnum = max_seqnum; + fraction_lost_MA = 0; + priv->first_rtcp = TRUE; + return; + } + + if (priv->prev_fraction_lost == 0) + thretholdValue = 1.0; + else + thretholdValue = 0.8; + + if (fraction_lost > 0) { + temp_fraction_lost = fraction_lost * 100 / 256; + GST_DEBUG_OBJECT (client, "fraction lost from sink RR [%d]", + temp_fraction_lost); + } else { + if ((max_seqnum > priv->prev_max_seqnum) + && (packetslost > priv->prev_max_packets_lost)) + temp_fraction_lost = + (((packetslost - priv->prev_max_packets_lost) * 100) / (max_seqnum - + priv->prev_max_seqnum)); + GST_DEBUG_OBJECT (client, "fraction lost calculated [%d]", + temp_fraction_lost); + } + statistics_fraction_lost = + (gint) (temp_fraction_lost * thretholdValue + + priv->prev_fraction_lost * (1 - thretholdValue)); + fraction_lost_MA = + (fraction_lost_MA * 7 + statistics_fraction_lost * 5) / 8; + + if (fraction_lost_MA > 100) + fraction_lost_MA = 100; + + GST_DEBUG_OBJECT (client, + "statistics fraction lost = %d, fraction lost MA = %d", + statistics_fraction_lost, fraction_lost_MA); + + if (temp_fraction_lost > 0) { + guint32 temp_change_bandwith_amount = 0; + gint32 fec_step = 0; + + if (statistics_fraction_lost >= 5) { + temp_change_bandwith_amount = max_bitrate - min_bitrate; + fec_step = 10; + } else if (temp_fraction_lost >= 3) { + temp_change_bandwith_amount = (max_bitrate - min_bitrate) / 2; + fec_step = 5; + } else { + temp_change_bandwith_amount = (max_bitrate - min_bitrate) / 4; + fec_step = 3; + } + + GST_DEBUG_OBJECT (client, + "LOSS case, statistics fraction lost = %d percent, temp change" + "bandwith amount = %d bit", statistics_fraction_lost, + temp_change_bandwith_amount); + + if (next_p >= 100) + next_k -= fec_step; + else + next_p += fec_step; + + if (next_k < 10) + next_k = 10; + + if (next_p > 100) + next_p = 100; + + if (bitrate <= min_bitrate) { + bitrate = min_bitrate; + priv->prev_fraction_lost = statistics_fraction_lost; + priv->prev_max_packets_lost = packetslost; + goto config; + } + + bitrate -= temp_change_bandwith_amount; + + if (bitrate < min_bitrate) + bitrate = min_bitrate; + + } else if (0 == temp_fraction_lost && fraction_lost_MA < 1) { + gint32 fec_step = 0; + + if (0 == priv->prev_fraction_lost) { + bitrate += 512 * 1024; + fec_step = 10; + } else { + bitrate += 100 * 1024; + fec_step = 5; + } + + if (bitrate > max_bitrate) + bitrate = max_bitrate; + + if (next_p <= 0) + next_k += fec_step; + else + next_p -= fec_step; + + if (next_k > 100) + next_k = 100; + + if (next_p < 0) + next_p = 0; + + if (bitrate >= max_bitrate) { + GST_DEBUG_OBJECT (client, "bitrate can not be increased"); + bitrate = max_bitrate; + priv->prev_fraction_lost = statistics_fraction_lost; + priv->prev_max_seqnum = max_seqnum; + priv->prev_max_packets_lost = packetslost; + goto config; + } + + } + + priv->prev_fraction_lost = statistics_fraction_lost; + priv->prev_max_seqnum = max_seqnum; + priv->prev_max_packets_lost = packetslost; + + GST_INFO_OBJECT (client, "final bitrate is %d", bitrate); + + config: + _bitrate_config (client, bitrate, min_bitrate); + gst_rtsp_media_ext_set_next_param (priv->media, next_k, next_p); + } +} + +static gchar * +handle_ext_m3_req_msg (GstRTSPWFDClient * client, gchar * data) +{ + gchar *tmp = NULL; + gchar *sink_user_agent = NULL; + GstWFDExtMessage *msg = NULL; + GstWFDResult wfd_res = GST_WFD_EINVAL; + gboolean is_appended = FALSE; + + g_return_if_fail (client != NULL); + g_return_val_if_fail (data != NULL, NULL); + + sink_user_agent = gst_rtsp_wfd_client_get_sink_user_agent (client); + + if (sink_user_agent && strstr (sink_user_agent, TIZEN_USER_AGENT)) { + + GST_INFO_OBJECT (client, + "Setting tizen extended features on wfd message..."); + + wfd_res = gst_wfd_ext_message_new (&msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to create wfd message..."); + goto error; + } + + wfd_res = gst_wfd_ext_message_init (msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to init wfd message..."); + goto error; + } + + GST_INFO_OBJECT (client, + "Setting tizen extended features on wfd message..."); + + wfd_res = gst_wfd_ext_message_set_tizen_retransmission (msg, 0, 0); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set tizen retransmission on wfd message..."); + goto error; + } + + wfd_res = gst_wfd_ext_message_set_tizen_fec (msg, 0, 0); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to set tizen fec on wfd message..."); + goto error; + } + + wfd_res = gst_wfd_ext_message_set_tizen_latency_mode (msg, 0); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set tizen latency mode on wfd message..."); + goto error; + } + + tmp = gst_wfd_ext_message_param_names_as_text (msg); + if (tmp) { + data = g_strconcat (data, tmp, NULL); + g_free (tmp); + is_appended = TRUE; + } else { + GST_ERROR_OBJECT (client, + "Failed to gst_wfd_ext_message_param_names_as_text"); + goto error; + } + } + if (msg != NULL) + gst_wfd_ext_message_free (msg); + + if (sink_user_agent != NULL) + g_free (sink_user_agent); + + if (is_appended == FALSE) + return NULL; + else + return data; + +error: + if (msg != NULL) + gst_wfd_ext_message_free (msg); + + if (sink_user_agent != NULL) + g_free (sink_user_agent); + + return NULL; +} + +static void +handle_ext_m3_res_msg (GstRTSPWFDClient * client, gchar * data) +{ + GstWFDExtMessage *msg = NULL; + GstRTSPExtClientPrivate *ext_priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (client); + GstWFDResult wfd_res = GST_WFD_EINVAL; + + g_return_if_fail (ext_priv != NULL); + g_return_val_if_fail (data != NULL, NULL); + + wfd_res = gst_wfd_ext_message_new (&msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to create wfd message..."); + goto error; + } + + wfd_res = gst_wfd_ext_message_init (msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to init wfd message..."); + goto error; + } + + wfd_res = + gst_wfd_ext_message_parse_buffer ((const guint8 *) data, strlen (data), + msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to parse buffer..."); + goto error; + } + + /* Get tizen extended features from WFD message. */ + if (msg->tizen_retransmission) { + + guint rtp_port = TIZEN_RETRANSMISSION_RTP_PORT_NONE; + guint rtcp_port = TIZEN_RETRANSMISSION_RTCP_PORT_NONE; + wfd_res = + gst_wfd_ext_message_get_tizen_retransmission (msg, &rtp_port, + &rtcp_port); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to get tizen retransmission from wfd message..."); + goto error; + } + + if (rtp_port >= MIN_PORT_NUM && rtp_port <= MAX_PORT_NUM) + ext_priv->tizen_retransmission_rtp_port = rtp_port; + + if (rtcp_port >= MIN_PORT_NUM && rtcp_port <= MAX_PORT_NUM) + ext_priv->tizen_retransmission_rtcp_port = rtcp_port; + + GST_DEBUG_OBJECT (client, "Tizen retransmission rtp_port[%d] rtcp_port[%d]", + ext_priv->tizen_retransmission_rtp_port, + ext_priv->tizen_retransmission_rtcp_port); + } + + if (msg->tizen_fec) { + + guint fec_t_max = TIZEN_T_MAX_NONE; + guint fec_p_max = TIZEN_P_MAX_NONE; + + wfd_res = gst_wfd_ext_message_get_tizen_fec (msg, &fec_t_max, &fec_p_max); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to get tizen fec from wfd message..."); + goto error; + } + + if (fec_t_max >= MIN_FEC_T_NUM && fec_t_max <= MAX_FEC_T_NUM) + ext_priv->tizen_fec_t_max = fec_t_max; + + if (fec_p_max >= MIN_FEC_P_NUM && fec_p_max <= MAX_FEC_P_NUM) + ext_priv->tizen_fec_p_max = fec_p_max; + + GST_DEBUG_OBJECT (client, "Tizen fec t_max[%d] p_max[%d]", + ext_priv->tizen_fec_t_max, ext_priv->tizen_fec_p_max); + } + + if (msg->tizen_latency_mode) { + wfd_res = + gst_wfd_ext_message_get_tizen_latency_mode (msg, + &ext_priv->tizen_latency_mode); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to get tizen latency mode on wfd message..."); + goto error; + } + GST_DEBUG_OBJECT (client, "Tizen latency mode[%d]", + ext_priv->tizen_latency_mode); + } + + if (msg != NULL) + gst_wfd_ext_message_free (msg); + + return; +error: + + if (msg != NULL) + gst_wfd_ext_message_free (msg); + + return; +} + +static void +media_ext_constructed (GstRTSPMediaFactory * factory, GstRTSPMedia * media, + GstRTSPExtClient * client) +{ + GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (client); + g_return_if_fail (priv != NULL); + + priv->media = GST_RTSP_MEDIA_EXT (media); + + if (priv->tizen_retransmission_rtp_port != TIZEN_RETRANSMISSION_RTP_PORT_NONE + && priv->tizen_retransmission_rtcp_port != + TIZEN_RETRANSMISSION_RTCP_PORT_NONE) { + GST_DEBUG_OBJECT (client, "Tizen retransmission rtp_port[%d] rtcp_port[%d]", + priv->tizen_retransmission_rtp_port, + priv->tizen_retransmission_rtcp_port); + gst_rtsp_media_ext_set_extended_mode (priv->media, MEDIA_EXT_MODE_RESEND); + gst_rtsp_media_ext_set_retrans_port (priv->media, + priv->tizen_retransmission_rtp_port); + } + if (priv->tizen_fec_t_max != TIZEN_T_MAX_NONE + && priv->tizen_fec_p_max != TIZEN_P_MAX_NONE) { + GST_DEBUG_OBJECT (client, "Tizen fec t_max[%d] p_max[%d]", + priv->tizen_fec_t_max, priv->tizen_fec_p_max); + gst_rtsp_media_ext_set_extended_mode (priv->media, MEDIA_EXT_MODE_FEC); + gst_rtsp_media_ext_set_fec_value (priv->media, priv->tizen_fec_t_max, + priv->tizen_fec_p_max); + } + if (priv->tizen_latency_mode != GST_WFD_TIZEN_LATENCY_NONE) { + GST_DEBUG_OBJECT (client, "Tizen latency mode[%d]", + priv->tizen_latency_mode); + gst_rtsp_media_ext_set_latency_mode (priv->media, priv->tizen_latency_mode); + } +} + +static void +gst_wfd_ext_listen_media_constructed (GstRTSPWFDClient * client) +{ + GstRTSPMediaFactory *factory = NULL; + GstRTSPMountPoints *mount_points = NULL; + gchar *path = NULL; + gint matched = 0; + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + GstRTSPExtClient *_client = GST_RTSP_EXT_CLIENT (client); + + if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no mount points..."); + goto no_mount_points; + } + + path = g_strdup (WFD_MOUNT_POINT); + if (!path) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no path..."); + goto no_path; + } + + if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no factory..."); + goto no_factory; + } + + g_signal_connect (factory, "media-constructed", + (GCallback) media_ext_constructed, _client); + +no_factory: + g_free (path); +no_path: + g_object_unref (mount_points); +no_mount_points: + return; +} + +static void +handle_ext_set_param_msg (GstRTSPWFDClient * client, gchar * data) +{ + GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (client); + + g_return_if_fail (priv != NULL); + g_return_val_if_fail (data != NULL, NULL); + + return; +} + +static gchar * +handle_ext_m4_req_msg (GstRTSPWFDClient * client, gchar * data) +{ + GstWFDExtMessage *msg = NULL; + gchar *tmp = NULL; + GstRTSPExtClientPrivate *ext_priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (client); + GstWFDResult wfd_res = GST_WFD_EINVAL; + gboolean is_appended = FALSE; + + g_return_if_fail (ext_priv != NULL); + g_return_val_if_fail (data != NULL, NULL); + + wfd_res = gst_wfd_ext_message_new (&msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to create wfd message..."); + goto error; + } + + wfd_res = gst_wfd_ext_message_init (msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to init wfd message..."); + goto error; + } + + GST_INFO_OBJECT (client, "Setting extended features on wfd message..."); + + if (ext_priv->tizen_retransmission_rtp_port != + TIZEN_RETRANSMISSION_RTP_PORT_NONE + && ext_priv->tizen_retransmission_rtcp_port != + TIZEN_RETRANSMISSION_RTCP_PORT_NONE) { + + wfd_res = + gst_wfd_ext_message_set_tizen_retransmission (msg, + ext_priv->tizen_retransmission_rtp_port, + ext_priv->tizen_retransmission_rtcp_port); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set tizen retransmission on wfd message..."); + goto error; + } + GST_DEBUG_OBJECT (client, "Tizen retransmission rtp_port[%d] rtcp_port[%d]", + ext_priv->tizen_retransmission_rtp_port, + ext_priv->tizen_retransmission_rtcp_port); + } + + if (ext_priv->tizen_fec_t_max != TIZEN_T_MAX_NONE + && ext_priv->tizen_fec_p_max != TIZEN_P_MAX_NONE) { + + wfd_res = + gst_wfd_ext_message_set_tizen_fec (msg, ext_priv->tizen_fec_t_max, + ext_priv->tizen_fec_p_max); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to set tizen fec on wfd message..."); + goto error; + } + GST_DEBUG_OBJECT (client, "Tizen fec t_max[%d] p_max[%d]", + ext_priv->tizen_fec_t_max, ext_priv->tizen_fec_p_max); + } + + if (ext_priv->tizen_latency_mode != GST_WFD_TIZEN_LATENCY_NONE) { + + wfd_res = + gst_wfd_ext_message_set_tizen_latency_mode (msg, + ext_priv->tizen_latency_mode); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set tizen latency mode on wfd message..."); + goto error; + } + GST_DEBUG_OBJECT (client, "Tizen latency mode[%d]", + ext_priv->tizen_latency_mode); + } + + tmp = gst_wfd_ext_message_as_text (msg); + if (tmp) { + data = g_strconcat (data, tmp, NULL); + g_free (tmp); + is_appended = TRUE; + } else { + GST_ERROR_OBJECT (client, "Failed to gst_wfd_ext_message_as_text"); + goto error; + } + + if (msg != NULL) + gst_wfd_ext_message_free (msg); + + gst_wfd_ext_listen_media_constructed (client); + + if (is_appended == FALSE) { + return NULL; + } else { + return data; + }; + + return data; +error: + if (tmp != NULL) + g_free (tmp); + + if (msg != NULL) + gst_wfd_ext_message_free (msg); + + return NULL; +} diff --git a/gst/rtsp-server/rtsp-client-ext.h b/gst/rtsp-server/rtsp-client-ext.h new file mode 100755 index 0000000..34efcde --- /dev/null +++ b/gst/rtsp-server/rtsp-client-ext.h @@ -0,0 +1,73 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +#ifndef __GST_RTSP_EXT_CLIENT_H__ +#define __GST_RTSP_EXT_CLIENT_H__ + +G_BEGIN_DECLS + +typedef struct _GstRTSPExtClient GstRTSPExtClient; +typedef struct _GstRTSPExtClientClass GstRTSPExtClientClass; +typedef struct _GstRTSPExtClientPrivate GstRTSPExtClientPrivate; + +#include "rtsp-mount-points.h" +#include "rtsp-client-wfd.h" + +#define GST_TYPE_RTSP_EXT_CLIENT (gst_rtsp_ext_client_get_type ()) +#define GST_IS_RTSP_EXT_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_EXT_CLIENT)) +#define GST_IS_RTSP_EXT_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_EXT_CLIENT)) +#define GST_RTSP_EXT_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_EXT_CLIENT, GstRTSPExtClientClass)) +#define GST_RTSP_EXT_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_EXT_CLIENT, GstRTSPExtClient)) +#define GST_RTSP_EXT_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_EXT_CLIENT, GstRTSPExtClientClass)) +#define GST_RTSP_EXT_CLIENT_CAST(obj) ((GstRTSPExtClient*)(obj)) +#define GST_RTSP_EXT_CLIENT_CLASS_CAST(klass) ((GstRTSPExtClientClass*)(klass)) + +/** + * GstRTSPExtClient: + * + * The client object represents the connection and its state with a client. + */ +struct _GstRTSPExtClient { + GstRTSPWFDClient parent; + + /*< private >*/ + GstRTSPExtClientPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPExtClientClass: + * + * The client class structure. + */ +struct _GstRTSPExtClientClass { + GstRTSPWFDClientClass parent_class; + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_rtsp_ext_client_get_type (void); + +GstRTSPExtClient * gst_rtsp_ext_client_new (void); + +G_END_DECLS + +#endif /* __GST_RTSP_EXT_CLIENT_H__ */ diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c old mode 100644 new mode 100755 index f0cd177..6e5729a --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -52,7 +52,8 @@ typedef struct _GstRTSPClientRTPStats GstRTSPClientRTPStats; -struct _GstRTSPClientRTPStats { +struct _GstRTSPClientRTPStats +{ GstRTSPStream *stream; guint64 last_sent_bytes; guint64 sent_bytes; @@ -138,6 +139,8 @@ struct _GstRTSPWFDClientPrivate GMutex stats_lock; guint stats_timer_id; gboolean rtcp_stats_enabled; + + gchar *sink_user_agent; }; #define DEFAULT_WFD_TIMEOUT 60 @@ -149,6 +152,11 @@ enum SIGNAL_WFD_GET_PARAMETER_REQUEST, SIGNAL_WFD_KEEP_ALIVE_FAIL, SIGNAL_WFD_PLAYING_DONE, + SIGNAL_WFD_RTP_STATS, + SIGNAL_WFD_M3_REQ_MSG, + SIGNAL_WFD_M3_RES_MSG, + SIGNAL_WFD_M4_REQ_MSG, + SIGNAL_WFD_SET_PARAM_MSG, SIGNAL_WFD_LAST }; @@ -174,15 +182,17 @@ static void send_generic_wfd_response (GstRTSPWFDClient * client, GstRTSPStatusCode code, GstRTSPContext * ctx); static gchar *wfd_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri); -static void wfd_options_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx); -static void wfd_get_param_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx); +static void wfd_options_request_done (GstRTSPWFDClient * client, + GstRTSPContext * ctx); +static void wfd_get_param_request_done (GstRTSPWFDClient * client, + GstRTSPContext * ctx); static void handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx); static void handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx); -static void wfd_set_keep_alive_condition(GstRTSPWFDClient * client); +static void wfd_set_keep_alive_condition (GstRTSPWFDClient * client); static gboolean wfd_ckeck_keep_alive_response (gpointer userdata); -static gboolean keep_alive_condition(gpointer userdata); -static gboolean wfd_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media, - GstRTSPStream * stream, GstRTSPContext * ctx); +static gboolean keep_alive_condition (gpointer userdata); +static gboolean wfd_configure_client_media (GstRTSPClient * client, + GstRTSPMedia * media, GstRTSPStream * stream, GstRTSPContext * ctx); GstRTSPResult prepare_trigger_request (GstRTSPWFDClient * client, GstRTSPMessage * request, GstWFDTriggerType trigger_type, gchar * url); @@ -240,17 +250,50 @@ gst_rtsp_wfd_client_class_init (GstRTSPWFDClientClass * klass) G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT); gst_rtsp_client_wfd_signals[SIGNAL_WFD_KEEP_ALIVE_FAIL] = - g_signal_new ("wfd-keep-alive-fail", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstRTSPWFDClientClass, wfd_keep_alive_fail), NULL, NULL, - g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE); + g_signal_new ("wfd-keep-alive-fail", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_keep_alive_fail), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 0, G_TYPE_NONE); gst_rtsp_client_wfd_signals[SIGNAL_WFD_PLAYING_DONE] = - g_signal_new ("wfd-playing-done", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstRTSPWFDClientClass, wfd_playing_done), NULL, NULL, - g_cclosure_marshal_generic, G_TYPE_NONE, 0, G_TYPE_NONE); + g_signal_new ("wfd-playing-done", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_playing_done), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 0, G_TYPE_NONE); + + gst_rtsp_client_wfd_signals[SIGNAL_WFD_RTP_STATS] = + g_signal_new ("wfd-rtp-stats", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_rtp_stats), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, GST_TYPE_STRUCTURE); + + gst_rtsp_client_wfd_signals[SIGNAL_WFD_M3_REQ_MSG] = + g_signal_new ("wfd-m3-request-msg", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_handle_m3_req_msg), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_STRING, 1, G_TYPE_STRING); + + gst_rtsp_client_wfd_signals[SIGNAL_WFD_M3_RES_MSG] = + g_signal_new ("wfd-m3-response-msg", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_handle_m3_res_msg), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, G_TYPE_STRING); + + gst_rtsp_client_wfd_signals[SIGNAL_WFD_M4_REQ_MSG] = + g_signal_new ("wfd-m4-request-msg", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_handle_m4_req_msg), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_STRING, 1, G_TYPE_STRING); + + gst_rtsp_client_wfd_signals[SIGNAL_WFD_SET_PARAM_MSG] = + g_signal_new ("wfd-set-param-msg", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass, + wfd_handle_set_param_msg), NULL, NULL, g_cclosure_marshal_generic, + G_TYPE_NONE, 1, G_TYPE_STRING); klass->wfd_options_request = wfd_options_request_done; klass->wfd_get_param_request = wfd_get_param_request_done; + klass->configure_client_media = wfd_configure_client_media; GST_DEBUG_CATEGORY_INIT (rtsp_wfd_client_debug, "rtspwfdclient", 0, "GstRTSPWFDClient"); @@ -278,6 +321,7 @@ gst_rtsp_wfd_client_init (GstRTSPWFDClient * client) priv->stats_timer_id = -1; priv->rtcp_stats_enabled = FALSE; memset (&priv->stats, 0x00, sizeof (GstRTSPClientRTPStats)); + priv->sink_user_agent = NULL; GST_INFO_OBJECT (client, "Client is initialized"); } @@ -298,7 +342,12 @@ gst_rtsp_wfd_client_finalize (GObject * obj) g_free (priv->host_address); if (priv->stats_timer_id > 0) - g_source_remove(priv->stats_timer_id); + g_source_remove (priv->stats_timer_id); + + if (priv->sink_user_agent) { + g_free (priv->sink_user_agent); + priv->sink_user_agent = NULL; + } g_mutex_clear (&priv->keep_alive_lock); g_mutex_clear (&priv->stats_lock); @@ -373,48 +422,53 @@ wfd_display_rtp_stats (gpointer userdata) priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); if (!priv) { - GST_ERROR("No priv"); + GST_ERROR ("No priv"); return FALSE; } - g_mutex_lock(&priv->stats_lock); + g_mutex_lock (&priv->stats_lock); seqnum = gst_rtsp_stream_get_current_seqnum (priv->stats.stream); bytes = gst_rtsp_stream_get_udp_sent_bytes (priv->stats.stream); GST_INFO ("----------------------------------------------------\n"); GST_INFO ("Sent RTP packets : %d", seqnum - priv->stats.last_seqnum); - GST_INFO ("Sent Bytes of RTP packets : %lld bytes", bytes - priv->stats.last_sent_bytes); + GST_INFO ("Sent Bytes of RTP packets : %lld bytes", + bytes - priv->stats.last_sent_bytes); priv->stats.last_seqnum = seqnum; priv->stats.last_sent_bytes = bytes; if (priv->rtcp_stats_enabled) { GST_INFO ("Fraction Lost: %d", priv->stats.fraction_lost); - GST_INFO ("Cumulative number of packets lost: %d", priv->stats.cumulative_lost_num); - GST_INFO ("Extended highest sequence number received: %d", priv->stats.max_seqnum); + GST_INFO ("Cumulative number of packets lost: %d", + priv->stats.cumulative_lost_num); + GST_INFO ("Extended highest sequence number received: %d", + priv->stats.max_seqnum); GST_INFO ("Interarrival Jitter: %d", priv->stats.arrival_jitter); GST_INFO ("Round trip time : %d", priv->stats.rtt); } GST_INFO ("----------------------------------------------------\n"); - g_mutex_unlock(&priv->stats_lock); + g_mutex_unlock (&priv->stats_lock); return TRUE; } static void -on_rtcp_stats (GstRTSPStream *stream, GstStructure *stats, GstRTSPClient *client) +on_rtcp_stats (GstRTSPStream * stream, GstStructure * stats, + GstRTSPClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); guint fraction_lost, exthighestseq, jitter, lsr, dlsr, rtt; gint packetslost; - if (!priv) return; + if (!priv) + return; - g_mutex_lock(&priv->stats_lock); + g_mutex_lock (&priv->stats_lock); gst_structure_get_uint (stats, "rb-fractionlost", &fraction_lost); gst_structure_get_int (stats, "rb-packetslost", &packetslost); @@ -428,15 +482,17 @@ on_rtcp_stats (GstRTSPStream *stream, GstStructure *stats, GstRTSPClient *client priv->rtcp_stats_enabled = TRUE; priv->stats.stream = stream; - priv->stats.fraction_lost = (guint8)fraction_lost; - priv->stats.cumulative_lost_num += (guint32)fraction_lost; - priv->stats.max_seqnum = (guint16)exthighestseq; - priv->stats.arrival_jitter = (guint32)jitter; - priv->stats.lsr = (guint32)lsr; - priv->stats.dlsr = (guint32)dlsr; - priv->stats.rtt = (guint32)rtt; + priv->stats.fraction_lost = (guint8) fraction_lost; + priv->stats.cumulative_lost_num += (guint32) fraction_lost; + priv->stats.max_seqnum = (guint16) exthighestseq; + priv->stats.arrival_jitter = (guint32) jitter; + priv->stats.lsr = (guint32) lsr; + priv->stats.dlsr = (guint32) dlsr; + priv->stats.rtt = (guint32) rtt; - g_mutex_unlock(&priv->stats_lock); + g_mutex_unlock (&priv->stats_lock); + g_signal_emit (client, gst_rtsp_client_wfd_signals[SIGNAL_WFD_RTP_STATS], 0, + stats); } static gboolean @@ -447,13 +503,16 @@ wfd_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media, GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); if (priv) priv->stats.stream = stream; - g_signal_connect (stream, "rtcp-statistics", (GCallback) on_rtcp_stats, client); + g_signal_connect (stream, "rtcp-statistics", (GCallback) on_rtcp_stats, + client); } - return GST_RTSP_CLIENT_CLASS (gst_rtsp_wfd_client_parent_class)->configure_client_media (client, media, stream, ctx); + return GST_RTSP_CLIENT_CLASS (gst_rtsp_wfd_client_parent_class)-> + configure_client_media (client, media, stream, ctx); } + static void -wfd_options_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx) +wfd_options_request_done (GstRTSPWFDClient * client, GstRTSPContext * ctx) { GstRTSPResult res = GST_RTSP_OK; GstRTSPWFDClientClass *klass = GST_RTSP_WFD_CLIENT_GET_CLASS (client); @@ -475,7 +534,7 @@ wfd_options_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx) } static void -wfd_get_param_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx) +wfd_get_param_request_done (GstRTSPWFDClient * client, GstRTSPContext * ctx) { GstRTSPResult res = GST_RTSP_OK; GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); @@ -499,8 +558,7 @@ wfd_get_param_request_done (GstRTSPWFDClient * client, GstRTSPContext *ctx) } static guint -wfd_get_prefered_audio_codec (guint8 srcAudioCodec, - guint sinkAudioCodec) +wfd_get_prefered_audio_codec (guint8 srcAudioCodec, guint sinkAudioCodec) { int i = 0; guint codec = 0; @@ -909,7 +967,7 @@ wfd_get_prefered_resolution (guint64 srcResolution, break; } } - break; + break; default: *cMaxWidth = 0; @@ -942,7 +1000,7 @@ handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx) g_return_if_fail (priv != NULL); - wfd_set_keep_alive_condition(_client); + wfd_set_keep_alive_condition (_client); priv->stats_timer_id = g_timeout_add (2000, wfd_display_rtp_stats, _client); @@ -974,6 +1032,15 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) goto error; } + if (priv->sink_user_agent == NULL) { + gchar *user_agent = NULL; + gst_rtsp_message_get_header (ctx->response, GST_RTSP_HDR_USER_AGENT, + &user_agent, 0); + priv->sink_user_agent = g_strdup (user_agent); + + GST_INFO_OBJECT (_client, "sink user_agent : %s", priv->sink_user_agent); + } + /* parsing the GET_PARAMTER response */ res = gst_rtsp_message_get_body (ctx->response, (guint8 **) & data, &size); if (res != GST_RTSP_OK) { @@ -1102,6 +1169,9 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) #endif } + g_signal_emit (client, + gst_rtsp_client_wfd_signals[SIGNAL_WFD_M3_RES_MSG], 0, data); + g_signal_emit (_client, gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST], 0, ctx); @@ -1118,12 +1188,12 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) gst_rtsp_wfd_client_trigger_request (_client, WFD_TRIGGER_SETUP); } else { - g_mutex_lock(&priv->keep_alive_lock); + g_mutex_lock (&priv->keep_alive_lock); if (priv->keep_alive_flag == FALSE) { GST_INFO_OBJECT (_client, "M16 response is done"); priv->keep_alive_flag = TRUE; } - g_mutex_unlock(&priv->keep_alive_lock); + g_mutex_unlock (&priv->keep_alive_lock); } } @@ -1235,11 +1305,11 @@ handle_wfd_set_param_request (GstRTSPClient * client, GstRTSPContext * ctx) GST_INFO_OBJECT (_client, "SET_PARAMETER Request : %s(%d)", data, size); if (g_strcmp0 ((const gchar *) data, "wfd_idr_request")) send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx); -#if 0 - else - /* TODO-WFD : Handle other set param request */ + else { send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx); -#endif + g_signal_emit (client, + gst_rtsp_client_wfd_signals[SIGNAL_WFD_SET_PARAM_MSG], 0, data); + } } else { goto bad_request; } @@ -1364,8 +1434,7 @@ typedef enum } GstWFDMessageType; static gboolean -_set_negotiated_audio_codec (GstRTSPWFDClient *client, - guint audio_codec) +_set_negotiated_audio_codec (GstRTSPWFDClient * client, guint audio_codec) { GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); @@ -1377,40 +1446,41 @@ _set_negotiated_audio_codec (GstRTSPWFDClient *client, if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { ret = FALSE; - GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no mount points..."); + GST_ERROR_OBJECT (client, + "Failed to set negotiated audio codec: no mount points..."); goto no_mount_points; } - path = g_strdup(WFD_MOUNT_POINT); + path = g_strdup (WFD_MOUNT_POINT); if (!path) { ret = FALSE; - GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no path..."); + GST_ERROR_OBJECT (client, + "Failed to set negotiated audio codec: no path..."); goto no_path; } - if (!(factory = gst_rtsp_mount_points_match (mount_points, - path, &matched))) { - GST_ERROR_OBJECT (client, "Failed to set negotiated audio codec: no factory..."); + if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated audio codec: no factory..."); ret = FALSE; goto no_factory; } - gst_rtsp_media_factory_wfd_set_audio_codec (factory, - audio_codec); + gst_rtsp_media_factory_wfd_set_audio_codec (factory, audio_codec); ret = TRUE; - g_object_unref(factory); + g_object_unref (factory); no_factory: - g_free(path); + g_free (path); no_path: - g_object_unref(mount_points); + g_object_unref (mount_points); no_mount_points: return ret; } static gboolean -_set_negotiated_resolution(GstRTSPWFDClient *client, +_set_negotiated_resolution (GstRTSPWFDClient * client, guint32 width, guint32 height) { GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); @@ -1423,34 +1493,35 @@ _set_negotiated_resolution(GstRTSPWFDClient *client, if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { ret = FALSE; - GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no mount points..."); + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no mount points..."); goto no_mount_points; } - path = g_strdup(WFD_MOUNT_POINT); + path = g_strdup (WFD_MOUNT_POINT); if (!path) { ret = FALSE; - GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no path..."); + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no path..."); goto no_path; } - if (!(factory = gst_rtsp_mount_points_match (mount_points, - path, &matched))) { - GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no factory..."); + if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated resolution: no factory..."); ret = FALSE; goto no_factory; } - gst_rtsp_media_factory_wfd_set_negotiated_resolution(factory, - width, height); + gst_rtsp_media_factory_wfd_set_negotiated_resolution (factory, width, height); ret = TRUE; - g_object_unref(factory); + g_object_unref (factory); no_factory: - g_free(path); + g_free (path); no_path: - g_object_unref(mount_points); + g_object_unref (mount_points); no_mount_points: return ret; } @@ -1539,6 +1610,16 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, GST_ERROR_OBJECT (client, "Failed to get wfd message as text..."); goto error; } else { + gchar *append_data = NULL; + + g_signal_emit (client, gst_rtsp_client_wfd_signals[SIGNAL_WFD_M3_REQ_MSG], + 0, *data, &append_data); + + if (append_data) { + g_free (*data); + *data = append_data; + } + *len = strlen (*data); } } else if (msg_type == M4_REQ_MSG) { @@ -1587,7 +1668,8 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, g_string_append (buf, priv->host_address); } else { GST_ERROR_OBJECT (client, "Failed to get host address"); - if (buf) g_string_free (buf, TRUE); + if (buf) + g_string_free (buf, TRUE); goto error; } @@ -1601,9 +1683,10 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, goto error; } - taudiocodec = wfd_get_prefered_audio_codec (priv->audio_codec, priv->caCodec); + taudiocodec = + wfd_get_prefered_audio_codec (priv->audio_codec, priv->caCodec); priv->caCodec = taudiocodec; - if (!_set_negotiated_audio_codec(client, priv->caCodec)) { + if (!_set_negotiated_audio_codec (client, priv->caCodec)) { GST_ERROR_OBJECT (client, "Failed to set negotiated " "audio codec to media factory..."); } @@ -1678,8 +1761,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, priv->cInterleaved); } - if (!_set_negotiated_resolution(client, priv->cMaxWidth, - priv->cMaxHeight)) { + if (!_set_negotiated_resolution (client, priv->cMaxWidth, priv->cMaxHeight)) { GST_ERROR_OBJECT (client, "Failed to set negotiated " "resolution to media factory..."); } @@ -1699,7 +1781,8 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, /* set the preffered RTP ports for the WFD server */ wfd_res = gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP, - GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1); + GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, + priv->crtp_port0, priv->crtp_port1); if (wfd_res != GST_WFD_OK) { GST_ERROR_OBJECT (client, "Failed to set supported video formats on wfd message..."); @@ -1711,6 +1794,16 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, GST_ERROR_OBJECT (client, "Failed to get wfd message as text..."); goto error; } else { + gchar *append_data = NULL; + + g_signal_emit (client, + gst_rtsp_client_wfd_signals[SIGNAL_WFD_M4_REQ_MSG], 0, *data, + &append_data); + + if (append_data) { + g_free (*data); + *data = append_data; + } *len = strlen (*data); } } else if (msg_type == M5_REQ_MSG) { @@ -1777,7 +1870,7 @@ gst_prepare_request (GstRTSPWFDClient * client, GstRTSPMessage * request, res = gst_rtsp_message_init_request (request, method, url); if (method == GST_RTSP_GET_PARAMETER || method == GST_RTSP_SET_PARAMETER) { - g_free(url); + g_free (url); } if (res < 0) { @@ -2349,7 +2442,7 @@ gst_rtsp_wfd_client_set_video_supported_resolution (GstRTSPWFDClient * client, g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL); priv->video_resolution_supported = supported_reso; - GST_DEBUG ("Resolution : %"G_GUINT64_FORMAT, supported_reso); + GST_DEBUG ("Resolution : %" G_GUINT64_FORMAT, supported_reso); return res; } @@ -2364,7 +2457,7 @@ gst_rtsp_wfd_client_set_video_native_resolution (GstRTSPWFDClient * client, g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL); priv->video_native_resolution = native_reso; - GST_DEBUG ("Native Resolution : %"G_GUINT64_FORMAT, native_reso); + GST_DEBUG ("Native Resolution : %" G_GUINT64_FORMAT, native_reso); return res; } @@ -2387,7 +2480,7 @@ gst_rtsp_wfd_client_set_audio_codec (GstRTSPWFDClient * client, static gboolean wfd_ckeck_keep_alive_response (gpointer userdata) { - GstRTSPWFDClient *client = (GstRTSPWFDClient *)userdata; + GstRTSPWFDClient *client = (GstRTSPWFDClient *) userdata; GstRTSPWFDClientPrivate *priv = NULL; if (!client) { return FALSE; @@ -2403,8 +2496,7 @@ wfd_ckeck_keep_alive_response (gpointer userdata) GST_INFO ("%p: source error notification", client); g_signal_emit (client, - gst_rtsp_client_wfd_signals[SIGNAL_WFD_KEEP_ALIVE_FAIL], 0, - NULL); + gst_rtsp_client_wfd_signals[SIGNAL_WFD_KEEP_ALIVE_FAIL], 0, NULL); return FALSE; } } @@ -2418,17 +2510,18 @@ handle_M16_message (GstRTSPWFDClient * client) GstRTSPMessage request = { 0 }; gchar *url_str = NULL; - url_str = g_strdup("rtsp://localhost/wfd1.0"); + url_str = g_strdup ("rtsp://localhost/wfd1.0"); - res = gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER, url_str); + res = + gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER, url_str); if (res < 0) { GST_ERROR ("init request failed"); - g_free(url_str); + g_free (url_str); return FALSE; } gst_send_request (client, NULL, &request); - g_free(url_str); + g_free (url_str); return GST_RTSP_OK; } @@ -2436,12 +2529,12 @@ handle_M16_message (GstRTSPWFDClient * client) * If yes, keep alive message is sent otherwise error message * will be displayed.*/ static gboolean -keep_alive_condition(gpointer userdata) +keep_alive_condition (gpointer userdata) { GstRTSPWFDClient *client; GstRTSPWFDClientPrivate *priv; GstRTSPResult res; - client = (GstRTSPWFDClient *)userdata; + client = (GstRTSPWFDClient *) userdata; if (!client) { return FALSE; } @@ -2449,36 +2542,38 @@ keep_alive_condition(gpointer userdata) g_return_val_if_fail (priv != NULL, FALSE); - g_mutex_lock(&priv->keep_alive_lock); - if(!priv->keep_alive_flag) { - g_timeout_add(5000, wfd_ckeck_keep_alive_response, client); + g_mutex_lock (&priv->keep_alive_lock); + if (!priv->keep_alive_flag) { + g_timeout_add (5000, wfd_ckeck_keep_alive_response, client); } else { GST_DEBUG_OBJECT (client, "have received last keep alive message response"); } - GST_DEBUG("sending keep alive message"); - res = handle_M16_message(client); - if(res == GST_RTSP_OK) { + GST_DEBUG ("sending keep alive message"); + res = handle_M16_message (client); + if (res == GST_RTSP_OK) { priv->keep_alive_flag = FALSE; } else { GST_ERROR_OBJECT (client, "Failed to send Keep Alive Message"); - g_mutex_unlock(&priv->keep_alive_lock); + g_mutex_unlock (&priv->keep_alive_lock); return FALSE; } - g_mutex_unlock(&priv->keep_alive_lock); + g_mutex_unlock (&priv->keep_alive_lock); return TRUE; } -static -void wfd_set_keep_alive_condition(GstRTSPWFDClient * client) +static void +wfd_set_keep_alive_condition (GstRTSPWFDClient * client) { - g_timeout_add((DEFAULT_WFD_TIMEOUT-5)*1000, keep_alive_condition, client); + g_timeout_add ((DEFAULT_WFD_TIMEOUT - 5) * 1000, keep_alive_condition, + client); } void -gst_rtsp_wfd_client_set_host_address (GstRTSPWFDClient *client, const gchar * address) +gst_rtsp_wfd_client_set_host_address (GstRTSPWFDClient * client, + const gchar * address) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); @@ -2492,7 +2587,7 @@ gst_rtsp_wfd_client_set_host_address (GstRTSPWFDClient *client, const gchar * ad } guint -gst_rtsp_wfd_client_get_audio_codec(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_audio_codec (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2501,7 +2596,7 @@ gst_rtsp_wfd_client_get_audio_codec(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_audio_freq(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_audio_freq (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2510,7 +2605,7 @@ gst_rtsp_wfd_client_get_audio_freq(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_audio_channels(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_audio_channels (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2519,7 +2614,7 @@ gst_rtsp_wfd_client_get_audio_channels(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_audio_bit_width(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_audio_bit_width (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2528,7 +2623,7 @@ gst_rtsp_wfd_client_get_audio_bit_width(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_audio_latency(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_audio_latency (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2537,7 +2632,7 @@ gst_rtsp_wfd_client_get_audio_latency(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_video_codec(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_codec (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2546,7 +2641,7 @@ gst_rtsp_wfd_client_get_video_codec(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_video_native(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_native (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2555,7 +2650,7 @@ gst_rtsp_wfd_client_get_video_native(GstRTSPWFDClient *client) } guint64 -gst_rtsp_wfd_client_get_video_native_resolution(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_native_resolution (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2564,7 +2659,7 @@ gst_rtsp_wfd_client_get_video_native_resolution(GstRTSPWFDClient *client) } guint64 -gst_rtsp_wfd_client_get_video_cea_resolution(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_cea_resolution (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2573,7 +2668,7 @@ gst_rtsp_wfd_client_get_video_cea_resolution(GstRTSPWFDClient *client) } guint64 -gst_rtsp_wfd_client_get_video_vesa_resolution(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_vesa_resolution (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2582,7 +2677,7 @@ gst_rtsp_wfd_client_get_video_vesa_resolution(GstRTSPWFDClient *client) } guint64 -gst_rtsp_wfd_client_get_video_hh_resolution(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_hh_resolution (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2591,7 +2686,7 @@ gst_rtsp_wfd_client_get_video_hh_resolution(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_video_profile(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_profile (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2600,7 +2695,7 @@ gst_rtsp_wfd_client_get_video_profile(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_video_level(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_level (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2609,7 +2704,7 @@ gst_rtsp_wfd_client_get_video_level(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_video_latency(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_latency (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2618,7 +2713,7 @@ gst_rtsp_wfd_client_get_video_latency(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_video_max_height(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_max_height (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2627,7 +2722,7 @@ gst_rtsp_wfd_client_get_video_max_height(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_video_max_width(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_max_width (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2636,7 +2731,7 @@ gst_rtsp_wfd_client_get_video_max_width(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_video_framerate(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_framerate (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2645,7 +2740,7 @@ gst_rtsp_wfd_client_get_video_framerate(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_video_min_slice_size(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_min_slice_size (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2654,7 +2749,7 @@ gst_rtsp_wfd_client_get_video_min_slice_size(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_video_slice_enc_params(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_slice_enc_params (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2663,7 +2758,7 @@ gst_rtsp_wfd_client_get_video_slice_enc_params(GstRTSPWFDClient *client) } guint -gst_rtsp_wfd_client_get_video_framerate_control(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_video_framerate_control (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2672,7 +2767,7 @@ gst_rtsp_wfd_client_get_video_framerate_control(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_rtp_port0(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_rtp_port0 (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2681,7 +2776,7 @@ gst_rtsp_wfd_client_get_rtp_port0(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_rtp_port1(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_rtp_port1 (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2690,7 +2785,7 @@ gst_rtsp_wfd_client_get_rtp_port1(GstRTSPWFDClient *client) } gboolean -gst_rtsp_wfd_client_get_edid_supported(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_edid_supported (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2699,7 +2794,7 @@ gst_rtsp_wfd_client_get_edid_supported(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_edid_hresolution(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_edid_hresolution (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2708,7 +2803,7 @@ gst_rtsp_wfd_client_get_edid_hresolution(GstRTSPWFDClient *client) } guint32 -gst_rtsp_wfd_client_get_edid_vresolution(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_edid_vresolution (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2717,7 +2812,7 @@ gst_rtsp_wfd_client_get_edid_vresolution(GstRTSPWFDClient *client) } gboolean -gst_rtsp_wfd_client_get_protection_enabled(GstRTSPWFDClient *client) +gst_rtsp_wfd_client_get_protection_enabled (GstRTSPWFDClient * client) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_val_if_fail (priv != NULL, 0); @@ -2726,7 +2821,7 @@ gst_rtsp_wfd_client_get_protection_enabled(GstRTSPWFDClient *client) } void -gst_rtsp_wfd_client_set_audio_freq(GstRTSPWFDClient *client, guint freq) +gst_rtsp_wfd_client_set_audio_freq (GstRTSPWFDClient * client, guint freq) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2735,7 +2830,8 @@ gst_rtsp_wfd_client_set_audio_freq(GstRTSPWFDClient *client, guint freq) } void -gst_rtsp_wfd_client_set_edid_supported(GstRTSPWFDClient *client, gboolean supported) +gst_rtsp_wfd_client_set_edid_supported (GstRTSPWFDClient * client, + gboolean supported) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2744,7 +2840,8 @@ gst_rtsp_wfd_client_set_edid_supported(GstRTSPWFDClient *client, gboolean suppor } void -gst_rtsp_wfd_client_set_edid_hresolution(GstRTSPWFDClient *client, guint32 reso) +gst_rtsp_wfd_client_set_edid_hresolution (GstRTSPWFDClient * client, + guint32 reso) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2753,7 +2850,8 @@ gst_rtsp_wfd_client_set_edid_hresolution(GstRTSPWFDClient *client, guint32 reso) } void -gst_rtsp_wfd_client_set_edid_vresolution(GstRTSPWFDClient *client, guint32 reso) +gst_rtsp_wfd_client_set_edid_vresolution (GstRTSPWFDClient * client, + guint32 reso) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2762,7 +2860,8 @@ gst_rtsp_wfd_client_set_edid_vresolution(GstRTSPWFDClient *client, guint32 reso) } void -gst_rtsp_wfd_client_set_protection_enabled(GstRTSPWFDClient *client, gboolean enable) +gst_rtsp_wfd_client_set_protection_enabled (GstRTSPWFDClient * client, + gboolean enable) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2771,7 +2870,8 @@ gst_rtsp_wfd_client_set_protection_enabled(GstRTSPWFDClient *client, gboolean en } void -gst_rtsp_wfd_client_set_hdcp_version(GstRTSPWFDClient *client, GstWFDHDCPProtection version) +gst_rtsp_wfd_client_set_hdcp_version (GstRTSPWFDClient * client, + GstWFDHDCPProtection version) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2780,7 +2880,7 @@ gst_rtsp_wfd_client_set_hdcp_version(GstRTSPWFDClient *client, GstWFDHDCPProtect } void -gst_rtsp_wfd_client_set_hdcp_port(GstRTSPWFDClient *client, guint32 port) +gst_rtsp_wfd_client_set_hdcp_port (GstRTSPWFDClient * client, guint32 port) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2788,19 +2888,21 @@ gst_rtsp_wfd_client_set_hdcp_port(GstRTSPWFDClient *client, guint32 port) priv->hdcp_tcpport = port; } -void gst_rtsp_wfd_client_set_keep_alive_flag(GstRTSPWFDClient *client, gboolean flag) +void +gst_rtsp_wfd_client_set_keep_alive_flag (GstRTSPWFDClient * client, + gboolean flag) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); - g_mutex_lock(&priv->keep_alive_lock); + g_mutex_lock (&priv->keep_alive_lock); if (priv->keep_alive_flag == !(flag)) priv->keep_alive_flag = flag; - g_mutex_unlock(&priv->keep_alive_lock); + g_mutex_unlock (&priv->keep_alive_lock); } void -gst_rtsp_wfd_client_set_aud_codec (GstRTSPWFDClient *client, guint acodec) +gst_rtsp_wfd_client_set_aud_codec (GstRTSPWFDClient * client, guint acodec) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2809,7 +2911,8 @@ gst_rtsp_wfd_client_set_aud_codec (GstRTSPWFDClient *client, guint acodec) } void -gst_rtsp_wfd_client_set_audio_channels(GstRTSPWFDClient *client, guint channels) +gst_rtsp_wfd_client_set_audio_channels (GstRTSPWFDClient * client, + guint channels) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2818,7 +2921,8 @@ gst_rtsp_wfd_client_set_audio_channels(GstRTSPWFDClient *client, guint channels) } void -gst_rtsp_wfd_client_set_audio_bit_width(GstRTSPWFDClient *client, guint bwidth) +gst_rtsp_wfd_client_set_audio_bit_width (GstRTSPWFDClient * client, + guint bwidth) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2827,7 +2931,7 @@ gst_rtsp_wfd_client_set_audio_bit_width(GstRTSPWFDClient *client, guint bwidth) } void -gst_rtsp_wfd_client_set_audio_latency(GstRTSPWFDClient *client, guint latency) +gst_rtsp_wfd_client_set_audio_latency (GstRTSPWFDClient * client, guint latency) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2836,7 +2940,7 @@ gst_rtsp_wfd_client_set_audio_latency(GstRTSPWFDClient *client, guint latency) } void -gst_rtsp_wfd_client_set_video_codec(GstRTSPWFDClient *client, guint vcodec) +gst_rtsp_wfd_client_set_video_codec (GstRTSPWFDClient * client, guint vcodec) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2845,7 +2949,7 @@ gst_rtsp_wfd_client_set_video_codec(GstRTSPWFDClient *client, guint vcodec) } void -gst_rtsp_wfd_client_set_video_native(GstRTSPWFDClient *client, guint native) +gst_rtsp_wfd_client_set_video_native (GstRTSPWFDClient * client, guint native) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2854,7 +2958,8 @@ gst_rtsp_wfd_client_set_video_native(GstRTSPWFDClient *client, guint native) } void -gst_rtsp_wfd_client_set_vid_native_resolution(GstRTSPWFDClient *client, guint64 res) +gst_rtsp_wfd_client_set_vid_native_resolution (GstRTSPWFDClient * client, + guint64 res) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2863,7 +2968,8 @@ gst_rtsp_wfd_client_set_vid_native_resolution(GstRTSPWFDClient *client, guint64 } void -gst_rtsp_wfd_client_set_video_cea_resolution(GstRTSPWFDClient *client, guint64 res) +gst_rtsp_wfd_client_set_video_cea_resolution (GstRTSPWFDClient * client, + guint64 res) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2872,7 +2978,8 @@ gst_rtsp_wfd_client_set_video_cea_resolution(GstRTSPWFDClient *client, guint64 r } void -gst_rtsp_wfd_client_set_video_vesa_resolution(GstRTSPWFDClient *client, guint64 res) +gst_rtsp_wfd_client_set_video_vesa_resolution (GstRTSPWFDClient * client, + guint64 res) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2881,7 +2988,8 @@ gst_rtsp_wfd_client_set_video_vesa_resolution(GstRTSPWFDClient *client, guint64 } void -gst_rtsp_wfd_client_set_video_hh_resolution(GstRTSPWFDClient *client, guint64 res) +gst_rtsp_wfd_client_set_video_hh_resolution (GstRTSPWFDClient * client, + guint64 res) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2890,7 +2998,7 @@ gst_rtsp_wfd_client_set_video_hh_resolution(GstRTSPWFDClient *client, guint64 re } void -gst_rtsp_wfd_client_set_video_profile(GstRTSPWFDClient *client, guint profile) +gst_rtsp_wfd_client_set_video_profile (GstRTSPWFDClient * client, guint profile) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2899,7 +3007,7 @@ gst_rtsp_wfd_client_set_video_profile(GstRTSPWFDClient *client, guint profile) } void -gst_rtsp_wfd_client_set_video_level(GstRTSPWFDClient *client, guint level) +gst_rtsp_wfd_client_set_video_level (GstRTSPWFDClient * client, guint level) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2908,7 +3016,7 @@ gst_rtsp_wfd_client_set_video_level(GstRTSPWFDClient *client, guint level) } void -gst_rtsp_wfd_client_set_video_latency(GstRTSPWFDClient *client, guint latency) +gst_rtsp_wfd_client_set_video_latency (GstRTSPWFDClient * client, guint latency) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2917,7 +3025,8 @@ gst_rtsp_wfd_client_set_video_latency(GstRTSPWFDClient *client, guint latency) } void -gst_rtsp_wfd_client_set_video_max_height(GstRTSPWFDClient *client, guint32 height) +gst_rtsp_wfd_client_set_video_max_height (GstRTSPWFDClient * client, + guint32 height) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2926,7 +3035,8 @@ gst_rtsp_wfd_client_set_video_max_height(GstRTSPWFDClient *client, guint32 heigh } void -gst_rtsp_wfd_client_set_video_max_width(GstRTSPWFDClient *client, guint32 width) +gst_rtsp_wfd_client_set_video_max_width (GstRTSPWFDClient * client, + guint32 width) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2935,7 +3045,8 @@ gst_rtsp_wfd_client_set_video_max_width(GstRTSPWFDClient *client, guint32 width) } void -gst_rtsp_wfd_client_set_video_framerate(GstRTSPWFDClient *client, guint32 framerate) +gst_rtsp_wfd_client_set_video_framerate (GstRTSPWFDClient * client, + guint32 framerate) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2944,7 +3055,8 @@ gst_rtsp_wfd_client_set_video_framerate(GstRTSPWFDClient *client, guint32 framer } void -gst_rtsp_wfd_client_set_video_min_slice_size(GstRTSPWFDClient *client, guint32 slice_size) +gst_rtsp_wfd_client_set_video_min_slice_size (GstRTSPWFDClient * client, + guint32 slice_size) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2953,7 +3065,8 @@ gst_rtsp_wfd_client_set_video_min_slice_size(GstRTSPWFDClient *client, guint32 s } void -gst_rtsp_wfd_client_set_video_slice_enc_params(GstRTSPWFDClient *client, guint32 enc_params) +gst_rtsp_wfd_client_set_video_slice_enc_params (GstRTSPWFDClient * client, + guint32 enc_params) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2962,7 +3075,8 @@ gst_rtsp_wfd_client_set_video_slice_enc_params(GstRTSPWFDClient *client, guint32 } void -gst_rtsp_wfd_client_set_video_framerate_control(GstRTSPWFDClient *client, guint framerate) +gst_rtsp_wfd_client_set_video_framerate_control (GstRTSPWFDClient * client, + guint framerate) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2971,7 +3085,7 @@ gst_rtsp_wfd_client_set_video_framerate_control(GstRTSPWFDClient *client, guint } void -gst_rtsp_wfd_client_set_rtp_port0(GstRTSPWFDClient *client, guint32 port) +gst_rtsp_wfd_client_set_rtp_port0 (GstRTSPWFDClient * client, guint32 port) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); @@ -2980,10 +3094,23 @@ gst_rtsp_wfd_client_set_rtp_port0(GstRTSPWFDClient *client, guint32 port) } void -gst_rtsp_wfd_client_set_rtp_port1(GstRTSPWFDClient *client, guint32 port) +gst_rtsp_wfd_client_set_rtp_port1 (GstRTSPWFDClient * client, guint32 port) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); priv->crtp_port1 = port; } + +gchar * +gst_rtsp_wfd_client_get_sink_user_agent (GstRTSPWFDClient * client) +{ + char *str = NULL; + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + g_return_val_if_fail (priv != NULL, NULL); + + if (priv->sink_user_agent != NULL) + str = g_strdup (priv->sink_user_agent); + + return str; +} diff --git a/gst/rtsp-server/rtsp-client-wfd.h b/gst/rtsp-server/rtsp-client-wfd.h index 5cbf650..f59835b 100644 --- a/gst/rtsp-server/rtsp-client-wfd.h +++ b/gst/rtsp-server/rtsp-client-wfd.h @@ -81,7 +81,9 @@ typedef gboolean (*GstRTSPWFDClientSendFunc) (GstRTSPWFDClient *client, struct _GstRTSPWFDClient { GstRTSPClient parent; +#if 0 /* unused variable */ gint supported_methods; +#endif /*< private >*/ GstRTSPWFDClientPrivate *priv; gpointer _gst_reserved[GST_PADDING]; @@ -107,12 +109,20 @@ struct _GstRTSPWFDClientClass { GstRTSPResult (*prepare_resource) (GstRTSPWFDClient *client, GstRTSPContext *ctx); GstRTSPResult (*confirm_resource) (GstRTSPWFDClient *client, GstRTSPContext *ctx); + gboolean (*configure_client_media) (GstRTSPClient * client, + GstRTSPMedia * media, GstRTSPStream * stream, + GstRTSPContext * ctx); /* signals */ void (*wfd_options_request) (GstRTSPWFDClient *client, GstRTSPContext *ctx); void (*wfd_get_param_request) (GstRTSPWFDClient *client, GstRTSPContext *ctx); void (*wfd_keep_alive_fail) (GstRTSPWFDClient *client); void (*wfd_playing_done) (GstRTSPWFDClient *client); + void (*wfd_rtp_stats) (GstRTSPWFDClient *client, GstStructure *stats); + gchar* (*wfd_handle_m3_req_msg) (GstRTSPWFDClient *client, gchar *data); + void (*wfd_handle_m3_res_msg) (GstRTSPWFDClient *client, gchar *data); + gchar* (*wfd_handle_m4_req_msg) (GstRTSPWFDClient *client, gchar *data); + void (*wfd_handle_set_param_msg) (GstRTSPWFDClient *client, gchar *data); /*< private >*/ gpointer _gst_reserved[GST_PADDING_LARGE]; @@ -197,6 +207,8 @@ void gst_rtsp_wfd_client_set_video_framerate_control(GstRTSPWFDClient *client, g void gst_rtsp_wfd_client_set_rtp_port0(GstRTSPWFDClient *client, guint32 port); void gst_rtsp_wfd_client_set_rtp_port1(GstRTSPWFDClient *client, guint32 port); +gchar *gst_rtsp_wfd_client_get_sink_user_agent(GstRTSPWFDClient *client); + /** * GstRTSPWFDClientSessionFilterFunc: * @client: a #GstRTSPWFDClient object diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index a600537..2017cc2 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -3961,9 +3961,8 @@ gst_rtsp_client_set_watch_flushing (GstRTSPClient * client, gboolean val) priv = GST_RTSP_CLIENT_GET_PRIVATE (client); /* make sure we unblock/block the backlog and accept/don't accept new messages on the watch */ - if (priv->watch != NULL) - { - GST_INFO("Set watch flushing as %d", val); - gst_rtsp_watch_set_flushing (priv->watch, val); + if (priv->watch != NULL) { + GST_INFO ("Set watch flushing as %d", val); + gst_rtsp_watch_set_flushing (priv->watch, val); } } diff --git a/gst/rtsp-server/rtsp-media-ext.c b/gst/rtsp-server/rtsp-media-ext.c new file mode 100755 index 0000000..abecb86 --- /dev/null +++ b/gst/rtsp-server/rtsp-media-ext.c @@ -0,0 +1,773 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/** + * SECTION:rtsp-media + * @short_description: The media pipeline + * @see_also: #GstRTSPMediaFactory, #GstRTSPStream, #GstRTSPSession, + * #GstRTSPSessionMedia + * + * a #GstRTSPMedia contains the complete GStreamer pipeline to manage the + * streaming to the clients. The actual data transfer is done by the + * #GstRTSPStream objects that are created and exposed by the #GstRTSPMedia. + * + * The #GstRTSPMedia is usually created from a #GstRTSPMediaFactory when the + * client does a DESCRIBE or SETUP of a resource. + * + * A media is created with gst_rtsp_media_new() that takes the element that will + * provide the streaming elements. For each of the streams, a new #GstRTSPStream + * object needs to be made with the gst_rtsp_media_create_stream() which takes + * the payloader element and the source pad that produces the RTP stream. + * + * The pipeline of the media is set to PAUSED with gst_rtsp_media_prepare(). The + * prepare method will add rtpbin and sinks and sources to send and receive RTP + * and RTCP packets from the clients. Each stream srcpad is connected to an + * input into the internal rtpbin. + * + * It is also possible to dynamically create #GstRTSPStream objects during the + * prepare phase. With gst_rtsp_media_get_status() you can check the status of + * the prepare phase. + * + * After the media is prepared, it is ready for streaming. It will usually be + * managed in a session with gst_rtsp_session_manage_media(). See + * #GstRTSPSession and #GstRTSPSessionMedia. + * + * The state of the media can be controlled with gst_rtsp_media_set_state (). + * Seeking can be done with gst_rtsp_media_seek(). + * + * With gst_rtsp_media_unprepare() the pipeline is stopped and shut down. When + * gst_rtsp_media_set_eos_shutdown() an EOS will be sent to the pipeline to + * cleanly shut down. + * + * With gst_rtsp_media_set_shared(), the media can be shared between multiple + * clients. With gst_rtsp_media_set_reusable() you can control if the pipeline + * can be prepared again after an unprepare. + * + * Last reviewed on 2013-07-11 (1.0.0) + */ + +#include +#include + +#include +#include + +#include "rtsp-media-ext.h" + +#define GST_RTSP_MEDIA_EXT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_EXT, GstRTSPMediaExtPrivate)) + +#define RTP_RETRANS_PORT 19120 + +typedef struct _GstRTSPMediaExtRTPResender GstRTSPMediaExtRTPResender; + +struct _GstRTSPMediaExtRTPResender +{ + /* sinks used for sending and receiving RTP and RTCP over ipv4, they share + * sockets */ + GstElement *udpsrc_v4; + + /* for TCP transport */ + GstElement *appsrc; + GstElement *funnel; + GstElement *resender; + GstElement *resend_sink; +}; + +struct _GstRTSPMediaExtPrivate +{ + GMutex lock; + GstRTSPMediaExtMode mode; + + GstRTSPMediaExtRTPResender rtp_resender; + GstElement *fecenc; + gboolean is_joined; + + /* pads on the rtpbin */ + GstPad *send_src; + + guint retransmit_port; + guint max_size_k; + guint max_size_p; + GstRTSPMediaExtLatency latency_mode; +#ifdef FORCE_DROP + GstElement *identity; +#endif +}; + +GST_DEBUG_CATEGORY_STATIC (rtsp_media_ext_debug); +#define GST_CAT_DEFAULT rtsp_media_ext_debug + +static void gst_rtsp_media_ext_get_property (GObject * object, guint propid, + GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_ext_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec); +static void gst_rtsp_media_ext_finalize (GObject * obj); + +static void ext_preparing (GstRTSPMedia * media, GstRTSPStream * stream, + guint idx); +static void ext_unpreparing (GstRTSPMedia * media, GstRTSPStream * stream, + guint idx); + +G_DEFINE_TYPE (GstRTSPMediaExt, gst_rtsp_media_ext, GST_TYPE_RTSP_MEDIA); + +static void +gst_rtsp_media_ext_class_init (GstRTSPMediaExtClass * klass) +{ + GObjectClass *gobject_class; + GstRTSPMediaClass *rtsp_media_class; + + g_type_class_add_private (klass, sizeof (GstRTSPMediaExtPrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + rtsp_media_class = GST_RTSP_MEDIA_CLASS (klass); + + gobject_class->get_property = gst_rtsp_media_ext_get_property; + gobject_class->set_property = gst_rtsp_media_ext_set_property; + gobject_class->finalize = gst_rtsp_media_ext_finalize; + + GST_DEBUG_CATEGORY_INIT (rtsp_media_ext_debug, "rtspmediaext", 0, + "GstRTSPMediaExt"); + + rtsp_media_class->preparing = ext_preparing; + rtsp_media_class->unpreparing = ext_unpreparing; +} + +static void +gst_rtsp_media_ext_init (GstRTSPMediaExt * media) +{ + GstRTSPMediaExtPrivate *priv = GST_RTSP_MEDIA_EXT_GET_PRIVATE (media); + + media->priv = priv; + priv->is_joined = FALSE; + priv->mode = MEDIA_EXT_MODE_RESEND; + priv->retransmit_port = RTP_RETRANS_PORT; + priv->max_size_k = 10; + priv->max_size_p = 10; + priv->latency_mode = MEDIA_EXT_LATENCY_LOW; + memset (&priv->rtp_resender, 0x00, sizeof (GstRTSPMediaExtRTPResender)); + g_mutex_init (&priv->lock); +} + +static void +gst_rtsp_media_ext_finalize (GObject * obj) +{ + GstRTSPMediaExtPrivate *priv; + GstRTSPMediaExt *media; + + media = GST_RTSP_MEDIA_EXT (obj); + priv = media->priv; + g_mutex_clear (&priv->lock); + + G_OBJECT_CLASS (gst_rtsp_media_ext_parent_class)->finalize (obj); +} + +static void +gst_rtsp_media_ext_get_property (GObject * object, guint propid, GValue * value, + GParamSpec * pspec) +{ +} + +static void +gst_rtsp_media_ext_set_property (GObject * object, guint propid, + const GValue * value, GParamSpec * pspec) +{ +} + +GstRTSPMediaExt * +gst_rtsp_media_ext_new (GstElement * element) +{ + GstRTSPMediaExt *result; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + result = g_object_new (GST_TYPE_RTSP_MEDIA_EXT, "element", element, NULL); + + return result; +} + +static gint in_idle_probe = FALSE; + +static gboolean +alloc_ports (GstRTSPMediaExt * media) +{ + GstStateChangeReturn ret; + GstElement *udpsrc; + GstElement *udpsink; + + gint tmp_feedback_rtcp; + gint feedback_rtcpport; + + GInetAddress *inetaddr = NULL; + GSocketAddress *feedback_rtcp_sockaddr = NULL; + GSocket *feedback_rtp_socket; + GSocketFamily family = G_SOCKET_FAMILY_IPV4; + const gchar *sink_socket = "socket"; + gchar *resend_uri = NULL; + + GstRTSPMediaExtPrivate *priv; + priv = media->priv; + + g_return_val_if_fail (priv != NULL, GST_PAD_PROBE_REMOVE); + + udpsrc = NULL; + udpsink = NULL; + + /* Start with random port */ + tmp_feedback_rtcp = priv->retransmit_port + 1; + + feedback_rtp_socket = + g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, + NULL); + + if (!feedback_rtp_socket) + goto no_udp_protocol; + + if (inetaddr == NULL) + inetaddr = g_inet_address_new_any (family); + + feedback_rtcp_sockaddr = + g_inet_socket_address_new (inetaddr, tmp_feedback_rtcp); + if (!g_socket_bind (feedback_rtp_socket, feedback_rtcp_sockaddr, FALSE, NULL)) { + g_object_unref (feedback_rtcp_sockaddr); + goto port_error; + } + g_object_unref (feedback_rtcp_sockaddr); + + udpsrc = gst_element_factory_make ("udpsrc", NULL); + + if (udpsrc == NULL) + goto no_udp_protocol; + + g_object_set (G_OBJECT (udpsrc), "socket", feedback_rtp_socket, NULL); + + ret = gst_element_set_state (udpsrc, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_FAILURE) + goto element_error; + + /* all fine, do port check */ + g_object_get (G_OBJECT (udpsrc), "port", &feedback_rtcpport, NULL); + + /* this should not happen... */ + if (feedback_rtcpport != tmp_feedback_rtcp) + goto port_error; + + resend_uri = g_strdup_printf ("udp://localhost:%d", priv->retransmit_port); + if (resend_uri) { + udpsink = gst_element_make_from_uri (GST_URI_SINK, resend_uri, NULL, NULL); + g_free (resend_uri); + } + + if (!udpsink) + goto no_udp_protocol; + + g_object_set (G_OBJECT (udpsink), "close-socket", FALSE, NULL); + g_object_set (G_OBJECT (udpsink), sink_socket, feedback_rtp_socket, NULL); + g_object_set (G_OBJECT (udpsink), "sync", FALSE, NULL); + g_object_set (G_OBJECT (udpsink), "async", FALSE, NULL); + g_object_set (G_OBJECT (udpsink), "send-duplicates", FALSE, NULL); + g_object_set (G_OBJECT (udpsink), "auto-multicast", FALSE, NULL); + g_object_set (G_OBJECT (udpsink), "loop", FALSE, NULL); + + priv->rtp_resender.resend_sink = udpsink; + priv->rtp_resender.udpsrc_v4 = udpsrc; + + return TRUE; + + /* ERRORS */ +no_udp_protocol: + { + goto cleanup; + } +port_error: + { + goto cleanup; + } +element_error: + { + goto cleanup; + } +cleanup: + { + if (udpsrc) { + gst_element_set_state (udpsrc, GST_STATE_NULL); + gst_object_unref (udpsrc); + } + if (udpsink) { + gst_element_set_state (udpsink, GST_STATE_NULL); + gst_object_unref (udpsink); + } + if (inetaddr) + g_object_unref (inetaddr); + return FALSE; + } +} + +static GstPadProbeReturn +pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) +{ + GstPad *sinkpad, *resend_pad, *fecpad; + GstRTSPMediaExt *media = NULL; + GstRTSPMediaExtPrivate *priv; + + if (!g_atomic_int_compare_and_exchange (&in_idle_probe, FALSE, TRUE)) + return GST_PAD_PROBE_OK; + + media = (GstRTSPMediaExt *) user_data; + + priv = media->priv; + + g_return_val_if_fail (priv != NULL, GST_PAD_PROBE_REMOVE); + + sinkpad = gst_pad_get_peer (priv->send_src); + gst_pad_unlink (priv->send_src, sinkpad); + + if (priv->mode & MEDIA_EXT_MODE_RESEND) { + GST_INFO_OBJECT (media, "joining resender"); + resend_pad = + gst_element_get_static_pad (priv->rtp_resender.resender, "rtp_sink"); + gst_pad_link (priv->send_src, resend_pad); + gst_object_unref (resend_pad); + +#ifdef FORCE_DROP + { + GstPad *identity_src, *identity_sink; + identity_src = gst_element_get_static_pad (priv->identity, "src"); + identity_sink = gst_element_get_static_pad (priv->identity, "sink"); + resend_pad = + gst_element_get_static_pad (priv->rtp_resender.resender, "send_src"); + gst_pad_link (resend_pad, identity_sink); + gst_pad_link (identity_src, sinkpad); + gst_object_unref (identity_sink); + gst_object_unref (identity_src); + } +#else + resend_pad = + gst_element_get_static_pad (priv->rtp_resender.resender, "send_src"); + gst_pad_link (resend_pad, sinkpad); +#endif + gst_object_unref (resend_pad); + } else if (priv->mode & MEDIA_EXT_MODE_FEC) { + GST_INFO_OBJECT (media, "joining fec encoder"); + fecpad = gst_element_get_static_pad (priv->fecenc, "sink"); + gst_pad_link (priv->send_src, fecpad); + gst_object_unref (fecpad); + +#ifdef FORCE_DROP + { + GstPad *identity_src, *identity_sink; + identity_src = gst_element_get_static_pad (priv->identity, "src"); + identity_sink = gst_element_get_static_pad (priv->identity, "sink"); + + fecpad = gst_element_get_static_pad (priv->fecenc, "src"); + + gst_pad_link (fecpad, identity_sink); + gst_pad_link (identity_src, sinkpad); + gst_object_unref (identity_sink); + gst_object_unref (identity_src); + } +#else + fecpad = gst_element_get_static_pad (priv->fecenc, "src"); + gst_pad_link (fecpad, sinkpad); +#endif + gst_object_unref (fecpad); + } + + gst_object_unref (sinkpad); + + return GST_PAD_PROBE_REMOVE; +} + +static gboolean +gst_rtsp_media_ext_join_extended_plugin (GstRTSPMediaExt * media, GstBin * bin, + GstElement * rtpbin, GstState state, guint idx) +{ + GstRTSPMediaExtPrivate *priv; + gchar *name; + GstPad *pad, *sinkpad, *selpad; + GstPad *resenderpad; + + g_return_val_if_fail (GST_IS_BIN (bin), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (rtpbin), FALSE); + + priv = media->priv; + g_return_val_if_fail (priv != NULL, FALSE); + + g_mutex_lock (&priv->lock); + if (priv->is_joined) + goto was_joined; + + GST_INFO ("media %p joining rtp resender %u", media, idx); + + /* get pads from the RTP session element for sending and receiving + * RTP/RTCP*/ + name = g_strdup_printf ("send_rtp_src_%u", idx); + priv->send_src = gst_element_get_static_pad (rtpbin, name); + g_free (name); + + /* make resender for RTP and link to stream */ + priv->rtp_resender.resender = gst_element_factory_make ("rtpresender", NULL); + gst_bin_add (bin, priv->rtp_resender.resender); + + gst_element_sync_state_with_parent (priv->rtp_resender.resender); + + if (!alloc_ports (media)) + goto no_ports; + + /* For the sender we create this bit of pipeline for both + * RTP and RTCP. Sync and preroll are enabled on udpsink so + * we need to add a queue before appsink to make the pipeline + * not block. For the TCP case, we want to pump data to the + * client as fast as possible anyway. + * + * .--------. .-----. .---------. + * | rtpbin | | tee | | udpsink | + * | send->sink src->sink | + * '--------' | | '---------' + * | | .---------. .---------. + * | | | queue | | appsink | + * | src->sink src->sink | + * '-----' '---------' '---------' + * + * When only UDP is allowed, we skip the tee, queue and appsink and link the + * udpsink directly to the session. + */ + /* add udpsink */ + gst_bin_add (bin, priv->rtp_resender.resend_sink); + sinkpad = gst_element_get_static_pad (priv->rtp_resender.resend_sink, "sink"); + resenderpad = + gst_element_get_static_pad (priv->rtp_resender.resender, "resend_src"); + + gst_pad_link (resenderpad, sinkpad); + gst_object_unref (resenderpad); + gst_object_unref (sinkpad); + + /* For the receiver we create this bit of pipeline for both + * RTP and RTCP. We receive RTP/RTCP on appsrc and udpsrc + * and it is all funneled into the rtpbin receive pad. + * + * .--------. .--------. .--------. + * | udpsrc | | funnel | | rtpbin | + * | src->sink src->sink | + * '--------' | | '--------' + * .--------. | | + * | appsrc | | | + * | src->sink | + * '--------' '--------' + */ + /* make funnel for the RTP/RTCP receivers */ + priv->rtp_resender.funnel = gst_element_factory_make ("funnel", NULL); + gst_bin_add (bin, priv->rtp_resender.funnel); + + resenderpad = + gst_element_get_static_pad (priv->rtp_resender.resender, "rtcp_sink"); + pad = gst_element_get_static_pad (priv->rtp_resender.funnel, "src"); + gst_pad_link (pad, resenderpad); + gst_object_unref (resenderpad); + gst_object_unref (pad); + + if (priv->rtp_resender.udpsrc_v4) { + /* we set and keep these to playing so that they don't cause NO_PREROLL return + * values */ + gst_element_set_state (priv->rtp_resender.udpsrc_v4, GST_STATE_PLAYING); + gst_element_set_locked_state (priv->rtp_resender.udpsrc_v4, TRUE); + /* add udpsrc */ + gst_bin_add (bin, priv->rtp_resender.udpsrc_v4); + + /* and link to the funnel v4 */ + selpad = gst_element_get_request_pad (priv->rtp_resender.funnel, "sink_%u"); + pad = gst_element_get_static_pad (priv->rtp_resender.udpsrc_v4, "src"); + gst_pad_link (pad, selpad); + gst_object_unref (pad); + gst_object_unref (selpad); + } + + /* make and add appsrc */ + priv->rtp_resender.appsrc = gst_element_factory_make ("appsrc", NULL); + gst_bin_add (bin, priv->rtp_resender.appsrc); + /* and link to the funnel */ + selpad = gst_element_get_request_pad (priv->rtp_resender.funnel, "sink_%u"); + pad = gst_element_get_static_pad (priv->rtp_resender.appsrc, "src"); + gst_pad_link (pad, selpad); + gst_object_unref (pad); + gst_object_unref (selpad); + + /* check if we need to set to a special state */ + if (state != GST_STATE_NULL) { + if (priv->rtp_resender.resend_sink) + gst_element_set_state (priv->rtp_resender.resend_sink, state); + if (priv->rtp_resender.funnel) + gst_element_set_state (priv->rtp_resender.funnel, state); + if (priv->rtp_resender.appsrc) + gst_element_set_state (priv->rtp_resender.appsrc, state); + } + + /* make alfec encoder for RTP and link to stream */ + priv->fecenc = gst_element_factory_make ("alfecencoder", NULL); + g_object_set (G_OBJECT (priv->fecenc), "max-size-k", priv->max_size_k, NULL); + g_object_set (G_OBJECT (priv->fecenc), "max-size-p", priv->max_size_p, NULL); + GST_DEBUG ("k:%d, p:%d", priv->max_size_k, priv->max_size_p); + g_object_set (G_OBJECT (priv->fecenc), "next-k", priv->max_size_k, NULL); + g_object_set (G_OBJECT (priv->fecenc), "next-p", priv->max_size_p, NULL); + g_object_set (G_OBJECT (priv->fecenc), "symbol-length", 1500, NULL); + gst_bin_add (bin, priv->fecenc); + + gst_element_sync_state_with_parent (priv->fecenc); + +#ifdef FORCE_DROP + priv->identity = gst_element_factory_make ("identity", NULL); + g_object_set (G_OBJECT (priv->identity), "drop-probability", 0.05, NULL); + gst_bin_add (bin, priv->identity); + + gst_element_sync_state_with_parent(priv->identity); +#endif + + in_idle_probe = FALSE; + gst_pad_add_probe (priv->send_src, GST_PAD_PROBE_TYPE_IDLE, pad_probe_cb, + media, NULL); + + priv->is_joined = TRUE; + g_mutex_unlock (&priv->lock); + + return TRUE; + + /* ERRORS */ +was_joined: + { + g_mutex_unlock (&priv->lock); + return TRUE; + } +no_ports: + { + g_mutex_unlock (&priv->lock); + GST_WARNING ("failed to allocate ports %u", idx); + return FALSE; + } +} + + +static void +ext_preparing (GstRTSPMedia * media, GstRTSPStream * stream, guint idx) +{ + gboolean ret = FALSE; + GstElement *rtpbin = NULL; + GstElement *pipeline = NULL; + GstRTSPMediaExt *_media = GST_RTSP_MEDIA_EXT (media); + GstRTSPMediaExtPrivate *priv; + + priv = _media->priv; + g_return_val_if_fail (priv != NULL, 0); + + pipeline = gst_rtsp_media_get_pipeline (media); + rtpbin = gst_rtsp_media_get_rtpbin (media); + + ret = + gst_rtsp_media_ext_join_extended_plugin (_media, GST_BIN (pipeline), + rtpbin, GST_STATE_NULL, idx); + if (!ret) + GST_ERROR_OBJECT (_media, "Fatal error to join resender"); + + g_object_unref (pipeline); + g_object_unref (rtpbin); + + return; +} + +static gboolean +gst_rtsp_media_ext_leave_extended_plugin (GstRTSPMediaExt * media, GstBin * bin, + GstElement * rtpbin) +{ + GstRTSPMediaExtPrivate *priv; + + g_return_val_if_fail (GST_IS_BIN (bin), FALSE); + g_return_val_if_fail (GST_IS_ELEMENT (rtpbin), FALSE); + + priv = media->priv; + g_return_val_if_fail (priv != NULL, FALSE); + + g_mutex_lock (&priv->lock); + if (!priv->is_joined) + goto was_not_joined; + + GST_INFO ("media %p leaving rtp resender", media); + + if (priv->rtp_resender.resend_sink) + gst_element_set_state (priv->rtp_resender.resend_sink, GST_STATE_NULL); + if (priv->rtp_resender.funnel) + gst_element_set_state (priv->rtp_resender.funnel, GST_STATE_NULL); + if (priv->rtp_resender.appsrc) + gst_element_set_state (priv->rtp_resender.appsrc, GST_STATE_NULL); + + if (priv->rtp_resender.udpsrc_v4) { + /* and set udpsrc to NULL now before removing */ + gst_element_set_locked_state (priv->rtp_resender.udpsrc_v4, FALSE); + gst_element_set_state (priv->rtp_resender.udpsrc_v4, GST_STATE_NULL); + /* removing them should also nicely release the request + * pads when they finalize */ + gst_bin_remove (bin, priv->rtp_resender.udpsrc_v4); + } + + if (priv->rtp_resender.resend_sink) + gst_bin_remove (bin, priv->rtp_resender.resend_sink); + if (priv->rtp_resender.appsrc) + gst_bin_remove (bin, priv->rtp_resender.appsrc); + if (priv->rtp_resender.funnel) + gst_bin_remove (bin, priv->rtp_resender.funnel); + + priv->rtp_resender.udpsrc_v4 = NULL; + priv->rtp_resender.resend_sink = NULL; + priv->rtp_resender.appsrc = NULL; + priv->rtp_resender.funnel = NULL; + + GST_INFO ("media %p leaving fec encoder", media); + + if (priv->fecenc) { + gst_element_set_state (priv->fecenc, GST_STATE_NULL); + priv->fecenc = NULL; + } + + gst_object_unref (priv->send_src); + priv->send_src = NULL; + priv->is_joined = FALSE; + g_mutex_unlock (&priv->lock); + + return TRUE; + +was_not_joined: + { + g_mutex_unlock (&priv->lock); + return TRUE; + } +} + + +static void +ext_unpreparing (GstRTSPMedia * media, GstRTSPStream * stream, guint idx) +{ + gboolean ret = FALSE; + GstElement *rtpbin = NULL; + GstElement *pipeline = NULL; + GstRTSPMediaExt *_media = GST_RTSP_MEDIA_EXT (media); + GstRTSPMediaExtPrivate *priv; + + priv = _media->priv; + g_return_val_if_fail (priv != NULL, 0); + + pipeline = gst_rtsp_media_get_pipeline (media); + rtpbin = gst_rtsp_media_get_rtpbin (media); + + ret = + gst_rtsp_media_ext_leave_extended_plugin (_media, GST_BIN (pipeline), + rtpbin); + + if (!ret) + GST_ERROR_OBJECT (_media, "Fatal error to leave resender"); + + g_object_unref (pipeline); + g_object_unref (rtpbin); + + return; +} + +guint +gst_rtsp_media_ext_get_resent_packets (GstRTSPMediaExt * media) +{ + guint resent_packets = 0; + GstRTSPMediaExtPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + + priv = media->priv; + g_return_val_if_fail (priv != NULL, 0); + + g_object_get (G_OBJECT (priv->rtp_resender.resender), "rtp-packets-resend", + &resent_packets, NULL); + + return resent_packets; +} + +void +gst_rtsp_media_ext_set_extended_mode (GstRTSPMediaExt * media, + GstRTSPMediaExtMode mode) +{ + GstRTSPMediaExtPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + + priv = media->priv; + g_return_val_if_fail (priv != NULL, 0); + + priv->mode = mode; +} + +void +gst_rtsp_media_ext_set_retrans_port (GstRTSPMediaExt * media, guint port) +{ + GstRTSPMediaExtPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + + priv = media->priv; + g_return_val_if_fail (priv != NULL, 0); + + priv->retransmit_port = port; +} + +void +gst_rtsp_media_ext_set_fec_value (GstRTSPMediaExt * media, guint max_k, + guint max_p) +{ + GstRTSPMediaExtPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + + priv = media->priv; + g_return_val_if_fail (priv != NULL, 0); + + priv->max_size_k = max_k; + priv->max_size_p = max_p; +} + +void +gst_rtsp_media_ext_set_latency_mode (GstRTSPMediaExt * media, + GstRTSPMediaExtLatency latency) +{ + GstRTSPMediaExtPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + + priv = media->priv; + g_return_val_if_fail (priv != NULL, 0); + + priv->latency_mode = latency; +} + +void +gst_rtsp_media_ext_set_next_param (GstRTSPMediaExt * media, gint32 next_k, + gint32 next_p) +{ + GstRTSPMediaExtPrivate *priv; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + + priv = media->priv; + g_return_val_if_fail (priv != NULL, 0); + + g_object_set (G_OBJECT (priv->fecenc), "next-k", next_k, NULL); + g_object_set (G_OBJECT (priv->fecenc), "next-p", next_p, NULL); +} diff --git a/gst/rtsp-server/rtsp-media-ext.h b/gst/rtsp-server/rtsp-media-ext.h new file mode 100755 index 0000000..5bf4d93 --- /dev/null +++ b/gst/rtsp-server/rtsp-media-ext.h @@ -0,0 +1,115 @@ +/* GStreamer + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#ifndef __GST_RTSP_MEDIA_EXT_H__ +#define __GST_RTSP_MEDIA_EXT_H__ + +G_BEGIN_DECLS + +/* types for the media */ +#define GST_TYPE_RTSP_MEDIA_EXT (gst_rtsp_media_ext_get_type ()) +#define GST_IS_RTSP_MEDIA_EXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_MEDIA_EXT)) +#define GST_IS_RTSP_MEDIA_EXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_MEDIA_EXT)) +#define GST_RTSP_MEDIA_EXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_MEDIA_EXT, GstRTSPMediaExtClass)) +#define GST_RTSP_MEDIA_EXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_MEDIA_EXT, GstRTSPMediaExt)) +#define GST_RTSP_MEDIA_EXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_MEDIA_EXT, GstRTSPMediaExtClass)) +#define GST_RTSP_MEDIA_EXT_CAST(obj) ((GstRTSPMediaExt*)(obj)) +#define GST_RTSP_MEDIA_EXT_CLASS_CAST(klass) ((GstRTSPMediaExtClass*)(klass)) + +typedef struct _GstRTSPMediaExt GstRTSPMediaExt; +typedef struct _GstRTSPMediaExtClass GstRTSPMediaExtClass; +typedef struct _GstRTSPMediaExtPrivate GstRTSPMediaExtPrivate; + +#include "rtsp-stream.h" + +typedef enum { + MEDIA_EXT_MODE_NONE = (0 << 0), + MEDIA_EXT_MODE_RESEND = (1 << 0), + MEDIA_EXT_MODE_FEC = (1 << 1) +} GstRTSPMediaExtMode; + +typedef enum { + MEDIA_EXT_LATENCY_NONE, + MEDIA_EXT_LATENCY_LOW, + MEDIA_EXT_LATENCY_MID, + MEDIA_EXT_LATENCY_HIGH +} GstRTSPMediaExtLatency; + +/** + * GstRTSPMedia: + * + * A class that contains the GStreamer element along with a list of + * #GstRTSPStream objects that can produce data. + * + * This object is usually created from a #GstRTSPMediaFactory. + */ +struct _GstRTSPMediaExt { + GstRTSPMedia parent; + + /*< private >*/ + GstRTSPMediaExtPrivate *priv; + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstRTSPMediaClass: + * @handle_message: handle a message + * @prepare: the default implementation adds all elements and sets the + * pipeline's state to GST_STATE_PAUSED (or GST_STATE_PLAYING + * in case of NO_PREROLL elements). + * @unprepare: the default implementation sets the pipeline's state + * to GST_STATE_NULL and removes all elements. + * @suspend: the default implementation sets the pipeline's state to + * GST_STATE_NULL GST_STATE_PAUSED depending on the selected + * suspend mode. + * @unsuspend: the default implementation reverts the suspend operation. + * The pipeline will be prerolled again if it's state was + * set to GST_STATE_NULL in suspend. + * @convert_range: convert a range to the given unit + * @query_position: query the current position in the pipeline + * @query_stop: query when playback will stop + * + * The RTSP media class + */ +struct _GstRTSPMediaExtClass { + GstRTSPMediaClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GType gst_rtsp_media_ext_get_type (void); + +/* creating the media */ +GstRTSPMediaExt * gst_rtsp_media_ext_new (GstElement *element); +guint gst_rtsp_media_ext_get_resent_packets (GstRTSPMediaExt *media); +void gst_rtsp_media_ext_set_extended_mode (GstRTSPMediaExt *media, GstRTSPMediaExtMode mode); +void gst_rtsp_media_ext_set_retrans_port (GstRTSPMediaExt *media, guint port); +void gst_rtsp_media_ext_set_fec_value (GstRTSPMediaExt *media, guint max_k, guint max_p); +void gst_rtsp_media_ext_set_latency_mode (GstRTSPMediaExt *media, GstRTSPMediaExtLatency latency); +void gst_rtsp_media_ext_set_next_param (GstRTSPMediaExt *media, gint32 next_k, gint32 next_p); + +G_END_DECLS + +#endif /* __GST_RTSP_MEDIA_EXT_H__ */ diff --git a/gst/rtsp-server/rtsp-media-factory-wfd.c b/gst/rtsp-server/rtsp-media-factory-wfd.c old mode 100644 new mode 100755 index 60371b1..c8ff33f --- a/gst/rtsp-server/rtsp-media-factory-wfd.c +++ b/gst/rtsp-server/rtsp-media-factory-wfd.c @@ -39,6 +39,7 @@ #include #include "rtsp-media-factory-wfd.h" #include "gstwfdmessage.h" +#include "rtsp-media-ext.h" #define GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_WFD, GstRTSPMediaFactoryWFDPrivate)) @@ -67,6 +68,12 @@ struct _GstRTSPMediaFactoryWFDPrivate guint video_enc_skip_inbuf_value; GstElement *video_queue; + GstElement *venc; + guint decide_udp_bitrate[21]; + guint min_udp_bitrate; + guint max_udp_bitrate; + gboolean decided_udp_bitrate; + gchar *audio_device; gchar *audio_encoder_aac; gchar *audio_encoder_ac3; @@ -125,6 +132,8 @@ static GstElement *rtsp_media_factory_wfd_create_element (GstRTSPMediaFactory * static GstRTSPMedia *rtsp_media_factory_wfd_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url); +static void _config_bitrate (GstRTSPMediaFactoryWFD * factory); + G_DEFINE_TYPE (GstRTSPMediaFactoryWFD, gst_rtsp_media_factory_wfd, GST_TYPE_RTSP_MEDIA_FACTORY); @@ -150,8 +159,9 @@ gst_rtsp_media_factory_wfd_class_init (GstRTSPMediaFactoryWFDClass * klass) "GstRTSPMediaFactoryWFD"); } -void gst_rtsp_media_factory_wfd_set (GstRTSPMediaFactoryWFD * factory, - guint8 videosrc_type, gchar *audio_device, guint64 audio_latency_time, +void +gst_rtsp_media_factory_wfd_set (GstRTSPMediaFactoryWFD * factory, + guint8 videosrc_type, gchar * audio_device, guint64 audio_latency_time, guint64 audio_buffer_time, gboolean audio_do_timestamp, guint mtu_size) { GstRTSPMediaFactoryWFDPrivate *priv = @@ -166,8 +176,9 @@ void gst_rtsp_media_factory_wfd_set (GstRTSPMediaFactoryWFD * factory, priv->mtu_size = mtu_size; } -void gst_rtsp_media_factory_wfd_set_encoders (GstRTSPMediaFactoryWFD * factory, - gchar *video_encoder, gchar *audio_encoder_aac, gchar *audio_encoder_ac3) +void +gst_rtsp_media_factory_wfd_set_encoders (GstRTSPMediaFactoryWFD * factory, + gchar * video_encoder, gchar * audio_encoder_aac, gchar * audio_encoder_ac3) { GstRTSPMediaFactoryWFDPrivate *priv = GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory); @@ -178,7 +189,8 @@ void gst_rtsp_media_factory_wfd_set_encoders (GstRTSPMediaFactoryWFD * factory, priv->audio_encoder_ac3 = audio_encoder_ac3; } -void gst_rtsp_media_factory_wfd_set_dump_ts (GstRTSPMediaFactoryWFD * factory, +void +gst_rtsp_media_factory_wfd_set_dump_ts (GstRTSPMediaFactoryWFD * factory, gboolean dump_ts) { GstRTSPMediaFactoryWFDPrivate *priv = @@ -187,17 +199,22 @@ void gst_rtsp_media_factory_wfd_set_dump_ts (GstRTSPMediaFactoryWFD * factory, priv->dump_ts = dump_ts; } -void gst_rtsp_media_factory_wfd_set_negotiated_resolution (GstRTSPMediaFactory *factory, - guint32 width, guint32 height) + +void +gst_rtsp_media_factory_wfd_set_negotiated_resolution (GstRTSPMediaFactory * + factory, guint32 width, guint32 height) { GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory); GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv; priv->video_width = width; priv->video_height = height; + _config_bitrate (factory_wfd); } -void gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory *factory, - guint audio_codec) + +void +gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory * factory, + guint audio_codec) { GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory); GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv; @@ -206,6 +223,95 @@ void gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory *factory, } static void +_config_bitrate (GstRTSPMediaFactoryWFD * factory) +{ + GstRTSPMediaFactoryWFDPrivate *priv = factory->priv; + + if (priv->decided_udp_bitrate) { + priv->video_bitrate = priv->decide_udp_bitrate[0]; + priv->min_udp_bitrate = priv->decide_udp_bitrate[1]; + priv->max_udp_bitrate = priv->decide_udp_bitrate[2]; + + if ((priv->video_width * priv->video_height) >= (1920 * 1080)) { + priv->video_bitrate = priv->decide_udp_bitrate[3]; + priv->min_udp_bitrate = priv->decide_udp_bitrate[4]; + priv->max_udp_bitrate = priv->decide_udp_bitrate[5]; + } else if ((priv->video_width * priv->video_height) >= (1280 * 720)) { + priv->video_bitrate = priv->decide_udp_bitrate[6]; + priv->min_udp_bitrate = priv->decide_udp_bitrate[7]; + priv->max_udp_bitrate = priv->decide_udp_bitrate[8]; + } else if ((priv->video_width * priv->video_height) >= (960 * 540)) { + priv->video_bitrate = priv->decide_udp_bitrate[9]; + priv->min_udp_bitrate = priv->decide_udp_bitrate[10]; + priv->max_udp_bitrate = priv->decide_udp_bitrate[11]; + } else if ((priv->video_width * priv->video_height) >= (854 * 480)) { + priv->video_bitrate = priv->decide_udp_bitrate[12]; + priv->min_udp_bitrate = priv->decide_udp_bitrate[13]; + priv->max_udp_bitrate = priv->decide_udp_bitrate[14]; + } else if ((priv->video_width * priv->video_height) >= (640 * 480)) { + priv->video_bitrate = priv->decide_udp_bitrate[15]; + priv->min_udp_bitrate = priv->decide_udp_bitrate[16]; + priv->max_udp_bitrate = priv->decide_udp_bitrate[17]; + } + } +} + +void +gst_rtsp_media_factory_wfd_set_venc_bitrate (GstRTSPMediaFactory * factory, + gint bitrate) +{ + GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory); + GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv; + + g_object_set (priv->venc, "target-bitrate", bitrate, NULL); + priv->video_bitrate = (guint) bitrate; +} + +void +gst_rtsp_media_factory_wfd_get_venc_bitrate (GstRTSPMediaFactory * factory, + gint * bitrate) +{ + int cur_bitrate = 0; + + GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory); + GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv; + + g_object_get (priv->venc, "target-bitrate", &cur_bitrate, NULL); + + if (cur_bitrate == 0) { + *bitrate = priv->video_bitrate; + } else { + *bitrate = (gint) cur_bitrate; + } +} + +void +gst_rtsp_media_factory_wfd_get_config_bitrate (GstRTSPMediaFactory * factory, + guint32 * min, guint32 * max) +{ + GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory); + GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv; + + *min = priv->min_udp_bitrate; + *max = priv->max_udp_bitrate; +} + +void +gst_rtsp_media_factory_wfd_set_config_bitrate (GstRTSPMediaFactoryWFD * factory, + guint * config_bitrate) +{ + GstRTSPMediaFactoryWFDPrivate *priv = factory->priv; + + gint idx = 0; + for (idx = 0; idx < 21; idx++) { + priv->decide_udp_bitrate[idx] = config_bitrate[idx]; + } + priv->decided_udp_bitrate = TRUE; + + _config_bitrate (factory); +} + +static void gst_rtsp_media_factory_wfd_init (GstRTSPMediaFactoryWFD * factory) { GstRTSPMediaFactoryWFDPrivate *priv = @@ -228,6 +334,9 @@ gst_rtsp_media_factory_wfd_init (GstRTSPMediaFactoryWFD * factory) priv->video_height = 480; priv->video_framerate = 30; priv->video_enc_skip_inbuf_value = 5; + priv->min_udp_bitrate = 938861; + priv->max_udp_bitrate = 1572864; + priv->decided_udp_bitrate = FALSE; priv->audio_device = g_strdup ("alsa_output.1.analog-stereo.monitor"); priv->audio_codec = GST_WFD_AUDIO_AAC; @@ -301,7 +410,7 @@ gst_rtsp_media_factory_wfd_set_property (GObject * object, } static GstPadProbeReturn -rtsp_media_wfd_dump_data (GstPad * pad, GstPadProbeInfo *info, gpointer u_data) +rtsp_media_wfd_dump_data (GstPad * pad, GstPadProbeInfo * info, gpointer u_data) { guint8 *data; gsize size; @@ -361,7 +470,7 @@ _rtsp_media_factory_wfd_create_audio_capture_bin (GstRTSPMediaFactoryWFD * GST_INFO_OBJECT (factory, "audio_do_timestamp : %d", priv->audio_do_timestamp); - audio_properties_name = gst_structure_new_from_string(priv->audio_device); + audio_properties_name = gst_structure_new_from_string (priv->audio_device); g_object_set (audiosrc, "stream-properties", audio_properties_name, NULL); g_object_set (audiosrc, "buffer-time", (gint64) priv->audio_buffer_time, @@ -383,15 +492,15 @@ _rtsp_media_factory_wfd_create_audio_capture_bin (GstRTSPMediaFactoryWFD * GST_ERROR_OBJECT (factory, "failed to create audio convert element"); goto create_error; } - g_object_set (audio_convert, "caps", gst_caps_new_simple("audio/x-lpcm", - "width", G_TYPE_INT, 16, - "rate", G_TYPE_INT, 48000, - "channels", G_TYPE_INT, 2, - "dynamic_range", G_TYPE_INT, 0, - "emphasis", G_TYPE_BOOLEAN, FALSE, - "mute", G_TYPE_BOOLEAN, FALSE, NULL), NULL); - g_object_set (audio_convert, "join", (gboolean)FALSE, NULL); - g_object_set (audio_convert, "replace", (gboolean)TRUE, NULL); + g_object_set (audio_convert, "caps", gst_caps_new_simple ("audio/x-lpcm", + "width", G_TYPE_INT, 16, + "rate", G_TYPE_INT, 48000, + "channels", G_TYPE_INT, 2, + "dynamic_range", G_TYPE_INT, 0, + "emphasis", G_TYPE_BOOLEAN, FALSE, + "mute", G_TYPE_BOOLEAN, FALSE, NULL), NULL); + g_object_set (audio_convert, "join", (gboolean) FALSE, NULL); + g_object_set (audio_convert, "replace", (gboolean) TRUE, NULL); acaps2 = gst_element_factory_make ("capsfilter", "audiocaps2"); if (NULL == acaps2) { @@ -399,11 +508,11 @@ _rtsp_media_factory_wfd_create_audio_capture_bin (GstRTSPMediaFactoryWFD * goto create_error; } /* In case of LPCM, uses big endian */ - g_object_set (G_OBJECT (acaps2), "caps", - gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16BE", - /* In case of LPCM, uses big endian */ - "rate", G_TYPE_INT, 48000, - "channels", G_TYPE_INT, 2, NULL), NULL); + g_object_set (G_OBJECT (acaps2), "caps", + gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16BE", + /* In case of LPCM, uses big endian */ + "rate", G_TYPE_INT, 48000, + "channels", G_TYPE_INT, 2, NULL), NULL); } /* create audio caps element */ @@ -492,22 +601,28 @@ _rtsp_media_factory_wfd_create_audio_capture_bin (GstRTSPMediaFactoryWFD * goto create_error; } - gst_bin_add_many (srcbin, audiosrc, acaps2, audio_convert, acaps, aqueue, NULL); + gst_bin_add_many (srcbin, audiosrc, acaps2, audio_convert, acaps, aqueue, + NULL); - if (!gst_element_link_many (audiosrc, acaps2, audio_convert, acaps, aqueue, NULL)) { + if (!gst_element_link_many (audiosrc, acaps2, audio_convert, acaps, aqueue, + NULL)) { GST_ERROR_OBJECT (factory, "Failed to link audio src elements..."); goto create_error; } } priv->audio_queue = aqueue; - if (acodec) g_free (acodec); - if (audio_properties_name) gst_structure_free(audio_properties_name); + if (acodec) + g_free (acodec); + if (audio_properties_name) + gst_structure_free (audio_properties_name); return TRUE; create_error: - if (acodec) g_free (acodec); - if (audio_properties_name) gst_structure_free(audio_properties_name); + if (acodec) + g_free (acodec); + if (audio_properties_name) + gst_structure_free (audio_properties_name); return FALSE; } @@ -579,7 +694,8 @@ _rtsp_media_factory_wfd_create_videotest_bin (GstRTSPMediaFactoryWFD * factory, } venc = gst_element_factory_make (vcodec, "videoenc"); - if (vcodec) g_free (vcodec); + if (vcodec) + g_free (vcodec); if (!venc) { GST_ERROR_OBJECT (factory, "failed to create video encoder element"); @@ -603,13 +719,16 @@ _rtsp_media_factory_wfd_create_videotest_bin (GstRTSPMediaFactoryWFD * factory, goto create_error; } - gst_bin_add_many (srcbin, videosrc, vcaps, videoconvert, venc_caps, venc, vparse, vqueue, NULL); - if (!gst_element_link_many (videosrc, vcaps, videoconvert, venc_caps, venc, vparse, vqueue, NULL)) { + gst_bin_add_many (srcbin, videosrc, vcaps, videoconvert, venc_caps, venc, + vparse, vqueue, NULL); + if (!gst_element_link_many (videosrc, vcaps, videoconvert, venc_caps, venc, + vparse, vqueue, NULL)) { GST_ERROR_OBJECT (factory, "Failed to link video src elements..."); goto create_error; } priv->video_queue = vqueue; + priv->venc = venc; return TRUE; @@ -662,7 +781,8 @@ _rtsp_media_factory_wfd_create_waylandsrc_bin (GstRTSPMediaFactoryWFD * factory, } venc = gst_element_factory_make (vcodec, "videoenc"); - if (vcodec) g_free (vcodec); + if (vcodec) + g_free (vcodec); if (!venc) { GST_ERROR_OBJECT (factory, "failed to create video encoder element"); @@ -672,6 +792,7 @@ _rtsp_media_factory_wfd_create_waylandsrc_bin (GstRTSPMediaFactoryWFD * factory, g_object_set (venc, "aud", 0, NULL); g_object_set (venc, "byte-stream", 1, NULL); g_object_set (venc, "bitrate", 512, NULL); + g_object_set (venc, "target-bitrate", priv->video_bitrate, NULL); vparse = gst_element_factory_make ("h264parse", "videoparse"); if (NULL == vparse) { @@ -693,6 +814,7 @@ _rtsp_media_factory_wfd_create_waylandsrc_bin (GstRTSPMediaFactoryWFD * factory, } priv->video_queue = vqueue; + priv->venc = venc; return TRUE; @@ -744,7 +866,8 @@ _rtsp_media_factory_wfd_create_camera_capture_bin (GstRTSPMediaFactoryWFD * } venc = gst_element_factory_make (vcodec, "videoenc"); - if (vcodec) g_free (vcodec); + if (vcodec) + g_free (vcodec); if (!venc) { GST_ERROR_OBJECT (factory, "failed to create video encoder element"); @@ -776,6 +899,7 @@ _rtsp_media_factory_wfd_create_camera_capture_bin (GstRTSPMediaFactoryWFD * } priv->video_queue = vqueue; + priv->venc = venc; return TRUE; @@ -841,7 +965,8 @@ _rtsp_media_factory_wfd_create_xcapture_bin (GstRTSPMediaFactoryWFD * factory, } venc = gst_element_factory_make (vcodec, "videoenc"); - if (vcodec) g_free (vcodec); + if (vcodec) + g_free (vcodec); if (!venc) { GST_ERROR_OBJECT (factory, "failed to create video encoder element"); @@ -884,6 +1009,7 @@ _rtsp_media_factory_wfd_create_xcapture_bin (GstRTSPMediaFactoryWFD * factory, } priv->video_queue = vqueue; + priv->venc = venc; return TRUE; @@ -966,12 +1092,15 @@ _rtsp_media_factory_wfd_create_xvcapture_bin (GstRTSPMediaFactoryWFD * factory, } priv->video_queue = vqueue; - if (vcodec) g_free (vcodec); + priv->venc = venc; + if (vcodec) + g_free (vcodec); return TRUE; create_error: - if (vcodec) g_free (vcodec); + if (vcodec) + g_free (vcodec); return FALSE; } @@ -1175,7 +1304,8 @@ rtsp_media_factory_wfd_construct (GstRTSPMediaFactory * factory, goto no_element; /* create a new empty media */ - media = gst_rtsp_media_new (element); + //media = gst_rtsp_media_new (element); + media = g_object_new (GST_TYPE_RTSP_MEDIA_EXT, "element", element, NULL); gst_rtsp_media_collect_streams (media); diff --git a/gst/rtsp-server/rtsp-media-factory-wfd.h b/gst/rtsp-server/rtsp-media-factory-wfd.h index 1751a22..582ded4 100644 --- a/gst/rtsp-server/rtsp-media-factory-wfd.h +++ b/gst/rtsp-server/rtsp-media-factory-wfd.h @@ -127,5 +127,14 @@ void gst_rtsp_media_factory_wfd_set_negotiated_resolution (GstRTSPMediaFactory * void gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory *factory, guint audio_codec); +void gst_rtsp_media_factory_wfd_set_venc_bitrate (GstRTSPMediaFactory *factory, + gint bitrate); +void gst_rtsp_media_factory_wfd_get_venc_bitrate (GstRTSPMediaFactory *factory, + gint *bitrate); +void gst_rtsp_media_factory_wfd_get_config_bitrate (GstRTSPMediaFactory *factory, + guint32 *min, guint32 *max); +void gst_rtsp_media_factory_wfd_set_config_bitrate (GstRTSPMediaFactoryWFD *factory, + guint *config_bitrate); + G_END_DECLS #endif /* __GST_RTSP_MEDIA_FACTORY_WFD_H__ */ diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 079730c..569c747 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -180,6 +180,8 @@ enum SIGNAL_UNPREPARED, SIGNAL_TARGET_STATE, SIGNAL_NEW_STATE, + SIGNAL_PREPARING, + SIGNAL_UNPREPARING, SIGNAL_LAST }; @@ -362,6 +364,18 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass) G_STRUCT_OFFSET (GstRTSPMediaClass, new_state), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_INT); + gst_rtsp_media_signals[SIGNAL_PREPARING] = + g_signal_new ("preparing", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRTSPMediaClass, preparing), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_RTSP_STREAM, + G_TYPE_UINT); + + gst_rtsp_media_signals[SIGNAL_UNPREPARING] = + g_signal_new ("unpreparing", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstRTSPMediaClass, unpreparing), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 2, GST_TYPE_RTSP_STREAM, + G_TYPE_UINT); + GST_DEBUG_CATEGORY_INIT (rtsp_media_debug, "rtspmedia", 0, "GstRTSPMedia"); klass->handle_message = default_handle_message; @@ -2062,11 +2076,21 @@ set_state (GstRTSPMedia * media, GstState state) media); ret = gst_element_set_state (priv->pipeline, state); + { + gchar *filename = NULL; + filename = g_strdup_printf ("media_%s", gst_element_state_get_name (state)); + GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (priv->pipeline), + GST_DEBUG_GRAPH_SHOW_ALL, filename); + + g_free (filename); + } + return ret; } GstStateChangeReturn -gst_rtsp_media_set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state) +gst_rtsp_media_set_target_state (GstRTSPMedia * media, GstState state, + gboolean do_state) { GstRTSPMediaPrivate *priv = media->priv; GstStateChangeReturn ret; @@ -2511,6 +2535,9 @@ default_start_prepare (GstRTSPMedia * media) priv->rtpbin, GST_STATE_NULL)) { goto join_bin_failed; } + + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_PREPARING], 0, stream, + i, NULL); } if (priv->rtpbin) @@ -2540,7 +2567,7 @@ default_start_prepare (GstRTSPMedia * media) } if (klass->start_preroll) - if(!klass->start_preroll (media)) + if (!klass->start_preroll (media)) goto preroll_failed; return FALSE; @@ -2611,9 +2638,9 @@ default_prepare (GstRTSPMedia * media, GstRTSPThread * thread) /* do remainder in context */ source = g_idle_source_new (); - if(klass->start_prepare) + if (klass->start_prepare) g_source_set_callback (source, (GSourceFunc) klass->start_prepare, - g_object_ref (media), (GDestroyNotify) g_object_unref); + g_object_ref (media), (GDestroyNotify) g_object_unref); g_source_attach (source, context); g_source_unref (source); @@ -2786,6 +2813,9 @@ finish_unprepare (GstRTSPMedia * media) stream = g_ptr_array_index (priv->streams, i); gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin); + + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_UNPREPARING], 0, stream, + i, NULL); } /* remove the pad signal handlers */ @@ -3845,7 +3875,7 @@ default_unsuspend (GstRTSPMedia * media) { gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING); if (klass->start_preroll) - if(!klass->start_preroll (media)) + if (!klass->start_preroll (media)) goto start_failed; g_rec_mutex_unlock (&priv->state_lock); @@ -4148,3 +4178,37 @@ gst_rtsp_media_get_transport_mode (GstRTSPMedia * media) return res; } + + +GstElement * +gst_rtsp_media_get_pipeline (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media));; + + priv = media->priv; + + g_mutex_lock (&priv->lock); + g_object_ref (priv->pipeline); + g_mutex_unlock (&priv->lock); + + return priv->pipeline; +} + + +GstElement * +gst_rtsp_media_get_rtpbin (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media));; + + priv = media->priv; + + g_mutex_lock (&priv->lock); + g_object_ref (priv->rtpbin); + g_mutex_unlock (&priv->lock); + + return priv->rtpbin; +} diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index 6f0ffdd..0050add 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -167,6 +167,8 @@ struct _GstRTSPMediaClass { gboolean (*handle_sdp) (GstRTSPMedia *media, GstSDPMessage *sdp); + void (*preparing) (GstRTSPMedia *media, GstRTSPStream * stream, guint idx); + void (*unpreparing) (GstRTSPMedia *media, GstRTSPStream * stream, guint idx); /*< private >*/ gpointer _gst_reserved[GST_PADDING_LARGE-1]; }; @@ -262,6 +264,9 @@ void gst_rtsp_media_set_pipeline_state (GstRTSPMedia * media, GstStateChangeReturn gst_rtsp_media_set_target_state (GstRTSPMedia * media, GstState state, gboolean do_state); void gst_rtsp_media_set_status (GstRTSPMedia * media, GstRTSPMediaStatus status); +GstElement * gst_rtsp_media_get_pipeline (GstRTSPMedia * media); +GstElement * gst_rtsp_media_get_rtpbin (GstRTSPMedia * media); + G_END_DECLS #endif /* __GST_RTSP_MEDIA_H__ */ diff --git a/gst/rtsp-server/rtsp-server-wfd.c b/gst/rtsp-server/rtsp-server-wfd.c index 4e72093..0fa2cd5 100644 --- a/gst/rtsp-server/rtsp-server-wfd.c +++ b/gst/rtsp-server/rtsp-server-wfd.c @@ -57,6 +57,7 @@ #include "rtsp-server-wfd.h" #include "rtsp-client-wfd.h" +#include "rtsp-client-ext.h" #define GST_RTSP_WFD_SERVER_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_WFD_SERVER, GstRTSPWFDServerPrivate)) @@ -208,14 +209,15 @@ create_client_wfd (GstRTSPServer * server) GstRTSPSessionPool *session_pool = NULL; GstRTSPMountPoints *mount_points = NULL; GstRTSPAuth *auth = NULL; - GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE(server); + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE (server); g_return_val_if_fail (priv != NULL, NULL); GST_INFO_OBJECT (server, "New Client is being created"); /* a new client connected, create a session to handle the client. */ - client = gst_rtsp_wfd_client_new (); + //client = gst_rtsp_wfd_client_new(); + client = (GstRTSPWFDClient *) gst_rtsp_ext_client_new (); thread_pool = gst_rtsp_server_get_thread_pool (server); session_pool = gst_rtsp_server_get_session_pool (server); @@ -235,13 +237,12 @@ create_client_wfd (GstRTSPServer * server) gst_rtsp_client_set_thread_pool (GST_RTSP_CLIENT_CAST (client), thread_pool); gst_rtsp_wfd_client_set_video_supported_resolution (client, - priv->supported_resolution); + priv->supported_resolution); gst_rtsp_wfd_client_set_video_native_resolution (client, - priv->native_resolution); + priv->native_resolution); - gst_rtsp_wfd_client_set_audio_codec (client, - priv->audio_codec); + gst_rtsp_wfd_client_set_audio_codec (client, priv->audio_codec); GST_RTSP_WFD_SERVER_UNLOCK (server); @@ -281,10 +282,11 @@ gst_rtsp_wfd_server_trigger_request (GstRTSPServer * server, } GstRTSPResult -gst_rtsp_wfd_server_set_supported_reso(GstRTSPWFDServer *server, guint64 supported_reso) +gst_rtsp_wfd_server_set_supported_reso (GstRTSPWFDServer * server, + guint64 supported_reso) { GstRTSPResult res = GST_RTSP_OK; - GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE(server); + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE (server); g_return_val_if_fail (GST_IS_RTSP_WFD_SERVER (server), GST_RTSP_ERROR); g_return_val_if_fail (priv != NULL, GST_RTSP_ERROR); @@ -298,10 +300,11 @@ gst_rtsp_wfd_server_set_supported_reso(GstRTSPWFDServer *server, guint64 support } GstRTSPResult -gst_rtsp_wfd_server_set_video_native_reso (GstRTSPWFDServer *server, guint64 native_reso) +gst_rtsp_wfd_server_set_video_native_reso (GstRTSPWFDServer * server, + guint64 native_reso) { GstRTSPResult res = GST_RTSP_OK; - GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE(server); + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE (server); g_return_val_if_fail (GST_IS_RTSP_WFD_SERVER (server), GST_RTSP_ERROR); g_return_val_if_fail (priv != NULL, GST_RTSP_ERROR); @@ -315,10 +318,11 @@ gst_rtsp_wfd_server_set_video_native_reso (GstRTSPWFDServer *server, guint64 nat } GstRTSPResult -gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer *server, guint8 audio_codec) +gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer * server, + guint8 audio_codec) { GstRTSPResult res = GST_RTSP_OK; - GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE(server); + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE (server); g_return_val_if_fail (GST_IS_RTSP_WFD_SERVER (server), GST_RTSP_ERROR); g_return_val_if_fail (priv != NULL, GST_RTSP_ERROR); diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c index ce2f5a4..6cf0c71 100644 --- a/gst/rtsp-server/rtsp-stream.c +++ b/gst/rtsp-server/rtsp-stream.c @@ -1600,7 +1600,8 @@ check_transport (GObject * source, GstRTSPStream * stream) dump_structure (stats); - g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_RTCP_STATS], 0, stats); + g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_RTCP_STATS], 0, + stats); rtcp_from = gst_structure_get_string (stats, "rtcp-from"); if ((trans = find_transport (stream, rtcp_from))) { @@ -1651,7 +1652,8 @@ on_ssrc_active (GObject * session, GObject * source, GstRTSPStream * stream) GstStructure *stats; g_object_get (source, "stats", &stats, NULL); if (stats) { - g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_RTCP_STATS], 0, stats); + g_signal_emit (stream, gst_rtsp_stream_signals[SIGNAL_RTCP_STATS], 0, + stats); dump_structure (stats); gst_structure_free (stats); @@ -3165,7 +3167,7 @@ gst_rtsp_stream_get_current_seqnum (GstRTSPStream * stream) } guint64 -gst_rtsp_stream_get_udp_sent_bytes (GstRTSPStream *stream) +gst_rtsp_stream_get_udp_sent_bytes (GstRTSPStream * stream) { GstRTSPStreamPrivate *priv; guint64 bytes = 0; diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index b0e3187..41b739c 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 1 +Release: 2 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From a7d6a4022465575a54b578de0514281c79b1314c Mon Sep 17 00:00:00 2001 From: "Hyunsoo, Park" Date: Fri, 11 Nov 2016 13:54:10 +0900 Subject: [PATCH 05/16] Emit signal SIGNAL_NEW_STATE only when state change happens [Version] 1.6.1 [Profile] Common [Issue Type] Modify signal condition [Dependency module] N/A [Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161101.3] Change-Id: I6eb2a742f3ed6eb95da25e92b79aa7e0debf8a1e Signed-off-by: Hyunsoo, Park --- gst/rtsp-server/rtsp-media.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 079730c..d63a4d1 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -4057,11 +4057,11 @@ gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state, media, do_state); if (priv->target_state != state) { - if (do_state) + if (do_state) { media_set_pipeline_state_locked (media, state); - - g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state, - NULL); + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_NEW_STATE], 0, state, + NULL); + } } /* remember where we are */ -- 2.7.4 From b25e522e47134c3709e4ffa5678bee27a80016b9 Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Mon, 21 Nov 2016 16:07:13 +0900 Subject: [PATCH 06/16] Fix return type Delete unreached code [Version] 1.6.1 - 2 [Profile] Common [Issue Type] Bug fix [Dependency module] N/A [Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161111.1] Signed-off-by: SeokHoon Lee Change-Id: Iea325ad74b7b31216c502068b18df2f5163b4b1c --- gst/rtsp-server/rtsp-client-ext.c | 21 ++++++--------------- gst/rtsp-server/rtsp-media-ext.c | 20 ++++++++++---------- gst/rtsp-server/rtsp-media.c | 4 ++-- packaging/gst-rtsp-server.spec | 2 +- 4 files changed, 19 insertions(+), 28 deletions(-) mode change 100755 => 100644 gst/rtsp-server/rtsp-client-ext.c mode change 100755 => 100644 gst/rtsp-server/rtsp-media-ext.c diff --git a/gst/rtsp-server/rtsp-client-ext.c b/gst/rtsp-server/rtsp-client-ext.c old mode 100755 new mode 100644 index 5f73c99..6c41344 --- a/gst/rtsp-server/rtsp-client-ext.c +++ b/gst/rtsp-server/rtsp-client-ext.c @@ -372,7 +372,7 @@ handle_ext_stats (GstRTSPWFDClient * client, GstStructure * stats) GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (_client); guint latest_resend_packets = 0; - g_return_val_if_fail (priv != NULL, FALSE); + g_return_if_fail (priv != NULL); latest_resend_packets = gst_rtsp_media_ext_get_resent_packets (priv->media); @@ -552,7 +552,7 @@ handle_ext_m3_req_msg (GstRTSPWFDClient * client, gchar * data) GstWFDResult wfd_res = GST_WFD_EINVAL; gboolean is_appended = FALSE; - g_return_if_fail (client != NULL); + g_return_val_if_fail (client != NULL, NULL); g_return_val_if_fail (data != NULL, NULL); sink_user_agent = gst_rtsp_wfd_client_get_sink_user_agent (client); @@ -637,7 +637,7 @@ handle_ext_m3_res_msg (GstRTSPWFDClient * client, gchar * data) GstWFDResult wfd_res = GST_WFD_EINVAL; g_return_if_fail (ext_priv != NULL); - g_return_val_if_fail (data != NULL, NULL); + g_return_if_fail (data != NULL); wfd_res = gst_wfd_ext_message_new (&msg); if (wfd_res != GST_WFD_OK) { @@ -811,7 +811,7 @@ handle_ext_set_param_msg (GstRTSPWFDClient * client, gchar * data) GstRTSPExtClientPrivate *priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); - g_return_val_if_fail (data != NULL, NULL); + g_return_if_fail (data != NULL); return; } @@ -823,9 +823,8 @@ handle_ext_m4_req_msg (GstRTSPWFDClient * client, gchar * data) gchar *tmp = NULL; GstRTSPExtClientPrivate *ext_priv = GST_RTSP_EXT_CLIENT_GET_PRIVATE (client); GstWFDResult wfd_res = GST_WFD_EINVAL; - gboolean is_appended = FALSE; - g_return_if_fail (ext_priv != NULL); + g_return_val_if_fail (ext_priv != NULL, NULL); g_return_val_if_fail (data != NULL, NULL); wfd_res = gst_wfd_ext_message_new (&msg); @@ -893,7 +892,6 @@ handle_ext_m4_req_msg (GstRTSPWFDClient * client, gchar * data) if (tmp) { data = g_strconcat (data, tmp, NULL); g_free (tmp); - is_appended = TRUE; } else { GST_ERROR_OBJECT (client, "Failed to gst_wfd_ext_message_as_text"); goto error; @@ -904,16 +902,9 @@ handle_ext_m4_req_msg (GstRTSPWFDClient * client, gchar * data) gst_wfd_ext_listen_media_constructed (client); - if (is_appended == FALSE) { - return NULL; - } else { - return data; - }; - return data; + error: - if (tmp != NULL) - g_free (tmp); if (msg != NULL) gst_wfd_ext_message_free (msg); diff --git a/gst/rtsp-server/rtsp-media-ext.c b/gst/rtsp-server/rtsp-media-ext.c old mode 100755 new mode 100644 index abecb86..d1d2ebe --- a/gst/rtsp-server/rtsp-media-ext.c +++ b/gst/rtsp-server/rtsp-media-ext.c @@ -571,7 +571,7 @@ ext_preparing (GstRTSPMedia * media, GstRTSPStream * stream, guint idx) GstRTSPMediaExtPrivate *priv; priv = _media->priv; - g_return_val_if_fail (priv != NULL, 0); + g_return_if_fail (priv != NULL); pipeline = gst_rtsp_media_get_pipeline (media); rtpbin = gst_rtsp_media_get_rtpbin (media); @@ -666,7 +666,7 @@ ext_unpreparing (GstRTSPMedia * media, GstRTSPStream * stream, guint idx) GstRTSPMediaExtPrivate *priv; priv = _media->priv; - g_return_val_if_fail (priv != NULL, 0); + g_return_if_fail (priv != NULL); pipeline = gst_rtsp_media_get_pipeline (media); rtpbin = gst_rtsp_media_get_rtpbin (media); @@ -720,10 +720,10 @@ gst_rtsp_media_ext_set_retrans_port (GstRTSPMediaExt * media, guint port) { GstRTSPMediaExtPrivate *priv; - g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + g_return_if_fail (GST_IS_RTSP_MEDIA_EXT (media)); priv = media->priv; - g_return_val_if_fail (priv != NULL, 0); + g_return_if_fail (priv != NULL); priv->retransmit_port = port; } @@ -734,10 +734,10 @@ gst_rtsp_media_ext_set_fec_value (GstRTSPMediaExt * media, guint max_k, { GstRTSPMediaExtPrivate *priv; - g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + g_return_if_fail (GST_IS_RTSP_MEDIA_EXT (media)); priv = media->priv; - g_return_val_if_fail (priv != NULL, 0); + g_return_if_fail (priv != NULL); priv->max_size_k = max_k; priv->max_size_p = max_p; @@ -749,10 +749,10 @@ gst_rtsp_media_ext_set_latency_mode (GstRTSPMediaExt * media, { GstRTSPMediaExtPrivate *priv; - g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + g_return_if_fail (GST_IS_RTSP_MEDIA_EXT (media)); priv = media->priv; - g_return_val_if_fail (priv != NULL, 0); + g_return_if_fail (priv != NULL); priv->latency_mode = latency; } @@ -763,10 +763,10 @@ gst_rtsp_media_ext_set_next_param (GstRTSPMediaExt * media, gint32 next_k, { GstRTSPMediaExtPrivate *priv; - g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + g_return_if_fail (GST_IS_RTSP_MEDIA_EXT (media)); priv = media->priv; - g_return_val_if_fail (priv != NULL, 0); + g_return_if_fail (priv != NULL); g_object_set (G_OBJECT (priv->fecenc), "next-k", next_k, NULL); g_object_set (G_OBJECT (priv->fecenc), "next-p", next_p, NULL); diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 8f29da0..f79a457 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -4185,7 +4185,7 @@ gst_rtsp_media_get_pipeline (GstRTSPMedia * media) { GstRTSPMediaPrivate *priv; - g_return_if_fail (GST_IS_RTSP_MEDIA (media));; + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); priv = media->priv; @@ -4202,7 +4202,7 @@ gst_rtsp_media_get_rtpbin (GstRTSPMedia * media) { GstRTSPMediaPrivate *priv; - g_return_if_fail (GST_IS_RTSP_MEDIA (media));; + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL); priv = media->priv; diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index 41b739c..f73387c 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 2 +Release: 3 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From e6b9d94ba0002775c7e1c6e7956e80ffd307f07b Mon Sep 17 00:00:00 2001 From: "Hyunsoo, Park" Date: Wed, 23 Nov 2016 13:48:18 +0900 Subject: [PATCH 07/16] Add 'TCP/UDP Switching' feature Using this feature, User can choose transport layer protocol between TCP and UDP. [Version] 1.6.1-4 [Profile] Common [Issue Type] Add feature [Dependency module] N/A [Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161111.1] Change-Id: Ief6aec65e3058c32760fc5490631c3bff635c254 Signed-off-by: Hyunsoo, Park --- gst/rtsp-server/gstwfdmessage.c | 240 +++++++++++++ gst/rtsp-server/gstwfdmessage.h | 55 +++ gst/rtsp-server/rtsp-client-wfd.c | 701 +++++++++++++++++++++++++++++++++++++- gst/rtsp-server/rtsp-client-wfd.h | 2 + gst/rtsp-server/rtsp-server-wfd.c | 58 ++++ gst/rtsp-server/rtsp-server-wfd.h | 2 + packaging/gst-rtsp-server.spec | 2 +- 7 files changed, 1057 insertions(+), 3 deletions(-) mode change 100644 => 100755 gst/rtsp-server/gstwfdmessage.c mode change 100644 => 100755 gst/rtsp-server/gstwfdmessage.h mode change 100755 => 100644 gst/rtsp-server/rtsp-client-wfd.c mode change 100644 => 100755 gst/rtsp-server/rtsp-client-wfd.h mode change 100644 => 100755 gst/rtsp-server/rtsp-server-wfd.h diff --git a/gst/rtsp-server/gstwfdmessage.c b/gst/rtsp-server/gstwfdmessage.c old mode 100644 new mode 100755 index 0e1f7dd..8d75982 --- a/gst/rtsp-server/gstwfdmessage.c +++ b/gst/rtsp-server/gstwfdmessage.c @@ -334,6 +334,21 @@ gst_wfd_message_uninit (GstWFDMessage * msg) if (msg->idr_request) { FREE_STRING (msg->idr_request); } + if (msg->tcp_ports) { + FREE_STRING(msg->tcp_ports); + } + + if (msg->buf_len) { + FREE_STRING(msg->buf_len); + } + + if (msg->audio_status) { + FREE_STRING(msg->audio_status); + } + + if (msg->video_status) { + FREE_STRING(msg->video_status); + } return GST_WFD_OK; } @@ -444,6 +459,7 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg) #define WFD_READ_STRING(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); REPLACE_STRING (field, temp) #define WFD_READ_UINT32(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 16) #define WFD_READ_UINT32_DIGIT(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoul (temp, NULL, 10) +#define WFD_READ_UINT64_DIGIT(field) _read_string_space_ended (temp, sizeof (temp), v); v+=strlen(temp); field = strtoull (temp, NULL, 10) _read_string_attr_and_value (attr, value, sizeof (attr), sizeof (value), ':', p); @@ -743,6 +759,40 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg) } else if (!g_strcmp0 (attr, GST_STRING_WFD_IDR_REQUEST)) { msg->idr_request = g_new0 (GstWFDIdrRequest, 1); msg->idr_request->idr_request = TRUE; + } else if (!g_strcmp0 (attr, GST_STRING_WFD2_TCP_PORTS)) { + msg->tcp_ports = g_new0 (GstWFDTCPPorts, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->tcp_ports->profile); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->tcp_ports->rtp_port0); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->tcp_ports->rtp_port1); + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->tcp_ports->mode); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD2_BUFFER_LEN)) { + msg->buf_len = g_new0 (GstWFDBufferLen, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->buf_len->buf_len); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD2_AUDIO_STATUS)) { + msg->audio_status = g_new0 (GstWFDAudioReport, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->audio_status->aud_bufsize); + WFD_SKIP_SPACE (v); + WFD_READ_UINT64_DIGIT (msg->audio_status->aud_pts); + } + } else if (!g_strcmp0 (attr, GST_STRING_WFD2_VIDEO_STATUS)) { + msg->video_status = g_new0 (GstWFDVideoReport, 1); + if (strlen (v)) { + WFD_SKIP_SPACE (v); + WFD_READ_UINT32_DIGIT (msg->video_status->vid_bufsize); + WFD_SKIP_SPACE (v); + WFD_READ_UINT64_DIGIT (msg->video_status->vid_pts); + } } return; } @@ -1106,6 +1156,24 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) g_string_append_printf (lines, "\r\n"); } + if (msg->tcp_ports) { + g_string_append_printf (lines, GST_STRING_WFD2_TCP_PORTS); + if (msg->tcp_ports->profile) { + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %s", msg->tcp_ports->profile); + g_string_append_printf (lines, " %d", msg->tcp_ports->rtp_port0); + g_string_append_printf (lines, " %d", msg->tcp_ports->rtp_port1); + g_string_append_printf (lines, " %s", msg->tcp_ports->mode); + } + g_string_append_printf (lines, "\r\n"); + } + + if (msg->buf_len) { + g_string_append_printf (lines, GST_STRING_WFD2_BUFFER_LEN); + g_string_append_printf (lines, ":"); + g_string_append_printf (lines, " %d", msg->buf_len->buf_len); + g_string_append_printf (lines, "\r\n"); + } return g_string_free (lines, FALSE); } @@ -1189,6 +1257,22 @@ gst_wfd_message_param_names_as_text (const GstWFDMessage * msg) g_string_append_printf (lines, GST_STRING_WFD_IDR_REQUEST); g_string_append_printf (lines, "\r\n"); } + if (msg->tcp_ports) { + g_string_append_printf (lines, GST_STRING_WFD2_TCP_PORTS); + g_string_append_printf (lines, "\r\n"); + } + if (msg->buf_len) { + g_string_append_printf (lines, GST_STRING_WFD2_BUFFER_LEN); + g_string_append_printf (lines, "\r\n"); + } + if (msg->audio_status) { + g_string_append_printf (lines, GST_STRING_WFD2_AUDIO_STATUS); + g_string_append_printf (lines, "\r\n"); + } + if (msg->video_status) { + g_string_append_printf (lines, GST_STRING_WFD2_VIDEO_STATUS); + g_string_append_printf (lines, "\r\n"); + } return g_string_free (lines, FALSE); } @@ -1383,6 +1467,35 @@ gst_wfd_message_dump (const GstWFDMessage * msg) g_print (GST_STRING_WFD_IDR_REQUEST); g_print ("\r\n"); } + if (msg->tcp_ports) { + g_print (" TCP Ports : \n"); + if (msg->tcp_ports->profile) { + g_print ("%s\n", msg->tcp_ports->profile); + g_print (" %d\n", msg->tcp_ports->rtp_port0); + g_print (" %d\n", msg->tcp_ports->rtp_port1); + g_print (" %s\n", msg->tcp_ports->mode); + } + g_print ("\r\n"); + } + + if (msg->buf_len) { + g_print (" Buffer Length : %d\n", msg->buf_len->buf_len); + g_print ("\r\n"); + } + + if (msg->audio_status) { + g_print ("Audio Playback Status : \n"); + g_print (" Current audio buffer size : %d\n", msg->audio_status->aud_bufsize); + g_print (" Current audio decoded PTS : %lld\n", msg->audio_status->aud_pts); + g_print ("\r\n"); + } + + if (msg->video_status) { + g_print ("Video Playback Status : \n"); + g_print (" Current video buffer size : %d\n", msg->video_status->vid_bufsize); + g_print (" Current video decoded PTS : %lld\n", msg->video_status->vid_pts); + g_print ("\r\n"); + } return GST_WFD_OK; } @@ -1982,3 +2095,130 @@ gst_wfd_message_get_av_format_change_timing (GstWFDMessage * msg, guint64 * PTS, return GST_WFD_OK; } +GstWFDResult +gst_wfd_messge_set_prefered_tcp_ports (GstWFDMessage *msg, + GstWFDRTSPTransMode trans, + GstWFDRTSPProfile profile, + GstWFDRTSPLowerTrans lowertrans, + guint32 rtp_port0, + guint32 rtp_port1) +{ + GString *lines; + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->tcp_ports) + msg->tcp_ports = g_new0 (GstWFDTCPPorts, 1); + + if (trans != GST_WFD_RTSP_TRANS_UNKNOWN) { + lines = g_string_new (""); + if (trans == GST_WFD_RTSP_TRANS_RTP) + g_string_append_printf (lines, "RTP"); + else if (trans == GST_WFD_RTSP_TRANS_RDT) + g_string_append_printf (lines, "RDT"); + + if (profile == GST_WFD_RTSP_PROFILE_AVP) + g_string_append_printf (lines, "/AVP"); + else if (profile == GST_WFD_RTSP_PROFILE_SAVP) + g_string_append_printf (lines, "/SAVP"); + + if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP) + g_string_append_printf (lines, "/UDP;unicast"); + else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST) + g_string_append_printf (lines, "/UDP;multicast"); + else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_TCP) + g_string_append_printf (lines, "/TCP;unicast"); + else if (lowertrans == GST_WFD_RTSP_LOWER_TRANS_HTTP) + g_string_append_printf (lines, "/HTTP"); + + msg->tcp_ports->profile = g_string_free (lines, FALSE); + msg->tcp_ports->rtp_port0 = rtp_port0; + msg->tcp_ports->rtp_port1 = rtp_port1; + msg->tcp_ports->mode = g_strdup ("mode=play"); + } + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_prefered_tcp_ports (GstWFDMessage *msg, + GstWFDRTSPTransMode *trans, + GstWFDRTSPProfile *profile, + GstWFDRTSPLowerTrans *lowertrans, + guint32 *rtp_port0, + guint32 *rtp_port1) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->tcp_ports != NULL, GST_WFD_EINVAL); + + if (g_strrstr (msg->tcp_ports->profile, "RTP")) + *trans = GST_WFD_RTSP_TRANS_RTP; + if (g_strrstr (msg->tcp_ports->profile, "RDT")) + *trans = GST_WFD_RTSP_TRANS_RDT; + if (g_strrstr (msg->tcp_ports->profile, "AVP")) + *profile = GST_WFD_RTSP_PROFILE_AVP; + if (g_strrstr (msg->tcp_ports->profile, "SAVP")) + *profile = GST_WFD_RTSP_PROFILE_SAVP; + if (g_strrstr (msg->tcp_ports->profile, "UDP;unicast")) + *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP; + if (g_strrstr (msg->tcp_ports->profile, "UDP;multicast")) + *lowertrans = GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST; + if (g_strrstr (msg->tcp_ports->profile, "TCP;unicast")) + *lowertrans = GST_WFD_RTSP_LOWER_TRANS_TCP; + if (g_strrstr (msg->tcp_ports->profile, "HTTP")) + *lowertrans = GST_WFD_RTSP_LOWER_TRANS_HTTP; + + *rtp_port0 = msg->tcp_ports->rtp_port0; + *rtp_port1 = msg->tcp_ports->rtp_port1; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_set_buffer_length (GstWFDMessage *msg, guint buf_len) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + + if (!msg->buf_len) + msg->buf_len = g_new0 (GstWFDBufferLen, 1); + msg->buf_len->buf_len = buf_len; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_buffer_length (GstWFDMessage *msg, guint *buf_len) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->buf_len != NULL, GST_WFD_EINVAL); + + *buf_len = msg->buf_len->buf_len; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_audio_playback_status (GstWFDMessage *msg, + guint *bufsize, + guint64 *pts) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->audio_status != NULL, GST_WFD_EINVAL); + + *bufsize = msg->audio_status->aud_bufsize; + *pts = msg->audio_status->aud_pts; + + return GST_WFD_OK; +} + +GstWFDResult +gst_wfd_message_get_video_playback_status (GstWFDMessage *msg, + guint *bufsize, + guint64 *pts) +{ + g_return_val_if_fail (msg != NULL, GST_WFD_EINVAL); + g_return_val_if_fail (msg->video_status != NULL, GST_WFD_EINVAL); + + *bufsize = msg->video_status->vid_bufsize; + *pts = msg->video_status->vid_pts; + + return GST_WFD_OK; +} diff --git a/gst/rtsp-server/gstwfdmessage.h b/gst/rtsp-server/gstwfdmessage.h old mode 100644 new mode 100755 index b390ef3..5a64696 --- a/gst/rtsp-server/gstwfdmessage.h +++ b/gst/rtsp-server/gstwfdmessage.h @@ -66,6 +66,10 @@ G_BEGIN_DECLS #define GST_STRING_WFD_CONNECTOR_TYPE "wfd_connector_type" #define GST_STRING_WFD_IDR_REQUEST "wfd_idr_request" +#define GST_STRING_WFD2_TCP_PORTS "wfd2_tcp_ports" +#define GST_STRING_WFD2_BUFFER_LEN "wfd2_buffer_len" +#define GST_STRING_WFD2_AUDIO_STATUS "wfd2_audio_playback_status" +#define GST_STRING_WFD2_VIDEO_STATUS "wfd2_video_playback_status" /** * GstWFDResult: * @GST_WFD_OK: A successful return value @@ -422,6 +426,26 @@ typedef struct { gboolean idr_request; } GstWFDIdrRequest; +typedef struct { + gchar *profile; + guint32 rtp_port0; + guint32 rtp_port1; + gchar *mode; +} GstWFDTCPPorts; + +typedef struct { + guint buf_len; +} GstWFDBufferLen; + +typedef struct { + guint aud_bufsize; + guint64 aud_pts; +} GstWFDAudioReport; + +typedef struct { + guint vid_bufsize; + guint64 vid_pts; +} GstWFDVideoReport; /** * GstWFDMessage: * @version: the protocol version @@ -459,6 +483,10 @@ typedef struct { GstWFDStandby *standby; GstWFDConnectorType *connector_type; GstWFDIdrRequest *idr_request; + GstWFDTCPPorts *tcp_ports; + GstWFDBufferLen *buf_len; + GstWFDAudioReport *audio_status; + GstWFDVideoReport *video_status; } GstWFDMessage; GType gst_wfd_message_get_type (void); @@ -613,6 +641,33 @@ GstWFDResult gst_wfd_message_set_av_format_change_timing(GstWFDMessage *msg, GstWFDResult gst_wfd_message_get_av_format_change_timing(GstWFDMessage *msg, guint64 *PTS, guint64 *DTS); +GstWFDResult gst_wfd_messge_set_prefered_tcp_ports (GstWFDMessage *msg, + GstWFDRTSPTransMode trans, + GstWFDRTSPProfile profile, + GstWFDRTSPLowerTrans lowertrans, + guint32 rtp_port0, + guint32 rtp_port1); + +GstWFDResult gst_wfd_message_get_prefered_tcp_ports (GstWFDMessage *msg, + GstWFDRTSPTransMode *trans, + GstWFDRTSPProfile *profile, + GstWFDRTSPLowerTrans *lowertrans, + guint32 *rtp_port0, + guint32 *rtp_port1); + +GstWFDResult gst_wfd_message_set_buffer_length (GstWFDMessage *msg, + guint buf_len); + +GstWFDResult gst_wfd_message_get_buffer_length (GstWFDMessage *msg, + guint *buf_len); + +GstWFDResult gst_wfd_message_get_audio_playback_status (GstWFDMessage *msg, + guint *bufsize, + guint64 *pts); + +GstWFDResult gst_wfd_message_get_video_playback_status (GstWFDMessage *msg, + guint *bufsize, + guint64 *pts); G_END_DECLS #endif /* __GST_WFD_MESSAGE_H__ */ diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c old mode 100755 new mode 100644 index 6e5729a..55c32d7 --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -41,6 +41,11 @@ #include #include +#include +#include +#include +#include +#include #include "rtsp-client-wfd.h" #include "rtsp-media-factory-wfd.h" @@ -71,6 +76,16 @@ struct _GstRTSPClientRTPStats guint resent_packets; }; +typedef enum { + WFD_TS_UDP, + WFD_TS_TCP +} WFDTSMode; + +typedef enum { + WFD_TS_REP_AUDIO, + WFD_TS_REP_VIDEO +} WFDTSReportType; + struct _GstRTSPWFDClientPrivate { GstRTSPWFDClientSendFunc send_func; /* protected by send_lock */ @@ -141,6 +156,19 @@ struct _GstRTSPWFDClientPrivate gboolean rtcp_stats_enabled; gchar *sink_user_agent; + guint ctrans_tcp; + guint cprofile_tcp; + guint clowertrans_tcp; + guint32 crtp_port0_tcp; + guint32 crtp_port1_tcp; + guint buf_len; + WFDTSMode ts_mode; + WFDTSReportType report_type; + GstRTSPWatch *datawatch; + guint datawatchid; + GstRTSPConnection *data_conn; + gchar *uristr; + GMutex tcp_send_lock; }; #define DEFAULT_WFD_TIMEOUT 60 @@ -323,6 +351,9 @@ gst_rtsp_wfd_client_init (GstRTSPWFDClient * client) memset (&priv->stats, 0x00, sizeof (GstRTSPClientRTPStats)); priv->sink_user_agent = NULL; + priv->ts_mode = WFD_TS_UDP; + priv->report_type = WFD_TS_REP_AUDIO; + g_mutex_init (&priv->tcp_send_lock); GST_INFO_OBJECT (client, "Client is initialized"); } @@ -351,6 +382,7 @@ gst_rtsp_wfd_client_finalize (GObject * obj) g_mutex_clear (&priv->keep_alive_lock); g_mutex_clear (&priv->stats_lock); + g_mutex_clear (&priv->tcp_send_lock); G_OBJECT_CLASS (gst_rtsp_wfd_client_parent_class)->finalize (obj); } @@ -499,6 +531,10 @@ static gboolean wfd_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media, GstRTSPStream * stream, GstRTSPContext * ctx) { + if (media) { + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + priv->media = media; + } if (stream) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); if (priv) @@ -1008,6 +1044,378 @@ handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx) gst_rtsp_client_wfd_signals[SIGNAL_WFD_PLAYING_DONE], 0, NULL); } +static gboolean +do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client) +{ + GstRTSPMessage message = { 0 }; + GstRTSPResult res = GST_RTSP_OK; + GstMapInfo map_info; + guint8 *data; + guint usize; + + gst_rtsp_message_init_data (&message, channel); + + /* FIXME, need some sort of iovec RTSPMessage here */ + if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) + return FALSE; + + gst_rtsp_message_take_body (&message, map_info.data, map_info.size); + + g_mutex_lock (&(GST_RTSP_WFD_CLIENT (client)->priv->tcp_send_lock)); + + gst_rtsp_watch_send_message (GST_RTSP_WFD_CLIENT (client)->priv->datawatch, &message, NULL); + + g_mutex_unlock (&(GST_RTSP_WFD_CLIENT (client)->priv->tcp_send_lock)); + + gst_rtsp_message_steal_body (&message, &data, &usize); + gst_buffer_unmap (buffer, &map_info); + + gst_rtsp_message_unset (&message); + + return res == GST_RTSP_OK; +} +static GstRTSPResult +message_received (GstRTSPWatch * watch, GstRTSPMessage * message, + gpointer user_data) +{ + return gst_rtsp_client_handle_message (GST_RTSP_CLIENT (user_data), message); +} + +static GstRTSPResult +message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data) +{ + GstRTSPClient *client; + + client = GST_RTSP_CLIENT (user_data); + if(client == NULL) + return GST_RTSP_ERROR; + return GST_RTSP_OK; +} + +static GstRTSPResult +error (GstRTSPWatch * watch, GstRTSPResult result, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + gchar *str; + + str = gst_rtsp_strresult (result); + GST_INFO ("client %p: received an error %s", client, str); + g_free (str); + + return GST_RTSP_OK; +} +static GstRTSPResult +closed_tcp (GstRTSPWatch * watch, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + + GST_INFO ("client %p: connection closed", client); + + return GST_RTSP_OK; +} + +static GstRTSPResult +error_full_tcp (GstRTSPWatch * watch, GstRTSPResult result, + GstRTSPMessage * message, guint id, gpointer user_data) +{ + GstRTSPClient *client = GST_RTSP_CLIENT (user_data); + gchar *str; + + str = gst_rtsp_strresult (result); + GST_INFO + ("client %p: received an error %s when handling message %p with id %d", + client, str, message, id); + g_free (str); + + return GST_RTSP_OK; +} + +static GstRTSPWatchFuncs watch_funcs_tcp = { + message_received, + message_sent, + closed_tcp, + error, + NULL, + NULL, + error_full_tcp, + NULL +}; +static void +client_watch_notify_tcp (GstRTSPClient * client) +{ + GST_INFO ("client %p: watch destroyed", client); + GST_RTSP_WFD_CLIENT (client)->priv->datawatch = NULL; + GST_RTSP_WFD_CLIENT (client)->priv->data_conn = NULL; +} + +static GstRTSPResult +new_tcp (GstRTSPWFDClient * client) +{ + int fd; + GstRTSPResult res = GST_RTSP_OK; + GstRTSPConnection *conn = NULL; + GstRTSPConnection *parent_conn = NULL; + GstRTSPUrl *url; + guint64 timeout = 20000000; + struct sockaddr_in server_addr; + socklen_t sin_len; + GSource *source; + GMainContext *context; + int retry = 0; + int bsize = 1024000; + int rn = sizeof(int); + int state = 1; + GSocket *tcp = NULL; + + struct sockaddr_in my_addr; + /* client's address */ + gint sockoptval = 1; + int ret; + GSocketAddress *local; + + /* Get the client connection details */ + parent_conn = gst_rtsp_client_get_connection (GST_RTSP_CLIENT (client)); + url = gst_rtsp_connection_get_url (parent_conn); + if(!url) + return GST_RTSP_ERROR; + + gst_rtsp_url_set_port (url, client->priv->crtp_port0_tcp); + + GST_INFO ("create new connection %p ip %s:%d", client, url->host, url->port); + + /* create a TCP/IP socket */ + if ((tcp = g_socket_new (AF_INET, SOCK_STREAM, 0, NULL)) == NULL) { + GST_ERROR ("cannot create socket"); + return GST_RTSP_ERROR; + } + /* allow immediate reuse of the port */ + ret = g_socket_set_option (tcp, SOL_SOCKET, SO_REUSEADDR, sockoptval, NULL); + if(ret == 0) + { + GST_ERROR ("cannot change socket options"); + return GST_RTSP_ERROR; + } + /* bind the socket to our source address */ + memset ((char*)&my_addr, 0, sizeof(my_addr)); + /* 0 out the structure */ + my_addr.sin_family = AF_INET; + /* address family */ + my_addr.sin_port = htons (url->port); + my_addr.sin_addr.s_addr = inet_addr(url->host); + + local = g_socket_address_new_from_native (&my_addr, sizeof(my_addr)); + + g_socket_set_blocking (tcp, FALSE); + +tcp_retry: + if ((g_socket_connect (tcp, local, NULL, NULL))) { + g_print( "Error connecting socket : %s\n", strerror( errno ) ); + if (retry < 50) { + GST_ERROR("Connection failed... Try again..."); + usleep(100000); + retry++; + goto tcp_retry; + } + + return GST_RTSP_ERROR; + } + + if ((res = gst_rtsp_connection_create_from_socket (tcp, url->host, url->port, NULL, &conn)) < 0) + return GST_RTSP_ERROR; + + GST_DEBUG_OBJECT (client, "Able to connect to new port"); + + sin_len = sizeof(struct sockaddr); + fd = g_socket_get_fd (gst_rtsp_connection_get_read_socket (conn)); + if (fd == -1) { + return GST_RTSP_EINVAL; + } + + if (getsockname (fd, (struct sockaddr *)&server_addr, &sin_len) < 0) { + GST_ERROR_OBJECT (client, "Getsockname fail"); + close(fd); + return GST_RTSP_ERROR; + } + + GST_DEBUG_OBJECT (client, "New port created : %d", ntohs(server_addr.sin_port)); + + /* Set send buffer size to 5242880 */ + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bsize, (socklen_t)rn) < 0) { + GST_ERROR_OBJECT(client, "setsockopt failed"); + } else { + getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bsize, (socklen_t *)&rn); + GST_WARNING_OBJECT(client, "New Send buf size : %d\n", bsize); + } + + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state)) < 0) { + GST_ERROR_OBJECT(client, "setsockopt failed"); + } else { + GST_WARNING_OBJECT(client, "TCP NO DELAY"); + } + + client->priv->data_conn = conn; + + /* create watch for the connection and attach */ + client->priv->datawatch = gst_rtsp_watch_new (client->priv->data_conn, &watch_funcs_tcp, client, (GDestroyNotify) client_watch_notify_tcp); + GST_DEBUG_OBJECT (client, "data watch : %p", client->priv->datawatch); + /* find the context to add the watch */ + if ((source = g_main_current_source ())) + context = g_source_get_context (source); + else + context = NULL; + + GST_DEBUG (" source = %p", source); + GST_INFO ("attaching to context %p", context); + client->priv->datawatchid = gst_rtsp_watch_attach (client->priv->datawatch, context); + gst_rtsp_watch_unref (client->priv->datawatch); + return res; +} + +static void +do_keepalive (GstRTSPSession * session) +{ + GST_INFO ("keep session %p alive", session); + gst_rtsp_session_touch (session); +} +static void +map_transport (GstRTSPWFDClient * client, GstRTSPTransport * ct) +{ + switch(client->priv->ctrans) { + case GST_WFD_RTSP_TRANS_RTP: + ct->trans = GST_RTSP_TRANS_RTP; + break; + case GST_WFD_RTSP_TRANS_RDT: + ct->trans = GST_RTSP_TRANS_RDT; + break; + default: + ct->trans = GST_RTSP_TRANS_UNKNOWN; + break; + } + switch(client->priv->cprofile) { + case GST_WFD_RTSP_PROFILE_AVP: + ct->profile = GST_RTSP_PROFILE_AVP; + break; + case GST_WFD_RTSP_PROFILE_SAVP: + ct->profile = GST_RTSP_PROFILE_SAVP; + break; + default: + ct->profile = GST_RTSP_PROFILE_UNKNOWN; + break; + } + switch(client->priv->clowertrans) { + case GST_WFD_RTSP_LOWER_TRANS_UDP: + ct->lower_transport = GST_RTSP_LOWER_TRANS_UDP; + break; + case GST_WFD_RTSP_LOWER_TRANS_UDP_MCAST: + ct->lower_transport = GST_RTSP_LOWER_TRANS_UDP_MCAST; + break; + case GST_WFD_RTSP_LOWER_TRANS_TCP: + ct->lower_transport = GST_RTSP_LOWER_TRANS_TCP; + break; + case GST_WFD_RTSP_LOWER_TRANS_HTTP: + ct->lower_transport = GST_RTSP_LOWER_TRANS_HTTP; + break; + default: + ct->lower_transport = GST_RTSP_LOWER_TRANS_UNKNOWN; + break; + } + + if (client->priv->ts_mode == WFD_TS_TCP) + ct->lower_transport = GST_RTSP_LOWER_TRANS_TCP; +} + +static GstRTSPResult +handle_ts_response (GstRTSPWFDClient * client, GstRTSPContext * ctx) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPTransport *ct; + GstRTSPConnection *conn; + GstRTSPUrl *url = NULL; + GList *t = NULL; + GstRTSPStreamTransport *tr = NULL; + GPtrArray *ta = NULL; + + ta = g_ptr_array_new(); + + t = client->priv->transports; + tr = GST_RTSP_STREAM_TRANSPORT (t->data); + g_ptr_array_add (ta, t->data); + + gst_rtsp_stream_transport_set_callbacks (tr, NULL, NULL, NULL, NULL); + gst_rtsp_stream_transport_set_keepalive (tr, NULL, ctx->session, NULL); + + gst_rtsp_transport_new (&ct); + gst_rtsp_transport_init (ct); + + map_transport (client, ct); + + if (ct->trans != GST_RTSP_TRANS_RTP || ct->profile != GST_RTSP_PROFILE_AVP) { + GST_WARNING_OBJECT (client, "Trans or profile is wrong"); + goto error; + } + if (ct->lower_transport == GST_RTSP_LOWER_TRANS_HTTP || + ct->lower_transport == GST_RTSP_LOWER_TRANS_UNKNOWN) { + GST_WARNING_OBJECT (client, "Lowertrans is wrong"); + goto error; + } + g_free (ct->destination); + if (client->priv->ts_mode == WFD_TS_UDP) { + g_print ("\nSwitched to UDP !!!\n"); + /* Free any previous TCP connection */ + if(client->priv->data_conn) + { + gst_rtsp_connection_close (client->priv->data_conn); + gst_rtsp_connection_free(client->priv->data_conn); + if (client->priv->datawatch) { + g_source_destroy ((GSource *)client->priv->datawatch); + } + } + conn = gst_rtsp_client_get_connection (GST_RTSP_CLIENT (client)); + url = gst_rtsp_connection_get_url (conn); + gst_rtsp_url_set_port (url, client->priv->crtp_port0); + ct->destination = g_strdup (url->host); + ct->client_port.min = client->priv->crtp_port0; + if(client->priv->crtp_port1 == 0) + ct->client_port.max = client->priv->crtp_port0 + 1; + else ct->client_port.max = client->priv->crtp_port1; + } else if (client->priv->ts_mode == WFD_TS_TCP) { + res = new_tcp(client); + if(res != GST_RTSP_OK) + goto error; + + conn = gst_rtsp_client_get_connection (GST_RTSP_CLIENT (client)); + url = gst_rtsp_connection_get_url (conn); + ct->destination = g_strdup (url->host); + ct->client_port.min = client->priv->crtp_port0_tcp; + if(client->priv->crtp_port1_tcp == 0) + ct->client_port.max = client->priv->crtp_port0_tcp + 1; + else ct->client_port.max = client->priv->crtp_port1_tcp; + } + + gst_rtsp_stream_transport_set_transport (tr, ct); + + GST_DEBUG ("client %p: linking transport", client); + if (client->priv->ts_mode == WFD_TS_TCP) { + g_print ("\nSwitched to TCP !!!\n"); + gst_rtsp_stream_transport_set_callbacks (tr, (GstRTSPSendFunc) do_send_data, + (GstRTSPSendFunc) do_send_data, client, NULL); + } + else if(client->priv->ts_mode == WFD_TS_UDP ) { + g_print ("\nSwitched to UDP !!!\n"); + /* configure keepalive for this transport */ + gst_rtsp_stream_transport_set_keepalive (tr, (GstRTSPKeepAliveFunc) do_keepalive, ctx->session, NULL); + gst_rtsp_stream_transport_set_callbacks (tr, NULL, NULL, client, NULL); + } + + gst_rtsp_media_set_state (client->priv->media, GST_STATE_PLAYING, ta); + + g_ptr_array_free (ta, FALSE); + + return res; + +error: + return GST_RTSP_ERROR; +} static void handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) { @@ -1111,6 +1519,28 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) goto error; } } + if (msg->tcp_ports) { + /* Get the TCP ports preferred by WFDSink */ + wfd_res = + gst_wfd_message_get_prefered_tcp_ports (msg, &priv->ctrans_tcp, + &priv->cprofile_tcp, &priv->clowertrans_tcp, &priv->crtp_port0_tcp, + &priv->crtp_port1_tcp); + if (wfd_res != GST_WFD_OK) { + GST_WARNING_OBJECT (client, + "Failed to get wfd prefered RTP ports..."); + goto error; + } + } + + if (msg->buf_len) { + wfd_res = + gst_wfd_message_get_buffer_length (msg, &priv->buf_len); + if (wfd_res != GST_WFD_OK) { + GST_WARNING_OBJECT (client, + "Failed to get wfd prefered RTP ports..."); + goto error; + } + } if (msg->display_edid) { guint32 edid_block_count = 0; @@ -1176,6 +1606,41 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST], 0, ctx); } else { + if (g_strrstr((char *)data, "wfd2_buffer_len")) { + GstWFDResult wfd_res; + GstWFDMessage *msg = NULL; + GST_DEBUG_OBJECT (_client, "Get TS message responce"); + + /* Parse TS response from sink */ + wfd_res = gst_wfd_message_new (&msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to create wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_init (msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to init wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_parse_buffer (data, size, msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to parse wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_get_buffer_length (msg, &_client->priv->buf_len); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to parse wfd message..."); + goto error; + } + + if (GST_RTSP_OK != handle_ts_response (_client, ctx)) { + GST_ERROR_OBJECT (client, "Failed to handle transport switch response"); + goto error; + } + } /* TODO-WFD: Handle another GET_PARAMETER response with body */ } } else if (size == 0) { @@ -1431,6 +1896,8 @@ typedef enum TEARDOWN_TRIGGER, PLAY_TRIGGER, PAUSE_TRIGGER, + TS_REQ_MSG, + TS_REP_REQ_MSG, } GstWFDMessageType; static gboolean @@ -1605,6 +2072,24 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, goto error; } + /* set the preffered TCP ports for the WFD server */ + wfd_res = + gst_wfd_messge_set_prefered_tcp_ports (msg, GST_WFD_RTSP_TRANS_RTP, + GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set tcp ports parameter on wfd message..."); + goto error; + } + + /* set the buffer length for the WFD server */ + wfd_res = + gst_wfd_message_set_buffer_length (msg, 0); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set tcp ports parameter on wfd message..."); + goto error; + } *data = gst_wfd_message_param_names_as_text (msg); if (*data == NULL) { GST_ERROR_OBJECT (client, "Failed to get wfd message as text..."); @@ -1794,6 +2279,69 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, GST_ERROR_OBJECT (client, "Failed to get wfd message as text..."); goto error; } else { + *len = strlen (*data); + } + + } else if (msg_type == TS_REQ_MSG) { + /* create transport switch request to be sent */ + wfd_res = gst_wfd_message_new (&msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to create wfd message..."); + goto error; + } + + wfd_res = gst_wfd_message_init (msg); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, "Failed to init wfd message..."); + goto error; + } + + g_string_append_printf (buf, "rtsp://"); + + if (priv->host_address) { + g_string_append (buf, priv->host_address); + } else { + GST_ERROR_OBJECT (client, "Failed to get host address"); + if (buf) g_string_free (buf, TRUE); + goto error; + } + + g_string_append_printf (buf, "/wfd1.0/streamid=0"); + + /* set the preffered TCP ports for the WFD server */ + if (priv->ts_mode == WFD_TS_UDP) { + wfd_res = + gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP, + GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set prefered RTP ports on wfd message..."); + goto error; + } + } else { + wfd_res = + gst_wfd_messge_set_prefered_tcp_ports (msg, GST_WFD_RTSP_TRANS_RTP, + GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_TCP, priv->crtp_port0_tcp, priv->crtp_port1_tcp); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set prefered TCP ports on wfd message..."); + goto error; + } + } + + wfd_res = + gst_wfd_message_set_buffer_length (msg, 200); + if (wfd_res != GST_WFD_OK) { + GST_ERROR_OBJECT (client, + "Failed to set prefered buffer length on wfd message..."); + goto error; + } + + *data = gst_wfd_message_as_text (msg); + if (*data == NULL) { + GST_ERROR_OBJECT (client, "Failed to get wfd message as text..."); + goto error; + } else { gchar *append_data = NULL; g_signal_emit (client, @@ -3102,8 +3650,157 @@ gst_rtsp_wfd_client_set_rtp_port1 (GstRTSPWFDClient * client, guint32 port) priv->crtp_port1 = port; } -gchar * -gst_rtsp_wfd_client_get_sink_user_agent (GstRTSPWFDClient * client) + +/** +* prepare_transport_switch_request: +* @client: client object +* @request : requst message to be prepared +* @url : url need to be in the request +* +* Prepares request based on @method & @message_type +* +* Returns: a #GstRTSPResult. +*/ +static GstRTSPResult +prepare_transport_switch_request (GstRTSPWFDClient * client, GstRTSPMessage * request) +{ + GstRTSPResult res = GST_RTSP_OK; + gchar *url = NULL; + gchar *msg = NULL; + guint msglen = 0; + GString *msglength; + + GstRTSPMethod method = GST_RTSP_SET_PARAMETER; + + url = g_strdup ("rtsp://localhost/wfd1.0"); + + GST_DEBUG_OBJECT (client, "Preparing request for transport switch"); + + /* initialize the request */ + res = gst_rtsp_message_init_request (request, method, url); + if (res < 0) { + GST_ERROR ("init request failed"); + return res; + } + + /* add content type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, + "text/parameters"); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp request..."); + goto error; + } + + _set_wfd_message_body (client, TS_REQ_MSG, &msg, &msglen); + msglength = g_string_new (""); + g_string_append_printf (msglength, "%d", msglen); + GST_DEBUG ("Transport switch server side message body: %s", msg); + + /* add content-length type */ + res = + gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, + g_string_free (msglength, FALSE)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (client, "Failed to add header to rtsp message..."); + goto error; + } + + g_free (msg); + + return res; + +error: + return GST_RTSP_ERROR; +} + +GstRTSPResult +gst_rtsp_wfd_client_switch_to_udp (GstRTSPWFDClient * client) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPMessage request = { 0 }; + GList *tl = NULL; + GPtrArray *ta = NULL; + + ta = g_ptr_array_new(); + + tl = gst_rtsp_stream_transport_filter (client->priv->stats.stream, NULL, NULL); + client->priv->transports = tl; + g_ptr_array_add (ta, tl->data); + + if (client->priv->ts_mode == WFD_TS_UDP) { + GST_ERROR_OBJECT (client, "Transport already UDP"); + return res; + } + + client->priv->ts_mode = WFD_TS_UDP; + res = prepare_transport_switch_request (client, &request); + if (GST_RTSP_OK != res) { + GST_ERROR_OBJECT (client, "Failed to prepare transport switch request....\n"); + goto error; + } + + GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message for transport switch..."); + + gst_send_request (client, NULL, &request); + + gst_rtsp_media_set_state (client->priv->media, GST_STATE_PAUSED, ta); + + g_ptr_array_free (ta, FALSE); + + return res; + +error: + return res; + +} + +GstRTSPResult +gst_rtsp_wfd_client_switch_to_tcp (GstRTSPWFDClient * client) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPMessage request = { 0 }; + GList *tl = NULL; + GPtrArray *ta = NULL; + + ta = g_ptr_array_new(); + + tl = gst_rtsp_stream_transport_filter (client->priv->stats.stream, NULL, NULL); + client->priv->transports = tl; + g_ptr_array_add (ta, tl->data); + + if (client->priv->ts_mode == WFD_TS_TCP) { + GST_ERROR_OBJECT (client, "Transport already TCP"); + return res; + } + + client->priv->ts_mode = WFD_TS_TCP; + res = prepare_transport_switch_request (client, &request); + if (GST_RTSP_OK != res) { + GST_ERROR_OBJECT (client, "Failed to prepare transport switch request....\n"); + goto error; + } + + GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message for transport switch..."); + + gst_send_request (client, NULL, &request); + + gst_rtsp_media_set_state (client->priv->media, GST_STATE_PAUSED, ta); + + g_ptr_array_free (ta, FALSE); + + return res; + +error: + return res; +} +gchar * gst_rtsp_wfd_client_get_sink_user_agent (GstRTSPWFDClient * client) { char *str = NULL; GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); diff --git a/gst/rtsp-server/rtsp-client-wfd.h b/gst/rtsp-server/rtsp-client-wfd.h old mode 100644 new mode 100755 index f59835b..4d78382 --- a/gst/rtsp-server/rtsp-client-wfd.h +++ b/gst/rtsp-server/rtsp-client-wfd.h @@ -149,6 +149,8 @@ GstRTSPResult gst_prepare_request (GstRTSPWFDClient * client, GstRTSPMessage * request, GstRTSPMethod method, gchar * url); void gst_send_request (GstRTSPWFDClient * client, GstRTSPSession * session, GstRTSPMessage * request); +GstRTSPResult gst_rtsp_wfd_client_switch_to_udp (GstRTSPWFDClient * client); +GstRTSPResult gst_rtsp_wfd_client_switch_to_tcp (GstRTSPWFDClient * client); guint gst_rtsp_wfd_client_get_audio_codec(GstRTSPWFDClient *client); guint gst_rtsp_wfd_client_get_audio_freq(GstRTSPWFDClient *client); diff --git a/gst/rtsp-server/rtsp-server-wfd.c b/gst/rtsp-server/rtsp-server-wfd.c index 0fa2cd5..042ec3b 100644 --- a/gst/rtsp-server/rtsp-server-wfd.c +++ b/gst/rtsp-server/rtsp-server-wfd.c @@ -334,3 +334,61 @@ gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer * server, GST_RTSP_WFD_SERVER_UNLOCK (server); return res; } + +GstRTSPResult +gst_rtsp_wfd_server_switch_to_udp (GstRTSPWFDServer *server) +{ + GstRTSPResult res = GST_RTSP_OK; + GList *clients, *walk, *next; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), GST_RTSP_ERROR); + + clients = gst_rtsp_server_client_filter (GST_RTSP_SERVER(server), NULL, NULL); + if (clients == NULL) { + GST_ERROR_OBJECT (server, "There is no client in this server"); + } + + for (walk = clients; walk; walk = next) { + GstRTSPClient *client = walk->data; + + next = g_list_next (walk); + + res = + gst_rtsp_wfd_client_switch_to_udp (GST_RTSP_WFD_CLIENT (client)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (server, "Failed to switch transport to UDP"); + } + g_object_unref (client); + } + + return res; +} + +GstRTSPResult +gst_rtsp_wfd_server_switch_to_tcp (GstRTSPWFDServer *server) +{ + GstRTSPResult res = GST_RTSP_OK; + GList *clients, *walk, *next; + + g_return_val_if_fail (GST_IS_RTSP_SERVER (server), GST_RTSP_ERROR); + + clients = gst_rtsp_server_client_filter (GST_RTSP_SERVER(server), NULL, NULL); + if (clients == NULL) { + GST_ERROR_OBJECT (server, "There is no client in this server"); + } + + for (walk = clients; walk; walk = next) { + GstRTSPClient *client = walk->data; + + next = g_list_next (walk); + + res = + gst_rtsp_wfd_client_switch_to_tcp (GST_RTSP_WFD_CLIENT (client)); + if (res != GST_RTSP_OK) { + GST_ERROR_OBJECT (server, "Failed to switch transport to TCP"); + } + g_object_unref (client); + } + + return res; +} diff --git a/gst/rtsp-server/rtsp-server-wfd.h b/gst/rtsp-server/rtsp-server-wfd.h old mode 100644 new mode 100755 index e718e62..1666f18 --- a/gst/rtsp-server/rtsp-server-wfd.h +++ b/gst/rtsp-server/rtsp-server-wfd.h @@ -81,6 +81,8 @@ GstRTSPResult gst_rtsp_wfd_server_trigger_request (GstRTSPServer *s GstRTSPResult gst_rtsp_wfd_server_set_supported_reso (GstRTSPWFDServer *server, guint64 supported_reso); GstRTSPResult gst_rtsp_wfd_server_set_video_native_reso (GstRTSPWFDServer *server, guint64 native_reso); GstRTSPResult gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer *server, guint8 audio_codec); +GstRTSPResult gst_rtsp_wfd_server_switch_to_udp (GstRTSPWFDServer *server); +GstRTSPResult gst_rtsp_wfd_server_switch_to_tcp (GstRTSPWFDServer *server); #if 0 void gst_rtsp_server_set_address (GstRTSPServer *server, const gchar *address); diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index f73387c..d6ae977 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 3 +Release: 4 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From 363980e83ec3b1933a3d532bc907d68014d81872 Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Wed, 30 Nov 2016 13:29:01 +0900 Subject: [PATCH 08/16] fix return value delete unused variable Signed-off-by: SeokHoon Lee Change-Id: I16b786adf29a582bd60ace505c033b309736950e --- gst/rtsp-server/rtsp-client-wfd.c | 1 - gst/rtsp-server/rtsp-media-ext.c | 4 ++-- packaging/gst-rtsp-server.spec | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c index 55c32d7..69741cf 100644 --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -1156,7 +1156,6 @@ new_tcp (GstRTSPWFDClient * client) GstRTSPConnection *conn = NULL; GstRTSPConnection *parent_conn = NULL; GstRTSPUrl *url; - guint64 timeout = 20000000; struct sockaddr_in server_addr; socklen_t sin_len; GSource *source; diff --git a/gst/rtsp-server/rtsp-media-ext.c b/gst/rtsp-server/rtsp-media-ext.c index d1d2ebe..10fb69d 100644 --- a/gst/rtsp-server/rtsp-media-ext.c +++ b/gst/rtsp-server/rtsp-media-ext.c @@ -707,10 +707,10 @@ gst_rtsp_media_ext_set_extended_mode (GstRTSPMediaExt * media, { GstRTSPMediaExtPrivate *priv; - g_return_val_if_fail (GST_IS_RTSP_MEDIA_EXT (media), 0); + g_return_if_fail (GST_IS_RTSP_MEDIA_EXT (media)); priv = media->priv; - g_return_val_if_fail (priv != NULL, 0); + g_return_if_fail (priv != NULL); priv->mode = mode; } diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index d6ae977..6d51203 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 4 +Release: 5 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From d6208d3b646f783620488f74359171ef04a92c09 Mon Sep 17 00:00:00 2001 From: "Hyunsoo, Park" Date: Wed, 30 Nov 2016 17:01:53 +0900 Subject: [PATCH 09/16] Modify spell 'prefered' to 'preferred' [Version] 1.6.1-6 [Profile] Common [Issue Type] Modify mispelling api name [Dependency module] N/A [Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161111.1] Change-Id: Idd3494c5e93eb38cf9c614976f100f282374ed4c Signed-off-by: Hyunsoo, Park --- gst/rtsp-server/gstwfdmessage.c | 16 +++++++-------- gst/rtsp-server/gstwfdmessage.h | 16 +++++++-------- gst/rtsp-server/rtsp-client-wfd.c | 42 +++++++++++++++++++-------------------- packaging/gst-rtsp-server.spec | 2 +- 4 files changed, 38 insertions(+), 38 deletions(-) mode change 100644 => 100755 gst/rtsp-server/rtsp-client-wfd.c diff --git a/gst/rtsp-server/gstwfdmessage.c b/gst/rtsp-server/gstwfdmessage.c index 8d75982..1e7e042 100755 --- a/gst/rtsp-server/gstwfdmessage.c +++ b/gst/rtsp-server/gstwfdmessage.c @@ -1547,7 +1547,7 @@ gst_wfd_message_set_supported_audio_format (GstWFDMessage * msg, } GstWFDResult -gst_wfd_message_set_prefered_audio_format (GstWFDMessage * msg, +gst_wfd_message_set_preferred_audio_format (GstWFDMessage * msg, GstWFDAudioFormats a_codec, GstWFDAudioFreq a_freq, GstWFDAudioChannels a_channels, guint a_bitwidth, guint32 a_latency) @@ -1609,7 +1609,7 @@ gst_wfd_message_get_supported_audio_format (GstWFDMessage * msg, } GstWFDResult -gst_wfd_message_get_prefered_audio_format (GstWFDMessage * msg, +gst_wfd_message_get_preferred_audio_format (GstWFDMessage * msg, GstWFDAudioFormats * a_codec, GstWFDAudioFreq * a_freq, GstWFDAudioChannels * a_channels, guint * a_bitwidth, guint32 * a_latency) @@ -1699,7 +1699,7 @@ gst_wfd_message_set_supported_video_format (GstWFDMessage * msg, } GstWFDResult -gst_wfd_message_set_prefered_video_format (GstWFDMessage * msg, +gst_wfd_message_set_preferred_video_format (GstWFDMessage * msg, GstWFDVideoCodecs v_codec, GstWFDVideoNativeResolution v_native, guint64 v_native_resolution, @@ -1801,7 +1801,7 @@ gst_wfd_message_get_supported_video_format (GstWFDMessage * msg, } GstWFDResult -gst_wfd_message_get_prefered_video_format (GstWFDMessage * msg, +gst_wfd_message_get_preferred_video_format (GstWFDMessage * msg, GstWFDVideoCodecs * v_codec, GstWFDVideoNativeResolution * v_native, guint64 * v_native_resolution, @@ -1966,7 +1966,7 @@ gst_wfd_message_get_contentprotection_type (GstWFDMessage * msg, GstWFDResult -gst_wfd_messge_set_prefered_rtp_ports (GstWFDMessage * msg, +gst_wfd_messge_set_preferred_rtp_ports (GstWFDMessage * msg, GstWFDRTSPTransMode trans, GstWFDRTSPProfile profile, GstWFDRTSPLowerTrans lowertrans, guint32 rtp_port0, guint32 rtp_port1) @@ -2007,7 +2007,7 @@ gst_wfd_messge_set_prefered_rtp_ports (GstWFDMessage * msg, } GstWFDResult -gst_wfd_message_get_prefered_rtp_ports (GstWFDMessage * msg, +gst_wfd_message_get_preferred_rtp_ports (GstWFDMessage * msg, GstWFDRTSPTransMode * trans, GstWFDRTSPProfile * profile, GstWFDRTSPLowerTrans * lowertrans, guint32 * rtp_port0, guint32 * rtp_port1) @@ -2096,7 +2096,7 @@ gst_wfd_message_get_av_format_change_timing (GstWFDMessage * msg, guint64 * PTS, return GST_WFD_OK; } GstWFDResult -gst_wfd_messge_set_prefered_tcp_ports (GstWFDMessage *msg, +gst_wfd_messge_set_preferred_tcp_ports (GstWFDMessage *msg, GstWFDRTSPTransMode trans, GstWFDRTSPProfile profile, GstWFDRTSPLowerTrans lowertrans, @@ -2139,7 +2139,7 @@ gst_wfd_messge_set_prefered_tcp_ports (GstWFDMessage *msg, } GstWFDResult -gst_wfd_message_get_prefered_tcp_ports (GstWFDMessage *msg, +gst_wfd_message_get_preferred_tcp_ports (GstWFDMessage *msg, GstWFDRTSPTransMode *trans, GstWFDRTSPProfile *profile, GstWFDRTSPLowerTrans *lowertrans, diff --git a/gst/rtsp-server/gstwfdmessage.h b/gst/rtsp-server/gstwfdmessage.h index 5a64696..6a506a6 100755 --- a/gst/rtsp-server/gstwfdmessage.h +++ b/gst/rtsp-server/gstwfdmessage.h @@ -513,7 +513,7 @@ GstWFDResult gst_wfd_message_set_supported_audio_format(GstWFDMessage *msg, guint a_freq, guint a_channels, guint a_bitwidth, guint32 a_latency); -GstWFDResult gst_wfd_message_set_prefered_audio_format(GstWFDMessage *msg, +GstWFDResult gst_wfd_message_set_preferred_audio_format(GstWFDMessage *msg, GstWFDAudioFormats a_codec, GstWFDAudioFreq a_freq, GstWFDAudioChannels a_channels, @@ -526,7 +526,7 @@ GstWFDResult gst_wfd_message_get_supported_audio_format (GstWFDMessage *msg, guint *a_bitwidth, guint32 *a_latency); -GstWFDResult gst_wfd_message_get_prefered_audio_format (GstWFDMessage *msg, +GstWFDResult gst_wfd_message_get_preferred_audio_format (GstWFDMessage *msg, GstWFDAudioFormats *a_codec, GstWFDAudioFreq *a_freq, GstWFDAudioChannels *a_channels, @@ -548,7 +548,7 @@ GstWFDResult gst_wfd_message_set_supported_video_format (GstWFDMessage *msg, guint32 slice_enc_params, guint frame_rate_control); -GstWFDResult gst_wfd_message_set_prefered_video_format(GstWFDMessage *msg, +GstWFDResult gst_wfd_message_set_preferred_video_format(GstWFDMessage *msg, GstWFDVideoCodecs v_codec, GstWFDVideoNativeResolution v_native, guint64 v_native_resolution, @@ -580,7 +580,7 @@ GstWFDResult gst_wfd_message_get_supported_video_format(GstWFDMessage *msg, guint32 *slice_enc_params, guint *frame_rate_control); -GstWFDResult gst_wfd_message_get_prefered_video_format(GstWFDMessage *msg, +GstWFDResult gst_wfd_message_get_preferred_video_format(GstWFDMessage *msg, GstWFDVideoCodecs *v_codec, GstWFDVideoNativeResolution *v_native, guint64 *v_native_resolution, @@ -614,14 +614,14 @@ GstWFDResult gst_wfd_message_get_contentprotection_type (GstWFDMessage *msg, GstWFDHDCPProtection *hdcpversion, guint32 *TCPPort); -GstWFDResult gst_wfd_messge_set_prefered_rtp_ports (GstWFDMessage *msg, +GstWFDResult gst_wfd_messge_set_preferred_rtp_ports (GstWFDMessage *msg, GstWFDRTSPTransMode trans, GstWFDRTSPProfile profile, GstWFDRTSPLowerTrans lowertrans, guint32 rtp_port0, guint32 rtp_port1); -GstWFDResult gst_wfd_message_get_prefered_rtp_ports (GstWFDMessage *msg, +GstWFDResult gst_wfd_message_get_preferred_rtp_ports (GstWFDMessage *msg, GstWFDRTSPTransMode *trans, GstWFDRTSPProfile *profile, GstWFDRTSPLowerTrans *lowertrans, @@ -641,14 +641,14 @@ GstWFDResult gst_wfd_message_set_av_format_change_timing(GstWFDMessage *msg, GstWFDResult gst_wfd_message_get_av_format_change_timing(GstWFDMessage *msg, guint64 *PTS, guint64 *DTS); -GstWFDResult gst_wfd_messge_set_prefered_tcp_ports (GstWFDMessage *msg, +GstWFDResult gst_wfd_messge_set_preferred_tcp_ports (GstWFDMessage *msg, GstWFDRTSPTransMode trans, GstWFDRTSPProfile profile, GstWFDRTSPLowerTrans lowertrans, guint32 rtp_port0, guint32 rtp_port1); -GstWFDResult gst_wfd_message_get_prefered_tcp_ports (GstWFDMessage *msg, +GstWFDResult gst_wfd_message_get_preferred_tcp_ports (GstWFDMessage *msg, GstWFDRTSPTransMode *trans, GstWFDRTSPProfile *profile, GstWFDRTSPLowerTrans *lowertrans, diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c old mode 100644 new mode 100755 index 69741cf..55ad960 --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -594,7 +594,7 @@ wfd_get_param_request_done (GstRTSPWFDClient * client, GstRTSPContext * ctx) } static guint -wfd_get_prefered_audio_codec (guint8 srcAudioCodec, guint sinkAudioCodec) +wfd_get_preferred_audio_codec (guint8 srcAudioCodec, guint sinkAudioCodec) { int i = 0; guint codec = 0; @@ -609,7 +609,7 @@ wfd_get_prefered_audio_codec (guint8 srcAudioCodec, guint sinkAudioCodec) } static guint64 -wfd_get_prefered_resolution (guint64 srcResolution, +wfd_get_preferred_resolution (guint64 srcResolution, guint64 sinkResolution, GstWFDVideoNativeResolution native, guint32 * cMaxWidth, @@ -1509,24 +1509,24 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) if (msg->client_rtp_ports) { /* Get the RTP ports preferred by WFDSink */ wfd_res = - gst_wfd_message_get_prefered_rtp_ports (msg, &priv->ctrans, + gst_wfd_message_get_preferred_rtp_ports (msg, &priv->ctrans, &priv->cprofile, &priv->clowertrans, &priv->crtp_port0, &priv->crtp_port1); if (wfd_res != GST_WFD_OK) { GST_WARNING_OBJECT (client, - "Failed to get wfd prefered RTP ports..."); + "Failed to get wfd preferred RTP ports..."); goto error; } } if (msg->tcp_ports) { /* Get the TCP ports preferred by WFDSink */ wfd_res = - gst_wfd_message_get_prefered_tcp_ports (msg, &priv->ctrans_tcp, + gst_wfd_message_get_preferred_tcp_ports (msg, &priv->ctrans_tcp, &priv->cprofile_tcp, &priv->clowertrans_tcp, &priv->crtp_port0_tcp, &priv->crtp_port1_tcp); if (wfd_res != GST_WFD_OK) { GST_WARNING_OBJECT (client, - "Failed to get wfd prefered RTP ports..."); + "Failed to get wfd preferred RTP ports..."); goto error; } } @@ -1536,7 +1536,7 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) gst_wfd_message_get_buffer_length (msg, &priv->buf_len); if (wfd_res != GST_WFD_OK) { GST_WARNING_OBJECT (client, - "Failed to get wfd prefered RTP ports..."); + "Failed to get wfd preferred RTP ports..."); goto error; } } @@ -2063,7 +2063,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, /* set the preffered RTP ports for the WFD server */ wfd_res = - gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_UNKNOWN, + gst_wfd_messge_set_preferred_rtp_ports (msg, GST_WFD_RTSP_TRANS_UNKNOWN, GST_WFD_RTSP_PROFILE_UNKNOWN, GST_WFD_RTSP_LOWER_TRANS_UNKNOWN, 0, 0); if (wfd_res != GST_WFD_OK) { GST_ERROR_OBJECT (client, @@ -2073,7 +2073,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, /* set the preffered TCP ports for the WFD server */ wfd_res = - gst_wfd_messge_set_prefered_tcp_ports (msg, GST_WFD_RTSP_TRANS_RTP, + gst_wfd_messge_set_preferred_tcp_ports (msg, GST_WFD_RTSP_TRANS_RTP, GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1); if (wfd_res != GST_WFD_OK) { GST_ERROR_OBJECT (client, @@ -2168,7 +2168,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, } taudiocodec = - wfd_get_prefered_audio_codec (priv->audio_codec, priv->caCodec); + wfd_get_preferred_audio_codec (priv->audio_codec, priv->caCodec); priv->caCodec = taudiocodec; if (!_set_negotiated_audio_codec (client, priv->caCodec)) { GST_ERROR_OBJECT (client, "Failed to set negotiated " @@ -2193,7 +2193,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, priv->cChanels = taudiochannels; wfd_res = - gst_wfd_message_set_prefered_audio_format (msg, taudiocodec, taudiofreq, + gst_wfd_message_set_preferred_audio_format (msg, taudiocodec, taudiofreq, taudiochannels, priv->cBitwidth, priv->caLatency); if (wfd_res != GST_WFD_OK) { GST_ERROR_OBJECT (priv, "Failed to set preffered audio formats..."); @@ -2217,7 +2217,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, if (priv->video_native_resolution == GST_WFD_VIDEO_CEA_RESOLUTION) { tcCEAResolution = - wfd_get_prefered_resolution (resolution_supported, + wfd_get_preferred_resolution (resolution_supported, priv->cCEAResolution, priv->video_native_resolution, &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); GST_DEBUG @@ -2226,7 +2226,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, priv->cInterleaved); } else if (priv->video_native_resolution == GST_WFD_VIDEO_VESA_RESOLUTION) { tcVESAResolution = - wfd_get_prefered_resolution (resolution_supported, + wfd_get_preferred_resolution (resolution_supported, priv->cVESAResolution, priv->video_native_resolution, &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); @@ -2236,7 +2236,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, priv->cInterleaved); } else if (priv->video_native_resolution == GST_WFD_VIDEO_HH_RESOLUTION) { tcHHResolution = - wfd_get_prefered_resolution (resolution_supported, + wfd_get_preferred_resolution (resolution_supported, priv->cHHResolution, priv->video_native_resolution, &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); GST_DEBUG @@ -2251,7 +2251,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, } wfd_res = - gst_wfd_message_set_prefered_video_format (msg, priv->cvCodec, + gst_wfd_message_set_preferred_video_format (msg, priv->cvCodec, priv->video_native_resolution, GST_WFD_CEA_UNKNOWN, tcCEAResolution, tcVESAResolution, tcHHResolution, tcProfile, tcLevel, priv->cvLatency, priv->cMaxWidth, priv->cMaxHeight, priv->cmin_slice_size, @@ -2264,7 +2264,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, /* set the preffered RTP ports for the WFD server */ wfd_res = - gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP, + gst_wfd_messge_set_preferred_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP, GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1); if (wfd_res != GST_WFD_OK) { @@ -2310,20 +2310,20 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, /* set the preffered TCP ports for the WFD server */ if (priv->ts_mode == WFD_TS_UDP) { wfd_res = - gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP, + gst_wfd_messge_set_preferred_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP, GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1); if (wfd_res != GST_WFD_OK) { GST_ERROR_OBJECT (client, - "Failed to set prefered RTP ports on wfd message..."); + "Failed to set preferred RTP ports on wfd message..."); goto error; } } else { wfd_res = - gst_wfd_messge_set_prefered_tcp_ports (msg, GST_WFD_RTSP_TRANS_RTP, + gst_wfd_messge_set_preferred_tcp_ports (msg, GST_WFD_RTSP_TRANS_RTP, GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_TCP, priv->crtp_port0_tcp, priv->crtp_port1_tcp); if (wfd_res != GST_WFD_OK) { GST_ERROR_OBJECT (client, - "Failed to set prefered TCP ports on wfd message..."); + "Failed to set preferred TCP ports on wfd message..."); goto error; } } @@ -2332,7 +2332,7 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, gst_wfd_message_set_buffer_length (msg, 200); if (wfd_res != GST_WFD_OK) { GST_ERROR_OBJECT (client, - "Failed to set prefered buffer length on wfd message..."); + "Failed to set preferred buffer length on wfd message..."); goto error; } diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index 6d51203..3f6fb7a 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 5 +Release: 6 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From e96377472cfd40548816c99cbba53298acc01d5a Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Tue, 6 Dec 2016 16:12:06 +0900 Subject: [PATCH 10/16] Change strerror to strerror_r because of thread safety Signed-off-by: SeokHoon Lee Change-Id: I81b5f14ba6dd5b984ea7d607cd82f6b43391ffe8 --- gst/rtsp-server/rtsp-client-wfd.c | 4 +++- packaging/gst-rtsp-server.spec | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c index 69741cf..49783ea 100644 --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -1208,7 +1208,9 @@ new_tcp (GstRTSPWFDClient * client) tcp_retry: if ((g_socket_connect (tcp, local, NULL, NULL))) { - g_print( "Error connecting socket : %s\n", strerror( errno ) ); + char buf[255] = {0, }; + strerror_r (errno, buf, sizeof(buf)); + g_print( "Error connecting socket : %s\n", buf ); if (retry < 50) { GST_ERROR("Connection failed... Try again..."); usleep(100000); diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index 6d51203..3f6fb7a 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 5 +Release: 6 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From 4ed4fb655ed9c3ac03c5cf53136cf5e2e3f65e61 Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Tue, 13 Dec 2016 17:04:08 +0900 Subject: [PATCH 11/16] Add gst_object_unref about pad [Version] 1.6.1-7 [Profile] Common [Issue Type] refactoring code [Dependency module] N/A [Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161130-2] Signed-off-by: SeokHoon Lee Change-Id: Icffe192c59b40aa683673961beea0df2e517b0a1 --- gst/rtsp-server/rtsp-media-factory-wfd.c | 8 ++++++++ packaging/gst-rtsp-server.spec | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) mode change 100755 => 100644 gst/rtsp-server/rtsp-media-factory-wfd.c diff --git a/gst/rtsp-server/rtsp-media-factory-wfd.c b/gst/rtsp-server/rtsp-media-factory-wfd.c old mode 100755 new mode 100644 index c8ff33f..de3569a --- a/gst/rtsp-server/rtsp-media-factory-wfd.c +++ b/gst/rtsp-server/rtsp-media-factory-wfd.c @@ -1259,6 +1259,8 @@ _rtsp_media_factory_wfd_create_srcbin (GstRTSPMediaFactoryWFD * factory) } gst_pad_add_probe (pad_probe, GST_PAD_PROBE_TYPE_BUFFER, rtsp_media_wfd_dump_data, factory, NULL); + if (pad_probe) + gst_object_unref (pad_probe); } GST_DEBUG_OBJECT (factory, "successfully created source bin..."); @@ -1267,6 +1269,12 @@ _rtsp_media_factory_wfd_create_srcbin (GstRTSPMediaFactoryWFD * factory) create_error: GST_ERROR_OBJECT (factory, "Failed to create pipeline"); + if (mux_vsinkpad) + gst_object_unref (mux_vsinkpad); + if (mux_asinkpad) + gst_object_unref (mux_asinkpad); + if (srcpad) + gst_object_unref (srcpad); return NULL; } diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index 3f6fb7a..d777ac1 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 6 +Release: 7 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From 5fc34fcac72592592e3d06d41f182ba76f97dbca Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Tue, 7 Feb 2017 16:13:04 +0900 Subject: [PATCH 12/16] Change wfd message wfd-video-formats have none parameter for audio only sink Signed-off-by: SeokHoon Lee Change-Id: Ie2703c2015aa110b8d45e937e327d953b58d2193 --- gst/rtsp-server/gstwfdmessage.c | 86 +++++++++------- gst/rtsp-server/rtsp-client-wfd.c | 168 ++++++++++++++++++++----------- gst/rtsp-server/rtsp-media-factory-wfd.c | 58 +++++++---- packaging/gst-rtsp-server.spec | 2 +- 4 files changed, 201 insertions(+), 113 deletions(-) mode change 100755 => 100644 gst/rtsp-server/gstwfdmessage.c mode change 100755 => 100644 gst/rtsp-server/rtsp-client-wfd.c diff --git a/gst/rtsp-server/gstwfdmessage.c b/gst/rtsp-server/gstwfdmessage.c old mode 100755 new mode 100644 index 1e7e042..4ad9d1b --- a/gst/rtsp-server/gstwfdmessage.c +++ b/gst/rtsp-server/gstwfdmessage.c @@ -484,44 +484,49 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg) } else if (!g_strcmp0 (attr, GST_STRING_WFD_VIDEO_FORMATS)) { msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1); if (strlen (v)) { - msg->video_formats->count = 1; - msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->native); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list-> - preferred_display_mode_supported); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.profile); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.level); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. - CEA_Support); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. - VESA_Support); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. - HH_Support); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. - latency); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. - min_slice_size); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. - slice_enc_params); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. - frame_rate_control_support); - WFD_SKIP_SPACE (v); - if (msg->video_formats->list->preferred_display_mode_supported == 1) { - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_hres); + if (strncmp (v, "none", 4)) { + msg->video_formats->count = 1; + msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1); + WFD_READ_UINT32 (msg->video_formats->list->native); WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_vres); + WFD_READ_UINT32 (msg->video_formats->list-> + preferred_display_mode_supported); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.profile); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.level); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + CEA_Support); WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + VESA_Support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + HH_Support); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + latency); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + min_slice_size); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + slice_enc_params); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.misc_params. + frame_rate_control_support); + WFD_SKIP_SPACE (v); + if (msg->video_formats->list->preferred_display_mode_supported == 1) { + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_hres); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->video_formats->list->H264_codec.max_vres); + WFD_SKIP_SPACE (v); + } + } else { + msg->video_formats->count = 0; + msg->video_formats->list = NULL; } } } else if (!g_strcmp0 (attr, GST_STRING_WFD_3D_VIDEO_FORMATS)) { @@ -904,8 +909,8 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) /* list of video codecs */ if (msg->video_formats) { g_string_append_printf (lines, GST_STRING_WFD_VIDEO_FORMATS); + g_string_append_printf (lines, ":"); if (msg->video_formats->list) { - g_string_append_printf (lines, ":"); g_string_append_printf (lines, " %02x", msg->video_formats->list->native); g_string_append_printf (lines, " %02x", msg->video_formats->list->preferred_display_mode_supported); @@ -940,6 +945,8 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) msg->video_formats->list->H264_codec.max_vres); else g_string_append_printf (lines, " none"); + } else { + g_string_append_printf (lines, " none"); } g_string_append_printf (lines, "\r\n"); } @@ -1720,6 +1727,13 @@ gst_wfd_message_set_preferred_video_format (GstWFDMessage * msg, if (!msg->video_formats) msg->video_formats = g_new0 (GstWFDVideoCodeclist, 1); + + if (v_codec == GST_WFD_VIDEO_UNKNOWN) { + msg->video_formats->list = NULL; + msg->video_formats->count = 0; + return GST_WFD_OK; + } + msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1); while (temp) { diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c old mode 100755 new mode 100644 index 973305f..d75b7c8 --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -1493,19 +1493,21 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) } /* Get the Video formats supported by WFDSink */ - wfd_res = - gst_wfd_message_get_supported_video_format (msg, &priv->cvCodec, - &priv->cNative, &priv->cNativeResolution, - (guint64 *) & priv->cCEAResolution, - (guint64 *) & priv->cVESAResolution, - (guint64 *) & priv->cHHResolution, &priv->cProfile, &priv->cLevel, - &priv->cvLatency, &priv->cMaxHeight, &priv->cMaxWidth, - &priv->cmin_slice_size, &priv->cslice_enc_params, - &priv->cframe_rate_control); - if (wfd_res != GST_WFD_OK) { - GST_WARNING_OBJECT (client, - "Failed to get wfd supported video formats..."); - goto error; + if (msg->video_formats && msg->video_formats->count > 0) { + wfd_res = + gst_wfd_message_get_supported_video_format (msg, &priv->cvCodec, + &priv->cNative, &priv->cNativeResolution, + (guint64 *) & priv->cCEAResolution, + (guint64 *) & priv->cVESAResolution, + (guint64 *) & priv->cHHResolution, &priv->cProfile, &priv->cLevel, + &priv->cvLatency, &priv->cMaxHeight, &priv->cMaxWidth, + &priv->cmin_slice_size, &priv->cslice_enc_params, + &priv->cframe_rate_control); + if (wfd_res != GST_WFD_OK) { + GST_WARNING_OBJECT (client, + "Failed to get wfd supported video formats..."); + goto error; + } } if (msg->client_rtp_ports) { @@ -1948,6 +1950,52 @@ no_mount_points: } static gboolean +_set_negotiated_video_codec (GstRTSPWFDClient * client, guint video_codec) +{ + GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client); + + GstRTSPMediaFactory *factory = NULL; + GstRTSPMountPoints *mount_points = NULL; + gchar *path = NULL; + gint matched = 0; + gboolean ret = TRUE; + + if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) { + ret = FALSE; + GST_ERROR_OBJECT (client, + "Failed to set negotiated video codec: no mount points..."); + goto no_mount_points; + } + + path = g_strdup (WFD_MOUNT_POINT); + if (!path) { + ret = FALSE; + GST_ERROR_OBJECT (client, + "Failed to set negotiated vidoe codec: no path..."); + goto no_path; + } + + if (!(factory = gst_rtsp_mount_points_match (mount_points, path, &matched))) { + GST_ERROR_OBJECT (client, + "Failed to set negotiated vidoe codec: no factory..."); + ret = FALSE; + goto no_factory; + } + + gst_rtsp_media_factory_wfd_set_video_codec (factory, video_codec); + ret = TRUE; + + g_object_unref (factory); + +no_factory: + g_free (path); +no_path: + g_object_unref (mount_points); +no_mount_points: + return ret; +} + +static gboolean _set_negotiated_resolution (GstRTSPWFDClient * client, guint32 width, guint32 height) { @@ -2203,53 +2251,61 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, } /* Set the preffered video formats */ - priv->cvCodec = GST_WFD_VIDEO_H264; - priv->cProfile = tcProfile = GST_WFD_H264_BASE_PROFILE; - priv->cLevel = tcLevel = GST_WFD_H264_LEVEL_3_1; - - resolution_supported = priv->video_resolution_supported; - - /* TODO-WFD: Need to verify this logic - if(priv->edid_supported) { - if (priv->edid_hres < 1920) resolution_supported = resolution_supported & 0x8C7F; - if (priv->edid_hres < 1280) resolution_supported = resolution_supported & 0x1F; - if (priv->edid_hres < 720) resolution_supported = resolution_supported & 0x01; - } - */ + GST_INFO_OBJECT (priv, "Set the video formats... %d", priv->cvCodec); + if (priv->cvCodec != GST_WFD_VIDEO_UNKNOWN) { + priv->cvCodec = GST_WFD_VIDEO_H264; + priv->cProfile = tcProfile = GST_WFD_H264_BASE_PROFILE; + priv->cLevel = tcLevel = GST_WFD_H264_LEVEL_3_1; + + resolution_supported = priv->video_resolution_supported; + + /* TODO-WFD: Need to verify this logic + if(priv->edid_supported) { + if (priv->edid_hres < 1920) resolution_supported = resolution_supported & 0x8C7F; + if (priv->edid_hres < 1280) resolution_supported = resolution_supported & 0x1F; + if (priv->edid_hres < 720) resolution_supported = resolution_supported & 0x01; + } + */ + + if (priv->video_native_resolution == GST_WFD_VIDEO_CEA_RESOLUTION) { + tcCEAResolution = + wfd_get_preferred_resolution (resolution_supported, + priv->cCEAResolution, priv->video_native_resolution, &priv->cMaxWidth, + &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); + GST_DEBUG + ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", + tcCEAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, + priv->cInterleaved); + } else if (priv->video_native_resolution == GST_WFD_VIDEO_VESA_RESOLUTION) { + tcVESAResolution = + wfd_get_preferred_resolution (resolution_supported, + priv->cVESAResolution, priv->video_native_resolution, + &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate, + &priv->cInterleaved); + GST_DEBUG + ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", + tcVESAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, + priv->cInterleaved); + } else if (priv->video_native_resolution == GST_WFD_VIDEO_HH_RESOLUTION) { + tcHHResolution = + wfd_get_preferred_resolution (resolution_supported, + priv->cHHResolution, priv->video_native_resolution, &priv->cMaxWidth, + &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); + GST_DEBUG + ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", + tcHHResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, + priv->cInterleaved); + } - if (priv->video_native_resolution == GST_WFD_VIDEO_CEA_RESOLUTION) { - tcCEAResolution = - wfd_get_preferred_resolution (resolution_supported, - priv->cCEAResolution, priv->video_native_resolution, &priv->cMaxWidth, - &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); - GST_DEBUG - ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", - tcCEAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, - priv->cInterleaved); - } else if (priv->video_native_resolution == GST_WFD_VIDEO_VESA_RESOLUTION) { - tcVESAResolution = - wfd_get_preferred_resolution (resolution_supported, - priv->cVESAResolution, priv->video_native_resolution, - &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate, - &priv->cInterleaved); - GST_DEBUG - ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", - tcVESAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, - priv->cInterleaved); - } else if (priv->video_native_resolution == GST_WFD_VIDEO_HH_RESOLUTION) { - tcHHResolution = - wfd_get_preferred_resolution (resolution_supported, - priv->cHHResolution, priv->video_native_resolution, &priv->cMaxWidth, - &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved); - GST_DEBUG - ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d", - tcHHResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate, - priv->cInterleaved); + if (!_set_negotiated_resolution (client, priv->cMaxWidth, priv->cMaxHeight)) { + GST_ERROR_OBJECT (client, "Failed to set negotiated " + "resolution to media factory..."); + } } - if (!_set_negotiated_resolution (client, priv->cMaxWidth, priv->cMaxHeight)) { + if (!_set_negotiated_video_codec (client, priv->cvCodec)) { GST_ERROR_OBJECT (client, "Failed to set negotiated " - "resolution to media factory..."); + "video format to media factory..."); } wfd_res = diff --git a/gst/rtsp-server/rtsp-media-factory-wfd.c b/gst/rtsp-server/rtsp-media-factory-wfd.c index de3569a..6d19dfa 100644 --- a/gst/rtsp-server/rtsp-media-factory-wfd.c +++ b/gst/rtsp-server/rtsp-media-factory-wfd.c @@ -222,6 +222,16 @@ gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory * factory, priv->audio_codec = audio_codec; } +void +gst_rtsp_media_factory_wfd_set_video_codec (GstRTSPMediaFactory * factory, + guint video_codec) +{ + GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory); + GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv; + + priv->video_codec = video_codec; +} + static void _config_bitrate (GstRTSPMediaFactoryWFD * factory) { @@ -752,6 +762,11 @@ _rtsp_media_factory_wfd_create_waylandsrc_bin (GstRTSPMediaFactoryWFD * factory, GST_INFO_OBJECT (factory, "picked waylandsrc as video source"); + if (priv->video_codec == GST_WFD_VIDEO_UNKNOWN) { + GST_INFO_OBJECT (factory, "Skip create video source."); + return TRUE; + } + videosrc = gst_element_factory_make ("waylandsrc", "videosrc"); if (NULL == videosrc) { GST_ERROR_OBJECT (factory, "failed to create ximagesrc element"); @@ -1126,6 +1141,7 @@ _rtsp_media_factory_wfd_create_srcbin (GstRTSPMediaFactoryWFD * factory) goto create_error; } + GST_INFO_OBJECT (factory, "Check video codec... %d", priv->video_codec); /* create video src element */ switch (priv->videosrc_type) { case GST_WFD_VSRC_XIMAGESRC: @@ -1196,29 +1212,31 @@ _rtsp_media_factory_wfd_create_srcbin (GstRTSPMediaFactoryWFD * factory) goto create_error; } - /* request video sink pad from muxer, which has elementary pid 0x1011 */ - mux_vsinkpad = gst_element_get_request_pad (mux, "sink_4113"); - if (!mux_vsinkpad) { - GST_ERROR_OBJECT (factory, "Failed to get sink pad from muxer..."); - goto create_error; - } + if (priv->video_codec > GST_WFD_VIDEO_UNKNOWN) { + /* request video sink pad from muxer, which has elementary pid 0x1011 */ + mux_vsinkpad = gst_element_get_request_pad (mux, "sink_4113"); + if (!mux_vsinkpad) { + GST_ERROR_OBJECT (factory, "Failed to get sink pad from muxer..."); + goto create_error; + } - /* request srcpad from video queue */ - srcpad = gst_element_get_static_pad (priv->video_queue, "src"); - if (!srcpad) { - GST_ERROR_OBJECT (factory, "Failed to get srcpad from video queue..."); - goto create_error; - } + /* request srcpad from video queue */ + srcpad = gst_element_get_static_pad (priv->video_queue, "src"); + if (!srcpad) { + GST_ERROR_OBJECT (factory, "Failed to get srcpad from video queue..."); + goto create_error; + } - if (gst_pad_link (srcpad, mux_vsinkpad) != GST_PAD_LINK_OK) { - GST_ERROR_OBJECT (factory, - "Failed to link video queue src pad & muxer video sink pad..."); - goto create_error; - } + if (gst_pad_link (srcpad, mux_vsinkpad) != GST_PAD_LINK_OK) { + GST_ERROR_OBJECT (factory, + "Failed to link video queue src pad & muxer video sink pad..."); + goto create_error; + } - gst_object_unref (mux_vsinkpad); - gst_object_unref (srcpad); - srcpad = NULL; + gst_object_unref (mux_vsinkpad); + gst_object_unref (srcpad); + srcpad = NULL; + } /* create audio source elements & add to pipeline */ if (!_rtsp_media_factory_wfd_create_audio_capture_bin (factory, srcbin)) diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index d777ac1..ac6ccb6 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 7 +Release: 8 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From 9ae1d7ee50992f41007371c3ef010afbb86d1702 Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Tue, 14 Feb 2017 13:42:51 +0900 Subject: [PATCH 13/16] fix memory leak and delete unused buffer - fix nativeidex underflow. - delete unused block about buf - free msg after use. - remove ta memoryleak in error case Signed-off-by: SeokHoon Lee Change-Id: Ib55adb29dc49e2e21852bd509c828040879253b6 --- gst/rtsp-server/gstwfdmessage.c | 5 +++- gst/rtsp-server/rtsp-client-wfd.c | 53 +++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/gst/rtsp-server/gstwfdmessage.c b/gst/rtsp-server/gstwfdmessage.c index 4ad9d1b..6540b9d 100644 --- a/gst/rtsp-server/gstwfdmessage.c +++ b/gst/rtsp-server/gstwfdmessage.c @@ -864,6 +864,7 @@ gst_wfd_message_free (GstWFDMessage * msg) gst_wfd_message_uninit (msg); g_free (msg); + msg = NULL; return GST_WFD_OK; } @@ -1670,12 +1671,14 @@ gst_wfd_message_set_supported_video_format (GstWFDMessage * msg, if (v_codec != GST_WFD_VIDEO_UNKNOWN) { msg->video_formats->list = g_new0 (GstWFDVideoCodec, 1); + + temp >>= 1; while (temp) { nativeindex++; temp >>= 1; } - msg->video_formats->list->native = nativeindex - 1; + msg->video_formats->list->native = nativeindex; msg->video_formats->list->native <<= 3; if (v_native == GST_WFD_VIDEO_VESA_RESOLUTION) diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c index d75b7c8..969e26a 100644 --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -2054,9 +2054,6 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, g_return_if_fail (priv != NULL); - buf = g_string_new (""); - g_return_if_fail (buf != NULL); - if (msg_type == M3_REQ_MSG) { /* create M3 request to be sent */ wfd_res = gst_wfd_message_new (&msg); @@ -2196,14 +2193,17 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, goto error; } + buf = g_string_new (""); + if (buf == NULL) + goto error; + g_string_append_printf (buf, "rtsp://"); if (priv->host_address) { g_string_append (buf, priv->host_address); } else { GST_ERROR_OBJECT (client, "Failed to get host address"); - if (buf) - g_string_free (buf, TRUE); + g_string_free (buf, TRUE); goto error; } @@ -2353,18 +2353,6 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, goto error; } - g_string_append_printf (buf, "rtsp://"); - - if (priv->host_address) { - g_string_append (buf, priv->host_address); - } else { - GST_ERROR_OBJECT (client, "Failed to get host address"); - if (buf) g_string_free (buf, TRUE); - goto error; - } - - g_string_append_printf (buf, "/wfd1.0/streamid=0"); - /* set the preffered TCP ports for the WFD server */ if (priv->ts_mode == WFD_TS_UDP) { wfd_res = @@ -2412,32 +2400,49 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, *len = strlen (*data); } } else if (msg_type == M5_REQ_MSG) { + buf = g_string_new (""); + if (buf == NULL) + goto error; g_string_append (buf, "wfd_trigger_method: SETUP"); g_string_append (buf, "\r\n"); *len = buf->len; *data = g_string_free (buf, FALSE); } else if (msg_type == TEARDOWN_TRIGGER) { + buf = g_string_new (""); + if (buf == NULL) + goto error; g_string_append (buf, "wfd_trigger_method: TEARDOWN"); g_string_append (buf, "\r\n"); *len = buf->len; *data = g_string_free (buf, FALSE); } else if (msg_type == PLAY_TRIGGER) { + buf = g_string_new (""); + if (buf == NULL) + goto error; g_string_append (buf, "wfd_trigger_method: PLAY"); g_string_append (buf, "\r\n"); *len = buf->len; *data = g_string_free (buf, FALSE); } else if (msg_type == PAUSE_TRIGGER) { + buf = g_string_new (""); + if (buf == NULL) + goto error; g_string_append (buf, "wfd_trigger_method: PAUSE"); g_string_append (buf, "\r\n"); *len = buf->len; *data = g_string_free (buf, FALSE); - } else { - return; } + if (msg != NULL) + gst_wfd_message_free(msg); + return; error: + + if (msg != NULL) + gst_wfd_message_free(msg); + *data = NULL; *len = 0; @@ -3785,17 +3790,17 @@ gst_rtsp_wfd_client_switch_to_udp (GstRTSPWFDClient * client) GList *tl = NULL; GPtrArray *ta = NULL; + if (client->priv->ts_mode == WFD_TS_UDP) { + GST_ERROR_OBJECT (client, "Transport already UDP"); + return res; + } + ta = g_ptr_array_new(); tl = gst_rtsp_stream_transport_filter (client->priv->stats.stream, NULL, NULL); client->priv->transports = tl; g_ptr_array_add (ta, tl->data); - if (client->priv->ts_mode == WFD_TS_UDP) { - GST_ERROR_OBJECT (client, "Transport already UDP"); - return res; - } - client->priv->ts_mode = WFD_TS_UDP; res = prepare_transport_switch_request (client, &request); if (GST_RTSP_OK != res) { -- 2.7.4 From fbcc329984ede6192f95a0024368c8e84658faa1 Mon Sep 17 00:00:00 2001 From: "Hyunsoo, Park" Date: Tue, 21 Feb 2017 20:22:01 +0900 Subject: [PATCH 14/16] Change wfd message for video only mirroring Using this patch, 'wfd-audio-formats' parameter have none parameter for video only sink. Basically, screen mirroring provides video & audio simultaneously. This patch will make screen mirroring to provide Video only. -When Video only mirroring mode goes, it makes 'wfd_audio_codecs' messages to 'none'. If 'sink session mode' in 'mmfw_wfd_sink.ini' is set '2', screen mirroring runs without audio(that is, video only mirroring) Change-Id: Ia88fb8a23c2f28cda222075835aa16c4a6bb3987 Signed-off-by: Hyunsoo, Park --- gst/rtsp-server/gstwfdmessage.c | 37 +++++++++++++++++-------- gst/rtsp-server/rtsp-client-wfd.c | 44 ++++++++++++++++-------------- gst/rtsp-server/rtsp-media-factory-wfd.c | 47 +++++++++++++++++++------------- gst/rtsp-server/rtsp-media-factory-wfd.h | 2 ++ packaging/gst-rtsp-server.spec | 2 +- 5 files changed, 79 insertions(+), 53 deletions(-) diff --git a/gst/rtsp-server/gstwfdmessage.c b/gst/rtsp-server/gstwfdmessage.c index 6540b9d..3e6d099 100644 --- a/gst/rtsp-server/gstwfdmessage.c +++ b/gst/rtsp-server/gstwfdmessage.c @@ -467,18 +467,24 @@ gst_wfd_parse_attribute (gchar * buffer, GstWFDMessage * msg) if (!g_strcmp0 (attr, GST_STRING_WFD_AUDIO_CODECS)) { msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1); if (strlen (v)) { - guint i = 0; - msg->audio_codecs->count = strlen (v) / 16; - msg->audio_codecs->list = + WFD_SKIP_SPACE (v); + if (strncmp (v, "none", 4)) { + guint i = 0; + msg->audio_codecs->count = strlen (v) / 16; + msg->audio_codecs->list = g_new0 (GstWFDAudioCodec, msg->audio_codecs->count); - for (; i < msg->audio_codecs->count; i++) { - WFD_SKIP_SPACE (v); - WFD_READ_STRING (msg->audio_codecs->list[i].audio_format); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->audio_codecs->list[i].modes); - WFD_SKIP_SPACE (v); - WFD_READ_UINT32 (msg->audio_codecs->list[i].latency); - WFD_SKIP_COMMA (v); + for (; i < msg->audio_codecs->count; i++) { + WFD_SKIP_SPACE (v); + WFD_READ_STRING (msg->audio_codecs->list[i].audio_format); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->audio_codecs->list[i].modes); + WFD_SKIP_SPACE (v); + WFD_READ_UINT32 (msg->audio_codecs->list[i].latency); + WFD_SKIP_COMMA (v); + } + } else { + msg->audio_codecs->count = 0; + msg->audio_codecs->list = NULL; } } } else if (!g_strcmp0 (attr, GST_STRING_WFD_VIDEO_FORMATS)) { @@ -891,8 +897,8 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) /* list of audio codecs */ if (msg->audio_codecs) { g_string_append_printf (lines, GST_STRING_WFD_AUDIO_CODECS); + g_string_append_printf (lines, ":"); if (msg->audio_codecs->list) { - g_string_append_printf (lines, ":"); for (i = 0; i < msg->audio_codecs->count; i++) { g_string_append_printf (lines, " %s", msg->audio_codecs->list[i].audio_format); @@ -903,6 +909,8 @@ gst_wfd_message_as_text (const GstWFDMessage * msg) if ((i + 1) < msg->audio_codecs->count) g_string_append_printf (lines, ","); } + } else { + g_string_append_printf (lines, " none"); } g_string_append_printf (lines, "\r\n"); } @@ -1565,6 +1573,11 @@ gst_wfd_message_set_preferred_audio_format (GstWFDMessage * msg, if (!msg->audio_codecs) msg->audio_codecs = g_new0 (GstWFDAudioCodeclist, 1); + if (a_codec == GST_WFD_AUDIO_UNKNOWN) { + msg->audio_codecs->list = NULL; + msg->audio_codecs->count = 0; + return GST_WFD_OK; + } msg->audio_codecs->list = g_new0 (GstWFDAudioCodec, 1); msg->audio_codecs->count = 1; if (a_codec == GST_WFD_AUDIO_LPCM) { diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c index 969e26a..42a2417 100644 --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -1481,7 +1481,7 @@ handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx) gst_wfd_message_as_text (msg)); /* Get the audio formats supported by WFDSink */ - if (msg->audio_codecs) { + if (msg->audio_codecs && msg->audio_codecs->count > 0) { wfd_res = gst_wfd_message_get_supported_audio_format (msg, &priv->caCodec, &priv->cFreq, &priv->cChanels, &priv->cBitwidth, &priv->caLatency); @@ -2217,31 +2217,33 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, goto error; } - taudiocodec = - wfd_get_preferred_audio_codec (priv->audio_codec, priv->caCodec); - priv->caCodec = taudiocodec; + if (priv->caCodec != GST_WFD_AUDIO_UNKNOWN) { + taudiocodec = wfd_get_preferred_audio_codec (priv->audio_codec, priv->caCodec); + priv->caCodec = taudiocodec; + } if (!_set_negotiated_audio_codec (client, priv->caCodec)) { GST_ERROR_OBJECT (client, "Failed to set negotiated " "audio codec to media factory..."); } - if (priv->cFreq & GST_WFD_FREQ_48000) - taudiofreq = GST_WFD_FREQ_48000; - else if (priv->cFreq & GST_WFD_FREQ_44100) - taudiofreq = GST_WFD_FREQ_44100; - priv->cFreq = taudiofreq; - - /* TODO-WFD: Currently only 2 channels is present */ - if (priv->cChanels & GST_WFD_CHANNEL_8) - taudiochannels = GST_WFD_CHANNEL_2; - else if (priv->cChanels & GST_WFD_CHANNEL_6) - taudiochannels = GST_WFD_CHANNEL_2; - else if (priv->cChanels & GST_WFD_CHANNEL_4) - taudiochannels = GST_WFD_CHANNEL_2; - else if (priv->cChanels & GST_WFD_CHANNEL_2) - taudiochannels = GST_WFD_CHANNEL_2; - priv->cChanels = taudiochannels; - + if (priv->caCodec != GST_WFD_AUDIO_UNKNOWN) { + if (priv->cFreq & GST_WFD_FREQ_48000) + taudiofreq = GST_WFD_FREQ_48000; + else if (priv->cFreq & GST_WFD_FREQ_44100) + taudiofreq = GST_WFD_FREQ_44100; + priv->cFreq = taudiofreq; + + /* TODO-WFD: Currently only 2 channels is present */ + if (priv->cChanels & GST_WFD_CHANNEL_8) + taudiochannels = GST_WFD_CHANNEL_2; + else if (priv->cChanels & GST_WFD_CHANNEL_6) + taudiochannels = GST_WFD_CHANNEL_2; + else if (priv->cChanels & GST_WFD_CHANNEL_4) + taudiochannels = GST_WFD_CHANNEL_2; + else if (priv->cChanels & GST_WFD_CHANNEL_2) + taudiochannels = GST_WFD_CHANNEL_2; + priv->cChanels = taudiochannels; + } wfd_res = gst_wfd_message_set_preferred_audio_format (msg, taudiocodec, taudiofreq, taudiochannels, priv->cBitwidth, priv->caLatency); diff --git a/gst/rtsp-server/rtsp-media-factory-wfd.c b/gst/rtsp-server/rtsp-media-factory-wfd.c index 6d19dfa..127af3c 100644 --- a/gst/rtsp-server/rtsp-media-factory-wfd.c +++ b/gst/rtsp-server/rtsp-media-factory-wfd.c @@ -465,6 +465,11 @@ _rtsp_media_factory_wfd_create_audio_capture_bin (GstRTSPMediaFactoryWFD * priv = factory->priv; + if (priv->audio_codec == GST_WFD_AUDIO_UNKNOWN) { + GST_INFO_OBJECT (factory, "Skip create audio source"); + return TRUE; + } + /* create audio src element */ audiosrc = gst_element_factory_make ("pulsesrc", "audiosrc"); if (!audiosrc) { @@ -1238,32 +1243,36 @@ _rtsp_media_factory_wfd_create_srcbin (GstRTSPMediaFactoryWFD * factory) srcpad = NULL; } + GST_INFO_OBJECT (factory, "Check audio codec... %d", priv->audio_codec); + /* create audio source elements & add to pipeline */ if (!_rtsp_media_factory_wfd_create_audio_capture_bin (factory, srcbin)) goto create_error; - /* request audio sink pad from muxer, which has elementary pid 0x1100 */ - mux_asinkpad = gst_element_get_request_pad (mux, "sink_4352"); - if (!mux_asinkpad) { - GST_ERROR_OBJECT (factory, "Failed to get sinkpad from muxer..."); - goto create_error; - } + if (priv->audio_codec > GST_WFD_AUDIO_UNKNOWN) { + /* request audio sink pad from muxer, which has elementary pid 0x1100 */ + mux_asinkpad = gst_element_get_request_pad (mux, "sink_4352"); + if (!mux_asinkpad) { + GST_ERROR_OBJECT (factory, "Failed to get sinkpad from muxer..."); + goto create_error; + } - /* request srcpad from audio queue */ - srcpad = gst_element_get_static_pad (priv->audio_queue, "src"); - if (!srcpad) { - GST_ERROR_OBJECT (factory, "Failed to get srcpad from audio queue..."); - goto create_error; - } + /* request srcpad from audio queue */ + srcpad = gst_element_get_static_pad (priv->audio_queue, "src"); + if (!srcpad) { + GST_ERROR_OBJECT (factory, "Failed to get srcpad from audio queue..."); + goto create_error; + } - /* link audio queue's srcpad & muxer sink pad */ - if (gst_pad_link (srcpad, mux_asinkpad) != GST_PAD_LINK_OK) { - GST_ERROR_OBJECT (factory, - "Failed to link audio queue src pad & muxer audio sink pad..."); - goto create_error; + /* link audio queue's srcpad & muxer sink pad */ + if (gst_pad_link (srcpad, mux_asinkpad) != GST_PAD_LINK_OK) { + GST_ERROR_OBJECT (factory, + "Failed to link audio queue src pad & muxer audio sink pad..."); + goto create_error; + } + gst_object_unref (mux_asinkpad); + gst_object_unref (srcpad); } - gst_object_unref (mux_asinkpad); - gst_object_unref (srcpad); if (priv->dump_ts) { diff --git a/gst/rtsp-server/rtsp-media-factory-wfd.h b/gst/rtsp-server/rtsp-media-factory-wfd.h index 582ded4..ba58776 100644 --- a/gst/rtsp-server/rtsp-media-factory-wfd.h +++ b/gst/rtsp-server/rtsp-media-factory-wfd.h @@ -126,6 +126,8 @@ void gst_rtsp_media_factory_wfd_set_negotiated_resolution (GstRTSPMediaFactory * guint32 width, guint32 height); void gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory *factory, guint audio_codec); +void gst_rtsp_media_factory_wfd_set_video_codec (GstRTSPMediaFactory * factory, + guint video_codec); void gst_rtsp_media_factory_wfd_set_venc_bitrate (GstRTSPMediaFactory *factory, gint bitrate); diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index ac6ccb6..bf13245 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 8 +Release: 9 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From 13eabe9ec46221f1ed8dd7e588c86c34f8d7aef7 Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Fri, 17 Mar 2017 15:45:28 +0900 Subject: [PATCH 15/16] Add video codec parameter for source - For video codec negotiation between source and sink, add video codec parameter in client Signed-off-by: SeokHoon Lee Change-Id: I89b22ee50fc8806bbaf932e0b50eff110b030eca --- gst/rtsp-server/rtsp-client-wfd.c | 21 +++++++++++++++++++-- gst/rtsp-server/rtsp-client-wfd.h | 4 +++- gst/rtsp-server/rtsp-server-wfd.c | 21 +++++++++++++++++++++ gst/rtsp-server/rtsp-server-wfd.h | 1 + packaging/gst-rtsp-server.spec | 2 +- 5 files changed, 45 insertions(+), 4 deletions(-) mode change 100755 => 100644 gst/rtsp-server/rtsp-client-wfd.h mode change 100755 => 100644 gst/rtsp-server/rtsp-server-wfd.h diff --git a/gst/rtsp-server/rtsp-client-wfd.c b/gst/rtsp-server/rtsp-client-wfd.c index 42a2417..c07f802 100644 --- a/gst/rtsp-server/rtsp-client-wfd.c +++ b/gst/rtsp-server/rtsp-client-wfd.c @@ -115,6 +115,7 @@ struct _GstRTSPWFDClientPrivate guint cBitwidth; guint caLatency; guint cvCodec; + guint8 video_codec; guint cNative; guint64 cNativeResolution; guint64 video_resolution_supported; @@ -2253,7 +2254,8 @@ _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type, } /* Set the preffered video formats */ - GST_INFO_OBJECT (priv, "Set the video formats... %d", priv->cvCodec); + GST_INFO_OBJECT (priv, "Set the video formats. source codec %d, sink codec %d", priv->video_codec, priv->cvCodec); + /* TODO : need to negotiate video codec between source and sink */ if (priv->cvCodec != GST_WFD_VIDEO_UNKNOWN) { priv->cvCodec = GST_WFD_VIDEO_H264; priv->cProfile = tcProfile = GST_WFD_H264_BASE_PROFILE; @@ -3075,6 +3077,21 @@ gst_rtsp_wfd_client_set_video_native_resolution (GstRTSPWFDClient * client, } GstRTSPResult +gst_rtsp_wfd_client_set_video_codec (GstRTSPWFDClient * client, + guint8 video_codec) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); + + g_return_val_if_fail (priv != NULL, GST_RTSP_EINVAL); + + priv->video_codec = video_codec; + GST_DEBUG ("Video codec : %d", video_codec); + + return res; +} + +GstRTSPResult gst_rtsp_wfd_client_set_audio_codec (GstRTSPWFDClient * client, guint8 audio_codec) { @@ -3552,7 +3569,7 @@ gst_rtsp_wfd_client_set_audio_latency (GstRTSPWFDClient * client, guint latency) } void -gst_rtsp_wfd_client_set_video_codec (GstRTSPWFDClient * client, guint vcodec) +gst_rtsp_wfd_client_set_vid_codec (GstRTSPWFDClient * client, guint vcodec) { GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client); g_return_if_fail (priv != NULL); diff --git a/gst/rtsp-server/rtsp-client-wfd.h b/gst/rtsp-server/rtsp-client-wfd.h old mode 100755 new mode 100644 index 4d78382..382ce16 --- a/gst/rtsp-server/rtsp-client-wfd.h +++ b/gst/rtsp-server/rtsp-client-wfd.h @@ -143,6 +143,8 @@ GstRTSPResult gst_rtsp_wfd_client_set_video_supported_resolution ( GstRTSPWFDClient * client, guint64 supported_reso); GstRTSPResult gst_rtsp_wfd_client_set_video_native_resolution ( GstRTSPWFDClient * client, guint64 native_reso); +GstRTSPResult gst_rtsp_wfd_client_set_video_codec ( + GstRTSPWFDClient * client, guint8 video_codec); GstRTSPResult gst_rtsp_wfd_client_set_audio_codec ( GstRTSPWFDClient * client, guint8 audio_codec); GstRTSPResult gst_prepare_request (GstRTSPWFDClient * client, @@ -191,7 +193,7 @@ void gst_rtsp_wfd_client_set_aud_codec(GstRTSPWFDClient *client, guint acodec); void gst_rtsp_wfd_client_set_audio_channels(GstRTSPWFDClient *client, guint channels); void gst_rtsp_wfd_client_set_audio_bit_width(GstRTSPWFDClient *client, guint bwidth); void gst_rtsp_wfd_client_set_audio_latency(GstRTSPWFDClient *client, guint latency); -void gst_rtsp_wfd_client_set_video_codec(GstRTSPWFDClient *client, guint vcodec); +void gst_rtsp_wfd_client_set_vid_codec(GstRTSPWFDClient *client, guint vcodec); void gst_rtsp_wfd_client_set_video_native(GstRTSPWFDClient *client, guint native); void gst_rtsp_wfd_client_set_vid_native_resolution(GstRTSPWFDClient *client, guint64 res); void gst_rtsp_wfd_client_set_video_cea_resolution(GstRTSPWFDClient *client, guint64 res); diff --git a/gst/rtsp-server/rtsp-server-wfd.c b/gst/rtsp-server/rtsp-server-wfd.c index 042ec3b..47cc17a 100644 --- a/gst/rtsp-server/rtsp-server-wfd.c +++ b/gst/rtsp-server/rtsp-server-wfd.c @@ -75,6 +75,7 @@ struct _GstRTSPWFDServerPrivate guint64 native_resolution; guint64 supported_resolution; guint8 audio_codec; + guint8 video_codec; }; G_DEFINE_TYPE (GstRTSPWFDServer, gst_rtsp_wfd_server, GST_TYPE_RTSP_SERVER); @@ -244,6 +245,8 @@ create_client_wfd (GstRTSPServer * server) gst_rtsp_wfd_client_set_audio_codec (client, priv->audio_codec); + gst_rtsp_wfd_client_set_video_codec (client, priv->video_codec); + GST_RTSP_WFD_SERVER_UNLOCK (server); return GST_RTSP_CLIENT (client); @@ -318,6 +321,24 @@ gst_rtsp_wfd_server_set_video_native_reso (GstRTSPWFDServer * server, } GstRTSPResult +gst_rtsp_wfd_server_set_video_codec (GstRTSPWFDServer * server, + guint8 video_codec) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPWFDServerPrivate *priv = GST_RTSP_WFD_SERVER_GET_PRIVATE (server); + + g_return_val_if_fail (GST_IS_RTSP_WFD_SERVER (server), GST_RTSP_ERROR); + g_return_val_if_fail (priv != NULL, GST_RTSP_ERROR); + + GST_RTSP_WFD_SERVER_LOCK (server); + + priv->video_codec = video_codec; + + GST_RTSP_WFD_SERVER_UNLOCK (server); + return res; +} + +GstRTSPResult gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer * server, guint8 audio_codec) { diff --git a/gst/rtsp-server/rtsp-server-wfd.h b/gst/rtsp-server/rtsp-server-wfd.h old mode 100755 new mode 100644 index 1666f18..663a9a4 --- a/gst/rtsp-server/rtsp-server-wfd.h +++ b/gst/rtsp-server/rtsp-server-wfd.h @@ -80,6 +80,7 @@ GstRTSPResult gst_rtsp_wfd_server_trigger_request (GstRTSPServer *s GstRTSPResult gst_rtsp_wfd_server_set_supported_reso (GstRTSPWFDServer *server, guint64 supported_reso); GstRTSPResult gst_rtsp_wfd_server_set_video_native_reso (GstRTSPWFDServer *server, guint64 native_reso); +GstRTSPResult gst_rtsp_wfd_server_set_video_codec (GstRTSPWFDServer *server, guint8 video_codec); GstRTSPResult gst_rtsp_wfd_server_set_audio_codec (GstRTSPWFDServer *server, guint8 audio_codec); GstRTSPResult gst_rtsp_wfd_server_switch_to_udp (GstRTSPWFDServer *server); GstRTSPResult gst_rtsp_wfd_server_switch_to_tcp (GstRTSPWFDServer *server); diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index bf13245..ba801c2 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 9 +Release: 10 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ -- 2.7.4 From 2ebc75ab20d2e3ffc8d5600398aa3c509fe65d3b Mon Sep 17 00:00:00 2001 From: "Hyunsoo, Park" Date: Wed, 22 Mar 2017 17:47:26 +0900 Subject: [PATCH 16/16] Modify license macro [Version] 1.6.1-10 [Profile] Common [Issue Type] Update [Dependency module] N/A Change-Id: I7869857b4d4b3bac4cda4776a9e740215209f968 Signed-off-by: Hyunsoo, Park --- packaging/gst-rtsp-server.spec | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packaging/gst-rtsp-server.spec b/packaging/gst-rtsp-server.spec index ba801c2..d1636f2 100644 --- a/packaging/gst-rtsp-server.spec +++ b/packaging/gst-rtsp-server.spec @@ -1,7 +1,7 @@ Name: gst-rtsp-server Summary: Multimedia Framework Library Version: 1.6.1 -Release: 10 +Release: 11 Url: http://gstreamer.freedesktop.org/ Group: System/Libraries License: LGPL-2.0+ @@ -50,8 +50,6 @@ make %{?jobs:-j%jobs} %install rm -rf %{buildroot} %make_install -mkdir -p %{buildroot}/%{_datadir}/license -cp -rf %{_builddir}/%{name}-%{version}/COPYING %{buildroot}%{_datadir}/license/%{name} %clean rm -rf %{buildroot} @@ -65,7 +63,7 @@ rm -rf %{buildroot} %files %manifest gst-rtsp-server.manifest %defattr(-,root,root,-) -%{_datadir}/license/%{name} +%license COPYING %{_libdir}/*.so.* %files devel -- 2.7.4