Initial release including wifi display based on gst-rtsp-server-1.4.1
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-media-factory-wfd.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.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 #include <stdio.h>
40 #include "rtsp-media-factory-wfd.h"
41 #include "gstwfdmessage.h"
42
43 #define GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE(obj)  \
44        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_MEDIA_FACTORY_WFD, GstRTSPMediaFactoryWFDPrivate))
45
46 #define GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f)       (&(GST_RTSP_MEDIA_FACTORY_WFD_CAST(f)->priv->lock))
47 #define GST_RTSP_MEDIA_FACTORY_WFD_LOCK(f)           (g_mutex_lock(GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f)))
48 #define GST_RTSP_MEDIA_FACTORY_WFD_UNLOCK(f)         (g_mutex_unlock(GST_RTSP_MEDIA_FACTORY_WFD_GET_LOCK(f)))
49
50 struct _GstRTSPMediaFactoryWFDPrivate
51 {
52   GMutex lock;
53   GstRTSPPermissions *permissions;
54   gchar *launch;
55   gboolean shared;
56   GstRTSPLowerTrans protocols;
57   guint buffer_size;
58   guint mtu_size;
59
60   guint8 videosrc_type;
61   guint8 video_codec;
62   guint video_bitrate;
63   guint video_width;
64   guint video_height;
65   guint video_framerate;
66   guint video_enc_skip_inbuf_value;
67   GstElement *video_queue;
68
69   gchar *audio_device;
70   guint8 audio_codec;
71   guint64 audio_latency_time;
72   guint64 audio_buffer_time;
73   gboolean audio_do_timestamp;
74   guint8 audio_channels;
75   guint8 audio_freq;
76   guint8 audio_bitrate;
77   GstElement *audio_queue;
78
79   guint64 video_resolution_supported;
80
81   gboolean dump_ts;
82 };
83
84 #define DEFAULT_LAUNCH          NULL
85 #define DEFAULT_SHARED          FALSE
86 #define DEFAULT_PROTOCOLS       GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
87                                         GST_RTSP_LOWER_TRANS_TCP
88 #define DEFAULT_BUFFER_SIZE     0x80000
89
90 enum
91 {
92   PROP_0,
93   PROP_LAUNCH,
94   PROP_SHARED,
95   PROP_SUSPEND_MODE,
96   PROP_EOS_SHUTDOWN,
97   PROP_PROTOCOLS,
98   PROP_BUFFER_SIZE,
99   PROP_LAST
100 };
101
102 enum
103 {
104   SIGNAL_MEDIA_CONSTRUCTED,
105   SIGNAL_MEDIA_CONFIGURE,
106   SIGNAL_LAST
107 };
108
109 GST_DEBUG_CATEGORY_STATIC (rtsp_media_wfd_debug);
110 #define GST_CAT_DEFAULT rtsp_media_wfd_debug
111
112 static void gst_rtsp_media_factory_wfd_get_property (GObject * object,
113     guint propid, GValue * value, GParamSpec * pspec);
114 static void gst_rtsp_media_factory_wfd_set_property (GObject * object,
115     guint propid, const GValue * value, GParamSpec * pspec);
116
117 static void gst_rtsp_media_factory_wfd_finalize (GObject * obj);
118
119
120 static GstElement *rtsp_media_factory_wfd_create_element (GstRTSPMediaFactory *
121     factory, const GstRTSPUrl * url);
122 static GstRTSPMedia *rtsp_media_factory_wfd_construct (GstRTSPMediaFactory *
123     factory, const GstRTSPUrl * url);
124
125 G_DEFINE_TYPE (GstRTSPMediaFactoryWFD, gst_rtsp_media_factory_wfd,
126     GST_TYPE_RTSP_MEDIA_FACTORY);
127
128 static void
129 gst_rtsp_media_factory_wfd_class_init (GstRTSPMediaFactoryWFDClass * klass)
130 {
131   GObjectClass *gobject_class;
132   GstRTSPMediaFactoryClass *factory_class;
133
134   g_type_class_add_private (klass, sizeof (GstRTSPMediaFactoryWFDPrivate));
135
136   gobject_class = G_OBJECT_CLASS (klass);
137   factory_class = GST_RTSP_MEDIA_FACTORY_CLASS (klass);
138
139   gobject_class->get_property = gst_rtsp_media_factory_wfd_get_property;
140   gobject_class->set_property = gst_rtsp_media_factory_wfd_set_property;
141   gobject_class->finalize = gst_rtsp_media_factory_wfd_finalize;
142
143   factory_class->construct = rtsp_media_factory_wfd_construct;
144   factory_class->create_element = rtsp_media_factory_wfd_create_element;
145
146   GST_DEBUG_CATEGORY_INIT (rtsp_media_wfd_debug, "rtspmediafactorywfd", 0,
147       "GstRTSPMediaFactoryWFD");
148 }
149
150 void  gst_rtsp_media_factory_wfd_set (GstRTSPMediaFactoryWFD * factory,
151     guint8 videosrc_type, gchar *audio_device, guint64 audio_latency_time,
152     guint64 audio_buffer_time, gboolean audio_do_timestamp, guint mtu_size)
153 {
154   GstRTSPMediaFactoryWFDPrivate *priv =
155       GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory);
156   factory->priv = priv;
157
158   priv->videosrc_type = videosrc_type;
159   priv->audio_device= audio_device;
160   priv->audio_latency_time = audio_latency_time;
161   priv->audio_buffer_time = audio_buffer_time;
162   priv->audio_do_timestamp = audio_do_timestamp;
163   priv->mtu_size = mtu_size;
164 }
165
166 void  gst_rtsp_media_factory_wfd_set_dump_ts (GstRTSPMediaFactoryWFD * factory,
167     gboolean dump_ts)
168 {
169   GstRTSPMediaFactoryWFDPrivate *priv =
170       GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory);
171   factory->priv = priv;
172
173   priv->dump_ts = dump_ts;
174 }
175 void gst_rtsp_media_factory_wfd_set_negotiated_resolution (GstRTSPMediaFactory *factory,
176    guint32 width, guint32 height)
177 {
178   GstRTSPMediaFactoryWFD *factory_wfd = GST_RTSP_MEDIA_FACTORY_WFD (factory);
179   GstRTSPMediaFactoryWFDPrivate *priv = factory_wfd->priv;
180
181   priv->video_width = width;
182   priv->video_height = height;
183 }
184
185 static void
186 gst_rtsp_media_factory_wfd_init (GstRTSPMediaFactoryWFD * factory)
187 {
188   GstRTSPMediaFactoryWFDPrivate *priv =
189       GST_RTSP_MEDIA_FACTORY_WFD_GET_PRIVATE (factory);
190   factory->priv = priv;
191
192   priv->launch = g_strdup (DEFAULT_LAUNCH);
193   priv->shared = DEFAULT_SHARED;
194   priv->protocols = DEFAULT_PROTOCOLS;
195   priv->buffer_size = DEFAULT_BUFFER_SIZE;
196
197   //priv->videosrc_type = GST_WFD_VSRC_XIMAGESRC;
198   //priv->videosrc_type = GST_WFD_VSRC_XVIMAGESRC;
199   //priv->videosrc_type = GST_WFD_VSRC_CAMERASRC;
200   priv->videosrc_type = GST_WFD_VSRC_VIDEOTESTSRC;
201   priv->video_codec = GST_WFD_VIDEO_H264;
202   priv->video_bitrate = 200000;
203   priv->video_width = 640;
204   priv->video_height = 480;
205   priv->video_framerate = 30;
206   priv->video_enc_skip_inbuf_value = 5;
207
208   priv->audio_device = g_strdup ("alsa_output.1.analog-stereo.monitor");
209   priv->audio_codec = GST_WFD_AUDIO_AAC;
210   priv->audio_latency_time = 10000;
211   priv->audio_buffer_time = 200000;
212   priv->audio_do_timestamp = FALSE;
213   priv->audio_channels = GST_WFD_CHANNEL_2;
214   priv->audio_freq = GST_WFD_FREQ_48000;
215
216   g_mutex_init (&priv->lock);
217 }
218
219 static void
220 gst_rtsp_media_factory_wfd_finalize (GObject * obj)
221 {
222   GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (obj);
223   GstRTSPMediaFactoryWFDPrivate *priv = factory->priv;
224
225   if (priv->permissions)
226     gst_rtsp_permissions_unref (priv->permissions);
227   g_free (priv->launch);
228   g_mutex_clear (&priv->lock);
229
230   if (priv->audio_device)
231     g_free (priv->audio_device);
232
233   G_OBJECT_CLASS (gst_rtsp_media_factory_wfd_parent_class)->finalize (obj);
234 }
235
236 GstRTSPMediaFactoryWFD *
237 gst_rtsp_media_factory_wfd_new (void)
238 {
239   GstRTSPMediaFactoryWFD *result;
240
241   result = g_object_new (GST_TYPE_RTSP_MEDIA_FACTORY_WFD, NULL);
242
243   return result;
244 }
245
246 static void
247 gst_rtsp_media_factory_wfd_get_property (GObject * object,
248     guint propid, GValue * value, GParamSpec * pspec)
249 {
250   //GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (object);
251
252   switch (propid) {
253     default:
254       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
255   }
256 }
257
258 static void
259 gst_rtsp_media_factory_wfd_set_property (GObject * object,
260     guint propid, const GValue * value, GParamSpec * pspec)
261 {
262   //GstRTSPMediaFactoryWFD *factory = GST_RTSP_MEDIA_FACTORY_WFD (object);
263
264   switch (propid) {
265     default:
266       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
267   }
268 }
269
270 static GstPadProbeReturn
271 rtsp_media_wfd_dump_data (GstPad * pad, GstPadProbeInfo *info, gpointer u_data)
272 {
273   guint8 *data;
274   gsize size;
275   FILE *f;
276   GstMapInfo mapinfo;
277
278   if (info->type == (GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH)) {
279     GstBuffer *buffer = gst_pad_probe_info_get_buffer (info);
280
281     gst_buffer_map (buffer, &mapinfo, GST_MAP_READ);
282     data = mapinfo.data;
283     size = gst_buffer_get_size (buffer);
284
285     f = fopen ("/root/probe.ts", "a");
286     fwrite (data, size, 1, f);
287     fclose (f);
288     gst_buffer_unmap (buffer, &mapinfo);
289   }
290
291   return GST_PAD_PROBE_OK;
292 }
293
294 static gboolean
295 _rtsp_media_factory_wfd_create_audio_capture_bin (GstRTSPMediaFactoryWFD *
296     factory, GstBin * srcbin)
297 {
298   GstElement *audiosrc = NULL;
299   GstElement *acaps = NULL;
300   GstElement *aenc = NULL;
301   GstElement *audio_convert = NULL;
302   GstElement *aqueue = NULL;
303   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
304
305   guint channels = 0;
306   gboolean is_enc_req = TRUE;
307   guint freq = 0;
308   gchar *acodec = NULL;
309
310   priv = factory->priv;
311
312   /* create audio src element */
313   audiosrc = gst_element_factory_make ("pulsesrc", "audiosrc");
314   if (!audiosrc) {
315     GST_ERROR_OBJECT (factory, "failed to create audiosrc element");
316     goto create_error;
317   }
318
319   GST_INFO_OBJECT (factory, "audio device : %s", priv->audio_device);
320   GST_INFO_OBJECT (factory, "audio latency time  : %lld",
321       priv->audio_latency_time);
322   GST_INFO_OBJECT (factory, "audio_buffer_time  : %lld",
323       priv->audio_buffer_time);
324   GST_INFO_OBJECT (factory, "audio_do_timestamp  : %d",
325       priv->audio_do_timestamp);
326
327   g_object_set (audiosrc, "device", priv->audio_device, NULL);
328   g_object_set (audiosrc, "buffer-time", (gint64) priv->audio_buffer_time,
329       NULL);
330   g_object_set (audiosrc, "latency-time", (gint64) priv->audio_latency_time,
331       NULL);
332   g_object_set (audiosrc, "do-timestamp", (gboolean) priv->audio_do_timestamp,
333       NULL);
334   g_object_set (audiosrc, "provide-clock", (gboolean) FALSE, NULL);
335   g_object_set (audiosrc, "is-live", (gboolean) TRUE, NULL);
336
337   if (priv->audio_codec == GST_WFD_AUDIO_LPCM) {
338     /* To meet miracast certification */
339     gint64 block_size = 1920;
340     g_object_set (audiosrc, "blocksize", (gint64) block_size, NULL);
341
342     audio_convert = gst_element_factory_make ("audioconvert", "audio_convert");
343     if (NULL == audio_convert) {
344       GST_ERROR_OBJECT (factory, "failed to create audio convert element");
345       goto create_error;
346     }
347   }
348
349   /* create audio caps element */
350   acaps = gst_element_factory_make ("capsfilter", "audiocaps");
351   if (NULL == acaps) {
352     GST_ERROR_OBJECT (factory, "failed to create audio capsilfter element");
353     goto create_error;
354   }
355
356   if (priv->audio_channels == GST_WFD_CHANNEL_2)
357     channels = 2;
358   else if (priv->audio_channels == GST_WFD_CHANNEL_4)
359     channels = 4;
360   else if (priv->audio_channels == GST_WFD_CHANNEL_6)
361     channels = 6;
362   else if (priv->audio_channels == GST_WFD_CHANNEL_8)
363     channels = 8;
364   else
365     channels = 2;
366
367   if (priv->audio_freq == GST_WFD_FREQ_44100)
368     freq = 44100;
369   else if (priv->audio_freq == GST_WFD_FREQ_48000)
370     freq = 48000;
371   else
372     freq = 44100;
373
374   if (priv->audio_codec == GST_WFD_AUDIO_LPCM) {
375     g_object_set (G_OBJECT (acaps), "caps",
376         gst_caps_new_simple ("audio/x-lpcm", "width", G_TYPE_INT, 16,
377             /* In case of LPCM, uses big endian */
378             "endianness", G_TYPE_INT, 4321,
379             "signed", G_TYPE_BOOLEAN, TRUE,
380             "depth", G_TYPE_INT, 16,
381             "rate", G_TYPE_INT, freq,
382             "channels", G_TYPE_INT, channels, NULL), NULL);
383   } else if ((priv->audio_codec == GST_WFD_AUDIO_AAC)
384       || (priv->audio_codec == GST_WFD_AUDIO_AC3)) {
385     g_object_set (G_OBJECT (acaps), "caps", gst_caps_new_simple ("audio/x-raw",
386             "endianness", G_TYPE_INT, 1234, "signed", G_TYPE_BOOLEAN, TRUE,
387             "depth", G_TYPE_INT, 16, "rate", G_TYPE_INT, freq, "channels",
388             G_TYPE_INT, channels, NULL), NULL);
389   }
390
391   if (priv->audio_codec == GST_WFD_AUDIO_AAC) {
392     acodec = g_strdup ("avenc_aac");
393     is_enc_req = TRUE;
394   } else if (priv->audio_codec == GST_WFD_AUDIO_AC3) {
395     acodec = g_strdup ("avenc_ac3");
396     is_enc_req = TRUE;
397   } else if (priv->audio_codec == GST_WFD_AUDIO_LPCM) {
398     GST_DEBUG_OBJECT (factory, "No codec required, raw data will be sent");
399     is_enc_req = FALSE;
400   } else {
401     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
402     goto create_error;
403   }
404
405   if (is_enc_req) {
406     aenc = gst_element_factory_make (acodec, "audioenc");
407     if (NULL == aenc) {
408       GST_ERROR_OBJECT (factory, "failed to create audio encoder element");
409       goto create_error;
410     }
411
412     g_object_set (aenc, "compliance", -2, NULL);
413     g_object_set (aenc, "tolerance", 400000000, NULL);
414     g_object_set (aenc, "bitrate", (guint) 128000, NULL);
415     g_object_set (aenc, "rate-control", 2, NULL);
416
417     aqueue = gst_element_factory_make ("queue", "audio-queue");
418     if (!aqueue) {
419       GST_ERROR_OBJECT (factory, "failed to create audio queue element");
420       goto create_error;
421     }
422
423     gst_bin_add_many (srcbin, audiosrc, acaps, aenc, aqueue, NULL);
424
425     if (!gst_element_link_many (audiosrc, acaps, aenc, aqueue, NULL)) {
426       GST_ERROR_OBJECT (factory, "Failed to link audio src elements...");
427       goto create_error;
428     }
429   } else {
430     aqueue = gst_element_factory_make ("queue", "audio-queue");
431     if (!aqueue) {
432       GST_ERROR_OBJECT (factory, "failed to create audio queue element");
433       goto create_error;
434     }
435
436     gst_bin_add_many (srcbin, audiosrc, audio_convert, acaps, aqueue, NULL);
437
438     if (!gst_element_link_many (audiosrc, audio_convert, acaps, aqueue, NULL)) {
439       GST_ERROR_OBJECT (factory, "Failed to link audio src elements...");
440       goto create_error;
441     }
442   }
443
444   priv->audio_queue = aqueue;
445
446   return TRUE;
447
448 create_error:
449   return FALSE;
450 }
451
452 static gboolean
453 _rtsp_media_factory_wfd_create_videotest_bin (GstRTSPMediaFactoryWFD * factory,
454     GstBin * srcbin)
455 {
456   GstElement *videosrc = NULL;
457   GstElement *vcaps = NULL;
458   GstElement *venc_caps = NULL;
459   gchar *vcodec = NULL;
460   GstElement *venc = NULL;
461   GstElement *vqueue = NULL;
462   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
463
464   priv = factory->priv;
465
466   GST_INFO_OBJECT (factory, "picked videotestsrc as video source");
467
468   videosrc = gst_element_factory_make ("videotestsrc", "videosrc");
469   if (NULL == videosrc) {
470     GST_ERROR_OBJECT (factory, "failed to create ximagesrc element");
471     goto create_error;
472   }
473
474   /* create video caps element */
475   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
476   if (NULL == vcaps) {
477     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
478     goto create_error;
479   }
480
481   g_object_set (G_OBJECT (vcaps), "caps",
482       gst_caps_new_simple ("video/x-raw",
483           "width", G_TYPE_INT, priv->video_width,
484           "height", G_TYPE_INT, priv->video_height,
485           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
486       NULL);
487
488   if (priv->video_codec == GST_WFD_VIDEO_H264)
489     vcodec = g_strdup ("x264enc");
490   else {
491     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
492     g_free (vcodec);
493     goto create_error;
494   }
495
496   venc = gst_element_factory_make (vcodec, "videoenc");
497   g_free (vcodec);
498
499   if (!venc) {
500     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
501     goto create_error;
502   }
503
504   g_object_set (venc, "aud", 0, NULL);
505   g_object_set (venc, "byte-stream", 1, NULL);
506   g_object_set (venc, "bitrate", 512, NULL);
507
508   venc_caps = gst_element_factory_make ("capsfilter", "venc_caps");
509   if (NULL == venc_caps) {
510     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
511     goto create_error;
512   }
513
514   g_object_set (G_OBJECT (venc_caps), "caps",
515       gst_caps_new_simple ("video/x-h264",
516           "profile", G_TYPE_STRING, "baseline", NULL), NULL);
517
518   vqueue = gst_element_factory_make ("queue", "video-queue");
519   if (!vqueue) {
520     GST_ERROR_OBJECT (factory, "failed to create video queue element");
521     goto create_error;
522   }
523
524   gst_bin_add_many (srcbin, videosrc, vcaps, venc, venc_caps, vqueue, NULL);
525   if (!gst_element_link_many (videosrc, vcaps, venc, venc_caps, vqueue, NULL)) {
526     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
527     goto create_error;
528   }
529
530   priv->video_queue = vqueue;
531
532   return TRUE;
533
534 create_error:
535   return FALSE;
536 }
537
538 static gboolean
539 _rtsp_media_factory_wfd_create_camera_capture_bin (GstRTSPMediaFactoryWFD *
540     factory, GstBin * srcbin)
541 {
542   GstElement *videosrc = NULL;
543   GstElement *vcaps = NULL;
544   GstElement *venc = NULL;
545   GstElement *vqueue = NULL;
546   gchar *vcodec = NULL;
547   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
548
549   priv = factory->priv;
550
551   videosrc = gst_element_factory_make ("camerasrc", "videosrc");
552   if (NULL == videosrc) {
553     GST_ERROR_OBJECT (factory, "failed to create camerasrc element");
554     goto create_error;
555   }
556
557   /* create video caps element */
558   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
559   if (NULL == vcaps) {
560     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
561     goto create_error;
562   }
563
564   GST_INFO_OBJECT (factory, "picked camerasrc as video source");
565   g_object_set (G_OBJECT (vcaps), "caps",
566       gst_caps_new_simple ("video/x-raw",
567           "width", G_TYPE_INT, priv->video_width,
568           "height", G_TYPE_INT, priv->video_height,
569           "format", G_TYPE_STRING, "SN12",
570           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
571       NULL);
572
573   if (priv->video_codec == GST_WFD_VIDEO_H264)
574     vcodec = g_strdup ("omxh264enc");
575   else {
576     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
577     goto create_error;
578   }
579
580   venc = gst_element_factory_make (vcodec, "videoenc");
581   if (!venc) {
582     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
583     goto create_error;
584   }
585
586   g_object_set (venc, "bitrate", priv->video_bitrate, NULL);
587   g_object_set (venc, "byte-stream", 1, NULL);
588   g_object_set (venc, "append-dci", 1, NULL);
589
590   vqueue = gst_element_factory_make ("queue", "video-queue");
591   if (!vqueue) {
592     GST_ERROR_OBJECT (factory, "failed to create video queue element");
593     goto create_error;
594   }
595
596   gst_bin_add_many (srcbin, videosrc, vcaps, venc, vqueue, NULL);
597
598   if (!gst_element_link_many (videosrc, vcaps, venc, vqueue, NULL)) {
599     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
600     goto create_error;
601   }
602
603   priv->video_queue = vqueue;
604
605   return TRUE;
606
607 create_error:
608   return FALSE;
609 }
610
611 static gboolean
612 _rtsp_media_factory_wfd_create_xcapture_bin (GstRTSPMediaFactoryWFD * factory,
613     GstBin * srcbin)
614 {
615   GstElement *videosrc = NULL;
616   GstElement *vcaps = NULL;
617   GstElement *venc_caps = NULL;
618   GstElement *videoconvert = NULL, *videoscale = NULL;
619   gchar *vcodec = NULL;
620   GstElement *venc = NULL;
621   GstElement *vqueue = NULL;
622   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
623
624   priv = factory->priv;
625
626   GST_INFO_OBJECT (factory, "picked ximagesrc as video source");
627
628   videosrc = gst_element_factory_make ("ximagesrc", "videosrc");
629   if (NULL == videosrc) {
630     GST_ERROR_OBJECT (factory, "failed to create ximagesrc element");
631     goto create_error;
632   }
633
634   videoscale = gst_element_factory_make ("videoscale", "videoscale");
635   if (NULL == videoscale) {
636     GST_ERROR_OBJECT (factory, "failed to create videoscale element");
637     goto create_error;
638   }
639
640   videoconvert = gst_element_factory_make ("videoconvert", "videoconvert");
641   if (NULL == videoconvert) {
642     GST_ERROR_OBJECT (factory, "failed to create videoconvert element");
643     goto create_error;
644   }
645
646   /* create video caps element */
647   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
648   if (NULL == vcaps) {
649     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
650     goto create_error;
651   }
652
653   g_object_set (G_OBJECT (vcaps), "caps",
654       gst_caps_new_simple ("video/x-raw",
655           "width", G_TYPE_INT, priv->video_width,
656           "height", G_TYPE_INT, priv->video_height,
657           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
658       NULL);
659
660   if (priv->video_codec == GST_WFD_VIDEO_H264)
661     vcodec = g_strdup ("x264enc");
662   else {
663     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
664     g_free (vcodec);
665     goto create_error;
666   }
667
668   venc = gst_element_factory_make (vcodec, "videoenc");
669   g_free (vcodec);
670
671   if (!venc) {
672     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
673     goto create_error;
674   }
675
676   g_object_set (venc, "aud", 0, NULL);
677   g_object_set (venc, "byte-stream", 1, NULL);
678   g_object_set (venc, "bitrate", 512, NULL);
679
680   venc_caps = gst_element_factory_make ("capsfilter", "venc_caps");
681   if (NULL == venc_caps) {
682     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
683     goto create_error;
684   }
685
686   g_object_set (G_OBJECT (venc_caps), "caps",
687       gst_caps_new_simple ("video/x-h264",
688           "profile", G_TYPE_STRING, "baseline", NULL), NULL);
689
690   vqueue = gst_element_factory_make ("queue", "video-queue");
691   if (!vqueue) {
692     GST_ERROR_OBJECT (factory, "failed to create video queue element");
693     goto create_error;
694   }
695
696   gst_bin_add_many (srcbin, videosrc, videoscale, videoconvert, vcaps, venc,
697       venc_caps, vqueue, NULL);
698   if (!gst_element_link_many (videosrc, videoscale, videoconvert, vcaps, venc,
699           venc_caps, vqueue, NULL)) {
700     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
701     goto create_error;
702   }
703
704   priv->video_queue = vqueue;
705
706   return TRUE;
707
708 create_error:
709   return FALSE;
710 }
711
712 static gboolean
713 _rtsp_media_factory_wfd_create_xvcapture_bin (GstRTSPMediaFactoryWFD * factory,
714     GstBin * srcbin)
715 {
716   GstElement *videosrc = NULL;
717   GstElement *vcaps = NULL;
718   gchar *vcodec = NULL;
719   GstElement *venc = NULL;
720   GstElement *vqueue = NULL;
721   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
722
723   priv = factory->priv;
724
725   GST_INFO_OBJECT (factory, "picked xvimagesrc as video source");
726
727   videosrc = gst_element_factory_make ("xvimagesrc", "videosrc");
728   if (NULL == videosrc) {
729     GST_ERROR_OBJECT (factory, "failed to create xvimagesrc element");
730     goto create_error;
731   }
732
733   /* create video caps element */
734   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
735   if (NULL == vcaps) {
736     GST_ERROR_OBJECT (factory, "failed to create video capsilfter element");
737     goto create_error;
738   }
739
740   g_object_set (G_OBJECT (vcaps), "caps",
741       gst_caps_new_simple ("video/x-raw",
742           "width", G_TYPE_INT, priv->video_width,
743           "height", G_TYPE_INT, priv->video_height,
744           "format", G_TYPE_STRING, "SN12",
745           "framerate", GST_TYPE_FRACTION, priv->video_framerate, 1, NULL),
746       NULL);
747
748   if (priv->video_codec == GST_WFD_VIDEO_H264) {
749     vcodec = g_strdup ("omxh264enc");
750   } else {
751     GST_ERROR_OBJECT (factory, "Yet to support other than H264 format");
752     goto create_error;
753   }
754
755   venc = gst_element_factory_make (vcodec, "videoenc");
756   if (!venc) {
757     GST_ERROR_OBJECT (factory, "failed to create video encoder element");
758     goto create_error;
759   }
760   g_object_set (venc, "bitrate", priv->video_bitrate, NULL);
761   g_object_set (venc, "byte-stream", 1, NULL);
762   g_object_set (venc, "append-dci", 1, NULL);
763   g_object_set (venc, "idr-period", 120, NULL);
764   g_object_set (venc, "skip-inbuf", priv->video_enc_skip_inbuf_value, NULL);
765
766   vqueue = gst_element_factory_make ("queue", "video-queue");
767   if (!vqueue) {
768     GST_ERROR_OBJECT (factory, "failed to create video queue element");
769     goto create_error;
770   }
771
772   gst_bin_add_many (srcbin, videosrc, vcaps, venc, vqueue, NULL);
773   if (!gst_element_link_many (videosrc, vcaps, venc, vqueue, NULL)) {
774     GST_ERROR_OBJECT (factory, "Failed to link video src elements...");
775     goto create_error;
776   }
777
778   priv->video_queue = vqueue;
779
780   return TRUE;
781
782 create_error:
783   return FALSE;
784 }
785
786 static GstElement *
787 _rtsp_media_factory_wfd_create_srcbin (GstRTSPMediaFactoryWFD * factory)
788 {
789   GstRTSPMediaFactoryWFDPrivate *priv = NULL;
790
791   GstBin *srcbin = NULL;
792   GstElement *mux = NULL;
793   GstElement *mux_queue = NULL;
794   GstElement *payload = NULL;
795   GstPad *srcpad = NULL;
796   GstPad *mux_vsinkpad = NULL;
797   GstPad *mux_asinkpad = NULL;
798
799   priv = factory->priv;
800
801   /* create source bin */
802   srcbin = GST_BIN (gst_bin_new ("srcbin"));
803   if (!srcbin) {
804     GST_ERROR_OBJECT (factory, "failed to create source bin...");
805     goto create_error;
806   }
807
808   /* create video src element */
809   switch (priv->videosrc_type) {
810     case GST_WFD_VSRC_XIMAGESRC:
811       if (!_rtsp_media_factory_wfd_create_xcapture_bin (factory, srcbin)) {
812         GST_ERROR_OBJECT (factory, "failed to create xcapture bin...");
813         goto create_error;
814       }
815       break;
816     case GST_WFD_VSRC_XVIMAGESRC:
817       if (!_rtsp_media_factory_wfd_create_xvcapture_bin (factory, srcbin)) {
818         GST_ERROR_OBJECT (factory, "failed to create xvcapture bin...");
819         goto create_error;
820       }
821       break;
822     case GST_WFD_VSRC_CAMERASRC:
823       if (!_rtsp_media_factory_wfd_create_camera_capture_bin (factory, srcbin)) {
824         GST_ERROR_OBJECT (factory, "failed to create camera capture bin...");
825         goto create_error;
826       }
827       break;
828     case GST_WFD_VSRC_VIDEOTESTSRC:
829       if (!_rtsp_media_factory_wfd_create_videotest_bin (factory, srcbin)) {
830         GST_ERROR_OBJECT (factory, "failed to create videotestsrc bin...");
831         goto create_error;
832       }
833       break;
834     default:
835       GST_ERROR_OBJECT (factory, "unknow mode selected...");
836       goto create_error;
837   }
838
839   mux = gst_element_factory_make ("mpegtsmux", "tsmux");
840   if (!mux) {
841     GST_ERROR_OBJECT (factory, "failed to create muxer element");
842     goto create_error;
843   }
844
845   g_object_set (mux, "wfd-mode", TRUE, NULL);
846
847   mux_queue = gst_element_factory_make ("queue", "muxer-queue");
848   if (!mux_queue) {
849     GST_ERROR_OBJECT (factory, "failed to create muxer-queue element");
850     goto create_error;
851   }
852
853   g_object_set (mux_queue, "max-size-buffers", 20000, NULL);
854
855   payload = gst_element_factory_make ("rtpmp2tpay", "pay0");
856   if (!payload) {
857     GST_ERROR_OBJECT (factory, "failed to create payload element");
858     goto create_error;
859   }
860
861   g_object_set (payload, "pt", 33, NULL);
862   g_object_set (payload, "mtu", priv->mtu_size, NULL);
863   g_object_set (payload, "rtp-flush", (gboolean) TRUE, NULL);
864
865   gst_bin_add_many (srcbin, mux, mux_queue, payload, NULL);
866
867   if (!gst_element_link_many (mux, mux_queue, payload, NULL)) {
868     GST_ERROR_OBJECT (factory, "Failed to link muxer & payload...");
869     goto create_error;
870   }
871
872   /* request video sink pad from muxer, which has elementary pid 0x1011 */
873   mux_vsinkpad = gst_element_get_request_pad (mux, "sink_4113");
874   if (!mux_vsinkpad) {
875     GST_ERROR_OBJECT (factory, "Failed to get sink pad from muxer...");
876     goto create_error;
877   }
878
879   /* request srcpad from video queue */
880   srcpad = gst_element_get_static_pad (priv->video_queue, "src");
881   if (!srcpad) {
882     GST_ERROR_OBJECT (factory, "Failed to get srcpad from video queue...");
883     goto create_error;
884   }
885
886   if (gst_pad_link (srcpad, mux_vsinkpad) != GST_PAD_LINK_OK) {
887     GST_ERROR_OBJECT (factory,
888         "Failed to link video queue src pad & muxer video sink pad...");
889     goto create_error;
890   }
891
892   gst_object_unref (mux_vsinkpad);
893   gst_object_unref (srcpad);
894   srcpad = NULL;
895
896   /* create audio source elements & add to pipeline */
897   if (!_rtsp_media_factory_wfd_create_audio_capture_bin (factory, srcbin))
898     goto create_error;
899
900   /* request audio sink pad from muxer, which has elementary pid 0x1100 */
901   mux_asinkpad = gst_element_get_request_pad (mux, "sink_4352");
902   if (!mux_asinkpad) {
903     GST_ERROR_OBJECT (factory, "Failed to get sinkpad from muxer...");
904     goto create_error;
905   }
906
907   /* request srcpad from audio queue */
908   srcpad = gst_element_get_static_pad (priv->audio_queue, "src");
909   if (!srcpad) {
910     GST_ERROR_OBJECT (factory, "Failed to get srcpad from audio queue...");
911     goto create_error;
912   }
913
914   /* link audio queue's srcpad & muxer sink pad */
915   if (gst_pad_link (srcpad, mux_asinkpad) != GST_PAD_LINK_OK) {
916     GST_ERROR_OBJECT (factory,
917         "Failed to link audio queue src pad & muxer audio sink pad...");
918     goto create_error;
919   }
920   gst_object_unref (mux_asinkpad);
921   gst_object_unref (srcpad);
922
923   if (priv->dump_ts)
924   {
925     GstPad *pad_probe = NULL;
926     pad_probe = gst_element_get_static_pad (mux, "src");
927
928     if (NULL == pad_probe) {
929       GST_INFO_OBJECT (factory, "pad for probe not created");
930     } else {
931       GST_INFO_OBJECT (factory, "pad for probe SUCCESSFUL");
932     }
933     gst_pad_add_probe (pad_probe, GST_PAD_PROBE_TYPE_BUFFER,
934         rtsp_media_wfd_dump_data, factory, NULL);
935   }
936
937   GST_DEBUG_OBJECT (factory, "successfully created source bin...");
938
939   return GST_ELEMENT_CAST (srcbin);
940
941 create_error:
942   GST_ERROR_OBJECT (factory, "Failed to create pipeline");
943   return NULL;
944 }
945
946 static GstElement *
947 rtsp_media_factory_wfd_create_element (GstRTSPMediaFactory * factory,
948     const GstRTSPUrl * url)
949 {
950   GstRTSPMediaFactoryWFD *_factory = GST_RTSP_MEDIA_FACTORY_WFD_CAST (factory);
951   GstElement *element = NULL;
952
953   GST_RTSP_MEDIA_FACTORY_WFD_LOCK (factory);
954
955   element = _rtsp_media_factory_wfd_create_srcbin (_factory);
956
957   GST_RTSP_MEDIA_FACTORY_WFD_UNLOCK (factory);
958
959   return element;
960 }
961
962 static GstRTSPMedia *
963 rtsp_media_factory_wfd_construct (GstRTSPMediaFactory * factory,
964     const GstRTSPUrl * url)
965 {
966   GstRTSPMedia *media;
967   GstElement *element, *pipeline;
968   GstRTSPMediaFactoryClass *klass;
969
970   klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
971
972   if (!klass->create_pipeline)
973     goto no_create;
974
975   element = gst_rtsp_media_factory_create_element (factory, url);
976   if (element == NULL)
977     goto no_element;
978
979   /* create a new empty media */
980   media = gst_rtsp_media_new (element);
981
982   gst_rtsp_media_collect_streams (media);
983
984   pipeline = klass->create_pipeline (factory, media);
985   if (pipeline == NULL)
986     goto no_pipeline;
987
988   return media;
989
990   /* ERRORS */
991 no_create:
992   {
993     g_critical ("no create_pipeline function");
994     return NULL;
995   }
996 no_element:
997   {
998     g_critical ("could not create element");
999     return NULL;
1000   }
1001 no_pipeline:
1002   {
1003     g_critical ("can't create pipeline");
1004     g_object_unref (media);
1005     return NULL;
1006   }
1007 }