[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