static void really_remove_tee (GstPad *pad, gboolean blocked, RBGstPipelineOp *op) { GstElement *bin; GstElement *parent; rb_debug ("really removing tee %p", op->element); _rb_player_gst_tee_emit_tee_pre_remove (RB_PLAYER_GST_TEE (op->player), op->element); /* find bin, remove everything */ bin = GST_ELEMENT_PARENT (op->element); g_object_ref (bin); parent = GST_ELEMENT_PARENT (bin); gst_bin_remove (GST_BIN (parent), bin); gst_element_set_state (bin, GST_STATE_NULL); gst_bin_remove (GST_BIN (bin), op->element); g_object_unref (bin); /* if we're supposed to be playing, unblock the sink */ if (blocked) { rb_debug ("unblocking pad after removing tee"); gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback)pipeline_op_done, NULL); } free_pipeline_op (op); }
bool MediaNode::disconnectNode(QObject *obj) { MediaNode *sink = qobject_cast<MediaNode*>(obj); if (root()) { // Disconnecting elements while playing or paused seems to cause // potential deadlock. Hence we force the pipeline into ready state // before any nodes are disconnected. gst_element_set_state(root()->pipeline(), GST_STATE_READY); Q_ASSERT(sink->root()); //sink has to have a root since it is onnected if (sink->description() & (AudioSink)) { GstPad *sinkPad = gst_element_get_pad(sink->audioElement(), "sink"); // Release requested src pad from tee GstPad *requestedPad = gst_pad_get_peer(sinkPad); if (requestedPad) { gst_element_release_request_pad(m_audioTee, requestedPad); gst_object_unref(requestedPad); } if (GST_ELEMENT_PARENT(sink->audioElement())) gst_bin_remove(GST_BIN(root()->audioGraph()), sink->audioElement()); gst_object_unref(sinkPad); } if (sink->description() & (VideoSink)) { GstPad *sinkPad = gst_element_get_pad(sink->videoElement(), "sink"); // Release requested src pad from tee GstPad *requestedPad = gst_pad_get_peer(sinkPad); if (requestedPad) { gst_element_release_request_pad(m_videoTee, requestedPad); gst_object_unref(requestedPad); } if (GST_ELEMENT_PARENT(sink->videoElement())) gst_bin_remove(GST_BIN(root()->videoGraph()), sink->videoElement()); gst_object_unref(sinkPad); } sink->breakGraph(); sink->setRoot(0); } m_videoSinkList.removeAll(obj); m_audioSinkList.removeAll(obj); if (sink->m_description & AudioSink) { // Remove sink from graph MediaNodeEvent event(MediaNodeEvent::AudioSinkRemoved, sink); mediaNodeEvent(&event); return true; } if ((m_description & VideoSource) && (sink->m_description & VideoSink)) { // Remove sink from graph MediaNodeEvent event(MediaNodeEvent::VideoSinkRemoved, sink); mediaNodeEvent(&event); return true; } return false; }
GstElement* PlaybackPipeline::pipeline() { if (!m_webKitMediaSrc || !GST_ELEMENT_PARENT(GST_ELEMENT(m_webKitMediaSrc.get()))) return nullptr; return GST_ELEMENT_PARENT(GST_ELEMENT_PARENT(GST_ELEMENT(m_webKitMediaSrc.get()))); }
static inline GstElementStats * get_element_stats (GstStatsTracer * self, GstElement * element) { GstElementStats *stats; gboolean is_new = FALSE; if (!element) { no_elem_stats.index = G_MAXUINT; return &no_elem_stats; } G_LOCK (_elem_stats); if (!(stats = g_object_get_qdata ((GObject *) element, data_quark))) { stats = create_element_stats (self, element); is_new = TRUE; } G_UNLOCK (_elem_stats); if (G_UNLIKELY (stats->parent_ix == G_MAXUINT)) { GstElement *parent = GST_ELEMENT_PARENT (element); if (parent) { GstElementStats *parent_stats = get_element_stats (self, parent); stats->parent_ix = parent_stats->index; } } if (G_UNLIKELY (is_new)) { log_new_element_stats (stats, element, GST_CLOCK_TIME_NONE); } return stats; }
static gboolean gst_bus_cb(GstBus *bus, GstMessage *msg, BusCbCtx *ctx) { if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ELEMENT && gst_structure_has_name(msg->structure, "level")) { GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg)); gchar *name = gst_element_get_name(src); if (!strcmp(name, "level")) { gdouble percent; gdouble threshold; GstElement *valve; percent = gst_msg_db_to_percent(msg, "rms"); gtk_progress_bar_set_fraction(ctx->level, percent * 5); percent = gst_msg_db_to_percent(msg, "decay"); threshold = gtk_range_get_value(ctx->threshold) / 100.0; valve = gst_bin_get_by_name(GST_BIN(GST_ELEMENT_PARENT(src)), "valve"); g_object_set(valve, "drop", (percent < threshold), NULL); g_object_set(ctx->level, "text", (percent < threshold) ? _("DROP") : " ", NULL); } g_free(name); } return TRUE; }
bool MediaNode::linkMediaNodeList(QList<QObject *> &list, GstElement *bin, GstElement *tee, GstElement *fakesink, GstElement *src) { if (!GST_ELEMENT_PARENT(tee)) { gst_bin_add(GST_BIN(bin), tee); if (!gst_element_link_pads(src, "src", tee, "sink")) return false; gst_element_set_state(tee, GST_STATE(bin)); } if (list.isEmpty()) { //connect node to a fake sink to avoid clogging the pipeline if (!connectToFakeSink(tee, fakesink, bin)) return false; } else { // Remove fake sink if previously connected if (!releaseFakeSinkIfConnected(tee, fakesink, bin)) return false; for (int i = 0 ; i < list.size() ; ++i) { QObject *sink = list[i]; if (MediaNode *output = qobject_cast<MediaNode*>(sink)) { if (!addOutput(output, tee)) return false; } } } return true; }
void gst_trace_element_discoved_entry_init_set_element (GstTraceElementDiscoveredEntry *entry, GstElement *element) { entry->element_id = element; g_strlcpy (entry->element_name, LGI_ELEMENT_NAME (element), GST_ELEMENT_NAME_LENGTH_MAX); g_strlcpy (entry->element_type_name, LGI_OBJECT_TYPE_NAME (element), GST_ELEMENT_TYPE_NAME_LENGTH_MAX); entry->parent_element_id = element ? GST_ELEMENT_PARENT (element) : NULL; }
static void really_add_tee (GstPad *pad, gboolean blocked, RBGstPipelineOp *op) { GstElement *queue; GstElement *audioconvert; GstElement *bin; GstElement *parent_bin; GstPad *sinkpad; GstPad *ghostpad; rb_debug ("really adding tee %p", op->element); /* set up containing bin */ bin = gst_bin_new (NULL); queue = gst_element_factory_make ("queue", NULL); audioconvert = gst_element_factory_make ("audioconvert", NULL); /* The bin contains elements that change state asynchronously * and not as part of a state change in the entire pipeline. */ g_object_set (bin, "async-handling", TRUE, NULL); g_object_set (queue, "max-size-buffers", 3, NULL); gst_bin_add_many (GST_BIN (bin), queue, audioconvert, op->element, NULL); gst_element_link_many (queue, audioconvert, op->element, NULL); /* add ghost pad */ sinkpad = gst_element_get_static_pad (queue, "sink"); ghostpad = gst_ghost_pad_new ("sink", sinkpad); gst_element_add_pad (bin, ghostpad); gst_object_unref (sinkpad); /* add it into the pipeline */ parent_bin = GST_ELEMENT_PARENT (op->fixture); gst_bin_add (GST_BIN (parent_bin), bin); gst_element_link (op->fixture, bin); /* if we're supposed to be playing, unblock the sink */ if (blocked) { rb_debug ("unblocking pad after adding tee"); gst_element_set_state (parent_bin, GST_STATE_PLAYING); gst_object_ref (ghostpad); gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback)pipeline_op_done, ghostpad); } else { gst_element_set_state (bin, GST_STATE_PAUSED); gst_object_ref (ghostpad); pipeline_op_done (NULL, FALSE, ghostpad); } _rb_player_gst_tee_emit_tee_inserted (RB_PLAYER_GST_TEE (op->player), op->element); free_pipeline_op (op); }
// Used to seal up unconnected source nodes by connecting unconnected src pads to fake sinks bool MediaNode::releaseFakeSinkIfConnected(GstElement *tee, GstElement *fakesink, GstElement *bin) { if (GST_ELEMENT_PARENT(fakesink) == GST_ELEMENT(bin)) { GstPad *sinkPad = gst_element_get_pad(fakesink, "sink"); // Release requested src pad from tee GstPad *requestedPad = gst_pad_get_peer(sinkPad); if (requestedPad) { gst_element_release_request_pad(tee, requestedPad); gst_object_unref(requestedPad); } gst_object_unref(sinkPad); gst_element_set_state(fakesink, GST_STATE_NULL); gst_bin_remove(GST_BIN(bin), fakesink); Q_ASSERT(!GST_ELEMENT_PARENT(fakesink)); } return true; }
static void request_pad_unlinked_cb(GstPad *pad, GstPad *peer, gpointer user_data) { GstElement *parent = GST_ELEMENT_PARENT(pad); GstIterator *iter; GstPad *remaining_pad; GstIteratorResult result; gst_element_release_request_pad(GST_ELEMENT_PARENT(pad), pad); iter = gst_element_iterate_src_pads(parent); result = gst_iterator_next(iter, (gpointer)&remaining_pad); if (result == GST_ITERATOR_DONE) { gst_element_set_locked_state(parent, TRUE); gst_element_set_state(parent, GST_STATE_NULL); gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(parent)), parent); } else if (result == GST_ITERATOR_OK) { gst_object_unref(remaining_pad); } gst_iterator_free(iter); }
bool MediaNode::unlink() { Q_ASSERT(root()); if (description() & AudioSource) { if (GST_ELEMENT_PARENT(m_audioTee) == GST_ELEMENT(root()->audioGraph())) { gst_element_set_state(m_audioTee, GST_STATE_NULL); gst_bin_remove(GST_BIN(root()->audioGraph()), m_audioTee); } for (int i=0; i<m_audioSinkList.size(); ++i) { QObject *audioSink = m_audioSinkList[i]; if (MediaNode *output = qobject_cast<MediaNode*>(audioSink)) { GstElement *element = output->audioElement(); if (GST_ELEMENT_PARENT(element) == GST_ELEMENT(root()->audioGraph())) { gst_element_set_state(element, GST_STATE_NULL); gst_bin_remove(GST_BIN(root()->audioGraph()), element); } } } } else if (description() & VideoSource) { if (GST_ELEMENT_PARENT(m_videoTee) == GST_ELEMENT(root()->videoGraph())) { gst_element_set_state(m_videoTee, GST_STATE_NULL); gst_bin_remove(GST_BIN(root()->videoGraph()), m_videoTee); } for (int i=0; i <m_videoSinkList.size(); ++i) { QObject *videoSink = m_videoSinkList[i]; if (MediaNode *vw = qobject_cast<MediaNode*>(videoSink)) { GstElement *element = vw->videoElement(); if (GST_ELEMENT_PARENT(element) == GST_ELEMENT(root()->videoGraph())) { gst_element_set_state(element, GST_STATE_NULL); gst_bin_remove(GST_BIN(root()->videoGraph()), element); } } } } return true; }
void GstUtils::sync_state_with_parent(GstElement *element) { if (!GST_IS_ELEMENT(element)) { g_debug("GstUtils::sync_state_with_parent, arg is not an element"); return; } GstElement *parent = GST_ELEMENT(GST_ELEMENT_PARENT(element)); if (GST_IS_ELEMENT(parent)) { if (GST_STATE(parent) != GST_STATE_TARGET(parent)) gst_element_set_state(element, GST_STATE_TARGET(parent)); else gst_element_sync_state_with_parent(element); } else g_warning ("GstUtils::sync_state_with_parent, cannot sync an orphan element"); }
static void window_id_cb(GstBus *bus, GstMessage *msg, PurpleMediaOutputWindow *ow) { GstElement *sink; if (GST_MESSAGE_TYPE(msg) != GST_MESSAGE_ELEMENT || !gst_structure_has_name(msg->structure, "prepare-xwindow-id")) return; sink = GST_ELEMENT(GST_MESSAGE_SRC(msg)); while (sink != ow->sink) { if (sink == NULL) return; sink = GST_ELEMENT_PARENT(sink); } g_signal_handlers_disconnect_matched(bus, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, window_id_cb, ow); gst_x_overlay_set_xwindow_id(GST_X_OVERLAY( GST_MESSAGE_SRC(msg)), ow->window_id); }
gboolean purple_media_manager_remove_output_window(PurpleMediaManager *manager, gulong output_window_id) { #ifdef USE_VV PurpleMediaOutputWindow *output_window = NULL; GList *iter; g_return_val_if_fail(PURPLE_IS_MEDIA_MANAGER(manager), FALSE); iter = manager->priv->output_windows; for (; iter; iter = g_list_next(iter)) { PurpleMediaOutputWindow *ow = iter->data; if (ow->id == output_window_id) { manager->priv->output_windows = g_list_delete_link( manager->priv->output_windows, iter); output_window = ow; break; } } if (output_window == NULL) return FALSE; if (output_window->sink != NULL) { GstPad *pad = gst_element_get_static_pad( output_window->sink, "sink"); GstPad *peer = gst_pad_get_peer(pad); GstElement *colorspace = GST_ELEMENT_PARENT(peer), *queue; gst_object_unref(pad); gst_object_unref(peer); pad = gst_element_get_static_pad(colorspace, "sink"); peer = gst_pad_get_peer(pad); queue = GST_ELEMENT_PARENT(peer); gst_object_unref(pad); gst_object_unref(peer); pad = gst_element_get_static_pad(queue, "sink"); peer = gst_pad_get_peer(pad); gst_object_unref(pad); if (peer != NULL) gst_element_release_request_pad(GST_ELEMENT_PARENT(peer), peer); gst_element_set_locked_state(queue, TRUE); gst_element_set_state(queue, GST_STATE_NULL); gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(queue)), queue); gst_element_set_locked_state(colorspace, TRUE); gst_element_set_state(colorspace, GST_STATE_NULL); gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(colorspace)), colorspace); gst_element_set_locked_state(output_window->sink, TRUE); gst_element_set_state(output_window->sink, GST_STATE_NULL); gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(output_window->sink)), output_window->sink); } g_free(output_window->session_id); g_free(output_window->participant); g_free(output_window); return TRUE; #else return FALSE; #endif }
gboolean purple_media_manager_create_output_window(PurpleMediaManager *manager, PurpleMedia *media, const gchar *session_id, const gchar *participant) { #ifdef USE_VV GList *iter; g_return_val_if_fail(PURPLE_IS_MEDIA(media), FALSE); iter = manager->priv->output_windows; for(; iter; iter = g_list_next(iter)) { PurpleMediaOutputWindow *ow = iter->data; if (ow->sink == NULL && ow->media == media && ((participant != NULL && ow->participant != NULL && !strcmp(participant, ow->participant)) || (participant == ow->participant)) && !strcmp(session_id, ow->session_id)) { GstBus *bus; GstElement *queue, *colorspace; GstElement *tee = purple_media_get_tee(media, session_id, participant); if (tee == NULL) continue; queue = gst_element_factory_make( "queue", NULL); colorspace = gst_element_factory_make( "ffmpegcolorspace", NULL); ow->sink = purple_media_manager_get_element( manager, PURPLE_MEDIA_RECV_VIDEO, ow->media, ow->session_id, ow->participant); if (participant == NULL) { /* aka this is a preview sink */ GObjectClass *klass = G_OBJECT_GET_CLASS(ow->sink); if (g_object_class_find_property(klass, "sync")) g_object_set(G_OBJECT(ow->sink), "sync", "FALSE", NULL); if (g_object_class_find_property(klass, "async")) g_object_set(G_OBJECT(ow->sink), "async", FALSE, NULL); } gst_bin_add_many(GST_BIN(GST_ELEMENT_PARENT(tee)), queue, colorspace, ow->sink, NULL); bus = gst_pipeline_get_bus(GST_PIPELINE( manager->priv->pipeline)); g_signal_connect(bus, "sync-message::element", G_CALLBACK(window_id_cb), ow); gst_object_unref(bus); gst_element_set_state(ow->sink, GST_STATE_PLAYING); gst_element_set_state(colorspace, GST_STATE_PLAYING); gst_element_set_state(queue, GST_STATE_PLAYING); gst_element_link(colorspace, ow->sink); gst_element_link(queue, colorspace); gst_element_link(tee, queue); } } return TRUE; #else return FALSE; #endif }
gboolean shmdata_base_reader_start (shmdata_base_reader_t * reader, const char *socketPath) { if (NULL == reader) return FALSE; g_mutex_lock (&reader->mutex_); destroy_polling_g_source (reader); if (reader->install_sync_handler_) { g_debug ("installing a sync handler"); //looking for the bus, searching the top level GstElement *pipe = reader->bin_; while (pipe != NULL && !GST_IS_PIPELINE (pipe)) pipe = GST_ELEMENT_PARENT (pipe); if( GST_IS_PIPELINE (pipe)) { GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipe)); gst_bus_set_sync_handler (bus, shmdata_base_reader_message_handler, NULL); gst_object_unref (bus); } else { g_warning ("no top level pipeline found when starting, cannot install sync_handler"); g_mutex_unlock (&reader->mutex_); return FALSE; } } reader->socket_name_ = g_strdup (socketPath); //monitoring the shared memory file reader->shmfile_ = g_file_new_for_commandline_arg (reader->socket_name_); if (g_file_query_exists (reader->shmfile_, NULL)) { g_debug ("existing shmdata, attaching (%s)", reader->socket_name_); reader->initialized_ = TRUE; g_mutex_unlock (&reader->mutex_);//give hand to user reader->on_first_data_ (reader, reader->on_first_data_userData_); shmdata_base_reader_attach (reader); //attach is acquiring mutex g_mutex_lock (&reader->mutex_);//get hand back } else g_debug ("monitoring %s", reader->socket_name_); //#ifdef HAVE_OSX #if 1 //directory monitoring is not working on osx, use polling :( /* g_timeout_add (500, */ /* shmdata_base_reader_poll_shmdata_path, */ /* reader); */ //GSource *source; reader->polling_g_source_ = g_timeout_source_new (500); g_source_set_callback (reader->polling_g_source_, shmdata_base_reader_poll_shmdata_path, reader, NULL); g_source_attach (reader->polling_g_source_, reader->g_main_context_); g_source_unref (reader->polling_g_source_); #else //FIXME fix monitoring with custom gmaincontext... find how to use "g_main_context_push_thread_default"... if (reader->g_main_context_ != NULL) { g_debug ("shmdata_base_reader_start: set a custom maincontext"); g_main_context_push_thread_default (reader->g_main_context_); } GFile *dir = g_file_get_parent (reader->shmfile_); if (!g_file_supports_thread_contexts(dir)) g_debug ("does not support thread_context"); GError *error = NULL; reader->dirMonitor_ = g_file_monitor_directory (dir, G_FILE_MONITOR_NONE, NULL, &error); g_object_unref (dir); if (reader->dirMonitor_ == NULL) { g_warning ("monitor directory failled: %s", error->message); g_error_free (error); g_mutex_unlock (&reader->mutex_); return FALSE; } g_signal_connect (reader->dirMonitor_, "changed", G_CALLBACK (shmdata_base_reader_file_system_monitor_change), reader); if (reader->g_main_context_ != NULL) g_main_context_pop_thread_default (reader->g_main_context_); #endif g_debug ("shmdata reader started (%s)", reader->socket_name_); g_mutex_unlock (&reader->mutex_); return TRUE; }
static void gst_tcp_mix_src_request_link_pad (GstTCPMixSrc * src, GstTCPMixSrcPad * pad) { GstTCPMixSrcPad *p; GstPad *pp; GList *item; gboolean linked = FALSE; GstBin *parent; GstElement *target; GstPadLinkReturn linkRet; if (gst_pad_is_linked (GST_PAD (pad))) { #if 1 pp = GST_PAD_PEER (pad); GST_WARNING_OBJECT (src, "Pad %s.%s already linked to %s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); #endif return; } GST_LOG_OBJECT (src, "Linking pad '%s.%s'", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad)); INFO ("link"); /** * Don't do GST_OBJECT_LOCK() here, it causes DEADLOCK. */ /* GST_OBJECT_LOCK (src); */ if (!src->autosink) goto find_sink; parent = GST_BIN (GST_ELEMENT_PARENT (src)); target = gst_bin_get_by_name (parent, src->autosink); INFO ("link"); if (!target) goto find_sink; pp = gst_element_get_request_pad (target, "sink_%u"); GST_DEBUG_OBJECT (src, "Link %s.%s-%s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); INFO ("link"); linkRet = gst_pad_link (GST_PAD (pad), GST_PAD (pp)); if (GST_PAD_LINK_FAILED (linkRet)) { GST_ERROR_OBJECT (src, "can't link"); } return; find_sink: #if 1 for (item = GST_ELEMENT_PADS (src); item; item = g_list_next (item)) { p = GST_TCP_MIX_SRC_PAD (item->data); if (GST_PAD_IS_SRC (p)) { GST_OBJECT_LOCK (p); if ((pp = GST_PAD_PEER (p))) { GstElement *ele = GST_ELEMENT (GST_PAD_PARENT (pp)); // FIXME: pad name calculation pp = gst_element_get_request_pad (ele, "sink_%u"); GST_DEBUG_OBJECT (src, "Link %s.%s-%s.%s", GST_ELEMENT_NAME (src), GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pp)), GST_PAD_NAME (pp)); linkRet = gst_pad_link (GST_PAD (pad), GST_PAD (pp)); if (GST_PAD_LINK_FAILED (linkRet)) { GST_ERROR_OBJECT (src, "can't link"); } else { linked = TRUE; } } GST_OBJECT_UNLOCK (p); if (linked) break; } } #endif /* GST_OBJECT_UNLOCK (src); */ return; }
static GstStateChangeReturn gst_camerabin_image_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstCameraBinImage *img = GST_CAMERABIN_IMAGE (element); GST_DEBUG_OBJECT (element, "changing state: %s -> %s", gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_camerabin_image_create_elements (img)) { return GST_STATE_CHANGE_FAILURE; } /* Allow setting filename when image bin in READY state */ gst_element_set_locked_state (img->sink, TRUE); GST_INFO_OBJECT (img, "locking imagebin->sink state to %s", gst_element_state_get_name (GST_STATE (img->sink))); break; case GST_STATE_CHANGE_READY_TO_PAUSED: if (!g_str_equal (img->filename->str, "")) { GST_INFO_OBJECT (img, "preparing image with filename: %s", img->filename->str); gst_element_set_locked_state (img->sink, FALSE); } else { GST_INFO_OBJECT (img, "keep sink locked, we have no filename yet"); } break; case GST_STATE_CHANGE_PAUSED_TO_READY: /* Set sink to NULL in order to write the file _now_ */ GST_INFO_OBJECT (img, "write image with filename: %s", img->filename->str); gst_element_set_locked_state (img->sink, TRUE); gst_element_set_state (img->sink, GST_STATE_NULL); g_string_assign (img->filename, ""); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_PLAYING: /* Write debug graph to file */ GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (GST_ELEMENT_PARENT (img)), GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS, "imagebin.playing"); break; case GST_STATE_CHANGE_READY_TO_NULL: gst_camerabin_image_destroy_elements (img); break; default: break; } GST_DEBUG_OBJECT (element, "changed state: %s -> %s = %s", gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)), gst_element_state_change_return_get_name (ret)); return ret; }