2 * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 * @short_description: A client connection state
22 * @see_also: #GstRTSPServer, #GstRTSPThreadPool
24 * The client object handles the connection with a client for as long as a TCP
27 * A #GstRTSPWFDClient is created by #GstRTSPServer when a new connection is
28 * accepted and it inherits the #GstRTSPMountPoints, #GstRTSPSessionPool,
29 * #GstRTSPAuth and #GstRTSPThreadPool from the server.
31 * The client connection should be configured with the #GstRTSPConnection using
32 * gst_rtsp_wfd_client_set_connection() before it can be attached to a #GMainContext
33 * using gst_rtsp_wfd_client_attach(). From then on the client will handle requests
36 * Use gst_rtsp_wfd_client_session_filter() to iterate or modify all the
37 * #GstRTSPSession objects managed by the client object.
39 * Last reviewed on 2013-07-11 (1.0.0)
45 #include "rtsp-client-wfd.h"
46 #include "rtsp-media-factory-wfd.h"
48 #include "rtsp-params.h"
49 #include "gstwfdmessage.h"
51 #define GST_RTSP_WFD_CLIENT_GET_PRIVATE(obj) \
52 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_WFD_CLIENT, GstRTSPWFDClientPrivate))
55 * send_lock, lock, tunnels_lock
58 struct _GstRTSPWFDClientPrivate
60 GstRTSPWFDClientSendFunc send_func; /* protected by send_lock */
61 gpointer send_data; /* protected by send_lock */
62 GDestroyNotify send_notify; /* protected by send_lock */
64 /* used to cache the media in the last requested DESCRIBE so that
65 * we can pick it up in the next SETUP immediately */
76 /* Parameters for WIFI-DISPLAY */
84 guint64 cNativeResolution;
85 guint64 video_resolution_supported;
86 gint video_native_resolution;
88 guint cVESAResolution;
96 guint32 cmin_slice_size;
97 guint32 cslice_enc_params;
98 guint cframe_rate_control;
106 gboolean protection_enabled;
107 GstWFDHDCPProtection hdcp_version;
108 guint32 hdcp_tcpport;
110 gboolean edid_supported;
114 guint8 keep_alive_flag;
115 GMutex keep_alive_lock;
118 #define DEFAULT_WFD_TIMEOUT 60
119 #define WFD_MOUNT_POINT "/wfd1.0/streamid=0"
123 SIGNAL_WFD_OPTIONS_REQUEST,
124 SIGNAL_WFD_GET_PARAMETER_REQUEST,
128 GST_DEBUG_CATEGORY_STATIC (rtsp_wfd_client_debug);
129 #define GST_CAT_DEFAULT rtsp_wfd_client_debug
131 static guint gst_rtsp_client_wfd_signals[SIGNAL_WFD_LAST] = { 0 };
133 static void gst_rtsp_wfd_client_get_property (GObject * object, guint propid,
134 GValue * value, GParamSpec * pspec);
135 static void gst_rtsp_wfd_client_set_property (GObject * object, guint propid,
136 const GValue * value, GParamSpec * pspec);
137 static void gst_rtsp_wfd_client_finalize (GObject * obj);
139 static gboolean handle_wfd_options_request (GstRTSPClient * client,
140 GstRTSPContext * ctx);
141 static gboolean handle_wfd_set_param_request (GstRTSPClient * client,
142 GstRTSPContext * ctx);
143 static gboolean handle_wfd_get_param_request (GstRTSPClient * client,
144 GstRTSPContext * ctx);
146 static void send_generic_wfd_response (GstRTSPWFDClient * client,
147 GstRTSPStatusCode code, GstRTSPContext * ctx);
148 static gchar *wfd_make_path_from_uri (GstRTSPClient * client,
149 const GstRTSPUrl * uri);
150 static void wfd_options_request_done (GstRTSPWFDClient * client);
151 static void wfd_get_param_request_done (GstRTSPWFDClient * client);
152 static void handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx);
153 static void handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx);
154 static void wfd_set_keep_alive_condition(GstRTSPClient * client);
155 static gboolean wfd_ckeck_keep_alive_response (gpointer userdata);
156 static gboolean keep_alive_condition(gpointer userdata);
158 GstRTSPResult prepare_trigger_request (GstRTSPWFDClient * client,
159 GstRTSPMessage * request, GstWFDTriggerType trigger_type, gchar * url);
161 GstRTSPResult prepare_request (GstRTSPWFDClient * client,
162 GstRTSPMessage * request, GstRTSPMethod method, gchar * url);
165 send_request (GstRTSPWFDClient * client, GstRTSPSession * session,
166 GstRTSPMessage * request);
169 prepare_response (GstRTSPWFDClient * client, GstRTSPMessage * request,
170 GstRTSPMessage * response, GstRTSPMethod method);
172 static GstRTSPResult handle_M1_message (GstRTSPWFDClient * client);
173 static GstRTSPResult handle_M3_message (GstRTSPWFDClient * client);
174 static GstRTSPResult handle_M4_message (GstRTSPWFDClient * client);
175 static GstRTSPResult handle_M16_message (GstRTSPWFDClient * client);
177 G_DEFINE_TYPE (GstRTSPWFDClient, gst_rtsp_wfd_client, GST_TYPE_RTSP_CLIENT);
180 gst_rtsp_wfd_client_class_init (GstRTSPWFDClientClass * klass)
182 GObjectClass *gobject_class;
183 GstRTSPClientClass *rtsp_client_class;
185 g_type_class_add_private (klass, sizeof (GstRTSPWFDClientPrivate));
187 gobject_class = G_OBJECT_CLASS (klass);
188 rtsp_client_class = GST_RTSP_CLIENT_CLASS (klass);
190 gobject_class->get_property = gst_rtsp_wfd_client_get_property;
191 gobject_class->set_property = gst_rtsp_wfd_client_set_property;
192 gobject_class->finalize = gst_rtsp_wfd_client_finalize;
194 //klass->create_sdp = create_sdp;
195 //klass->configure_client_media = default_configure_client_media;
196 //klass->configure_client_transport = default_configure_client_transport;
197 //klass->params_set = default_params_set;
198 //klass->params_get = default_params_get;
200 rtsp_client_class->handle_options_request = handle_wfd_options_request;
201 rtsp_client_class->handle_set_param_request = handle_wfd_set_param_request;
202 rtsp_client_class->handle_get_param_request = handle_wfd_get_param_request;
203 rtsp_client_class->make_path_from_uri = wfd_make_path_from_uri;
205 rtsp_client_class->handle_response = handle_wfd_response;
206 rtsp_client_class->play_request = handle_wfd_play;
208 gst_rtsp_client_wfd_signals[SIGNAL_WFD_OPTIONS_REQUEST] =
209 g_signal_new ("wfd-options-request", G_TYPE_FROM_CLASS (klass),
210 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
211 wfd_options_request), NULL, NULL, g_cclosure_marshal_VOID__POINTER,
212 G_TYPE_NONE, 1, G_TYPE_POINTER);
214 gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST] =
215 g_signal_new ("wfd-get-parameter-request", G_TYPE_FROM_CLASS (klass),
216 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPWFDClientClass,
217 wfd_get_param_request), NULL, NULL, g_cclosure_marshal_VOID__POINTER,
218 G_TYPE_NONE, 1, G_TYPE_POINTER);
220 klass->wfd_options_request = wfd_options_request_done;
221 klass->wfd_get_param_request = wfd_get_param_request_done;
223 GST_DEBUG_CATEGORY_INIT (rtsp_wfd_client_debug, "rtspwfdclient", 0,
228 gst_rtsp_wfd_client_init (GstRTSPWFDClient * client)
230 GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
233 priv->protection_enabled = FALSE;
234 priv->video_native_resolution = GST_WFD_VIDEO_CEA_RESOLUTION;
235 priv->video_resolution_supported = GST_WFD_CEA_640x480P60;
236 g_mutex_init (&priv->keep_alive_lock);
237 GST_INFO_OBJECT (client, "Client is initialized");
240 /* A client is finalized when the connection is broken */
242 gst_rtsp_wfd_client_finalize (GObject * obj)
244 GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (obj);
245 GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
247 GST_INFO ("finalize client %p", client);
249 g_mutex_clear (&priv->keep_alive_lock);
250 G_OBJECT_CLASS (gst_rtsp_wfd_client_parent_class)->finalize (obj);
254 gst_rtsp_wfd_client_get_property (GObject * object, guint propid,
255 GValue * value, GParamSpec * pspec)
257 //GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (object);
261 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
266 gst_rtsp_wfd_client_set_property (GObject * object, guint propid,
267 const GValue * value, GParamSpec * pspec)
269 //GstRTSPWFDClient *client = GST_RTSP_WFD_CLIENT (object);
273 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
278 * gst_rtsp_wfd_client_new:
280 * Create a new #GstRTSPWFDClient instance.
282 * Returns: a new #GstRTSPWFDClient
285 gst_rtsp_wfd_client_new (void)
287 GstRTSPWFDClient *result;
289 result = g_object_new (GST_TYPE_RTSP_WFD_CLIENT, NULL);
295 gst_rtsp_wfd_client_start_wfd (GstRTSPWFDClient * client)
297 GstRTSPResult res = GST_RTSP_OK;
298 GST_INFO_OBJECT (client, "gst_rtsp_wfd_client_start_wfd");
300 res = handle_M1_message (client);
301 if (res < GST_RTSP_OK) {
302 GST_ERROR_OBJECT (client, "handle_M1_message failed : %d", res);
309 wfd_options_request_done (GstRTSPWFDClient * client)
311 GstRTSPResult res = GST_RTSP_OK;
312 GST_INFO_OBJECT (client, "M2 done..");
314 res = handle_M3_message (client);
315 if (res < GST_RTSP_OK) {
316 GST_ERROR_OBJECT (client, "handle_M3_message failed : %d", res);
323 wfd_get_param_request_done (GstRTSPWFDClient * client)
325 GstRTSPResult res = GST_RTSP_OK;
326 GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
327 priv->m3_done = TRUE;
328 GST_INFO_OBJECT (client, "M3 done..");
330 res = handle_M4_message (client);
331 if (res < GST_RTSP_OK) {
332 GST_ERROR_OBJECT (client, "handle_M4_message failed : %d", res);
339 wfd_get_prefered_resolution (guint64 srcResolution,
340 guint64 sinkResolution,
341 GstWFDVideoNativeResolution native,
343 guint32 * cMaxHeight, guint32 * cFramerate, guint32 * interleaved)
346 guint64 resolution = 0;
347 for (i = 0; i < 32; i++) {
348 if (((sinkResolution << i) & 0x80000000)
349 && ((srcResolution << i) & 0x80000000)) {
350 resolution = (0x00000001 << (31 - i));
355 case GST_WFD_VIDEO_CEA_RESOLUTION:
357 switch (resolution) {
358 case GST_WFD_CEA_640x480P60:
364 case GST_WFD_CEA_720x480P60:
370 case GST_WFD_CEA_720x480I60:
376 case GST_WFD_CEA_720x576P50:
382 case GST_WFD_CEA_720x576I50:
388 case GST_WFD_CEA_1280x720P30:
394 case GST_WFD_CEA_1280x720P60:
400 case GST_WFD_CEA_1920x1080P30:
406 case GST_WFD_CEA_1920x1080P60:
412 case GST_WFD_CEA_1920x1080I60:
418 case GST_WFD_CEA_1280x720P25:
424 case GST_WFD_CEA_1280x720P50:
430 case GST_WFD_CEA_1920x1080P25:
436 case GST_WFD_CEA_1920x1080P50:
442 case GST_WFD_CEA_1920x1080I50:
448 case GST_WFD_CEA_1280x720P24:
454 case GST_WFD_CEA_1920x1080P24:
469 case GST_WFD_VIDEO_VESA_RESOLUTION:
471 switch (resolution) {
472 case GST_WFD_VESA_800x600P30:
478 case GST_WFD_VESA_800x600P60:
484 case GST_WFD_VESA_1024x768P30:
490 case GST_WFD_VESA_1024x768P60:
496 case GST_WFD_VESA_1152x864P30:
502 case GST_WFD_VESA_1152x864P60:
508 case GST_WFD_VESA_1280x768P30:
514 case GST_WFD_VESA_1280x768P60:
520 case GST_WFD_VESA_1280x800P30:
526 case GST_WFD_VESA_1280x800P60:
532 case GST_WFD_VESA_1360x768P30:
538 case GST_WFD_VESA_1360x768P60:
544 case GST_WFD_VESA_1366x768P30:
550 case GST_WFD_VESA_1366x768P60:
556 case GST_WFD_VESA_1280x1024P30:
562 case GST_WFD_VESA_1280x1024P60:
568 case GST_WFD_VESA_1400x1050P30:
574 case GST_WFD_VESA_1400x1050P60:
580 case GST_WFD_VESA_1440x900P30:
586 case GST_WFD_VESA_1440x900P60:
592 case GST_WFD_VESA_1600x900P30:
598 case GST_WFD_VESA_1600x900P60:
604 case GST_WFD_VESA_1600x1200P30:
610 case GST_WFD_VESA_1600x1200P60:
616 case GST_WFD_VESA_1680x1024P30:
622 case GST_WFD_VESA_1680x1024P60:
628 case GST_WFD_VESA_1680x1050P30:
634 case GST_WFD_VESA_1680x1050P60:
640 case GST_WFD_VESA_1920x1200P30:
646 case GST_WFD_VESA_1920x1200P60:
661 case GST_WFD_VIDEO_HH_RESOLUTION:
664 switch (resolution) {
665 case GST_WFD_HH_800x480P30:
670 case GST_WFD_HH_800x480P60:
675 case GST_WFD_HH_854x480P30:
680 case GST_WFD_HH_854x480P60:
685 case GST_WFD_HH_864x480P30:
690 case GST_WFD_HH_864x480P60:
695 case GST_WFD_HH_640x360P30:
700 case GST_WFD_HH_640x360P60:
705 case GST_WFD_HH_960x540P30:
710 case GST_WFD_HH_960x540P60:
715 case GST_WFD_HH_848x480P30:
720 case GST_WFD_HH_848x480P60:
744 wfd_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri)
748 GST_DEBUG_OBJECT (client, "Got URI abspath : %s", uri->abspath);
749 path = g_strdup ("/wfd1.0/streamid=0");
755 handle_wfd_play (GstRTSPClient * client, GstRTSPContext * ctx)
757 wfd_set_keep_alive_condition(client);
761 handle_wfd_response (GstRTSPClient * client, GstRTSPContext * ctx)
763 GstRTSPResult res = GST_RTSP_OK;
767 GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
768 GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
770 GST_INFO_OBJECT (_client, "Handling response..");
773 GST_ERROR_OBJECT (_client, "Context is NULL");
775 GST_ERROR_OBJECT (_client, "Response is NULL");
777 /* parsing the GET_PARAMTER response */
778 res = gst_rtsp_message_get_body (ctx->response, (guint8 **) & data, &size);
779 if (res != GST_RTSP_OK) {
780 GST_ERROR_OBJECT (_client, "Failed to get body of response...");
784 GST_INFO_OBJECT (_client, "Response body is %d", size);
786 if (!priv->m3_done) {
787 GstWFDResult wfd_res;
788 GstWFDMessage *msg = NULL;
789 /* Parse M3 response from sink */
790 wfd_res = gst_wfd_message_new (&msg);
791 if (wfd_res != GST_WFD_OK) {
792 GST_ERROR_OBJECT (client, "Failed to create wfd message...");
796 wfd_res = gst_wfd_message_init (msg);
797 if (wfd_res != GST_WFD_OK) {
798 GST_ERROR_OBJECT (client, "Failed to init wfd message...");
802 wfd_res = gst_wfd_message_parse_buffer (data, size, msg);
804 GST_DEBUG_OBJECT (client, "M3 response server side message body: %s",
805 gst_wfd_message_as_text (msg));
807 /* Get the audio formats supported by WFDSink */
808 if (msg->audio_codecs) {
810 gst_wfd_message_get_supported_audio_format (msg, &priv->caCodec,
811 &priv->cFreq, &priv->cChanels, &priv->cBitwidth, &priv->caLatency);
812 if (wfd_res != GST_WFD_OK) {
813 GST_WARNING_OBJECT (client,
814 "Failed to get wfd support audio formats...");
819 /* Get the Video formats supported by WFDSink */
821 gst_wfd_message_get_supported_video_format (msg, &priv->cvCodec,
822 &priv->cNative, &priv->cNativeResolution,
823 (guint64 *) & priv->cCEAResolution,
824 (guint64 *) & priv->cVESAResolution,
825 (guint64 *) & priv->cHHResolution, &priv->cProfile, &priv->cLevel,
826 &priv->cvLatency, &priv->cMaxHeight, &priv->cMaxWidth,
827 &priv->cmin_slice_size, &priv->cslice_enc_params,
828 &priv->cframe_rate_control);
829 if (wfd_res != GST_WFD_OK) {
830 GST_WARNING_OBJECT (client,
831 "Failed to get wfd supported video formats...");
835 if (msg->client_rtp_ports) {
836 /* Get the RTP ports preferred by WFDSink */
838 gst_wfd_message_get_prefered_rtp_ports (msg, &priv->ctrans,
839 &priv->cprofile, &priv->clowertrans, &priv->crtp_port0,
841 if (wfd_res != GST_WFD_OK) {
842 GST_WARNING_OBJECT (client,
843 "Failed to get wfd prefered RTP ports...");
848 if (msg->display_edid) {
849 guint32 edid_block_count = 0;
850 gchar *edid_payload = NULL;
851 priv->edid_supported = FALSE;
852 /* Get the display edid preferred by WFDSink */
853 GST_DEBUG_OBJECT (client, "Going to gst_wfd_message_get_display_edid");
855 gst_wfd_message_get_display_edid (msg, &priv->edid_supported,
856 &edid_block_count, &edid_payload);
857 if (wfd_res != GST_WFD_OK) {
858 GST_ERROR_OBJECT (client, "Failed to get wfd display edid...");
861 GST_DEBUG_OBJECT (client, " edid supported: %d edid_block_count: %d",
862 priv->edid_supported, edid_block_count);
863 if (priv->edid_supported) {
867 (guint32) (((edid_payload[54 + 4] >> 4) << 8) | edid_payload[54 +
870 (guint32) (((edid_payload[54 + 7] >> 4) << 8) | edid_payload[54 +
872 GST_DEBUG_OBJECT (client, " edid supported Hres: %d Wres: %d",
873 priv->edid_hres, priv->edid_vres);
874 if ((priv->edid_hres < 640) || (priv->edid_vres < 480)
875 || (priv->edid_hres > 1920) || (priv->edid_vres > 1080)) {
878 priv->edid_supported = FALSE;
879 GST_WARNING_OBJECT (client, " edid invalid resolutions");
884 if (msg->content_protection) {
886 /*Get the hdcp version and tcp port by WFDSink */
888 gst_wfd_message_get_contentprotection_type (msg,
889 &priv->hdcp_version, &priv->hdcp_tcpport);
890 GST_DEBUG ("hdcp version =%d, tcp port = %d", priv->hdcp_version,
892 if (priv->hdcp_version > 0 && priv->hdcp_tcpport > 0)
893 priv->protection_enabled = TRUE;
895 if (wfd_res != GST_WFD_OK) {
896 GST_WARNING_OBJECT (client,
897 "Failed to get wfd content protection...");
901 GST_WARNING_OBJECT (client, "Don't use content protection");
905 g_signal_emit (_client,
906 gst_rtsp_client_wfd_signals[SIGNAL_WFD_GET_PARAMETER_REQUEST], 0,
909 /* TODO-WFD: Handle another GET_PARAMETER response with body */
911 } else if (size == 0) {
912 if (!priv->m1_done) {
913 GST_INFO_OBJECT (_client, "M1 response is done");
914 priv->m1_done = TRUE;
915 } else if (!priv->m4_done) {
916 GST_INFO_OBJECT (_client, "M4 response is done");
917 priv->m4_done = TRUE;
919 gst_rtsp_wfd_client_trigger_request (_client, WFD_TRIGGER_SETUP);
921 g_mutex_lock(&priv->keep_alive_lock);
922 if (priv->keep_alive_flag == FALSE) {
923 GST_INFO_OBJECT (_client, "M16 response is done");
924 priv->keep_alive_flag = TRUE;
926 g_mutex_unlock(&priv->keep_alive_lock);
937 handle_wfd_options_request (GstRTSPClient * client, GstRTSPContext * ctx)
939 GstRTSPResult res = GST_RTSP_OK;
940 GstRTSPMethod options;
943 gchar *user_agent = NULL;
945 options = GST_RTSP_OPTIONS |
949 GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
951 str = gst_rtsp_options_as_text (options);
953 /*append WFD specific method */
954 tmp = g_strdup (", org.wfa.wfd1.0");
955 g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1);
957 gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK,
958 gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request);
960 gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_PUBLIC, str);
965 gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_USER_AGENT,
967 if (res == GST_RTSP_OK) {
968 gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_USER_AGENT,
974 res = gst_rtsp_client_send_message (client, NULL, ctx->response);
975 if (res != GST_RTSP_OK) {
976 GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
980 GST_DEBUG_OBJECT (client, "Sent M2 response...");
982 g_signal_emit (client,
983 gst_rtsp_client_wfd_signals[SIGNAL_WFD_OPTIONS_REQUEST], 0, ctx);
989 handle_wfd_get_param_request (GstRTSPClient * client, GstRTSPContext * ctx)
991 GstRTSPResult res = GST_RTSP_OK;
995 GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
997 /* parsing the GET_PARAMTER request */
998 res = gst_rtsp_message_get_body (ctx->request, (guint8 **) & data, &size);
999 if (res != GST_RTSP_OK) {
1000 GST_ERROR_OBJECT (_client, "Failed to get body of request...");
1005 send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1007 /* TODO-WFD: Handle other GET_PARAMETER request from sink */
1014 handle_wfd_set_param_request (GstRTSPClient * client, GstRTSPContext * ctx)
1016 GstRTSPResult res = GST_RTSP_OK;
1017 guint8 *data = NULL;
1020 GstRTSPWFDClient *_client = GST_RTSP_WFD_CLIENT (client);
1022 res = gst_rtsp_message_get_body (ctx->request, &data, &size);
1023 if (res != GST_RTSP_OK)
1027 /* no body, keep-alive request */
1028 send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1031 GST_INFO_OBJECT (_client, "SET_PARAMETER Request : %s(%d)", data, size);
1032 if (g_strcmp0 ((const gchar *) data, "wfd_idr_request"))
1033 send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1035 /* TODO-WFD : Handle other set param request */
1036 send_generic_wfd_response (_client, GST_RTSP_STS_OK, ctx);
1047 GST_ERROR ("_client %p: bad request", _client);
1048 send_generic_wfd_response (_client, GST_RTSP_STS_BAD_REQUEST, ctx);
1055 gst_rtsp_wfd_client_parse_methods (GstRTSPWFDClient * client,
1056 GstRTSPMessage * response)
1058 GstRTSPHeaderField field;
1063 gboolean found_wfd_method = FALSE;
1065 /* reset supported methods */
1066 client->supported_methods = 0;
1068 /* Try Allow Header first */
1069 field = GST_RTSP_HDR_ALLOW;
1072 gst_rtsp_message_get_header (response, field, &respoptions, indx);
1073 if (indx == 0 && !respoptions) {
1074 /* if no Allow header was found then try the Public header... */
1075 field = GST_RTSP_HDR_PUBLIC;
1076 gst_rtsp_message_get_header (response, field, &respoptions, indx);
1081 /* If we get here, the server gave a list of supported methods, parse
1082 * them here. The string is like:
1084 * OPTIONS, PLAY, SETUP, ...
1086 options = g_strsplit (respoptions, ",", 0);
1088 for (i = 0; options[i]; i++) {
1092 stripped = g_strstrip (options[i]);
1093 method = gst_rtsp_find_method (stripped);
1095 if (!g_ascii_strcasecmp ("org.wfa.wfd1.0", stripped))
1096 found_wfd_method = TRUE;
1098 /* keep bitfield of supported methods */
1099 if (method != GST_RTSP_INVALID)
1100 client->supported_methods |= method;
1102 g_strfreev (options);
1107 if (!found_wfd_method) {
1108 GST_ERROR_OBJECT (client,
1109 "WFD client is not supporting WFD mandatory message : org.wfa.wfd1.0...");
1110 goto no_required_methods;
1113 /* Checking mandatory method */
1114 if (!(client->supported_methods & GST_RTSP_SET_PARAMETER)) {
1115 GST_ERROR_OBJECT (client,
1116 "WFD client is not supporting WFD mandatory message : SET_PARAMETER...");
1117 goto no_required_methods;
1120 /* Checking mandatory method */
1121 if (!(client->supported_methods & GST_RTSP_GET_PARAMETER)) {
1122 GST_ERROR_OBJECT (client,
1123 "WFD client is not supporting WFD mandatory message : GET_PARAMETER...");
1124 goto no_required_methods;
1127 if (!(client->supported_methods & GST_RTSP_OPTIONS)) {
1128 GST_INFO_OBJECT (client, "assuming OPTIONS is supported by client...");
1129 client->supported_methods |= GST_RTSP_OPTIONS;
1135 no_required_methods:
1137 GST_ELEMENT_ERROR (client, RESOURCE, OPEN_READ, (NULL),
1138 ("WFD Client does not support mandatory methods."));
1156 } GstWFDMessageType;
1159 _set_negotiated_resolution(GstRTSPWFDClient *client,
1160 guint32 width, guint32 height)
1162 GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1164 GstRTSPMediaFactory *factory = NULL;
1165 GstRTSPMountPoints *mount_points = NULL;
1168 gboolean ret = TRUE;
1170 if (!(mount_points = gst_rtsp_client_get_mount_points (parent_client))) {
1172 GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no mount points...");
1173 goto no_mount_points;
1176 path = g_strdup(WFD_MOUNT_POINT);
1179 GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no path...");
1183 if (!(factory = gst_rtsp_mount_points_match (mount_points,
1185 GST_ERROR_OBJECT (client, "Failed to set negotiated resolution: no factory...");
1190 gst_rtsp_media_factory_wfd_set_negotiated_resolution(factory,
1194 g_object_unref(factory);
1199 g_object_unref(mount_points);
1205 _set_wfd_message_body (GstRTSPWFDClient * client, GstWFDMessageType msg_type,
1206 gchar ** data, guint * len)
1208 GString *buf = NULL;
1209 GstWFDMessage *msg = NULL;
1210 GstWFDResult wfd_res = GST_WFD_EINVAL;
1211 GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
1213 buf = g_string_new ("");
1215 if (msg_type == M3_REQ_MSG) {
1216 /* create M3 request to be sent */
1217 wfd_res = gst_wfd_message_new (&msg);
1218 if (wfd_res != GST_WFD_OK) {
1219 GST_ERROR_OBJECT (client, "Failed to create wfd message...");
1223 wfd_res = gst_wfd_message_init (msg);
1224 if (wfd_res != GST_WFD_OK) {
1225 GST_ERROR_OBJECT (client, "Failed to init wfd message...");
1229 /* set the supported audio formats by the WFD server */
1231 gst_wfd_message_set_supported_audio_format (msg, GST_WFD_AUDIO_UNKNOWN,
1232 GST_WFD_FREQ_UNKNOWN, GST_WFD_CHANNEL_UNKNOWN, 0, 0);
1233 if (wfd_res != GST_WFD_OK) {
1234 GST_ERROR_OBJECT (client,
1235 "Failed to set supported audio formats on wfd message...");
1239 /* set the supported Video formats by the WFD server */
1241 gst_wfd_message_set_supported_video_format (msg, GST_WFD_VIDEO_UNKNOWN,
1242 GST_WFD_VIDEO_CEA_RESOLUTION, GST_WFD_CEA_UNKNOWN, GST_WFD_CEA_UNKNOWN,
1243 GST_WFD_VESA_UNKNOWN, GST_WFD_HH_UNKNOWN, GST_WFD_H264_UNKNOWN_PROFILE,
1244 GST_WFD_H264_LEVEL_UNKNOWN, 0, 0, 0, 0, 0, 0);
1245 if (wfd_res != GST_WFD_OK) {
1246 GST_ERROR_OBJECT (client,
1247 "Failed to set supported video formats on wfd message...");
1251 wfd_res = gst_wfd_message_set_display_edid (msg, 0, 0, NULL);
1252 if (wfd_res != GST_WFD_OK) {
1253 GST_ERROR_OBJECT (client,
1254 "Failed to set display edid type on wfd message...");
1258 if (priv->protection_enabled) {
1260 gst_wfd_message_set_contentprotection_type (msg, GST_WFD_HDCP_NONE,
1262 if (wfd_res != GST_WFD_OK) {
1263 GST_ERROR_OBJECT (client,
1264 "Failed to set supported content protection type on wfd message...");
1269 /* set the preffered RTP ports for the WFD server */
1271 gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_UNKNOWN,
1272 GST_WFD_RTSP_PROFILE_UNKNOWN, GST_WFD_RTSP_LOWER_TRANS_UNKNOWN, 0, 0);
1273 if (wfd_res != GST_WFD_OK) {
1274 GST_ERROR_OBJECT (client,
1275 "Failed to set supported video formats on wfd message...");
1279 *data = gst_wfd_message_param_names_as_text (msg);
1280 if (*data == NULL) {
1281 GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
1284 *len = strlen (*data);
1286 } else if (msg_type == M4_REQ_MSG) {
1287 GstRTSPUrl *url = NULL;
1289 GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1290 GstRTSPConnection *connection =
1291 gst_rtsp_client_get_connection (parent_client);
1293 /* Parameters for the preffered audio formats */
1294 GstWFDAudioFormats taudiocodec = GST_WFD_AUDIO_UNKNOWN;
1295 GstWFDAudioFreq taudiofreq = GST_WFD_FREQ_UNKNOWN;
1296 GstWFDAudioChannels taudiochannels = GST_WFD_CHANNEL_UNKNOWN;
1298 /* Parameters for the preffered video formats */
1299 GstWFDVideoCEAResolution tcCEAResolution = GST_WFD_CEA_UNKNOWN;
1300 GstWFDVideoVESAResolution tcVESAResolution = GST_WFD_VESA_UNKNOWN;
1301 GstWFDVideoHHResolution tcHHResolution = GST_WFD_HH_UNKNOWN;
1302 GstWFDVideoH264Profile tcProfile;
1303 GstWFDVideoH264Level tcLevel;
1304 guint64 resolution_supported = 0;
1306 url = gst_rtsp_connection_get_url (connection);
1308 GST_ERROR_OBJECT (client, "Failed to get connection URL");
1312 /* Logic to negotiate with information of M3 response */
1313 /* create M4 request to be sent */
1314 wfd_res = gst_wfd_message_new (&msg);
1315 if (wfd_res != GST_WFD_OK) {
1316 GST_ERROR_OBJECT (client, "Failed to create wfd message...");
1320 wfd_res = gst_wfd_message_init (msg);
1321 if (wfd_res != GST_WFD_OK) {
1322 GST_ERROR_OBJECT (client, "Failed to init wfd message...");
1326 buf = g_string_new ("");
1327 g_string_append_printf (buf, "rtsp://");
1328 /* FIXME-WFD : Should set host's URL, but url->host is client's URL */
1329 g_string_append (buf, url->host);
1330 g_string_append_printf (buf, "/wfd1.0/streamid=0");
1332 gst_wfd_message_set_presentation_url (msg, g_string_free (buf, FALSE),
1334 if (wfd_res != GST_WFD_OK) {
1335 GST_ERROR_OBJECT (client, "Failed to set presentation url");
1339 /* set the preffered audio formats */
1340 if (priv->caCodec & GST_WFD_AUDIO_AC3) {
1341 GST_ERROR_OBJECT (client, "AC3 is not supported");
1343 } else if (priv->caCodec & GST_WFD_AUDIO_AAC) {
1344 taudiocodec = GST_WFD_AUDIO_AAC;
1345 } else if (priv->caCodec & GST_WFD_AUDIO_LPCM) {
1346 taudiocodec = GST_WFD_AUDIO_LPCM;
1348 priv->caCodec = taudiocodec;
1350 if (priv->cFreq & GST_WFD_FREQ_48000)
1351 taudiofreq = GST_WFD_FREQ_48000;
1352 else if (priv->cFreq & GST_WFD_FREQ_44100)
1353 taudiofreq = GST_WFD_FREQ_44100;
1354 priv->cFreq = taudiofreq;
1356 /* TODO-WFD: Currently only 2 channels is present */
1357 if (priv->cChanels & GST_WFD_CHANNEL_8)
1358 taudiochannels = GST_WFD_CHANNEL_2;
1359 else if (priv->cChanels & GST_WFD_CHANNEL_6)
1360 taudiochannels = GST_WFD_CHANNEL_2;
1361 else if (priv->cChanels & GST_WFD_CHANNEL_4)
1362 taudiochannels = GST_WFD_CHANNEL_2;
1363 else if (priv->cChanels & GST_WFD_CHANNEL_2)
1364 taudiochannels = GST_WFD_CHANNEL_2;
1365 priv->cChanels = taudiochannels;
1368 gst_wfd_message_set_prefered_audio_format (msg, taudiocodec, taudiofreq,
1369 taudiochannels, priv->cBitwidth, priv->caLatency);
1370 if (wfd_res != GST_WFD_OK) {
1371 GST_ERROR_OBJECT (priv, "Failed to set preffered audio formats...");
1375 /* Set the preffered video formats */
1376 priv->cvCodec = GST_WFD_VIDEO_H264;
1377 priv->cProfile = tcProfile = GST_WFD_H264_BASE_PROFILE;
1378 priv->cLevel = tcLevel = GST_WFD_H264_LEVEL_3_1;
1380 resolution_supported = priv->video_resolution_supported;
1382 /* TODO-WFD: Need to verify this logic
1383 if(priv->edid_supported) {
1384 if (priv->edid_hres < 1920) resolution_supported = resolution_supported & 0x8C7F;
1385 if (priv->edid_hres < 1280) resolution_supported = resolution_supported & 0x1F;
1386 if (priv->edid_hres < 720) resolution_supported = resolution_supported & 0x01;
1390 if (priv->video_native_resolution == GST_WFD_VIDEO_CEA_RESOLUTION) {
1392 wfd_get_prefered_resolution (resolution_supported,
1393 priv->cCEAResolution, priv->video_native_resolution, &priv->cMaxWidth,
1394 &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved);
1396 ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1397 tcCEAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1398 priv->cInterleaved);
1399 } else if (priv->video_native_resolution == GST_WFD_VIDEO_VESA_RESOLUTION) {
1401 wfd_get_prefered_resolution (resolution_supported,
1402 priv->cVESAResolution, priv->video_native_resolution,
1403 &priv->cMaxWidth, &priv->cMaxHeight, &priv->cFramerate,
1404 &priv->cInterleaved);
1406 ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1407 tcVESAResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1408 priv->cInterleaved);
1409 } else if (priv->video_native_resolution == GST_WFD_VIDEO_HH_RESOLUTION) {
1411 wfd_get_prefered_resolution (resolution_supported,
1412 priv->cHHResolution, priv->video_native_resolution, &priv->cMaxWidth,
1413 &priv->cMaxHeight, &priv->cFramerate, &priv->cInterleaved);
1415 ("wfd negotiated resolution: %08x, width: %d, height: %d, framerate: %d, interleaved: %d",
1416 tcHHResolution, priv->cMaxWidth, priv->cMaxHeight, priv->cFramerate,
1417 priv->cInterleaved);
1420 if (!_set_negotiated_resolution(client, priv->cMaxWidth,
1421 priv->cMaxHeight)) {
1422 GST_ERROR_OBJECT (client, "Failed to set negotiated "
1423 "resolution to media factory...");
1427 gst_wfd_message_set_prefered_video_format (msg, priv->cvCodec,
1428 priv->video_native_resolution, GST_WFD_CEA_UNKNOWN, tcCEAResolution,
1429 tcVESAResolution, tcHHResolution, tcProfile, tcLevel, priv->cvLatency,
1430 priv->cMaxWidth, priv->cMaxHeight, priv->cmin_slice_size,
1431 priv->cslice_enc_params, priv->cframe_rate_control);
1433 if (wfd_res != GST_WFD_OK) {
1434 GST_ERROR_OBJECT (client, "Failed to set preffered video formats...");
1438 /* set the preffered RTP ports for the WFD server */
1440 gst_wfd_messge_set_prefered_rtp_ports (msg, GST_WFD_RTSP_TRANS_RTP,
1441 GST_WFD_RTSP_PROFILE_AVP, GST_WFD_RTSP_LOWER_TRANS_UDP, priv->crtp_port0, priv->crtp_port1);
1442 if (wfd_res != GST_WFD_OK) {
1443 GST_ERROR_OBJECT (client,
1444 "Failed to set supported video formats on wfd message...");
1448 *data = gst_wfd_message_as_text (msg);
1449 if (*data == NULL) {
1450 GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
1453 *len = strlen (*data);
1455 } else if (msg_type == M5_REQ_MSG) {
1456 g_string_append (buf, "wfd_trigger_method: SETUP");
1457 g_string_append (buf, "\r\n");
1459 *data = g_string_free (buf, FALSE);
1460 } else if (msg_type == TEARDOWN_TRIGGER) {
1461 g_string_append (buf, "wfd_trigger_method: TEARDOWN");
1462 g_string_append (buf, "\r\n");
1464 *data = g_string_free (buf, FALSE);
1480 * @client: client object
1481 * @request : requst message to be prepared
1482 * @method : RTSP method of the request
1483 * @url : url need to be in the request
1484 * @message_type : WFD message type
1485 * @trigger_type : trigger method to be used for M5 mainly
1487 * Prepares request based on @method & @message_type
1489 * Returns: a #GstRTSPResult.
1492 prepare_request (GstRTSPWFDClient * client, GstRTSPMessage * request,
1493 GstRTSPMethod method, gchar * url)
1495 GstRTSPResult res = GST_RTSP_OK;
1498 if (method == GST_RTSP_GET_PARAMETER || method == GST_RTSP_SET_PARAMETER) {
1500 url = g_strdup ("rtsp://localhost/wfd1.0");
1503 GST_DEBUG_OBJECT (client, "Preparing request: %d", method);
1505 /* initialize the request */
1506 res = gst_rtsp_message_init_request (request, method, url);
1508 GST_ERROR ("init request failed");
1513 /* Prepare OPTIONS request to send */
1514 case GST_RTSP_OPTIONS:{
1515 /* add wfd specific require filed "org.wfa.wfd1.0" */
1516 str = g_strdup ("org.wfa.wfd1.0");
1517 res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_REQUIRE, str);
1519 GST_ERROR ("Failed to add header");
1528 /* Prepare GET_PARAMETER request */
1529 case GST_RTSP_GET_PARAMETER:{
1534 /* add content type */
1536 gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1539 GST_ERROR ("Failed to add header");
1543 _set_wfd_message_body (client, M3_REQ_MSG, &msg, &msglen);
1544 msglength = g_string_new ("");
1545 g_string_append_printf (msglength, "%d", msglen);
1546 GST_DEBUG ("M3 server side message body: %s", msg);
1548 /* add content-length type */
1550 gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1551 g_string_free (msglength, FALSE));
1552 if (res != GST_RTSP_OK) {
1553 GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1557 res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1558 if (res != GST_RTSP_OK) {
1559 GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1567 /* Prepare SET_PARAMETER request */
1568 case GST_RTSP_SET_PARAMETER:{
1573 /* add content type */
1575 gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1577 if (res != GST_RTSP_OK) {
1578 GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1582 _set_wfd_message_body (client, M4_REQ_MSG, &msg, &msglen);
1583 msglength = g_string_new ("");
1584 g_string_append_printf (msglength, "%d", msglen);
1585 GST_DEBUG ("M4 server side message body: %s", msg);
1587 /* add content-length type */
1589 gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1590 g_string_free (msglength, FALSE));
1591 if (res != GST_RTSP_OK) {
1592 GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1596 res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1597 if (res != GST_RTSP_OK) {
1598 GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1613 return GST_RTSP_ERROR;
1617 prepare_trigger_request (GstRTSPWFDClient * client, GstRTSPMessage * request,
1618 GstWFDTriggerType trigger_type, gchar * url)
1620 GstRTSPResult res = GST_RTSP_OK;
1622 /* initialize the request */
1623 res = gst_rtsp_message_init_request (request, GST_RTSP_SET_PARAMETER, url);
1625 GST_ERROR ("init request failed");
1629 switch (trigger_type) {
1630 case WFD_TRIGGER_SETUP:{
1635 /* add content type */
1637 gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1639 if (res != GST_RTSP_OK) {
1640 GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1644 _set_wfd_message_body (client, M5_REQ_MSG, &msg, &msglen);
1645 msglength = g_string_new ("");
1646 g_string_append_printf (msglength, "%d", msglen);
1647 GST_DEBUG ("M5 server side message body: %s", msg);
1649 /* add content-length type */
1651 gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1652 g_string_free (msglength, FALSE));
1653 if (res != GST_RTSP_OK) {
1654 GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1658 res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1659 if (res != GST_RTSP_OK) {
1660 GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1667 case WFD_TRIGGER_TEARDOWN:{
1672 /* add content type */
1674 gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE,
1676 if (res != GST_RTSP_OK) {
1677 GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
1681 _set_wfd_message_body (client, TEARDOWN_TRIGGER, &msg, &msglen);
1682 msglength = g_string_new ("");
1683 g_string_append_printf (msglength, "%d", msglen);
1684 GST_DEBUG ("Trigger TEARDOWN server side message body: %s", msg);
1686 /* add content-length type */
1688 gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH,
1689 g_string_free (msglength, FALSE));
1690 if (res != GST_RTSP_OK) {
1691 GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1695 res = gst_rtsp_message_set_body (request, (guint8 *) msg, msglen);
1696 if (res != GST_RTSP_OK) {
1697 GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
1704 /* TODO-WFD: implement to handle other trigger type */
1717 send_request (GstRTSPWFDClient * client, GstRTSPSession * session,
1718 GstRTSPMessage * request)
1720 GstRTSPResult res = GST_RTSP_OK;
1721 GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1723 /* remove any previous header */
1724 gst_rtsp_message_remove_header (request, GST_RTSP_HDR_SESSION, -1);
1726 /* add the new session header for new session ids */
1729 const gchar *sessionid = NULL;
1732 sessionid = gst_rtsp_session_get_sessionid (session);
1733 GST_INFO_OBJECT (client, "Session id : %s", sessionid);
1735 timeout = gst_rtsp_session_get_timeout (session);
1736 if (timeout != DEFAULT_WFD_TIMEOUT)
1737 str = g_strdup_printf ("%s; timeout=%d", sessionid, timeout);
1739 str = g_strdup (sessionid);
1741 gst_rtsp_message_take_header (request, GST_RTSP_HDR_SESSION, str);
1744 if (gst_debug_category_get_threshold (rtsp_wfd_client_debug) >= GST_LEVEL_LOG) {
1745 gst_rtsp_message_dump (request);
1748 res = gst_rtsp_client_send_message (parent_client, session, request);
1749 if (res != GST_RTSP_OK) {
1750 GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
1753 gst_rtsp_message_unset (request);
1758 * @client: client object
1759 * @request : requst message received
1760 * @response : response to be prepare based on request
1761 * @method : RTSP method
1763 * prepare response to the request based on @method & @message_type
1765 * Returns: a #GstRTSPResult.
1768 prepare_response (GstRTSPWFDClient * client, GstRTSPMessage * request,
1769 GstRTSPMessage * response, GstRTSPMethod method)
1771 GstRTSPResult res = GST_RTSP_OK;
1774 /* prepare OPTIONS response */
1775 case GST_RTSP_OPTIONS:{
1776 GstRTSPMethod options;
1779 gchar *user_agent = NULL;
1781 options = GST_RTSP_OPTIONS |
1785 GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
1787 str = gst_rtsp_options_as_text (options);
1789 /*append WFD specific method */
1790 tmp = g_strdup (", org.wfa.wfd1.0");
1791 g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1);
1793 gst_rtsp_message_init_response (response, GST_RTSP_STS_OK,
1794 gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
1796 gst_rtsp_message_add_header (response, GST_RTSP_HDR_PUBLIC, str);
1800 gst_rtsp_message_get_header (request, GST_RTSP_HDR_USER_AGENT,
1802 if (res == GST_RTSP_OK) {
1803 gst_rtsp_message_add_header (response, GST_RTSP_HDR_USER_AGENT,
1810 GST_ERROR_OBJECT (client, "Unhandled method...");
1811 return GST_RTSP_EINVAL;
1819 send_generic_wfd_response (GstRTSPWFDClient * client, GstRTSPStatusCode code,
1820 GstRTSPContext * ctx)
1822 GstRTSPResult res = GST_RTSP_OK;
1823 GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1825 gst_rtsp_message_init_response (ctx->response, code,
1826 gst_rtsp_status_as_text (code), ctx->request);
1828 res = gst_rtsp_client_send_message (parent_client, NULL, ctx->response);
1829 if (res != GST_RTSP_OK) {
1830 GST_ERROR_OBJECT (client, "gst_rtsp_client_send_message failed : %d", res);
1835 static GstRTSPResult
1836 handle_M1_message (GstRTSPWFDClient * client)
1838 GstRTSPResult res = GST_RTSP_OK;
1839 GstRTSPMessage request = { 0 };
1841 res = prepare_request (client, &request, GST_RTSP_OPTIONS, (gchar *) "*");
1842 if (GST_RTSP_OK != res) {
1843 GST_ERROR_OBJECT (client, "Failed to prepare M1 request....\n");
1847 GST_DEBUG_OBJECT (client, "Sending M1 request.. (OPTIONS request)");
1849 send_request (client, NULL, &request);
1855 * handle_M3_message:
1856 * @client: client object
1858 * Handles M3 WFD message.
1859 * This API will send M3 message (GET_PARAMETER) to WFDSink to query supported formats by the WFDSink.
1860 * After getting supported formats info, this API will set those values on WFDConfigMessage obj
1862 * Returns: a #GstRTSPResult.
1864 static GstRTSPResult
1865 handle_M3_message (GstRTSPWFDClient * client)
1867 GstRTSPResult res = GST_RTSP_OK;
1868 GstRTSPMessage request = { 0 };
1869 GstRTSPUrl *url = NULL;
1870 gchar *url_str = NULL;
1872 GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1873 GstRTSPConnection *connection =
1874 gst_rtsp_client_get_connection (parent_client);
1876 url = gst_rtsp_connection_get_url (connection);
1878 GST_ERROR_OBJECT (client, "Failed to get connection URL");
1879 res = GST_RTSP_ERROR;
1883 url_str = gst_rtsp_url_get_request_uri (url);
1884 if (url_str == NULL) {
1885 GST_ERROR_OBJECT (client, "Failed to get connection URL");
1886 res = GST_RTSP_ERROR;
1890 res = prepare_request (client, &request, GST_RTSP_GET_PARAMETER, url_str);
1891 if (GST_RTSP_OK != res) {
1892 GST_ERROR_OBJECT (client, "Failed to prepare M3 request....\n");
1896 GST_DEBUG_OBJECT (client, "Sending GET_PARAMETER request message (M3)...");
1898 send_request (client, NULL, &request);
1906 static GstRTSPResult
1907 handle_M4_message (GstRTSPWFDClient * client)
1909 GstRTSPResult res = GST_RTSP_OK;
1910 GstRTSPMessage request = { 0 };
1911 GstRTSPUrl *url = NULL;
1912 gchar *url_str = NULL;
1914 GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1915 GstRTSPConnection *connection =
1916 gst_rtsp_client_get_connection (parent_client);
1918 url = gst_rtsp_connection_get_url (connection);
1920 GST_ERROR_OBJECT (client, "Failed to get connection URL");
1921 res = GST_RTSP_ERROR;
1925 url_str = gst_rtsp_url_get_request_uri (url);
1926 if (url_str == NULL) {
1927 GST_ERROR_OBJECT (client, "Failed to get connection URL");
1928 res = GST_RTSP_ERROR;
1932 res = prepare_request (client, &request, GST_RTSP_SET_PARAMETER, url_str);
1933 if (GST_RTSP_OK != res) {
1934 GST_ERROR_OBJECT (client, "Failed to prepare M4 request....\n");
1938 GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message (M4)...");
1940 send_request (client, NULL, &request);
1949 gst_rtsp_wfd_client_trigger_request (GstRTSPWFDClient * client,
1950 GstWFDTriggerType type)
1952 GstRTSPResult res = GST_RTSP_OK;
1953 GstRTSPMessage request = { 0 };
1954 GstRTSPUrl *url = NULL;
1955 gchar *url_str = NULL;
1957 GstRTSPClient *parent_client = GST_RTSP_CLIENT_CAST (client);
1958 GstRTSPConnection *connection =
1959 gst_rtsp_client_get_connection (parent_client);
1961 url = gst_rtsp_connection_get_url (connection);
1963 GST_ERROR_OBJECT (client, "Failed to get connection URL");
1964 res = GST_RTSP_ERROR;
1968 url_str = gst_rtsp_url_get_request_uri (url);
1969 if (url_str == NULL) {
1970 GST_ERROR_OBJECT (client, "Failed to get connection URL");
1971 res = GST_RTSP_ERROR;
1975 res = prepare_trigger_request (client, &request, type, url_str);
1976 if (GST_RTSP_OK != res) {
1977 GST_ERROR_OBJECT (client, "Failed to prepare M5 request....\n");
1981 GST_DEBUG_OBJECT (client, "Sending trigger request message...: %d", type);
1983 send_request (client, NULL, &request);
1992 gst_rtsp_wfd_client_set_video_supported_resolution (GstRTSPWFDClient * client,
1993 guint64 supported_reso)
1995 GstRTSPResult res = GST_RTSP_OK;
1996 GstRTSPWFDClientPrivate *priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
1997 priv->video_resolution_supported = supported_reso;
1998 GST_DEBUG ("Resolution : %lld", supported_reso);
2004 wfd_ckeck_keep_alive_response (gpointer userdata)
2006 GstRTSPWFDClient *client = (GstRTSPWFDClient *)userdata;
2007 GstRTSPWFDClientPrivate *priv;
2011 priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2012 if (priv->keep_alive_flag) {
2016 GST_INFO ("%p: source error notification", client);
2017 // FIXME Do something here. Maybe emit some signal?
2022 /*Sending keep_alive (M16) message.
2023 Without calling prepare_request function.*/
2024 static GstRTSPResult
2025 handle_M16_message (GstRTSPWFDClient * client)
2027 GstRTSPResult res = GST_RTSP_OK;
2028 GstRTSPMessage request = { 0 };
2029 gchar *url_str = NULL;
2031 url_str = g_strdup("rtsp://localhost/wfd1.0");
2033 res = gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER, url_str);
2035 GST_ERROR ("init request failed");
2039 send_request (client, NULL, &request);
2043 /*CHecking whether source has got response of any request.
2044 * If yes, keep alive message is sent otherwise error message
2045 * will be displayed.*/
2047 keep_alive_condition(gpointer userdata)
2049 GstRTSPWFDClient *client;
2050 GstRTSPWFDClientPrivate *priv;
2052 client = (GstRTSPWFDClient *)userdata;
2056 priv = GST_RTSP_WFD_CLIENT_GET_PRIVATE (client);
2058 g_mutex_lock(&priv->keep_alive_lock);
2059 if(!priv->keep_alive_flag) {
2060 g_timeout_add(5000, wfd_ckeck_keep_alive_response, client);
2063 GST_DEBUG_OBJECT (client, "have received last keep alive message response");
2066 GST_DEBUG("sending keep alive message");
2067 res = handle_M16_message(client);
2069 priv->keep_alive_flag = FALSE;
2072 GST_ERROR_OBJECT (client, "Failed to send Keep Alive Message");
2073 g_mutex_unlock(&priv->keep_alive_lock);
2076 g_mutex_unlock(&priv->keep_alive_lock);
2081 void wfd_set_keep_alive_condition(GstRTSPClient * client)
2083 GstRTSPWFDClient *wfd_client;
2084 wfd_client = GST_RTSP_WFD_CLIENT(client);
2086 g_timeout_add((DEFAULT_WFD_TIMEOUT-5)*1000, keep_alive_condition, wfd_client);