d3dx9: Unify calling parse_mesh helper functions.
[wine.git] / dlls / winegstreamer / video_processor.c
blob3075bf997d226dfe6ae8be1770702b01be1599fe
1 /* Copyright 2022 RĂ©mi Bernon for CodeWeavers
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 #include "gst_private.h"
20 #include "mfapi.h"
21 #include "mferror.h"
22 #include "mfobjects.h"
23 #include "mftransform.h"
24 #include "wmcodecdsp.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
29 WINE_DECLARE_DEBUG_CHANNEL(winediag);
31 static const GUID *const input_types[] =
33 &MFVideoFormat_IYUV,
34 &MFVideoFormat_YV12,
35 &MFVideoFormat_NV12,
36 &MFVideoFormat_420O,
37 &MFVideoFormat_UYVY,
38 &MFVideoFormat_YUY2,
39 &MEDIASUBTYPE_P208,
40 &MFVideoFormat_NV11,
41 &MFVideoFormat_AYUV,
42 &MFVideoFormat_ARGB32,
43 &MFVideoFormat_RGB32,
44 &MFVideoFormat_RGB24,
45 &MFVideoFormat_I420,
46 &MFVideoFormat_YVYU,
47 &MFVideoFormat_RGB555,
48 &MFVideoFormat_RGB565,
49 &MFVideoFormat_RGB8,
50 &MFVideoFormat_Y216,
51 &MFVideoFormat_v410,
52 &MFVideoFormat_Y41P,
53 &MFVideoFormat_Y41T,
54 &MFVideoFormat_Y42T,
56 static const GUID *const output_types[] =
58 &MFVideoFormat_YUY2,
59 &MFVideoFormat_IYUV,
60 &MFVideoFormat_I420,
61 &MFVideoFormat_NV12,
62 &MFVideoFormat_RGB24,
63 &MFVideoFormat_ARGB32,
64 &MFVideoFormat_RGB32,
65 &MFVideoFormat_YV12,
66 &MFVideoFormat_AYUV,
67 &MFVideoFormat_RGB555,
68 &MFVideoFormat_RGB565,
71 struct video_processor
73 IMFTransform IMFTransform_iface;
74 LONG refcount;
76 IMFAttributes *attributes;
77 IMFAttributes *output_attributes;
79 IMFMediaType *input_type;
80 MFT_INPUT_STREAM_INFO input_info;
81 IMFMediaType *output_type;
82 MFT_OUTPUT_STREAM_INFO output_info;
84 wg_transform_t wg_transform;
85 struct wg_sample_queue *wg_sample_queue;
88 static HRESULT try_create_wg_transform(struct video_processor *impl)
90 struct wg_format input_format, output_format;
91 struct wg_transform_attrs attrs = {0};
93 if (impl->wg_transform)
94 wg_transform_destroy(impl->wg_transform);
95 impl->wg_transform = 0;
97 mf_media_type_to_wg_format(impl->input_type, &input_format);
98 if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
99 return MF_E_INVALIDMEDIATYPE;
101 mf_media_type_to_wg_format(impl->output_type, &output_format);
102 if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
103 return MF_E_INVALIDMEDIATYPE;
105 if (!(impl->wg_transform = wg_transform_create(&input_format, &output_format, &attrs)))
106 return E_FAIL;
108 return S_OK;
111 static struct video_processor *impl_from_IMFTransform(IMFTransform *iface)
113 return CONTAINING_RECORD(iface, struct video_processor, IMFTransform_iface);
116 static HRESULT WINAPI video_processor_QueryInterface(IMFTransform *iface, REFIID iid, void **out)
118 struct video_processor *impl = impl_from_IMFTransform(iface);
120 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
122 if (IsEqualGUID(iid, &IID_IMFTransform))
123 *out = &impl->IMFTransform_iface;
124 else
126 *out = NULL;
127 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
128 return E_NOINTERFACE;
131 IUnknown_AddRef((IUnknown *)*out);
132 return S_OK;
135 static ULONG WINAPI video_processor_AddRef(IMFTransform *iface)
137 struct video_processor *impl = impl_from_IMFTransform(iface);
138 ULONG refcount = InterlockedIncrement(&impl->refcount);
140 TRACE("iface %p increasing refcount to %lu.\n", iface, refcount);
142 return refcount;
145 static ULONG WINAPI video_processor_Release(IMFTransform *iface)
147 struct video_processor *impl = impl_from_IMFTransform(iface);
148 ULONG refcount = InterlockedDecrement(&impl->refcount);
150 TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
152 if (!refcount)
154 if (impl->wg_transform)
155 wg_transform_destroy(impl->wg_transform);
156 if (impl->input_type)
157 IMFMediaType_Release(impl->input_type);
158 if (impl->output_type)
159 IMFMediaType_Release(impl->output_type);
160 if (impl->attributes)
161 IMFAttributes_Release(impl->attributes);
162 if (impl->output_attributes)
163 IMFAttributes_Release(impl->output_attributes);
165 wg_sample_queue_destroy(impl->wg_sample_queue);
166 free(impl);
169 return refcount;
172 static HRESULT WINAPI video_processor_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
173 DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
175 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
176 iface, input_minimum, input_maximum, output_minimum, output_maximum);
177 *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
178 return S_OK;
181 static HRESULT WINAPI video_processor_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
183 TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs);
184 *inputs = *outputs = 1;
185 return S_OK;
188 static HRESULT WINAPI video_processor_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
189 DWORD output_size, DWORD *outputs)
191 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface,
192 input_size, inputs, output_size, outputs);
193 return E_NOTIMPL;
196 static HRESULT WINAPI video_processor_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
198 struct video_processor *impl = impl_from_IMFTransform(iface);
200 TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
202 if (id)
203 return MF_E_INVALIDSTREAMNUMBER;
205 *info = impl->input_info;
206 return S_OK;
209 static HRESULT WINAPI video_processor_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
211 struct video_processor *impl = impl_from_IMFTransform(iface);
213 TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
215 if (id)
216 return MF_E_INVALIDSTREAMNUMBER;
218 *info = impl->output_info;
219 return S_OK;
222 static HRESULT WINAPI video_processor_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
224 struct video_processor *impl = impl_from_IMFTransform(iface);
226 FIXME("iface %p, attributes %p semi-stub!\n", iface, attributes);
228 if (!attributes)
229 return E_POINTER;
231 IMFAttributes_AddRef((*attributes = impl->attributes));
232 return S_OK;
235 static HRESULT WINAPI video_processor_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
237 TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
238 return E_NOTIMPL;
241 static HRESULT WINAPI video_processor_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
243 struct video_processor *impl = impl_from_IMFTransform(iface);
245 FIXME("iface %p, id %#lx, attributes %p semi-stub!\n", iface, id, attributes);
247 if (!attributes)
248 return E_POINTER;
249 if (id)
250 return MF_E_INVALIDSTREAMNUMBER;
252 IMFAttributes_AddRef((*attributes = impl->output_attributes));
253 return S_OK;
256 static HRESULT WINAPI video_processor_DeleteInputStream(IMFTransform *iface, DWORD id)
258 TRACE("iface %p, id %#lx.\n", iface, id);
259 return E_NOTIMPL;
262 static HRESULT WINAPI video_processor_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
264 TRACE("iface %p, streams %lu, ids %p.\n", iface, streams, ids);
265 return E_NOTIMPL;
268 static HRESULT WINAPI video_processor_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
269 IMFMediaType **type)
271 IMFMediaType *media_type;
272 const GUID *subtype;
273 HRESULT hr;
275 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
277 *type = NULL;
279 if (index >= ARRAY_SIZE(input_types))
280 return MF_E_NO_MORE_TYPES;
281 subtype = input_types[index];
283 if (FAILED(hr = MFCreateMediaType(&media_type)))
284 return hr;
286 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)))
287 goto done;
288 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, subtype)))
289 goto done;
291 IMFMediaType_AddRef((*type = media_type));
293 done:
294 IMFMediaType_Release(media_type);
295 return hr;
298 static HRESULT WINAPI video_processor_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
299 IMFMediaType **type)
301 struct video_processor *impl = impl_from_IMFTransform(iface);
302 IMFMediaType *media_type;
303 UINT64 frame_size;
304 GUID subtype;
305 HRESULT hr;
307 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
309 *type = NULL;
311 if (!impl->input_type)
312 return MF_E_NO_MORE_TYPES;
314 if (FAILED(hr = IMFMediaType_GetGUID(impl->input_type, &MF_MT_SUBTYPE, &subtype))
315 || FAILED(hr = IMFMediaType_GetUINT64(impl->input_type, &MF_MT_FRAME_SIZE, &frame_size)))
316 return hr;
318 if (index > ARRAY_SIZE(output_types))
319 return MF_E_NO_MORE_TYPES;
320 if (index > 0)
321 subtype = *output_types[index - 1];
323 if (FAILED(hr = MFCreateMediaType(&media_type)))
324 return hr;
326 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)))
327 goto done;
328 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &subtype)))
329 goto done;
330 if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, frame_size)))
331 goto done;
333 IMFMediaType_AddRef((*type = media_type));
335 done:
336 IMFMediaType_Release(media_type);
337 return hr;
340 static HRESULT WINAPI video_processor_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
342 struct video_processor *impl = impl_from_IMFTransform(iface);
343 GUID major, subtype;
344 UINT64 frame_size;
345 HRESULT hr;
346 ULONG i;
348 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
350 if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major))
351 || !IsEqualGUID(&major, &MFMediaType_Video))
352 return E_INVALIDARG;
353 if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
354 return MF_E_INVALIDMEDIATYPE;
355 if (FAILED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
356 return hr;
358 for (i = 0; i < ARRAY_SIZE(input_types); ++i)
359 if (IsEqualGUID(&subtype, input_types[i]))
360 break;
361 if (i == ARRAY_SIZE(input_types))
362 return MF_E_INVALIDMEDIATYPE;
363 if (flags & MFT_SET_TYPE_TEST_ONLY)
364 return S_OK;
366 if (impl->input_type)
367 IMFMediaType_Release(impl->input_type);
368 IMFMediaType_AddRef((impl->input_type = type));
370 if (impl->output_type && FAILED(hr = try_create_wg_transform(impl)))
372 IMFMediaType_Release(impl->input_type);
373 impl->input_type = NULL;
376 if (FAILED(hr) || FAILED(MFCalculateImageSize(&subtype, frame_size >> 32, (UINT32)frame_size,
377 (UINT32 *)&impl->input_info.cbSize)))
378 impl->input_info.cbSize = 0;
380 return hr;
383 static HRESULT WINAPI video_processor_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
385 struct video_processor *impl = impl_from_IMFTransform(iface);
386 GUID major, subtype;
387 UINT64 frame_size;
388 HRESULT hr;
389 ULONG i;
391 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
393 if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major))
394 || !IsEqualGUID(&major, &MFMediaType_Video))
395 return E_INVALIDARG;
396 if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
397 return MF_E_INVALIDMEDIATYPE;
398 if (FAILED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
399 return hr;
401 for (i = 0; i < ARRAY_SIZE(output_types); ++i)
402 if (IsEqualGUID(&subtype, output_types[i]))
403 break;
404 if (i == ARRAY_SIZE(output_types))
405 return MF_E_INVALIDMEDIATYPE;
406 if (flags & MFT_SET_TYPE_TEST_ONLY)
407 return S_OK;
409 if (impl->output_type)
410 IMFMediaType_Release(impl->output_type);
411 IMFMediaType_AddRef((impl->output_type = type));
413 if (impl->input_type && FAILED(hr = try_create_wg_transform(impl)))
415 IMFMediaType_Release(impl->output_type);
416 impl->output_type = NULL;
419 if (FAILED(hr) || FAILED(MFCalculateImageSize(&subtype, frame_size >> 32, (UINT32)frame_size,
420 (UINT32 *)&impl->output_info.cbSize)))
421 impl->output_info.cbSize = 0;
423 return hr;
426 static HRESULT WINAPI video_processor_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
428 struct video_processor *impl = impl_from_IMFTransform(iface);
429 HRESULT hr;
431 TRACE("iface %p, id %#lx, type %p.\n", iface, id, type);
433 if (id != 0)
434 return MF_E_INVALIDSTREAMNUMBER;
436 if (!impl->input_type)
437 return MF_E_TRANSFORM_TYPE_NOT_SET;
439 if (FAILED(hr = MFCreateMediaType(type)))
440 return hr;
442 if (FAILED(hr = IMFMediaType_CopyAllItems(impl->input_type, (IMFAttributes *)*type)))
443 IMFMediaType_Release(*type);
445 return hr;
448 static HRESULT WINAPI video_processor_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
450 struct video_processor *impl = impl_from_IMFTransform(iface);
451 HRESULT hr;
453 TRACE("iface %p, id %#lx, type %p.\n", iface, id, type);
455 if (id != 0)
456 return MF_E_INVALIDSTREAMNUMBER;
458 if (!impl->output_type)
459 return MF_E_TRANSFORM_TYPE_NOT_SET;
461 if (FAILED(hr = MFCreateMediaType(type)))
462 return hr;
464 if (FAILED(hr = IMFMediaType_CopyAllItems(impl->output_type, (IMFAttributes *)*type)))
465 IMFMediaType_Release(*type);
467 return hr;
470 static HRESULT WINAPI video_processor_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
472 struct video_processor *impl = impl_from_IMFTransform(iface);
474 FIXME("iface %p, id %#lx, flags %p stub!\n", iface, id, flags);
476 if (!impl->input_type)
477 return MF_E_TRANSFORM_TYPE_NOT_SET;
479 *flags = MFT_INPUT_STATUS_ACCEPT_DATA;
480 return S_OK;
483 static HRESULT WINAPI video_processor_GetOutputStatus(IMFTransform *iface, DWORD *flags)
485 struct video_processor *impl = impl_from_IMFTransform(iface);
487 FIXME("iface %p, flags %p stub!\n", iface, flags);
489 if (!impl->output_type)
490 return MF_E_TRANSFORM_TYPE_NOT_SET;
492 return E_NOTIMPL;
495 static HRESULT WINAPI video_processor_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
497 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper);
498 return E_NOTIMPL;
501 static HRESULT WINAPI video_processor_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
503 FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event);
504 return E_NOTIMPL;
507 static HRESULT WINAPI video_processor_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
509 FIXME("iface %p, message %#x, param %#Ix stub!\n", iface, message, param);
510 return S_OK;
513 static HRESULT WINAPI video_processor_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
515 struct video_processor *impl = impl_from_IMFTransform(iface);
517 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags);
519 if (!impl->wg_transform)
520 return MF_E_TRANSFORM_TYPE_NOT_SET;
522 return wg_transform_push_mf(impl->wg_transform, sample, impl->wg_sample_queue);
525 static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
526 MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
528 struct video_processor *impl = impl_from_IMFTransform(iface);
529 MFT_OUTPUT_STREAM_INFO info;
530 HRESULT hr;
532 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
534 if (count != 1)
535 return E_INVALIDARG;
537 if (!impl->wg_transform)
538 return MF_E_TRANSFORM_TYPE_NOT_SET;
540 samples->dwStatus = 0;
541 if (!samples->pSample)
542 return E_INVALIDARG;
544 if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
545 return hr;
547 if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample,
548 info.cbSize, NULL, &samples->dwStatus)))
549 wg_sample_queue_flush(impl->wg_sample_queue, false);
551 return hr;
554 static const IMFTransformVtbl video_processor_vtbl =
556 video_processor_QueryInterface,
557 video_processor_AddRef,
558 video_processor_Release,
559 video_processor_GetStreamLimits,
560 video_processor_GetStreamCount,
561 video_processor_GetStreamIDs,
562 video_processor_GetInputStreamInfo,
563 video_processor_GetOutputStreamInfo,
564 video_processor_GetAttributes,
565 video_processor_GetInputStreamAttributes,
566 video_processor_GetOutputStreamAttributes,
567 video_processor_DeleteInputStream,
568 video_processor_AddInputStreams,
569 video_processor_GetInputAvailableType,
570 video_processor_GetOutputAvailableType,
571 video_processor_SetInputType,
572 video_processor_SetOutputType,
573 video_processor_GetInputCurrentType,
574 video_processor_GetOutputCurrentType,
575 video_processor_GetInputStatus,
576 video_processor_GetOutputStatus,
577 video_processor_SetOutputBounds,
578 video_processor_ProcessEvent,
579 video_processor_ProcessMessage,
580 video_processor_ProcessInput,
581 video_processor_ProcessOutput,
584 HRESULT video_processor_create(REFIID riid, void **ret)
586 static const struct wg_format input_format =
588 .major_type = WG_MAJOR_TYPE_VIDEO,
589 .u.video =
591 .format = WG_VIDEO_FORMAT_I420,
592 .width = 1920,
593 .height = 1080,
596 static const struct wg_format output_format =
598 .major_type = WG_MAJOR_TYPE_VIDEO,
599 .u.video =
601 .format = WG_VIDEO_FORMAT_NV12,
602 .width = 1920,
603 .height = 1080,
606 struct wg_transform_attrs attrs = {0};
607 wg_transform_t transform;
608 struct video_processor *impl;
609 HRESULT hr;
611 TRACE("riid %s, ret %p.\n", debugstr_guid(riid), ret);
613 if (!(transform = wg_transform_create(&input_format, &output_format, &attrs)))
615 ERR_(winediag)("GStreamer doesn't support video conversion, please install appropriate plugins.\n");
616 return E_FAIL;
618 wg_transform_destroy(transform);
620 if (!(impl = calloc(1, sizeof(*impl))))
621 return E_OUTOFMEMORY;
623 if (FAILED(hr = MFCreateAttributes(&impl->attributes, 0)))
624 goto failed;
625 if (FAILED(hr = MFCreateAttributes(&impl->output_attributes, 0)))
626 goto failed;
627 if (FAILED(hr = wg_sample_queue_create(&impl->wg_sample_queue)))
628 goto failed;
630 impl->IMFTransform_iface.lpVtbl = &video_processor_vtbl;
631 impl->refcount = 1;
633 *ret = &impl->IMFTransform_iface;
634 TRACE("Created %p\n", *ret);
635 return S_OK;
637 failed:
638 if (impl->output_attributes)
639 IMFAttributes_Release(impl->output_attributes);
640 if (impl->attributes)
641 IMFAttributes_Release(impl->attributes);
642 free(impl);
643 return hr;