[PATCH 1/5] winegstreamer: Flush connected pins directly in SetPositions().
Instead of propagating GStreamer flush events to corresponding DirectShow pins. This is mainly to avoid more callbacks from GStreamer and further separate the Win32 and Unix code. Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/winegstreamer/gstdemux.c | 130 ++++++++++++++++++++++------------ 1 file changed, 86 insertions(+), 44 deletions(-) diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 30f6fbca168..a1be51472ba 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -65,7 +65,7 @@ struct parser /* FIXME: It would be nice to avoid duplicating these with strmbase. * However, synchronization is tricky; we need access to be protected by a * separate lock. */ - bool streaming; + bool streaming, flushing; BOOL initial, ignore_flush; GstElement *container; @@ -111,8 +111,9 @@ struct parser_source GstCaps *caps; SourceSeeking seek; - CONDITION_VARIABLE event_cv, event_empty_cv, flushing_cv, flush_stop_cv; - bool flushing, thread_blocked; + CRITICAL_SECTION flushing_cs; + CONDITION_VARIABLE event_cv, event_empty_cv; + bool flushing; struct parser_event event; HANDLE thread; }; @@ -630,8 +631,6 @@ static gboolean gst_base_src_perform_seek(struct parser *This, GstEvent *event) tevent = gst_event_new_flush_start(); gst_event_set_seqnum(tevent, seqnum); gst_pad_push_event(This->my_src, tevent); - if (This->reader) - IAsyncReader_BeginFlush(This->reader); if (thread) gst_pad_set_active(This->my_src, 1); } @@ -643,8 +642,6 @@ static gboolean gst_base_src_perform_seek(struct parser *This, GstEvent *event) tevent = gst_event_new_flush_stop(TRUE); gst_event_set_seqnum(tevent, seqnum); gst_pad_push_event(This->my_src, tevent); - if (This->reader) - IAsyncReader_EndFlush(This->reader); if (thread) gst_pad_set_active(This->my_src, 1); } @@ -659,25 +656,18 @@ static gboolean event_src(GstPad *pad, GstObject *parent, GstEvent *event) TRACE("filter %p, type \"%s\".\n", This, GST_EVENT_TYPE_NAME(event)); - switch (event->type) { + switch (event->type) + { case GST_EVENT_SEEK: ret = gst_base_src_perform_seek(This, event); break; + case GST_EVENT_FLUSH_START: - EnterCriticalSection(&This->filter.filter_cs); - if (This->reader) - IAsyncReader_BeginFlush(This->reader); - LeaveCriticalSection(&This->filter.filter_cs); - break; case GST_EVENT_FLUSH_STOP: - EnterCriticalSection(&This->filter.filter_cs); - if (This->reader) - IAsyncReader_EndFlush(This->reader); - LeaveCriticalSection(&This->filter.filter_cs); - break; case GST_EVENT_QOS: case GST_EVENT_RECONFIGURE: break; + default: WARN("Ignoring \"%s\" event.\n", GST_EVENT_TYPE_NAME(event)); ret = FALSE; @@ -757,19 +747,11 @@ static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event) } if (pin->pin.pin.peer) { - IPin_BeginFlush(pin->pin.pin.peer); - EnterCriticalSection(&filter->cs); pin->flushing = true; - WakeConditionVariable(&pin->event_cv); WakeConditionVariable(&pin->event_empty_cv); - /* Wait for the thread to pause itself, to ensure that no stale - * samples are sent. */ - while (!pin->thread_blocked) - SleepConditionVariableCS(&pin->flushing_cv, &filter->cs, INFINITE); - /* And flush out any buffered event. */ switch (pin->event.type) { case PARSER_EVENT_NONE: @@ -797,9 +779,6 @@ static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event) EnterCriticalSection(&filter->cs); pin->flushing = false; LeaveCriticalSection(&filter->cs); - WakeConditionVariable(&pin->flush_stop_cv); - - IPin_EndFlush(pin->pin.pin.peer); } break; @@ -1058,32 +1037,31 @@ static DWORD CALLBACK stream_thread(void *arg) { struct parser_event event; + EnterCriticalSection(&pin->flushing_cs); EnterCriticalSection(&filter->cs); - while (filter->streaming && !pin->flushing && pin->event.type == PARSER_EVENT_NONE) + while (filter->streaming && !filter->flushing && pin->event.type == PARSER_EVENT_NONE) SleepConditionVariableCS(&pin->event_cv, &filter->cs, INFINITE); - if (pin->flushing) + if (filter->flushing) { - TRACE("Filter is flushing; pausing thread.\n"); - pin->thread_blocked = true; - WakeConditionVariable(&pin->flushing_cv); - do - SleepConditionVariableCS(&pin->flush_stop_cv, &filter->cs, INFINITE); - while (pin->flushing); - pin->thread_blocked = false; - TRACE("Filter is no longer flushing; resuming thread.\n"); + LeaveCriticalSection(&filter->cs); + LeaveCriticalSection(&pin->flushing_cs); + TRACE("Filter is flushing.\n"); + continue; } if (!filter->streaming) { LeaveCriticalSection(&filter->cs); + LeaveCriticalSection(&pin->flushing_cs); break; } if (!pin->event.type) { LeaveCriticalSection(&filter->cs); + LeaveCriticalSection(&pin->flushing_cs); continue; } @@ -1128,6 +1106,8 @@ static DWORD CALLBACK stream_thread(void *arg) case PARSER_EVENT_NONE: assert(0); } + + LeaveCriticalSection(&pin->flushing_cs); } TRACE("Streaming stopped; exiting.\n"); @@ -2154,7 +2134,10 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface, { GstSeekType current_type = GST_SEEK_TYPE_SET, stop_type = GST_SEEK_TYPE_SET; struct parser_source *pin = impl_from_IMediaSeeking(iface); + struct parser *filter = impl_from_strmbase_filter(pin->pin.pin.filter); GstSeekFlags flags = 0; + HRESULT hr = S_OK; + int i; TRACE("pin %p, current %s, current_flags %#x, stop %s, stop_flags %#x.\n", pin, current ? debugstr_time(*current) : "<null>", current_flags, @@ -2162,9 +2145,40 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface, mark_wine_thread(); - SourceSeekingImpl_SetPositions(iface, current, current_flags, stop, stop_flags); if (pin->pin.pin.filter->state == State_Stopped) + { + SourceSeekingImpl_SetPositions(iface, current, current_flags, stop, stop_flags); return S_OK; + } + + if (!(current_flags & AM_SEEKING_NoFlush)) + { + EnterCriticalSection(&filter->cs); + filter->flushing = true; + LeaveCriticalSection(&filter->cs); + + for (i = 0; i < filter->source_count; ++i) + { + if (filter->sources[i]->pin.pin.peer) + { + WakeConditionVariable(&pin->event_cv); + IPin_BeginFlush(filter->sources[i]->pin.pin.peer); + } + } + + if (filter->reader) + IAsyncReader_BeginFlush(filter->reader); + } + + /* Acquire the flushing locks. This blocks the streaming threads, and + * ensures the seek is serialized between flushes. */ + for (i = 0; i < filter->source_count; ++i) + { + if (filter->sources[i]->pin.pin.peer) + EnterCriticalSection(&pin->flushing_cs); + } + + SourceSeekingImpl_SetPositions(iface, current, current_flags, stop, stop_flags); if (current_flags & AM_SEEKING_SeekToKeyFrame) flags |= GST_SEEK_FLAG_KEY_UNIT; @@ -2183,9 +2197,33 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface, { ERR("Failed to seek (current %s, stop %s).\n", debugstr_time(pin->seek.llCurrent), debugstr_time(pin->seek.llStop)); - return E_FAIL; + hr = E_FAIL; } - return S_OK; + + if (!(current_flags & AM_SEEKING_NoFlush)) + { + EnterCriticalSection(&filter->cs); + filter->flushing = false; + LeaveCriticalSection(&filter->cs); + + for (i = 0; i < filter->source_count; ++i) + { + if (filter->sources[i]->pin.pin.peer) + IPin_EndFlush(filter->sources[i]->pin.pin.peer); + } + + if (filter->reader) + IAsyncReader_EndFlush(filter->reader); + } + + /* Release the flushing locks. */ + for (i = filter->source_count - 1; i >= 0; --i) + { + if (filter->sources[i]->pin.pin.peer) + LeaveCriticalSection(&pin->flushing_cs); + } + + return hr; } static const IMediaSeekingVtbl GST_Seeking_Vtbl = @@ -2398,6 +2436,9 @@ static void free_source_pin(struct parser_source *pin) CloseHandle(pin->eos_event); gst_segment_free(pin->segment); + pin->flushing_cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&pin->flushing_cs); + strmbase_seeking_cleanup(&pin->seek); strmbase_source_cleanup(&pin->pin); heap_free(pin); @@ -2435,10 +2476,11 @@ static struct parser_source *create_pin(struct parser *filter, const WCHAR *name GST_ChangeCurrent, GST_ChangeRate); InitializeConditionVariable(&pin->event_cv); InitializeConditionVariable(&pin->event_empty_cv); - InitializeConditionVariable(&pin->flushing_cv); - InitializeConditionVariable(&pin->flush_stop_cv); BaseFilterImpl_IncrementPinVersion(&filter->filter); + InitializeCriticalSection(&pin->flushing_cs); + pin->flushing_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": pin.flushing_cs"); + sprintf(pad_name, "qz_sink_%u", filter->source_count); pin->my_sink = gst_pad_new(pad_name, GST_PAD_SINK); gst_pad_set_element_private(pin->my_sink, pin); -- 2.30.0
It does not matter whether we use PAUSED or PLAYING, but we should at least be consistent. Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/winegstreamer/gstdemux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index a1be51472ba..7efe4f90ca8 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1876,7 +1876,7 @@ static BOOL decodebin_parser_init_gst(struct parser *filter) return FALSE; } - gst_element_set_state(filter->container, GST_STATE_PLAYING); + gst_element_set_state(filter->container, GST_STATE_PAUSED); ret = gst_element_get_state(filter->container, NULL, NULL, -1); if (ret == GST_STATE_CHANGE_FAILURE) { @@ -2777,7 +2777,7 @@ static BOOL avi_splitter_init_gst(struct parser *filter) return FALSE; } - gst_element_set_state(filter->container, GST_STATE_PLAYING); + gst_element_set_state(filter->container, GST_STATE_PAUSED); ret = gst_element_get_state(filter->container, NULL, NULL, -1); if (ret == GST_STATE_CHANGE_FAILURE) { -- 2.30.0
This is a fatal error condition for GStreamer, but should not cause errors for DirectShow. Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/winegstreamer/gstdemux.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 7efe4f90ca8..d532d4b35bb 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -878,18 +878,12 @@ static GstFlowReturn got_data_sink(GstPad *pad, GstObject *parent, GstBuffer *bu TRACE("pad %p, pin %p, buffer %p.\n", pad, pin, buffer); - if (filter->initial) + if (filter->initial || !pin->pin.pin.peer) { gst_buffer_unref(buffer); return GST_FLOW_OK; } - if (!pin->pin.pin.peer) - { - gst_buffer_unref(buffer); - return GST_FLOW_NOT_LINKED; - } - stream_event.type = PARSER_EVENT_BUFFER; stream_event.u.buffer = buffer; /* Transfer our reference to the buffer to the thread. */ -- 2.30.0
This noticeably improves stream startup time. The process of typefinding and negotiation takes about 70 ms for a simple test file on one machine, and this is currently done twice. This patch replaces the second instance with a simple seek, which takes less than 10 ms. Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/winegstreamer/gstdemux.c | 194 ++++++---------------------------- 1 file changed, 32 insertions(+), 162 deletions(-) diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index d532d4b35bb..e7a4740b566 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -67,7 +67,6 @@ struct parser * separate lock. */ bool streaming, flushing; - BOOL initial, ignore_flush; GstElement *container; GstPad *my_src, *their_sink; GstBus *bus; @@ -682,9 +681,9 @@ static GstFlowReturn queue_stream_event(struct parser_source *pin, const struct struct parser *filter = impl_from_strmbase_filter(pin->pin.pin.filter); EnterCriticalSection(&filter->cs); - while (filter->streaming && !pin->flushing && pin->event.type != PARSER_EVENT_NONE) + while (!pin->flushing && pin->event.type != PARSER_EVENT_NONE) SleepConditionVariableCS(&pin->event_empty_cv, &filter->cs, INFINITE); - if (!filter->streaming || pin->flushing) + if (pin->flushing) { LeaveCriticalSection(&filter->cs); TRACE("Filter is flushing; discarding event.\n"); @@ -734,17 +733,6 @@ static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event) break; case GST_EVENT_FLUSH_START: - if (impl_from_strmbase_filter(pin->pin.pin.filter)->ignore_flush) { - /* gst-plugins-base prior to 1.7 contains a bug which causes - * our sink pins to receive a flush-start event when the - * decodebin changes from PAUSED to READY (including - * PLAYING->PAUSED->READY), but no matching flush-stop event is - * sent. See <gst-plugins-base.git:60bad4815db966a8e4). Here we - * unset the flushing flag to avoid the problem. */ - TRACE("Working around gst <1.7 bug, ignoring FLUSH_START\n"); - GST_PAD_UNSET_FLUSHING (pad); - break; - } if (pin->pin.pin.peer) { EnterCriticalSection(&filter->cs); @@ -872,13 +860,12 @@ static DWORD CALLBACK push_data(LPVOID iface) static GstFlowReturn got_data_sink(GstPad *pad, GstObject *parent, GstBuffer *buffer) { struct parser_source *pin = gst_pad_get_element_private(pad); - struct parser *filter = impl_from_strmbase_filter(pin->pin.pin.filter); struct parser_event stream_event; GstFlowReturn ret; TRACE("pad %p, pin %p, buffer %p.\n", pad, pin, buffer); - if (filter->initial || !pin->pin.pin.peer) + if (!pin->pin.pin.peer) { gst_buffer_unref(buffer); return GST_FLOW_OK; @@ -1143,30 +1130,6 @@ static GstFlowReturn request_buffer_src(GstPad *pad, GstObject *parent, guint64 return GST_FLOW_OK; } -static DWORD CALLBACK push_data_init(LPVOID iface) -{ - struct parser *This = iface; - DWORD64 ofs = 0; - - TRACE("Starting..\n"); - for (;;) { - GstBuffer *buf; - GstFlowReturn ret = request_buffer_src(This->my_src, NULL, ofs, 4096, &buf); - if (ret < 0) { - ERR("Obtaining buffer returned: %i\n", ret); - break; - } - ret = gst_pad_push(This->my_src, buf); - ofs += 4096; - if (ret) - TRACE("Sending returned: %i\n", ret); - if (ret < 0) - break; - } - TRACE("Stopping..\n"); - return 0; -} - static void removed_decoded_pad(GstElement *bin, GstPad *pad, gpointer user) { struct parser *filter = user; @@ -1344,39 +1307,12 @@ out: static void existing_new_pad(GstElement *bin, GstPad *pad, gpointer user) { struct parser *This = user; - unsigned int i; - int ret; TRACE("%p %p %p\n", This, bin, pad); if (gst_pad_is_linked(pad)) return; - /* Still holding our own lock */ - if (This->initial) { - init_new_decoded_pad(bin, pad, This); - return; - } - - for (i = 0; i < This->source_count; ++i) - { - struct parser_source *pin = This->sources[i]; - if (!pin->their_src) { - gst_segment_init(pin->segment, GST_FORMAT_TIME); - - if (pin->post_sink) - ret = gst_pad_link(pad, pin->post_sink); - else - ret = gst_pad_link(pad, pin->my_sink); - - if (ret >= 0) { - pin->their_src = pad; - gst_object_ref(pin->their_src); - TRACE("Relinked\n"); - return; - } - } - } init_new_decoded_pad(bin, pad, This); } @@ -1428,23 +1364,18 @@ static gboolean activate_push(GstPad *pad, gboolean activate) EnterCriticalSection(&This->filter.filter_cs); if (!activate) { TRACE("Deactivating\n"); - if (!This->initial) - IAsyncReader_BeginFlush(This->reader); + IAsyncReader_BeginFlush(This->reader); if (This->push_thread) { WaitForSingleObject(This->push_thread, -1); CloseHandle(This->push_thread); This->push_thread = NULL; } - if (!This->initial) - IAsyncReader_EndFlush(This->reader); + IAsyncReader_EndFlush(This->reader); if (This->filter.state == State_Stopped) This->nextofs = This->start; } else if (!This->push_thread) { TRACE("Activating\n"); - if (This->initial) - This->push_thread = CreateThread(NULL, 0, push_data_init, This, 0, NULL); - else - This->push_thread = CreateThread(NULL, 0, push_data, This, 0, NULL); + This->push_thread = CreateThread(NULL, 0, push_data, This, 0, NULL); } LeaveCriticalSection(&This->filter.filter_cs); return TRUE; @@ -1557,10 +1488,8 @@ static HRESULT GST_Connect(struct parser *This, IPin *pConnectPin) This->start = This->nextofs = This->nextpullofs = This->stop = 0; - This->initial = TRUE; if (!This->init_gst(This)) return E_FAIL; - This->initial = FALSE; This->nextofs = This->nextpullofs = 0; return S_OK; @@ -1650,8 +1579,8 @@ static void parser_destroy(struct strmbase_filter *iface) static HRESULT parser_init_stream(struct strmbase_filter *iface) { struct parser *filter = impl_from_strmbase_filter(iface); + GstSeekType stop_type = GST_SEEK_TYPE_NONE; const SourceSeeking *seeking; - GstStateChangeReturn ret; unsigned int i; if (!filter->container) @@ -1661,6 +1590,17 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface) filter->streaming = true; LeaveCriticalSection(&filter->cs); + /* DirectShow retains the old seek positions, but resets to them every time + * it transitions from stopped -> paused. */ + + seeking = &filter->sources[0]->seek; + if (seeking->llStop && seeking->llStop != seeking->llDuration) + stop_type = GST_SEEK_TYPE_SET; + gst_pad_push_event(filter->sources[0]->my_sink, gst_event_new_seek( + seeking->dRate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, seeking->llCurrent * 100, + stop_type, seeking->llStop * 100)); + for (i = 0; i < filter->source_count; ++i) { HRESULT hr; @@ -1674,44 +1614,12 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface) filter->sources[i]->thread = CreateThread(NULL, 0, stream_thread, filter->sources[i], 0, NULL); } - if (filter->no_more_pads_event) - ResetEvent(filter->no_more_pads_event); - - if ((ret = gst_element_set_state(filter->container, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) - { - ERR("Failed to pause stream.\n"); - return E_FAIL; - } - - /* Make sure that all of our pads are connected before returning, lest we - * e.g. try to seek and fail. */ - if (filter->no_more_pads_event) - WaitForSingleObject(filter->no_more_pads_event, INFINITE); - - seeking = &filter->sources[0]->seek; - - /* GStreamer can't seek while stopped, and it resets position to the - * beginning of the stream every time it is stopped. */ - if (seeking->llCurrent) - { - GstSeekType stop_type = GST_SEEK_TYPE_NONE; - - if (seeking->llStop && seeking->llStop != seeking->llDuration) - stop_type = GST_SEEK_TYPE_SET; - - gst_pad_push_event(filter->sources[0]->my_sink, gst_event_new_seek( - seeking->dRate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, - GST_SEEK_TYPE_SET, seeking->llCurrent * 100, - stop_type, seeking->llStop * 100)); - } - return S_OK; } static HRESULT parser_cleanup_stream(struct strmbase_filter *iface) { struct parser *filter = impl_from_strmbase_filter(iface); - GstStateChangeReturn ret; unsigned int i; if (!filter->container) @@ -1729,17 +1637,7 @@ static HRESULT parser_cleanup_stream(struct strmbase_filter *iface) continue; WakeConditionVariable(&pin->event_cv); - WakeConditionVariable(&pin->event_empty_cv); - } - - filter->ignore_flush = TRUE; - if ((ret = gst_element_set_state(filter->container, GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) - { - ERR("Failed to pause stream.\n"); - return E_FAIL; } - gst_element_get_state(filter->container, NULL, NULL, GST_CLOCK_TIME_NONE); - filter->ignore_flush = FALSE; for (i = 0; i < filter->source_count; ++i) { @@ -1758,33 +1656,12 @@ static HRESULT parser_cleanup_stream(struct strmbase_filter *iface) return S_OK; } -static HRESULT parser_wait_state(struct strmbase_filter *iface, DWORD timeout) -{ - struct parser *filter = impl_from_strmbase_filter(iface); - GstStateChangeReturn ret; - - if (!filter->container) - return S_OK; - - ret = gst_element_get_state(filter->container, NULL, NULL, - timeout == INFINITE ? GST_CLOCK_TIME_NONE : timeout * 1000000); - if (ret == GST_STATE_CHANGE_FAILURE) - { - ERR("Failed to get state.\n"); - return E_FAIL; - } - else if (ret == GST_STATE_CHANGE_ASYNC) - return VFW_S_STATE_INTERMEDIATE; - return S_OK; -} - static const struct strmbase_filter_ops filter_ops = { .filter_get_pin = parser_get_pin, .filter_destroy = parser_destroy, .filter_init_stream = parser_init_stream, .filter_cleanup_stream = parser_cleanup_stream, - .filter_wait_state = parser_wait_state, }; static inline struct parser *impl_from_strmbase_sink(struct strmbase_sink *iface) @@ -1895,11 +1772,6 @@ static BOOL decodebin_parser_init_gst(struct parser *filter) return FALSE; } - filter->ignore_flush = TRUE; - gst_element_set_state(filter->container, GST_STATE_READY); - gst_element_get_state(filter->container, NULL, NULL, -1); - filter->ignore_flush = FALSE; - return TRUE; } @@ -2396,6 +2268,10 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, buffer_size = format->nAvgBytesPerSec; } + gst_pad_push_event(pin->my_sink, gst_event_new_reconfigure()); + /* We do need to drop any buffers that might have been sent with the old + * caps, but this will be handled in parser_init_stream(). */ + props->cBuffers = max(props->cBuffers, 1); props->cbBuffer = max(props->cbBuffer, buffer_size); props->cbAlign = max(props->cbAlign, 1); @@ -2495,6 +2371,16 @@ static HRESULT GST_RemoveOutputPins(struct parser *This) if (!This->container) return S_OK; + + /* Unblock all of our streams. */ + EnterCriticalSection(&This->cs); + for (i = 0; i < This->source_count; ++i) + { + This->sources[i]->flushing = true; + WakeConditionVariable(&This->sources[i]->event_empty_cv); + } + LeaveCriticalSection(&This->cs); + gst_element_set_state(This->container, GST_STATE_NULL); gst_pad_unlink(This->my_src, This->their_sink); gst_object_unref(This->my_src); @@ -2671,11 +2557,6 @@ static BOOL wave_parser_init_gst(struct parser *filter) if (WaitForMultipleObjects(2, events, FALSE, INFINITE)) return FALSE; - filter->ignore_flush = TRUE; - gst_element_set_state(filter->container, GST_STATE_READY); - gst_element_get_state(filter->container, NULL, NULL, -1); - filter->ignore_flush = FALSE; - return TRUE; } @@ -2796,11 +2677,6 @@ static BOOL avi_splitter_init_gst(struct parser *filter) return FALSE; } - filter->ignore_flush = TRUE; - gst_element_set_state(filter->container, GST_STATE_READY); - gst_element_get_state(filter->container, NULL, NULL, -1); - filter->ignore_flush = FALSE; - return TRUE; } @@ -2930,11 +2806,6 @@ static BOOL mpeg_splitter_init_gst(struct parser *filter) if (WaitForMultipleObjects(2, events, FALSE, INFINITE)) return FALSE; - filter->ignore_flush = TRUE; - gst_element_set_state(filter->container, GST_STATE_READY); - gst_element_get_state(filter->container, NULL, NULL, -1); - filter->ignore_flush = FALSE; - return TRUE; } @@ -2981,7 +2852,6 @@ static const struct strmbase_filter_ops mpeg_splitter_ops = .filter_destroy = parser_destroy, .filter_init_stream = parser_init_stream, .filter_cleanup_stream = parser_cleanup_stream, - .filter_wait_state = parser_wait_state, }; HRESULT mpeg_splitter_create(IUnknown *outer, IUnknown **out) -- 2.30.0
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com> --- dlls/winegstreamer/gstdemux.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index e7a4740b566..58d8e0e2248 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1014,14 +1014,14 @@ static DWORD CALLBACK stream_thread(void *arg) TRACE("Starting streaming thread for pin %p.\n", pin); - for (;;) + while (filter->streaming) { struct parser_event event; EnterCriticalSection(&pin->flushing_cs); EnterCriticalSection(&filter->cs); - while (filter->streaming && !filter->flushing && pin->event.type == PARSER_EVENT_NONE) + while (!filter->flushing && pin->event.type == PARSER_EVENT_NONE) SleepConditionVariableCS(&pin->event_cv, &filter->cs, INFINITE); if (filter->flushing) @@ -1032,13 +1032,6 @@ static DWORD CALLBACK stream_thread(void *arg) continue; } - if (!filter->streaming) - { - LeaveCriticalSection(&filter->cs); - LeaveCriticalSection(&pin->flushing_cs); - break; - } - if (!pin->event.type) { LeaveCriticalSection(&filter->cs); @@ -1586,8 +1579,9 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface) if (!filter->container) return S_OK; - EnterCriticalSection(&filter->cs); filter->streaming = true; + EnterCriticalSection(&filter->cs); + filter->flushing = false; LeaveCriticalSection(&filter->cs); /* DirectShow retains the old seek positions, but resets to them every time @@ -1625,8 +1619,9 @@ static HRESULT parser_cleanup_stream(struct strmbase_filter *iface) if (!filter->container) return S_OK; - EnterCriticalSection(&filter->cs); filter->streaming = false; + EnterCriticalSection(&filter->cs); + filter->flushing = true; LeaveCriticalSection(&filter->cs); for (i = 0; i < filter->source_count; ++i) @@ -1870,6 +1865,7 @@ static void parser_init_common(struct parser *object) object->error_event = CreateEventW(NULL, TRUE, FALSE, NULL); InitializeCriticalSection(&object->cs); object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": parser.cs"); + object->flushing = true; } HRESULT decodebin_parser_create(IUnknown *outer, IUnknown **out) -- 2.30.0
participants (1)
-
Zebediah Figura