[Gst Example] tutorial-6 and 7
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Mon, 26 Mar 2018 04:54:36 +0000 (13:54 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Mon, 26 Mar 2018 04:54:36 +0000 (13:54 +0900)
Added tutorial 6 and 7

Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
gst_example/tutorial6/basic-tutorial-6.c [new file with mode: 0644]
gst_example/tutorial7/basic-tutorial-7.c [new file with mode: 0644]

diff --git a/gst_example/tutorial6/basic-tutorial-6.c b/gst_example/tutorial6/basic-tutorial-6.c
new file mode 100644 (file)
index 0000000..95b487f
--- /dev/null
@@ -0,0 +1,208 @@
+#include <gst/gst.h>
+
+/* Functions below print the Capabilities in a human-friendly format */
+static gboolean print_field (GQuark field, const GValue * value, gpointer pfx) {
+  gchar *str = gst_value_serialize (value);
+
+  g_print ("%s  %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str);
+  g_free (str);
+  return TRUE;
+}
+
+static void print_caps (const GstCaps * caps, const gchar * pfx) {
+  guint i;
+
+  g_return_if_fail (caps != NULL);
+
+  if (gst_caps_is_any (caps)) {
+    g_print ("%sANY\n", pfx);
+    return;
+  }
+  if (gst_caps_is_empty (caps)) {
+    g_print ("%sEMPTY\n", pfx);
+    return;
+  }
+
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    GstStructure *structure = gst_caps_get_structure (caps, i);
+
+    g_print ("%s%s\n", pfx, gst_structure_get_name (structure));
+    gst_structure_foreach (structure, print_field, (gpointer) pfx);
+  }
+}
+
+/* Prints information about a Pad Template, including its Capabilities */
+static void print_pad_templates_information (GstElementFactory * factory) {
+  const GList *pads;
+  GstStaticPadTemplate *padtemplate;
+
+  g_print ("Pad Templates for %s:\n", gst_element_factory_get_longname (factory));
+  if (!gst_element_factory_get_num_pad_templates (factory)) {
+    g_print ("  none\n");
+    return;
+  }
+
+  pads = gst_element_factory_get_static_pad_templates (factory);
+  while (pads) {
+    padtemplate = pads->data;
+    pads = g_list_next (pads);
+
+    if (padtemplate->direction == GST_PAD_SRC)
+      g_print ("  SRC template: '%s'\n", padtemplate->name_template);
+    else if (padtemplate->direction == GST_PAD_SINK)
+      g_print ("  SINK template: '%s'\n", padtemplate->name_template);
+    else
+      g_print ("  UNKNOWN!!! template: '%s'\n", padtemplate->name_template);
+
+    if (padtemplate->presence == GST_PAD_ALWAYS)
+      g_print ("    Availability: Always\n");
+    else if (padtemplate->presence == GST_PAD_SOMETIMES)
+      g_print ("    Availability: Sometimes\n");
+    else if (padtemplate->presence == GST_PAD_REQUEST) {
+      g_print ("    Availability: On request\n");
+    } else
+      g_print ("    Availability: UNKNOWN!!!\n");
+
+    if (padtemplate->static_caps.string) {
+      GstCaps *caps;
+      g_print ("    Capabilities:\n");
+      caps = gst_static_caps_get (&padtemplate->static_caps);
+      print_caps (caps, "      ");
+      gst_caps_unref (caps);
+
+    }
+
+    g_print ("\n");
+  }
+}
+
+/* Shows the CURRENT capabilities of the requested pad in the given element */
+static void print_pad_capabilities (GstElement *element, gchar *pad_name) {
+  GstPad *pad = NULL;
+  GstCaps *caps = NULL;
+
+  /* Retrieve pad */
+  pad = gst_element_get_static_pad (element, pad_name);
+  if (!pad) {
+    g_printerr ("Could not retrieve pad '%s'\n", pad_name);
+    return;
+  }
+
+  /* Retrieve negotiated caps (or acceptable caps if negotiation is not finished yet) */
+  caps = gst_pad_get_current_caps (pad);
+  if (!caps)
+    caps = gst_pad_query_caps (pad, NULL);
+
+  /* Print and free */
+  g_print ("Caps for the %s pad:\n", pad_name);
+  print_caps (caps, "      ");
+  gst_caps_unref (caps);
+  gst_object_unref (pad);
+}
+
+int main(int argc, char *argv[]) {
+  GstElement *pipeline, *source, *sink;
+  GstElementFactory *source_factory, *sink_factory;
+  GstBus *bus;
+  GstMessage *msg;
+  GstStateChangeReturn ret;
+  gboolean terminate = FALSE;
+
+  /* Initialize GStreamer */
+  gst_init (&argc, &argv);
+
+  /* Create the element factories */
+  source_factory = gst_element_factory_find ("audiotestsrc");
+  sink_factory = gst_element_factory_find ("autoaudiosink");
+  if (!source_factory || !sink_factory) {
+    g_printerr ("Not all element factories could be created.\n");
+    return -1;
+  }
+
+  /* Print information about the pad templates of these factories */
+  print_pad_templates_information (source_factory);
+  print_pad_templates_information (sink_factory);
+
+  /* Ask the factories to instantiate actual elements */
+  source = gst_element_factory_create (source_factory, "source");
+  sink = gst_element_factory_create (sink_factory, "sink");
+
+  /* Create the empty pipeline */
+  pipeline = gst_pipeline_new ("test-pipeline");
+
+  if (!pipeline || !source || !sink) {
+    g_printerr ("Not all elements could be created.\n");
+    return -1;
+  }
+
+  /* Build the pipeline */
+  gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
+  if (gst_element_link (source, sink) != TRUE) {
+    g_printerr ("Elements could not be linked.\n");
+    gst_object_unref (pipeline);
+    return -1;
+  }
+
+  /* Print initial negotiated caps (in NULL state) */
+  g_print ("In NULL state:\n");
+  print_pad_capabilities (sink, "sink");
+
+  /* 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 (check the bus for error messages).\n");
+  }
+
+  /* Wait until error, EOS or State Change */
+  bus = gst_element_get_bus (pipeline);
+  do {
+    msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS |
+        GST_MESSAGE_STATE_CHANGED);
+
+    /* 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);
+          terminate = TRUE;
+          break;
+        case GST_MESSAGE_EOS:
+          g_print ("End-Of-Stream reached.\n");
+          terminate = TRUE;
+          break;
+        case GST_MESSAGE_STATE_CHANGED:
+          /* We are only interested in state-changed messages from the pipeline */
+          if (GST_MESSAGE_SRC (msg) == GST_OBJECT (pipeline)) {
+            GstState old_state, new_state, pending_state;
+            gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
+            g_print ("\nPipeline state changed from %s to %s:\n",
+                gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
+            /* Print the current capabilities of the sink element */
+            print_pad_capabilities (sink, "sink");
+          }
+          break;
+        default:
+          /* We should not reach here because we only asked for ERRORs, EOS and STATE_CHANGED */
+          g_printerr ("Unexpected message received.\n");
+          break;
+      }
+      gst_message_unref (msg);
+    }
+  } while (!terminate);
+
+  /* Free resources */
+  gst_object_unref (bus);
+  gst_element_set_state (pipeline, GST_STATE_NULL);
+  gst_object_unref (pipeline);
+  gst_object_unref (source_factory);
+  gst_object_unref (sink_factory);
+  return 0;
+}
+
diff --git a/gst_example/tutorial7/basic-tutorial-7.c b/gst_example/tutorial7/basic-tutorial-7.c
new file mode 100644 (file)
index 0000000..735d636
--- /dev/null
@@ -0,0 +1,88 @@
+#include <gst/gst.h>
+
+int main(int argc, char *argv[]) {
+  GstElement *pipeline, *audio_source, *tee, *audio_queue, *audio_convert, *audio_resample, *audio_sink;
+  GstElement *video_queue, *visual, *video_convert, *video_sink;
+  GstBus *bus;
+  GstMessage *msg;
+  GstPad *tee_audio_pad, *tee_video_pad;
+  GstPad *queue_audio_pad, *queue_video_pad;
+
+  /* Initialize GStreamer */
+  gst_init (&argc, &argv);
+
+  /* Create the elements */
+  audio_source = gst_element_factory_make ("audiotestsrc", "audio_source");
+  tee = gst_element_factory_make ("tee", "tee");
+  audio_queue = gst_element_factory_make ("queue", "audio_queue");
+  audio_convert = gst_element_factory_make ("audioconvert", "audio_convert");
+  audio_resample = gst_element_factory_make ("audioresample", "audio_resample");
+  audio_sink = gst_element_factory_make ("autoaudiosink", "audio_sink");
+  video_queue = gst_element_factory_make ("queue", "video_queue");
+  visual = gst_element_factory_make ("wavescope", "visual");
+  video_convert = gst_element_factory_make ("videoconvert", "csp");
+  video_sink = gst_element_factory_make ("autovideosink", "video_sink");
+
+  /* Create the empty pipeline */
+  pipeline = gst_pipeline_new ("test-pipeline");
+
+  if (!pipeline || !audio_source || !tee || !audio_queue || !audio_convert || !audio_resample || !audio_sink ||
+      !video_queue || !visual || !video_convert || !video_sink) {
+    g_printerr ("Not all elements could be created.\n");
+    return -1;
+  }
+
+  /* Configure elements */
+  g_object_set (audio_source, "freq", 215.0f, NULL);
+  g_object_set (visual, "shader", 0, "style", 1, NULL);
+
+  /* Link all elements that can be automatically linked because they have "Always" pads */
+  gst_bin_add_many (GST_BIN (pipeline), audio_source, tee, audio_queue, audio_convert, audio_resample, audio_sink,
+      video_queue, visual, video_convert, video_sink, NULL);
+  if (gst_element_link_many (audio_source, tee, NULL) != TRUE ||
+      gst_element_link_many (audio_queue, audio_convert, audio_resample, audio_sink, NULL) != TRUE ||
+      gst_element_link_many (video_queue, visual, video_convert, video_sink, NULL) != TRUE) {
+    g_printerr ("Elements could not be linked.\n");
+    gst_object_unref (pipeline);
+    return -1;
+  }
+
+  /* Manually link the Tee, which has "Request" pads */
+  tee_audio_pad = gst_element_get_request_pad (tee, "src_%u");
+  g_print ("Obtained request pad %s for audio branch.\n", gst_pad_get_name (tee_audio_pad));
+  queue_audio_pad = gst_element_get_static_pad (audio_queue, "sink");
+  tee_video_pad = gst_element_get_request_pad (tee, "src_%u");
+  g_print ("Obtained request pad %s for video branch.\n", gst_pad_get_name (tee_video_pad));
+  queue_video_pad = gst_element_get_static_pad (video_queue, "sink");
+  if (gst_pad_link (tee_audio_pad, queue_audio_pad) != GST_PAD_LINK_OK ||
+      gst_pad_link (tee_video_pad, queue_video_pad) != GST_PAD_LINK_OK) {
+    g_printerr ("Tee could not be linked.\n");
+    gst_object_unref (pipeline);
+    return -1;
+  }
+  gst_object_unref (queue_audio_pad);
+  gst_object_unref (queue_video_pad);
+
+  /* Start playing the pipeline */
+  gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+  /* 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);
+
+  /* Release the request pads from the Tee, and unref them */
+  gst_element_release_request_pad (tee, tee_audio_pad);
+  gst_element_release_request_pad (tee, tee_video_pad);
+  gst_object_unref (tee_audio_pad);
+  gst_object_unref (tee_video_pad);
+
+  /* Free resources */
+  if (msg != NULL)
+    gst_message_unref (msg);
+  gst_object_unref (bus);
+  gst_element_set_state (pipeline, GST_STATE_NULL);
+
+  gst_object_unref (pipeline);
+  return 0;
+}
+