gstbaseparse never resets drain flag
Running GStreamer 1.16.0. I have an issue with some streams in combination with seeking after EOS. Most basic example use case is rewind to start of stream after EOS.
Example app with pipeline below:
#include <gst/gst.h>
int main()
{
gst_init(NULL, NULL);
GstElement *pipe = gst_parse_launch("filesrc location=file.265 ! h265parse ! identity dump=false ! decodebin ! autovideoconvert ! xvimagesink max-lateness=-1 qos=false", NULL);
GstBus *bus = gst_element_get_bus(pipe);
gst_element_set_state(pipe, GST_STATE_PLAYING);
gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS);
g_print("\n");
g_print("loop\n");
g_print("\n");
gst_element_seek_simple(pipe, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, 0);
gst_element_set_state(pipe, GST_STATE_PLAYING);
gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS);
gst_element_set_state(pipe, GST_STATE_NULL);
gst_object_unref(bus);
gst_object_unref(pipe);
return 0;
}
The first buffer after the seek is truncated to a max buffer size of 0x10000. If the NAL does not fit in this buffer it gets handed to decoder incomplete causing visible distortion.
A little bit of debugging got me to gstbaseparse.c:3456
where parse->priv->drain
is set:
/* if we got a short read, inform subclass we are draining leftover
* and no more is to be expected */
if (gst_buffer_get_size (buffer) < min_size) {
GST_LOG_OBJECT (parse, "... but did not get that; marked draining");
parse->priv->drain = TRUE;
}
A little further down I think it exits the function at the block at gstbaseparse.c:3497
:
/* something flushed means something happened,
* and we should bail out of this loop so as not to occupy
* the task thread indefinitely */
if (flushed) {
GST_LOG_OBJECT (parse, "frame finished, breaking loop");
break;
}
basically leaving parse->priv->drain
as it is set.
I seems that all data is consumed in this data path, never running through gstbaseparse.c:3517
:
parse->priv->drain = FALSE;
Where parse->priv->drain
would be reset. So after seek/flush this flag is still present causing the subclass (h265parse at least) to trip over its logic since it thinks it is draining.
I haven't checked if, when or how it recovers - but the rest of the streams basically decodes fine once the distortions have recovered.
I simply tried adding parse->priv->drain = FALSE;
after the subclass is called in gstbaseparse.c:3478
:
ret = gst_base_parse_handle_buffer (parse, buffer, &skip, &flushed);
if (ret != GST_FLOW_OK)
break;
and it fixed the obvious issue I was having. That clearly isn't the correct fix as parse->priv->drain
's value is checked later in that function..
Should this flag be reset in some specific code paths where it is missing - or should it get reset on a flush? It certainly feels like it should not be set on a new segment after it was previously draining.