a/v freeze while flushing audio chain of pipeline in running state (clock and renderer sync related)

Enrique Ocaña González eocanha at igalia.com
Thu Jun 8 10:25:30 UTC 2017


El jueves, 8 de junio de 2017 14:18:51 (CEST) Nitin Mahajan escribió:

> The sequence of operations done on adaptive demux plugin are as follows:
> On audio src pad of demux:
> Flush buffered audio packets:
> - push gst_event_new_flush_start()
> - push gst_event_new_flush_stop(FALSE)
> - push new segment event
> - push buffers with the time stamps corresponding to the current
> presentation time

First of all, sorry if my comment isn't completely related to the problem you 
describe. Feel free to ignore it if it only adds noise to the discussion. I 
think it might be relevant, though.

I'm having a similar problem in our use case: Two appsrcs pushing already 
demuxed buffers (video/x-h264 and audio/mpeg) and the pipeline filled of 
buffers. Then our app receives an update of some of the audio buffers (eg: 
higher/lower quality) and needs to replace the buffers already in the pipeline 
(playbin) in a seamless way (keeping the streamsynchronizer happy and the 
video stream unaware of the replacement in the audio stream).

We do something similar to what you describe:

- We ask the pipeline for the current position (the PTS of the buffer being 
rendered)
- We send flush start and stop (false) events
- Use gst_base_src_new_seamless_segment() to send a new [position, old_stop] 
  segment (to convince appsrc to schedule the new buffers properly)
- Fix the segment emitted by appsrc using a probe, so it's again [position, 
  old_stop] and clear flags (not reset-time).

The new replacement buffers start to fill the audio stream of the pipeline 
again, the faad audio decoder does fine (thanks to the flush), and the audio 
buffers reach the audio sink (GstOMXHdmiAudioSink). So far so good.

Then the problems start. For some reason, audiobasesink doesn't reconfigure 
its audioringbuffer properly. Normally, I have a diff of ~40 between segdone 
(the write position in the audioringbuffer) and readseg (the read position of 
the data that goes to the actual audio device). That matches with segtotal 
(the size of the audioringbuffer). However, after the flushes and new segment 
the diff is ~15000 (clearly wrong, much higher than segtotal). This causes 
gst_audio_ring_buffer_commit() (implemented by default_commit) to wait until 
the diff is again less than segtotal. It waits forever.

This long audio sink wait stalls the audio stream and we start to lose audio.

If you want to know if you're having the same problem as we have, enable these 
logs:

 GST_DEBUG='basesink:TRACE,ringbuffer:TRACE,audiosink:TRACE,\
           audiobasesink:TRACE,audioclock:DEBUG'

and grep for this kind of messages:

 cat /tmp/log.txt | grep default_commit | grep 'diff'

You should see the diff jump (from ~40 to ~15000) like this:

0:00:25.508332021  1277 0x72e0d4f0 DEBUG             ringbuffer 
gstaudioringbuffer.c:1525:default_commit:<audiosinkringbuffer0> pointer at 
1033, write to 1072-1340, diff 39, segtotal 40, segsize 1764, base 0
0:00:25.508480042  1277 0x72e0d4f0 DEBUG             ringbuffer 
gstaudioringbuffer.c:1525:default_commit:<audiosinkringbuffer0> pointer at 
1033, write to 1073-0, diff 40, segtotal 40, segsize 1764, base 0
0:00:25.615070250  1277 0x72e0d4f0 DEBUG             ringbuffer 
gstaudioringbuffer.c:1525:default_commit:<audiosinkringbuffer0> pointer at 
1034, write to 16497-1204, diff 15463, segtotal 40, segsize 1764, base 0
0:00:25.615523479  1277 0x72e0d4f0 DEBUG             ringbuffer 
gstaudioringbuffer.c:1525:default_commit:<audiosinkringbuffer0> pointer at 
1035, write to 16497-1204, diff 15462, segtotal 40, segsize 1764, base 0

I haven't found a solution yet and by now we're just applying a workaround on 
the app side to avoid the need of replacing already buffered audio data.

Cheers.

-- 
Enrique Ocaña González


More information about the gstreamer-devel mailing list