Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 110 ++++++++++++++++++++++++++++++------- dlls/mfplat/tests/mfplat.c | 23 ++++++-- 2 files changed, 107 insertions(+), 26 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 69633134f5..1727ff1e90 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -1136,9 +1136,78 @@ static HRESULT WINAPI sample_GetBufferByIndex(IMFSample *iface, DWORD index, IMF return hr; }
+static unsigned int sample_get_total_length(struct sample *sample) +{ + DWORD total_length = 0, length; + size_t i; + + for (i = 0; i < sample->buffer_count; ++i) + { + length = 0; + if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample->buffers[i], &length))) + total_length += length; + } + + return total_length; +} + +static HRESULT sample_copy_to_buffer(struct sample *sample, IMFMediaBuffer *buffer) +{ + DWORD total_length, dst_length, dst_current_length, src_max_length, current_length; + BYTE *src_ptr, *dst_ptr; + BOOL locked; + HRESULT hr; + size_t i; + + total_length = sample_get_total_length(sample); + dst_current_length = 0; + + dst_ptr = NULL; + dst_length = current_length = 0; + locked = SUCCEEDED(hr = IMFMediaBuffer_Lock(buffer, &dst_ptr, &dst_length, ¤t_length)); + if (locked) + { + if (dst_length < total_length) + hr = MF_E_BUFFERTOOSMALL; + else if (dst_ptr) + { + for (i = 0; i < sample->buffer_count && SUCCEEDED(hr); ++i) + { + src_ptr = NULL; + src_max_length = current_length = 0; + if (SUCCEEDED(hr = IMFMediaBuffer_Lock(sample->buffers[i], &src_ptr, &src_max_length, ¤t_length))) + { + if (src_ptr) + { + if (current_length > dst_length) + hr = MF_E_BUFFERTOOSMALL; + else if (current_length) + { + memcpy(dst_ptr, src_ptr, current_length); + dst_length -= current_length; + dst_current_length += current_length; + dst_ptr += current_length; + } + } + IMFMediaBuffer_Unlock(sample->buffers[i]); + } + } + } + } + + IMFMediaBuffer_SetCurrentLength(buffer, dst_current_length); + + if (locked) + IMFMediaBuffer_Unlock(buffer); + + return hr; +} + static HRESULT WINAPI sample_ConvertToContiguousBuffer(IMFSample *iface, IMFMediaBuffer **buffer) { struct sample *sample = impl_from_IMFSample(iface); + unsigned int total_length, i; + IMFMediaBuffer *dest_buffer; HRESULT hr = S_OK;
TRACE("%p, %p.\n", iface, buffer); @@ -1147,15 +1216,29 @@ static HRESULT WINAPI sample_ConvertToContiguousBuffer(IMFSample *iface, IMFMedi
if (sample->buffer_count == 0) hr = E_UNEXPECTED; - else if (sample->buffer_count == 1) + else if (sample->buffer_count > 1) { - *buffer = sample->buffers[0]; - IMFMediaBuffer_AddRef(*buffer); + total_length = sample_get_total_length(sample); + if (SUCCEEDED(hr = MFCreateMemoryBuffer(total_length, &dest_buffer))) + { + if (SUCCEEDED(hr = sample_copy_to_buffer(sample, dest_buffer))) + { + for (i = 0; i < sample->buffer_count; ++i) + IMFMediaBuffer_Release(sample->buffers[i]); + + sample->buffers[0] = dest_buffer; + IMFMediaBuffer_AddRef(sample->buffers[0]); + + sample->buffer_count = 1; + } + IMFMediaBuffer_Release(dest_buffer); + } } - else + + if (SUCCEEDED(hr)) { - FIXME("Samples with multiple buffers are not supported.\n"); - hr = E_NOTIMPL; + *buffer = sample->buffers[0]; + IMFMediaBuffer_AddRef(*buffer); }
LeaveCriticalSection(&sample->attributes.cs); @@ -1225,21 +1308,6 @@ static HRESULT WINAPI sample_RemoveAllBuffers(IMFSample *iface) return S_OK; }
-static DWORD sample_get_total_length(struct sample *sample) -{ - DWORD total_length = 0, length; - size_t i; - - for (i = 0; i < sample->buffer_count; ++i) - { - length = 0; - if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample->buffers[i], &length))) - total_length += length; - } - - return total_length; -} - static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_length) { struct sample *sample = impl_from_IMFSample(iface); diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index bf63337b60..a2bc7115a5 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -1778,7 +1778,7 @@ static void test_system_memory_buffer(void) static void test_sample(void) { static const DWORD test_pattern = 0x22222222; - IMFMediaBuffer *buffer, *buffer2; + IMFMediaBuffer *buffer, *buffer2, *buffer3; DWORD count, flags, length; IMFAttributes *attributes; IMFSample *sample; @@ -1998,9 +1998,15 @@ static void test_sample(void) ok(buffer2 == buffer, "Unexpected buffer instance.\n"); IMFMediaBuffer_Release(buffer2);
+ hr = IMFMediaBuffer_SetCurrentLength(buffer, 3); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = MFCreateMemoryBuffer(16, &buffer2); ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
+ hr = IMFMediaBuffer_SetCurrentLength(buffer2, 4); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFSample_AddBuffer(sample, buffer2); ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr); IMFMediaBuffer_Release(buffer2); @@ -2009,15 +2015,22 @@ static void test_sample(void) ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr); ok(count == 2, "Unexpected buffer count %u.\n", count);
- hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer2); -todo_wine + hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer3); ok(hr == S_OK, "Failed to convert, hr %#x.\n", hr); + + hr = IMFMediaBuffer_GetMaxLength(buffer3, &length); + ok(hr == S_OK, "Failed to get maximum length, hr %#x.\n", hr); + ok(length == 7, "Unexpected length %u.\n", length); + + hr = IMFMediaBuffer_GetCurrentLength(buffer3, &length); + ok(hr == S_OK, "Failed to get maximum length, hr %#x.\n", hr); + ok(length == 7, "Unexpected length %u.\n", length); + if (SUCCEEDED(hr)) - IMFMediaBuffer_Release(buffer2); + IMFMediaBuffer_Release(buffer3);
hr = IMFSample_GetBufferCount(sample, &count); ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr); -todo_wine ok(count == 1, "Unexpected buffer count %u.\n", count);
IMFMediaBuffer_Release(buffer);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 2 +- dlls/mfplat/tests/mfplat.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 1727ff1e90..7c123e3e65 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -1235,7 +1235,7 @@ static HRESULT WINAPI sample_ConvertToContiguousBuffer(IMFSample *iface, IMFMedi } }
- if (SUCCEEDED(hr)) + if (SUCCEEDED(hr) && buffer) { *buffer = sample->buffers[0]; IMFMediaBuffer_AddRef(*buffer); diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index a2bc7115a5..8f0abb8ec7 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -1993,6 +1993,9 @@ static void test_sample(void) ok(buffer2 == buffer, "Unexpected buffer instance.\n"); IMFMediaBuffer_Release(buffer2);
+ hr = IMFSample_ConvertToContiguousBuffer(sample, NULL); + ok(hr == S_OK, "Failed to convert, hr %#x.\n", hr); + hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer2); ok(hr == S_OK, "Failed to convert, hr %#x.\n", hr); ok(buffer2 == buffer, "Unexpected buffer instance.\n"); @@ -2026,8 +2029,21 @@ static void test_sample(void) ok(hr == S_OK, "Failed to get maximum length, hr %#x.\n", hr); ok(length == 7, "Unexpected length %u.\n", length);
- if (SUCCEEDED(hr)) - IMFMediaBuffer_Release(buffer3); + IMFMediaBuffer_Release(buffer3); + + hr = IMFSample_GetBufferCount(sample, &count); + ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr); + ok(count == 1, "Unexpected buffer count %u.\n", count); + + hr = IMFSample_AddBuffer(sample, buffer); + ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr); + + hr = IMFSample_GetBufferCount(sample, &count); + ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr); + ok(count == 2, "Unexpected buffer count %u.\n", count); + + hr = IMFSample_ConvertToContiguousBuffer(sample, NULL); + ok(hr == S_OK, "Failed to convert, hr %#x.\n", hr);
hr = IMFSample_GetBufferCount(sample, &count); ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 7c123e3e65..323603cf21 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -24,7 +24,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
-#define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1))) +#define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment)))
struct memory_buffer { @@ -262,7 +262,7 @@ static HRESULT WINAPI memory_1d_2d_buffer_Lock(IMFMediaBuffer *iface, BYTE **dat hr = MF_E_INVALIDREQUEST; else if (!buffer->_2d.linear_buffer) { - if (!(buffer->_2d.linear_buffer = heap_alloc(ALIGN_SIZE(buffer->_2d.plane_size, 64)))) + if (!(buffer->_2d.linear_buffer = heap_alloc(ALIGN_SIZE(buffer->_2d.plane_size, MF_64_BYTE_ALIGNMENT)))) hr = E_OUTOFMEMORY; }
@@ -575,7 +575,7 @@ static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bo if (!object) return E_OUTOFMEMORY;
- pitch = ALIGN_SIZE(width * bpp, 64); + pitch = ALIGN_SIZE(width * bpp, MF_64_BYTE_ALIGNMENT);
switch (fourcc) {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=67352
Your paranoid android.
=== debiant (32 bit WoW report) ===
mfplat: Unhandled exception: page fault on read access to 0x00000009 in 32-bit code (0x658820b7).
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/main.c b/dlls/mf/main.c index ecf7de23b6..20b587e413 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -1957,6 +1957,7 @@ static HRESULT WINAPI sample_copier_transform_ProcessOutput(IMFTransform *iface, MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status) { struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + IMFMediaBuffer *buffer; DWORD sample_flags; HRESULT hr = S_OK; LONGLONG time; @@ -1981,7 +1982,15 @@ static HRESULT WINAPI sample_copier_transform_ProcessOutput(IMFTransform *iface, if (SUCCEEDED(IMFSample_GetSampleFlags(transform->sample, &sample_flags))) IMFSample_SetSampleFlags(buffers->pSample, sample_flags);
- FIXME("Copy buffers.\n"); + if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(transform->sample, NULL))) + { + if (SUCCEEDED(IMFSample_GetBufferByIndex(buffers->pSample, 0, &buffer))) + { + if (FAILED(IMFSample_CopyToBuffer(transform->sample, buffer))) + hr = MF_E_UNEXPECTED; + IMFMediaBuffer_Release(buffer); + } + }
IMFSample_Release(transform->sample); transform->sample = NULL;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 07cfc4ee8c..69d1fdf569 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -2492,6 +2492,38 @@ static void session_deliver_sample(struct media_session *session, IMFMediaStream IMFTopologyNode_Release(downstream_node); }
+static void session_sink_invalidated(struct media_session *session, IMFMediaEvent *event, IMFStreamSink *sink) +{ + struct topo_node *node, *sink_node = NULL; + HRESULT hr; + + LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry) + { + if (node->type == MF_TOPOLOGY_OUTPUT_NODE && node->object.sink_stream == sink) + { + sink_node = node; + break; + } + } + + if (!sink_node) + return; + + if (!event) + { + if (FAILED(hr = MFCreateMediaEvent(MESinkInvalidated, &GUID_NULL, S_OK, NULL, &event))) + WARN("Failed to create event, hr %#x.\n", hr); + } + + if (!event) + return; + + IMFMediaEvent_SetUINT64(event, &MF_EVENT_OUTPUT_NODE, sink_node->node_id); + IMFMediaEventQueue_QueueEvent(session->event_queue, event); + + session_set_topo_status(session, S_OK, MF_TOPOSTATUS_ENDED); +} + static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct media_session *session = impl_from_events_callback_IMFAsyncCallback(iface); @@ -2573,13 +2605,31 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM EnterCriticalSection(&session->cs); session_request_sample(session, (IMFStreamSink *)event_source); LeaveCriticalSection(&session->cs); - break;
+ break; case MEMediaSample:
EnterCriticalSection(&session->cs); session_deliver_sample(session, (IMFMediaStream *)event_source, &value); LeaveCriticalSection(&session->cs); + + break; + case MEAudioSessionDeviceRemoved: + case MEAudioSessionDisconnected: + case MEAudioSessionExclusiveModeOverride: + case MEAudioSessionFormatChanged: + case MEAudioSessionServerShutdown: + + IMFMediaEventQueue_QueueEvent(session->event_queue, event); + /* fallthrough */ + case MESinkInvalidated: + + EnterCriticalSection(&session->cs); + session_sink_invalidated(session, event_type == MESinkInvalidated ? event : NULL, + (IMFStreamSink *)event_source); + LeaveCriticalSection(&session->cs); + + break; default: ; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 323603cf21..05e1ce5fd6 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -97,16 +97,13 @@ static HRESULT WINAPI memory_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID IsEqualIID(riid, &IID_IUnknown)) { *out = &buffer->IMFMediaBuffer_iface; - } - else - { - FIXME("(%s, %p)\n", debugstr_guid(riid), out); - *out = NULL; - return E_NOINTERFACE; + IMFMediaBuffer_AddRef(iface); + return S_OK; }
- IUnknown_AddRef((IUnknown*)*out); - return S_OK; + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; }
static ULONG WINAPI memory_buffer_AddRef(IMFMediaBuffer *iface)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=67350
Your paranoid android.
=== w1064v1809_2scr (32 bit report) ===
mfplat: mfplat.c:2707: Test failed: Unexpected return value 0x102. mfplat.c:2058: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:2061: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:2064: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. mfplat.c:2067: Test failed: Unexpected result, hr 0xc00d3e85. 1994:mfplat: unhandled exception c0000005 at 00401AFB
=== w1064v1809_ja (32 bit report) ===
mfplat: mfplat.c:2707: Test failed: Unexpected return value 0x102. mfplat.c:2058: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:2061: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:2064: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. mfplat.c:2067: Test failed: Unexpected result, hr 0xc00d3e85. 048c:mfplat: unhandled exception c0000005 at 00401AFB