Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gst_private.h | 4 ++++ dlls/winegstreamer/gstdemux.c | 31 ++++++------------------------- dlls/winegstreamer/wg_parser.c | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 25 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 3c6d1147477..c77c5c14665 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -228,6 +228,10 @@ struct unix_funcs bool (CDECL *wg_parser_stream_get_event)(struct wg_parser_stream *stream, struct wg_parser_event *event); void (CDECL *wg_parser_stream_notify_qos)(struct wg_parser_stream *stream, bool underflow, double proportion, int64_t diff, uint64_t timestamp); + + /* start_pos and stop_pos are in 100-nanosecond units. */ + bool (CDECL *wg_parser_stream_seek)(struct wg_parser_stream *stream, double rate, + uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags); };
extern const struct unix_funcs *unix_funcs; diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index da294c31e01..1af34441984 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -848,7 +848,7 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface) { struct parser *filter = impl_from_strmbase_filter(iface); struct wg_parser *parser = filter->wg_parser; - GstSeekType stop_type = GST_SEEK_TYPE_NONE; + DWORD stop_flags = AM_SEEKING_NoPositioning; const SourceSeeking *seeking; unsigned int i;
@@ -861,15 +861,11 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface) /* DirectShow retains the old seek positions, but resets to them every time * it transitions from stopped -> paused. */
- parser->next_offset = parser->start_offset; - seeking = &filter->sources[0]->seek; if (seeking->llStop && seeking->llStop != seeking->llDuration) - stop_type = GST_SEEK_TYPE_SET; - gst_pad_push_event(filter->sources[0]->wg_stream->my_sink, gst_event_new_seek( - seeking->dRate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, - GST_SEEK_TYPE_SET, seeking->llCurrent * 100, - stop_type, seeking->llStop * 100)); + stop_flags = AM_SEEKING_AbsolutePositioning; + unix_funcs->wg_parser_stream_seek(filter->sources[0]->wg_stream, seeking->dRate, + seeking->llCurrent, seeking->llStop, AM_SEEKING_AbsolutePositioning, stop_flags);
for (i = 0; i < filter->source_count; ++i) { @@ -1212,11 +1208,8 @@ static ULONG WINAPI GST_Seeking_Release(IMediaSeeking *iface) static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface, LONGLONG *current, DWORD current_flags, LONGLONG *stop, DWORD stop_flags) { - GstSeekType current_type = GST_SEEK_TYPE_SET, stop_type = GST_SEEK_TYPE_SET; struct parser_source *pin = impl_from_IMediaSeeking(iface); - struct wg_parser_stream *stream = pin->wg_stream; struct parser *filter = impl_from_strmbase_filter(pin->pin.pin.filter); - GstSeekFlags flags = 0; HRESULT hr = S_OK; int i;
@@ -1256,20 +1249,8 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface,
SourceSeekingImpl_SetPositions(iface, current, current_flags, stop, stop_flags);
- if (current_flags & AM_SEEKING_SeekToKeyFrame) - flags |= GST_SEEK_FLAG_KEY_UNIT; - if (current_flags & AM_SEEKING_Segment) - flags |= GST_SEEK_FLAG_SEGMENT; - if (!(current_flags & AM_SEEKING_NoFlush)) - flags |= GST_SEEK_FLAG_FLUSH; - - if ((current_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning) - current_type = GST_SEEK_TYPE_NONE; - if ((stop_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning) - stop_type = GST_SEEK_TYPE_NONE; - - if (!gst_pad_push_event(stream->my_sink, gst_event_new_seek(pin->seek.dRate, GST_FORMAT_TIME, flags, - current_type, pin->seek.llCurrent * 100, stop_type, pin->seek.llStop * 100))) + if (!unix_funcs->wg_parser_stream_seek(pin->wg_stream, pin->seek.dRate, + pin->seek.llCurrent, pin->seek.llStop, current_flags, stop_flags)) { ERR("Failed to seek (current %s, stop %s).\n", debugstr_time(pin->seek.llCurrent), debugstr_time(pin->seek.llStop)); diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 79fa45eadca..0738df150b2 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -391,6 +391,28 @@ static bool CDECL wg_parser_stream_get_event(struct wg_parser_stream *stream, st return true; }
+static bool CDECL wg_parser_stream_seek(struct wg_parser_stream *stream, double rate, + uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags) +{ + GstSeekType start_type = GST_SEEK_TYPE_SET, stop_type = GST_SEEK_TYPE_SET; + GstSeekFlags flags = 0; + + if (start_flags & AM_SEEKING_SeekToKeyFrame) + flags |= GST_SEEK_FLAG_KEY_UNIT; + if (start_flags & AM_SEEKING_Segment) + flags |= GST_SEEK_FLAG_SEGMENT; + if (!(start_flags & AM_SEEKING_NoFlush)) + flags |= GST_SEEK_FLAG_FLUSH; + + if ((start_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning) + start_type = GST_SEEK_TYPE_NONE; + if ((stop_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning) + stop_type = GST_SEEK_TYPE_NONE; + + return gst_pad_push_event(stream->my_sink, gst_event_new_seek(rate, + GST_FORMAT_TIME, flags, start_type, start_pos * 100, stop_type, stop_pos * 100)); +} + static void CDECL wg_parser_stream_notify_qos(struct wg_parser_stream *stream, bool underflow, double proportion, int64_t diff, uint64_t timestamp) { @@ -1565,6 +1587,8 @@ static const struct unix_funcs funcs =
wg_parser_stream_get_event, wg_parser_stream_notify_qos, + + wg_parser_stream_seek, };
NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gstdemux.c | 5 ----- dlls/winegstreamer/wg_parser.c | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 1af34441984..f4573c75f86 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1430,7 +1430,6 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, IMemAllocator *allocator, ALLOCATOR_PROPERTIES *props) { struct parser_source *pin = impl_source_from_IPin(&iface->pin.IPin_iface); - struct wg_parser_stream *stream = pin->wg_stream; unsigned int buffer_size = 16384; ALLOCATOR_PROPERTIES ret_props; struct wg_format format; @@ -1440,10 +1439,6 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, { VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pin->pin.pin.mt.pbFormat; buffer_size = format->bmiHeader.biSizeImage; - - gst_util_set_object_arg(G_OBJECT(stream->flip), "method", - (format->bmiHeader.biCompression == BI_RGB - || format->bmiHeader.biCompression == BI_BITFIELDS) ? "vertical-flip" : "none"); } else if (IsEqualGUID(&pin->pin.pin.mt.formattype, &FORMAT_WaveFormatEx) && (IsEqualGUID(&pin->pin.pin.mt.subtype, &MEDIASUBTYPE_PCM) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 0738df150b2..8437dc1897d 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -358,6 +358,33 @@ static void CDECL wg_parser_stream_enable(struct wg_parser_stream *stream, const { stream->current_format = *format; stream->enabled = true; + + if (format->major_type == WG_MAJOR_TYPE_VIDEO) + { + switch (format->u.video.format) + { + case WG_VIDEO_FORMAT_BGRA: + case WG_VIDEO_FORMAT_BGRx: + case WG_VIDEO_FORMAT_BGR: + case WG_VIDEO_FORMAT_RGB15: + case WG_VIDEO_FORMAT_RGB16: + gst_util_set_object_arg(G_OBJECT(stream->flip), "method", "vertical-flip"); + break; + + case WG_VIDEO_FORMAT_AYUV: + case WG_VIDEO_FORMAT_I420: + case WG_VIDEO_FORMAT_NV12: + case WG_VIDEO_FORMAT_UYVY: + case WG_VIDEO_FORMAT_YUY2: + case WG_VIDEO_FORMAT_YV12: + case WG_VIDEO_FORMAT_YVYU: + case WG_VIDEO_FORMAT_UNKNOWN: + case WG_VIDEO_FORMAT_CINEPAK: + gst_util_set_object_arg(G_OBJECT(stream->flip), "method", "none"); + break; + } + } + gst_pad_push_event(stream->my_sink, gst_event_new_reconfigure()); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gstdemux.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index f4573c75f86..cc55b4fa60a 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1178,12 +1178,11 @@ static HRESULT WINAPI GST_ChangeStop(IMediaSeeking *iface)
static HRESULT WINAPI GST_ChangeRate(IMediaSeeking *iface) { - struct parser_source *This = impl_from_IMediaSeeking(iface); - struct wg_parser_stream *stream = This->wg_stream; - GstEvent *ev = gst_event_new_seek(This->seek.dRate, GST_FORMAT_TIME, 0, GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1); - TRACE("(%p) New rate %g\n", This, This->seek.dRate); + struct parser_source *pin = impl_from_IMediaSeeking(iface); + mark_wine_thread(); - gst_pad_push_event(stream->my_sink, ev); + unix_funcs->wg_parser_stream_seek(pin->wg_stream, pin->seek.dRate, 0, 0, + AM_SEEKING_NoPositioning, AM_SEEKING_NoPositioning); return S_OK; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gst_private.h | 13 ++++- dlls/winegstreamer/gstdemux.c | 89 ++++++++++++++++-------------- dlls/winegstreamer/wg_parser.c | 94 ++++++++++++++++++++++++++------ 3 files changed, 138 insertions(+), 58 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index c77c5c14665..068cb47adc2 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -179,7 +179,13 @@ struct wg_parser_event enum wg_parser_event_type type; union { - GstBuffer *buffer; + struct + { + /* pts and duration are in 100-nanosecond units. */ + uint64_t pts, duration; + uint32_t size; + bool discontinuity, preroll, delta, has_pts, has_duration; + } buffer; struct { uint64_t position, stop; @@ -198,6 +204,8 @@ struct wg_parser_stream
pthread_cond_t event_cond, event_empty_cond; struct wg_parser_event event; + GstBuffer *buffer; + GstMapInfo map_info;
bool flushing, eos, enabled, has_caps;
@@ -226,6 +234,9 @@ struct unix_funcs void (CDECL *wg_parser_stream_disable)(struct wg_parser_stream *stream);
bool (CDECL *wg_parser_stream_get_event)(struct wg_parser_stream *stream, struct wg_parser_event *event); + bool (CDECL *wg_parser_stream_copy_buffer)(struct wg_parser_stream *stream, + void *data, uint32_t offset, uint32_t size); + void (CDECL *wg_parser_stream_release_buffer)(struct wg_parser_stream *stream); void (CDECL *wg_parser_stream_notify_qos)(struct wg_parser_stream *stream, bool underflow, double proportion, int64_t diff, uint64_t timestamp);
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index cc55b4fa60a..c256d963273 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -568,11 +568,13 @@ static bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
/* Fill and send a single IMediaSample. */ static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample, - GstBuffer *buf, GstMapInfo *info, gsize offset, gsize size, DWORD bytes_per_second) + const struct wg_parser_event *event, uint32_t offset, uint32_t size, DWORD bytes_per_second) { HRESULT hr; BYTE *ptr = NULL;
+ TRACE("offset %u, size %u, sample size %u\n", offset, size, IMediaSample_GetSize(sample)); + hr = IMediaSample_SetActualDataLength(sample, size); if(FAILED(hr)){ WARN("SetActualDataLength failed: %08x\n", hr); @@ -581,37 +583,48 @@ static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample,
IMediaSample_GetPointer(sample, &ptr);
- memcpy(ptr, &info->data[offset], size); - - if (GST_BUFFER_PTS_IS_VALID(buf)) { - REFERENCE_TIME rtStart, ptsStart = buf->pts; - - if (offset > 0) - ptsStart = buf->pts + gst_util_uint64_scale(offset, GST_SECOND, bytes_per_second); - rtStart = ((ptsStart / 100) - pin->seek.llCurrent) * pin->seek.dRate; - - if (GST_BUFFER_DURATION_IS_VALID(buf)) { - REFERENCE_TIME rtStop, tStart, tStop, ptsStop = buf->pts + buf->duration; - if (offset + size < info->size) - ptsStop = buf->pts + gst_util_uint64_scale(offset + size, GST_SECOND, bytes_per_second); - tStart = ptsStart / 100; - tStop = ptsStop / 100; - rtStop = ((ptsStop / 100) - pin->seek.llCurrent) * pin->seek.dRate; - 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); + if (!unix_funcs->wg_parser_stream_copy_buffer(pin->wg_stream, ptr, offset, size)) + { + /* The GStreamer pin has been flushed. */ + return S_OK; + } + + if (event->u.buffer.has_pts) + { + REFERENCE_TIME start_pts = event->u.buffer.pts; + + if (offset) + start_pts += gst_util_uint64_scale(offset, 10000000, bytes_per_second); + start_pts -= pin->seek.llCurrent; + start_pts *= pin->seek.dRate; + + if (event->u.buffer.has_duration) + { + REFERENCE_TIME end_pts = event->u.buffer.pts + event->u.buffer.duration; + + if (offset + size < event->u.buffer.size) + end_pts = event->u.buffer.pts + gst_util_uint64_scale(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 { + } + else + { IMediaSample_SetTime(sample, NULL, NULL); IMediaSample_SetMediaTime(sample, NULL, NULL); }
- IMediaSample_SetDiscontinuity(sample, !offset && 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, !offset && event->u.buffer.discontinuity); + IMediaSample_SetPreroll(sample, event->u.buffer.preroll); + IMediaSample_SetSyncPoint(sample, !event->u.buffer.delta);
if (!pin->pin.pin.peer) hr = VFW_E_NOT_CONNECTED; @@ -625,23 +638,21 @@ static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample,
/* Send a single GStreamer buffer (splitting it into multiple IMediaSamples if * necessary). */ -static void send_buffer(struct parser_source *pin, GstBuffer *buf) +static void send_buffer(struct parser_source *pin, const struct wg_parser_event *event) { HRESULT hr; IMediaSample *sample; - GstMapInfo info; - - gst_buffer_map(buf, &info, GST_MAP_READ);
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))) { WAVEFORMATEX *format = (WAVEFORMATEX *)pin->pin.pin.mt.pbFormat; - gsize offset = 0; - while (offset < info.size) + uint32_t offset = 0; + + while (offset < event->u.buffer.size) { - gsize advance; + uint32_t advance;
hr = BaseOutputPinImpl_GetDeliveryBuffer(&pin->pin, &sample, NULL, NULL, 0);
@@ -652,9 +663,9 @@ static void send_buffer(struct parser_source *pin, GstBuffer *buf) break; }
- advance = min(IMediaSample_GetSize(sample), info.size - offset); + advance = min(IMediaSample_GetSize(sample), event->u.buffer.size - offset);
- hr = send_sample(pin, sample, buf, &info, offset, advance, format->nAvgBytesPerSec); + hr = send_sample(pin, sample, event, offset, advance, format->nAvgBytesPerSec);
IMediaSample_Release(sample);
@@ -675,15 +686,13 @@ static void send_buffer(struct parser_source *pin, GstBuffer *buf) } else { - hr = send_sample(pin, sample, buf, &info, 0, info.size, 0); + hr = send_sample(pin, sample, event, 0, event->u.buffer.size, 0);
IMediaSample_Release(sample); } }
- gst_buffer_unmap(buf, &info); - - gst_buffer_unref(buf); + unix_funcs->wg_parser_stream_release_buffer(pin->wg_stream); }
static DWORD CALLBACK stream_thread(void *arg) @@ -710,7 +719,7 @@ static DWORD CALLBACK stream_thread(void *arg) switch (event.type) { case WG_PARSER_EVENT_BUFFER: - send_buffer(pin, event.u.buffer); + send_buffer(pin, &event); break;
case WG_PARSER_EVENT_EOS: diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 8437dc1897d..de066f83881 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -410,14 +410,56 @@ static bool CDECL wg_parser_stream_get_event(struct wg_parser_stream *stream, st }
*event = stream->event; - stream->event.type = WG_PARSER_EVENT_NONE;
+ if (stream->event.type != WG_PARSER_EVENT_BUFFER) + { + stream->event.type = WG_PARSER_EVENT_NONE; + pthread_cond_signal(&stream->event_empty_cond); + } pthread_mutex_unlock(&parser->mutex); - pthread_cond_signal(&stream->event_empty_cond);
return true; }
+static bool CDECL wg_parser_stream_copy_buffer(struct wg_parser_stream *stream, + void *data, uint32_t offset, uint32_t size) +{ + struct wg_parser *parser = stream->parser; + + pthread_mutex_lock(&parser->mutex); + + if (!stream->buffer) + { + pthread_mutex_unlock(&parser->mutex); + return false; + } + + assert(stream->event.type == WG_PARSER_EVENT_BUFFER); + assert(offset < stream->map_info.size); + assert(offset + size <= stream->map_info.size); + memcpy(data, stream->map_info.data + offset, size); + + pthread_mutex_unlock(&parser->mutex); + return true; +} + +static void CDECL wg_parser_stream_release_buffer(struct wg_parser_stream *stream) +{ + struct wg_parser *parser = stream->parser; + + pthread_mutex_lock(&parser->mutex); + + assert(stream->event.type == WG_PARSER_EVENT_BUFFER); + + gst_buffer_unmap(stream->buffer, &stream->map_info); + gst_buffer_unref(stream->buffer); + stream->buffer = NULL; + stream->event.type = WG_PARSER_EVENT_NONE; + + pthread_mutex_unlock(&parser->mutex); + pthread_cond_signal(&stream->event_empty_cond); +} + static bool CDECL wg_parser_stream_seek(struct wg_parser_stream *stream, double rate, uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags) { @@ -482,7 +524,8 @@ static void no_more_pads(GstElement *element, gpointer user) pthread_cond_signal(&parser->init_cond); }
-static GstFlowReturn queue_stream_event(struct wg_parser_stream *stream, const struct wg_parser_event *event) +static GstFlowReturn queue_stream_event(struct wg_parser_stream *stream, + const struct wg_parser_event *event, GstBuffer *buffer) { struct wg_parser *parser = stream->parser;
@@ -501,7 +544,18 @@ static GstFlowReturn queue_stream_event(struct wg_parser_stream *stream, const s GST_DEBUG("Filter is flushing; discarding event."); return GST_FLOW_FLUSHING; } + if (buffer) + { + assert(GST_IS_BUFFER(buffer)); + if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ)) + { + pthread_mutex_unlock(&parser->mutex); + GST_ERROR("Failed to map buffer.\n"); + return GST_FLOW_ERROR; + } + } stream->event = *event; + stream->buffer = buffer; pthread_mutex_unlock(&parser->mutex); pthread_cond_signal(&stream->event_cond); GST_LOG("Event queued."); @@ -535,7 +589,7 @@ static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event) stream_event.u.segment.position = segment->position / 100; stream_event.u.segment.stop = segment->stop / 100; stream_event.u.segment.rate = segment->rate * segment->applied_rate; - queue_stream_event(stream, &stream_event); + queue_stream_event(stream, &stream_event, NULL); } break;
@@ -545,7 +599,7 @@ static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event) struct wg_parser_event stream_event;
stream_event.type = WG_PARSER_EVENT_EOS; - queue_stream_event(stream, &stream_event); + queue_stream_event(stream, &stream_event, NULL); } else { @@ -564,16 +618,11 @@ static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event) stream->flushing = true; pthread_cond_signal(&stream->event_empty_cond);
- switch (stream->event.type) + if (stream->event.type == WG_PARSER_EVENT_BUFFER) { - case WG_PARSER_EVENT_NONE: - case WG_PARSER_EVENT_EOS: - case WG_PARSER_EVENT_SEGMENT: - break; - - case WG_PARSER_EVENT_BUFFER: - gst_buffer_unref(stream->event.u.buffer); - break; + gst_buffer_unmap(stream->buffer, &stream->map_info); + gst_buffer_unref(stream->buffer); + stream->buffer = NULL; } stream->event.type = WG_PARSER_EVENT_NONE;
@@ -625,9 +674,18 @@ static GstFlowReturn got_data_sink(GstPad *pad, GstObject *parent, GstBuffer *bu }
stream_event.type = WG_PARSER_EVENT_BUFFER; - stream_event.u.buffer = buffer; - /* Transfer our reference to the buffer to the object. */ - if ((ret = queue_stream_event(stream, &stream_event)) != GST_FLOW_OK) + + if ((stream_event.u.buffer.has_pts = GST_BUFFER_PTS_IS_VALID(buffer))) + stream_event.u.buffer.pts = GST_BUFFER_PTS(buffer) / 100; + if ((stream_event.u.buffer.has_duration = GST_BUFFER_DURATION_IS_VALID(buffer))) + stream_event.u.buffer.duration = GST_BUFFER_DURATION(buffer) / 100; + stream_event.u.buffer.discontinuity = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT); + stream_event.u.buffer.preroll = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE); + stream_event.u.buffer.delta = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT); + stream_event.u.buffer.size = gst_buffer_get_size(buffer); + + /* Transfer our reference to the buffer to the stream object. */ + if ((ret = queue_stream_event(stream, &stream_event, buffer)) != GST_FLOW_OK) gst_buffer_unref(buffer); return ret; } @@ -1613,6 +1671,8 @@ static const struct unix_funcs funcs = wg_parser_stream_disable,
wg_parser_stream_get_event, + wg_parser_stream_copy_buffer, + wg_parser_stream_release_buffer, wg_parser_stream_notify_qos,
wg_parser_stream_seek,
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gstdemux.c | 51 +++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index c256d963273..2a7383111b1 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -566,6 +566,53 @@ static 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@cse.ogi.edu + * 2000 Wim Taymans wtay@chello.be + * 2002 Thomas Vander Stichele thomas@apestaart.org + * 2004 Wim Taymans wim@fluendo.com + * 2015 Jan Schmidt jan@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 = i.u.LowPart * numerator; + high.QuadPart = 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_event *event, uint32_t offset, uint32_t size, DWORD bytes_per_second) @@ -594,7 +641,7 @@ static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample, REFERENCE_TIME start_pts = event->u.buffer.pts;
if (offset) - start_pts += gst_util_uint64_scale(offset, 10000000, bytes_per_second); + start_pts += scale_uint64(offset, 10000000, bytes_per_second); start_pts -= pin->seek.llCurrent; start_pts *= pin->seek.dRate;
@@ -603,7 +650,7 @@ static HRESULT send_sample(struct parser_source *pin, IMediaSample *sample, REFERENCE_TIME end_pts = event->u.buffer.pts + event->u.buffer.duration;
if (offset + size < event->u.buffer.size) - end_pts = event->u.buffer.pts + gst_util_uint64_scale(offset + size, 10000000, bytes_per_second); + end_pts = event->u.buffer.pts + scale_uint64(offset + size, 10000000, bytes_per_second); end_pts -= pin->seek.llCurrent; end_pts *= pin->seek.dRate;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gst_private.h | 4 ++++ dlls/winegstreamer/gstdemux.c | 21 +++++++------------ dlls/winegstreamer/wg_parser.c | 35 ++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 068cb47adc2..33c87f2c1ec 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -226,6 +226,10 @@ struct unix_funcs void (CDECL *wg_parser_begin_flush)(struct wg_parser *parser); void (CDECL *wg_parser_end_flush)(struct wg_parser *parser);
+ bool (CDECL *wg_parser_get_read_request)(struct wg_parser *parser, + GstBuffer **buffer, uint64_t *offset, uint32_t *size); + void (CDECL *wg_parser_complete_read_request)(struct wg_parser *parser, GstFlowReturn ret); + uint32_t (CDECL *wg_parser_get_stream_count)(struct wg_parser *parser); struct wg_parser_stream *(CDECL *wg_parser_get_stream)(struct wg_parser *parser, uint32_t index);
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 2a7383111b1..4e476c78e9e 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -822,29 +822,22 @@ static GstFlowReturn read_buffer(struct parser *This, guint64 ofs, guint len, Gs static DWORD CALLBACK read_thread(void *arg) { struct parser *filter = arg; - struct wg_parser *parser = filter->wg_parser;
TRACE("Starting read thread for filter %p.\n", filter);
- pthread_mutex_lock(&parser->mutex); - while (filter->sink_connected) { - while (parser->sink_connected && !parser->read_request.buffer) - pthread_cond_wait(&parser->read_cond, &parser->mutex); + GstBuffer *buffer; + uint64_t offset; + uint32_t size;
- if (!parser->sink_connected) - break; + if (!unix_funcs->wg_parser_get_read_request(filter->wg_parser, &buffer, &offset, &size)) + continue;
- parser->read_request.done = true; - parser->read_request.ret = read_buffer(filter, parser->read_request.offset, - parser->read_request.size, parser->read_request.buffer); - parser->read_request.buffer = NULL; - pthread_cond_signal(&parser->read_done_cond); + unix_funcs->wg_parser_complete_read_request(filter->wg_parser, + read_buffer(filter, offset, size, buffer)); }
- pthread_mutex_unlock(&parser->mutex); - TRACE("Streaming stopped; exiting.\n"); return 0; } diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index de066f83881..96c6fc1e715 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -349,6 +349,38 @@ static void CDECL wg_parser_end_flush(struct wg_parser *parser) pthread_mutex_unlock(&parser->mutex); }
+static bool CDECL wg_parser_get_read_request(struct wg_parser *parser, + GstBuffer **buffer, uint64_t *offset, uint32_t *size) +{ + pthread_mutex_lock(&parser->mutex); + + while (parser->sink_connected && !parser->read_request.buffer) + pthread_cond_wait(&parser->read_cond, &parser->mutex); + + if (!parser->sink_connected) + { + pthread_mutex_unlock(&parser->mutex); + return false; + } + + *buffer = parser->read_request.buffer; + *offset = parser->read_request.offset; + *size = parser->read_request.size; + + pthread_mutex_unlock(&parser->mutex); + return true; +} + +static void CDECL wg_parser_complete_read_request(struct wg_parser *parser, GstFlowReturn ret) +{ + pthread_mutex_lock(&parser->mutex); + parser->read_request.done = true; + parser->read_request.ret = ret; + parser->read_request.buffer = NULL; + pthread_mutex_unlock(&parser->mutex); + pthread_cond_signal(&parser->read_done_cond); +} + static void CDECL wg_parser_stream_get_preferred_format(struct wg_parser_stream *stream, struct wg_format *format) { *format = stream->preferred_format; @@ -1663,6 +1695,9 @@ static const struct unix_funcs funcs = wg_parser_begin_flush, wg_parser_end_flush,
+ wg_parser_get_read_request, + wg_parser_complete_read_request, + wg_parser_get_stream_count, wg_parser_get_stream,