Merge branch 'upstream/1.19.3' into tizen_gst_1.19.3
[platform/upstream/gstreamer.git] / subprojects / gst-rtsp-server / gst / rtsp-server / rtsp-media-factory-wfd.c
1 /* GStreamer
2  * Copyright (C) 2015 Samsung Electronics Hyunjun Ko <zzoon.ko@samsung.com>
3  *
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.
8  *
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.
13  *
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.
18  */
19 /*
20  * SECTION:rtsp-media-factory
21  * @short_description: A factory for media pipelines
22  * @see_also: #GstRTSPMountPoints, #GstRTSPMedia
23  *
24  * The #GstRTSPMediaFactoryWFD is responsible for creating or recycling
25  * #GstRTSPMedia objects based on the passed URL.
26  *
27  * The default implementation of the object can create #GstRTSPMedia objects
28  * containing a pipeline created from a launch description set with
29  * gst_rtsp_media_factory_wfd_set_launch().
30  *
31  * Media from a factory can be shared by setting the shared flag with
32  * gst_rtsp_media_factory_wfd_set_shared(). When a factory is shared,
33  * gst_rtsp_media_factory_wfd_construct() will return the same #GstRTSPMedia when
34  * the url matches.
35  *
36  * Last reviewed on 2013-07-11 (1.0.0)
37  */
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include <stdio.h>
44 #include <string.h>
45
46 #include "rtsp-media-factory-wfd.h"
47 #include "gstwfdmessage.h"
48 #include "rtsp-media-ext.h"
49
50 #define GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE(obj)  \
51        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_WFD, GstRTSPMediaFactoryWFDPrivate))
52
53 #define GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f)       (&(GST_RTSP_MEDIA_FACTORY_WFD_CAST(f)->priv->lock))
54 #define GST_RTSP_MEDIA_FACTORY_WFD_LOCK(f)           (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f)))
55 #define GST_RTSP_MEDIA_FACTORY_WFD_UNLOCK(f)         (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f)))
56
57 typedef struct _GstRTPSMediaWFDTypeFindResult GstRTPSMediaWFDTypeFindResult;
58
59 struct _GstRTPSMediaWFDTypeFindResult{
60   gint h264_found;
61   gint aac_found;
62   gint ac3_found;
63   GstElementFactory *demux_fact;
64   GstElementFactory *src_fact;
65 };
66
67 typedef struct _GstRTSPMediaWFDDirectPipelineData GstRTSPMediaWFDDirectPipelineData;
68
69 struct _GstRTSPMediaWFDDirectPipelineData {
70   GstBin *pipeline;
71   GstElement *ap;
72   GstElement *vp;
73   GstElement *aq;
74   GstElement *vq;
75   GstElement *tsmux;
76   GstElement *mux_fs;
77   gchar *uri;
78 };
79
80
81 struct _GstRTSPMediaFactoryWFDPrivate
82 {
83   GMutex lock;
84   GstRTSPPermissions *permissions;
85   gchar *launch;
86   gboolean shared;
87   GstRTSPLowerTrans protocols;
88   guint buffer_size;
89   guint mtu_size;
90
91   guint8 videosrc_type;
92   guint8 video_codec;
93   gchar *video_encoder;
94   guint video_bitrate;
95   guint video_width;
96   guint video_height;
97   guint video_framerate;
98   guint video_enc_skip_inbuf_value;
99   GstElement *video_queue;
100   GstBin *video_srcbin;
101
102   GstElement *venc;
103   guint decide_udp_bitrate[21];
104   guint min_udp_bitrate;
105   guint max_udp_bitrate;
106   gboolean decided_udp_bitrate;
107
108   gchar *audio_device;
109   gchar *audio_encoder_aac;
110   gchar *audio_encoder_ac3;
111   guint8 audio_codec;
112   guint64 audio_latency_time;
113   guint64 audio_buffer_time;
114   gboolean audio_do_timestamp;
115   guint8 audio_channels;
116   guint8 audio_freq;
117   guint8 audio_bitrate;
118   GstElement *audio_queue;
119   GstBin *audio_srcbin;
120
121   GMutex direct_lock;
122   GCond direct_cond;
123   GType decodebin_type;
124   GstBin *discover_pipeline;
125   GstRTPSMediaWFDTypeFindResult res;
126   GstRTSPMediaWFDDirectPipelineData *direct_pipe;
127   GstBin *stream_bin;
128   GstElement *mux;
129   GstElement *mux_queue;
130   GstElement *pay;
131   GstElement *stub_fs;
132   GMainLoop *discover_loop;
133
134   guint64 video_resolution_supported;
135
136   gboolean dump_ts;
137 };
138
139 #define DEFAULT_LAUNCH          NULL
140 #define DEFAULT_SHARED          FALSE
141 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
142                                         GST_RTSP_LOWER_TRANS_TCP
143 #define DEFAULT_BUFFER_SIZE     0x80000
144
145 enum
146 {
147   PROP_0,
148   PROP_LAUNCH,
149   PROP_SHARED,
150   PROP_SUSPEND_MODE,
151   PROP_EOS_SHUTDOWN,
152   PROP_PROTOCOLS,
153   PROP_BUFFER_SIZE,
154   PROP_LAST
155 };
156
157 enum
158 {
159   SIGNAL_MEDIA_CONSTRUCTED,
160   SIGNAL_MEDIA_CONFIGURE,
161   SIGNAL_DIRECT_STREAMING_END,
162   SIGNAL_LAST
163 };
164
165 GST_DEBUG_CATEGORY_STATIC (rtsp_media_wfd_debug);
166 #define GST_CAT_DEFAULT rtsp_media_wfd_debug
167
168 static guint gst_rtsp_media_factory_wfd_signals[SIGNAL_LAST] = { 0 };
169
170 static void gst_rtsp_media_factory_wfd_get_property (GObject * object,
171     guint propid, GValue * value, GParamSpec * pspec);
172 static void gst_rtsp_media_factory_wfd_set_property (GObject * object,
173     guint propid, const GValue * value, GParamSpec * pspec);
174
175 static void gst_rtsp_media_factory_wfd_finalize (GObject * obj);
176
177
178 static GstElement *rtsp_media_factory_wfd_create_element (GstRTSPMediaFactory *
179     factory, const GstRTSPUrl * url);
180 static GstRTSPMedia *rtsp_media_factory_wfd_construct (GstRTSPMediaFactory *
181     factory, const GstRTSPUrl * url);
182
183 static void _config_bitrate (GstRTSPMediaFactoryWFD * factory);
184
185 G_DEFINE_TYPE (GstRTSPMediaFactoryWFD, gst_rtsp_media_factory_wfd,
186     GST_TYPE_RTSP_MEDIA_FACTORY);
187
188 static void
189 gst_rtsp_media_factory_wfd_class_init (GstRTSPMediaFactoryWFDClass * klass)
190 {
191   GObjectClass *gobject_class;
192   GstRTSPMediaFactoryClass *factory_class;
193
194   g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryWFDPrivate));
195
196   gobject_class = G_OBJECT_CLASS (klass);
197   factory_class = GST_RTSP_MEDIA_FACTORY_CLASS (klass);
198
199   gobject_class->get_property = gst_rtsp_media_factory_wfd_get_property;
200   gobject_class->set_property = gst_rtsp_media_factory_wfd_set_property;
201   gobject_class->finalize = gst_rtsp_media_factory_wfd_finalize;
202
203   gst_rtsp_media_factory_wfd_signals[SIGNAL_DIRECT_STREAMING_END] =
204       g_signal_new ("direct-stream-end", G_TYPE_FROM_CLASS (klass),
205       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryWFDClass,
206           direct_stream_end), NULL, NULL, g_cclosure_marshal_generic,
207       G_TYPE_NONE, 0, G_TYPE_NONE);
208
209   factory_class->construct = rtsp_media_factory_wfd_construct;
210   factory_class->create_element = rtsp_media_factory_wfd_create_element;
211
212   GST_DEBUG_CATEGORY_INIT (rtsp_media_wfd_debug, "rtspmediafactorywfd", 0,
213       "GstRTSPMediaFactoryWFD");
214 }
215
216 void
217 gst_rtsp_media_factory_wfd_set (GstRTSPMediaFactoryWFD * factory,
218     guint8 videosrc_type, gchar * audio_device, guint64 audio_latency_time,
219     guint64 audio_buffer_time, gboolean audio_do_timestamp, guint mtu_size)
220 {
221   GstRTSPMediaFactoryWFDPrivate *priv =
222       GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory);
223   factory->priv = priv;
224
225   priv->videosrc_type = videosrc_type;
226   priv->audio_device = audio_device;
227   priv->audio_latency_time = audio_latency_time;
228   priv->audio_buffer_time = audio_buffer_time;
229   priv->audio_do_timestamp = audio_do_timestamp;
230   priv->mtu_size = mtu_size;
231 }
232
233 void
234 gst_rtsp_media_factory_wfd_set_encoders (GstRTSPMediaFactoryWFD * factory,
235     gchar * video_encoder, gchar * audio_encoder_aac, gchar * audio_encoder_ac3)
236 {
237   GstRTSPMediaFactoryWFDPrivate *priv =
238       GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory);
239   factory->priv = priv;
240
241   priv->video_encoder = video_encoder;
242   priv->audio_encoder_aac = audio_encoder_aac;
243   priv->audio_encoder_ac3 = audio_encoder_ac3;
244 }
245
246 void
247 gst_rtsp_media_factory_wfd_set_dump_ts (GstRTSPMediaFactoryWFD * factory,
248     gboolean dump_ts)
249 {
250   GstRTSPMediaFactoryWFDPrivate *priv =
251       GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory);
252   factory->priv = priv;
253
254   priv->dump_ts = dump_ts;
255 }
256
257 void
258 gst_rtsp_media_factory_wfd_set_negotiated_resolution (GstRTSPMediaFactory *
259     factory, guint32 width, guint32 height)
260 {
261   GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory);
262   GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv;
263
264   priv->video_width = width;
265   priv->video_height = height;
266   _config_bitrate (factory_wfd);
267 }
268
269 void
270 gst_rtsp_media_factory_wfd_set_audio_codec (GstRTSPMediaFactory * factory,
271     guint audio_codec)
272 {
273   GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory);
274   GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv;
275
276   priv->audio_codec = audio_codec;
277 }
278
279 void
280 gst_rtsp_media_factory_wfd_set_video_codec (GstRTSPMediaFactory * factory,
281     guint video_codec)
282 {
283   GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory);
284   GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv;
285
286   priv->video_codec = video_codec;
287 }
288
289 static void
290 _config_bitrate (GstRTSPMediaFactoryWFD * factory)
291 {
292   GstRTSPMediaFactoryWFDPrivate *priv = factory->priv;
293
294   if (priv->decided_udp_bitrate) {
295     priv->video_bitrate = priv->decide_udp_bitrate[0];
296     priv->min_udp_bitrate = priv->decide_udp_bitrate[1];
297     priv->max_udp_bitrate = priv->decide_udp_bitrate[2];
298
299     if ((priv->video_width * priv->video_height) >= (1920 * 1080)) {
300       priv->video_bitrate = priv->decide_udp_bitrate[3];
301       priv->min_udp_bitrate = priv->decide_udp_bitrate[4];
302       priv->max_udp_bitrate = priv->decide_udp_bitrate[5];
303     } else if ((priv->video_width * priv->video_height) >= (1280 * 720)) {
304       priv->video_bitrate = priv->decide_udp_bitrate[6];
305       priv->min_udp_bitrate = priv->decide_udp_bitrate[7];
306       priv->max_udp_bitrate = priv->decide_udp_bitrate[8];
307     } else if ((priv->video_width * priv->video_height) >= (960 * 540)) {
308       priv->video_bitrate = priv->decide_udp_bitrate[9];
309       priv->min_udp_bitrate = priv->decide_udp_bitrate[10];
310       priv->max_udp_bitrate = priv->decide_udp_bitrate[11];
311     } else if ((priv->video_width * priv->video_height) >= (854 * 480)) {
312       priv->video_bitrate = priv->decide_udp_bitrate[12];
313       priv->min_udp_bitrate = priv->decide_udp_bitrate[13];
314       priv->max_udp_bitrate = priv->decide_udp_bitrate[14];
315     } else if ((priv->video_width * priv->video_height) >= (640 * 480)) {
316       priv->video_bitrate = priv->decide_udp_bitrate[15];
317       priv->min_udp_bitrate = priv->decide_udp_bitrate[16];
318       priv->max_udp_bitrate = priv->decide_udp_bitrate[17];
319     }
320   }
321 }
322
323 void
324 gst_rtsp_media_factory_wfd_set_venc_bitrate (GstRTSPMediaFactory * factory,
325     gint bitrate)
326 {
327   GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory);
328   GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv;
329
330   g_object_set (priv->venc, "target-bitrate", bitrate, NULL);
331   priv->video_bitrate = (guint) bitrate;
332 }
333
334 void
335 gst_rtsp_media_factory_wfd_get_venc_bitrate (GstRTSPMediaFactory * factory,
336     gint * bitrate)
337 {
338   int cur_bitrate = 0;
339
340   GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory);
341   GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv;
342
343   g_object_get (priv->venc, "target-bitrate", &cur_bitrate, NULL);
344
345   if (cur_bitrate == 0) {
346     *bitrate = priv->video_bitrate;
347   } else {
348     *bitrate = (gint) cur_bitrate;
349   }
350 }
351
352 void
353 gst_rtsp_media_factory_wfd_get_config_bitrate (GstRTSPMediaFactory * factory,
354     guint32 * min, guint32 * max)
355 {
356   GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory);
357   GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv;
358
359   *min = priv->min_udp_bitrate;
360   *max = priv->max_udp_bitrate;
361 }
362
363 void
364 gst_rtsp_media_factory_wfd_set_config_bitrate (GstRTSPMediaFactoryWFD * factory,
365     guint * config_bitrate)
366 {
367   GstRTSPMediaFactoryWFDPrivate *priv = factory->priv;
368
369   gint idx = 0;
370   for (idx = 0; idx < 21; idx++) {
371     priv->decide_udp_bitrate[idx] = config_bitrate[idx];
372   }
373   priv->decided_udp_bitrate = TRUE;
374
375   _config_bitrate (factory);
376 }
377
378 static void
379 gst_rtsp_media_factory_wfd_init (GstRTSPMediaFactoryWFD * factory)
380 {
381   GstRTSPMediaFactoryWFDPrivate *priv =
382       GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory);
383   factory->priv = priv;
384
385   priv->launch = g_strdup (DEFAULT_LAUNCH);
386   priv->shared = DEFAULT_SHARED;
387   priv->protocols = DEFAULT_PROTOCOLS;
388   priv->buffer_size = DEFAULT_BUFFER_SIZE;
389
390   //priv->videosrc_type = GST_WFD_VSRC_XIMAGESRC;
391   //priv->videosrc_type = GST_WFD_VSRC_XVIMAGESRC;
392   //priv->videosrc_type = GST_WFD_VSRC_CAMERASRC;
393   priv->videosrc_type = GST_WFD_VSRC_VIDEOTESTSRC;
394   priv->video_codec = GST_WFD_VIDEO_H264;
395   priv->video_encoder = g_strdup ("omxh264enc");
396   priv->video_bitrate = 200000;
397   priv->video_width = 640;
398   priv->video_height = 480;
399   priv->video_framerate = 30;
400   priv->video_enc_skip_inbuf_value = 5;
401   priv->video_srcbin = NULL;
402   priv->min_udp_bitrate = 938861;
403   priv->max_udp_bitrate = 1572864;
404   priv->decided_udp_bitrate = FALSE;
405
406   priv->audio_device = g_strdup ("alsa_output.1.analog-stereo.monitor");
407   priv->audio_codec = GST_WFD_AUDIO_AAC;
408   priv->audio_encoder_aac = g_strdup ("avenc_aac");
409   priv->audio_encoder_ac3 = g_strdup ("avenc_ac3");
410   priv->audio_latency_time = 10000;
411   priv->audio_buffer_time = 200000;
412   priv->audio_do_timestamp = FALSE;
413   priv->audio_channels = GST_WFD_CHANNEL_2;
414   priv->audio_freq = GST_WFD_FREQ_48000;
415   priv->audio_srcbin = NULL;
416
417   g_mutex_init (&priv->direct_lock);
418   g_cond_init (&priv->direct_cond);
419
420   priv->discover_pipeline = NULL;
421   priv->direct_pipe = NULL;
422   memset (&priv->res, 0x00, sizeof (GstRTPSMediaWFDTypeFindResult));
423   priv->stream_bin = NULL;
424   priv->mux = NULL;
425   priv->mux_queue = NULL;
426   priv->pay = NULL;
427
428   g_mutex_init (&priv->lock);
429 }
430
431 static void
432 gst_rtsp_media_factory_wfd_finalize (GObject * obj)
433 {
434   GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (obj);
435   GstRTSPMediaFactoryWFDPrivate *priv = factory->priv;
436
437   if (priv->permissions)
438     gst_rtsp_permissions_unref (priv->permissions);
439   g_free (priv->launch);
440   g_mutex_clear (&priv->lock);
441
442   g_mutex_clear (&priv->direct_lock);
443   g_cond_clear (&priv->direct_cond);
444
445   if (priv->audio_device)
446     g_free (priv->audio_device);
447   if (priv->audio_encoder_aac)
448     g_free (priv->audio_encoder_aac);
449   if (priv->audio_encoder_ac3)
450     g_free (priv->audio_encoder_ac3);
451
452   if (priv->video_encoder)
453     g_free (priv->video_encoder);
454
455   G_OBJECT_CLASS (gst_rtsp_media_factory_wfd_parent_class)->finalize (obj);
456 }
457
458 GstRTSPMediaFactoryWFD *
459 gst_rtsp_media_factory_wfd_new (void)
460 {
461   GstRTSPMediaFactoryWFD *result;
462
463   result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY_WFD, NULL);
464
465   return result;
466 }
467
468 static void
469 gst_rtsp_media_factory_wfd_get_property (GObject * object,
470     guint propid, GValue * value, GParamSpec * pspec)
471 {
472   //GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (object);
473
474   switch (propid) {
475     default:
476       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
477   }
478 }
479
480 static void
481 gst_rtsp_media_factory_wfd_set_property (GObject * object,
482     guint propid, const GValue * value, GParamSpec * pspec)
483 {
484   //GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (object);
485
486   switch (propid) {
487     default:
488       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
489   }
490 }
491
492 static GstPadProbeReturn
493 rtsp_media_wfd_dump_data (GstPad * pad, GstPadProbeInfo * info, gpointer u_data)
494 {
495   guint8 *data;
496   gsize size;
497   FILE *f;
498   GstMapInfo mapinfo;
499
500   if (info->type == (GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH)) {
501     GstBuffer *buffer = gst_pad_probe_info_get_buffer (info);
502
503     gst_buffer_map (buffer, &mapinfo, GST_MAP_READ);
504     data = mapinfo.data;
505     size = gst_buffer_get_size (buffer);
506
507     f = fopen ("/root/probe.ts", "a");
508     if (f != NULL) {
509       fwrite (data, size, 1, f);
510       fclose (f);
511     }
512     gst_buffer_unmap (buffer, &mapinfo);
513   }
514
515   return GST_PAD_PROBE_OK;
516 }
517
518 static gboolean
519 _rtsp_media_factory_wfd_create_audio_capture_bin (GstRTSPMediaFactoryWFD *
520     factory, GstBin * srcbin)
521 {
522   GstElement *audiosrc = NULL;
523   GstElement *acaps = NULL;
524   GstElement *acaps2 = NULL;
525   GstElement *aenc = NULL;
526   GstElement *audio_convert = NULL;
527   GstElement *aqueue = NULL;
528   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
529   GstStructure *audio_properties_name = NULL;
530
531   guint channels = 0;
532   gboolean is_enc_req = TRUE;
533   guint freq = 0;
534   g_autofree gchar *acodec = NULL;
535
536   priv = factory->priv;
537
538   if (priv->audio_codec == GST_WFD_AUDIO_UNKNOWN) {
539     GST_INFO_OBJECT (factory, "Skip create audio source");
540     return TRUE;
541   }
542
543   priv->audio_srcbin = (GstBin *)gst_bin_new ("audio");
544
545   /* create audio src element */
546   audiosrc = gst_element_factory_make ("pulsesrc", "audiosrc");
547   if (!audiosrc) {
548     GST_ERROR_OBJECT (factory, "failed to create audiosrc element");
549     goto create_error;
550   }
551
552   GST_INFO_OBJECT (factory, "audio device : %s", priv->audio_device);
553   GST_INFO_OBJECT (factory, "audio latency time  : %"G_GUINT64_FORMAT,
554       priv->audio_latency_time);
555   GST_INFO_OBJECT (factory, "audio_buffer_time  : %"G_GUINT64_FORMAT,
556       priv->audio_buffer_time);
557   GST_INFO_OBJECT (factory, "audio_do_timestamp  : %d",
558       priv->audio_do_timestamp);
559
560   audio_properties_name = gst_structure_new_from_string (priv->audio_device);
561
562   g_object_set (audiosrc, "stream-properties", audio_properties_name, NULL);
563   g_object_set (audiosrc, "buffer-time", (gint64) priv->audio_buffer_time,
564       NULL);
565   g_object_set (audiosrc, "latency-time", (gint64) priv->audio_latency_time,
566       NULL);
567   g_object_set (audiosrc, "do-timestamp", (gboolean) priv->audio_do_timestamp,
568       NULL);
569   g_object_set (audiosrc, "provide-clock", (gboolean) FALSE, NULL);
570   g_object_set (audiosrc, "is-live", (gboolean) TRUE, NULL);
571
572   if (priv->audio_codec == GST_WFD_AUDIO_LPCM) {
573     /* To meet miracast certification */
574     gint64 block_size = 1920;
575     g_object_set (audiosrc, "blocksize", (gint64) block_size, NULL);
576
577     audio_convert = gst_element_factory_make ("capssetter", "audio_convert");
578     if (NULL == audio_convert) {
579       GST_ERROR_OBJECT (factory, "failed to create audio convert element");
580       goto create_error;
581     }
582     g_object_set (audio_convert, "caps", gst_caps_new_simple ("audio/x-lpcm",
583             "width", G_TYPE_INT, 16,
584             "rate", G_TYPE_INT, 48000,
585             "channels", G_TYPE_INT, 2,
586             "dynamic_range", G_TYPE_INT, 0,
587             "emphasis", G_TYPE_BOOLEAN, FALSE,
588             "mute", G_TYPE_BOOLEAN, FALSE, NULL), NULL);
589     g_object_set (audio_convert, "join", (gboolean) FALSE, NULL);
590     g_object_set (audio_convert, "replace", (gboolean) TRUE, NULL);
591
592     acaps2 = gst_element_factory_make ("capsfilter", "audiocaps2");
593     if (NULL == acaps2) {
594       GST_ERROR_OBJECT (factory, "failed to create audio capsilfter element");
595       goto create_error;
596     }
597     /* In case of LPCM, uses big endian */
598     g_object_set (G_OBJECT (acaps2), "caps",
599         gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16BE",
600             /* In case of LPCM, uses big endian */
601             "rate", G_TYPE_INT, 48000,
602             "channels", G_TYPE_INT, 2, NULL), NULL);
603   }
604
605   /* create audio caps element */
606   acaps = gst_element_factory_make ("capsfilter", "audiocaps");
607   if (NULL == acaps) {
608     GST_ERROR_OBJECT (factory, "failed to create audio capsilfter element");
609     goto create_error;
610   }
611
612   if (priv->audio_channels == GST_WFD_CHANNEL_2)
613     channels = 2;
614   else if (priv->audio_channels == GST_WFD_CHANNEL_4)
615     channels = 4;
616   else if (priv->audio_channels == GST_WFD_CHANNEL_6)
617     channels = 6;
618   else if (priv->audio_channels == GST_WFD_CHANNEL_8)
619     channels = 8;
620   else
621     channels = 2;
622
623   if (priv->audio_freq == GST_WFD_FREQ_44100)
624     freq = 44100;
625   else if (priv->audio_freq == GST_WFD_FREQ_48000)
626     freq = 48000;
627   else
628     freq = 44100;
629
630   if (priv->audio_codec == GST_WFD_AUDIO_LPCM) {
631     g_object_set (G_OBJECT (acaps), "caps",
632         gst_caps_new_simple ("audio/x-lpcm", "width", G_TYPE_INT, 16,
633             "rate", G_TYPE_INT, 48000,
634             "channels", G_TYPE_INT, 2,
635             "dynamic_range", G_TYPE_INT, 0,
636             "emphasis", G_TYPE_BOOLEAN, FALSE,
637             "mute", G_TYPE_BOOLEAN, FALSE, NULL), NULL);
638   } else if ((priv->audio_codec == GST_WFD_AUDIO_AAC)
639       || (priv->audio_codec == GST_WFD_AUDIO_AC3)) {
640     g_object_set (G_OBJECT (acaps), "caps", gst_caps_new_simple ("audio/x-raw",
641             "endianness", G_TYPE_INT, 1234, "signed", G_TYPE_BOOLEAN, TRUE,
642             "depth", G_TYPE_INT, 16, "rate", G_TYPE_INT, freq, "channels",
643             G_TYPE_INT, channels, NULL), NULL);
644   }
645
646   if (priv->audio_codec == GST_WFD_AUDIO_AAC) {
647     acodec = g_strdup (priv->audio_encoder_aac);
648     is_enc_req = TRUE;
649   } else if (priv->audio_codec == GST_WFD_AUDIO_AC3) {
650     acodec = g_strdup (priv->audio_encoder_ac3);
651     is_enc_req = TRUE;
652   } else if (priv->audio_codec == GST_WFD_AUDIO_LPCM) {
653     GST_DEBUG_OBJECT (factory, "No codec required, raw data will be sent");
654     is_enc_req = FALSE;
655   } else {
656     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
657     goto create_error;
658   }
659
660   if (is_enc_req) {
661     aenc = gst_element_factory_make (acodec, "audioenc");
662     if (NULL == aenc) {
663       GST_ERROR_OBJECT (factory, "failed to create audio encoder element");
664       goto create_error;
665     }
666
667     g_object_set (aenc, "compliance", -2, NULL);
668     g_object_set (aenc, "tolerance", 400000000, NULL);
669     g_object_set (aenc, "bitrate", (guint) 128000, NULL);
670     g_object_set (aenc, "rate-control", 2, NULL);
671
672     aqueue = gst_element_factory_make ("queue", "audio-queue");
673     if (!aqueue) {
674       GST_ERROR_OBJECT (factory, "failed to create audio queue element");
675       goto create_error;
676     }
677
678     gst_bin_add_many (priv->audio_srcbin, audiosrc, acaps, aenc, aqueue, NULL);
679     gst_bin_add (srcbin, GST_ELEMENT (priv->audio_srcbin));
680
681     if (!gst_element_link_many (audiosrc, acaps, aenc, aqueue, NULL)) {
682       GST_ERROR_OBJECT (factory, "Failed to link audio src elements...");
683       goto create_error;
684     }
685   } else {
686     aqueue = gst_element_factory_make ("queue", "audio-queue");
687     if (!aqueue) {
688       GST_ERROR_OBJECT (factory, "failed to create audio queue element");
689       goto create_error;
690     }
691
692     gst_bin_add_many (priv->audio_srcbin, audiosrc, acaps2, audio_convert, acaps, aqueue, NULL);
693     gst_bin_add (srcbin, GST_ELEMENT (priv->audio_srcbin));
694
695     if (!gst_element_link_many (audiosrc, acaps2, audio_convert, acaps, aqueue,
696             NULL)) {
697       GST_ERROR_OBJECT (factory, "Failed to link audio src elements...");
698       goto create_error;
699     }
700   }
701
702   priv->audio_queue = aqueue;
703   if (audio_properties_name)
704     gst_structure_free (audio_properties_name);
705   return TRUE;
706
707 create_error:
708   gst_object_unref (acaps);
709   gst_object_unref (aqueue);
710   if (audio_properties_name)
711     gst_structure_free (audio_properties_name);
712   return FALSE;
713 }
714
715 static gboolean
716 _rtsp_media_factory_wfd_create_videotest_bin (GstRTSPMediaFactoryWFD * factory,
717     GstBin * srcbin)
718 {
719   GstElement *videosrc = NULL;
720   GstElement *vcaps = NULL;
721   GstElement *videoconvert = NULL;
722   GstElement *venc_caps = NULL;
723   GstElement *venc = NULL;
724   GstElement *vparse = NULL;
725   GstElement *vqueue = NULL;
726   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
727
728   priv = factory->priv;
729
730   GST_INFO_OBJECT (factory, "picked videotestsrc as video source");
731   priv->video_srcbin = (GstBin *)gst_bin_new ("video");
732
733   videosrc = gst_element_factory_make ("videotestsrc", "videosrc");
734   if (NULL == videosrc) {
735     GST_ERROR_OBJECT (factory, "failed to create ximagesrc element");
736     goto create_error;
737   }
738
739   /* create video caps element */
740   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
741   if (NULL == vcaps) {
742     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
743     goto create_error;
744   }
745
746   g_object_set (G_OBJECT (vcaps), "caps",
747       gst_caps_new_simple ("video/x-raw",
748           "format", G_TYPE_STRING, "I420",
749           "width", G_TYPE_INT, priv->video_width,
750           "height", G_TYPE_INT, priv->video_height,
751           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
752       NULL);
753
754   /* create video convert element */
755   videoconvert = gst_element_factory_make ("videoconvert", "videoconvert");
756   if (NULL == videoconvert) {
757     GST_ERROR_OBJECT (factory, "failed to create video videoconvert element");
758     goto create_error;
759   }
760
761   venc_caps = gst_element_factory_make ("capsfilter", "venc_caps");
762   if (NULL == venc_caps) {
763     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
764     goto create_error;
765   }
766
767   g_object_set (G_OBJECT (venc_caps), "caps",
768       gst_caps_new_simple ("video/x-raw",
769           "format", G_TYPE_STRING, "SN12",
770           "width", G_TYPE_INT, priv->video_width,
771           "height", G_TYPE_INT, priv->video_height,
772           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
773       NULL);
774
775   if (priv->video_codec != GST_WFD_VIDEO_H264) {
776     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
777     goto create_error;
778   }
779
780   venc = gst_element_factory_make (priv->video_encoder, "videoenc");
781   if (!venc) {
782     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
783     goto create_error;
784   }
785
786   g_object_set (venc, "aud", 0, NULL);
787   g_object_set (venc, "byte-stream", 1, NULL);
788   g_object_set (venc, "bitrate", 512, NULL);
789
790   vparse = gst_element_factory_make ("h264parse", "videoparse");
791   if (NULL == vparse) {
792     GST_ERROR_OBJECT (factory, "failed to create h264 parse element");
793     goto create_error;
794   }
795   g_object_set (vparse, "config-interval", 1, NULL);
796
797   vqueue = gst_element_factory_make ("queue", "video-queue");
798   if (!vqueue) {
799     GST_ERROR_OBJECT (factory, "failed to create video queue element");
800     goto create_error;
801   }
802
803   gst_bin_add_many (priv->video_srcbin, videosrc, vcaps, videoconvert, venc_caps, venc, vparse, vqueue, NULL);
804   gst_bin_add (srcbin, GST_ELEMENT (priv->video_srcbin));
805   if (!gst_element_link_many (videosrc, vcaps, videoconvert, venc_caps, venc,
806           vparse, vqueue, NULL)) {
807     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
808     goto create_error;
809   }
810
811   priv->video_queue = vqueue;
812   priv->venc = venc;
813
814   return TRUE;
815
816 create_error:
817   gst_object_unref(videosrc);
818   gst_object_unref(vcaps);
819   gst_object_unref(videoconvert);
820   gst_object_unref(venc_caps);
821   gst_object_unref(venc);
822   gst_object_unref(vparse);
823   gst_object_unref(vqueue);
824   return FALSE;
825 }
826
827 static gboolean
828 _rtsp_media_factory_wfd_create_waylandsrc_bin (GstRTSPMediaFactoryWFD * factory,
829     GstBin * srcbin)
830 {
831   GstElement *videosrc = NULL;
832   GstElement *vcaps = NULL;
833   GstElement *venc = NULL;
834   GstElement *vparse = NULL;
835   GstElement *vqueue = NULL;
836   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
837
838   priv = factory->priv;
839
840   GST_INFO_OBJECT (factory, "picked waylandsrc as video source");
841
842   if (priv->video_codec == GST_WFD_VIDEO_UNKNOWN) {
843     GST_INFO_OBJECT (factory, "Skip create video source.");
844     return TRUE;
845   }
846
847   priv->video_srcbin = (GstBin *)gst_bin_new ("video");
848
849   videosrc = gst_element_factory_make ("waylandsrc", "videosrc");
850   if (NULL == videosrc) {
851     GST_ERROR_OBJECT (factory, "failed to create ximagesrc element");
852     goto create_error;
853   }
854
855   /* create video caps element */
856   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
857   if (NULL == vcaps) {
858     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
859     goto create_error;
860   }
861
862   g_object_set (G_OBJECT (vcaps), "caps",
863       gst_caps_new_simple ("video/x-raw",
864           "format", G_TYPE_STRING, "SN12",
865           "width", G_TYPE_INT, priv->video_width,
866           "height", G_TYPE_INT, priv->video_height,
867           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
868       NULL);
869
870   if (priv->video_codec != GST_WFD_VIDEO_H264) {
871     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
872     goto create_error;
873   }
874
875   venc = gst_element_factory_make (priv->video_encoder, "videoenc");
876   if (!venc) {
877     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
878     goto create_error;
879   }
880
881   g_object_set (venc, "aud", 0, NULL);
882   g_object_set (venc, "byte-stream", 1, NULL);
883   g_object_set (venc, "bitrate", 512, NULL);
884   g_object_set (venc, "target-bitrate", priv->video_bitrate, NULL);
885
886   vparse = gst_element_factory_make ("h264parse", "videoparse");
887   if (NULL == vparse) {
888     GST_ERROR_OBJECT (factory, "failed to create h264 parse element");
889     goto create_error;
890   }
891   g_object_set (vparse, "config-interval", 1, NULL);
892
893   vqueue = gst_element_factory_make ("queue", "video-queue");
894   if (!vqueue) {
895     GST_ERROR_OBJECT (factory, "failed to create video queue element");
896     goto create_error;
897   }
898
899   gst_bin_add_many (priv->video_srcbin, videosrc, vcaps, venc, vparse, vqueue, NULL);
900   gst_bin_add (srcbin, GST_ELEMENT (priv->video_srcbin));
901   if (!gst_element_link_many (videosrc, vcaps, venc, vparse, vqueue, NULL)) {
902     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
903     goto create_error;
904   }
905
906   priv->video_queue = vqueue;
907   priv->venc = venc;
908
909   return TRUE;
910
911 create_error:
912   gst_object_unref (videosrc);
913   gst_object_unref (vqueue);
914   return FALSE;
915 }
916
917 static gboolean
918 _rtsp_media_factory_wfd_create_camera_capture_bin (GstRTSPMediaFactoryWFD *
919     factory, GstBin * srcbin)
920 {
921   GstElement *videosrc = NULL;
922   GstElement *vcaps = NULL;
923   GstElement *venc = NULL;
924   GstElement *vparse = NULL;
925   GstElement *vqueue = NULL;
926   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
927
928   priv = factory->priv;
929   priv->video_srcbin = (GstBin *)gst_bin_new ("video");
930
931   videosrc = gst_element_factory_make ("camerasrc", "videosrc");
932   if (NULL == videosrc) {
933     GST_ERROR_OBJECT (factory, "failed to create camerasrc element");
934     goto create_error;
935   }
936
937   /* create video caps element */
938   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
939   if (NULL == vcaps) {
940     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
941     goto create_error;
942   }
943
944   GST_INFO_OBJECT (factory, "picked camerasrc as video source");
945   g_object_set (G_OBJECT (vcaps), "caps",
946       gst_caps_new_simple ("video/x-raw",
947           "width", G_TYPE_INT, priv->video_width,
948           "height", G_TYPE_INT, priv->video_height,
949           "format", G_TYPE_STRING, "SN12",
950           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
951       NULL);
952
953   if (priv->video_codec != GST_WFD_VIDEO_H264) {
954     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
955     goto create_error;
956   }
957
958   venc = gst_element_factory_make (priv->video_encoder, "videoenc");
959   if (!venc) {
960     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
961     goto create_error;
962   }
963
964   g_object_set (venc, "bitrate", priv->video_bitrate, NULL);
965   g_object_set (venc, "byte-stream", 1, NULL);
966   g_object_set (venc, "append-dci", 1, NULL);
967
968   vparse = gst_element_factory_make ("h264parse", "videoparse");
969   if (NULL == vparse) {
970     GST_ERROR_OBJECT (factory, "failed to create h264 parse element");
971     goto create_error;
972   }
973   g_object_set (vparse, "config-interval", 1, NULL);
974
975   vqueue = gst_element_factory_make ("queue", "video-queue");
976   if (!vqueue) {
977     GST_ERROR_OBJECT (factory, "failed to create video queue element");
978     goto create_error;
979   }
980
981   gst_bin_add_many (priv->video_srcbin, videosrc, vcaps, venc, vparse, vqueue, NULL);
982   gst_bin_add (srcbin, GST_ELEMENT (priv->video_srcbin));
983
984   if (!gst_element_link_many (videosrc, vcaps, venc, vparse, vqueue, NULL)) {
985     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
986     goto create_error;
987   }
988
989   priv->video_queue = vqueue;
990   priv->venc = venc;
991
992   return TRUE;
993
994 create_error:
995   gst_object_unref (videosrc);
996   gst_object_unref (vqueue);
997   return FALSE;
998 }
999
1000 static gboolean
1001 _rtsp_media_factory_wfd_create_xcapture_bin (GstRTSPMediaFactoryWFD * factory,
1002     GstBin * srcbin)
1003 {
1004   GstElement *videosrc = NULL;
1005   GstElement *vcaps = NULL;
1006   GstElement *venc_caps = NULL;
1007   GstElement *videoconvert = NULL, *videoscale = NULL;
1008   GstElement *venc = NULL;
1009   GstElement *vparse = NULL;
1010   GstElement *vqueue = NULL;
1011   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1012
1013   priv = factory->priv;
1014
1015   GST_INFO_OBJECT (factory, "picked ximagesrc as video source");
1016   priv->video_srcbin = (GstBin *)gst_bin_new ("video");
1017
1018   videosrc = gst_element_factory_make ("ximagesrc", "videosrc");
1019   if (NULL == videosrc) {
1020     GST_ERROR_OBJECT (factory, "failed to create ximagesrc element");
1021     goto create_error;
1022   }
1023
1024   videoscale = gst_element_factory_make ("videoscale", "videoscale");
1025   if (NULL == videoscale) {
1026     GST_ERROR_OBJECT (factory, "failed to create videoscale element");
1027     goto create_error;
1028   }
1029
1030   videoconvert = gst_element_factory_make ("videoconvert", "videoconvert");
1031   if (NULL == videoconvert) {
1032     GST_ERROR_OBJECT (factory, "failed to create videoconvert element");
1033     goto create_error;
1034   }
1035
1036   /* create video caps element */
1037   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
1038   if (NULL == vcaps) {
1039     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
1040     goto create_error;
1041   }
1042
1043   g_object_set (G_OBJECT (vcaps), "caps",
1044       gst_caps_new_simple ("video/x-raw",
1045           "width", G_TYPE_INT, priv->video_width,
1046           "height", G_TYPE_INT, priv->video_height,
1047           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
1048       NULL);
1049
1050   if (priv->video_codec != GST_WFD_VIDEO_H264) {
1051     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
1052     goto create_error;
1053   }
1054
1055   venc = gst_element_factory_make (priv->video_encoder, "videoenc");
1056   if (!venc) {
1057     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
1058     goto create_error;
1059   }
1060
1061   g_object_set (venc, "aud", 0, NULL);
1062   g_object_set (venc, "byte-stream", 1, NULL);
1063   g_object_set (venc, "bitrate", 512, NULL);
1064
1065   venc_caps = gst_element_factory_make ("capsfilter", "venc_caps");
1066   if (NULL == venc_caps) {
1067     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
1068     goto create_error;
1069   }
1070
1071   g_object_set (G_OBJECT (venc_caps), "caps",
1072       gst_caps_new_simple ("video/x-h264",
1073           "profile", G_TYPE_STRING, "baseline", NULL), NULL);
1074
1075   vparse = gst_element_factory_make ("h264parse", "videoparse");
1076   if (NULL == vparse) {
1077     GST_ERROR_OBJECT (factory, "failed to create h264 parse element");
1078     goto create_error;
1079   }
1080   g_object_set (vparse, "config-interval", 1, NULL);
1081
1082   vqueue = gst_element_factory_make ("queue", "video-queue");
1083   if (!vqueue) {
1084     GST_ERROR_OBJECT (factory, "failed to create video queue element");
1085     goto create_error;
1086   }
1087
1088   gst_bin_add_many (priv->video_srcbin, videosrc, videoscale, videoconvert, vcaps, venc,
1089       venc_caps, vparse, vqueue, NULL);
1090   gst_bin_add (srcbin, GST_ELEMENT (priv->video_srcbin));
1091   if (!gst_element_link_many (videosrc, videoscale, videoconvert, vcaps, venc,
1092           venc_caps, vparse, vqueue, NULL)) {
1093     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
1094     goto create_error;
1095   }
1096
1097   priv->video_queue = vqueue;
1098   priv->venc = venc;
1099
1100   return TRUE;
1101
1102 create_error:
1103   gst_object_unref(videosrc);
1104   gst_object_unref(vcaps);
1105   gst_object_unref(venc_caps);
1106   gst_object_unref(videoconvert);
1107   gst_object_unref(videoscale);
1108   gst_object_unref(venc);
1109   gst_object_unref(vparse);
1110   gst_object_unref(vqueue);
1111   return FALSE;
1112 }
1113
1114 static gboolean
1115 _rtsp_media_factory_wfd_create_xvcapture_bin (GstRTSPMediaFactoryWFD * factory,
1116     GstBin * srcbin)
1117 {
1118   GstElement *videosrc = NULL;
1119   GstElement *vcaps = NULL;
1120   GstElement *venc = NULL;
1121   GstElement *vparse = NULL;
1122   GstElement *vqueue = NULL;
1123   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1124
1125   priv = factory->priv;
1126
1127   GST_INFO_OBJECT (factory, "picked xvimagesrc as video source");
1128   priv->video_srcbin = (GstBin *)gst_bin_new ("video");
1129
1130   videosrc = gst_element_factory_make ("xvimagesrc", "videosrc");
1131   if (NULL == videosrc) {
1132     GST_ERROR_OBJECT (factory, "failed to create xvimagesrc element");
1133     goto create_error;
1134   }
1135
1136   /* create video caps element */
1137   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
1138   if (NULL == vcaps) {
1139     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
1140     goto create_error;
1141   }
1142
1143   g_object_set (G_OBJECT (vcaps), "caps",
1144       gst_caps_new_simple ("video/x-raw",
1145           "width", G_TYPE_INT, priv->video_width,
1146           "height", G_TYPE_INT, priv->video_height,
1147           "format", G_TYPE_STRING, "SN12",
1148           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
1149       NULL);
1150
1151   if (priv->video_codec != GST_WFD_VIDEO_H264) {
1152     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
1153     goto create_error;
1154   }
1155
1156   venc = gst_element_factory_make (priv->video_encoder, "videoenc");
1157   if (!venc) {
1158     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
1159     goto create_error;
1160   }
1161   g_object_set (venc, "bitrate", priv->video_bitrate, NULL);
1162   g_object_set (venc, "byte-stream", 1, NULL);
1163   g_object_set (venc, "append-dci", 1, NULL);
1164   g_object_set (venc, "idr-period", 120, NULL);
1165   g_object_set (venc, "skip-inbuf", priv->video_enc_skip_inbuf_value, NULL);
1166
1167   vparse = gst_element_factory_make ("h264parse", "videoparse");
1168   if (NULL == vparse) {
1169     GST_ERROR_OBJECT (factory, "failed to create h264 parse element");
1170     goto create_error;
1171   }
1172   g_object_set (vparse, "config-interval", 1, NULL);
1173
1174   vqueue = gst_element_factory_make ("queue", "video-queue");
1175   if (!vqueue) {
1176     GST_ERROR_OBJECT (factory, "failed to create video queue element");
1177     goto create_error;
1178   }
1179
1180   gst_bin_add_many (priv->video_srcbin, videosrc, vcaps, venc, vparse, vqueue, NULL);
1181   gst_bin_add (srcbin, GST_ELEMENT (priv->video_srcbin));
1182   if (!gst_element_link_many (videosrc, vcaps, venc, vparse, vqueue, NULL)) {
1183     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
1184     goto create_error;
1185   }
1186
1187   priv->video_queue = vqueue;
1188   priv->venc = venc;
1189
1190   return TRUE;
1191
1192 create_error:
1193   gst_object_unref (videosrc);
1194   gst_object_unref (vqueue);
1195
1196   return FALSE;
1197 }
1198
1199 static GstElement *
1200 _rtsp_media_factory_wfd_create_srcbin (GstRTSPMediaFactoryWFD * factory)
1201 {
1202   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1203
1204   GstBin *srcbin = NULL;
1205   GstElement *mux = NULL;
1206   GstElement *mux_queue = NULL;
1207   GstElement *payload = NULL;
1208   GstPad *srcpad = NULL;
1209   GstPad *mux_vsinkpad = NULL;
1210   GstPad *mux_asinkpad = NULL;
1211   GstPad *ghost_pad = NULL;
1212
1213   priv = factory->priv;
1214
1215   /* create source bin */
1216   srcbin = GST_BIN (gst_bin_new ("srcbin"));
1217   if (!srcbin) {
1218     GST_ERROR_OBJECT (factory, "failed to create source bin...");
1219     goto create_error;
1220   }
1221
1222   GST_INFO_OBJECT (factory, "Check video codec... %d", priv->video_codec);
1223   /* create video src element */
1224   switch (priv->videosrc_type) {
1225     case GST_WFD_VSRC_XIMAGESRC:
1226       if (!_rtsp_media_factory_wfd_create_xcapture_bin (factory, srcbin)) {
1227         GST_ERROR_OBJECT (factory, "failed to create xcapture bin...");
1228         goto create_error;
1229       }
1230       break;
1231     case GST_WFD_VSRC_XVIMAGESRC:
1232       if (!_rtsp_media_factory_wfd_create_xvcapture_bin (factory, srcbin)) {
1233         GST_ERROR_OBJECT (factory, "failed to create xvcapture bin...");
1234         goto create_error;
1235       }
1236       break;
1237     case GST_WFD_VSRC_CAMERASRC:
1238       if (!_rtsp_media_factory_wfd_create_camera_capture_bin (factory, srcbin)) {
1239         GST_ERROR_OBJECT (factory, "failed to create camera capture bin...");
1240         goto create_error;
1241       }
1242       break;
1243     case GST_WFD_VSRC_VIDEOTESTSRC:
1244       if (!_rtsp_media_factory_wfd_create_videotest_bin (factory, srcbin)) {
1245         GST_ERROR_OBJECT (factory, "failed to create videotestsrc bin...");
1246         goto create_error;
1247       }
1248       break;
1249     case GST_WFD_VSRC_WAYLANDSRC:
1250       if (!_rtsp_media_factory_wfd_create_waylandsrc_bin (factory, srcbin)) {
1251         GST_ERROR_OBJECT (factory, "failed to create videotestsrc bin...");
1252         goto create_error;
1253       }
1254       break;
1255     default:
1256       GST_ERROR_OBJECT (factory, "unknow mode selected...");
1257       goto create_error;
1258   }
1259
1260   mux = gst_element_factory_make ("mpegtsmux", "tsmux");
1261   if (!mux) {
1262     GST_ERROR_OBJECT (factory, "failed to create muxer element");
1263     goto create_error;
1264   }
1265
1266   g_object_set (mux, "wfd-mode", TRUE, NULL);
1267
1268   mux_queue = gst_element_factory_make ("queue", "muxer-queue");
1269   if (!mux_queue) {
1270     GST_ERROR_OBJECT (factory, "failed to create muxer-queue element");
1271     goto create_error;
1272   }
1273
1274   g_object_set (mux_queue, "max-size-buffers", 20000, NULL);
1275
1276   payload = gst_element_factory_make ("rtpmp2tpay", "pay0");
1277   if (!payload) {
1278     GST_ERROR_OBJECT (factory, "failed to create payload element");
1279     goto create_error;
1280   }
1281
1282   g_object_set (payload, "pt", 33, NULL);
1283   g_object_set (payload, "mtu", priv->mtu_size, NULL);
1284   g_object_set (payload, "rtp-flush", (gboolean) TRUE, NULL);
1285
1286   gst_bin_add_many (srcbin, mux, mux_queue, payload, NULL);
1287
1288   if (!gst_element_link_many (mux, mux_queue, payload, NULL)) {
1289     GST_ERROR_OBJECT (factory, "Failed to link muxer & payload...");
1290     goto create_error;
1291   }
1292
1293   if (priv->video_codec > GST_WFD_VIDEO_UNKNOWN) {
1294     /* request video sink pad from muxer, which has elementary pid 0x1011 */
1295     mux_vsinkpad = gst_element_get_request_pad (mux, "sink_4113");
1296     if (!mux_vsinkpad) {
1297       GST_ERROR_OBJECT (factory, "Failed to get sink pad from muxer...");
1298       goto create_error;
1299     }
1300
1301     /* request srcpad from video queue */
1302     srcpad = gst_element_get_static_pad (priv->video_queue, "src");
1303     if (!srcpad) {
1304       GST_ERROR_OBJECT (factory, "Failed to get srcpad from video queue...");
1305       goto create_error;
1306     }
1307   ghost_pad = gst_ghost_pad_new ("video_src", srcpad);
1308   gst_element_add_pad (GST_ELEMENT (priv->video_srcbin), ghost_pad);
1309
1310   if (gst_pad_link (ghost_pad, mux_vsinkpad) != GST_PAD_LINK_OK) {
1311       GST_ERROR_OBJECT (factory,
1312           "Failed to link video queue src pad & muxer video sink pad...");
1313       goto create_error;
1314     }
1315
1316     gst_object_unref (mux_vsinkpad);
1317     gst_object_unref (srcpad);
1318     srcpad = NULL;
1319   ghost_pad = NULL;
1320   }
1321
1322   GST_INFO_OBJECT (factory, "Check audio codec... %d", priv->audio_codec);
1323
1324   /* create audio source elements & add to pipeline */
1325   if (!_rtsp_media_factory_wfd_create_audio_capture_bin (factory, srcbin))
1326     goto create_error;
1327
1328   if (priv->audio_codec > GST_WFD_AUDIO_UNKNOWN) {
1329     /* request audio sink pad from muxer, which has elementary pid 0x1100 */
1330     mux_asinkpad = gst_element_get_request_pad (mux, "sink_4352");
1331     if (!mux_asinkpad) {
1332       GST_ERROR_OBJECT (factory, "Failed to get sinkpad from muxer...");
1333       goto create_error;
1334     }
1335
1336     /* request srcpad from audio queue */
1337     srcpad = gst_element_get_static_pad (priv->audio_queue, "src");
1338     if (!srcpad) {
1339       GST_ERROR_OBJECT (factory, "Failed to get srcpad from audio queue...");
1340       goto create_error;
1341     }
1342   ghost_pad = gst_ghost_pad_new ("audio_src", srcpad);
1343   gst_element_add_pad (GST_ELEMENT (priv->audio_srcbin), ghost_pad);
1344
1345     /* link audio queue's srcpad & muxer sink pad */
1346   if (gst_pad_link (ghost_pad, mux_asinkpad) != GST_PAD_LINK_OK) {
1347       GST_ERROR_OBJECT (factory,
1348           "Failed to link audio queue src pad & muxer audio sink pad...");
1349       goto create_error;
1350     }
1351     gst_object_unref (mux_asinkpad);
1352     gst_object_unref (srcpad);
1353   }
1354
1355   if (priv->dump_ts)
1356   {
1357     GstPad *pad_probe = NULL;
1358     pad_probe = gst_element_get_static_pad (mux, "src");
1359
1360     if (NULL == pad_probe) {
1361       GST_INFO_OBJECT (factory, "pad for probe not created");
1362     } else {
1363       GST_INFO_OBJECT (factory, "pad for probe SUCCESSFUL");
1364     }
1365     gst_pad_add_probe (pad_probe, GST_PAD_PROBE_TYPE_BUFFER,
1366         rtsp_media_wfd_dump_data, factory, NULL);
1367     if (pad_probe)
1368       gst_object_unref (pad_probe);
1369   }
1370
1371   GST_DEBUG_OBJECT (factory, "successfully created source bin...");
1372
1373   priv->stream_bin = srcbin;
1374   priv->mux = gst_object_ref (mux);
1375   priv->mux_queue = gst_object_ref (mux_queue);
1376   priv->pay = gst_object_ref (payload);
1377
1378   return GST_ELEMENT_CAST (srcbin);
1379
1380 create_error:
1381   GST_ERROR_OBJECT (factory, "Failed to create pipeline");
1382   if (mux_vsinkpad)
1383     gst_object_unref (mux_vsinkpad);
1384   if (mux_asinkpad)
1385     gst_object_unref (mux_asinkpad);
1386   if (srcpad)
1387     gst_object_unref (srcpad);
1388   if (srcbin)
1389     gst_object_unref (srcbin);
1390   return NULL;
1391 }
1392
1393 static GstElement *
1394 rtsp_media_factory_wfd_create_element (GstRTSPMediaFactory * factory,
1395     const GstRTSPUrl * url)
1396 {
1397   GstRTSPMediaFactoryWFD *_factory = GST_RTSP_MEDIA_FACTORY_WFD_CAST (factory);
1398   GstElement *element = NULL;
1399
1400   GST_RTSP_MEDIA_FACTORY_WFD_LOCK (factory);
1401
1402   element = _rtsp_media_factory_wfd_create_srcbin (_factory);
1403
1404   GST_RTSP_MEDIA_FACTORY_WFD_UNLOCK (factory);
1405
1406   return element;
1407 }
1408
1409 static GstRTSPMedia *
1410 rtsp_media_factory_wfd_construct (GstRTSPMediaFactory * factory,
1411     const GstRTSPUrl * url)
1412 {
1413   GstRTSPMedia *media;
1414   GstElement *element, *pipeline;
1415   GstRTSPMediaFactoryClass *klass;
1416
1417   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
1418
1419   if (!klass->create_pipeline)
1420     goto no_create;
1421
1422   element = gst_rtsp_media_factory_create_element (factory, url);
1423   if (element == NULL)
1424     goto no_element;
1425
1426   /* create a new empty media */
1427   media = gst_rtsp_media_new (element);
1428   //media = g_object_new (GST_TYPE_RTSP_MEDIA_EXT, "element", element, NULL);
1429
1430   gst_rtsp_media_collect_streams (media);
1431
1432   pipeline = klass->create_pipeline (factory, media);
1433   if (pipeline == NULL)
1434     goto no_pipeline;
1435
1436   return media;
1437
1438   /* ERRORS */
1439 no_create:
1440   {
1441     g_critical ("no create_pipeline function");
1442     return NULL;
1443   }
1444 no_element:
1445   {
1446     g_critical ("could not create element");
1447     return NULL;
1448   }
1449 no_pipeline:
1450   {
1451     g_critical ("can't create pipeline");
1452     g_object_unref (media);
1453     return NULL;
1454   }
1455 }
1456
1457 gint type_detected = FALSE;
1458 gint linked = FALSE;
1459 static gint in_pad_probe;
1460
1461 static GstPadProbeReturn
1462 _rtsp_media_factory_wfd_restore_pipe_probe_cb (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
1463 {
1464   GstPad *old_src = NULL;
1465   GstPad *sink = NULL;
1466   GstPad *old_sink = NULL;
1467   GstPad *new_src = NULL;
1468   GstRTSPMediaFactoryWFD *factory = NULL;
1469   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1470   GstRTSPMediaWFDDirectPipelineData *pipe_data = NULL;
1471
1472   if (!g_atomic_int_compare_and_exchange (&in_pad_probe, FALSE, TRUE))
1473     return GST_PAD_PROBE_OK;
1474
1475   factory = (GstRTSPMediaFactoryWFD *) user_data;
1476   priv = factory->priv;
1477   pipe_data = priv->direct_pipe;
1478
1479   gst_element_sync_state_with_parent (GST_ELEMENT(priv->audio_srcbin));
1480   gst_element_sync_state_with_parent (GST_ELEMENT(priv->video_srcbin));
1481   gst_element_sync_state_with_parent (GST_ELEMENT(priv->mux));
1482   gst_element_sync_state_with_parent (GST_ELEMENT(priv->mux_queue));
1483
1484   sink = gst_element_get_static_pad (priv->pay, "sink");
1485   old_src = gst_pad_get_peer (sink);
1486   gst_pad_unlink (old_src, sink);
1487
1488   new_src = gst_element_get_static_pad (priv->mux_queue, "src");
1489   old_sink = gst_pad_get_peer (new_src);
1490   gst_pad_unlink (new_src, old_sink);
1491   gst_element_set_state (priv->stub_fs, GST_STATE_NULL);
1492   gst_bin_remove ((GstBin *)priv->stream_bin, priv->stub_fs);
1493
1494   gst_pad_link (new_src, sink);
1495   gst_object_unref (new_src);
1496   gst_object_unref (old_sink);
1497
1498   gst_element_set_state (GST_ELEMENT(pipe_data->pipeline), GST_STATE_PAUSED);
1499
1500   /* signal that new pipeline linked */
1501   g_mutex_lock (&priv->direct_lock);
1502   g_cond_signal (&priv->direct_cond);
1503   linked = TRUE;
1504   g_mutex_unlock (&priv->direct_lock);
1505
1506   return GST_PAD_PROBE_REMOVE;
1507 }
1508
1509 static gboolean
1510 _rtsp_media_factory_wfd_destroy_direct_pipe(void *user_data)
1511 {
1512   GstRTSPMediaFactoryWFD *factory = NULL;
1513   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1514   GstRTSPMediaWFDDirectPipelineData *pipe_data = NULL;
1515
1516   factory = (GstRTSPMediaFactoryWFD *) user_data;
1517   priv = factory->priv;
1518   pipe_data = priv->direct_pipe;
1519
1520   GST_DEBUG_OBJECT (factory, "Deleting pipeline");
1521   gst_element_set_state (GST_ELEMENT(pipe_data->pipeline), GST_STATE_NULL);
1522   gst_bin_remove ((GstBin *)priv->stream_bin, GST_ELEMENT(pipe_data->pipeline));
1523   g_free (pipe_data);
1524   g_signal_emit (factory,
1525       gst_rtsp_media_factory_wfd_signals[SIGNAL_DIRECT_STREAMING_END], 0, NULL);
1526   return FALSE;
1527 }
1528
1529 static void
1530 _rtsp_media_factory_wfd_demux_pad_added_cb (GstElement *element,
1531               GstPad     *pad,
1532               gpointer    data)
1533 {
1534   GstPad *sinkpad = NULL;
1535   GstRTSPMediaFactoryWFD *factory = NULL;
1536   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1537   GstRTSPMediaWFDDirectPipelineData *pipe_data = NULL;
1538
1539   GstCaps *caps = gst_pad_get_current_caps (pad);
1540   g_autofree gchar *pad_name = gst_pad_get_name (pad);
1541   g_autofree gchar *caps_string = gst_caps_to_string (caps);
1542   g_autofree gchar *temp_caps = NULL;
1543
1544   gst_caps_unref (caps);
1545
1546   factory = (GstRTSPMediaFactoryWFD *) data;
1547   priv = factory->priv;
1548   pipe_data = priv->direct_pipe;
1549   temp_caps = g_ascii_strdown(caps_string, -1);
1550
1551   if (g_strrstr (temp_caps, "audio")) {
1552     sinkpad = gst_element_get_static_pad (pipe_data->ap, "sink");
1553     if (gst_pad_is_linked (sinkpad)) {
1554       gst_object_unref (sinkpad);
1555       GST_DEBUG_OBJECT (factory, "pad linked");
1556       return;
1557     }
1558     if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)
1559       GST_DEBUG_OBJECT (factory, "can't link demux %s pad", pad_name);
1560
1561     gst_object_unref (sinkpad);
1562     sinkpad = NULL;
1563   }
1564
1565   if (g_strrstr (temp_caps, "video")) {
1566     if (g_strrstr (temp_caps, "h264")) {
1567       sinkpad = gst_element_get_static_pad (pipe_data->vp, "sink");
1568       if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)
1569         GST_DEBUG_OBJECT (factory, "can't link demux %s pad", pad_name);
1570
1571       gst_object_unref (sinkpad);
1572       sinkpad = NULL;
1573     }
1574   }
1575 }
1576
1577 static GstPadProbeReturn
1578 _rtsp_media_factory_wfd_pay_pad_probe_cb (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
1579 {
1580   GstPad *old_src = NULL;
1581   GstPad *sink = NULL;
1582   GstPad *old_sink = NULL;
1583   GstPad *new_src = NULL;
1584   GstPad *fas_sink = NULL;
1585   GstPad *gp = NULL;
1586   GstRTSPMediaFactoryWFD *factory = NULL;
1587   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1588   GstRTSPMediaWFDDirectPipelineData *pipe_data = NULL;
1589
1590   if (!g_atomic_int_compare_and_exchange (&in_pad_probe, FALSE, TRUE))
1591     return GST_PAD_PROBE_OK;
1592
1593   factory = (GstRTSPMediaFactoryWFD *) user_data;
1594   priv = factory->priv;
1595   pipe_data = priv->direct_pipe;
1596
1597   sink = gst_element_get_static_pad (priv->pay, "sink");
1598   old_src = gst_pad_get_peer (sink);
1599   gst_pad_unlink (old_src, sink);
1600
1601   new_src = gst_element_get_static_pad (pipe_data->tsmux, "src");
1602   old_sink = gst_pad_get_peer (new_src);
1603   gst_pad_unlink (new_src, old_sink);
1604   gst_element_set_state (pipe_data->mux_fs, GST_STATE_NULL);
1605   gst_bin_remove ((GstBin *)pipe_data->pipeline, pipe_data->mux_fs);
1606
1607   gp = gst_ghost_pad_new ("audio_file", new_src);
1608   gst_pad_set_active(gp,TRUE);
1609   gst_element_add_pad (GST_ELEMENT (pipe_data->pipeline), gp);
1610   gst_pad_link (gp, sink);
1611   gst_object_unref (new_src);
1612   gst_object_unref (old_sink);
1613
1614   priv->stub_fs = gst_element_factory_make ("fakesink", NULL);
1615   gst_bin_add (priv->stream_bin, priv->stub_fs);
1616   gst_element_sync_state_with_parent (priv->stub_fs);
1617   fas_sink = gst_element_get_static_pad (priv->stub_fs, "sink");
1618   gst_pad_link (old_src, fas_sink);
1619   gst_object_unref (old_src);
1620   gst_object_unref (fas_sink);
1621   gst_element_set_state (GST_ELEMENT(priv->audio_srcbin), GST_STATE_PAUSED);
1622   gst_element_set_state (GST_ELEMENT(priv->video_srcbin), GST_STATE_PAUSED);
1623   gst_element_set_state (GST_ELEMENT(priv->mux), GST_STATE_PAUSED);
1624   gst_element_set_state (GST_ELEMENT(priv->mux_queue), GST_STATE_PAUSED);
1625
1626   /* signal that new pipeline linked */
1627   g_mutex_lock (&priv->direct_lock);
1628   linked = TRUE;
1629   g_cond_signal (&priv->direct_cond);
1630   g_mutex_unlock (&priv->direct_lock);
1631
1632   return GST_PAD_PROBE_REMOVE;
1633 }
1634
1635 static gboolean
1636 _rtsp_media_factory_wfd_relink_pipeline(GstRTSPMediaFactoryWFD * factory)
1637 {
1638   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1639   GstPad *probe_pad = NULL;
1640   gint64 end_time = 0;
1641
1642   priv = factory->priv;
1643
1644   probe_pad = gst_element_get_static_pad (priv->pay, "sink");
1645   if (probe_pad == NULL)
1646     return FALSE;
1647
1648   in_pad_probe = FALSE;
1649   linked = FALSE;
1650   gst_pad_add_probe (probe_pad, GST_PAD_PROBE_TYPE_IDLE, _rtsp_media_factory_wfd_restore_pipe_probe_cb, factory, NULL);
1651
1652   g_mutex_lock (&factory->priv->direct_lock);
1653   end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND;
1654   if (!g_cond_wait_until (&factory->priv->direct_cond, &factory->priv->direct_lock, end_time)) {
1655     g_mutex_unlock (&factory->priv->direct_lock);
1656     GST_ERROR_OBJECT (factory, "Failed to relink pipeline");
1657     return linked;
1658   }
1659   g_mutex_unlock (&factory->priv->direct_lock);
1660   return linked;
1661 }
1662
1663
1664 static GstPadProbeReturn
1665 _rtsp_media_factory_wfd_src_pad_probe_cb(GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
1666 {
1667   GstRTSPMediaFactoryWFD *factory = NULL;
1668   GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info);
1669
1670   factory = (GstRTSPMediaFactoryWFD *) user_data;
1671
1672   if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
1673     GST_INFO_OBJECT (factory, "Got event: %s in direct streaming", GST_EVENT_TYPE_NAME (event));
1674     info->data = NULL;
1675     info->data = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty ("fillEOS"));
1676
1677     if (!_rtsp_media_factory_wfd_relink_pipeline(factory)) {
1678       GST_ERROR_OBJECT (factory, "Failed to relink pipeline");
1679       return GST_PAD_PROBE_REMOVE;
1680     }
1681
1682     g_idle_add((GSourceFunc)_rtsp_media_factory_wfd_destroy_direct_pipe, factory);
1683     return GST_PAD_PROBE_REMOVE;
1684   }
1685
1686   return GST_PAD_PROBE_OK;
1687 }
1688
1689 static gboolean
1690 _rtsp_media_factory_wfd_create_direct_pipeline(GstRTSPMediaFactoryWFD * factory)
1691 {
1692   GstElement *src = NULL;
1693   GstElement *demux = NULL;
1694   g_autofree gchar *path = NULL;
1695   g_autofree gchar *elem_name = NULL;
1696   GstPad *srcpad = NULL;
1697   GstPad *mux_vsinkpad = NULL;
1698   GstPad *mux_asinkpad = NULL;
1699   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1700   GstRTSPMediaWFDDirectPipelineData *pipe_data = NULL;
1701
1702   priv = factory->priv;
1703   pipe_data = priv->direct_pipe;
1704
1705   pipe_data->pipeline = (GstBin *) gst_bin_new ("direct");
1706
1707   src = gst_element_factory_create(priv->res.src_fact, NULL);
1708   demux = gst_element_factory_create(priv->res.demux_fact, NULL);
1709   pipe_data->ap = gst_element_factory_make ("aacparse", NULL);
1710   pipe_data->vp = gst_element_factory_make ("h264parse", NULL);
1711   pipe_data->aq = gst_element_factory_make ("queue", NULL);
1712   pipe_data->vq = gst_element_factory_make ("queue", NULL);
1713   pipe_data->tsmux = gst_element_factory_make ("mpegtsmux", NULL);
1714   pipe_data->mux_fs = gst_element_factory_make ("fakesink", NULL);
1715
1716   if (src == NULL || demux == NULL || pipe_data->tsmux == NULL ||
1717       pipe_data->ap == NULL || pipe_data->vp == NULL ||
1718       pipe_data->aq == NULL || pipe_data->vq == NULL ||
1719       pipe_data->mux_fs == NULL) {
1720     GST_ERROR_OBJECT (factory, "Not all element created");
1721     return FALSE;
1722   }
1723
1724   elem_name = g_ascii_strdown(g_type_name(G_OBJECT_TYPE(src)), -1);
1725
1726   if (g_strrstr (elem_name, "file")) {
1727     path = g_filename_from_uri (pipe_data->uri, NULL, NULL);
1728
1729     if (path == NULL) {
1730       GST_ERROR_OBJECT(factory, "No file path");
1731       return FALSE;
1732     }
1733     g_object_set (src, "location", path, NULL);
1734   } else
1735     g_object_set (src, "uri", pipe_data->uri, NULL);
1736
1737   gst_bin_add_many (pipe_data->pipeline, src, demux, pipe_data->ap,
1738       pipe_data->vp, pipe_data->aq, pipe_data->vq,
1739       pipe_data->tsmux, pipe_data->mux_fs, NULL);
1740
1741   if (!gst_element_link (src, demux)) {
1742     GST_ERROR_OBJECT (factory, "Can't link src with demux");
1743     return FALSE;
1744   }
1745
1746   if (!gst_element_link (pipe_data->ap, pipe_data->aq)) {
1747     GST_ERROR_OBJECT (factory, "Can't link audio parse and queue");
1748     return FALSE;
1749   }
1750
1751   if (!gst_element_link (pipe_data->vp, pipe_data->vq)) {
1752     GST_ERROR_OBJECT (factory, "Can't link video parse and queue");
1753     return FALSE;
1754   }
1755
1756   if (!gst_element_link (pipe_data->tsmux, pipe_data->mux_fs)) {
1757     GST_DEBUG_OBJECT (factory, "Can't link muxer and fakesink");
1758     return FALSE;
1759   }
1760
1761   g_signal_connect_object (demux, "pad-added", G_CALLBACK (_rtsp_media_factory_wfd_demux_pad_added_cb), factory, 0);
1762
1763   gst_bin_add (priv->stream_bin, GST_ELEMENT (pipe_data->pipeline));
1764
1765
1766   /* request video sink pad from muxer, which has elementary pid 0x1011 */
1767   mux_vsinkpad = gst_element_get_request_pad (pipe_data->tsmux, "sink_4113");
1768   if (!mux_vsinkpad) {
1769     GST_ERROR_OBJECT (factory, "Failed to get sink pad from muxer...");
1770     return FALSE;
1771   }
1772
1773   /* request srcpad from video queue */
1774   srcpad = gst_element_get_static_pad (pipe_data->vq, "src");
1775   if (!srcpad) {
1776     GST_ERROR_OBJECT (factory, "Failed to get srcpad from video queue...");
1777   }
1778
1779   if (gst_pad_link (srcpad, mux_vsinkpad) != GST_PAD_LINK_OK) {
1780     GST_ERROR_OBJECT (factory, "Failed to link video queue src pad & muxer video sink pad...");
1781     return FALSE;
1782   }
1783
1784   gst_object_unref (mux_vsinkpad);
1785   gst_object_unref (srcpad);
1786   srcpad = NULL;
1787
1788   /* request audio sink pad from muxer, which has elementary pid 0x1100 */
1789   mux_asinkpad = gst_element_get_request_pad (pipe_data->tsmux, "sink_4352");
1790   if (!mux_asinkpad) {
1791     GST_ERROR_OBJECT (factory, "Failed to get sinkpad from muxer...");
1792     return FALSE;
1793   }
1794
1795   /* request srcpad from audio queue */
1796   srcpad = gst_element_get_static_pad (pipe_data->aq, "src");
1797   if (!srcpad) {
1798     GST_ERROR_OBJECT (factory, "Failed to get srcpad from audio queue...");
1799     return FALSE;
1800   }
1801
1802   /* link audio queue's srcpad & muxer sink pad */
1803   if (gst_pad_link (srcpad, mux_asinkpad) != GST_PAD_LINK_OK) {
1804     GST_ERROR_OBJECT (factory, "Failed to link audio queue src pad & muxer audio sink pad...");
1805     return FALSE;
1806   }
1807   gst_object_unref (mux_asinkpad);
1808   gst_object_unref (srcpad);
1809   srcpad = NULL;
1810
1811   gst_element_sync_state_with_parent (GST_ELEMENT (pipe_data->pipeline));
1812
1813   srcpad = gst_element_get_static_pad (priv->pay, "sink");
1814
1815   in_pad_probe = FALSE;
1816   gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_IDLE, _rtsp_media_factory_wfd_pay_pad_probe_cb, factory, NULL);
1817   gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, _rtsp_media_factory_wfd_src_pad_probe_cb, factory, NULL);
1818
1819   return TRUE;
1820 }
1821
1822 static void
1823 _rtsp_media_factory_wfd_decodebin_element_added_cb (GstElement *decodebin,
1824         GstElement *child, void *user_data)
1825 {
1826   g_autofree gchar *elem_name = g_ascii_strdown(g_type_name(G_OBJECT_TYPE(child)), -1);
1827   GstRTSPMediaFactoryWFD *factory = NULL;
1828   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1829
1830   factory = (GstRTSPMediaFactoryWFD *) user_data;
1831   priv = factory->priv;
1832
1833   if (g_strrstr (elem_name, "h264"))
1834     priv->res.h264_found++;
1835   if (g_strrstr (elem_name, "aac"))
1836     priv->res.aac_found++;
1837   if (g_strrstr (elem_name, "ac3"))
1838     priv->res.ac3_found++;
1839   if (g_strrstr (elem_name, "demux"))
1840     priv->res.demux_fact = gst_element_get_factory(child);
1841 }
1842
1843 static void
1844 _rtsp_media_factory_wfd_uridecodebin_element_added_cb (GstElement *uridecodebin,
1845         GstElement *child, void *user_data)
1846 {
1847   g_autofree gchar *elem_name = g_ascii_strdown(g_type_name(G_OBJECT_TYPE(child)), -1);
1848   GstRTSPMediaFactoryWFD *factory = NULL;
1849   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1850
1851   factory = (GstRTSPMediaFactoryWFD *) user_data;
1852   priv = factory->priv;
1853
1854   if (g_strrstr (elem_name, "src"))
1855     priv->res.src_fact = gst_element_get_factory(child);
1856
1857   if (G_OBJECT_TYPE(child) == priv->decodebin_type)
1858     g_signal_connect_object (child, "element-added",
1859         G_CALLBACK (_rtsp_media_factory_wfd_decodebin_element_added_cb), factory, 0);
1860 }
1861
1862 static void
1863 _rtsp_media_factory_wfd_discover_pad_added_cb (GstElement *uridecodebin, GstPad *pad,
1864     GstBin *pipeline)
1865 {
1866   GstPad *sinkpad = NULL;
1867   GstCaps *caps;
1868
1869   GstElement *queue = gst_element_factory_make ("queue", NULL);
1870   GstElement *sink = gst_element_factory_make ("fakesink", NULL);
1871
1872   if (G_UNLIKELY (queue == NULL || sink == NULL))
1873     goto error;
1874
1875   g_object_set (sink, "silent", TRUE, NULL);
1876   g_object_set (queue, "max-size-buffers", 1, "silent", TRUE, NULL);
1877
1878   caps = gst_pad_query_caps (pad, NULL);
1879
1880   sinkpad = gst_element_get_static_pad (queue, "sink");
1881   if (sinkpad == NULL)
1882     goto error;
1883
1884   gst_caps_unref (caps);
1885
1886   gst_bin_add_many (pipeline, queue, sink, NULL);
1887
1888   if (!gst_element_link_pads_full (queue, "src", sink, "sink",
1889           GST_PAD_LINK_CHECK_NOTHING))
1890     goto error;
1891   if (!gst_element_sync_state_with_parent (sink))
1892     goto error;
1893   if (!gst_element_sync_state_with_parent (queue))
1894     goto error;
1895
1896   if (gst_pad_link_full (pad, sinkpad,
1897           GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)
1898     goto error;
1899   gst_object_unref (sinkpad);
1900
1901   return;
1902
1903 error:
1904   if (sinkpad)
1905     gst_object_unref (sinkpad);
1906   if (queue)
1907     gst_object_unref (queue);
1908   if (sink)
1909     gst_object_unref (sink);
1910   return;
1911 }
1912
1913 static void
1914 _rtsp_media_factory_wfd_uridecode_no_pad_cb (GstElement * uridecodebin, void * user_data)
1915 {
1916   GstRTSPMediaFactoryWFD *factory = NULL;
1917   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1918
1919   factory = (GstRTSPMediaFactoryWFD *) user_data;
1920   priv = factory->priv;
1921   type_detected = TRUE;
1922   g_main_loop_quit (priv->discover_loop);
1923 }
1924
1925 static void
1926 _rtsp_media_factory_wfd_discover_pipe_bus_call (GstBus *bus,
1927           GstMessage *msg,
1928           gpointer data)
1929 {
1930   GstRTSPMediaFactoryWFD *factory = NULL;
1931   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1932
1933   factory = (GstRTSPMediaFactoryWFD *) data;
1934   priv = factory->priv;
1935
1936   switch (GST_MESSAGE_TYPE (msg)) {
1937     case GST_MESSAGE_ERROR: {
1938       GError *error = NULL;
1939
1940       gst_message_parse_error (msg, &error, NULL);
1941
1942       GST_ERROR_OBJECT (factory, "Error: %s", error->message);
1943       g_error_free (error);
1944
1945       type_detected = FALSE;
1946       g_main_loop_quit (priv->discover_loop);
1947       break;
1948     }
1949     default:
1950       break;
1951   }
1952 }
1953
1954 static gboolean
1955 _rtsp_media_factory_wfd_find_media_type (GstRTSPMediaFactoryWFD * factory, gchar *uri)
1956 {
1957   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
1958   GstElement *uridecode = NULL;
1959   GstElement *tmp = NULL;
1960   GstBus *bus;
1961   GMainContext *context;
1962   GSource *source;
1963
1964   priv = factory->priv;
1965
1966   context = g_main_context_new();
1967   priv->discover_loop = g_main_loop_new(context, FALSE);
1968
1969   tmp = gst_element_factory_make ("decodebin", NULL);
1970   priv->decodebin_type = G_OBJECT_TYPE (tmp);
1971   gst_object_unref (tmp);
1972
1973   /* if a URI was provided, use it instead of the default one */
1974   priv->discover_pipeline = (GstBin *) gst_pipeline_new ("Discover");
1975   uridecode = gst_element_factory_make("uridecodebin", "uri");
1976   g_object_set (G_OBJECT (uridecode), "uri", uri, NULL);
1977   gst_bin_add (priv->discover_pipeline, uridecode);
1978   if (priv->decodebin_type == NULL || priv->discover_pipeline == NULL || uridecode == NULL) {
1979     GST_INFO_OBJECT (factory, "Failed to create type find pipeline");
1980     type_detected = FALSE;
1981     return FALSE;
1982   }
1983
1984   /* we add a message handler */
1985   bus = gst_pipeline_get_bus (GST_PIPELINE (priv->discover_pipeline));
1986   source = gst_bus_create_watch (bus);
1987   gst_bus_add_signal_watch (bus);
1988
1989   g_source_set_callback (source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL);
1990   g_source_attach (source, context);
1991   g_signal_connect_object (bus, "message",
1992       G_CALLBACK (_rtsp_media_factory_wfd_discover_pipe_bus_call), factory, 0);
1993
1994   g_signal_connect_object (uridecode, "pad-added",
1995       G_CALLBACK (_rtsp_media_factory_wfd_discover_pad_added_cb), priv->discover_pipeline, 0);
1996   g_signal_connect_object (uridecode, "element-added",
1997             G_CALLBACK (_rtsp_media_factory_wfd_uridecodebin_element_added_cb),
1998             factory, 0);
1999   g_signal_connect_object (uridecode, "no-more-pads",
2000             G_CALLBACK (_rtsp_media_factory_wfd_uridecode_no_pad_cb), factory, 0);
2001   gst_element_set_state (GST_ELEMENT (priv->discover_pipeline), GST_STATE_PLAYING);
2002
2003   g_main_loop_run(priv->discover_loop);
2004
2005   gst_element_set_state (GST_ELEMENT (priv->discover_pipeline), GST_STATE_NULL);
2006   g_source_destroy(source);
2007   g_source_unref (source);
2008   g_main_loop_unref(priv->discover_loop);
2009   g_main_context_unref(context);
2010   gst_object_unref(bus);
2011   gst_object_unref (GST_OBJECT (priv->discover_pipeline));
2012
2013   return TRUE;
2014 }
2015
2016 gint
2017 gst_rtsp_media_factory_wfd_uri_type_find(GstRTSPMediaFactory *factory,
2018     gchar *filesrc, guint8 *detected_video_codec, guint8 *detected_audio_codec)
2019 {
2020   GstRTSPMediaFactoryWFD *_factory = GST_RTSP_MEDIA_FACTORY_WFD_CAST (factory);
2021   GstRTSPMediaFactoryWFDPrivate *priv = _factory->priv;
2022
2023   type_detected = FALSE;
2024
2025   _rtsp_media_factory_wfd_find_media_type (_factory, filesrc);
2026
2027   if (type_detected == FALSE) {
2028     GST_ERROR_OBJECT (_factory, "Media type cannot be detected");
2029     return GST_RTSP_ERROR;
2030   }
2031   GST_INFO_OBJECT (_factory, "Media type detected");
2032
2033   if (priv->res.h264_found)
2034     *detected_video_codec = GST_WFD_VIDEO_H264;
2035
2036   if (priv->res.aac_found)
2037     *detected_audio_codec = GST_WFD_AUDIO_AAC;
2038
2039   if (priv->res.ac3_found)
2040     *detected_audio_codec = GST_WFD_AUDIO_AC3;
2041
2042   return GST_RTSP_OK;
2043 }
2044
2045 gint
2046 gst_rtsp_media_factory_wfd_set_direct_streaming(GstRTSPMediaFactory * factory,
2047     gint direct_streaming, gchar *filesrc)
2048 {
2049   GstRTSPMediaFactoryWFD *_factory = GST_RTSP_MEDIA_FACTORY_WFD_CAST (factory);
2050   linked = FALSE;
2051
2052   if (direct_streaming == 0) {
2053     if (!_rtsp_media_factory_wfd_relink_pipeline(_factory)) {
2054       GST_ERROR_OBJECT (factory, "Failed to relink pipeline");
2055       return GST_RTSP_ERROR;
2056     }
2057
2058     _rtsp_media_factory_wfd_destroy_direct_pipe ((void *)_factory);
2059
2060     GST_INFO_OBJECT (_factory, "Direct streaming bin removed");
2061
2062     return GST_RTSP_OK;
2063   }
2064
2065   _factory->priv->direct_pipe = g_new0 (GstRTSPMediaWFDDirectPipelineData, 1);
2066   _factory->priv->direct_pipe->uri = g_strdup(filesrc);
2067
2068   if (!_rtsp_media_factory_wfd_create_direct_pipeline(_factory)) {
2069     GST_ERROR_OBJECT (_factory, "Direct pipeline creation failed");
2070     return GST_RTSP_ERROR;
2071   }
2072
2073   g_mutex_lock (&_factory->priv->direct_lock);
2074   while (linked != TRUE) {
2075     gint64 end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND;
2076     if (!g_cond_wait_until (&_factory->priv->direct_cond, &_factory->priv->direct_lock, end_time)) {
2077       g_mutex_unlock (&_factory->priv->direct_lock);
2078       GST_ERROR_OBJECT (_factory, "Direct pipeline linking failed");
2079       return GST_RTSP_ERROR;
2080     }
2081   }
2082   g_mutex_unlock (&_factory->priv->direct_lock);
2083
2084   GST_INFO_OBJECT (_factory, "Direct streaming bin created");
2085
2086   return GST_RTSP_OK;
2087 }