static gboolean gst_deinterleave_src_query (GstPad * pad, GstQuery * query) { GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); gboolean res; res = gst_pad_query_default (pad, query); if (res && GST_QUERY_TYPE (query) == GST_QUERY_DURATION) { GstFormat format; gint64 dur; gst_query_parse_duration (query, &format, &dur); /* Need to divide by the number of channels in byte format * to get the correct value. All other formats should be fine */ if (format == GST_FORMAT_BYTES && dur != -1) gst_query_set_duration (query, format, dur / self->channels); } else if (res && GST_QUERY_TYPE (query) == GST_QUERY_POSITION) { GstFormat format; gint64 pos; gst_query_parse_position (query, &format, &pos); /* Need to divide by the number of channels in byte format * to get the correct value. All other formats should be fine */ if (format == GST_FORMAT_BYTES && pos != -1) gst_query_set_position (query, format, pos / self->channels); } gst_object_unref (self); return res; }
/* FIXME: * * When we add a new stream (or remove a stream) the duration might * also become invalid again and we need to post a new DURATION * message to notify this fact to the parent. * For now we take the max of all the upstream elements so the simple * cases work at least somewhat. */ static gboolean gst_live_adder_query_duration (GstLiveAdder * adder, GstQuery * query) { GstFormat format; gint64 max; gboolean res; /* parse format */ gst_query_parse_duration (query, &format, NULL); res = gst_live_adder_query_pos_dur (adder, format, FALSE, &max); if (res) { /* and store the max */ gst_query_set_duration (query, format, max); } return res; }
static gboolean gst_spc_dec_src_query (GstPad * pad, GstQuery * query) { GstSpcDec *spc = GST_SPC_DEC (gst_pad_get_parent (pad)); gboolean result = TRUE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: { GstFormat format; gst_query_parse_duration (query, &format, NULL); if (!spc->initialized || format != GST_FORMAT_TIME) { result = FALSE; break; } gst_query_set_duration (query, GST_FORMAT_TIME, gst_spc_duration (spc) + gst_spc_fadeout (spc)); break; } case GST_QUERY_POSITION: { GstFormat format; gst_query_parse_position (query, &format, NULL); if (!spc->initialized || format != GST_FORMAT_TIME) { result = FALSE; break; } gst_query_set_position (query, GST_FORMAT_TIME, (gint64) gst_util_uint64_scale (spc->byte_pos, GST_SECOND, 32000 * 2 * 2)); break; } default: result = gst_pad_query_default (pad, query); break; } gst_object_unref (spc); return result; }
static gboolean gst_deinterleave_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstDeinterleave *self = GST_DEINTERLEAVE (parent); gboolean res; res = gst_pad_query_default (pad, parent, query); if (res && GST_QUERY_TYPE (query) == GST_QUERY_DURATION) { GstFormat format; gint64 dur; gst_query_parse_duration (query, &format, &dur); /* Need to divide by the number of channels in byte format * to get the correct value. All other formats should be fine */ if (format == GST_FORMAT_BYTES && dur != -1) gst_query_set_duration (query, format, dur / GST_AUDIO_INFO_CHANNELS (&self->audio_info)); } else if (res && GST_QUERY_TYPE (query) == GST_QUERY_POSITION) { GstFormat format; gint64 pos; gst_query_parse_position (query, &format, &pos); /* Need to divide by the number of channels in byte format * to get the correct value. All other formats should be fine */ if (format == GST_FORMAT_BYTES && pos != -1) gst_query_set_position (query, format, pos / GST_AUDIO_INFO_CHANNELS (&self->audio_info)); } else if (res && GST_QUERY_TYPE (query) == GST_QUERY_CAPS) { GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); caps = gst_deinterleave_sink_getcaps (pad, parent, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); } return res; }
static gboolean gst_real_audio_demux_src_query (GstPad * pad, GstQuery * query) { GstRealAudioDemux *demux; gboolean ret = FALSE; demux = GST_REAL_AUDIO_DEMUX (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION:{ GstFormat format; gst_query_parse_duration (query, &format, NULL); if (format == GST_FORMAT_TIME && demux->duration > 0) { gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration); ret = TRUE; } else if (format == GST_FORMAT_BYTES && demux->upstream_size > 0) { gst_query_set_duration (query, GST_FORMAT_BYTES, demux->upstream_size - demux->data_offset); ret = TRUE; } break; } case GST_QUERY_SEEKING:{ GstFormat format; gboolean seekable; gst_query_parse_seeking (query, &format, NULL, NULL, NULL); seekable = (format == GST_FORMAT_TIME && demux->seekable); gst_query_set_seeking (query, format, seekable, 0, (format == GST_FORMAT_TIME) ? demux->duration : -1); ret = TRUE; break; } default: ret = gst_pad_query_default (pad, query); break; } gst_object_unref (demux); return ret; }
static gboolean gst_gme_dec_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstGmeDec *gme = GST_GME_DEC (parent); gboolean result = TRUE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: { GstFormat format; gst_query_parse_duration (query, &format, NULL); if (!gme->initialized || format != GST_FORMAT_TIME || gme->total_duration == GST_CLOCK_TIME_NONE) { result = FALSE; break; } gst_query_set_duration (query, GST_FORMAT_TIME, gme->total_duration); break; } case GST_QUERY_POSITION: { GstFormat format; gst_query_parse_position (query, &format, NULL); if (!gme->initialized || format != GST_FORMAT_TIME) { result = FALSE; break; } gst_query_set_position (query, GST_FORMAT_TIME, (gint64) gme_tell (gme->player) * GST_MSECOND); break; } default: result = gst_pad_query_default (pad, parent, query); break; } return result; }
static gboolean gst_cdxa_parse_src_query (GstPad * srcpad, GstQuery * query) { GstCDXAParse *cdxa = GST_CDXA_PARSE (gst_pad_get_parent (srcpad)); gboolean res = FALSE; GST_DEBUG_OBJECT (cdxa, "Handling %s query", gst_query_type_get_name (GST_QUERY_TYPE (query))); res = gst_pad_query_default (srcpad, query); if (res) { GstFormat format; gint64 val; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: gst_query_parse_duration (query, &format, &val); if (format == GST_FORMAT_BYTES) { val = gst_cdxa_parse_convert_sink_to_src_offset (cdxa, val); gst_query_set_duration (query, format, val); } break; case GST_QUERY_POSITION: gst_query_parse_position (query, &format, &val); if (format == GST_FORMAT_BYTES) { val = gst_cdxa_parse_convert_sink_to_src_offset (cdxa, val); gst_query_set_position (query, format, val); } break; default: break; } } gst_object_unref (cdxa); return res; }
static gboolean gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query) { gboolean res = TRUE; GstTSDemux *demux; demux = GST_TS_DEMUX (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: { GstFormat format; gst_query_parse_duration (query, &format, NULL); /* can only get position in time */ if (format != GST_FORMAT_TIME) goto wrong_format; gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration); break; } default: res = gst_pad_query_default (pad, query); break; } done: gst_object_unref (demux); return res; wrong_format: { GST_DEBUG_OBJECT (demux, "only query duration on TIME is supported"); res = FALSE; goto done; } }
static gboolean gst_ss_demux_handle_src_query (GstPad * pad, GstQuery * query) { gboolean res = FALSE; GstSSDemux *ssdemux = GST_SS_DEMUX (gst_pad_get_parent (pad)); GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query)); // TODO: need to add other query types as well switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION:{ GstFormat fmt; gst_query_parse_duration (query, &fmt, NULL); if (fmt == GST_FORMAT_TIME) { gint64 duration = -1; duration = gst_util_uint64_scale (GST_SSM_PARSE_GET_DURATION(ssdemux->parser), GST_SECOND, GST_SSM_PARSE_GET_TIMESCALE(ssdemux->parser)); if (duration > 0) { gst_query_set_duration (query, GST_FORMAT_TIME, duration); res = TRUE; } } break; } default: res = gst_pad_query_default (pad, query); break; } gst_object_unref (ssdemux); return res; }
static gboolean gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query) { gint64 min; gboolean res; GstFormat format; GstIterator *it; gboolean done; /* parse format */ gst_query_parse_duration (query, &format, NULL); min = -1; res = TRUE; done = FALSE; /* Take minimum of all durations */ it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self)); while (!done) { GstIteratorResult ires; GValue item = { 0 }; ires = gst_iterator_next (it, &item); switch (ires) { case GST_ITERATOR_DONE: done = TRUE; break; case GST_ITERATOR_OK: { GstPad *pad = g_value_get_object (&item); gint64 duration; /* ask sink peer for duration */ res &= gst_pad_peer_query_duration (pad, format, &duration); /* take min from all valid return values */ if (res) { /* valid unknown length, stop searching */ if (duration == -1) { min = duration; done = TRUE; } /* else see if smaller than current min */ else if (duration < min) min = duration; } g_value_reset (&item); break; } case GST_ITERATOR_RESYNC: min = -1; res = TRUE; gst_iterator_resync (it); break; default: res = FALSE; done = TRUE; break; } g_value_unset (&item); } gst_iterator_free (it); if (res) { /* and store the min */ GST_DEBUG_OBJECT (self, "Total duration in format %s: %" GST_TIME_FORMAT, gst_format_get_name (format), GST_TIME_ARGS (min)); gst_query_set_duration (query, format, min); } return res; }
static gboolean gst_interleave_src_query_duration (GstInterleave * self, GstQuery * query) { gint64 max; gboolean res; GstFormat format; GstIterator *it; gboolean done; /* parse format */ gst_query_parse_duration (query, &format, NULL); max = -1; res = TRUE; done = FALSE; /* Take maximum of all durations */ it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self)); while (!done) { GstIteratorResult ires; GValue item = { 0, }; ires = gst_iterator_next (it, &item); switch (ires) { case GST_ITERATOR_DONE: done = TRUE; break; case GST_ITERATOR_OK: { GstPad *pad = GST_PAD_CAST (g_value_dup_object (&item)); gint64 duration; /* ask sink peer for duration */ res &= gst_pad_peer_query_duration (pad, format, &duration); /* take max from all valid return values */ if (res) { /* valid unknown length, stop searching */ if (duration == -1) { max = duration; done = TRUE; } /* else see if bigger than current max */ else if (duration > max) max = duration; } gst_object_unref (pad); g_value_unset (&item); break; } case GST_ITERATOR_RESYNC: max = -1; res = TRUE; gst_iterator_resync (it); break; default: res = FALSE; done = TRUE; break; } } gst_iterator_free (it); if (res) { /* If in bytes format we have to multiply with the number of channels * to get the correct results. All other formats should be fine */ if (format == GST_FORMAT_BYTES && max != -1) max *= self->channels; /* and store the max */ GST_DEBUG_OBJECT (self, "Total duration in format %s: %" GST_TIME_FORMAT, gst_format_get_name (format), GST_TIME_ARGS (max)); gst_query_set_duration (query, format, max); } return res; }
static gboolean gst_au_parse_src_query (GstPad * pad, GstQuery * query) { GstAuParse *auparse; gboolean ret = FALSE; auparse = GST_AU_PARSE (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION:{ GstFormat bformat = GST_FORMAT_BYTES; GstFormat format; gint64 len, val; gst_query_parse_duration (query, &format, NULL); if (!gst_pad_query_peer_duration (auparse->sinkpad, &bformat, &len)) { GST_DEBUG_OBJECT (auparse, "failed to query upstream length"); break; } GST_OBJECT_LOCK (auparse); len -= auparse->offset; GST_OBJECT_UNLOCK (auparse); ret = gst_au_parse_src_convert (auparse, bformat, len, format, &val); if (ret) { gst_query_set_duration (query, format, val); } break; } case GST_QUERY_POSITION:{ GstFormat bformat = GST_FORMAT_BYTES; GstFormat format; gint64 pos, val; gst_query_parse_position (query, &format, NULL); if (!gst_pad_query_peer_position (auparse->sinkpad, &bformat, &pos)) { GST_DEBUG_OBJECT (auparse, "failed to query upstream position"); break; } GST_OBJECT_LOCK (auparse); pos -= auparse->offset; GST_OBJECT_UNLOCK (auparse); ret = gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, pos, format, &val); if (ret) { gst_query_set_position (query, format, val); } break; } case GST_QUERY_SEEKING:{ GstFormat format; gst_query_parse_seeking (query, &format, NULL, NULL, NULL); /* FIXME: query duration in 'format' gst_query_set_seeking (query, format, TRUE, 0, duration); */ gst_query_set_seeking (query, format, TRUE, 0, GST_CLOCK_TIME_NONE); ret = TRUE; break; } default: ret = gst_pad_query_default (pad, query); break; } gst_object_unref (auparse); return ret; }
static gboolean gst_speex_enc_src_query (GstPad * pad, GstQuery * query) { gboolean res = TRUE; GstSpeexEnc *enc; enc = GST_SPEEX_ENC (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat fmt, req_fmt; gint64 pos, val; gst_query_parse_position (query, &req_fmt, NULL); if ((res = gst_pad_query_peer_position (enc->sinkpad, &req_fmt, &val))) { gst_query_set_position (query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if (!(res = gst_pad_query_peer_position (enc->sinkpad, &fmt, &pos))) break; if ((res = gst_pad_query_peer_convert (enc->sinkpad, fmt, pos, &req_fmt, &val))) gst_query_set_position (query, req_fmt, val); break; } case GST_QUERY_DURATION: { GstFormat fmt, req_fmt; gint64 dur, val; gst_query_parse_duration (query, &req_fmt, NULL); if ((res = gst_pad_query_peer_duration (enc->sinkpad, &req_fmt, &val))) { gst_query_set_duration (query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if (!(res = gst_pad_query_peer_duration (enc->sinkpad, &fmt, &dur))) break; if ((res = gst_pad_query_peer_convert (enc->sinkpad, fmt, dur, &req_fmt, &val))) { gst_query_set_duration (query, req_fmt, val); } break; } case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); if (!(res = gst_speex_enc_convert_src (pad, src_fmt, src_val, &dest_fmt, &dest_val))) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } case GST_QUERY_LATENCY: { gboolean live; GstClockTime min_latency, max_latency; gint64 latency; if ((res = gst_pad_peer_query (enc->sinkpad, query))) { gst_query_parse_latency (query, &live, &min_latency, &max_latency); GST_LOG_OBJECT (pad, "Upstream latency: %" GST_PTR_FORMAT, query); latency = gst_speex_enc_get_latency (enc); /* add our latency */ min_latency += latency; if (max_latency != -1) max_latency += latency; gst_query_set_latency (query, live, min_latency, max_latency); GST_LOG_OBJECT (pad, "Adjusted latency: %" GST_PTR_FORMAT, query); } break; } default: res = gst_pad_peer_query (enc->sinkpad, query); break; } error: gst_object_unref (enc); return res; }
static gboolean gst_cdaudio_query (GstElement * element, GstQuery * query) { GstCDAudio *cdaudio; gboolean res = TRUE; gulong micros; gdouble seconds; cdaudio = GST_CDAUDIO (element); GST_LOG_OBJECT (element, "handling %s query", gst_query_type_get_name (GST_QUERY_TYPE (query))); /* take new snapshot every 1000 miliseconds */ seconds = g_timer_elapsed (cdaudio->timer, µs); if (micros > 1000 || seconds > 1) { cd_stat (cdaudio->cd_desc, &cdaudio->info); g_timer_start (cdaudio->timer); } switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: { GstFormat dest_format; gint64 dest_val; gst_query_parse_duration (query, &dest_format, NULL); switch (dest_format) { case GST_FORMAT_TIME: dest_val = (cdaudio->info.disc_length.minutes * 60 + cdaudio->info.disc_length.seconds) * GST_SECOND; break; default: { if (dest_format == track_format) { dest_val = cdaudio->info.disc_total_tracks; } else { res = FALSE; } break; } } if (res) gst_query_set_duration (query, dest_format, dest_val); break; } case GST_QUERY_POSITION: { GstFormat dest_format; gint64 dest_val; gst_query_parse_position (query, &dest_format, NULL); switch (dest_format) { case GST_FORMAT_TIME: dest_val = (cdaudio->info.disc_time.minutes * 60 + cdaudio->info.disc_time.seconds) * GST_SECOND; break; default: { if (dest_format == track_format) { dest_val = cdaudio->info.disc_current_track; } else { res = FALSE; } break; } } if (res) gst_query_set_position (query, dest_format, dest_val); break; } default: res = FALSE; break; } return res; }
static gboolean gst_raw_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstRawParse *rp = GST_RAW_PARSE (parent); gboolean ret = FALSE; GST_DEBUG ("src_query %s", gst_query_type_get_name (GST_QUERY_TYPE (query))); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat format; gint64 time, value; GST_LOG ("query position"); gst_query_parse_position (query, &format, NULL); time = rp->segment.position; ret = gst_raw_parse_convert (rp, GST_FORMAT_TIME, time, format, &value); gst_query_set_position (query, format, value); break; } case GST_QUERY_DURATION:{ gint64 duration; GstFormat format; GstQuery *bquery; GST_LOG ("query duration"); ret = gst_pad_peer_query (rp->sinkpad, query); if (ret) goto done; gst_query_parse_duration (query, &format, NULL); /* We only handle TIME and DEFAULT format */ if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT) goto error; bquery = gst_query_new_duration (GST_FORMAT_BYTES); ret = gst_pad_peer_query (rp->sinkpad, bquery); if (!ret) { gst_query_unref (bquery); goto error; } gst_query_parse_duration (bquery, NULL, &duration); gst_query_unref (bquery); ret = gst_raw_parse_convert (rp, GST_FORMAT_BYTES, duration, format, &duration); if (ret) gst_query_set_duration (query, format, duration); break; } case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; GST_LOG ("query convert"); gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); ret = gst_raw_parse_convert (rp, src_fmt, src_val, dest_fmt, &dest_val); if (!ret) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } case GST_QUERY_SEEKING:{ GstFormat fmt; ret = TRUE; gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); if (fmt != GST_FORMAT_TIME && fmt != GST_FORMAT_DEFAULT && fmt != GST_FORMAT_BYTES) { gst_query_set_seeking (query, fmt, FALSE, -1, -1); } else if (rp->mode == GST_PAD_MODE_PUSH) { GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES); gboolean seekable; seekable = gst_pad_peer_query (rp->sinkpad, peerquery); if (seekable) gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL); gst_query_unref (peerquery); gst_query_set_seeking (query, fmt, seekable, seekable ? 0 : -1, -1); } else { gst_query_set_seeking (query, fmt, TRUE, 0, -1); } break; } default: /* else forward upstream */ ret = gst_pad_query_default (rp->sinkpad, parent, query); break; } done: return ret; /* ERRORS */ error: { GST_DEBUG_OBJECT (rp, "query failed"); goto done; } }
gint main (gint argc, gchar * argv[]) { GstElement *pipeline, *filesrc, *decodebin; GstStateChangeReturn res; GstIterator *it; GstBus *bus; GValue data = { 0, }; gst_init (&argc, &argv); pipeline = gst_pipeline_new ("pipeline"); filesrc = gst_element_factory_make ("filesrc", "filesrc"); g_assert (filesrc); decodebin = gst_element_factory_make ("decodebin", "decodebin"); g_assert (decodebin); gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, NULL); gst_element_link (filesrc, decodebin); if (argc < 2) { g_print ("usage: %s <filenames>\n", argv[0]); exit (-1); } if (!g_str_has_prefix (argv[1], "file://")) { g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); } else { g_object_set (G_OBJECT (filesrc), "location", argv[1] + 7, NULL); } /* we've got to connect fakesinks to newly decoded pads to make sure * buffers have actually been flowing over those pads and caps have * been set on them. decodebin might insert internal queues and * without fakesinks it's pot-luck what caps we get from the pad, because * it depends on whether the queues have started pushing buffers yet or not. * With fakesinks we make sure that the pipeline doesn't go to PAUSED state * before each fakesink has a buffer queued. */ g_signal_connect (decodebin, "new-decoded-pad", G_CALLBACK (new_decoded_pad_cb), pipeline); bus = gst_element_get_bus (pipeline); g_print ("pause..\n"); res = gst_element_set_state (pipeline, GST_STATE_PAUSED); if (res == GST_STATE_CHANGE_FAILURE) { show_error ("Could not go to PAUSED state", bus); exit (-1); } g_print ("waiting..\n"); res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); if (res != GST_STATE_CHANGE_SUCCESS) { show_error ("Failed to complete state change to PAUSED", bus); exit (-1); } g_print ("stats..\n"); it = gst_element_iterate_src_pads (decodebin); while (gst_iterator_next (it, &data) == GST_ITERATOR_OK) { GstPad *pad = g_value_get_object (&data); GstCaps *caps; gchar *str; GstQuery *query; g_print ("stream %s:\n", GST_OBJECT_NAME (pad)); caps = gst_pad_query_caps (pad, NULL); str = gst_caps_to_string (caps); g_print (" caps: %s\n", str); g_free (str); gst_caps_unref (caps); query = gst_query_new_duration (GST_FORMAT_TIME); if (gst_pad_query (pad, query)) { gint64 duration; gst_query_parse_duration (query, NULL, &duration); g_print (" duration: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (duration)); } gst_query_unref (query); g_value_reset (&data); } g_value_unset (&data); gst_iterator_free (it); return 0; }
static gboolean gst_image_freeze_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstImageFreeze *self = GST_IMAGE_FREEZE (parent); gboolean ret = FALSE; GST_LOG_OBJECT (pad, "Handling query of type '%s'", gst_query_type_get_name (GST_QUERY_TYPE (query))); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONVERT: { GstFormat src_format, dest_format; gint64 src_value, dest_value; gst_query_parse_convert (query, &src_format, &src_value, &dest_format, &dest_value); ret = gst_image_freeze_convert (self, src_format, src_value, &dest_format, &dest_value); if (ret) gst_query_set_convert (query, src_format, src_value, dest_format, dest_value); break; } case GST_QUERY_POSITION: { GstFormat format; gint64 position; gst_query_parse_position (query, &format, NULL); switch (format) { case GST_FORMAT_DEFAULT: { g_mutex_lock (&self->lock); position = self->offset; g_mutex_unlock (&self->lock); ret = TRUE; break; } case GST_FORMAT_TIME: { g_mutex_lock (&self->lock); position = self->segment.position; g_mutex_unlock (&self->lock); ret = TRUE; break; } default: break; } if (ret) { gst_query_set_position (query, format, position); GST_DEBUG_OBJECT (pad, "Returning position %" G_GINT64_FORMAT " in format %s", position, gst_format_get_name (format)); } else { GST_DEBUG_OBJECT (pad, "Position query failed"); } break; } case GST_QUERY_DURATION: { GstFormat format; gint64 duration; gst_query_parse_duration (query, &format, NULL); switch (format) { case GST_FORMAT_TIME: { g_mutex_lock (&self->lock); duration = self->segment.stop; g_mutex_unlock (&self->lock); ret = TRUE; break; } case GST_FORMAT_DEFAULT: { g_mutex_lock (&self->lock); duration = self->segment.stop; if (duration != -1) duration = gst_util_uint64_scale (duration, self->fps_n, GST_SECOND * self->fps_d); g_mutex_unlock (&self->lock); ret = TRUE; break; } default: break; } if (ret) { gst_query_set_duration (query, format, duration); GST_DEBUG_OBJECT (pad, "Returning duration %" G_GINT64_FORMAT " in format %s", duration, gst_format_get_name (format)); } else { GST_DEBUG_OBJECT (pad, "Duration query failed"); } break; } case GST_QUERY_SEEKING: { GstFormat format; gboolean seekable; gst_query_parse_seeking (query, &format, NULL, NULL, NULL); seekable = (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT); gst_query_set_seeking (query, format, seekable, (seekable ? 0 : -1), -1); ret = TRUE; break; } default: ret = FALSE; break; } return ret; }
static gboolean gst_musepackdec_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (parent); GstFormat format; gboolean res = FALSE; gint samplerate; samplerate = g_atomic_int_get (&musepackdec->rate); if (samplerate == 0) goto done; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION:{ gint64 cur, cur_off; gst_query_parse_position (query, &format, NULL); GST_OBJECT_LOCK (musepackdec); cur_off = musepackdec->segment.position; GST_OBJECT_UNLOCK (musepackdec); if (format == GST_FORMAT_TIME) { cur = gst_util_uint64_scale_int (cur_off, GST_SECOND, samplerate); gst_query_set_position (query, GST_FORMAT_TIME, cur); res = TRUE; } else if (format == GST_FORMAT_DEFAULT) { gst_query_set_position (query, GST_FORMAT_DEFAULT, cur_off); res = TRUE; } break; } case GST_QUERY_DURATION:{ gint64 len, len_off; gst_query_parse_duration (query, &format, NULL); GST_OBJECT_LOCK (musepackdec); len_off = musepackdec->segment.duration; GST_OBJECT_UNLOCK (musepackdec); if (format == GST_FORMAT_TIME) { len = gst_util_uint64_scale_int (len_off, GST_SECOND, samplerate); gst_query_set_duration (query, GST_FORMAT_TIME, len); res = TRUE; } else if (format == GST_FORMAT_DEFAULT) { gst_query_set_duration (query, GST_FORMAT_DEFAULT, len_off); res = TRUE; } break; } case GST_QUERY_SEEKING:{ GstFormat fmt; gint64 len, len_off; res = TRUE; gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); GST_OBJECT_LOCK (musepackdec); len_off = musepackdec->segment.duration; GST_OBJECT_UNLOCK (musepackdec); if (fmt == GST_FORMAT_TIME) { len = gst_util_uint64_scale_int (len_off, GST_SECOND, samplerate); gst_query_set_seeking (query, fmt, TRUE, 0, len); } else if (fmt == GST_FORMAT_DEFAULT) { gst_query_set_seeking (query, fmt, TRUE, 0, len_off); } else { gst_query_set_seeking (query, fmt, FALSE, -1, -1); } break; } default: res = gst_pad_query_default (pad, parent, query); break; } done: return res; }
static gboolean gst_real_audio_demux_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstRealAudioDemux *demux; gboolean ret = FALSE; demux = GST_REAL_AUDIO_DEMUX (parent); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION:{ GstFormat format; gst_query_parse_duration (query, &format, NULL); if (format == GST_FORMAT_TIME && demux->duration > 0) { gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration); ret = TRUE; } else if (format == GST_FORMAT_BYTES && demux->upstream_size > 0) { gst_query_set_duration (query, GST_FORMAT_BYTES, demux->upstream_size - demux->data_offset); ret = TRUE; } break; } case GST_QUERY_SEEKING:{ GstFormat format; gboolean seekable; gst_query_parse_seeking (query, &format, NULL, NULL, NULL); seekable = (format == GST_FORMAT_TIME && demux->seekable); gst_query_set_seeking (query, format, seekable, 0, (format == GST_FORMAT_TIME) ? demux->duration : -1); ret = TRUE; break; } case GST_QUERY_SEGMENT: { GstFormat format; gint64 start, stop; format = demux->segment.format; start = gst_segment_to_stream_time (&demux->segment, format, demux->segment.start); if ((stop = demux->segment.stop) == -1) stop = demux->segment.duration; else stop = gst_segment_to_stream_time (&demux->segment, format, stop); gst_query_set_segment (query, demux->segment.rate, format, start, stop); ret = TRUE; break; } default: ret = gst_pad_query_default (pad, parent, query); break; } return ret; }
/* FIXME, the duration query should reflect how long you will produce * data, that is the amount of stream time until you will emit EOS. * * For synchronized mixing this is always the max of all the durations * of upstream since we emit EOS when all of them finished. * * We don't do synchronized mixing so this really depends on where the * streams where punched in and what their relative offsets are against * eachother which we can get from the first timestamps we see. * * When we add a new stream (or remove a stream) the duration might * also become invalid again and we need to post a new DURATION * message to notify this fact to the parent. * For now we take the max of all the upstream elements so the simple * cases work at least somewhat. */ static gboolean gst_adder_query_duration (GstAdder * adder, GstQuery * query) { gint64 max; gboolean res; GstFormat format; GstIterator *it; gboolean done; /* parse format */ gst_query_parse_duration (query, &format, NULL); max = -1; res = TRUE; done = FALSE; it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder)); while (!done) { GstIteratorResult ires; gpointer item; ires = gst_iterator_next (it, &item); switch (ires) { case GST_ITERATOR_DONE: done = TRUE; break; case GST_ITERATOR_OK: { GstPad *pad = GST_PAD_CAST (item); gint64 duration; /* ask sink peer for duration */ res &= gst_pad_query_peer_duration (pad, &format, &duration); /* take max from all valid return values */ if (res) { /* valid unknown length, stop searching */ if (duration == -1) { max = duration; done = TRUE; } /* else see if bigger than current max */ else if (duration > max) max = duration; } gst_object_unref (pad); break; } case GST_ITERATOR_RESYNC: max = -1; res = TRUE; gst_iterator_resync (it); break; default: res = FALSE; done = TRUE; break; } } gst_iterator_free (it); if (res) { /* and store the max */ GST_DEBUG_OBJECT (adder, "Total duration in format %s: %" GST_TIME_FORMAT, gst_format_get_name (format), GST_TIME_ARGS (max)); gst_query_set_duration (query, format, max); } return res; }
static gboolean gst_wavpack_parse_src_query (GstPad * pad, GstQuery * query) { GstWavpackParse *parse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad)); GstFormat format; gboolean ret = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION:{ gint64 cur; guint rate; GST_OBJECT_LOCK (parse); cur = parse->segment.last_stop; rate = parse->samplerate; GST_OBJECT_UNLOCK (parse); if (rate == 0) { GST_DEBUG_OBJECT (parse, "haven't read header yet"); break; } gst_query_parse_position (query, &format, NULL); switch (format) { case GST_FORMAT_TIME: cur = gst_util_uint64_scale_int (cur, GST_SECOND, rate); gst_query_set_position (query, GST_FORMAT_TIME, cur); ret = TRUE; break; case GST_FORMAT_DEFAULT: gst_query_set_position (query, GST_FORMAT_DEFAULT, cur); ret = TRUE; break; default: GST_DEBUG_OBJECT (parse, "cannot handle position query in " "%s format. Forwarding upstream.", gst_format_get_name (format)); ret = gst_pad_query_default (pad, query); break; } break; } case GST_QUERY_DURATION:{ gint64 len; guint rate; GST_OBJECT_LOCK (parse); rate = parse->samplerate; len = parse->total_samples; GST_OBJECT_UNLOCK (parse); if (rate == 0) { GST_DEBUG_OBJECT (parse, "haven't read header yet"); break; } gst_query_parse_duration (query, &format, NULL); switch (format) { case GST_FORMAT_TIME: if (len != G_GINT64_CONSTANT (-1)) len = gst_util_uint64_scale_int (len, GST_SECOND, rate); gst_query_set_duration (query, GST_FORMAT_TIME, len); ret = TRUE; break; case GST_FORMAT_DEFAULT: gst_query_set_duration (query, GST_FORMAT_DEFAULT, len); ret = TRUE; break; default: GST_DEBUG_OBJECT (parse, "cannot handle duration query in " "%s format. Forwarding upstream.", gst_format_get_name (format)); ret = gst_pad_query_default (pad, query); break; } break; } case GST_QUERY_SEEKING:{ gst_query_parse_seeking (query, &format, NULL, NULL, NULL); if (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT) { gboolean seekable; gint64 duration = -1; /* only fails if we didn't read the headers yet and can't say * anything about our seeking capabilities */ if (!gst_pad_query_duration (pad, &format, &duration)) break; /* can't seek in streaming mode yet */ GST_OBJECT_LOCK (parse); seekable = (parse->adapter == NULL); GST_OBJECT_UNLOCK (parse); gst_query_set_seeking (query, format, seekable, 0, duration); ret = TRUE; } break; } default:{ ret = gst_pad_query_default (pad, query); break; } } gst_object_unref (parse); return ret; }
static gboolean gst_swfdec_src_query (GstPad * pad, GstQuery * query) { gboolean res = TRUE; GstSwfdec *swfdec; swfdec = GST_SWFDEC (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat format; gint64 value; gst_query_parse_position (query, &format, NULL); switch (format) { case GST_FORMAT_TIME: value = swfdec_render_get_frame_index (swfdec->decoder) * swfdec->interval; gst_query_set_position (query, GST_FORMAT_TIME, value); res = TRUE; default: res = FALSE; break; } break; } case GST_QUERY_DURATION: { GstFormat format; gint64 value; gst_query_parse_duration (query, &format, NULL); switch (format) { case GST_FORMAT_TIME: { int n_frames; int ret; res = FALSE; ret = swfdec_decoder_get_n_frames (swfdec->decoder, &n_frames); if (ret == SWF_OK) { value = n_frames * swfdec->interval; gst_query_set_duration (query, GST_FORMAT_TIME, value); res = TRUE; } break; } default: res = FALSE; break; } break; } default: res = FALSE; break; } gst_object_unref (swfdec); return res; }
static gboolean gst_video_rate_query (GstBaseTransform * trans, GstPadDirection direction, GstQuery * query) { GstVideoRate *videorate = GST_VIDEO_RATE (trans); gboolean res = FALSE; GstPad *otherpad; otherpad = (direction == GST_PAD_SRC) ? GST_BASE_TRANSFORM_SINK_PAD (trans) : GST_BASE_TRANSFORM_SRC_PAD (trans); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_LATENCY: { GstClockTime min, max; gboolean live; guint64 latency; guint64 avg_period; GstPad *peer; GST_OBJECT_LOCK (videorate); avg_period = videorate->average_period_set; GST_OBJECT_UNLOCK (videorate); if (avg_period == 0 && (peer = gst_pad_get_peer (otherpad))) { if ((res = gst_pad_query (peer, query))) { gst_query_parse_latency (query, &live, &min, &max); GST_DEBUG_OBJECT (videorate, "Peer latency: min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max)); if (videorate->from_rate_numerator != 0) { /* add latency. We don't really know since we hold on to the frames * until we get a next frame, which can be anything. We assume * however that this will take from_rate time. */ latency = gst_util_uint64_scale (GST_SECOND, videorate->from_rate_denominator, videorate->from_rate_numerator); } else { /* no input framerate, we don't know */ latency = 0; } GST_DEBUG_OBJECT (videorate, "Our latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); min += latency; if (max != -1) max += latency; GST_DEBUG_OBJECT (videorate, "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; } /* Simple fallthrough if we don't have a latency or not a peer that we * can't ask about its latency yet.. */ } case GST_QUERY_DURATION: { GstFormat format; gint64 duration; gst_query_parse_duration (query, &format, &duration); if (format != GST_FORMAT_TIME) { GST_DEBUG_OBJECT (videorate, "not TIME format"); break; } GST_LOG_OBJECT (videorate, "upstream duration: %" G_GINT64_FORMAT, duration); duration = (gint64) (duration / videorate->rate); GST_LOG_OBJECT (videorate, "our duration: %" G_GINT64_FORMAT, duration); gst_query_set_duration (query, format, duration); res = TRUE; break; } case GST_QUERY_POSITION: { GstFormat dst_format; gint64 dst_value; gst_query_parse_position (query, &dst_format, &dst_value); if (dst_format != GST_FORMAT_TIME) { GST_DEBUG_OBJECT (videorate, "not TIME format"); break; } dst_value = (gint64) (videorate->next_ts / videorate->rate); GST_LOG_OBJECT (videorate, "our position: %" G_GINT64_FORMAT, dst_value); gst_query_set_position (query, dst_format, dst_value); res = TRUE; break; } default: res = GST_BASE_TRANSFORM_CLASS (parent_class)->query (trans, direction, query); break; } return res; }
static gboolean speed_src_query (GstPad * pad, GstQuery * query) { gboolean ret = TRUE; GstSpeed *filter; filter = GST_SPEED (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat format; GstFormat rformat = GST_FORMAT_TIME; gint64 cur; GstFormat conv_format = GST_FORMAT_TIME; /* save requested format */ gst_query_parse_position (query, &format, NULL); /* query peer for current position in time */ gst_query_set_position (query, GST_FORMAT_TIME, -1); if (!gst_pad_query_peer_position (filter->sinkpad, &rformat, &cur)) { GST_LOG_OBJECT (filter, "query on peer pad failed"); goto error; } if (rformat == GST_FORMAT_BYTES) GST_LOG_OBJECT (filter, "peer pad returned current=%" G_GINT64_FORMAT " bytes", cur); else if (rformat == GST_FORMAT_TIME) GST_LOG_OBJECT (filter, "peer pad returned time=%" G_GINT64_FORMAT, cur); /* convert to time format */ if (!gst_speed_convert (pad, rformat, cur, &conv_format, &cur)) { ret = FALSE; break; } /* adjust for speed factor */ cur /= filter->speed; /* convert to time format */ if (!gst_speed_convert (pad, conv_format, cur, &format, &cur)) { ret = FALSE; break; } gst_query_set_position (query, format, cur); GST_LOG_OBJECT (filter, "position query: we return %" G_GUINT64_FORMAT " (format %u)", cur, format); break; } case GST_QUERY_DURATION: { GstFormat format; GstFormat rformat = GST_FORMAT_TIME; gint64 end; GstFormat conv_format = GST_FORMAT_TIME; /* save requested format */ gst_query_parse_duration (query, &format, NULL); /* query peer for total length in time */ gst_query_set_duration (query, GST_FORMAT_TIME, -1); if (!gst_pad_query_peer_duration (filter->sinkpad, &rformat, &end)) { GST_LOG_OBJECT (filter, "query on peer pad failed"); goto error; } if (rformat == GST_FORMAT_BYTES) GST_LOG_OBJECT (filter, "peer pad returned total=%" G_GINT64_FORMAT " bytes", end); else if (rformat == GST_FORMAT_TIME) GST_LOG_OBJECT (filter, "peer pad returned time=%" G_GINT64_FORMAT, end); /* convert to time format */ if (!gst_speed_convert (pad, rformat, end, &conv_format, &end)) { ret = FALSE; break; } /* adjust for speed factor */ end /= filter->speed; /* convert to time format */ if (!gst_speed_convert (pad, conv_format, end, &format, &end)) { ret = FALSE; break; } gst_query_set_duration (query, format, end); GST_LOG_OBJECT (filter, "duration query: we return %" G_GUINT64_FORMAT " (format %u)", end, format); break; } default: ret = FALSE; break; } gst_object_unref (filter); return ret; error: gst_object_unref (filter); GST_DEBUG ("error handling query"); return FALSE; }
static void test_queries (InsanityTest * test) { GstQuery *query = gst_query_new_seeking (GST_FORMAT_TIME); if (gst_element_query (glob_pipeline, query)) { GstFormat fmt; gboolean seekable, known_seekable; gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL); if (glob_media_desc_parser == NULL) { insanity_test_validate_checklist_item (test, "seekable-detection", TRUE, "No media-descriptor file, result not verified against it"); glob_seekable = seekable; } else { known_seekable = media_descriptor_parser_get_seekable (glob_media_desc_parser); insanity_test_validate_checklist_item (test, "seekable-detection", known_seekable == seekable, NULL); glob_seekable = known_seekable; } } else { if (glob_media_desc_parser != NULL) glob_seekable = media_descriptor_parser_get_seekable (glob_media_desc_parser); LOG (test, "%s Does not handle seeking queries (seekable-detection \"SKIP\")", gst_element_factory_get_metadata (gst_element_get_factory (glob_demuxer), GST_ELEMENT_METADATA_LONGNAME)); } gst_query_unref (query); query = gst_query_new_duration (GST_FORMAT_TIME); if (gst_element_query (glob_pipeline, query)) { GstFormat fmt; gchar *validate_msg = NULL; gint64 duration; if (glob_media_desc_parser == NULL) { gst_query_parse_duration (query, &fmt, &duration); validate_msg = g_strdup_printf ("Found duration %" GST_TIME_FORMAT " No media-descriptor file, result not verified against it", GST_TIME_ARGS (duration)); insanity_test_validate_checklist_item (test, "duration-detection", TRUE, validate_msg); g_free (validate_msg); glob_duration = duration; } else { glob_duration = media_descriptor_parser_get_duration (glob_media_desc_parser); gst_query_parse_duration (query, &fmt, &duration); if (glob_duration != duration) { validate_msg = g_strdup_printf ("Found time %" GST_TIME_FORMAT "-> %" GST_TIME_FORMAT, GST_TIME_ARGS (duration), GST_TIME_ARGS (glob_duration)); insanity_test_validate_checklist_item (test, "duration-detection", glob_duration == duration, validate_msg); g_free (validate_msg); } else { insanity_test_validate_checklist_item (test, "duration-detection", TRUE, NULL); } } } else { if (glob_media_desc_parser != NULL) glob_duration = media_descriptor_parser_get_seekable (glob_media_desc_parser); LOG (test, "%s Does not handle duration queries " "(duration-detection \"SKIP\")", gst_element_factory_get_metadata (gst_element_get_factory (glob_demuxer), GST_ELEMENT_METADATA_LONGNAME)); } if (GST_CLOCK_TIME_IS_VALID (glob_duration) && glob_playback_duration > glob_duration) { LOG (test, "playback_duration > media duration, setting it" "to media_duration != 2"); glob_playback_duration = glob_duration / 2; } gst_query_unref (query); next_test (test); }
static gboolean gst_ts_shifter_query (GstElement * element, GstQuery * query) { gboolean ret = TRUE; GstTSShifter *ts = GST_TS_SHIFTER (element); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { gint64 pos = -1; GstFormat format; /* get format */ gst_query_parse_position (query, &format, NULL); switch (format) { case GST_FORMAT_BYTES: pos = ts->cur_bytes; break; default: GST_WARNING_OBJECT (ts, "dropping query in %s format, don't " "know how to handle", gst_format_get_name (format)); ret = FALSE; break; } /* set updated position */ if (ret) gst_query_set_position (query, format, pos); break; } case GST_QUERY_DURATION: { GstFormat format; gst_query_parse_duration (query, &format, NULL); if (format == GST_FORMAT_BYTES) { GST_LOG_OBJECT (ts, "replying duration query with %" G_GUINT64_FORMAT, gst_ts_cache_get_total_bytes_received (ts->cache)); gst_query_set_duration (query, GST_FORMAT_BYTES, gst_ts_cache_get_total_bytes_received (ts->cache)); ret = TRUE; } else { ret = FALSE; } break; } case GST_QUERY_SEEKING: { GstFormat fmt; gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); if (fmt == GST_FORMAT_BYTES) { gst_query_set_seeking (query, fmt, TRUE, 0, -1); ret = TRUE; } else { ret = FALSE; } break; } case GST_QUERY_LATENCY: { gst_query_set_latency (query, FALSE, 0, -1); break; } case GST_QUERY_BUFFERING: { GstFormat format; guint64 bytes_begin, bytes_end; gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL); if (format != GST_FORMAT_BYTES) { ret = FALSE; break; } gst_ts_cache_buffered_range (ts->cache, &bytes_begin, &bytes_end); gst_query_set_buffering_range (query, format, bytes_begin, bytes_end, -1); ret = TRUE; break; } default: ret = FALSE; break; } return ret; }
static gboolean gst_hls_demux_src_query (GstPad * pad, GstQuery * query) { GstHLSDemux *hlsdemux; gboolean ret = FALSE; if (query == NULL) return FALSE; hlsdemux = GST_HLS_DEMUX (gst_pad_get_element_private (pad)); switch (query->type) { case GST_QUERY_DURATION:{ GstClockTime duration = -1; GstFormat fmt; gst_query_parse_duration (query, &fmt, NULL); if (fmt == GST_FORMAT_TIME) { duration = gst_m3u8_client_get_duration (hlsdemux->client); if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) { gst_query_set_duration (query, GST_FORMAT_TIME, duration); ret = TRUE; } } GST_INFO_OBJECT (hlsdemux, "GST_QUERY_DURATION returns %s with duration %" GST_TIME_FORMAT, ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration)); break; } case GST_QUERY_URI: if (hlsdemux->client) { /* FIXME: Do we answer with the variant playlist, with the current * playlist or the the uri of the least downlowaded fragment? */ gst_query_set_uri (query, hlsdemux->client->current->uri); ret = TRUE; } break; case GST_QUERY_SEEKING:{ GstFormat fmt; gint64 stop = -1; gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); GST_INFO_OBJECT (hlsdemux, "Received GST_QUERY_SEEKING with format %d", fmt); if (fmt == GST_FORMAT_TIME) { GstClockTime duration; duration = gst_m3u8_client_get_duration (hlsdemux->client); if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) stop = duration; gst_query_set_seeking (query, fmt, !gst_m3u8_client_is_live (hlsdemux->client), 0, stop); ret = TRUE; GST_INFO_OBJECT (hlsdemux, "GST_QUERY_SEEKING returning with stop : %" GST_TIME_FORMAT, GST_TIME_ARGS (stop)); } break; } default: /* Don't fordward queries upstream because of the special nature of this * "demuxer", which relies on the upstream element only to be fed with the * first playlist */ break; } return ret; }
static gboolean gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query) { gboolean res = TRUE; GstVorbisEnc *vorbisenc; GstPad *peerpad; vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad)); peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat fmt, req_fmt; gint64 pos, val; gst_query_parse_position (query, &req_fmt, NULL); if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) { gst_query_set_position (query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if (!(res = gst_pad_query_position (peerpad, &fmt, &pos))) break; if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) { gst_query_set_position (query, req_fmt, val); } break; } case GST_QUERY_DURATION: { GstFormat fmt, req_fmt; gint64 dur, val; gst_query_parse_duration (query, &req_fmt, NULL); if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) { gst_query_set_duration (query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur))) break; if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) { gst_query_set_duration (query, req_fmt, val); } break; } case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); if (!(res = gst_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt, &dest_val))) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); break; } default: res = gst_pad_query_default (pad, query); break; } error: gst_object_unref (peerpad); gst_object_unref (vorbisenc); return res; }
/* handle queries for location and length in requested format */ static gboolean gst_aiff_parse_pad_query (GstPad * pad, GstQuery * query) { gboolean res = TRUE; GstAiffParse *aiff = GST_AIFF_PARSE (gst_pad_get_parent (pad)); /* only if we know */ if (aiff->state != AIFF_PARSE_DATA) { gst_object_unref (aiff); return FALSE; } switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: { gint64 duration = 0; GstFormat format; gst_query_parse_duration (query, &format, NULL); switch (format) { case GST_FORMAT_TIME:{ if ((res = gst_aiff_parse_calculate_duration (aiff))) { duration = aiff->duration; } break; } default: format = GST_FORMAT_BYTES; duration = aiff->datasize; break; } gst_query_set_duration (query, format, duration); break; } case GST_QUERY_CONVERT: { gint64 srcvalue, dstvalue; GstFormat srcformat, dstformat; gst_query_parse_convert (query, &srcformat, &srcvalue, &dstformat, &dstvalue); res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue, &dstformat, &dstvalue); if (res) gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue); break; } case GST_QUERY_SEEKING:{ GstFormat fmt; gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); if (fmt == GST_FORMAT_TIME) { gboolean seekable = TRUE; if (!gst_aiff_parse_calculate_duration (aiff)) { seekable = FALSE; } gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, aiff->duration); res = TRUE; } break; } default: res = gst_pad_query_default (pad, query); break; } gst_object_unref (aiff); return res; }
static gboolean xing_mp3_encoder_src_query(GstPad * pad, GstQuery * query) { gboolean res = TRUE; XingMp3Encoder *encoder; GstPad *peerpad; encoder = XING_MP3_ENCODER(gst_pad_get_parent(pad)); peerpad = gst_pad_get_peer(GST_PAD(encoder->sinkpad)); switch(GST_QUERY_TYPE(query)) { case GST_QUERY_DURATION: { GstFormat fmt, req_fmt; gint64 dur, val; gst_query_parse_duration(query, &req_fmt, NULL); if((res = gst_pad_query_duration(peerpad, &req_fmt, &val))) { gst_query_set_duration(query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if(!(res = gst_pad_query_duration (peerpad, &fmt, &dur))) { break; } if((res = gst_pad_query_convert(peerpad, fmt, dur, &req_fmt, &val))) { gst_query_set_duration(query, req_fmt, val); } break; } case GST_QUERY_POSITION: { GstFormat fmt, req_fmt; gint64 pos, val; gst_query_parse_position(query, &req_fmt, NULL); if((res = gst_pad_query_position(peerpad, &req_fmt, &val))) { gst_query_set_position (query, req_fmt, val); break; } fmt = GST_FORMAT_TIME; if(!(res = gst_pad_query_position(peerpad, &fmt, &pos))) { break; } if((res = gst_pad_query_convert(peerpad, fmt, pos, &req_fmt, &val))) { gst_query_set_position(query, req_fmt, val); } break; } case GST_QUERY_CONVERT: { GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert(query, &src_fmt, &src_val, &dest_fmt, &dest_val); if(!(res = xing_mp3_encoder_convert_src(pad, src_fmt, src_val, &dest_fmt, &dest_val))) { gst_object_unref(peerpad); gst_object_unref(encoder); } gst_query_set_convert(query, src_fmt, src_val, dest_fmt, dest_val); break; } default: res = gst_pad_query_default(pad, query); break; } return res; }