include: Be consistent in naming regarding MSF's block.
[wine.git] / dlls / winegstreamer / color_convert.c
blob0eaddc687ee8b0577937c5d5b9430905223a734b
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 HRESULT hr;
367 ULONG i;
369 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
371 if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
372 FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
373 return MF_E_ATTRIBUTENOTFOUND;
375 if (!IsEqualGUID(&major, &MFMediaType_Video)
376 || IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))
377 return E_INVALIDARG;
379 for (i = 0; i < ARRAY_SIZE(input_types); ++i)
380 if (IsEqualGUID(&subtype, input_types[i]))
381 break;
382 if (i == ARRAY_SIZE(input_types))
383 return MF_E_INVALIDMEDIATYPE;
384 if (flags & MFT_SET_TYPE_TEST_ONLY)
385 return S_OK;
387 if (!impl->input_type && FAILED(hr = MFCreateMediaType(&impl->input_type)))
388 return hr;
390 if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)impl->input_type)))
392 IMFMediaType_Release(impl->input_type);
393 impl->input_type = NULL;
396 if (impl->output_type && FAILED(hr = try_create_wg_transform(impl)))
398 IMFMediaType_Release(impl->input_type);
399 impl->input_type = NULL;
402 if (FAILED(hr) || FAILED(MFCalculateImageSize(&subtype, frame_size >> 32, (UINT32)frame_size,
403 (UINT32 *)&impl->input_info.cbSize)))
404 impl->input_info.cbSize = 0;
406 return hr;
409 static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
411 struct color_convert *impl = impl_from_IMFTransform(iface);
412 GUID major, subtype;
413 UINT64 frame_size;
414 HRESULT hr;
415 ULONG i;
417 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
419 if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
420 FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
421 return MF_E_ATTRIBUTENOTFOUND;
423 if (!IsEqualGUID(&major, &MFMediaType_Video)
424 || IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))
425 return E_INVALIDARG;
427 for (i = 0; i < ARRAY_SIZE(output_types); ++i)
428 if (IsEqualGUID(&subtype, output_types[i]))
429 break;
430 if (i == ARRAY_SIZE(output_types))
431 return MF_E_INVALIDMEDIATYPE;
432 if (flags & MFT_SET_TYPE_TEST_ONLY)
433 return S_OK;
435 if (!impl->output_type && FAILED(hr = MFCreateMediaType(&impl->output_type)))
436 return hr;
438 if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)impl->output_type)))
440 IMFMediaType_Release(impl->output_type);
441 impl->output_type = NULL;
444 if (impl->input_type && FAILED(hr = try_create_wg_transform(impl)))
446 IMFMediaType_Release(impl->output_type);
447 impl->output_type = NULL;
450 if (FAILED(hr) || FAILED(MFCalculateImageSize(&subtype, frame_size >> 32, (UINT32)frame_size,
451 (UINT32 *)&impl->output_info.cbSize)))
452 impl->output_info.cbSize = 0;
454 return hr;
457 static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
459 struct color_convert *impl = impl_from_IMFTransform(iface);
460 HRESULT hr;
462 TRACE("iface %p, id %#lx, type %p.\n", iface, id, type);
464 if (id != 0)
465 return MF_E_INVALIDSTREAMNUMBER;
467 if (!impl->input_type)
468 return MF_E_TRANSFORM_TYPE_NOT_SET;
470 if (FAILED(hr = MFCreateMediaType(type)))
471 return hr;
473 if (FAILED(hr = IMFMediaType_CopyAllItems(impl->input_type, (IMFAttributes *)*type)))
474 IMFMediaType_Release(*type);
476 return hr;
479 static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
481 struct color_convert *impl = impl_from_IMFTransform(iface);
482 HRESULT hr;
484 TRACE("iface %p, id %#lx, type %p.\n", iface, id, type);
486 if (id != 0)
487 return MF_E_INVALIDSTREAMNUMBER;
489 if (!impl->output_type)
490 return MF_E_TRANSFORM_TYPE_NOT_SET;
492 if (FAILED(hr = MFCreateMediaType(type)))
493 return hr;
495 if (FAILED(hr = IMFMediaType_CopyAllItems(impl->output_type, (IMFAttributes *)*type)))
496 IMFMediaType_Release(*type);
498 return hr;
501 static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
503 FIXME("iface %p, id %#lx, flags %p stub!\n", iface, id, flags);
504 return E_NOTIMPL;
507 static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags)
509 FIXME("iface %p, flags %p stub!\n", iface, flags);
510 return E_NOTIMPL;
513 static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
515 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper);
516 return E_NOTIMPL;
519 static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
521 FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event);
522 return E_NOTIMPL;
525 static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
527 FIXME("iface %p, message %#x, param %#Ix stub!\n", iface, message, param);
528 return S_OK;
531 static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
533 struct color_convert *impl = impl_from_IMFTransform(iface);
535 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags);
537 if (!impl->wg_transform)
538 return MF_E_TRANSFORM_TYPE_NOT_SET;
540 return wg_transform_push_mf(impl->wg_transform, sample, impl->wg_sample_queue);
543 static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
544 MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
546 struct color_convert *impl = impl_from_IMFTransform(iface);
547 MFT_OUTPUT_STREAM_INFO info;
548 HRESULT hr;
550 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
552 if (count != 1)
553 return E_INVALIDARG;
555 if (!impl->wg_transform)
556 return MF_E_TRANSFORM_TYPE_NOT_SET;
558 *status = samples->dwStatus = 0;
559 if (!samples->pSample)
560 return E_INVALIDARG;
562 if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
563 return hr;
565 if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample,
566 info.cbSize, NULL, &samples->dwStatus)))
567 wg_sample_queue_flush(impl->wg_sample_queue, false);
569 return hr;
572 static const IMFTransformVtbl transform_vtbl =
574 transform_QueryInterface,
575 transform_AddRef,
576 transform_Release,
577 transform_GetStreamLimits,
578 transform_GetStreamCount,
579 transform_GetStreamIDs,
580 transform_GetInputStreamInfo,
581 transform_GetOutputStreamInfo,
582 transform_GetAttributes,
583 transform_GetInputStreamAttributes,
584 transform_GetOutputStreamAttributes,
585 transform_DeleteInputStream,
586 transform_AddInputStreams,
587 transform_GetInputAvailableType,
588 transform_GetOutputAvailableType,
589 transform_SetInputType,
590 transform_SetOutputType,
591 transform_GetInputCurrentType,
592 transform_GetOutputCurrentType,
593 transform_GetInputStatus,
594 transform_GetOutputStatus,
595 transform_SetOutputBounds,
596 transform_ProcessEvent,
597 transform_ProcessMessage,
598 transform_ProcessInput,
599 transform_ProcessOutput,
602 static inline struct color_convert *impl_from_IMediaObject(IMediaObject *iface)
604 return CONTAINING_RECORD(iface, struct color_convert, IMediaObject_iface);
607 static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
609 return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj);
612 static ULONG WINAPI media_object_AddRef(IMediaObject *iface)
614 return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer);
617 static ULONG WINAPI media_object_Release(IMediaObject *iface)
619 return IUnknown_Release(impl_from_IMediaObject(iface)->outer);
622 static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
624 FIXME("iface %p, input %p, output %p stub!\n", iface, input, output);
625 return E_NOTIMPL;
628 static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
630 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
631 return E_NOTIMPL;
634 static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
636 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
637 return E_NOTIMPL;
640 static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index,
641 DMO_MEDIA_TYPE *type)
643 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type);
644 return E_NOTIMPL;
647 static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index,
648 DMO_MEDIA_TYPE *type)
650 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type);
651 return E_NOTIMPL;
654 static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index,
655 const DMO_MEDIA_TYPE *type, DWORD flags)
657 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags);
658 return E_NOTIMPL;
661 static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index,
662 const DMO_MEDIA_TYPE *type, DWORD flags)
664 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags);
665 return E_NOTIMPL;
668 static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
670 FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type);
671 return E_NOTIMPL;
674 static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
676 FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type);
677 return E_NOTIMPL;
680 static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size,
681 DWORD *lookahead, DWORD *alignment)
683 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size,
684 lookahead, alignment);
685 return E_NOTIMPL;
688 static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment)
690 FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface, index, size, alignment);
691 return E_NOTIMPL;
694 static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency)
696 FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency);
697 return E_NOTIMPL;
700 static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency)
702 FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency));
703 return E_NOTIMPL;
706 static HRESULT WINAPI media_object_Flush(IMediaObject *iface)
708 FIXME("iface %p stub!\n", iface);
709 return E_NOTIMPL;
712 static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index)
714 FIXME("iface %p, index %lu stub!\n", iface, index);
715 return E_NOTIMPL;
718 static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface)
720 FIXME("iface %p stub!\n", iface);
721 return E_NOTIMPL;
724 static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface)
726 FIXME("iface %p stub!\n", iface);
727 return E_NOTIMPL;
730 static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags)
732 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
733 return E_NOTIMPL;
736 static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index,
737 IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength)
739 FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface,
740 index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength));
741 return E_NOTIMPL;
744 static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count,
745 DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
747 FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface, flags, count, buffers, status);
748 return E_NOTIMPL;
751 static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock)
753 FIXME("iface %p, lock %ld stub!\n", iface, lock);
754 return E_NOTIMPL;
757 static const IMediaObjectVtbl media_object_vtbl =
759 media_object_QueryInterface,
760 media_object_AddRef,
761 media_object_Release,
762 media_object_GetStreamCount,
763 media_object_GetInputStreamInfo,
764 media_object_GetOutputStreamInfo,
765 media_object_GetInputType,
766 media_object_GetOutputType,
767 media_object_SetInputType,
768 media_object_SetOutputType,
769 media_object_GetInputCurrentType,
770 media_object_GetOutputCurrentType,
771 media_object_GetInputSizeInfo,
772 media_object_GetOutputSizeInfo,
773 media_object_GetInputMaxLatency,
774 media_object_SetInputMaxLatency,
775 media_object_Flush,
776 media_object_Discontinuity,
777 media_object_AllocateStreamingResources,
778 media_object_FreeStreamingResources,
779 media_object_GetInputStatus,
780 media_object_ProcessInput,
781 media_object_ProcessOutput,
782 media_object_Lock,
785 static inline struct color_convert *impl_from_IPropertyBag(IPropertyBag *iface)
787 return CONTAINING_RECORD(iface, struct color_convert, IPropertyBag_iface);
790 static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out)
792 return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out);
795 static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface)
797 return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer);
800 static ULONG WINAPI property_bag_Release(IPropertyBag *iface)
802 return IUnknown_Release(impl_from_IPropertyBag(iface)->outer);
805 static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value,
806 IErrorLog *error_log)
808 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log);
809 return E_NOTIMPL;
812 static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value)
814 FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value);
815 return S_OK;
818 static const IPropertyBagVtbl property_bag_vtbl =
820 property_bag_QueryInterface,
821 property_bag_AddRef,
822 property_bag_Release,
823 property_bag_Read,
824 property_bag_Write,
827 static inline struct color_convert *impl_from_IPropertyStore(IPropertyStore *iface)
829 return CONTAINING_RECORD(iface, struct color_convert, IPropertyStore_iface);
832 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out)
834 return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out);
837 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
839 return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer);
842 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
844 return IUnknown_Release(impl_from_IPropertyStore(iface)->outer);
847 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
849 FIXME("iface %p, count %p stub!\n", iface, count);
850 return E_NOTIMPL;
853 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
855 FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key);
856 return E_NOTIMPL;
859 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
861 FIXME("iface %p, key %p, value %p stub!\n", iface, key, value);
862 return E_NOTIMPL;
865 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
867 FIXME("iface %p, key %p, value %p stub!\n", iface, key, value);
868 return E_NOTIMPL;
871 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
873 FIXME("iface %p stub!\n", iface);
874 return E_NOTIMPL;
877 static const IPropertyStoreVtbl property_store_vtbl =
879 property_store_QueryInterface,
880 property_store_AddRef,
881 property_store_Release,
882 property_store_GetCount,
883 property_store_GetAt,
884 property_store_GetValue,
885 property_store_SetValue,
886 property_store_Commit,
889 HRESULT color_convert_create(IUnknown *outer, IUnknown **out)
891 static const struct wg_format input_format =
893 .major_type = WG_MAJOR_TYPE_VIDEO,
894 .u.video =
896 .format = WG_VIDEO_FORMAT_I420,
897 .width = 1920,
898 .height = 1080,
901 static const struct wg_format output_format =
903 .major_type = WG_MAJOR_TYPE_VIDEO,
904 .u.video =
906 .format = WG_VIDEO_FORMAT_NV12,
907 .width = 1920,
908 .height = 1080,
911 struct wg_transform *transform;
912 struct color_convert *impl;
913 HRESULT hr;
915 TRACE("outer %p, out %p.\n", outer, out);
917 if (!(transform = wg_transform_create(&input_format, &output_format)))
919 ERR_(winediag)("GStreamer doesn't support video conversion, please install appropriate plugins.\n");
920 return E_FAIL;
922 wg_transform_destroy(transform);
924 if (!(impl = calloc(1, sizeof(*impl))))
925 return E_OUTOFMEMORY;
927 if (FAILED(hr = wg_sample_queue_create(&impl->wg_sample_queue)))
929 free(impl);
930 return hr;
933 impl->IUnknown_inner.lpVtbl = &unknown_vtbl;
934 impl->IMFTransform_iface.lpVtbl = &transform_vtbl;
935 impl->IMediaObject_iface.lpVtbl = &media_object_vtbl;
936 impl->IPropertyBag_iface.lpVtbl = &property_bag_vtbl;
937 impl->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
938 impl->refcount = 1;
939 impl->outer = outer ? outer : &impl->IUnknown_inner;
941 impl->input_info.cbAlignment = 1;
942 impl->output_info.cbAlignment = 1;
944 *out = &impl->IUnknown_inner;
945 TRACE("Created %p\n", *out);
946 return S_OK;