basesink: implement percentage position and duration queries

If upstream does not handle them, then implement those ourself.
This commit is contained in:
Stefan Kost 2010-04-15 10:36:52 +03:00
parent c29e34113f
commit c96dec2a06

View file

@ -4512,6 +4512,39 @@ convert_failed:
} }
} }
static gboolean
gst_base_sink_get_duration (GstBaseSink * basesink, GstFormat format,
gint64 * dur, gboolean * upstream)
{
gboolean res = FALSE;
if (basesink->pad_mode == GST_ACTIVATE_PULL) {
GstFormat uformat = GST_FORMAT_BYTES;
gint64 uduration;
/* get the duration in bytes, in pull mode that's all we are sure to
* know. We have to explicitly get this value from upstream instead of
* using our cached value because it might change. Duration caching
* should be done at a higher level. */
res = gst_pad_query_peer_duration (basesink->sinkpad, &uformat, &uduration);
if (res) {
gst_segment_set_duration (&basesink->segment, uformat, uduration);
if (format != uformat) {
/* convert to the requested format */
res = gst_pad_query_convert (basesink->sinkpad, uformat, uduration,
&format, dur);
} else {
*dur = uduration;
}
}
*upstream = FALSE;
} else {
*upstream = TRUE;
}
return res;
}
static gboolean static gboolean
gst_base_sink_query (GstElement * element, GstQuery * query) gst_base_sink_query (GstElement * element, GstQuery * query)
{ {
@ -4539,45 +4572,63 @@ gst_base_sink_query (GstElement * element, GstQuery * query)
/* fallback to peer query */ /* fallback to peer query */
res = gst_pad_peer_query (basesink->sinkpad, query); res = gst_pad_peer_query (basesink->sinkpad, query);
} }
if (!res) {
/* we can handle a few things if upstream failed */
if (format == GST_FORMAT_PERCENT) {
gint64 dur = 0;
GstFormat uformat = GST_FORMAT_TIME;
res = gst_base_sink_get_position (basesink, GST_FORMAT_TIME, &cur,
&upstream);
if (!res && upstream) {
res = gst_pad_query_peer_position (basesink->sinkpad, &uformat,
&cur);
}
if (res) {
res = gst_base_sink_get_duration (basesink, GST_FORMAT_TIME, &dur,
&upstream);
if (!res && upstream) {
res = gst_pad_query_peer_duration (basesink->sinkpad, &uformat,
&dur);
}
}
if (res) {
gint64 pos;
pos = gst_util_uint64_scale (100 * GST_FORMAT_PERCENT_SCALE, cur,
dur);
gst_query_set_position (query, GST_FORMAT_PERCENT, pos);
}
}
}
break; break;
} }
case GST_QUERY_DURATION: case GST_QUERY_DURATION:
{ {
GstFormat format, uformat; gint64 dur = 0;
gint64 duration, uduration; GstFormat format;
gboolean upstream = FALSE;
gst_query_parse_duration (query, &format, NULL); gst_query_parse_duration (query, &format, NULL);
GST_DEBUG_OBJECT (basesink, "duration query in format %s", GST_DEBUG_OBJECT (basesink, "duration query in format %s",
gst_format_get_name (format)); gst_format_get_name (format));
if (basesink->pad_mode == GST_ACTIVATE_PULL) { if ((res =
uformat = GST_FORMAT_BYTES; gst_base_sink_get_duration (basesink, format, &dur, &upstream))) {
gst_query_set_duration (query, format, dur);
/* get the duration in bytes, in pull mode that's all we are sure to } else if (upstream) {
* know. We have to explicitly get this value from upstream instead of /* fallback to peer query */
* using our cached value because it might change. Duration caching
* should be done at a higher level. */
res = gst_pad_query_peer_duration (basesink->sinkpad, &uformat,
&uduration);
if (res) {
gst_segment_set_duration (&basesink->segment, uformat, uduration);
if (format != uformat) {
/* convert to the requested format */
res = gst_pad_query_convert (basesink->sinkpad, uformat, uduration,
&format, &duration);
} else {
duration = uduration;
}
if (res) {
/* set the result */
gst_query_set_duration (query, format, duration);
}
}
} else {
/* in push mode we simply forward upstream */
res = gst_pad_peer_query (basesink->sinkpad, query); res = gst_pad_peer_query (basesink->sinkpad, query);
} }
if (!res) {
/* we can handle a few things if upstream failed */
if (format == GST_FORMAT_PERCENT) {
gst_query_set_duration (query, GST_FORMAT_PERCENT,
GST_FORMAT_PERCENT_MAX);
res = TRUE;
}
}
break; break;
} }
case GST_QUERY_LATENCY: case GST_QUERY_LATENCY: