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
29 #define WIN32_NO_STATUS
30 #include "gst_private.h"
34 #include <gst/video/video.h>
35 #include <gst/audio/audio.h>
37 /* GStreamer callbacks may be called on threads not created by Wine, and
38 * therefore cannot access the Wine TEB. This means that we must use GStreamer
39 * debug logging instead of Wine debug logging. In order to be safe we forbid
40 * any use of Wine debug logging in this entire file. */
42 GST_DEBUG_CATEGORY_STATIC(wine
);
43 #define GST_CAT_DEFAULT wine
47 BOOL (*init_gst
)(struct wg_parser
*parser
);
49 struct wg_parser_stream
**streams
;
50 unsigned int stream_count
;
52 GstElement
*container
, *decodebin
;
54 GstPad
*my_src
, *their_sink
;
56 guint64 file_size
, start_offset
, next_offset
, stop_offset
;
57 guint64 next_pull_offset
;
59 pthread_t push_thread
;
61 pthread_mutex_t mutex
;
63 pthread_cond_t init_cond
;
64 bool no_more_pads
, has_duration
, error
;
66 pthread_cond_t read_cond
, read_done_cond
;
76 bool flushing
, sink_connected
;
79 struct wg_parser_stream
81 struct wg_parser
*parser
;
83 GstPad
*their_src
, *post_sink
, *post_src
, *my_sink
;
86 struct wg_format preferred_format
, current_format
;
88 pthread_cond_t event_cond
, event_empty_cond
;
89 struct wg_parser_event event
;
93 bool flushing
, eos
, enabled
, has_caps
;
98 static enum wg_audio_format
wg_audio_format_from_gst(GstAudioFormat format
)
102 case GST_AUDIO_FORMAT_U8
:
103 return WG_AUDIO_FORMAT_U8
;
104 case GST_AUDIO_FORMAT_S16LE
:
105 return WG_AUDIO_FORMAT_S16LE
;
106 case GST_AUDIO_FORMAT_S24LE
:
107 return WG_AUDIO_FORMAT_S24LE
;
108 case GST_AUDIO_FORMAT_S32LE
:
109 return WG_AUDIO_FORMAT_S32LE
;
110 case GST_AUDIO_FORMAT_F32LE
:
111 return WG_AUDIO_FORMAT_F32LE
;
112 case GST_AUDIO_FORMAT_F64LE
:
113 return WG_AUDIO_FORMAT_F64LE
;
115 return WG_AUDIO_FORMAT_UNKNOWN
;
119 static uint32_t wg_channel_position_from_gst(GstAudioChannelPosition position
)
121 static const uint32_t position_map
[] =
125 SPEAKER_FRONT_CENTER
,
126 SPEAKER_LOW_FREQUENCY
,
129 SPEAKER_FRONT_LEFT_OF_CENTER
,
130 SPEAKER_FRONT_RIGHT_OF_CENTER
,
135 SPEAKER_TOP_FRONT_LEFT
,
136 SPEAKER_TOP_FRONT_RIGHT
,
137 SPEAKER_TOP_FRONT_CENTER
,
139 SPEAKER_TOP_BACK_LEFT
,
140 SPEAKER_TOP_BACK_RIGHT
,
143 SPEAKER_TOP_BACK_CENTER
,
146 if (position
< ARRAY_SIZE(position_map
))
147 return position_map
[position
];
151 static uint32_t wg_channel_mask_from_gst(const GstAudioInfo
*info
)
153 uint32_t mask
= 0, position
;
156 for (i
= 0; i
< GST_AUDIO_INFO_CHANNELS(info
); ++i
)
158 if (!(position
= wg_channel_position_from_gst(GST_AUDIO_INFO_POSITION(info
, i
))))
160 GST_WARNING("Unsupported channel %#x.", GST_AUDIO_INFO_POSITION(info
, i
));
163 /* Make sure it's also in WinMM order. WinMM mandates that channels be
164 * ordered, as it were, from least to most significant SPEAKER_* bit.
165 * Hence we fail if the current channel was already specified, or if any
166 * higher bit was already specified. */
167 if (mask
& ~(position
- 1))
169 GST_WARNING("Unsupported channel order.");
177 static void wg_format_from_audio_info(struct wg_format
*format
, const GstAudioInfo
*info
)
179 format
->major_type
= WG_MAJOR_TYPE_AUDIO
;
180 format
->u
.audio
.format
= wg_audio_format_from_gst(GST_AUDIO_INFO_FORMAT(info
));
181 format
->u
.audio
.channels
= GST_AUDIO_INFO_CHANNELS(info
);
182 format
->u
.audio
.channel_mask
= wg_channel_mask_from_gst(info
);
183 format
->u
.audio
.rate
= GST_AUDIO_INFO_RATE(info
);
186 static enum wg_video_format
wg_video_format_from_gst(GstVideoFormat format
)
190 case GST_VIDEO_FORMAT_BGRA
:
191 return WG_VIDEO_FORMAT_BGRA
;
192 case GST_VIDEO_FORMAT_BGRx
:
193 return WG_VIDEO_FORMAT_BGRx
;
194 case GST_VIDEO_FORMAT_BGR
:
195 return WG_VIDEO_FORMAT_BGR
;
196 case GST_VIDEO_FORMAT_RGB15
:
197 return WG_VIDEO_FORMAT_RGB15
;
198 case GST_VIDEO_FORMAT_RGB16
:
199 return WG_VIDEO_FORMAT_RGB16
;
200 case GST_VIDEO_FORMAT_AYUV
:
201 return WG_VIDEO_FORMAT_AYUV
;
202 case GST_VIDEO_FORMAT_I420
:
203 return WG_VIDEO_FORMAT_I420
;
204 case GST_VIDEO_FORMAT_NV12
:
205 return WG_VIDEO_FORMAT_NV12
;
206 case GST_VIDEO_FORMAT_UYVY
:
207 return WG_VIDEO_FORMAT_UYVY
;
208 case GST_VIDEO_FORMAT_YUY2
:
209 return WG_VIDEO_FORMAT_YUY2
;
210 case GST_VIDEO_FORMAT_YV12
:
211 return WG_VIDEO_FORMAT_YV12
;
212 case GST_VIDEO_FORMAT_YVYU
:
213 return WG_VIDEO_FORMAT_YVYU
;
215 return WG_VIDEO_FORMAT_UNKNOWN
;
219 static void wg_format_from_video_info(struct wg_format
*format
, const GstVideoInfo
*info
)
221 format
->major_type
= WG_MAJOR_TYPE_VIDEO
;
222 format
->u
.video
.format
= wg_video_format_from_gst(GST_VIDEO_INFO_FORMAT(info
));
223 format
->u
.video
.width
= GST_VIDEO_INFO_WIDTH(info
);
224 format
->u
.video
.height
= GST_VIDEO_INFO_HEIGHT(info
);
225 format
->u
.video
.fps_n
= GST_VIDEO_INFO_FPS_N(info
);
226 format
->u
.video
.fps_d
= GST_VIDEO_INFO_FPS_D(info
);
229 static void wg_format_from_caps_audio_mpeg(struct wg_format
*format
, const GstCaps
*caps
)
231 const GstStructure
*structure
= gst_caps_get_structure(caps
, 0);
232 gint layer
, channels
, rate
;
234 if (!gst_structure_get_int(structure
, "layer", &layer
))
236 GST_WARNING("Missing \"layer\" value.");
239 if (!gst_structure_get_int(structure
, "channels", &channels
))
241 GST_WARNING("Missing \"channels\" value.");
244 if (!gst_structure_get_int(structure
, "rate", &rate
))
246 GST_WARNING("Missing \"rate\" value.");
250 format
->major_type
= WG_MAJOR_TYPE_AUDIO
;
253 format
->u
.audio
.format
= WG_AUDIO_FORMAT_MPEG1_LAYER1
;
255 format
->u
.audio
.format
= WG_AUDIO_FORMAT_MPEG1_LAYER2
;
257 format
->u
.audio
.format
= WG_AUDIO_FORMAT_MPEG1_LAYER3
;
259 format
->u
.audio
.channels
= channels
;
260 format
->u
.audio
.rate
= rate
;
263 static void wg_format_from_caps_video_cinepak(struct wg_format
*format
, const GstCaps
*caps
)
265 const GstStructure
*structure
= gst_caps_get_structure(caps
, 0);
266 gint width
, height
, fps_n
, fps_d
;
268 if (!gst_structure_get_int(structure
, "width", &width
))
270 GST_WARNING("Missing \"width\" value.");
273 if (!gst_structure_get_int(structure
, "height", &height
))
275 GST_WARNING("Missing \"height\" value.");
278 if (!gst_structure_get_fraction(structure
, "framerate", &fps_n
, &fps_d
))
284 format
->major_type
= WG_MAJOR_TYPE_VIDEO
;
285 format
->u
.video
.format
= WG_VIDEO_FORMAT_CINEPAK
;
286 format
->u
.video
.width
= width
;
287 format
->u
.video
.height
= height
;
288 format
->u
.video
.fps_n
= fps_n
;
289 format
->u
.video
.fps_d
= fps_d
;
292 static void wg_format_from_caps(struct wg_format
*format
, const GstCaps
*caps
)
294 const GstStructure
*structure
= gst_caps_get_structure(caps
, 0);
295 const char *name
= gst_structure_get_name(structure
);
297 memset(format
, 0, sizeof(*format
));
299 if (!strcmp(name
, "audio/x-raw"))
303 if (gst_audio_info_from_caps(&info
, caps
))
304 wg_format_from_audio_info(format
, &info
);
306 else if (!strcmp(name
, "video/x-raw"))
310 if (gst_video_info_from_caps(&info
, caps
))
311 wg_format_from_video_info(format
, &info
);
313 else if (!strcmp(name
, "audio/mpeg"))
315 wg_format_from_caps_audio_mpeg(format
, caps
);
317 else if (!strcmp(name
, "video/x-cinepak"))
319 wg_format_from_caps_video_cinepak(format
, caps
);
323 gchar
*str
= gst_caps_to_string(caps
);
325 GST_FIXME("Unhandled caps %s.", str
);
330 static GstAudioFormat
wg_audio_format_to_gst(enum wg_audio_format format
)
334 case WG_AUDIO_FORMAT_U8
: return GST_AUDIO_FORMAT_U8
;
335 case WG_AUDIO_FORMAT_S16LE
: return GST_AUDIO_FORMAT_S16LE
;
336 case WG_AUDIO_FORMAT_S24LE
: return GST_AUDIO_FORMAT_S24LE
;
337 case WG_AUDIO_FORMAT_S32LE
: return GST_AUDIO_FORMAT_S32LE
;
338 case WG_AUDIO_FORMAT_F32LE
: return GST_AUDIO_FORMAT_F32LE
;
339 case WG_AUDIO_FORMAT_F64LE
: return GST_AUDIO_FORMAT_F64LE
;
340 default: return GST_AUDIO_FORMAT_UNKNOWN
;
344 static void wg_channel_mask_to_gst(GstAudioChannelPosition
*positions
, uint32_t mask
, uint32_t channel_count
)
346 const uint32_t orig_mask
= mask
;
350 static const GstAudioChannelPosition position_map
[] =
352 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT
,
353 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT
,
354 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER
,
355 GST_AUDIO_CHANNEL_POSITION_LFE1
,
356 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT
,
357 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
,
358 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
,
359 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
,
360 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER
,
361 GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT
,
362 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
,
363 GST_AUDIO_CHANNEL_POSITION_TOP_CENTER
,
364 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT
,
365 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER
,
366 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT
,
367 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT
,
368 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER
,
369 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT
,
372 for (i
= 0; i
< channel_count
; ++i
)
374 positions
[i
] = GST_AUDIO_CHANNEL_POSITION_NONE
;
375 if (BitScanForward(&bit
, mask
))
377 if (bit
< ARRAY_SIZE(position_map
))
378 positions
[i
] = position_map
[bit
];
380 GST_WARNING("Invalid channel mask %#x.\n", orig_mask
);
385 GST_WARNING("Incomplete channel mask %#x.\n", orig_mask
);
390 static GstCaps
*wg_format_to_caps_audio(const struct wg_format
*format
)
392 GstAudioChannelPosition positions
[32];
393 GstAudioFormat audio_format
;
396 if ((audio_format
= wg_audio_format_to_gst(format
->u
.audio
.format
)) == GST_AUDIO_FORMAT_UNKNOWN
)
399 wg_channel_mask_to_gst(positions
, format
->u
.audio
.channel_mask
, format
->u
.audio
.channels
);
400 gst_audio_info_set_format(&info
, audio_format
, format
->u
.audio
.rate
, format
->u
.audio
.channels
, positions
);
401 return gst_audio_info_to_caps(&info
);
404 static GstVideoFormat
wg_video_format_to_gst(enum wg_video_format format
)
408 case WG_VIDEO_FORMAT_BGRA
: return GST_VIDEO_FORMAT_BGRA
;
409 case WG_VIDEO_FORMAT_BGRx
: return GST_VIDEO_FORMAT_BGRx
;
410 case WG_VIDEO_FORMAT_BGR
: return GST_VIDEO_FORMAT_BGR
;
411 case WG_VIDEO_FORMAT_RGB15
: return GST_VIDEO_FORMAT_RGB15
;
412 case WG_VIDEO_FORMAT_RGB16
: return GST_VIDEO_FORMAT_RGB16
;
413 case WG_VIDEO_FORMAT_AYUV
: return GST_VIDEO_FORMAT_AYUV
;
414 case WG_VIDEO_FORMAT_I420
: return GST_VIDEO_FORMAT_I420
;
415 case WG_VIDEO_FORMAT_NV12
: return GST_VIDEO_FORMAT_NV12
;
416 case WG_VIDEO_FORMAT_UYVY
: return GST_VIDEO_FORMAT_UYVY
;
417 case WG_VIDEO_FORMAT_YUY2
: return GST_VIDEO_FORMAT_YUY2
;
418 case WG_VIDEO_FORMAT_YV12
: return GST_VIDEO_FORMAT_YV12
;
419 case WG_VIDEO_FORMAT_YVYU
: return GST_VIDEO_FORMAT_YVYU
;
420 default: return GST_VIDEO_FORMAT_UNKNOWN
;
424 static GstCaps
*wg_format_to_caps_video(const struct wg_format
*format
)
426 GstVideoFormat video_format
;
431 if ((video_format
= wg_video_format_to_gst(format
->u
.video
.format
)) == GST_VIDEO_FORMAT_UNKNOWN
)
434 gst_video_info_set_format(&info
, video_format
, format
->u
.video
.width
, format
->u
.video
.height
);
435 if ((caps
= gst_video_info_to_caps(&info
)))
437 /* Clear some fields that shouldn't prevent us from connecting. */
438 for (i
= 0; i
< gst_caps_get_size(caps
); ++i
)
440 gst_structure_remove_fields(gst_caps_get_structure(caps
, i
),
441 "framerate", "pixel-aspect-ratio", "colorimetry", "chroma-site", NULL
);
447 static GstCaps
*wg_format_to_caps(const struct wg_format
*format
)
449 switch (format
->major_type
)
451 case WG_MAJOR_TYPE_UNKNOWN
:
453 case WG_MAJOR_TYPE_AUDIO
:
454 return wg_format_to_caps_audio(format
);
455 case WG_MAJOR_TYPE_VIDEO
:
456 return wg_format_to_caps_video(format
);
462 static bool wg_format_compare(const struct wg_format
*a
, const struct wg_format
*b
)
464 if (a
->major_type
!= b
->major_type
)
467 switch (a
->major_type
)
469 case WG_MAJOR_TYPE_UNKNOWN
:
472 case WG_MAJOR_TYPE_AUDIO
:
473 return a
->u
.audio
.format
== b
->u
.audio
.format
474 && a
->u
.audio
.channels
== b
->u
.audio
.channels
475 && a
->u
.audio
.rate
== b
->u
.audio
.rate
;
477 case WG_MAJOR_TYPE_VIDEO
:
478 /* Do not compare FPS. */
479 return a
->u
.video
.format
== b
->u
.video
.format
480 && a
->u
.video
.width
== b
->u
.video
.width
481 && a
->u
.video
.height
== b
->u
.video
.height
;
488 static uint32_t CDECL
wg_parser_get_stream_count(struct wg_parser
*parser
)
490 return parser
->stream_count
;
493 static struct wg_parser_stream
* CDECL
wg_parser_get_stream(struct wg_parser
*parser
, uint32_t index
)
495 return parser
->streams
[index
];
498 static void CDECL
wg_parser_begin_flush(struct wg_parser
*parser
)
502 pthread_mutex_lock(&parser
->mutex
);
503 parser
->flushing
= true;
504 pthread_mutex_unlock(&parser
->mutex
);
506 for (i
= 0; i
< parser
->stream_count
; ++i
)
508 if (parser
->streams
[i
]->enabled
)
509 pthread_cond_signal(&parser
->streams
[i
]->event_cond
);
513 static void CDECL
wg_parser_end_flush(struct wg_parser
*parser
)
515 pthread_mutex_lock(&parser
->mutex
);
516 parser
->flushing
= false;
517 pthread_mutex_unlock(&parser
->mutex
);
520 static bool CDECL
wg_parser_get_read_request(struct wg_parser
*parser
,
521 void **data
, uint64_t *offset
, uint32_t *size
)
523 pthread_mutex_lock(&parser
->mutex
);
525 while (parser
->sink_connected
&& !parser
->read_request
.data
)
526 pthread_cond_wait(&parser
->read_cond
, &parser
->mutex
);
528 if (!parser
->sink_connected
)
530 pthread_mutex_unlock(&parser
->mutex
);
534 *data
= parser
->read_request
.data
;
535 *offset
= parser
->read_request
.offset
;
536 *size
= parser
->read_request
.size
;
538 pthread_mutex_unlock(&parser
->mutex
);
542 static void CDECL
wg_parser_complete_read_request(struct wg_parser
*parser
, bool ret
)
544 pthread_mutex_lock(&parser
->mutex
);
545 parser
->read_request
.done
= true;
546 parser
->read_request
.ret
= ret
;
547 parser
->read_request
.data
= NULL
;
548 pthread_mutex_unlock(&parser
->mutex
);
549 pthread_cond_signal(&parser
->read_done_cond
);
552 static void CDECL
wg_parser_set_unlimited_buffering(struct wg_parser
*parser
)
554 g_object_set(parser
->decodebin
, "max-size-buffers", G_MAXUINT
, NULL
);
555 g_object_set(parser
->decodebin
, "max-size-time", G_MAXUINT64
, NULL
);
556 g_object_set(parser
->decodebin
, "max-size-bytes", G_MAXUINT
, NULL
);
559 static void CDECL
wg_parser_stream_get_preferred_format(struct wg_parser_stream
*stream
, struct wg_format
*format
)
561 *format
= stream
->preferred_format
;
564 static void CDECL
wg_parser_stream_enable(struct wg_parser_stream
*stream
, const struct wg_format
*format
)
566 stream
->current_format
= *format
;
567 stream
->enabled
= true;
569 if (format
->major_type
== WG_MAJOR_TYPE_VIDEO
)
571 switch (format
->u
.video
.format
)
573 case WG_VIDEO_FORMAT_BGRA
:
574 case WG_VIDEO_FORMAT_BGRx
:
575 case WG_VIDEO_FORMAT_BGR
:
576 case WG_VIDEO_FORMAT_RGB15
:
577 case WG_VIDEO_FORMAT_RGB16
:
578 gst_util_set_object_arg(G_OBJECT(stream
->flip
), "method", "vertical-flip");
581 case WG_VIDEO_FORMAT_AYUV
:
582 case WG_VIDEO_FORMAT_I420
:
583 case WG_VIDEO_FORMAT_NV12
:
584 case WG_VIDEO_FORMAT_UYVY
:
585 case WG_VIDEO_FORMAT_YUY2
:
586 case WG_VIDEO_FORMAT_YV12
:
587 case WG_VIDEO_FORMAT_YVYU
:
588 case WG_VIDEO_FORMAT_UNKNOWN
:
589 case WG_VIDEO_FORMAT_CINEPAK
:
590 gst_util_set_object_arg(G_OBJECT(stream
->flip
), "method", "none");
595 gst_pad_push_event(stream
->my_sink
, gst_event_new_reconfigure());
598 static void CDECL
wg_parser_stream_disable(struct wg_parser_stream
*stream
)
600 stream
->enabled
= false;
603 static bool CDECL
wg_parser_stream_get_event(struct wg_parser_stream
*stream
, struct wg_parser_event
*event
)
605 struct wg_parser
*parser
= stream
->parser
;
607 pthread_mutex_lock(&parser
->mutex
);
609 while (!parser
->flushing
&& stream
->event
.type
== WG_PARSER_EVENT_NONE
)
610 pthread_cond_wait(&stream
->event_cond
, &parser
->mutex
);
612 if (parser
->flushing
)
614 pthread_mutex_unlock(&parser
->mutex
);
615 GST_DEBUG("Filter is flushing.\n");
619 *event
= stream
->event
;
621 if (stream
->event
.type
!= WG_PARSER_EVENT_BUFFER
)
623 stream
->event
.type
= WG_PARSER_EVENT_NONE
;
624 pthread_cond_signal(&stream
->event_empty_cond
);
626 pthread_mutex_unlock(&parser
->mutex
);
631 static bool CDECL
wg_parser_stream_copy_buffer(struct wg_parser_stream
*stream
,
632 void *data
, uint32_t offset
, uint32_t size
)
634 struct wg_parser
*parser
= stream
->parser
;
636 pthread_mutex_lock(&parser
->mutex
);
640 pthread_mutex_unlock(&parser
->mutex
);
644 assert(stream
->event
.type
== WG_PARSER_EVENT_BUFFER
);
645 assert(offset
< stream
->map_info
.size
);
646 assert(offset
+ size
<= stream
->map_info
.size
);
647 memcpy(data
, stream
->map_info
.data
+ offset
, size
);
649 pthread_mutex_unlock(&parser
->mutex
);
653 static void CDECL
wg_parser_stream_release_buffer(struct wg_parser_stream
*stream
)
655 struct wg_parser
*parser
= stream
->parser
;
657 pthread_mutex_lock(&parser
->mutex
);
659 assert(stream
->event
.type
== WG_PARSER_EVENT_BUFFER
);
661 gst_buffer_unmap(stream
->buffer
, &stream
->map_info
);
662 gst_buffer_unref(stream
->buffer
);
663 stream
->buffer
= NULL
;
664 stream
->event
.type
= WG_PARSER_EVENT_NONE
;
666 pthread_mutex_unlock(&parser
->mutex
);
667 pthread_cond_signal(&stream
->event_empty_cond
);
670 static uint64_t CDECL
wg_parser_stream_get_duration(struct wg_parser_stream
*stream
)
672 return stream
->duration
;
675 static bool CDECL
wg_parser_stream_seek(struct wg_parser_stream
*stream
, double rate
,
676 uint64_t start_pos
, uint64_t stop_pos
, DWORD start_flags
, DWORD stop_flags
)
678 GstSeekType start_type
= GST_SEEK_TYPE_SET
, stop_type
= GST_SEEK_TYPE_SET
;
679 GstSeekFlags flags
= 0;
681 if (start_flags
& AM_SEEKING_SeekToKeyFrame
)
682 flags
|= GST_SEEK_FLAG_KEY_UNIT
;
683 if (start_flags
& AM_SEEKING_Segment
)
684 flags
|= GST_SEEK_FLAG_SEGMENT
;
685 if (!(start_flags
& AM_SEEKING_NoFlush
))
686 flags
|= GST_SEEK_FLAG_FLUSH
;
688 if ((start_flags
& AM_SEEKING_PositioningBitsMask
) == AM_SEEKING_NoPositioning
)
689 start_type
= GST_SEEK_TYPE_NONE
;
690 if ((stop_flags
& AM_SEEKING_PositioningBitsMask
) == AM_SEEKING_NoPositioning
)
691 stop_type
= GST_SEEK_TYPE_NONE
;
693 return gst_pad_push_event(stream
->my_sink
, gst_event_new_seek(rate
,
694 GST_FORMAT_TIME
, flags
, start_type
, start_pos
* 100, stop_type
, stop_pos
* 100));
697 static void CDECL
wg_parser_stream_notify_qos(struct wg_parser_stream
*stream
,
698 bool underflow
, double proportion
, int64_t diff
, uint64_t timestamp
)
700 GstClockTime stream_time
;
703 /* We return timestamps in stream time, i.e. relative to the start of the
704 * file (or other medium), but gst_event_new_qos() expects the timestamp in
706 stream_time
= gst_segment_to_running_time(&stream
->segment
, GST_FORMAT_TIME
, timestamp
* 100);
707 if (stream_time
== -1)
709 /* This can happen legitimately if the sample falls outside of the
710 * segment bounds. GStreamer elements shouldn't present the sample in
711 * that case, but DirectShow doesn't care. */
712 GST_LOG("Ignoring QoS event.\n");
716 if (!(event
= gst_event_new_qos(underflow
? GST_QOS_TYPE_UNDERFLOW
: GST_QOS_TYPE_OVERFLOW
,
717 proportion
, diff
* 100, stream_time
)))
718 GST_ERROR("Failed to create QOS event.\n");
719 gst_pad_push_event(stream
->my_sink
, event
);
722 static GstAutoplugSelectResult
autoplug_select_cb(GstElement
*bin
, GstPad
*pad
,
723 GstCaps
*caps
, GstElementFactory
*fact
, gpointer user
)
725 const char *name
= gst_element_factory_get_longname(fact
);
727 GST_INFO("Using \"%s\".", name
);
729 if (strstr(name
, "Player protection"))
731 GST_WARNING("Blacklisted a/52 decoder because it only works in Totem.");
732 return GST_AUTOPLUG_SELECT_SKIP
;
734 if (!strcmp(name
, "Fluendo Hardware Accelerated Video Decoder"))
736 GST_WARNING("Disabled video acceleration since it breaks in wine.");
737 return GST_AUTOPLUG_SELECT_SKIP
;
739 return GST_AUTOPLUG_SELECT_TRY
;
742 static void no_more_pads_cb(GstElement
*element
, gpointer user
)
744 struct wg_parser
*parser
= user
;
746 GST_DEBUG("parser %p.", parser
);
748 pthread_mutex_lock(&parser
->mutex
);
749 parser
->no_more_pads
= true;
750 pthread_mutex_unlock(&parser
->mutex
);
751 pthread_cond_signal(&parser
->init_cond
);
754 static GstFlowReturn
queue_stream_event(struct wg_parser_stream
*stream
,
755 const struct wg_parser_event
*event
, GstBuffer
*buffer
)
757 struct wg_parser
*parser
= stream
->parser
;
759 /* Unlike request_buffer_src() [q.v.], we need to watch for GStreamer
760 * flushes here. The difference is that we can be blocked by the streaming
761 * thread not running (or itself flushing on the DirectShow side).
762 * request_buffer_src() can only be blocked by the upstream source, and that
763 * is solved by flushing the upstream source. */
765 pthread_mutex_lock(&parser
->mutex
);
766 while (!stream
->flushing
&& stream
->event
.type
!= WG_PARSER_EVENT_NONE
)
767 pthread_cond_wait(&stream
->event_empty_cond
, &parser
->mutex
);
768 if (stream
->flushing
)
770 pthread_mutex_unlock(&parser
->mutex
);
771 GST_DEBUG("Filter is flushing; discarding event.");
772 return GST_FLOW_FLUSHING
;
776 assert(GST_IS_BUFFER(buffer
));
777 if (!gst_buffer_map(buffer
, &stream
->map_info
, GST_MAP_READ
))
779 pthread_mutex_unlock(&parser
->mutex
);
780 GST_ERROR("Failed to map buffer.\n");
781 return GST_FLOW_ERROR
;
784 stream
->event
= *event
;
785 stream
->buffer
= buffer
;
786 pthread_mutex_unlock(&parser
->mutex
);
787 pthread_cond_signal(&stream
->event_cond
);
788 GST_LOG("Event queued.");
792 static gboolean
sink_event_cb(GstPad
*pad
, GstObject
*parent
, GstEvent
*event
)
794 struct wg_parser_stream
*stream
= gst_pad_get_element_private(pad
);
795 struct wg_parser
*parser
= stream
->parser
;
797 GST_LOG("stream %p, type \"%s\".", stream
, GST_EVENT_TYPE_NAME(event
));
801 case GST_EVENT_SEGMENT
:
804 struct wg_parser_event stream_event
;
805 const GstSegment
*segment
;
807 gst_event_parse_segment(event
, &segment
);
809 if (segment
->format
!= GST_FORMAT_TIME
)
811 GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(segment
->format
));
815 gst_segment_copy_into(segment
, &stream
->segment
);
817 stream_event
.type
= WG_PARSER_EVENT_SEGMENT
;
818 stream_event
.u
.segment
.position
= segment
->position
/ 100;
819 stream_event
.u
.segment
.stop
= segment
->stop
/ 100;
820 stream_event
.u
.segment
.rate
= segment
->rate
* segment
->applied_rate
;
821 queue_stream_event(stream
, &stream_event
, NULL
);
828 struct wg_parser_event stream_event
;
830 stream_event
.type
= WG_PARSER_EVENT_EOS
;
831 queue_stream_event(stream
, &stream_event
, NULL
);
835 pthread_mutex_lock(&parser
->mutex
);
837 pthread_mutex_unlock(&parser
->mutex
);
838 pthread_cond_signal(&parser
->init_cond
);
842 case GST_EVENT_FLUSH_START
:
845 pthread_mutex_lock(&parser
->mutex
);
847 stream
->flushing
= true;
848 pthread_cond_signal(&stream
->event_empty_cond
);
850 if (stream
->event
.type
== WG_PARSER_EVENT_BUFFER
)
852 gst_buffer_unmap(stream
->buffer
, &stream
->map_info
);
853 gst_buffer_unref(stream
->buffer
);
854 stream
->buffer
= NULL
;
856 stream
->event
.type
= WG_PARSER_EVENT_NONE
;
858 pthread_mutex_unlock(&parser
->mutex
);
862 case GST_EVENT_FLUSH_STOP
:
866 gst_event_parse_flush_stop(event
, &reset_time
);
869 gst_segment_init(&stream
->segment
, GST_FORMAT_UNDEFINED
);
873 pthread_mutex_lock(&parser
->mutex
);
874 stream
->flushing
= false;
875 pthread_mutex_unlock(&parser
->mutex
);
884 gst_event_parse_caps(event
, &caps
);
885 pthread_mutex_lock(&parser
->mutex
);
886 wg_format_from_caps(&stream
->preferred_format
, caps
);
887 stream
->has_caps
= true;
888 pthread_mutex_unlock(&parser
->mutex
);
889 pthread_cond_signal(&parser
->init_cond
);
894 GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event
));
896 gst_event_unref(event
);
900 static GstFlowReturn
sink_chain_cb(GstPad
*pad
, GstObject
*parent
, GstBuffer
*buffer
)
902 struct wg_parser_stream
*stream
= gst_pad_get_element_private(pad
);
903 struct wg_parser_event stream_event
;
906 GST_LOG("stream %p, buffer %p.", stream
, buffer
);
908 if (!stream
->enabled
)
910 gst_buffer_unref(buffer
);
914 stream_event
.type
= WG_PARSER_EVENT_BUFFER
;
916 /* FIXME: Should we use gst_segment_to_stream_time_full()? Under what
917 * circumstances is the stream time not equal to the buffer PTS? Note that
918 * this will need modification to wg_parser_stream_notify_qos() as well. */
920 if ((stream_event
.u
.buffer
.has_pts
= GST_BUFFER_PTS_IS_VALID(buffer
)))
921 stream_event
.u
.buffer
.pts
= GST_BUFFER_PTS(buffer
) / 100;
922 if ((stream_event
.u
.buffer
.has_duration
= GST_BUFFER_DURATION_IS_VALID(buffer
)))
923 stream_event
.u
.buffer
.duration
= GST_BUFFER_DURATION(buffer
) / 100;
924 stream_event
.u
.buffer
.discontinuity
= GST_BUFFER_FLAG_IS_SET(buffer
, GST_BUFFER_FLAG_DISCONT
);
925 stream_event
.u
.buffer
.preroll
= GST_BUFFER_FLAG_IS_SET(buffer
, GST_BUFFER_FLAG_LIVE
);
926 stream_event
.u
.buffer
.delta
= GST_BUFFER_FLAG_IS_SET(buffer
, GST_BUFFER_FLAG_DELTA_UNIT
);
927 stream_event
.u
.buffer
.size
= gst_buffer_get_size(buffer
);
929 /* Transfer our reference to the buffer to the stream object. */
930 if ((ret
= queue_stream_event(stream
, &stream_event
, buffer
)) != GST_FLOW_OK
)
931 gst_buffer_unref(buffer
);
935 static gboolean
sink_query_cb(GstPad
*pad
, GstObject
*parent
, GstQuery
*query
)
937 struct wg_parser_stream
*stream
= gst_pad_get_element_private(pad
);
939 GST_LOG("stream %p, type \"%s\".", stream
, gst_query_type_get_name(query
->type
));
945 GstCaps
*caps
, *filter
, *temp
;
947 gst_query_parse_caps(query
, &filter
);
950 caps
= wg_format_to_caps(&stream
->current_format
);
952 caps
= gst_caps_new_any();
958 temp
= gst_caps_intersect(caps
, filter
);
959 gst_caps_unref(caps
);
963 gst_query_set_caps_result(query
, caps
);
964 gst_caps_unref(caps
);
968 case GST_QUERY_ACCEPT_CAPS
:
970 struct wg_format format
;
974 if (!stream
->enabled
)
976 gst_query_set_accept_caps_result(query
, TRUE
);
980 gst_query_parse_accept_caps(query
, &caps
);
981 wg_format_from_caps(&format
, caps
);
982 ret
= wg_format_compare(&format
, &stream
->current_format
);
983 if (!ret
&& gst_debug_category_get_threshold(GST_CAT_DEFAULT
) >= GST_LEVEL_WARNING
)
985 gchar
*str
= gst_caps_to_string(caps
);
986 GST_WARNING("Rejecting caps \"%s\".", str
);
989 gst_query_set_accept_caps_result(query
, ret
);
994 return gst_pad_query_default (pad
, parent
, query
);
998 static GstElement
*create_element(const char *name
, const char *plugin_set
)
1000 GstElement
*element
;
1002 if (!(element
= gst_element_factory_make(name
, NULL
)))
1003 fprintf(stderr
, "winegstreamer: failed to create %s, are %u-bit GStreamer \"%s\" plugins installed?\n",
1004 name
, 8 * (unsigned int)sizeof(void *), plugin_set
);
1008 static struct wg_parser_stream
*create_stream(struct wg_parser
*parser
)
1010 struct wg_parser_stream
*stream
, **new_array
;
1013 if (!(new_array
= realloc(parser
->streams
, (parser
->stream_count
+ 1) * sizeof(*parser
->streams
))))
1015 parser
->streams
= new_array
;
1017 if (!(stream
= calloc(1, sizeof(*stream
))))
1020 gst_segment_init(&stream
->segment
, GST_FORMAT_UNDEFINED
);
1022 stream
->parser
= parser
;
1023 pthread_cond_init(&stream
->event_cond
, NULL
);
1024 pthread_cond_init(&stream
->event_empty_cond
, NULL
);
1026 sprintf(pad_name
, "qz_sink_%u", parser
->stream_count
);
1027 stream
->my_sink
= gst_pad_new(pad_name
, GST_PAD_SINK
);
1028 gst_pad_set_element_private(stream
->my_sink
, stream
);
1029 gst_pad_set_chain_function(stream
->my_sink
, sink_chain_cb
);
1030 gst_pad_set_event_function(stream
->my_sink
, sink_event_cb
);
1031 gst_pad_set_query_function(stream
->my_sink
, sink_query_cb
);
1033 parser
->streams
[parser
->stream_count
++] = stream
;
1037 static void pad_added_cb(GstElement
*element
, GstPad
*pad
, gpointer user
)
1039 struct wg_parser
*parser
= user
;
1040 struct wg_parser_stream
*stream
;
1045 GST_LOG("parser %p, element %p, pad %p.", parser
, element
, pad
);
1047 if (gst_pad_is_linked(pad
))
1050 caps
= gst_pad_query_caps(pad
, NULL
);
1051 name
= gst_structure_get_name(gst_caps_get_structure(caps
, 0));
1053 if (!(stream
= create_stream(parser
)))
1056 if (!strcmp(name
, "video/x-raw"))
1058 GstElement
*deinterlace
, *vconv
, *flip
, *vconv2
;
1060 /* DirectShow can express interlaced video, but downstream filters can't
1061 * necessarily consume it. In particular, the video renderer can't. */
1062 if (!(deinterlace
= create_element("deinterlace", "good")))
1065 /* decodebin considers many YUV formats to be "raw", but some quartz
1066 * filters can't handle those. Also, videoflip can't handle all "raw"
1067 * formats either. Add a videoconvert to swap color spaces. */
1068 if (!(vconv
= create_element("videoconvert", "base")))
1071 /* GStreamer outputs RGB video top-down, but DirectShow expects bottom-up. */
1072 if (!(flip
= create_element("videoflip", "good")))
1075 /* videoflip does not support 15 and 16-bit RGB so add a second videoconvert
1076 * to do the final conversion. */
1077 if (!(vconv2
= create_element("videoconvert", "base")))
1080 /* The bin takes ownership of these elements. */
1081 gst_bin_add(GST_BIN(parser
->container
), deinterlace
);
1082 gst_element_sync_state_with_parent(deinterlace
);
1083 gst_bin_add(GST_BIN(parser
->container
), vconv
);
1084 gst_element_sync_state_with_parent(vconv
);
1085 gst_bin_add(GST_BIN(parser
->container
), flip
);
1086 gst_element_sync_state_with_parent(flip
);
1087 gst_bin_add(GST_BIN(parser
->container
), vconv2
);
1088 gst_element_sync_state_with_parent(vconv2
);
1090 gst_element_link(deinterlace
, vconv
);
1091 gst_element_link(vconv
, flip
);
1092 gst_element_link(flip
, vconv2
);
1094 stream
->post_sink
= gst_element_get_static_pad(deinterlace
, "sink");
1095 stream
->post_src
= gst_element_get_static_pad(vconv2
, "src");
1096 stream
->flip
= flip
;
1098 else if (!strcmp(name
, "audio/x-raw"))
1100 GstElement
*convert
;
1102 /* Currently our dsound can't handle 64-bit formats or all
1103 * surround-sound configurations. Native dsound can't always handle
1104 * 64-bit formats either. Add an audioconvert to allow changing bit
1105 * depth and channel count. */
1106 if (!(convert
= create_element("audioconvert", "base")))
1109 gst_bin_add(GST_BIN(parser
->container
), convert
);
1110 gst_element_sync_state_with_parent(convert
);
1112 stream
->post_sink
= gst_element_get_static_pad(convert
, "sink");
1113 stream
->post_src
= gst_element_get_static_pad(convert
, "src");
1116 if (stream
->post_sink
)
1118 if ((ret
= gst_pad_link(pad
, stream
->post_sink
)) < 0)
1120 GST_ERROR("Failed to link decodebin source pad to post-processing elements, error %s.",
1121 gst_pad_link_get_name(ret
));
1122 gst_object_unref(stream
->post_sink
);
1123 stream
->post_sink
= NULL
;
1127 if ((ret
= gst_pad_link(stream
->post_src
, stream
->my_sink
)) < 0)
1129 GST_ERROR("Failed to link post-processing elements to our sink pad, error %s.",
1130 gst_pad_link_get_name(ret
));
1131 gst_object_unref(stream
->post_src
);
1132 stream
->post_src
= NULL
;
1133 gst_object_unref(stream
->post_sink
);
1134 stream
->post_sink
= NULL
;
1138 else if ((ret
= gst_pad_link(pad
, stream
->my_sink
)) < 0)
1140 GST_ERROR("Failed to link decodebin source pad to our sink pad, error %s.",
1141 gst_pad_link_get_name(ret
));
1145 gst_pad_set_active(stream
->my_sink
, 1);
1146 gst_object_ref(stream
->their_src
= pad
);
1148 gst_caps_unref(caps
);
1151 static void pad_removed_cb(GstElement
*element
, GstPad
*pad
, gpointer user
)
1153 struct wg_parser
*parser
= user
;
1157 GST_LOG("parser %p, element %p, pad %p.", parser
, element
, pad
);
1159 for (i
= 0; i
< parser
->stream_count
; ++i
)
1161 struct wg_parser_stream
*stream
= parser
->streams
[i
];
1163 if (stream
->their_src
== pad
)
1165 if (stream
->post_sink
)
1166 gst_pad_unlink(stream
->their_src
, stream
->post_sink
);
1168 gst_pad_unlink(stream
->their_src
, stream
->my_sink
);
1169 gst_object_unref(stream
->their_src
);
1170 stream
->their_src
= NULL
;
1175 name
= gst_pad_get_name(pad
);
1176 GST_WARNING("No pin matching pad \"%s\" found.", name
);
1180 static GstFlowReturn
src_getrange_cb(GstPad
*pad
, GstObject
*parent
,
1181 guint64 offset
, guint size
, GstBuffer
**buffer
)
1183 struct wg_parser
*parser
= gst_pad_get_element_private(pad
);
1184 GstBuffer
*new_buffer
= NULL
;
1185 GstMapInfo map_info
;
1188 GST_LOG("pad %p, offset %" G_GINT64_MODIFIER
"u, length %u, buffer %p.", pad
, offset
, size
, *buffer
);
1190 if (offset
== GST_BUFFER_OFFSET_NONE
)
1191 offset
= parser
->next_pull_offset
;
1192 parser
->next_pull_offset
= offset
+ size
;
1193 if (offset
>= parser
->file_size
)
1194 return GST_FLOW_EOS
;
1195 if (offset
+ size
>= parser
->file_size
)
1196 size
= parser
->file_size
- offset
;
1199 *buffer
= new_buffer
= gst_buffer_new_and_alloc(size
);
1201 gst_buffer_map(*buffer
, &map_info
, GST_MAP_WRITE
);
1203 pthread_mutex_lock(&parser
->mutex
);
1205 assert(!parser
->read_request
.data
);
1206 parser
->read_request
.data
= map_info
.data
;
1207 parser
->read_request
.offset
= offset
;
1208 parser
->read_request
.size
= size
;
1209 parser
->read_request
.done
= false;
1210 pthread_cond_signal(&parser
->read_cond
);
1212 /* Note that we don't unblock this wait on GST_EVENT_FLUSH_START. We expect
1213 * the upstream pin to flush if necessary. We should never be blocked on
1214 * read_thread() not running. */
1216 while (!parser
->read_request
.done
)
1217 pthread_cond_wait(&parser
->read_done_cond
, &parser
->mutex
);
1219 ret
= parser
->read_request
.ret
;
1221 pthread_mutex_unlock(&parser
->mutex
);
1223 gst_buffer_unmap(*buffer
, &map_info
);
1225 GST_LOG("Request returned %d.", ret
);
1227 if (!ret
&& new_buffer
)
1228 gst_buffer_unref(new_buffer
);
1230 return ret
? GST_FLOW_OK
: GST_FLOW_ERROR
;
1233 static gboolean
src_query_cb(GstPad
*pad
, GstObject
*parent
, GstQuery
*query
)
1235 struct wg_parser
*parser
= gst_pad_get_element_private(pad
);
1238 GST_LOG("parser %p, type %s.", parser
, GST_QUERY_TYPE_NAME(query
));
1240 switch (GST_QUERY_TYPE(query
))
1242 case GST_QUERY_DURATION
:
1243 gst_query_parse_duration(query
, &format
, NULL
);
1244 if (format
== GST_FORMAT_PERCENT
)
1246 gst_query_set_duration(query
, GST_FORMAT_PERCENT
, GST_FORMAT_PERCENT_MAX
);
1249 else if (format
== GST_FORMAT_BYTES
)
1251 gst_query_set_duration(query
, GST_FORMAT_BYTES
, parser
->file_size
);
1256 case GST_QUERY_SEEKING
:
1257 gst_query_parse_seeking (query
, &format
, NULL
, NULL
, NULL
);
1258 if (format
!= GST_FORMAT_BYTES
)
1260 GST_WARNING("Cannot seek using format \"%s\".", gst_format_get_name(format
));
1263 gst_query_set_seeking(query
, GST_FORMAT_BYTES
, 1, 0, parser
->file_size
);
1266 case GST_QUERY_SCHEDULING
:
1267 gst_query_set_scheduling(query
, GST_SCHEDULING_FLAG_SEEKABLE
, 1, -1, 0);
1268 gst_query_add_scheduling_mode(query
, GST_PAD_MODE_PUSH
);
1269 gst_query_add_scheduling_mode(query
, GST_PAD_MODE_PULL
);
1273 GST_WARNING("Unhandled query type %s.", GST_QUERY_TYPE_NAME(query
));
1278 static void *push_data(void *arg
)
1280 struct wg_parser
*parser
= arg
;
1284 GST_DEBUG("Starting push thread.");
1286 if (!(buffer
= gst_buffer_new_allocate(NULL
, 16384, NULL
)))
1288 GST_ERROR("Failed to allocate memory.");
1292 max_size
= parser
->stop_offset
? parser
->stop_offset
: parser
->file_size
;
1299 if (parser
->next_offset
>= max_size
)
1301 size
= min(16384, max_size
- parser
->next_offset
);
1303 if ((ret
= src_getrange_cb(parser
->my_src
, NULL
, parser
->next_offset
, size
, &buffer
)) < 0)
1305 GST_ERROR("Failed to read data, ret %s.", gst_flow_get_name(ret
));
1309 parser
->next_offset
+= size
;
1311 buffer
->duration
= buffer
->pts
= -1;
1312 if ((ret
= gst_pad_push(parser
->my_src
, buffer
)) < 0)
1314 GST_ERROR("Failed to push data, ret %s.", gst_flow_get_name(ret
));
1319 gst_buffer_unref(buffer
);
1321 gst_pad_push_event(parser
->my_src
, gst_event_new_eos());
1323 GST_DEBUG("Stopping push thread.");
1328 static gboolean
activate_push(GstPad
*pad
, gboolean activate
)
1330 struct wg_parser
*parser
= gst_pad_get_element_private(pad
);
1334 if (parser
->push_thread
)
1336 pthread_join(parser
->push_thread
, NULL
);
1337 parser
->push_thread
= 0;
1340 else if (!parser
->push_thread
)
1344 if ((ret
= pthread_create(&parser
->push_thread
, NULL
, push_data
, parser
)))
1346 GST_ERROR("Failed to create push thread: %s", strerror(errno
));
1347 parser
->push_thread
= 0;
1354 static gboolean
src_activate_mode_cb(GstPad
*pad
, GstObject
*parent
, GstPadMode mode
, gboolean activate
)
1356 struct wg_parser
*parser
= gst_pad_get_element_private(pad
);
1358 GST_DEBUG("%s source pad for parser %p in %s mode.",
1359 activate
? "Activating" : "Deactivating", parser
, gst_pad_mode_get_name(mode
));
1363 case GST_PAD_MODE_PULL
:
1365 case GST_PAD_MODE_PUSH
:
1366 return activate_push(pad
, activate
);
1367 case GST_PAD_MODE_NONE
:
1373 static GstBusSyncReply
bus_handler_cb(GstBus
*bus
, GstMessage
*msg
, gpointer user
)
1375 struct wg_parser
*parser
= user
;
1376 gchar
*dbg_info
= NULL
;
1379 GST_DEBUG("parser %p, message type %s.", parser
, GST_MESSAGE_TYPE_NAME(msg
));
1383 case GST_MESSAGE_ERROR
:
1384 gst_message_parse_error(msg
, &err
, &dbg_info
);
1385 fprintf(stderr
, "winegstreamer error: %s: %s\n", GST_OBJECT_NAME(msg
->src
), err
->message
);
1386 fprintf(stderr
, "winegstreamer error: %s: %s\n", GST_OBJECT_NAME(msg
->src
), dbg_info
);
1389 pthread_mutex_lock(&parser
->mutex
);
1390 parser
->error
= true;
1391 pthread_mutex_unlock(&parser
->mutex
);
1392 pthread_cond_signal(&parser
->init_cond
);
1395 case GST_MESSAGE_WARNING
:
1396 gst_message_parse_warning(msg
, &err
, &dbg_info
);
1397 fprintf(stderr
, "winegstreamer warning: %s: %s\n", GST_OBJECT_NAME(msg
->src
), err
->message
);
1398 fprintf(stderr
, "winegstreamer warning: %s: %s\n", GST_OBJECT_NAME(msg
->src
), dbg_info
);
1403 case GST_MESSAGE_DURATION_CHANGED
:
1404 pthread_mutex_lock(&parser
->mutex
);
1405 parser
->has_duration
= true;
1406 pthread_mutex_unlock(&parser
->mutex
);
1407 pthread_cond_signal(&parser
->init_cond
);
1413 gst_message_unref(msg
);
1414 return GST_BUS_DROP
;
1417 static gboolean
src_perform_seek(struct wg_parser
*parser
, GstEvent
*event
)
1419 BOOL thread
= !!parser
->push_thread
;
1420 GstSeekType cur_type
, stop_type
;
1421 GstFormat seek_format
;
1422 GstEvent
*flush_event
;
1428 gst_event_parse_seek(event
, &rate
, &seek_format
, &flags
,
1429 &cur_type
, &cur
, &stop_type
, &stop
);
1431 if (seek_format
!= GST_FORMAT_BYTES
)
1433 GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(seek_format
));
1437 seqnum
= gst_event_get_seqnum(event
);
1439 /* send flush start */
1440 if (flags
& GST_SEEK_FLAG_FLUSH
)
1442 flush_event
= gst_event_new_flush_start();
1443 gst_event_set_seqnum(flush_event
, seqnum
);
1444 gst_pad_push_event(parser
->my_src
, flush_event
);
1446 gst_pad_set_active(parser
->my_src
, 1);
1449 parser
->next_offset
= parser
->start_offset
= cur
;
1451 /* and prepare to continue streaming */
1452 if (flags
& GST_SEEK_FLAG_FLUSH
)
1454 flush_event
= gst_event_new_flush_stop(TRUE
);
1455 gst_event_set_seqnum(flush_event
, seqnum
);
1456 gst_pad_push_event(parser
->my_src
, flush_event
);
1458 gst_pad_set_active(parser
->my_src
, 1);
1464 static gboolean
src_event_cb(GstPad
*pad
, GstObject
*parent
, GstEvent
*event
)
1466 struct wg_parser
*parser
= gst_pad_get_element_private(pad
);
1467 gboolean ret
= TRUE
;
1469 GST_LOG("parser %p, type \"%s\".", parser
, GST_EVENT_TYPE_NAME(event
));
1471 switch (event
->type
)
1473 case GST_EVENT_SEEK
:
1474 ret
= src_perform_seek(parser
, event
);
1477 case GST_EVENT_FLUSH_START
:
1478 case GST_EVENT_FLUSH_STOP
:
1480 case GST_EVENT_RECONFIGURE
:
1484 GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event
));
1488 gst_event_unref(event
);
1492 static HRESULT CDECL
wg_parser_connect(struct wg_parser
*parser
, uint64_t file_size
)
1494 GstStaticPadTemplate src_template
= GST_STATIC_PAD_TEMPLATE("quartz_src",
1495 GST_PAD_SRC
, GST_PAD_ALWAYS
, GST_STATIC_CAPS_ANY
);
1498 parser
->file_size
= file_size
;
1499 parser
->sink_connected
= true;
1503 parser
->bus
= gst_bus_new();
1504 gst_bus_set_sync_handler(parser
->bus
, bus_handler_cb
, parser
, NULL
);
1507 parser
->container
= gst_bin_new(NULL
);
1508 gst_element_set_bus(parser
->container
, parser
->bus
);
1510 parser
->my_src
= gst_pad_new_from_static_template(&src_template
, "quartz-src");
1511 gst_pad_set_getrange_function(parser
->my_src
, src_getrange_cb
);
1512 gst_pad_set_query_function(parser
->my_src
, src_query_cb
);
1513 gst_pad_set_activatemode_function(parser
->my_src
, src_activate_mode_cb
);
1514 gst_pad_set_event_function(parser
->my_src
, src_event_cb
);
1515 gst_pad_set_element_private(parser
->my_src
, parser
);
1517 parser
->start_offset
= parser
->next_offset
= parser
->stop_offset
= 0;
1518 parser
->next_pull_offset
= 0;
1520 if (!parser
->init_gst(parser
))
1523 pthread_mutex_lock(&parser
->mutex
);
1525 for (i
= 0; i
< parser
->stream_count
; ++i
)
1527 struct wg_parser_stream
*stream
= parser
->streams
[i
];
1528 gint64 duration
, byte_length
;
1530 while (!stream
->has_caps
&& !parser
->error
)
1531 pthread_cond_wait(&parser
->init_cond
, &parser
->mutex
);
1533 /* GStreamer doesn't actually provide any guarantees about when duration
1534 * is available, even for seekable streams. It's basically built for
1535 * applications that don't care, e.g. movie players that can display
1536 * a duration once it's available, and update it visually if a better
1537 * estimate is found. This doesn't really match well with DirectShow or
1538 * Media Foundation, which both expect duration to be available
1539 * immediately on connecting, so we have to use some complex heuristics
1540 * to try to actually get a usable duration.
1542 * Some elements (avidemux, wavparse, qtdemux) record duration almost
1543 * immediately, before fixing caps. Such elements don't send
1544 * duration-changed messages. Therefore always try querying duration
1545 * after caps have been found.
1547 * Some elements (mpegaudioparse) send duration-changed. In the case of
1548 * a mp3 stream without seek tables it will not be sent immediately, but
1549 * only after enough frames have been parsed to form an estimate. They
1550 * may send it multiple times with increasingly accurate estimates, but
1551 * unfortunately we have no way of knowing whether another estimate will
1552 * be sent, so we always take the first one. We assume that if the
1553 * duration is not immediately available then the element will always
1554 * send duration-changed.
1561 pthread_mutex_unlock(&parser
->mutex
);
1564 if (gst_pad_query_duration(stream
->their_src
, GST_FORMAT_TIME
, &duration
))
1566 stream
->duration
= duration
/ 100;
1570 GST_INFO("Failed to query time duration; trying to convert from byte length.\n");
1572 /* To accurately get a duration for the stream, we want to only
1573 * consider the length of that stream. Hence, query for the pad
1574 * duration, instead of using the file duration. */
1575 if (gst_pad_query_duration(stream
->their_src
, GST_FORMAT_BYTES
, &byte_length
)
1576 && gst_pad_query_convert(stream
->their_src
, GST_FORMAT_BYTES
, byte_length
,
1577 GST_FORMAT_TIME
, &duration
))
1579 stream
->duration
= duration
/ 100;
1584 stream
->duration
= 0;
1585 GST_WARNING("Failed to query duration.\n");
1589 /* Elements based on GstBaseParse send duration-changed before
1590 * actually updating the duration in GStreamer versions prior
1591 * to 1.17.1. See <gstreamer.git:d28e0b4147fe7073b2>. So after
1592 * receiving duration-changed we have to continue polling until
1593 * the query succeeds. */
1594 if (parser
->has_duration
)
1596 pthread_mutex_unlock(&parser
->mutex
);
1598 pthread_mutex_lock(&parser
->mutex
);
1602 pthread_cond_wait(&parser
->init_cond
, &parser
->mutex
);
1607 pthread_mutex_unlock(&parser
->mutex
);
1609 parser
->next_offset
= 0;
1613 static void free_stream(struct wg_parser_stream
*stream
)
1615 if (stream
->their_src
)
1617 if (stream
->post_sink
)
1619 gst_pad_unlink(stream
->their_src
, stream
->post_sink
);
1620 gst_pad_unlink(stream
->post_src
, stream
->my_sink
);
1621 gst_object_unref(stream
->post_src
);
1622 gst_object_unref(stream
->post_sink
);
1623 stream
->post_src
= stream
->post_sink
= NULL
;
1626 gst_pad_unlink(stream
->their_src
, stream
->my_sink
);
1627 gst_object_unref(stream
->their_src
);
1629 gst_object_unref(stream
->my_sink
);
1631 pthread_cond_destroy(&stream
->event_cond
);
1632 pthread_cond_destroy(&stream
->event_empty_cond
);
1637 static void CDECL
wg_parser_disconnect(struct wg_parser
*parser
)
1641 /* Unblock all of our streams. */
1642 pthread_mutex_lock(&parser
->mutex
);
1643 for (i
= 0; i
< parser
->stream_count
; ++i
)
1645 parser
->streams
[i
]->flushing
= true;
1646 pthread_cond_signal(&parser
->streams
[i
]->event_empty_cond
);
1648 pthread_mutex_unlock(&parser
->mutex
);
1650 gst_element_set_state(parser
->container
, GST_STATE_NULL
);
1651 gst_pad_unlink(parser
->my_src
, parser
->their_sink
);
1652 gst_object_unref(parser
->my_src
);
1653 gst_object_unref(parser
->their_sink
);
1654 parser
->my_src
= parser
->their_sink
= NULL
;
1656 pthread_mutex_lock(&parser
->mutex
);
1657 parser
->sink_connected
= false;
1658 pthread_mutex_unlock(&parser
->mutex
);
1659 pthread_cond_signal(&parser
->read_cond
);
1661 for (i
= 0; i
< parser
->stream_count
; ++i
)
1662 free_stream(parser
->streams
[i
]);
1664 parser
->stream_count
= 0;
1665 free(parser
->streams
);
1666 parser
->streams
= NULL
;
1668 gst_element_set_bus(parser
->container
, NULL
);
1669 gst_object_unref(parser
->container
);
1670 parser
->container
= NULL
;
1673 static BOOL
decodebin_parser_init_gst(struct wg_parser
*parser
)
1675 GstElement
*element
;
1678 if (!(element
= create_element("decodebin", "base")))
1681 gst_bin_add(GST_BIN(parser
->container
), element
);
1682 parser
->decodebin
= element
;
1684 g_signal_connect(element
, "pad-added", G_CALLBACK(pad_added_cb
), parser
);
1685 g_signal_connect(element
, "pad-removed", G_CALLBACK(pad_removed_cb
), parser
);
1686 g_signal_connect(element
, "autoplug-select", G_CALLBACK(autoplug_select_cb
), parser
);
1687 g_signal_connect(element
, "no-more-pads", G_CALLBACK(no_more_pads_cb
), parser
);
1689 parser
->their_sink
= gst_element_get_static_pad(element
, "sink");
1691 pthread_mutex_lock(&parser
->mutex
);
1692 parser
->no_more_pads
= parser
->error
= false;
1693 pthread_mutex_unlock(&parser
->mutex
);
1695 if ((ret
= gst_pad_link(parser
->my_src
, parser
->their_sink
)) < 0)
1697 GST_ERROR("Failed to link pads, error %d.\n", ret
);
1701 gst_element_set_state(parser
->container
, GST_STATE_PAUSED
);
1702 ret
= gst_element_get_state(parser
->container
, NULL
, NULL
, -1);
1703 if (ret
== GST_STATE_CHANGE_FAILURE
)
1705 GST_ERROR("Failed to play stream.\n");
1709 pthread_mutex_lock(&parser
->mutex
);
1710 while (!parser
->no_more_pads
&& !parser
->error
)
1711 pthread_cond_wait(&parser
->init_cond
, &parser
->mutex
);
1714 pthread_mutex_unlock(&parser
->mutex
);
1717 pthread_mutex_unlock(&parser
->mutex
);
1722 static BOOL
avi_parser_init_gst(struct wg_parser
*parser
)
1724 GstElement
*element
;
1727 if (!(element
= create_element("avidemux", "good")))
1730 gst_bin_add(GST_BIN(parser
->container
), element
);
1732 g_signal_connect(element
, "pad-added", G_CALLBACK(pad_added_cb
), parser
);
1733 g_signal_connect(element
, "pad-removed", G_CALLBACK(pad_removed_cb
), parser
);
1734 g_signal_connect(element
, "no-more-pads", G_CALLBACK(no_more_pads_cb
), parser
);
1736 parser
->their_sink
= gst_element_get_static_pad(element
, "sink");
1738 pthread_mutex_lock(&parser
->mutex
);
1739 parser
->no_more_pads
= parser
->error
= false;
1740 pthread_mutex_unlock(&parser
->mutex
);
1742 if ((ret
= gst_pad_link(parser
->my_src
, parser
->their_sink
)) < 0)
1744 GST_ERROR("Failed to link pads, error %d.\n", ret
);
1748 gst_element_set_state(parser
->container
, GST_STATE_PAUSED
);
1749 ret
= gst_element_get_state(parser
->container
, NULL
, NULL
, -1);
1750 if (ret
== GST_STATE_CHANGE_FAILURE
)
1752 GST_ERROR("Failed to play stream.\n");
1756 pthread_mutex_lock(&parser
->mutex
);
1757 while (!parser
->no_more_pads
&& !parser
->error
)
1758 pthread_cond_wait(&parser
->init_cond
, &parser
->mutex
);
1761 pthread_mutex_unlock(&parser
->mutex
);
1764 pthread_mutex_unlock(&parser
->mutex
);
1769 static BOOL
mpeg_audio_parser_init_gst(struct wg_parser
*parser
)
1771 struct wg_parser_stream
*stream
;
1772 GstElement
*element
;
1775 if (!(element
= create_element("mpegaudioparse", "good")))
1778 gst_bin_add(GST_BIN(parser
->container
), element
);
1780 parser
->their_sink
= gst_element_get_static_pad(element
, "sink");
1781 if ((ret
= gst_pad_link(parser
->my_src
, parser
->their_sink
)) < 0)
1783 GST_ERROR("Failed to link sink pads, error %d.\n", ret
);
1787 if (!(stream
= create_stream(parser
)))
1790 gst_object_ref(stream
->their_src
= gst_element_get_static_pad(element
, "src"));
1791 if ((ret
= gst_pad_link(stream
->their_src
, stream
->my_sink
)) < 0)
1793 GST_ERROR("Failed to link source pads, error %d.\n", ret
);
1797 gst_pad_set_active(stream
->my_sink
, 1);
1798 gst_element_set_state(parser
->container
, GST_STATE_PAUSED
);
1799 ret
= gst_element_get_state(parser
->container
, NULL
, NULL
, -1);
1800 if (ret
== GST_STATE_CHANGE_FAILURE
)
1802 GST_ERROR("Failed to play stream.\n");
1809 static BOOL
wave_parser_init_gst(struct wg_parser
*parser
)
1811 struct wg_parser_stream
*stream
;
1812 GstElement
*element
;
1815 if (!(element
= create_element("wavparse", "good")))
1818 gst_bin_add(GST_BIN(parser
->container
), element
);
1820 parser
->their_sink
= gst_element_get_static_pad(element
, "sink");
1821 if ((ret
= gst_pad_link(parser
->my_src
, parser
->their_sink
)) < 0)
1823 GST_ERROR("Failed to link sink pads, error %d.\n", ret
);
1827 if (!(stream
= create_stream(parser
)))
1830 stream
->their_src
= gst_element_get_static_pad(element
, "src");
1831 gst_object_ref(stream
->their_src
);
1832 if ((ret
= gst_pad_link(stream
->their_src
, stream
->my_sink
)) < 0)
1834 GST_ERROR("Failed to link source pads, error %d.\n", ret
);
1838 gst_pad_set_active(stream
->my_sink
, 1);
1839 gst_element_set_state(parser
->container
, GST_STATE_PAUSED
);
1840 ret
= gst_element_get_state(parser
->container
, NULL
, NULL
, -1);
1841 if (ret
== GST_STATE_CHANGE_FAILURE
)
1843 GST_ERROR("Failed to play stream.\n");
1850 static struct wg_parser
*wg_parser_create(void)
1852 struct wg_parser
*parser
;
1854 if (!(parser
= calloc(1, sizeof(*parser
))))
1857 pthread_mutex_init(&parser
->mutex
, NULL
);
1858 pthread_cond_init(&parser
->init_cond
, NULL
);
1859 pthread_cond_init(&parser
->read_cond
, NULL
);
1860 pthread_cond_init(&parser
->read_done_cond
, NULL
);
1861 parser
->flushing
= true;
1863 GST_DEBUG("Created winegstreamer parser %p.\n", parser
);
1867 static struct wg_parser
* CDECL
wg_decodebin_parser_create(void)
1869 struct wg_parser
*parser
;
1871 if ((parser
= wg_parser_create()))
1872 parser
->init_gst
= decodebin_parser_init_gst
;
1876 static struct wg_parser
* CDECL
wg_avi_parser_create(void)
1878 struct wg_parser
*parser
;
1880 if ((parser
= wg_parser_create()))
1881 parser
->init_gst
= avi_parser_init_gst
;
1885 static struct wg_parser
* CDECL
wg_mpeg_audio_parser_create(void)
1887 struct wg_parser
*parser
;
1889 if ((parser
= wg_parser_create()))
1890 parser
->init_gst
= mpeg_audio_parser_init_gst
;
1894 static struct wg_parser
* CDECL
wg_wave_parser_create(void)
1896 struct wg_parser
*parser
;
1898 if ((parser
= wg_parser_create()))
1899 parser
->init_gst
= wave_parser_init_gst
;
1903 static void CDECL
wg_parser_destroy(struct wg_parser
*parser
)
1907 gst_bus_set_sync_handler(parser
->bus
, NULL
, NULL
, NULL
);
1908 gst_object_unref(parser
->bus
);
1911 pthread_mutex_destroy(&parser
->mutex
);
1912 pthread_cond_destroy(&parser
->init_cond
);
1913 pthread_cond_destroy(&parser
->read_cond
);
1914 pthread_cond_destroy(&parser
->read_done_cond
);
1919 static const struct unix_funcs funcs
=
1921 wg_decodebin_parser_create
,
1922 wg_avi_parser_create
,
1923 wg_mpeg_audio_parser_create
,
1924 wg_wave_parser_create
,
1928 wg_parser_disconnect
,
1930 wg_parser_begin_flush
,
1931 wg_parser_end_flush
,
1933 wg_parser_get_read_request
,
1934 wg_parser_complete_read_request
,
1936 wg_parser_set_unlimited_buffering
,
1938 wg_parser_get_stream_count
,
1939 wg_parser_get_stream
,
1941 wg_parser_stream_get_preferred_format
,
1942 wg_parser_stream_enable
,
1943 wg_parser_stream_disable
,
1945 wg_parser_stream_get_event
,
1946 wg_parser_stream_copy_buffer
,
1947 wg_parser_stream_release_buffer
,
1948 wg_parser_stream_notify_qos
,
1950 wg_parser_stream_get_duration
,
1951 wg_parser_stream_seek
,
1954 NTSTATUS CDECL
__wine_init_unix_lib(HMODULE module
, DWORD reason
, const void *ptr_in
, void *ptr_out
)
1956 if (reason
== DLL_PROCESS_ATTACH
)
1958 char arg0
[] = "wine";
1959 char arg1
[] = "--gst-disable-registry-fork";
1960 char *args
[] = {arg0
, arg1
, NULL
};
1961 int argc
= ARRAY_SIZE(args
) - 1;
1965 if (!gst_init_check(&argc
, &argv
, &err
))
1967 fprintf(stderr
, "winegstreamer: failed to initialize GStreamer: %s\n", debugstr_a(err
->message
));
1969 return STATUS_UNSUCCESSFUL
;
1972 GST_DEBUG_CATEGORY_INIT(wine
, "WINE", GST_DEBUG_FG_RED
, "Wine GStreamer support");
1974 GST_INFO("GStreamer library version %s; wine built with %d.%d.%d.\n",
1975 gst_version_string(), GST_VERSION_MAJOR
, GST_VERSION_MINOR
, GST_VERSION_MICRO
);
1977 *(const struct unix_funcs
**)ptr_out
= &funcs
;
1979 return STATUS_SUCCESS
;