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
;
44 IWMResamplerProps IWMResamplerProps_iface
;
48 IMFMediaType
*input_type
;
49 MFT_INPUT_STREAM_INFO input_info
;
50 IMFMediaType
*output_type
;
51 MFT_OUTPUT_STREAM_INFO output_info
;
53 wg_transform_t wg_transform
;
54 struct wg_sample_queue
*wg_sample_queue
;
57 static HRESULT
try_create_wg_transform(struct resampler
*impl
)
59 struct wg_format input_format
, output_format
;
60 struct wg_transform_attrs attrs
= {0};
62 if (impl
->wg_transform
)
63 wg_transform_destroy(impl
->wg_transform
);
64 impl
->wg_transform
= 0;
66 mf_media_type_to_wg_format(impl
->input_type
, &input_format
);
67 if (input_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
68 return MF_E_INVALIDMEDIATYPE
;
70 mf_media_type_to_wg_format(impl
->output_type
, &output_format
);
71 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
72 return MF_E_INVALIDMEDIATYPE
;
74 if (!(impl
->wg_transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
80 static inline struct resampler
*impl_from_IUnknown(IUnknown
*iface
)
82 return CONTAINING_RECORD(iface
, struct resampler
, IUnknown_inner
);
85 static HRESULT WINAPI
unknown_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
87 struct resampler
*impl
= impl_from_IUnknown(iface
);
89 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
91 if (IsEqualGUID(iid
, &IID_IUnknown
))
92 *out
= &impl
->IUnknown_inner
;
93 else if (IsEqualGUID(iid
, &IID_IMFTransform
))
94 *out
= &impl
->IMFTransform_iface
;
95 else if (IsEqualGUID(iid
, &IID_IMediaObject
))
96 *out
= &impl
->IMediaObject_iface
;
97 else if (IsEqualIID(iid
, &IID_IPropertyBag
))
98 *out
= &impl
->IPropertyBag_iface
;
99 else if (IsEqualIID(iid
, &IID_IPropertyStore
))
100 *out
= &impl
->IPropertyStore_iface
;
101 else if (IsEqualIID(iid
, &IID_IWMResamplerProps
))
102 *out
= &impl
->IWMResamplerProps_iface
;
106 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
107 return E_NOINTERFACE
;
110 IUnknown_AddRef((IUnknown
*)*out
);
114 static ULONG WINAPI
unknown_AddRef(IUnknown
*iface
)
116 struct resampler
*impl
= impl_from_IUnknown(iface
);
117 ULONG refcount
= InterlockedIncrement(&impl
->refcount
);
119 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
124 static ULONG WINAPI
unknown_Release(IUnknown
*iface
)
126 struct resampler
*impl
= impl_from_IUnknown(iface
);
127 ULONG refcount
= InterlockedDecrement(&impl
->refcount
);
129 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
133 if (impl
->wg_transform
)
134 wg_transform_destroy(impl
->wg_transform
);
135 if (impl
->input_type
)
136 IMFMediaType_Release(impl
->input_type
);
137 if (impl
->output_type
)
138 IMFMediaType_Release(impl
->output_type
);
140 wg_sample_queue_destroy(impl
->wg_sample_queue
);
147 static const IUnknownVtbl unknown_vtbl
=
149 unknown_QueryInterface
,
154 static struct resampler
*impl_from_IMFTransform(IMFTransform
*iface
)
156 return CONTAINING_RECORD(iface
, struct resampler
, IMFTransform_iface
);
159 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
161 return IUnknown_QueryInterface(impl_from_IMFTransform(iface
)->outer
, iid
, out
);
164 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
166 return IUnknown_AddRef(impl_from_IMFTransform(iface
)->outer
);
169 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
171 return IUnknown_Release(impl_from_IMFTransform(iface
)->outer
);
174 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
175 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
177 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
178 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
179 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
183 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
185 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
186 *inputs
= *outputs
= 1;
190 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
191 DWORD output_size
, DWORD
*outputs
)
193 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
194 input_size
, inputs
, output_size
, outputs
);
198 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
200 struct resampler
*impl
= impl_from_IMFTransform(iface
);
202 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
204 if (!impl
->input_type
|| !impl
->output_type
)
206 memset(info
, 0, sizeof(*info
));
207 return MF_E_TRANSFORM_TYPE_NOT_SET
;
210 *info
= impl
->input_info
;
214 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
216 struct resampler
*impl
= impl_from_IMFTransform(iface
);
218 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
220 if (!impl
->input_type
|| !impl
->output_type
)
222 memset(info
, 0, sizeof(*info
));
223 return MF_E_TRANSFORM_TYPE_NOT_SET
;
226 *info
= impl
->output_info
;
230 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
232 TRACE("iface %p, attributes %p.\n", iface
, attributes
);
236 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
238 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
242 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
244 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
248 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
250 TRACE("iface %p, id %#lx.\n", iface
, id
);
254 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
256 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
260 static HRESULT
get_available_media_type(DWORD index
, IMFMediaType
**type
, BOOL output
)
262 UINT32 sample_size
, sample_rate
= 48000, block_alignment
, channel_count
= 2;
263 IMFMediaType
*media_type
;
269 if (index
>= (output
? 2 : 1) * ARRAY_SIZE(audio_formats
))
270 return MF_E_NO_MORE_TYPES
;
271 subtype
= audio_formats
[index
% ARRAY_SIZE(audio_formats
)];
273 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
276 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
)))
278 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
280 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, 1)))
282 if (index
< ARRAY_SIZE(audio_formats
))
285 if (IsEqualGUID(subtype
, &MFAudioFormat_Float
))
287 else if (IsEqualGUID(subtype
, &MFAudioFormat_PCM
))
291 FIXME("Subtype %s not implemented!\n", debugstr_guid(subtype
));
296 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, sample_size
)))
298 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, channel_count
)))
300 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, sample_rate
)))
303 block_alignment
= sample_size
* channel_count
/ 8;
304 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, block_alignment
)))
306 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, sample_rate
* block_alignment
)))
308 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_PREFER_WAVEFORMATEX
, 1)))
313 IMFMediaType_AddRef((*type
= media_type
));
315 IMFMediaType_Release(media_type
);
319 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
322 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
323 return get_available_media_type(index
, type
, FALSE
);
326 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
329 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
330 return get_available_media_type(index
, type
, TRUE
);
333 static HRESULT
check_media_type(IMFMediaType
*type
)
335 MF_ATTRIBUTE_TYPE item_type
;
340 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
341 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
342 return MF_E_ATTRIBUTENOTFOUND
;
344 if (!IsEqualGUID(&major
, &MFMediaType_Audio
))
345 return MF_E_INVALIDMEDIATYPE
;
347 for (i
= 0; i
< ARRAY_SIZE(audio_formats
); ++i
)
348 if (IsEqualGUID(&subtype
, audio_formats
[i
]))
350 if (i
== ARRAY_SIZE(audio_formats
))
351 return MF_E_INVALIDMEDIATYPE
;
353 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &item_type
)) ||
354 item_type
!= MF_ATTRIBUTE_UINT32
)
355 return MF_E_INVALIDMEDIATYPE
;
356 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, &item_type
)) ||
357 item_type
!= MF_ATTRIBUTE_UINT32
)
358 return MF_E_INVALIDMEDIATYPE
;
359 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &item_type
)) ||
360 item_type
!= MF_ATTRIBUTE_UINT32
)
361 return MF_E_INVALIDMEDIATYPE
;
362 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &item_type
)) ||
363 item_type
!= MF_ATTRIBUTE_UINT32
)
364 return MF_E_INVALIDMEDIATYPE
;
369 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
371 struct resampler
*impl
= impl_from_IMFTransform(iface
);
372 UINT32 block_alignment
;
375 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
377 if (FAILED(hr
= check_media_type(type
)))
379 if (FAILED(hr
= IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
380 return MF_E_INVALIDMEDIATYPE
;
381 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
384 if (!impl
->input_type
&& FAILED(hr
= MFCreateMediaType(&impl
->input_type
)))
387 if (impl
->output_type
)
389 IMFMediaType_Release(impl
->output_type
);
390 impl
->output_type
= NULL
;
393 if (SUCCEEDED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)impl
->input_type
)))
394 impl
->input_info
.cbSize
= block_alignment
;
397 IMFMediaType_Release(impl
->input_type
);
398 impl
->input_info
.cbSize
= 0;
399 impl
->input_type
= NULL
;
405 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
407 struct resampler
*impl
= impl_from_IMFTransform(iface
);
408 UINT32 block_alignment
;
411 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
413 if (!impl
->input_type
)
414 return MF_E_TRANSFORM_TYPE_NOT_SET
;
416 if (FAILED(hr
= check_media_type(type
)))
418 if (FAILED(hr
= IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
419 return MF_E_INVALIDMEDIATYPE
;
420 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
423 if (!impl
->output_type
&& FAILED(hr
= MFCreateMediaType(&impl
->output_type
)))
426 if (FAILED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)impl
->output_type
)))
429 if (FAILED(hr
= try_create_wg_transform(impl
)))
432 impl
->output_info
.cbSize
= block_alignment
;
436 IMFMediaType_Release(impl
->output_type
);
437 impl
->output_info
.cbSize
= 0;
438 impl
->output_type
= NULL
;
442 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
444 struct resampler
*impl
= impl_from_IMFTransform(iface
);
447 TRACE("iface %p, id %#lx, type %p.\n", iface
, id
, type
);
450 return MF_E_INVALIDSTREAMNUMBER
;
452 if (!impl
->input_type
)
453 return MF_E_TRANSFORM_TYPE_NOT_SET
;
455 if (FAILED(hr
= MFCreateMediaType(type
)))
458 if (FAILED(hr
= IMFMediaType_CopyAllItems(impl
->input_type
, (IMFAttributes
*)*type
)))
459 IMFMediaType_Release(*type
);
464 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
466 struct resampler
*impl
= impl_from_IMFTransform(iface
);
469 TRACE("iface %p, id %#lx, type %p.\n", iface
, id
, type
);
472 return MF_E_INVALIDSTREAMNUMBER
;
474 if (!impl
->output_type
)
475 return MF_E_TRANSFORM_TYPE_NOT_SET
;
477 if (FAILED(hr
= MFCreateMediaType(type
)))
480 if (FAILED(hr
= IMFMediaType_CopyAllItems(impl
->output_type
, (IMFAttributes
*)*type
)))
481 IMFMediaType_Release(*type
);
486 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
488 FIXME("iface %p, id %#lx, flags %p stub!\n", iface
, id
, flags
);
492 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
494 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
498 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
500 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
504 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
506 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
510 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
512 FIXME("iface %p, message %#x, param %p stub!\n", iface
, message
, (void *)param
);
516 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
518 struct resampler
*impl
= impl_from_IMFTransform(iface
);
520 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
522 if (!impl
->wg_transform
)
523 return MF_E_TRANSFORM_TYPE_NOT_SET
;
525 return wg_transform_push_mf(impl
->wg_transform
, sample
, impl
->wg_sample_queue
);
528 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
529 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
531 struct resampler
*impl
= impl_from_IMFTransform(iface
);
532 MFT_OUTPUT_STREAM_INFO info
;
535 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface
, flags
, count
, samples
, status
);
540 if (!impl
->wg_transform
)
541 return MF_E_TRANSFORM_TYPE_NOT_SET
;
543 *status
= samples
->dwStatus
= 0;
544 if (!samples
->pSample
)
546 samples
->dwStatus
= MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
;
547 return MF_E_TRANSFORM_NEED_MORE_INPUT
;
550 if (FAILED(hr
= IMFTransform_GetOutputStreamInfo(iface
, 0, &info
)))
553 if (SUCCEEDED(hr
= wg_transform_read_mf(impl
->wg_transform
, samples
->pSample
,
554 info
.cbSize
, NULL
, &samples
->dwStatus
)))
555 wg_sample_queue_flush(impl
->wg_sample_queue
, false);
560 static const IMFTransformVtbl transform_vtbl
=
562 transform_QueryInterface
,
565 transform_GetStreamLimits
,
566 transform_GetStreamCount
,
567 transform_GetStreamIDs
,
568 transform_GetInputStreamInfo
,
569 transform_GetOutputStreamInfo
,
570 transform_GetAttributes
,
571 transform_GetInputStreamAttributes
,
572 transform_GetOutputStreamAttributes
,
573 transform_DeleteInputStream
,
574 transform_AddInputStreams
,
575 transform_GetInputAvailableType
,
576 transform_GetOutputAvailableType
,
577 transform_SetInputType
,
578 transform_SetOutputType
,
579 transform_GetInputCurrentType
,
580 transform_GetOutputCurrentType
,
581 transform_GetInputStatus
,
582 transform_GetOutputStatus
,
583 transform_SetOutputBounds
,
584 transform_ProcessEvent
,
585 transform_ProcessMessage
,
586 transform_ProcessInput
,
587 transform_ProcessOutput
,
590 static inline struct resampler
*impl_from_IMediaObject(IMediaObject
*iface
)
592 return CONTAINING_RECORD(iface
, struct resampler
, IMediaObject_iface
);
595 static HRESULT WINAPI
media_object_QueryInterface(IMediaObject
*iface
, REFIID iid
, void **obj
)
597 return IUnknown_QueryInterface(impl_from_IMediaObject(iface
)->outer
, iid
, obj
);
600 static ULONG WINAPI
media_object_AddRef(IMediaObject
*iface
)
602 return IUnknown_AddRef(impl_from_IMediaObject(iface
)->outer
);
605 static ULONG WINAPI
media_object_Release(IMediaObject
*iface
)
607 return IUnknown_Release(impl_from_IMediaObject(iface
)->outer
);
610 static HRESULT WINAPI
media_object_GetStreamCount(IMediaObject
*iface
, DWORD
*input
, DWORD
*output
)
612 FIXME("iface %p, input %p, output %p semi-stub!\n", iface
, input
, output
);
613 *input
= *output
= 1;
617 static HRESULT WINAPI
media_object_GetInputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
619 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
623 static HRESULT WINAPI
media_object_GetOutputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
625 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
629 static HRESULT WINAPI
media_object_GetInputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
630 DMO_MEDIA_TYPE
*type
)
632 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface
, index
, type_index
, type
);
636 static HRESULT WINAPI
media_object_GetOutputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
637 DMO_MEDIA_TYPE
*type
)
639 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface
, index
, type_index
, type
);
643 static HRESULT WINAPI
media_object_SetInputType(IMediaObject
*iface
, DWORD index
,
644 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
646 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface
, index
, type
, flags
);
650 static HRESULT WINAPI
media_object_SetOutputType(IMediaObject
*iface
, DWORD index
,
651 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
653 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface
, index
, type
, flags
);
657 static HRESULT WINAPI
media_object_GetInputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
659 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
663 static HRESULT WINAPI
media_object_GetOutputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
665 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
669 static HRESULT WINAPI
media_object_GetInputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
,
670 DWORD
*lookahead
, DWORD
*alignment
)
672 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface
, index
, size
,
673 lookahead
, alignment
);
677 static HRESULT WINAPI
media_object_GetOutputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
, DWORD
*alignment
)
679 FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface
, index
, size
, alignment
);
683 static HRESULT WINAPI
media_object_GetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME
*latency
)
685 FIXME("iface %p, index %lu, latency %p stub!\n", iface
, index
, latency
);
689 static HRESULT WINAPI
media_object_SetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME latency
)
691 FIXME("iface %p, index %lu, latency %s stub!\n", iface
, index
, wine_dbgstr_longlong(latency
));
695 static HRESULT WINAPI
media_object_Flush(IMediaObject
*iface
)
697 FIXME("iface %p stub!\n", iface
);
701 static HRESULT WINAPI
media_object_Discontinuity(IMediaObject
*iface
, DWORD index
)
703 FIXME("iface %p, index %lu stub!\n", iface
, index
);
707 static HRESULT WINAPI
media_object_AllocateStreamingResources(IMediaObject
*iface
)
709 FIXME("iface %p stub!\n", iface
);
713 static HRESULT WINAPI
media_object_FreeStreamingResources(IMediaObject
*iface
)
715 FIXME("iface %p stub!\n", iface
);
719 static HRESULT WINAPI
media_object_GetInputStatus(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
721 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
725 static HRESULT WINAPI
media_object_ProcessInput(IMediaObject
*iface
, DWORD index
,
726 IMediaBuffer
*buffer
, DWORD flags
, REFERENCE_TIME timestamp
, REFERENCE_TIME timelength
)
728 FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface
,
729 index
, buffer
, flags
, wine_dbgstr_longlong(timestamp
), wine_dbgstr_longlong(timelength
));
733 static HRESULT WINAPI
media_object_ProcessOutput(IMediaObject
*iface
, DWORD flags
, DWORD count
,
734 DMO_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
736 FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface
, flags
, count
, buffers
, status
);
740 static HRESULT WINAPI
media_object_Lock(IMediaObject
*iface
, LONG lock
)
742 FIXME("iface %p, lock %ld stub!\n", iface
, lock
);
746 static const IMediaObjectVtbl media_object_vtbl
=
748 media_object_QueryInterface
,
750 media_object_Release
,
751 media_object_GetStreamCount
,
752 media_object_GetInputStreamInfo
,
753 media_object_GetOutputStreamInfo
,
754 media_object_GetInputType
,
755 media_object_GetOutputType
,
756 media_object_SetInputType
,
757 media_object_SetOutputType
,
758 media_object_GetInputCurrentType
,
759 media_object_GetOutputCurrentType
,
760 media_object_GetInputSizeInfo
,
761 media_object_GetOutputSizeInfo
,
762 media_object_GetInputMaxLatency
,
763 media_object_SetInputMaxLatency
,
765 media_object_Discontinuity
,
766 media_object_AllocateStreamingResources
,
767 media_object_FreeStreamingResources
,
768 media_object_GetInputStatus
,
769 media_object_ProcessInput
,
770 media_object_ProcessOutput
,
774 static inline struct resampler
*impl_from_IPropertyBag(IPropertyBag
*iface
)
776 return CONTAINING_RECORD(iface
, struct resampler
, IPropertyBag_iface
);
779 static HRESULT WINAPI
property_bag_QueryInterface(IPropertyBag
*iface
, REFIID iid
, void **out
)
781 return IUnknown_QueryInterface(impl_from_IPropertyBag(iface
)->outer
, iid
, out
);
784 static ULONG WINAPI
property_bag_AddRef(IPropertyBag
*iface
)
786 return IUnknown_AddRef(impl_from_IPropertyBag(iface
)->outer
);
789 static ULONG WINAPI
property_bag_Release(IPropertyBag
*iface
)
791 return IUnknown_Release(impl_from_IPropertyBag(iface
)->outer
);
794 static HRESULT WINAPI
property_bag_Read(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
,
795 IErrorLog
*error_log
)
797 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface
, debugstr_w(prop_name
), value
, error_log
);
801 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
)
803 FIXME("iface %p, prop_name %s, value %p stub!\n", iface
, debugstr_w(prop_name
), value
);
807 static const IPropertyBagVtbl property_bag_vtbl
=
809 property_bag_QueryInterface
,
811 property_bag_Release
,
816 static inline struct resampler
*impl_from_IPropertyStore(IPropertyStore
*iface
)
818 return CONTAINING_RECORD(iface
, struct resampler
, IPropertyStore_iface
);
821 static HRESULT WINAPI
property_store_QueryInterface(IPropertyStore
*iface
, REFIID iid
, void **out
)
823 return IUnknown_QueryInterface(impl_from_IPropertyStore(iface
)->outer
, iid
, out
);
826 static ULONG WINAPI
property_store_AddRef(IPropertyStore
*iface
)
828 return IUnknown_AddRef(impl_from_IPropertyStore(iface
)->outer
);
831 static ULONG WINAPI
property_store_Release(IPropertyStore
*iface
)
833 return IUnknown_Release(impl_from_IPropertyStore(iface
)->outer
);
836 static HRESULT WINAPI
property_store_GetCount(IPropertyStore
*iface
, DWORD
*count
)
838 FIXME("iface %p, count %p stub!\n", iface
, count
);
842 static HRESULT WINAPI
property_store_GetAt(IPropertyStore
*iface
, DWORD index
, PROPERTYKEY
*key
)
844 FIXME("iface %p, index %lu, key %p stub!\n", iface
, index
, key
);
848 static HRESULT WINAPI
property_store_GetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*value
)
850 FIXME("iface %p, key %p, value %p stub!\n", iface
, key
, value
);
854 static HRESULT WINAPI
property_store_SetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, REFPROPVARIANT value
)
856 FIXME("iface %p, key %p, value %p stub!\n", iface
, key
, value
);
860 static HRESULT WINAPI
property_store_Commit(IPropertyStore
*iface
)
862 FIXME("iface %p stub!\n", iface
);
866 static const IPropertyStoreVtbl property_store_vtbl
=
868 property_store_QueryInterface
,
869 property_store_AddRef
,
870 property_store_Release
,
871 property_store_GetCount
,
872 property_store_GetAt
,
873 property_store_GetValue
,
874 property_store_SetValue
,
875 property_store_Commit
,
878 static inline struct resampler
*impl_from_IWMResamplerProps(IWMResamplerProps
*iface
)
880 return CONTAINING_RECORD(iface
, struct resampler
, IWMResamplerProps_iface
);
883 static HRESULT WINAPI
resampler_props_QueryInterface(IWMResamplerProps
*iface
, REFIID iid
, void **out
)
885 return IUnknown_QueryInterface(impl_from_IWMResamplerProps(iface
)->outer
, iid
, out
);
888 static ULONG WINAPI
resampler_props_AddRef(IWMResamplerProps
*iface
)
890 return IUnknown_AddRef(impl_from_IWMResamplerProps(iface
)->outer
);
893 static ULONG WINAPI
resampler_props_Release(IWMResamplerProps
*iface
)
895 return IUnknown_Release(impl_from_IWMResamplerProps(iface
)->outer
);
898 static HRESULT WINAPI
resampler_props_SetHalfFilterLength(IWMResamplerProps
*iface
, LONG length
)
900 FIXME("iface %p, count %lu stub!\n", iface
, length
);
904 static HRESULT WINAPI
resampler_props_SetUserChannelMtx(IWMResamplerProps
*iface
, ChMtxType
*conversion_matrix
)
906 FIXME("iface %p, userChannelMtx %p stub!\n", iface
, conversion_matrix
);
910 static const IWMResamplerPropsVtbl resampler_props_vtbl
=
912 resampler_props_QueryInterface
,
913 resampler_props_AddRef
,
914 resampler_props_Release
,
915 resampler_props_SetHalfFilterLength
,
916 resampler_props_SetUserChannelMtx
,
919 HRESULT
resampler_create(IUnknown
*outer
, IUnknown
**out
)
921 static const struct wg_format input_format
=
923 .major_type
= WG_MAJOR_TYPE_AUDIO
,
926 .format
= WG_AUDIO_FORMAT_S16LE
,
932 static const struct wg_format output_format
=
934 .major_type
= WG_MAJOR_TYPE_AUDIO
,
937 .format
= WG_AUDIO_FORMAT_F32LE
,
943 struct wg_transform_attrs attrs
= {0};
944 wg_transform_t transform
;
945 struct resampler
*impl
;
948 TRACE("outer %p, out %p.\n", outer
, out
);
950 if (!(transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
952 ERR_(winediag
)("GStreamer doesn't support audio resampling, please install appropriate plugins.\n");
955 wg_transform_destroy(transform
);
957 if (!(impl
= calloc(1, sizeof(*impl
))))
958 return E_OUTOFMEMORY
;
960 if (FAILED(hr
= wg_sample_queue_create(&impl
->wg_sample_queue
)))
966 impl
->IUnknown_inner
.lpVtbl
= &unknown_vtbl
;
967 impl
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
968 impl
->IMediaObject_iface
.lpVtbl
= &media_object_vtbl
;
969 impl
->IPropertyBag_iface
.lpVtbl
= &property_bag_vtbl
;
970 impl
->IPropertyStore_iface
.lpVtbl
= &property_store_vtbl
;
971 impl
->IWMResamplerProps_iface
.lpVtbl
= &resampler_props_vtbl
;
973 impl
->outer
= outer
? outer
: &impl
->IUnknown_inner
;
975 impl
->input_info
.cbAlignment
= 1;
976 impl
->output_info
.cbAlignment
= 1;
978 *out
= &impl
->IUnknown_inner
;
979 TRACE("Created %p\n", *out
);