winegstreamer: Remove support for flushing the wg_parser object.
[wine.git] / dlls / winegstreamer / wg_parser.c
blob61120a72da8e3929901bd8292acef2f5d8f74250
1 /*
2 * GStreamer parser backend
4 * Copyright 2010 Maarten Lankhorst for CodeWeavers
5 * Copyright 2010 Aric Stewart for CodeWeavers
6 * Copyright 2019-2020 Zebediah Figura
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #if 0
24 #pragma makedep unix
25 #endif
27 #include "config.h"
29 #include <assert.h>
30 #include <stdarg.h>
31 #include <stdio.h>
33 #include <gst/gst.h>
34 #include <gst/video/video.h>
35 #include <gst/audio/audio.h>
37 #include "winternl.h"
38 #include "dshow.h"
40 #include "unix_private.h"
42 typedef enum
44 GST_AUTOPLUG_SELECT_TRY,
45 GST_AUTOPLUG_SELECT_EXPOSE,
46 GST_AUTOPLUG_SELECT_SKIP,
47 } GstAutoplugSelectResult;
49 /* GStreamer callbacks may be called on threads not created by Wine, and
50 * therefore cannot access the Wine TEB. This means that we must use GStreamer
51 * debug logging instead of Wine debug logging. In order to be safe we forbid
52 * any use of Wine debug logging in this entire file. */
54 GST_DEBUG_CATEGORY(wine);
55 #define GST_CAT_DEFAULT wine
57 typedef BOOL (*init_gst_cb)(struct wg_parser *parser);
59 struct wg_parser
61 init_gst_cb init_gst;
63 struct wg_parser_stream **streams;
64 unsigned int stream_count;
66 GstElement *container, *decodebin;
67 GstBus *bus;
68 GstPad *my_src, *their_sink;
70 guint64 file_size, start_offset, next_offset, stop_offset;
71 guint64 next_pull_offset;
73 pthread_t push_thread;
75 pthread_mutex_t mutex;
77 pthread_cond_t init_cond;
78 bool no_more_pads, has_duration, error;
80 pthread_cond_t read_cond, read_done_cond;
81 struct
83 GstBuffer *buffer;
84 uint64_t offset;
85 uint32_t size;
86 bool done;
87 GstFlowReturn ret;
88 } read_request;
90 bool sink_connected;
92 bool unlimited_buffering;
95 struct wg_parser_stream
97 struct wg_parser *parser;
99 GstPad *their_src, *post_sink, *post_src, *my_sink;
100 GstElement *flip;
101 GstSegment segment;
102 struct wg_format preferred_format, current_format;
104 pthread_cond_t event_cond, event_empty_cond;
105 struct wg_parser_event event;
106 GstBuffer *buffer;
107 GstMapInfo map_info;
109 bool flushing, eos, enabled, has_caps;
111 uint64_t duration;
114 static NTSTATUS wg_parser_get_stream_count(void *args)
116 struct wg_parser_get_stream_count_params *params = args;
118 params->count = params->parser->stream_count;
119 return S_OK;
122 static NTSTATUS wg_parser_get_stream(void *args)
124 struct wg_parser_get_stream_params *params = args;
126 params->stream = params->parser->streams[params->index];
127 return S_OK;
130 static NTSTATUS wg_parser_get_next_read_offset(void *args)
132 struct wg_parser_get_next_read_offset_params *params = args;
133 struct wg_parser *parser = params->parser;
135 pthread_mutex_lock(&parser->mutex);
137 while (parser->sink_connected && !parser->read_request.size)
138 pthread_cond_wait(&parser->read_cond, &parser->mutex);
140 if (!parser->sink_connected)
142 pthread_mutex_unlock(&parser->mutex);
143 return VFW_E_WRONG_STATE;
146 params->offset = parser->read_request.offset;
147 params->size = parser->read_request.size;
149 pthread_mutex_unlock(&parser->mutex);
150 return S_OK;
153 static NTSTATUS wg_parser_push_data(void *args)
155 const struct wg_parser_push_data_params *params = args;
156 struct wg_parser *parser = params->parser;
157 const void *data = params->data;
158 uint32_t size = params->size;
160 pthread_mutex_lock(&parser->mutex);
162 if (data)
164 if (size)
166 GstMapInfo map_info;
168 /* Note that we don't allocate the buffer until we have a size.
169 * midiparse passes a NULL buffer and a size of UINT_MAX, in an
170 * apparent attempt to read the whole input stream at once. */
171 if (!parser->read_request.buffer)
172 parser->read_request.buffer = gst_buffer_new_and_alloc(size);
173 gst_buffer_map(parser->read_request.buffer, &map_info, GST_MAP_WRITE);
174 memcpy(map_info.data, data, size);
175 gst_buffer_unmap(parser->read_request.buffer, &map_info);
176 parser->read_request.ret = GST_FLOW_OK;
178 else
180 parser->read_request.ret = GST_FLOW_EOS;
183 else
185 parser->read_request.ret = GST_FLOW_ERROR;
187 parser->read_request.done = true;
188 parser->read_request.size = 0;
190 pthread_mutex_unlock(&parser->mutex);
191 pthread_cond_signal(&parser->read_done_cond);
193 return S_OK;
196 static NTSTATUS wg_parser_stream_get_preferred_format(void *args)
198 const struct wg_parser_stream_get_preferred_format_params *params = args;
200 *params->format = params->stream->preferred_format;
201 return S_OK;
204 static NTSTATUS wg_parser_stream_enable(void *args)
206 const struct wg_parser_stream_enable_params *params = args;
207 struct wg_parser_stream *stream = params->stream;
208 const struct wg_format *format = params->format;
210 stream->current_format = *format;
211 stream->enabled = true;
213 if (format->major_type == WG_MAJOR_TYPE_VIDEO)
215 bool flip = (format->u.video.height < 0);
217 switch (format->u.video.format)
219 case WG_VIDEO_FORMAT_BGRA:
220 case WG_VIDEO_FORMAT_BGRx:
221 case WG_VIDEO_FORMAT_BGR:
222 case WG_VIDEO_FORMAT_RGB15:
223 case WG_VIDEO_FORMAT_RGB16:
224 flip = !flip;
225 break;
227 case WG_VIDEO_FORMAT_AYUV:
228 case WG_VIDEO_FORMAT_I420:
229 case WG_VIDEO_FORMAT_NV12:
230 case WG_VIDEO_FORMAT_UYVY:
231 case WG_VIDEO_FORMAT_YUY2:
232 case WG_VIDEO_FORMAT_YV12:
233 case WG_VIDEO_FORMAT_YVYU:
234 case WG_VIDEO_FORMAT_UNKNOWN:
235 case WG_VIDEO_FORMAT_CINEPAK:
236 break;
239 gst_util_set_object_arg(G_OBJECT(stream->flip), "method", flip ? "vertical-flip" : "none");
242 gst_pad_push_event(stream->my_sink, gst_event_new_reconfigure());
243 return S_OK;
246 static NTSTATUS wg_parser_stream_disable(void *args)
248 struct wg_parser_stream *stream = args;
250 stream->enabled = false;
251 return S_OK;
254 static NTSTATUS wg_parser_stream_get_event(void *args)
256 const struct wg_parser_stream_get_event_params *params = args;
257 struct wg_parser_stream *stream = params->stream;
258 struct wg_parser *parser = stream->parser;
260 pthread_mutex_lock(&parser->mutex);
262 while (stream->event.type == WG_PARSER_EVENT_NONE)
263 pthread_cond_wait(&stream->event_cond, &parser->mutex);
265 *params->event = stream->event;
267 if (stream->event.type != WG_PARSER_EVENT_BUFFER)
269 stream->event.type = WG_PARSER_EVENT_NONE;
270 pthread_cond_signal(&stream->event_empty_cond);
272 pthread_mutex_unlock(&parser->mutex);
274 return S_OK;
277 static NTSTATUS wg_parser_stream_copy_buffer(void *args)
279 const struct wg_parser_stream_copy_buffer_params *params = args;
280 struct wg_parser_stream *stream = params->stream;
281 struct wg_parser *parser = stream->parser;
282 uint32_t offset = params->offset;
283 uint32_t size = params->size;
285 pthread_mutex_lock(&parser->mutex);
287 if (!stream->buffer)
289 pthread_mutex_unlock(&parser->mutex);
290 return VFW_E_WRONG_STATE;
293 assert(stream->event.type == WG_PARSER_EVENT_BUFFER);
294 assert(offset < stream->map_info.size);
295 assert(offset + size <= stream->map_info.size);
296 memcpy(params->data, stream->map_info.data + offset, size);
298 pthread_mutex_unlock(&parser->mutex);
299 return S_OK;
302 static NTSTATUS wg_parser_stream_release_buffer(void *args)
304 struct wg_parser_stream *stream = args;
305 struct wg_parser *parser = stream->parser;
307 pthread_mutex_lock(&parser->mutex);
309 assert(stream->event.type == WG_PARSER_EVENT_BUFFER);
311 gst_buffer_unmap(stream->buffer, &stream->map_info);
312 gst_buffer_unref(stream->buffer);
313 stream->buffer = NULL;
314 stream->event.type = WG_PARSER_EVENT_NONE;
316 pthread_mutex_unlock(&parser->mutex);
317 pthread_cond_signal(&stream->event_empty_cond);
319 return S_OK;
322 static NTSTATUS wg_parser_stream_get_duration(void *args)
324 struct wg_parser_stream_get_duration_params *params = args;
326 params->duration = params->stream->duration;
327 return S_OK;
330 static NTSTATUS wg_parser_stream_seek(void *args)
332 GstSeekType start_type = GST_SEEK_TYPE_SET, stop_type = GST_SEEK_TYPE_SET;
333 const struct wg_parser_stream_seek_params *params = args;
334 DWORD start_flags = params->start_flags;
335 DWORD stop_flags = params->stop_flags;
336 GstSeekFlags flags = 0;
338 if (start_flags & AM_SEEKING_SeekToKeyFrame)
339 flags |= GST_SEEK_FLAG_KEY_UNIT;
340 if (start_flags & AM_SEEKING_Segment)
341 flags |= GST_SEEK_FLAG_SEGMENT;
342 if (!(start_flags & AM_SEEKING_NoFlush))
343 flags |= GST_SEEK_FLAG_FLUSH;
345 if ((start_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning)
346 start_type = GST_SEEK_TYPE_NONE;
347 if ((stop_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning)
348 stop_type = GST_SEEK_TYPE_NONE;
350 if (!gst_pad_push_event(params->stream->my_sink, gst_event_new_seek(params->rate, GST_FORMAT_TIME,
351 flags, start_type, params->start_pos * 100, stop_type, params->stop_pos * 100)))
352 GST_ERROR("Failed to seek.\n");
354 return S_OK;
357 static NTSTATUS wg_parser_stream_notify_qos(void *args)
359 const struct wg_parser_stream_notify_qos_params *params = args;
360 struct wg_parser_stream *stream = params->stream;
361 GstClockTime stream_time;
362 GstEvent *event;
364 /* We return timestamps in stream time, i.e. relative to the start of the
365 * file (or other medium), but gst_event_new_qos() expects the timestamp in
366 * running time. */
367 stream_time = gst_segment_to_running_time(&stream->segment, GST_FORMAT_TIME, params->timestamp * 100);
368 if (stream_time == -1)
370 /* This can happen legitimately if the sample falls outside of the
371 * segment bounds. GStreamer elements shouldn't present the sample in
372 * that case, but DirectShow doesn't care. */
373 GST_LOG("Ignoring QoS event.\n");
374 return S_OK;
377 if (!(event = gst_event_new_qos(params->underflow ? GST_QOS_TYPE_UNDERFLOW : GST_QOS_TYPE_OVERFLOW,
378 params->proportion, params->diff * 100, stream_time)))
379 GST_ERROR("Failed to create QOS event.\n");
380 gst_pad_push_event(stream->my_sink, event);
382 return S_OK;
385 static GstAutoplugSelectResult autoplug_select_cb(GstElement *bin, GstPad *pad,
386 GstCaps *caps, GstElementFactory *fact, gpointer user)
388 const char *name = gst_element_factory_get_longname(fact);
390 GST_INFO("Using \"%s\".", name);
392 if (strstr(name, "Player protection"))
394 GST_WARNING("Blacklisted a/52 decoder because it only works in Totem.");
395 return GST_AUTOPLUG_SELECT_SKIP;
397 if (!strcmp(name, "Fluendo Hardware Accelerated Video Decoder"))
399 GST_WARNING("Disabled video acceleration since it breaks in wine.");
400 return GST_AUTOPLUG_SELECT_SKIP;
402 return GST_AUTOPLUG_SELECT_TRY;
405 static void no_more_pads_cb(GstElement *element, gpointer user)
407 struct wg_parser *parser = user;
409 GST_DEBUG("parser %p.", parser);
411 pthread_mutex_lock(&parser->mutex);
412 parser->no_more_pads = true;
413 pthread_mutex_unlock(&parser->mutex);
414 pthread_cond_signal(&parser->init_cond);
417 static GstFlowReturn queue_stream_event(struct wg_parser_stream *stream,
418 const struct wg_parser_event *event, GstBuffer *buffer)
420 struct wg_parser *parser = stream->parser;
422 /* Unlike request_buffer_src() [q.v.], we need to watch for GStreamer
423 * flushes here. The difference is that we can be blocked by the streaming
424 * thread not running (or itself flushing on the DirectShow side).
425 * request_buffer_src() can only be blocked by the upstream source, and that
426 * is solved by flushing the upstream source. */
428 pthread_mutex_lock(&parser->mutex);
429 while (!stream->flushing && stream->event.type != WG_PARSER_EVENT_NONE)
430 pthread_cond_wait(&stream->event_empty_cond, &parser->mutex);
431 if (stream->flushing)
433 pthread_mutex_unlock(&parser->mutex);
434 GST_DEBUG("Filter is flushing; discarding event.");
435 return GST_FLOW_FLUSHING;
437 if (buffer)
439 assert(GST_IS_BUFFER(buffer));
440 if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ))
442 pthread_mutex_unlock(&parser->mutex);
443 GST_ERROR("Failed to map buffer.\n");
444 return GST_FLOW_ERROR;
447 stream->event = *event;
448 stream->buffer = buffer;
449 pthread_mutex_unlock(&parser->mutex);
450 pthread_cond_signal(&stream->event_cond);
451 GST_LOG("Event queued.");
452 return GST_FLOW_OK;
455 static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
457 struct wg_parser_stream *stream = gst_pad_get_element_private(pad);
458 struct wg_parser *parser = stream->parser;
460 GST_LOG("stream %p, type \"%s\".", stream, GST_EVENT_TYPE_NAME(event));
462 switch (event->type)
464 case GST_EVENT_SEGMENT:
465 if (stream->enabled)
467 const GstSegment *segment;
469 gst_event_parse_segment(event, &segment);
471 if (segment->format != GST_FORMAT_TIME)
473 GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(segment->format));
474 break;
477 gst_segment_copy_into(segment, &stream->segment);
479 break;
481 case GST_EVENT_EOS:
482 if (stream->enabled)
484 struct wg_parser_event stream_event;
486 stream_event.type = WG_PARSER_EVENT_EOS;
487 queue_stream_event(stream, &stream_event, NULL);
489 else
491 pthread_mutex_lock(&parser->mutex);
492 stream->eos = true;
493 pthread_mutex_unlock(&parser->mutex);
494 pthread_cond_signal(&parser->init_cond);
496 break;
498 case GST_EVENT_FLUSH_START:
499 if (stream->enabled)
501 pthread_mutex_lock(&parser->mutex);
503 stream->flushing = true;
504 pthread_cond_signal(&stream->event_empty_cond);
506 if (stream->event.type == WG_PARSER_EVENT_BUFFER)
508 gst_buffer_unmap(stream->buffer, &stream->map_info);
509 gst_buffer_unref(stream->buffer);
510 stream->buffer = NULL;
512 stream->event.type = WG_PARSER_EVENT_NONE;
514 pthread_mutex_unlock(&parser->mutex);
516 break;
518 case GST_EVENT_FLUSH_STOP:
520 gboolean reset_time;
522 gst_event_parse_flush_stop(event, &reset_time);
524 if (reset_time)
525 gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED);
527 if (stream->enabled)
529 pthread_mutex_lock(&parser->mutex);
530 stream->flushing = false;
531 pthread_mutex_unlock(&parser->mutex);
533 break;
536 case GST_EVENT_CAPS:
538 GstCaps *caps;
540 gst_event_parse_caps(event, &caps);
541 pthread_mutex_lock(&parser->mutex);
542 wg_format_from_caps(&stream->preferred_format, caps);
543 stream->has_caps = true;
544 pthread_mutex_unlock(&parser->mutex);
545 pthread_cond_signal(&parser->init_cond);
546 break;
549 default:
550 GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event));
552 gst_event_unref(event);
553 return TRUE;
556 static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer)
558 struct wg_parser_stream *stream = gst_pad_get_element_private(pad);
559 struct wg_parser_event stream_event;
560 GstFlowReturn ret;
562 GST_LOG("stream %p, buffer %p.", stream, buffer);
564 if (!stream->enabled)
566 gst_buffer_unref(buffer);
567 return GST_FLOW_OK;
570 stream_event.type = WG_PARSER_EVENT_BUFFER;
572 /* FIXME: Should we use gst_segment_to_stream_time_full()? Under what
573 * circumstances is the stream time not equal to the buffer PTS? Note that
574 * this will need modification to wg_parser_stream_notify_qos() as well. */
576 if ((stream_event.u.buffer.has_pts = GST_BUFFER_PTS_IS_VALID(buffer)))
577 stream_event.u.buffer.pts = GST_BUFFER_PTS(buffer) / 100;
578 if ((stream_event.u.buffer.has_duration = GST_BUFFER_DURATION_IS_VALID(buffer)))
579 stream_event.u.buffer.duration = GST_BUFFER_DURATION(buffer) / 100;
580 stream_event.u.buffer.discontinuity = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT);
581 stream_event.u.buffer.preroll = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE);
582 stream_event.u.buffer.delta = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
583 stream_event.u.buffer.size = gst_buffer_get_size(buffer);
585 /* Transfer our reference to the buffer to the stream object. */
586 if ((ret = queue_stream_event(stream, &stream_event, buffer)) != GST_FLOW_OK)
587 gst_buffer_unref(buffer);
588 return ret;
591 static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
593 struct wg_parser_stream *stream = gst_pad_get_element_private(pad);
595 GST_LOG("stream %p, type \"%s\".", stream, gst_query_type_get_name(query->type));
597 switch (query->type)
599 case GST_QUERY_CAPS:
601 GstCaps *caps, *filter, *temp;
602 gchar *str;
604 gst_query_parse_caps(query, &filter);
606 if (stream->enabled)
607 caps = wg_format_to_caps(&stream->current_format);
608 else
609 caps = gst_caps_new_any();
610 if (!caps)
611 return FALSE;
613 str = gst_caps_to_string(caps);
614 GST_LOG("Stream caps are \"%s\".", str);
615 g_free(str);
617 if (filter)
619 temp = gst_caps_intersect(caps, filter);
620 gst_caps_unref(caps);
621 caps = temp;
624 gst_query_set_caps_result(query, caps);
625 gst_caps_unref(caps);
626 return TRUE;
629 case GST_QUERY_ACCEPT_CAPS:
631 struct wg_format format;
632 gboolean ret = TRUE;
633 GstCaps *caps;
635 if (!stream->enabled)
637 gst_query_set_accept_caps_result(query, TRUE);
638 return TRUE;
641 gst_query_parse_accept_caps(query, &caps);
642 wg_format_from_caps(&format, caps);
643 ret = wg_format_compare(&format, &stream->current_format);
644 if (!ret && gst_debug_category_get_threshold(GST_CAT_DEFAULT) >= GST_LEVEL_WARNING)
646 gchar *str = gst_caps_to_string(caps);
647 GST_WARNING("Rejecting caps \"%s\".", str);
648 g_free(str);
650 gst_query_set_accept_caps_result(query, ret);
651 return TRUE;
654 default:
655 return gst_pad_query_default (pad, parent, query);
659 GstElement *create_element(const char *name, const char *plugin_set)
661 GstElement *element;
663 if (!(element = gst_element_factory_make(name, NULL)))
664 fprintf(stderr, "winegstreamer: failed to create %s, are %u-bit GStreamer \"%s\" plugins installed?\n",
665 name, 8 * (unsigned int)sizeof(void *), plugin_set);
666 return element;
669 static struct wg_parser_stream *create_stream(struct wg_parser *parser)
671 struct wg_parser_stream *stream, **new_array;
672 char pad_name[19];
674 if (!(new_array = realloc(parser->streams, (parser->stream_count + 1) * sizeof(*parser->streams))))
675 return NULL;
676 parser->streams = new_array;
678 if (!(stream = calloc(1, sizeof(*stream))))
679 return NULL;
681 gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED);
683 stream->parser = parser;
684 pthread_cond_init(&stream->event_cond, NULL);
685 pthread_cond_init(&stream->event_empty_cond, NULL);
687 sprintf(pad_name, "qz_sink_%u", parser->stream_count);
688 stream->my_sink = gst_pad_new(pad_name, GST_PAD_SINK);
689 gst_pad_set_element_private(stream->my_sink, stream);
690 gst_pad_set_chain_function(stream->my_sink, sink_chain_cb);
691 gst_pad_set_event_function(stream->my_sink, sink_event_cb);
692 gst_pad_set_query_function(stream->my_sink, sink_query_cb);
694 parser->streams[parser->stream_count++] = stream;
695 return stream;
698 static void free_stream(struct wg_parser_stream *stream)
700 if (stream->their_src)
702 if (stream->post_sink)
704 gst_pad_unlink(stream->their_src, stream->post_sink);
705 gst_pad_unlink(stream->post_src, stream->my_sink);
706 gst_object_unref(stream->post_src);
707 gst_object_unref(stream->post_sink);
708 stream->post_src = stream->post_sink = NULL;
710 else
711 gst_pad_unlink(stream->their_src, stream->my_sink);
712 gst_object_unref(stream->their_src);
714 gst_object_unref(stream->my_sink);
716 pthread_cond_destroy(&stream->event_cond);
717 pthread_cond_destroy(&stream->event_empty_cond);
719 free(stream);
722 static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
724 struct wg_parser *parser = user;
725 struct wg_parser_stream *stream;
726 const char *name;
727 GstCaps *caps;
728 int ret;
730 GST_LOG("parser %p, element %p, pad %p.", parser, element, pad);
732 if (gst_pad_is_linked(pad))
733 return;
735 caps = gst_pad_query_caps(pad, NULL);
736 name = gst_structure_get_name(gst_caps_get_structure(caps, 0));
738 if (!(stream = create_stream(parser)))
739 goto out;
741 if (!strcmp(name, "video/x-raw"))
743 GstElement *deinterlace, *vconv, *flip, *vconv2;
745 /* DirectShow can express interlaced video, but downstream filters can't
746 * necessarily consume it. In particular, the video renderer can't. */
747 if (!(deinterlace = create_element("deinterlace", "good")))
748 goto out;
750 /* decodebin considers many YUV formats to be "raw", but some quartz
751 * filters can't handle those. Also, videoflip can't handle all "raw"
752 * formats either. Add a videoconvert to swap color spaces. */
753 if (!(vconv = create_element("videoconvert", "base")))
754 goto out;
756 /* GStreamer outputs RGB video top-down, but DirectShow expects bottom-up. */
757 if (!(flip = create_element("videoflip", "good")))
758 goto out;
760 /* videoflip does not support 15 and 16-bit RGB so add a second videoconvert
761 * to do the final conversion. */
762 if (!(vconv2 = create_element("videoconvert", "base")))
763 goto out;
765 /* The bin takes ownership of these elements. */
766 gst_bin_add(GST_BIN(parser->container), deinterlace);
767 gst_element_sync_state_with_parent(deinterlace);
768 gst_bin_add(GST_BIN(parser->container), vconv);
769 gst_element_sync_state_with_parent(vconv);
770 gst_bin_add(GST_BIN(parser->container), flip);
771 gst_element_sync_state_with_parent(flip);
772 gst_bin_add(GST_BIN(parser->container), vconv2);
773 gst_element_sync_state_with_parent(vconv2);
775 gst_element_link(deinterlace, vconv);
776 gst_element_link(vconv, flip);
777 gst_element_link(flip, vconv2);
779 stream->post_sink = gst_element_get_static_pad(deinterlace, "sink");
780 stream->post_src = gst_element_get_static_pad(vconv2, "src");
781 stream->flip = flip;
783 else if (!strcmp(name, "audio/x-raw"))
785 GstElement *convert;
787 /* Currently our dsound can't handle 64-bit formats or all
788 * surround-sound configurations. Native dsound can't always handle
789 * 64-bit formats either. Add an audioconvert to allow changing bit
790 * depth and channel count. */
791 if (!(convert = create_element("audioconvert", "base")))
792 goto out;
794 gst_bin_add(GST_BIN(parser->container), convert);
795 gst_element_sync_state_with_parent(convert);
797 stream->post_sink = gst_element_get_static_pad(convert, "sink");
798 stream->post_src = gst_element_get_static_pad(convert, "src");
801 if (stream->post_sink)
803 if ((ret = gst_pad_link(pad, stream->post_sink)) < 0)
805 GST_ERROR("Failed to link decodebin source pad to post-processing elements, error %s.",
806 gst_pad_link_get_name(ret));
807 gst_object_unref(stream->post_sink);
808 stream->post_sink = NULL;
809 goto out;
812 if ((ret = gst_pad_link(stream->post_src, stream->my_sink)) < 0)
814 GST_ERROR("Failed to link post-processing elements to our sink pad, error %s.",
815 gst_pad_link_get_name(ret));
816 gst_object_unref(stream->post_src);
817 stream->post_src = NULL;
818 gst_object_unref(stream->post_sink);
819 stream->post_sink = NULL;
820 goto out;
823 else if ((ret = gst_pad_link(pad, stream->my_sink)) < 0)
825 GST_ERROR("Failed to link decodebin source pad to our sink pad, error %s.",
826 gst_pad_link_get_name(ret));
827 goto out;
830 gst_pad_set_active(stream->my_sink, 1);
831 gst_object_ref(stream->their_src = pad);
832 out:
833 gst_caps_unref(caps);
836 static void pad_removed_cb(GstElement *element, GstPad *pad, gpointer user)
838 struct wg_parser *parser = user;
839 unsigned int i;
840 char *name;
842 GST_LOG("parser %p, element %p, pad %p.", parser, element, pad);
844 for (i = 0; i < parser->stream_count; ++i)
846 struct wg_parser_stream *stream = parser->streams[i];
848 if (stream->their_src == pad)
850 if (stream->post_sink)
851 gst_pad_unlink(stream->their_src, stream->post_sink);
852 else
853 gst_pad_unlink(stream->their_src, stream->my_sink);
854 gst_object_unref(stream->their_src);
855 stream->their_src = NULL;
856 return;
860 name = gst_pad_get_name(pad);
861 GST_WARNING("No pin matching pad \"%s\" found.", name);
862 g_free(name);
865 static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
866 guint64 offset, guint size, GstBuffer **buffer)
868 struct wg_parser *parser = gst_pad_get_element_private(pad);
869 GstFlowReturn ret;
871 GST_LOG("pad %p, offset %" G_GINT64_MODIFIER "u, size %u, buffer %p.", pad, offset, size, *buffer);
873 if (offset == GST_BUFFER_OFFSET_NONE)
874 offset = parser->next_pull_offset;
875 parser->next_pull_offset = offset + size;
877 if (!size)
879 /* asfreader occasionally asks for zero bytes. gst_buffer_map() will
880 * return NULL in this case. Avoid confusing the read thread by asking
881 * it for zero bytes. */
882 if (!*buffer)
883 *buffer = gst_buffer_new_and_alloc(0);
884 gst_buffer_set_size(*buffer, 0);
885 GST_LOG("Returning empty buffer.");
886 return GST_FLOW_OK;
889 pthread_mutex_lock(&parser->mutex);
891 assert(!parser->read_request.size);
892 parser->read_request.buffer = *buffer;
893 parser->read_request.offset = offset;
894 parser->read_request.size = size;
895 parser->read_request.done = false;
896 pthread_cond_signal(&parser->read_cond);
898 /* Note that we don't unblock this wait on GST_EVENT_FLUSH_START. We expect
899 * the upstream pin to flush if necessary. We should never be blocked on
900 * read_thread() not running. */
902 while (!parser->read_request.done)
903 pthread_cond_wait(&parser->read_done_cond, &parser->mutex);
905 *buffer = parser->read_request.buffer;
906 ret = parser->read_request.ret;
908 pthread_mutex_unlock(&parser->mutex);
910 GST_LOG("Request returned %s.", gst_flow_get_name(ret));
912 return ret;
915 static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
917 struct wg_parser *parser = gst_pad_get_element_private(pad);
918 GstFormat format;
920 GST_LOG("parser %p, type %s.", parser, GST_QUERY_TYPE_NAME(query));
922 switch (GST_QUERY_TYPE(query))
924 case GST_QUERY_DURATION:
925 gst_query_parse_duration(query, &format, NULL);
926 if (format == GST_FORMAT_PERCENT)
928 gst_query_set_duration(query, GST_FORMAT_PERCENT, GST_FORMAT_PERCENT_MAX);
929 return TRUE;
931 else if (format == GST_FORMAT_BYTES)
933 gst_query_set_duration(query, GST_FORMAT_BYTES, parser->file_size);
934 return TRUE;
936 return FALSE;
938 case GST_QUERY_SEEKING:
939 gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
940 if (format != GST_FORMAT_BYTES)
942 GST_WARNING("Cannot seek using format \"%s\".", gst_format_get_name(format));
943 return FALSE;
945 gst_query_set_seeking(query, GST_FORMAT_BYTES, 1, 0, parser->file_size);
946 return TRUE;
948 case GST_QUERY_SCHEDULING:
949 gst_query_set_scheduling(query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
950 gst_query_add_scheduling_mode(query, GST_PAD_MODE_PUSH);
951 gst_query_add_scheduling_mode(query, GST_PAD_MODE_PULL);
952 return TRUE;
954 default:
955 GST_WARNING("Unhandled query type %s.", GST_QUERY_TYPE_NAME(query));
956 return FALSE;
960 static void *push_data(void *arg)
962 struct wg_parser *parser = arg;
963 GstBuffer *buffer;
964 guint max_size;
966 GST_DEBUG("Starting push thread.");
968 if (!(buffer = gst_buffer_new_allocate(NULL, 16384, NULL)))
970 GST_ERROR("Failed to allocate memory.");
971 return NULL;
974 max_size = parser->stop_offset ? parser->stop_offset : parser->file_size;
976 for (;;)
978 ULONG size;
979 int ret;
981 if (parser->next_offset >= max_size)
982 break;
983 size = min(16384, max_size - parser->next_offset);
985 if ((ret = src_getrange_cb(parser->my_src, NULL, parser->next_offset, size, &buffer)) < 0)
987 GST_ERROR("Failed to read data, ret %s.", gst_flow_get_name(ret));
988 break;
991 parser->next_offset += size;
993 buffer->duration = buffer->pts = -1;
994 if ((ret = gst_pad_push(parser->my_src, buffer)) < 0)
996 GST_ERROR("Failed to push data, ret %s.", gst_flow_get_name(ret));
997 break;
1001 gst_buffer_unref(buffer);
1003 gst_pad_push_event(parser->my_src, gst_event_new_eos());
1005 GST_DEBUG("Stopping push thread.");
1007 return NULL;
1010 static gboolean activate_push(GstPad *pad, gboolean activate)
1012 struct wg_parser *parser = gst_pad_get_element_private(pad);
1014 if (!activate)
1016 if (parser->push_thread)
1018 pthread_join(parser->push_thread, NULL);
1019 parser->push_thread = 0;
1022 else if (!parser->push_thread)
1024 int ret;
1026 if ((ret = pthread_create(&parser->push_thread, NULL, push_data, parser)))
1028 GST_ERROR("Failed to create push thread: %s", strerror(errno));
1029 parser->push_thread = 0;
1030 return FALSE;
1033 return TRUE;
1036 static gboolean src_activate_mode_cb(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate)
1038 struct wg_parser *parser = gst_pad_get_element_private(pad);
1040 GST_DEBUG("%s source pad for parser %p in %s mode.",
1041 activate ? "Activating" : "Deactivating", parser, gst_pad_mode_get_name(mode));
1043 switch (mode)
1045 case GST_PAD_MODE_PULL:
1046 return TRUE;
1047 case GST_PAD_MODE_PUSH:
1048 return activate_push(pad, activate);
1049 case GST_PAD_MODE_NONE:
1050 break;
1052 return FALSE;
1055 static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer user)
1057 struct wg_parser *parser = user;
1058 gchar *dbg_info = NULL;
1059 GError *err = NULL;
1061 GST_DEBUG("parser %p, message type %s.", parser, GST_MESSAGE_TYPE_NAME(msg));
1063 switch (msg->type)
1065 case GST_MESSAGE_ERROR:
1066 gst_message_parse_error(msg, &err, &dbg_info);
1067 fprintf(stderr, "winegstreamer error: %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
1068 fprintf(stderr, "winegstreamer error: %s: %s\n", GST_OBJECT_NAME(msg->src), dbg_info);
1069 g_error_free(err);
1070 g_free(dbg_info);
1071 pthread_mutex_lock(&parser->mutex);
1072 parser->error = true;
1073 pthread_mutex_unlock(&parser->mutex);
1074 pthread_cond_signal(&parser->init_cond);
1075 break;
1077 case GST_MESSAGE_WARNING:
1078 gst_message_parse_warning(msg, &err, &dbg_info);
1079 fprintf(stderr, "winegstreamer warning: %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
1080 fprintf(stderr, "winegstreamer warning: %s: %s\n", GST_OBJECT_NAME(msg->src), dbg_info);
1081 g_error_free(err);
1082 g_free(dbg_info);
1083 break;
1085 case GST_MESSAGE_DURATION_CHANGED:
1086 pthread_mutex_lock(&parser->mutex);
1087 parser->has_duration = true;
1088 pthread_mutex_unlock(&parser->mutex);
1089 pthread_cond_signal(&parser->init_cond);
1090 break;
1092 default:
1093 break;
1095 gst_message_unref(msg);
1096 return GST_BUS_DROP;
1099 static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event)
1101 BOOL thread = !!parser->push_thread;
1102 GstSeekType cur_type, stop_type;
1103 GstFormat seek_format;
1104 GstEvent *flush_event;
1105 GstSeekFlags flags;
1106 gint64 cur, stop;
1107 guint32 seqnum;
1108 gdouble rate;
1110 gst_event_parse_seek(event, &rate, &seek_format, &flags,
1111 &cur_type, &cur, &stop_type, &stop);
1113 if (seek_format != GST_FORMAT_BYTES)
1115 GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(seek_format));
1116 return FALSE;
1119 seqnum = gst_event_get_seqnum(event);
1121 /* send flush start */
1122 if (flags & GST_SEEK_FLAG_FLUSH)
1124 flush_event = gst_event_new_flush_start();
1125 gst_event_set_seqnum(flush_event, seqnum);
1126 gst_pad_push_event(parser->my_src, flush_event);
1127 if (thread)
1128 gst_pad_set_active(parser->my_src, 1);
1131 parser->next_offset = parser->start_offset = cur;
1133 /* and prepare to continue streaming */
1134 if (flags & GST_SEEK_FLAG_FLUSH)
1136 flush_event = gst_event_new_flush_stop(TRUE);
1137 gst_event_set_seqnum(flush_event, seqnum);
1138 gst_pad_push_event(parser->my_src, flush_event);
1139 if (thread)
1140 gst_pad_set_active(parser->my_src, 1);
1143 return TRUE;
1146 static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
1148 struct wg_parser *parser = gst_pad_get_element_private(pad);
1149 gboolean ret = TRUE;
1151 GST_LOG("parser %p, type \"%s\".", parser, GST_EVENT_TYPE_NAME(event));
1153 switch (event->type)
1155 case GST_EVENT_SEEK:
1156 ret = src_perform_seek(parser, event);
1157 break;
1159 case GST_EVENT_FLUSH_START:
1160 case GST_EVENT_FLUSH_STOP:
1161 case GST_EVENT_QOS:
1162 case GST_EVENT_RECONFIGURE:
1163 break;
1165 default:
1166 GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event));
1167 ret = FALSE;
1168 break;
1170 gst_event_unref(event);
1171 return ret;
1174 static NTSTATUS wg_parser_connect(void *args)
1176 GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("quartz_src",
1177 GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
1178 const struct wg_parser_connect_params *params = args;
1179 struct wg_parser *parser = params->parser;
1180 unsigned int i;
1181 int ret;
1183 parser->file_size = params->file_size;
1184 parser->sink_connected = true;
1186 if (!parser->bus)
1188 parser->bus = gst_bus_new();
1189 gst_bus_set_sync_handler(parser->bus, bus_handler_cb, parser, NULL);
1192 parser->container = gst_bin_new(NULL);
1193 gst_element_set_bus(parser->container, parser->bus);
1195 parser->my_src = gst_pad_new_from_static_template(&src_template, "quartz-src");
1196 gst_pad_set_getrange_function(parser->my_src, src_getrange_cb);
1197 gst_pad_set_query_function(parser->my_src, src_query_cb);
1198 gst_pad_set_activatemode_function(parser->my_src, src_activate_mode_cb);
1199 gst_pad_set_event_function(parser->my_src, src_event_cb);
1200 gst_pad_set_element_private(parser->my_src, parser);
1202 parser->start_offset = parser->next_offset = parser->stop_offset = 0;
1203 parser->next_pull_offset = 0;
1204 parser->error = false;
1206 if (!parser->init_gst(parser))
1207 goto out;
1209 gst_element_set_state(parser->container, GST_STATE_PAUSED);
1210 ret = gst_element_get_state(parser->container, NULL, NULL, -1);
1211 if (ret == GST_STATE_CHANGE_FAILURE)
1213 GST_ERROR("Failed to play stream.\n");
1214 goto out;
1217 pthread_mutex_lock(&parser->mutex);
1219 while (!parser->no_more_pads && !parser->error)
1220 pthread_cond_wait(&parser->init_cond, &parser->mutex);
1221 if (parser->error)
1223 pthread_mutex_unlock(&parser->mutex);
1224 goto out;
1227 for (i = 0; i < parser->stream_count; ++i)
1229 struct wg_parser_stream *stream = parser->streams[i];
1230 gint64 duration;
1232 while (!stream->has_caps && !parser->error)
1233 pthread_cond_wait(&parser->init_cond, &parser->mutex);
1235 /* GStreamer doesn't actually provide any guarantees about when duration
1236 * is available, even for seekable streams. It's basically built for
1237 * applications that don't care, e.g. movie players that can display
1238 * a duration once it's available, and update it visually if a better
1239 * estimate is found. This doesn't really match well with DirectShow or
1240 * Media Foundation, which both expect duration to be available
1241 * immediately on connecting, so we have to use some complex heuristics
1242 * to try to actually get a usable duration.
1244 * Some elements (avidemux, wavparse, qtdemux) record duration almost
1245 * immediately, before fixing caps. Such elements don't send
1246 * duration-changed messages. Therefore always try querying duration
1247 * after caps have been found.
1249 * Some elements (mpegaudioparse) send duration-changed. In the case of
1250 * a mp3 stream without seek tables it will not be sent immediately, but
1251 * only after enough frames have been parsed to form an estimate. They
1252 * may send it multiple times with increasingly accurate estimates, but
1253 * unfortunately we have no way of knowing whether another estimate will
1254 * be sent, so we always take the first one. We assume that if the
1255 * duration is not immediately available then the element will always
1256 * send duration-changed.
1259 for (;;)
1261 if (parser->error)
1263 pthread_mutex_unlock(&parser->mutex);
1264 goto out;
1266 if (gst_pad_query_duration(stream->their_src, GST_FORMAT_TIME, &duration))
1268 stream->duration = duration / 100;
1269 break;
1272 if (stream->eos)
1274 stream->duration = 0;
1275 GST_WARNING("Failed to query duration.\n");
1276 break;
1279 /* Elements based on GstBaseParse send duration-changed before
1280 * actually updating the duration in GStreamer versions prior
1281 * to 1.17.1. See <gstreamer.git:d28e0b4147fe7073b2>. So after
1282 * receiving duration-changed we have to continue polling until
1283 * the query succeeds. */
1284 if (parser->has_duration)
1286 pthread_mutex_unlock(&parser->mutex);
1287 g_usleep(10000);
1288 pthread_mutex_lock(&parser->mutex);
1290 else
1292 pthread_cond_wait(&parser->init_cond, &parser->mutex);
1297 pthread_mutex_unlock(&parser->mutex);
1299 parser->next_offset = 0;
1300 return S_OK;
1302 out:
1303 if (parser->container)
1304 gst_element_set_state(parser->container, GST_STATE_NULL);
1305 if (parser->their_sink)
1307 gst_pad_unlink(parser->my_src, parser->their_sink);
1308 gst_object_unref(parser->their_sink);
1309 parser->my_src = parser->their_sink = NULL;
1312 for (i = 0; i < parser->stream_count; ++i)
1313 free_stream(parser->streams[i]);
1314 parser->stream_count = 0;
1315 free(parser->streams);
1316 parser->streams = NULL;
1318 if (parser->container)
1320 gst_element_set_bus(parser->container, NULL);
1321 gst_object_unref(parser->container);
1322 parser->container = NULL;
1325 pthread_mutex_lock(&parser->mutex);
1326 parser->sink_connected = false;
1327 pthread_mutex_unlock(&parser->mutex);
1328 pthread_cond_signal(&parser->read_cond);
1330 return E_FAIL;
1333 static NTSTATUS wg_parser_disconnect(void *args)
1335 struct wg_parser *parser = args;
1336 unsigned int i;
1338 /* Unblock all of our streams. */
1339 pthread_mutex_lock(&parser->mutex);
1340 for (i = 0; i < parser->stream_count; ++i)
1342 parser->streams[i]->flushing = true;
1343 pthread_cond_signal(&parser->streams[i]->event_empty_cond);
1345 pthread_mutex_unlock(&parser->mutex);
1347 gst_element_set_state(parser->container, GST_STATE_NULL);
1348 gst_pad_unlink(parser->my_src, parser->their_sink);
1349 gst_object_unref(parser->my_src);
1350 gst_object_unref(parser->their_sink);
1351 parser->my_src = parser->their_sink = NULL;
1353 pthread_mutex_lock(&parser->mutex);
1354 parser->sink_connected = false;
1355 pthread_mutex_unlock(&parser->mutex);
1356 pthread_cond_signal(&parser->read_cond);
1358 for (i = 0; i < parser->stream_count; ++i)
1359 free_stream(parser->streams[i]);
1361 parser->stream_count = 0;
1362 free(parser->streams);
1363 parser->streams = NULL;
1365 gst_element_set_bus(parser->container, NULL);
1366 gst_object_unref(parser->container);
1367 parser->container = NULL;
1369 return S_OK;
1372 static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
1374 GstElement *element;
1375 int ret;
1377 if (!(element = create_element("decodebin", "base")))
1378 return FALSE;
1380 gst_bin_add(GST_BIN(parser->container), element);
1381 parser->decodebin = element;
1383 if (parser->unlimited_buffering)
1385 g_object_set(parser->decodebin, "max-size-buffers", G_MAXUINT, NULL);
1386 g_object_set(parser->decodebin, "max-size-time", G_MAXUINT64, NULL);
1387 g_object_set(parser->decodebin, "max-size-bytes", G_MAXUINT, NULL);
1390 g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser);
1391 g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser);
1392 g_signal_connect(element, "autoplug-select", G_CALLBACK(autoplug_select_cb), parser);
1393 g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser);
1395 parser->their_sink = gst_element_get_static_pad(element, "sink");
1397 pthread_mutex_lock(&parser->mutex);
1398 parser->no_more_pads = false;
1399 pthread_mutex_unlock(&parser->mutex);
1401 if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
1403 GST_ERROR("Failed to link pads, error %d.", ret);
1404 return FALSE;
1407 return TRUE;
1410 static BOOL avi_parser_init_gst(struct wg_parser *parser)
1412 GstElement *element;
1413 int ret;
1415 if (!(element = create_element("avidemux", "good")))
1416 return FALSE;
1418 gst_bin_add(GST_BIN(parser->container), element);
1420 g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser);
1421 g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser);
1422 g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser);
1424 parser->their_sink = gst_element_get_static_pad(element, "sink");
1426 pthread_mutex_lock(&parser->mutex);
1427 parser->no_more_pads = false;
1428 pthread_mutex_unlock(&parser->mutex);
1430 if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
1432 GST_ERROR("Failed to link pads, error %d.", ret);
1433 return FALSE;
1436 return TRUE;
1439 static BOOL mpeg_audio_parser_init_gst(struct wg_parser *parser)
1441 struct wg_parser_stream *stream;
1442 GstElement *element;
1443 int ret;
1445 if (!(element = create_element("mpegaudioparse", "good")))
1446 return FALSE;
1448 gst_bin_add(GST_BIN(parser->container), element);
1450 parser->their_sink = gst_element_get_static_pad(element, "sink");
1451 if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
1453 GST_ERROR("Failed to link sink pads, error %d.", ret);
1454 return FALSE;
1457 if (!(stream = create_stream(parser)))
1458 return FALSE;
1460 gst_object_ref(stream->their_src = gst_element_get_static_pad(element, "src"));
1461 if ((ret = gst_pad_link(stream->their_src, stream->my_sink)) < 0)
1463 GST_ERROR("Failed to link source pads, error %d.", ret);
1464 return FALSE;
1466 gst_pad_set_active(stream->my_sink, 1);
1468 parser->no_more_pads = true;
1470 return TRUE;
1473 static BOOL wave_parser_init_gst(struct wg_parser *parser)
1475 struct wg_parser_stream *stream;
1476 GstElement *element;
1477 int ret;
1479 if (!(element = create_element("wavparse", "good")))
1480 return FALSE;
1482 gst_bin_add(GST_BIN(parser->container), element);
1484 parser->their_sink = gst_element_get_static_pad(element, "sink");
1485 if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
1487 GST_ERROR("Failed to link sink pads, error %d.", ret);
1488 return FALSE;
1491 if (!(stream = create_stream(parser)))
1492 return FALSE;
1494 stream->their_src = gst_element_get_static_pad(element, "src");
1495 gst_object_ref(stream->their_src);
1496 if ((ret = gst_pad_link(stream->their_src, stream->my_sink)) < 0)
1498 GST_ERROR("Failed to link source pads, error %d.", ret);
1499 return FALSE;
1501 gst_pad_set_active(stream->my_sink, 1);
1503 parser->no_more_pads = true;
1505 return TRUE;
1508 static void init_gstreamer_once(void)
1510 char arg0[] = "wine";
1511 char arg1[] = "--gst-disable-registry-fork";
1512 char *args[] = {arg0, arg1, NULL};
1513 int argc = ARRAY_SIZE(args) - 1;
1514 char **argv = args;
1515 GError *err;
1517 if (!gst_init_check(&argc, &argv, &err))
1519 fprintf(stderr, "winegstreamer: failed to initialize GStreamer: %s\n", err->message);
1520 g_error_free(err);
1521 return;
1524 GST_DEBUG_CATEGORY_INIT(wine, "WINE", GST_DEBUG_FG_RED, "Wine GStreamer support");
1526 GST_INFO("GStreamer library version %s; wine built with %d.%d.%d.",
1527 gst_version_string(), GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO);
1530 bool init_gstreamer(void)
1532 static pthread_once_t init_once = PTHREAD_ONCE_INIT;
1534 return !pthread_once(&init_once, init_gstreamer_once);
1537 static NTSTATUS wg_parser_create(void *args)
1539 static const init_gst_cb init_funcs[] =
1541 [WG_PARSER_DECODEBIN] = decodebin_parser_init_gst,
1542 [WG_PARSER_AVIDEMUX] = avi_parser_init_gst,
1543 [WG_PARSER_MPEGAUDIOPARSE] = mpeg_audio_parser_init_gst,
1544 [WG_PARSER_WAVPARSE] = wave_parser_init_gst,
1547 struct wg_parser_create_params *params = args;
1548 struct wg_parser *parser;
1550 if (!init_gstreamer())
1551 return E_FAIL;
1553 if (!(parser = calloc(1, sizeof(*parser))))
1554 return E_OUTOFMEMORY;
1556 pthread_mutex_init(&parser->mutex, NULL);
1557 pthread_cond_init(&parser->init_cond, NULL);
1558 pthread_cond_init(&parser->read_cond, NULL);
1559 pthread_cond_init(&parser->read_done_cond, NULL);
1560 parser->init_gst = init_funcs[params->type];
1561 parser->unlimited_buffering = params->unlimited_buffering;
1563 GST_DEBUG("Created winegstreamer parser %p.", parser);
1564 params->parser = parser;
1565 return S_OK;
1568 static NTSTATUS wg_parser_destroy(void *args)
1570 struct wg_parser *parser = args;
1572 if (parser->bus)
1574 gst_bus_set_sync_handler(parser->bus, NULL, NULL, NULL);
1575 gst_object_unref(parser->bus);
1578 pthread_mutex_destroy(&parser->mutex);
1579 pthread_cond_destroy(&parser->init_cond);
1580 pthread_cond_destroy(&parser->read_cond);
1581 pthread_cond_destroy(&parser->read_done_cond);
1583 free(parser);
1584 return S_OK;
1587 const unixlib_entry_t __wine_unix_call_funcs[] =
1589 #define X(name) [unix_ ## name] = name
1590 X(wg_parser_create),
1591 X(wg_parser_destroy),
1593 X(wg_parser_connect),
1594 X(wg_parser_disconnect),
1596 X(wg_parser_get_next_read_offset),
1597 X(wg_parser_push_data),
1599 X(wg_parser_get_stream_count),
1600 X(wg_parser_get_stream),
1602 X(wg_parser_stream_get_preferred_format),
1603 X(wg_parser_stream_enable),
1604 X(wg_parser_stream_disable),
1606 X(wg_parser_stream_get_event),
1607 X(wg_parser_stream_copy_buffer),
1608 X(wg_parser_stream_release_buffer),
1609 X(wg_parser_stream_notify_qos),
1611 X(wg_parser_stream_get_duration),
1612 X(wg_parser_stream_seek),
1614 X(wg_transform_create),
1615 X(wg_transform_destroy),