From: Alfred Agrell floating@muncher.se
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=9127 --- dlls/winegstreamer/quartz_parser.c | 33 ++++++++++++++++---- dlls/winegstreamer/unixlib.h | 2 +- dlls/winegstreamer/wg_parser.c | 48 ++++++++++++++++++++---------- 3 files changed, 61 insertions(+), 22 deletions(-)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 81d6a12da24..a74d9baee69 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -1300,7 +1300,8 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface) if (seeking->llStop) stop_flags = AM_SEEKING_AbsolutePositioning; wg_parser_stream_seek(filter->sources[0]->wg_stream, seeking->dRate, - seeking->llCurrent, seeking->llStop, AM_SEEKING_AbsolutePositioning, stop_flags); + seeking->llCurrent, seeking->llStop == seeking->llDuration ? -1 : seeking->llStop, + AM_SEEKING_AbsolutePositioning, stop_flags);
for (i = 0; i < filter->source_count; ++i) { @@ -2163,10 +2164,10 @@ static HRESULT mpeg_splitter_sink_query_accept(struct strmbase_pin *iface, const { if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Stream)) return S_FALSE; - if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1Audio)) + if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1Audio) + || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1System)) return S_OK; if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1Video) - || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1System) || IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1VideoCD)) FIXME("Unsupported subtype %s.\n", wine_dbgstr_guid(&mt->subtype)); return S_FALSE; @@ -2181,8 +2182,28 @@ static const struct strmbase_sink_ops mpeg_splitter_sink_ops =
static BOOL mpeg_splitter_filter_init_gst(struct parser *filter) { - if (!create_pin(filter, wg_parser_get_stream(filter->wg_parser, 0), L"Audio")) - return FALSE; + wg_parser_t parser = filter->wg_parser; + unsigned int i, stream_count; + wg_parser_stream_t stream; + struct wg_format fmt; + + stream_count = wg_parser_get_stream_count(parser); + for (i = 0; i < stream_count; ++i) + { + stream = wg_parser_get_stream(parser, i); + wg_parser_stream_get_preferred_format(stream, &fmt); + if (fmt.major_type == WG_MAJOR_TYPE_VIDEO_MPEG1) + { + if (!create_pin(filter, wg_parser_get_stream(parser, i), L"Video")) + return FALSE; + } + else if (fmt.major_type == WG_MAJOR_TYPE_AUDIO_MPEG1) + { + if (!create_pin(filter, wg_parser_get_stream(parser, i), L"Audio")) + return FALSE; + } + else FIXME("unexpected format %u\n", fmt.major_type); + }
return TRUE; } @@ -2242,7 +2263,7 @@ HRESULT mpeg_splitter_create(IUnknown *outer, IUnknown **out) struct parser *object; HRESULT hr;
- if (FAILED(hr = parser_create(WG_PARSER_MPEGAUDIOPARSE, &object))) + if (FAILED(hr = parser_create(WG_PARSER_MPEGSPLIT, &object))) return hr;
strmbase_filter_init(&object->filter, outer, &CLSID_MPEG1Splitter, &mpeg_splitter_ops); diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index ff24886fce9..5d3bfefce46 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -208,7 +208,7 @@ enum wg_parser_type { WG_PARSER_DECODEBIN, WG_PARSER_AVIDEMUX, - WG_PARSER_MPEGAUDIOPARSE, + WG_PARSER_MPEGSPLIT, WG_PARSER_WAVPARSE, };
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 299eea09c90..efac26b4fb3 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -80,6 +80,7 @@ struct wg_parser pthread_cond_t init_cond; bool no_more_pads, has_duration, error; bool err_on, warn_on; + bool chain_decodebins;
pthread_cond_t read_cond, read_done_cond; struct @@ -451,7 +452,8 @@ static NTSTATUS wg_parser_stream_seek(void *args) stop_type = GST_SEEK_TYPE_NONE;
if (!push_event(get_stream(params->stream)->my_sink, gst_event_new_seek(params->rate, GST_FORMAT_TIME, - flags, start_type, params->start_pos * 100, stop_type, params->stop_pos * 100))) + flags, start_type, params->start_pos * 100, stop_type, + params->stop_pos == -1 ? -1 : params->stop_pos * 100))) GST_ERROR("Failed to seek.\n");
return S_OK; @@ -468,7 +470,7 @@ static NTSTATUS wg_parser_stream_notify_qos(void *args) * file (or other medium), but gst_event_new_qos() expects the timestamp in * running time. */ stream_time = gst_segment_to_running_time(&stream->segment, GST_FORMAT_TIME, params->timestamp * 100); - if (stream_time == -1) + if (stream_time == -1 || -params->diff*100 >= stream_time) { /* This can happen legitimately if the sample falls outside of the * segment bounds. GStreamer elements shouldn't present the sample in @@ -979,7 +981,7 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user) gst_caps_unref(caps);
/* For compressed stream, create an extra decodebin to decode it. */ - if (format_is_compressed(&stream->codec_format)) + if (parser->chain_decodebins && format_is_compressed(&stream->codec_format)) { if (!stream_decodebin_create(stream)) { @@ -1768,6 +1770,7 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
gst_bin_add(GST_BIN(parser->container), element); parser->decodebin = element; + parser->chain_decodebins = true;
g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser); g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser); @@ -1808,27 +1811,42 @@ static BOOL avi_parser_init_gst(struct wg_parser *parser) return TRUE; }
-static BOOL mpeg_audio_parser_init_gst(struct wg_parser *parser) +static BOOL mpeg_split_parser_init_gst(struct wg_parser *parser) { - struct wg_parser_stream *stream; GstElement *element;
- if (!(element = create_element("mpegaudioparse", "good"))) + if (!(element = create_element("decodebin", "base"))) return FALSE;
gst_bin_add(GST_BIN(parser->container), element); + parser->decodebin = element; + parser->chain_decodebins = false;
- if (!link_src_to_element(parser->my_src, element)) - return FALSE; + g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser); + g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser); + g_signal_connect(element, "autoplug-continue", G_CALLBACK(autoplug_continue_cb), parser); + g_signal_connect(element, "autoplug-select", G_CALLBACK(autoplug_select_cb), parser); + g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser);
- if (!(stream = create_stream(parser))) - return FALSE; + g_object_set(element, "caps", + gst_caps_new_full( + gst_structure_new("video/mpeg", + "mpegversion", G_TYPE_INT, 1, + "systemstream", G_TYPE_BOOLEAN, FALSE, + "parsed", G_TYPE_BOOLEAN, TRUE, + NULL), + gst_structure_new("audio/mpeg", + "mpegversion", G_TYPE_INT, 1, + "parsed", G_TYPE_BOOLEAN, TRUE, + NULL), + NULL), NULL);
- if (!link_element_to_sink(element, stream->my_sink)) - return FALSE; - gst_pad_set_active(stream->my_sink, 1); + pthread_mutex_lock(&parser->mutex); + parser->no_more_pads = false; + pthread_mutex_unlock(&parser->mutex);
- parser->no_more_pads = true; + if (!link_src_to_element(parser->my_src, element)) + return FALSE;
return TRUE; } @@ -1864,7 +1882,7 @@ static NTSTATUS wg_parser_create(void *args) { [WG_PARSER_DECODEBIN] = decodebin_parser_init_gst, [WG_PARSER_AVIDEMUX] = avi_parser_init_gst, - [WG_PARSER_MPEGAUDIOPARSE] = mpeg_audio_parser_init_gst, + [WG_PARSER_MPEGSPLIT] = mpeg_split_parser_init_gst, [WG_PARSER_WAVPARSE] = wave_parser_init_gst, };