wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / winegstreamer / wg_parser.c
blobe0eff9ee3094157083736c4389337b9dcf15f388
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"
28 #include "ntstatus.h"
29 #define WIN32_NO_STATUS
30 #include "gst_private.h"
31 #include "winternl.h"
33 #include <gst/gst.h>
34 #include <gst/video/video.h>
35 #include <gst/audio/audio.h>
37 WINE_DEFAULT_DEBUG_CHANNEL(gstreamer);
39 GST_DEBUG_CATEGORY_STATIC(wine);
40 #define GST_CAT_DEFAULT wine
42 struct wg_parser
44 BOOL (*init_gst)(struct wg_parser *parser);
46 struct wg_parser_stream **streams;
47 unsigned int stream_count;
49 GstElement *container, *decodebin;
50 GstBus *bus;
51 GstPad *my_src, *their_sink;
53 guint64 file_size, start_offset, next_offset, stop_offset;
54 guint64 next_pull_offset;
56 pthread_t push_thread;
58 pthread_mutex_t mutex;
60 pthread_cond_t init_cond;
61 bool no_more_pads, has_duration, error;
63 pthread_cond_t read_cond, read_done_cond;
64 struct
66 void *data;
67 uint64_t offset;
68 uint32_t size;
69 bool done;
70 bool ret;
71 } read_request;
73 bool flushing, sink_connected;
76 struct wg_parser_stream
78 struct wg_parser *parser;
80 GstPad *their_src, *post_sink, *post_src, *my_sink;
81 GstElement *flip;
82 GstSegment segment;
83 struct wg_format preferred_format, current_format;
85 pthread_cond_t event_cond, event_empty_cond;
86 struct wg_parser_event event;
87 GstBuffer *buffer;
88 GstMapInfo map_info;
90 bool flushing, eos, enabled, has_caps;
92 uint64_t duration;
95 static enum wg_audio_format wg_audio_format_from_gst(GstAudioFormat format)
97 switch (format)
99 case GST_AUDIO_FORMAT_U8:
100 return WG_AUDIO_FORMAT_U8;
101 case GST_AUDIO_FORMAT_S16LE:
102 return WG_AUDIO_FORMAT_S16LE;
103 case GST_AUDIO_FORMAT_S24LE:
104 return WG_AUDIO_FORMAT_S24LE;
105 case GST_AUDIO_FORMAT_S32LE:
106 return WG_AUDIO_FORMAT_S32LE;
107 case GST_AUDIO_FORMAT_F32LE:
108 return WG_AUDIO_FORMAT_F32LE;
109 case GST_AUDIO_FORMAT_F64LE:
110 return WG_AUDIO_FORMAT_F64LE;
111 default:
112 return WG_AUDIO_FORMAT_UNKNOWN;
116 static uint32_t wg_channel_position_from_gst(GstAudioChannelPosition position)
118 static const uint32_t position_map[] =
120 SPEAKER_FRONT_LEFT,
121 SPEAKER_FRONT_RIGHT,
122 SPEAKER_FRONT_CENTER,
123 SPEAKER_LOW_FREQUENCY,
124 SPEAKER_BACK_LEFT,
125 SPEAKER_BACK_RIGHT,
126 SPEAKER_FRONT_LEFT_OF_CENTER,
127 SPEAKER_FRONT_RIGHT_OF_CENTER,
128 SPEAKER_BACK_CENTER,
130 SPEAKER_SIDE_LEFT,
131 SPEAKER_SIDE_RIGHT,
132 SPEAKER_TOP_FRONT_LEFT,
133 SPEAKER_TOP_FRONT_RIGHT,
134 SPEAKER_TOP_FRONT_CENTER,
135 SPEAKER_TOP_CENTER,
136 SPEAKER_TOP_BACK_LEFT,
137 SPEAKER_TOP_BACK_RIGHT,
140 SPEAKER_TOP_BACK_CENTER,
143 if (position < ARRAY_SIZE(position_map))
144 return position_map[position];
145 return 0;
148 static uint32_t wg_channel_mask_from_gst(const GstAudioInfo *info)
150 uint32_t mask = 0, position;
151 unsigned int i;
153 for (i = 0; i < GST_AUDIO_INFO_CHANNELS(info); ++i)
155 if (!(position = wg_channel_position_from_gst(GST_AUDIO_INFO_POSITION(info, i))))
157 GST_WARNING("Unsupported channel %#x.", GST_AUDIO_INFO_POSITION(info, i));
158 return 0;
160 /* Make sure it's also in WinMM order. WinMM mandates that channels be
161 * ordered, as it were, from least to most significant SPEAKER_* bit.
162 * Hence we fail if the current channel was already specified, or if any
163 * higher bit was already specified. */
164 if (mask & ~(position - 1))
166 GST_WARNING("Unsupported channel order.");
167 return 0;
169 mask |= position;
171 return mask;
174 static void wg_format_from_audio_info(struct wg_format *format, const GstAudioInfo *info)
176 format->major_type = WG_MAJOR_TYPE_AUDIO;
177 format->u.audio.format = wg_audio_format_from_gst(GST_AUDIO_INFO_FORMAT(info));
178 format->u.audio.channels = GST_AUDIO_INFO_CHANNELS(info);
179 format->u.audio.channel_mask = wg_channel_mask_from_gst(info);
180 format->u.audio.rate = GST_AUDIO_INFO_RATE(info);
183 static enum wg_video_format wg_video_format_from_gst(GstVideoFormat format)
185 switch (format)
187 case GST_VIDEO_FORMAT_BGRA:
188 return WG_VIDEO_FORMAT_BGRA;
189 case GST_VIDEO_FORMAT_BGRx:
190 return WG_VIDEO_FORMAT_BGRx;
191 case GST_VIDEO_FORMAT_BGR:
192 return WG_VIDEO_FORMAT_BGR;
193 case GST_VIDEO_FORMAT_RGB15:
194 return WG_VIDEO_FORMAT_RGB15;
195 case GST_VIDEO_FORMAT_AYUV:
196 return WG_VIDEO_FORMAT_AYUV;
197 case GST_VIDEO_FORMAT_I420:
198 return WG_VIDEO_FORMAT_I420;
199 case GST_VIDEO_FORMAT_NV12:
200 return WG_VIDEO_FORMAT_NV12;
201 case GST_VIDEO_FORMAT_UYVY:
202 return WG_VIDEO_FORMAT_UYVY;
203 case GST_VIDEO_FORMAT_YUY2:
204 return WG_VIDEO_FORMAT_YUY2;
205 case GST_VIDEO_FORMAT_YV12:
206 return WG_VIDEO_FORMAT_YV12;
207 case GST_VIDEO_FORMAT_YVYU:
208 return WG_VIDEO_FORMAT_YVYU;
209 default:
210 return WG_VIDEO_FORMAT_UNKNOWN;
214 static void wg_format_from_video_info(struct wg_format *format, const GstVideoInfo *info)
216 format->major_type = WG_MAJOR_TYPE_VIDEO;
217 format->u.video.format = wg_video_format_from_gst(GST_VIDEO_INFO_FORMAT(info));
218 format->u.video.width = GST_VIDEO_INFO_WIDTH(info);
219 format->u.video.height = GST_VIDEO_INFO_HEIGHT(info);
220 format->u.video.fps_n = GST_VIDEO_INFO_FPS_N(info);
221 format->u.video.fps_d = GST_VIDEO_INFO_FPS_D(info);
224 static void wg_format_from_caps_audio_mpeg(struct wg_format *format, const GstCaps *caps)
226 const GstStructure *structure = gst_caps_get_structure(caps, 0);
227 gint layer, channels, rate;
229 if (!gst_structure_get_int(structure, "layer", &layer))
231 GST_WARNING("Missing \"layer\" value.");
232 return;
234 if (!gst_structure_get_int(structure, "channels", &channels))
236 GST_WARNING("Missing \"channels\" value.");
237 return;
239 if (!gst_structure_get_int(structure, "rate", &rate))
241 GST_WARNING("Missing \"rate\" value.");
242 return;
245 format->major_type = WG_MAJOR_TYPE_AUDIO;
247 if (layer == 1)
248 format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER1;
249 else if (layer == 2)
250 format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER2;
251 else if (layer == 3)
252 format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER3;
254 format->u.audio.channels = channels;
255 format->u.audio.rate = rate;
258 static void wg_format_from_caps_video_cinepak(struct wg_format *format, const GstCaps *caps)
260 const GstStructure *structure = gst_caps_get_structure(caps, 0);
261 gint width, height, fps_n, fps_d;
263 if (!gst_structure_get_int(structure, "width", &width))
265 GST_WARNING("Missing \"width\" value.");
266 return;
268 if (!gst_structure_get_int(structure, "height", &height))
270 GST_WARNING("Missing \"height\" value.");
271 return;
273 if (!gst_structure_get_fraction(structure, "framerate", &fps_n, &fps_d))
275 fps_n = 0;
276 fps_d = 1;
279 format->major_type = WG_MAJOR_TYPE_VIDEO;
280 format->u.video.format = WG_VIDEO_FORMAT_CINEPAK;
281 format->u.video.width = width;
282 format->u.video.height = height;
283 format->u.video.fps_n = fps_n;
284 format->u.video.fps_d = fps_d;
287 static void wg_format_from_caps(struct wg_format *format, const GstCaps *caps)
289 const GstStructure *structure = gst_caps_get_structure(caps, 0);
290 const char *name = gst_structure_get_name(structure);
292 memset(format, 0, sizeof(*format));
294 if (!strcmp(name, "audio/x-raw"))
296 GstAudioInfo info;
298 if (gst_audio_info_from_caps(&info, caps))
299 wg_format_from_audio_info(format, &info);
301 else if (!strcmp(name, "video/x-raw"))
303 GstVideoInfo info;
305 if (gst_video_info_from_caps(&info, caps))
306 wg_format_from_video_info(format, &info);
308 else if (!strcmp(name, "audio/mpeg"))
310 wg_format_from_caps_audio_mpeg(format, caps);
312 else if (!strcmp(name, "video/x-cinepak"))
314 wg_format_from_caps_video_cinepak(format, caps);
316 else
318 gchar *str = gst_caps_to_string(caps);
320 GST_FIXME("Unhandled caps %s.", str);
321 g_free(str);
325 static GstAudioFormat wg_audio_format_to_gst(enum wg_audio_format format)
327 switch (format)
329 case WG_AUDIO_FORMAT_U8: return GST_AUDIO_FORMAT_U8;
330 case WG_AUDIO_FORMAT_S16LE: return GST_AUDIO_FORMAT_S16LE;
331 case WG_AUDIO_FORMAT_S24LE: return GST_AUDIO_FORMAT_S24LE;
332 case WG_AUDIO_FORMAT_S32LE: return GST_AUDIO_FORMAT_S32LE;
333 case WG_AUDIO_FORMAT_F32LE: return GST_AUDIO_FORMAT_F32LE;
334 case WG_AUDIO_FORMAT_F64LE: return GST_AUDIO_FORMAT_F64LE;
335 default: return GST_AUDIO_FORMAT_UNKNOWN;
339 static void wg_channel_mask_to_gst(GstAudioChannelPosition *positions, uint32_t mask, uint32_t channel_count)
341 const uint32_t orig_mask = mask;
342 unsigned int i;
343 DWORD bit;
345 static const GstAudioChannelPosition position_map[] =
347 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
348 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
349 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
350 GST_AUDIO_CHANNEL_POSITION_LFE1,
351 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
352 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
353 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
354 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
355 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
356 GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
357 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
358 GST_AUDIO_CHANNEL_POSITION_TOP_CENTER,
359 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT,
360 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER,
361 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT,
362 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT,
363 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER,
364 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT,
367 for (i = 0; i < channel_count; ++i)
369 positions[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
370 if (BitScanForward(&bit, mask))
372 if (bit < ARRAY_SIZE(position_map))
373 positions[i] = position_map[bit];
374 else
375 GST_WARNING("Invalid channel mask %#x.\n", orig_mask);
376 mask &= ~(1 << bit);
378 else
380 GST_WARNING("Incomplete channel mask %#x.\n", orig_mask);
385 static GstCaps *wg_format_to_caps_audio(const struct wg_format *format)
387 GstAudioChannelPosition positions[32];
388 GstAudioFormat audio_format;
389 GstAudioInfo info;
391 if ((audio_format = wg_audio_format_to_gst(format->u.audio.format)) == GST_AUDIO_FORMAT_UNKNOWN)
392 return NULL;
394 wg_channel_mask_to_gst(positions, format->u.audio.channel_mask, format->u.audio.channels);
395 gst_audio_info_set_format(&info, audio_format, format->u.audio.rate, format->u.audio.channels, positions);
396 return gst_audio_info_to_caps(&info);
399 static GstVideoFormat wg_video_format_to_gst(enum wg_video_format format)
401 switch (format)
403 case WG_VIDEO_FORMAT_BGRA: return GST_VIDEO_FORMAT_BGRA;
404 case WG_VIDEO_FORMAT_BGRx: return GST_VIDEO_FORMAT_BGRx;
405 case WG_VIDEO_FORMAT_BGR: return GST_VIDEO_FORMAT_BGR;
406 case WG_VIDEO_FORMAT_RGB15: return GST_VIDEO_FORMAT_RGB15;
407 case WG_VIDEO_FORMAT_RGB16: return GST_VIDEO_FORMAT_RGB16;
408 case WG_VIDEO_FORMAT_AYUV: return GST_VIDEO_FORMAT_AYUV;
409 case WG_VIDEO_FORMAT_I420: return GST_VIDEO_FORMAT_I420;
410 case WG_VIDEO_FORMAT_NV12: return GST_VIDEO_FORMAT_NV12;
411 case WG_VIDEO_FORMAT_UYVY: return GST_VIDEO_FORMAT_UYVY;
412 case WG_VIDEO_FORMAT_YUY2: return GST_VIDEO_FORMAT_YUY2;
413 case WG_VIDEO_FORMAT_YV12: return GST_VIDEO_FORMAT_YV12;
414 case WG_VIDEO_FORMAT_YVYU: return GST_VIDEO_FORMAT_YVYU;
415 default: return GST_VIDEO_FORMAT_UNKNOWN;
419 static GstCaps *wg_format_to_caps_video(const struct wg_format *format)
421 GstVideoFormat video_format;
422 GstVideoInfo info;
423 unsigned int i;
424 GstCaps *caps;
426 if ((video_format = wg_video_format_to_gst(format->u.video.format)) == GST_VIDEO_FORMAT_UNKNOWN)
427 return NULL;
429 gst_video_info_set_format(&info, video_format, format->u.video.width, format->u.video.height);
430 if ((caps = gst_video_info_to_caps(&info)))
432 /* Clear some fields that shouldn't prevent us from connecting. */
433 for (i = 0; i < gst_caps_get_size(caps); ++i)
435 gst_structure_remove_fields(gst_caps_get_structure(caps, i),
436 "framerate", "pixel-aspect-ratio", "colorimetry", "chroma-site", NULL);
439 return caps;
442 static GstCaps *wg_format_to_caps(const struct wg_format *format)
444 switch (format->major_type)
446 case WG_MAJOR_TYPE_UNKNOWN:
447 return NULL;
448 case WG_MAJOR_TYPE_AUDIO:
449 return wg_format_to_caps_audio(format);
450 case WG_MAJOR_TYPE_VIDEO:
451 return wg_format_to_caps_video(format);
453 assert(0);
454 return NULL;
457 static bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
459 if (a->major_type != b->major_type)
460 return false;
462 switch (a->major_type)
464 case WG_MAJOR_TYPE_UNKNOWN:
465 return false;
467 case WG_MAJOR_TYPE_AUDIO:
468 return a->u.audio.format == b->u.audio.format
469 && a->u.audio.channels == b->u.audio.channels
470 && a->u.audio.rate == b->u.audio.rate;
472 case WG_MAJOR_TYPE_VIDEO:
473 /* Do not compare FPS. */
474 return a->u.video.format == b->u.video.format
475 && a->u.video.width == b->u.video.width
476 && a->u.video.height == b->u.video.height;
479 assert(0);
480 return false;
483 static uint32_t CDECL wg_parser_get_stream_count(struct wg_parser *parser)
485 return parser->stream_count;
488 static struct wg_parser_stream * CDECL wg_parser_get_stream(struct wg_parser *parser, uint32_t index)
490 return parser->streams[index];
493 static void CDECL wg_parser_begin_flush(struct wg_parser *parser)
495 unsigned int i;
497 pthread_mutex_lock(&parser->mutex);
498 parser->flushing = true;
499 pthread_mutex_unlock(&parser->mutex);
501 for (i = 0; i < parser->stream_count; ++i)
503 if (parser->streams[i]->enabled)
504 pthread_cond_signal(&parser->streams[i]->event_cond);
508 static void CDECL wg_parser_end_flush(struct wg_parser *parser)
510 pthread_mutex_lock(&parser->mutex);
511 parser->flushing = false;
512 pthread_mutex_unlock(&parser->mutex);
515 static bool CDECL wg_parser_get_read_request(struct wg_parser *parser,
516 void **data, uint64_t *offset, uint32_t *size)
518 pthread_mutex_lock(&parser->mutex);
520 while (parser->sink_connected && !parser->read_request.data)
521 pthread_cond_wait(&parser->read_cond, &parser->mutex);
523 if (!parser->sink_connected)
525 pthread_mutex_unlock(&parser->mutex);
526 return false;
529 *data = parser->read_request.data;
530 *offset = parser->read_request.offset;
531 *size = parser->read_request.size;
533 pthread_mutex_unlock(&parser->mutex);
534 return true;
537 static void CDECL wg_parser_complete_read_request(struct wg_parser *parser, bool ret)
539 pthread_mutex_lock(&parser->mutex);
540 parser->read_request.done = true;
541 parser->read_request.ret = ret;
542 parser->read_request.data = NULL;
543 pthread_mutex_unlock(&parser->mutex);
544 pthread_cond_signal(&parser->read_done_cond);
547 static void CDECL wg_parser_set_unlimited_buffering(struct wg_parser *parser)
549 g_object_set(parser->decodebin, "max-size-buffers", G_MAXUINT, NULL);
550 g_object_set(parser->decodebin, "max-size-time", G_MAXUINT64, NULL);
551 g_object_set(parser->decodebin, "max-size-bytes", G_MAXUINT, NULL);
554 static void CDECL wg_parser_stream_get_preferred_format(struct wg_parser_stream *stream, struct wg_format *format)
556 *format = stream->preferred_format;
559 static void CDECL wg_parser_stream_enable(struct wg_parser_stream *stream, const struct wg_format *format)
561 stream->current_format = *format;
562 stream->enabled = true;
564 if (format->major_type == WG_MAJOR_TYPE_VIDEO)
566 switch (format->u.video.format)
568 case WG_VIDEO_FORMAT_BGRA:
569 case WG_VIDEO_FORMAT_BGRx:
570 case WG_VIDEO_FORMAT_BGR:
571 case WG_VIDEO_FORMAT_RGB15:
572 case WG_VIDEO_FORMAT_RGB16:
573 gst_util_set_object_arg(G_OBJECT(stream->flip), "method", "vertical-flip");
574 break;
576 case WG_VIDEO_FORMAT_AYUV:
577 case WG_VIDEO_FORMAT_I420:
578 case WG_VIDEO_FORMAT_NV12:
579 case WG_VIDEO_FORMAT_UYVY:
580 case WG_VIDEO_FORMAT_YUY2:
581 case WG_VIDEO_FORMAT_YV12:
582 case WG_VIDEO_FORMAT_YVYU:
583 case WG_VIDEO_FORMAT_UNKNOWN:
584 case WG_VIDEO_FORMAT_CINEPAK:
585 gst_util_set_object_arg(G_OBJECT(stream->flip), "method", "none");
586 break;
590 gst_pad_push_event(stream->my_sink, gst_event_new_reconfigure());
593 static void CDECL wg_parser_stream_disable(struct wg_parser_stream *stream)
595 stream->enabled = false;
598 static bool CDECL wg_parser_stream_get_event(struct wg_parser_stream *stream, struct wg_parser_event *event)
600 struct wg_parser *parser = stream->parser;
602 pthread_mutex_lock(&parser->mutex);
604 while (!parser->flushing && stream->event.type == WG_PARSER_EVENT_NONE)
605 pthread_cond_wait(&stream->event_cond, &parser->mutex);
607 if (parser->flushing)
609 pthread_mutex_unlock(&parser->mutex);
610 TRACE("Filter is flushing.\n");
611 return false;
614 *event = stream->event;
616 if (stream->event.type != WG_PARSER_EVENT_BUFFER)
618 stream->event.type = WG_PARSER_EVENT_NONE;
619 pthread_cond_signal(&stream->event_empty_cond);
621 pthread_mutex_unlock(&parser->mutex);
623 return true;
626 static bool CDECL wg_parser_stream_copy_buffer(struct wg_parser_stream *stream,
627 void *data, uint32_t offset, uint32_t size)
629 struct wg_parser *parser = stream->parser;
631 pthread_mutex_lock(&parser->mutex);
633 if (!stream->buffer)
635 pthread_mutex_unlock(&parser->mutex);
636 return false;
639 assert(stream->event.type == WG_PARSER_EVENT_BUFFER);
640 assert(offset < stream->map_info.size);
641 assert(offset + size <= stream->map_info.size);
642 memcpy(data, stream->map_info.data + offset, size);
644 pthread_mutex_unlock(&parser->mutex);
645 return true;
648 static void CDECL wg_parser_stream_release_buffer(struct wg_parser_stream *stream)
650 struct wg_parser *parser = stream->parser;
652 pthread_mutex_lock(&parser->mutex);
654 assert(stream->event.type == WG_PARSER_EVENT_BUFFER);
656 gst_buffer_unmap(stream->buffer, &stream->map_info);
657 gst_buffer_unref(stream->buffer);
658 stream->buffer = NULL;
659 stream->event.type = WG_PARSER_EVENT_NONE;
661 pthread_mutex_unlock(&parser->mutex);
662 pthread_cond_signal(&stream->event_empty_cond);
665 static uint64_t CDECL wg_parser_stream_get_duration(struct wg_parser_stream *stream)
667 return stream->duration;
670 static bool CDECL wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
671 uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags)
673 GstSeekType start_type = GST_SEEK_TYPE_SET, stop_type = GST_SEEK_TYPE_SET;
674 GstSeekFlags flags = 0;
676 if (start_flags & AM_SEEKING_SeekToKeyFrame)
677 flags |= GST_SEEK_FLAG_KEY_UNIT;
678 if (start_flags & AM_SEEKING_Segment)
679 flags |= GST_SEEK_FLAG_SEGMENT;
680 if (!(start_flags & AM_SEEKING_NoFlush))
681 flags |= GST_SEEK_FLAG_FLUSH;
683 if ((start_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning)
684 start_type = GST_SEEK_TYPE_NONE;
685 if ((stop_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning)
686 stop_type = GST_SEEK_TYPE_NONE;
688 return gst_pad_push_event(stream->my_sink, gst_event_new_seek(rate,
689 GST_FORMAT_TIME, flags, start_type, start_pos * 100, stop_type, stop_pos * 100));
692 static void CDECL wg_parser_stream_notify_qos(struct wg_parser_stream *stream,
693 bool underflow, double proportion, int64_t diff, uint64_t timestamp)
695 GstClockTime stream_time;
696 GstEvent *event;
698 /* We return timestamps in stream time, i.e. relative to the start of the
699 * file (or other medium), but gst_event_new_qos() expects the timestamp in
700 * running time. */
701 stream_time = gst_segment_to_running_time(&stream->segment, GST_FORMAT_TIME, timestamp * 100);
702 if (stream_time == -1)
704 /* This can happen legitimately if the sample falls outside of the
705 * segment bounds. GStreamer elements shouldn't present the sample in
706 * that case, but DirectShow doesn't care. */
707 TRACE("Ignoring QoS event.\n");
708 return;
711 if (!(event = gst_event_new_qos(underflow ? GST_QOS_TYPE_UNDERFLOW : GST_QOS_TYPE_OVERFLOW,
712 proportion, diff * 100, stream_time)))
713 ERR("Failed to create QOS event.\n");
714 gst_pad_push_event(stream->my_sink, event);
717 static GstAutoplugSelectResult autoplug_select_cb(GstElement *bin, GstPad *pad,
718 GstCaps *caps, GstElementFactory *fact, gpointer user)
720 const char *name = gst_element_factory_get_longname(fact);
722 GST_TRACE("Using \"%s\".", name);
724 if (strstr(name, "Player protection"))
726 GST_WARNING("Blacklisted a/52 decoder because it only works in Totem.");
727 return GST_AUTOPLUG_SELECT_SKIP;
729 if (!strcmp(name, "Fluendo Hardware Accelerated Video Decoder"))
731 GST_WARNING("Disabled video acceleration since it breaks in wine.");
732 return GST_AUTOPLUG_SELECT_SKIP;
734 return GST_AUTOPLUG_SELECT_TRY;
737 static void no_more_pads_cb(GstElement *element, gpointer user)
739 struct wg_parser *parser = user;
741 GST_DEBUG("parser %p.", parser);
743 pthread_mutex_lock(&parser->mutex);
744 parser->no_more_pads = true;
745 pthread_mutex_unlock(&parser->mutex);
746 pthread_cond_signal(&parser->init_cond);
749 static GstFlowReturn queue_stream_event(struct wg_parser_stream *stream,
750 const struct wg_parser_event *event, GstBuffer *buffer)
752 struct wg_parser *parser = stream->parser;
754 /* Unlike request_buffer_src() [q.v.], we need to watch for GStreamer
755 * flushes here. The difference is that we can be blocked by the streaming
756 * thread not running (or itself flushing on the DirectShow side).
757 * request_buffer_src() can only be blocked by the upstream source, and that
758 * is solved by flushing the upstream source. */
760 pthread_mutex_lock(&parser->mutex);
761 while (!stream->flushing && stream->event.type != WG_PARSER_EVENT_NONE)
762 pthread_cond_wait(&stream->event_empty_cond, &parser->mutex);
763 if (stream->flushing)
765 pthread_mutex_unlock(&parser->mutex);
766 GST_DEBUG("Filter is flushing; discarding event.");
767 return GST_FLOW_FLUSHING;
769 if (buffer)
771 assert(GST_IS_BUFFER(buffer));
772 if (!gst_buffer_map(buffer, &stream->map_info, GST_MAP_READ))
774 pthread_mutex_unlock(&parser->mutex);
775 GST_ERROR("Failed to map buffer.\n");
776 return GST_FLOW_ERROR;
779 stream->event = *event;
780 stream->buffer = buffer;
781 pthread_mutex_unlock(&parser->mutex);
782 pthread_cond_signal(&stream->event_cond);
783 GST_LOG("Event queued.");
784 return GST_FLOW_OK;
787 static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
789 struct wg_parser_stream *stream = gst_pad_get_element_private(pad);
790 struct wg_parser *parser = stream->parser;
792 GST_LOG("stream %p, type \"%s\".", stream, GST_EVENT_TYPE_NAME(event));
794 switch (event->type)
796 case GST_EVENT_SEGMENT:
797 if (stream->enabled)
799 struct wg_parser_event stream_event;
800 const GstSegment *segment;
802 gst_event_parse_segment(event, &segment);
804 if (segment->format != GST_FORMAT_TIME)
806 GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(segment->format));
807 break;
810 gst_segment_copy_into(segment, &stream->segment);
812 stream_event.type = WG_PARSER_EVENT_SEGMENT;
813 stream_event.u.segment.position = segment->position / 100;
814 stream_event.u.segment.stop = segment->stop / 100;
815 stream_event.u.segment.rate = segment->rate * segment->applied_rate;
816 queue_stream_event(stream, &stream_event, NULL);
818 break;
820 case GST_EVENT_EOS:
821 if (stream->enabled)
823 struct wg_parser_event stream_event;
825 stream_event.type = WG_PARSER_EVENT_EOS;
826 queue_stream_event(stream, &stream_event, NULL);
828 else
830 pthread_mutex_lock(&parser->mutex);
831 stream->eos = true;
832 pthread_mutex_unlock(&parser->mutex);
833 pthread_cond_signal(&parser->init_cond);
835 break;
837 case GST_EVENT_FLUSH_START:
838 if (stream->enabled)
840 pthread_mutex_lock(&parser->mutex);
842 stream->flushing = true;
843 pthread_cond_signal(&stream->event_empty_cond);
845 if (stream->event.type == WG_PARSER_EVENT_BUFFER)
847 gst_buffer_unmap(stream->buffer, &stream->map_info);
848 gst_buffer_unref(stream->buffer);
849 stream->buffer = NULL;
851 stream->event.type = WG_PARSER_EVENT_NONE;
853 pthread_mutex_unlock(&parser->mutex);
855 break;
857 case GST_EVENT_FLUSH_STOP:
859 gboolean reset_time;
861 gst_event_parse_flush_stop(event, &reset_time);
863 if (reset_time)
864 gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED);
866 if (stream->enabled)
868 pthread_mutex_lock(&parser->mutex);
869 stream->flushing = false;
870 pthread_mutex_unlock(&parser->mutex);
872 break;
875 case GST_EVENT_CAPS:
877 GstCaps *caps;
879 gst_event_parse_caps(event, &caps);
880 pthread_mutex_lock(&parser->mutex);
881 wg_format_from_caps(&stream->preferred_format, caps);
882 stream->has_caps = true;
883 pthread_mutex_unlock(&parser->mutex);
884 pthread_cond_signal(&parser->init_cond);
885 break;
888 default:
889 GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event));
891 gst_event_unref(event);
892 return TRUE;
895 static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer)
897 struct wg_parser_stream *stream = gst_pad_get_element_private(pad);
898 struct wg_parser_event stream_event;
899 GstFlowReturn ret;
901 GST_LOG("stream %p, buffer %p.", stream, buffer);
903 if (!stream->enabled)
905 gst_buffer_unref(buffer);
906 return GST_FLOW_OK;
909 stream_event.type = WG_PARSER_EVENT_BUFFER;
911 /* FIXME: Should we use gst_segment_to_stream_time_full()? Under what
912 * circumstances is the stream time not equal to the buffer PTS? Note that
913 * this will need modification to wg_parser_stream_notify_qos() as well. */
915 if ((stream_event.u.buffer.has_pts = GST_BUFFER_PTS_IS_VALID(buffer)))
916 stream_event.u.buffer.pts = GST_BUFFER_PTS(buffer) / 100;
917 if ((stream_event.u.buffer.has_duration = GST_BUFFER_DURATION_IS_VALID(buffer)))
918 stream_event.u.buffer.duration = GST_BUFFER_DURATION(buffer) / 100;
919 stream_event.u.buffer.discontinuity = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT);
920 stream_event.u.buffer.preroll = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE);
921 stream_event.u.buffer.delta = GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
922 stream_event.u.buffer.size = gst_buffer_get_size(buffer);
924 /* Transfer our reference to the buffer to the stream object. */
925 if ((ret = queue_stream_event(stream, &stream_event, buffer)) != GST_FLOW_OK)
926 gst_buffer_unref(buffer);
927 return ret;
930 static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
932 struct wg_parser_stream *stream = gst_pad_get_element_private(pad);
934 GST_LOG("stream %p, type \"%s\".", stream, gst_query_type_get_name(query->type));
936 switch (query->type)
938 case GST_QUERY_CAPS:
940 GstCaps *caps, *filter, *temp;
942 gst_query_parse_caps(query, &filter);
944 if (stream->enabled)
945 caps = wg_format_to_caps(&stream->current_format);
946 else
947 caps = gst_caps_new_any();
948 if (!caps)
949 return FALSE;
951 if (filter)
953 temp = gst_caps_intersect(caps, filter);
954 gst_caps_unref(caps);
955 caps = temp;
958 gst_query_set_caps_result(query, caps);
959 gst_caps_unref(caps);
960 return TRUE;
963 case GST_QUERY_ACCEPT_CAPS:
965 struct wg_format format;
966 gboolean ret = TRUE;
967 GstCaps *caps;
969 if (!stream->enabled)
971 gst_query_set_accept_caps_result(query, TRUE);
972 return TRUE;
975 gst_query_parse_accept_caps(query, &caps);
976 wg_format_from_caps(&format, caps);
977 ret = wg_format_compare(&format, &stream->current_format);
978 if (!ret && WARN_ON(gstreamer))
980 gchar *str = gst_caps_to_string(caps);
981 GST_WARNING("Rejecting caps \"%s\".", str);
982 g_free(str);
984 gst_query_set_accept_caps_result(query, ret);
985 return TRUE;
988 default:
989 return gst_pad_query_default (pad, parent, query);
993 static struct wg_parser_stream *create_stream(struct wg_parser *parser)
995 struct wg_parser_stream *stream, **new_array;
996 char pad_name[19];
998 if (!(new_array = realloc(parser->streams, (parser->stream_count + 1) * sizeof(*parser->streams))))
999 return NULL;
1000 parser->streams = new_array;
1002 if (!(stream = calloc(1, sizeof(*stream))))
1003 return NULL;
1005 gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED);
1007 stream->parser = parser;
1008 pthread_cond_init(&stream->event_cond, NULL);
1009 pthread_cond_init(&stream->event_empty_cond, NULL);
1011 sprintf(pad_name, "qz_sink_%u", parser->stream_count);
1012 stream->my_sink = gst_pad_new(pad_name, GST_PAD_SINK);
1013 gst_pad_set_element_private(stream->my_sink, stream);
1014 gst_pad_set_chain_function(stream->my_sink, sink_chain_cb);
1015 gst_pad_set_event_function(stream->my_sink, sink_event_cb);
1016 gst_pad_set_query_function(stream->my_sink, sink_query_cb);
1018 parser->streams[parser->stream_count++] = stream;
1019 return stream;
1022 static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
1024 struct wg_parser *parser = user;
1025 struct wg_parser_stream *stream;
1026 const char *name;
1027 GstCaps *caps;
1028 int ret;
1030 GST_LOG("parser %p, element %p, pad %p.", parser, element, pad);
1032 if (gst_pad_is_linked(pad))
1033 return;
1035 caps = gst_pad_query_caps(pad, NULL);
1036 name = gst_structure_get_name(gst_caps_get_structure(caps, 0));
1038 if (!(stream = create_stream(parser)))
1039 goto out;
1041 if (!strcmp(name, "video/x-raw"))
1043 GstElement *deinterlace, *vconv, *flip, *vconv2;
1045 /* DirectShow can express interlaced video, but downstream filters can't
1046 * necessarily consume it. In particular, the video renderer can't. */
1047 if (!(deinterlace = gst_element_factory_make("deinterlace", NULL)))
1049 fprintf(stderr, "winegstreamer: failed to create deinterlace, are %u-bit GStreamer \"good\" plugins installed?\n",
1050 8 * (int)sizeof(void *));
1051 goto out;
1054 /* decodebin considers many YUV formats to be "raw", but some quartz
1055 * filters can't handle those. Also, videoflip can't handle all "raw"
1056 * formats either. Add a videoconvert to swap color spaces. */
1057 if (!(vconv = gst_element_factory_make("videoconvert", NULL)))
1059 fprintf(stderr, "winegstreamer: failed to create videoconvert, are %u-bit GStreamer \"base\" plugins installed?\n",
1060 8 * (int)sizeof(void *));
1061 goto out;
1064 /* GStreamer outputs RGB video top-down, but DirectShow expects bottom-up. */
1065 if (!(flip = gst_element_factory_make("videoflip", NULL)))
1067 fprintf(stderr, "winegstreamer: failed to create videoflip, are %u-bit GStreamer \"good\" plugins installed?\n",
1068 8 * (int)sizeof(void *));
1069 goto out;
1072 /* videoflip does not support 15 and 16-bit RGB so add a second videoconvert
1073 * to do the final conversion. */
1074 if (!(vconv2 = gst_element_factory_make("videoconvert", NULL)))
1076 fprintf(stderr, "winegstreamer: failed to create videoconvert, are %u-bit GStreamer \"base\" plugins installed?\n",
1077 8 * (int)sizeof(void *));
1078 goto out;
1081 /* The bin takes ownership of these elements. */
1082 gst_bin_add(GST_BIN(parser->container), deinterlace);
1083 gst_element_sync_state_with_parent(deinterlace);
1084 gst_bin_add(GST_BIN(parser->container), vconv);
1085 gst_element_sync_state_with_parent(vconv);
1086 gst_bin_add(GST_BIN(parser->container), flip);
1087 gst_element_sync_state_with_parent(flip);
1088 gst_bin_add(GST_BIN(parser->container), vconv2);
1089 gst_element_sync_state_with_parent(vconv2);
1091 gst_element_link(deinterlace, vconv);
1092 gst_element_link(vconv, flip);
1093 gst_element_link(flip, vconv2);
1095 stream->post_sink = gst_element_get_static_pad(deinterlace, "sink");
1096 stream->post_src = gst_element_get_static_pad(vconv2, "src");
1097 stream->flip = flip;
1099 else if (!strcmp(name, "audio/x-raw"))
1101 GstElement *convert;
1103 /* Currently our dsound can't handle 64-bit formats or all
1104 * surround-sound configurations. Native dsound can't always handle
1105 * 64-bit formats either. Add an audioconvert to allow changing bit
1106 * depth and channel count. */
1107 if (!(convert = gst_element_factory_make("audioconvert", NULL)))
1109 fprintf(stderr, "winegstreamer: failed to create audioconvert, are %u-bit GStreamer \"base\" plugins installed?\n",
1110 8 * (int)sizeof(void *));
1111 goto out;
1114 gst_bin_add(GST_BIN(parser->container), convert);
1115 gst_element_sync_state_with_parent(convert);
1117 stream->post_sink = gst_element_get_static_pad(convert, "sink");
1118 stream->post_src = gst_element_get_static_pad(convert, "src");
1121 if (stream->post_sink)
1123 if ((ret = gst_pad_link(pad, stream->post_sink)) < 0)
1125 GST_ERROR("Failed to link decodebin source pad to post-processing elements, error %s.",
1126 gst_pad_link_get_name(ret));
1127 gst_object_unref(stream->post_sink);
1128 stream->post_sink = NULL;
1129 goto out;
1132 if ((ret = gst_pad_link(stream->post_src, stream->my_sink)) < 0)
1134 GST_ERROR("Failed to link post-processing elements to our sink pad, error %s.",
1135 gst_pad_link_get_name(ret));
1136 gst_object_unref(stream->post_src);
1137 stream->post_src = NULL;
1138 gst_object_unref(stream->post_sink);
1139 stream->post_sink = NULL;
1140 goto out;
1143 else if ((ret = gst_pad_link(pad, stream->my_sink)) < 0)
1145 GST_ERROR("Failed to link decodebin source pad to our sink pad, error %s.",
1146 gst_pad_link_get_name(ret));
1147 goto out;
1150 gst_pad_set_active(stream->my_sink, 1);
1151 gst_object_ref(stream->their_src = pad);
1152 out:
1153 gst_caps_unref(caps);
1156 static void pad_removed_cb(GstElement *element, GstPad *pad, gpointer user)
1158 struct wg_parser *parser = user;
1159 unsigned int i;
1160 char *name;
1162 GST_LOG("parser %p, element %p, pad %p.", parser, element, pad);
1164 for (i = 0; i < parser->stream_count; ++i)
1166 struct wg_parser_stream *stream = parser->streams[i];
1168 if (stream->their_src == pad)
1170 if (stream->post_sink)
1171 gst_pad_unlink(stream->their_src, stream->post_sink);
1172 else
1173 gst_pad_unlink(stream->their_src, stream->my_sink);
1174 gst_object_unref(stream->their_src);
1175 stream->their_src = NULL;
1176 return;
1180 name = gst_pad_get_name(pad);
1181 GST_WARNING("No pin matching pad \"%s\" found.", name);
1182 g_free(name);
1185 static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
1186 guint64 offset, guint size, GstBuffer **buffer)
1188 struct wg_parser *parser = gst_pad_get_element_private(pad);
1189 GstBuffer *new_buffer = NULL;
1190 GstMapInfo map_info;
1191 bool ret;
1193 GST_LOG("pad %p, offset %" G_GINT64_MODIFIER "u, length %u, buffer %p.", pad, offset, size, *buffer);
1195 if (offset == GST_BUFFER_OFFSET_NONE)
1196 offset = parser->next_pull_offset;
1197 parser->next_pull_offset = offset + size;
1198 if (offset >= parser->file_size)
1199 return GST_FLOW_EOS;
1200 if (offset + size >= parser->file_size)
1201 size = parser->file_size - offset;
1203 if (!*buffer)
1204 *buffer = new_buffer = gst_buffer_new_and_alloc(size);
1206 gst_buffer_map(*buffer, &map_info, GST_MAP_WRITE);
1208 pthread_mutex_lock(&parser->mutex);
1210 assert(!parser->read_request.data);
1211 parser->read_request.data = map_info.data;
1212 parser->read_request.offset = offset;
1213 parser->read_request.size = size;
1214 parser->read_request.done = false;
1215 pthread_cond_signal(&parser->read_cond);
1217 /* Note that we don't unblock this wait on GST_EVENT_FLUSH_START. We expect
1218 * the upstream pin to flush if necessary. We should never be blocked on
1219 * read_thread() not running. */
1221 while (!parser->read_request.done)
1222 pthread_cond_wait(&parser->read_done_cond, &parser->mutex);
1224 ret = parser->read_request.ret;
1226 pthread_mutex_unlock(&parser->mutex);
1228 gst_buffer_unmap(*buffer, &map_info);
1230 GST_LOG("Request returned %d.", ret);
1232 if (!ret && new_buffer)
1233 gst_buffer_unref(new_buffer);
1235 return ret ? GST_FLOW_OK : GST_FLOW_ERROR;
1238 static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
1240 struct wg_parser *parser = gst_pad_get_element_private(pad);
1241 GstFormat format;
1243 GST_LOG("parser %p, type %s.", parser, GST_QUERY_TYPE_NAME(query));
1245 switch (GST_QUERY_TYPE(query))
1247 case GST_QUERY_DURATION:
1248 gst_query_parse_duration(query, &format, NULL);
1249 if (format == GST_FORMAT_PERCENT)
1251 gst_query_set_duration(query, GST_FORMAT_PERCENT, GST_FORMAT_PERCENT_MAX);
1252 return TRUE;
1254 else if (format == GST_FORMAT_BYTES)
1256 gst_query_set_duration(query, GST_FORMAT_BYTES, parser->file_size);
1257 return TRUE;
1259 return FALSE;
1261 case GST_QUERY_SEEKING:
1262 gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
1263 if (format != GST_FORMAT_BYTES)
1265 GST_WARNING("Cannot seek using format \"%s\".", gst_format_get_name(format));
1266 return FALSE;
1268 gst_query_set_seeking(query, GST_FORMAT_BYTES, 1, 0, parser->file_size);
1269 return TRUE;
1271 case GST_QUERY_SCHEDULING:
1272 gst_query_set_scheduling(query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
1273 gst_query_add_scheduling_mode(query, GST_PAD_MODE_PUSH);
1274 gst_query_add_scheduling_mode(query, GST_PAD_MODE_PULL);
1275 return TRUE;
1277 default:
1278 GST_WARNING("Unhandled query type %s.", GST_QUERY_TYPE_NAME(query));
1279 return FALSE;
1283 static void *push_data(void *arg)
1285 struct wg_parser *parser = arg;
1286 GstBuffer *buffer;
1287 guint max_size;
1289 GST_DEBUG("Starting push thread.");
1291 if (!(buffer = gst_buffer_new_allocate(NULL, 16384, NULL)))
1293 GST_ERROR("Failed to allocate memory.");
1294 return NULL;
1297 max_size = parser->stop_offset ? parser->stop_offset : parser->file_size;
1299 for (;;)
1301 ULONG size;
1302 int ret;
1304 if (parser->next_offset >= max_size)
1305 break;
1306 size = min(16384, max_size - parser->next_offset);
1308 if ((ret = src_getrange_cb(parser->my_src, NULL, parser->next_offset, size, &buffer)) < 0)
1310 GST_ERROR("Failed to read data, ret %s.", gst_flow_get_name(ret));
1311 break;
1314 parser->next_offset += size;
1316 buffer->duration = buffer->pts = -1;
1317 if ((ret = gst_pad_push(parser->my_src, buffer)) < 0)
1319 GST_ERROR("Failed to push data, ret %s.", gst_flow_get_name(ret));
1320 break;
1324 gst_buffer_unref(buffer);
1326 gst_pad_push_event(parser->my_src, gst_event_new_eos());
1328 GST_DEBUG("Stopping push thread.");
1330 return NULL;
1333 static gboolean activate_push(GstPad *pad, gboolean activate)
1335 struct wg_parser *parser = gst_pad_get_element_private(pad);
1337 if (!activate)
1339 if (parser->push_thread)
1341 pthread_join(parser->push_thread, NULL);
1342 parser->push_thread = 0;
1345 else if (!parser->push_thread)
1347 int ret;
1349 if ((ret = pthread_create(&parser->push_thread, NULL, push_data, parser)))
1351 GST_ERROR("Failed to create push thread: %s", strerror(errno));
1352 parser->push_thread = 0;
1353 return FALSE;
1356 return TRUE;
1359 static gboolean src_activate_mode_cb(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate)
1361 struct wg_parser *parser = gst_pad_get_element_private(pad);
1363 GST_DEBUG("%s source pad for parser %p in %s mode.",
1364 activate ? "Activating" : "Deactivating", parser, gst_pad_mode_get_name(mode));
1366 switch (mode)
1368 case GST_PAD_MODE_PULL:
1369 return TRUE;
1370 case GST_PAD_MODE_PUSH:
1371 return activate_push(pad, activate);
1372 case GST_PAD_MODE_NONE:
1373 break;
1375 return FALSE;
1378 static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer user)
1380 struct wg_parser *parser = user;
1381 gchar *dbg_info = NULL;
1382 GError *err = NULL;
1384 GST_DEBUG("parser %p, message type %s.", parser, GST_MESSAGE_TYPE_NAME(msg));
1386 switch (msg->type)
1388 case GST_MESSAGE_ERROR:
1389 gst_message_parse_error(msg, &err, &dbg_info);
1390 fprintf(stderr, "winegstreamer: error: %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
1391 fprintf(stderr, "winegstreamer: error: %s: %s\n", GST_OBJECT_NAME(msg->src), dbg_info);
1392 g_error_free(err);
1393 g_free(dbg_info);
1394 pthread_mutex_lock(&parser->mutex);
1395 parser->error = true;
1396 pthread_mutex_unlock(&parser->mutex);
1397 pthread_cond_signal(&parser->init_cond);
1398 break;
1400 case GST_MESSAGE_WARNING:
1401 gst_message_parse_warning(msg, &err, &dbg_info);
1402 fprintf(stderr, "winegstreamer: warning: %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
1403 fprintf(stderr, "winegstreamer: warning: %s: %s\n", GST_OBJECT_NAME(msg->src), dbg_info);
1404 g_error_free(err);
1405 g_free(dbg_info);
1406 break;
1408 case GST_MESSAGE_DURATION_CHANGED:
1409 pthread_mutex_lock(&parser->mutex);
1410 parser->has_duration = true;
1411 pthread_mutex_unlock(&parser->mutex);
1412 pthread_cond_signal(&parser->init_cond);
1413 break;
1415 default:
1416 break;
1418 gst_message_unref(msg);
1419 return GST_BUS_DROP;
1422 static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event)
1424 BOOL thread = !!parser->push_thread;
1425 GstSeekType cur_type, stop_type;
1426 GstFormat seek_format;
1427 GstEvent *flush_event;
1428 GstSeekFlags flags;
1429 gint64 cur, stop;
1430 guint32 seqnum;
1431 gdouble rate;
1433 gst_event_parse_seek(event, &rate, &seek_format, &flags,
1434 &cur_type, &cur, &stop_type, &stop);
1436 if (seek_format != GST_FORMAT_BYTES)
1438 GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(seek_format));
1439 return FALSE;
1442 seqnum = gst_event_get_seqnum(event);
1444 /* send flush start */
1445 if (flags & GST_SEEK_FLAG_FLUSH)
1447 flush_event = gst_event_new_flush_start();
1448 gst_event_set_seqnum(flush_event, seqnum);
1449 gst_pad_push_event(parser->my_src, flush_event);
1450 if (thread)
1451 gst_pad_set_active(parser->my_src, 1);
1454 parser->next_offset = parser->start_offset = cur;
1456 /* and prepare to continue streaming */
1457 if (flags & GST_SEEK_FLAG_FLUSH)
1459 flush_event = gst_event_new_flush_stop(TRUE);
1460 gst_event_set_seqnum(flush_event, seqnum);
1461 gst_pad_push_event(parser->my_src, flush_event);
1462 if (thread)
1463 gst_pad_set_active(parser->my_src, 1);
1466 return TRUE;
1469 static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
1471 struct wg_parser *parser = gst_pad_get_element_private(pad);
1472 gboolean ret = TRUE;
1474 GST_LOG("parser %p, type \"%s\".", parser, GST_EVENT_TYPE_NAME(event));
1476 switch (event->type)
1478 case GST_EVENT_SEEK:
1479 ret = src_perform_seek(parser, event);
1480 break;
1482 case GST_EVENT_FLUSH_START:
1483 case GST_EVENT_FLUSH_STOP:
1484 case GST_EVENT_QOS:
1485 case GST_EVENT_RECONFIGURE:
1486 break;
1488 default:
1489 GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event));
1490 ret = FALSE;
1491 break;
1493 gst_event_unref(event);
1494 return ret;
1497 static LONGLONG query_duration(GstPad *pad)
1499 gint64 duration, byte_length;
1501 if (gst_pad_query_duration(pad, GST_FORMAT_TIME, &duration))
1502 return duration / 100;
1504 WARN("Failed to query time duration; trying to convert from byte length.\n");
1506 /* To accurately get a duration for the stream, we want to only consider the
1507 * length of that stream. Hence, query for the pad duration, instead of
1508 * using the file duration. */
1509 if (gst_pad_query_duration(pad, GST_FORMAT_BYTES, &byte_length)
1510 && gst_pad_query_convert(pad, GST_FORMAT_BYTES, byte_length, GST_FORMAT_TIME, &duration))
1511 return duration / 100;
1513 ERR("Failed to query duration.\n");
1514 return 0;
1517 static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_size)
1519 GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("quartz_src",
1520 GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
1521 unsigned int i;
1523 parser->file_size = file_size;
1524 parser->sink_connected = true;
1526 if (!parser->bus)
1528 parser->bus = gst_bus_new();
1529 gst_bus_set_sync_handler(parser->bus, bus_handler_cb, parser, NULL);
1532 parser->container = gst_bin_new(NULL);
1533 gst_element_set_bus(parser->container, parser->bus);
1535 parser->my_src = gst_pad_new_from_static_template(&src_template, "quartz-src");
1536 gst_pad_set_getrange_function(parser->my_src, src_getrange_cb);
1537 gst_pad_set_query_function(parser->my_src, src_query_cb);
1538 gst_pad_set_activatemode_function(parser->my_src, src_activate_mode_cb);
1539 gst_pad_set_event_function(parser->my_src, src_event_cb);
1540 gst_pad_set_element_private(parser->my_src, parser);
1542 parser->start_offset = parser->next_offset = parser->stop_offset = 0;
1543 parser->next_pull_offset = 0;
1545 if (!parser->init_gst(parser))
1546 return E_FAIL;
1548 pthread_mutex_lock(&parser->mutex);
1550 for (i = 0; i < parser->stream_count; ++i)
1552 struct wg_parser_stream *stream = parser->streams[i];
1554 stream->duration = query_duration(stream->their_src);
1555 while (!stream->has_caps && !parser->error)
1556 pthread_cond_wait(&parser->init_cond, &parser->mutex);
1557 if (parser->error)
1559 pthread_mutex_unlock(&parser->mutex);
1560 return E_FAIL;
1564 pthread_mutex_unlock(&parser->mutex);
1566 parser->next_offset = 0;
1567 return S_OK;
1570 static void free_stream(struct wg_parser_stream *stream)
1572 if (stream->their_src)
1574 if (stream->post_sink)
1576 gst_pad_unlink(stream->their_src, stream->post_sink);
1577 gst_pad_unlink(stream->post_src, stream->my_sink);
1578 gst_object_unref(stream->post_src);
1579 gst_object_unref(stream->post_sink);
1580 stream->post_src = stream->post_sink = NULL;
1582 else
1583 gst_pad_unlink(stream->their_src, stream->my_sink);
1584 gst_object_unref(stream->their_src);
1586 gst_object_unref(stream->my_sink);
1588 pthread_cond_destroy(&stream->event_cond);
1589 pthread_cond_destroy(&stream->event_empty_cond);
1591 free(stream);
1594 static void CDECL wg_parser_disconnect(struct wg_parser *parser)
1596 unsigned int i;
1598 /* Unblock all of our streams. */
1599 pthread_mutex_lock(&parser->mutex);
1600 for (i = 0; i < parser->stream_count; ++i)
1602 parser->streams[i]->flushing = true;
1603 pthread_cond_signal(&parser->streams[i]->event_empty_cond);
1605 pthread_mutex_unlock(&parser->mutex);
1607 gst_element_set_state(parser->container, GST_STATE_NULL);
1608 gst_pad_unlink(parser->my_src, parser->their_sink);
1609 gst_object_unref(parser->my_src);
1610 gst_object_unref(parser->their_sink);
1611 parser->my_src = parser->their_sink = NULL;
1613 pthread_mutex_lock(&parser->mutex);
1614 parser->sink_connected = false;
1615 pthread_mutex_unlock(&parser->mutex);
1616 pthread_cond_signal(&parser->read_cond);
1618 for (i = 0; i < parser->stream_count; ++i)
1619 free_stream(parser->streams[i]);
1621 parser->stream_count = 0;
1622 free(parser->streams);
1623 parser->streams = NULL;
1625 gst_element_set_bus(parser->container, NULL);
1626 gst_object_unref(parser->container);
1627 parser->container = NULL;
1630 static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
1632 GstElement *element = gst_element_factory_make("decodebin", NULL);
1633 int ret;
1635 if (!element)
1637 ERR("Failed to create decodebin; are %u-bit GStreamer \"base\" plugins installed?\n",
1638 8 * (int)sizeof(void*));
1639 return FALSE;
1642 gst_bin_add(GST_BIN(parser->container), element);
1643 parser->decodebin = element;
1645 g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser);
1646 g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser);
1647 g_signal_connect(element, "autoplug-select", G_CALLBACK(autoplug_select_cb), parser);
1648 g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser);
1650 parser->their_sink = gst_element_get_static_pad(element, "sink");
1652 pthread_mutex_lock(&parser->mutex);
1653 parser->no_more_pads = parser->error = false;
1654 pthread_mutex_unlock(&parser->mutex);
1656 if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
1658 ERR("Failed to link pads, error %d.\n", ret);
1659 return FALSE;
1662 gst_element_set_state(parser->container, GST_STATE_PAUSED);
1663 ret = gst_element_get_state(parser->container, NULL, NULL, -1);
1664 if (ret == GST_STATE_CHANGE_FAILURE)
1666 ERR("Failed to play stream.\n");
1667 return FALSE;
1670 pthread_mutex_lock(&parser->mutex);
1671 while (!parser->no_more_pads && !parser->error)
1672 pthread_cond_wait(&parser->init_cond, &parser->mutex);
1673 if (parser->error)
1675 pthread_mutex_unlock(&parser->mutex);
1676 return FALSE;
1678 pthread_mutex_unlock(&parser->mutex);
1680 return TRUE;
1683 static BOOL avi_parser_init_gst(struct wg_parser *parser)
1685 GstElement *element = gst_element_factory_make("avidemux", NULL);
1686 int ret;
1688 if (!element)
1690 ERR("Failed to create avidemux; are %u-bit GStreamer \"good\" plugins installed?\n",
1691 8 * (int)sizeof(void*));
1692 return FALSE;
1695 gst_bin_add(GST_BIN(parser->container), element);
1697 g_signal_connect(element, "pad-added", G_CALLBACK(pad_added_cb), parser);
1698 g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser);
1699 g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser);
1701 parser->their_sink = gst_element_get_static_pad(element, "sink");
1703 pthread_mutex_lock(&parser->mutex);
1704 parser->no_more_pads = parser->error = false;
1705 pthread_mutex_unlock(&parser->mutex);
1707 if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
1709 ERR("Failed to link pads, error %d.\n", ret);
1710 return FALSE;
1713 gst_element_set_state(parser->container, GST_STATE_PAUSED);
1714 ret = gst_element_get_state(parser->container, NULL, NULL, -1);
1715 if (ret == GST_STATE_CHANGE_FAILURE)
1717 ERR("Failed to play stream.\n");
1718 return FALSE;
1721 pthread_mutex_lock(&parser->mutex);
1722 while (!parser->no_more_pads && !parser->error)
1723 pthread_cond_wait(&parser->init_cond, &parser->mutex);
1724 if (parser->error)
1726 pthread_mutex_unlock(&parser->mutex);
1727 return FALSE;
1729 pthread_mutex_unlock(&parser->mutex);
1731 return TRUE;
1734 static BOOL mpeg_audio_parser_init_gst(struct wg_parser *parser)
1736 struct wg_parser_stream *stream;
1737 GstElement *element;
1738 int ret;
1740 if (!(element = gst_element_factory_make("mpegaudioparse", NULL)))
1742 ERR("Failed to create mpegaudioparse; are %u-bit GStreamer \"good\" plugins installed?\n",
1743 8 * (int)sizeof(void*));
1744 return FALSE;
1747 gst_bin_add(GST_BIN(parser->container), element);
1749 parser->their_sink = gst_element_get_static_pad(element, "sink");
1750 if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
1752 ERR("Failed to link sink pads, error %d.\n", ret);
1753 return FALSE;
1756 if (!(stream = create_stream(parser)))
1757 return FALSE;
1759 gst_object_ref(stream->their_src = gst_element_get_static_pad(element, "src"));
1760 if ((ret = gst_pad_link(stream->their_src, stream->my_sink)) < 0)
1762 ERR("Failed to link source pads, error %d.\n", ret);
1763 return FALSE;
1766 gst_pad_set_active(stream->my_sink, 1);
1767 gst_element_set_state(parser->container, GST_STATE_PAUSED);
1768 ret = gst_element_get_state(parser->container, NULL, NULL, -1);
1769 if (ret == GST_STATE_CHANGE_FAILURE)
1771 ERR("Failed to play stream.\n");
1772 return FALSE;
1775 pthread_mutex_lock(&parser->mutex);
1776 while (!parser->has_duration && !parser->error && !stream->eos)
1777 pthread_cond_wait(&parser->init_cond, &parser->mutex);
1778 if (parser->error)
1780 pthread_mutex_unlock(&parser->mutex);
1781 return FALSE;
1783 pthread_mutex_unlock(&parser->mutex);
1784 return TRUE;
1787 static BOOL wave_parser_init_gst(struct wg_parser *parser)
1789 struct wg_parser_stream *stream;
1790 GstElement *element;
1791 int ret;
1793 if (!(element = gst_element_factory_make("wavparse", NULL)))
1795 ERR("Failed to create wavparse; are %u-bit GStreamer \"good\" plugins installed?\n",
1796 8 * (int)sizeof(void*));
1797 return FALSE;
1800 gst_bin_add(GST_BIN(parser->container), element);
1802 parser->their_sink = gst_element_get_static_pad(element, "sink");
1803 if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
1805 ERR("Failed to link sink pads, error %d.\n", ret);
1806 return FALSE;
1809 if (!(stream = create_stream(parser)))
1810 return FALSE;
1812 stream->their_src = gst_element_get_static_pad(element, "src");
1813 gst_object_ref(stream->their_src);
1814 if ((ret = gst_pad_link(stream->their_src, stream->my_sink)) < 0)
1816 ERR("Failed to link source pads, error %d.\n", ret);
1817 return FALSE;
1820 gst_pad_set_active(stream->my_sink, 1);
1821 gst_element_set_state(parser->container, GST_STATE_PAUSED);
1822 ret = gst_element_get_state(parser->container, NULL, NULL, -1);
1823 if (ret == GST_STATE_CHANGE_FAILURE)
1825 ERR("Failed to play stream.\n");
1826 return FALSE;
1829 return TRUE;
1832 static struct wg_parser *wg_parser_create(void)
1834 struct wg_parser *parser;
1836 if (!(parser = calloc(1, sizeof(*parser))))
1837 return NULL;
1839 pthread_mutex_init(&parser->mutex, NULL);
1840 pthread_cond_init(&parser->init_cond, NULL);
1841 pthread_cond_init(&parser->read_cond, NULL);
1842 pthread_cond_init(&parser->read_done_cond, NULL);
1843 parser->flushing = true;
1845 TRACE("Created winegstreamer parser %p.\n", parser);
1846 return parser;
1849 static struct wg_parser * CDECL wg_decodebin_parser_create(void)
1851 struct wg_parser *parser;
1853 if ((parser = wg_parser_create()))
1854 parser->init_gst = decodebin_parser_init_gst;
1855 return parser;
1858 static struct wg_parser * CDECL wg_avi_parser_create(void)
1860 struct wg_parser *parser;
1862 if ((parser = wg_parser_create()))
1863 parser->init_gst = avi_parser_init_gst;
1864 return parser;
1867 static struct wg_parser * CDECL wg_mpeg_audio_parser_create(void)
1869 struct wg_parser *parser;
1871 if ((parser = wg_parser_create()))
1872 parser->init_gst = mpeg_audio_parser_init_gst;
1873 return parser;
1876 static struct wg_parser * CDECL wg_wave_parser_create(void)
1878 struct wg_parser *parser;
1880 if ((parser = wg_parser_create()))
1881 parser->init_gst = wave_parser_init_gst;
1882 return parser;
1885 static void CDECL wg_parser_destroy(struct wg_parser *parser)
1887 if (parser->bus)
1889 gst_bus_set_sync_handler(parser->bus, NULL, NULL, NULL);
1890 gst_object_unref(parser->bus);
1893 pthread_mutex_destroy(&parser->mutex);
1894 pthread_cond_destroy(&parser->init_cond);
1895 pthread_cond_destroy(&parser->read_cond);
1896 pthread_cond_destroy(&parser->read_done_cond);
1898 free(parser);
1901 static const struct unix_funcs funcs =
1903 wg_decodebin_parser_create,
1904 wg_avi_parser_create,
1905 wg_mpeg_audio_parser_create,
1906 wg_wave_parser_create,
1907 wg_parser_destroy,
1909 wg_parser_connect,
1910 wg_parser_disconnect,
1912 wg_parser_begin_flush,
1913 wg_parser_end_flush,
1915 wg_parser_get_read_request,
1916 wg_parser_complete_read_request,
1918 wg_parser_set_unlimited_buffering,
1920 wg_parser_get_stream_count,
1921 wg_parser_get_stream,
1923 wg_parser_stream_get_preferred_format,
1924 wg_parser_stream_enable,
1925 wg_parser_stream_disable,
1927 wg_parser_stream_get_event,
1928 wg_parser_stream_copy_buffer,
1929 wg_parser_stream_release_buffer,
1930 wg_parser_stream_notify_qos,
1932 wg_parser_stream_get_duration,
1933 wg_parser_stream_seek,
1936 NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
1938 if (reason == DLL_PROCESS_ATTACH)
1940 char arg0[] = "wine";
1941 char arg1[] = "--gst-disable-registry-fork";
1942 char *args[] = {arg0, arg1, NULL};
1943 int argc = ARRAY_SIZE(args) - 1;
1944 char **argv = args;
1945 GError *err;
1947 if (!gst_init_check(&argc, &argv, &err))
1949 ERR("Failed to initialize GStreamer: %s\n", debugstr_a(err->message));
1950 g_error_free(err);
1951 return STATUS_UNSUCCESSFUL;
1953 TRACE("GStreamer library version %s; wine built with %d.%d.%d.\n",
1954 gst_version_string(), GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO);
1956 GST_DEBUG_CATEGORY_INIT(wine, "WINE", GST_DEBUG_FG_RED, "Wine GStreamer support");
1958 *(const struct unix_funcs **)ptr_out = &funcs;
1960 return STATUS_SUCCESS;