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@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);
It does not matter whether we use PAUSED or PLAYING, but we should at least be consistent.
Signed-off-by: Zebediah Figura z.figura12@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) {
This is a fatal error condition for GStreamer, but should not cause errors for DirectShow.
Signed-off-by: Zebediah Figura z.figura12@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. */
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@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)
Signed-off-by: Zebediah Figura z.figura12@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)