mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
tests/examples/dynamic/: Add example app that dynamically switches between 3 'encoders'.
Original commit message from CVS: * tests/examples/dynamic/Makefile.am: * tests/examples/dynamic/codec-select.c: (make_encoder), (make_pipeline), (do_switch), (my_bus_callback), (main): Add example app that dynamically switches between 3 'encoders'.
This commit is contained in:
parent
76456cb647
commit
0667fb7e25
4 changed files with 312 additions and 3 deletions
|
@ -1,3 +1,10 @@
|
|||
2008-08-01 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||
|
||||
* tests/examples/dynamic/Makefile.am:
|
||||
* tests/examples/dynamic/codec-select.c: (make_encoder),
|
||||
(make_pipeline), (do_switch), (my_bus_callback), (main):
|
||||
Add example app that dynamically switches between 3 'encoders'.
|
||||
|
||||
2008-07-31 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||
|
||||
* gst/playback/gstplaysink.c: (gst_play_sink_set_vis_plugin):
|
||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
|||
Subproject commit e79879859bc866545379eb77e1378a906dc30ebf
|
||||
Subproject commit d70ca17ae6fbe6020996e4567275d5e14972ed45
|
|
@ -1,5 +1,9 @@
|
|||
noinst_PROGRAMS = addstream
|
||||
noinst_PROGRAMS = addstream codec-select
|
||||
|
||||
addstream_SOURCES = addstream.c
|
||||
addstream_SOURCES = addstream.c
|
||||
addstream_CFLAGS = $(GST_CFLAGS) -D_GNU_SOURCE
|
||||
addstream_LDFLAGS = $(GST_LIBS)
|
||||
|
||||
codec_select_SOURCES = codec-select.c
|
||||
codec_select_CFLAGS = $(GST_CFLAGS) -D_GNU_SOURCE
|
||||
codec_select_LDFLAGS = $(GST_LIBS)
|
||||
|
|
298
tests/examples/dynamic/codec-select.c
Normal file
298
tests/examples/dynamic/codec-select.c
Normal file
|
@ -0,0 +1,298 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* codec-select.c: sample application to dynamically select a codec
|
||||
*
|
||||
* Copyright (C) <2008> Wim Taymans <wim dot taymans at gmail dot com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example sets up a pipeline to 'encode' an audiotestsrc into 3 different
|
||||
* formats. The format can be selected dynamically at runtime.
|
||||
*
|
||||
* Each of the encoders require the audio in a specific different format.
|
||||
*
|
||||
* This example uses identity as the encoder and enforces the caps on identity
|
||||
* with a capsfilter.
|
||||
*
|
||||
* This is a good example of input and output selector and how these elements
|
||||
* preserve segment and timing information while switching between streams.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
/* Create an encoder element.
|
||||
* We make a bin containing:
|
||||
*
|
||||
* audioresample ! <enccaps> ! identity
|
||||
*
|
||||
* The sinkpad of audioresample and source pad of identity are ghosted on the
|
||||
* bin.
|
||||
*/
|
||||
static GstElement *
|
||||
make_encoder (const GstCaps * caps)
|
||||
{
|
||||
GstElement *result;
|
||||
GstElement *audioresample;
|
||||
GstElement *capsfilter;
|
||||
GstElement *identity;
|
||||
GstPad *pad;
|
||||
|
||||
/* create result bin */
|
||||
result = gst_bin_new (NULL);
|
||||
g_assert (result);
|
||||
|
||||
/* create elements */
|
||||
audioresample = gst_element_factory_make ("audioresample", NULL);
|
||||
g_assert (audioresample);
|
||||
|
||||
capsfilter = gst_element_factory_make ("capsfilter", NULL);
|
||||
g_assert (capsfilter);
|
||||
g_object_set (capsfilter, "caps", caps, NULL);
|
||||
|
||||
identity = gst_element_factory_make ("identity", NULL);
|
||||
g_assert (identity);
|
||||
g_object_set (identity, "silent", TRUE, NULL);
|
||||
|
||||
/* add elements to result bin */
|
||||
gst_bin_add (GST_BIN (result), audioresample);
|
||||
gst_bin_add (GST_BIN (result), capsfilter);
|
||||
gst_bin_add (GST_BIN (result), identity);
|
||||
|
||||
/* link elements */
|
||||
gst_element_link_pads (audioresample, "src", capsfilter, "sink");
|
||||
gst_element_link_pads (capsfilter, "src", identity, "sink");
|
||||
|
||||
/* ghost src and sink pads */
|
||||
pad = gst_element_get_static_pad (audioresample, "sink");
|
||||
gst_element_add_pad (result, gst_ghost_pad_new ("sink", pad));
|
||||
gst_object_unref (pad);
|
||||
|
||||
pad = gst_element_get_static_pad (identity, "src");
|
||||
gst_element_add_pad (result, gst_ghost_pad_new ("src", pad));
|
||||
gst_object_unref (pad);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* We generate:
|
||||
*
|
||||
* audiotestsrc ! <audiocaps> ! output-selector ! [enc1 .. enc3] ! input-selector
|
||||
* select-all = true ! fakesink
|
||||
*
|
||||
* <audiocaps> makes sure we only produce one format from the audiotestsrc.
|
||||
*
|
||||
* Each encX element consists of:
|
||||
*
|
||||
* audioresample ! <enccaps> ! identity !
|
||||
*
|
||||
* This way we can simply switch encoders without having to renegotiate.
|
||||
*/
|
||||
static GstElement *
|
||||
make_pipeline (void)
|
||||
{
|
||||
GstElement *result;
|
||||
GstElement *audiotestsrc;
|
||||
GstElement *audiocaps;
|
||||
GstElement *outputselect;
|
||||
GstElement *inputselect;
|
||||
GstElement *sink;
|
||||
GstCaps *caps;
|
||||
GstCaps *capslist[3];
|
||||
gint i;
|
||||
|
||||
/* create result pipeline */
|
||||
result = gst_pipeline_new (NULL);
|
||||
g_assert (result);
|
||||
|
||||
/* create various elements */
|
||||
audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
|
||||
g_object_set (audiotestsrc, "num-buffers", 1000, NULL);
|
||||
g_assert (audiotestsrc);
|
||||
|
||||
audiocaps = gst_element_factory_make ("capsfilter", NULL);
|
||||
g_assert (audiocaps);
|
||||
|
||||
caps =
|
||||
gst_caps_from_string
|
||||
("audio/x-raw-int,signed=true,width=16,depth=16,rate=48000,channels=1");
|
||||
g_object_set (audiocaps, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
outputselect = gst_element_factory_make ("output-selector", "select");
|
||||
g_assert (outputselect);
|
||||
|
||||
inputselect = gst_element_factory_make ("input-selector", NULL);
|
||||
g_assert (inputselect);
|
||||
g_object_set (inputselect, "select-all", TRUE, NULL);
|
||||
|
||||
sink = gst_element_factory_make ("fakesink", NULL);
|
||||
g_object_set (sink, "sync", TRUE, NULL);
|
||||
g_object_set (sink, "silent", TRUE, NULL);
|
||||
g_assert (sink);
|
||||
|
||||
/* add elements */
|
||||
gst_bin_add (GST_BIN (result), audiotestsrc);
|
||||
gst_bin_add (GST_BIN (result), audiocaps);
|
||||
gst_bin_add (GST_BIN (result), outputselect);
|
||||
gst_bin_add (GST_BIN (result), inputselect);
|
||||
gst_bin_add (GST_BIN (result), sink);
|
||||
|
||||
/* link elements */
|
||||
gst_element_link_pads (audiotestsrc, "src", audiocaps, "sink");
|
||||
gst_element_link_pads (audiocaps, "src", outputselect, "sink");
|
||||
gst_element_link_pads (inputselect, "src", sink, "sink");
|
||||
|
||||
/* make caps */
|
||||
capslist[0] =
|
||||
gst_caps_from_string
|
||||
("audio/x-raw-int,signed=true,width=16,depth=16,rate=48000,channels=1");
|
||||
capslist[1] =
|
||||
gst_caps_from_string
|
||||
("audio/x-raw-int,signed=true,width=16,depth=16,rate=16000,channels=1");
|
||||
capslist[2] =
|
||||
gst_caps_from_string
|
||||
("audio/x-raw-int,signed=true,width=16,depth=16,rate=8000,channels=1");
|
||||
|
||||
/* create encoder elements */
|
||||
for (i = 0; i < 3; i++) {
|
||||
GstElement *encoder;
|
||||
GstPad *srcpad, *sinkpad;
|
||||
|
||||
encoder = make_encoder (capslist[i]);
|
||||
g_assert (encoder);
|
||||
|
||||
gst_bin_add (GST_BIN (result), encoder);
|
||||
|
||||
srcpad = gst_element_get_request_pad (outputselect, "src%d");
|
||||
sinkpad = gst_element_get_static_pad (encoder, "sink");
|
||||
gst_pad_link (srcpad, sinkpad);
|
||||
gst_object_unref (srcpad);
|
||||
gst_object_unref (sinkpad);
|
||||
|
||||
srcpad = gst_element_get_static_pad (encoder, "src");
|
||||
sinkpad = gst_element_get_request_pad (inputselect, "sink%d");
|
||||
gst_pad_link (srcpad, sinkpad);
|
||||
gst_object_unref (srcpad);
|
||||
gst_object_unref (sinkpad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_switch (GstElement * pipeline)
|
||||
{
|
||||
gint rand;
|
||||
GstElement *select;
|
||||
gchar *name;
|
||||
GstPad *pad;
|
||||
|
||||
rand = g_random_int_range (0, 3);
|
||||
|
||||
g_print ("switching to %d\n", rand);
|
||||
|
||||
/* find the selector */
|
||||
select = gst_bin_get_by_name (GST_BIN (pipeline), "select");
|
||||
|
||||
/* get the named pad */
|
||||
name = g_strdup_printf ("src%d", rand);
|
||||
pad = gst_element_get_static_pad (select, name);
|
||||
g_free (name);
|
||||
|
||||
/* set the active pad */
|
||||
g_object_set (select, "active-pad", pad, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
|
||||
{
|
||||
GstElement *sender = (GstElement *) GST_MESSAGE_SRC (message);
|
||||
const gchar *name = gst_element_get_name (sender);
|
||||
GMainLoop *loop = (GMainLoop *) data;
|
||||
|
||||
g_print ("Got %s message from %s\n", GST_MESSAGE_TYPE_NAME (message), name);
|
||||
|
||||
switch (GST_MESSAGE_TYPE (message)) {
|
||||
|
||||
case GST_MESSAGE_ERROR:{
|
||||
GError *err;
|
||||
gchar *debug;
|
||||
|
||||
gst_message_parse_error (message, &err, &debug);
|
||||
g_print ("Error: %s (%s)\n", err->message, debug);
|
||||
g_error_free (err);
|
||||
g_free (debug);
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_EOS:
|
||||
/* end-of-stream */
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
default:
|
||||
/* unhandled message */
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar * argv[])
|
||||
{
|
||||
GstElement *pipeline;
|
||||
GstBus *bus;
|
||||
GMainLoop *loop;
|
||||
|
||||
/* init GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
/* set up */
|
||||
pipeline = make_pipeline ();
|
||||
|
||||
g_signal_connect (pipeline, "deep_notify",
|
||||
G_CALLBACK (gst_object_default_deep_notify), NULL);
|
||||
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
gst_bus_add_watch (bus, my_bus_callback, loop);
|
||||
gst_object_unref (bus);
|
||||
|
||||
g_print ("Starting pipeline\n");
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
/* add a timeout to cycle between the formats */
|
||||
g_timeout_add (1000, (GSourceFunc) do_switch, pipeline);
|
||||
|
||||
/* now run */
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_print ("Nulling pipeline\n");
|
||||
|
||||
/* also clean up */
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (pipeline);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue