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"
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
[] =
39 &MFVideoFormat_RGB565
,
44 &MFVideoFormat_RGB555
,
54 static const GUID
*const output_types
[] =
62 &MFVideoFormat_RGB565
,
67 &MFVideoFormat_RGB555
,
76 IUnknown IUnknown_inner
;
77 IMFTransform IMFTransform_iface
;
78 IMediaObject IMediaObject_iface
;
79 IPropertyBag IPropertyBag_iface
;
80 IPropertyStore IPropertyStore_iface
;
84 IMFMediaType
*input_type
;
85 MFT_INPUT_STREAM_INFO input_info
;
86 IMFMediaType
*output_type
;
87 MFT_OUTPUT_STREAM_INFO output_info
;
89 wg_transform_t 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
;
101 struct wg_transform_attrs attrs
= {0};
103 if (impl
->wg_transform
)
104 wg_transform_destroy(impl
->wg_transform
);
105 impl
->wg_transform
= 0;
107 mf_media_type_to_wg_format(impl
->input_type
, &input_format
);
108 if (input_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
109 return MF_E_INVALIDMEDIATYPE
;
111 mf_media_type_to_wg_format(impl
->output_type
, &output_format
);
112 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
113 return MF_E_INVALIDMEDIATYPE
;
115 if (!(impl
->wg_transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
121 static HRESULT WINAPI
unknown_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
123 struct color_convert
*impl
= impl_from_IUnknown(iface
);
125 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
127 if (IsEqualGUID(iid
, &IID_IUnknown
))
128 *out
= &impl
->IUnknown_inner
;
129 else if (IsEqualGUID(iid
, &IID_IMFTransform
))
130 *out
= &impl
->IMFTransform_iface
;
131 else if (IsEqualGUID(iid
, &IID_IMediaObject
))
132 *out
= &impl
->IMediaObject_iface
;
133 else if (IsEqualIID(iid
, &IID_IPropertyBag
))
134 *out
= &impl
->IPropertyBag_iface
;
135 else if (IsEqualIID(iid
, &IID_IPropertyStore
))
136 *out
= &impl
->IPropertyStore_iface
;
140 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
141 return E_NOINTERFACE
;
144 IUnknown_AddRef((IUnknown
*)*out
);
148 static ULONG WINAPI
unknown_AddRef(IUnknown
*iface
)
150 struct color_convert
*impl
= impl_from_IUnknown(iface
);
151 ULONG refcount
= InterlockedIncrement(&impl
->refcount
);
153 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
158 static ULONG WINAPI
unknown_Release(IUnknown
*iface
)
160 struct color_convert
*impl
= impl_from_IUnknown(iface
);
161 ULONG refcount
= InterlockedDecrement(&impl
->refcount
);
163 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
167 if (impl
->wg_transform
)
168 wg_transform_destroy(impl
->wg_transform
);
169 if (impl
->input_type
)
170 IMFMediaType_Release(impl
->input_type
);
171 if (impl
->output_type
)
172 IMFMediaType_Release(impl
->output_type
);
174 wg_sample_queue_destroy(impl
->wg_sample_queue
);
181 static const IUnknownVtbl unknown_vtbl
=
183 unknown_QueryInterface
,
188 static struct color_convert
*impl_from_IMFTransform(IMFTransform
*iface
)
190 return CONTAINING_RECORD(iface
, struct color_convert
, IMFTransform_iface
);
193 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
195 return IUnknown_QueryInterface(impl_from_IMFTransform(iface
)->outer
, iid
, out
);
198 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
200 return IUnknown_AddRef(impl_from_IMFTransform(iface
)->outer
);
203 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
205 return IUnknown_Release(impl_from_IMFTransform(iface
)->outer
);
208 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
209 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
211 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
212 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
213 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
217 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
219 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
220 *inputs
= *outputs
= 1;
224 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
225 DWORD output_size
, DWORD
*outputs
)
227 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
228 input_size
, inputs
, output_size
, outputs
);
232 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
234 struct color_convert
*impl
= impl_from_IMFTransform(iface
);
236 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
238 if (!impl
->input_type
|| !impl
->output_type
)
240 memset(info
, 0, sizeof(*info
));
241 return MF_E_TRANSFORM_TYPE_NOT_SET
;
244 *info
= impl
->input_info
;
248 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
250 struct color_convert
*impl
= impl_from_IMFTransform(iface
);
252 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
254 if (!impl
->input_type
|| !impl
->output_type
)
256 memset(info
, 0, sizeof(*info
));
257 return MF_E_TRANSFORM_TYPE_NOT_SET
;
260 *info
= impl
->output_info
;
264 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
266 TRACE("iface %p, attributes %p.\n", iface
, attributes
);
270 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
272 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
276 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
278 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
282 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
284 TRACE("iface %p, id %#lx.\n", iface
, id
);
288 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
290 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
294 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
297 IMFMediaType
*media_type
;
301 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
305 if (index
>= ARRAY_SIZE(input_types
))
306 return MF_E_NO_MORE_TYPES
;
307 subtype
= input_types
[index
];
309 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
312 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)))
314 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
316 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, 1)))
318 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, 1)))
321 IMFMediaType_AddRef((*type
= media_type
));
324 IMFMediaType_Release(media_type
);
328 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
331 IMFMediaType
*media_type
;
335 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
339 if (index
>= ARRAY_SIZE(output_types
))
340 return MF_E_NO_MORE_TYPES
;
341 subtype
= output_types
[index
];
343 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
346 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)))
348 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
350 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, 1)))
352 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, 1)))
355 IMFMediaType_AddRef((*type
= media_type
));
358 IMFMediaType_Release(media_type
);
362 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
364 struct color_convert
*impl
= impl_from_IMFTransform(iface
);
371 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
373 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
374 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
375 return MF_E_ATTRIBUTENOTFOUND
;
377 if (!IsEqualGUID(&major
, &MFMediaType_Video
)
378 || IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
))
381 for (i
= 0; i
< ARRAY_SIZE(input_types
); ++i
)
382 if (IsEqualGUID(&subtype
, input_types
[i
]))
384 if (i
== ARRAY_SIZE(input_types
))
385 return MF_E_INVALIDMEDIATYPE
;
386 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
389 if (!impl
->input_type
&& FAILED(hr
= MFCreateMediaType(&impl
->input_type
)))
392 if (FAILED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)impl
->input_type
)))
394 IMFMediaType_Release(impl
->input_type
);
395 impl
->input_type
= NULL
;
397 if (FAILED(IMFMediaType_GetUINT32(impl
->input_type
, &MF_MT_DEFAULT_STRIDE
, &stride
)))
399 if (FAILED(hr
= MFGetStrideForBitmapInfoHeader(subtype
.Data1
, frame_size
>> 32, (LONG
*)&stride
)))
401 IMFMediaType_Release(impl
->input_type
);
402 impl
->input_type
= NULL
;
404 if (FAILED(hr
= IMFMediaType_SetUINT32(impl
->input_type
, &MF_MT_DEFAULT_STRIDE
, abs((INT32
)stride
))))
406 IMFMediaType_Release(impl
->input_type
);
407 impl
->input_type
= NULL
;
411 if (impl
->output_type
&& FAILED(hr
= try_create_wg_transform(impl
)))
413 IMFMediaType_Release(impl
->input_type
);
414 impl
->input_type
= NULL
;
417 if (FAILED(hr
) || FAILED(MFCalculateImageSize(&subtype
, frame_size
>> 32, (UINT32
)frame_size
,
418 (UINT32
*)&impl
->input_info
.cbSize
)))
419 impl
->input_info
.cbSize
= 0;
424 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
426 struct color_convert
*impl
= impl_from_IMFTransform(iface
);
433 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
435 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
436 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
437 return MF_E_ATTRIBUTENOTFOUND
;
439 if (!IsEqualGUID(&major
, &MFMediaType_Video
)
440 || IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
))
443 for (i
= 0; i
< ARRAY_SIZE(output_types
); ++i
)
444 if (IsEqualGUID(&subtype
, output_types
[i
]))
446 if (i
== ARRAY_SIZE(output_types
))
447 return MF_E_INVALIDMEDIATYPE
;
448 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
451 if (!impl
->output_type
&& FAILED(hr
= MFCreateMediaType(&impl
->output_type
)))
454 if (FAILED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)impl
->output_type
)))
456 IMFMediaType_Release(impl
->output_type
);
457 impl
->output_type
= NULL
;
459 if (FAILED(IMFMediaType_GetUINT32(impl
->output_type
, &MF_MT_DEFAULT_STRIDE
, &stride
)))
461 if (FAILED(hr
= MFGetStrideForBitmapInfoHeader(subtype
.Data1
, frame_size
>> 32, (LONG
*)&stride
)))
463 IMFMediaType_Release(impl
->output_type
);
464 impl
->output_type
= NULL
;
466 if (FAILED(hr
= IMFMediaType_SetUINT32(impl
->output_type
, &MF_MT_DEFAULT_STRIDE
, abs((INT32
)stride
))))
468 IMFMediaType_Release(impl
->output_type
);
469 impl
->output_type
= NULL
;
473 if (impl
->input_type
&& FAILED(hr
= try_create_wg_transform(impl
)))
475 IMFMediaType_Release(impl
->output_type
);
476 impl
->output_type
= NULL
;
479 if (FAILED(hr
) || FAILED(MFCalculateImageSize(&subtype
, frame_size
>> 32, (UINT32
)frame_size
,
480 (UINT32
*)&impl
->output_info
.cbSize
)))
481 impl
->output_info
.cbSize
= 0;
486 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
488 struct color_convert
*impl
= impl_from_IMFTransform(iface
);
491 TRACE("iface %p, id %#lx, type %p.\n", iface
, id
, type
);
494 return MF_E_INVALIDSTREAMNUMBER
;
496 if (!impl
->input_type
)
497 return MF_E_TRANSFORM_TYPE_NOT_SET
;
499 if (FAILED(hr
= MFCreateMediaType(type
)))
502 if (FAILED(hr
= IMFMediaType_CopyAllItems(impl
->input_type
, (IMFAttributes
*)*type
)))
503 IMFMediaType_Release(*type
);
508 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
510 struct color_convert
*impl
= impl_from_IMFTransform(iface
);
513 TRACE("iface %p, id %#lx, type %p.\n", iface
, id
, type
);
516 return MF_E_INVALIDSTREAMNUMBER
;
518 if (!impl
->output_type
)
519 return MF_E_TRANSFORM_TYPE_NOT_SET
;
521 if (FAILED(hr
= MFCreateMediaType(type
)))
524 if (FAILED(hr
= IMFMediaType_CopyAllItems(impl
->output_type
, (IMFAttributes
*)*type
)))
525 IMFMediaType_Release(*type
);
530 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
532 FIXME("iface %p, id %#lx, flags %p stub!\n", iface
, id
, flags
);
536 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
538 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
542 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
544 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
548 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
550 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
554 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
556 FIXME("iface %p, message %#x, param %#Ix stub!\n", iface
, message
, param
);
560 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
562 struct color_convert
*impl
= impl_from_IMFTransform(iface
);
564 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
566 if (!impl
->wg_transform
)
567 return MF_E_TRANSFORM_TYPE_NOT_SET
;
569 return wg_transform_push_mf(impl
->wg_transform
, sample
, impl
->wg_sample_queue
);
572 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
573 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
575 struct color_convert
*impl
= impl_from_IMFTransform(iface
);
576 MFT_OUTPUT_STREAM_INFO info
;
579 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface
, flags
, count
, samples
, status
);
584 if (!impl
->wg_transform
)
585 return MF_E_TRANSFORM_TYPE_NOT_SET
;
587 *status
= samples
->dwStatus
= 0;
588 if (!samples
->pSample
)
591 if (FAILED(hr
= IMFTransform_GetOutputStreamInfo(iface
, 0, &info
)))
594 if (SUCCEEDED(hr
= wg_transform_read_mf(impl
->wg_transform
, samples
->pSample
,
595 info
.cbSize
, NULL
, &samples
->dwStatus
)))
596 wg_sample_queue_flush(impl
->wg_sample_queue
, false);
601 static const IMFTransformVtbl transform_vtbl
=
603 transform_QueryInterface
,
606 transform_GetStreamLimits
,
607 transform_GetStreamCount
,
608 transform_GetStreamIDs
,
609 transform_GetInputStreamInfo
,
610 transform_GetOutputStreamInfo
,
611 transform_GetAttributes
,
612 transform_GetInputStreamAttributes
,
613 transform_GetOutputStreamAttributes
,
614 transform_DeleteInputStream
,
615 transform_AddInputStreams
,
616 transform_GetInputAvailableType
,
617 transform_GetOutputAvailableType
,
618 transform_SetInputType
,
619 transform_SetOutputType
,
620 transform_GetInputCurrentType
,
621 transform_GetOutputCurrentType
,
622 transform_GetInputStatus
,
623 transform_GetOutputStatus
,
624 transform_SetOutputBounds
,
625 transform_ProcessEvent
,
626 transform_ProcessMessage
,
627 transform_ProcessInput
,
628 transform_ProcessOutput
,
631 static inline struct color_convert
*impl_from_IMediaObject(IMediaObject
*iface
)
633 return CONTAINING_RECORD(iface
, struct color_convert
, IMediaObject_iface
);
636 static HRESULT WINAPI
media_object_QueryInterface(IMediaObject
*iface
, REFIID iid
, void **obj
)
638 return IUnknown_QueryInterface(impl_from_IMediaObject(iface
)->outer
, iid
, obj
);
641 static ULONG WINAPI
media_object_AddRef(IMediaObject
*iface
)
643 return IUnknown_AddRef(impl_from_IMediaObject(iface
)->outer
);
646 static ULONG WINAPI
media_object_Release(IMediaObject
*iface
)
648 return IUnknown_Release(impl_from_IMediaObject(iface
)->outer
);
651 static HRESULT WINAPI
media_object_GetStreamCount(IMediaObject
*iface
, DWORD
*input
, DWORD
*output
)
653 FIXME("iface %p, input %p, output %p stub!\n", iface
, input
, output
);
657 static HRESULT WINAPI
media_object_GetInputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
659 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
663 static HRESULT WINAPI
media_object_GetOutputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
665 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
669 static HRESULT WINAPI
media_object_GetInputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
670 DMO_MEDIA_TYPE
*type
)
672 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface
, index
, type_index
, type
);
676 static HRESULT WINAPI
media_object_GetOutputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
677 DMO_MEDIA_TYPE
*type
)
679 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface
, index
, type_index
, type
);
683 static HRESULT WINAPI
media_object_SetInputType(IMediaObject
*iface
, DWORD index
,
684 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
686 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface
, index
, type
, flags
);
690 static HRESULT WINAPI
media_object_SetOutputType(IMediaObject
*iface
, DWORD index
,
691 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
693 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface
, index
, type
, flags
);
697 static HRESULT WINAPI
media_object_GetInputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
699 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
703 static HRESULT WINAPI
media_object_GetOutputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
705 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
709 static HRESULT WINAPI
media_object_GetInputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
,
710 DWORD
*lookahead
, DWORD
*alignment
)
712 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface
, index
, size
,
713 lookahead
, alignment
);
717 static HRESULT WINAPI
media_object_GetOutputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
, DWORD
*alignment
)
719 FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface
, index
, size
, alignment
);
723 static HRESULT WINAPI
media_object_GetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME
*latency
)
725 FIXME("iface %p, index %lu, latency %p stub!\n", iface
, index
, latency
);
729 static HRESULT WINAPI
media_object_SetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME latency
)
731 FIXME("iface %p, index %lu, latency %s stub!\n", iface
, index
, wine_dbgstr_longlong(latency
));
735 static HRESULT WINAPI
media_object_Flush(IMediaObject
*iface
)
737 FIXME("iface %p stub!\n", iface
);
741 static HRESULT WINAPI
media_object_Discontinuity(IMediaObject
*iface
, DWORD index
)
743 FIXME("iface %p, index %lu stub!\n", iface
, index
);
747 static HRESULT WINAPI
media_object_AllocateStreamingResources(IMediaObject
*iface
)
749 FIXME("iface %p stub!\n", iface
);
753 static HRESULT WINAPI
media_object_FreeStreamingResources(IMediaObject
*iface
)
755 FIXME("iface %p stub!\n", iface
);
759 static HRESULT WINAPI
media_object_GetInputStatus(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
761 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
765 static HRESULT WINAPI
media_object_ProcessInput(IMediaObject
*iface
, DWORD index
,
766 IMediaBuffer
*buffer
, DWORD flags
, REFERENCE_TIME timestamp
, REFERENCE_TIME timelength
)
768 FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface
,
769 index
, buffer
, flags
, wine_dbgstr_longlong(timestamp
), wine_dbgstr_longlong(timelength
));
773 static HRESULT WINAPI
media_object_ProcessOutput(IMediaObject
*iface
, DWORD flags
, DWORD count
,
774 DMO_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
776 FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface
, flags
, count
, buffers
, status
);
780 static HRESULT WINAPI
media_object_Lock(IMediaObject
*iface
, LONG lock
)
782 FIXME("iface %p, lock %ld stub!\n", iface
, lock
);
786 static const IMediaObjectVtbl media_object_vtbl
=
788 media_object_QueryInterface
,
790 media_object_Release
,
791 media_object_GetStreamCount
,
792 media_object_GetInputStreamInfo
,
793 media_object_GetOutputStreamInfo
,
794 media_object_GetInputType
,
795 media_object_GetOutputType
,
796 media_object_SetInputType
,
797 media_object_SetOutputType
,
798 media_object_GetInputCurrentType
,
799 media_object_GetOutputCurrentType
,
800 media_object_GetInputSizeInfo
,
801 media_object_GetOutputSizeInfo
,
802 media_object_GetInputMaxLatency
,
803 media_object_SetInputMaxLatency
,
805 media_object_Discontinuity
,
806 media_object_AllocateStreamingResources
,
807 media_object_FreeStreamingResources
,
808 media_object_GetInputStatus
,
809 media_object_ProcessInput
,
810 media_object_ProcessOutput
,
814 static inline struct color_convert
*impl_from_IPropertyBag(IPropertyBag
*iface
)
816 return CONTAINING_RECORD(iface
, struct color_convert
, IPropertyBag_iface
);
819 static HRESULT WINAPI
property_bag_QueryInterface(IPropertyBag
*iface
, REFIID iid
, void **out
)
821 return IUnknown_QueryInterface(impl_from_IPropertyBag(iface
)->outer
, iid
, out
);
824 static ULONG WINAPI
property_bag_AddRef(IPropertyBag
*iface
)
826 return IUnknown_AddRef(impl_from_IPropertyBag(iface
)->outer
);
829 static ULONG WINAPI
property_bag_Release(IPropertyBag
*iface
)
831 return IUnknown_Release(impl_from_IPropertyBag(iface
)->outer
);
834 static HRESULT WINAPI
property_bag_Read(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
,
835 IErrorLog
*error_log
)
837 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface
, debugstr_w(prop_name
), value
, error_log
);
841 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
)
843 FIXME("iface %p, prop_name %s, value %p stub!\n", iface
, debugstr_w(prop_name
), value
);
847 static const IPropertyBagVtbl property_bag_vtbl
=
849 property_bag_QueryInterface
,
851 property_bag_Release
,
856 static inline struct color_convert
*impl_from_IPropertyStore(IPropertyStore
*iface
)
858 return CONTAINING_RECORD(iface
, struct color_convert
, IPropertyStore_iface
);
861 static HRESULT WINAPI
property_store_QueryInterface(IPropertyStore
*iface
, REFIID iid
, void **out
)
863 return IUnknown_QueryInterface(impl_from_IPropertyStore(iface
)->outer
, iid
, out
);
866 static ULONG WINAPI
property_store_AddRef(IPropertyStore
*iface
)
868 return IUnknown_AddRef(impl_from_IPropertyStore(iface
)->outer
);
871 static ULONG WINAPI
property_store_Release(IPropertyStore
*iface
)
873 return IUnknown_Release(impl_from_IPropertyStore(iface
)->outer
);
876 static HRESULT WINAPI
property_store_GetCount(IPropertyStore
*iface
, DWORD
*count
)
878 FIXME("iface %p, count %p stub!\n", iface
, count
);
882 static HRESULT WINAPI
property_store_GetAt(IPropertyStore
*iface
, DWORD index
, PROPERTYKEY
*key
)
884 FIXME("iface %p, index %lu, key %p stub!\n", iface
, index
, key
);
888 static HRESULT WINAPI
property_store_GetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*value
)
890 FIXME("iface %p, key %p, value %p stub!\n", iface
, key
, value
);
894 static HRESULT WINAPI
property_store_SetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, REFPROPVARIANT value
)
896 FIXME("iface %p, key %p, value %p stub!\n", iface
, key
, value
);
900 static HRESULT WINAPI
property_store_Commit(IPropertyStore
*iface
)
902 FIXME("iface %p stub!\n", iface
);
906 static const IPropertyStoreVtbl property_store_vtbl
=
908 property_store_QueryInterface
,
909 property_store_AddRef
,
910 property_store_Release
,
911 property_store_GetCount
,
912 property_store_GetAt
,
913 property_store_GetValue
,
914 property_store_SetValue
,
915 property_store_Commit
,
918 HRESULT
color_convert_create(IUnknown
*outer
, IUnknown
**out
)
920 static const struct wg_format input_format
=
922 .major_type
= WG_MAJOR_TYPE_VIDEO
,
925 .format
= WG_VIDEO_FORMAT_I420
,
930 static const struct wg_format output_format
=
932 .major_type
= WG_MAJOR_TYPE_VIDEO
,
935 .format
= WG_VIDEO_FORMAT_NV12
,
940 struct wg_transform_attrs attrs
= {0};
941 wg_transform_t transform
;
942 struct color_convert
*impl
;
945 TRACE("outer %p, out %p.\n", outer
, out
);
947 if (!(transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
949 ERR_(winediag
)("GStreamer doesn't support video conversion, please install appropriate plugins.\n");
952 wg_transform_destroy(transform
);
954 if (!(impl
= calloc(1, sizeof(*impl
))))
955 return E_OUTOFMEMORY
;
957 if (FAILED(hr
= wg_sample_queue_create(&impl
->wg_sample_queue
)))
963 impl
->IUnknown_inner
.lpVtbl
= &unknown_vtbl
;
964 impl
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
965 impl
->IMediaObject_iface
.lpVtbl
= &media_object_vtbl
;
966 impl
->IPropertyBag_iface
.lpVtbl
= &property_bag_vtbl
;
967 impl
->IPropertyStore_iface
.lpVtbl
= &property_store_vtbl
;
969 impl
->outer
= outer
? outer
: &impl
->IUnknown_inner
;
971 impl
->input_info
.cbAlignment
= 1;
972 impl
->output_info
.cbAlignment
= 1;
974 *out
= &impl
->IUnknown_inner
;
975 TRACE("Created %p\n", *out
);