oggdemux in push mode estimates wrong duration with highly compressed ogg vorbis file
GStreamer Version: 1.23.0 (GIT) and older (tested on 1.16.3 x86_64 and 1.20.5 armv7l, both Linux)
gst-plugins-base 1.23.0 version: 921c93a9
OS: Linux Mint x86_64
Steps:
1, gst-launch-1.0 pushfilesrc location= ./sine-1kHz_OGG-Q5.ogg ! queue ! oggdemux ! vorbisdec ! alsasink
2, observe wrong time printed by gst-launch 04.4 (always the same) instead of 30.0
Findings:
The 04.4 is calculated by file byte size 88572 and bitrate 160000 (20000 B/s) the result is 4.4286 seconds.
If filesrc in pull mode without queue is used, oggdemux responds on duration query correct 30:00 seconds
If pushfilesrc without queue is used it gives 28.6 sec gst-launch-1.0 pushfilesrc location=./sine-1kHz_OGG-Q5.ogg ! oggdemux ! vorbisdec ! alsasink
Workaround fix:
If the same pipeline is run with logs oggdemux:5 and higher the issue is partially fixed to show 28.6 sec.
GST_DEBUG=oggdemux:5 gst-launch-1.0 pushfilesrc location=/home/nayana/Hudba/upnpfail/sine-1kHz_OGG-Q5.ogg ! queue ! oggdemux ! vorbisdec ! alsasink
Its caused by the delay in gst_ogg_demux_chain when printing line
GST_DEBUG_OBJECT (ogg, "Dropping buffer because we have a pending seek");
If we do not enable logs and just add g_usleep(0); before the log line 28.6 sec is returned.
Workaround explained
When there is no delay, EOS is received, we seek to 0 and start playing the track without duration info and its calculated based on idx bitrate from pages.
If the delay is there, we manage to seek back before EOS. Then the buffers are parsed in gst_ogg_pad_handle_push_mode_state and ogg->total_time is being calculated based on parsed information.
Then finally at gst_ogg_pad_src_query in GST_QUERY_DURATION if ogg->total_time was filled, its used for the query response with more correct 28.6. If the ogg->total_time was not filled, estimate is calculated as mentioned above, and 04.4 is returned (based on file size and idx_bitrate value)
Test file, simple sine wave, exact 30 seconds duration: