static gboolean gst_type_find_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstTypeFindElement *typefind; gboolean res = FALSE; typefind = GST_TYPE_FIND_ELEMENT (parent); GST_DEBUG_OBJECT (typefind, "Handling src query %s", GST_QUERY_TYPE_NAME (query)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_SCHEDULING: /* FIXME, filter out the scheduling modes that we understand */ res = gst_pad_peer_query (typefind->sink, query); break; case GST_QUERY_CAPS: { GST_DEBUG_OBJECT (typefind, "Got caps query, our caps are %" GST_PTR_FORMAT, typefind->caps); /* We can hijack caps query if we typefind already */ if (typefind->caps) { gst_query_set_caps_result (query, typefind->caps); res = TRUE; } else { res = gst_pad_peer_query (typefind->sink, query); } break; } case GST_QUERY_POSITION: { gint64 peer_pos; GstFormat format; if (!(res = gst_pad_peer_query (typefind->sink, query))) goto out; gst_query_parse_position (query, &format, &peer_pos); GST_OBJECT_LOCK (typefind); /* FIXME: this code assumes that there's no discont in the queue */ switch (format) { case GST_FORMAT_BYTES: peer_pos -= gst_adapter_available (typefind->adapter); break; default: /* FIXME */ break; } GST_OBJECT_UNLOCK (typefind); gst_query_set_position (query, format, peer_pos); break; } default: res = gst_pad_query_default (pad, parent, query); break; } out: return res; }
/* 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; }
QString Query::typeName() const { return QString::fromUtf8(GST_QUERY_TYPE_NAME(object<GstQuery>())); }
static gboolean gst_deinterlace2_src_query (GstPad * pad, GstQuery * query) { GstDeinterlace2 *self = GST_DEINTERLACE2 (gst_pad_get_parent (pad)); gboolean res = FALSE; GST_LOG_OBJECT (self, "%s query", GST_QUERY_TYPE_NAME (query)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_LATENCY: { GstClockTime min, max; gboolean live; GstPad *peer; if ((peer = gst_pad_get_peer (self->sinkpad))) { if ((res = gst_pad_query (peer, query))) { GstClockTime latency; gint fields_required = 0; gint method_latency = 0; if (self->method) { fields_required = gst_deinterlace_method_get_fields_required (self->method); method_latency = gst_deinterlace_method_get_latency (self->method); } gst_query_parse_latency (query, &live, &min, &max); GST_DEBUG ("Peer latency: min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max)); /* add our own latency */ latency = (fields_required + method_latency) * self->field_duration; GST_DEBUG ("Our latency: min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, GST_TIME_ARGS (latency), GST_TIME_ARGS (latency)); min += latency; if (max != GST_CLOCK_TIME_NONE) max += latency; else max = latency; GST_DEBUG ("Calculated total latency : min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max)); gst_query_set_latency (query, live, min, max); } gst_object_unref (peer); } break; } default: res = gst_pad_query_default (pad, query); break; } gst_object_unref (self); return res; }
static gboolean gst_spot_src_query (GstBaseSrc * basesrc, GstQuery * query) { gboolean ret = TRUE; GstSpotSrc *spot = GST_SPOT_SRC (basesrc); gint samplerate = GST_SPOT_SRC_FORMAT (spot)->sample_rate; gint64 src_val, dest_val; if (!GST_SPOT_SRC_FORMAT (spot)) { ret = FALSE; goto no_format_yet; } samplerate = GST_SPOT_SRC_FORMAT (spot)->sample_rate; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { /*FIXME * this one we get, answer it or propagate? * seems like if we answer it we are not asked * to convert, so i guess this is better? gint64 pos; GstFormat format; gst_query_parse_position (query, &format, &pos); pos = GST_SPOT_SRC_READ_POS (GST_SPOT_SRC (basesrc)); GST_INFO_OBJECT (spot, "Query_position pos=%"G_GINT64_FORMAT); */ ret = FALSE; } break; case GST_QUERY_DURATION:{ GstFormat format; guint64 duration; gint64 value; gst_query_parse_duration (query, &format, &value); /* duration in ms */ duration = run_spot_cmd (spot, SPOT_CMD_DURATION, 0); /* duration in ns */ duration = 1000000 * duration; switch (format) { case GST_FORMAT_BYTES: { guint64 duration_bytes = (duration / 1000000000) * samplerate * 4; GST_INFO_OBJECT (spot, "Query_duration, duration_bytes=%" G_GUINT64_FORMAT, duration_bytes); gst_query_set_duration (query, format, duration_bytes); } break; case GST_FORMAT_TIME: { guint64 duration_time = duration; GST_INFO_OBJECT (spot, "Query_duration, duration_time=%" G_GUINT64_FORMAT, duration_time); gst_query_set_duration (query, format, duration_time); } break; default: ret = FALSE; g_assert_not_reached (); break; } break; } /* FIXME: JUST FOR DEBUGING */ case GST_QUERY_LATENCY: /* propagate to basesrc */ ret = FALSE; GST_INFO_OBJECT (spot, "Query_latency"); break; case GST_QUERY_RATE: /* propagate to basesrc */ ret = FALSE; GST_INFO_OBJECT (spot, "Query_latency"); break; case GST_QUERY_SEEKING: /* propagate to basesrc */ ret = FALSE; GST_INFO_OBJECT (spot, "Query_seeking"); break; case GST_QUERY_SEGMENT: /* propagate to basesrc */ ret = FALSE; GST_INFO_OBJECT (spot, "Query_segment"); break; case GST_QUERY_FORMATS: /* propagate to basesrc */ ret = FALSE; GST_INFO_OBJECT (spot, "Query_formats"); break; case GST_QUERY_BUFFERING: /* propagate to basesrc */ ret = FALSE; GST_INFO_OBJECT (spot, "Query_buffering"); break; case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); if (src_fmt == dest_fmt) { dest_val = src_val; GST_INFO_OBJECT (spot, "Convert done, dst_fmt == src_fmt"); goto done; } GST_INFO_OBJECT (spot, "Convert src_fmt=%s to dst_fmt=%s", gst_format_get_name (src_fmt), gst_format_get_name (dest_fmt)); switch (src_fmt) { case GST_FORMAT_BYTES: switch (dest_fmt) { case GST_FORMAT_TIME: /* samples to time convertion * - each sample has two channels with 16 bits, 4byte * - samplerate is usually 44100hz * - time is in nano seconds */ dest_val = (src_val * 1000000000) / ((float)samplerate * 4); GST_INFO_OBJECT (spot,"Convert src_val=%" G_GINT64_FORMAT " b, dst_val=%" G_GINT64_FORMAT " ns", src_val, dest_val); break; default: ret = FALSE; g_assert_not_reached (); break; } break; case GST_FORMAT_TIME: switch (dest_fmt) { case GST_FORMAT_BYTES: /* time to samples */ dest_val = (src_val * samplerate * 4) / 1000000000; GST_INFO_OBJECT (spot,"Convert src_val=%" G_GINT64_FORMAT " ns, dst_val=%" G_GINT64_FORMAT " b", src_val, dest_val); break; default: ret = FALSE; g_assert_not_reached (); break; } break; default: ret = FALSE; g_assert_not_reached (); break; } done: gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } case GST_QUERY_URI: gst_query_set_uri (query, spot->uri); break; default: GST_LOG_OBJECT (spot, "Query type unknown, default, type=%s", GST_QUERY_TYPE_NAME (query)); g_assert_not_reached (); break; } if (!ret) { GST_LOG_OBJECT (spot, "Let basesrc handle query type=%s", GST_QUERY_TYPE_NAME (query)); ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); } no_format_yet: if (!ret) { GST_DEBUG_OBJECT (spot, "Query failed"); } return ret; }