From ae5999ee6bbba58725b55724b36db9aa62612347 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Mon, 26 Mar 2018 13:54:36 +0900 Subject: [PATCH] [Gst Example] tutorial-6 and 7 Added tutorial 6 and 7 Signed-off-by: MyungJoo Ham --- gst_example/tutorial6/basic-tutorial-6.c | 208 +++++++++++++++++++++++++++++++ gst_example/tutorial7/basic-tutorial-7.c | 88 +++++++++++++ 2 files changed, 296 insertions(+) create mode 100644 gst_example/tutorial6/basic-tutorial-6.c create mode 100644 gst_example/tutorial7/basic-tutorial-7.c diff --git a/gst_example/tutorial6/basic-tutorial-6.c b/gst_example/tutorial6/basic-tutorial-6.c new file mode 100644 index 0000000..95b487f --- /dev/null +++ b/gst_example/tutorial6/basic-tutorial-6.c @@ -0,0 +1,208 @@ +#include + +/* 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 index 0000000..735d636 --- /dev/null +++ b/gst_example/tutorial7/basic-tutorial-7.c @@ -0,0 +1,88 @@ +#include + +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; +} + -- 2.7.4