Play multiple audio files with gst pipeline - c++

I am using gst library to play multiple audio files and I have a problem:
Error: Internal data flow error
This is my code (without other demuxer and sink init):
GstElement *elm1, *elm2;
elm1 = gst_element_factory_make ("filesrc", "file1.ogg");
elm2 = gst_element_factory_make ("filesrc", "file2.ogg");
g_object_set (G_OBJECT (elm1), "location", "file1.ogg", NULL);
g_object_set (G_OBJECT (elm2), "location", "file2.ogg", NULL);
GstBus *bus;
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
gst_bin_add_many (GST_BIN (pipeline), elm1, elm2, demuxer, sink, NULL);
gst_element_link_many (elm1, elm2, demuxer);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), sink);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
Did I make something wrong?

you need to listen for EOS for file-1 and then change the filesrc to file-2.
the following answer should help you -
'GStreamer dynamically change the filesrc location of a pipeline- No sound'

Related

GstCaps filter issue

trying to create filter using caps:
GMainLoop *loop;
GstElement *pipeline, *source, *demuxer, *decoder, *typefind, *conv, *sink;;
GstBus *bus;
guint bus_watch_id;
loop = g_main_loop_new(NULL, FALSE);
pipeline = gst_pipeline_new ("audio-player");
source = gst_element_factory_make ("filesrc", "file-source");
typefind = gst_element_factory_make ("typefind", "typefinder");
demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer");
decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder");
conv = gst_element_factory_make ("audioconvert", "converter");
sink = gst_element_factory_make ("autoaudiosink", "audio-output");
if (!pipeline || !source || !demuxer || !decoder || !conv || !sink) {
return -1;
}
g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), loop);
g_object_set(G_OBJECT(source), "location", name_of_file, NULL);
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
gst_object_unref(bus);
gst_bin_add_many(GST_BIN(pipeline), source, typefind, demuxer, decoder, conv, sink, NULL);
GstCaps *my_caps = gst_caps_new_simple ("audio/x-raw","rate", G_TYPE_INT, 384,NULL);
gboolean test=false;
test = gst_element_link_filtered(source,typefind, my_caps);
test = gst_element_link(typefind, demuxer);
test = gst_element_link_many(decoder, conv,sink, NULL);
g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), decoder);
......
Debug: gsttypefindelement.c(1169): gst_type_find_element_loop (): /GstPipeline:a
udio-player/GstTypeFindElement:typefinder:
stream stopped, reason not-linked
Var test == 1 after gst_element_link_filtered(source,typefind,
my_caps);
test == 0 after gst_element_link(typefind, demuxer);
test == 1 after gst_element_link_many(decoder, conv,sink, NULL);
If I just change gst_element_link_filtered on gst_element_link all going ok and file plays.
What am I doing wrong?
You seem to also have posted this to the gst-devel mailing list and you have a reply there:
http://gstreamer-devel.966125.n4.nabble.com/GstCaps-filter-issue-td4672796.html
Setting a filter caps of raw audio between the filesrc and the demuxer while you seem to want to play an OGG file is wrong. You should explain better what you want to do in order for us to provide some more refined guidance.

How to use videomixer element for gstreamer?

I want to play two local video file using gstreamer,but I got an error: Segmentation fault It from libgstvideomixer.so.What's wrong with my code? The videomixer element is needed to play two videos.Should I use videobox for that?
gst-launch --no-fault filesrc location=/mnt/upan/source.264 ! queue ! typefind ! ffdec_h264 ! videomixer name=mix ! xvimagesink sync=false filesrc location=/mnt/upan/source.264 ! queue ! typefind ! ffdec_h264! mix.
static void p_gst_init(void)
{
App *app = &s_app;
GError *error = NULL;
GstBus *bus;
GstElement *parse, *decoder, *queue;
GstElement *parse2, *decoder2, *queue2;
gst_init (NULL, NULL);
/* create a mainloop to get messages */
app->loop = g_main_loop_new (NULL, TRUE);
app->playbin = gst_pipeline_new ("pipeline");
app->appsrc = gst_element_factory_make ("filesrc", "disk_source");
g_object_set (G_OBJECT (app->appsrc), "location", "/mnt/upan/test.264", NULL);
queue = gst_element_factory_make ("queue", "queue");
parse = gst_element_factory_make ("typefind", "parse");
decoder = gst_element_factory_make ("ffdec_h264", "decoder");
GstElement *filesrc2;
filesrc2 = gst_element_factory_make ("filesrc", "disk_source2");
g_object_set (G_OBJECT (appsrc2), "location", "/mnt/upan/source.264", NULL);
queue2 = gst_element_factory_make ("queue", "queue2");
parse2 = gst_element_factory_make ("typefind", "parse2");
decoder2 = gst_element_factory_make ("ffdec_h264", "decoder2");
/*
GstElement * videobox;
videobox = gst_element_factory_make("videobox", NULL);
g_object_set (videobox, "alpha", 0, "border-alpha", 0, "bottom", 100, "left", 100, "right", 100, "top", 100, NULL);
*/
GstElement * videomixer;
videomixer = gst_element_factory_make("videomixer","videomixer");
app->xvimagesink = gst_element_factory_make ("xvimagesink", "play_video");
g_object_set (G_OBJECT (app->xvimagesink), "synchronous", FALSE, NULL);
gst_bin_add_many (GST_BIN (app->playbin), app->appsrc, queue, parse, decoder, videomixer, app->xvimagesink, filesrc2, queue2, parse2, decoder2, NULL);
if(gst_element_link_many (app->appsrc, queue, parse, decoder, videomixer, NULL))
{
printf("---------link element success-----------------\n");
}
else
printf("---------link element failed-----------------\n");
gst_element_link_many (filesrc2, queue2, parse2, decoder2, videomixer, NULL);
gst_element_link_many(videomixer, app->xvimagesink, NULL);
bus = gst_pipeline_get_bus (GST_PIPELINE (app->playbin));
gst_bus_add_watch (bus, (GstBusFunc) bus_message, app);
gst_bus_set_sync_handler(bus, (GstBusSyncHandler)create_window, app);
g_signal_connect (app->appsrc, "need-data", G_CALLBACK (feed_data), app);
return ;
}

Gstreamer source code doesnt work

i have the following pipelines that one of them sends voice signals on udp port and the other receives them on the same port number on the receiver side
gst-launch-1.0 -v alsasrc ! audioconvert
! audio/x-raw,channels=2,depth=16,width=16,rate=44100 !
rtpL16pay ! udpsink
host=127.0.0.1 port=5000 //sender
and
gst-launch-1.0 udpsrc port=5000 ! "application/x-rtp,
media=(string)audio, clock-rate=(int)44100,
encoding-name=(string)L16, channels=(int)2,
payload=(int)96" ! rtpL16depay ! audioconvert
! alsasink //receiver
now i am trying to write a source code using Gstreamer SDK that does the same thing. I have come so far:
#include <gst/gst.h>
#include <string.h>
int main(int argc, char *argv[]) {
GstElement *pipeline, *source, *audiosink,*rtppay,*rtpdepay,*filter,*filter1,*conv,*conv1,*udpsink,*udpsrc,*receive_resample;
GstBus *bus;
GstMessage *msg;
GstCaps *filtercaps;
GstStateChangeReturn ret;
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Create the elements */
source = gst_element_factory_make ("alsasrc", "source");
conv= gst_element_factory_make ("audioconvert", "conv");
conv1= gst_element_factory_make ("audioconvert", "conv1");
filter=gst_element_factory_make("capsfilter","filter");
rtppay=gst_element_factory_make("rtpL16pay","rtppay");
rtpdepay=gst_element_factory_make("rtpL16depay","rtpdepay");
udpsink=gst_element_factory_make("udpsink","udpsink");
audiosink = gst_element_factory_make ("autoaudiosink", "audiosink");
receive_resample = gst_element_factory_make("audioresample", NULL);
udpsrc=gst_element_factory_make("udpsrc",NULL);
filter1=gst_element_factory_make("capsfilter","filter");
g_object_set(udpsrc,"port",5000,NULL);
g_object_set (G_OBJECT (udpsrc), "caps", gst_caps_from_string("application/x-rtp,media=audio,payload=96,clock-rate=44100,encoding-name=L16,channels=2"), NULL);
/* Create the empty pipeline */
pipeline = gst_pipeline_new ("test-pipeline");
if (!pipeline || !source || !filter || !conv || !rtppay || !udpsink ) {
g_printerr ("Not all elements could be created.\n");
return -1;
}
g_object_set(G_OBJECT(udpsink),"host","127.0.0.1",NULL);
g_object_set(G_OBJECT(udpsink),"port",5000,NULL);
filtercaps = gst_caps_new_simple ("audio/x-raw",
"channels", G_TYPE_INT, 2,
"width", G_TYPE_INT, 16,
"depth", G_TYPE_INT, 16,
"rate", G_TYPE_INT, 44100,
NULL);
g_object_set (G_OBJECT (filter), "caps", filtercaps, NULL);
gst_caps_unref (filtercaps);
filtercaps = gst_caps_new_simple ("application/x-rtp",
"media",G_TYPE_STRING,"audio",
"clock-rate",G_TYPE_INT,44100,
"encoding-name",G_TYPE_STRING,"L16",
"channels", G_TYPE_INT, 2,
"payload",G_TYPE_INT,96,
NULL);
g_object_set (G_OBJECT (filter1), "caps", filtercaps, NULL);
gst_caps_unref (filtercaps);
/* Build the pipeline */
gst_bin_add_many (GST_BIN (pipeline), source,filter,conv,rtppay,udpsink, NULL);
if (gst_element_link_many (source,filter,conv,rtppay,udpsink, NULL) != TRUE) {
g_printerr ("Elements could not be linked.\n");
gst_object_unref (pipeline);
return -1;
}
gst_bin_add_many (GST_BIN (pipeline),udpsrc,rtpdepay,conv1,receive_resample,audiosink,NULL);
if (gst_element_link_many (udpsrc,rtpdepay,conv1,receive_resample,audiosink,NULL) != TRUE) {
g_printerr ("Elements could not be linked.\n");
gst_object_unref (pipeline);
return -1;
}
/* Modify the source's properties */
// g_object_set (source, "pattern", 0, NULL);
/* Start playing */
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
g_printerr ("Unable to set the pipeline to the playing state.\n");
gst_object_unref (pipeline);
return -1;
}
/* Wait until error or EOS */
bus = gst_element_get_bus (pipeline);
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
/* Parse message */
if (msg != NULL) {
GError *err;
gchar *debug_info;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &err, &debug_info);
g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error (&err);
g_free (debug_info);
break;
case GST_MESSAGE_EOS:
g_print ("End-Of-Stream reached.\n");
break;
default:
/* We should not reach here because we only asked for ERRORs and EOS */
g_printerr ("Unexpected message received.\n");
break;
}
gst_message_unref (msg);
}
/* Free resources */
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
return 0;
}
but somehow i dont receive any voice on the receiver. i dont get any errors of any kind.
Any ideas why this is happening?
Well i figured it out. I don't know why but when i divided the source code into two separate ones and in one of them i included the code up until the UDPsink element and included the rest of the elements after that ( meaning udpsrc, rtpdepay and audiosink) in another source code file and compiled them separately in two separate Terminals it worked. I still don't know why it is like this , but i am happy that it works.
The sender and reciever are supposed to be two different processes, which is why it works when you use two terminals.
In your code, you're putting two different pipelines in the same pipeline element and setting it to playing.
This is not supported, you need to create a different pipeline for that.
pipeline1 = gst_pipeline_new ("src-pipeline");
pipeline2 = gst_pipeline_new ("sink-pipeline");

why is gstreamer caps is blocking pipeline

I am trying a basic pipeline below. If I run the pipeline without the caps function it passes straight through (assuming same I/O format). Once I add the caps the pre-roll starts but the video does not continue through to the sink output.
Am I coding this wrong?
thx
Art
#include <gst/gst.h>
#include <glib.h>
static void
on_pad_added (GstElement *element,
GstPad *pad,
gpointer data)
{
GstPad *sinkpad;
GstElement *decoder = (GstElement *) data;
g_print ("Dynamic pad created, linking out/in \n");
sinkpad = gst_element_get_static_pad (decoder, "sink");
gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
}
int
main (int argc,
char *argv[])
{
GMainLoop *loop;
gboolean link_ok;
GstElement *pipeline, *source, *decoder, *ffcs, *vidsc, *capsfout, *sink;
GstBus *bus;
GstCaps *caps;
/* Initialisation */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("video-player");
source = gst_element_factory_make ("filesrc", "file-source");
decoder = gst_element_factory_make ("decodebin2", "dec-bin2");
ffcs = gst_element_factory_make ("ffmpegcolorspace", "ffcs");
vidsc = gst_element_factory_make ("videoscale", "vidsc");
capsfout = gst_element_factory_make ("capsfilter", "capsfout");
sink = gst_element_factory_make ("filesink", "vidout");
if (!pipeline || !source || !decoder || !ffcs || !vidsc || !capsfout || !sink) {
g_printerr ("One element could not be created. Exiting.\n");
return -1;
}
/* we set the input/output filename to the source element */
g_object_set (G_OBJECT (source), "location", argv[1], NULL);
g_object_set (G_OBJECT (sink), "location", argv[2], NULL);
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bin_add_many (GST_BIN (pipeline),
source, decoder, ffcs, vidsc, capsfout, sink, NULL);
/* we link the elements together */
gst_element_link (source, decoder);
gst_element_link (decoder, ffcs);
gst_element_link (ffcs, vidsc);
caps = gst_caps_new_simple("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
"width", G_TYPE_INT, 384,
"height", G_TYPE_INT, 216,
"framerate", GST_TYPE_FRACTION, 25, 1,
NULL);
link_ok = gst_element_link_filtered(vidsc,sink,caps);
gst_caps_unref (caps);
if (!link_ok) {
g_warning ("Failed to link vidsc to sink!");
}else{
g_print("seems ok, no error reported?\n");
}
/* Set the pipeline to "playing" state*/
g_print ("Now playing: %s\n", argv[1]);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* Iterate */
g_print ("Running...\n");
g_main_loop_run (loop);
/* Out of the main loop, clean up nicely */
g_print ("Returned, stopping playback\n");
gst_element_set_state (pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
It may be late to answer but you maybe forgot to do the dynamic pad link between some elements and you never call the on_pad_added function. I had the same problem.
Have you tried to add it since then? For example this line to dynamically link two elements instead of the gst_element_link:
g_signal_connect (decoder, "pad-added", G_CALLBACK (on_pad_added), ffcs);
For what reasons do you need the capsfilter? Only constrain the properties you need. E.g. you set a framerate, but don't have a videorate element before the capsfilter. If you don't care about the framerate (e.g. just want to force a size) remove the framerate from the caps you set on capsfilter..

Unable to play .wav file using gstreamer apis

Following code is written to play a .wav file but it doesn't seem to work.
I would like to know if i am missing something in it.
Code:
#include <gst/gst.h>
#include <glib.h>
int main(int argc , char *argv[])
{
GMainLoop *loop;
GstElement *source,*audioparser,*sink,*pipeline;
GstBus *bus;
gst_init(&argc,&argv);
// create a pipeline
loop = g_main_loop_new (NULL, FALSE);
pipeline = gst_pipeline_new ("wav-player");
source = gst_element_factory_make("filesrc","file-source");
audioparser = gst_element_factory_make("wavparse","wav-parser");
sink = gst_element_factory_make("alsasink","sink1");
g_object_set (G_OBJECT (source), "location", argv[1], NULL);
gst_element_set_state (pipeline, GST_STATE_NULL);
// set location to current sourceg_object_set(G_OBJECT(source),"location",argv[1],NULL);
// add elements to bin
gst_bin_add_many(GST_BIN(pipeline),source,audioparser,sink,NULL);
gst_element_link_many(source,audioparser,sink,NULL);
// create bus
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run (loop);
return 1;
}
Please compile this using following command:
gcc -Wall $(pkg-config --cflags --libs gstreamer-0.10) wav.c -o wavparser
Thanks in advance
Just use playbin2 instead of a hand-crafted pipeline
that is, replace everything from "pipeline = gst_pipeline_new()" to "gst_element_link_many" by:
pipeline = gst_element_factory_make("playbin2", NULL);
g_object_set(pipeline, "uri", "file:///the/file/I/want.wav", NULL);
maybe playbin2 is exactly what you need, but answerring question: wavparse does not have static src-pad, so you must handle "pad-added" signal from this element on runtime. something like the code:
gst_bin_add_many (GST_BIN (pipeline), wavsrc, wavparse,audioconvert, audiosink, NULL);
g_object_set (G_OBJECT (wavsrc), "location", "sound.wav", NULL);
gst_element_link(wavsrc, wavparse);
gst_element_link(audioconvert, audiosink);
g_signal_connect (wavparse, "pad-added", G_CALLBACK (on_pad_added), audioconvert);
where: wavsrc is filesrc, wavparse is wavparse, audioconvert is audioconvert, audiosink is alsasink (i'm not sure alsasink works for you, so you can choose another)
void on_pad_added (GstElement *src_element, GstPad *src_pad, gpointer data)
{
g_print ("Linking dynamic pad...\n");
GstElement *sink_element = (GstElement *) data; // is audioconvert
GstPad *sink_pad = gst_element_get_static_pad (sink_element, "sink");
gst_pad_link (src_pad, sink_pad);
gst_object_unref (sink_pad);
src_element = NULL; // yup, i don't want "unused" warning here
}