wined3d: Do not set last_was_pshader from the GLSL fragment pipe.
[wine.git] / dlls / winegstreamer / unixlib.c
blob513ece95a90c8d1f3c7daf972038f00d561d311d
1 /*
2 * winegstreamer Unix library interface
4 * Copyright 2020-2021 Zebediah Figura for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <assert.h>
28 #include <stdarg.h>
29 #include <stdio.h>
31 #include <gst/gst.h>
32 #include <gst/video/video.h>
33 #include <gst/audio/audio.h>
34 #include <gst/tag/tag.h>
36 #include "ntstatus.h"
37 #define WIN32_NO_STATUS
38 #include "winternl.h"
39 #include "dshow.h"
41 #include "unix_private.h"
43 /* GStreamer callbacks may be called on threads not created by Wine, and
44 * therefore cannot access the Wine TEB. This means that we must use GStreamer
45 * debug logging instead of Wine debug logging. In order to be safe we forbid
46 * any use of Wine debug logging in this entire file. */
48 GST_DEBUG_CATEGORY(wine);
50 GstStreamType stream_type_from_caps(GstCaps *caps)
52 const gchar *media_type;
54 if (!caps || !gst_caps_get_size(caps))
55 return GST_STREAM_TYPE_UNKNOWN;
57 media_type = gst_structure_get_name(gst_caps_get_structure(caps, 0));
58 if (g_str_has_prefix(media_type, "video/")
59 || g_str_has_prefix(media_type, "image/"))
60 return GST_STREAM_TYPE_VIDEO;
61 if (g_str_has_prefix(media_type, "audio/"))
62 return GST_STREAM_TYPE_AUDIO;
63 if (g_str_has_prefix(media_type, "text/")
64 || g_str_has_prefix(media_type, "subpicture/")
65 || g_str_has_prefix(media_type, "closedcaption/"))
66 return GST_STREAM_TYPE_TEXT;
68 return GST_STREAM_TYPE_UNKNOWN;
71 GstElement *create_element(const char *name, const char *plugin_set)
73 GstElement *element;
75 if (!(element = gst_element_factory_make(name, NULL)))
76 fprintf(stderr, "winegstreamer: failed to create %s, are %u-bit GStreamer \"%s\" plugins installed?\n",
77 name, 8 * (unsigned int)sizeof(void *), plugin_set);
78 return element;
81 GstElement *find_element(GstElementFactoryListType type, GstCaps *src_caps, GstCaps *sink_caps)
83 GstElement *element = NULL;
84 GList *tmp, *transforms;
85 const gchar *name;
87 if (!(transforms = gst_element_factory_list_get_elements(type, GST_RANK_MARGINAL)))
88 goto done;
90 if (src_caps)
92 tmp = gst_element_factory_list_filter(transforms, src_caps, GST_PAD_SINK, FALSE);
93 gst_plugin_feature_list_free(transforms);
94 if (!(transforms = tmp))
95 goto done;
98 if (sink_caps)
100 tmp = gst_element_factory_list_filter(transforms, sink_caps, GST_PAD_SRC, FALSE);
101 gst_plugin_feature_list_free(transforms);
102 if (!(transforms = tmp))
103 goto done;
106 transforms = g_list_sort(transforms, gst_plugin_feature_rank_compare_func);
107 for (tmp = transforms; tmp != NULL && element == NULL; tmp = tmp->next)
109 name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(tmp->data));
111 if (!strcmp(name, "vaapidecodebin"))
113 /* vaapidecodebin adds asynchronicity which breaks wg_transform synchronous drain / flush
114 * requirements. Ignore it and use VA-API decoders directly instead.
116 GST_WARNING("Ignoring vaapidecodebin decoder.");
117 continue;
120 if (!(element = gst_element_factory_create(GST_ELEMENT_FACTORY(tmp->data), NULL)))
121 GST_WARNING("Failed to create %s element.", name);
123 gst_plugin_feature_list_free(transforms);
125 done:
126 if (element)
128 GST_DEBUG("Created %s element %p.", name, element);
130 else
132 gchar *src_str = gst_caps_to_string(src_caps), *sink_str = gst_caps_to_string(sink_caps);
133 GST_WARNING("Failed to create element matching caps %s / %s.", src_str, sink_str);
134 g_free(sink_str);
135 g_free(src_str);
138 return element;
141 bool append_element(GstElement *container, GstElement *element, GstElement **first, GstElement **last)
143 gchar *name = gst_element_get_name(element);
144 bool success = false;
146 if (!gst_bin_add(GST_BIN(container), element) ||
147 !gst_element_sync_state_with_parent(element) ||
148 (*last && !gst_element_link(*last, element)))
150 GST_ERROR("Failed to link %s element.", name);
152 else
154 GST_DEBUG("Linked %s element %p.", name, element);
155 if (!*first)
156 *first = element;
157 *last = element;
158 success = true;
161 g_free(name);
162 return success;
165 bool link_src_to_element(GstPad *src_pad, GstElement *element)
167 GstPadLinkReturn ret;
168 GstPad *sink_pad;
170 if (!(sink_pad = gst_element_get_static_pad(element, "sink")))
172 gchar *name = gst_element_get_name(element);
173 GST_ERROR("Failed to find sink pad on %s", name);
174 g_free(name);
175 return false;
177 if ((ret = gst_pad_link(src_pad, sink_pad)))
179 gchar *src_name = gst_pad_get_name(src_pad), *sink_name = gst_pad_get_name(sink_pad);
180 GST_ERROR("Failed to link element pad %s with pad %s", src_name, sink_name);
181 g_free(sink_name);
182 g_free(src_name);
184 gst_object_unref(sink_pad);
185 return !ret;
188 bool link_element_to_sink(GstElement *element, GstPad *sink_pad)
190 GstPadLinkReturn ret;
191 GstPad *src_pad;
193 if (!(src_pad = gst_element_get_static_pad(element, "src")))
195 gchar *name = gst_element_get_name(element);
196 GST_ERROR("Failed to find src pad on %s", name);
197 g_free(name);
198 return false;
200 if ((ret = gst_pad_link(src_pad, sink_pad)))
202 gchar *src_name = gst_pad_get_name(src_pad), *sink_name = gst_pad_get_name(sink_pad);
203 GST_ERROR("Failed to link pad %s with element pad %s", src_name, sink_name);
204 g_free(sink_name);
205 g_free(src_name);
207 gst_object_unref(src_pad);
208 return !ret;
211 bool push_event(GstPad *pad, GstEvent *event)
213 if (!gst_pad_push_event(pad, event))
215 const gchar *type_name = gst_event_type_get_name(GST_EVENT_TYPE(event));
216 gchar *pad_name = gst_pad_get_name(pad);
218 GST_ERROR("Failed to push %s event %p to pad %s.", type_name, event, pad_name);
219 g_free(pad_name);
220 return false;
222 return true;
225 NTSTATUS wg_init_gstreamer(void *arg)
227 char arg0[] = "wine";
228 char arg1[] = "--gst-disable-registry-fork";
229 char *args[] = {arg0, arg1, NULL};
230 int argc = ARRAY_SIZE(args) - 1;
231 char **argv = args;
232 GError *err;
234 if (!gst_init_check(&argc, &argv, &err))
236 fprintf(stderr, "winegstreamer: failed to initialize GStreamer: %s\n", err->message);
237 g_error_free(err);
238 return STATUS_UNSUCCESSFUL;
241 GST_DEBUG_CATEGORY_INIT(wine, "WINE", GST_DEBUG_FG_RED, "Wine GStreamer support");
243 GST_INFO("GStreamer library version %s; wine built with %d.%d.%d.",
244 gst_version_string(), GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO);
245 return STATUS_SUCCESS;