/*
gcc -Wall gst.c -o gst $(pkg-config --cflags --libs gstreamer-0.10)
*/
#include <gst/gst.h>
#include <glib.h>
static gboolean
bus_call (GstBus *bus,
GstMessage *msg,
gpointer data)
{
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:
g_print ("End of stream\n");
/* restart playback if at end */
GstElement *play = GST_ELEMENT(data);
if (!gst_element_seek(play,
1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, 0,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
g_print("Seek failed!\n");
}
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);
}
/*
static gboolean
idle_exit_loop (gpointer data)
{
g_main_loop_quit ((GMainLoop *) data);
return FALSE;
}
static void
cb_typefound (GstElement *typefind,
guint probability,
GstCaps *caps,
gpointer data)
{
GMainLoop *loop = data;
gchar *type;
type = gst_caps_to_string (caps);
g_print ("Media type %s found, probability %d%%\n", type, probability);
g_free (type);
* since we connect to a signal in the pipeline thread context, we need
* to set an idle handler to exit the main loop in the mainloop context.
* Normally, your app should not need to worry about such things. *
g_idle_add (idle_exit_loop, loop);
}
*/
static gboolean
cb_print_position (GstElement *pipeline)
{
GstFormat fmt = GST_FORMAT_TIME;
gint64 pos, len;
if (gst_element_query_position (pipeline, &fmt, &pos)
&& gst_element_query_duration (pipeline, &fmt, &len)) {
g_print ("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
GST_TIME_ARGS (pos), GST_TIME_ARGS (len));
}
/* call me again */
return TRUE;
}
int
main (int argc,
char *argv[])
{
GMainLoop *loop;
GstElement *pipeline, *source, *demuxer, *vqueue, *vpudec, *sink;
GstBus *bus;
guint bus_watch_id;
/* Initialisation */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* Check input arguments */
if (argc != 3) {
g_printerr ("Usage: %s <mp4 filename1> </dev/video**>\n", argv[0]);
return -1;
}
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("video-player");
source = gst_element_factory_make ("filesrc", "source");
//typefind = gst_element_factory_make ("typefind", "typefinder");
demuxer = gst_element_factory_make ("aiurdemux", "demuxer");
vqueue = gst_element_factory_make ("queue", "videoqueue");
vpudec = gst_element_factory_make ("vpudec", "video_decoder");
sink = gst_element_factory_make ("mfw_v4lsink", "video_sink");
if (!pipeline || !source || !demuxer || !vqueue || !vpudec || !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);
g_object_set (G_OBJECT (sink), "device", argv[2], NULL);
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, pipeline);
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, vqueue, vpudec, sink, NULL);
/* we link the elements together */
/* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output */
GstCaps *caps;
/* for mp4 playback use "video/quicktime", if it is ts file use "video/mpegts" , likewise corresponding to other files. You can find what to use as caps using gst-discoverer command for the file*/
caps = gst_caps_new_simple("video/quicktime",NULL);
//After creating caps link using link_filtered to the demuxer
if (!gst_element_link_filtered(source,demuxer,caps)){
g_printerr ("Elements could not be linked.\n");
gst_object_unref (GST_OBJECT (pipeline));
return -1;
}
gst_caps_unref(caps); //unref after use, then the normal code continues with generating //pad-added signal.
gst_element_link (source, demuxer);
gst_element_link_many (vqueue, vpudec, sink, NULL);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), vqueue);
/* 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.*/
//loopplay:
/* Set the pipeline to "playing" state*/
g_print ("Now playing: %s\n", argv[1]);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
// g_timeout_add (200, (GSourceFunc) cb_print_position, pipeline);
/* 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);
// goto loopplay;
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (pipeline));
g_source_remove (bus_watch_id);
g_main_loop_unref (loop);
return 0;
}