static void on_pad_added (GstElement * element, GstPad * pad, GstElement * pipeline) { GstElement *ipcpipelinesink; GstPad *sinkpad; GstCaps *caps; const GstStructure *structure; GstIterator *it; GValue elem = G_VALUE_INIT; int sockets[2]; gboolean create_sockets; caps = gst_pad_get_current_caps (pad); structure = gst_caps_get_structure (caps, 0); it = gst_bin_iterate_sinks (GST_BIN (pipeline)); if (gst_iterator_find_custom (it, find_ipcpipelinesink, &elem, (gpointer) gst_structure_get_name (structure))) { ipcpipelinesink = g_value_get_object (&elem); create_sockets = FALSE; g_value_reset (&elem); } else { ipcpipelinesink = gst_element_factory_make ("ipcpipelinesink", NULL); gst_bin_add (GST_BIN (pipeline), ipcpipelinesink); create_sockets = TRUE; } sinkpad = gst_element_get_static_pad (ipcpipelinesink, "sink"); if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) { fprintf (stderr, "Failed to link ipcpipelinesink\n"); exit (1); } gst_object_unref (sinkpad); g_signal_connect (pad, "unlinked", (GCallback) on_pad_unlinked, pipeline); if (create_sockets) { if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockets)) { fprintf (stderr, "Error creating sockets: %s\n", strerror (errno)); exit (1); } if (fcntl (sockets[0], F_SETFL, O_NONBLOCK) < 0 || fcntl (sockets[1], F_SETFL, O_NONBLOCK) < 0) { fprintf (stderr, "Error setting O_NONBLOCK on sockets: %s\n", strerror (errno)); exit (1); } g_object_set (ipcpipelinesink, "fdin", sockets[0], "fdout", sockets[0], NULL); printf ("new socket %d\n", sockets[1]); sendfd (pipes[1], sockets[1]); } gst_element_set_state (ipcpipelinesink, GST_STATE_PLAYING); GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pad.added"); }
static GstElement * find_composition (GESTrack * track) { GstIterator *it = gst_bin_iterate_recurse (GST_BIN (track)); GValue val = { 0, }; GstElement *ret = NULL; if (gst_iterator_find_custom (it, (GCompareFunc) find_composition_func, &val, NULL)) ret = g_value_get_object (&val); g_value_unset (&val); gst_iterator_free (it); return ret; }
GstElement *find_element_by_factory_name(GstBin *p_bin, std::string const &p_factory_name) { GstIterator *iter = gst_bin_iterate_recurse(p_bin); if (iter == nullptr) return nullptr; GValue result = G_VALUE_INIT; gboolean found = gst_iterator_find_custom(iter, find_by_factory_func, &result, (gpointer)(&p_factory_name)); gst_iterator_free(iter); if (found) { GstElement *elem = GST_ELEMENT(g_value_dup_object(&result)); g_value_unset(&result); return elem; } else return nullptr; }
GstElement * rb_player_gst_find_element_with_property (GstElement *element, const char *property) { GstIterator *iter; GstElement *result; if (GST_IS_BIN (element) == FALSE) { if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), property) != NULL) { return g_object_ref (element); } return NULL; } rb_debug ("iterating bin looking for property %s", property); iter = gst_bin_iterate_recurse (GST_BIN (element)); result = gst_iterator_find_custom (iter, (GCompareFunc) find_property_element, (gpointer) property); gst_iterator_free (iter); return result; }
static void suboverlay_child_added_cb (GstElement * suboverlay, GstElement * child, InsanityTest * test) { GstIterator *it = NULL; GstPad *render_sub_sink, *tmppad; GstElementFactory *fact; const gchar *klass, *name; gulong probe_id; GValue value = { 0, }; gboolean is_renderer = FALSE; /* cc-ed from -base/gstsubtitleoveraly.c */ fact = gst_element_get_factory (child); klass = gst_element_factory_get_metadata (fact, GST_ELEMENT_METADATA_KLASS); if (GST_IS_BIN (child)) return; name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (fact)); if (g_strrstr (klass, "Overlay/Subtitle") != NULL || g_strrstr (klass, "Overlay/SubPicture") != NULL) is_renderer = TRUE; else if (g_strcmp0 (name, "textoverlay") == 0) is_renderer = TRUE; if (is_renderer == FALSE) goto done; LOG (test, "Renderer found: %s", name); /* Now adding the probe to the renderer "subtitle" sink pad */ it = gst_element_iterate_sink_pads (child); if (gst_iterator_find_custom (it, (GCompareFunc) find_renderer_subtitle_sinkpad, &value, NULL)) { render_sub_sink = g_value_get_object (&value); } else { goto done; } if (insanity_gst_test_add_data_probe (INSANITY_GST_TEST (test), GST_BIN (glob_pipeline), GST_OBJECT_NAME (child), GST_ELEMENT_NAME (render_sub_sink), &tmppad, &probe_id, &renderer_probe_cb, NULL, NULL) == TRUE) { glob_renderer_sink_probe = g_slice_new0 (ProbeContext); glob_renderer_sink_probe->probe_id = probe_id; glob_renderer_sink_probe->pad = render_sub_sink; glob_renderer_sink_probe->element = child; glob_renderer_sink_probe->test = test; glob_renderer_sink_probe->waiting_first_segment = TRUE; insanity_test_validate_checklist_item (test, "install-probes", TRUE, NULL); } else { insanity_test_validate_checklist_item (test, "install-probes", FALSE, "Failed to attach probe to fakesink"); insanity_test_done (test); goto done; } done: if (it) gst_iterator_free (it); }
static gboolean validate_codec_profile (FsCodec *codec,const gchar *bin_description, gboolean is_send) { GError *error = NULL; GstElement *bin = NULL; guint src_pad_count = 0, sink_pad_count = 0; GstCaps *caps; gpointer matching_pad = NULL; GstIterator *iter; bin = parse_bin_from_description_all_linked (bin_description, &src_pad_count, &sink_pad_count, &error); /* if could not build bin, fail */ if (!bin) { GST_WARNING ("Could not build profile (%s): %s", bin_description, error->message); g_clear_error (&error); return FALSE; } g_clear_error (&error); caps = fs_codec_to_gst_caps (codec); if (is_send) iter = gst_element_iterate_src_pads (bin); else iter = gst_element_iterate_sink_pads (bin); matching_pad = gst_iterator_find_custom (iter, find_matching_pad, caps); gst_iterator_free (iter); if (!matching_pad) { GST_WARNING ("Invalid profile (%s), has no %s pad that matches the codec" " details", is_send ? "src" : "sink", bin_description); gst_caps_unref (caps); gst_object_unref (bin); return FALSE; } gst_caps_unref (caps); gst_object_unref (bin); if (is_send) { if (src_pad_count == 0) { GST_WARNING ("Invalid profile (%s), has 0 src pad", bin_description); return FALSE; } } else { if (src_pad_count != 1) { GST_WARNING ("Invalid profile (%s), has %u src pads, should have one", bin_description, src_pad_count); return FALSE; } } if (sink_pad_count != 1) { GST_WARNING ("Invalid profile (%s), has %u sink pads, should have one", bin_description, sink_pad_count); return FALSE; } return TRUE; }
static gboolean hls_test_bus_message (InsanityGstPipelineTest * ptest, GstMessage * msg) { switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_BUFFERING: { gint per; gst_message_parse_buffering (msg, &per); /* First buffering happend properly, this is requiered to be able to * start seeking */ if (G_UNLIKELY (glob_buffered == FALSE)) { if (per == 100) { insanity_test_validate_checklist_item (INSANITY_TEST (ptest), "done-buffering", TRUE, NULL); glob_buffered = TRUE; if (glob_buffering_timeout != 0) { g_source_remove (glob_buffering_timeout); glob_buffering_timeout = 0; } } else { glob_buffering_timeout = g_timeout_add (250, (GSourceFunc) buffering_timeout, INSANITY_TEST (ptest)); } } break; } case GST_MESSAGE_STATE_CHANGED: if (GST_MESSAGE_SRC (msg) == GST_OBJECT (glob_pipeline)) { const char *validate_checklist_item = glob_validate_on_playing; GstState oldstate, newstate, pending; gst_message_parse_state_changed (msg, &oldstate, &newstate, &pending); if (newstate == GST_STATE_PAUSED && oldstate == GST_STATE_READY) { GstIterator *it; GValue v = { 0, }; gboolean queried; InsanityTest *test = INSANITY_TEST (ptest); GstQuery *query = gst_query_new_latency (); const gchar *step_message = "Could not query seeking\n"; if ((queried = gst_element_query (glob_pipeline, query))) { gst_query_parse_latency (query, &glob_is_live, NULL, NULL); step_message = NULL; } else insanity_test_printf (test, "Could not query\n"); insanity_gst_pipeline_test_set_live (ptest, glob_is_live); insanity_test_validate_checklist_item (test, "queried-live", queried, step_message); gst_query_unref (query); step_message = "Could not query seekable\n"; query = gst_query_new_seeking (GST_FORMAT_TIME); if ((queried = gst_element_query (glob_pipeline, query))) { gst_query_parse_seeking (query, NULL, &glob_is_seekable, NULL, NULL); step_message = NULL; } else insanity_test_printf (test, "Could not query\n"); insanity_test_validate_checklist_item (test, "queried-seekable", queried, step_message); gst_query_unref (query); /* Iterate over the bins to find a hlsdemux */ it = gst_bin_iterate_recurse (GST_BIN (glob_pipeline)); if (gst_iterator_find_custom (it, (GCompareFunc) find_hlsdemux, &v, NULL)) { glob_hlsdemux = g_value_dup_object (&v); } g_value_unset (&v); gst_iterator_free (it); if (glob_hlsdemux != NULL) { insanity_test_validate_checklist_item (test, "protocol-is-hls", TRUE, "HLS protocol in use"); gst_object_unref (glob_hlsdemux); } else { insanity_test_validate_checklist_item (test, "protocol-is-hls", FALSE, "HLS protocol in use"); insanity_test_done (test); } /* Watch pipeline only if seekable */ if (glob_is_seekable) watch_pipeline (ptest); } else if (newstate == GST_STATE_PLAYING && pending == GST_STATE_VOID_PENDING && validate_checklist_item) { glob_validate_on_playing = NULL; insanity_test_validate_checklist_item (INSANITY_TEST (ptest), validate_checklist_item, TRUE, NULL); /* let it run a couple seconds */ glob_wait_time = hls_test_get_wait_time (INSANITY_TEST (ptest)); glob_timer_id = g_timeout_add (250, (GSourceFunc) & wait_and_end_step, INSANITY_TEST (ptest)); } } break; case GST_MESSAGE_EOS: return FALSE; default: break; } return TRUE; }
/* This function looks for an input-selector, and, if one is found, cycle through its sink pads */ static gboolean check_track_selection (GstValidateMediaInfo * mi, gchar ** error_message) { GstElement *playbin; GstElement *videosink, *audiosink; GstElement *input_selector = NULL; GstBus *bus; GstMessage *msg; gboolean ret = TRUE; GstStateChangeReturn state_ret; GstIterator *iterator; GstPad *original_pad; static const GstClockTime switch_delay = GST_SECOND * 5; GValue value = { 0, }; playbin = gst_element_factory_make ("playbin", "fc-playbin"); videosink = gst_element_factory_make ("fakesink", "fc-videosink"); audiosink = gst_element_factory_make ("fakesink", "fc-audiosink"); if (!playbin || !videosink || !audiosink) { *error_message = g_strdup ("Playbin and/or fakesink not available"); } g_object_set (playbin, "video-sink", videosink, "audio-sink", audiosink, "uri", mi->uri, NULL); g_object_set (videosink, "sync", TRUE, NULL); g_object_set (audiosink, "sync", TRUE, NULL); bus = gst_pipeline_get_bus (GST_PIPELINE (playbin)); state_ret = gst_element_set_state (playbin, GST_STATE_PAUSED); if (state_ret == GST_STATE_CHANGE_FAILURE) { *error_message = g_strdup ("Failed to change pipeline to paused"); ret = FALSE; goto end; } else if (state_ret == GST_STATE_CHANGE_ASYNC) { msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_EOS | GST_MESSAGE_ERROR); if (msg && GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) { gst_message_unref (msg); } else { ret = FALSE; *error_message = g_strdup ("Playback finihshed unexpectedly"); goto end; } } if (gst_element_set_state (playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { *error_message = g_strdup ("Failed to set pipeline to playing"); ret = FALSE; goto end; } iterator = gst_bin_iterate_recurse (GST_BIN (playbin)); if (!gst_iterator_find_custom (iterator, (GCompareFunc) find_input_selector, &value, NULL)) { /* It's fine, there's only one if several tracks of the same type */ gst_iterator_free (iterator); input_selector = NULL; goto end; } input_selector = g_value_dup_object (&value); g_value_reset (&value); gst_iterator_free (iterator); g_object_get (input_selector, "active-pad", &original_pad, NULL); if (!original_pad) { /* Unexpected, log an error somehow ? */ ret = FALSE; gst_object_unref (input_selector); input_selector = NULL; goto end; } /* Attach a buffer counter to each pad */ setup_input_selector_counters (input_selector); while (1) { msg = gst_bus_timed_pop_filtered (bus, switch_delay, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); if (msg) { if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) { /* all good */ ret = TRUE; } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) { GError *error = NULL; gchar *debug = NULL; gst_message_parse_error (msg, &error, &debug); *error_message = g_strdup_printf ("Playback error: %s : %s", error->message, debug); g_error_free (error); g_free (debug); ret = FALSE; } else { g_assert_not_reached (); } gst_message_unref (msg); } else { /* Timeout, switch track if we have more, or stop */ GstPad *active_pad, *next_pad; g_object_get (input_selector, "active-pad", &active_pad, NULL); if (!active_pad) { *error_message = g_strdup ("Failed to get active-pad from input-selector"); ret = FALSE; goto end; } next_pad = find_next_pad (input_selector, active_pad); gst_object_unref (active_pad); if (!next_pad) { ret = FALSE; goto end; } if (next_pad == original_pad) { goto end; } g_object_set (input_selector, "active-pad", next_pad, NULL); gst_object_unref (next_pad); } } end: if (input_selector) { if (!check_and_remove_input_selector_counters (input_selector, error_message)) ret = FALSE; gst_object_unref (input_selector); } gst_object_unref (bus); gst_element_set_state (playbin, GST_STATE_NULL); gst_object_unref (playbin); return ret; }
GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) { gchar * sourceName; // source GstObject * source; source = GST_MESSAGE_SRC(msg); if (!GST_IS_OBJECT(source)) return GST_BUS_DROP; sourceName = gst_object_get_name(source); switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: { g_message("End-of-stream"); end_eof = 1; break; } case GST_MESSAGE_ERROR: { gchar * debug; GError *err; gst_message_parse_error(msg, &err, &debug); g_free (debug); lt_info_c( "%s:%s - GST_MESSAGE_ERROR: %s (%i) from %s\n", FILENAME, __FUNCTION__, err->message, err->code, sourceName ); if ( err->domain == GST_STREAM_ERROR ) { if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND ) { if ( g_strrstr(sourceName, "videosink") ) lt_info_c( "%s:%s - GST_MESSAGE_ERROR: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? else if ( g_strrstr(sourceName, "audiosink") ) lt_info_c( "%s:%s - GST_MESSAGE_ERROR: audioSink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? } } g_error_free(err); end_eof = 1; // NOTE: just to exit break; } case GST_MESSAGE_INFO: { gchar *debug; GError *inf; gst_message_parse_info (msg, &inf, &debug); g_free (debug); if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE ) { if ( g_strrstr(sourceName, "videosink") ) lt_info_c( "%s:%s - GST_MESSAGE_INFO: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? } g_error_free(inf); break; } case GST_MESSAGE_TAG: { GstTagList *tags, *result; gst_message_parse_tag(msg, &tags); result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE); if (result) { if (m_stream_tags) gst_tag_list_free(m_stream_tags); m_stream_tags = result; } const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0); if ( gv_image ) { GstBuffer *buf_image; buf_image = gst_value_get_buffer (gv_image); int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644); if(fd >= 0) { int ret = write(fd, GST_BUFFER_DATA(buf_image), GST_BUFFER_SIZE(buf_image)); close(fd); lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__ , ret); } //FIXME: how shall playback handle this event??? } gst_tag_list_free(tags); lt_info_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? break; } case GST_MESSAGE_STATE_CHANGED: { if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin)) break; GstState old_state, new_state; gst_message_parse_state_changed(msg, &old_state, &new_state, NULL); if(old_state == new_state) break; lt_info_c( "%s:%s - GST_MESSAGE_STATE_CHANGED: state transition %s -> %s\n", FILENAME, __FUNCTION__, gst_element_state_get_name(old_state), gst_element_state_get_name(new_state)); GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state); switch(transition) { case GST_STATE_CHANGE_NULL_TO_READY: { } break; case GST_STATE_CHANGE_READY_TO_PAUSED: { GstIterator *children; if (audioSink) { gst_object_unref(GST_OBJECT(audioSink)); audioSink = NULL; } if (videoSink) { gst_object_unref(GST_OBJECT(videoSink)); videoSink = NULL; } children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); audioSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBAudioSink")); videoSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBVideoSink")); gst_iterator_free(children); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { } break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: { } break; case GST_STATE_CHANGE_PAUSED_TO_READY: { if (audioSink) { gst_object_unref(GST_OBJECT(audioSink)); audioSink = NULL; } if (videoSink) { gst_object_unref(GST_OBJECT(videoSink)); videoSink = NULL; } } break; case GST_STATE_CHANGE_READY_TO_NULL: { } break; } break; } #if 0 case GST_MESSAGE_ELEMENT: { if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-xwindow-id")) { // set window id gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID()); // reshape window gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(GST_MESSAGE_SRC (msg)), 0, 0, glfb->getOSDWidth(), glfb->getOSDHeight()); // sync frames gst_x_overlay_expose(GST_X_OVERLAY(GST_MESSAGE_SRC (msg))); } } #endif break; default: break; } return GST_BUS_DROP; }