Last active
June 10, 2026 09:49
-
-
Save SanchayanMaity/d7a7e2ec1de2ef43b4fccb3cb4461c93 to your computer and use it in GitHub Desktop.
qtdemux per stream pad query
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <gst/gst.h> | |
| #include <stdio.h> | |
| static gboolean | |
| bus_callback (GstBus * bus, GstMessage * message, gpointer data) | |
| { | |
| GMainLoop *loop = data; | |
| switch (GST_MESSAGE_TYPE (message)) { | |
| case GST_MESSAGE_ERROR: | |
| { | |
| g_main_loop_quit (loop); | |
| break; | |
| } | |
| case GST_MESSAGE_EOS: | |
| g_main_loop_quit (loop); | |
| break; | |
| default: | |
| break; | |
| } | |
| return TRUE; | |
| } | |
| static gboolean query_position_timeout(gpointer user_data) { | |
| GstElement *pipeline = (GstElement *)user_data; | |
| GstElement *qtdemux; | |
| gint64 duration, position; | |
| GstIterator *iterator; | |
| GValue value = G_VALUE_INIT; | |
| gboolean done = FALSE; | |
| qtdemux = gst_bin_get_by_name(GST_BIN(pipeline), "qtdemux"); | |
| if (!qtdemux) { | |
| g_printerr("Failed to find qtdemux element\n"); | |
| return G_SOURCE_CONTINUE; | |
| } | |
| if (gst_element_query_position(qtdemux, GST_FORMAT_TIME, &position)) { | |
| g_print("Element position (qtdemux): %" GST_TIME_FORMAT "\n", | |
| GST_TIME_ARGS(position)); | |
| } else { | |
| g_print("Failed to query element position\n"); | |
| } | |
| iterator = gst_element_iterate_src_pads(qtdemux); | |
| while (!done) { | |
| switch (gst_iterator_next(iterator, &value)) { | |
| case GST_ITERATOR_OK: { | |
| GstPad *pad = g_value_get_object(&value); | |
| if (gst_pad_query_position(pad, GST_FORMAT_TIME, &position)) { | |
| g_print("Pad position - Name: %s, Position: %" GST_TIME_FORMAT "\n", | |
| GST_PAD_NAME(pad), GST_TIME_ARGS(position)); | |
| } else { | |
| g_print("Failed to query position for pad: %s\n", GST_PAD_NAME(pad)); | |
| } | |
| if (gst_pad_query_duration(pad, GST_FORMAT_TIME, &duration)) { | |
| g_print("Pad duration - Name: %s, Duration: %" GST_TIME_FORMAT "\n", | |
| GST_PAD_NAME(pad), GST_TIME_ARGS(duration)); | |
| } else { | |
| g_print("Failed to query duration for pad: %s\n", GST_PAD_NAME(pad)); | |
| } | |
| g_value_unset(&value); | |
| break; | |
| } | |
| case GST_ITERATOR_RESYNC: | |
| gst_iterator_resync(iterator); | |
| break; | |
| case GST_ITERATOR_ERROR: | |
| g_printerr("Error iterating source pads\n"); | |
| done = TRUE; | |
| break; | |
| case GST_ITERATOR_DONE: | |
| done = TRUE; | |
| break; | |
| } | |
| } | |
| gst_iterator_free(iterator); | |
| gst_object_unref(qtdemux); | |
| g_print("---\n"); | |
| return G_SOURCE_CONTINUE; | |
| } | |
| static void on_pad_added(GstElement *qtdemux, GstPad *pad, gpointer user_data) { | |
| GstElement *pipeline = (GstElement *)user_data; | |
| GstPadLinkReturn ret; | |
| GstCaps *caps; | |
| GstStructure *str; | |
| const gchar *mime_type; | |
| gchar queue_name[32]; | |
| gchar fakesink_name[32]; | |
| gint64 duration; | |
| caps = gst_pad_get_current_caps(pad); | |
| if (!caps) { | |
| caps = gst_pad_query_caps(pad, NULL); | |
| } | |
| str = gst_caps_get_structure(caps, 0); | |
| mime_type = gst_structure_get_name(str); | |
| g_print("Pad added: %s, MIME type: %s\n", GST_PAD_NAME(pad), mime_type); | |
| g_snprintf(queue_name, sizeof(queue_name), "queue_%s", GST_PAD_NAME(pad)); | |
| g_snprintf(fakesink_name, sizeof(fakesink_name), "fakesink_%s", GST_PAD_NAME(pad)); | |
| GstElement *queue = gst_element_factory_make("queue", queue_name); | |
| GstElement *fakesink = gst_element_factory_make("fakesink", fakesink_name); | |
| g_object_set (fakesink, "sync", TRUE, NULL); | |
| if (!queue || !fakesink) { | |
| g_printerr("Failed to create queue or fakesink element\n"); | |
| gst_caps_unref(caps); | |
| return; | |
| } | |
| gst_bin_add_many(GST_BIN(pipeline), queue, fakesink, NULL); | |
| if (gst_element_link(queue, fakesink) != TRUE) { | |
| g_printerr("Failed to link queue to fakesink\n"); | |
| gst_caps_unref(caps); | |
| return; | |
| } | |
| gst_element_sync_state_with_parent(queue); | |
| gst_element_sync_state_with_parent(fakesink); | |
| GstPad *queue_sink_pad = gst_element_get_static_pad(queue, "sink"); | |
| ret = gst_pad_link(pad, queue_sink_pad); | |
| gst_object_unref(queue_sink_pad); | |
| if (ret != GST_PAD_LINK_OK) { | |
| g_printerr("Failed to link qtdemux pad to queue: %d\n", ret); | |
| gst_caps_unref(caps); | |
| return; | |
| } | |
| gst_caps_unref(caps); | |
| if (gst_element_query_duration (qtdemux, GST_FORMAT_TIME, &duration)) { | |
| g_print("Element duration (qtdemux): %" GST_TIME_FORMAT "\n", GST_TIME_ARGS(duration)); | |
| } | |
| } | |
| static void on_no_more_pads(GstElement *qtdemux, gpointer user_data) { | |
| g_print("No more pads will be added\n\n"); | |
| } | |
| int main(int argc, char *argv[]) { | |
| GstElement *pipeline, *filesrc, *qtdemux; | |
| GstBus *bus; | |
| const gchar *filename; | |
| guint timeout_id; | |
| GMainLoop *mainloop; | |
| gst_init(&argc, &argv); | |
| if (argc < 2) { | |
| g_printerr("Usage: %s <input_file.mov|mp4|m4a|3gp>\n", argv[0]); | |
| return -1; | |
| } | |
| filename = argv[1]; | |
| pipeline = gst_pipeline_new("qtdemux_pipeline"); | |
| filesrc = gst_element_factory_make("filesrc", "filesrc"); | |
| qtdemux = gst_element_factory_make("qtdemux", "qtdemux"); | |
| if (!pipeline || !filesrc || !qtdemux) { | |
| g_printerr("Failed to create elements\n"); | |
| return -1; | |
| } | |
| g_object_set(G_OBJECT(filesrc), "location", filename, NULL); | |
| gst_bin_add_many(GST_BIN(pipeline), filesrc, qtdemux, NULL); | |
| if (!gst_element_link(filesrc, qtdemux)) { | |
| g_printerr("Failed to link filesrc to qtdemux\n"); | |
| gst_object_unref(pipeline); | |
| return -1; | |
| } | |
| g_signal_connect(qtdemux, "pad-added", G_CALLBACK(on_pad_added), pipeline); | |
| g_signal_connect(qtdemux, "no-more-pads", G_CALLBACK(on_no_more_pads), NULL); | |
| GstStateChangeReturn ret = gst_element_set_state(pipeline, GST_STATE_PLAYING); | |
| if (ret == GST_STATE_CHANGE_FAILURE) { | |
| g_printerr("Failed to set pipeline to PLAYING state\n"); | |
| gst_object_unref(pipeline); | |
| return -1; | |
| } | |
| timeout_id = g_timeout_add(5000, query_position_timeout, pipeline); | |
| mainloop = g_main_loop_new (NULL, FALSE); | |
| bus = gst_element_get_bus(pipeline); | |
| gst_bus_add_signal_watch (bus); | |
| g_signal_connect (bus, "message", (GCallback) bus_callback, mainloop); | |
| g_main_loop_run (mainloop); | |
| if (timeout_id > 0) { | |
| g_source_remove(timeout_id); | |
| } | |
| gst_element_set_state(pipeline, GST_STATE_NULL); | |
| gst_object_unref(bus); | |
| gst_object_unref(pipeline); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment