Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50355 Signed-off-by: Anton Baskanov baskanov@gmail.com --- v2: Set discontinuity and sync point flags only for the first sample. --- dlls/winegstreamer/gstdemux.c | 144 +++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 54 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 9114e6610a3..676b7396515 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,108 @@ 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, + !position && 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, + !position && !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 +2138,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);