diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 288d127b23b..2f37d97378d 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -80,7 +80,7 @@ void wg_parser_stream_get_preferred_format(struct wg_parser_stream *stream, stru void wg_parser_stream_enable(struct wg_parser_stream *stream, const struct wg_format *format); void wg_parser_stream_disable(struct wg_parser_stream *stream); -void wg_parser_stream_get_event(struct wg_parser_stream *stream, struct wg_parser_event *event); +bool wg_parser_stream_get_event(struct wg_parser_stream *stream, struct wg_parser_event *event); bool wg_parser_stream_copy_buffer(struct wg_parser_stream *stream, void *data, uint32_t offset, uint32_t size); void wg_parser_stream_release_buffer(struct wg_parser_stream *stream); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 13db07c6edb..e9e347b0c65 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -172,7 +172,7 @@ void wg_parser_stream_disable(struct wg_parser_stream *stream) __wine_unix_call(unix_handle, unix_wg_parser_stream_disable, stream); } -void wg_parser_stream_get_event(struct wg_parser_stream *stream, struct wg_parser_event *event) +bool wg_parser_stream_get_event(struct wg_parser_stream *stream, struct wg_parser_event *event) { struct wg_parser_stream_get_event_params params = { @@ -180,7 +180,7 @@ void wg_parser_stream_get_event(struct wg_parser_stream *stream, struct wg_parse .event = event, }; - __wine_unix_call(unix_handle, unix_wg_parser_stream_get_event, ¶ms); + return !__wine_unix_call(unix_handle, unix_wg_parser_stream_get_event, ¶ms); } bool wg_parser_stream_copy_buffer(struct wg_parser_stream *stream, diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 694497da259..92cb27dc5dc 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -532,33 +532,15 @@ static void wait_on_sample(struct media_stream *stream, IUnknown *token) TRACE("%p, %p\n", stream, token); - if (stream->eos) + if (wg_parser_stream_get_event(stream->wg_stream, &event)) { - IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEError, &GUID_NULL, MF_E_END_OF_STREAM, &empty_var); - return; + send_buffer(stream, &event, token); } - - for (;;) + else { - wg_parser_stream_get_event(stream->wg_stream, &event); - - TRACE("Got event of type %#x.\n", event.type); - - switch (event.type) - { - case WG_PARSER_EVENT_BUFFER: - send_buffer(stream, &event, token); - return; - - case WG_PARSER_EVENT_EOS: - stream->eos = TRUE; - IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEEndOfStream, &GUID_NULL, S_OK, &empty_var); - dispatch_end_of_presentation(stream->parent_source); - return; - - case WG_PARSER_EVENT_NONE: - assert(0); - } + stream->eos = TRUE; + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEEndOfStream, &GUID_NULL, S_OK, &empty_var); + dispatch_end_of_presentation(stream->parent_source); } } diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 628758b838b..9b0fa4acb93 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -833,25 +833,19 @@ static DWORD CALLBACK stream_thread(void *arg) continue; } - wg_parser_stream_get_event(pin->wg_stream, &event); + if (wg_parser_stream_get_event(pin->wg_stream, &event)) + { + send_buffer(pin, &event); + } + else + { + TRACE("Got EOS.\n"); + IPin_EndOfStream(pin->pin.pin.peer); + pin->eos = true; + } TRACE("Got event of type %#x.\n", event.type); - switch (event.type) - { - case WG_PARSER_EVENT_BUFFER: - send_buffer(pin, &event); - break; - - case WG_PARSER_EVENT_EOS: - IPin_EndOfStream(pin->pin.pin.peer); - pin->eos = true; - break; - - case WG_PARSER_EVENT_NONE: - assert(0); - } - LeaveCriticalSection(&pin->flushing_cs); } diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 1ef80991fb4..9d75e94cb6a 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -107,7 +107,6 @@ enum wg_parser_event_type { WG_PARSER_EVENT_NONE = 0, WG_PARSER_EVENT_BUFFER, - WG_PARSER_EVENT_EOS, }; struct wg_parser_event diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 61120a72da8..3cdeeeb5374 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -259,19 +259,20 @@ static NTSTATUS wg_parser_stream_get_event(void *args) pthread_mutex_lock(&parser->mutex); - while (stream->event.type == WG_PARSER_EVENT_NONE) + while (!stream->eos && stream->event.type == WG_PARSER_EVENT_NONE) pthread_cond_wait(&stream->event_cond, &parser->mutex); - *params->event = stream->event; - - if (stream->event.type != WG_PARSER_EVENT_BUFFER) + /* Note that we can both have a buffer and stream->eos, in which case we + * must return the buffer. */ + if (stream->event.type != WG_PARSER_EVENT_NONE) { - stream->event.type = WG_PARSER_EVENT_NONE; - pthread_cond_signal(&stream->event_empty_cond); + *params->event = stream->event; + pthread_mutex_unlock(&parser->mutex); + return S_OK; } - pthread_mutex_unlock(&parser->mutex); - return S_OK; + pthread_mutex_unlock(&parser->mutex); + return S_FALSE; } static NTSTATUS wg_parser_stream_copy_buffer(void *args) @@ -434,16 +435,15 @@ static GstFlowReturn queue_stream_event(struct wg_parser_stream *stream, GST_DEBUG("Filter is flushing; discarding event."); return GST_FLOW_FLUSHING; } - if (buffer) + + assert(GST_IS_BUFFER(buffer)); + if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ)) { - assert(GST_IS_BUFFER(buffer)); - if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ)) - { - pthread_mutex_unlock(&parser->mutex); - GST_ERROR("Failed to map buffer.\n"); - return GST_FLOW_ERROR; - } + pthread_mutex_unlock(&parser->mutex); + GST_ERROR("Failed to map buffer.\n"); + return GST_FLOW_ERROR; } + stream->event = *event; stream->buffer = buffer; pthread_mutex_unlock(&parser->mutex); @@ -479,20 +479,13 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) break; case GST_EVENT_EOS: + pthread_mutex_lock(&parser->mutex); + stream->eos = true; + pthread_mutex_unlock(&parser->mutex); if (stream->enabled) - { - struct wg_parser_event stream_event; - - stream_event.type = WG_PARSER_EVENT_EOS; - queue_stream_event(stream, &stream_event, NULL); - } + pthread_cond_signal(&stream->event_cond); else - { - pthread_mutex_lock(&parser->mutex); - stream->eos = true; - pthread_mutex_unlock(&parser->mutex); pthread_cond_signal(&parser->init_cond); - } break; case GST_EVENT_FLUSH_START: @@ -524,12 +517,13 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) if (reset_time) gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED); + pthread_mutex_lock(&parser->mutex); + + stream->eos = false; if (stream->enabled) - { - pthread_mutex_lock(&parser->mutex); stream->flushing = false; - pthread_mutex_unlock(&parser->mutex); - } + + pthread_mutex_unlock(&parser->mutex); break; } diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index 6d2b9edbd09..96de6f2a3ba 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -1826,6 +1826,10 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream, IWMReaderCallbackAdvanced *callback_advanced = stream->reader->callback_advanced; struct wg_parser_stream *wg_stream = stream->wg_stream; struct wg_parser_event event; + DWORD size, capacity; + INSSBuffer *sample; + HRESULT hr; + BYTE *data; if (stream->selection == WMT_OFF) return NS_E_INVALID_REQUEST; @@ -1835,104 +1839,88 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream, for (;;) { - wg_parser_stream_get_event(wg_stream, &event); - - TRACE("Got event of type %#x for %s stream %p.\n", event.type, - get_major_type_string(stream->format.major_type), stream); - - switch (event.type) + if (!wg_parser_stream_get_event(wg_stream, &event)) { - case WG_PARSER_EVENT_BUFFER: + stream->eos = true; + TRACE("End of stream.\n"); + return NS_E_NO_MORE_SAMPLES; + } + + TRACE("Got buffer for '%s' stream %p.\n", get_major_type_string(stream->format.major_type), stream); + + if (callback_advanced && stream->read_compressed && stream->allocate_stream) + { + if (FAILED(hr = IWMReaderCallbackAdvanced_AllocateForStream(callback_advanced, + stream->index + 1, event.u.buffer.size, &sample, NULL))) { - DWORD size, capacity; - INSSBuffer *sample; - HRESULT hr; - BYTE *data; - - if (callback_advanced && stream->read_compressed && stream->allocate_stream) - { - if (FAILED(hr = IWMReaderCallbackAdvanced_AllocateForStream(callback_advanced, - stream->index + 1, event.u.buffer.size, &sample, NULL))) - { - ERR("Failed to allocate stream sample of %u bytes, hr %#lx.\n", event.u.buffer.size, hr); - wg_parser_stream_release_buffer(wg_stream); - return hr; - } - } - else if (callback_advanced && !stream->read_compressed && stream->allocate_output) - { - if (FAILED(hr = IWMReaderCallbackAdvanced_AllocateForOutput(callback_advanced, - stream->index, event.u.buffer.size, &sample, NULL))) - { - ERR("Failed to allocate output sample of %u bytes, hr %#lx.\n", event.u.buffer.size, hr); - wg_parser_stream_release_buffer(wg_stream); - return hr; - } - } - else - { - struct buffer *object; - - /* FIXME: Should these be pooled? */ - if (!(object = calloc(1, offsetof(struct buffer, data[event.u.buffer.size])))) - { - wg_parser_stream_release_buffer(wg_stream); - return E_OUTOFMEMORY; - } - - object->INSSBuffer_iface.lpVtbl = &buffer_vtbl; - object->refcount = 1; - object->capacity = event.u.buffer.size; - - TRACE("Created buffer %p.\n", object); - sample = &object->INSSBuffer_iface; - } - - if (FAILED(hr = INSSBuffer_GetBufferAndLength(sample, &data, &size))) - ERR("Failed to get data pointer, hr %#lx.\n", hr); - if (FAILED(hr = INSSBuffer_GetMaxLength(sample, &capacity))) - ERR("Failed to get capacity, hr %#lx.\n", hr); - if (event.u.buffer.size > capacity) - ERR("Returned capacity %lu is less than requested capacity %u.\n", - capacity, event.u.buffer.size); - - if (!wg_parser_stream_copy_buffer(wg_stream, data, 0, event.u.buffer.size)) - { - /* The GStreamer pin has been flushed. */ - INSSBuffer_Release(sample); - break; - } - - if (FAILED(hr = INSSBuffer_SetLength(sample, event.u.buffer.size))) - ERR("Failed to set size %u, hr %#lx.\n", event.u.buffer.size, hr); - + ERR("Failed to allocate stream sample of %u bytes, hr %#lx.\n", event.u.buffer.size, hr); wg_parser_stream_release_buffer(wg_stream); + return hr; + } + } + else if (callback_advanced && !stream->read_compressed && stream->allocate_output) + { + if (FAILED(hr = IWMReaderCallbackAdvanced_AllocateForOutput(callback_advanced, + stream->index, event.u.buffer.size, &sample, NULL))) + { + ERR("Failed to allocate output sample of %u bytes, hr %#lx.\n", event.u.buffer.size, hr); + wg_parser_stream_release_buffer(wg_stream); + return hr; + } + } + else + { + struct buffer *object; - if (!event.u.buffer.has_pts) - FIXME("Missing PTS.\n"); - if (!event.u.buffer.has_duration) - FIXME("Missing duration.\n"); - - *pts = event.u.buffer.pts; - *duration = event.u.buffer.duration; - *flags = 0; - if (event.u.buffer.discontinuity) - *flags |= WM_SF_DISCONTINUITY; - if (!event.u.buffer.delta) - *flags |= WM_SF_CLEANPOINT; - - *ret_sample = sample; - return S_OK; + /* FIXME: Should these be pooled? */ + if (!(object = calloc(1, offsetof(struct buffer, data[event.u.buffer.size])))) + { + wg_parser_stream_release_buffer(wg_stream); + return E_OUTOFMEMORY; } - case WG_PARSER_EVENT_EOS: - stream->eos = true; - TRACE("End of stream.\n"); - return NS_E_NO_MORE_SAMPLES; + object->INSSBuffer_iface.lpVtbl = &buffer_vtbl; + object->refcount = 1; + object->capacity = event.u.buffer.size; - case WG_PARSER_EVENT_NONE: - assert(0); + TRACE("Created buffer %p.\n", object); + sample = &object->INSSBuffer_iface; } + + if (FAILED(hr = INSSBuffer_GetBufferAndLength(sample, &data, &size))) + ERR("Failed to get data pointer, hr %#lx.\n", hr); + if (FAILED(hr = INSSBuffer_GetMaxLength(sample, &capacity))) + ERR("Failed to get capacity, hr %#lx.\n", hr); + if (event.u.buffer.size > capacity) + ERR("Returned capacity %lu is less than requested capacity %u.\n", capacity, event.u.buffer.size); + + if (!wg_parser_stream_copy_buffer(wg_stream, data, 0, event.u.buffer.size)) + { + /* The GStreamer pin has been flushed. */ + INSSBuffer_Release(sample); + continue; + } + + if (FAILED(hr = INSSBuffer_SetLength(sample, event.u.buffer.size))) + ERR("Failed to set size %u, hr %#lx.\n", event.u.buffer.size, hr); + + wg_parser_stream_release_buffer(wg_stream); + + if (!event.u.buffer.has_pts) + FIXME("Missing PTS.\n"); + if (!event.u.buffer.has_duration) + FIXME("Missing duration.\n"); + + *pts = event.u.buffer.pts; + *duration = event.u.buffer.duration; + *flags = 0; + if (event.u.buffer.discontinuity) + *flags |= WM_SF_DISCONTINUITY; + if (!event.u.buffer.delta) + *flags |= WM_SF_CLEANPOINT; + + *ret_sample = sample; + return S_OK; } }