gst_plugins_base/tests/examples/app/appsink-src.c
changeset 0 0e761a78d257
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 #include <gst/gst.h>
       
    18 
       
    19 #include <string.h>
       
    20 
       
    21 #include <gst/app/gstappsrc.h>
       
    22 #include <gst/app/gstappsink.h>
       
    23 #include <gst/app/gstappbuffer.h>
       
    24 
       
    25 /* these are the caps we are going to pass through the appsink and appsrc */
       
    26 const gchar *audio_caps =
       
    27     "audio/x-raw-int,channels=1,rate=8000,signed=(boolean)true,width=16,depth=16,endianness=1234";
       
    28 
       
    29 typedef struct
       
    30 {
       
    31   GMainLoop *loop;
       
    32   GstElement *source;
       
    33   GstElement *sink;
       
    34 } ProgramData;
       
    35 
       
    36 /* called when the appsink notifies us that there is a new buffer ready for
       
    37  * processing */
       
    38 static void
       
    39 on_new_buffer_from_source (GstElement * elt, ProgramData * data)
       
    40 {
       
    41   guint size;
       
    42   gpointer raw_buffer;
       
    43   GstBuffer *app_buffer, *buffer;
       
    44   GstElement *source;
       
    45 
       
    46   /* get the buffer from appsink */
       
    47   buffer = gst_app_sink_pull_buffer (GST_APP_SINK (elt));
       
    48 
       
    49   /* turn it into an app buffer, it's not really needed, we could simply push
       
    50    * the retrieved buffer from appsink into appsrc just fine.  */
       
    51   size = GST_BUFFER_SIZE (buffer);
       
    52   g_print ("Pushing a buffer of size %d\n", size);
       
    53   raw_buffer = g_malloc0 (size);
       
    54   memcpy (raw_buffer, GST_BUFFER_DATA (buffer), size);
       
    55   app_buffer = gst_app_buffer_new (raw_buffer, size, g_free, raw_buffer);
       
    56 
       
    57   /* newer basesrc will set caps for use automatically but it does not really
       
    58    * hurt to set it on the buffer again */
       
    59   gst_buffer_set_caps (app_buffer, GST_BUFFER_CAPS (buffer));
       
    60 
       
    61   /* we don't need the appsink buffer anymore */
       
    62   gst_buffer_unref (buffer);
       
    63 
       
    64   /* get source an push new buffer */
       
    65   source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
       
    66   gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer);
       
    67 }
       
    68 
       
    69 /* called when we get a GstMessage from the source pipeline when we get EOS, we
       
    70  * notify the appsrc of it. */
       
    71 static gboolean
       
    72 on_source_message (GstBus * bus, GstMessage * message, ProgramData * data)
       
    73 {
       
    74   GstElement *source;
       
    75 
       
    76   switch (GST_MESSAGE_TYPE (message)) {
       
    77     case GST_MESSAGE_EOS:
       
    78       g_print ("The source got dry\n");
       
    79       source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
       
    80       gst_app_src_end_of_stream (GST_APP_SRC (source));
       
    81       break;
       
    82     case GST_MESSAGE_ERROR:
       
    83       g_print ("Received error\n");
       
    84       g_main_loop_quit (data->loop);
       
    85       break;
       
    86     default:
       
    87       break;
       
    88   }
       
    89   return TRUE;
       
    90 }
       
    91 
       
    92 /* called when we get a GstMessage from the sink pipeline when we get EOS, we
       
    93  * exit the mainloop and this testapp. */
       
    94 static gboolean
       
    95 on_sink_message (GstBus * bus, GstMessage * message, ProgramData * data)
       
    96 {
       
    97   /* nil */
       
    98   switch (GST_MESSAGE_TYPE (message)) {
       
    99     case GST_MESSAGE_EOS:
       
   100       g_print ("Finished playback\n");
       
   101       g_main_loop_quit (data->loop);
       
   102       break;
       
   103     case GST_MESSAGE_ERROR:
       
   104       g_print ("Received error\n");
       
   105       g_main_loop_quit (data->loop);
       
   106       break;
       
   107     default:
       
   108       break;
       
   109   }
       
   110   return TRUE;
       
   111 }
       
   112 
       
   113 int
       
   114 main (int argc, char *argv[])
       
   115 {
       
   116   gchar *filename = NULL;
       
   117   ProgramData *data = NULL;
       
   118   gchar *string = NULL;
       
   119   GstBus *bus = NULL;
       
   120   GstElement *testsink = NULL;
       
   121   GstElement *testsource = NULL;
       
   122 
       
   123   gst_init (&argc, &argv);
       
   124 
       
   125   if (argc == 2)
       
   126     filename = g_strdup (argv[1]);
       
   127   else
       
   128     filename = g_strdup ("/usr/share/sounds/ekiga/ring.wav");
       
   129 
       
   130   data = g_new0 (ProgramData, 1);
       
   131 
       
   132   data->loop = g_main_loop_new (NULL, FALSE);
       
   133 
       
   134   /* setting up source pipeline, we read from a file and convert to our desired
       
   135    * caps. */
       
   136   string =
       
   137       g_strdup_printf
       
   138       ("filesrc location=\"%s\" ! wavparse ! audioconvert ! audioresample ! appsink caps=\"%s\" name=testsink",
       
   139       filename, audio_caps);
       
   140   g_free (filename);
       
   141   data->source = gst_parse_launch (string, NULL);
       
   142   g_free (string);
       
   143 
       
   144   if (data->source == NULL) {
       
   145     g_print ("Bad source\n");
       
   146     return -1;
       
   147   }
       
   148 
       
   149   /* to be notified of messages from this pipeline, mostly EOS */
       
   150   bus = gst_element_get_bus (data->source);
       
   151   gst_bus_add_watch (bus, (GstBusFunc) on_source_message, data);
       
   152   gst_object_unref (bus);
       
   153 
       
   154   /* we use appsink in push mode, it sends us a signal when data is available
       
   155    * and we pull out the data in the signal callback. We want the appsink to
       
   156    * push as fast as it can, hence the sync=false */
       
   157   testsink = gst_bin_get_by_name (GST_BIN (data->source), "testsink");
       
   158   g_object_set (G_OBJECT (testsink), "emit-signals", TRUE, "sync", FALSE, NULL);
       
   159   g_signal_connect (testsink, "new-buffer",
       
   160       G_CALLBACK (on_new_buffer_from_source), data);
       
   161   gst_object_unref (testsink);
       
   162 
       
   163   /* setting up sink pipeline, we push audio data into this pipeline that will
       
   164    * then play it back using the default audio sink. We have no blocking
       
   165    * behaviour on the src which means that we will push the entire file into
       
   166    * memory. */
       
   167   string =
       
   168       g_strdup_printf ("appsrc name=testsource caps=\"%s\" ! autoaudiosink",
       
   169       audio_caps);
       
   170   data->sink = gst_parse_launch (string, NULL);
       
   171   g_free (string);
       
   172 
       
   173   if (data->sink == NULL) {
       
   174     g_print ("Bad sink\n");
       
   175     return -1;
       
   176   }
       
   177 
       
   178   testsource = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
       
   179   /* configure for time-based format */
       
   180   g_object_set (testsource, "format", GST_FORMAT_TIME, NULL);
       
   181   /* uncomment the next line to block when appsrc has buffered enough */
       
   182   /* g_object_set (testsource, "block", TRUE, NULL); */
       
   183   gst_object_unref (testsource);
       
   184 
       
   185   bus = gst_element_get_bus (data->sink);
       
   186   gst_bus_add_watch (bus, (GstBusFunc) on_sink_message, data);
       
   187   gst_object_unref (bus);
       
   188 
       
   189   /* launching things */
       
   190   gst_element_set_state (data->sink, GST_STATE_PLAYING);
       
   191   gst_element_set_state (data->source, GST_STATE_PLAYING);
       
   192 
       
   193   /* let's run !, this loop will quit when the sink pipeline goes EOS or when an
       
   194    * error occurs in the source or sink pipelines. */
       
   195   g_print ("Let's run!\n");
       
   196   g_main_loop_run (data->loop);
       
   197   g_print ("Going out\n");
       
   198 
       
   199   gst_element_set_state (data->source, GST_STATE_NULL);
       
   200   gst_element_set_state (data->sink, GST_STATE_NULL);
       
   201 
       
   202   gst_object_unref (data->source);
       
   203   gst_object_unref (data->sink);
       
   204   g_main_loop_unref (data->loop);
       
   205   g_free (data);
       
   206 
       
   207   return 0;
       
   208 }