• Matthew Waters's avatar
    oggdemux: fix a race in push mode when performing the duration seek · cd06dcc0
    Matthew Waters authored and Tim-Philipp Müller's avatar Tim-Philipp Müller committed
    There may be two or more threads involved here however the important
    interaction is the use of ogg->seeK_event_drop_till value that was only
    set in the push-mode seek-event thread and could race with upstream
    sending e.g. and EOS (or data).
    
    Scenario is this:
    1. oggdemux performs a seek to near the end of the file to try and find
       the duration. ogg->push_state is set to PUSH_DURATION.
    2. Seek is picked up by the dedicated seek event thread and sets
       ogg->seek_event_drop_till to the seek event's seqnum.
    3. Most operations are blocked or dropped waiting on the duration to
       be determined and processing continues until a duration is found.
    4. Two branching options for how this ultimately plays out
    4a. The source is too fast and we receive an EOS event which is dropped
        because ogg->push_state == PUSH_DURATION.  In this case everything
        works.
    4b. We hit our 'almost at the end' check in
        gst_ogg_pad_handle_push_mode_state() and attempt to seek back to the
        beginning (or to a user-provided seek).  This seek is marshalled to
        the seek event thread without setting ogg->seek_event_drop_till but
        with change ogg->push_state = PUSH_PLAYING.  If an EOS event or
        e.g. buffers arrive from upstream before the seek event thread has
        picked up the seek event, then the EOS/data is processed as if it
        came as a result of the seek event.  This is the case that fails.
    
    The fix is two-fold:
    1. Preemptively set ogg->seek_event_drop_till when setting the seek
       event so that data and other events can be dropped correctly.
    2. In addition to dropping and EOS events while ogg->push_state ==
       PUSH_DURATION, also drop any EOS events that are received before the
       seek event has been processed by also tracking the seqnum of the seek.
    
    Part-of: <!1291>
    cd06dcc0