wow64: Use the right SEH opcode in raise_exception on arm64.
[wine.git] / dlls / winegstreamer / color_convert.c
blob7ffe29de90747d09f92988cb52e3cc25c1c57004
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 struct wg_sample *wg_sample;
549 HRESULT hr;
551 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
553 if (count != 1)
554 return E_INVALIDARG;
556 if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
557 return hr;
559 if (!impl->wg_transform)
560 return MF_E_TRANSFORM_TYPE_NOT_SET;
562 *status = 0;
563 samples[0].dwStatus = 0;
564 if (!samples[0].pSample) return E_INVALIDARG;
566 if (FAILED(hr = wg_sample_create_mf(samples[0].pSample, &wg_sample)))
567 return hr;
569 if (wg_sample->max_size < info.cbSize)
571 wg_sample_release(wg_sample);
572 return MF_E_BUFFERTOOSMALL;
575 if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, wg_sample, NULL,
576 &samples[0].dwStatus)))
577 wg_sample_queue_flush(impl->wg_sample_queue, false);
579 wg_sample_release(wg_sample);
581 return hr;
584 static const IMFTransformVtbl transform_vtbl =
586 transform_QueryInterface,
587 transform_AddRef,
588 transform_Release,
589 transform_GetStreamLimits,
590 transform_GetStreamCount,
591 transform_GetStreamIDs,
592 transform_GetInputStreamInfo,
593 transform_GetOutputStreamInfo,
594 transform_GetAttributes,
595 transform_GetInputStreamAttributes,
596 transform_GetOutputStreamAttributes,
597 transform_DeleteInputStream,
598 transform_AddInputStreams,
599 transform_GetInputAvailableType,
600 transform_GetOutputAvailableType,
601 transform_SetInputType,
602 transform_SetOutputType,
603 transform_GetInputCurrentType,
604 transform_GetOutputCurrentType,
605 transform_GetInputStatus,
606 transform_GetOutputStatus,
607 transform_SetOutputBounds,
608 transform_ProcessEvent,
609 transform_ProcessMessage,
610 transform_ProcessInput,
611 transform_ProcessOutput,
614 static inline struct color_convert *impl_from_IMediaObject(IMediaObject *iface)
616 return CONTAINING_RECORD(iface, struct color_convert, IMediaObject_iface);
619 static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
621 return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj);
624 static ULONG WINAPI media_object_AddRef(IMediaObject *iface)
626 return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer);
629 static ULONG WINAPI media_object_Release(IMediaObject *iface)
631 return IUnknown_Release(impl_from_IMediaObject(iface)->outer);
634 static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
636 FIXME("iface %p, input %p, output %p stub!\n", iface, input, output);
637 return E_NOTIMPL;
640 static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
642 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
643 return E_NOTIMPL;
646 static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
648 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
649 return E_NOTIMPL;
652 static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index,
653 DMO_MEDIA_TYPE *type)
655 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type);
656 return E_NOTIMPL;
659 static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index,
660 DMO_MEDIA_TYPE *type)
662 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type);
663 return E_NOTIMPL;
666 static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index,
667 const DMO_MEDIA_TYPE *type, DWORD flags)
669 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags);
670 return E_NOTIMPL;
673 static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index,
674 const DMO_MEDIA_TYPE *type, DWORD flags)
676 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags);
677 return E_NOTIMPL;
680 static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
682 FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type);
683 return E_NOTIMPL;
686 static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
688 FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type);
689 return E_NOTIMPL;
692 static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size,
693 DWORD *lookahead, DWORD *alignment)
695 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size,
696 lookahead, alignment);
697 return E_NOTIMPL;
700 static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment)
702 FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface, index, size, alignment);
703 return E_NOTIMPL;
706 static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency)
708 FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency);
709 return E_NOTIMPL;
712 static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency)
714 FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency));
715 return E_NOTIMPL;
718 static HRESULT WINAPI media_object_Flush(IMediaObject *iface)
720 FIXME("iface %p stub!\n", iface);
721 return E_NOTIMPL;
724 static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index)
726 FIXME("iface %p, index %lu stub!\n", iface, index);
727 return E_NOTIMPL;
730 static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface)
732 FIXME("iface %p stub!\n", iface);
733 return E_NOTIMPL;
736 static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface)
738 FIXME("iface %p stub!\n", iface);
739 return E_NOTIMPL;
742 static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags)
744 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
745 return E_NOTIMPL;
748 static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index,
749 IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength)
751 FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface,
752 index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength));
753 return E_NOTIMPL;
756 static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count,
757 DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
759 FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface, flags, count, buffers, status);
760 return E_NOTIMPL;
763 static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock)
765 FIXME("iface %p, lock %ld stub!\n", iface, lock);
766 return E_NOTIMPL;
769 static const IMediaObjectVtbl media_object_vtbl =
771 media_object_QueryInterface,
772 media_object_AddRef,
773 media_object_Release,
774 media_object_GetStreamCount,
775 media_object_GetInputStreamInfo,
776 media_object_GetOutputStreamInfo,
777 media_object_GetInputType,
778 media_object_GetOutputType,
779 media_object_SetInputType,
780 media_object_SetOutputType,
781 media_object_GetInputCurrentType,
782 media_object_GetOutputCurrentType,
783 media_object_GetInputSizeInfo,
784 media_object_GetOutputSizeInfo,
785 media_object_GetInputMaxLatency,
786 media_object_SetInputMaxLatency,
787 media_object_Flush,
788 media_object_Discontinuity,
789 media_object_AllocateStreamingResources,
790 media_object_FreeStreamingResources,
791 media_object_GetInputStatus,
792 media_object_ProcessInput,
793 media_object_ProcessOutput,
794 media_object_Lock,
797 static inline struct color_convert *impl_from_IPropertyBag(IPropertyBag *iface)
799 return CONTAINING_RECORD(iface, struct color_convert, IPropertyBag_iface);
802 static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out)
804 return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out);
807 static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface)
809 return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer);
812 static ULONG WINAPI property_bag_Release(IPropertyBag *iface)
814 return IUnknown_Release(impl_from_IPropertyBag(iface)->outer);
817 static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value,
818 IErrorLog *error_log)
820 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log);
821 return E_NOTIMPL;
824 static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value)
826 FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value);
827 return S_OK;
830 static const IPropertyBagVtbl property_bag_vtbl =
832 property_bag_QueryInterface,
833 property_bag_AddRef,
834 property_bag_Release,
835 property_bag_Read,
836 property_bag_Write,
839 static inline struct color_convert *impl_from_IPropertyStore(IPropertyStore *iface)
841 return CONTAINING_RECORD(iface, struct color_convert, IPropertyStore_iface);
844 static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out)
846 return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out);
849 static ULONG WINAPI property_store_AddRef(IPropertyStore *iface)
851 return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer);
854 static ULONG WINAPI property_store_Release(IPropertyStore *iface)
856 return IUnknown_Release(impl_from_IPropertyStore(iface)->outer);
859 static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count)
861 FIXME("iface %p, count %p stub!\n", iface, count);
862 return E_NOTIMPL;
865 static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key)
867 FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key);
868 return E_NOTIMPL;
871 static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
873 FIXME("iface %p, key %p, value %p stub!\n", iface, key, value);
874 return E_NOTIMPL;
877 static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
879 FIXME("iface %p, key %p, value %p stub!\n", iface, key, value);
880 return E_NOTIMPL;
883 static HRESULT WINAPI property_store_Commit(IPropertyStore *iface)
885 FIXME("iface %p stub!\n", iface);
886 return E_NOTIMPL;
889 static const IPropertyStoreVtbl property_store_vtbl =
891 property_store_QueryInterface,
892 property_store_AddRef,
893 property_store_Release,
894 property_store_GetCount,
895 property_store_GetAt,
896 property_store_GetValue,
897 property_store_SetValue,
898 property_store_Commit,
901 HRESULT color_convert_create(IUnknown *outer, IUnknown **out)
903 static const struct wg_format input_format =
905 .major_type = WG_MAJOR_TYPE_VIDEO,
906 .u.video =
908 .format = WG_VIDEO_FORMAT_I420,
909 .width = 1920,
910 .height = 1080,
913 static const struct wg_format output_format =
915 .major_type = WG_MAJOR_TYPE_VIDEO,
916 .u.video =
918 .format = WG_VIDEO_FORMAT_NV12,
919 .width = 1920,
920 .height = 1080,
923 struct wg_transform *transform;
924 struct color_convert *impl;
925 HRESULT hr;
927 TRACE("outer %p, out %p.\n", outer, out);
929 if (!(transform = wg_transform_create(&input_format, &output_format)))
931 ERR_(winediag)("GStreamer doesn't support video conversion, please install appropriate plugins.\n");
932 return E_FAIL;
934 wg_transform_destroy(transform);
936 if (!(impl = calloc(1, sizeof(*impl))))
937 return E_OUTOFMEMORY;
939 if (FAILED(hr = wg_sample_queue_create(&impl->wg_sample_queue)))
941 free(impl);
942 return hr;
945 impl->IUnknown_inner.lpVtbl = &unknown_vtbl;
946 impl->IMFTransform_iface.lpVtbl = &transform_vtbl;
947 impl->IMediaObject_iface.lpVtbl = &media_object_vtbl;
948 impl->IPropertyBag_iface.lpVtbl = &property_bag_vtbl;
949 impl->IPropertyStore_iface.lpVtbl = &property_store_vtbl;
950 impl->refcount = 1;
951 impl->outer = outer ? outer : &impl->IUnknown_inner;
953 impl->input_info.cbAlignment = 1;
954 impl->output_info.cbAlignment = 1;
956 *out = &impl->IUnknown_inner;
957 TRACE("Created %p\n", *out);
958 return S_OK;