Advertisement
Guest User

Untitled

a guest
Oct 14th, 2015
697
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.92 KB | None | 0 0
  1. // gcc test-netclock2-appsink.c -o s2appsink `pkg-config --cflags --libs gstreamer-rtsp-server-1.0 gstreamer-1.0 gstreamer-net-1.0 gstreamer-rtsp-1.0`
  2.  
  3. /* GStreamer
  4.  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
  5.  * Copyright (C) 2014 Jan Schmidt <jan@centricular.com>
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Library General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Library General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Library General Public
  18.  * License along with this library; if not, write to the
  19.  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  20.  * Boston, MA 02110-1301, USA.
  21.  */
  22. #include <stdlib.h>     /* atoi */
  23. #include <gst/gst.h>
  24.  
  25. #include <gst/net/gstnettimeprovider.h>
  26. #include <gst/rtsp-server/rtsp-server.h>
  27.  
  28. GstClock *global_clock;
  29.  
  30. #define TEST_TYPE_RTSP_MEDIA_FACTORY      (test_rtsp_media_factory_get_type ())
  31. #define TEST_TYPE_RTSP_MEDIA              (test_rtsp_media_get_type ())
  32.  
  33. GType test_rtsp_media_factory_get_type (void);
  34. GType test_rtsp_media_get_type (void);
  35.  
  36. static GstRTSPMediaFactory *test_rtsp_media_factory_new (void);
  37. static GstElement *create_pipeline (GstRTSPMediaFactory * factory,
  38.     GstRTSPMedia * media);
  39.  
  40. typedef struct TestRTSPMediaFactoryClass TestRTSPMediaFactoryClass;
  41. typedef struct TestRTSPMediaFactory TestRTSPMediaFactory;
  42.  
  43. struct TestRTSPMediaFactoryClass
  44. {
  45.   GstRTSPMediaFactoryClass parent;
  46. };
  47.  
  48. struct TestRTSPMediaFactory
  49. {
  50.   GstRTSPMediaFactory parent;
  51. };
  52.  
  53. typedef struct TestRTSPMediaClass TestRTSPMediaClass;
  54. typedef struct TestRTSPMedia TestRTSPMedia;
  55.  
  56. struct TestRTSPMediaClass
  57. {
  58.   GstRTSPMediaClass parent;
  59. };
  60.  
  61. struct TestRTSPMedia
  62. {
  63.   GstRTSPMedia parent;
  64. };
  65.  
  66. GstRTSPMediaFactory *
  67. test_rtsp_media_factory_new (void)
  68. {
  69.   GstRTSPMediaFactory *result;
  70.  
  71.   result = g_object_new (TEST_TYPE_RTSP_MEDIA_FACTORY, NULL);
  72.  
  73.   return result;
  74. }
  75.  
  76. G_DEFINE_TYPE (TestRTSPMediaFactory, test_rtsp_media_factory,
  77.     GST_TYPE_RTSP_MEDIA_FACTORY);
  78.  
  79. static gboolean custom_setup_rtpbin (GstRTSPMedia * media, GstElement * rtpbin);
  80.  
  81. static void
  82. test_rtsp_media_factory_class_init (TestRTSPMediaFactoryClass * test_klass)
  83. {
  84.   GstRTSPMediaFactoryClass *mf_klass =
  85.       (GstRTSPMediaFactoryClass *) (test_klass);
  86.   mf_klass->create_pipeline = create_pipeline;
  87. }
  88.  
  89. static void
  90. test_rtsp_media_factory_init (TestRTSPMediaFactory * factory)
  91. {
  92. }
  93.  
  94. static GstElement *
  95. create_pipeline (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
  96. {
  97.   GstElement *pipeline;
  98.  
  99.   pipeline = gst_pipeline_new ("media-pipeline");
  100.   if (global_clock == NULL) {
  101.     g_print ("No clock!!!!\n");
  102.   } else {
  103.     gst_pipeline_use_clock (GST_PIPELINE (pipeline), global_clock);
  104.   }
  105.   gst_rtsp_media_take_pipeline (media, GST_PIPELINE_CAST (pipeline));
  106.  
  107.   return pipeline;
  108. }
  109.  
  110. G_DEFINE_TYPE (TestRTSPMedia, test_rtsp_media, GST_TYPE_RTSP_MEDIA);
  111.  
  112. static void
  113. test_rtsp_media_class_init (TestRTSPMediaClass * test_klass)
  114. {
  115.   GstRTSPMediaClass *klass = (GstRTSPMediaClass *) (test_klass);
  116.   klass->setup_rtpbin = custom_setup_rtpbin;
  117. }
  118.  
  119. static void
  120. test_rtsp_media_init (TestRTSPMedia * media)
  121. {
  122. }
  123.  
  124. static gboolean
  125. custom_setup_rtpbin (GstRTSPMedia * media, GstElement * rtpbin)
  126. {
  127.   g_object_set (rtpbin, "ntp-time-source", 3, NULL);
  128.   return TRUE;
  129. }
  130.  
  131. void
  132. client_connection (GstRTSPServer *gstrtspserver,
  133.                GstRTSPClient *arg1,
  134.                gpointer       user_data)
  135. {
  136.   GstRTSPConnection * conn = (GstRTSPConnection*) gst_rtsp_client_get_connection (arg1);
  137.   g_print ("Local ip %s\n",
  138.         gst_rtsp_connection_get_ip (conn));
  139.  
  140.   gint * port = (gint*) user_data;
  141.  
  142.   g_print ("Port %d\n", *port);  
  143.  
  144.   if (global_clock == NULL) {
  145.     g_print ("No clocks already available\n");
  146.   } else {
  147.     g_print ("A clock was present, unref it!.\n");
  148.   }
  149.  
  150.   global_clock = gst_net_client_clock_new ("net_clock", gst_rtsp_connection_get_ip (conn), 8554, 0);
  151.  
  152.   if (global_clock == NULL) {
  153.     g_print ("Failed to create net clock client for %s:%d\n",
  154.         "192.168.0.1", 8554);
  155.     return;
  156.   }
  157.  
  158.   g_print ("Waiting clock...");
  159.   /* Wait for the clock to stabilise */
  160.   gst_clock_wait_for_sync (global_clock, GST_CLOCK_TIME_NONE);
  161.  
  162.   g_print ("Synked!\n");        
  163. }
  164.  
  165. typedef struct
  166. {
  167.   gboolean white;
  168.   GstClockTime timestamp;
  169. } MyContext;
  170.  
  171.  
  172. /* called when we need to give data to appsrc */
  173. static void
  174. need_data (GstElement * appsrc, guint unused, MyContext * ctx)
  175. {
  176.   GstBuffer *buffer;
  177.   guint size;
  178.   GstFlowReturn ret;
  179.  
  180.   static int predictable_seq = 0;
  181.  
  182.   size = 385 * 288 * 2;
  183.  
  184.   buffer = gst_buffer_new_allocate (NULL, size, NULL);
  185.  
  186.   /* this makes the image black/white */
  187.   gst_buffer_memset (buffer, 0, ctx->white ? 0xff : 0x0, size);
  188.  
  189.   ctx->white = !ctx->white;
  190.  
  191.   /* increment the timestamp every 1/2 second */
  192.   GST_BUFFER_PTS (buffer) = ctx->timestamp;
  193.   g_print("PTS: %lf BASETIME %lf SUM %lf\n", (double) ctx->timestamp, (double) gst_element_get_base_time(appsrc),
  194.             ((double) ctx->timestamp) + ( (double) gst_element_get_base_time(appsrc)));
  195.  
  196.  
  197.   // add 0 to 20 ms delay
  198.   //int r = (rand() % 20);
  199.   // add controlled delay
  200.   int r = 0;
  201.   if (((predictable_seq++)%100)<10)
  202.   {
  203.       g_print("PREDICTABLE SEQUENCE STARTING\n");
  204.       g_print("#############################\n");
  205.       r = predictable_seq%100;
  206.   } else {
  207.       r = (rand() % 20);
  208.   }
  209.   g_print("Random delay: %d milliseconds (%lf ns)\n", r , (double) gst_util_uint64_scale_int (r, GST_MSECOND, 1));
  210.   GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 2) +
  211.                                     gst_util_uint64_scale_int (r, GST_MSECOND, 1);
  212.   ctx->timestamp += GST_BUFFER_DURATION (buffer);
  213.  
  214.  
  215.   g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
  216. }
  217.  
  218. /* called when a new media pipeline is constructed. We can query the
  219.  * pipeline and configure our appsrc */
  220. static void
  221. media_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media,
  222.     gpointer user_data)
  223. {
  224.   GstElement *element, *appsrc;
  225.   MyContext *ctx;
  226.  
  227.   /* get the element used for providing the streams of the media */
  228.   element = gst_rtsp_media_get_element (media);
  229.  
  230.   /* get our appsrc, we named it 'mysrc' with the name property */
  231.   appsrc = gst_bin_get_by_name_recurse_up (GST_BIN (element), "mysrc");
  232.  
  233.   /* this instructs appsrc that we will be dealing with timed buffer */
  234.   gst_util_set_object_arg (G_OBJECT (appsrc), "format", "time");
  235.   /* configure the caps of the video */
  236.   g_object_set (G_OBJECT (appsrc), "caps",
  237.       gst_caps_new_simple ("video/x-raw",
  238.           "format", G_TYPE_STRING, "RGB16",
  239.           "width", G_TYPE_INT, 384,
  240.           "height", G_TYPE_INT, 288,
  241.           "framerate", GST_TYPE_FRACTION, 0, 1, NULL), NULL);
  242.  
  243.   ctx = g_new0 (MyContext, 1);
  244.   ctx->white = FALSE;
  245.   ctx->timestamp = 0;
  246.   /* make sure ther datais freed when the media is gone */
  247.   g_object_set_data_full (G_OBJECT (media), "my-extra-data", ctx,
  248.       (GDestroyNotify) g_free);
  249.  
  250.   /* install the callback that will be called when a buffer is needed */
  251.   g_signal_connect (appsrc, "need-data", (GCallback) need_data, ctx);
  252.   gst_object_unref (appsrc);
  253.   gst_object_unref (element);
  254. }
  255.  
  256.  
  257. int
  258. main (int argc, char *argv[])
  259. {
  260.   GMainLoop *loop;
  261.   GstRTSPServer *server;
  262.   GstRTSPMountPoints *mounts;
  263.   GstRTSPMediaFactory *factory;
  264.  
  265.   gst_init (&argc, &argv);
  266.  
  267.   if (argc < 1) {
  268.     g_print ("usage: %s [portnum] \n"
  269.         "example: %s 8555 \n"
  270.         "Pipeline is fixed. Default port 8554\n",
  271.         argv[0], argv[0]);
  272.     return -1;
  273.   }
  274.  
  275.   loop = g_main_loop_new (NULL, FALSE);
  276.  
  277.   //global_clock = gst_system_clock_obtain ();
  278.   //gst_net_time_provider_new (global_clock, "0.0.0.0", 8554);
  279.  
  280.  
  281.   /* create a server instance */
  282.   server = gst_rtsp_server_new ();
  283.  
  284.   gint * portnum;
  285.   portnum = malloc(sizeof(gint));
  286.   *portnum = 8554;
  287.   if (argc == 2)
  288.   {
  289.     /* set server listening port*/
  290.     gst_rtsp_server_set_service (server,argv[1]);
  291.     *portnum = atoi(argv[1]);  
  292.   }
  293.  
  294.  
  295.   /* callback for clients */
  296.   g_signal_connect (server, "client-connected", G_CALLBACK (client_connection), portnum);
  297.  
  298.  
  299.   /* get the mount points for this server, every server has a default object
  300.    * that be used to map uri mount points to media factories */
  301.   mounts = gst_rtsp_server_get_mount_points (server);
  302.  
  303.   /* make a media factory for a test stream. The default media factory can use
  304.    * gst-launch syntax to create pipelines.
  305.    * any launch line works as long as it contains elements named pay%d. Each
  306.    * element with pay%d names will be a stream */
  307.   factory = test_rtsp_media_factory_new ();
  308.   gst_rtsp_media_factory_set_launch (factory,
  309.       "( appsrc name=mysrc ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96 )");
  310.  
  311.   g_signal_connect (factory, "media-configure", (GCallback) media_configure,
  312.       NULL);      
  313.      
  314.   gst_rtsp_media_factory_set_shared (GST_RTSP_MEDIA_FACTORY (factory), TRUE);
  315.   gst_rtsp_media_factory_set_media_gtype (GST_RTSP_MEDIA_FACTORY (factory),
  316.       TEST_TYPE_RTSP_MEDIA);
  317.  
  318.   /* attach the test factory to the /test url */
  319.   gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
  320.  
  321.   /* don't need the ref to the mapper anymore */
  322.   g_object_unref (mounts);
  323.  
  324.   /* attach the server to the default maincontext */
  325.   gst_rtsp_server_attach (server, NULL);
  326.  
  327.   /* start serving */
  328.   if (argc < 2)
  329.     g_print ("stream ready at rtsp://127.0.0.1:8554/test\n");
  330.   else
  331.   {
  332.     g_print ("stream ready at rtsp://127.0.0.1:");
  333.     g_print (argv[1]);
  334.     g_print ("/test\n");
  335.   }
  336.   g_main_loop_run (loop);
  337.  
  338.   return 0;
  339. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement