gstreamer : encountered a general stream error - gstreamer

Now I'm trying to play mp4 files.
After trying to play mp4 file to demux, a stream error occurs.
My code is below, please let me know if there are any problems.
Any advises? Thank you
error -> encountered a general stream error
int main(int argc, char* argv[]){
GMainLoop *loop;
GstElement *pipeline, *vsource, *demux, *vqueue, *ssource, *muxer, *filesink;
GstElement *vplay, *conv;
//GstBin *recording;
GstBus *bus;
GstPad *srcpad, *sinkpad;
guint bus_watch_id;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
pipeline = gst_pipeline_new("Live Recording");
vsource = gst_element_factory_make("filesrc","v-file-source");
demux = gst_element_factory_make("qtdemux","v-file-demux");
vqueue = gst_element_factory_make("queue2","v-file-queue");
vplay = gst_element_factory_make("autovideosink","play");
conv = gst_element_factory_make("videoconvert","converter");
if(!pipeline)
g_print("no pipe\n");
if(!vsource)
g_print("no video source\n");
if(!demux)
g_print("no video demux\n");
if(!vqueue)
g_print("no video queue\n");
if(!vplay)
g_print("no video play\n");
if(!conv)
g_print("no conv");
g_object_set (G_OBJECT (vsource), "location", "./sample.mp4", 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),vsource,demux,vqueue, conv, vplay,NULL);
if(!gst_element_link(vsource, demux)){
g_print("no link");
}
if(!gst_element_link_many(vqueue, conv, vplay,NULL)){
g_print("no link many");
}
g_print("now play\n");
g_signal_connect (demux, "pad-added", G_CALLBACK (on_pad_added), vqueue);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run(loop);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
g_source_remove(bus_watch_id);
g_main_loop_unref(loop);
return 0;
}

Related

Gstreamer FLAC pipeline creation Error

I keep getting this error:
$ ./test recit24bit.flac
Now playing: recit24bit.flac
Running...
Error: Internal data flow error.
Returned, stopping playback
Deleting pipeline
When compiling this code:
#include <gst/gst.h>
#include <glib.h>
static gboolean bus_call (GstBus *bus,
GstMessage *msg,
gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
switch (GST_MESSAGE_TYPE (msg))
{
case GST_MESSAGE_EOS:
{
g_print ("End of stream\n");
g_main_loop_quit (loop);
break;
}
case GST_MESSAGE_ERROR:
{
gchar *debug;
GError *error;
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
g_main_loop_quit (loop);
break;
}
default:
{
break;
}
}
return TRUE;
}
/*
static void on_pad_added (GstElement *element,
GstPad *pad,
gpointer data)
{
GstPad *sinkpad;
GstElement *decoder = (GstElement *) data;
// We can now link this pad with the vorbis-decoder sink pad
g_print ("Dynamic pad created, linking demuxer/decoder\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;
GstElement *pipeline,
*source,
//*demuxer,
*decoder,
*conv,
*sink;
GstBus *bus;
guint bus_watch_id;
/* Initialisation */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* Check input arguments */
if (argc != 2)
{
g_printerr ("Usage: %s <Flac filename>\n", argv[0]);
return -1;
}
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("audio-player");
source = gst_element_factory_make ("filesrc", "file-source");
//demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer");
decoder = gst_element_factory_make ("flacdec", "flac-decoder");
conv = gst_element_factory_make ("audioconvert", "converter");
sink = gst_element_factory_make ("alsasink", "audio-output");
if (!pipeline || !source ||/* !demuxer ||*/ !decoder ||/* !conv ||*/ !sink)
{
g_printerr ("One element could not be created. Exiting.\n");
return -1;
}
/* Set up the pipeline */
/* we set the input filename to the source element */
g_object_set (G_OBJECT (source), "location", argv[1], NULL);
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
/* we add all elements into the pipeline */
/* file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output */
gst_bin_add_many (GST_BIN (pipeline), source,/* demuxer,*/ decoder, conv, sink, NULL);
/* we link the elements together */
/* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output */
//gst_element_link (source, demuxer);
gst_element_link_many (source, decoder, conv, sink, NULL);
// g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder);
/* note that the demuxer will be linked to the decoder dynamically.
The reason is that Ogg may contain various streams (for example
audio and video). The source pad(s) will be created at run time,
by the demuxer when it detects the amount and nature of streams.
Therefore we connect a callback function which will be executed
when the "pad-added" is emitted.*/
/* 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));
g_source_remove (bus_watch_id);
g_main_loop_unref (loop);
return 0;
I'm using this to compile it successfully:
g++ -Wall test-flac.cc -o test $(pkg-config --cflags --libs gstreamer-1.0)
I'm using Arch, if that means anything. Does anybody have some advice? I'm a pretty big noob, but I don't understand what I'm not doing right because it seems like it should work.
I just needed to replace the demuxer with a parsar, which is (apparently) necessary. Derp. I used flacparse, of course.

running the gstreamer pipeline (not able to get video and audio data in the callback)

I'm a newbie to gstreamer and I wanted to get the audio and video both buffers from a 3gp file and do some processing in the callback.
(I'm starting my pipeline into a separate thread, pipeline gives audio buffers in a callback AudioCallback and video buffers in VideoCallback.)
This is how my pipeline looks:
GstElement* audioQueue;//global variable , needed in on_pad_added (cant pass both while connecting demuxer to callback)
GstElement* videoQueue;//global variable , needed in on_pad_added (cant pass both while connecting demuxer to callback)
//static functions
static gboolean
bus_call (GstBus* bus, GstMessage* msg, gpointer data)
{
GMainLoop* loop = (GMainLoop*) data;
switch (GST_MESSAGE_TYPE (msg))
{
case GST_MESSAGE_EOS:
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ERROR: {
gchar *debug;
GError *error;
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
g_main_loop_quit (loop);
break;
}
default:
break;
}
return true;
}
static void link_two_elements(GstElement* src_element, GstElement* sink_element)
{
if(!gst_element_link(src_element, sink_element))
g_printerr ("Linking Error");
}
static void
on_pad_added (GstElement *element,
GstPad *pad,
gpointer data)
{
GstCaps *caps;
GstStructure *str;
gchar *tex;
GstPad* sinkpad;
/* check media type */
caps = gst_pad_get_caps (pad);
str = gst_caps_get_structure (caps, 0);
tex = (gchar*)gst_structure_get_name(str);
if(g_strrstr(tex,"audio"))
{
//GstElement *audioQueue = (GstElement *) data;
sinkpad = gst_element_get_static_pad (audioQueue, "sink");
if(sinkpad)
{
GstPadLinkReturn linkReturn = gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
}
}
if(g_strrstr(tex,"video"))
{
//GstElement *videoQueue = (GstElement *) data;
sinkpad = gst_element_get_static_pad (videoQueue, "sink");
GstPadLinkReturn linkReturn = gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
}
}
void runPipeline()
{
GMainLoop *loop;
GstElement *__pPipeline, *source, *demuxer, *audioDecoder, *audioConverter, *audioresample, /**audioQueue,*/ *audioSink, *videoDecoder, *videoSink, /**videoQueue,*/ *ffmpegcolorspace, *videoscale;
GstBus* bus;
//Initialisation
gst_init (null,null);
loop = g_main_loop_new (NULL, FALSE);
// Create gstreamer elements
__pPipeline = gst_pipeline_new("test_appsink");
source = gst_element_factory_make ("filesrc", "file-source");
demuxer = gst_element_factory_make("qtdemux", "demuxer");
//audioDecoder = gst_element_factory_make("ffdec_mp3", "audioDecoder");
audioDecoder = gst_element_factory_make("decodebin", "audioDecoder");
audioConverter = gst_element_factory_make("audioconvert", "audioConverter");
audioresample = gst_element_factory_make("audioresample", "audioresample");
audioSink = gst_element_factory_make("appsink", "audioSink");
audioQueue = gst_element_factory_make("queue2", "audioQueue");
//videoDecoder = gst_element_factory_make("ffdec_h264", "videoDecoder");
videoQueue = gst_element_factory_make("queue2", "videoQueue");
videoDecoder = gst_element_factory_make("decodebin ", "videoDecoder");
ffmpegcolorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace");
videoscale = gst_element_factory_make("videoscale", "videoscale");
videoSink = gst_element_factory_make("appsink", "videoSink");
//appsink = gst_element_factory_make("appsink", "sink-buffer");
if (!__pPipeline || !source || !demuxer || !audioDecoder || !audioConverter ||!audioresample || !audioSink || !videoSink || !audioQueue || !videoQueue || !videoDecoder || !ffmpegcolorspace || !videoscale )
{
//return -1;
}
//we set the input filename to the source element
g_object_set (G_OBJECT (source), "location", "/etc/20000101-161404.3gp", NULL);
//Make appsink emit the "new-preroll" and "new-buffer" signals.
gst_app_sink_set_emit_signals ((GstAppSink*) audioSink, TRUE);
gst_app_sink_set_emit_signals ((GstAppSink*) videoSink, TRUE);
//we add a message handler
bus = gst_pipeline_get_bus (GST_PIPELINE (__pPipeline));
gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
//we add all elements into the pipeline
gst_bin_add_many (GST_BIN (__pPipeline),
source, demuxer, videoDecoder, audioDecoder, audioConverter, audioresample, audioSink, videoSink,
audioQueue, videoQueue, ffmpegcolorspace, videoscale, NULL);
//link source and demuxer seperately
link_two_elements(source, demuxer);
//link rest of the elements
int retValVideoLinking = (int)gst_element_link_many (videoQueue, videoDecoder, ffmpegcolorspace, videoscale, videoSink, NULL);
int retValAudioLinking = (int)gst_element_link_many (audioQueue, audioDecoder, audioConverter, audioresample, audioSink, NULL);
gulong sigConRet = g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), null);
_ArAudioIn audioInstance = _ArAudioIn::GetArAudioInstance();
g_signal_connect (videoSink, "new-buffer", G_CALLBACK (AudioCallback), null);//AudioCallback static API
g_signal_connect (audioSink, "new-buffer", G_CALLBACK (VideoCallback), null);//VideoCallback static API
//Set the pipeline to "playing" state
GstStateChangeReturn state = gst_element_set_state (__pPipeline, GST_STATE_PLAYING);
g_main_loop_run (loop);
return null;
}
I'm just getting a single video buffer in my Videocallback and also in the on_pad_addded : I'm getting a linking err for audio pad linking.
GST_PAD_LINK_NOFORMAT = -4,
I'm trying to link the queue's sink pad to the pad recieved in on_pad_added, same is working for video but not for audio.
If anybody has any idea about this then please give me some pointers to get rid off this err and make this pipeline work.
It would be nice if you cleanup you code before asking us to debug it. As a general advice, check the return values and either log a warning or simply exit(1) to ensure that your pipeline setup works (E.g. in the pad_added handler). I'd also start using a normal video and audiosink to check that it plays.
Finally, it is usually a bad idea to pull out data from the pipleine. Perhaps you could tell what you want to do with the data once you have it in your callback, so that we can give better advice.

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
}

How to convert a Gstreamer program to stream video via udp into a Qt program?

I have a Gstreamer program that streams video via UDP source. I need to implement the program in Qt. Please let me know how can I do it.
The program I'm using is shown below.
#include <gst/gst.h>
#include <stdio.h>
#include <stdlib.h>
GstElement *pipeline,
*source,
*decoder,
*video_sink,
*text,
*audio_sink;
static gboolean
bus_call (GstBus *bus,
GstMessage *msg,
gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:
g_print ("End-of-stream\n");
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ERROR:
{
gchar *debug;
GError *err;
gst_message_parse_error (msg, &err, &debug);
g_free (debug);
g_print ("Error: %s\n", err->message);
g_error_free (err);
g_main_loop_quit (loop);
break;
}
default:
break;
}
return TRUE;
}
static void
new_pad (GstElement *element,
GstPad *pad,
gpointer data)
{
GstPad *sinkpad = NULL;
const gchar *mime;
GstCaps *caps;
// get capabilities
caps = gst_pad_get_caps (pad);
// get mime type
mime = gst_structure_get_name (gst_caps_get_structure (caps, 0));
g_print ("Dynamic pad %s:%s created with mime-type %s\n", GST_OBJECT_NAME (element), GST_OBJECT_NAME (pad), mime);
if (g_strrstr (mime, "video"))
{
g_print ("Linking video...\n");
sinkpad = gst_element_get_static_pad (text, "video_sink");
}
if (g_strrstr (mime, "audio"))
{
g_print ("Linking audio...\n");
sinkpad = gst_element_get_static_pad (audio_sink, "sink");
}
if(sinkpad!=NULL)
{
// link
gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
}
gst_caps_unref (caps);
}
int main (int argc, char *argv[])
{
GMainLoop *loop;
GstBus *bus;
// initialize GStreamer
gst_init (&argc, &argv);
printf("step 0\n");
loop = g_main_loop_new (NULL, FALSE);
/* check input arguments
if (argc != 2)
{
g_print ("Usage: %s <filename>\n", argv[0]);
return -1;
}*/
// argv[1]="http://192.168.0.247:1234/Documents/6.mpg";
//"udp://192.168.0.247:1234";
//"/home/quarkgluon/Documents/rajesh/gstreamer/Serenity.mp4";
printf("step 1\n");
// create elements
pipeline = gst_pipeline_new ("video-player");
source = gst_element_factory_make ("udpsrc", "source");
decoder = gst_element_factory_make ("decodebin2", "decoder");
text = gst_element_factory_make ("textoverlay", "text");
video_sink = gst_element_factory_make ("xvimagesink", "vsink");
audio_sink = gst_element_factory_make ("alsasink", "asink");
if (!pipeline || !source || !decoder || !video_sink || !text || !audio_sink)
{
g_print ("One element could not be created\n");
return -1;
}
// set filename property on the file source. Also add a message
// handler.
g_object_set (G_OBJECT (source),"port",1234, NULL);
// g_object_set (G_OBJECT (text), "text", "hello world awertyuiop!!!", NULL);
// g_object_set (G_OBJECT (text), "italic", 1, NULL);
//g_object_set (G_OBJECT (text), "bold", 1, NULL);
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
// put all elements in a bin
gst_bin_add_many (GST_BIN (pipeline), source, decoder, video_sink, text, audio_sink, NULL);
// link together - note that we cannot link the decoder and
// sink yet, because the decoder uses dynamic pads. For that,
// we set a pad-added signal handler.
gst_element_link (source, decoder);
gst_element_link (text, video_sink);
g_signal_connect (decoder, "pad-added", G_CALLBACK (new_pad), NULL);
printf("step 2\n");
// Now set to playing and iterate.
g_print ("Setting to PLAYING\n");
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_print ("Running\n");
g_main_loop_run (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;
}
http://cgit.freedesktop.org/gstreamer/qt-gstreamer/