[PATCH] winegstreamer: Split audio data to fit in the sample buffer.

Anton Baskanov baskanov at gmail.com
Thu Dec 24 13:49:30 CST 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50355
Signed-off-by: Anton Baskanov <baskanov at gmail.com>
---
 dlls/winegstreamer/gstdemux.c | 142 +++++++++++++++++++++-------------
 1 file changed, 88 insertions(+), 54 deletions(-)

diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index 9114e6610a3..8a9c0a84191 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -81,6 +81,7 @@ struct gstdemux_source
     HANDLE caps_event, eos_event;
     GstSegment *segment;
     SourceSeeking seek;
+    DWORD bytes_per_second;
 };
 
 static inline struct gstdemux *impl_from_strmbase_filter(struct strmbase_filter *iface)
@@ -801,6 +802,7 @@ static GstFlowReturn got_data_sink(GstPad *pad, GstObject *parent, GstBuffer *bu
     BYTE *ptr = NULL;
     IMediaSample *sample;
     GstMapInfo info;
+    gsize position = 0;
 
     TRACE("%p %p\n", pad, buf);
 
@@ -809,76 +811,106 @@ static GstFlowReturn got_data_sink(GstPad *pad, GstObject *parent, GstBuffer *bu
         return GST_FLOW_OK;
     }
 
-    hr = BaseOutputPinImpl_GetDeliveryBuffer(&pin->pin, &sample, NULL, NULL, 0);
-
-    if (hr == VFW_E_NOT_CONNECTED) {
-        gst_buffer_unref(buf);
-        return GST_FLOW_NOT_LINKED;
-    }
+    gst_buffer_map(buf, &info, GST_MAP_READ);
 
-    if (FAILED(hr)) {
-        gst_buffer_unref(buf);
-        ERR("Could not get a delivery buffer (%x), returning GST_FLOW_FLUSHING\n", hr);
-        return GST_FLOW_FLUSHING;
-    }
+    while (position < info.size)
+    {
+        gsize advance;
 
-    gst_buffer_map(buf, &info, GST_MAP_READ);
+        hr = BaseOutputPinImpl_GetDeliveryBuffer(&pin->pin, &sample, NULL, NULL, 0);
 
-    hr = IMediaSample_SetActualDataLength(sample, info.size);
-    if(FAILED(hr)){
-        WARN("SetActualDataLength failed: %08x\n", hr);
-        return GST_FLOW_FLUSHING;
-    }
+        if (hr == VFW_E_NOT_CONNECTED) {
+            gst_buffer_unmap(buf, &info);
+            gst_buffer_unref(buf);
+            return GST_FLOW_NOT_LINKED;
+        }
 
-    IMediaSample_GetPointer(sample, &ptr);
+        if (FAILED(hr)) {
+            gst_buffer_unmap(buf, &info);
+            gst_buffer_unref(buf);
+            ERR("Could not get a delivery buffer (%x), returning GST_FLOW_FLUSHING\n", hr);
+            return GST_FLOW_FLUSHING;
+        }
 
-    memcpy(ptr, info.data, info.size);
+        advance = min(IMediaSample_GetSize(sample), info.size - position);
 
-    gst_buffer_unmap(buf, &info);
+        hr = IMediaSample_SetActualDataLength(sample, advance);
+        if(FAILED(hr)){
+            gst_buffer_unmap(buf, &info);
+            gst_buffer_unref(buf);
+            WARN("SetActualDataLength failed: %08x\n", hr);
+            return GST_FLOW_FLUSHING;
+        }
 
-    if (GST_BUFFER_PTS_IS_VALID(buf)) {
-        REFERENCE_TIME rtStart = gst_segment_to_running_time(pin->segment, GST_FORMAT_TIME, buf->pts);
-        if (rtStart >= 0)
-            rtStart /= 100;
-
-        if (GST_BUFFER_DURATION_IS_VALID(buf)) {
-            REFERENCE_TIME tStart = buf->pts / 100;
-            REFERENCE_TIME tStop = (buf->pts + buf->duration) / 100;
-            REFERENCE_TIME rtStop;
-            rtStop = gst_segment_to_running_time(pin->segment, GST_FORMAT_TIME, buf->pts + buf->duration);
-            if (rtStop >= 0)
-                rtStop /= 100;
-            TRACE("Current time on %p: %i to %i ms\n", pin, (int)(rtStart / 10000), (int)(rtStop / 10000));
-            IMediaSample_SetTime(sample, &rtStart, rtStop >= 0 ? &rtStop : NULL);
-            IMediaSample_SetMediaTime(sample, &tStart, &tStop);
+        IMediaSample_GetPointer(sample, &ptr);
+
+        memcpy(ptr, &info.data[position], advance);
+
+        if (GST_BUFFER_PTS_IS_VALID(buf)) {
+            REFERENCE_TIME rtStart;
+            GstClockTime ptsStart = buf->pts;
+            if (position > 0 && pin->bytes_per_second)
+                ptsStart = buf->pts + gst_util_uint64_scale(position, GST_SECOND, pin->bytes_per_second);
+            rtStart = gst_segment_to_running_time(pin->segment, GST_FORMAT_TIME, ptsStart);
+            if (rtStart >= 0)
+                rtStart /= 100;
+
+            if (GST_BUFFER_DURATION_IS_VALID(buf)) {
+                REFERENCE_TIME rtStop;
+                REFERENCE_TIME tStart;
+                REFERENCE_TIME tStop;
+                GstClockTime ptsStop = buf->pts + buf->duration;
+                if (position + advance < info.size && pin->bytes_per_second)
+                    ptsStop = buf->pts + gst_util_uint64_scale(position + advance, GST_SECOND, pin->bytes_per_second);
+                tStart = ptsStart / 100;
+                tStop = ptsStop / 100;
+                rtStop = gst_segment_to_running_time(pin->segment, GST_FORMAT_TIME, ptsStop);
+                if (rtStop >= 0)
+                    rtStop /= 100;
+                TRACE("Current time on %p: %i to %i ms\n", pin, (int)(rtStart / 10000), (int)(rtStop / 10000));
+                IMediaSample_SetTime(sample, &rtStart, rtStop >= 0 ? &rtStop : NULL);
+                IMediaSample_SetMediaTime(sample, &tStart, &tStop);
+            } else {
+                IMediaSample_SetTime(sample, rtStart >= 0 ? &rtStart : NULL, NULL);
+                IMediaSample_SetMediaTime(sample, NULL, NULL);
+            }
         } else {
-            IMediaSample_SetTime(sample, rtStart >= 0 ? &rtStart : NULL, NULL);
+            IMediaSample_SetTime(sample, NULL, NULL);
             IMediaSample_SetMediaTime(sample, NULL, NULL);
         }
-    } else {
-        IMediaSample_SetTime(sample, NULL, NULL);
-        IMediaSample_SetMediaTime(sample, NULL, NULL);
-    }
 
-    IMediaSample_SetDiscontinuity(sample, GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DISCONT));
-    IMediaSample_SetPreroll(sample, GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_LIVE));
-    IMediaSample_SetSyncPoint(sample, !GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT));
+        IMediaSample_SetDiscontinuity(sample, GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DISCONT));
+        IMediaSample_SetPreroll(sample, GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_LIVE));
+        IMediaSample_SetSyncPoint(sample, !GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT));
 
