static gboolean gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) { GstElement *csp = NULL; GstElement *videoscale = NULL; GstPad *firstpad = NULL; const gchar *missing_element_name; gboolean newsink = FALSE; gboolean updated_converters = FALSE; GST_DEBUG_OBJECT (vfbin, "Creating internal elements"); /* First check if we need to add/replace the internal sink */ if (vfbin->video_sink) { if (vfbin->user_video_sink && vfbin->video_sink != vfbin->user_video_sink) { gst_bin_remove (GST_BIN_CAST (vfbin), vfbin->video_sink); gst_object_unref (vfbin->video_sink); vfbin->video_sink = NULL; } } if (!vfbin->video_sink) { if (vfbin->user_video_sink) vfbin->video_sink = gst_object_ref (vfbin->user_video_sink); else { vfbin->video_sink = gst_element_factory_make ("autovideosink", "vfbin-sink"); if (!vfbin->video_sink) { missing_element_name = "autovideosink"; goto missing_element; } } gst_bin_add (GST_BIN_CAST (vfbin), gst_object_ref (vfbin->video_sink)); newsink = TRUE; } /* check if we want add/remove the conversion elements */ if (vfbin->elements_created && vfbin->disable_converters) { /* remove the elements, user doesn't want them */ gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), NULL); csp = gst_bin_get_by_name (GST_BIN_CAST (vfbin), "vfbin-csp"); videoscale = gst_bin_get_by_name (GST_BIN_CAST (vfbin), "vfbin-videoscale"); gst_bin_remove (GST_BIN_CAST (vfbin), csp); gst_bin_remove (GST_BIN_CAST (vfbin), videoscale); gst_object_unref (csp); gst_object_unref (videoscale); updated_converters = TRUE; } else if (!vfbin->elements_created && !vfbin->disable_converters) { gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), NULL); /* add the elements, user wants them */ csp = gst_element_factory_make ("videoconvert", "vfbin-csp"); if (!csp) { missing_element_name = "videoconvert"; goto missing_element; } gst_bin_add (GST_BIN_CAST (vfbin), csp); videoscale = gst_element_factory_make ("videoscale", "vfbin->videoscale"); if (!videoscale) { missing_element_name = "videoscale"; goto missing_element; } gst_bin_add (GST_BIN_CAST (vfbin), videoscale); gst_element_link_pads_full (csp, "src", videoscale, "sink", GST_PAD_LINK_CHECK_NOTHING); vfbin->elements_created = TRUE; GST_DEBUG_OBJECT (vfbin, "Elements succesfully created and linked"); updated_converters = TRUE; } /* otherwise, just leave it as is */ /* if sink was replaced -> link it to the internal converters */ if (newsink && !vfbin->disable_converters) { gboolean unref = FALSE; if (!videoscale) { videoscale = gst_bin_get_by_name (GST_BIN_CAST (vfbin), "vfbin-videscale"); unref = TRUE; } if (!gst_element_link_pads_full (videoscale, "src", vfbin->video_sink, "sink", GST_PAD_LINK_CHECK_CAPS)) { GST_ELEMENT_ERROR (vfbin, CORE, NEGOTIATION, (NULL), ("linking videoscale and viewfindersink failed")); } if (unref) gst_object_unref (videoscale); videoscale = NULL; } /* Check if we need a new ghostpad target */ if (updated_converters || (newsink && vfbin->disable_converters)) { if (vfbin->disable_converters) { firstpad = gst_element_get_static_pad (vfbin->video_sink, "sink"); } else { /* csp should always exist at this point */ firstpad = gst_element_get_static_pad (csp, "sink"); } } /* need to change the ghostpad target if firstpad is set */ if (firstpad) { if (!gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), firstpad)) goto error; gst_object_unref (firstpad); firstpad = NULL; } return TRUE; missing_element: gst_element_post_message (GST_ELEMENT_CAST (vfbin), gst_missing_element_message_new (GST_ELEMENT_CAST (vfbin), missing_element_name)); GST_ELEMENT_ERROR (vfbin, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), missing_element_name), (NULL)); goto error; error: GST_WARNING_OBJECT (vfbin, "Creating internal elements failed"); if (firstpad) gst_object_unref (firstpad); return FALSE; }
static GstElement * ges_track_video_transition_create_element (GESTrackObject * object) { GstElement *topbin, *iconva, *iconvb, *scalea, *scaleb, *capsfilt, *oconv; GstObject *target = NULL; const gchar *propname = NULL; GstElement *mixer = NULL; GstPad *sinka_target, *sinkb_target, *src_target, *sinka, *sinkb, *src, *srca_pad; GESTrackVideoTransition *self; GESTrackVideoTransitionPrivate *priv; self = GES_TRACK_VIDEO_TRANSITION (object); priv = self->priv; GST_LOG ("creating a video bin"); topbin = gst_bin_new ("transition-bin"); iconva = gst_element_factory_make ("videoconvert", "tr-csp-a"); iconvb = gst_element_factory_make ("videoconvert", "tr-csp-b"); scalea = gst_element_factory_make ("videoscale", "vs-a"); scaleb = gst_element_factory_make ("videoscale", "vs-b"); capsfilt = gst_element_factory_make ("capsfilter", "capsfilt"); oconv = gst_element_factory_make ("videoconvert", "tr-csp-output"); gst_bin_add_many (GST_BIN (topbin), iconva, iconvb, scalea, scaleb, capsfilt, oconv, NULL); mixer = gst_element_factory_make ("videomixer", NULL); g_assert (mixer); g_object_set (G_OBJECT (mixer), "background", 1, NULL); gst_bin_add (GST_BIN (topbin), mixer); if (priv->pending_type != GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE) { priv->sinka = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconva, mixer, priv->pending_type, NULL); priv->sinkb = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconvb, mixer, priv->pending_type, &priv->smpte); target = GST_OBJECT (priv->smpte); propname = "position"; priv->start_value = 1.0; priv->end_value = 0.0; } else { gst_element_link_pads_full (iconva, "src", scalea, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full (iconvb, "src", scaleb, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full (scaleb, "src", capsfilt, "sink", GST_PAD_LINK_CHECK_NOTHING); priv->sinka = (GstPad *) link_element_to_mixer (scalea, mixer); priv->sinkb = (GstPad *) link_element_to_mixer (capsfilt, mixer); target = GST_OBJECT (priv->sinkb); propname = "alpha"; priv->start_value = 0.0; priv->end_value = 1.0; } priv->mixer = gst_object_ref (mixer); fast_element_link (mixer, oconv); sinka_target = gst_element_get_static_pad (iconva, "sink"); sinkb_target = gst_element_get_static_pad (iconvb, "sink"); src_target = gst_element_get_static_pad (oconv, "src"); sinka = gst_ghost_pad_new ("sinka", sinka_target); sinkb = gst_ghost_pad_new ("sinkb", sinkb_target); src = gst_ghost_pad_new ("src", src_target); gst_element_add_pad (topbin, src); gst_element_add_pad (topbin, sinka); gst_element_add_pad (topbin, sinkb); srca_pad = gst_element_get_static_pad (scalea, "src"); g_signal_connect (srca_pad, "notify::caps", G_CALLBACK (on_caps_set), (GstElement *) capsfilt); gst_object_unref (sinka_target); gst_object_unref (sinkb_target); gst_object_unref (src_target); gst_object_unref (srca_pad); /* set up interpolation */ set_interpolation (target, priv, propname); priv->topbin = topbin; priv->type = priv->pending_type; return topbin; }
static gboolean gst_switch_commit_new_kid (GstSwitchSink * sink) { GstPad *targetpad; GstState kid_state; GstElement *new_kid, *old_kid; gboolean is_fakesink = FALSE; GstBus *bus; /* need locking around member accesses */ GST_OBJECT_LOCK (sink); /* If we're currently changing state, set the child to the next state * we're transitioning too, rather than our current state which is * about to change */ if (GST_STATE_NEXT (sink) != GST_STATE_VOID_PENDING) kid_state = GST_STATE_NEXT (sink); else kid_state = GST_STATE (sink); new_kid = sink->new_kid; sink->new_kid = NULL; GST_OBJECT_UNLOCK (sink); /* Fakesink by default if NULL is passed as the new child */ if (new_kid == NULL) { GST_DEBUG_OBJECT (sink, "Replacing kid with fakesink"); new_kid = gst_element_factory_make ("fakesink", "testsink"); if (new_kid == NULL) { GST_ERROR_OBJECT (sink, "Failed to create fakesink"); return FALSE; } /* Add a reference, as it would if the element came from sink->new_kid */ gst_object_ref (new_kid); g_object_set (new_kid, "sync", TRUE, NULL); is_fakesink = TRUE; } else { GST_DEBUG_OBJECT (sink, "Setting new kid"); } /* set temporary bus of our own to catch error messages from the child * (could we just set our own bus on it, or would the state change messages * from the not-yet-added element confuse the state change algorithm? Let's * play it safe for now) */ bus = gst_bus_new (); gst_element_set_bus (new_kid, bus); gst_object_unref (bus); if (gst_element_set_state (new_kid, kid_state) == GST_STATE_CHANGE_FAILURE) { GstMessage *msg; /* check if child posted an error message and if so re-post it on our bus * so that the application gets to see a decent error and not our generic * fallback error message which is completely indecipherable to the user */ msg = gst_bus_pop_filtered (GST_ELEMENT_BUS (new_kid), GST_MESSAGE_ERROR); if (msg) { GST_INFO_OBJECT (sink, "Forwarding kid error: %" GST_PTR_FORMAT, msg); gst_element_post_message (GST_ELEMENT (sink), msg); } /* FIXME: need a translated error message that tells the user to check * her GConf audio/video settings */ GST_ELEMENT_ERROR (sink, CORE, STATE_CHANGE, (NULL), ("Failed to set state on new child.")); gst_element_set_bus (new_kid, NULL); gst_object_unref (new_kid); return FALSE; } gst_element_set_bus (new_kid, NULL); gst_bin_add (GST_BIN (sink), new_kid); /* Now, replace the existing child */ GST_OBJECT_LOCK (sink); old_kid = sink->kid; sink->kid = new_kid; /* Mark whether a custom kid or fakesink has been installed */ sink->have_kid = !is_fakesink; GST_OBJECT_UNLOCK (sink); /* kill old element */ if (old_kid) { GST_DEBUG_OBJECT (sink, "Removing old kid %" GST_PTR_FORMAT, old_kid); gst_element_set_state (old_kid, GST_STATE_NULL); gst_bin_remove (GST_BIN (sink), old_kid); gst_object_unref (old_kid); } /* re-attach ghostpad */ GST_DEBUG_OBJECT (sink, "Creating new ghostpad"); targetpad = gst_element_get_static_pad (sink->kid, "sink"); gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad); gst_object_unref (targetpad); GST_DEBUG_OBJECT (sink, "done changing child of switchsink"); /* FIXME: Push new-segment info and pre-roll buffer(s) into the kid */ /* Unblock the target pad if necessary */ if (sink->awaiting_block) { gst_pad_set_blocked (sink->pad, FALSE); sink->awaiting_block = FALSE; } return TRUE; }
/* if element caps already in list, will make sure Transform elements have * priority and replace old ones */ static GList * create_codec_cap_list (GstElementFactory *factory, GstPadDirection direction, GList *list, GstCaps *rtp_caps) { const GList *pads = gst_element_factory_get_static_pad_templates (factory); gint i; /* Let us look at each pad for stuff to add*/ while (pads) { GstCaps *caps = NULL; GstStaticPadTemplate *padtemplate = NULL; padtemplate = (GstStaticPadTemplate *) (pads->data); pads = g_list_next (pads); if (padtemplate->direction != direction) continue; if (padtemplate->presence != GST_PAD_ALWAYS) { continue; } caps = gst_static_pad_template_get_caps (padtemplate); /* DEBUG ("%s caps are %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), gst_caps_to_string (caps)); */ /* skips caps ANY */ if (!caps || gst_caps_is_any (caps)) { goto done; } /* let us add one entry to the list per media type */ for (i = 0; i < gst_caps_get_size (caps); i++) { CodecCap *entry = NULL; GList *found_item = NULL; GstStructure *structure = gst_caps_get_structure (caps, i); GstCaps *cur_caps = NULL; /* FIXME fix this in gstreamer! The rtpdepay element is bogus, it claims to * be a depayloader yet has application/x-rtp on both sides and does * absolutely nothing */ /* Let's check if media caps are really media caps, this is to deal with * wierd elements such as rtpdepay that says it's a depayloader but has * application/x-rtp on src and sink pads */ const gchar *name = gst_structure_get_name (structure); if (g_ascii_strcasecmp (name, "application/x-rtp") == 0) { GST_DEBUG ("skipping %s : %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), name); continue; } cur_caps = gst_caps_new_full (gst_structure_copy (structure), NULL); /* let's check if this caps is already in the list, if so let's replace * that CodecCap list instead of creating a new one */ /* we need to compare both media caps and rtp caps */ found_item = g_list_find_custom (list, cur_caps, (GCompareFunc)compare_media_caps); if (found_item) { entry = (CodecCap *)found_item->data; /* if RTP caps exist and don't match nullify entry */ if (rtp_caps && compare_rtp_caps (found_item->data, rtp_caps)) { entry = NULL; } } if (!entry) { entry = g_slice_new0 (CodecCap); entry->caps = cur_caps; if (rtp_caps) { entry->rtp_caps = rtp_caps; gst_caps_ref (rtp_caps); } list = g_list_append (list, entry); entry->element_list1 = g_list_prepend (NULL, g_list_prepend (NULL, factory)); gst_object_ref (factory); } else { entry->element_list1->data = g_list_append (entry->element_list1->data, factory); gst_object_ref (factory); if (rtp_caps) { if (entry->rtp_caps) { GstCaps *tmp = gst_caps_intersect (rtp_caps, entry->rtp_caps); gst_caps_unref (entry->rtp_caps); entry->rtp_caps = tmp; } else { entry->rtp_caps = gst_caps_ref (rtp_caps); /* This shouldn't happen, its we're looking at rtp elements * or we're not */ g_assert_not_reached (); } } entry->caps = gst_caps_merge (cur_caps, entry->caps); } } done: if (caps != NULL) { gst_caps_unref (caps); } } return list; }
static gboolean splitmux_part_pad_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstSplitMuxPartPad *part_pad = SPLITMUX_PART_PAD_CAST (pad); GstSplitMuxPartReader *reader = part_pad->reader; gboolean ret = TRUE; SplitMuxSrcPad *target; GstDataQueueItem *item; SPLITMUX_PART_LOCK (reader); target = gst_object_ref (part_pad->target); GST_LOG_OBJECT (reader, "Pad %" GST_PTR_FORMAT " event %" GST_PTR_FORMAT, pad, event); if (part_pad->flushing && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) goto drop_event; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT:{ GstSegment *seg = &part_pad->segment; GST_LOG_OBJECT (pad, "Received segment %" GST_PTR_FORMAT, event); gst_event_copy_segment (event, seg); gst_event_copy_segment (event, &part_pad->orig_segment); if (seg->format != GST_FORMAT_TIME) goto wrong_segment; /* Adjust segment */ /* Adjust start/stop so the overall file is 0 + start_offset based */ if (seg->stop != -1) { seg->stop -= seg->start; seg->stop += seg->time + reader->start_offset; } seg->start = seg->time + reader->start_offset; seg->time += reader->start_offset; seg->position += reader->start_offset; GST_LOG_OBJECT (pad, "Adjusted segment now %" GST_PTR_FORMAT, event); /* Replace event */ gst_event_unref (event); event = gst_event_new_segment (seg); if (reader->prep_state != PART_STATE_PREPARING_COLLECT_STREAMS && reader->prep_state != PART_STATE_PREPARING_MEASURE_STREAMS) break; /* Only do further stuff with segments during initial measuring */ /* Take the first segment from the first part */ if (target->segment.format == GST_FORMAT_UNDEFINED) { gst_segment_copy_into (seg, &target->segment); GST_DEBUG_OBJECT (reader, "Target pad segment now %" GST_SEGMENT_FORMAT, &target->segment); } if (seg->stop != -1 && target->segment.stop != -1) { GstClockTime stop = seg->base + seg->stop; if (stop > target->segment.stop) { target->segment.stop = stop; GST_DEBUG_OBJECT (reader, "Adjusting segment stop by %" GST_TIME_FORMAT " output now %" GST_SEGMENT_FORMAT, GST_TIME_ARGS (reader->start_offset), &target->segment); } } GST_LOG_OBJECT (pad, "Forwarding segment %" GST_PTR_FORMAT, event); break; } case GST_EVENT_EOS:{ GST_DEBUG_OBJECT (part_pad, "State %u EOS event. MaxTS seen %" GST_TIME_FORMAT, reader->prep_state, GST_TIME_ARGS (part_pad->max_ts)); if (reader->prep_state == PART_STATE_PREPARING_COLLECT_STREAMS || reader->prep_state == PART_STATE_PREPARING_MEASURE_STREAMS) { /* Mark this pad as EOS */ part_pad->is_eos = TRUE; if (splitmux_part_is_eos_locked (reader)) { /* Finished measuring things, set state and tell the state change func * so it can seek back to the start */ GST_LOG_OBJECT (reader, "EOS while measuring streams. Resetting for ready"); reader->prep_state = PART_STATE_PREPARING_RESET_FOR_READY; SPLITMUX_PART_BROADCAST (reader); } goto drop_event; } break; } case GST_EVENT_FLUSH_START: reader->flushing = TRUE; part_pad->flushing = TRUE; GST_LOG_OBJECT (reader, "Pad %" GST_PTR_FORMAT " flushing dataqueue", part_pad); gst_data_queue_set_flushing (part_pad->queue, TRUE); SPLITMUX_PART_BROADCAST (reader); break; case GST_EVENT_FLUSH_STOP:{ gst_data_queue_set_flushing (part_pad->queue, FALSE); gst_data_queue_flush (part_pad->queue); part_pad->seen_buffer = FALSE; part_pad->flushing = FALSE; part_pad->is_eos = FALSE; reader->flushing = splitmux_is_flushing (reader); GST_LOG_OBJECT (reader, "%s pad %" GST_PTR_FORMAT " flush_stop. Overall flushing=%d", reader->path, pad, reader->flushing); SPLITMUX_PART_BROADCAST (reader); break; } default: break; } /* Don't send events downstream while preparing */ if (reader->prep_state != PART_STATE_READY) goto drop_event; /* Don't pass flush events - those are done by the parent */ if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) goto drop_event; if (!block_until_can_push (reader)) { SPLITMUX_PART_UNLOCK (reader); gst_object_unref (target); gst_event_unref (event); return FALSE; } switch (GST_EVENT_TYPE (event)) { case GST_EVENT_GAP:{ /* FIXME: Drop initial gap (if any) in each segment, not all GAPs */ goto drop_event; } default: break; } /* We are active, and one queue is empty, place this buffer in * the dataqueue */ gst_object_ref (part_pad->queue); SPLITMUX_PART_UNLOCK (reader); GST_LOG_OBJECT (reader, "Enqueueing event %" GST_PTR_FORMAT, event); item = g_slice_new (GstDataQueueItem); item->destroy = (GDestroyNotify) splitmux_part_free_queue_item; item->object = GST_MINI_OBJECT (event); item->size = 0; item->duration = 0; if (item->duration == GST_CLOCK_TIME_NONE) item->duration = 0; item->visible = FALSE; if (!gst_data_queue_push (part_pad->queue, item)) { splitmux_part_free_queue_item (item); ret = FALSE; } gst_object_unref (part_pad->queue); gst_object_unref (target); return ret; wrong_segment: gst_event_unref (event); gst_object_unref (target); SPLITMUX_PART_UNLOCK (reader); GST_ELEMENT_ERROR (reader, STREAM, FAILED, (NULL), ("Received non-time segment - reader %s pad %" GST_PTR_FORMAT, reader->path, pad)); return FALSE; drop_event: GST_LOG_OBJECT (pad, "Dropping event %" GST_PTR_FORMAT " from %" GST_PTR_FORMAT " on %" GST_PTR_FORMAT, event, pad, target); gst_event_unref (event); gst_object_unref (target); SPLITMUX_PART_UNLOCK (reader); return TRUE; }
gboolean fs_rtp_sub_stream_set_codecbin_unlock (FsRtpSubStream *substream, FsCodec *codec, GstElement *codecbin, GError **error) { GstCaps *caps = NULL; gchar *tmp; gboolean ret = FALSE; GstPad *pad; gboolean codec_changed = TRUE; FS_RTP_SUB_STREAM_LOCK (substream); if (substream->priv->stopped) { FS_RTP_SUB_STREAM_UNLOCK (substream); FS_RTP_SESSION_UNLOCK (substream->priv->session); gst_object_unref (codecbin); fs_codec_destroy (codec); fs_rtp_sub_stream_try_stop (substream); return TRUE; } substream->priv->modifying = TRUE; FS_RTP_SUB_STREAM_UNLOCK (substream); if (substream->codec) { if (!fs_codec_are_equal (codec, substream->codec)) codec_changed = FALSE; } if (substream->priv->codecbin) { FsCodec *saved_codec = substream->codec; GstElement *old_codecbin; gst_element_set_locked_state (substream->priv->codecbin, TRUE); if (gst_element_set_state (substream->priv->codecbin, GST_STATE_NULL) != GST_STATE_CHANGE_SUCCESS) { gst_element_set_locked_state (substream->priv->codecbin, FALSE); g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL, "Could not set the codec bin for ssrc %u" " and payload type %d to the state NULL", substream->ssrc, substream->pt); FS_RTP_SUB_STREAM_LOCK (substream); substream->priv->modifying = FALSE; FS_RTP_SUB_STREAM_UNLOCK (substream); FS_RTP_SESSION_UNLOCK (substream->priv->session); gst_object_unref (codecbin); fs_codec_destroy (codec); fs_rtp_sub_stream_try_stop (substream); return FALSE; } old_codecbin = substream->priv->codecbin; substream->priv->codecbin = NULL; FS_RTP_SESSION_UNLOCK (substream->priv->session); gst_bin_remove (GST_BIN (substream->priv->conference), old_codecbin); FS_RTP_SESSION_LOCK (substream->priv->session); if (substream->codec == saved_codec) { fs_codec_destroy (substream->codec); substream->codec = NULL; } if (substream->priv->caps) gst_caps_unref (substream->priv->caps); substream->priv->caps = NULL; } FS_RTP_SESSION_UNLOCK (substream->priv->session); gst_object_ref (codecbin); if (!gst_bin_add (GST_BIN (substream->priv->conference), codecbin)) { gst_object_unref (codecbin); g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not add the codec bin to the conference"); FS_RTP_SUB_STREAM_LOCK (substream); substream->priv->modifying = FALSE; FS_RTP_SUB_STREAM_UNLOCK (substream); fs_rtp_sub_stream_try_stop (substream); return FALSE; } if (gst_element_set_state (codecbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not set the codec bin to the playing state"); goto error; } if (!gst_element_link_pads (codecbin, "src", substream->priv->output_valve, "sink")) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not link the codec bin to the output_valve"); goto error; } if (!gst_element_link_pads (substream->priv->capsfilter, "src", codecbin, "sink")) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not link the receive capsfilter and the codecbin for pt %d", substream->pt); goto error; } caps = fs_codec_to_gst_caps (codec); tmp = gst_caps_to_string (caps); GST_DEBUG ("Setting caps %s on recv substream", tmp); g_free (tmp); g_object_set (substream->priv->capsfilter, "caps", caps, NULL); pad = gst_element_get_static_pad (codecbin, "sink"); if (!pad) { g_set_error (error, FS_ERROR, FS_ERROR_INTERNAL, "Could not get sink pad" " from codecbin"); goto error; } /* This is a non-error error * Some codecs require config data to start.. so we should just ignore them */ if (!gst_pad_set_caps (pad, caps)) { ret = TRUE; gst_object_unref (pad); gst_caps_unref (caps); GST_DEBUG ("Could not set the caps on the codecbin, waiting on config-data" " for SSRC:%x pt:%d", substream->ssrc, substream->pt); /* We call this to drop all buffers until something comes up */ fs_rtp_sub_stream_add_probe_locked (substream); goto error; } gst_object_unref (pad); FS_RTP_SESSION_LOCK (substream->priv->session); substream->priv->caps = caps; substream->priv->codecbin = codecbin; substream->codec = codec; FS_RTP_SUB_STREAM_LOCK (substream); substream->priv->modifying = FALSE; FS_RTP_SUB_STREAM_UNLOCK (substream); if (substream->priv->stream && !substream->priv->output_ghostpad) { if (!fs_rtp_sub_stream_add_output_ghostpad_unlock (substream, error)) goto error; } else { FS_RTP_SESSION_UNLOCK (substream->priv->session); if (codec_changed) g_signal_emit (substream, signals[CODEC_CHANGED], 0); } gst_object_unref (codecbin); fs_rtp_sub_stream_try_stop (substream); return TRUE; error: FS_RTP_SUB_STREAM_LOCK (substream); substream->priv->modifying = FALSE; FS_RTP_SUB_STREAM_UNLOCK (substream); gst_element_set_locked_state (codecbin, TRUE); gst_element_set_state (codecbin, GST_STATE_NULL); gst_object_ref (codecbin); gst_bin_remove (GST_BIN (substream->priv->conference), codecbin); gst_object_unref (codecbin); fs_codec_destroy (codec); fs_rtp_sub_stream_try_stop (substream); return ret; }
static void demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin) { gboolean skip_mq = FALSE; GstPad *mq_pad = NULL; GstPad *dest_pad = NULL; GstCaps *caps; GstStructure *s; GST_DEBUG_OBJECT (dvdbin, "New pad: %" GST_PTR_FORMAT, pad); caps = gst_pad_query_caps (pad, NULL); if (caps == NULL) { GST_WARNING_OBJECT (dvdbin, "NULL caps from pad %" GST_PTR_FORMAT, pad); return; } if (!gst_caps_is_fixed (caps)) { GST_WARNING_OBJECT (dvdbin, "Unfixed caps %" GST_PTR_FORMAT " on pad %" GST_PTR_FORMAT, caps, pad); gst_caps_unref (caps); return; } GST_DEBUG_OBJECT (dvdbin, "Pad %" GST_PTR_FORMAT " has caps: %" GST_PTR_FORMAT, pad, caps); s = gst_caps_get_structure (caps, 0); g_return_if_fail (s != NULL); if (can_sink_caps (dvdbin->pieces[DVD_ELEM_VIDPARSE], caps)) { GST_LOG_OBJECT (dvdbin, "Found video pad w/ caps %" GST_PTR_FORMAT, caps); dest_pad = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDPARSE], "sink"); } else if (g_str_equal (gst_structure_get_name (s), "subpicture/x-dvd")) { GST_LOG_OBJECT (dvdbin, "Found subpicture pad w/ caps %" GST_PTR_FORMAT, caps); dest_pad = gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "sink_%u"); skip_mq = TRUE; } else if (can_sink_caps (dvdbin->pieces[DVD_ELEM_AUDDEC], caps)) { GST_LOG_OBJECT (dvdbin, "Found audio pad w/ caps %" GST_PTR_FORMAT, caps); dest_pad = gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "sink_%u"); } else { GstStructure *s; GST_DEBUG_OBJECT (dvdbin, "Ignoring unusable pad w/ caps %" GST_PTR_FORMAT, caps); gst_element_post_message (GST_ELEMENT_CAST (dvdbin), gst_missing_decoder_message_new (GST_ELEMENT_CAST (dvdbin), caps)); s = gst_caps_get_structure (caps, 0); if (g_str_has_prefix ("video/", gst_structure_get_name (s))) { GST_ELEMENT_ERROR (dvdbin, STREAM, CODEC_NOT_FOUND, (NULL), ("No MPEG video decoder found")); } else { GST_ELEMENT_WARNING (dvdbin, STREAM, CODEC_NOT_FOUND, (NULL), ("No audio decoder found")); } } gst_caps_unref (caps); if (dest_pad == NULL) { GST_DEBUG_OBJECT (dvdbin, "Don't know how to handle pad. Ignoring"); return; } if (skip_mq) { mq_pad = gst_object_ref (pad); } else { mq_pad = connect_thru_mq (dvdbin, pad); if (mq_pad == NULL) goto failed; GST_DEBUG_OBJECT (dvdbin, "Linking new pad %" GST_PTR_FORMAT " through multiqueue to %" GST_PTR_FORMAT, pad, dest_pad); } gst_pad_link (mq_pad, dest_pad); gst_object_unref (mq_pad); gst_object_unref (dest_pad); return; failed: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Failed to handle new demuxer pad %s", GST_PAD_NAME (pad))); if (mq_pad) gst_object_unref (mq_pad); if (dest_pad) gst_object_unref (dest_pad); return; }
static GstStateChangeReturn gst_play_sink_audio_convert_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; GstPlaySinkAudioConvert *self = GST_PLAY_SINK_AUDIO_CONVERT_CAST (element); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: GST_PLAY_SINK_AUDIO_CONVERT_LOCK (self); if (gst_pad_is_blocked (self->sink_proxypad)) gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE, (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self), (GDestroyNotify) gst_object_unref); GST_PLAY_SINK_AUDIO_CONVERT_UNLOCK (self); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: GST_PLAY_SINK_AUDIO_CONVERT_LOCK (self); gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); if (self->conv) { gst_element_set_state (self->conv, GST_STATE_NULL); gst_bin_remove (GST_BIN_CAST (self), self->conv); self->conv = NULL; } if (self->resample) { gst_element_set_state (self->resample, GST_STATE_NULL); gst_bin_remove (GST_BIN_CAST (self), self->resample); self->resample = NULL; } if (self->volume) { gst_element_set_state (self->volume, GST_STATE_NULL); if (GST_OBJECT_PARENT (self->volume) == GST_OBJECT_CAST (self)) { gst_bin_remove (GST_BIN_CAST (self), self->volume); } } gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); self->raw = FALSE; GST_PLAY_SINK_AUDIO_CONVERT_UNLOCK (self); break; case GST_STATE_CHANGE_READY_TO_PAUSED: GST_PLAY_SINK_AUDIO_CONVERT_LOCK (self); if (!gst_pad_is_blocked (self->sink_proxypad)) gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE, (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self), (GDestroyNotify) gst_object_unref); GST_PLAY_SINK_AUDIO_CONVERT_UNLOCK (self); default: break; } return ret; }
static void pad_blocked_cb (GstPad * pad, gboolean blocked, GstPlaySinkAudioConvert * self) { GstPad *peer; GstCaps *caps; gboolean raw; GST_PLAY_SINK_AUDIO_CONVERT_LOCK (self); self->sink_proxypad_blocked = blocked; GST_DEBUG_OBJECT (self, "Pad blocked: %d", blocked); if (!blocked) goto done; /* There must be a peer at this point */ peer = gst_pad_get_peer (self->sinkpad); caps = gst_pad_get_negotiated_caps (peer); if (!caps) caps = gst_pad_get_caps_reffed (peer); gst_object_unref (peer); raw = is_raw_caps (caps); GST_DEBUG_OBJECT (self, "Caps %" GST_PTR_FORMAT " are raw: %d", caps, raw); gst_caps_unref (caps); if (raw == self->raw) goto unblock; self->raw = raw; if (raw) { GstBin *bin = GST_BIN_CAST (self); GstElement *head = NULL, *prev = NULL; GstPad *pad; GST_DEBUG_OBJECT (self, "Creating raw conversion pipeline"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL); if (self->use_converters) { self->conv = gst_element_factory_make ("audioconvert", "conv"); if (self->conv == NULL) { post_missing_element_message (self, "audioconvert"); GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "audioconvert"), ("audio rendering might fail")); } else { gst_bin_add (bin, self->conv); gst_element_sync_state_with_parent (self->conv); distribute_running_time (self->conv, &self->segment); prev = head = self->conv; } self->resample = gst_element_factory_make ("audioresample", "resample"); if (self->resample == NULL) { post_missing_element_message (self, "audioresample"); GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "audioresample"), ("possibly a liboil version mismatch?")); } else { gst_bin_add (bin, self->resample); gst_element_sync_state_with_parent (self->resample); distribute_running_time (self->resample, &self->segment); if (prev) { if (!gst_element_link_pads_full (prev, "src", self->resample, "sink", GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) goto link_failed; } else { head = self->resample; } prev = self->resample; } } if (self->use_volume && self->volume) { gst_bin_add (bin, gst_object_ref (self->volume)); gst_element_sync_state_with_parent (self->volume); distribute_running_time (self->volume, &self->segment); if (prev) { if (!gst_element_link_pads_full (prev, "src", self->volume, "sink", GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) goto link_failed; } else { head = self->volume; } prev = self->volume; } if (head) { pad = gst_element_get_static_pad (head, "sink"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), pad); gst_object_unref (pad); } if (prev) { pad = gst_element_get_static_pad (prev, "src"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), pad); gst_object_unref (pad); } if (!head && !prev) { gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); } GST_DEBUG_OBJECT (self, "Raw conversion pipeline created"); } else { GstBin *bin = GST_BIN_CAST (self); GST_DEBUG_OBJECT (self, "Removing raw conversion pipeline"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL); if (self->conv) { gst_element_set_state (self->conv, GST_STATE_NULL); gst_bin_remove (bin, self->conv); self->conv = NULL; } if (self->resample) { gst_element_set_state (self->resample, GST_STATE_NULL); gst_bin_remove (bin, self->resample); self->resample = NULL; } if (self->volume) { gst_element_set_state (self->volume, GST_STATE_NULL); if (GST_OBJECT_PARENT (self->volume) == GST_OBJECT_CAST (self)) { gst_bin_remove (GST_BIN_CAST (self), self->volume); } } gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); GST_DEBUG_OBJECT (self, "Raw conversion pipeline removed"); } unblock: gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE, (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self), (GDestroyNotify) gst_object_unref); done: GST_PLAY_SINK_AUDIO_CONVERT_UNLOCK (self); return; link_failed: { GST_ELEMENT_ERROR (self, CORE, PAD, (NULL), ("Failed to configure the audio converter.")); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), self->sink_proxypad); gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE, (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self), (GDestroyNotify) gst_object_unref); return; } }
static gboolean webkitVideoSinkProposeAllocation(GstBaseSink* baseSink, GstQuery* query) { WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(baseSink); GstCaps* caps = NULL; gboolean need_pool; gst_query_parse_allocation(query, &caps, &need_pool); if (!caps) return FALSE; if (!gst_video_info_from_caps(&sink->priv->info, caps)) return FALSE; #if USE(OPENGL_ES_2) && GST_CHECK_VERSION(1, 3, 0) // Code adapted from gst-plugins-bad's glimagesink. GstBufferPool* pool; GstStructure* config; guint size; GstAllocator* allocator = 0; GstAllocationParams params; if (!_ensure_gl_setup(sink)) return FALSE; if ((pool = sink->priv->pool)) gst_object_ref(pool); if (pool) { GstCaps* pcaps; // We had a pool, check its caps. GST_DEBUG_OBJECT (sink, "check existing pool caps"); config = gst_buffer_pool_get_config(pool); gst_buffer_pool_config_get_params(config, &pcaps, &size, 0, 0); if (!gst_caps_is_equal(caps, pcaps)) { GST_DEBUG_OBJECT(sink, "pool has different caps"); // Different caps, we can't use this pool. gst_object_unref(pool); pool = 0; } gst_structure_free(config); } if (need_pool && !pool) { GstVideoInfo info; if (!gst_video_info_from_caps(&info, caps)) { GST_DEBUG_OBJECT(sink, "invalid caps specified"); return FALSE; } GST_DEBUG_OBJECT(sink, "create new pool"); pool = gst_gl_buffer_pool_new(sink->priv->context); // The normal size of a frame. size = info.size; config = gst_buffer_pool_get_config(pool); gst_buffer_pool_config_set_params(config, caps, size, 0, 0); if (!gst_buffer_pool_set_config(pool, config)) { GST_DEBUG_OBJECT(sink, "failed setting config"); return FALSE; } } // [WiP] Let's require 8 buffers for now. The player holds to the last 3 // ones and the sink holds only the last one so in theory 5 should // be enough. if (pool) { gst_query_add_allocation_pool(query, pool, size, 8, 0); gst_object_unref(pool); } gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, 0); gst_allocation_params_init(¶ms); allocator = gst_allocator_find(GST_EGL_IMAGE_MEMORY_TYPE); gst_query_add_allocation_param(query, allocator, ¶ms); gst_object_unref(allocator); #else gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, 0); gst_query_add_allocation_meta(query, GST_VIDEO_CROP_META_API_TYPE, 0); gst_query_add_allocation_meta(query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, 0); #endif return TRUE; }
static gpointer _gst_object_ref0 (gpointer self) { return self ? gst_object_ref (self) : NULL; }
static GstFlowReturn webkitVideoSinkRender(GstBaseSink* baseSink, GstBuffer* buffer) { WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(baseSink); WebKitVideoSinkPrivate* priv = sink->priv; g_mutex_lock(priv->bufferMutex); if (priv->unlocked) { g_mutex_unlock(priv->bufferMutex); return GST_FLOW_OK; } #if USE(NATIVE_FULLSCREEN_VIDEO) // Ignore buffers if the video is already in fullscreen using // another sink. if (priv->gstGWorld->isFullscreen()) { g_mutex_unlock(priv->bufferMutex); return GST_FLOW_OK; } #endif priv->buffer = gst_buffer_ref(buffer); #ifndef GST_API_VERSION_1 // For the unlikely case where the buffer has no caps, the caps // are implicitely the caps of the pad. This shouldn't happen. if (UNLIKELY(!GST_BUFFER_CAPS(buffer))) { buffer = priv->buffer = gst_buffer_make_metadata_writable(priv->buffer); gst_buffer_set_caps(priv->buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(baseSink))); } GRefPtr<GstCaps> caps = GST_BUFFER_CAPS(buffer); #else GRefPtr<GstCaps> caps; // The video info structure is valid only if the sink handled an allocation query. if (GST_VIDEO_INFO_FORMAT(&priv->info) != GST_VIDEO_FORMAT_UNKNOWN) caps = adoptGRef(gst_video_info_to_caps(&priv->info)); else caps = priv->currentCaps; #endif GstVideoFormat format; WebCore::IntSize size; int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; if (!getVideoSizeAndFormatFromCaps(caps.get(), size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) { gst_buffer_unref(buffer); g_mutex_unlock(priv->bufferMutex); return GST_FLOW_ERROR; } // Cairo's ARGB has pre-multiplied alpha while GStreamer's doesn't. // Here we convert to Cairo's ARGB. if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) { // Because GstBaseSink::render() only owns the buffer reference in the // method scope we can't use gst_buffer_make_writable() here. Also // The buffer content should not be changed here because the same buffer // could be passed multiple times to this method (in theory). GstBuffer* newBuffer = createGstBuffer(buffer); // Check if allocation failed. if (UNLIKELY(!newBuffer)) { g_mutex_unlock(priv->bufferMutex); return GST_FLOW_ERROR; } // We don't use Color::premultipliedARGBFromColor() here because // one function call per video pixel is just too expensive: // For 720p/PAL for example this means 1280*720*25=23040000 // function calls per second! #ifndef GST_API_VERSION_1 const guint8* source = GST_BUFFER_DATA(buffer); guint8* destination = GST_BUFFER_DATA(newBuffer); #else GstMapInfo sourceInfo; GstMapInfo destinationInfo; gst_buffer_map(buffer, &sourceInfo, GST_MAP_READ); const guint8* source = const_cast<guint8*>(sourceInfo.data); gst_buffer_map(newBuffer, &destinationInfo, GST_MAP_WRITE); guint8* destination = static_cast<guint8*>(destinationInfo.data); #endif for (int x = 0; x < size.height(); x++) { for (int y = 0; y < size.width(); y++) { #if G_BYTE_ORDER == G_LITTLE_ENDIAN unsigned short alpha = source[3]; destination[0] = (source[0] * alpha + 128) / 255; destination[1] = (source[1] * alpha + 128) / 255; destination[2] = (source[2] * alpha + 128) / 255; destination[3] = alpha; #else unsigned short alpha = source[0]; destination[0] = alpha; destination[1] = (source[1] * alpha + 128) / 255; destination[2] = (source[2] * alpha + 128) / 255; destination[3] = (source[3] * alpha + 128) / 255; #endif source += 4; destination += 4; } } #ifdef GST_API_VERSION_1 gst_buffer_unmap(buffer, &sourceInfo); gst_buffer_unmap(newBuffer, &destinationInfo); #endif gst_buffer_unref(buffer); buffer = priv->buffer = newBuffer; } // This should likely use a lower priority, but glib currently starves // lower priority sources. // See: https://bugzilla.gnome.org/show_bug.cgi?id=610830. priv->timeoutId = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, webkitVideoSinkTimeoutCallback, gst_object_ref(sink), reinterpret_cast<GDestroyNotify>(gst_object_unref)); g_cond_wait(priv->dataCondition, priv->bufferMutex); g_mutex_unlock(priv->bufferMutex); return GST_FLOW_OK; }
static void gst_nle_source_pad_added_cb (GstElement * element, GstPad * pad, GstNleSource * nlesrc) { GstCaps *caps; const GstStructure *s; const gchar *mime; GstElement *appsink = NULL; GstPad *sink_pad; GstAppSinkCallbacks appsink_cbs; GstNleSrcItem *item; item = (GstNleSrcItem *) g_list_nth_data (nlesrc->queue, nlesrc->index); caps = gst_pad_get_caps_reffed (pad); s = gst_caps_get_structure (caps, 0); mime = gst_structure_get_name (s); GST_DEBUG_OBJECT (nlesrc, "Found mime type: %s", mime); if (g_strrstr (mime, "video") && !nlesrc->video_linked) { appsink = gst_element_factory_make ("appsink", NULL); memset (&appsink_cbs, 0, sizeof (appsink_cbs)); appsink_cbs.eos = gst_nle_source_on_video_eos; appsink_cbs.new_preroll = gst_nle_source_on_preroll_buffer; appsink_cbs.new_buffer = gst_nle_source_on_video_buffer; nlesrc->video_linked = TRUE; if (!nlesrc->video_srcpad_added) { gst_pad_set_active (nlesrc->video_srcpad, TRUE); gst_element_add_pad (GST_ELEMENT (nlesrc), gst_object_ref (nlesrc->video_srcpad)); nlesrc->video_srcpad_added = TRUE; } gst_pad_add_event_probe (GST_BASE_SINK_PAD (GST_BASE_SINK (appsink)), (GCallback) gst_nle_source_video_pad_probe_cb, nlesrc); nlesrc->video_eos = FALSE; } else if (g_strrstr (mime, "audio") && nlesrc->with_audio && !nlesrc->audio_linked && (item ? item->rate == 1.0 : TRUE)) { appsink = gst_element_factory_make ("appsink", NULL); memset (&appsink_cbs, 0, sizeof (appsink_cbs)); appsink_cbs.eos = gst_nle_source_on_audio_eos; appsink_cbs.new_preroll = gst_nle_source_on_preroll_buffer; appsink_cbs.new_buffer = gst_nle_source_on_audio_buffer; nlesrc->audio_linked = TRUE; if (!nlesrc->audio_srcpad_added) { gst_pad_set_active (nlesrc->audio_srcpad, TRUE); gst_element_add_pad (GST_ELEMENT (nlesrc), gst_object_ref (nlesrc->audio_srcpad)); nlesrc->audio_srcpad_added = TRUE; } gst_pad_add_event_probe (GST_BASE_SINK_PAD (GST_BASE_SINK (appsink)), (GCallback) gst_nle_source_audio_pad_probe_cb, nlesrc); nlesrc->audio_eos = FALSE; } if (appsink != NULL) { g_object_set (appsink, "sync", FALSE, NULL); gst_app_sink_set_callbacks (GST_APP_SINK (appsink), &appsink_cbs, nlesrc, NULL); gst_bin_add (GST_BIN (nlesrc->decoder), appsink); sink_pad = gst_element_get_static_pad (appsink, "sink"); gst_pad_link (pad, sink_pad); gst_element_sync_state_with_parent (appsink); gst_object_unref (sink_pad); } }
static GstElement *find_color_balance_element() { GstIterator *iterator = gst_bin_iterate_all_by_interface( GST_BIN(pipeline), GST_TYPE_COLOR_BALANCE); GstElement *color_balance_element = NULL; gboolean done = FALSE, hardware = FALSE; #if GST_CHECK_VERSION(1, 0, 0) GValue item = G_VALUE_INIT; #else gpointer item; #endif while (!done) { switch (gst_iterator_next(iterator, &item)) { case GST_ITERATOR_OK : { #if GST_CHECK_VERSION(1, 0, 0) GstElement *element = g_value_get_object(&item); #else GstElement *element = GST_ELEMENT(item); #endif if (is_valid_color_balance_element(element)) { if (!color_balance_element) { color_balance_element = GST_ELEMENT_CAST( gst_object_ref(element)); hardware = (gst_color_balance_get_balance_type(GST_COLOR_BALANCE (element)) == GST_COLOR_BALANCE_HARDWARE); } else if (!hardware) { gboolean tmp = (gst_color_balance_get_balance_type(GST_COLOR_BALANCE (element)) == GST_COLOR_BALANCE_HARDWARE); if (tmp) { if (color_balance_element) gst_object_unref(color_balance_element); color_balance_element = GST_ELEMENT_CAST(gst_object_ref(element)); hardware = TRUE; } } } #if GST_CHECK_VERSION(1, 0, 0) g_value_reset(&item); #endif if (hardware && color_balance_element) done = TRUE; break; } case GST_ITERATOR_RESYNC : gst_iterator_resync(iterator); done = FALSE; hardware = FALSE; if (color_balance_element) gst_object_unref(color_balance_element); color_balance_element = NULL; break; case GST_ITERATOR_DONE: case GST_ITERATOR_ERROR: default: done = TRUE; } } #if GST_CHECK_VERSION(1, 0, 0) g_value_unset(&item); #endif gst_iterator_free(iterator); return color_balance_element; }
static gboolean extractable_set_asset (GESExtractable * self, GESAsset * asset) { gboolean res = TRUE; GESUriClip *uriclip = GES_URI_CLIP (self); GESUriClipAsset *uri_clip_asset; GESClip *clip = GES_CLIP (self); GESLayer *layer = ges_clip_get_layer (clip); GList *tmp; GESTimelineElement *audio_source = NULL, *video_source = NULL; g_return_val_if_fail (GES_IS_URI_CLIP_ASSET (asset), FALSE); uri_clip_asset = GES_URI_CLIP_ASSET (asset); if (GST_CLOCK_TIME_IS_VALID (GES_TIMELINE_ELEMENT_DURATION (clip)) == FALSE) _set_duration0 (GES_TIMELINE_ELEMENT (uriclip), ges_uri_clip_asset_get_duration (uri_clip_asset)); ges_timeline_element_set_max_duration (GES_TIMELINE_ELEMENT (uriclip), ges_uri_clip_asset_get_duration (uri_clip_asset)); ges_uri_clip_set_is_image (uriclip, ges_uri_clip_asset_is_image (uri_clip_asset)); if (ges_clip_get_supported_formats (clip) == GES_TRACK_TYPE_UNKNOWN) { ges_clip_set_supported_formats (clip, ges_clip_asset_get_supported_formats (GES_CLIP_ASSET (uri_clip_asset))); } GES_TIMELINE_ELEMENT (uriclip)->asset = asset; if (layer) { GList *children = ges_container_get_children (GES_CONTAINER (self), TRUE); for (tmp = children; tmp; tmp = tmp->next) { if (GES_IS_SOURCE (tmp->data)) { GESTrack *track = ges_track_element_get_track (tmp->data); if (track->type == GES_TRACK_TYPE_AUDIO) audio_source = gst_object_ref (tmp->data); else if (track->type == GES_TRACK_TYPE_VIDEO) video_source = gst_object_ref (tmp->data); ges_track_remove_element (track, tmp->data); ges_container_remove (GES_CONTAINER (self), tmp->data); } } g_list_free_full (children, g_object_unref); gst_object_ref (clip); ges_layer_remove_clip (layer, clip); res = ges_layer_add_clip (layer, clip); for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) { if (GES_IS_SOURCE (tmp->data)) { GESTrack *track = ges_track_element_get_track (tmp->data); if (track->type == GES_TRACK_TYPE_AUDIO && audio_source) ges_track_element_copy_properties (audio_source, tmp->data); else if (track->type == GES_TRACK_TYPE_VIDEO && video_source) ges_track_element_copy_properties (video_source, tmp->data); } } g_clear_object (&audio_source); g_clear_object (&video_source); gst_object_unref (clip); gst_object_unref (layer); } if (res) { g_free (uriclip->priv->uri); uriclip->priv->uri = g_strdup (ges_asset_get_id (asset)); } return res; }
GStreamerVideoOutputCallback (GstDecklinkVideoSink * sink) :IDeckLinkVideoOutputCallback (), m_refcount (1) { m_sink = GST_DECKLINK_VIDEO_SINK_CAST (gst_object_ref (sink)); g_mutex_init (&m_mutex); }
static GstGLShader * _maybe_recompile_shader (GstGLFilterShader * filtershader) { GstGLContext *context = GST_GL_BASE_FILTER (filtershader)->context; GstGLShader *shader; GError *error = NULL; GST_OBJECT_LOCK (filtershader); if (!filtershader->shader || filtershader->update_shader) { filtershader->update_shader = FALSE; GST_OBJECT_UNLOCK (filtershader); g_signal_emit (filtershader, gst_gl_shader_signals[SIGNAL_CREATE_SHADER], 0, &shader); GST_OBJECT_LOCK (filtershader); if (shader) { if (filtershader->shader) gst_object_unref (filtershader->shader); filtershader->new_source = FALSE; filtershader->shader = gst_object_ref (shader); filtershader->new_uniforms = TRUE; _update_uniforms (filtershader); GST_OBJECT_UNLOCK (filtershader); return shader; } } if (filtershader->shader) { shader = gst_object_ref (filtershader->shader); _update_uniforms (filtershader); GST_OBJECT_UNLOCK (filtershader); return shader; } if (filtershader->new_source) { GstGLSLStage *stage; shader = gst_gl_shader_new (context); if (filtershader->vertex) { if (!(stage = gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER, GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE, filtershader->vertex))) { g_set_error (&error, GST_GLSL_ERROR, GST_GLSL_ERROR_COMPILE, "Failed to create shader vertex stage"); goto print_error; } } else { stage = gst_glsl_stage_new_default_vertex (context); } if (!gst_gl_shader_compile_attach_stage (shader, stage, &error)) { gst_object_unref (stage); goto print_error; } if (filtershader->fragment) { if (!(stage = gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE, filtershader->fragment))) { g_set_error (&error, GST_GLSL_ERROR, GST_GLSL_ERROR_COMPILE, "Failed to create shader fragment stage"); goto print_error; } } else { stage = gst_glsl_stage_new_default_fragment (context); } if (!gst_gl_shader_compile_attach_stage (shader, stage, &error)) { gst_object_unref (stage); goto print_error; } if (!gst_gl_shader_link (shader, &error)) { goto print_error; } if (filtershader->shader) gst_object_unref (filtershader->shader); filtershader->shader = gst_object_ref (shader); filtershader->new_source = FALSE; filtershader->new_uniforms = TRUE; _update_uniforms (filtershader); GST_OBJECT_UNLOCK (filtershader); return shader; } else if (filtershader->shader) { _update_uniforms (filtershader); shader = gst_object_ref (filtershader->shader); GST_OBJECT_UNLOCK (filtershader); return shader; } return NULL; print_error: if (shader) { gst_object_unref (shader); shader = NULL; } GST_OBJECT_UNLOCK (filtershader); GST_ELEMENT_ERROR (filtershader, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); return NULL; }
int main (int argc, gchar * argv[]) { GstElement *thread, *element; long usage1; gint i, iters; gst_init (&argc, &argv); if (argc == 2) iters = atoi (argv[1]); else iters = ITERS; g_print ("starting test\n"); usage1 = vmsize (); thread = gst_thread_new ("somethread"); gst_object_unref (thread); g_print ("create/unref new thread %ld\n", vmsize () - usage1); for (i = 0; i < iters; i++) { thread = gst_thread_new ("somethread"); gst_object_unref (thread); } g_print ("create/unref %d threads %ld\n", iters, vmsize () - usage1); thread = gst_thread_new ("somethread"); g_assert (GST_OBJECT_FLOATING (thread)); gst_object_ref (thread); gst_object_sink (GST_OBJECT (thread)); g_assert (!GST_OBJECT_FLOATING (thread)); gst_object_unref (thread); g_print ("create/ref/sink/unref new thread %ld\n", vmsize () - usage1); for (i = 0; i < iters; i++) { thread = gst_thread_new ("somethread"); gst_object_ref (thread); gst_object_sink (GST_OBJECT (thread)); gst_object_unref (thread); } g_print ("create/ref/sink/unref %d threads %ld\n", iters, vmsize () - usage1); thread = gst_thread_new ("somethread"); g_assert (!GST_OBJECT_DESTROYED (thread)); gst_object_unref (thread); g_assert (GST_OBJECT_DESTROYED (thread)); gst_object_unref (thread); g_print ("create/destroy/unref new thread %ld\n", vmsize () - usage1); for (i = 0; i < iters; i++) { thread = gst_thread_new ("somethread"); gst_object_unref (thread); gst_object_unref (thread); } g_print ("create/destroy/unref %d thread %ld\n", iters, vmsize () - usage1); thread = gst_thread_new ("somethread"); gst_object_ref (thread); gst_object_unref (thread); gst_object_unref (thread); g_print ("create/ref/unref/unref new thread %ld\n", vmsize () - usage1); for (i = 0; i < iters; i++) { thread = gst_thread_new ("somethread"); gst_object_ref (thread); gst_object_unref (thread); gst_object_unref (thread); } g_print ("create/ref/unref/unref %d thread %ld\n", iters, vmsize () - usage1); thread = gst_thread_new ("somethread"); gst_object_ref (thread); gst_object_unref (thread); gst_object_unref (thread); gst_object_unref (thread); g_print ("craete/ref/destroy/unref/unref new thread %ld\n", vmsize () - usage1); for (i = 0; i < iters; i++) { thread = gst_thread_new ("somethread"); gst_object_ref (thread); gst_object_unref (thread); gst_object_unref (thread); gst_object_unref (thread); } g_print ("craete/ref/destroy/unref/unref %d threads %ld\n", iters, vmsize () - usage1); for (i = 0; i < iters; i++) { thread = gst_thread_new ("somethread"); gst_object_ref (thread); gst_element_set_name (thread, "testing123"); gst_object_unref (thread); gst_element_set_name (thread, "testing123"); gst_object_unref (thread); gst_object_unref (thread); } g_print ("craete/ref/destroy/unref/unref %d threads with name %ld\n", iters, vmsize () - usage1); thread = gst_thread_new ("somethread"); for (i = 0; i < iters; i++) { gst_element_set_name (thread, "testing"); } gst_object_unref (thread); g_print ("set name %d times %ld\n", iters, vmsize () - usage1); for (i = 0; i < iters; i++) { thread = gst_thread_new ("somethread"); element = gst_element_new (); gst_element_set_name (element, "test1"); gst_bin_add (GST_BIN (thread), element); gst_object_unref (thread); } g_print ("create/unref %d thread with one element %ld\n", iters, vmsize () - usage1); for (i = 0; i < iters; i++) { thread = create_thread (); gst_object_unref (thread); } g_print ("create/unref %d thread with children %ld\n", iters, vmsize () - usage1); for (i = 0; i < iters / 2; i++) { thread = create_thread_ghostpads (); gst_object_unref (thread); } g_print ("create/unref %d thread with children and ghostpads %ld\n", iters / 2, vmsize () - usage1); for (i = 0; i < iters; i++) { add_remove_test1 (); } g_print ("add/remove test1 %d in thread %ld\n", iters, vmsize () - usage1); for (i = 0; i < iters; i++) { add_remove_test2 (); } g_print ("add/remove test2 %d in thread %ld\n", iters, vmsize () - usage1); for (i = 0; i < iters; i++) { add_remove_test3 (); } g_print ("add/destroy/remove test3 %d in thread %ld\n", iters, vmsize () - usage1); for (i = 0; i < iters; i++) { add_remove_test4 (); } g_print ("add/destroy/remove test4 %d in thread %ld\n", iters, vmsize () - usage1); g_print ("leaked: %ld\n", vmsize () - usage1); return (vmsize () - usage1 ? -1 : 0); }
static gboolean create_elements (RsnDvdBin * dvdbin) { GstPadTemplate *src_templ = NULL; GstPad *src = NULL; GstPad *sink = NULL; RsnDvdBinPadBlockCtx *bctx = NULL; if (!try_create_piece (dvdbin, DVD_ELEM_SOURCE, NULL, RESIN_TYPE_DVDSRC, "dvdsrc", "DVD source")) { return FALSE; } /* FIXME: Locking */ if (dvdbin->device) { g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_SOURCE]), "device", dvdbin->device, NULL); } /* FIXME: Import and use local copy of mpeg PS demuxer */ if (!try_create_piece (dvdbin, DVD_ELEM_DEMUX, NULL, GST_TYPE_FLUPS_DEMUX, "dvddemux", "DVD demuxer")) return FALSE; if (gst_element_link (dvdbin->pieces[DVD_ELEM_SOURCE], dvdbin->pieces[DVD_ELEM_DEMUX]) == FALSE) goto failed_connect; /* Listen for new pads from the demuxer */ g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "pad-added", G_CALLBACK (demux_pad_added), dvdbin); g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "no-more-pads", G_CALLBACK (demux_no_more_pads), dvdbin); if (!try_create_piece (dvdbin, DVD_ELEM_MQUEUE, "multiqueue", 0, "rsnmq", "multiqueue")) return FALSE; g_object_set (dvdbin->pieces[DVD_ELEM_MQUEUE], "max-size-time", (7 * GST_SECOND / 10), "max-size-bytes", 0, "max-size-buffers", 0, NULL); if (!try_create_piece (dvdbin, DVD_ELEM_VIDPARSE, "mpegvideoparse", 0, "rsnvidparse", "video parser")) return FALSE; /* Decodebin will throw a missing element message to find an MPEG decoder */ if (!try_create_piece (dvdbin, DVD_ELEM_VIDDEC, NULL, RSN_TYPE_VIDEODEC, "rsnviddec", "video decoder")) return FALSE; /* FIXME: Replace identity */ if (!try_create_piece (dvdbin, DVD_ELEM_PARSET, NULL, RSN_TYPE_RSNPARSETTER, "rsnparsetter", "Aspect ratio adjustment")) return FALSE; if (!try_link_pieces (dvdbin->pieces[DVD_ELEM_VIDPARSE], "src", dvdbin->pieces[DVD_ELEM_VIDDEC], "sink")) goto failed_vidparse_connect; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDDEC], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "sink"); if (src == NULL || sink == NULL) goto failed_viddec_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_viddec_connect; gst_object_unref (src); gst_object_unref (sink); src = sink = NULL; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "src"); if (src == NULL) goto failed_video_ghost; src_templ = gst_static_pad_template_get (&video_src_template); dvdbin->video_pad = gst_ghost_pad_new_from_template ("video", src, src_templ); gst_object_unref (src_templ); if (dvdbin->video_pad == NULL) goto failed_video_ghost; gst_pad_set_active (dvdbin->video_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->video_pad); bctx->pad_block_id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; #if DEBUG_TIMING gst_pad_add_probe (dvdbin->video_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_FLUSH, (GstPadProbeCallback) dvdbin_dump_timing_info, NULL, NULL); #endif /* FIXME: Merge stream-selection logic to core and switch back */ if (!try_create_piece (dvdbin, DVD_ELEM_SPU_SELECT, NULL, RSN_TYPE_INPUT_SELECTOR, "subpselect", "Subpicture stream selector")) return FALSE; g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_SPU_SELECT]), "sync-streams", FALSE, NULL); /* Add a single standalone queue to hold a single buffer of SPU data */ if (!try_create_piece (dvdbin, DVD_ELEM_SPUQ, "queue", 0, "spu_q", "subpicture decoder buffer")) return FALSE; /* Allow a lot more while pre-rolling */ g_object_set (dvdbin->pieces[DVD_ELEM_SPUQ], "max-size-time", G_GUINT64_CONSTANT (0), "max-size-bytes", 0, "max-size-buffers", 100, NULL); src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPUQ], "sink"); if (src == NULL || sink == NULL) goto failed_spuq_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_spuq_connect; gst_object_unref (src); gst_object_unref (sink); src = sink = NULL; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPUQ], "src"); if (src == NULL) goto failed_spu_ghost; src_templ = gst_static_pad_template_get (&subpicture_src_template); dvdbin->subpicture_pad = gst_ghost_pad_new_from_template ("subpicture", src, src_templ); gst_object_unref (src_templ); if (dvdbin->subpicture_pad == NULL) goto failed_spu_ghost; gst_pad_set_active (dvdbin->subpicture_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->subpicture_pad); bctx->pad_block_id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; if (!try_create_piece (dvdbin, DVD_ELEM_AUD_SELECT, NULL, RSN_TYPE_INPUT_SELECTOR, "audioselect", "Audio stream selector")) return FALSE; g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_AUD_SELECT]), "sync-streams", FALSE, NULL); if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, NULL, RSN_TYPE_AUDIODEC, "auddec", "audio decoder")) return FALSE; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink"); if (src == NULL || sink == NULL) goto failed_aud_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_aud_connect; gst_object_unref (sink); gst_object_unref (src); src = sink = NULL; /* ghost audio munge output pad onto bin */ src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src"); if (src == NULL) goto failed_aud_ghost; src_templ = gst_static_pad_template_get (&audio_src_template); dvdbin->audio_pad = gst_ghost_pad_new_from_template ("audio", src, src_templ); gst_object_unref (src_templ); if (dvdbin->audio_pad == NULL) goto failed_aud_ghost; gst_pad_set_active (dvdbin->audio_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->audio_pad); bctx->pad_block_id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; if (dvdbin->video_added && (dvdbin->audio_added || dvdbin->audio_broken) && dvdbin->subpicture_added) { rsn_dvdbin_no_more_pads (dvdbin); } return TRUE; failed_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD source and demuxer elements")); goto error_out; failed_vidparse_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD video parser and video decoder")); goto error_out; failed_viddec_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD video decoder and aspect ratio adjuster")); goto error_out; failed_video_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost video output pad")); goto error_out; failed_spuq_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD subpicture selector and buffer elements")); goto error_out; failed_spu_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost SPU output pad")); goto error_out; failed_aud_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD audio decoder")); goto error_out; failed_aud_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost audio output pad")); goto error_out; error_out: if (src != NULL) gst_object_unref (src); if (sink != NULL) gst_object_unref (sink); return FALSE; }
static gboolean gst_d3dvideosink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstD3DVideoSink *sink = GST_D3DVIDEOSINK (bsink); GstBufferPool *pool; GstStructure *config; GstCaps *caps; guint size; gboolean need_pool; gst_query_parse_allocation (query, &caps, &need_pool); if (!caps) { GST_DEBUG_OBJECT (sink, "no caps specified"); return FALSE; } gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); #ifdef DISABLE_BUFFER_POOL return TRUE; #endif GST_OBJECT_LOCK (sink); pool = sink->pool ? gst_object_ref (sink->pool) : NULL; GST_OBJECT_UNLOCK (sink); if (pool) { GstCaps *pcaps; /* we had a pool, check caps */ GST_DEBUG_OBJECT (sink, "check existing pool caps"); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); if (!gst_caps_is_equal (caps, pcaps)) { GST_DEBUG_OBJECT (sink, "pool has different caps"); /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } gst_structure_free (config); } if (pool == NULL && need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR_OBJECT (sink, "allocation query has invalid caps %" GST_PTR_FORMAT, caps); return FALSE; } GST_DEBUG_OBJECT (sink, "create new pool"); pool = gst_d3dsurface_buffer_pool_new (sink); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); /* we need at least 2 buffer because we hold on to the last one */ gst_buffer_pool_config_set_params (config, caps, size, 2, 0); if (!gst_buffer_pool_set_config (pool, config)) { gst_object_unref (pool); GST_ERROR_OBJECT (sink, "failed to set pool configuration"); return FALSE; } } if (pool) { /* we need at least 2 buffer because we hold on to the last one */ gst_query_add_allocation_pool (query, pool, size, 2, 0); gst_object_unref (pool); } return TRUE; }
/** * gst_device_provider_factory_get: * @factory: factory to instantiate * * Returns the device provider of the type defined by the given device * providerfactory. * * Returns: (transfer full) (nullable): the #GstDeviceProvider or %NULL * if the device provider couldn't be created * * Since: 1.4 */ GstDeviceProvider * gst_device_provider_factory_get (GstDeviceProviderFactory * factory) { GstDeviceProvider *device_provider; GstDeviceProviderClass *oclass; GstDeviceProviderFactory *newfactory; g_return_val_if_fail (factory != NULL, NULL); newfactory = GST_DEVICE_PROVIDER_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE (factory))); if (newfactory == NULL) goto load_failed; factory = newfactory; GST_INFO ("getting device provider \"%s\"", GST_OBJECT_NAME (factory)); if (factory->type == 0) goto no_type; device_provider = g_atomic_pointer_get (&newfactory->provider); if (device_provider) return gst_object_ref (device_provider); /* create an instance of the device provider, cast so we don't assert on NULL * also set name as early as we can */ device_provider = GST_DEVICE_PROVIDER_CAST (g_object_newv (factory->type, 0, NULL)); if (G_UNLIKELY (device_provider == NULL)) goto no_device_provider; /* fill in the pointer to the factory in the device provider class. The * class will not be unreffed currently. * Be thread safe as there might be 2 threads creating the first instance of * an device provider at the same moment */ oclass = GST_DEVICE_PROVIDER_GET_CLASS (device_provider); if (!g_atomic_pointer_compare_and_exchange (&oclass->factory, NULL, factory)) gst_object_unref (factory); gst_object_ref_sink (device_provider); /* We use an atomic to make sure we don't create two in parallel */ if (!g_atomic_pointer_compare_and_exchange (&newfactory->provider, NULL, device_provider)) { gst_object_unref (device_provider); device_provider = g_atomic_pointer_get (&newfactory->provider); } GST_DEBUG ("created device provider \"%s\"", GST_OBJECT_NAME (factory)); return gst_object_ref (device_provider); /* ERRORS */ load_failed: { GST_WARNING_OBJECT (factory, "loading plugin containing feature %s returned NULL!", GST_OBJECT_NAME (factory)); return NULL; } no_type: { GST_WARNING_OBJECT (factory, "factory has no type"); gst_object_unref (factory); return NULL; } no_device_provider: { GST_WARNING_OBJECT (factory, "could not create device provider"); gst_object_unref (factory); return NULL; } }
static gboolean gst_wavpack_parse_create_src_pad (GstWavpackParse * wvparse, GstBuffer * buf, WavpackHeader * header) { GstWavpackMetadata meta; GstCaps *caps = NULL; guchar *bufptr; g_assert (wvparse->srcpad == NULL); bufptr = GST_BUFFER_DATA (buf) + sizeof (WavpackHeader); while (gst_wavpack_read_metadata (&meta, GST_BUFFER_DATA (buf), &bufptr)) { switch (meta.id) { case ID_WVC_BITSTREAM:{ caps = gst_caps_new_simple ("audio/x-wavpack-correction", "framed", G_TYPE_BOOLEAN, TRUE, NULL); wvparse->srcpad = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (wvparse), "wvcsrc"), "wvcsrc"); break; } case ID_WV_BITSTREAM: case ID_WVX_BITSTREAM:{ WavpackStreamReader *stream_reader = gst_wavpack_stream_reader_new (); WavpackContext *wpc; gchar error_msg[80]; read_id rid; gint channel_mask; rid.buffer = GST_BUFFER_DATA (buf); rid.length = GST_BUFFER_SIZE (buf); rid.position = 0; wpc = WavpackOpenFileInputEx (stream_reader, &rid, NULL, error_msg, 0, 0); if (!wpc) return FALSE; wvparse->samplerate = WavpackGetSampleRate (wpc); wvparse->channels = WavpackGetNumChannels (wpc); wvparse->total_samples = (header->total_samples == 0xffffffff) ? G_GINT64_CONSTANT (-1) : header->total_samples; caps = gst_caps_new_simple ("audio/x-wavpack", "width", G_TYPE_INT, WavpackGetBitsPerSample (wpc), "channels", G_TYPE_INT, wvparse->channels, "rate", G_TYPE_INT, wvparse->samplerate, "framed", G_TYPE_BOOLEAN, TRUE, NULL); #ifdef WAVPACK_OLD_API channel_mask = wpc->config.channel_mask; #else channel_mask = WavpackGetChannelMask (wpc); #endif if (channel_mask == 0) channel_mask = gst_wavpack_get_default_channel_mask (wvparse->channels); if (channel_mask != 0) { if (!gst_wavpack_set_channel_layout (caps, channel_mask)) { GST_WARNING_OBJECT (wvparse, "Failed to set channel layout"); gst_caps_unref (caps); caps = NULL; WavpackCloseFile (wpc); g_free (stream_reader); break; } } wvparse->srcpad = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (wvparse), "src"), "src"); WavpackCloseFile (wpc); g_free (stream_reader); break; } default:{ GST_LOG_OBJECT (wvparse, "unhandled ID: 0x%02x", meta.id); break; } } if (caps != NULL) break; } if (caps == NULL || wvparse->srcpad == NULL) return FALSE; GST_DEBUG_OBJECT (wvparse, "Added src pad with caps %" GST_PTR_FORMAT, caps); gst_pad_set_query_function (wvparse->srcpad, GST_DEBUG_FUNCPTR (gst_wavpack_parse_src_query)); gst_pad_set_query_type_function (wvparse->srcpad, GST_DEBUG_FUNCPTR (gst_wavpack_parse_get_src_query_types)); gst_pad_set_event_function (wvparse->srcpad, GST_DEBUG_FUNCPTR (gst_wavpack_parse_src_event)); gst_pad_set_caps (wvparse->srcpad, caps); gst_caps_unref (caps); gst_pad_use_fixed_caps (wvparse->srcpad); gst_object_ref (wvparse->srcpad); gst_pad_set_active (wvparse->srcpad, TRUE); gst_element_add_pad (GST_ELEMENT (wvparse), wvparse->srcpad); gst_element_no_more_pads (GST_ELEMENT (wvparse)); return TRUE; }
/** * gst_plugin_load_file: * @filename: the plugin filename to load * @error: pointer to a NULL-valued GError * * Loads the given plugin and refs it. Caller needs to unref after use. * * Returns: a reference to the existing loaded GstPlugin, a reference to the * newly-loaded GstPlugin, or NULL if an error occurred. */ GstPlugin * gst_plugin_load_file (const gchar * filename, GError ** error) { GstPlugin *plugin; GModule *module; gboolean ret; gpointer ptr; struct stat file_status; GstRegistry *registry; g_return_val_if_fail (filename != NULL, NULL); registry = gst_registry_get_default (); g_static_mutex_lock (&gst_plugin_loading_mutex); plugin = gst_registry_lookup (registry, filename); if (plugin) { if (plugin->module) { g_static_mutex_unlock (&gst_plugin_loading_mutex); return plugin; } else { gst_object_unref (plugin); plugin = NULL; } } GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "attempt to load plugin \"%s\"", filename); if (g_module_supported () == FALSE) { GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "module loading not supported"); g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, "Dynamic loading not supported"); goto return_error; } if (g_stat (filename, &file_status)) { GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "problem accessing file"); g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, "Problem accessing file %s: %s", filename, g_strerror (errno)); goto return_error; } module = g_module_open (filename, G_MODULE_BIND_LOCAL); if (module == NULL) { GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "module_open failed: %s", g_module_error ()); g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, "Opening module failed: %s", g_module_error ()); /* If we failed to open the shared object, then it's probably because a * plugin is linked against the wrong libraries. Print out an easy-to-see * message in this case. */ g_warning ("Failed to load plugin '%s': %s", filename, g_module_error ()); goto return_error; } plugin = g_object_new (GST_TYPE_PLUGIN, NULL); plugin->module = module; plugin->filename = g_strdup (filename); plugin->basename = g_path_get_basename (filename); plugin->file_mtime = file_status.st_mtime; plugin->file_size = file_status.st_size; ret = g_module_symbol (module, "gst_plugin_desc", &ptr); if (!ret) { GST_DEBUG ("Could not find plugin entry point in \"%s\"", filename); g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, "File \"%s\" is not a GStreamer plugin", filename); g_module_close (module); goto return_error; } plugin->orig_desc = (GstPluginDesc *) ptr; /* check plugin description: complain about bad values but accept them, to * maintain backwards compatibility (FIXME: 0.11) */ CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, name, filename); CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, description, filename); CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, version, filename); CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, license, filename); CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, source, filename); CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, package, filename); CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, origin, filename); GST_LOG ("Plugin %p for file \"%s\" prepared, calling entry function...", plugin, filename); /* this is where we load the actual .so, so let's trap SIGSEGV */ _gst_plugin_fault_handler_setup (); _gst_plugin_fault_handler_filename = plugin->filename; GST_LOG ("Plugin %p for file \"%s\" prepared, registering...", plugin, filename); if (!gst_plugin_register_func (plugin, plugin->orig_desc)) { /* remove signal handler */ _gst_plugin_fault_handler_restore (); GST_DEBUG ("gst_plugin_register_func failed for plugin \"%s\"", filename); /* plugin == NULL */ g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, "File \"%s\" appears to be a GStreamer plugin, but it failed to initialize", filename); g_module_close (module); goto return_error; } /* remove signal handler */ _gst_plugin_fault_handler_restore (); _gst_plugin_fault_handler_filename = NULL; GST_INFO ("plugin \"%s\" loaded", plugin->filename); gst_object_ref (plugin); gst_default_registry_add_plugin (plugin); g_static_mutex_unlock (&gst_plugin_loading_mutex); return plugin; return_error: { if (plugin) gst_object_unref (plugin); g_static_mutex_unlock (&gst_plugin_loading_mutex); return NULL; } }
/** * gst_gl_context_new_wrapped: * @display: a #GstGLDisplay * @handle: the OpenGL context to wrap * @context_type: a #GstGLPlatform specifying the type of context in @handle * @available_apis: a #GstGLAPI containing the available OpenGL apis in @handle * * Wraps an existing OpenGL context into a #GstGLContext. * * Returns: a #GstGLContext wrapping @handle * * Since: 1.4 */ GstGLContext * gst_gl_context_new_wrapped (GstGLDisplay * display, guintptr handle, GstGLPlatform context_type, GstGLAPI available_apis) { GstGLContext *context; GstGLWrappedContext *context_wrap = NULL; GstGLContextClass *context_class; GstGLAPI display_api; _init_debug (); display_api = gst_gl_display_get_gl_api (display); g_return_val_if_fail ((display_api & available_apis) != GST_GL_API_NONE, NULL); context_wrap = g_object_new (GST_GL_TYPE_WRAPPED_CONTEXT, NULL); if (!context_wrap) { /* subclass returned a NULL context */ GST_ERROR ("Could not wrap existing context"); return NULL; } context = (GstGLContext *) context_wrap; context->priv->display = gst_object_ref (display); context_wrap->handle = handle; context_wrap->platform = context_type; context_wrap->available_apis = available_apis; context_class = GST_GL_CONTEXT_GET_CLASS (context); #if GST_GL_HAVE_PLATFORM_GLX if (context_type == GST_GL_PLATFORM_GLX) { context_class->get_current_context = gst_gl_context_glx_get_current_context; context_class->get_proc_address = gst_gl_context_glx_get_proc_address; } #endif #if GST_GL_HAVE_PLATFORM_EGL if (context_type == GST_GL_PLATFORM_EGL) { context_class->get_current_context = gst_gl_context_egl_get_current_context; context_class->get_proc_address = gst_gl_context_egl_get_proc_address; } #endif #if GST_GL_HAVE_PLATFORM_CGL if (context_type == GST_GL_PLATFORM_CGL) { context_class->get_current_context = gst_gl_context_cocoa_get_current_context; context_class->get_proc_address = _default_get_proc_address; } #endif #if GST_GL_HAVE_PLATFORM_WGL if (context_type == GST_GL_PLATFORM_WGL) { context_class->get_current_context = gst_gl_context_wgl_get_current_context; context_class->get_proc_address = gst_gl_context_wgl_get_proc_address; } #endif #if GST_GL_HAVE_PLATFORM_EAGL if (context_type == GST_GL_PLATFORM_EAGL) { context_class->get_current_context = gst_gl_context_eagl_get_current_context; context_class->get_proc_address = _default_get_proc_address; } #endif if (!context_class->get_current_context) { /* we don't have API support */ gst_object_unref (context); return NULL; } return context; }
/** * gst_gl_base_memory_init: * @mem: the #GstGLBaseMemory to initialize * @allocator: the #GstAllocator to initialize with * @parent: (allow-none): the parent #GstMemory to initialize with * @context: the #GstGLContext to initialize with * @params: (allow-none): the @GstAllocationParams to initialize with * @size: the number of bytes to be allocated * @user_data: (allow-none): user data to call @notify with * @notify: (allow-none): a #GDestroyNotify * * Initializes @mem with the required parameters */ void gst_gl_base_memory_init (GstGLBaseMemory * mem, GstAllocator * allocator, GstMemory * parent, GstGLContext * context, GstAllocationParams * params, gsize size, gpointer user_data, GDestroyNotify notify) { gsize align = gst_memory_alignment, offset = 0, maxsize; GstMemoryFlags flags = 0; struct create_data data; /* A note on sizes. * gl_mem->alloc_size: the size to allocate when we control the allocation. * Size of the unaligned allocation. * mem->maxsize: the size that is used by GstMemory for mapping, to map the * entire memory. The size of the aligned allocation * mem->size: represents the size of the valid data. Can be reduced with * gst_memory_resize() * * It holds that: * mem->size + mem->offset <= mem->maxsize * and * mem->maxsize + alignment offset <= gl_mem->alloc_size * * We need to add the alignment mask to the allocated size in order to have * the freedom to align the gl_mem->data pointer correctly which may be offset * by at most align bytes in the alloc_data pointer. * * maxsize is not suitable for this as it is used by GstMemory as the size * to map with. */ mem->alloc_size = maxsize = size; if (params) { flags = params->flags; align |= params->align; offset = params->prefix; maxsize += params->prefix + params->padding; /* deals with any alignment */ mem->alloc_size = maxsize + align; } gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, parent, maxsize, align, offset, size); mem->context = gst_object_ref (context); mem->notify = notify; mem->user_data = user_data; g_mutex_init (&mem->lock); data.mem = mem; gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _mem_create_gl, &data); if (!data.result) { GST_CAT_ERROR (GST_CAT_GL_BASE_MEMORY, "Could not create GL buffer with context:%p", context); } GST_CAT_DEBUG (GST_CAT_GL_BASE_MEMORY, "new GL buffer memory:%p size:%" G_GSIZE_FORMAT, mem, maxsize); }
static GstElement * ges_track_video_transition_create_element (GESTrackObject * object) { GstElement *topbin, *iconva, *iconvb, *oconv; GObject *target = NULL; const gchar *propname = NULL; GstElement *mixer = NULL; GstPad *sinka_target, *sinkb_target, *src_target, *sinka, *sinkb, *src; GstController *controller; GstInterpolationControlSource *control_source; GESTrackVideoTransition *self; GESTrackVideoTransitionPrivate *priv; self = GES_TRACK_VIDEO_TRANSITION (object); priv = self->priv; GST_LOG ("creating a video bin"); topbin = gst_bin_new ("transition-bin"); iconva = gst_element_factory_make ("ffmpegcolorspace", "tr-csp-a"); iconvb = gst_element_factory_make ("ffmpegcolorspace", "tr-csp-b"); oconv = gst_element_factory_make ("ffmpegcolorspace", "tr-csp-output"); gst_bin_add_many (GST_BIN (topbin), iconva, iconvb, oconv, NULL); /* Prefer videomixer2 to videomixer */ mixer = gst_element_factory_make ("videomixer2", NULL); if (mixer == NULL) mixer = gst_element_factory_make ("videomixer", NULL); g_object_set (G_OBJECT (mixer), "background", 1, NULL); gst_bin_add (GST_BIN (topbin), mixer); if (priv->type != GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE) { priv->sinka = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconva, mixer, priv->type, NULL); priv->sinkb = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconvb, mixer, priv->type, &priv->smpte); target = (GObject *) priv->smpte; propname = "position"; priv->start_value = 1.0; priv->end_value = 0.0; } else { priv->sinka = (GstPad *) link_element_to_mixer (iconva, mixer); priv->sinkb = (GstPad *) link_element_to_mixer (iconvb, mixer); target = (GObject *) priv->sinkb; propname = "alpha"; priv->start_value = 0.0; priv->end_value = 1.0; } priv->mixer = gst_object_ref (mixer); fast_element_link (mixer, oconv); sinka_target = gst_element_get_static_pad (iconva, "sink"); sinkb_target = gst_element_get_static_pad (iconvb, "sink"); src_target = gst_element_get_static_pad (oconv, "src"); sinka = gst_ghost_pad_new ("sinka", sinka_target); sinkb = gst_ghost_pad_new ("sinkb", sinkb_target); src = gst_ghost_pad_new ("src", src_target); gst_element_add_pad (topbin, src); gst_element_add_pad (topbin, sinka); gst_element_add_pad (topbin, sinkb); gst_object_unref (sinka_target); gst_object_unref (sinkb_target); gst_object_unref (src_target); /* set up interpolation */ g_object_set (target, propname, (gfloat) 0.0, NULL); controller = gst_object_control_properties (target, propname, NULL); control_source = gst_interpolation_control_source_new (); gst_controller_set_control_source (controller, propname, GST_CONTROL_SOURCE (control_source)); gst_interpolation_control_source_set_interpolation_mode (control_source, GST_INTERPOLATE_LINEAR); priv->controller = controller; priv->control_source = control_source; return topbin; }
static gboolean gst_gl_mixer_propose_allocation (GstGLMixer * mix, GstQuery * decide_query, GstQuery * query) { GstBufferPool *pool; GstStructure *config; GstCaps *caps; guint size = 0; gboolean need_pool; GError *error = NULL; GstStructure *gl_context; gchar *platform, *gl_apis; gpointer handle; GstAllocator *allocator = NULL; GstAllocationParams params; gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) goto no_caps; if ((pool = mix->priv->pool)) gst_object_ref (pool); if (pool != NULL) { GstCaps *pcaps; /* we had a pool, check caps */ GST_DEBUG_OBJECT (mix, "check existing pool caps"); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); if (!gst_caps_is_equal (caps, pcaps)) { GST_DEBUG_OBJECT (mix, "pool has different caps"); /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } gst_structure_free (config); } if (!gst_gl_ensure_display (mix, &mix->display)) return FALSE; if (!mix->context) { mix->context = gst_gl_context_new (mix->display); if (!gst_gl_context_create (mix->context, NULL, &error)) goto context_error; } if (pool == NULL && need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; GST_DEBUG_OBJECT (mix, "create new pool"); pool = gst_gl_buffer_pool_new (mix->context); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, 0, 0); if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; } if (pool) { gst_query_add_allocation_pool (query, pool, size, 1, 0); gst_object_unref (pool); } /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); gl_apis = gst_gl_api_to_string (gst_gl_context_get_gl_api (mix->context)); platform = gst_gl_platform_to_string (gst_gl_context_get_gl_platform (mix->context)); handle = (gpointer) gst_gl_context_get_gl_context (mix->context); gl_context = gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, mix->context, "gst.gl.context.handle", G_TYPE_POINTER, handle, "gst.gl.context.type", G_TYPE_STRING, platform, "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL); gst_query_add_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, gl_context); g_free (gl_apis); g_free (platform); gst_structure_free (gl_context); gst_allocation_params_init (¶ms); allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR); gst_query_add_allocation_param (query, allocator, ¶ms); gst_object_unref (allocator); return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (mix, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (mix, "invalid caps specified"); return FALSE; } config_failed: { GST_DEBUG_OBJECT (mix, "failed setting config"); return FALSE; } context_error: { GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); return FALSE; } }
static GstElement * gst_auto_convert_add_element (GstAutoConvert * autoconvert, GstElementFactory * factory) { GstElement *element = NULL; GstPad *internal_sinkpad = NULL; GstPad *internal_srcpad = NULL; GstPad *sinkpad; GstPad *srcpad; GstPadLinkReturn padlinkret; GST_DEBUG_OBJECT (autoconvert, "Adding element %s to the autoconvert bin", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); element = gst_element_factory_create (factory, NULL); if (!element) return NULL; if (!gst_bin_add (GST_BIN (autoconvert), element)) { GST_ERROR_OBJECT (autoconvert, "Could not add element %s to the bin", GST_OBJECT_NAME (element)); gst_object_unref (element); return NULL; } srcpad = get_pad_by_direction (element, GST_PAD_SRC); if (!srcpad) { GST_ERROR_OBJECT (autoconvert, "Could not find source in %s", GST_OBJECT_NAME (element)); goto error; } sinkpad = get_pad_by_direction (element, GST_PAD_SINK); if (!sinkpad) { GST_ERROR_OBJECT (autoconvert, "Could not find sink in %s", GST_OBJECT_NAME (element)); goto error; } internal_sinkpad = gst_pad_new_from_static_template (&sink_internal_template, "sink_internal"); internal_srcpad = gst_pad_new_from_static_template (&src_internal_template, "src_internal"); if (!internal_sinkpad || !internal_srcpad) { GST_ERROR_OBJECT (autoconvert, "Could not create internal pads"); goto error; } g_object_weak_ref (G_OBJECT (element), (GWeakNotify) gst_object_unref, internal_sinkpad); g_object_weak_ref (G_OBJECT (element), (GWeakNotify) gst_object_unref, internal_srcpad); gst_pad_set_active (internal_sinkpad, TRUE); gst_pad_set_active (internal_srcpad, TRUE); g_object_set_qdata (G_OBJECT (internal_srcpad), parent_quark, autoconvert); g_object_set_qdata (G_OBJECT (internal_sinkpad), parent_quark, autoconvert); gst_pad_set_chain_function (internal_sinkpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_chain)); gst_pad_set_event_function (internal_sinkpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_event)); gst_pad_set_query_function (internal_sinkpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_query)); gst_pad_set_query_type_function (internal_sinkpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_query_type)); gst_pad_set_getcaps_function (internal_sinkpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_getcaps)); gst_pad_set_bufferalloc_function (internal_sinkpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_buffer_alloc)); gst_pad_set_fixatecaps_function (internal_sinkpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_fixatecaps)); gst_pad_set_event_function (internal_srcpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_src_event)); gst_pad_set_query_function (internal_srcpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_src_query)); gst_pad_set_query_type_function (internal_srcpad, GST_DEBUG_FUNCPTR (gst_auto_convert_internal_src_query_type)); padlinkret = gst_pad_link (internal_srcpad, sinkpad); if (GST_PAD_LINK_FAILED (padlinkret)) { GST_WARNING_OBJECT (autoconvert, "Could not links pad %s:%s to %s:%s" " for reason %d", GST_DEBUG_PAD_NAME (internal_srcpad), GST_DEBUG_PAD_NAME (sinkpad), padlinkret); goto error; } padlinkret = gst_pad_link (srcpad, internal_sinkpad); if (GST_PAD_LINK_FAILED (padlinkret)) { GST_WARNING_OBJECT (autoconvert, "Could not links pad %s:%s to %s:%s" " for reason %d", GST_DEBUG_PAD_NAME (internal_srcpad), GST_DEBUG_PAD_NAME (sinkpad), padlinkret); goto error; } g_object_set_qdata (G_OBJECT (element), internal_srcpad_quark, internal_srcpad); g_object_set_qdata (G_OBJECT (element), internal_sinkpad_quark, internal_sinkpad); /* Iffy */ gst_element_sync_state_with_parent (element); /* Increment the reference count we will return to the caller */ gst_object_ref (element); return element; error: gst_bin_remove (GST_BIN (autoconvert), element); return NULL; }
static gboolean gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstGLBufferPool *glpool = GST_GL_BUFFER_POOL_CAST (pool); GstGLBufferPoolPrivate *priv = glpool->priv; GstVideoInfo info; GstCaps *caps = NULL; guint min_buffers, max_buffers; guint max_align, n; GstAllocator *allocator = NULL; GstAllocationParams alloc_params; GstGLTextureTarget tex_target; gboolean ret = TRUE; gint p; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, &max_buffers)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); if (!gst_buffer_pool_config_get_allocator (config, &allocator, &alloc_params)) goto wrong_config; gst_caps_replace (&priv->caps, caps); if (priv->allocator) gst_object_unref (priv->allocator); if (allocator /* && GST_IS_GL_MEMORY_ALLOCATOR (allocator) FIXME EGLImage */ ) { priv->allocator = gst_object_ref (allocator); } else { priv->allocator = GST_ALLOCATOR (gst_gl_memory_allocator_get_default (glpool->context)); g_assert (priv->allocator); } priv->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); priv->add_glsyncmeta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); #if GST_GL_HAVE_PLATFORM_EGL if (priv->allocator) { priv->want_eglimage = (g_strcmp0 (priv->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0); } else #endif { priv->want_eglimage = FALSE; } if (priv->gl_params) gst_gl_allocation_params_free ((GstGLAllocationParams *) priv->gl_params); priv->gl_params = (GstGLVideoAllocationParams *) gst_buffer_pool_config_get_gl_allocation_params (config); if (!priv->gl_params) priv->gl_params = gst_gl_video_allocation_params_new (glpool->context, &alloc_params, &info, -1, NULL, 0); max_align = alloc_params.align; if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { priv->add_videometa = TRUE; gst_buffer_pool_config_get_video_alignment (config, priv->gl_params->valign); for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n) max_align |= priv->gl_params->valign->stride_align[n]; for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n) priv->gl_params->valign->stride_align[n] = max_align; gst_video_info_align (priv->gl_params->v_info, priv->gl_params->valign); gst_buffer_pool_config_set_video_alignment (config, priv->gl_params->valign); } if (alloc_params.align < max_align) { GST_WARNING_OBJECT (pool, "allocation params alignment %u is smaller " "than the max specified video stride alignment %u, fixing", (guint) alloc_params.align, max_align); alloc_params.align = max_align; gst_buffer_pool_config_set_allocator (config, allocator, &alloc_params); if (priv->gl_params->parent.alloc_params) gst_allocation_params_free (priv->gl_params->parent.alloc_params); priv->gl_params->parent.alloc_params = gst_allocation_params_copy (&alloc_params); } { GstStructure *s = gst_caps_get_structure (caps, 0); const gchar *target_str = gst_structure_get_string (s, "texture-target"); gboolean multiple_texture_targets = FALSE; tex_target = priv->gl_params->target; if (target_str) tex_target = gst_gl_texture_target_from_string (target_str); if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_2D) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_2D; } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_RECTANGLE) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_RECTANGLE; } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_EXTERNAL_OES) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_EXTERNAL_OES; } if (!tex_target) tex_target = GST_GL_TEXTURE_TARGET_2D; if (multiple_texture_targets) { GST_WARNING_OBJECT (pool, "Multiple texture targets configured either " "through caps or buffer pool options"); ret = FALSE; } priv->gl_params->target = tex_target; } /* Recalulate the size and offset as we don't add padding between planes. */ priv->gl_params->v_info->size = 0; for (p = 0; p < GST_VIDEO_INFO_N_PLANES (priv->gl_params->v_info); p++) { priv->gl_params->v_info->offset[p] = priv->gl_params->v_info->size; priv->gl_params->v_info->size += gst_gl_get_plane_data_size (priv->gl_params->v_info, priv->gl_params->valign, p); } gst_buffer_pool_config_set_params (config, caps, priv->gl_params->v_info->size, min_buffers, max_buffers); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config) && ret; /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } }
/** * gst_wrapper_camera_bin_src_construct_pipeline: * @bcamsrc: camerasrc object * * This function creates and links the elements of the camerasrc bin * videosrc ! cspconv ! srcfilter ! cspconv ! capsfilter ! crop ! scale ! \ * capsfilter ! tee name=t * t. ! ... (viewfinder pad) * t. ! output-selector name=outsel * outsel. ! (image pad) * outsel. ! (video pad) * * Returns: TRUE, if elements were successfully created, FALSE otherwise */ static gboolean gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) { GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc); GstBin *cbin = GST_BIN (bcamsrc); GstElement *tee; GstElement *filter_csp; GstElement *src_csp; GstElement *capsfilter; gboolean ret = FALSE; GstPad *vf_pad; GstPad *tee_capture_pad; GstPad *src_caps_src_pad; if (!self->elements_created) { GST_DEBUG_OBJECT (self, "constructing pipeline"); /* Add application set or default video src element */ if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin, self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC, "camerasrc-real-src"))) { self->src_vid_src = NULL; goto done; } else { if (!gst_camerabin_add_element (cbin, self->src_vid_src)) { goto done; } } /* we lost the reference */ self->app_vid_src = NULL; /* we listen for changes to max-zoom in the video src so that * we can proxy them to the basecamerasrc property */ if (g_object_class_find_property (G_OBJECT_GET_CLASS (bcamsrc), "max-zoom")) { g_signal_connect (G_OBJECT (self->src_vid_src), "notify::max-zoom", (GCallback) gst_wrapper_camera_bin_src_max_zoom_cb, bcamsrc); } /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ { GstPad *pad; pad = gst_element_get_static_pad (self->src_vid_src, "src"); self->src_event_probe_id = gst_pad_add_event_probe (pad, (GCallback) gst_wrapper_camera_src_src_event_probe, self); gst_object_unref (pad); } if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", "src-colorspace")) goto done; if (!(self->src_filter = gst_camerabin_create_and_add_element (cbin, "capsfilter", "src-capsfilter"))) goto done; /* attach to notify::caps on the first capsfilter and use a callback * to recalculate the zoom properties when these caps change and to * propagate the caps to the second capsfilter */ src_caps_src_pad = gst_element_get_static_pad (self->src_filter, "src"); g_signal_connect (src_caps_src_pad, "notify::caps", G_CALLBACK (gst_wrapper_camera_bin_src_caps_cb), self); gst_object_unref (src_caps_src_pad); if (!(self->src_zoom_crop = gst_camerabin_create_and_add_element (cbin, "videocrop", "zoom-crop"))) goto done; if (!(self->src_zoom_scale = gst_camerabin_create_and_add_element (cbin, "videoscale", "zoom-scale"))) goto done; if (!(self->src_zoom_filter = gst_camerabin_create_and_add_element (cbin, "capsfilter", "zoom-capsfilter"))) goto done; if (!(tee = gst_camerabin_create_and_add_element (cbin, "tee", "camerasrc-tee"))) goto done; /* viewfinder pad */ vf_pad = gst_element_get_request_pad (tee, "src%d"); g_object_set (tee, "alloc-pad", vf_pad, NULL); gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad); gst_object_unref (vf_pad); /* image/video pad from tee */ tee_capture_pad = gst_element_get_request_pad (tee, "src%d"); self->output_selector = gst_element_factory_make ("output-selector", "outsel"); g_object_set (self->output_selector, "pad-negotiation-mode", 0, NULL); gst_bin_add (GST_BIN (self), self->output_selector); { GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink"); /* check return TODO */ gst_pad_link (tee_capture_pad, pad); gst_object_unref (pad); } gst_object_unref (tee_capture_pad); /* Create the 2 output pads for video and image */ self->outsel_vidpad = gst_element_get_request_pad (self->output_selector, "src%d"); self->outsel_imgpad = gst_element_get_request_pad (self->output_selector, "src%d"); g_assert (self->outsel_vidpad != NULL); g_assert (self->outsel_imgpad != NULL); gst_pad_add_buffer_probe (self->outsel_imgpad, G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self); gst_pad_add_buffer_probe (self->outsel_vidpad, G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), self->outsel_imgpad); gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), self->outsel_vidpad); if (bcamsrc->mode == MODE_IMAGE) { g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, NULL); } else { g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, NULL); } gst_pad_set_active (self->vfsrc, TRUE); gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ } /* Do this even if pipeline is constructed */ if (self->video_filter) { /* check if we need to replace the current one */ if (self->video_filter != self->app_vid_filter) { gst_bin_remove (cbin, self->video_filter); gst_object_unref (self->video_filter); self->video_filter = NULL; filter_csp = gst_bin_get_by_name (cbin, "filter-colorspace"); gst_bin_remove (cbin, filter_csp); gst_object_unref (filter_csp); filter_csp = NULL; } } if (!self->video_filter) { if (self->app_vid_filter) { self->video_filter = gst_object_ref (self->app_vid_filter); filter_csp = gst_element_factory_make ("ffmpegcolorspace", "filter-colorspace"); gst_bin_add_many (cbin, self->video_filter, filter_csp, NULL); src_csp = gst_bin_get_by_name (cbin, "src-colorspace"); capsfilter = gst_bin_get_by_name (cbin, "src-capsfilter"); if (gst_pad_is_linked (gst_element_get_static_pad (src_csp, "src"))) gst_element_unlink (src_csp, capsfilter); if (!gst_element_link_many (src_csp, self->video_filter, filter_csp, capsfilter, NULL)) goto done; } } ret = TRUE; self->elements_created = TRUE; done: return ret; }