ntdll: Use a separate memory allocation for the kernel stack.
[wine.git] / dlls / winegstreamer / color_convert.c
blobed591c8e6695220dd1b43523ca0e7bd2633dbbca
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_YV12,
34 &MFVideoFormat_YUY2,
35 &MFVideoFormat_UYVY,
36 &MFVideoFormat_AYUV,
37 &MFVideoFormat_NV12,
38 &MFVideoFormat_RGB32,
39 &MFVideoFormat_RGB565,
40 &MFVideoFormat_I420,
41 &MFVideoFormat_IYUV,
42 &MFVideoFormat_YVYU,
43 &MFVideoFormat_RGB24,
44 &MFVideoFormat_RGB555,
45 &MEDIASUBTYPE_RGB8,
46 &MEDIASUBTYPE_V216,
47 &MEDIASUBTYPE_V410,
48 &MFVideoFormat_NV11,
49 &MFVideoFormat_Y41P,
50 &MFVideoFormat_Y41T,
51 &MFVideoFormat_Y42T,
52 &MFVideoFormat_YVU9,
54 static const GUID *const output_types[] =
56 &MFVideoFormat_YV12,
57 &MFVideoFormat_YUY2,
58 &MFVideoFormat_UYVY,
59 &MFVideoFormat_AYUV,
60 &MFVideoFormat_NV12,
61 &MFVideoFormat_RGB32,
62 &MFVideoFormat_RGB565,
63 &MFVideoFormat_I420,
64 &MFVideoFormat_IYUV,
65 &MFVideoFormat_YVYU,
66 &MFVideoFormat_RGB24,
67 &MFVideoFormat_RGB555,
68 &MEDIASUBTYPE_RGB8,
69 &MEDIASUBTYPE_V216,
70 &MEDIASUBTYPE_V410,
71 &MFVideoFormat_NV11,
74 struct color_convert
76 IUnknown IUnknown_inner;
77 IMFTransform IMFTransform_iface;
78 IMediaObject IMediaObject_iface;
79 IPropertyBag IPropertyBag_iface;
80 IPropertyStore IPropertyStore_iface;
81 IUnknown *outer;
82 LONG refcount;
84 IMFMediaType *input_type;
85 MFT_INPUT_STREAM_INFO input_info;
86 IMFMediaType *output_type;
87 MFT_OUTPUT_STREAM_INFO output_info;
89 struct wg_transform *wg_transform;
90 struct wg_sample_queue *wg_sample_queue;
93 static inline struct color_convert *impl_from_IUnknown(IUnknown *iface)
95 return CONTAINING_RECORD(iface, struct color_convert, IUnknown_inner);
98 static HRESULT try_create_wg_transform(struct color_convert *impl)
100 struct wg_format input_format, output_format;
102 if (impl->wg_transform)
103 wg_transform_destroy(impl->wg_transform);
104 impl->wg_transform = NULL;
106 mf_media_type_to_wg_format(impl->input_type, &input_format);
107 if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
108 return MF_E_INVALIDMEDIATYPE;
110 mf_media_type_to_wg_format(impl->output_type, &output_format);
111 if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
112 return MF_E_INVALIDMEDIATYPE;
114 if (!(impl->wg_transform = wg_transform_create(&input_format, &output_format)))
115 return E_FAIL;
117 return S_OK;
120 static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out)
122 struct color_convert *impl = impl_from_IUnknown(iface);
124 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
126 if (IsEqualGUID(iid, &IID_IUnknown))
127 *out = &impl->IUnknown_inner;
128 else if (IsEqualGUID(iid, &IID_IMFTransform))
129 *out = &impl->IMFTransform_iface;
130 else if (IsEqualGUID(iid, &IID_IMediaObject))
131 *out = &impl->IMediaObject_iface;
132 else if (IsEqualIID(iid, &IID_IPropertyBag))
133 *out = &impl->IPropertyBag_iface;
134 else if (IsEqualIID(iid, &IID_IPropertyStore))
135 *out = &impl->IPropertyStore_iface;
136 else
138 *out = NULL;
139 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
140 return E_NOINTERFACE;
143 IUnknown_AddRef((IUnknown *)*out);
144 return S_OK;
147 static ULONG WINAPI unknown_AddRef(IUnknown *iface)
149 struct color_convert *impl = impl_from_IUnknown(iface);
150 ULONG refcount = InterlockedIncrement(&impl->refcount);
152 TRACE("iface %p increasing refcount to %lu.\n", iface, refcount);
154 return refcount;
157 static ULONG WINAPI unknown_Release(IUnknown *iface)
159 struct color_convert *impl = impl_from_IUnknown(iface);
160 ULONG refcount = InterlockedDecrement(&impl->refcount);
162 TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount);
164 if (!refcount)
166 if (impl->wg_transform)
167 wg_transform_destroy(impl->wg_transform);
168 if (impl->input_type)
169 IMFMediaType_Release(impl->input_type);
170 if (impl->output_type)
171 IMFMediaType_Release(impl->output_type);
173 wg_sample_queue_destroy(impl->wg_sample_queue);
174 free(impl);
177 return refcount;
180 static const IUnknownVtbl unknown_vtbl =
182 unknown_QueryInterface,
183 unknown_AddRef,
184 unknown_Release,
187 static struct color_convert *impl_from_IMFTransform(IMFTransform *iface)
189 return CONTAINING_RECORD(iface, struct color_convert, IMFTransform_iface);
192 static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out)
194 return IUnknown_QueryInterface(impl_from_IMFTransform(iface)->outer, iid, out);
197 static ULONG WINAPI transform_AddRef(IMFTransform *iface)
199 return IUnknown_AddRef(impl_from_IMFTransform(iface)->outer);
202 static ULONG WINAPI transform_Release(IMFTransform *iface)
204 return IUnknown_Release(impl_from_IMFTransform(iface)->outer);
207 static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
208 DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
210 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
211 iface, input_minimum, input_maximum, output_minimum, output_maximum);
212 *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
213 return S_OK;
216 static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
218 TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs);
219 *inputs = *outputs = 1;
220 return S_OK;
223 static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
224 DWORD output_size, DWORD *outputs)
226 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface,
227 input_size, inputs, output_size, outputs);
228 return E_NOTIMPL;
231 static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
233 struct color_convert *impl = impl_from_IMFTransform(iface);
235 TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
237 if (!impl->input_type || !impl->output_type)
239 memset(info, 0, sizeof(*info));
240 return MF_E_TRANSFORM_TYPE_NOT_SET;
243 *info = impl->input_info;
244 return S_OK;
247 static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
249 struct color_convert *impl = impl_from_IMFTransform(iface);
251 TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
253 if (!impl->input_type || !impl->output_type)
255 memset(info, 0, sizeof(*info));
256 return MF_E_TRANSFORM_TYPE_NOT_SET;
259 *info = impl->output_info;
260 return S_OK;
263 static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
265 TRACE("iface %p, attributes %p.\n", iface, attributes);
266 return E_NOTIMPL;
269 static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
271 TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
272 return E_NOTIMPL;
275 static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
277 TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
278 return E_NOTIMPL;
281 static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id)
283 TRACE("iface %p, id %#lx.\n", iface, id);
284 return E_NOTIMPL;
287 static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
289 TRACE("iface %p, streams %lu, ids %p.\n", iface, streams, ids);
290 return E_NOTIMPL;
293 static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
294 IMFMediaType **type)
296 IMFMediaType *media_type;
297 const GUID *subtype;
298 HRESULT hr;
300 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
302 *type = NULL;
304 if (index >= ARRAY_SIZE(input_types))
305 return MF_E_NO_MORE_TYPES;
306 subtype = input_types[index];
308 if (FAILED(hr = MFCreateMediaType(&media_type)))
309 return hr;
311 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)))
312 goto done;
313 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, subtype)))
314 goto done;
315 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1)))
316 goto done;
317 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1)))
318 goto done;
320 IMFMediaType_AddRef((*type = media_type));
322 done:
323 IMFMediaType_Release(media_type);
324 return hr;
327 static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
328 IMFMediaType **type)
330 IMFMediaType *media_type;
331 const GUID *subtype;
332 HRESULT hr;
334 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
336 *type = NULL;
338 if (index >= ARRAY_SIZE(output_types))
339 return MF_E_NO_MORE_TYPES;
340 subtype = output_types[index];
342 if (FAILED(hr = MFCreateMediaType(&media_type)))
343 return hr;
345 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)))
346 goto done;
347 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, subtype)))
348 goto done;
349 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1)))
350 goto done;
351 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1)))
352 goto done;
354 IMFMediaType_AddRef((*type = media_type));
356 done:
357 IMFMediaType_Release(media_type);
358 return hr;
361 static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
363 struct color_convert *impl = impl_from_IMFTransform(iface);
364 GUID major, subtype;
365 UINT64 frame_size;
366 UINT32 stride;
367 HRESULT hr;
368 ULONG i;
370 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
372 if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
373 FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
374 return MF_E_ATTRIBUTENOTFOUND;
376 if (!IsEqualGUID(&major, &MFMediaType_Video)
377 || IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))
378 return E_INVALIDARG;
380 for (i = 0; i < ARRAY_SIZE(input_types); ++i)
381 if (IsEqualGUID(&subtype, input_types[i]))
382 break;
383 if (i == ARRAY_SIZE(input_types))
384 return MF_E_INVALIDMEDIATYPE;
385 if (flags & MFT_SET_TYPE_TEST_ONLY)
386 return S_OK;
388 if (!impl->input_type && FAILED(hr = MFCreateMediaType(&impl->input_type)))
389 return hr;
391 if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)impl->input_type)))
393 IMFMediaType_Release(impl->input_type);
394 impl->input_type = NULL;
396 if (FAILED(IMFMediaType_GetUINT32(impl->input_type, &MF_MT_DEFAULT_STRIDE, &stride)))
398 if (FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, frame_size >> 32, (LONG *)&stride)))
400 IMFMediaType_Release(impl->input_type);
401 impl->input_type = NULL;
403 if (FAILED(hr = IMFMediaType_SetUINT32(impl->input_type, &MF_MT_DEFAULT_STRIDE, abs((INT32)stride))))
405 IMFMediaType_Release(impl->input_type);
406 impl->input_type = NULL;
410 if (impl->output_type && FAILED(hr = try_create_wg_transform(impl)))
412 IMFMediaType_Release(impl->input_type);
413 impl->input_type = NULL;
416 if (FAILED(hr) || FAILED(MFCalculateImageSize(&subtype, frame_size >> 32, (UINT32)frame_size,
417 (UINT32 *)&impl->input_info.cbSize)))
418 impl->input_info.cbSize = 0;
420 return hr;
423 static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
425 struct color_convert *impl = impl_from_IMFTransform(iface);
426 GUID major, subtype;
427 UINT64 frame_size;
428 UINT32 stride;
429 HRESULT hr;
430 ULONG i;
432 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
434 if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
435 FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
436 return MF_E_ATTRIBUTENOTFOUND;
438 if (!IsEqualGUID(&major, &MFMediaType_Video)
439 || IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))
440 return E_INVALIDARG;
442 for (i = 0; i < ARRAY_SIZE(output_types); ++i)
443 if (IsEqualGUID(&subtype, output_types[i]))
444 break;
445 if (i == ARRAY_SIZE(output_types))
446 return MF_E_INVALIDMEDIATYPE;
447 if (flags & MFT_SET_TYPE_TEST_ONLY)
448 return S_OK;
450 if (!impl->output_type && FAILED(hr = MFCreateMediaType(&impl->output_type)))
451 return hr;
453 if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)impl->output_type)))
455 IMFMediaType_Release(impl->output_type);
456 impl->output_type = NULL;
458 if (FAILED(IMFMediaType_GetUINT32(impl->output_type, &MF_MT_DEFAULT_STRIDE, &stride)))
460 if (FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, frame_size >> 32, (LONG *)&stride)))
462 IMFMediaType_Release(impl->output_type);
463 impl->output_type = NULL;
465 if (FAILED(hr = IMFMediaType_SetUINT32(impl->output_type, &MF_MT_DEFAULT_STRIDE, abs((INT32)stride))))
467 IMFMediaType_Release(impl->output_type);
468 impl->output_type = NULL;
472 if (impl->input_type && FAILED(hr = try_create_wg_transform(impl)))
474 IMFMediaType_Release(impl->output_type);
475 impl->output_type = NULL;
478 if (FAILED(hr) || FAILED(MFCalculateImageSize(&subtype, frame_size >> 32, (UINT32)frame_size,
479 (UINT32 *)&impl->output_info.cbSize)))
480 impl->output_info.cbSize = 0;
482 return hr;
485 static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
487 struct color_convert *impl = impl_from_IMFTransform(iface);
488 HRESULT hr;
490 TRACE("iface %p, id %#lx, type %p.\n", iface, id, type);
492 if (id != 0)
493 return MF_E_INVALIDSTREAMNUMBER;
495 if (!impl->input_type)
496 return MF_E_TRANSFORM_TYPE_NOT_SET;
498 if (FAILED(hr = MFCreateMediaType(type)))
499 return hr;
501 if (FAILED(hr = IMFMediaType_CopyAllItems(impl->input_type, (IMFAttributes *)*type)))
502 IMFMediaType_Release(*type);
504 return hr;
507 static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
509 struct color_convert *impl = impl_from_IMFTransform(iface);
510 HRESULT hr;
512 TRACE("iface %p, id %#lx, type %p.\n", iface, id, type);
514 if (id != 0)
515 return MF_E_INVALIDSTREAMNUMBER;
517 if (!impl->output_type)
518 return MF_E_TRANSFORM_TYPE_NOT_SET;
520 if (FAILED(hr = MFCreateMediaType(type)))
521 return hr;
523 if (FAILED(hr = IMFMediaType_CopyAllItems(impl->output_type, (IMFAttributes *)*type)))
524 IMFMediaType_Release(*type);
526 return hr;
529 static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
531 FIXME("iface %p, id %#lx, flags %p stub!\n", iface, id, flags);
532 return E_NOTIMPL;
535 static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags)
537 FIXME("iface %p, flags %p stub!\n", iface, flags);
538 return E_NOTIMPL;
541 static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
543 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper);
544 return E_NOTIMPL;
547 static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
549 FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event);
550 return E_NOTIMPL;
553 static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
555 FIXME("iface %p, message %#x, param %#Ix stub!\n", iface, message, param);
556 return S_OK;
559 static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
561 struct color_convert *impl = impl_from_IMFTransform(iface);
563 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags);
565 if (!impl->wg_transform)
566 return MF_E_TRANSFORM_TYPE_NOT_SET;
568 return wg_transform_push_mf(impl->wg_transform, sample, impl->wg_sample_queue);
571 static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
572 MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
574 struct color_convert *impl = impl_from_IMFTransform(iface);
575 MFT_OUTPUT_STREAM_INFO info;
576 HRESULT hr;
578 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
580 if (count != 1)
581 return E_INVALIDARG;
583 if (!impl->wg_transform)
584 return MF_E_TRANSFORM_TYPE_NOT_SET;
586 *status = samples->dwStatus = 0;
587 if (!samples->pSample)
588 return E_INVALIDARG;
590 if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
591 return hr;
593 if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample,
594 info.cbSize, NULL, &samples->dwStatus)))
595 wg_sample_queue_flush(impl->wg_sample_queue, false);
597 return hr;
600 static const IMFTransformVtbl transform_vtbl =
602 transform_QueryInterface,
603 transform_AddRef,
604 transform_Release,
605 transform_GetStreamLimits,
606 transform_GetStreamCount,
607 transform_GetStreamIDs,
608 transform_GetInputStreamInfo,
609 transform_GetOutputStreamInfo,
610 transform_GetAttributes,
611 transform_GetInputStreamAttributes,
612 transform_GetOutputStreamAttributes,
613 transform_DeleteInputStream,
614 transform_AddInputStreams,
615 transform_GetInputAvailableType,
616 transform_GetOutputAvailableType,
617 transform_SetInputType,
618 transform_SetOutputType,
619 transform_GetInputCurrentType,
620 transform_GetOutputCurrentType,
621 transform_GetInputStatus,
622 transform_GetOutputStatus,
623 transform_SetOutputBounds,
624 transform_ProcessEvent,
625 transform_ProcessMessage,
626 transform_ProcessInput,
627 transform_ProcessOutput,
630 static inline struct color_convert *impl_from_IMediaObject(IMediaObject *iface)
632 return CONTAINING_RECORD(iface, struct color_convert, IMediaObject_iface);
635 static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
637 return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj);
640 static ULONG WINAPI media_object_AddRef(IMediaObject *iface)
642 return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer);
645 static ULONG WINAPI media_object_Release(IMediaObject *iface)
647 return IUnknown_Release(impl_from_IMediaObject(iface)->outer);
650 static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
652 FIXME("iface %p, input %p, output %p stub!\n", iface, input, output);
653 return E_NOTIMPL;
656 static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
658 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
659 return E_NOTIMPL;
662 static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
664 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
665 return E_NOTIMPL;
668 static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index,
669 DMO_MEDIA_TYPE *type)
671 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type);
672 return E_NOTIMPL;
675 static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index,
676 DMO_MEDIA_TYPE *type)
678 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type);
679 return E_NOTIMPL;
682 static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index,
683 const DMO_MEDIA_TYPE *type, DWORD flags)
685 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags);
686 return E_NOTIMPL;
689 static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index,
690 const DMO_MEDIA_TYPE *type, DWORD flags)
692 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags);
693 return E_NOTIMPL;
696 static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
698 FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type);
699 return E_NOTIMPL;
702 static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
704 FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type);
705 return E_NOTIMPL;
708 static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size,
709 DWORD *lookahead, DWORD *alignment)
711 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size,
712 lookahead, alignment);
713 return E_NOTIMPL;
716 static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment)
718 FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface, index, size, alignment);
719 return E_NOTIMPL;
722 static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency)
724 FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency);
725 return E_NOTIMPL;
728 static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency)
730 FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency));
731 return E_NOTIMPL;
734 static HRESULT WINAPI media_object_Flush(IMediaObject *iface)
736 FIXME("iface %p stub!\n", iface);
737 return E_NOTIMPL;
740 static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index)
742 FIXME("iface %p, index %lu stub!\n", iface, index);
743 return E_NOTIMPL;
746 static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface)
748 FIXME("iface %p stub!\n", iface);
749 return E_NOTIMPL;
752 static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface)
754 FIXME("iface %p stub!\n", iface);
755 return E_NOTIMPL;
758 static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags)
760 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
761 return E_NOTIMPL;
764 static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index,
765 IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength)
767 FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface,
768 index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength));
769 return E_NOTIMPL;
772 static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count,
773 DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
775 FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface, flags, count, buffers, status);
776 return E_NOTIMPL;
779 static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock)
781 FIXME("iface %p, lock %ld stub!\n", iface, lock);
782 return E_NOTIMPL;
785 static const IMediaObjectVtbl media_object_vtbl =
787 media_object_QueryInterface,
788 media_object_AddRef,
789 media_object_Release,
790 media_object_GetStreamCount,
791 media_object_GetInputStreamInfo,
792 media_object_GetOutputStreamInfo,
793 media_object_GetInputType,
794 media_object_GetOutputType,
795 media_object_SetInputType,
796 media_object_SetOutputType,
797 media_object_GetInputCurrentType,
798 media_object_GetOutputCurrentType,
799 media_object_GetInputSizeInfo,
800 media_object_GetOutputSizeInfo,
801 media_object_GetInputMaxLatency,
802 media_object_SetInputMaxLatency,
803 media_object_Flush,
804 media_object_Discontinuity,
805 media_object_AllocateStreamingResources,
806 media_object_FreeStreamingResources,
807 media_object_GetInputStatus,
808 media_object_ProcessInput,
809 media_object_ProcessOutput,
810 media_object_Lock,
813 static inline struct color_convert *impl_from_IPropertyBag(IPropertyBag *iface)
815 return CONTAINING_RECORD(iface, struct color_convert, IPropertyBag_iface);
818 static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out)
820 return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out);
823 static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface)
825 return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer);
828 static ULONG WINAPI property_bag_Release(IPropertyBag *iface)
830 return IUnknown_Release(impl_from_IPropertyBag(iface)->outer);
833 static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value,
834 IErrorLog *error_log)
836 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log);
837 return E_NOTIMPL;
840 static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value)
842 FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value);
843 return S_OK;
846 static const IPropertyBagVtbl property_bag_vtbl =
848 property_bag_QueryInterface,
849 property_bag_AddRef,
850 property_bag_Release,
851 property_bag_Read,
852 property_bag_Write,
855 static inline struct color_convert *impl_from_IPropertyStore(IPropertyStore *iface)
857 return CONTAINING_RECORD(iface, struct color_convert, IPropertyStore_iface);
860 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out)
862 return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out);
865 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
867 return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer);
870 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
872 return IUnknown_Release(impl_from_IPropertyStore(iface)->outer);
875 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
877 FIXME("iface %p, count %p stub!\n", iface, count);
878 return E_NOTIMPL;
881 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
883 FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key);
884 return E_NOTIMPL;
887 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
889 FIXME("iface %p, key %p, value %p stub!\n", iface, key, value);
890 return E_NOTIMPL;
893 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
895 FIXME("iface %p, key %p, value %p stub!\n", iface, key, value);
896 return E_NOTIMPL;
899 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
901 FIXME("iface %p stub!\n", iface);
902 return E_NOTIMPL;
905 static const IPropertyStoreVtbl property_store_vtbl =
907 property_store_QueryInterface,
908 property_store_AddRef,
909 property_store_Release,
910 property_store_GetCount,
911 property_store_GetAt,
912 property_store_GetValue,
913 property_store_SetValue,
914 property_store_Commit,
917 HRESULT color_convert_create(IUnknown *outer, IUnknown **out)
919 static const struct wg_format input_format =
921 .major_type = WG_MAJOR_TYPE_VIDEO,
922 .u.video =
924 .format = WG_VIDEO_FORMAT_I420,
925 .width = 1920,
926 .height = 1080,
929 static const struct wg_format output_format =
931 .major_type = WG_MAJOR_TYPE_VIDEO,
932 .u.video =
934 .format = WG_VIDEO_FORMAT_NV12,
935 .width = 1920,
936 .height = 1080,
939 struct wg_transform *transform;
940 struct color_convert *impl;
941 HRESULT hr;
943 TRACE("outer %p, out %p.\n", outer, out);
945 if (!(transform = wg_transform_create(&input_format, &output_format)))
947 ERR_(winediag)("GStreamer doesn't support video conversion, please install appropriate plugins.\n");
948 return E_FAIL;
950 wg_transform_destroy(transform);
952 if (!(impl = calloc(1, sizeof(*impl))))
953 return E_OUTOFMEMORY;
955 if (FAILED(hr = wg_sample_queue_create(&impl->wg_sample_queue)))
957 free(impl);
958 return hr;
961 impl->IUnknown_inner.lpVtbl = &unknown_vtbl;
962 impl->IMFTransform_iface.lpVtbl = &transform_vtbl;
963 impl->IMediaObject_iface.lpVtbl = &media_object_vtbl;
964 impl->IPropertyBag_iface.lpVtbl = &property_bag_vtbl;
965 impl->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
966 impl->refcount = 1;
967 impl->outer = outer ? outer : &impl->IUnknown_inner;
969 impl->input_info.cbAlignment = 1;
970 impl->output_info.cbAlignment = 1;
972 *out = &impl->IUnknown_inner;
973 TRACE("Created %p\n", *out);
974 return S_OK;