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 1/9] mscoree: Avoid using pointer after free.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/mscoree/corruntimehost.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c
index 1651ca69d29..42081ad99bb 100644
--- a/dlls/mscoree/corruntimehost.c
+++ b/dlls/mscoree/corruntimehost.c
@@ -1917,7 +1917,7 @@ HRESULT create_monodata(REFCLSID clsid, LPVOID *ppObj)
HeapFree(GetProcessHeap(), 0, filenameA);
if (!assembly)
{
- ERR("Cannot open assembly %s, status=%i\n", filenameA, status);
+ ERR("Cannot open assembly %s, status=%i\n", debugstr_w(filename), status);
domain_restore(prev_domain);
goto cleanup;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/180
June 3, 2022
[PATCH 0/9] MR180: misc: Fixes and workarounds for UAF warnings. (GCC12)
by Rémi Bernon
The mscoree one is a genuine UAF bug, other are more arguably false positive but GCC doesn't like freed pointer value to be used in any way.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/180
June 3, 2022
[PATCH 6/6] winegstreamer: Remove now unused wg_parser unixlib entry points.
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/main.c | 23 ------------
dlls/winegstreamer/unixlib.h | 17 ++-------
dlls/winegstreamer/wg_parser.c | 61 +-------------------------------
4 files changed, 4 insertions(+), 100 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index fff849fd71e..08b61120a67 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -81,9 +81,6 @@ void wg_parser_stream_enable(struct wg_parser_stream *stream, const struct wg_fo
void wg_parser_stream_disable(struct wg_parser_stream *stream);
bool wg_parser_stream_get_buffer(struct wg_parser_stream *stream, struct wg_parser_buffer *buffer);
-bool wg_parser_stream_copy_buffer(struct wg_parser_stream *stream,
- void *data, uint32_t offset, uint32_t size);
-void wg_parser_stream_release_buffer(struct wg_parser_stream *stream);
bool wg_parser_stream_read_data(struct wg_parser_stream *stream, struct wg_sample *sample);
void wg_parser_stream_notify_qos(struct wg_parser_stream *stream,
bool underflow, double proportion, int64_t diff, uint64_t timestamp);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 23153137bd9..a4d545d3fb3 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -212,29 +212,6 @@ bool wg_parser_stream_get_buffer(struct wg_parser_stream *stream, struct wg_pars
return !__wine_unix_call(unix_handle, unix_wg_parser_stream_get_buffer, ¶ms);
}
-bool wg_parser_stream_copy_buffer(struct wg_parser_stream *stream,
- void *data, uint32_t offset, uint32_t size)
-{
- struct wg_parser_stream_copy_buffer_params params =
- {
- .stream = stream,
- .data = data,
- .offset = offset,
- .size = size,
- };
-
- TRACE("stream %p, data %p, offset %u, size %u.\n", stream, data, offset, size);
-
- return !__wine_unix_call(unix_handle, unix_wg_parser_stream_copy_buffer, ¶ms);
-}
-
-void wg_parser_stream_release_buffer(struct wg_parser_stream *stream)
-{
- TRACE("stream %p.\n", stream);
-
- __wine_unix_call(unix_handle, unix_wg_parser_stream_release_buffer, stream);
-}
-
bool wg_parser_stream_read_data(struct wg_parser_stream *stream, struct wg_sample *sample)
{
struct wg_parser_stream_read_data_params params =
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index e5135d67e74..420b48240c9 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -138,12 +138,11 @@ struct wg_sample
struct wg_parser_buffer
{
- /* pts and duration are in 100-nanosecond units. */
- UINT64 pts, duration;
+ /* pts is in 100-nanosecond units. */
+ UINT64 pts;
UINT32 size;
- bool discontinuity, preroll, delta, has_pts, has_duration;
+ bool has_pts;
};
-C_ASSERT(sizeof(struct wg_parser_buffer) == 32);
enum wg_parser_type
{
@@ -211,14 +210,6 @@ struct wg_parser_stream_get_buffer_params
struct wg_parser_buffer *buffer;
};
-struct wg_parser_stream_copy_buffer_params
-{
- struct wg_parser_stream *stream;
- void *data;
- UINT32 offset;
- UINT32 size;
-};
-
struct wg_parser_stream_read_data_params
{
struct wg_parser_stream *stream;
@@ -289,8 +280,6 @@ enum unix_funcs
unix_wg_parser_stream_disable,
unix_wg_parser_stream_get_buffer,
- unix_wg_parser_stream_copy_buffer,
- unix_wg_parser_stream_release_buffer,
unix_wg_parser_stream_read_data,
unix_wg_parser_stream_notify_qos,
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index c949108f8eb..77b2159abd1 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -283,11 +283,6 @@ static NTSTATUS wg_parser_stream_get_buffer(void *args)
if ((wg_buffer->has_pts = GST_BUFFER_PTS_IS_VALID(buffer)))
wg_buffer->pts = GST_BUFFER_PTS(buffer) / 100;
- if ((wg_buffer->has_duration = GST_BUFFER_DURATION_IS_VALID(buffer)))
- wg_buffer->duration = GST_BUFFER_DURATION(buffer) / 100;
- wg_buffer->discontinuity = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT);
- wg_buffer->preroll = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE);
- wg_buffer->delta = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
wg_buffer->size = gst_buffer_get_size(buffer);
pthread_mutex_unlock(&parser->mutex);
@@ -298,58 +293,6 @@ static NTSTATUS wg_parser_stream_get_buffer(void *args)
return S_FALSE;
}
-static NTSTATUS wg_parser_stream_copy_buffer(void *args)
-{
- const struct wg_parser_stream_copy_buffer_params *params = args;
- struct wg_parser_stream *stream = params->stream;
- struct wg_parser *parser = stream->parser;
- uint32_t offset = params->offset;
- uint32_t size = params->size;
- GstMapInfo map_info;
-
- pthread_mutex_lock(&parser->mutex);
-
- if (!stream->buffer)
- {
- pthread_mutex_unlock(&parser->mutex);
- return VFW_E_WRONG_STATE;
- }
-
- if (!gst_buffer_map(stream->buffer, &map_info, GST_MAP_READ))
- {
- pthread_mutex_unlock(&parser->mutex);
- GST_ERROR("Failed to map buffer.\n");
- return E_FAIL;
- }
-
- assert(offset < map_info.size);
- assert(offset + size <= map_info.size);
- memcpy(params->data, map_info.data + offset, size);
-
- gst_buffer_unmap(stream->buffer, &map_info);
-
- pthread_mutex_unlock(&parser->mutex);
- return S_OK;
-}
-
-static NTSTATUS wg_parser_stream_release_buffer(void *args)
-{
- struct wg_parser_stream *stream = args;
- struct wg_parser *parser = stream->parser;
-
- pthread_mutex_lock(&parser->mutex);
-
- assert(stream->buffer);
-
- gst_buffer_unref(stream->buffer);
- stream->buffer = NULL;
-
- pthread_mutex_unlock(&parser->mutex);
- pthread_cond_signal(&stream->event_empty_cond);
-
- return S_OK;
-}
-
static NTSTATUS wg_parser_stream_read_data(void *args)
{
struct wg_parser_stream_read_data_params *params = args;
@@ -607,7 +550,7 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu
/* The chain callback is given a reference to the buffer. Transfer that
* reference to the stream object, which will release it in
- * wg_parser_stream_release_buffer(). */
+ * wg_parser_stream_read_data(). */
GST_LOG("Buffer queued.");
return GST_FLOW_OK;
@@ -1644,8 +1587,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_parser_stream_disable),
X(wg_parser_stream_get_buffer),
- X(wg_parser_stream_copy_buffer),
- X(wg_parser_stream_release_buffer),
X(wg_parser_stream_read_data),
X(wg_parser_stream_notify_qos),
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/179
June 3, 2022
[PATCH 5/6] winegstreamer: Read quartz_parser stream data using wg_sample struct.
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_parser.c | 177 +++++------------------------
dlls/winegstreamer/unixlib.h | 1 +
dlls/winegstreamer/wg_sample.c | 71 ++++++++++++
dlls/winegstreamer/wg_transform.c | 2 +
5 files changed, 102 insertions(+), 150 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 8fb1bdf9576..fff849fd71e 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -122,6 +122,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_wrap_mf(IMFSample *mf_sample, struct wg_sample **out);
+HRESULT wg_sample_wrap_qz(IMediaSample *qz_sample, struct wg_sample **out);
HRESULT wg_sample_wrap_wm(INSSBuffer *wm_sample, QWORD pts, QWORD duration, DWORD flags,
struct wg_sample **out);
void wg_sample_unwrap(struct wg_sample *wg_sample);
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index 34848c0b503..81f6b795bd3 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -651,127 +651,14 @@ bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
return false;
}
-/*
- * scale_uint64() is based on gst_util_scale_int() from GStreamer, which is
- * covered by the following license:
- *
- * GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega(a)cse.ogi.edu>
- * 2000 Wim Taymans <wtay(a)chello.be>
- * 2002 Thomas Vander Stichele <thomas(a)apestaart.org>
- * 2004 Wim Taymans <wim(a)fluendo.com>
- * 2015 Jan Schmidt <jan(a)centricular.com>
- *
- * gstutils.c: Utility functions
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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.
- */
-static uint64_t scale_uint64(uint64_t value, uint32_t numerator, uint32_t denominator)
-{
- ULARGE_INTEGER i, high, low;
-
- if (!value)
- return 0;
-
- i.QuadPart = value;
- low.QuadPart = (ULONGLONG)i.u.LowPart * numerator;
- high.QuadPart = (ULONGLONG)i.u.HighPart * numerator + low.u.HighPart;
- low.u.HighPart = 0;
-
- if (high.u.HighPart >= denominator)
- return ULLONG_MAX;
-
- low.QuadPart += (high.QuadPart % denominator) << 32;
- return ((high.QuadPart / denominator) << 32) + (low.QuadPart / denominator);
-}
-
-/* Fill and send a single IMediaSample. */
-static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample,
- const struct wg_parser_buffer *buffer, uint32_t offset, uint32_t size, DWORD bytes_per_second)
-{
- HRESULT hr;
- BYTE *ptr = NULL;
-
- TRACE("offset %u, size %u, sample size %lu.\n", offset, size, IMediaSample_GetSize(sample));
-
- hr = IMediaSample_SetActualDataLength(sample, size);
- if(FAILED(hr)){
- ERR("Failed to set sample size, hr %#lx.\n", hr);
- return hr;
- }
-
- IMediaSample_GetPointer(sample, &ptr);
-
- if (!wg_parser_stream_copy_buffer(pin->wg_stream, ptr, offset, size))
- {
- /* The GStreamer pin has been flushed. */
- return S_OK;
- }
-
- if (buffer->has_pts)
- {
- REFERENCE_TIME start_pts = buffer->pts;
-
- if (offset)
- start_pts += scale_uint64(offset, 10000000, bytes_per_second);
- start_pts -= pin->seek.llCurrent;
- start_pts *= pin->seek.dRate;
-
- if (buffer->has_duration)
- {
- REFERENCE_TIME end_pts = buffer->pts + buffer->duration;
-
- if (offset + size < buffer->size)
- end_pts = buffer->pts + scale_uint64(offset + size, 10000000, bytes_per_second);
- end_pts -= pin->seek.llCurrent;
- end_pts *= pin->seek.dRate;
-
- IMediaSample_SetTime(sample, &start_pts, &end_pts);
- IMediaSample_SetMediaTime(sample, &start_pts, &end_pts);
- }
- else
- {
- IMediaSample_SetTime(sample, &start_pts, NULL);
- IMediaSample_SetMediaTime(sample, NULL, NULL);
- }
- }
- else
- {
- IMediaSample_SetTime(sample, NULL, NULL);
- IMediaSample_SetMediaTime(sample, NULL, NULL);
- }
-
- IMediaSample_SetDiscontinuity(sample, !offset && buffer->discontinuity);
- IMediaSample_SetPreroll(sample, buffer->preroll);
- IMediaSample_SetSyncPoint(sample, !buffer->delta);
-
- if (!pin->pin.pin.peer)
- return VFW_E_NOT_CONNECTED;
-
- hr = IMemInputPin_Receive(pin->pin.pMemInputPin, sample);
- TRACE("Receive() returned hr %#lx.\n", hr);
- return hr;
-}
-
/* Send a single GStreamer buffer (splitting it into multiple IMediaSamples if
* necessary). */
static void send_buffer(struct parser_source *pin, const struct wg_parser_buffer *buffer)
{
- HRESULT hr;
+ bool success, incomplete = true;
+ struct wg_sample *wg_sample;
IMediaSample *sample;
+ HRESULT hr = S_OK;
if (pin->need_segment)
{
@@ -781,50 +668,40 @@ static void send_buffer(struct parser_source *pin, const struct wg_parser_buffer
pin->need_segment = false;
}
- if (IsEqualGUID(&pin->pin.pin.mt.formattype, &FORMAT_WaveFormatEx)
- && (IsEqualGUID(&pin->pin.pin.mt.subtype, &MEDIASUBTYPE_PCM)
- || IsEqualGUID(&pin->pin.pin.mt.subtype, &MEDIASUBTYPE_IEEE_FLOAT)))
+ while (SUCCEEDED(hr) && incomplete)
{
- WAVEFORMATEX *format = (WAVEFORMATEX *)pin->pin.pin.mt.pbFormat;
- uint32_t offset = 0;
-
- while (offset < buffer->size)
+ if (FAILED(hr = IMemAllocator_GetBuffer(pin->pin.pAllocator, &sample, NULL, NULL, 0)))
{
- uint32_t advance;
-
- if (FAILED(hr = IMemAllocator_GetBuffer(pin->pin.pAllocator, &sample, NULL, NULL, 0)))
- {
- ERR("Failed to get a sample, hr %#lx.\n", hr);
- break;
- }
-
- advance = min(IMediaSample_GetSize(sample), buffer->size - offset);
-
- hr = send_sample(pin, sample, buffer, offset, advance, format->nAvgBytesPerSec);
-
+ ERR("Failed to get a sample, hr %#lx.\n", hr);
+ break;
+ }
+ if (FAILED(hr = wg_sample_wrap_qz(sample, &wg_sample)))
+ {
+ ERR("Failed to create sample, hr %#lx.\n", hr);
IMediaSample_Release(sample);
-
- if (FAILED(hr))
- break;
-
- offset += advance;
+ break;
}
- }
- else
- {
- if (FAILED(hr = IMemAllocator_GetBuffer(pin->pin.pAllocator, &sample, NULL, NULL, 0)))
+
+ if ((success = wg_parser_stream_read_data(pin->wg_stream, wg_sample)))
{
- ERR("Failed to get a sample, hr %#lx.\n", hr);
+ /* update pts and duration to current seeking time and rate */
+ wg_sample->pts -= pin->seek.llCurrent;
+ wg_sample->pts *= pin->seek.dRate;
+ wg_sample->duration *= pin->seek.dRate;
+ incomplete = wg_sample->flags & WG_SAMPLE_FLAG_INCOMPLETE;
}
+ wg_sample_unwrap(wg_sample);
+
+ if (!success || !pin->pin.pin.peer)
+ hr = E_FAIL;
else
{
- hr = send_sample(pin, sample, buffer, 0, buffer->size, 0);
-
- IMediaSample_Release(sample);
+ hr = IMemInputPin_Receive(pin->pin.pMemInputPin, sample);
+ TRACE("Receive() returned hr %#lx.\n", hr);
}
- }
- wg_parser_stream_release_buffer(pin->wg_stream);
+ IMediaSample_Release(sample);
+ }
}
static DWORD CALLBACK stream_thread(void *arg)
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 7e639abfd3c..e5135d67e74 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -122,6 +122,7 @@ enum wg_sample_flag
WG_SAMPLE_FLAG_HAS_DURATION = 4,
WG_SAMPLE_FLAG_SYNC_POINT = 8,
WG_SAMPLE_FLAG_DISCONTINUITY = 0x10,
+ WG_SAMPLE_FLAG_PREROLL = 0x20,
};
struct wg_sample
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
index fd757fa44f6..1a0e7ca9209 100644
--- a/dlls/winegstreamer/wg_sample.c
+++ b/dlls/winegstreamer/wg_sample.c
@@ -25,6 +25,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
WINE_DECLARE_DEBUG_CHANNEL(wmvcore);
+WINE_DECLARE_DEBUG_CHANNEL(quartz);
struct sample
{
@@ -33,6 +34,7 @@ struct sample
{
WG_SAMPLE_TYPE_MF = 1,
WG_SAMPLE_TYPE_WM = 2,
+ WG_SAMPLE_TYPE_QZ = 3,
} type;
union
@@ -46,6 +48,10 @@ struct sample
{
INSSBuffer *sample;
} wm;
+ struct
+ {
+ IMediaSample *sample;
+ } qz;
} u;
};
@@ -130,6 +136,32 @@ HRESULT wg_sample_wrap_wm(INSSBuffer *wm_sample, QWORD pts, QWORD duration, DWOR
return S_OK;
}
+HRESULT wg_sample_wrap_qz(IMediaSample *qz_sample, struct wg_sample **out)
+{
+ DWORD current_length, max_length;
+ struct sample *sample;
+ BYTE *buffer;
+ HRESULT hr;
+
+ if (FAILED(hr = IMediaSample_GetPointer(qz_sample, &buffer)))
+ return hr;
+ current_length = IMediaSample_GetActualDataLength(qz_sample);
+ max_length = IMediaSample_GetSize(qz_sample);
+
+ if (!(sample = calloc(1, sizeof(*sample))))
+ return E_OUTOFMEMORY;
+
+ IMediaSample_AddRef((sample->u.qz.sample = qz_sample));
+ sample->wg_sample.data = buffer;
+ sample->wg_sample.size = current_length;
+ sample->wg_sample.max_size = max_length;
+ sample->type = WG_SAMPLE_TYPE_QZ;
+
+ TRACE_(quartz)("Created wg_sample %p for sample %p.\n", &sample->wg_sample, qz_sample);
+ *out = &sample->wg_sample;
+ return S_OK;
+}
+
void wg_sample_unwrap(struct wg_sample *wg_sample)
{
struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
@@ -160,6 +192,45 @@ void wg_sample_unwrap(struct wg_sample *wg_sample)
INSSBuffer_Release(sample->u.wm.sample);
break;
+ case WG_SAMPLE_TYPE_QZ:
+ {
+ REFERENCE_TIME start_pts = wg_sample->pts, end_pts = start_pts + wg_sample->duration;
+ BOOL value;
+
+ TRACE_(quartz)("wg_sample %p\n", wg_sample);
+
+ IMediaSample_SetActualDataLength(sample->u.qz.sample, wg_sample->size);
+
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
+ {
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
+ {
+ IMediaSample_SetTime(sample->u.qz.sample, &start_pts, &end_pts);
+ IMediaSample_SetMediaTime(sample->u.qz.sample, &start_pts, &end_pts);
+ }
+ else
+ {
+ IMediaSample_SetTime(sample->u.qz.sample, &start_pts, NULL);
+ IMediaSample_SetMediaTime(sample->u.qz.sample, NULL, NULL);
+ }
+ }
+ else
+ {
+ IMediaSample_SetTime(sample->u.qz.sample, NULL, NULL);
+ IMediaSample_SetMediaTime(sample->u.qz.sample, NULL, NULL);
+ }
+
+ value = !!(wg_sample->flags & WG_SAMPLE_FLAG_DISCONTINUITY);
+ IMediaSample_SetDiscontinuity(sample->u.qz.sample, value);
+ value = !!(wg_sample->flags & WG_SAMPLE_FLAG_DISCONTINUITY);
+ IMediaSample_SetPreroll(sample->u.qz.sample, value);
+ value = !!(wg_sample->flags & WG_SAMPLE_FLAG_DISCONTINUITY);
+ IMediaSample_SetSyncPoint(sample->u.qz.sample, value);
+
+ IMediaSample_Release(sample->u.qz.sample);
+ break;
+ }
+
default:
FIXME("Unknown wg_sample %p, type %u\n", wg_sample, sample->type);
break;
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index bd53c13e84b..37f9cadde76 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -652,6 +652,8 @@ NTSTATUS wg_sample_read_from_buffer(GstBuffer *buffer, GstCaps *caps, gsize plan
sample->flags |= WG_SAMPLE_FLAG_SYNC_POINT;
if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT))
sample->flags |= WG_SAMPLE_FLAG_DISCONTINUITY;
+ if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE))
+ sample->flags |= WG_SAMPLE_FLAG_PREROLL;
GST_INFO("Copied %u bytes, sample %p, flags %#x", sample->size, sample, sample->flags);
return STATUS_SUCCESS;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/179
June 3, 2022
[PATCH 4/6] winegstreamer: Read wm_reader stream data using wg_sample struct.
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/unixlib.h | 1 +
dlls/winegstreamer/wg_sample.c | 48 +++++++++++++++++++++++++
dlls/winegstreamer/wg_transform.c | 4 +++
dlls/winegstreamer/wm_reader.c | 58 ++++++++++++++-----------------
5 files changed, 81 insertions(+), 32 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 8daa8223584..8fb1bdf9576 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -122,6 +122,8 @@ 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_wrap_mf(IMFSample *mf_sample, struct wg_sample **out);
+HRESULT wg_sample_wrap_wm(INSSBuffer *wm_sample, QWORD pts, QWORD duration, DWORD flags,
+ struct wg_sample **out);
void wg_sample_unwrap(struct wg_sample *wg_sample);
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 79926042f3c..7e639abfd3c 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -121,6 +121,7 @@ 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_DISCONTINUITY = 0x10,
};
struct wg_sample
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
index e20e393e396..fd757fa44f6 100644
--- a/dlls/winegstreamer/wg_sample.c
+++ b/dlls/winegstreamer/wg_sample.c
@@ -24,6 +24,7 @@
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+WINE_DECLARE_DEBUG_CHANNEL(wmvcore);
struct sample
{
@@ -31,6 +32,7 @@ struct sample
enum wg_sample_type
{
WG_SAMPLE_TYPE_MF = 1,
+ WG_SAMPLE_TYPE_WM = 2,
} type;
union
@@ -40,6 +42,10 @@ struct sample
IMFSample *sample;
IMFMediaBuffer *buffer;
} mf;
+ struct
+ {
+ INSSBuffer *sample;
+ } wm;
} u;
};
@@ -89,6 +95,41 @@ failed:
return hr;
}
+HRESULT wg_sample_wrap_wm(INSSBuffer *wm_sample, QWORD pts, QWORD duration, DWORD flags,
+ struct wg_sample **out)
+{
+ DWORD current_length, max_length;
+ struct sample *sample;
+ BYTE *buffer;
+ HRESULT hr;
+
+ if (FAILED(hr = INSSBuffer_GetBufferAndLength(wm_sample, &buffer, ¤t_length)))
+ return hr;
+ if (FAILED(hr = INSSBuffer_GetMaxLength(wm_sample, &max_length)))
+ return hr;
+ if (!(sample = calloc(1, sizeof(*sample))))
+ return E_OUTOFMEMORY;
+
+ if ((sample->wg_sample.pts = pts) != ~(QWORD)0)
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
+ if ((sample->wg_sample.duration = duration) != ~(QWORD)0)
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
+ if (flags & WM_SF_CLEANPOINT)
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT;
+ if (flags & WM_SF_DISCONTINUITY)
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_DISCONTINUITY;
+
+ INSSBuffer_AddRef((sample->u.wm.sample = wm_sample));
+ sample->wg_sample.data = buffer;
+ sample->wg_sample.size = current_length;
+ sample->wg_sample.max_size = max_length;
+ sample->type = WG_SAMPLE_TYPE_WM;
+
+ TRACE_(wmvcore)("Created wg_sample %p for sample %p.\n", &sample->wg_sample, wm_sample);
+ *out = &sample->wg_sample;
+ return S_OK;
+}
+
void wg_sample_unwrap(struct wg_sample *wg_sample)
{
struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
@@ -112,6 +153,13 @@ void wg_sample_unwrap(struct wg_sample *wg_sample)
IMFSample_Release(sample->u.mf.sample);
break;
+ case WG_SAMPLE_TYPE_WM:
+ TRACE_(wmvcore)("wg_sample %p\n", wg_sample);
+
+ INSSBuffer_SetLength(sample->u.wm.sample, wg_sample->size);
+ INSSBuffer_Release(sample->u.wm.sample);
+ break;
+
default:
FIXME("Unknown wg_sample %p, type %u\n", wg_sample, sample->type);
break;
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 7f0d74340db..bd53c13e84b 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -523,6 +523,8 @@ NTSTATUS wg_transform_push_data(void *args)
GST_BUFFER_DURATION(buffer) = sample->duration * 100;
if (!(sample->flags & WG_SAMPLE_FLAG_SYNC_POINT))
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
+ if (sample->flags & WG_SAMPLE_FLAG_DISCONTINUITY)
+ GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DISCONT);
gst_buffer_list_insert(transform->input, -1, buffer);
GST_INFO("Copied %u bytes from sample %p to input buffer list", sample->size, sample);
@@ -648,6 +650,8 @@ NTSTATUS wg_sample_read_from_buffer(GstBuffer *buffer, GstCaps *caps, gsize plan
}
if (!GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT))
sample->flags |= WG_SAMPLE_FLAG_SYNC_POINT;
+ if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT))
+ sample->flags |= WG_SAMPLE_FLAG_DISCONTINUITY;
GST_INFO("Copied %u bytes, sample %p, flags %#x", sample->size, sample, sample->flags);
return STATUS_SUCCESS;
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 03adea8a318..72a2d207c57 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -1877,11 +1877,11 @@ HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number
IWMReaderCallbackAdvanced *callback_advanced = reader->callback_advanced;
struct wg_parser_stream *wg_stream;
struct wg_parser_buffer wg_buffer;
+ struct wg_sample *wg_sample;
struct wm_stream *stream;
- DWORD size, capacity;
INSSBuffer *sample;
+ bool success;
HRESULT hr;
- BYTE *data;
for (;;)
{
@@ -1930,7 +1930,6 @@ HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number
stream->index + 1, wg_buffer.size, &sample, NULL)))
{
ERR("Failed to allocate stream sample of %u bytes, hr %#lx.\n", wg_buffer.size, hr);
- wg_parser_stream_release_buffer(wg_stream);
return hr;
}
}
@@ -1940,7 +1939,6 @@ HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number
stream->index, wg_buffer.size, &sample, NULL)))
{
ERR("Failed to allocate output sample of %u bytes, hr %#lx.\n", wg_buffer.size, hr);
- wg_parser_stream_release_buffer(wg_stream);
return hr;
}
}
@@ -1950,10 +1948,7 @@ HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number
/* FIXME: Should these be pooled? */
if (!(object = calloc(1, offsetof(struct buffer, data[wg_buffer.size]))))
- {
- wg_parser_stream_release_buffer(wg_stream);
return E_OUTOFMEMORY;
- }
object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
object->refcount = 1;
@@ -1963,38 +1958,37 @@ HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number
sample = &object->INSSBuffer_iface;
}
- if (FAILED(hr = INSSBuffer_GetBufferAndLength(sample, &data, &size)))
- ERR("Failed to get data pointer, hr %#lx.\n", hr);
- if (FAILED(hr = INSSBuffer_GetMaxLength(sample, &capacity)))
- ERR("Failed to get capacity, hr %#lx.\n", hr);
- if (wg_buffer.size > capacity)
- ERR("Returned capacity %lu is less than requested capacity %u.\n", capacity, wg_buffer.size);
+ if (FAILED(hr = wg_sample_wrap_wm(sample, ~(QWORD)0, ~(QWORD)0, 0, &wg_sample)))
+ {
+ ERR("Failed to create wg_sample, hr %#lx.\n", hr);
+ INSSBuffer_Release(sample);
+ return hr;
+ }
- if (!wg_parser_stream_copy_buffer(wg_stream, data, 0, wg_buffer.size))
+ if ((success = wg_parser_stream_read_data(wg_stream, wg_sample)))
+ {
+ if (!(wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS))
+ FIXME("Missing PTS.\n");
+ if (!(wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION))
+ FIXME("Missing duration.\n");
+
+ *pts = wg_sample->pts;
+ *duration = wg_sample->duration;
+ *flags = 0;
+ if (wg_sample->flags & WG_SAMPLE_FLAG_DISCONTINUITY)
+ *flags |= WM_SF_DISCONTINUITY;
+ if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT)
+ *flags |= WM_SF_CLEANPOINT;
+ }
+ wg_sample_unwrap(wg_sample);
+
+ if (!success)
{
/* The GStreamer pin has been flushed. */
INSSBuffer_Release(sample);
continue;
}
- if (FAILED(hr = INSSBuffer_SetLength(sample, wg_buffer.size)))
- ERR("Failed to set size %u, hr %#lx.\n", wg_buffer.size, hr);
-
- wg_parser_stream_release_buffer(wg_stream);
-
- if (!wg_buffer.has_pts)
- FIXME("Missing PTS.\n");
- if (!wg_buffer.has_duration)
- FIXME("Missing duration.\n");
-
- *pts = wg_buffer.pts;
- *duration = wg_buffer.duration;
- *flags = 0;
- if (wg_buffer.discontinuity)
- *flags |= WM_SF_DISCONTINUITY;
- if (!wg_buffer.delta)
- *flags |= WM_SF_CLEANPOINT;
-
*ret_sample = sample;
*ret_stream_number = stream_number;
return S_OK;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/179
June 3, 2022
[PATCH 3/6] winegstreamer: Read media_source stream data using wg_sample struct.
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/main.c | 13 +++++
dlls/winegstreamer/media_source.c | 81 +++++++++++--------------------
dlls/winegstreamer/unix_private.h | 3 ++
dlls/winegstreamer/unixlib.h | 7 +++
dlls/winegstreamer/wg_parser.c | 30 ++++++++++++
dlls/winegstreamer/wg_transform.c | 4 +-
7 files changed, 84 insertions(+), 55 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 7ae2eb99076..8daa8223584 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -84,6 +84,7 @@ bool wg_parser_stream_get_buffer(struct wg_parser_stream *stream, struct wg_pars
bool wg_parser_stream_copy_buffer(struct wg_parser_stream *stream,
void *data, uint32_t offset, uint32_t size);
void wg_parser_stream_release_buffer(struct wg_parser_stream *stream);
+bool wg_parser_stream_read_data(struct wg_parser_stream *stream, struct wg_sample *sample);
void wg_parser_stream_notify_qos(struct wg_parser_stream *stream,
bool underflow, double proportion, int64_t diff, uint64_t timestamp);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 5075b3118cd..23153137bd9 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -235,6 +235,19 @@ void wg_parser_stream_release_buffer(struct wg_parser_stream *stream)
__wine_unix_call(unix_handle, unix_wg_parser_stream_release_buffer, stream);
}
+bool wg_parser_stream_read_data(struct wg_parser_stream *stream, struct wg_sample *sample)
+{
+ struct wg_parser_stream_read_data_params params =
+ {
+ .stream = stream,
+ .sample = sample,
+ };
+
+ TRACE("stream %p, sample %p.\n", stream, sample);
+
+ return !__wine_unix_call(unix_handle, unix_wg_parser_stream_read_data, ¶ms);
+}
+
void wg_parser_stream_notify_qos(struct wg_parser_stream *stream,
bool underflow, double proportion, int64_t diff, uint64_t timestamp)
{
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index f07b83f413e..1c5518d53d2 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -451,78 +451,53 @@ static void dispatch_end_of_presentation(struct media_source *source)
IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MEEndOfPresentation, &GUID_NULL, S_OK, &empty);
}
-static void send_buffer(struct media_stream *stream, const struct wg_parser_buffer *wg_buffer, IUnknown *token)
+static HRESULT mf_allocate_sample(UINT32 size, IMFSample **sample)
{
IMFMediaBuffer *buffer;
- IMFSample *sample;
HRESULT hr;
- BYTE *data;
- if (FAILED(hr = MFCreateSample(&sample)))
- {
- ERR("Failed to create sample, hr %#lx.\n", hr);
- return;
- }
-
- if (FAILED(hr = MFCreateMemoryBuffer(wg_buffer->size, &buffer)))
- {
- ERR("Failed to create buffer, hr %#lx.\n", hr);
- IMFSample_Release(sample);
- return;
- }
+ if (FAILED(hr = MFCreateSample(sample)))
+ return hr;
- if (FAILED(hr = IMFSample_AddBuffer(sample, buffer)))
+ if (SUCCEEDED(hr = MFCreateMemoryBuffer(size, &buffer)))
{
- ERR("Failed to add buffer, hr %#lx.\n", hr);
- goto out;
+ hr = IMFSample_AddBuffer(*sample, buffer);
+ IMFMediaBuffer_Release(buffer);
}
- if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(buffer, wg_buffer->size)))
- {
- ERR("Failed to set size, hr %#lx.\n", hr);
- goto out;
- }
+ return hr;
+}
- if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL)))
- {
- ERR("Failed to lock buffer, hr %#lx.\n", hr);
- goto out;
- }
+static void send_buffer(struct media_stream *stream, const struct wg_parser_buffer *wg_buffer, IUnknown *token)
+{
+ struct wg_sample *wg_sample;
+ IMFSample *sample;
+ bool success;
+ HRESULT hr;
- if (!wg_parser_stream_copy_buffer(stream->wg_stream, data, 0, wg_buffer->size))
+ if (FAILED(hr = mf_allocate_sample(wg_buffer->size, &sample)))
{
- wg_parser_stream_release_buffer(stream->wg_stream);
- IMFMediaBuffer_Unlock(buffer);
- goto out;
+ ERR("Failed to create sample, hr %#lx.\n", hr);
+ return;
}
- wg_parser_stream_release_buffer(stream->wg_stream);
-
- if (FAILED(hr = IMFMediaBuffer_Unlock(buffer)))
+ if (FAILED(hr = wg_sample_wrap_mf(sample, &wg_sample)))
{
- ERR("Failed to unlock buffer, hr %#lx.\n", hr);
- goto out;
+ ERR("Failed to create sample, hr %#lx.\n", hr);
+ IMFSample_Release(sample);
+ return;
}
- if (FAILED(hr = IMFSample_SetSampleTime(sample, wg_buffer->pts)))
- {
- ERR("Failed to set sample time, hr %#lx.\n", hr);
- goto out;
- }
+ success = wg_parser_stream_read_data(stream->wg_stream, wg_sample);
+ wg_sample_unwrap(wg_sample);
- if (FAILED(hr = IMFSample_SetSampleDuration(sample, wg_buffer->duration)))
+ if (success)
{
- ERR("Failed to set sample duration, hr %#lx.\n", hr);
- goto out;
+ if (token)
+ IMFSample_SetUnknown(sample, &MFSampleExtension_Token, token);
+ IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample,
+ &GUID_NULL, S_OK, (IUnknown *)sample);
}
- if (token)
- IMFSample_SetUnknown(sample, &MFSampleExtension_Token, token);
-
- IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample,
- &GUID_NULL, S_OK, (IUnknown *)sample);
-
-out:
- IMFMediaBuffer_Release(buffer);
IMFSample_Release(sample);
}
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index 7bce8263aaf..c83aabb59e6 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -37,4 +37,7 @@ extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_push_data(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_read_data(void *args) DECLSPEC_HIDDEN;
+extern NTSTATUS wg_sample_read_from_buffer(GstBuffer *buffer, GstCaps *caps, gsize plane_align,
+ struct wg_sample *sample) DECLSPEC_HIDDEN;
+
#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index f334a168bd1..79926042f3c 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -217,6 +217,12 @@ struct wg_parser_stream_copy_buffer_params
UINT32 size;
};
+struct wg_parser_stream_read_data_params
+{
+ struct wg_parser_stream *stream;
+ struct wg_sample *sample;
+};
+
struct wg_parser_stream_notify_qos_params
{
struct wg_parser_stream *stream;
@@ -283,6 +289,7 @@ enum unix_funcs
unix_wg_parser_stream_get_buffer,
unix_wg_parser_stream_copy_buffer,
unix_wg_parser_stream_release_buffer,
+ unix_wg_parser_stream_read_data,
unix_wg_parser_stream_notify_qos,
unix_wg_parser_stream_get_duration,
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 6b1a98c0e7d..c949108f8eb 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -350,6 +350,35 @@ static NTSTATUS wg_parser_stream_release_buffer(void *args)
return S_OK;
}
+static NTSTATUS wg_parser_stream_read_data(void *args)
+{
+ struct wg_parser_stream_read_data_params *params = args;
+ struct wg_parser_stream *stream = params->stream;
+ struct wg_parser *parser = stream->parser;
+ struct wg_sample *sample = params->sample;
+ NTSTATUS status;
+
+ pthread_mutex_lock(&parser->mutex);
+
+ if (!stream->buffer)
+ {
+ pthread_mutex_unlock(&parser->mutex);
+ return VFW_E_WRONG_STATE;
+ }
+
+ status = wg_sample_read_from_buffer(stream->buffer, NULL, 0, sample);
+ if (!(sample->flags & WG_SAMPLE_FLAG_INCOMPLETE))
+ {
+ gst_buffer_unref(stream->buffer);
+ stream->buffer = NULL;
+ pthread_cond_signal(&stream->event_empty_cond);
+ }
+
+ pthread_mutex_unlock(&parser->mutex);
+
+ return status;
+}
+
static NTSTATUS wg_parser_stream_get_duration(void *args)
{
struct wg_parser_stream_get_duration_params *params = args;
@@ -1617,6 +1646,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_parser_stream_get_buffer),
X(wg_parser_stream_copy_buffer),
X(wg_parser_stream_release_buffer),
+ X(wg_parser_stream_read_data),
X(wg_parser_stream_notify_qos),
X(wg_parser_stream_get_duration),
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index fb852b4cf3d..7f0d74340db 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -611,7 +611,7 @@ static bool copy_buffer(GstBuffer *buffer, GstCaps *caps, struct wg_sample *samp
return true;
}
-static NTSTATUS read_transform_output_data(GstBuffer *buffer, GstCaps *caps, gsize plane_align,
+NTSTATUS wg_sample_read_from_buffer(GstBuffer *buffer, GstCaps *caps, gsize plane_align,
struct wg_sample *sample)
{
gsize total_size;
@@ -725,7 +725,7 @@ NTSTATUS wg_transform_read_data(void *args)
return STATUS_SUCCESS;
}
- if ((status = read_transform_output_data(output_buffer, output_caps,
+ if ((status = wg_sample_read_from_buffer(output_buffer, output_caps,
transform->output_plane_align, sample)))
return status;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/179
June 3, 2022
[PATCH 2/6] winegstreamer: Map wg_parser_stream buffer only when needed.
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_parser.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 7d55897aa0a..6b1a98c0e7d 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -103,7 +103,6 @@ struct wg_parser_stream
pthread_cond_t event_cond, event_empty_cond;
GstBuffer *buffer;
- GstMapInfo map_info;
bool flushing, eos, enabled, has_caps;
@@ -306,6 +305,7 @@ static NTSTATUS wg_parser_stream_copy_buffer(void *args)
struct wg_parser *parser = stream->parser;
uint32_t offset = params->offset;
uint32_t size = params->size;
+ GstMapInfo map_info;
pthread_mutex_lock(&parser->mutex);
@@ -315,9 +315,18 @@ static NTSTATUS wg_parser_stream_copy_buffer(void *args)
return VFW_E_WRONG_STATE;
}
- assert(offset < stream->map_info.size);
- assert(offset + size <= stream->map_info.size);
- memcpy(params->data, stream->map_info.data + offset, size);
+ if (!gst_buffer_map(stream->buffer, &map_info, GST_MAP_READ))
+ {
+ pthread_mutex_unlock(&parser->mutex);
+ GST_ERROR("Failed to map buffer.\n");
+ return E_FAIL;
+ }
+
+ assert(offset < map_info.size);
+ assert(offset + size <= map_info.size);
+ memcpy(params->data, map_info.data + offset, size);
+
+ gst_buffer_unmap(stream->buffer, &map_info);
pthread_mutex_unlock(&parser->mutex);
return S_OK;
@@ -332,7 +341,6 @@ static NTSTATUS wg_parser_stream_release_buffer(void *args)
assert(stream->buffer);
- gst_buffer_unmap(stream->buffer, &stream->map_info);
gst_buffer_unref(stream->buffer);
stream->buffer = NULL;
@@ -486,7 +494,6 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
if (stream->buffer)
{
- gst_buffer_unmap(stream->buffer, &stream->map_info);
gst_buffer_unref(stream->buffer);
stream->buffer = NULL;
}
@@ -564,14 +571,6 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu
return GST_FLOW_FLUSHING;
}
- if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ))
- {
- pthread_mutex_unlock(&parser->mutex);
- GST_ERROR("Failed to map buffer.\n");
- gst_buffer_unref(buffer);
- return GST_FLOW_ERROR;
- }
-
stream->buffer = buffer;
pthread_mutex_unlock(&parser->mutex);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/179
June 3, 2022
[PATCH 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/gst_private.h | 4 +-
dlls/winegstreamer/h264_decoder.c | 11 ++-
dlls/winegstreamer/mfplat.c | 71 ------------------
dlls/winegstreamer/wg_sample.c | 121 ++++++++++++++++++++++++++++++
dlls/winegstreamer/wma_decoder.c | 12 +--
6 files changed, 135 insertions(+), 85 deletions(-)
create mode 100644 dlls/winegstreamer/wg_sample.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index e4c2636d02d..bac01776e4c 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -16,6 +16,7 @@ C_SRCS = \
quartz_transform.c \
wg_format.c \
wg_parser.c \
+ wg_sample.c \
wg_transform.c \
wm_asyncreader.c \
wm_reader.c \
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 159143d7e54..7ae2eb99076 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -120,8 +120,8 @@ extern HRESULT mfplat_DllRegisterServer(void);
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 mf_create_wg_sample(IMFSample *sample, struct wg_sample **out);
-void mf_destroy_wg_sample(struct wg_sample *wg_sample);
+HRESULT wg_sample_wrap_mf(IMFSample *mf_sample, struct wg_sample **out);
+void wg_sample_unwrap(struct wg_sample *wg_sample);
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 19a36a9a77a..43d714f63be 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -540,12 +540,11 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS
if (!decoder->wg_transform)
return MF_E_TRANSFORM_TYPE_NOT_SET;
- if (FAILED(hr = mf_create_wg_sample(sample, &wg_sample)))
+ if (FAILED(hr = wg_sample_wrap_mf(sample, &wg_sample)))
return hr;
hr = wg_transform_push_data(decoder->wg_transform, wg_sample);
-
- mf_destroy_wg_sample(wg_sample);
+ wg_sample_unwrap(wg_sample);
return hr;
}
@@ -574,18 +573,18 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
samples[0].dwStatus = 0;
if (!samples[0].pSample) return E_INVALIDARG;
- if (FAILED(hr = mf_create_wg_sample(samples[0].pSample, &wg_sample)))
+ if (FAILED(hr = wg_sample_wrap_mf(samples[0].pSample, &wg_sample)))
return hr;
if (wg_sample->max_size < info.cbSize)
{
- mf_destroy_wg_sample(wg_sample);
+ wg_sample_unwrap(wg_sample);
return MF_E_BUFFERTOOSMALL;
}
hr = wg_transform_read_data(decoder->wg_transform, wg_sample,
&wg_format);
- mf_destroy_wg_sample(wg_sample);
+ wg_sample_unwrap(wg_sample);
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
{
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 0226e7a2e45..687ea6db5c7 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -957,74 +957,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 mf_sample
-{
- IMFSample *sample;
- IMFMediaBuffer *media_buffer;
- struct wg_sample wg_sample;
-};
-
-HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out)
-{
- DWORD current_length, max_length;
- struct mf_sample *mf_sample;
- LONGLONG time, duration;
- UINT32 value;
- 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;
-
- if (SUCCEEDED(IMFSample_GetSampleTime(sample, &time)))
- {
- mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
- mf_sample->wg_sample.pts = time;
- }
- if (SUCCEEDED(IMFSample_GetSampleDuration(sample, &duration)))
- {
- mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
- mf_sample->wg_sample.duration = duration;
- }
- if (SUCCEEDED(IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value)) && value)
- mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT;
-
- 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 mf_destroy_wg_sample(struct wg_sample *wg_sample)
-{
- struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample);
-
- IMFMediaBuffer_Unlock(mf_sample->media_buffer);
- IMFMediaBuffer_SetCurrentLength(mf_sample->media_buffer, wg_sample->size);
- IMFMediaBuffer_Release(mf_sample->media_buffer);
-
- 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);
-
- IMFSample_Release(mf_sample->sample);
- free(mf_sample);
-}
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c
new file mode 100644
index 00000000000..e20e393e396
--- /dev/null
+++ b/dlls/winegstreamer/wg_sample.c
@@ -0,0 +1,121 @@
+/*
+ * 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"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
+struct sample
+{
+ struct wg_sample wg_sample;
+ enum wg_sample_type
+ {
+ WG_SAMPLE_TYPE_MF = 1,
+ } type;
+
+ union
+ {
+ struct
+ {
+ IMFSample *sample;
+ IMFMediaBuffer *buffer;
+ } mf;
+ } u;
+};
+
+HRESULT wg_sample_wrap_mf(IMFSample *mf_sample, struct wg_sample **out)
+{
+ DWORD current_length, max_length;
+ LONGLONG time, duration;
+ struct sample *sample;
+ UINT32 value;
+ BYTE *buffer;
+ HRESULT hr;
+
+ if (!(sample = calloc(1, sizeof(*sample))))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(mf_sample, &sample->u.mf.buffer)))
+ goto failed;
+ if (FAILED(hr = IMFMediaBuffer_Lock(sample->u.mf.buffer, &buffer, &max_length, ¤t_length)))
+ goto failed;
+
+ if (SUCCEEDED(IMFSample_GetSampleTime(mf_sample, &time)))
+ {
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
+ sample->wg_sample.pts = time;
+ }
+ if (SUCCEEDED(IMFSample_GetSampleDuration(mf_sample, &duration)))
+ {
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
+ sample->wg_sample.duration = duration;
+ }
+ if (SUCCEEDED(IMFSample_GetUINT32(mf_sample, &MFSampleExtension_CleanPoint, &value)) && value)
+ sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT;
+
+ 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->type = WG_SAMPLE_TYPE_MF;
+
+ TRACE("Created wg_sample %p for sample %p.\n", &sample->wg_sample, mf_sample);
+ *out = &sample->wg_sample;
+ return S_OK;
+
+failed:
+ if (sample->u.mf.buffer)
+ IMFMediaBuffer_Release(sample->u.mf.buffer);
+ free(sample);
+ return hr;
+}
+
+void wg_sample_unwrap(struct wg_sample *wg_sample)
+{
+ struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample);
+
+ switch (sample->type)
+ {
+ case WG_SAMPLE_TYPE_MF:
+ TRACE("wg_sample %p\n", wg_sample);
+
+ IMFMediaBuffer_Unlock(sample->u.mf.buffer);
+ IMFMediaBuffer_SetCurrentLength(sample->u.mf.buffer, wg_sample->size);
+ IMFMediaBuffer_Release(sample->u.mf.buffer);
+
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
+ IMFSample_SetSampleTime(sample->u.mf.sample, wg_sample->pts);
+ if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
+ IMFSample_SetSampleDuration(sample->u.mf.sample, wg_sample->duration);
+ if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT)
+ IMFSample_SetUINT32(sample->u.mf.sample, &MFSampleExtension_CleanPoint, 1);
+
+ IMFSample_Release(sample->u.mf.sample);
+ break;
+
+ default:
+ FIXME("Unknown wg_sample %p, type %u\n", wg_sample, sample->type);
+ break;
+ }
+
+ free(sample);
+}
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 106d32adce9..dc3d1aaef1a 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -534,18 +534,18 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS
if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info)))
return hr;
- if (FAILED(hr = mf_create_wg_sample(sample, &wg_sample)))
+ if (FAILED(hr = wg_sample_wrap_mf(sample, &wg_sample)))
return hr;
/* WMA transform uses fixed size input samples and ignores samples with invalid sizes */
if (wg_sample->size % info.cbSize)
{
- mf_destroy_wg_sample(wg_sample);
+ wg_sample_unwrap(wg_sample);
return S_OK;
}
hr = wg_transform_push_data(decoder->wg_transform, wg_sample);
- mf_destroy_wg_sample(wg_sample);
+ wg_sample_unwrap(wg_sample);
return hr;
}
@@ -576,13 +576,13 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
return MF_E_TRANSFORM_NEED_MORE_INPUT;
}
- if (FAILED(hr = mf_create_wg_sample(samples[0].pSample, &wg_sample)))
+ if (FAILED(hr = wg_sample_wrap_mf(samples[0].pSample, &wg_sample)))
return hr;
wg_sample->size = 0;
if (wg_sample->max_size < info.cbSize)
{
- mf_destroy_wg_sample(wg_sample);
+ wg_sample_unwrap(wg_sample);
return MF_E_BUFFERTOOSMALL;
}
@@ -592,7 +592,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_INCOMPLETE;
}
- mf_destroy_wg_sample(wg_sample);
+ wg_sample_unwrap(wg_sample);
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
{
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/179
June 3, 2022
Re: [PATCH 6/6] kernelbase: Cleanup and simplify LocalReAlloc.
by Marvin
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=116146
Your paranoid android.
=== debian11 (32 bit WoW report) ===
kernel32:
change.c:309: Test failed: should be ready
change.c:339: Test failed: should be ready
June 3, 2022