[PATCH v6 5/5] winegstreamer: Replace source pad interface with GstAppSrc.
Zebediah Figura (she/her)
zfigura at codeweavers.com
Tue Sep 28 17:18:27 CDT 2021
On 9/28/21 03:08, Derek Lesho wrote:
>
> On 9/28/21 07:23, Zebediah Figura (she/her) wrote:
>> On 9/24/21 14:23, Derek Lesho wrote:
>>>
>>> On 9/24/21 12:38, Zebediah Figura wrote:
>>>> On 9/24/21 3:05 AM, Derek Lesho wrote:
>>>>> On 9/21/21 13:02, Zebediah Figura wrote:
>>>>>
>>>>>>
>>>>>>
>>>>>> 1. Rely on the fact that seek-data is sent during a seek, and use it
>>>>>> to effectively invalidate any buffers sent before the seek. Unlike
>>>>>> the
>>>>>> aforementioned problem with validation, this will actually work: at
>>>>>> the time that seek-data is sent appsrc should be flushing, so any
>>>>>> buffers we send before it will be discarded by appsrc, and any
>>>>>> buffers
>>>>>> we send afterward can be discarded by us if they aren't valid.
>>>>>> This is
>>>>>> very fragile, though. There's really no reason for appsrc to send
>>>>>> seek-data for random-access streams in the first place, and this kind
>>>>>> of synchronization is easy to get wrong if I haven't already.
>>>>>
>>>>> This sounds like the best way forward in my opinion, how is it
>>>>> fragile?
>>>>
>>>> It's fragile in general because we're making a lot of assumptions,
>>>> that aren't documented, about when and from which thread gstappsrc
>>>> will send these signals, and what synchronization guarantees it
>>>> applies when doing so.
>>>
>>> My perspective is that if we can get it working, documenting the two
>>> required quirks to the GStreamer project, eventually the problem will
>>> be be cleared up and/or fixed, and we can remove the quirks then.
>>
>> The problem is that we're still going to have to keep those
>> workarounds for a long time. Not to mention that clearly filing a bug
>> is not enough to get the attention of the GStreamer developers.
>>
>> As the maintainer of this code, I don't think I feel very comfortable
>> relying this much on the internals of appsrc, whether as workarounds
>> or not.
>>
>>>
>>>>
>>>>> It seems that if we just ensure that a pushed buffer takes into
>>>>> account
>>>>> the latest seek/need data pair, not much can go wrong.
>>>>>
>>>>
>>>> That's not enough by itself. We can, generally speaking, send a
>>>> buffer after a seek-data/need-data is triggered but before it is
>>>> actually sent.
>>> Before what is sent?
>>
>> Before the seek-data or need-data signal is sent. There is a window
>> there, however short.
>
> I'm not sure exactly what the difference between triggering a signal and
> sending a signal is, but assuming you mean that if seek-data doesn't
> acquire the mutex, it would be possible to push-buffer to not see the
> seek, then send the buffer after seek-data, then yeah, we do need to put
> seek-data and push-buffer in the same mutex to make sure that
> push-buffer is responding to the latest seek/need data callbacks.
>
>>
>>>> This happens in practice with flushes.
>>>>
>>>> In order to get around that, you need the hack I mentioned: assume
>>>> that a flush will be accompanied by a seek-data signal. This is
>>>> especially fragile because there's no reason for appsrc to even be
>>>> sending this signal in the first place (it only really makes sense
>>>> in "seekable" mode), and they could easily decide to not do that.
>>>
>>> I'm not sure I understand, whenever the next buffer app source wants
>>> is not consecutively after the last, seek-data is required (and
>>> sent). What does "assume the flush will be accompanied by a seek-data
>>> signal" mean? The app source client doesn't have any conception of a
>>> flush, just seek-data and need-data, and to fix this problem all we
>>> need to do is add a quite rational check that push_data is responding
>>> to the latest seek/need data pair.
>>
>> Let me try to explain more clearly. At least one race, the one I've
>> been trying to describe, looks like this:
>>
>>
>> read thread main thread
>> -------------------------------------
>> push seek event
>> retrieve data
>> validate offset
>> send flush-start
>> emit seek-data
>> send flush-stop
>> push-buffer
>>
>>
>> At which point appsrc will get the wrong buffer.
>>
>> Solution 1 has us rely on the seek-data signal to effectively wait for
>> the read thread (most likely using the parser mutex) and, in a sense,
>> put a barrier between reads occuring before and after the flush.
>
>
> I mean, yeah, but from the perspective of the interface, all we are
> doing is making sure that buffers that are responding to requests from
> before a seek-data don't get sent, which I really don't think should be
> too controversial. That the seek happens to be caused by a flush
> shouldn't matter, we're putting a barrier between buffers sent for a
> different offset, and the current offset we've gotten from seek-data.
> Honestly, I'm not even sure this is a GStreamer bug, should they really
> have to handle a case where the client responds with an incorrect buffer
> after a seek?
I don't think this is obvious at all. It's certainly not called out in
the documentation. And, moreover, it's a lot of work, and it doesn't
even look like a remotely idiomatic solution. Not to mention that, as
I've said, appsrc really has no reason to send seek-data at all here.
I'm pretty sure that you're correct that putting the whole of
wg_parser_push_data inside a mutex, and the seek-data callback inside
the same mutex, is actually sufficient to fix this race. But that stops
being true if appsrc stops sending seek-data here.
Fundamentally the API contract here is that you don't send old buffers
after a flush stops. DirectShow and GStreamer are both built on that
idea. I believe that Media Foundation does away with it, which is one of
the good things about Media Foundation. appsrc doesn't expose flushes to
us, and it doesn't seem to do a good enough job of taking care of them
itself. Trying to infer when they happen is too fragile for my taste.
More information about the wine-devel
mailing list