Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 486958f5f79..a77372977c7 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -21,6 +21,7 @@ #include "mf_private.h" #include "uuids.h" #include "evr.h" +#include "evcode.h" #include "d3d9.h" #include "initguid.h" #include "dxva2api.h" @@ -1723,9 +1724,34 @@ static ULONG WINAPI video_renderer_event_sink_Release(IMediaEventSink *iface)
static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, LONG event, LONG_PTR param1, LONG_PTR param2) { - FIXME("%p, %d, %ld, %ld.\n", iface, event, param1, param2); + struct video_renderer *renderer = impl_from_IMediaEventSink(iface); + HRESULT hr = S_OK; + unsigned int idx;
- return E_NOTIMPL; + TRACE("%p, %d, %ld, %ld.\n", iface, event, param1, param2); + + EnterCriticalSection(&renderer->cs); + + if (event == EC_SAMPLE_NEEDED) + { + idx = param1; + if (idx >= renderer->stream_count) + hr = MF_E_INVALIDSTREAMNUMBER; + else + { + hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue, + MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); + } + } + else + { + WARN("Unhandled event %d.\n", event); + hr = MF_E_UNEXPECTED; + } + + LeaveCriticalSection(&renderer->cs); + + return hr; }
static const IMediaEventSinkVtbl media_event_sink_vtbl =
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index a77372977c7..d01bb0f06f1 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -1743,6 +1743,15 @@ static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, L MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); } } + else if (event >= EC_USER) + { + PROPVARIANT code; + + code.vt = VT_I4; + code.lVal = event; + hr = IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, MERendererEvent, + &GUID_NULL, S_OK, &code); + } else { WARN("Unhandled event %d.\n", event);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 29 +++++++++++++++++++++++++++-- dlls/mf/tests/mf.c | 3 +++ 2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index a1b54b7080e..0fa6b49498d 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -303,6 +303,9 @@ struct quality_manager { IMFQualityManager IMFQualityManager_iface; LONG refcount; + + IMFPresentationClock *clock; + CRITICAL_SECTION cs; };
static inline struct media_session *impl_from_IMFMediaSession(IMFMediaSession *iface) @@ -3393,6 +3396,12 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses goto failed; }
+ if (object->quality_manager && FAILED(hr = IMFQualityManager_NotifyPresentationClock(object->quality_manager, + object->clock))) + { + goto failed; + } + *session = &object->IMFMediaSession_iface;
return S_OK; @@ -4459,6 +4468,9 @@ static ULONG WINAPI standard_quality_manager_Release(IMFQualityManager *iface)
if (!refcount) { + if (manager->clock) + IMFPresentationClock_Release(manager->clock); + DeleteCriticalSection(&manager->cs); heap_free(manager); }
@@ -4475,9 +4487,21 @@ static HRESULT WINAPI standard_quality_manager_NotifyTopology(IMFQualityManager static HRESULT WINAPI standard_quality_manager_NotifyPresentationClock(IMFQualityManager *iface, IMFPresentationClock *clock) { - FIXME("%p, %p stub.\n", iface, clock); + struct quality_manager *manager = impl_from_IMFQualityManager(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, clock); + + if (!clock) + return E_POINTER; + + EnterCriticalSection(&manager->cs); + if (manager->clock) + IMFPresentationClock_Release(manager->clock); + manager->clock = clock; + IMFPresentationClock_AddRef(manager->clock); + LeaveCriticalSection(&manager->cs); + + return S_OK; }
static HRESULT WINAPI standard_quality_manager_NotifyProcessInput(IMFQualityManager *iface, IMFTopologyNode *node, @@ -4536,6 +4560,7 @@ HRESULT WINAPI MFCreateStandardQualityManager(IMFQualityManager **manager)
object->IMFQualityManager_iface.lpVtbl = &standard_quality_manager_vtbl; object->refcount = 1; + InitializeCriticalSection(&object->cs);
*manager = &object->IMFQualityManager_iface;
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index c38c817eb4b..7780bf4ea58 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2815,6 +2815,9 @@ static void test_quality_manager(void) hr = MFCreateStandardQualityManager(&manager); ok(hr == S_OK, "Failed to create quality manager, hr %#x.\n", hr);
+ hr = IMFQualityManager_NotifyPresentationClock(manager, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + IMFQualityManager_Release(manager); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 0fa6b49498d..8d5ff6d5c07 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -42,7 +42,9 @@ enum session_command SESSION_CMD_START, SESSION_CMD_PAUSE, SESSION_CMD_STOP, - SESSION_CMD_END, /* Internal use only. */ + /* Internally used commands. */ + SESSION_CMD_END, + SESSION_CMD_QM_NOTIFY_TOPOLOGY, };
struct session_op @@ -62,6 +64,10 @@ struct session_op GUID time_format; PROPVARIANT start_position; } start; + struct + { + IMFTopology *topology; + } notify_topology; } u; struct list entry; }; @@ -492,6 +498,10 @@ static ULONG WINAPI session_op_Release(IUnknown *iface) case SESSION_CMD_START: PropVariantClear(&op->u.start.start_position); break; + case SESSION_CMD_QM_NOTIFY_TOPOLOGY: + if (op->u.notify_topology.topology) + IMFTopology_Release(op->u.notify_topology.topology); + break; default: ; } @@ -1301,9 +1311,21 @@ static HRESULT session_set_current_topology(struct media_session *session, IMFTo DWORD caps, object_flags; struct media_sink *sink; struct topo_node *node; + struct session_op *op; IMFMediaEvent *event; HRESULT hr;
+ if (session->quality_manager) + { + if (SUCCEEDED(create_session_op(SESSION_CMD_QM_NOTIFY_TOPOLOGY, &op))) + { + op->u.notify_topology.topology = topology; + IMFTopology_AddRef(op->u.notify_topology.topology); + session_submit_command(session, op); + IUnknown_Release(&op->IUnknown_iface); + } + } + if (FAILED(hr = IMFTopology_CloneFrom(session->presentation.current_topology, topology))) { WARN("Failed to clone topology, hr %#x.\n", hr); @@ -1929,6 +1951,9 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface, case SESSION_CMD_CLOSE: session_close(session); break; + case SESSION_CMD_QM_NOTIFY_TOPOLOGY: + IMFQualityManager_NotifyTopology(session->quality_manager, op->u.notify_topology.topology); + break; default: ; } @@ -4481,7 +4506,7 @@ static HRESULT WINAPI standard_quality_manager_NotifyTopology(IMFQualityManager { FIXME("%p, %p stub.\n", iface, topology);
- return E_NOTIMPL; + return S_OK; }
static HRESULT WINAPI standard_quality_manager_NotifyPresentationClock(IMFQualityManager *iface,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 8d5ff6d5c07..5bbd47b3418 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -2465,7 +2465,7 @@ static struct sample *transform_create_sample(IMFSample *sample) return sample_entry; }
-static HRESULT transform_node_pull_samples(struct topo_node *node) +static HRESULT transform_node_pull_samples(const struct media_session *session, struct topo_node *node) { MFT_OUTPUT_STREAM_INFO stream_info; MFT_OUTPUT_DATA_BUFFER *buffers; @@ -2518,6 +2518,9 @@ static HRESULT transform_node_pull_samples(struct topo_node *node)
if (SUCCEEDED(hr) && !(buffers[i].dwStatus & MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) { + if (session->quality_manager) + IMFQualityManager_NotifyProcessOutput(session->quality_manager, node->node, i, buffers[i].pSample); + queued_sample = transform_create_sample(buffers[i].pSample); list_add_tail(&node->u.transform.outputs[i].samples, &queued_sample->entry); } @@ -2544,6 +2547,9 @@ static void session_deliver_sample_to_node(struct media_session *session, IMFTop unsigned int i; HRESULT hr;
+ if (session->quality_manager) + IMFQualityManager_NotifyProcessInput(session->quality_manager, node, input, sample); + IMFTopologyNode_GetNodeType(node, &node_type); IMFTopologyNode_GetTopoNodeID(node, &node_id);
@@ -2569,7 +2575,7 @@ static void session_deliver_sample_to_node(struct media_session *session, IMFTop break; case MF_TOPOLOGY_TRANSFORM_NODE:
- transform_node_pull_samples(topo_node); + transform_node_pull_samples(session, topo_node);
sample_entry = transform_create_sample(sample); list_add_tail(&topo_node->u.transform.inputs[input].samples, &sample_entry->entry); @@ -2603,7 +2609,7 @@ static void session_deliver_sample_to_node(struct media_session *session, IMFTop WARN("Drain command failed for transform, hr %#x.\n", hr); }
- transform_node_pull_samples(topo_node); + transform_node_pull_samples(session, topo_node);
/* Remaining unprocessed input has been discarded, now queue markers for every output. */ if (drain) @@ -4532,7 +4538,7 @@ static HRESULT WINAPI standard_quality_manager_NotifyPresentationClock(IMFQualit static HRESULT WINAPI standard_quality_manager_NotifyProcessInput(IMFQualityManager *iface, IMFTopologyNode *node, LONG input_index, IMFSample *sample) { - FIXME("%p, %p, %d, %p stub.\n", iface, node, input_index, sample); + TRACE("%p, %p, %d, %p stub.\n", iface, node, input_index, sample);
return E_NOTIMPL; } @@ -4540,7 +4546,7 @@ static HRESULT WINAPI standard_quality_manager_NotifyProcessInput(IMFQualityMana static HRESULT WINAPI standard_quality_manager_NotifyProcessOutput(IMFQualityManager *iface, IMFTopologyNode *node, LONG output_index, IMFSample *sample) { - FIXME("%p, %p, %d, %p stub.\n", iface, node, output_index, sample); + TRACE("%p, %p, %d, %p stub.\n", iface, node, output_index, sample);
return E_NOTIMPL; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 5bbd47b3418..d586f1c6be9 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -2910,6 +2910,7 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM IMFMediaEventGenerator *event_source; IMFMediaEvent *event = NULL; MediaEventType event_type; + IUnknown *object = NULL; IMFMediaSource *source; IMFMediaStream *stream; PROPVARIANT value; @@ -3057,6 +3058,21 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM (IMFStreamSink *)event_source); LeaveCriticalSection(&session->cs);
+ break; + case MEQualityNotify: + + if (session->quality_manager) + { + if (FAILED(IMFMediaEventGenerator_QueryInterface(event_source, &IID_IMFStreamSink, (void **)&object))) + IMFMediaEventGenerator_QueryInterface(event_source, &IID_IMFTransform, (void **)&object); + + if (object) + { + IMFQualityManager_NotifyQualityEvent(session->quality_manager, object, event); + IUnknown_Release(object); + } + } + break; default: ;