From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@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) {
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@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);
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@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;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@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;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@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@cse.ogi.edu - * 2000 Wim Taymans wtay@chello.be - * 2002 Thomas Vander Stichele thomas@apestaart.org - * 2004 Wim Taymans wim@fluendo.com - * 2015 Jan Schmidt jan@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;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@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),
I've been staring at this for a while, and I'm still not convinced that this abstraction is an improvement. I think I get the idea—to try to share code between the input and output sample path—but as far as I can tell the only code that's actually *shared* is the code to retrieve the buffer pointer itself and the maximum length. Everything else is either input-only or output-only. As such we end up introducing a lot of code into the common path that kind of obscures the otherwise simpler functionality of push/read. (It's also kind of confusing that we're reading the previous values of an output sample, or writing values into an input sample.)
I don't intend to let that block progress on the transform objects, but if it's possible I'd rather hold off on converting the parser to this abstraction—at least until the transforms have reached their "final" (zero-copy) form [not that it's immediately clear why this abstraction makes more sense in that case]. Would it be feasible to hold off on these patches for now?
This merge request was closed by Rémi Bernon.