[PATCH 5/6] winegstreamer: Read quartz_parser stream data using wg_sample struct.
Rémi Bernon
wine at gitlab.winehq.org
Fri Jun 3 04:17:14 CDT 2022
From: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon at 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 at cse.ogi.edu>
- * 2000 Wim Taymans <wtay at chello.be>
- * 2002 Thomas Vander Stichele <thomas at apestaart.org>
- * 2004 Wim Taymans <wim at fluendo.com>
- * 2015 Jan Schmidt <jan at 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
More information about the wine-devel
mailing list