"Fossies" - the Fresh Open Source Software Archive

Member "gstreamer-1.16.1/tests/check/elements/filesink.c" (19 Apr 2019, 20102 Bytes) of package /linux/misc/gstreamer-1.16.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "filesink.c": 1.14.4_vs_1.16.0.

    1 /* GStreamer unit test for the filesink element
    2  *
    3  * Copyright (C) 2006 Thomas Vander Stichele <thomas at apestaart dot org>
    4  * Copyright (C) 2007 Tim-Philipp Müller <tim centricular net>
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Library General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 2 of the License, or (at your option) any later version.
   10  *
   11  * This library is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14  * Library General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU Library General Public
   17  * License along with this library; if not, write to the
   18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
   19  * Boston, MA 02110-1301, USA.
   20  */
   21 
   22 #ifdef HAVE_CONFIG_H
   23 #include "config.h"
   24 #endif
   25 
   26 #include <stdio.h>
   27 
   28 #include <glib.h>
   29 #include <glib/gstdio.h>
   30 
   31 #include <gst/check/gstcheck.h>
   32 
   33 static GstPad *mysrcpad;
   34 static gboolean sync_buffers = FALSE;
   35 
   36 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
   37     GST_PAD_SRC,
   38     GST_PAD_ALWAYS,
   39     GST_STATIC_CAPS_ANY);
   40 
   41 static GstElement *
   42 setup_filesink (void)
   43 {
   44   GstElement *filesink;
   45 
   46   GST_DEBUG ("setup_filesink");
   47   filesink = gst_check_setup_element ("filesink");
   48   mysrcpad = gst_check_setup_src_pad (filesink, &srctemplate);
   49   gst_pad_set_active (mysrcpad, TRUE);
   50   return filesink;
   51 }
   52 
   53 static void
   54 cleanup_filesink (GstElement * filesink)
   55 {
   56   gst_pad_set_active (mysrcpad, FALSE);
   57   gst_check_teardown_src_pad (filesink);
   58   gst_check_teardown_element (filesink);
   59 }
   60 
   61 #if 0
   62 /* this queries via the element vfunc, which is currently not implemented */
   63 #define CHECK_QUERY_POSITION(filesink,format,position)                  \
   64     G_STMT_START {                                                       \
   65       gint64 pos;                                                        \
   66       fail_unless (gst_element_query_position (filesink, format, &pos)); \
   67       fail_unless_equals_int (pos, position);                            \
   68     } G_STMT_END
   69 #else
   70 #define CHECK_QUERY_POSITION(filesink,format,position)                   \
   71     G_STMT_START {                                                       \
   72       GstPad *pad;                                                       \
   73       gint64 pos;                                                        \
   74       pad = gst_element_get_static_pad (filesink, "sink");               \
   75       fail_unless (gst_pad_query_position (pad, format, &pos));          \
   76       fail_unless_equals_int (pos, position);                            \
   77       gst_object_unref (pad);                                            \
   78     } G_STMT_END
   79 #endif
   80 
   81 #define PUSH_BYTES(num_bytes)                                             \
   82     G_STMT_START {                                                        \
   83       GstBuffer *buf = gst_buffer_new_and_alloc(num_bytes);               \
   84       GRand *rand = g_rand_new_with_seed (num_bytes);                     \
   85       GstMapInfo info;                                                    \
   86       guint i;                                                            \
   87       if (sync_buffers)                                                   \
   88         GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_SYNC_AFTER);            \
   89       fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE));           \
   90       for (i = 0; i < num_bytes; ++i)                                     \
   91         ((guint8 *)info.data)[i] = (g_rand_int (rand) >> 24) & 0xff;      \
   92       gst_buffer_unmap (buf, &info);                                      \
   93       fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK); \
   94       g_rand_free (rand);                                                 \
   95     } G_STMT_END
   96 
   97 /* Push Buffer with num_mem_blocks memory block each of size num_bytes*/
   98 #define PUSH_BUFFER_WITH_MULTIPLE_MEM_BLOCKS(num_mem_blocks, num_bytes)      \
   99     G_STMT_START {                                                           \
  100       GstBuffer *buf = gst_buffer_new();                                     \
  101       guint i;                                                               \
  102       if (sync_buffers)                                                      \
  103         GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_SYNC_AFTER);               \
  104       for (i = 0; i < num_mem_blocks; ++i){                                  \
  105         GstMapInfo info;                                                     \
  106         GstMemory* mem_block = gst_allocator_alloc(NULL,num_bytes,NULL);     \
  107         GRand *rand = g_rand_new_with_seed (num_bytes);                      \
  108         guint j;                                                             \
  109         fail_unless (gst_memory_map (mem_block, &info, GST_MAP_WRITE));      \
  110         for (j = 0; j < num_bytes; ++j)                                      \
  111            ((guint8 *)info.data)[j] = (g_rand_int (rand) >> 24) & 0xff;      \
  112         gst_memory_unmap (mem_block, &info);                                 \
  113         gst_buffer_append_memory(buf,mem_block);                             \
  114         g_rand_free (rand);                                                  \
  115       }                                                                      \
  116       fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK);    \
  117     } G_STMT_END
  118 
  119 /* Push Buffer List with num_buffers buffers each containing num_mem_blocks
  120  * memory blocks of size num_bytes */
  121 #define PUSH_BUFFER_LIST_WITH_MULTI_MEM_BLOCKS_BUFFERS(num_buffers, num_mem_blocks, num_bytes) \
  122     G_STMT_START {                                                             \
  123       guint i;                                                                 \
  124       GstBufferList* buf_list = gst_buffer_list_new();                         \
  125       for(i = 0; i < num_buffers; ++i){                                        \
  126         GstBuffer *buf = gst_buffer_new();                                     \
  127         guint j;                                                               \
  128         if (sync_buffers)                                                      \
  129           GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_SYNC_AFTER);               \
  130         for (j = 0; j < num_mem_blocks; ++j){                                  \
  131           GstMapInfo info;                                                     \
  132           GstMemory* mem_block = gst_allocator_alloc(NULL,num_bytes,NULL);     \
  133           GRand *rand = g_rand_new_with_seed (num_bytes);                      \
  134           guint k;                                                             \
  135           fail_unless (gst_memory_map (mem_block, &info, GST_MAP_WRITE));      \
  136           for (k = 0; k < num_bytes; ++k)                                      \
  137             ((guint8 *)info.data)[k] = (g_rand_int (rand) >> 24) & 0xff;       \
  138           gst_memory_unmap (mem_block, &info);                                 \
  139           gst_buffer_append_memory(buf,mem_block);                             \
  140           g_rand_free (rand);                                                  \
  141         }                                                                      \
  142         gst_buffer_list_add(buf_list,buf);                                     \
  143       }                                                                        \
  144       fail_unless_equals_int (gst_pad_push_list (mysrcpad, buf_list), GST_FLOW_OK); \
  145     } G_STMT_END
  146 
  147 /* Push buffer_list containing num_buffers number of buffers with size
  148  *   num_bytes bytes
  149  * Example: PUSH_BUFFER_LIST(2,10) will push the buffer list containing
  150  *   2 buffers with size 10 bytes each */
  151 #define PUSH_BUFFER_LIST(num_buffers, num_bytes)                          \
  152     G_STMT_START {                                                        \
  153       guint i;                                                            \
  154       GstBufferList* buf_list = gst_buffer_list_new();                    \
  155       for(i = 0; i < num_buffers; ++i){                                   \
  156         GstBuffer *buf = gst_buffer_new_and_alloc(num_bytes);             \
  157         GRand *rand = g_rand_new_with_seed (num_bytes);                   \
  158         GstMapInfo info;                                                  \
  159         guint j;                                                          \
  160         if (sync_buffers)                                                 \
  161           GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_SYNC_AFTER);          \
  162         fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE));         \
  163         for (j = 0; j < num_bytes; ++j)                                   \
  164           ((guint8 *)info.data)[j] = (g_rand_int (rand) >> 24) & 0xff;    \
  165         gst_buffer_unmap (buf, &info);                                    \
  166         gst_buffer_list_add(buf_list,buf);                                \
  167         g_rand_free (rand);                                               \
  168       }                                                                   \
  169       fail_unless_equals_int (gst_pad_push_list (mysrcpad, buf_list), GST_FLOW_OK); \
  170     } G_STMT_END
  171 
  172 #define CHECK_WRITTEN_BYTES(offset,written,file_size)                      \
  173     G_STMT_START {                                                        \
  174       gchar *data = NULL;                                                 \
  175       gsize len;                                                          \
  176       fail_unless (g_file_get_contents (tmp_fn, &data, &len, NULL),       \
  177           "Failed to read in newly-created file '%s'", tmp_fn);           \
  178       fail_unless_equals_int (len, file_size);                            \
  179       {                                                                   \
  180         /* we wrote <written> bytes at position 0 */                      \
  181         GRand *rand = g_rand_new_with_seed (written);                     \
  182         guint i;                                                          \
  183         for (i = 0; i < written; ++i) {                                   \
  184           guint8 byte_written = *(((guint8 *) data) + offset + i);        \
  185                                                                           \
  186           fail_unless_equals_int (byte_written, g_rand_int (rand) >> 24); \
  187         }                                                                 \
  188         g_rand_free (rand);                                               \
  189       }                                                                   \
  190       g_free (data);                                                      \
  191     } G_STMT_END
  192 
  193 static gchar *
  194 create_temporary_file (void)
  195 {
  196   const gchar *tmpdir;
  197   gchar *tmp_fn;
  198   gint fd;
  199 
  200   tmpdir = g_get_tmp_dir ();
  201   if (tmpdir == NULL)
  202     return NULL;
  203 
  204   /* this is just silly, but gcc warns if we try to use tpmnam() */
  205   tmp_fn = g_build_filename (tmpdir, "gstreamer-filesink-test-XXXXXX", NULL);
  206   fd = g_mkstemp (tmp_fn);
  207   if (fd < 0) {
  208     GST_ERROR ("can't create temp file %s: %s", tmp_fn, g_strerror (errno));
  209     g_free (tmp_fn);
  210     return NULL;
  211   }
  212   /* don't want the file, just a filename (hence silly, see above) */
  213   g_close (fd, NULL);
  214   g_remove (tmp_fn);
  215 
  216   return tmp_fn;
  217 }
  218 
  219 /* TODO: we don't check that the data is actually written to the right
  220  * position after a seek */
  221 GST_START_TEST (test_seeking)
  222 {
  223   GstElement *filesink;
  224   gchar *tmp_fn;
  225   GstSegment segment;
  226 
  227   tmp_fn = create_temporary_file ();
  228   if (tmp_fn == NULL)
  229     return;
  230   filesink = setup_filesink ();
  231 
  232   sync_buffers = TRUE;
  233 
  234   GST_LOG ("using temp file '%s'", tmp_fn);
  235   g_object_set (filesink, "location", tmp_fn, NULL);
  236 
  237   fail_unless_equals_int (gst_element_set_state (filesink, GST_STATE_PLAYING),
  238       GST_STATE_CHANGE_ASYNC);
  239 
  240 #if 0
  241   /* Test that filesink is seekable with a file fd */
  242   /* filesink doesn't implement seekable query at the moment */
  243   GstQuery *seeking_query;
  244   gboolean seekable;
  245 
  246   fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES))
  247       != NULL);
  248   fail_unless (gst_element_query (filesink, seeking_query) == TRUE);
  249   gst_query_parse_seeking (seeking_query, NULL, &seekable, NULL, NULL);
  250   fail_unless (seekable == TRUE);
  251   gst_query_unref (seeking_query);
  252 #endif
  253 
  254   fail_unless (gst_pad_push_event (mysrcpad,
  255           gst_event_new_stream_start ("test")));
  256 
  257   gst_segment_init (&segment, GST_FORMAT_BYTES);
  258   fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
  259 
  260   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0);
  261 
  262   /* push buffer with size 0 and NULL data */
  263   PUSH_BYTES (0);
  264   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0);
  265 
  266   PUSH_BYTES (1);
  267   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 1);
  268 
  269   PUSH_BYTES (99);
  270   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 100);
  271 
  272   PUSH_BYTES (8800);
  273   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8900);
  274 
  275   /* Push buffer list with 2 buffers each of size 50 bytes */
  276   PUSH_BUFFER_LIST (2, 50);
  277   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 9000);
  278   /* Push buffer list with 3 buffers each of size 10 bytes */
  279   PUSH_BUFFER_LIST (3, 10);
  280   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 9030);
  281   /* Check bytes written using push buffer list */
  282   CHECK_WRITTEN_BYTES (8900, 50, 9030);
  283   CHECK_WRITTEN_BYTES (8950, 50, 9030);
  284   CHECK_WRITTEN_BYTES (9000, 10, 9030);
  285   CHECK_WRITTEN_BYTES (9010, 10, 9030);
  286   CHECK_WRITTEN_BYTES (9020, 10, 9030);
  287 
  288   /* Push buffer with 2 memory blocks each of size 20 bytes */
  289   PUSH_BUFFER_WITH_MULTIPLE_MEM_BLOCKS (2, 20);
  290   CHECK_WRITTEN_BYTES (9030, 20, 9070);
  291   CHECK_WRITTEN_BYTES (9050, 20, 9070);
  292 
  293   /* Push buffer list with 2 buffers each containing 2 memory blocks each of size 20 bytes */
  294   PUSH_BUFFER_LIST_WITH_MULTI_MEM_BLOCKS_BUFFERS (2, 2, 20);
  295   CHECK_WRITTEN_BYTES (9070, 20, 9150);
  296   CHECK_WRITTEN_BYTES (9090, 20, 9150);
  297   CHECK_WRITTEN_BYTES (9110, 20, 9150);
  298   CHECK_WRITTEN_BYTES (9130, 20, 9150);
  299 
  300   segment.start = 8800;
  301   if (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))) {
  302     GST_LOG ("seek ok");
  303     /* make sure that new position is reported immediately */
  304     CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8800);
  305     PUSH_BYTES (1);
  306     CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8801);
  307     PUSH_BYTES (9256);
  308     CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 18057);
  309   } else {
  310     GST_INFO ("seeking not supported for tempfile?!");
  311   }
  312 
  313   fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
  314 
  315   fail_unless_equals_int (gst_element_set_state (filesink, GST_STATE_NULL),
  316       GST_STATE_CHANGE_SUCCESS);
  317 
  318   /* cleanup */
  319   cleanup_filesink (filesink);
  320 
  321   CHECK_WRITTEN_BYTES (8801, 9256, 18057);
  322 
  323   sync_buffers = FALSE;
  324 
  325   /* remove file */
  326   g_remove (tmp_fn);
  327   g_free (tmp_fn);
  328 }
  329 
  330 GST_END_TEST;
  331 
  332 GST_START_TEST (test_flush)
  333 {
  334   GstElement *filesink;
  335   gchar *tmp_fn;
  336   GstSegment segment;
  337 
  338   tmp_fn = create_temporary_file ();
  339   if (tmp_fn == NULL)
  340     return;
  341   filesink = setup_filesink ();
  342 
  343   sync_buffers = FALSE;
  344 
  345   GST_LOG ("using temp file '%s'", tmp_fn);
  346   g_object_set (filesink, "location", tmp_fn, NULL);
  347 
  348   fail_unless_equals_int (gst_element_set_state (filesink, GST_STATE_PLAYING),
  349       GST_STATE_CHANGE_ASYNC);
  350 
  351   fail_unless (gst_pad_push_event (mysrcpad,
  352           gst_event_new_stream_start ("test")));
  353 
  354   gst_segment_init (&segment, GST_FORMAT_TIME);
  355   fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
  356 
  357   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0);
  358 
  359   PUSH_BYTES (8);
  360   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8);
  361 
  362   fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_start ()));
  363   fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE)));
  364   fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));
  365 
  366   fail_unless_equals_int (gst_element_set_state (filesink, GST_STATE_PLAYING),
  367       GST_STATE_CHANGE_ASYNC);
  368 
  369   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0);
  370 
  371   PUSH_BYTES (4);
  372   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 4);
  373 
  374   cleanup_filesink (filesink);
  375 
  376   CHECK_WRITTEN_BYTES (0, 4, 4);
  377 
  378   g_remove (tmp_fn);
  379   g_free (tmp_fn);
  380 }
  381 
  382 GST_END_TEST;
  383 
  384 GST_START_TEST (test_coverage)
  385 {
  386   GstElement *filesink;
  387   gchar *location;
  388   GstBus *bus;
  389   GstMessage *message;
  390 
  391   filesink = setup_filesink ();
  392   bus = gst_bus_new ();
  393 
  394   gst_element_set_bus (filesink, bus);
  395 
  396   g_object_set (filesink, "location", "/i/do/not/exist", NULL);
  397   g_object_get (filesink, "location", &location, NULL);
  398   fail_unless_equals_string (location, "/i/do/not/exist");
  399   g_free (location);
  400 
  401   fail_unless_equals_int (gst_element_set_state (filesink, GST_STATE_PLAYING),
  402       GST_STATE_CHANGE_FAILURE);
  403 
  404   /* a state change and an error */
  405   fail_if ((message = gst_bus_pop (bus)) == NULL);
  406   fail_unless_message_error (message, RESOURCE, OPEN_WRITE);
  407   gst_message_unref (message);
  408 
  409   g_object_set (filesink, "location", NULL, NULL);
  410   g_object_get (filesink, "location", &location, NULL);
  411   fail_if (location);
  412 
  413   /* cleanup */
  414   gst_element_set_bus (filesink, NULL);
  415   gst_object_unref (GST_OBJECT (bus));
  416   cleanup_filesink (filesink);
  417 }
  418 
  419 GST_END_TEST;
  420 
  421 GST_START_TEST (test_uri_interface)
  422 {
  423   GstElement *filesink;
  424   gchar *location;
  425   GstBus *bus;
  426 
  427   filesink = setup_filesink ();
  428   bus = gst_bus_new ();
  429 
  430   gst_element_set_bus (filesink, bus);
  431 
  432   g_object_set (G_OBJECT (filesink), "location", "/i/do/not/exist", NULL);
  433   g_object_get (G_OBJECT (filesink), "location", &location, NULL);
  434   fail_unless_equals_string (location, "/i/do/not/exist");
  435   g_free (location);
  436 
  437   location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
  438   fail_unless_equals_string (location, "file:///i/do/not/exist");
  439   g_free (location);
  440 
  441   /* should accept file:///foo/bar URIs */
  442   fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (filesink),
  443           "file:///foo/bar", NULL));
  444   location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
  445   fail_unless_equals_string (location, "file:///foo/bar");
  446   g_free (location);
  447   g_object_get (G_OBJECT (filesink), "location", &location, NULL);
  448   fail_unless_equals_string (location, "/foo/bar");
  449   g_free (location);
  450 
  451   /* should accept file://localhost/foo/bar URIs */
  452   fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (filesink),
  453           "file://localhost/foo/baz", NULL));
  454   location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
  455   fail_unless_equals_string (location, "file:///foo/baz");
  456   g_free (location);
  457   g_object_get (G_OBJECT (filesink), "location", &location, NULL);
  458   fail_unless_equals_string (location, "/foo/baz");
  459   g_free (location);
  460 
  461   /* should escape non-uri characters for the URI but not for the location */
  462   g_object_set (G_OBJECT (filesink), "location", "/foo/b?r", NULL);
  463   g_object_get (G_OBJECT (filesink), "location", &location, NULL);
  464   fail_unless_equals_string (location, "/foo/b?r");
  465   g_free (location);
  466   location = gst_uri_handler_get_uri (GST_URI_HANDLER (filesink));
  467   fail_unless_equals_string (location, "file:///foo/b%3Fr");
  468   g_free (location);
  469 
  470   g_object_set (G_OBJECT (filesink), "location", "\".donotexist", NULL);
  471   g_object_get (G_OBJECT (filesink), "location", &location, NULL);
  472   fail_unless_equals_string (location, "\".donotexist");
  473   g_free (location);
  474 
  475   /* should fail with other hostnames */
  476   fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (filesink),
  477           "file://hostname/foo/foo", NULL));
  478 
  479   /* cleanup */
  480   gst_element_set_bus (filesink, NULL);
  481   gst_object_unref (GST_OBJECT (bus));
  482   cleanup_filesink (filesink);
  483 }
  484 
  485 GST_END_TEST;
  486 
  487 static Suite *
  488 filesink_suite (void)
  489 {
  490   Suite *s = suite_create ("filesink");
  491   TCase *tc_chain = tcase_create ("general");
  492 
  493   suite_add_tcase (s, tc_chain);
  494 
  495   tcase_add_test (tc_chain, test_coverage);
  496   tcase_add_test (tc_chain, test_uri_interface);
  497   tcase_add_test (tc_chain, test_seeking);
  498   tcase_add_test (tc_chain, test_flush);
  499 
  500   return s;
  501 }
  502 
  503 GST_CHECK_MAIN (filesink);