-    if (!pin->pin.pin.peer)
-        hr = VFW_E_NOT_CONNECTED;
-    else
-        hr = IMemInputPin_Receive(pin->pin.pMemInputPin, sample);
+        if (!pin->pin.pin.peer)
+            hr = VFW_E_NOT_CONNECTED;
+        else
+            hr = IMemInputPin_Receive(pin->pin.pMemInputPin, sample);
 
-    TRACE("sending sample returned: %08x\n", hr);
+        TRACE("sending sample returned: %08x\n", hr);
 
-    gst_buffer_unref(buf);
-    IMediaSample_Release(sample);
+        IMediaSample_Release(sample);
 
-    if (hr == VFW_E_NOT_CONNECTED)
-        return GST_FLOW_NOT_LINKED;
+        if (hr == VFW_E_NOT_CONNECTED)
+        {
+            gst_buffer_unmap(buf, &info);
+            gst_buffer_unref(buf);
+            return GST_FLOW_NOT_LINKED;
+        }
 
-    if (FAILED(hr))
-        return GST_FLOW_FLUSHING;
+        if (FAILED(hr))
+        {
+            gst_buffer_unmap(buf, &info);
+            gst_buffer_unref(buf);
+            return GST_FLOW_FLUSHING;
+        }
+
+        position += advance;
+    }
+
+    gst_buffer_unmap(buf, &info);
+    gst_buffer_unref(buf);
 
     return GST_FLOW_OK;
 }
@@ -2104,6 +2136,8 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface,
     {
         WAVEFORMATEX *format = (WAVEFORMATEX *)pin->pin.pin.mt.pbFormat;
         buffer_size = format->nAvgBytesPerSec;
+
+        pin->bytes_per_second = format->nAvgBytesPerSec;
     }
 
     props->cBuffers = max(props->cBuffers, 1);
-- 
2.25.1




More information about the wine-devel mailing list