gst_plugins_base/tests/check/elements/multifdsink.c
changeset 0 0e761a78d257
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  *
       
     3  * Copyright (C) 2006 Thomas Vander Stichele <thomas at apestaart dot org>
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Library General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Library General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Library General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 #include <unistd.h>
       
    22 #include <sys/ioctl.h>
       
    23 #ifdef HAVE_FIONREAD_IN_SYS_FILIO
       
    24 #include <sys/filio.h>
       
    25 #endif
       
    26 
       
    27 #include <gst/check/gstcheck.h>
       
    28 
       
    29 static GstPad *mysrcpad;
       
    30 
       
    31 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
       
    32     GST_PAD_SRC,
       
    33     GST_PAD_ALWAYS,
       
    34     GST_STATIC_CAPS ("application/x-gst-check")
       
    35     );
       
    36 
       
    37 static GstElement *
       
    38 setup_multifdsink (void)
       
    39 {
       
    40   GstElement *multifdsink;
       
    41 
       
    42   GST_DEBUG ("setup_multifdsink");
       
    43   multifdsink = gst_check_setup_element ("multifdsink");
       
    44   mysrcpad = gst_check_setup_src_pad (multifdsink, &srctemplate, NULL);
       
    45 
       
    46   return multifdsink;
       
    47 }
       
    48 
       
    49 static void
       
    50 cleanup_multifdsink (GstElement * multifdsink)
       
    51 {
       
    52   GST_DEBUG ("cleanup_multifdsink");
       
    53 
       
    54   gst_check_teardown_src_pad (multifdsink);
       
    55   gst_check_teardown_element (multifdsink);
       
    56 }
       
    57 
       
    58 static void
       
    59 wait_bytes_served (GstElement * sink, guint64 bytes)
       
    60 {
       
    61   guint64 bytes_served = 0;
       
    62 
       
    63   while (bytes_served != bytes) {
       
    64     g_object_get (sink, "bytes-served", &bytes_served, NULL);
       
    65   }
       
    66 }
       
    67 
       
    68 /* FIXME: possibly racy, since if it would write, we may not get it
       
    69  * immediately ? */
       
    70 #define fail_if_can_read(msg,fd) \
       
    71 G_STMT_START { \
       
    72   long avail; \
       
    73 \
       
    74   fail_if (ioctl (fd, FIONREAD, &avail) < 0, "%s: could not ioctl", msg); \
       
    75   fail_if (avail > 0, "%s: has bytes available to read"); \
       
    76 } G_STMT_END;
       
    77 
       
    78 
       
    79 GST_START_TEST (test_no_clients)
       
    80 {
       
    81   GstElement *sink;
       
    82   GstBuffer *buffer;
       
    83   GstCaps *caps;
       
    84 
       
    85   sink = setup_multifdsink ();
       
    86 
       
    87   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
       
    88 
       
    89   caps = gst_caps_from_string ("application/x-gst-check");
       
    90   buffer = gst_buffer_new_and_alloc (4);
       
    91   gst_buffer_set_caps (buffer, caps);
       
    92   gst_caps_unref (caps);
       
    93   fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
    94 
       
    95   GST_DEBUG ("cleaning up multifdsink");
       
    96   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
       
    97   cleanup_multifdsink (sink);
       
    98 }
       
    99 
       
   100 GST_END_TEST;
       
   101 
       
   102 GST_START_TEST (test_add_client)
       
   103 {
       
   104   GstElement *sink;
       
   105   GstBuffer *buffer;
       
   106   GstCaps *caps;
       
   107   int pfd[2];
       
   108   gchar data[4];
       
   109 
       
   110   sink = setup_multifdsink ();
       
   111 
       
   112   fail_if (pipe (pfd) == -1);
       
   113 
       
   114   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
       
   115 
       
   116   /* add the client */
       
   117   g_signal_emit_by_name (sink, "add", pfd[1]);
       
   118 
       
   119   caps = gst_caps_from_string ("application/x-gst-check");
       
   120   GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps);
       
   121   buffer = gst_buffer_new_and_alloc (4);
       
   122   gst_buffer_set_caps (buffer, caps);
       
   123   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
       
   124   memcpy (GST_BUFFER_DATA (buffer), "dead", 4);
       
   125   fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
   126 
       
   127   GST_DEBUG ("reading");
       
   128   fail_if (read (pfd[0], data, 4) < 4);
       
   129   fail_unless (strncmp (data, "dead", 4) == 0);
       
   130   wait_bytes_served (sink, 4);
       
   131 
       
   132   GST_DEBUG ("cleaning up multifdsink");
       
   133   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
       
   134   cleanup_multifdsink (sink);
       
   135 
       
   136   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
       
   137   gst_caps_unref (caps);
       
   138 }
       
   139 
       
   140 GST_END_TEST;
       
   141 
       
   142 #define fail_unless_read(msg,fd,size,ref) \
       
   143 G_STMT_START { \
       
   144   char data[size + 1]; \
       
   145   int nbytes; \
       
   146 \
       
   147   GST_DEBUG ("%s: reading %d bytes", msg, size); \
       
   148   nbytes = read (fd, data, size); \
       
   149   data[size] = 0; \
       
   150   GST_DEBUG ("%s: read %d bytes", msg, nbytes); \
       
   151   fail_if (nbytes < size); \
       
   152   fail_unless (memcmp (data, ref, size) == 0, \
       
   153       "data read '%s' differs from '%s'", data, ref); \
       
   154 } G_STMT_END;
       
   155 
       
   156 /* from the given two data buffers, create two streamheader buffers and
       
   157  * some caps that match it, and store them in the given pointers
       
   158  * returns  one ref to each of the buffers and the caps */
       
   159 static void
       
   160 gst_multifdsink_create_streamheader (const gchar * data1,
       
   161     const gchar * data2, GstBuffer ** hbuf1, GstBuffer ** hbuf2,
       
   162     GstCaps ** caps)
       
   163 {
       
   164   GstBuffer *buf;
       
   165   GValue array = { 0 };
       
   166   GValue value = { 0 };
       
   167   GstStructure *structure;
       
   168   guint size1 = strlen (data1);
       
   169   guint size2 = strlen (data2);
       
   170 
       
   171   fail_if (hbuf1 == NULL);
       
   172   fail_if (hbuf2 == NULL);
       
   173   fail_if (caps == NULL);
       
   174 
       
   175   /* create caps with streamheader, set the caps, and push the IN_CAPS
       
   176    * buffers */
       
   177   *hbuf1 = gst_buffer_new_and_alloc (size1);
       
   178   GST_BUFFER_FLAG_SET (*hbuf1, GST_BUFFER_FLAG_IN_CAPS);
       
   179   memcpy (GST_BUFFER_DATA (*hbuf1), data1, size1);
       
   180   *hbuf2 = gst_buffer_new_and_alloc (size2);
       
   181   GST_BUFFER_FLAG_SET (*hbuf2, GST_BUFFER_FLAG_IN_CAPS);
       
   182   memcpy (GST_BUFFER_DATA (*hbuf2), data2, size2);
       
   183   /* we want to keep them around for the tests */
       
   184   gst_buffer_ref (*hbuf1);
       
   185   gst_buffer_ref (*hbuf2);
       
   186 
       
   187   g_value_init (&array, GST_TYPE_ARRAY);
       
   188 
       
   189   g_value_init (&value, GST_TYPE_BUFFER);
       
   190   /* we take a copy, set it on the array (which refs it), then unref our copy */
       
   191   buf = gst_buffer_copy (*hbuf1);
       
   192   gst_value_set_buffer (&value, buf);
       
   193   ASSERT_BUFFER_REFCOUNT (buf, "copied buffer", 2);
       
   194   gst_buffer_unref (buf);
       
   195   gst_value_array_append_value (&array, &value);
       
   196   g_value_unset (&value);
       
   197 
       
   198   g_value_init (&value, GST_TYPE_BUFFER);
       
   199   buf = gst_buffer_copy (*hbuf2);
       
   200   gst_value_set_buffer (&value, buf);
       
   201   ASSERT_BUFFER_REFCOUNT (buf, "copied buffer", 2);
       
   202   gst_buffer_unref (buf);
       
   203   gst_value_array_append_value (&array, &value);
       
   204   g_value_unset (&value);
       
   205 
       
   206   *caps = gst_caps_from_string ("application/x-gst-check");
       
   207   structure = gst_caps_get_structure (*caps, 0);
       
   208 
       
   209   gst_structure_set_value (structure, "streamheader", &array);
       
   210   g_value_unset (&array);
       
   211   ASSERT_CAPS_REFCOUNT (*caps, "streamheader caps", 1);
       
   212 
       
   213   /* set our streamheadery caps on the buffers */
       
   214   gst_buffer_set_caps (*hbuf1, *caps);
       
   215   gst_buffer_set_caps (*hbuf2, *caps);
       
   216   ASSERT_CAPS_REFCOUNT (*caps, "streamheader caps", 3);
       
   217 
       
   218   GST_DEBUG ("created streamheader caps %p %" GST_PTR_FORMAT, *caps, *caps);
       
   219 }
       
   220 
       
   221 
       
   222 /* this test:
       
   223  * - adds a first client
       
   224  * - sets streamheader caps on the pad
       
   225  * - pushes the IN_CAPS buffers
       
   226  * - pushes a buffer
       
   227  * - verifies that the client received all the data correctly, and did not
       
   228  *   get multiple copies of the streamheader
       
   229  * - adds a second client
       
   230  * - verifies that this second client receives the streamheader caps too, plus
       
   231  * - the new buffer
       
   232  */
       
   233 GST_START_TEST (test_streamheader)
       
   234 {
       
   235   GstElement *sink;
       
   236   GstBuffer *hbuf1, *hbuf2, *buf;
       
   237   GstCaps *caps;
       
   238   int pfd1[2], pfd2[2];
       
   239 
       
   240   sink = setup_multifdsink ();
       
   241 
       
   242   fail_if (pipe (pfd1) == -1);
       
   243   fail_if (pipe (pfd2) == -1);
       
   244 
       
   245   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
       
   246 
       
   247   /* add the first client */
       
   248   g_signal_emit_by_name (sink, "add", pfd1[1]);
       
   249 
       
   250   /* create caps with streamheader, set the caps, and push the IN_CAPS
       
   251    * buffers */
       
   252   gst_multifdsink_create_streamheader ("babe", "deadbeef", &hbuf1, &hbuf2,
       
   253       &caps);
       
   254   fail_unless (gst_pad_set_caps (mysrcpad, caps));
       
   255   /* one is ours, two on the buffers, and one now on the pad */
       
   256   ASSERT_CAPS_REFCOUNT (caps, "caps", 4);
       
   257 
       
   258   fail_unless (gst_pad_push (mysrcpad, hbuf1) == GST_FLOW_OK);
       
   259   fail_unless (gst_pad_push (mysrcpad, hbuf2) == GST_FLOW_OK);
       
   260 
       
   261   //FIXME:
       
   262   //fail_if_can_read ("first client", pfd1[0]);
       
   263 
       
   264   /* push a non-IN_CAPS buffer, this should trigger the client receiving the
       
   265    * first three buffers */
       
   266   buf = gst_buffer_new_and_alloc (4);
       
   267   memcpy (GST_BUFFER_DATA (buf), "f00d", 4);
       
   268   gst_pad_push (mysrcpad, buf);
       
   269 
       
   270   fail_unless_read ("first client", pfd1[0], 4, "babe");
       
   271   fail_unless_read ("first client", pfd1[0], 8, "deadbeef");
       
   272   fail_unless_read ("first client", pfd1[0], 4, "f00d");
       
   273   wait_bytes_served (sink, 16);
       
   274 
       
   275   /* now add the second client */
       
   276   g_signal_emit_by_name (sink, "add", pfd2[1]);
       
   277   //FIXME:
       
   278   //fail_if_can_read ("second client", pfd2[0]);
       
   279 
       
   280   /* now push another buffer, which will trigger streamheader for second
       
   281    * client */
       
   282   buf = gst_buffer_new_and_alloc (4);
       
   283   memcpy (GST_BUFFER_DATA (buf), "deaf", 4);
       
   284   gst_pad_push (mysrcpad, buf);
       
   285 
       
   286   fail_unless_read ("first client", pfd1[0], 4, "deaf");
       
   287 
       
   288   fail_unless_read ("second client", pfd2[0], 4, "babe");
       
   289   fail_unless_read ("second client", pfd2[0], 8, "deadbeef");
       
   290   /* we missed the f00d buffer */
       
   291   fail_unless_read ("second client", pfd2[0], 4, "deaf");
       
   292   wait_bytes_served (sink, 36);
       
   293 
       
   294   GST_DEBUG ("cleaning up multifdsink");
       
   295 
       
   296   g_signal_emit_by_name (sink, "remove", pfd1[1]);
       
   297   g_signal_emit_by_name (sink, "remove", pfd2[1]);
       
   298 
       
   299   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
       
   300   cleanup_multifdsink (sink);
       
   301 
       
   302   ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 1);
       
   303   ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 1);
       
   304   gst_buffer_unref (hbuf1);
       
   305   gst_buffer_unref (hbuf2);
       
   306 
       
   307   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
       
   308   gst_caps_unref (caps);
       
   309 }
       
   310 
       
   311 GST_END_TEST;
       
   312 
       
   313 /* this tests changing of streamheaders
       
   314  * - set streamheader caps on the pad
       
   315  * - pushes the IN_CAPS buffers
       
   316  * - pushes a buffer
       
   317  * - add a first client
       
   318  * - verifies that this first client receives the first streamheader caps,
       
   319  *   plus a new buffer
       
   320  * - change streamheader caps
       
   321  * - verify that the first client receives the new streamheader buffers as well
       
   322  */
       
   323 GST_START_TEST (test_change_streamheader)
       
   324 {
       
   325   GstElement *sink;
       
   326   GstBuffer *hbuf1, *hbuf2, *buf;
       
   327   GstCaps *caps;
       
   328   int pfd1[2], pfd2[2];
       
   329 
       
   330   sink = setup_multifdsink ();
       
   331 
       
   332   fail_if (pipe (pfd1) == -1);
       
   333   fail_if (pipe (pfd2) == -1);
       
   334 
       
   335   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
       
   336 
       
   337   /* create caps with streamheader, set the caps, and push the IN_CAPS
       
   338    * buffers */
       
   339   gst_multifdsink_create_streamheader ("first", "header", &hbuf1, &hbuf2,
       
   340       &caps);
       
   341   fail_unless (gst_pad_set_caps (mysrcpad, caps));
       
   342   /* one is ours, two on the buffers, and one now on the pad */
       
   343   ASSERT_CAPS_REFCOUNT (caps, "caps", 4);
       
   344 
       
   345   /* one to hold for the test and one to give away */
       
   346   ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 2);
       
   347   ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 2);
       
   348 
       
   349   fail_unless (gst_pad_push (mysrcpad, hbuf1) == GST_FLOW_OK);
       
   350   fail_unless (gst_pad_push (mysrcpad, hbuf2) == GST_FLOW_OK);
       
   351 
       
   352   /* add the first client */
       
   353   g_signal_emit_by_name (sink, "add", pfd1[1]);
       
   354 
       
   355   /* verify this hasn't triggered a write yet */
       
   356   /* FIXME: possibly racy, since if it would write, we may not get it
       
   357    * immediately ? */
       
   358   //fail_if_can_read ("first client, no buffer", pfd1[0]);
       
   359 
       
   360   /* now push a buffer and read */
       
   361   buf = gst_buffer_new_and_alloc (4);
       
   362   memcpy (GST_BUFFER_DATA (buf), "f00d", 4);
       
   363   gst_pad_push (mysrcpad, buf);
       
   364 
       
   365   fail_unless_read ("change: first client", pfd1[0], 5, "first");
       
   366   fail_unless_read ("change: first client", pfd1[0], 6, "header");
       
   367   fail_unless_read ("change: first client", pfd1[0], 4, "f00d");
       
   368   //wait_bytes_served (sink, 16);
       
   369 
       
   370   /* now add the second client */
       
   371   g_signal_emit_by_name (sink, "add", pfd2[1]);
       
   372   //fail_if_can_read ("second client, no buffer", pfd2[0]);
       
   373 
       
   374   /* change the streamheader */
       
   375 
       
   376   /* before we change, multifdsink still has a list of the old streamheaders */
       
   377   ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 2);
       
   378   ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 2);
       
   379   gst_buffer_unref (hbuf1);
       
   380   gst_buffer_unref (hbuf2);
       
   381 
       
   382   /* drop our ref to the previous caps */
       
   383   gst_caps_unref (caps);
       
   384 
       
   385   gst_multifdsink_create_streamheader ("second", "header", &hbuf1, &hbuf2,
       
   386       &caps);
       
   387   fail_unless (gst_pad_set_caps (mysrcpad, caps));
       
   388   /* one to hold for the test and one to give away */
       
   389   ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 2);
       
   390   ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 2);
       
   391 
       
   392   fail_unless (gst_pad_push (mysrcpad, hbuf1) == GST_FLOW_OK);
       
   393   fail_unless (gst_pad_push (mysrcpad, hbuf2) == GST_FLOW_OK);
       
   394 
       
   395   /* verify neither client has new data available to read */
       
   396   //fail_if_can_read ("first client, changed streamheader", pfd1[0]);
       
   397   //fail_if_can_read ("second client, changed streamheader", pfd2[0]);
       
   398 
       
   399   /* now push another buffer, which will trigger streamheader for second
       
   400    * client, but should also send new streamheaders to first client */
       
   401   buf = gst_buffer_new_and_alloc (8);
       
   402   memcpy (GST_BUFFER_DATA (buf), "deadbabe", 8);
       
   403   gst_pad_push (mysrcpad, buf);
       
   404 
       
   405   fail_unless_read ("first client", pfd1[0], 6, "second");
       
   406   fail_unless_read ("first client", pfd1[0], 6, "header");
       
   407   fail_unless_read ("first client", pfd1[0], 8, "deadbabe");
       
   408 
       
   409   /* new streamheader data */
       
   410   fail_unless_read ("second client", pfd2[0], 6, "second");
       
   411   fail_unless_read ("second client", pfd2[0], 6, "header");
       
   412   /* we missed the f00d buffer */
       
   413   fail_unless_read ("second client", pfd2[0], 8, "deadbabe");
       
   414   //wait_bytes_served (sink, 36);
       
   415 
       
   416   GST_DEBUG ("cleaning up multifdsink");
       
   417   g_signal_emit_by_name (sink, "remove", pfd1[1]);
       
   418   g_signal_emit_by_name (sink, "remove", pfd2[1]);
       
   419   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
       
   420 
       
   421   /* setting to NULL should have cleared the streamheader */
       
   422   ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 1);
       
   423   ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 1);
       
   424   gst_buffer_unref (hbuf1);
       
   425   gst_buffer_unref (hbuf2);
       
   426   cleanup_multifdsink (sink);
       
   427 
       
   428   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
       
   429   gst_caps_unref (caps);
       
   430 }
       
   431 
       
   432 GST_END_TEST;
       
   433 
       
   434 /* keep 100 bytes and burst 80 bytes to clients */
       
   435 GST_START_TEST (test_burst_client_bytes)
       
   436 {
       
   437   GstElement *sink;
       
   438   GstBuffer *buffer;
       
   439   GstCaps *caps;
       
   440   int pfd1[2];
       
   441   int pfd2[2];
       
   442   int pfd3[2];
       
   443   gchar data[16];
       
   444   gint i;
       
   445   guint buffers_queued;
       
   446 
       
   447   sink = setup_multifdsink ();
       
   448   /* make sure we keep at least 100 bytes at all times */
       
   449   g_object_set (sink, "bytes-min", 100, NULL);
       
   450   g_object_set (sink, "sync-method", 3, NULL);  /* 3 = burst */
       
   451   g_object_set (sink, "burst-unit", 3, NULL);   /* 3 = bytes */
       
   452   g_object_set (sink, "burst-value", (guint64) 80, NULL);
       
   453 
       
   454   fail_if (pipe (pfd1) == -1);
       
   455   fail_if (pipe (pfd2) == -1);
       
   456   fail_if (pipe (pfd3) == -1);
       
   457 
       
   458   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
       
   459 
       
   460   caps = gst_caps_from_string ("application/x-gst-check");
       
   461   GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps);
       
   462 
       
   463   /* push buffers in, 9 * 16 bytes = 144 bytes */
       
   464   for (i = 0; i < 9; i++) {
       
   465     gchar *data;
       
   466 
       
   467     buffer = gst_buffer_new_and_alloc (16);
       
   468     gst_buffer_set_caps (buffer, caps);
       
   469 
       
   470     /* copy some id */
       
   471     data = (gchar *) GST_BUFFER_DATA (buffer);
       
   472     g_snprintf (data, 16, "deadbee%08x", i);
       
   473 
       
   474     fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
   475   }
       
   476 
       
   477   /* check that at least 7 buffers (112 bytes) are in the queue */
       
   478   g_object_get (sink, "buffers-queued", &buffers_queued, NULL);
       
   479   fail_if (buffers_queued != 7);
       
   480 
       
   481   /* now add the clients */
       
   482   g_signal_emit_by_name (sink, "add", pfd1[1]);
       
   483   g_signal_emit_by_name (sink, "add_full", pfd2[1], 3,
       
   484       3, (guint64) 50, 3, (guint64) 200);
       
   485   g_signal_emit_by_name (sink, "add_full", pfd3[1], 3,
       
   486       3, (guint64) 50, 3, (guint64) 50);
       
   487 
       
   488   /* push last buffer to make client fds ready for reading */
       
   489   for (i = 9; i < 10; i++) {
       
   490     gchar *data;
       
   491 
       
   492     buffer = gst_buffer_new_and_alloc (16);
       
   493     gst_buffer_set_caps (buffer, caps);
       
   494 
       
   495     /* copy some id */
       
   496     data = (gchar *) GST_BUFFER_DATA (buffer);
       
   497     g_snprintf (data, 16, "deadbee%08x", i);
       
   498 
       
   499     fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
   500   }
       
   501 
       
   502   /* now we should only read the last 5 buffers (5 * 16 = 80 bytes) */
       
   503   GST_DEBUG ("Reading from client 1");
       
   504   fail_if (read (pfd1[0], data, 16) < 16);
       
   505   fail_unless (strncmp (data, "deadbee00000005", 16) == 0);
       
   506   fail_if (read (pfd1[0], data, 16) < 16);
       
   507   fail_unless (strncmp (data, "deadbee00000006", 16) == 0);
       
   508   fail_if (read (pfd1[0], data, 16) < 16);
       
   509   fail_unless (strncmp (data, "deadbee00000007", 16) == 0);
       
   510   fail_if (read (pfd1[0], data, 16) < 16);
       
   511   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   512   fail_if (read (pfd1[0], data, 16) < 16);
       
   513   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   514 
       
   515   /* second client only bursts 50 bytes = 4 buffers (we get 4 buffers since
       
   516    * the max alows it) */
       
   517   GST_DEBUG ("Reading from client 2");
       
   518   fail_if (read (pfd2[0], data, 16) < 16);
       
   519   fail_unless (strncmp (data, "deadbee00000006", 16) == 0);
       
   520   fail_if (read (pfd2[0], data, 16) < 16);
       
   521   fail_unless (strncmp (data, "deadbee00000007", 16) == 0);
       
   522   fail_if (read (pfd2[0], data, 16) < 16);
       
   523   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   524   fail_if (read (pfd2[0], data, 16) < 16);
       
   525   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   526 
       
   527   /* third client only bursts 50 bytes = 4 buffers, we can't send
       
   528    * more than 50 bytes so we only get 3 buffers (48 bytes). */
       
   529   GST_DEBUG ("Reading from client 3");
       
   530   fail_if (read (pfd3[0], data, 16) < 16);
       
   531   fail_unless (strncmp (data, "deadbee00000007", 16) == 0);
       
   532   fail_if (read (pfd3[0], data, 16) < 16);
       
   533   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   534   fail_if (read (pfd3[0], data, 16) < 16);
       
   535   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   536 
       
   537   GST_DEBUG ("cleaning up multifdsink");
       
   538   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
       
   539   cleanup_multifdsink (sink);
       
   540 
       
   541   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
       
   542   gst_caps_unref (caps);
       
   543 }
       
   544 
       
   545 GST_END_TEST;
       
   546 
       
   547 /* keep 100 bytes and burst 80 bytes to clients */
       
   548 GST_START_TEST (test_burst_client_bytes_keyframe)
       
   549 {
       
   550   GstElement *sink;
       
   551   GstBuffer *buffer;
       
   552   GstCaps *caps;
       
   553   int pfd1[2];
       
   554   int pfd2[2];
       
   555   int pfd3[2];
       
   556   gchar data[16];
       
   557   gint i;
       
   558   guint buffers_queued;
       
   559 
       
   560   sink = setup_multifdsink ();
       
   561   /* make sure we keep at least 100 bytes at all times */
       
   562   g_object_set (sink, "bytes-min", 100, NULL);
       
   563   g_object_set (sink, "sync-method", 4, NULL);  /* 3 = burst_keyframe */
       
   564   g_object_set (sink, "burst-unit", 3, NULL);   /* 3 = bytes */
       
   565   g_object_set (sink, "burst-value", (guint64) 80, NULL);
       
   566 
       
   567   fail_if (pipe (pfd1) == -1);
       
   568   fail_if (pipe (pfd2) == -1);
       
   569   fail_if (pipe (pfd3) == -1);
       
   570 
       
   571   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
       
   572 
       
   573   caps = gst_caps_from_string ("application/x-gst-check");
       
   574   GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps);
       
   575 
       
   576   /* push buffers in, 9 * 16 bytes = 144 bytes */
       
   577   for (i = 0; i < 9; i++) {
       
   578     gchar *data;
       
   579 
       
   580     buffer = gst_buffer_new_and_alloc (16);
       
   581     gst_buffer_set_caps (buffer, caps);
       
   582 
       
   583     /* mark most buffers as delta */
       
   584     if (i != 0 && i != 4 && i != 8)
       
   585       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
       
   586 
       
   587     /* copy some id */
       
   588     data = (gchar *) GST_BUFFER_DATA (buffer);
       
   589     g_snprintf (data, 16, "deadbee%08x", i);
       
   590 
       
   591     fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
   592   }
       
   593 
       
   594   /* check that at least 7 buffers (112 bytes) are in the queue */
       
   595   g_object_get (sink, "buffers-queued", &buffers_queued, NULL);
       
   596   fail_if (buffers_queued != 7);
       
   597 
       
   598   /* now add the clients */
       
   599   g_signal_emit_by_name (sink, "add", pfd1[1]);
       
   600   g_signal_emit_by_name (sink, "add_full", pfd2[1], 4,
       
   601       3, (guint64) 50, 3, (guint64) 90);
       
   602   g_signal_emit_by_name (sink, "add_full", pfd3[1], 4,
       
   603       3, (guint64) 50, 3, (guint64) 50);
       
   604 
       
   605   /* push last buffer to make client fds ready for reading */
       
   606   for (i = 9; i < 10; i++) {
       
   607     gchar *data;
       
   608 
       
   609     buffer = gst_buffer_new_and_alloc (16);
       
   610     gst_buffer_set_caps (buffer, caps);
       
   611     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
       
   612 
       
   613     /* copy some id */
       
   614     data = (gchar *) GST_BUFFER_DATA (buffer);
       
   615     g_snprintf (data, 16, "deadbee%08x", i);
       
   616 
       
   617     fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
   618   }
       
   619 
       
   620   /* now we should only read the last 6 buffers (min 5 * 16 = 80 bytes),
       
   621    * keyframe at buffer 4 */
       
   622   GST_DEBUG ("Reading from client 1");
       
   623   fail_if (read (pfd1[0], data, 16) < 16);
       
   624   fail_unless (strncmp (data, "deadbee00000004", 16) == 0);
       
   625   fail_if (read (pfd1[0], data, 16) < 16);
       
   626   fail_unless (strncmp (data, "deadbee00000005", 16) == 0);
       
   627   fail_if (read (pfd1[0], data, 16) < 16);
       
   628   fail_unless (strncmp (data, "deadbee00000006", 16) == 0);
       
   629   fail_if (read (pfd1[0], data, 16) < 16);
       
   630   fail_unless (strncmp (data, "deadbee00000007", 16) == 0);
       
   631   fail_if (read (pfd1[0], data, 16) < 16);
       
   632   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   633   fail_if (read (pfd1[0], data, 16) < 16);
       
   634   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   635 
       
   636   /* second client only bursts 50 bytes = 4 buffers, there is
       
   637    * no keyframe above min and below max, so get one below min */
       
   638   GST_DEBUG ("Reading from client 2");
       
   639   fail_if (read (pfd2[0], data, 16) < 16);
       
   640   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   641   fail_if (read (pfd2[0], data, 16) < 16);
       
   642   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   643 
       
   644   /* third client only bursts 50 bytes = 4 buffers, we can't send
       
   645    * more than 50 bytes so we only get 2 buffers (32 bytes). */
       
   646   GST_DEBUG ("Reading from client 3");
       
   647   fail_if (read (pfd3[0], data, 16) < 16);
       
   648   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   649   fail_if (read (pfd3[0], data, 16) < 16);
       
   650   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   651 
       
   652   GST_DEBUG ("cleaning up multifdsink");
       
   653   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
       
   654   cleanup_multifdsink (sink);
       
   655 
       
   656   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
       
   657   gst_caps_unref (caps);
       
   658 }
       
   659 
       
   660 GST_END_TEST;
       
   661 
       
   662 /* keep 100 bytes and burst 80 bytes to clients */
       
   663 GST_START_TEST (test_burst_client_bytes_with_keyframe)
       
   664 {
       
   665   GstElement *sink;
       
   666   GstBuffer *buffer;
       
   667   GstCaps *caps;
       
   668   int pfd1[2];
       
   669   int pfd2[2];
       
   670   int pfd3[2];
       
   671   gchar data[16];
       
   672   gint i;
       
   673   guint buffers_queued;
       
   674 
       
   675   sink = setup_multifdsink ();
       
   676   /* make sure we keep at least 100 bytes at all times */
       
   677   g_object_set (sink, "bytes-min", 100, NULL);
       
   678   g_object_set (sink, "sync-method", 5, NULL);  /* 3 = burst_with_keyframe */
       
   679   g_object_set (sink, "burst-unit", 3, NULL);   /* 3 = bytes */
       
   680   g_object_set (sink, "burst-value", (guint64) 80, NULL);
       
   681 
       
   682   fail_if (pipe (pfd1) == -1);
       
   683   fail_if (pipe (pfd2) == -1);
       
   684   fail_if (pipe (pfd3) == -1);
       
   685 
       
   686   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
       
   687 
       
   688   caps = gst_caps_from_string ("application/x-gst-check");
       
   689   GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps);
       
   690 
       
   691   /* push buffers in, 9 * 16 bytes = 144 bytes */
       
   692   for (i = 0; i < 9; i++) {
       
   693     gchar *data;
       
   694 
       
   695     buffer = gst_buffer_new_and_alloc (16);
       
   696     gst_buffer_set_caps (buffer, caps);
       
   697 
       
   698     /* mark most buffers as delta */
       
   699     if (i != 0 && i != 4 && i != 8)
       
   700       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
       
   701 
       
   702     /* copy some id */
       
   703     data = (gchar *) GST_BUFFER_DATA (buffer);
       
   704     g_snprintf (data, 16, "deadbee%08x", i);
       
   705 
       
   706     fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
   707   }
       
   708 
       
   709   /* check that at least 7 buffers (112 bytes) are in the queue */
       
   710   g_object_get (sink, "buffers-queued", &buffers_queued, NULL);
       
   711   fail_if (buffers_queued != 7);
       
   712 
       
   713   /* now add the clients */
       
   714   g_signal_emit_by_name (sink, "add", pfd1[1]);
       
   715   g_signal_emit_by_name (sink, "add_full", pfd2[1], 5,
       
   716       3, (guint64) 50, 3, (guint64) 90);
       
   717   g_signal_emit_by_name (sink, "add_full", pfd3[1], 5,
       
   718       3, (guint64) 50, 3, (guint64) 50);
       
   719 
       
   720   /* push last buffer to make client fds ready for reading */
       
   721   for (i = 9; i < 10; i++) {
       
   722     gchar *data;
       
   723 
       
   724     buffer = gst_buffer_new_and_alloc (16);
       
   725     gst_buffer_set_caps (buffer, caps);
       
   726     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
       
   727 
       
   728     /* copy some id */
       
   729     data = (gchar *) GST_BUFFER_DATA (buffer);
       
   730     g_snprintf (data, 16, "deadbee%08x", i);
       
   731 
       
   732     fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
   733   }
       
   734 
       
   735   /* now we should only read the last 6 buffers (min 5 * 16 = 80 bytes),
       
   736    * keyframe at buffer 4 */
       
   737   GST_DEBUG ("Reading from client 1");
       
   738   fail_if (read (pfd1[0], data, 16) < 16);
       
   739   fail_unless (strncmp (data, "deadbee00000004", 16) == 0);
       
   740   fail_if (read (pfd1[0], data, 16) < 16);
       
   741   fail_unless (strncmp (data, "deadbee00000005", 16) == 0);
       
   742   fail_if (read (pfd1[0], data, 16) < 16);
       
   743   fail_unless (strncmp (data, "deadbee00000006", 16) == 0);
       
   744   fail_if (read (pfd1[0], data, 16) < 16);
       
   745   fail_unless (strncmp (data, "deadbee00000007", 16) == 0);
       
   746   fail_if (read (pfd1[0], data, 16) < 16);
       
   747   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   748   fail_if (read (pfd1[0], data, 16) < 16);
       
   749   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   750 
       
   751   /* second client only bursts 50 bytes = 4 buffers, there is
       
   752    * no keyframe above min and below max, so send min */
       
   753   GST_DEBUG ("Reading from client 2");
       
   754   fail_if (read (pfd2[0], data, 16) < 16);
       
   755   fail_unless (strncmp (data, "deadbee00000006", 16) == 0);
       
   756   fail_if (read (pfd2[0], data, 16) < 16);
       
   757   fail_unless (strncmp (data, "deadbee00000007", 16) == 0);
       
   758   fail_if (read (pfd2[0], data, 16) < 16);
       
   759   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   760   fail_if (read (pfd2[0], data, 16) < 16);
       
   761   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   762 
       
   763   /* third client only bursts 50 bytes = 4 buffers, we can't send
       
   764    * more than 50 bytes so we only get 3 buffers (48 bytes). */
       
   765   GST_DEBUG ("Reading from client 3");
       
   766   fail_if (read (pfd3[0], data, 16) < 16);
       
   767   fail_unless (strncmp (data, "deadbee00000007", 16) == 0);
       
   768   fail_if (read (pfd3[0], data, 16) < 16);
       
   769   fail_unless (strncmp (data, "deadbee00000008", 16) == 0);
       
   770   fail_if (read (pfd3[0], data, 16) < 16);
       
   771   fail_unless (strncmp (data, "deadbee00000009", 16) == 0);
       
   772 
       
   773   GST_DEBUG ("cleaning up multifdsink");
       
   774   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
       
   775   cleanup_multifdsink (sink);
       
   776 
       
   777   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
       
   778   gst_caps_unref (caps);
       
   779 }
       
   780 
       
   781 GST_END_TEST;
       
   782 
       
   783 /* Check that we can get data when multifdsink is configured in next-keyframe
       
   784  * mode */
       
   785 GST_START_TEST (test_client_next_keyframe)
       
   786 {
       
   787   GstElement *sink;
       
   788   GstBuffer *buffer;
       
   789   GstCaps *caps;
       
   790   int pfd1[2];
       
   791   gchar data[16];
       
   792   gint i;
       
   793 
       
   794   sink = setup_multifdsink ();
       
   795   g_object_set (sink, "sync-method", 1, NULL);  /* 1 = next-keyframe */
       
   796 
       
   797   fail_if (pipe (pfd1) == -1);
       
   798 
       
   799   ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC);
       
   800 
       
   801   caps = gst_caps_from_string ("application/x-gst-check");
       
   802   GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps);
       
   803 
       
   804   /* now add our client */
       
   805   g_signal_emit_by_name (sink, "add", pfd1[1]);
       
   806 
       
   807   /* push buffers in: keyframe, then non-keyframe */
       
   808   for (i = 0; i < 2; i++) {
       
   809     gchar *data;
       
   810 
       
   811     buffer = gst_buffer_new_and_alloc (16);
       
   812     gst_buffer_set_caps (buffer, caps);
       
   813 
       
   814     /* copy some id */
       
   815     data = (gchar *) GST_BUFFER_DATA (buffer);
       
   816     g_snprintf (data, 16, "deadbee%08x", i);
       
   817     if (i > 0)
       
   818       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
       
   819 
       
   820     fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
       
   821   }
       
   822 
       
   823   /* now we should be able to read some data */
       
   824   GST_DEBUG ("Reading from client 1");
       
   825   fail_if (read (pfd1[0], data, 16) < 16);
       
   826   fail_unless (strncmp (data, "deadbee00000000", 16) == 0);
       
   827   fail_if (read (pfd1[0], data, 16) < 16);
       
   828   fail_unless (strncmp (data, "deadbee00000001", 16) == 0);
       
   829 
       
   830   GST_DEBUG ("cleaning up multifdsink");
       
   831   ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS);
       
   832   cleanup_multifdsink (sink);
       
   833 
       
   834   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
       
   835   gst_caps_unref (caps);
       
   836 }
       
   837 
       
   838 GST_END_TEST;
       
   839 
       
   840 /* FIXME: add test simulating chained oggs where:
       
   841  * sync-method is burst-on-connect
       
   842  * (when multifdsink actually does burst-on-connect based on byte size, not
       
   843    "last keyframe" which any frame for audio :))
       
   844  * an old client still needs to read from before the new streamheaders
       
   845  * a new client gets the new streamheaders
       
   846  */
       
   847 static Suite *
       
   848 multifdsink_suite (void)
       
   849 {
       
   850   Suite *s = suite_create ("multifdsink");
       
   851   TCase *tc_chain = tcase_create ("general");
       
   852 
       
   853   suite_add_tcase (s, tc_chain);
       
   854   tcase_add_test (tc_chain, test_no_clients);
       
   855   tcase_add_test (tc_chain, test_add_client);
       
   856   tcase_add_test (tc_chain, test_streamheader);
       
   857   tcase_add_test (tc_chain, test_change_streamheader);
       
   858   tcase_add_test (tc_chain, test_burst_client_bytes);
       
   859   tcase_add_test (tc_chain, test_burst_client_bytes_keyframe);
       
   860   tcase_add_test (tc_chain, test_burst_client_bytes_with_keyframe);
       
   861   tcase_add_test (tc_chain, test_client_next_keyframe);
       
   862 
       
   863   return s;
       
   864 }
       
   865 
       
   866 int
       
   867 main (int argc, char **argv)
       
   868 {
       
   869   int nf;
       
   870 
       
   871   Suite *s = multifdsink_suite ();
       
   872   SRunner *sr = srunner_create (s);
       
   873 
       
   874   gst_check_init (&argc, &argv);
       
   875 
       
   876   srunner_run_all (sr, CK_NORMAL);
       
   877   nf = srunner_ntests_failed (sr);
       
   878   srunner_free (sr);
       
   879 
       
   880   return nf;
       
   881 }