kernelbase: Reimplement LocaleNameToLCID() using the locale.nls data.
[wine.git] / dlls / winegstreamer / wg_format.c
blobfc50fad6d12e5b376d3b7b2f0d3cc0efe3a5e247
1 /*
2 * GStreamer format helpers
4 * Copyright 2010 Maarten Lankhorst for CodeWeavers
5 * Copyright 2010 Aric Stewart for CodeWeavers
6 * Copyright 2019-2020 Zebediah Figura
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #if 0
24 #pragma makedep unix
25 #endif
27 #include "config.h"
29 #include <assert.h>
30 #include <stdarg.h>
31 #include <stdio.h>
33 #include <gst/gst.h>
34 #include <gst/video/video.h>
35 #include <gst/audio/audio.h>
37 #include "winternl.h"
38 #include "dshow.h"
40 #include "unix_private.h"
42 GST_DEBUG_CATEGORY_EXTERN(wine);
43 #define GST_CAT_DEFAULT wine
45 static enum wg_audio_format wg_audio_format_from_gst(GstAudioFormat format)
47 switch (format)
49 case GST_AUDIO_FORMAT_U8:
50 return WG_AUDIO_FORMAT_U8;
51 case GST_AUDIO_FORMAT_S16LE:
52 return WG_AUDIO_FORMAT_S16LE;
53 case GST_AUDIO_FORMAT_S24LE:
54 return WG_AUDIO_FORMAT_S24LE;
55 case GST_AUDIO_FORMAT_S32LE:
56 return WG_AUDIO_FORMAT_S32LE;
57 case GST_AUDIO_FORMAT_F32LE:
58 return WG_AUDIO_FORMAT_F32LE;
59 case GST_AUDIO_FORMAT_F64LE:
60 return WG_AUDIO_FORMAT_F64LE;
61 default:
62 return WG_AUDIO_FORMAT_UNKNOWN;
66 static uint32_t wg_channel_position_from_gst(GstAudioChannelPosition position)
68 static const uint32_t position_map[] =
70 SPEAKER_FRONT_LEFT,
71 SPEAKER_FRONT_RIGHT,
72 SPEAKER_FRONT_CENTER,
73 SPEAKER_LOW_FREQUENCY,
74 SPEAKER_BACK_LEFT,
75 SPEAKER_BACK_RIGHT,
76 SPEAKER_FRONT_LEFT_OF_CENTER,
77 SPEAKER_FRONT_RIGHT_OF_CENTER,
78 SPEAKER_BACK_CENTER,
80 SPEAKER_SIDE_LEFT,
81 SPEAKER_SIDE_RIGHT,
82 SPEAKER_TOP_FRONT_LEFT,
83 SPEAKER_TOP_FRONT_RIGHT,
84 SPEAKER_TOP_FRONT_CENTER,
85 SPEAKER_TOP_CENTER,
86 SPEAKER_TOP_BACK_LEFT,
87 SPEAKER_TOP_BACK_RIGHT,
90 SPEAKER_TOP_BACK_CENTER,
93 if (position == GST_AUDIO_CHANNEL_POSITION_MONO)
94 return SPEAKER_FRONT_CENTER;
96 if (position >= 0 && position < ARRAY_SIZE(position_map))
97 return position_map[position];
98 return 0;
101 static uint32_t wg_channel_mask_from_gst(const GstAudioInfo *info)
103 uint32_t mask = 0, position;
104 unsigned int i;
106 for (i = 0; i < GST_AUDIO_INFO_CHANNELS(info); ++i)
108 if (!(position = wg_channel_position_from_gst(GST_AUDIO_INFO_POSITION(info, i))))
110 GST_WARNING("Unsupported channel %#x.", GST_AUDIO_INFO_POSITION(info, i));
111 return 0;
113 /* Make sure it's also in WinMM order. WinMM mandates that channels be
114 * ordered, as it were, from least to most significant SPEAKER_* bit.
115 * Hence we fail if the current channel was already specified, or if any
116 * higher bit was already specified. */
117 if (mask & ~(position - 1))
119 GST_WARNING("Unsupported channel order.");
120 return 0;
122 mask |= position;
124 return mask;
127 static void wg_format_from_audio_info(struct wg_format *format, const GstAudioInfo *info)
129 format->major_type = WG_MAJOR_TYPE_AUDIO;
130 format->u.audio.format = wg_audio_format_from_gst(GST_AUDIO_INFO_FORMAT(info));
131 format->u.audio.channels = GST_AUDIO_INFO_CHANNELS(info);
132 format->u.audio.channel_mask = wg_channel_mask_from_gst(info);
133 format->u.audio.rate = GST_AUDIO_INFO_RATE(info);
136 static enum wg_video_format wg_video_format_from_gst(GstVideoFormat format)
138 switch (format)
140 case GST_VIDEO_FORMAT_BGRA:
141 return WG_VIDEO_FORMAT_BGRA;
142 case GST_VIDEO_FORMAT_BGRx:
143 return WG_VIDEO_FORMAT_BGRx;
144 case GST_VIDEO_FORMAT_BGR:
145 return WG_VIDEO_FORMAT_BGR;
146 case GST_VIDEO_FORMAT_RGB15:
147 return WG_VIDEO_FORMAT_RGB15;
148 case GST_VIDEO_FORMAT_RGB16:
149 return WG_VIDEO_FORMAT_RGB16;
150 case GST_VIDEO_FORMAT_AYUV:
151 return WG_VIDEO_FORMAT_AYUV;
152 case GST_VIDEO_FORMAT_I420:
153 return WG_VIDEO_FORMAT_I420;
154 case GST_VIDEO_FORMAT_NV12:
155 return WG_VIDEO_FORMAT_NV12;
156 case GST_VIDEO_FORMAT_UYVY:
157 return WG_VIDEO_FORMAT_UYVY;
158 case GST_VIDEO_FORMAT_YUY2:
159 return WG_VIDEO_FORMAT_YUY2;
160 case GST_VIDEO_FORMAT_YV12:
161 return WG_VIDEO_FORMAT_YV12;
162 case GST_VIDEO_FORMAT_YVYU:
163 return WG_VIDEO_FORMAT_YVYU;
164 default:
165 return WG_VIDEO_FORMAT_UNKNOWN;
169 static void wg_format_from_video_info(struct wg_format *format, const GstVideoInfo *info)
171 format->major_type = WG_MAJOR_TYPE_VIDEO;
172 format->u.video.format = wg_video_format_from_gst(GST_VIDEO_INFO_FORMAT(info));
173 format->u.video.width = GST_VIDEO_INFO_WIDTH(info);
174 format->u.video.height = GST_VIDEO_INFO_HEIGHT(info);
175 format->u.video.fps_n = GST_VIDEO_INFO_FPS_N(info);
176 format->u.video.fps_d = GST_VIDEO_INFO_FPS_D(info);
179 static void wg_format_from_caps_audio_mpeg(struct wg_format *format, const GstCaps *caps)
181 const GstStructure *structure = gst_caps_get_structure(caps, 0);
182 gint layer, channels, rate;
184 if (!gst_structure_get_int(structure, "layer", &layer))
186 GST_WARNING("Missing \"layer\" value.");
187 return;
189 if (!gst_structure_get_int(structure, "channels", &channels))
191 GST_WARNING("Missing \"channels\" value.");
192 return;
194 if (!gst_structure_get_int(structure, "rate", &rate))
196 GST_WARNING("Missing \"rate\" value.");
197 return;
200 format->major_type = WG_MAJOR_TYPE_AUDIO;
202 if (layer == 1)
203 format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER1;
204 else if (layer == 2)
205 format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER2;
206 else if (layer == 3)
207 format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER3;
209 format->u.audio.channels = channels;
210 format->u.audio.rate = rate;
213 static void wg_format_from_caps_video_cinepak(struct wg_format *format, const GstCaps *caps)
215 const GstStructure *structure = gst_caps_get_structure(caps, 0);
216 gint width, height, fps_n, fps_d;
218 if (!gst_structure_get_int(structure, "width", &width))
220 GST_WARNING("Missing \"width\" value.");
221 return;
223 if (!gst_structure_get_int(structure, "height", &height))
225 GST_WARNING("Missing \"height\" value.");
226 return;
228 if (!gst_structure_get_fraction(structure, "framerate", &fps_n, &fps_d))
230 fps_n = 0;
231 fps_d = 1;
234 format->major_type = WG_MAJOR_TYPE_VIDEO;
235 format->u.video.format = WG_VIDEO_FORMAT_CINEPAK;
236 format->u.video.width = width;
237 format->u.video.height = height;
238 format->u.video.fps_n = fps_n;
239 format->u.video.fps_d = fps_d;
242 void wg_format_from_caps(struct wg_format *format, const GstCaps *caps)
244 const GstStructure *structure = gst_caps_get_structure(caps, 0);
245 const char *name = gst_structure_get_name(structure);
247 memset(format, 0, sizeof(*format));
249 if (!strcmp(name, "audio/x-raw"))
251 GstAudioInfo info;
253 if (gst_audio_info_from_caps(&info, caps))
254 wg_format_from_audio_info(format, &info);
256 else if (!strcmp(name, "video/x-raw"))
258 GstVideoInfo info;
260 if (gst_video_info_from_caps(&info, caps))
261 wg_format_from_video_info(format, &info);
263 else if (!strcmp(name, "audio/mpeg"))
265 wg_format_from_caps_audio_mpeg(format, caps);
267 else if (!strcmp(name, "video/x-cinepak"))
269 wg_format_from_caps_video_cinepak(format, caps);
271 else
273 gchar *str = gst_caps_to_string(caps);
275 GST_FIXME("Unhandled caps %s.", str);
276 g_free(str);
280 static GstAudioFormat wg_audio_format_to_gst(enum wg_audio_format format)
282 switch (format)
284 case WG_AUDIO_FORMAT_U8: return GST_AUDIO_FORMAT_U8;
285 case WG_AUDIO_FORMAT_S16LE: return GST_AUDIO_FORMAT_S16LE;
286 case WG_AUDIO_FORMAT_S24LE: return GST_AUDIO_FORMAT_S24LE;
287 case WG_AUDIO_FORMAT_S32LE: return GST_AUDIO_FORMAT_S32LE;
288 case WG_AUDIO_FORMAT_F32LE: return GST_AUDIO_FORMAT_F32LE;
289 case WG_AUDIO_FORMAT_F64LE: return GST_AUDIO_FORMAT_F64LE;
290 default: return GST_AUDIO_FORMAT_UNKNOWN;
294 static void wg_channel_mask_to_gst(GstAudioChannelPosition *positions, uint32_t mask, uint32_t channel_count)
296 const uint32_t orig_mask = mask;
297 unsigned int i;
298 DWORD bit;
300 static const GstAudioChannelPosition position_map[] =
302 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
303 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
304 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
305 GST_AUDIO_CHANNEL_POSITION_LFE1,
306 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
307 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
308 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
309 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
310 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
311 GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
312 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
313 GST_AUDIO_CHANNEL_POSITION_TOP_CENTER,
314 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT,
315 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER,
316 GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT,
317 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT,
318 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER,
319 GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT,
322 for (i = 0; i < channel_count; ++i)
324 positions[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
325 if (BitScanForward(&bit, mask))
327 if (bit < ARRAY_SIZE(position_map))
328 positions[i] = position_map[bit];
329 else
330 GST_WARNING("Invalid channel mask %#x.", orig_mask);
331 mask &= ~(1 << bit);
333 else
335 GST_WARNING("Incomplete channel mask %#x.", orig_mask);
340 static GstCaps *wg_format_to_caps_audio(const struct wg_format *format)
342 GstAudioChannelPosition positions[32];
343 GstAudioFormat audio_format;
344 GstAudioInfo info;
346 if ((audio_format = wg_audio_format_to_gst(format->u.audio.format)) == GST_AUDIO_FORMAT_UNKNOWN)
347 return NULL;
349 wg_channel_mask_to_gst(positions, format->u.audio.channel_mask, format->u.audio.channels);
350 gst_audio_info_set_format(&info, audio_format, format->u.audio.rate, format->u.audio.channels, positions);
351 return gst_audio_info_to_caps(&info);
354 static GstVideoFormat wg_video_format_to_gst(enum wg_video_format format)
356 switch (format)
358 case WG_VIDEO_FORMAT_BGRA: return GST_VIDEO_FORMAT_BGRA;
359 case WG_VIDEO_FORMAT_BGRx: return GST_VIDEO_FORMAT_BGRx;
360 case WG_VIDEO_FORMAT_BGR: return GST_VIDEO_FORMAT_BGR;
361 case WG_VIDEO_FORMAT_RGB15: return GST_VIDEO_FORMAT_RGB15;
362 case WG_VIDEO_FORMAT_RGB16: return GST_VIDEO_FORMAT_RGB16;
363 case WG_VIDEO_FORMAT_AYUV: return GST_VIDEO_FORMAT_AYUV;
364 case WG_VIDEO_FORMAT_I420: return GST_VIDEO_FORMAT_I420;
365 case WG_VIDEO_FORMAT_NV12: return GST_VIDEO_FORMAT_NV12;
366 case WG_VIDEO_FORMAT_UYVY: return GST_VIDEO_FORMAT_UYVY;
367 case WG_VIDEO_FORMAT_YUY2: return GST_VIDEO_FORMAT_YUY2;
368 case WG_VIDEO_FORMAT_YV12: return GST_VIDEO_FORMAT_YV12;
369 case WG_VIDEO_FORMAT_YVYU: return GST_VIDEO_FORMAT_YVYU;
370 default: return GST_VIDEO_FORMAT_UNKNOWN;
374 static GstCaps *wg_format_to_caps_video(const struct wg_format *format)
376 GstVideoFormat video_format;
377 GstVideoInfo info;
378 unsigned int i;
379 GstCaps *caps;
381 if ((video_format = wg_video_format_to_gst(format->u.video.format)) == GST_VIDEO_FORMAT_UNKNOWN)
382 return NULL;
384 gst_video_info_set_format(&info, video_format, format->u.video.width, abs(format->u.video.height));
385 if ((caps = gst_video_info_to_caps(&info)))
387 /* Clear some fields that shouldn't prevent us from connecting. */
388 for (i = 0; i < gst_caps_get_size(caps); ++i)
390 gst_structure_remove_fields(gst_caps_get_structure(caps, i),
391 "framerate", "pixel-aspect-ratio", "colorimetry", "chroma-site", NULL);
394 return caps;
397 static GstCaps *wg_format_to_caps_wma(const struct wg_format *format)
399 GstBuffer *buffer;
400 GstCaps *caps;
402 if (!(caps = gst_caps_new_empty_simple("audio/x-wma")))
403 return NULL;
404 if (format->u.wma.version)
405 gst_caps_set_simple(caps, "wmaversion", G_TYPE_INT, format->u.wma.version, NULL);
407 if (format->u.wma.bitrate)
408 gst_caps_set_simple(caps, "bitrate", G_TYPE_INT, format->u.wma.bitrate, NULL);
409 if (format->u.wma.rate)
410 gst_caps_set_simple(caps, "rate", G_TYPE_INT, format->u.wma.rate, NULL);
411 if (format->u.wma.depth)
412 gst_caps_set_simple(caps, "depth", G_TYPE_INT, format->u.wma.depth, NULL);
413 if (format->u.wma.channels)
414 gst_caps_set_simple(caps, "channels", G_TYPE_INT, format->u.wma.channels, NULL);
415 if (format->u.wma.block_align)
416 gst_caps_set_simple(caps, "block_align", G_TYPE_INT, format->u.wma.block_align, NULL);
418 if (format->u.wma.codec_data_len)
420 if (!(buffer = gst_buffer_new_and_alloc(format->u.wma.codec_data_len)))
422 gst_caps_unref(caps);
423 return NULL;
426 gst_buffer_fill(buffer, 0, format->u.wma.codec_data, format->u.wma.codec_data_len);
427 gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL);
428 gst_buffer_unref(buffer);
431 return caps;
434 GstCaps *wg_format_to_caps(const struct wg_format *format)
436 switch (format->major_type)
438 case WG_MAJOR_TYPE_UNKNOWN:
439 return NULL;
440 case WG_MAJOR_TYPE_WMA:
441 return wg_format_to_caps_wma(format);
442 case WG_MAJOR_TYPE_AUDIO:
443 return wg_format_to_caps_audio(format);
444 case WG_MAJOR_TYPE_VIDEO:
445 return wg_format_to_caps_video(format);
447 assert(0);
448 return NULL;
451 bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
453 if (a->major_type != b->major_type)
454 return false;
456 switch (a->major_type)
458 case WG_MAJOR_TYPE_UNKNOWN:
459 return false;
461 case WG_MAJOR_TYPE_WMA:
462 GST_FIXME("WMA format not implemented!\n");
463 return false;
465 case WG_MAJOR_TYPE_AUDIO:
466 return a->u.audio.format == b->u.audio.format
467 && a->u.audio.channels == b->u.audio.channels
468 && a->u.audio.rate == b->u.audio.rate;
470 case WG_MAJOR_TYPE_VIDEO:
471 /* Do not compare FPS. */
472 return a->u.video.format == b->u.video.format
473 && a->u.video.width == b->u.video.width
474 && abs(a->u.video.height) == abs(b->u.video.height);
477 assert(0);
478 return false;