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
*audio_formats
[] =
39 IUnknown IUnknown_inner
;
40 IMFTransform IMFTransform_iface
;
41 IMediaObject IMediaObject_iface
;
42 IPropertyBag IPropertyBag_iface
;
43 IPropertyStore IPropertyStore_iface
;
47 IMFMediaType
*input_type
;
48 MFT_INPUT_STREAM_INFO input_info
;
49 IMFMediaType
*output_type
;
50 MFT_OUTPUT_STREAM_INFO output_info
;
52 wg_transform_t wg_transform
;
53 struct wg_sample_queue
*wg_sample_queue
;
56 static HRESULT
try_create_wg_transform(struct resampler
*impl
)
58 struct wg_format input_format
, output_format
;
59 struct wg_transform_attrs attrs
= {0};
61 if (impl
->wg_transform
)
62 wg_transform_destroy(impl
->wg_transform
);
63 impl
->wg_transform
= 0;
65 mf_media_type_to_wg_format(impl
->input_type
, &input_format
);
66 if (input_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
67 return MF_E_INVALIDMEDIATYPE
;
69 mf_media_type_to_wg_format(impl
->output_type
, &output_format
);
70 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
71 return MF_E_INVALIDMEDIATYPE
;
73 if (!(impl
->wg_transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
79 static inline struct resampler
*impl_from_IUnknown(IUnknown
*iface
)
81 return CONTAINING_RECORD(iface
, struct resampler
, IUnknown_inner
);
84 static HRESULT WINAPI
unknown_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
86 struct resampler
*impl
= impl_from_IUnknown(iface
);
88 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
90 if (IsEqualGUID(iid
, &IID_IUnknown
))
91 *out
= &impl
->IUnknown_inner
;
92 else if (IsEqualGUID(iid
, &IID_IMFTransform
))
93 *out
= &impl
->IMFTransform_iface
;
94 else if (IsEqualGUID(iid
, &IID_IMediaObject
))
95 *out
= &impl
->IMediaObject_iface
;
96 else if (IsEqualIID(iid
, &IID_IPropertyBag
))
97 *out
= &impl
->IPropertyBag_iface
;
98 else if (IsEqualIID(iid
, &IID_IPropertyStore
))
99 *out
= &impl
->IPropertyStore_iface
;
103 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
104 return E_NOINTERFACE
;
107 IUnknown_AddRef((IUnknown
*)*out
);
111 static ULONG WINAPI
unknown_AddRef(IUnknown
*iface
)
113 struct resampler
*impl
= impl_from_IUnknown(iface
);
114 ULONG refcount
= InterlockedIncrement(&impl
->refcount
);
116 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
121 static ULONG WINAPI
unknown_Release(IUnknown
*iface
)
123 struct resampler
*impl
= impl_from_IUnknown(iface
);
124 ULONG refcount
= InterlockedDecrement(&impl
->refcount
);
126 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
130 if (impl
->wg_transform
)
131 wg_transform_destroy(impl
->wg_transform
);
132 if (impl
->input_type
)
133 IMFMediaType_Release(impl
->input_type
);
134 if (impl
->output_type
)
135 IMFMediaType_Release(impl
->output_type
);
137 wg_sample_queue_destroy(impl
->wg_sample_queue
);
144 static const IUnknownVtbl unknown_vtbl
=
146 unknown_QueryInterface
,
151 static struct resampler
*impl_from_IMFTransform(IMFTransform
*iface
)
153 return CONTAINING_RECORD(iface
, struct resampler
, IMFTransform_iface
);
156 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
158 return IUnknown_QueryInterface(impl_from_IMFTransform(iface
)->outer
, iid
, out
);
161 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
163 return IUnknown_AddRef(impl_from_IMFTransform(iface
)->outer
);
166 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
168 return IUnknown_Release(impl_from_IMFTransform(iface
)->outer
);
171 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
172 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
174 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
175 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
176 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
180 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
182 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
183 *inputs
= *outputs
= 1;
187 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
188 DWORD output_size
, DWORD
*outputs
)
190 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
191 input_size
, inputs
, output_size
, outputs
);
195 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
197 struct resampler
*impl
= impl_from_IMFTransform(iface
);
199 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
201 if (!impl
->input_type
|| !impl
->output_type
)
203 memset(info
, 0, sizeof(*info
));
204 return MF_E_TRANSFORM_TYPE_NOT_SET
;
207 *info
= impl
->input_info
;
211 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
213 struct resampler
*impl
= impl_from_IMFTransform(iface
);
215 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
217 if (!impl
->input_type
|| !impl
->output_type
)
219 memset(info
, 0, sizeof(*info
));
220 return MF_E_TRANSFORM_TYPE_NOT_SET
;
223 *info
= impl
->output_info
;
227 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
229 TRACE("iface %p, attributes %p.\n", iface
, attributes
);
233 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
235 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
239 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
241 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
245 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
247 TRACE("iface %p, id %#lx.\n", iface
, id
);
251 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
253 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
257 static HRESULT
get_available_media_type(DWORD index
, IMFMediaType
**type
, BOOL output
)
259 UINT32 sample_size
, sample_rate
= 48000, block_alignment
, channel_count
= 2;
260 IMFMediaType
*media_type
;
266 if (index
>= (output
? 2 : 1) * ARRAY_SIZE(audio_formats
))
267 return MF_E_NO_MORE_TYPES
;
268 subtype
= audio_formats
[index
% ARRAY_SIZE(audio_formats
)];
270 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
273 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
)))
275 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
277 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, 1)))
279 if (index
< ARRAY_SIZE(audio_formats
))
282 if (IsEqualGUID(subtype
, &MFAudioFormat_Float
))
284 else if (IsEqualGUID(subtype
, &MFAudioFormat_PCM
))
288 FIXME("Subtype %s not implemented!\n", debugstr_guid(subtype
));
293 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, sample_size
)))
295 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, channel_count
)))
297 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, sample_rate
)))
300 block_alignment
= sample_size
* channel_count
/ 8;
301 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, block_alignment
)))
303 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, sample_rate
* block_alignment
)))
305 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_PREFER_WAVEFORMATEX
, 1)))
310 IMFMediaType_AddRef((*type
= media_type
));
312 IMFMediaType_Release(media_type
);
316 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
319 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
320 return get_available_media_type(index
, type
, FALSE
);
323 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
326 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
327 return get_available_media_type(index
, type
, TRUE
);
330 static HRESULT
check_media_type(IMFMediaType
*type
)
332 MF_ATTRIBUTE_TYPE item_type
;
337 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
338 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
339 return MF_E_ATTRIBUTENOTFOUND
;
341 if (!IsEqualGUID(&major
, &MFMediaType_Audio
))
342 return MF_E_INVALIDMEDIATYPE
;
344 for (i
= 0; i
< ARRAY_SIZE(audio_formats
); ++i
)
345 if (IsEqualGUID(&subtype
, audio_formats
[i
]))
347 if (i
== ARRAY_SIZE(audio_formats
))
348 return MF_E_INVALIDMEDIATYPE
;
350 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &item_type
)) ||
351 item_type
!= MF_ATTRIBUTE_UINT32
)
352 return MF_E_INVALIDMEDIATYPE
;
353 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, &item_type
)) ||
354 item_type
!= MF_ATTRIBUTE_UINT32
)
355 return MF_E_INVALIDMEDIATYPE
;
356 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &item_type
)) ||
357 item_type
!= MF_ATTRIBUTE_UINT32
)
358 return MF_E_INVALIDMEDIATYPE
;
359 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &item_type
)) ||
360 item_type
!= MF_ATTRIBUTE_UINT32
)
361 return MF_E_INVALIDMEDIATYPE
;
366 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
368 struct resampler
*impl
= impl_from_IMFTransform(iface
);
369 UINT32 block_alignment
;
372 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
374 if (FAILED(hr
= check_media_type(type
)))
376 if (FAILED(hr
= IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
377 return MF_E_INVALIDMEDIATYPE
;
378 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
381 if (!impl
->input_type
&& FAILED(hr
= MFCreateMediaType(&impl
->input_type
)))
384 if (impl
->output_type
)
386 IMFMediaType_Release(impl
->output_type
);
387 impl
->output_type
= NULL
;
390 if (SUCCEEDED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)impl
->input_type
)))
391 impl
->input_info
.cbSize
= block_alignment
;
394 IMFMediaType_Release(impl
->input_type
);
395 impl
->input_info
.cbSize
= 0;
396 impl
->input_type
= NULL
;
402 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
404 struct resampler
*impl
= impl_from_IMFTransform(iface
);
405 UINT32 block_alignment
;
408 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
410 if (!impl
->input_type
)
411 return MF_E_TRANSFORM_TYPE_NOT_SET
;
413 if (FAILED(hr
= check_media_type(type
)))
415 if (FAILED(hr
= IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
416 return MF_E_INVALIDMEDIATYPE
;
417 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
420 if (!impl
->output_type
&& FAILED(hr
= MFCreateMediaType(&impl
->output_type
)))
423 if (FAILED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)impl
->output_type
)))
426 if (FAILED(hr
= try_create_wg_transform(impl
)))
429 impl
->output_info
.cbSize
= block_alignment
;
433 IMFMediaType_Release(impl
->output_type
);
434 impl
->output_info
.cbSize
= 0;
435 impl
->output_type
= NULL
;
439 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
441 struct resampler
*impl
= impl_from_IMFTransform(iface
);
444 TRACE("iface %p, id %#lx, type %p.\n", iface
, id
, type
);
447 return MF_E_INVALIDSTREAMNUMBER
;
449 if (!impl
->input_type
)
450 return MF_E_TRANSFORM_TYPE_NOT_SET
;
452 if (FAILED(hr
= MFCreateMediaType(type
)))
455 if (FAILED(hr
= IMFMediaType_CopyAllItems(impl
->input_type
, (IMFAttributes
*)*type
)))
456 IMFMediaType_Release(*type
);
461 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
463 struct resampler
*impl
= impl_from_IMFTransform(iface
);
466 TRACE("iface %p, id %#lx, type %p.\n", iface
, id
, type
);
469 return MF_E_INVALIDSTREAMNUMBER
;
471 if (!impl
->output_type
)
472 return MF_E_TRANSFORM_TYPE_NOT_SET
;
474 if (FAILED(hr
= MFCreateMediaType(type
)))
477 if (FAILED(hr
= IMFMediaType_CopyAllItems(impl
->output_type
, (IMFAttributes
*)*type
)))
478 IMFMediaType_Release(*type
);
483 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
485 FIXME("iface %p, id %#lx, flags %p stub!\n", iface
, id
, flags
);
489 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
491 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
495 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
497 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
501 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
503 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
507 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
509 FIXME("iface %p, message %#x, param %p stub!\n", iface
, message
, (void *)param
);
513 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
515 struct resampler
*impl
= impl_from_IMFTransform(iface
);
517 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
519 if (!impl
->wg_transform
)
520 return MF_E_TRANSFORM_TYPE_NOT_SET
;
522 return wg_transform_push_mf(impl
->wg_transform
, sample
, impl
->wg_sample_queue
);
525 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
526 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
528 struct resampler
*impl
= impl_from_IMFTransform(iface
);
529 MFT_OUTPUT_STREAM_INFO info
;
532 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface
, flags
, count
, samples
, status
);
537 if (!impl
->wg_transform
)
538 return MF_E_TRANSFORM_TYPE_NOT_SET
;
540 *status
= samples
->dwStatus
= 0;
541 if (!samples
->pSample
)
543 samples
->dwStatus
= MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
;
544 return MF_E_TRANSFORM_NEED_MORE_INPUT
;
547 if (FAILED(hr
= IMFTransform_GetOutputStreamInfo(iface
, 0, &info
)))
550 if (SUCCEEDED(hr
= wg_transform_read_mf(impl
->wg_transform
, samples
->pSample
,
551 info
.cbSize
, NULL
, &samples
->dwStatus
)))
552 wg_sample_queue_flush(impl
->wg_sample_queue
, false);
557 static const IMFTransformVtbl transform_vtbl
=
559 transform_QueryInterface
,
562 transform_GetStreamLimits
,
563 transform_GetStreamCount
,
564 transform_GetStreamIDs
,
565 transform_GetInputStreamInfo
,
566 transform_GetOutputStreamInfo
,
567 transform_GetAttributes
,
568 transform_GetInputStreamAttributes
,
569 transform_GetOutputStreamAttributes
,
570 transform_DeleteInputStream
,
571 transform_AddInputStreams
,
572 transform_GetInputAvailableType
,
573 transform_GetOutputAvailableType
,
574 transform_SetInputType
,
575 transform_SetOutputType
,
576 transform_GetInputCurrentType
,
577 transform_GetOutputCurrentType
,
578 transform_GetInputStatus
,
579 transform_GetOutputStatus
,
580 transform_SetOutputBounds
,
581 transform_ProcessEvent
,
582 transform_ProcessMessage
,
583 transform_ProcessInput
,
584 transform_ProcessOutput
,
587 static inline struct resampler
*impl_from_IMediaObject(IMediaObject
*iface
)
589 return CONTAINING_RECORD(iface
, struct resampler
, IMediaObject_iface
);
592 static HRESULT WINAPI
media_object_QueryInterface(IMediaObject
*iface
, REFIID iid
, void **obj
)
594 return IUnknown_QueryInterface(impl_from_IMediaObject(iface
)->outer
, iid
, obj
);
597 static ULONG WINAPI
media_object_AddRef(IMediaObject
*iface
)
599 return IUnknown_AddRef(impl_from_IMediaObject(iface
)->outer
);
602 static ULONG WINAPI
media_object_Release(IMediaObject
*iface
)
604 return IUnknown_Release(impl_from_IMediaObject(iface
)->outer
);
607 static HRESULT WINAPI
media_object_GetStreamCount(IMediaObject
*iface
, DWORD
*input
, DWORD
*output
)
609 FIXME("iface %p, input %p, output %p semi-stub!\n", iface
, input
, output
);
610 *input
= *output
= 1;
614 static HRESULT WINAPI
media_object_GetInputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
616 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
620 static HRESULT WINAPI
media_object_GetOutputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
622 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
626 static HRESULT WINAPI
media_object_GetInputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
627 DMO_MEDIA_TYPE
*type
)
629 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface
, index
, type_index
, type
);
633 static HRESULT WINAPI
media_object_GetOutputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
634 DMO_MEDIA_TYPE
*type
)
636 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface
, index
, type_index
, type
);
640 static HRESULT WINAPI
media_object_SetInputType(IMediaObject
*iface
, DWORD index
,
641 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
643 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface
, index
, type
, flags
);
647 static HRESULT WINAPI
media_object_SetOutputType(IMediaObject
*iface
, DWORD index
,
648 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
650 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface
, index
, type
, flags
);
654 static HRESULT WINAPI
media_object_GetInputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
656 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
660 static HRESULT WINAPI
media_object_GetOutputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
662 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
666 static HRESULT WINAPI
media_object_GetInputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
,
667 DWORD
*lookahead
, DWORD
*alignment
)
669 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface
, index
, size
,
670 lookahead
, alignment
);
674 static HRESULT WINAPI
media_object_GetOutputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
, DWORD
*alignment
)
676 FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface
, index
, size
, alignment
);
680 static HRESULT WINAPI
media_object_GetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME
*latency
)
682 FIXME("iface %p, index %lu, latency %p stub!\n", iface
, index
, latency
);
686 static HRESULT WINAPI
media_object_SetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME latency
)
688 FIXME("iface %p, index %lu, latency %s stub!\n", iface
, index
, wine_dbgstr_longlong(latency
));
692 static HRESULT WINAPI
media_object_Flush(IMediaObject
*iface
)
694 FIXME("iface %p stub!\n", iface
);
698 static HRESULT WINAPI
media_object_Discontinuity(IMediaObject
*iface
, DWORD index
)
700 FIXME("iface %p, index %lu stub!\n", iface
, index
);
704 static HRESULT WINAPI
media_object_AllocateStreamingResources(IMediaObject
*iface
)
706 FIXME("iface %p stub!\n", iface
);
710 static HRESULT WINAPI
media_object_FreeStreamingResources(IMediaObject
*iface
)
712 FIXME("iface %p stub!\n", iface
);
716 static HRESULT WINAPI
media_object_GetInputStatus(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
718 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
722 static HRESULT WINAPI
media_object_ProcessInput(IMediaObject
*iface
, DWORD index
,
723 IMediaBuffer
*buffer
, DWORD flags
, REFERENCE_TIME timestamp
, REFERENCE_TIME timelength
)
725 FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface
,
726 index
, buffer
, flags
, wine_dbgstr_longlong(timestamp
), wine_dbgstr_longlong(timelength
));
730 static HRESULT WINAPI
media_object_ProcessOutput(IMediaObject
*iface
, DWORD flags
, DWORD count
,
731 DMO_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
733 FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface
, flags
, count
, buffers
, status
);
737 static HRESULT WINAPI
media_object_Lock(IMediaObject
*iface
, LONG lock
)
739 FIXME("iface %p, lock %ld stub!\n", iface
, lock
);
743 static const IMediaObjectVtbl media_object_vtbl
=
745 media_object_QueryInterface
,
747 media_object_Release
,
748 media_object_GetStreamCount
,
749 media_object_GetInputStreamInfo
,
750 media_object_GetOutputStreamInfo
,
751 media_object_GetInputType
,
752 media_object_GetOutputType
,
753 media_object_SetInputType
,
754 media_object_SetOutputType
,
755 media_object_GetInputCurrentType
,
756 media_object_GetOutputCurrentType
,
757 media_object_GetInputSizeInfo
,
758 media_object_GetOutputSizeInfo
,
759 media_object_GetInputMaxLatency
,
760 media_object_SetInputMaxLatency
,
762 media_object_Discontinuity
,
763 media_object_AllocateStreamingResources
,
764 media_object_FreeStreamingResources
,
765 media_object_GetInputStatus
,
766 media_object_ProcessInput
,
767 media_object_ProcessOutput
,
771 static inline struct resampler
*impl_from_IPropertyBag(IPropertyBag
*iface
)
773 return CONTAINING_RECORD(iface
, struct resampler
, IPropertyBag_iface
);
776 static HRESULT WINAPI
property_bag_QueryInterface(IPropertyBag
*iface
, REFIID iid
, void **out
)
778 return IUnknown_QueryInterface(impl_from_IPropertyBag(iface
)->outer
, iid
, out
);
781 static ULONG WINAPI
property_bag_AddRef(IPropertyBag
*iface
)
783 return IUnknown_AddRef(impl_from_IPropertyBag(iface
)->outer
);
786 static ULONG WINAPI
property_bag_Release(IPropertyBag
*iface
)
788 return IUnknown_Release(impl_from_IPropertyBag(iface
)->outer
);
791 static HRESULT WINAPI
property_bag_Read(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
,
792 IErrorLog
*error_log
)
794 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface
, debugstr_w(prop_name
), value
, error_log
);
798 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
)
800 FIXME("iface %p, prop_name %s, value %p stub!\n", iface
, debugstr_w(prop_name
), value
);
804 static const IPropertyBagVtbl property_bag_vtbl
=
806 property_bag_QueryInterface
,
808 property_bag_Release
,
813 static inline struct resampler
*impl_from_IPropertyStore(IPropertyStore
*iface
)
815 return CONTAINING_RECORD(iface
, struct resampler
, IPropertyStore_iface
);
818 static HRESULT WINAPI
property_store_QueryInterface(IPropertyStore
*iface
, REFIID iid
, void **out
)
820 return IUnknown_QueryInterface(impl_from_IPropertyStore(iface
)->outer
, iid
, out
);
823 static ULONG WINAPI
property_store_AddRef(IPropertyStore
*iface
)
825 return IUnknown_AddRef(impl_from_IPropertyStore(iface
)->outer
);
828 static ULONG WINAPI
property_store_Release(IPropertyStore
*iface
)
830 return IUnknown_Release(impl_from_IPropertyStore(iface
)->outer
);
833 static HRESULT WINAPI
property_store_GetCount(IPropertyStore
*iface
, DWORD
*count
)
835 FIXME("iface %p, count %p stub!\n", iface
, count
);
839 static HRESULT WINAPI
property_store_GetAt(IPropertyStore
*iface
, DWORD index
, PROPERTYKEY
*key
)
841 FIXME("iface %p, index %lu, key %p stub!\n", iface
, index
, key
);
845 static HRESULT WINAPI
property_store_GetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*value
)
847 FIXME("iface %p, key %p, value %p stub!\n", iface
, key
, value
);
851 static HRESULT WINAPI
property_store_SetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, REFPROPVARIANT value
)
853 FIXME("iface %p, key %p, value %p stub!\n", iface
, key
, value
);
857 static HRESULT WINAPI
property_store_Commit(IPropertyStore
*iface
)
859 FIXME("iface %p stub!\n", iface
);
863 static const IPropertyStoreVtbl property_store_vtbl
=
865 property_store_QueryInterface
,
866 property_store_AddRef
,
867 property_store_Release
,
868 property_store_GetCount
,
869 property_store_GetAt
,
870 property_store_GetValue
,
871 property_store_SetValue
,
872 property_store_Commit
,
875 HRESULT
resampler_create(IUnknown
*outer
, IUnknown
**out
)
877 static const struct wg_format input_format
=
879 .major_type
= WG_MAJOR_TYPE_AUDIO
,
882 .format
= WG_AUDIO_FORMAT_S16LE
,
888 static const struct wg_format output_format
=
890 .major_type
= WG_MAJOR_TYPE_AUDIO
,
893 .format
= WG_AUDIO_FORMAT_F32LE
,
899 struct wg_transform_attrs attrs
= {0};
900 wg_transform_t transform
;
901 struct resampler
*impl
;
904 TRACE("outer %p, out %p.\n", outer
, out
);
906 if (!(transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
908 ERR_(winediag
)("GStreamer doesn't support audio resampling, please install appropriate plugins.\n");
911 wg_transform_destroy(transform
);
913 if (!(impl
= calloc(1, sizeof(*impl
))))
914 return E_OUTOFMEMORY
;
916 if (FAILED(hr
= wg_sample_queue_create(&impl
->wg_sample_queue
)))
922 impl
->IUnknown_inner
.lpVtbl
= &unknown_vtbl
;
923 impl
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
924 impl
->IMediaObject_iface
.lpVtbl
= &media_object_vtbl
;
925 impl
->IPropertyBag_iface
.lpVtbl
= &property_bag_vtbl
;
926 impl
->IPropertyStore_iface
.lpVtbl
= &property_store_vtbl
;
928 impl
->outer
= outer
? outer
: &impl
->IUnknown_inner
;
930 impl
->input_info
.cbAlignment
= 1;
931 impl
->output_info
.cbAlignment
= 1;
933 *out
= &impl
->IUnknown_inner
;
934 TRACE("Created %p\n", *out
);