From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/session.c | 128 +++++++++++++++++++++++++++------------------- 1 file changed, 75 insertions(+), 53 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index f31bd92380b..474c4a58a94 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -145,15 +145,9 @@ struct media_sink BOOL finalized; };
-struct sample -{ - struct list entry; - IMFSample *sample; -}; - struct transform_stream { - struct list samples; + IMFCollection *events; unsigned int requests; unsigned int min_buffer_size; BOOL draining; @@ -675,41 +669,30 @@ static void session_set_caps(struct media_session *session, DWORD caps) IMFMediaEvent_Release(event); }
-static HRESULT transform_stream_push_sample(struct transform_stream *stream, IMFSample *sample) +static void transform_stream_push_sample(struct transform_stream *stream, IMFSample *sample) { - struct sample *entry; - - if (!(entry = calloc(1, sizeof(*entry)))) - return E_OUTOFMEMORY; - - entry->sample = sample; - IMFSample_AddRef(entry->sample); + PROPVARIANT value = {.vt = VT_UNKNOWN, .punkVal = (IUnknown *)sample}; + IMFMediaEvent *event;
- list_add_tail(&stream->samples, &entry->entry); - return S_OK; + if (SUCCEEDED(MFCreateMediaEvent(MEMediaSample, &GUID_NULL, S_OK, &value, &event))) + { + IMFCollection_AddElement(stream->events, (IUnknown *)event); + IMFMediaEvent_Release(event); + } }
-static HRESULT transform_stream_pop_sample(struct transform_stream *stream, IMFSample **sample) +static HRESULT transform_stream_pop_event(struct transform_stream *stream, IMFMediaEvent **event) { - struct sample *entry; - struct list *ptr; - - if (!(ptr = list_head(&stream->samples))) - return MF_E_TRANSFORM_NEED_MORE_INPUT; - - entry = LIST_ENTRY(ptr, struct sample, entry); - list_remove(&entry->entry); - *sample = entry->sample; - free(entry); - return S_OK; + HRESULT hr = IMFCollection_RemoveElement(stream->events, 0, (IUnknown **)event); + return hr == E_INVALIDARG ? MF_E_TRANSFORM_NEED_MORE_INPUT : hr; }
-static void transform_stream_drop_samples(struct transform_stream *stream) +static void transform_stream_drop_events(struct transform_stream *stream) { - IMFSample *sample; + IMFMediaEvent *event;
- while (SUCCEEDED(transform_stream_pop_sample(stream, &sample))) - IMFSample_Release(sample); + while (SUCCEEDED(transform_stream_pop_event(stream, &event))) + IMFMediaEvent_Release(event); }
static void release_topo_node(struct topo_node *node) @@ -724,9 +707,15 @@ static void release_topo_node(struct topo_node *node) break; case MF_TOPOLOGY_TRANSFORM_NODE: for (i = 0; i < node->u.transform.input_count; ++i) - transform_stream_drop_samples(&node->u.transform.inputs[i]); + { + transform_stream_drop_events(&node->u.transform.inputs[i]); + IMFCollection_Release(node->u.transform.inputs[i].events); + } for (i = 0; i < node->u.transform.output_count; ++i) - transform_stream_drop_samples(&node->u.transform.outputs[i]); + { + transform_stream_drop_events(&node->u.transform.outputs[i]); + IMFCollection_Release(node->u.transform.outputs[i].events); + } free(node->u.transform.inputs); free(node->u.transform.outputs); free(node->u.transform.input_map); @@ -1630,14 +1619,14 @@ static HRESULT session_set_transform_stream_info(struct topo_node *node)
streams = calloc(input_count, sizeof(*streams)); for (i = 0; i < input_count; ++i) - list_init(&streams[i].samples); + MFCreateCollection(&streams[i].events); node->u.transform.inputs = streams; node->u.transform.input_count = input_count;
streams = calloc(output_count, sizeof(*streams)); for (i = 0; i < output_count; ++i) { - list_init(&streams[i].samples); + MFCreateCollection(&streams[i].events);
if (SUCCEEDED(IMFTransform_GetOutputCurrentType(node->object.transform, transform_node_get_stream_id(node, TRUE, i), &media_type))) @@ -3255,8 +3244,7 @@ static HRESULT transform_node_pull_samples(const struct media_session *session, { if (session->quality_manager) IMFQualityManager_NotifyProcessOutput(session->quality_manager, node->node, i, buffers[i].pSample); - if (FAILED(hr = transform_stream_push_sample(stream, buffers[i].pSample))) - WARN("Failed to queue output sample, hr %#lx\n", hr); + transform_stream_push_sample(stream, buffers[i].pSample); } }
@@ -3304,7 +3292,7 @@ static HRESULT transform_node_push_sample(const struct media_session *session, s { hr = IMFTransform_ProcessInput(transform, id, sample, 0); if (hr == MF_E_NOTACCEPTING) - hr = transform_stream_push_sample(stream, sample); + transform_stream_push_sample(stream, sample); } else { @@ -3320,12 +3308,40 @@ static HRESULT transform_node_push_sample(const struct media_session *session, s static void session_deliver_sample_to_node(struct media_session *session, struct topo_node *topo_node, unsigned int input, IMFSample *sample);
+static HRESULT transform_stream_handle_event(struct media_session *session, struct transform_stream *stream, + struct topo_node *topo_node, unsigned int input, IMFMediaEvent *event) +{ + MediaEventType type; + PROPVARIANT value; + HRESULT hr; + + if (FAILED(hr = IMFMediaEvent_GetType(event, &type))) + return hr; + PropVariantInit(&value); + + switch (type) + { + case MEMediaSample: + if (SUCCEEDED(hr = IMFMediaEvent_GetValue(event, &value))) + session_deliver_sample_to_node(session, topo_node, input, (IMFSample *)value.punkVal); + break; + + default: + ERR("Unexpected event type %lu\n", type); + hr = E_NOTIMPL; + break; + } + + PropVariantClear(&value); + return hr; +} + static void transform_node_deliver_samples(struct media_session *session, struct topo_node *topo_node) { BOOL drained = transform_node_is_drained(topo_node); struct topo_node *up_node, *down_node; + IMFMediaEvent *event; DWORD output, input; - IMFSample *sample; HRESULT hr = S_OK;
/* Push down all available output. */ @@ -3341,18 +3357,22 @@ static void transform_node_deliver_samples(struct media_session *session, struct
while (stream->requests) { - if (FAILED(hr = transform_stream_pop_sample(stream, &sample))) + MediaEventType type; + + if (FAILED(hr = transform_stream_pop_event(stream, &event))) { /* try getting more samples by calling IMFTransform_ProcessOutput */ if (FAILED(hr = transform_node_pull_samples(session, topo_node))) break; - if (FAILED(hr = transform_stream_pop_sample(stream, &sample))) + if (FAILED(hr = transform_stream_pop_event(stream, &event))) break; }
- session_deliver_sample_to_node(session, down_node, input, sample); - stream->requests--; - IMFSample_Release(sample); + if (FAILED(hr = transform_stream_handle_event(session, stream, down_node, input, event))) + ERR("Failed to handle stream event, hr %#lx\n", hr); + else if (SUCCEEDED(IMFMediaEvent_GetType(event, &type)) && type == MEMediaSample) + stream->requests--; + IMFMediaEvent_Release(event); }
while (stream->requests && drained) @@ -3369,10 +3389,11 @@ static void transform_node_deliver_samples(struct media_session *session, struct input = topo_node->u.transform.next_input++ % topo_node->u.transform.input_count; stream = &topo_node->u.transform.inputs[input];
- if (SUCCEEDED(transform_stream_pop_sample(stream, &sample))) + if (SUCCEEDED(transform_stream_pop_event(stream, &event))) { - session_deliver_sample_to_node(session, topo_node, input, sample); - IMFSample_Release(sample); + if (FAILED(hr = transform_stream_handle_event(session, stream, topo_node, input, event))) + ERR("Failed to handle stream event, hr %#lx\n", hr); + IMFMediaEvent_Release(event); } else if (!(up_node = session_get_topo_node_input(session, topo_node, input, &output))) WARN("Failed to node %p/%lu input\n", topo_node, input); @@ -3439,7 +3460,6 @@ static HRESULT session_request_sample_from_node(struct media_session *session, s { struct topo_node *down_node; HRESULT hr = S_OK; - IMFSample *sample; DWORD input;
switch (topo_node->type) @@ -3451,6 +3471,7 @@ static HRESULT session_request_sample_from_node(struct media_session *session, s case MF_TOPOLOGY_TRANSFORM_NODE: { struct transform_stream *stream = &topo_node->u.transform.outputs[output]; + IMFMediaEvent *event;
if (!(down_node = session_get_topo_node_output(session, topo_node, output, &input))) { @@ -3458,10 +3479,11 @@ static HRESULT session_request_sample_from_node(struct media_session *session, s break; }
- if (SUCCEEDED(transform_stream_pop_sample(stream, &sample))) + if (SUCCEEDED(transform_stream_pop_event(stream, &event))) { - session_deliver_sample_to_node(session, down_node, input, sample); - IMFSample_Release(sample); + if (FAILED(hr = transform_stream_handle_event(session, stream, down_node, input, event))) + ERR("Failed to handle stream event, hr %#lx\n", hr); + IMFMediaEvent_Release(event); } else if (transform_node_has_requests(topo_node)) {