winegstreamer: Duplicate source shutdown path into constructor with leak fixes.
Instead of having mixing together IMFMediaSource::Shutdown() and the constructors' failure paths, creating confusion about what should be released where, designate ::Shutdown/::Release to shutting down fully initialized objects without checks, and keep the partially-created object cleanup code in the constructor. Signed-off-by: Derek Lesho <dlesho@codeweavers.com> Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
721b1eb2eb
commit
67734bfce3
|
@ -22,6 +22,7 @@
|
||||||
#define __GST_PRIVATE_INCLUDED__
|
#define __GST_PRIVATE_INCLUDED__
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
|
@ -733,6 +733,12 @@ static HRESULT new_media_stream(struct media_source *source,
|
||||||
object->IMFMediaStream_iface.lpVtbl = &media_stream_vtbl;
|
object->IMFMediaStream_iface.lpVtbl = &media_stream_vtbl;
|
||||||
object->ref = 1;
|
object->ref = 1;
|
||||||
|
|
||||||
|
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||||
|
{
|
||||||
|
free(object);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||||
object->parent_source = source;
|
object->parent_source = source;
|
||||||
object->stream_id = stream_id;
|
object->stream_id = stream_id;
|
||||||
|
@ -741,20 +747,11 @@ static HRESULT new_media_stream(struct media_source *source,
|
||||||
object->eos = FALSE;
|
object->eos = FALSE;
|
||||||
object->wg_stream = wg_stream;
|
object->wg_stream = wg_stream;
|
||||||
|
|
||||||
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
TRACE("Created stream object %p.\n", object);
|
TRACE("Created stream object %p.\n", object);
|
||||||
|
|
||||||
*out_stream = object;
|
*out_stream = object;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
fail:
|
|
||||||
WARN("Failed to construct media stream, hr %#x.\n", hr);
|
|
||||||
|
|
||||||
IMFMediaStream_Release(&object->IMFMediaStream_iface);
|
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT media_stream_init_desc(struct media_stream *stream)
|
static HRESULT media_stream_init_desc(struct media_stream *stream)
|
||||||
|
@ -847,10 +844,16 @@ static HRESULT media_stream_init_desc(struct media_stream *stream)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &type_handler)))
|
if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &type_handler)))
|
||||||
|
{
|
||||||
|
IMFStreamDescriptor_Release(stream->descriptor);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_types[0])))
|
if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_types[0])))
|
||||||
|
{
|
||||||
|
IMFStreamDescriptor_Release(stream->descriptor);
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (type_handler)
|
if (type_handler)
|
||||||
|
@ -1213,19 +1216,13 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||||
|
|
||||||
unix_funcs->wg_parser_disconnect(source->wg_parser);
|
unix_funcs->wg_parser_disconnect(source->wg_parser);
|
||||||
|
|
||||||
if (source->read_thread)
|
source->read_thread_shutdown = true;
|
||||||
{
|
WaitForSingleObject(source->read_thread, INFINITE);
|
||||||
source->read_thread_shutdown = true;
|
CloseHandle(source->read_thread);
|
||||||
WaitForSingleObject(source->read_thread, INFINITE);
|
|
||||||
CloseHandle(source->read_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source->pres_desc)
|
IMFPresentationDescriptor_Release(source->pres_desc);
|
||||||
IMFPresentationDescriptor_Release(source->pres_desc);
|
IMFMediaEventQueue_Shutdown(source->event_queue);
|
||||||
if (source->event_queue)
|
IMFByteStream_Release(source->byte_stream);
|
||||||
IMFMediaEventQueue_Shutdown(source->event_queue);
|
|
||||||
if (source->byte_stream)
|
|
||||||
IMFByteStream_Release(source->byte_stream);
|
|
||||||
|
|
||||||
for (i = 0; i < source->stream_count; i++)
|
for (i = 0; i < source->stream_count; i++)
|
||||||
{
|
{
|
||||||
|
@ -1233,23 +1230,18 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||||
|
|
||||||
stream->state = STREAM_SHUTDOWN;
|
stream->state = STREAM_SHUTDOWN;
|
||||||
|
|
||||||
if (stream->event_queue)
|
IMFMediaEventQueue_Shutdown(stream->event_queue);
|
||||||
IMFMediaEventQueue_Shutdown(stream->event_queue);
|
IMFStreamDescriptor_Release(stream->descriptor);
|
||||||
if (stream->descriptor)
|
IMFMediaSource_Release(&stream->parent_source->IMFMediaSource_iface);
|
||||||
IMFStreamDescriptor_Release(stream->descriptor);
|
|
||||||
if (stream->parent_source)
|
|
||||||
IMFMediaSource_Release(&stream->parent_source->IMFMediaSource_iface);
|
|
||||||
|
|
||||||
IMFMediaStream_Release(&stream->IMFMediaStream_iface);
|
IMFMediaStream_Release(&stream->IMFMediaStream_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
unix_funcs->wg_parser_destroy(source->wg_parser);
|
unix_funcs->wg_parser_destroy(source->wg_parser);
|
||||||
|
|
||||||
if (source->stream_count)
|
free(source->streams);
|
||||||
free(source->streams);
|
|
||||||
|
|
||||||
if (source->async_commands_queue)
|
MFUnlockWorkQueue(source->async_commands_queue);
|
||||||
MFUnlockWorkQueue(source->async_commands_queue);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1274,6 +1266,7 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source)
|
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source)
|
||||||
{
|
{
|
||||||
IMFStreamDescriptor **descriptors = NULL;
|
IMFStreamDescriptor **descriptors = NULL;
|
||||||
|
unsigned int stream_count = UINT_MAX;
|
||||||
struct media_source *object;
|
struct media_source *object;
|
||||||
UINT64 total_pres_time = 0;
|
UINT64 total_pres_time = 0;
|
||||||
struct wg_parser *parser;
|
struct wg_parser *parser;
|
||||||
|
@ -1337,15 +1330,15 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||||
* leak occurs with native. */
|
* leak occurs with native. */
|
||||||
unix_funcs->wg_parser_set_unlimited_buffering(parser);
|
unix_funcs->wg_parser_set_unlimited_buffering(parser);
|
||||||
|
|
||||||
object->stream_count = unix_funcs->wg_parser_get_stream_count(parser);
|
stream_count = unix_funcs->wg_parser_get_stream_count(parser);
|
||||||
|
|
||||||
if (!(object->streams = calloc(object->stream_count, sizeof(*object->streams))))
|
if (!(object->streams = calloc(stream_count, sizeof(*object->streams))))
|
||||||
{
|
{
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < object->stream_count; ++i)
|
for (i = 0; i < stream_count; ++i)
|
||||||
{
|
{
|
||||||
if (FAILED(hr = new_media_stream(object, unix_funcs->wg_parser_get_stream(parser, i), i, &object->streams[i])))
|
if (FAILED(hr = new_media_stream(object, unix_funcs->wg_parser_get_stream(parser, i), i, &object->streams[i])))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1353,9 +1346,13 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||||
if (FAILED(hr = media_stream_init_desc(object->streams[i])))
|
if (FAILED(hr = media_stream_init_desc(object->streams[i])))
|
||||||
{
|
{
|
||||||
ERR("Failed to finish initialization of media stream %p, hr %x.\n", object->streams[i], hr);
|
ERR("Failed to finish initialization of media stream %p, hr %x.\n", object->streams[i], hr);
|
||||||
IMFMediaStream_Release(&object->streams[i]->IMFMediaStream_iface);
|
IMFMediaSource_Release(&object->streams[i]->parent_source->IMFMediaSource_iface);
|
||||||
|
IMFMediaEventQueue_Release(object->streams[i]->event_queue);
|
||||||
|
free(object->streams[i]);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object->stream_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init presentation descriptor */
|
/* init presentation descriptor */
|
||||||
|
@ -1392,8 +1389,39 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||||
fail:
|
fail:
|
||||||
WARN("Failed to construct MFMediaSource, hr %#x.\n", hr);
|
WARN("Failed to construct MFMediaSource, hr %#x.\n", hr);
|
||||||
|
|
||||||
free(descriptors);
|
if (descriptors)
|
||||||
IMFMediaSource_Release(&object->IMFMediaSource_iface);
|
{
|
||||||
|
for (i = 0; i < object->stream_count; i++)
|
||||||
|
IMFStreamDescriptor_Release(descriptors[i]);
|
||||||
|
free(descriptors);
|
||||||
|
}
|
||||||
|
for (i = 0; i < object->stream_count; i++)
|
||||||
|
{
|
||||||
|
struct media_stream *stream = object->streams[i];
|
||||||
|
|
||||||
|
IMFMediaEventQueue_Release(stream->event_queue);
|
||||||
|
IMFStreamDescriptor_Release(stream->descriptor);
|
||||||
|
IMFMediaSource_Release(&stream->parent_source->IMFMediaSource_iface);
|
||||||
|
|
||||||
|
free(stream);
|
||||||
|
}
|
||||||
|
free(object->streams);
|
||||||
|
if (stream_count != UINT_MAX)
|
||||||
|
unix_funcs->wg_parser_disconnect(object->wg_parser);
|
||||||
|
if (object->read_thread)
|
||||||
|
{
|
||||||
|
object->read_thread_shutdown = true;
|
||||||
|
WaitForSingleObject(object->read_thread, INFINITE);
|
||||||
|
CloseHandle(object->read_thread);
|
||||||
|
}
|
||||||
|
if (object->wg_parser)
|
||||||
|
unix_funcs->wg_parser_destroy(object->wg_parser);
|
||||||
|
if (object->async_commands_queue)
|
||||||
|
MFUnlockWorkQueue(object->async_commands_queue);
|
||||||
|
if (object->event_queue)
|
||||||
|
IMFMediaEventQueue_Release(object->event_queue);
|
||||||
|
IMFByteStream_Release(object->byte_stream);
|
||||||
|
free(object);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue