static gboolean gst_x265_enc_sink_query (GstVideoEncoder * enc, GstQuery * query) { gboolean res; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_ACCEPT_CAPS:{ GstCaps *acceptable, *caps; acceptable = gst_x265_enc_get_supported_input_caps (); gst_query_parse_accept_caps (query, &caps); gst_query_set_accept_caps_result (query, gst_caps_is_subset (caps, acceptable)); gst_caps_unref (acceptable); res = TRUE; } break; default: res = GST_VIDEO_ENCODER_CLASS (parent_class)->sink_query (enc, query); break; } return res; }
static gboolean gst_play_sink_convert_bin_query (GstPad * pad, GstObject * parent, GstQuery * query) { gboolean res = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_ACCEPT_CAPS: { GstCaps *caps; gst_query_parse_accept_caps (query, &caps); gst_query_set_accept_caps_result (query, gst_play_sink_convert_bin_acceptcaps (pad, caps)); res = TRUE; break; } case GST_QUERY_CAPS: { GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); caps = gst_play_sink_convert_bin_getcaps (pad, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); res = TRUE; break; } default: res = gst_pad_query_default (pad, parent, query); break; } return res; }
static gboolean gst_imx_compositor_sink_query(GstImxBPAggregator *aggregator, GstImxBPAggregatorPad *pad, GstQuery *query) { switch (GST_QUERY_TYPE(query)) { case GST_QUERY_CAPS: { /* Custom caps query response. Take the sinkpad template caps, * optionally filter them, and return them as the result. * This ensures that the caps that the derived class supports * for input data are actually used (by default, the aggregator * base classes try to keep input and output caps equal) */ GstCaps *filter, *caps; gst_query_parse_caps(query, &filter); caps = gst_pad_get_pad_template_caps(GST_PAD(pad)); if (filter != NULL) { GstCaps *unfiltered_caps = gst_caps_make_writable(caps); caps = gst_caps_intersect(unfiltered_caps, filter); gst_caps_unref(unfiltered_caps); } GST_DEBUG_OBJECT(aggregator, "responding to CAPS query with caps %" GST_PTR_FORMAT, (gpointer)caps); gst_query_set_caps_result(query, caps); gst_caps_unref(caps); return TRUE; } case GST_QUERY_ACCEPT_CAPS: { /* Custom accept_caps query response. Simply check if * the supplied caps are a valid subset of the sinkpad's * template caps. This is done for the same reasons * as the caps query response above. */ GstCaps *accept_caps = NULL, *template_caps = NULL; gboolean ret; gst_query_parse_accept_caps(query, &accept_caps); template_caps = gst_pad_get_pad_template_caps(GST_PAD(pad)); ret = gst_caps_is_subset(accept_caps, template_caps); GST_DEBUG_OBJECT(aggregator, "responding to ACCEPT_CAPS query with value %d (acceptcaps: %" GST_PTR_FORMAT " template caps %" GST_PTR_FORMAT ")", ret, (gpointer)accept_caps, (gpointer)template_caps); gst_query_set_accept_caps_result(query, ret); return TRUE; } default: return GST_IMXBP_AGGREGATOR_CLASS(gst_imx_compositor_parent_class)->sink_query(aggregator, pad, query); } }
static gboolean kms_recorder_endpoint_query_accept_caps (KmsElement * element, GstPad * pad, GstQuery * query) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (element); GstCaps *caps, *accept; GstElement *appsrc; gboolean ret = TRUE; switch (kms_element_get_pad_type (element, pad)) { case KMS_ELEMENT_PAD_TYPE_VIDEO: g_object_get (self->priv->mux, KMS_MUXING_PIPELINE_VIDEO_APPSRC, &appsrc, NULL); caps = kms_recorder_endpoint_get_caps_from_profile (self, KMS_ELEMENT_PAD_TYPE_VIDEO); break; case KMS_ELEMENT_PAD_TYPE_AUDIO: g_object_get (self->priv->mux, KMS_MUXING_PIPELINE_AUDIO_APPSRC, &appsrc, NULL); caps = kms_recorder_endpoint_get_caps_from_profile (self, KMS_ELEMENT_PAD_TYPE_AUDIO); break; default: GST_ERROR_OBJECT (pad, "unknown pad"); return FALSE; } if (caps == NULL) { GST_ERROR_OBJECT (self, "Can not accept caps without profile"); gst_query_set_accept_caps_result (query, FALSE); g_object_unref (appsrc); return TRUE; } gst_query_parse_accept_caps (query, &accept); ret = gst_caps_can_intersect (accept, caps); if (ret) { GstPad *srcpad; srcpad = gst_element_get_static_pad (appsrc, "src"); ret = gst_pad_peer_query_accept_caps (srcpad, accept); gst_object_unref (srcpad); } else { GST_ERROR_OBJECT (self, "Incompatbile caps %" GST_PTR_FORMAT, caps); } gst_caps_unref (caps); g_object_unref (appsrc); gst_query_set_accept_caps_result (query, ret); return TRUE; }
static gboolean tee_query_function (GstPad * pad, GstObject * parent, GstQuery * query) { if (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS) { GstCaps *caps; KmsTreeBin *self = KMS_TREE_BIN (GST_OBJECT_PARENT (parent)); gst_query_parse_accept_caps (query, &caps); kms_tree_bin_set_input_caps (self, caps); } return gst_pad_query_default (pad, parent, query); }
/** * @brief This function handles sink pad query. */ static gboolean gst_tensor_aggregator_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstTensorAggregator *self; self = GST_TENSOR_AGGREGATOR (parent); GST_DEBUG_OBJECT (self, "Received %s query: %" GST_PTR_FORMAT, GST_QUERY_TYPE_NAME (query), query); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CAPS: { GstCaps *caps; GstCaps *filter; gst_query_parse_caps (query, &filter); caps = gst_tensor_aggregator_query_caps (self, pad, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); return TRUE; } case GST_QUERY_ACCEPT_CAPS: { GstCaps *caps; GstCaps *template_caps; gboolean res = FALSE; gst_query_parse_accept_caps (query, &caps); silent_debug_caps (caps, "accept-caps"); if (gst_caps_is_fixed (caps)) { template_caps = gst_pad_get_pad_template_caps (pad); res = gst_caps_can_intersect (template_caps, caps); gst_caps_unref (template_caps); } gst_query_set_accept_caps_result (query, res); return TRUE; } default: break; } return gst_pad_query_default (pad, parent, query); }
static gboolean gst_alsasink_query (GstBaseSink * sink, GstQuery * query) { GstAlsaSink *alsa = GST_ALSA_SINK (sink); gboolean ret; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_ACCEPT_CAPS: { GstCaps *caps; gst_query_parse_accept_caps (query, &caps); ret = gst_alsasink_acceptcaps (alsa, caps); gst_query_set_accept_caps_result (query, ret); ret = TRUE; break; } default: ret = GST_BASE_SINK_CLASS (parent_class)->query (sink, query); break; } return ret; }
static gboolean gst_osx_audio_sink_query (GstBaseSink * base, GstQuery * query) { GstOsxAudioSink *sink = GST_OSX_AUDIO_SINK (base); gboolean ret = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_ACCEPT_CAPS: { GstCaps *caps = NULL; gst_query_parse_accept_caps (query, &caps); ret = gst_osx_audio_sink_acceptcaps (sink, caps); gst_query_set_accept_caps_result (query, ret); ret = TRUE; break; } default: ret = GST_BASE_SINK_CLASS (parent_class)->query (base, query); break; } return ret; }
static gboolean kms_recorder_endpoint_query_accept_caps (KmsElement * element, GstPad * pad, GstQuery * query) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (element); GstCaps *caps, *accept; gboolean ret = TRUE; switch (kms_element_get_pad_type (element, pad)) { case KMS_ELEMENT_PAD_TYPE_VIDEO: caps = kms_recorder_endpoint_get_caps_from_profile (self, KMS_ELEMENT_PAD_TYPE_VIDEO); break; case KMS_ELEMENT_PAD_TYPE_AUDIO: caps = kms_recorder_endpoint_get_caps_from_profile (self, KMS_ELEMENT_PAD_TYPE_AUDIO); break; default: GST_ERROR_OBJECT (pad, "unknown pad"); return FALSE; } if (caps == NULL) { GST_ERROR_OBJECT (self, "Can not accept caps without profile"); gst_query_set_accept_caps_result (query, FALSE); return TRUE; } gst_query_parse_accept_caps (query, &accept); ret = gst_caps_can_intersect (accept, caps); if (ret) { GstElement *appsrc; GstPad *srcpad; gchar *id; id = gst_pad_get_name (pad); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); appsrc = g_hash_table_lookup (self->priv->srcs, id); g_free (id); if (appsrc == NULL) { KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); GST_DEBUG_OBJECT (self, "No appsrc attached to pad %" GST_PTR_FORMAT, pad); goto end; } srcpad = gst_element_get_static_pad (appsrc, "src"); KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); ret = gst_pad_peer_query_accept_caps (srcpad, accept); gst_object_unref (srcpad); } else { GST_ERROR_OBJECT (self, "Incompatbile caps %" GST_PTR_FORMAT, caps); } end: gst_caps_unref (caps); gst_query_set_accept_caps_result (query, ret); return TRUE; }
/* Probe on the output of a parser chain (the last * src pad) */ static GstPadProbeReturn parse_chain_output_probe (GstPad * pad, GstPadProbeInfo * info, DecodebinInputStream * input) { GstPadProbeReturn ret = GST_PAD_PROBE_OK; if (GST_IS_EVENT (GST_PAD_PROBE_INFO_DATA (info))) { GstEvent *ev = GST_PAD_PROBE_INFO_EVENT (info); GST_DEBUG_OBJECT (pad, "Got event %s", GST_EVENT_TYPE_NAME (ev)); switch (GST_EVENT_TYPE (ev)) { case GST_EVENT_STREAM_START: { GstStream *stream = NULL; guint group_id = G_MAXUINT32; gst_event_parse_group_id (ev, &group_id); GST_DEBUG_OBJECT (pad, "Got stream-start, group_id:%d, input %p", group_id, input->input); if (set_input_group_id (input->input, &group_id)) { ev = gst_event_make_writable (ev); gst_event_set_group_id (ev, group_id); GST_PAD_PROBE_INFO_DATA (info) = ev; } input->saw_eos = FALSE; gst_event_parse_stream (ev, &stream); /* FIXME : Would we ever end up with a stream already set on the input ?? */ if (stream) { if (input->active_stream != stream) { MultiQueueSlot *slot; if (input->active_stream) gst_object_unref (input->active_stream); input->active_stream = stream; /* We have the beginning of a stream, get a multiqueue slot and link to it */ g_mutex_lock (&input->dbin->selection_lock); slot = get_slot_for_input (input->dbin, input); link_input_to_slot (input, slot); g_mutex_unlock (&input->dbin->selection_lock); } else gst_object_unref (stream); } } break; case GST_EVENT_CAPS: { GstCaps *caps = NULL; gst_event_parse_caps (ev, &caps); GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps); if (caps && input->active_stream) gst_stream_set_caps (input->active_stream, caps); } break; case GST_EVENT_EOS: input->saw_eos = TRUE; if (all_inputs_are_eos (input->dbin)) { GST_DEBUG_OBJECT (pad, "real input pad, marking as EOS"); check_all_streams_for_eos (input->dbin); } else { GstPad *peer = gst_pad_get_peer (input->srcpad); if (peer) { /* Send custom-eos event to multiqueue slot */ GstStructure *s; GstEvent *event; GST_DEBUG_OBJECT (pad, "Got EOS end of input stream, post custom-eos"); s = gst_structure_new_empty ("decodebin3-custom-eos"); event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); gst_pad_send_event (peer, event); gst_object_unref (peer); } else { GST_FIXME_OBJECT (pad, "No peer, what should we do ?"); } } ret = GST_PAD_PROBE_DROP; break; case GST_EVENT_FLUSH_STOP: GST_DEBUG_OBJECT (pad, "Clear saw_eos flag"); input->saw_eos = FALSE; default: break; } } else if (GST_IS_QUERY (GST_PAD_PROBE_INFO_DATA (info))) { GstQuery *q = GST_PAD_PROBE_INFO_QUERY (info); GST_DEBUG_OBJECT (pad, "Seeing query %s", GST_QUERY_TYPE_NAME (q)); /* If we have a parser, we want to reply to the caps query */ /* FIXME: Set a flag when the input stream is created for * streams where we shouldn't reply to these queries */ if (GST_QUERY_TYPE (q) == GST_QUERY_CAPS && (info->type & GST_PAD_PROBE_TYPE_PULL)) { GstCaps *filter = NULL; GstCaps *allowed; gst_query_parse_caps (q, &filter); allowed = get_parser_caps_filter (input->dbin, filter); GST_DEBUG_OBJECT (pad, "Intercepting caps query, setting %" GST_PTR_FORMAT, allowed); gst_query_set_caps_result (q, allowed); gst_caps_unref (allowed); ret = GST_PAD_PROBE_HANDLED; } else if (GST_QUERY_TYPE (q) == GST_QUERY_ACCEPT_CAPS) { GstCaps *prop = NULL; gst_query_parse_accept_caps (q, &prop); /* Fast check against target caps */ if (gst_caps_can_intersect (prop, input->dbin->caps)) gst_query_set_accept_caps_result (q, TRUE); else { gboolean accepted = check_parser_caps_filter (input->dbin, prop); /* check against caps filter */ gst_query_set_accept_caps_result (q, accepted); GST_DEBUG_OBJECT (pad, "ACCEPT_CAPS query, returning %d", accepted); } ret = GST_PAD_PROBE_HANDLED; } } return ret; }
static gboolean gst_gl_mixer_sink_query (GstAggregator * agg, GstAggregatorPad * bpad, GstQuery * query) { gboolean ret = FALSE; GstGLMixer *mix = GST_GL_MIXER (agg); GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix); GST_TRACE ("QUERY %" GST_PTR_FORMAT, query); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CAPS: { GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); caps = gst_gl_mixer_pad_sink_getcaps (GST_PAD (bpad), mix, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); ret = TRUE; break; } case GST_QUERY_ACCEPT_CAPS: { GstCaps *caps; gst_query_parse_accept_caps (query, &caps); ret = gst_gl_mixer_pad_sink_acceptcaps (GST_PAD (bpad), mix, caps); gst_query_set_accept_caps_result (query, ret); ret = TRUE; break; } case GST_QUERY_ALLOCATION: { GstQuery *decide_query = NULL; GST_OBJECT_LOCK (mix); if (G_UNLIKELY (!mix->priv->negotiated)) { GST_DEBUG_OBJECT (mix, "not negotiated yet, can't answer ALLOCATION query"); GST_OBJECT_UNLOCK (mix); return FALSE; } if ((decide_query = mix->priv->query)) gst_query_ref (decide_query); GST_OBJECT_UNLOCK (mix); GST_DEBUG_OBJECT (mix, "calling propose allocation with query %" GST_PTR_FORMAT, decide_query); /* pass the query to the propose_allocation vmethod if any */ ret = gst_gl_mixer_propose_allocation (mix, decide_query, query); if (decide_query) gst_query_unref (decide_query); GST_DEBUG_OBJECT (mix, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret, query); break; } case GST_QUERY_CONTEXT: { ret = gst_gl_handle_context_query ((GstElement *) mix, query, &mix->display, &mix->other_context); if (mix->display) gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api); break; } default: ret = GST_AGGREGATOR_CLASS (parent_class)->sink_query (agg, bpad, query); break; } return ret; }
static gboolean stereosplit_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstGLStereoSplit *split = GST_GL_STEREOSPLIT (parent); GST_DEBUG_OBJECT (split, "sink query %s", gst_query_type_get_name (GST_QUERY_TYPE (query))); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONTEXT: { const gchar *context_type; GstContext *context, *old_context; gboolean ret; ret = gst_gl_handle_context_query ((GstElement *) split, query, &split->display, &split->other_context); if (split->display) gst_gl_display_filter_gl_api (split->display, SUPPORTED_GL_APIS); gst_query_parse_context_type (query, &context_type); if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) { GstStructure *s; gst_query_parse_context (query, &old_context); if (old_context) context = gst_context_copy (old_context); else context = gst_context_new ("gst.gl.local_context", FALSE); s = gst_context_writable_structure (context); gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, split->context, NULL); gst_query_set_context (query, context); gst_context_unref (context); ret = split->context != NULL; } GST_LOG_OBJECT (split, "context query of type %s %i", context_type, ret); if (ret) return ret; return gst_pad_query_default (pad, parent, query); } case GST_QUERY_ALLOCATION: { return stereosplit_propose_allocation (split, query); } case GST_QUERY_ACCEPT_CAPS: { GstCaps *possible, *caps; gboolean allowed; gst_query_parse_accept_caps (query, &caps); if (!(possible = gst_pad_query_caps (split->sink_pad, caps))) return FALSE; allowed = gst_caps_is_subset (caps, possible); gst_caps_unref (possible); gst_query_set_accept_caps_result (query, allowed); return allowed; } case GST_QUERY_CAPS: { GstCaps *filter, *left, *right, *combined, *ret, *templ_caps; gst_query_parse_caps (query, &filter); /* Calculate what downstream can collectively support */ if (!(left = gst_pad_peer_query_caps (split->left_pad, NULL))) return FALSE; if (!(right = gst_pad_peer_query_caps (split->right_pad, NULL))) return FALSE; /* Strip out multiview mode and flags that might break the * intersection, since we can convert. * We could keep downstream preferred flip/flopping and list * separated as preferred in the future which might * theoretically allow us an easier conversion, but it's not essential */ left = strip_mview_fields (left, GST_VIDEO_MULTIVIEW_FLAGS_NONE); right = strip_mview_fields (right, GST_VIDEO_MULTIVIEW_FLAGS_NONE); combined = gst_caps_intersect (left, right); gst_caps_unref (left); gst_caps_unref (right); /* Intersect peer caps with our template formats */ templ_caps = gst_pad_get_pad_template_caps (split->left_pad); ret = gst_caps_intersect_full (combined, templ_caps, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (templ_caps); gst_caps_unref (combined); combined = ret; if (!combined || gst_caps_is_empty (combined)) { gst_caps_unref (combined); return FALSE; } /* Convert from the src pad caps to input formats we support */ ret = stereosplit_transform_caps (split, GST_PAD_SRC, combined, filter); gst_caps_unref (combined); combined = ret; /* Intersect with the sink pad template then */ templ_caps = gst_pad_get_pad_template_caps (split->sink_pad); ret = gst_caps_intersect_full (combined, templ_caps, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (templ_caps); GST_LOG_OBJECT (split, "Returning sink pad caps %" GST_PTR_FORMAT, ret); gst_query_set_caps_result (query, ret); return !gst_caps_is_empty (ret); } default: return gst_pad_query_default (pad, parent, query); } }
static gboolean gst_directsound_sink_acceptcaps (GstBaseSink * sink, GstQuery * query) { GstDirectSoundSink *dsink = GST_DIRECTSOUND_SINK (sink); GstPad *pad; GstCaps *caps; GstCaps *pad_caps; GstStructure *st; gboolean ret = FALSE; GstAudioRingBufferSpec spec = { 0 }; if (G_UNLIKELY (dsink == NULL)) return FALSE; pad = sink->sinkpad; gst_query_parse_accept_caps (query, &caps); GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps); pad_caps = gst_pad_query_caps (pad, NULL); if (pad_caps) { gboolean cret = gst_caps_is_subset (caps, pad_caps); gst_caps_unref (pad_caps); if (!cret) { GST_DEBUG_OBJECT (dsink, "Caps are not a subset of the pad caps, not accepting caps"); goto done; } } /* If we've not got fixed caps, creating a stream might fail, so let's just * return from here with default acceptcaps behaviour */ if (!gst_caps_is_fixed (caps)) { GST_DEBUG_OBJECT (dsink, "Caps are not fixed, not accepting caps"); goto done; } spec.latency_time = GST_SECOND; if (!gst_audio_ring_buffer_parse_caps (&spec, caps)) { GST_DEBUG_OBJECT (dsink, "Failed to parse caps, not accepting"); goto done; } /* Make sure input is framed (one frame per buffer) and can be payloaded */ switch (spec.type) { case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3: case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS: { gboolean framed = FALSE, parsed = FALSE; st = gst_caps_get_structure (caps, 0); gst_structure_get_boolean (st, "framed", &framed); gst_structure_get_boolean (st, "parsed", &parsed); if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0) { GST_DEBUG_OBJECT (dsink, "Wrong AC3/DTS caps, not accepting"); goto done; } } default: break; } ret = TRUE; GST_DEBUG_OBJECT (dsink, "Accepting caps"); done: gst_query_set_accept_caps_result (query, ret); return TRUE; }