Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
[PATCH 4/5] mfplat/tests: Test interaction between Lock2D() and LockRect().
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
dlls/mfplat/tests/mfplat.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index c9da9fecef4..16599532d8f 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -6520,9 +6520,23 @@ static void test_MFCreateDXSurfaceBuffer(void)
hr = IMF2DBuffer_GetScanline0AndPitch(_2dbuffer, &data, &pitch);
ok(hr == HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED), "Unexpected hr %#lx.\n", hr);
+ hr = IDirect3DSurface9_LockRect(backbuffer, &locked_rect, NULL, 0);
+ ok(hr == S_OK, "Failed to lock back buffer, hr %#lx.\n", hr);
+
+ /* Cannot lock the buffer while the surface is locked. */
+ hr = IMF2DBuffer_Lock2D(_2dbuffer, &data, &pitch);
+ ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr);
+
+ hr = IDirect3DSurface9_UnlockRect(backbuffer);
+ ok(hr == S_OK, "Failed to unlock back buffer, hr %#lx.\n", hr);
+
hr = IMF2DBuffer_Lock2D(_2dbuffer, &data, &pitch);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ /* Cannot lock the surface once the buffer is locked. */
+ hr = IDirect3DSurface9_LockRect(backbuffer, &locked_rect, NULL, 0);
+ ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr);
+
hr = IMF2DBuffer_GetScanline0AndPitch(_2dbuffer, &data, &pitch);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
--
2.36.1
June 13, 2022
[PATCH 3/5] mfplat/tests: Test interaction between Lock() and LockRect().
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
dlls/mfplat/tests/mfplat.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 9a326ae5243..c9da9fecef4 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -6392,6 +6392,7 @@ static void test_MFCreateDXSurfaceBuffer(void)
{
IDirect3DSurface9 *backbuffer = NULL, *surface;
IDirect3DSwapChain9 *swapchain;
+ D3DLOCKED_RECT locked_rect;
DWORD length, max_length;
IDirect3DDevice9 *device;
IMF2DBuffer2 *_2dbuffer2;
@@ -6464,9 +6465,32 @@ static void test_MFCreateDXSurfaceBuffer(void)
ok(hr == S_OK, "Failed to get length, hr %#lx.\n", hr);
ok(length == 2 * max_length, "Unexpected length %lu.\n", length);
+ hr = IDirect3DSurface9_LockRect(backbuffer, &locked_rect, NULL, 0);
+ ok(hr == S_OK, "Failed to lock back buffer, hr %#lx.\n", hr);
+
+ /* Cannot lock while the surface is locked. */
+ hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
+ ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#lx.\n", hr);
+
+ hr = IDirect3DSurface9_UnlockRect(backbuffer);
+ ok(hr == S_OK, "Failed to unlock back buffer, hr %#lx.\n", hr);
+
+ hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(length == max_length, "Unexpected length %lu instead of %lu.\n", length, max_length);
+
+ /* You can lock the surface while the media buffer is locked. */
+ hr = IDirect3DSurface9_LockRect(backbuffer, &locked_rect, NULL, 0);
+ ok(hr == S_OK, "Failed to lock back buffer, hr %#lx.\n", hr);
+
hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- ok(length == max_length, "Unexpected length.\n");
+
+ hr = IMFMediaBuffer_Unlock(buffer);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+
+ hr = IDirect3DSurface9_UnlockRect(backbuffer);
+ ok(hr == S_OK, "Failed to unlock back buffer, hr %#lx.\n", hr);
/* Unlock twice. */
hr = IMFMediaBuffer_Unlock(buffer);
--
2.36.1
June 13, 2022
[PATCH 2/5] mfplat/buffer: Fix image copy function for IMC2/IMC4 buffers with odd height.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
dlls/mfplat/buffer.c | 3 +--
dlls/mfplat/tests/mfplat.c | 9 ++++-----
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index 39407ccc9e2..a7ba306223d 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -100,8 +100,7 @@ static void copy_image_imc1(BYTE *dest, LONG dest_stride, const BYTE *src, LONG
static void copy_image_imc2(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines)
{
- MFCopyImage(dest, dest_stride, src, src_stride, width / 2, lines / 2);
- MFCopyImage(dest + dest_stride / 2, dest_stride, src + src_stride / 2, src_stride, width / 2, lines / 2);
+ MFCopyImage(dest, dest_stride / 2, src, src_stride / 2, width / 2, lines);
}
static inline struct buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 8fddef8fd40..9a326ae5243 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -6028,12 +6028,11 @@ static void test_MFCreate2DMediaBuffer(void)
case MAKEFOURCC('I','M','C','2'):
case MAKEFOURCC('I','M','C','4'):
- for (j = ptr->height; j < length2 / stride; j++)
+ for (j = 0; ptr->height * stride + j * (stride / 2) < length2; j++)
for (k = 0; k < ptr->width / 2; k++)
- ok(data[j * pitch + k] == 0xff, "Unexpected byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k);
- for (j = ptr->height; j < length2 / stride; j++)
- for (k = pitch / 2; k < pitch / 2 + ptr->width / 2; k++)
- ok(data[j * pitch + k] == 0xff, "Unexpected byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k);
+ ok(data[ptr->height * pitch + j * (pitch / 2) + k] == 0xff,
+ "Unexpected byte %02x at test %d row %d column %d.\n",
+ data[ptr->height * pitch + j * (pitch / 2) + k], i, j, k);
break;
case MAKEFOURCC('N','V','1','2'):
--
2.36.1
June 13, 2022
[PATCH 1/5] mfplat/buffer: Fix size for IMC2/IMC4 buffers with odd height.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
dlls/mfplat/buffer.c | 22 +++++++++++++++++++---
dlls/mfplat/tests/mfplat.c | 9 ++-------
2 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index eada3df18ad..39407ccc9e2 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -1351,8 +1351,25 @@ static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bo
if (is_yuv && bottom_up)
return MF_E_INVALIDMEDIATYPE;
- if (FAILED(hr = MFGetPlaneSize(fourcc, width, height, &plane_size)))
- return hr;
+ switch (fourcc)
+ {
+ case MAKEFOURCC('I','M','C','1'):
+ case MAKEFOURCC('I','M','C','3'):
+ plane_size = stride * height * 2;
+ break;
+ case MAKEFOURCC('I','M','C','2'):
+ case MAKEFOURCC('I','M','C','4'):
+ plane_size = stride * 3 / 2 * height;
+ break;
+ case MAKEFOURCC('N','V','1','2'):
+ case MAKEFOURCC('Y','V','1','2'):
+ case MAKEFOURCC('I','4','2','0'):
+ case MAKEFOURCC('I','Y','U','V'):
+ plane_size = stride * height * 3 / 2;
+ break;
+ default:
+ plane_size = stride * height;
+ }
if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY;
@@ -1377,7 +1394,6 @@ static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bo
case MAKEFOURCC('I','M','C','1'):
case MAKEFOURCC('I','M','C','3'):
max_length = pitch * height * 2;
- plane_size *= 2;
break;
case MAKEFOURCC('N','V','1','2'):
case MAKEFOURCC('Y','V','1','2'):
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 28b89de4b1f..8fddef8fd40 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -5736,9 +5736,11 @@ static void test_MFCreate2DMediaBuffer(void)
{ 2, 2, MAKEFOURCC('I','M','C','2'), 6, 128, 0, 384 },
{ 4, 2, MAKEFOURCC('I','M','C','2'), 12, 128 },
{ 2, 4, MAKEFOURCC('I','M','C','2'), 12, 128 },
+ { 3, 5, MAKEFOURCC('I','M','C','2'), 20, 128 },
{ 2, 2, MAKEFOURCC('I','M','C','4'), 6, 128 },
{ 4, 2, MAKEFOURCC('I','M','C','4'), 12, 128 },
{ 2, 4, MAKEFOURCC('I','M','C','4'), 12, 128 },
+ { 3, 5, MAKEFOURCC('I','M','C','4'), 20, 128 },
{ 4, 2, MAKEFOURCC('I','M','C','1'), 32, 128, 2 },
{ 4, 4, MAKEFOURCC('I','M','C','1'), 64, 128, 2 },
@@ -5998,13 +6000,6 @@ static void test_MFCreate2DMediaBuffer(void)
hr = IMFMediaBuffer_Unlock(buffer);
ok(hr == S_OK, "Failed to unlock buffer, hr %#lx.\n", hr);
- hr = pMFGetPlaneSize(ptr->fourcc, ptr->width, ptr->height, &length2);
- ok(hr == S_OK, "Failed to get plane size, hr %#lx.\n", hr);
- if (ptr->plane_multiplier)
- length2 *= ptr->plane_multiplier;
- ok(length2 == length, "%d: contiguous length %lu does not match plane size %lu, %u x %u, format %s.\n", i, length,
- length2, ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->fourcc, 4));
-
hr = IMF2DBuffer_Lock2D(_2dbuffer, &data, &pitch);
ok(hr == S_OK, "Failed to lock buffer, hr %#lx.\n", hr);
--
2.36.1
June 13, 2022
[PATCH v2 6/6] winegstreamer: Remove copying support from wg_transform_push_data.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 3 ---
dlls/winegstreamer/unixlib.h | 2 --
dlls/winegstreamer/wg_sample.c | 8 +++++++-
dlls/winegstreamer/wg_transform.c | 12 +-----------
4 files changed, 8 insertions(+), 17 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index da0f1b103b3..e1abe7018da 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -102,9 +102,6 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
struct wg_transform *wg_transform_create(const struct wg_format *input_format,
const struct wg_format *output_format);
void wg_transform_destroy(struct wg_transform *transform);
-HRESULT wg_transform_push_data(struct wg_transform *transform, struct wg_sample *sample);
-HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample,
- struct wg_format *format);
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index ed56fb47908..860a8ab2a52 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -121,8 +121,6 @@ enum wg_sample_flag
WG_SAMPLE_FLAG_HAS_PTS = 2,
WG_SAMPLE_FLAG_HAS_DURATION = 4,
WG_SAMPLE_FLAG_SYNC_POINT = 8,
-
- WG_SAMPLE_FLAG_HAS_REFCOUNT = 0x10000, /* sample is queued on the client side and may be wrapped */
};
struct wg_sample
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
index 47892b71796..ae8a2d4d0c7 100644
--- a/dlls/winegstreamer/wg_sample.c
+++ b/dlls/winegstreamer/wg_sample.c
@@ -185,7 +185,6 @@ static void wg_sample_queue_begin_append(struct wg_sample_queue *queue, struct w
/* make sure a concurrent wg_sample_queue_flush call won't release the sample until we're done */
InterlockedIncrement(&wg_sample->refcount);
- sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_REFCOUNT;
EnterCriticalSection(&queue->cs);
list_add_tail(&queue->samples, &sample->entry);
@@ -245,6 +244,13 @@ void wg_sample_queue_destroy(struct wg_sample_queue *queue)
free(queue);
}
+/* These unixlib entry points should not be used directly, they assume samples
+ * to be queued and zero-copy support, use the helpers below instead.
+ */
+HRESULT wg_transform_push_data(struct wg_transform *transform, struct wg_sample *sample);
+HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample,
+ struct wg_format *format);
+
HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *wg_sample,
struct wg_sample_queue *queue)
{
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index d40f508250c..b5517f24515 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -542,17 +542,7 @@ NTSTATUS wg_transform_push_data(void *args)
return STATUS_SUCCESS;
}
- if (!(sample->flags & WG_SAMPLE_FLAG_HAS_REFCOUNT))
- {
- if (!(buffer = gst_buffer_new_and_alloc(sample->size)))
- {
- GST_ERROR("Failed to allocate input buffer");
- return STATUS_NO_MEMORY;
- }
- gst_buffer_fill(buffer, 0, sample->data, sample->size);
- GST_INFO("Copied %u bytes from sample %p to buffer %p", sample->size, sample, buffer);
- }
- else if (!(buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, sample->data, sample->max_size,
+ if (!(buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, sample->data, sample->max_size,
0, sample->size, sample, wg_sample_free_notify)))
{
GST_ERROR("Failed to allocate input buffer");
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/220
June 13, 2022
[PATCH v2 5/6] winegstreamer: Support zero-copy wg_transform_read_data in quartz_transform.c.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/quartz_transform.c | 31 +++---------------------
dlls/winegstreamer/wg_sample.c | 35 +++++++++++++++++++++++++++
3 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index a72d72bab18..da0f1b103b3 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -136,6 +136,7 @@ HRESULT wg_transform_push_quartz(struct wg_transform *transform, struct wg_sampl
struct wg_sample_queue *queue);
HRESULT wg_transform_read_mf(struct wg_transform *transform, struct wg_sample *sample,
struct wg_format *format);
+HRESULT wg_transform_read_quartz(struct wg_transform *transform, struct wg_sample *sample);
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c
index 5617e904bf7..30cfb7b855b 100644
--- a/dlls/winegstreamer/quartz_transform.c
+++ b/dlls/winegstreamer/quartz_transform.c
@@ -291,8 +291,6 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa
{
struct transform *filter = impl_from_strmbase_filter(pin->pin.filter);
struct wg_sample *wg_sample;
- REFERENCE_TIME start_time;
- REFERENCE_TIME end_time;
HRESULT hr;
/* We do not expect pin connection state to change while the filter is
@@ -334,10 +332,11 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa
return hr;
}
- hr = wg_transform_read_data(filter->transform, wg_sample, NULL);
+ hr = wg_transform_read_quartz(filter->transform, wg_sample);
+ wg_sample_release(wg_sample);
+
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
{
- wg_sample_release(wg_sample);
IMediaSample_Release(output_sample);
break;
}
@@ -345,36 +344,12 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa
{
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
FIXME("Unexpected stream format change!\n");
- wg_sample_release(wg_sample);
IMediaSample_Release(output_sample);
return hr;
}
wg_sample_queue_flush(filter->sample_queue, false);
- hr = IMediaSample_SetActualDataLength(output_sample, wg_sample->size);
- if (FAILED(hr))
- {
- wg_sample_release(wg_sample);
- IMediaSample_Release(output_sample);
- return hr;
- }
-
- if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
- {
- start_time = wg_sample->pts;
- if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
- {
- end_time = start_time + wg_sample->duration;
- IMediaSample_SetTime(output_sample, &start_time, &end_time);
- }
- else
- {
- IMediaSample_SetTime(output_sample, &start_time, NULL);
- }
- }
- wg_sample_release(wg_sample);
-
hr = IMemInputPin_Receive(filter->source.pMemInputPin, output_sample);
if (FAILED(hr))
{
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
index cd17b88cdd3..47892b71796 100644
--- a/dlls/winegstreamer/wg_sample.c
+++ b/dlls/winegstreamer/wg_sample.c
@@ -329,3 +329,38 @@ HRESULT wg_transform_push_quartz(struct wg_transform *transform, struct wg_sampl
return hr;
}
+
+HRESULT wg_transform_read_quartz(struct wg_transform *transform, struct wg_sample *wg_sample)
+{
+ struct sample *sample = unsafe_quartz_from_wg_sample(wg_sample);
+ REFERENCE_TIME start_time, end_time;
+ HRESULT hr;
+ BOOL value;
+
+ TRACE_(mfplat)("transform %p, wg_sample %p.\n", transform, wg_sample);
+
+ if (FAILED(hr = wg_transform_read_data(transform, wg_sample, NULL)))
+ return hr;
+
+ if (FAILED(hr = IMediaSample_SetActualDataLength(sample->u.quartz.sample, wg_sample->size)))
+ return hr;
+
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
+ {
+ start_time = wg_sample->pts;
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
+ {
+ end_time = start_time + wg_sample->duration;
+ IMediaSample_SetTime(sample->u.quartz.sample, &start_time, &end_time);
+ }
+ else
+ {
+ IMediaSample_SetTime(sample->u.quartz.sample, &start_time, NULL);
+ }
+ }
+
+ value = !!(wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT);
+ IMediaSample_SetSyncPoint(sample->u.quartz.sample, value);
+
+ return S_OK;
+}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/220
June 13, 2022
[PATCH v2 4/6] winegstreamer: Support zero-copy wg_transform_push_data in quartz_transform.c.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 2 ++
dlls/winegstreamer/quartz_transform.c | 18 +++-------------
dlls/winegstreamer/wg_sample.c | 31 +++++++++++++++++++++++++++
3 files changed, 36 insertions(+), 15 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 21bd4f25028..a72d72bab18 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -132,6 +132,8 @@ void wg_sample_release(struct wg_sample *wg_sample);
HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *sample,
struct wg_sample_queue *queue);
+HRESULT wg_transform_push_quartz(struct wg_transform *transform, struct wg_sample *sample,
+ struct wg_sample_queue *queue);
HRESULT wg_transform_read_mf(struct wg_transform *transform, struct wg_sample *sample,
struct wg_format *format);
diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c
index 2dd7d038f2f..5617e904bf7 100644
--- a/dlls/winegstreamer/quartz_transform.c
+++ b/dlls/winegstreamer/quartz_transform.c
@@ -315,21 +315,7 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa
if (FAILED(hr))
return hr;
- hr = IMediaSample_GetTime(sample, &start_time, &end_time);
- if (SUCCEEDED(hr))
- {
- wg_sample->pts = start_time;
- wg_sample->flags |= WG_SAMPLE_FLAG_HAS_PTS;
- }
- if (hr == S_OK)
- {
- wg_sample->duration = end_time - start_time;
- wg_sample->flags |= WG_SAMPLE_FLAG_HAS_DURATION;
- }
-
- hr = wg_transform_push_data(filter->transform, wg_sample);
- wg_sample_release(wg_sample);
-
+ hr = wg_transform_push_quartz(filter->transform, wg_sample, filter->sample_queue);
if (FAILED(hr))
return hr;
@@ -364,6 +350,8 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa
return hr;
}
+ wg_sample_queue_flush(filter->sample_queue, false);
+
hr = IMediaSample_SetActualDataLength(output_sample, wg_sample->size);
if (FAILED(hr))
{
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
index dded264b079..cd17b88cdd3 100644
--- a/dlls/winegstreamer/wg_sample.c
+++ b/dlls/winegstreamer/wg_sample.c
@@ -298,3 +298,34 @@ HRESULT wg_transform_read_mf(struct wg_transform *transform, struct wg_sample *w
return S_OK;
}
+
+HRESULT wg_transform_push_quartz(struct wg_transform *transform, struct wg_sample *wg_sample,
+ struct wg_sample_queue *queue)
+{
+ struct sample *sample = unsafe_quartz_from_wg_sample(wg_sample);
+ REFERENCE_TIME start_time, end_time;
+ HRESULT hr;
+
+ TRACE_(quartz)("transform %p, wg_sample %p, queue %p.\n", transform, wg_sample, queue);
+
+ hr = IMediaSample_GetTime(sample->u.quartz.sample, &start_time, &end_time);
+ if (SUCCEEDED(hr))
+ {
+ wg_sample->pts = start_time;
+ wg_sample->flags |= WG_SAMPLE_FLAG_HAS_PTS;
+ }
+ if (hr == S_OK)
+ {
+ wg_sample->duration = end_time - start_time;
+ wg_sample->flags |= WG_SAMPLE_FLAG_HAS_DURATION;
+ }
+
+ if (IMediaSample_IsSyncPoint(sample->u.quartz.sample) == S_OK)
+ wg_sample->flags |= WG_SAMPLE_FLAG_SYNC_POINT;
+
+ wg_sample_queue_begin_append(queue, wg_sample);
+ hr = wg_transform_push_data(transform, wg_sample);
+ wg_sample_queue_end_append(queue, wg_sample);
+
+ return hr;
+}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/220
June 13, 2022
[PATCH v2 3/6] winegstreamer: Introduce new wg_sample_create_quartz helper for quartz_transform.c.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/quartz_transform.c | 40 ++++++++++----------
dlls/winegstreamer/wg_sample.c | 54 +++++++++++++++++++++++++++
3 files changed, 75 insertions(+), 20 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index da76452fbf4..21bd4f25028 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -127,6 +127,7 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format);
void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format);
HRESULT wg_sample_create_mf(IMFSample *sample, struct wg_sample **out);
+HRESULT wg_sample_create_quartz(IMediaSample *sample, struct wg_sample **out);
void wg_sample_release(struct wg_sample *wg_sample);
HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *sample,
diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c
index b701b3f6369..2dd7d038f2f 100644
--- a/dlls/winegstreamer/quartz_transform.c
+++ b/dlls/winegstreamer/quartz_transform.c
@@ -290,7 +290,7 @@ static HRESULT transform_sink_query_interface(struct strmbase_pin *pin, REFIID i
static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSample *sample)
{
struct transform *filter = impl_from_strmbase_filter(pin->pin.filter);
- struct wg_sample input_wg_sample = {0};
+ struct wg_sample *wg_sample;
REFERENCE_TIME start_time;
REFERENCE_TIME end_time;
HRESULT hr;
@@ -311,50 +311,47 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa
if (filter->sink.flushing)
return S_FALSE;
- input_wg_sample.max_size = IMediaSample_GetSize(sample);
- input_wg_sample.size = IMediaSample_GetActualDataLength(sample);
-
- hr = IMediaSample_GetPointer(sample, &input_wg_sample.data);
+ hr = wg_sample_create_quartz(sample, &wg_sample);
if (FAILED(hr))
return hr;
hr = IMediaSample_GetTime(sample, &start_time, &end_time);
if (SUCCEEDED(hr))
{
- input_wg_sample.pts = start_time;
- input_wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
+ wg_sample->pts = start_time;
+ wg_sample->flags |= WG_SAMPLE_FLAG_HAS_PTS;
}
if (hr == S_OK)
{
- input_wg_sample.duration = end_time - start_time;
- input_wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
+ wg_sample->duration = end_time - start_time;
+ wg_sample->flags |= WG_SAMPLE_FLAG_HAS_DURATION;
}
- hr = wg_transform_push_data(filter->transform, &input_wg_sample);
+ hr = wg_transform_push_data(filter->transform, wg_sample);
+ wg_sample_release(wg_sample);
+
if (FAILED(hr))
return hr;
for (;;)
{
- struct wg_sample output_wg_sample = {0};
IMediaSample *output_sample;
hr = IMemAllocator_GetBuffer(filter->source.pAllocator, &output_sample, NULL, NULL, 0);
if (FAILED(hr))
return hr;
- output_wg_sample.max_size = IMediaSample_GetSize(output_sample);
-
- hr = IMediaSample_GetPointer(output_sample, &output_wg_sample.data);
+ hr = wg_sample_create_quartz(output_sample, &wg_sample);
if (FAILED(hr))
{
IMediaSample_Release(output_sample);
return hr;
}
- hr = wg_transform_read_data(filter->transform, &output_wg_sample, NULL);
+ hr = wg_transform_read_data(filter->transform, wg_sample, NULL);
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
{
+ wg_sample_release(wg_sample);
IMediaSample_Release(output_sample);
break;
}
@@ -362,23 +359,25 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa
{
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
FIXME("Unexpected stream format change!\n");
+ wg_sample_release(wg_sample);
IMediaSample_Release(output_sample);
return hr;
}
- hr = IMediaSample_SetActualDataLength(output_sample, output_wg_sample.size);
+ hr = IMediaSample_SetActualDataLength(output_sample, wg_sample->size);
if (FAILED(hr))
{
+ wg_sample_release(wg_sample);
IMediaSample_Release(output_sample);
return hr;
}
- if (output_wg_sample.flags & WG_SAMPLE_FLAG_HAS_PTS)
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
{
- start_time = output_wg_sample.pts;
- if (output_wg_sample.flags & WG_SAMPLE_FLAG_HAS_DURATION)
+ start_time = wg_sample->pts;
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
{
- end_time = start_time + output_wg_sample.duration;
+ end_time = start_time + wg_sample->duration;
IMediaSample_SetTime(output_sample, &start_time, &end_time);
}
else
@@ -386,6 +385,7 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa
IMediaSample_SetTime(output_sample, &start_time, NULL);
}
}
+ wg_sample_release(wg_sample);
hr = IMemInputPin_Receive(filter->source.pMemInputPin, output_sample);
if (FAILED(hr))
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
index cf57bdd996b..dded264b079 100644
--- a/dlls/winegstreamer/wg_sample.c
+++ b/dlls/winegstreamer/wg_sample.c
@@ -25,6 +25,7 @@
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+WINE_DECLARE_DEBUG_CHANNEL(quartz);
struct wg_sample_queue
{
@@ -51,6 +52,10 @@ struct sample
IMFSample *sample;
IMFMediaBuffer *buffer;
} mf;
+ struct
+ {
+ IMediaSample *sample;
+ } quartz;
} u;
};
@@ -110,6 +115,55 @@ fail:
return hr;
}
+static const struct wg_sample_ops quartz_sample_ops;
+
+static inline struct sample *unsafe_quartz_from_wg_sample(struct wg_sample *wg_sample)
+{
+ struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+ if (sample->ops != &quartz_sample_ops) return NULL;
+ return sample;
+}
+
+static void quartz_sample_destroy(struct wg_sample *wg_sample)
+{
+ struct sample *sample = unsafe_quartz_from_wg_sample(wg_sample);
+
+ TRACE_(quartz)("wg_sample %p.\n", wg_sample);
+
+ IMediaSample_Release(sample->u.quartz.sample);
+}
+
+static const struct wg_sample_ops quartz_sample_ops =
+{
+ quartz_sample_destroy,
+};
+
+HRESULT wg_sample_create_quartz(IMediaSample *media_sample, struct wg_sample **out)
+{
+ DWORD current_length, max_length;
+ struct sample *sample;
+ BYTE *buffer;
+ HRESULT hr;
+
+ if (FAILED(hr = IMediaSample_GetPointer(media_sample, &buffer)))
+ return hr;
+ current_length = IMediaSample_GetActualDataLength(media_sample);
+ max_length = IMediaSample_GetSize(media_sample);
+
+ if (!(sample = calloc(1, sizeof(*sample))))
+ return E_OUTOFMEMORY;
+
+ IMediaSample_AddRef((sample->u.quartz.sample = media_sample));
+ sample->wg_sample.data = buffer;
+ sample->wg_sample.size = current_length;
+ sample->wg_sample.max_size = max_length;
+ sample->ops = &quartz_sample_ops;
+
+ TRACE_(quartz)("Created wg_sample %p for IMediaSample %p.\n", &sample->wg_sample, media_sample);
+ *out = &sample->wg_sample;
+ return S_OK;
+}
+
void wg_sample_release(struct wg_sample *wg_sample)
{
struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/220
June 13, 2022
[PATCH v2 2/6] winegstreamer: Use a union in struct sample to keep API pointers.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/wg_sample.c | 81 ++++++++++++++++++++++++++--------
1 file changed, 62 insertions(+), 19 deletions(-)
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
index 051e6199ec9..cf57bdd996b 100644
--- a/dlls/winegstreamer/wg_sample.c
+++ b/dlls/winegstreamer/wg_sample.c
@@ -32,12 +32,51 @@ struct wg_sample_queue
struct list samples;
};
+struct wg_sample_ops
+{
+ void (*destroy)(struct wg_sample *sample);
+};
+
struct sample
{
- IMFSample *sample;
- IMFMediaBuffer *media_buffer;
struct wg_sample wg_sample;
+
+ const struct wg_sample_ops *ops;
struct list entry;
+
+ union
+ {
+ struct
+ {
+ IMFSample *sample;
+ IMFMediaBuffer *buffer;
+ } mf;
+ } u;
+};
+
+static const struct wg_sample_ops mf_sample_ops;
+
+static inline struct sample *unsafe_mf_from_wg_sample(struct wg_sample *wg_sample)
+{
+ struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+ if (sample->ops != &mf_sample_ops) return NULL;
+ return sample;
+}
+
+static void mf_sample_destroy(struct wg_sample *wg_sample)
+{
+ struct sample *sample = unsafe_mf_from_wg_sample(wg_sample);
+
+ TRACE_(mfplat)("wg_sample %p.\n", wg_sample);
+
+ IMFMediaBuffer_Unlock(sample->u.mf.buffer);
+ IMFMediaBuffer_Release(sample->u.mf.buffer);
+ IMFSample_Release(sample->u.mf.sample);
+}
+
+static const struct wg_sample_ops mf_sample_ops =
+{
+ mf_sample_destroy,
};
HRESULT wg_sample_create_mf(IMFSample *mf_sample, struct wg_sample **out)
@@ -49,23 +88,24 @@ HRESULT wg_sample_create_mf(IMFSample *mf_sample, struct wg_sample **out)
if (!(sample = calloc(1, sizeof(*sample))))
return E_OUTOFMEMORY;
- if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(mf_sample, &sample->media_buffer)))
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(mf_sample, &sample->u.mf.buffer)))
goto fail;
- if (FAILED(hr = IMFMediaBuffer_Lock(sample->media_buffer, &buffer, &max_length, ¤t_length)))
+ if (FAILED(hr = IMFMediaBuffer_Lock(sample->u.mf.buffer, &buffer, &max_length, ¤t_length)))
goto fail;
- IMFSample_AddRef((sample->sample = mf_sample));
+ IMFSample_AddRef((sample->u.mf.sample = mf_sample));
sample->wg_sample.data = buffer;
sample->wg_sample.size = current_length;
sample->wg_sample.max_size = max_length;
+ sample->ops = &mf_sample_ops;
*out = &sample->wg_sample;
TRACE_(mfplat)("Created wg_sample %p for IMFSample %p.\n", *out, mf_sample);
return S_OK;
fail:
- if (sample->media_buffer)
- IMFMediaBuffer_Release(sample->media_buffer);
+ if (sample->u.mf.buffer)
+ IMFMediaBuffer_Release(sample->u.mf.buffer);
free(sample);
return hr;
}
@@ -80,9 +120,7 @@ void wg_sample_release(struct wg_sample *wg_sample)
return;
}
- IMFMediaBuffer_Unlock(sample->media_buffer);
- IMFMediaBuffer_Release(sample->media_buffer);
- IMFSample_Release(sample->sample);
+ sample->ops->destroy(wg_sample);
free(sample);
}
@@ -156,22 +194,24 @@ void wg_sample_queue_destroy(struct wg_sample_queue *queue)
HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *wg_sample,
struct wg_sample_queue *queue)
{
- struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+ struct sample *sample = unsafe_mf_from_wg_sample(wg_sample);
LONGLONG time, duration;
UINT32 value;
HRESULT hr;
- if (SUCCEEDED(IMFSample_GetSampleTime(sample->sample, &time)))
+ TRACE_(mfplat)("transform %p, wg_sample %p, queue %p.\n", transform, wg_sample, queue);
+
+ if (SUCCEEDED(IMFSample_GetSampleTime(sample->u.mf.sample, &time)))
{
sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
sample->wg_sample.pts = time;
}
- if (SUCCEEDED(IMFSample_GetSampleDuration(sample->sample, &duration)))
+ if (SUCCEEDED(IMFSample_GetSampleDuration(sample->u.mf.sample, &duration)))
{
sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
sample->wg_sample.duration = duration;
}
- if (SUCCEEDED(IMFSample_GetUINT32(sample->sample, &MFSampleExtension_CleanPoint, &value)) && value)
+ if (SUCCEEDED(IMFSample_GetUINT32(sample->u.mf.sample, &MFSampleExtension_CleanPoint, &value)) && value)
sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT;
wg_sample_queue_begin_append(queue, wg_sample);
@@ -184,20 +224,23 @@ HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *w
HRESULT wg_transform_read_mf(struct wg_transform *transform, struct wg_sample *wg_sample,
struct wg_format *format)
{
- struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+ struct sample *sample = unsafe_mf_from_wg_sample(wg_sample);
HRESULT hr;
+ TRACE_(mfplat)("transform %p, wg_sample %p, format %p.\n", transform, wg_sample, format);
+
if (FAILED(hr = wg_transform_read_data(transform, wg_sample, format)))
return hr;
- IMFMediaBuffer_SetCurrentLength(sample->media_buffer, wg_sample->size);
+ if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(sample->u.mf.buffer, wg_sample->size)))
+ return hr;
if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
- IMFSample_SetSampleTime(sample->sample, wg_sample->pts);
+ IMFSample_SetSampleTime(sample->u.mf.sample, wg_sample->pts);
if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
- IMFSample_SetSampleDuration(sample->sample, wg_sample->duration);
+ IMFSample_SetSampleDuration(sample->u.mf.sample, wg_sample->duration);
if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT)
- IMFSample_SetUINT32(sample->sample, &MFSampleExtension_CleanPoint, 1);
+ IMFSample_SetUINT32(sample->u.mf.sample, &MFSampleExtension_CleanPoint, 1);
return S_OK;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/220
June 13, 2022
[PATCH v2 1/6] winegstreamer: Split wg_sample wrapper helpers to a separate source.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/Makefile.in | 1 +
dlls/winegstreamer/mfplat.c | 176 ----------------------------
dlls/winegstreamer/wg_sample.c | 203 +++++++++++++++++++++++++++++++++
3 files changed, 204 insertions(+), 176 deletions(-)
create mode 100644 dlls/winegstreamer/wg_sample.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index 50f4dc861d4..6e3517dcb36 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -17,6 +17,7 @@ C_SRCS = \
wg_allocator.c \
wg_format.c \
wg_parser.c \
+ wg_sample.c \
wg_transform.c \
wm_asyncreader.c \
wm_reader.c \
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 157ed3ad2f2..c5ca4b15c0f 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -958,179 +958,3 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
else
FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type));
}
-
-struct wg_sample_queue
-{
- CRITICAL_SECTION cs;
- struct list samples;
-};
-
-struct mf_sample
-{
- IMFSample *sample;
- IMFMediaBuffer *media_buffer;
- struct wg_sample wg_sample;
- struct list entry;
-};
-
-HRESULT wg_sample_create_mf(IMFSample *sample, struct wg_sample **out)
-{
- DWORD current_length, max_length;
- struct mf_sample *mf_sample;
- BYTE *buffer;
- HRESULT hr;
-
- if (!(mf_sample = calloc(1, sizeof(*mf_sample))))
- return E_OUTOFMEMORY;
- if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &mf_sample->media_buffer)))
- goto out;
- if (FAILED(hr = IMFMediaBuffer_Lock(mf_sample->media_buffer, &buffer, &max_length, ¤t_length)))
- goto out;
-
- IMFSample_AddRef((mf_sample->sample = sample));
- mf_sample->wg_sample.data = buffer;
- mf_sample->wg_sample.size = current_length;
- mf_sample->wg_sample.max_size = max_length;
-
- TRACE("Created mf_sample %p for sample %p.\n", mf_sample, sample);
- *out = &mf_sample->wg_sample;
- return S_OK;
-
-out:
- if (mf_sample->media_buffer)
- IMFMediaBuffer_Release(mf_sample->media_buffer);
- free(mf_sample);
- return hr;
-}
-
-void wg_sample_release(struct wg_sample *wg_sample)
-{
- struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample);
-
- if (InterlockedOr(&wg_sample->refcount, 0))
- {
- ERR("Sample %p is still in use, trouble ahead!\n", wg_sample);
- return;
- }
-
- IMFMediaBuffer_Unlock(mf_sample->media_buffer);
- IMFMediaBuffer_Release(mf_sample->media_buffer);
- IMFSample_Release(mf_sample->sample);
-
- free(mf_sample);
-}
-
-static void wg_sample_queue_begin_append(struct wg_sample_queue *queue, struct wg_sample *wg_sample)
-{
- struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample);
-
- /* make sure a concurrent wg_sample_queue_flush call won't release the sample until we're done */
- InterlockedIncrement(&wg_sample->refcount);
- mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_REFCOUNT;
-
- EnterCriticalSection(&queue->cs);
- list_add_tail(&queue->samples, &mf_sample->entry);
- LeaveCriticalSection(&queue->cs);
-}
-
-static void wg_sample_queue_end_append(struct wg_sample_queue *queue, struct wg_sample *wg_sample)
-{
- /* release temporary ref taken in wg_sample_queue_begin_append */
- InterlockedDecrement(&wg_sample->refcount);
-
- wg_sample_queue_flush(queue, false);
-}
-
-void wg_sample_queue_flush(struct wg_sample_queue *queue, bool all)
-{
- struct mf_sample *mf_sample, *next;
-
- EnterCriticalSection(&queue->cs);
-
- LIST_FOR_EACH_ENTRY_SAFE(mf_sample, next, &queue->samples, struct mf_sample, entry)
- {
- if (!InterlockedOr(&mf_sample->wg_sample.refcount, 0) || all)
- {
- list_remove(&mf_sample->entry);
- wg_sample_release(&mf_sample->wg_sample);
- }
- }
-
- LeaveCriticalSection(&queue->cs);
-}
-
-HRESULT wg_sample_queue_create(struct wg_sample_queue **out)
-{
- struct wg_sample_queue *queue;
-
- if (!(queue = calloc(1, sizeof(*queue))))
- return E_OUTOFMEMORY;
-
- InitializeCriticalSection(&queue->cs);
- queue->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
- list_init(&queue->samples);
-
- TRACE("Created sample queue %p\n", queue);
- *out = queue;
-
- return S_OK;
-}
-
-void wg_sample_queue_destroy(struct wg_sample_queue *queue)
-{
- wg_sample_queue_flush(queue, true);
-
- queue->cs.DebugInfo->Spare[0] = 0;
- InitializeCriticalSection(&queue->cs);
-
- free(queue);
-}
-
-HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *wg_sample,
- struct wg_sample_queue *queue)
-{
- struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample);
- LONGLONG time, duration;
- UINT32 value;
- HRESULT hr;
-
- if (SUCCEEDED(IMFSample_GetSampleTime(mf_sample->sample, &time)))
- {
- mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
- mf_sample->wg_sample.pts = time;
- }
- if (SUCCEEDED(IMFSample_GetSampleDuration(mf_sample->sample, &duration)))
- {
- mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
- mf_sample->wg_sample.duration = duration;
- }
- if (SUCCEEDED(IMFSample_GetUINT32(mf_sample->sample, &MFSampleExtension_CleanPoint, &value)) && value)
- mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT;
-
- wg_sample_queue_begin_append(queue, wg_sample);
- hr = wg_transform_push_data(transform, wg_sample);
- wg_sample_queue_end_append(queue, wg_sample);
-
- return hr;
-}
-
-HRESULT wg_transform_read_mf(struct wg_transform *transform, struct wg_sample *wg_sample,
- struct wg_format *format)
-{
- struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample);
- HRESULT hr;
-
- if (FAILED(hr = wg_transform_read_data(transform, wg_sample, format)))
- return hr;
-
- IMFMediaBuffer_SetCurrentLength(mf_sample->media_buffer, wg_sample->size);
-
- if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
- IMFSample_SetSampleTime(mf_sample->sample, wg_sample->pts);
- if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
- IMFSample_SetSampleDuration(mf_sample->sample, wg_sample->duration);
- if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT)
- IMFSample_SetUINT32(mf_sample->sample, &MFSampleExtension_CleanPoint, 1);
-
- return S_OK;
-}
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
new file mode 100644
index 00000000000..051e6199ec9
--- /dev/null
+++ b/dlls/winegstreamer/wg_sample.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2022 Rémi Bernon for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "gst_private.h"
+
+#include "wmcodecdsp.h"
+#include "mfapi.h"
+
+#include "wine/debug.h"
+#include "wine/list.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
+struct wg_sample_queue
+{
+ CRITICAL_SECTION cs;
+ struct list samples;
+};
+
+struct sample
+{
+ IMFSample *sample;
+ IMFMediaBuffer *media_buffer;
+ struct wg_sample wg_sample;
+ struct list entry;
+};
+
+HRESULT wg_sample_create_mf(IMFSample *mf_sample, struct wg_sample **out)
+{
+ DWORD current_length, max_length;
+ struct sample *sample;
+ BYTE *buffer;
+ HRESULT hr;
+
+ if (!(sample = calloc(1, sizeof(*sample))))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(mf_sample, &sample->media_buffer)))
+ goto fail;
+ if (FAILED(hr = IMFMediaBuffer_Lock(sample->media_buffer, &buffer, &max_length, ¤t_length)))
+ goto fail;
+
+ IMFSample_AddRef((sample->sample = mf_sample));
+ sample->wg_sample.data = buffer;
+ sample->wg_sample.size = current_length;
+ sample->wg_sample.max_size = max_length;
+
+ *out = &sample->wg_sample;
+ TRACE_(mfplat)("Created wg_sample %p for IMFSample %p.\n", *out, mf_sample);
+ return S_OK;
+
+fail:
+ if (sample->media_buffer)
+ IMFMediaBuffer_Release(sample->media_buffer);
+ free(sample);
+ return hr;
+}
+
+void wg_sample_release(struct wg_sample *wg_sample)
+{
+ struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+
+ if (InterlockedOr(&wg_sample->refcount, 0))
+ {
+ ERR("wg_sample %p is still in use, trouble ahead!\n", wg_sample);
+ return;
+ }
+
+ IMFMediaBuffer_Unlock(sample->media_buffer);
+ IMFMediaBuffer_Release(sample->media_buffer);
+ IMFSample_Release(sample->sample);
+
+ free(sample);
+}
+
+static void wg_sample_queue_begin_append(struct wg_sample_queue *queue, struct wg_sample *wg_sample)
+{
+ struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+
+ /* make sure a concurrent wg_sample_queue_flush call won't release the sample until we're done */
+ InterlockedIncrement(&wg_sample->refcount);
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_REFCOUNT;
+
+ EnterCriticalSection(&queue->cs);
+ list_add_tail(&queue->samples, &sample->entry);
+ LeaveCriticalSection(&queue->cs);
+}
+
+static void wg_sample_queue_end_append(struct wg_sample_queue *queue, struct wg_sample *wg_sample)
+{
+ /* release temporary ref taken in wg_sample_queue_begin_append */
+ InterlockedDecrement(&wg_sample->refcount);
+
+ wg_sample_queue_flush(queue, false);
+}
+
+void wg_sample_queue_flush(struct wg_sample_queue *queue, bool all)
+{
+ struct sample *sample, *next;
+
+ EnterCriticalSection(&queue->cs);
+
+ LIST_FOR_EACH_ENTRY_SAFE(sample, next, &queue->samples, struct sample, entry)
+ {
+ if (!InterlockedOr(&sample->wg_sample.refcount, 0) || all)
+ {
+ list_remove(&sample->entry);
+ wg_sample_release(&sample->wg_sample);
+ }
+ }
+
+ LeaveCriticalSection(&queue->cs);
+}
+
+HRESULT wg_sample_queue_create(struct wg_sample_queue **out)
+{
+ struct wg_sample_queue *queue;
+
+ if (!(queue = calloc(1, sizeof(*queue))))
+ return E_OUTOFMEMORY;
+
+ InitializeCriticalSection(&queue->cs);
+ queue->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
+ list_init(&queue->samples);
+
+ TRACE("Created wg_sample_queue %p.\n", queue);
+ *out = queue;
+
+ return S_OK;
+}
+
+void wg_sample_queue_destroy(struct wg_sample_queue *queue)
+{
+ wg_sample_queue_flush(queue, true);
+
+ queue->cs.DebugInfo->Spare[0] = 0;
+ InitializeCriticalSection(&queue->cs);
+
+ free(queue);
+}
+
+HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *wg_sample,
+ struct wg_sample_queue *queue)
+{
+ struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+ LONGLONG time, duration;
+ UINT32 value;
+ HRESULT hr;
+
+ if (SUCCEEDED(IMFSample_GetSampleTime(sample->sample, &time)))
+ {
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
+ sample->wg_sample.pts = time;
+ }
+ if (SUCCEEDED(IMFSample_GetSampleDuration(sample->sample, &duration)))
+ {
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
+ sample->wg_sample.duration = duration;
+ }
+ if (SUCCEEDED(IMFSample_GetUINT32(sample->sample, &MFSampleExtension_CleanPoint, &value)) && value)
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT;
+
+ wg_sample_queue_begin_append(queue, wg_sample);
+ hr = wg_transform_push_data(transform, wg_sample);
+ wg_sample_queue_end_append(queue, wg_sample);
+
+ return hr;
+}
+
+HRESULT wg_transform_read_mf(struct wg_transform *transform, struct wg_sample *wg_sample,
+ struct wg_format *format)
+{
+ struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+ HRESULT hr;
+
+ if (FAILED(hr = wg_transform_read_data(transform, wg_sample, format)))
+ return hr;
+
+ IMFMediaBuffer_SetCurrentLength(sample->media_buffer, wg_sample->size);
+
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
+ IMFSample_SetSampleTime(sample->sample, wg_sample->pts);
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
+ IMFSample_SetSampleDuration(sample->sample, wg_sample->duration);
+ if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT)
+ IMFSample_SetUINT32(sample->sample, &MFSampleExtension_CleanPoint, 1);
+
+ return S_OK;
+}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/220
June 13, 2022