Deconstructing a pipeline
Jack D
jackstuff3 at gmail.com
Tue Nov 15 23:04:36 UTC 2016
I am trying to duplicate the following pipeline through a C program
gst-launch-1.0 v4l2src device=/dev/video0 !
'video/x-raw,width=800,height=480' ! gtksink
The C program nearly duplicates the output of this command line pipeline.
The problem is the video is fuzzy or unfocused. I can run them side by side
and the action is precise, just the command line output is clear and
pristine and the c code output is bad.
Since the C code is relatively short, I'll include it here.
Thanks,
Jack
#include <string.h>
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>
#include <gdk/gdk.h>
#define vid_caps "video/x-raw,width=800,height=480"
/* Structure to contain all our information, so we can pass it around */
typedef struct _CustomData {
GstElement *pipeline; /* Pipeline */
GstElement *playbin; /* Source */
GstElement *playsink; /* Sink */
GstElement *sink; /* sink to hold video */
GstState state; /* Current state of the pipeline */
} CustomData;
/* This function is called when the PLAY button is clicked */
static void play_cb (GtkButton *button, CustomData *data) {
gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
}
/* This function is called when the PAUSE button is clicked */
static void pause_cb (GtkButton *button, CustomData *data) {
gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
}
/* This function is called when the STOP button is clicked */
static void stop_cb (GtkButton *button, CustomData *data) {
gst_element_set_state (data->pipeline, GST_STATE_READY);
}
/* This function is called when the main window is closed */
static void delete_event_cb (GtkWidget *widget, GdkEvent *event, CustomData
*data) {
stop_cb (NULL, data);
gtk_main_quit ();
}
/* This creates all the GTK+ widgets that compose our application, and
registers the callbacks */
static void create_ui (CustomData *data) {
GtkWidget *main_window; /* The uppermost window, containing all other
windows */
GtkWidget *video_window; /* The drawing area where the video will be
shown */
GtkWidget *main_box; /* VBox to hold main_hbox and the controls */
GtkWidget *main_hbox; /* HBox to hold the video_window and the stream
info text widget */
GtkWidget *controls; /* HBox to hold the buttons and the slider */
GtkWidget *play_button, *pause_button, *stop_button; /* Buttons */
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (main_window), "delete-event", G_CALLBACK
(delete_event_cb), data);
g_object_get (data->playsink, "widget", &video_window, NULL);
gtk_widget_set_double_buffered (video_window, FALSE);
play_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PLAY);
g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK
(play_cb), data);
pause_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PAUSE);
g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK
(pause_cb), data);
controls = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start (GTK_BOX (controls), play_button, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (controls), pause_button, FALSE, FALSE, 2);
main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start (GTK_BOX (main_hbox), video_window, TRUE, TRUE, 0);
main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start (GTK_BOX (main_box), main_hbox, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (main_box), controls, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (main_window), main_box);
gtk_window_set_default_size (GTK_WINDOW (main_window), 640, 480);
gtk_widget_show_all (main_window);
}
/* This function is called when an End-Of-Stream message is posted on the
bus.
* We just set the pipeline to READY (which stops playback) */
static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) {
g_print ("End-Of-Stream reached.\n");
gst_element_set_state (data->pipeline, GST_STATE_READY);
}
int main(int argc, char *argv[]) {
CustomData data;
GstStateChangeReturn ret;
GstBus *bus;
GError **parse_error;
GstCaps *video_caps;
gboolean link_ok;
/* Initialize GTK */
gtk_init (&argc, &argv);
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Initialize our data structure */
memset (&data, 0, sizeof (data));
/* Create the elements */
data.pipeline = gst_pipeline_new ("pipeline");
data.playbin = gst_element_factory_make ("v4l2src", "source");
data.playsink = gst_element_factory_make ("gtksink", "playsink");
video_caps = gst_caps_from_string(vid_caps);
// printf("Vid caps %s.\n", vid_caps);
if (!data.playbin || !data.pipeline || !data.playsink || !video_caps) {
g_printerr ("Not all elements could be created.\n");
return -1;
}
/* Set the URI to play */
g_object_set (G_OBJECT(data.playbin), "device", "/dev/video0", NULL);
gst_bin_add (GST_BIN(data.pipeline), data.playbin);
gst_bin_add (GST_BIN(data.pipeline), data.playsink);
if (!(gst_element_link(data.playbin, data.playsink))) {
g_printerr ("Unable to link the source and the sink.\n");
gst_object_unref (data.pipeline);
return -1;
}
gst_element_link_many (data.playbin, data.playsink, NULL);
link_ok = gst_element_link_filtered (data.playbin, data.playsink,
video_caps);
gst_caps_unref(video_caps);
if (!link_ok) {
g_warning("Failed to link playbin and playsink with caps");
}
/* Create the GUI */
create_ui (&data);
/* Start playing */
ret = gst_element_set_state (data.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 (data.pipeline);
return -1;
}
/* Start the GTK main loop. We will not regain control until
gtk_main_quit is called. */
gtk_main ();
/* Free resources */
gst_element_set_state (data.pipeline, GST_STATE_NULL);
gst_object_unref (data.pipeline);
return 0;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20161115/16459d1d/attachment-0001.html>
More information about the gstreamer-devel
mailing list