From: Yuxuan Shui yshui@codeweavers.com
I've also tried saving a cancel cookie from `BeginCreateObject*` and using it to cancel the operation in engine shutdown. However there are 2 problems:
1. Callback might still get called after `CancelObjectCreation`. Microsoft's [own documentation](https://learn.microsoft.com/en-us/windows/win32/api/mfidl/nf-mfidl-imfsource...) says as much: > Because these methods are asynchronous, however, they might be completed before the > operation can be canceled. Therefore, your callback might still be invoked after you > call this method. 2. Our implementations of `BeginCreateObject*` are not cancellable. They call either `MFPutWorkItem` or `IMFByteStream_BeginRead`, neight of which provides cancellation. (and our `CancelObjectCreation` doesn't actually work. AsyncResult objects aren't added to `handler->results` list until they are completed, which means any attempts to cancel an yet-to-be-completed object creation will always fail with `MF_E_UNEXPECTED`) --- dlls/mfmediaengine/main.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c index 5a63974967d..77c7b2bd745 100644 --- a/dlls/mfmediaengine/main.c +++ b/dlls/mfmediaengine/main.c @@ -1356,12 +1356,6 @@ static HRESULT WINAPI media_engine_load_handler_Invoke(IMFAsyncCallback *iface,
EnterCriticalSection(&engine->cs);
- engine->network_state = MF_MEDIA_ENGINE_NETWORK_LOADING; - IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_LOADSTART, 0, 0); - - start_playback = engine->flags & FLAGS_ENGINE_PLAY_PENDING; - media_engine_set_flag(engine, FLAGS_ENGINE_SOURCE_PENDING | FLAGS_ENGINE_PLAY_PENDING, FALSE); - if (SUCCEEDED(IMFAsyncResult_GetState(result, &state))) { hr = IMFSourceResolver_EndCreateObjectFromByteStream(engine->resolver, result, &obj_type, &object); @@ -1373,6 +1367,20 @@ static HRESULT WINAPI media_engine_load_handler_Invoke(IMFAsyncCallback *iface, if (FAILED(hr)) WARN("Failed to create source object, hr %#lx.\n", hr);
+ if (engine->flags & FLAGS_ENGINE_SHUT_DOWN) + { + LeaveCriticalSection(&engine->cs); + TRACE("Engine is shut down, stopping...\n"); + IUnknown_Release(object); + return S_OK; + } + + engine->network_state = MF_MEDIA_ENGINE_NETWORK_LOADING; + IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_LOADSTART, 0, 0); + + start_playback = engine->flags & FLAGS_ENGINE_PLAY_PENDING; + media_engine_set_flag(engine, FLAGS_ENGINE_SOURCE_PENDING | FLAGS_ENGINE_PLAY_PENDING, FALSE); + if (object) { if (SUCCEEDED(hr = IUnknown_QueryInterface(object, &IID_IMFMediaSource, (void **)&source)))
According to my experiments with media extension instance, I don't think there is a need to call EndCreate*() if the engine was shut down. What we'll need to do instead is to release the resolver/extension on Shutdown() as well, as a separate fix. This also implies that on Invoke() you'll have nothing to call EndCreate* on.
Cancellation call is also not used with the extension, so I don't think it's a requirement to cancel it.