Zebediah Figura : winegstreamer: DirectShow and GStreamer proportions are inverted with respect to each other.

Alexandre Julliard julliard at winehq.org
Thu Oct 22 15:27:32 CDT 2020


Module: wine
Branch: master
Commit: 63cf882e392478f8df339a3aa45940af9fe75936
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=63cf882e392478f8df339a3aa45940af9fe75936

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Thu Oct 22 11:10:17 2020 -0500

winegstreamer: DirectShow and GStreamer proportions are inverted with respect to each other.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winegstreamer/gst_private.h | 22 +++++++++++++++++++++
 dlls/winegstreamer/gstdemux.c    | 42 ++++++++++++++++++++++++++--------------
 2 files changed, 49 insertions(+), 15 deletions(-)

diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 60b38a48f5a..57d40d19a89 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -37,9 +37,31 @@
 #include "dshow.h"
 #include "strmif.h"
 #include "mfobjects.h"
+#include "wine/debug.h"
 #include "wine/heap.h"
 #include "wine/strmbase.h"
 
+static inline const char *debugstr_time(REFERENCE_TIME time)
+{
+    ULONGLONG abstime = time >= 0 ? time : -time;
+    unsigned int i = 0, j = 0;
+    char buffer[23], rev[23];
+
+    while (abstime || i <= 8)
+    {
+        buffer[i++] = '0' + (abstime % 10);
+        abstime /= 10;
+        if (i == 7) buffer[i++] = '.';
+    }
+    if (time < 0) buffer[i++] = '-';
+
+    while (i--) rev[j++] = buffer[i];
+    while (rev[j-1] == '0' && rev[j-2] != '.') --j;
+    rev[j] = 0;
+
+    return wine_dbg_sprintf("%s", rev);
+}
+
 #define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000)
 
 extern LONG object_locks;
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index 68b12cf8f14..9f5e147b7ed 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -2032,45 +2032,57 @@ static ULONG WINAPI GST_QualityControl_Release(IQualityControl *iface)
     return IPin_Release(&pin->pin.pin.IPin_iface);
 }
 
-static HRESULT WINAPI GST_QualityControl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality qm)
+static HRESULT WINAPI GST_QualityControl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality q)
 {
     struct gstdemux_source *pin = impl_from_IQualityControl(iface);
     GstQOSType type = GST_QOS_TYPE_OVERFLOW;
     GstClockTime timestamp;
     GstClockTimeDiff diff;
-    GstEvent *evt;
+    GstEvent *event;
 
-    TRACE("(%p)->(%p, { 0x%x %u %s %s })\n", pin, sender,
-            qm.Type, qm.Proportion,
-            wine_dbgstr_longlong(qm.Late),
-            wine_dbgstr_longlong(qm.TimeStamp));
+    TRACE("pin %p, sender %p, type %s, proportion %u, late %s, timestamp %s.\n",
+            pin, sender, q.Type == Famine ? "Famine" : "Flood", q.Proportion,
+            debugstr_time(q.Late), debugstr_time(q.TimeStamp));
 
     mark_wine_thread();
 
-    /* GSTQOS_TYPE_OVERFLOW is also used for buffers that arrive on time, but
+    /* GST_QOS_TYPE_OVERFLOW is also used for buffers that arrive on time, but
      * DirectShow filters might use Famine, so check that there actually is an
      * underrun. */
-    if (qm.Type == Famine && qm.Proportion > 1000)
+    if (q.Type == Famine && q.Proportion < 1000)
         type = GST_QOS_TYPE_UNDERFLOW;
 
     /* DirectShow filters sometimes pass negative timestamps (Audiosurf uses the
      * current time instead of the time of the last buffer). GstClockTime is
      * unsigned, so clamp it to 0. */
-    timestamp = max(qm.TimeStamp * 100, 0);
+    timestamp = max(q.TimeStamp * 100, 0);
 
     /* The documentation specifies that timestamp + diff must be nonnegative. */
-    diff = qm.Late * 100;
+    diff = q.Late * 100;
     if (diff < 0 && timestamp < (GstClockTime)-diff)
         diff = -timestamp;
 
-    evt = gst_event_new_qos(type, qm.Proportion / 1000.0, diff, timestamp);
+    /* DirectShow "Proportion" describes what percentage of buffers the upstream
+     * filter should keep (i.e. dropping the rest). If frames are late, the
+     * proportion will be less than 1. For example, a proportion of 500 means
+     * that the element should drop half of its frames, essentially because
+     * frames are taking twice as long as they should to arrive.
+     *
+     * GStreamer "proportion" is the inverse of this; it describes how much
+     * faster the upstream element should produce frames. I.e. if frames are
+     * taking twice as long as they should to arrive, we want the frames to be
+     * decoded twice as fast, and so we pass 2.0 to GStreamer. */
 
-    if (!evt) {
-        WARN("Failed to create QOS event\n");
-        return E_INVALIDARG;
+    if (!q.Proportion)
+    {
+        WARN("Ignoring quality message with zero proportion.\n");
+        return S_OK;
     }
 
-    gst_pad_push_event(pin->my_sink, evt);
+    if (!(event = gst_event_new_qos(type, 1000.0 / q.Proportion, diff, timestamp)))
+        ERR("Failed to create QOS event.\n");
+
+    gst_pad_push_event(pin->my_sink, event);
 
     return S_OK;
 }




More information about the wine-cvs mailing list