Deconstructing a pipeline

Michael Yarochkin michael.yarochkin at timetronics.be
Thu Nov 17 10:51:44 UTC 2016


Hello, Jack


I don`t really get your question.

Can you be more specific, please?

Also more details will be useful.


Mikl

________________________________
From: gstreamer-devel <gstreamer-devel-bounces at lists.freedesktop.org> on behalf of Jack D <jackstuff3 at gmail.com>
Sent: Wednesday, November 16, 2016 12:04:36 AM
To: Discussion of the development of and with GStreamer
Subject: Deconstructing a pipeline

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/20161117/b0b7604a/attachment-0001.html>


More information about the gstreamer-devel mailing list