Fix a couple of potential leaks, avoid silently eating errors and simplify the presentation and stream descriptor initialization code.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 41 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 63147d64b32..4501e60fa65 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -191,7 +191,7 @@ static const IUnknownVtbl source_async_command_vtbl = source_async_command_Release, };
-static HRESULT source_create_async_op(enum source_async_op op, struct source_async_command **ret) +static HRESULT source_create_async_op(enum source_async_op op, IUnknown **out) { struct source_async_command *command;
@@ -201,8 +201,7 @@ static HRESULT source_create_async_op(enum source_async_op op, struct source_asy command->IUnknown_iface.lpVtbl = &source_async_command_vtbl; command->op = op;
- *ret = command; - + *out = &command->IUnknown_iface; return S_OK; }
@@ -293,15 +292,16 @@ static void flush_token_queue(struct media_stream *stream, BOOL send) { if (send) { + IUnknown *op; HRESULT hr; - struct source_async_command *command; - if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_REQUEST_SAMPLE, &command))) + + if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_REQUEST_SAMPLE, &op))) { + struct source_async_command *command = impl_from_async_command_IUnknown(op); command->u.request_sample.stream = stream; command->u.request_sample.token = stream->token_queue[i];
- hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, - &command->IUnknown_iface); + hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op); } if (FAILED(hr)) WARN("Could not enqueue sample request, hr %#lx\n", hr); @@ -795,7 +795,7 @@ static HRESULT WINAPI media_stream_RequestSample(IMFMediaStream *iface, IUnknown { struct media_stream *stream = impl_from_IMFMediaStream(iface); struct media_source *source = impl_from_IMFMediaSource(stream->media_source); - struct source_async_command *command; + IUnknown *op; HRESULT hr;
TRACE("%p, %p.\n", iface, token); @@ -808,14 +808,15 @@ static HRESULT WINAPI media_stream_RequestSample(IMFMediaStream *iface, IUnknown hr = MF_E_MEDIA_SOURCE_WRONGSTATE; else if (stream->eos) hr = MF_E_END_OF_STREAM; - else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_REQUEST_SAMPLE, &command))) + else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_REQUEST_SAMPLE, &op))) { + struct source_async_command *command = impl_from_async_command_IUnknown(op); command->u.request_sample.stream = stream; if (token) IUnknown_AddRef(token); command->u.request_sample.token = token;
- hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, &command->IUnknown_iface); + hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op); }
LeaveCriticalSection(&source->cs); @@ -1314,7 +1315,7 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD const GUID *time_format, const PROPVARIANT *position) { struct media_source *source = impl_from_IMFMediaSource(iface); - struct source_async_command *command; + IUnknown *op; HRESULT hr;
TRACE("%p, %p, %p, %p.\n", iface, descriptor, time_format, position); @@ -1325,13 +1326,14 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD hr = MF_E_SHUTDOWN; else if (!(IsEqualIID(time_format, &GUID_NULL))) hr = MF_E_UNSUPPORTED_TIME_FORMAT; - else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_START, &command))) + else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_START, &op))) { + struct source_async_command *command = impl_from_async_command_IUnknown(op); command->u.start.descriptor = descriptor; command->u.start.format = *time_format; PropVariantCopy(&command->u.start.position, position);
- hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, &command->IUnknown_iface); + hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op); }
LeaveCriticalSection(&source->cs); @@ -1342,7 +1344,7 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface) { struct media_source *source = impl_from_IMFMediaSource(iface); - struct source_async_command *command; + IUnknown *op; HRESULT hr;
TRACE("%p.\n", iface); @@ -1351,8 +1353,8 @@ static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface)
if (source->state == SOURCE_SHUTDOWN) hr = MF_E_SHUTDOWN; - else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_STOP, &command))) - hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, &command->IUnknown_iface); + else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_STOP, &op))) + hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op);
LeaveCriticalSection(&source->cs);
@@ -1362,7 +1364,7 @@ static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface) static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface) { struct media_source *source = impl_from_IMFMediaSource(iface); - struct source_async_command *command; + IUnknown *op; HRESULT hr;
TRACE("%p.\n", iface); @@ -1373,9 +1375,8 @@ static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface) hr = MF_E_SHUTDOWN; else if (source->state != SOURCE_RUNNING) hr = MF_E_INVALID_STATE_TRANSITION; - else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_PAUSE, &command))) - hr = MFPutWorkItem(source->async_commands_queue, - &source->async_commands_callback, &command->IUnknown_iface); + else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_PAUSE, &op))) + hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op);
LeaveCriticalSection(&source->cs);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 4501e60fa65..89edd9527e2 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -199,6 +199,7 @@ static HRESULT source_create_async_op(enum source_async_op op, IUnknown **out) return E_OUTOFMEMORY;
command->IUnknown_iface.lpVtbl = &source_async_command_vtbl; + command->refcount = 1; command->op = op;
*out = &command->IUnknown_iface; @@ -302,6 +303,7 @@ static void flush_token_queue(struct media_stream *stream, BOOL send) command->u.request_sample.token = stream->token_queue[i];
hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op); + IUnknown_Release(op); } if (FAILED(hr)) WARN("Could not enqueue sample request, hr %#lx\n", hr); @@ -817,6 +819,7 @@ static HRESULT WINAPI media_stream_RequestSample(IMFMediaStream *iface, IUnknown command->u.request_sample.token = token;
hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op); + IUnknown_Release(op); }
LeaveCriticalSection(&source->cs); @@ -1334,6 +1337,7 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD PropVariantCopy(&command->u.start.position, position);
hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op); + IUnknown_Release(op); }
LeaveCriticalSection(&source->cs); @@ -1354,7 +1358,10 @@ static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface) if (source->state == SOURCE_SHUTDOWN) hr = MF_E_SHUTDOWN; else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_STOP, &op))) + { hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op); + IUnknown_Release(op); + }
LeaveCriticalSection(&source->cs);
@@ -1376,7 +1383,10 @@ static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface) else if (source->state != SOURCE_RUNNING) hr = MF_E_INVALID_STATE_TRANSITION; else if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_PAUSE, &op))) + { hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, op); + IUnknown_Release(op); + }
LeaveCriticalSection(&source->cs);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 41 ++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 89edd9527e2..c7046dbcd4a 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -241,6 +241,32 @@ static ULONG WINAPI source_async_commands_callback_Release(IMFAsyncCallback *ifa return IMFMediaSource_Release(&source->IMFMediaSource_iface); }
+static HRESULT stream_descriptor_get_media_type(IMFStreamDescriptor *descriptor, IMFMediaType **media_type) +{ + IMFMediaTypeHandler *handler; + HRESULT hr; + + if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(descriptor, &handler))) + return hr; + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, media_type); + IMFMediaTypeHandler_Release(handler); + + return hr; +} + +static HRESULT wg_format_from_stream_descriptor(IMFStreamDescriptor *descriptor, struct wg_format *format) +{ + IMFMediaType *media_type; + HRESULT hr; + + if (FAILED(hr = stream_descriptor_get_media_type(descriptor, &media_type))) + return hr; + mf_media_type_to_wg_format(media_type, format); + IMFMediaType_Release(media_type); + + return hr; +} + static IMFStreamDescriptor *stream_descriptor_from_id(IMFPresentationDescriptor *pres_desc, DWORD id, BOOL *selected) { ULONG sd_count; @@ -322,6 +348,7 @@ static void start_pipeline(struct media_source *source, struct source_async_comm PROPVARIANT *position = &command->u.start.position; BOOL seek_message = source->state != SOURCE_STOPPED && position->vt != VT_EMPTY; unsigned int i; + HRESULT hr;
/* seek to beginning on stop->play */ if (source->state == SOURCE_STOPPED && position->vt == VT_EMPTY) @@ -334,8 +361,7 @@ static void start_pipeline(struct media_source *source, struct source_async_comm { struct media_stream *stream; IMFStreamDescriptor *sd; - IMFMediaTypeHandler *mth; - IMFMediaType *current_mt; + struct wg_format format; DWORD stream_id; BOOL was_active; BOOL selected; @@ -352,16 +378,9 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
if (selected) { - struct wg_format format; - - IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &mth); - IMFMediaTypeHandler_GetCurrentMediaType(mth, ¤t_mt); - - mf_media_type_to_wg_format(current_mt, &format); + if (FAILED(hr = wg_format_from_stream_descriptor(stream->descriptor, &format))) + WARN("Failed to get wg_format from stream descriptor, hr %#lx\n", hr); wg_parser_stream_enable(stream->wg_stream, &format); - - IMFMediaType_Release(current_mt); - IMFMediaTypeHandler_Release(mth); } else {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 53 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 28 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index c7046dbcd4a..be3a04820f6 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -343,6 +343,25 @@ static void flush_token_queue(struct media_stream *stream, BOOL send) stream->token_queue_cap = 0; }
+static HRESULT media_stream_start(struct media_stream *stream, BOOL active, BOOL seeking, const PROPVARIANT *position) +{ + struct media_source *source = impl_from_IMFMediaSource(stream->media_source); + struct wg_format format; + HRESULT hr; + + TRACE("source %p, stream %p\n", source, stream); + + if (FAILED(hr = wg_format_from_stream_descriptor(stream->descriptor, &format))) + WARN("Failed to get wg_format from stream descriptor, hr %#lx\n", hr); + wg_parser_stream_enable(stream->wg_stream, &format); + + if (FAILED(hr = IMFMediaEventQueue_QueueEventParamUnk(source->event_queue, active ? MEUpdatedStream : MENewStream, + &GUID_NULL, S_OK, (IUnknown *)&stream->IMFMediaStream_iface))) + WARN("Failed to send source stream event, hr %#lx\n", hr); + return IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, seeking ? MEStreamSeeked : MEStreamStarted, + &GUID_NULL, S_OK, position); +} + static void start_pipeline(struct media_source *source, struct source_async_command *command) { PROPVARIANT *position = &command->u.start.position; @@ -360,46 +379,24 @@ static void start_pipeline(struct media_source *source, struct source_async_comm for (i = 0; i < source->stream_count; i++) { struct media_stream *stream; + BOOL was_active, selected; IMFStreamDescriptor *sd; - struct wg_format format; DWORD stream_id; - BOOL was_active; - BOOL selected;
stream = source->streams[i]; + was_active = stream->active;
IMFStreamDescriptor_GetStreamIdentifier(stream->descriptor, &stream_id); - sd = stream_descriptor_from_id(command->u.start.descriptor, stream_id, &selected); IMFStreamDescriptor_Release(sd);
- was_active = stream->active; - stream->active = selected; - - if (selected) - { - if (FAILED(hr = wg_format_from_stream_descriptor(stream->descriptor, &format))) - WARN("Failed to get wg_format from stream descriptor, hr %#lx\n", hr); - wg_parser_stream_enable(stream->wg_stream, &format); - } - else - { - wg_parser_stream_disable(stream->wg_stream); - } - if (position->vt != VT_EMPTY) stream->eos = FALSE;
- if (selected) - { - TRACE("Stream %u (%p) selected\n", i, stream); - IMFMediaEventQueue_QueueEventParamUnk(source->event_queue, - was_active ? MEUpdatedStream : MENewStream, &GUID_NULL, - S_OK, (IUnknown*) &stream->IMFMediaStream_iface); - - IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, - seek_message ? MEStreamSeeked : MEStreamStarted, &GUID_NULL, S_OK, position); - } + if (!(stream->active = selected)) + wg_parser_stream_disable(stream->wg_stream); + else if (FAILED(hr = media_stream_start(stream, was_active, seek_message, position))) + WARN("Failed to start media stream, hr %#lx\n", hr); }
IMFMediaEventQueue_QueueEventParamVar(source->event_queue,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 113 ++++++++++++------------------ 1 file changed, 43 insertions(+), 70 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index be3a04820f6..dcf3e5dda67 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -452,59 +452,19 @@ static void stop_pipeline(struct media_source *source) flush_token_queue(source->streams[i], FALSE); }
-static void dispatch_end_of_presentation(struct media_source *source) -{ - PROPVARIANT empty = {.vt = VT_EMPTY}; - unsigned int i; - - /* A stream has ended, check whether all have */ - for (i = 0; i < source->stream_count; i++) - { - struct media_stream *stream = source->streams[i]; - if (stream->active && !stream->eos) - return; - } - - IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MEEndOfPresentation, &GUID_NULL, S_OK, &empty); -} - -static void send_buffer(struct media_stream *stream, const struct wg_parser_buffer *wg_buffer, IUnknown *token) +static HRESULT media_stream_send_sample(struct media_stream *stream, const struct wg_parser_buffer *wg_buffer, IUnknown *token) { + IMFSample *sample = NULL; IMFMediaBuffer *buffer; - IMFSample *sample; HRESULT hr; BYTE *data;
- if (FAILED(hr = MFCreateSample(&sample))) - { - ERR("Failed to create sample, hr %#lx.\n", hr); - return; - } - if (FAILED(hr = MFCreateMemoryBuffer(wg_buffer->size, &buffer))) - { - ERR("Failed to create buffer, hr %#lx.\n", hr); - IMFSample_Release(sample); - return; - } - - if (FAILED(hr = IMFSample_AddBuffer(sample, buffer))) - { - ERR("Failed to add buffer, hr %#lx.\n", hr); - goto out; - } - + return hr; if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(buffer, wg_buffer->size))) - { - ERR("Failed to set size, hr %#lx.\n", hr); goto out; - } - if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL))) - { - ERR("Failed to lock buffer, hr %#lx.\n", hr); goto out; - }
if (!wg_parser_stream_copy_buffer(stream->wg_stream, data, 0, wg_buffer->size)) { @@ -515,52 +475,62 @@ static void send_buffer(struct media_stream *stream, const struct wg_parser_buff wg_parser_stream_release_buffer(stream->wg_stream);
if (FAILED(hr = IMFMediaBuffer_Unlock(buffer))) - { - ERR("Failed to unlock buffer, hr %#lx.\n", hr); goto out; - }
+ if (FAILED(hr = MFCreateSample(&sample))) + goto out; + if (FAILED(hr = IMFSample_AddBuffer(sample, buffer))) + goto out; if (FAILED(hr = IMFSample_SetSampleTime(sample, wg_buffer->pts))) - { - ERR("Failed to set sample time, hr %#lx.\n", hr); goto out; - } - if (FAILED(hr = IMFSample_SetSampleDuration(sample, wg_buffer->duration))) - { - ERR("Failed to set sample duration, hr %#lx.\n", hr); goto out; - } - - if (token) - IMFSample_SetUnknown(sample, &MFSampleExtension_Token, token); + if (token && FAILED(hr = IMFSample_SetUnknown(sample, &MFSampleExtension_Token, token))) + goto out;
- IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample, + hr = IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample, &GUID_NULL, S_OK, (IUnknown *)sample);
out: + if (sample) + IMFSample_Release(sample); IMFMediaBuffer_Release(buffer); - IMFSample_Release(sample); + return hr; +} + +static HRESULT media_stream_send_eos(struct media_source *source, struct media_stream *stream) +{ + PROPVARIANT empty = {.vt = VT_EMPTY}; + HRESULT hr; + UINT i; + + stream->eos = TRUE; + if (FAILED(hr = IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEEndOfStream, &GUID_NULL, S_OK, &empty))) + WARN("Failed to queue MEEndOfStream event, hr %#lx\n", hr); + + for (i = 0; i < source->stream_count; i++) + { + struct media_stream *stream = source->streams[i]; + if (stream->active && !stream->eos) + return S_OK; + } + + if (FAILED(hr = IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MEEndOfPresentation, &GUID_NULL, S_OK, &empty))) + WARN("Failed to queue MEEndOfPresentation event, hr %#lx\n", hr); + return S_OK; }
-static void wait_on_sample(struct media_stream *stream, IUnknown *token) +static HRESULT wait_on_sample(struct media_stream *stream, IUnknown *token) { struct media_source *source = impl_from_IMFMediaSource(stream->media_source); - PROPVARIANT empty_var = {.vt = VT_EMPTY}; struct wg_parser_buffer buffer;
TRACE("%p, %p\n", stream, token);
if (wg_parser_stream_get_buffer(source->wg_parser, stream->wg_stream, &buffer)) - { - send_buffer(stream, &buffer, token); - } - else - { - stream->eos = TRUE; - IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEEndOfStream, &GUID_NULL, S_OK, &empty_var); - dispatch_end_of_presentation(source); - } + return media_stream_send_sample(stream, &buffer, token); + + return media_stream_send_eos(source, stream); }
static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) @@ -594,7 +564,10 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA if (source->state == SOURCE_PAUSED) enqueue_token(command->u.request_sample.stream, command->u.request_sample.token); else if (source->state == SOURCE_RUNNING) - wait_on_sample(command->u.request_sample.stream, command->u.request_sample.token); + { + if (FAILED(hr = wait_on_sample(command->u.request_sample.stream, command->u.request_sample.token))) + WARN("Failed to request sample, hr %#lx\n", hr); + } break; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 60 +++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 19 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index dcf3e5dda67..c11178cc485 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -362,13 +362,19 @@ static HRESULT media_stream_start(struct media_stream *stream, BOOL active, BOOL &GUID_NULL, S_OK, position); }
-static void start_pipeline(struct media_source *source, struct source_async_command *command) +static HRESULT media_source_start(struct media_source *source, IMFPresentationDescriptor *descriptor, + GUID *format, PROPVARIANT *position) { - PROPVARIANT *position = &command->u.start.position; BOOL seek_message = source->state != SOURCE_STOPPED && position->vt != VT_EMPTY; unsigned int i; HRESULT hr;
+ TRACE("source %p, descriptor %p, format %s, position %s\n", source, descriptor, + debugstr_guid(format), wine_dbgstr_variant((VARIANT *)position)); + + if (source->state == SOURCE_SHUTDOWN) + return MF_E_SHUTDOWN; + /* seek to beginning on stop->play */ if (source->state == SOURCE_STOPPED && position->vt == VT_EMPTY) { @@ -387,7 +393,7 @@ static void start_pipeline(struct media_source *source, struct source_async_comm was_active = stream->active;
IMFStreamDescriptor_GetStreamIdentifier(stream->descriptor, &stream_id); - sd = stream_descriptor_from_id(command->u.start.descriptor, stream_id, &selected); + sd = stream_descriptor_from_id(descriptor, stream_id, &selected); IMFStreamDescriptor_Release(sd);
if (position->vt != VT_EMPTY) @@ -399,10 +405,6 @@ static void start_pipeline(struct media_source *source, struct source_async_comm WARN("Failed to start media stream, hr %#lx\n", hr); }
- IMFMediaEventQueue_QueueEventParamVar(source->event_queue, - seek_message ? MESourceSeeked : MESourceStarted, - &GUID_NULL, S_OK, position); - source->state = SOURCE_RUNNING;
if (position->vt == VT_I8) @@ -411,13 +413,21 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
for (i = 0; i < source->stream_count; i++) flush_token_queue(source->streams[i], position->vt == VT_EMPTY); + + return IMFMediaEventQueue_QueueEventParamVar(source->event_queue, + seek_message ? MESourceSeeked : MESourceStarted, &GUID_NULL, S_OK, position); }
-static void pause_pipeline(struct media_source *source) +static HRESULT media_source_pause(struct media_source *source) { unsigned int i; HRESULT hr;
+ TRACE("source %p\n", source); + + if (source->state == SOURCE_SHUTDOWN) + return MF_E_SHUTDOWN; + for (i = 0; i < source->stream_count; i++) { struct media_stream *stream = source->streams[i]; @@ -426,16 +436,20 @@ static void pause_pipeline(struct media_source *source) WARN("Failed to queue MEStreamPaused event, hr %#lx\n", hr); }
- IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourcePaused, &GUID_NULL, S_OK, NULL); - source->state = SOURCE_PAUSED; + return IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourcePaused, &GUID_NULL, S_OK, NULL); }
-static void stop_pipeline(struct media_source *source) +static HRESULT media_source_stop(struct media_source *source) { unsigned int i; HRESULT hr;
+ TRACE("source %p\n", source); + + if (source->state == SOURCE_SHUTDOWN) + return MF_E_SHUTDOWN; + for (i = 0; i < source->stream_count; i++) { struct media_stream *stream = source->streams[i]; @@ -444,12 +458,12 @@ static void stop_pipeline(struct media_source *source) WARN("Failed to queue MEStreamStopped event, hr %#lx\n", hr); }
- IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourceStopped, &GUID_NULL, S_OK, NULL); - source->state = SOURCE_STOPPED;
for (i = 0; i < source->stream_count; i++) flush_token_queue(source->streams[i], FALSE); + + return IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourceStopped, &GUID_NULL, S_OK, NULL); }
static HRESULT media_stream_send_sample(struct media_stream *stream, const struct wg_parser_buffer *wg_buffer, IUnknown *token) @@ -504,6 +518,8 @@ static HRESULT media_stream_send_eos(struct media_source *source, struct media_s HRESULT hr; UINT i;
+ TRACE("source %p, stream %p\n", source, stream); + stream->eos = TRUE; if (FAILED(hr = IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEEndOfStream, &GUID_NULL, S_OK, &empty))) WARN("Failed to queue MEEndOfStream event, hr %#lx\n", hr); @@ -549,16 +565,22 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA switch (command->op) { case SOURCE_ASYNC_START: - if (source->state != SOURCE_SHUTDOWN) - start_pipeline(source, command); + { + IMFPresentationDescriptor *descriptor = command->u.start.descriptor; + GUID format = command->u.start.format; + PROPVARIANT position = command->u.start.position; + + if (FAILED(hr = media_source_start(source, descriptor, &format, &position))) + WARN("Failed to start source %p, hr %#lx\n", source, hr); break; + } case SOURCE_ASYNC_PAUSE: - if (source->state != SOURCE_SHUTDOWN) - pause_pipeline(source); + if (FAILED(hr = media_source_pause(source))) + WARN("Failed to pause source %p, hr %#lx\n", source, hr); break; case SOURCE_ASYNC_STOP: - if (source->state != SOURCE_SHUTDOWN) - stop_pipeline(source); + if (FAILED(hr = media_source_stop(source))) + WARN("Failed to stop source %p, hr %#lx\n", source, hr); break; case SOURCE_ASYNC_REQUEST_SAMPLE: if (source->state == SOURCE_PAUSED)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 48 ++++++++++++++----------------- 1 file changed, 22 insertions(+), 26 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index c11178cc485..3fcb065a02a 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -92,8 +92,10 @@ struct media_source
struct wg_parser *wg_parser;
+ IMFStreamDescriptor **descriptors; struct media_stream **streams; ULONG stream_count; + IMFPresentationDescriptor *pres_desc; enum { @@ -1432,9 +1434,11 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface) while (source->stream_count--) { struct media_stream *stream = source->streams[source->stream_count]; + IMFStreamDescriptor_Release(source->descriptors[source->stream_count]); IMFMediaEventQueue_Shutdown(stream->event_queue); IMFMediaStream_Release(&stream->IMFMediaStream_iface); } + free(source->descriptors); free(source->streams);
MFUnlockWorkQueue(source->async_commands_queue); @@ -1463,7 +1467,6 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source) { - IMFStreamDescriptor **descriptors = NULL; unsigned int stream_count = UINT_MAX; struct media_source *object; UINT64 total_pres_time = 0; @@ -1531,32 +1534,37 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
stream_count = wg_parser_get_stream_count(parser);
- if (!(object->streams = calloc(stream_count, sizeof(*object->streams)))) + if (!(object->descriptors = calloc(stream_count, sizeof(*object->descriptors))) + || !(object->streams = calloc(stream_count, sizeof(*object->streams)))) { + free(object->descriptors); hr = E_OUTOFMEMORY; goto fail; }
for (i = 0; i < stream_count; ++i) { - if (FAILED(hr = media_stream_create(&object->IMFMediaSource_iface, i, &object->streams[i]))) - goto fail; + struct media_stream *stream;
- if (FAILED(hr = media_stream_init_desc(object->streams[i]))) + if (FAILED(hr = media_stream_create(&object->IMFMediaSource_iface, i, &stream))) + goto fail; + if (FAILED(hr = media_stream_init_desc(stream))) { - ERR("Failed to finish initialization of media stream %p, hr %#lx.\n", object->streams[i], hr); - IMFMediaSource_Release(object->streams[i]->media_source); - IMFMediaEventQueue_Release(object->streams[i]->event_queue); - free(object->streams[i]); + ERR("Failed to finish initialization of media stream %p, hr %#lx.\n", stream, hr); + IMFMediaSource_Release(stream->media_source); + IMFMediaEventQueue_Release(stream->event_queue); + free(stream); goto fail; }
+ IMFStreamDescriptor_AddRef(stream->descriptor); + object->descriptors[i] = stream->descriptor; + object->streams[i] = stream; object->stream_count++; }
/* init presentation descriptor */
- descriptors = malloc(object->stream_count * sizeof(IMFStreamDescriptor *)); for (i = 0; i < object->stream_count; i++) { static const struct @@ -1574,8 +1582,6 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ DWORD len; char *str;
- IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[i]); - for (j = 0; j < ARRAY_SIZE(tags); ++j) { if (!(str = wg_parser_stream_get_tag(object->streams[i]->wg_stream, tags[j].tag))) @@ -1587,22 +1593,17 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ } strW = malloc(len * sizeof(*strW)); if (MultiByteToWideChar(CP_UTF8, 0, str, -1, strW, len)) - IMFStreamDescriptor_SetString(descriptors[i], tags[j].mf_attr, strW); + IMFStreamDescriptor_SetString(object->descriptors[i], tags[j].mf_attr, strW); free(strW); free(str); } }
- if (FAILED(hr = MFCreatePresentationDescriptor(object->stream_count, descriptors, &object->pres_desc))) + if (FAILED(hr = MFCreatePresentationDescriptor(object->stream_count, object->descriptors, &object->pres_desc))) goto fail;
for (i = 0; i < object->stream_count; i++) - { IMFPresentationDescriptor_SelectStream(object->pres_desc, i); - IMFStreamDescriptor_Release(descriptors[i]); - } - free(descriptors); - descriptors = NULL;
for (i = 0; i < object->stream_count; i++) total_pres_time = max(total_pres_time, @@ -1619,18 +1620,13 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ fail: WARN("Failed to construct MFMediaSource, hr %#lx.\n", hr);
- if (descriptors) - { - for (i = 0; i < object->stream_count; i++) - IMFStreamDescriptor_Release(descriptors[i]); - free(descriptors); - } - while (object->streams && object->stream_count--) { struct media_stream *stream = object->streams[object->stream_count]; + IMFStreamDescriptor_Release(object->descriptors[object->stream_count]); IMFMediaStream_Release(&stream->IMFMediaStream_iface); } + free(object->descriptors); free(object->streams);
if (stream_count != UINT_MAX)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 3fcb065a02a..9e66ae233b8 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -91,12 +91,12 @@ struct media_source CRITICAL_SECTION cs;
struct wg_parser *wg_parser; + UINT64 duration;
IMFStreamDescriptor **descriptors; struct media_stream **streams; ULONG stream_count;
- IMFPresentationDescriptor *pres_desc; enum { SOURCE_OPENING, @@ -367,7 +367,7 @@ static HRESULT media_stream_start(struct media_stream *stream, BOOL active, BOOL static HRESULT media_source_start(struct media_source *source, IMFPresentationDescriptor *descriptor, GUID *format, PROPVARIANT *position) { - BOOL seek_message = source->state != SOURCE_STOPPED && position->vt != VT_EMPTY; + BOOL starting = source->state == SOURCE_STOPPED, seek_message = !starting && position->vt != VT_EMPTY; unsigned int i; HRESULT hr;
@@ -392,7 +392,7 @@ static HRESULT media_source_start(struct media_source *source, IMFPresentationDe DWORD stream_id;
stream = source->streams[i]; - was_active = stream->active; + was_active = !starting && stream->active;
IMFStreamDescriptor_GetStreamIdentifier(stream->descriptor, &stream_id); sd = stream_descriptor_from_id(descriptor, stream_id, &selected); @@ -879,7 +879,7 @@ static HRESULT media_stream_create(IMFMediaSource *source, DWORD id, object->media_source = source; object->stream_id = id;
- object->active = FALSE; + object->active = TRUE; object->eos = FALSE; object->wg_stream = wg_parser_get_stream(wg_parser, id);
@@ -1240,7 +1240,6 @@ static ULONG WINAPI media_source_Release(IMFMediaSource *iface) if (!ref) { IMFMediaSource_Shutdown(iface); - IMFPresentationDescriptor_Release(source->pres_desc); IMFMediaEventQueue_Release(source->event_queue); IMFByteStream_Release(source->byte_stream); wg_parser_destroy(source->wg_parser); @@ -1312,6 +1311,7 @@ static HRESULT WINAPI media_source_CreatePresentationDescriptor(IMFMediaSource * { struct media_source *source = impl_from_IMFMediaSource(iface); HRESULT hr; + UINT i;
TRACE("%p, %p.\n", iface, descriptor);
@@ -1319,8 +1319,21 @@ static HRESULT WINAPI media_source_CreatePresentationDescriptor(IMFMediaSource *
if (source->state == SOURCE_SHUTDOWN) hr = MF_E_SHUTDOWN; - else - hr = IMFPresentationDescriptor_Clone(source->pres_desc, descriptor); + else if (SUCCEEDED(hr = MFCreatePresentationDescriptor(source->stream_count, source->descriptors, descriptor))) + { + if (FAILED(hr = IMFPresentationDescriptor_SetUINT64(*descriptor, &MF_PD_DURATION, source->duration))) + WARN("Failed to set presentation descriptor MF_PD_DURATION, hr %#lx\n", hr); + + for (i = 0; i < source->stream_count; ++i) + { + if (!source->streams[i]->active) + continue; + if (FAILED(hr = IMFPresentationDescriptor_SelectStream(*descriptor, i))) + WARN("Failed to select stream %u, hr %#lx\n", i, hr); + } + + hr = S_OK; + }
LeaveCriticalSection(&source->cs);
@@ -1469,7 +1482,6 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ { unsigned int stream_count = UINT_MAX; struct media_source *object; - UINT64 total_pres_time = 0; struct wg_parser *parser; DWORD bytestream_caps; uint64_t file_size; @@ -1557,6 +1569,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ goto fail; }
+ object->duration = max(object->duration, wg_parser_stream_get_duration(stream->wg_stream)); IMFStreamDescriptor_AddRef(stream->descriptor); object->descriptors[i] = stream->descriptor; object->streams[i] = stream; @@ -1599,19 +1612,6 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ } }
- if (FAILED(hr = MFCreatePresentationDescriptor(object->stream_count, object->descriptors, &object->pres_desc))) - goto fail; - - for (i = 0; i < object->stream_count; i++) - IMFPresentationDescriptor_SelectStream(object->pres_desc, i); - - for (i = 0; i < object->stream_count; i++) - total_pres_time = max(total_pres_time, - wg_parser_stream_get_duration(object->streams[i]->wg_stream)); - - if (object->stream_count) - IMFPresentationDescriptor_SetUINT64(object->pres_desc, &MF_PD_DURATION, total_pres_time); - object->state = SOURCE_STOPPED;
*out_media_source = object;
This is all mfplat code, so adding Nikolay as reviewer. I didn't notice any obvious errors from a quick review, though.
I did notice a failure while running the tests: the media source was somehow being leaked in test_media_session_events() [last release returned 1]. I can't reproduce it, though, even by running the test in a loop. Hence I don't know if it's preëxisting or not.
Why is `winegstreamer: Create media source presentation descriptor as needed.` necessary?
On Mon May 8 17:21:23 2023 +0000, Nikolay Sivov wrote:
Why is `winegstreamer: Create media source presentation descriptor as needed.` necessary?
It's not necessary, but it simplifies the code, saves an allocation and the corresponding error handling during media source creation.
Nikolay Sivov (@nsivov) commented about dlls/winegstreamer/media_source.c:
hr = IMFPresentationDescriptor_Clone(source->pres_desc, descriptor);
- else if (SUCCEEDED(hr = MFCreatePresentationDescriptor(source->stream_count, source->descriptors, descriptor)))
- {
if (FAILED(hr = IMFPresentationDescriptor_SetUINT64(*descriptor, &MF_PD_DURATION, source->duration)))
WARN("Failed to set presentation descriptor MF_PD_DURATION, hr %#lx\n", hr);
for (i = 0; i < source->stream_count; ++i)
{
if (!source->streams[i]->active)
continue;
if (FAILED(hr = IMFPresentationDescriptor_SelectStream(*descriptor, i)))
WARN("Failed to select stream %u, hr %#lx\n", i, hr);
}
hr = S_OK;
- }
Why does it check for "active"? Before this change all streams were selected. I don't think CreatePresentationDescriptor() should reflect source state changes.