1 /* WMA Decoder DMO / MF Transform
3 * Copyright 2022 RĂ©mi Bernon for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "gst_private.h"
24 #include "mfobjects.h"
25 #include "mftransform.h"
26 #include "wmcodecdsp.h"
28 #include "wine/debug.h"
29 #include "wine/heap.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wmadec
);
32 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
34 static const GUID
*const wma_decoder_input_types
[] =
36 &MEDIASUBTYPE_MSAUDIO1
,
37 &MFAudioFormat_WMAudioV8
,
38 &MFAudioFormat_WMAudioV9
,
39 &MFAudioFormat_WMAudio_Lossless
,
41 static const GUID
*const wma_decoder_output_types
[] =
49 IUnknown IUnknown_inner
;
50 IMFTransform IMFTransform_iface
;
51 IMediaObject IMediaObject_iface
;
52 IPropertyBag IPropertyBag_iface
;
56 IMFMediaType
*input_type
;
57 MFT_INPUT_STREAM_INFO input_info
;
58 IMFMediaType
*output_type
;
59 MFT_OUTPUT_STREAM_INFO output_info
;
61 wg_transform_t wg_transform
;
62 struct wg_sample_queue
*wg_sample_queue
;
65 static inline struct wma_decoder
*impl_from_IUnknown(IUnknown
*iface
)
67 return CONTAINING_RECORD(iface
, struct wma_decoder
, IUnknown_inner
);
70 static HRESULT
try_create_wg_transform(struct wma_decoder
*decoder
)
72 struct wg_format input_format
, output_format
;
73 struct wg_transform_attrs attrs
= {0};
75 if (decoder
->wg_transform
)
76 wg_transform_destroy(decoder
->wg_transform
);
77 decoder
->wg_transform
= 0;
79 mf_media_type_to_wg_format(decoder
->input_type
, &input_format
);
80 if (input_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
81 return MF_E_INVALIDMEDIATYPE
;
83 mf_media_type_to_wg_format(decoder
->output_type
, &output_format
);
84 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
85 return MF_E_INVALIDMEDIATYPE
;
87 if (!(decoder
->wg_transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
93 static HRESULT WINAPI
unknown_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
95 struct wma_decoder
*decoder
= impl_from_IUnknown(iface
);
97 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
99 if (IsEqualGUID(iid
, &IID_IUnknown
))
100 *out
= &decoder
->IUnknown_inner
;
101 else if (IsEqualGUID(iid
, &IID_IMFTransform
))
102 *out
= &decoder
->IMFTransform_iface
;
103 else if (IsEqualGUID(iid
, &IID_IMediaObject
))
104 *out
= &decoder
->IMediaObject_iface
;
105 else if (IsEqualIID(iid
, &IID_IPropertyBag
))
106 *out
= &decoder
->IPropertyBag_iface
;
110 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
111 return E_NOINTERFACE
;
114 IUnknown_AddRef((IUnknown
*)*out
);
118 static ULONG WINAPI
unknown_AddRef(IUnknown
*iface
)
120 struct wma_decoder
*decoder
= impl_from_IUnknown(iface
);
121 ULONG refcount
= InterlockedIncrement(&decoder
->refcount
);
123 TRACE("iface %p increasing refcount to %lu.\n", decoder
, refcount
);
128 static ULONG WINAPI
unknown_Release(IUnknown
*iface
)
130 struct wma_decoder
*decoder
= impl_from_IUnknown(iface
);
131 ULONG refcount
= InterlockedDecrement(&decoder
->refcount
);
133 TRACE("iface %p decreasing refcount to %lu.\n", decoder
, refcount
);
137 if (decoder
->wg_transform
)
138 wg_transform_destroy(decoder
->wg_transform
);
139 if (decoder
->input_type
)
140 IMFMediaType_Release(decoder
->input_type
);
141 if (decoder
->output_type
)
142 IMFMediaType_Release(decoder
->output_type
);
144 wg_sample_queue_destroy(decoder
->wg_sample_queue
);
151 static const IUnknownVtbl unknown_vtbl
=
153 unknown_QueryInterface
,
158 static struct wma_decoder
*impl_from_IMFTransform(IMFTransform
*iface
)
160 return CONTAINING_RECORD(iface
, struct wma_decoder
, IMFTransform_iface
);
163 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
165 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
166 return IUnknown_QueryInterface(decoder
->outer
, iid
, out
);
169 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
171 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
172 return IUnknown_AddRef(decoder
->outer
);
175 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
177 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
178 return IUnknown_Release(decoder
->outer
);
181 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
182 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
184 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
185 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
186 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
190 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
192 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
193 *inputs
= *outputs
= 1;
197 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
198 DWORD output_size
, DWORD
*outputs
)
200 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
201 input_size
, inputs
, output_size
, outputs
);
205 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
207 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
209 TRACE("iface %p, id %lu, info %p.\n", iface
, id
, info
);
211 if (!decoder
->input_type
|| !decoder
->output_type
)
213 memset(info
, 0, sizeof(*info
));
214 return MF_E_TRANSFORM_TYPE_NOT_SET
;
217 *info
= decoder
->input_info
;
221 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
223 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
225 TRACE("iface %p, id %lu, info %p.\n", iface
, id
, info
);
227 if (!decoder
->input_type
|| !decoder
->output_type
)
229 memset(info
, 0, sizeof(*info
));
230 return MF_E_TRANSFORM_TYPE_NOT_SET
;
233 *info
= decoder
->output_info
;
237 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
239 TRACE("iface %p, attributes %p.\n", iface
, attributes
);
243 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
245 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
249 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
251 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
255 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
257 TRACE("iface %p, id %#lx.\n", iface
, id
);
261 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
263 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
267 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
270 FIXME("iface %p, id %lu, index %lu, type %p stub!\n", iface
, id
, index
, type
);
274 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
277 UINT32 channel_count
, sample_size
, sample_rate
, block_alignment
;
278 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
279 IMFMediaType
*media_type
;
280 const GUID
*output_type
;
283 TRACE("iface %p, id %lu, index %lu, type %p.\n", iface
, id
, index
, type
);
285 if (!decoder
->input_type
)
286 return MF_E_TRANSFORM_TYPE_NOT_SET
;
290 if (index
>= ARRAY_SIZE(wma_decoder_output_types
))
291 return MF_E_NO_MORE_TYPES
;
292 output_type
= wma_decoder_output_types
[index
];
294 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
297 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
)))
299 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, output_type
)))
302 if (IsEqualGUID(output_type
, &MFAudioFormat_Float
))
304 else if (IsEqualGUID(output_type
, &MFAudioFormat_PCM
))
308 FIXME("Subtype %s not implemented!\n", debugstr_guid(output_type
));
313 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, sample_size
)))
316 if (FAILED(hr
= IMFMediaType_GetUINT32(decoder
->input_type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channel_count
)))
318 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, channel_count
)))
321 if (FAILED(hr
= IMFMediaType_GetUINT32(decoder
->input_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &sample_rate
)))
323 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, sample_rate
)))
326 block_alignment
= sample_size
* channel_count
/ 8;
327 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, block_alignment
)))
329 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, sample_rate
* block_alignment
)))
332 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, 1)))
334 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, 1)))
336 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_PREFER_WAVEFORMATEX
, 1)))
341 IMFMediaType_AddRef((*type
= media_type
));
343 IMFMediaType_Release(media_type
);
347 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
349 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
350 MF_ATTRIBUTE_TYPE item_type
;
351 UINT32 block_alignment
;
356 TRACE("iface %p, id %lu, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
358 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
359 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
362 if (!IsEqualGUID(&major
, &MFMediaType_Audio
))
363 return MF_E_INVALIDMEDIATYPE
;
365 for (i
= 0; i
< ARRAY_SIZE(wma_decoder_input_types
); ++i
)
366 if (IsEqualGUID(&subtype
, wma_decoder_input_types
[i
]))
368 if (i
== ARRAY_SIZE(wma_decoder_input_types
))
369 return MF_E_INVALIDMEDIATYPE
;
371 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_USER_DATA
, &item_type
)) ||
372 item_type
!= MF_ATTRIBUTE_BLOB
)
373 return MF_E_INVALIDMEDIATYPE
;
374 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
375 return MF_E_INVALIDMEDIATYPE
;
376 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &item_type
)) ||
377 item_type
!= MF_ATTRIBUTE_UINT32
)
378 return MF_E_INVALIDMEDIATYPE
;
379 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &item_type
)) ||
380 item_type
!= MF_ATTRIBUTE_UINT32
)
381 return MF_E_INVALIDMEDIATYPE
;
382 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
385 if (!decoder
->input_type
&& FAILED(hr
= MFCreateMediaType(&decoder
->input_type
)))
388 if (decoder
->output_type
)
390 IMFMediaType_Release(decoder
->output_type
);
391 decoder
->output_type
= NULL
;
394 if (SUCCEEDED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)decoder
->input_type
)))
395 decoder
->input_info
.cbSize
= block_alignment
;
398 IMFMediaType_Release(decoder
->input_type
);
399 decoder
->input_info
.cbSize
= 0;
400 decoder
->input_type
= NULL
;
406 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
408 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
409 UINT32 channel_count
, block_alignment
;
410 MF_ATTRIBUTE_TYPE item_type
;
411 ULONG i
, sample_size
;
415 TRACE("iface %p, id %lu, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
417 if (!decoder
->input_type
)
418 return MF_E_TRANSFORM_TYPE_NOT_SET
;
420 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
421 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
424 if (!IsEqualGUID(&major
, &MFMediaType_Audio
))
425 return MF_E_INVALIDMEDIATYPE
;
427 for (i
= 0; i
< ARRAY_SIZE(wma_decoder_output_types
); ++i
)
428 if (IsEqualGUID(&subtype
, wma_decoder_output_types
[i
]))
430 if (i
== ARRAY_SIZE(wma_decoder_output_types
))
431 return MF_E_INVALIDMEDIATYPE
;
433 if (IsEqualGUID(&subtype
, &MFAudioFormat_Float
))
435 else if (IsEqualGUID(&subtype
, &MFAudioFormat_PCM
))
439 FIXME("Subtype %s not implemented!\n", debugstr_guid(&subtype
));
444 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, &item_type
)) ||
445 item_type
!= MF_ATTRIBUTE_UINT32
)
446 return MF_E_INVALIDMEDIATYPE
;
447 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &item_type
)) ||
448 item_type
!= MF_ATTRIBUTE_UINT32
)
449 return MF_E_INVALIDMEDIATYPE
;
450 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channel_count
)))
451 return MF_E_INVALIDMEDIATYPE
;
452 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &item_type
)) ||
453 item_type
!= MF_ATTRIBUTE_UINT32
)
454 return MF_E_INVALIDMEDIATYPE
;
455 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
456 return MF_E_INVALIDMEDIATYPE
;
457 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
460 if (FAILED(IMFMediaType_SetUINT32(decoder
->input_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, sample_size
)))
461 return MF_E_INVALIDMEDIATYPE
;
463 if (!decoder
->output_type
&& FAILED(hr
= MFCreateMediaType(&decoder
->output_type
)))
466 if (FAILED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)decoder
->output_type
)))
469 if (FAILED(hr
= try_create_wg_transform(decoder
)))
472 decoder
->output_info
.cbSize
= 1024 * block_alignment
* channel_count
;
476 IMFMediaType_Release(decoder
->output_type
);
477 decoder
->output_info
.cbSize
= 0;
478 decoder
->output_type
= NULL
;
482 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
484 FIXME("iface %p, id %lu, type %p stub!\n", iface
, id
, type
);
488 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
490 FIXME("iface %p, id %lu, type %p stub!\n", iface
, id
, type
);
494 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
496 FIXME("iface %p, id %lu, flags %p stub!\n", iface
, id
, flags
);
500 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
502 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
506 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
508 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
512 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
514 FIXME("iface %p, id %lu, event %p stub!\n", iface
, id
, event
);
518 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
520 FIXME("iface %p, message %#x, param %p stub!\n", iface
, message
, (void *)param
);
524 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
526 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
527 MFT_INPUT_STREAM_INFO info
;
531 TRACE("iface %p, id %lu, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
533 if (!decoder
->wg_transform
)
534 return MF_E_TRANSFORM_TYPE_NOT_SET
;
536 if (FAILED(hr
= IMFTransform_GetInputStreamInfo(iface
, 0, &info
))
537 || FAILED(hr
= IMFSample_GetTotalLength(sample
, &total_length
)))
540 /* WMA transform uses fixed size input samples and ignores samples with invalid sizes */
541 if (total_length
% info
.cbSize
)
544 return wg_transform_push_mf(decoder
->wg_transform
, sample
, decoder
->wg_sample_queue
);
547 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
548 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
550 struct wma_decoder
*decoder
= impl_from_IMFTransform(iface
);
551 MFT_OUTPUT_STREAM_INFO info
;
554 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface
, flags
, count
, samples
, status
);
559 if (!decoder
->wg_transform
)
560 return MF_E_TRANSFORM_TYPE_NOT_SET
;
562 *status
= samples
->dwStatus
= 0;
563 if (!samples
->pSample
)
565 samples
[0].dwStatus
= MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
;
566 return MF_E_TRANSFORM_NEED_MORE_INPUT
;
569 if (FAILED(hr
= IMFTransform_GetOutputStreamInfo(iface
, 0, &info
)))
572 if (SUCCEEDED(hr
= wg_transform_read_mf(decoder
->wg_transform
, samples
->pSample
,
573 info
.cbSize
, NULL
, &samples
->dwStatus
)))
574 wg_sample_queue_flush(decoder
->wg_sample_queue
, false);
579 static const IMFTransformVtbl transform_vtbl
=
581 transform_QueryInterface
,
584 transform_GetStreamLimits
,
585 transform_GetStreamCount
,
586 transform_GetStreamIDs
,
587 transform_GetInputStreamInfo
,
588 transform_GetOutputStreamInfo
,
589 transform_GetAttributes
,
590 transform_GetInputStreamAttributes
,
591 transform_GetOutputStreamAttributes
,
592 transform_DeleteInputStream
,
593 transform_AddInputStreams
,
594 transform_GetInputAvailableType
,
595 transform_GetOutputAvailableType
,
596 transform_SetInputType
,
597 transform_SetOutputType
,
598 transform_GetInputCurrentType
,
599 transform_GetOutputCurrentType
,
600 transform_GetInputStatus
,
601 transform_GetOutputStatus
,
602 transform_SetOutputBounds
,
603 transform_ProcessEvent
,
604 transform_ProcessMessage
,
605 transform_ProcessInput
,
606 transform_ProcessOutput
,
609 static inline struct wma_decoder
*impl_from_IMediaObject(IMediaObject
*iface
)
611 return CONTAINING_RECORD(iface
, struct wma_decoder
, IMediaObject_iface
);
614 static HRESULT WINAPI
media_object_QueryInterface(IMediaObject
*iface
, REFIID iid
, void **obj
)
616 struct wma_decoder
*decoder
= impl_from_IMediaObject(iface
);
617 return IUnknown_QueryInterface(decoder
->outer
, iid
, obj
);
620 static ULONG WINAPI
media_object_AddRef(IMediaObject
*iface
)
622 struct wma_decoder
*decoder
= impl_from_IMediaObject(iface
);
623 return IUnknown_AddRef(decoder
->outer
);
626 static ULONG WINAPI
media_object_Release(IMediaObject
*iface
)
628 struct wma_decoder
*decoder
= impl_from_IMediaObject(iface
);
629 return IUnknown_Release(decoder
->outer
);
632 static HRESULT WINAPI
media_object_GetStreamCount(IMediaObject
*iface
, DWORD
*input
, DWORD
*output
)
634 FIXME("iface %p, input %p, output %p semi-stub!\n", iface
, input
, output
);
635 *input
= *output
= 1;
639 static HRESULT WINAPI
media_object_GetInputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
641 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
645 static HRESULT WINAPI
media_object_GetOutputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
647 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
651 static HRESULT WINAPI
media_object_GetInputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
652 DMO_MEDIA_TYPE
*type
)
654 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface
, index
, type_index
, type
);
658 static HRESULT WINAPI
media_object_GetOutputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
659 DMO_MEDIA_TYPE
*type
)
661 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface
, index
, type_index
, type
);
665 static HRESULT WINAPI
media_object_SetInputType(IMediaObject
*iface
, DWORD index
,
666 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
668 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface
, index
, type
, flags
);
672 static HRESULT WINAPI
media_object_SetOutputType(IMediaObject
*iface
, DWORD index
,
673 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
675 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface
, index
, type
, flags
);
679 static HRESULT WINAPI
media_object_GetInputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
681 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
685 static HRESULT WINAPI
media_object_GetOutputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
687 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
691 static HRESULT WINAPI
media_object_GetInputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
,
692 DWORD
*lookahead
, DWORD
*alignment
)
694 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface
, index
, size
,
695 lookahead
, alignment
);
699 static HRESULT WINAPI
media_object_GetOutputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
, DWORD
*alignment
)
701 FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface
, index
, size
, alignment
);
705 static HRESULT WINAPI
media_object_GetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME
*latency
)
707 FIXME("iface %p, index %lu, latency %p stub!\n", iface
, index
, latency
);
711 static HRESULT WINAPI
media_object_SetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME latency
)
713 FIXME("iface %p, index %lu, latency %s stub!\n", iface
, index
, wine_dbgstr_longlong(latency
));
717 static HRESULT WINAPI
media_object_Flush(IMediaObject
*iface
)
719 FIXME("iface %p stub!\n", iface
);
723 static HRESULT WINAPI
media_object_Discontinuity(IMediaObject
*iface
, DWORD index
)
725 FIXME("iface %p, index %lu stub!\n", iface
, index
);
729 static HRESULT WINAPI
media_object_AllocateStreamingResources(IMediaObject
*iface
)
731 FIXME("iface %p stub!\n", iface
);
735 static HRESULT WINAPI
media_object_FreeStreamingResources(IMediaObject
*iface
)
737 FIXME("iface %p stub!\n", iface
);
741 static HRESULT WINAPI
media_object_GetInputStatus(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
743 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
747 static HRESULT WINAPI
media_object_ProcessInput(IMediaObject
*iface
, DWORD index
,
748 IMediaBuffer
*buffer
, DWORD flags
, REFERENCE_TIME timestamp
, REFERENCE_TIME timelength
)
750 FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface
,
751 index
, buffer
, flags
, wine_dbgstr_longlong(timestamp
), wine_dbgstr_longlong(timelength
));
755 static HRESULT WINAPI
media_object_ProcessOutput(IMediaObject
*iface
, DWORD flags
, DWORD count
,
756 DMO_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
758 FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface
, flags
, count
, buffers
, status
);
762 static HRESULT WINAPI
media_object_Lock(IMediaObject
*iface
, LONG lock
)
764 FIXME("iface %p, lock %ld stub!\n", iface
, lock
);
768 static const IMediaObjectVtbl media_object_vtbl
=
770 media_object_QueryInterface
,
772 media_object_Release
,
773 media_object_GetStreamCount
,
774 media_object_GetInputStreamInfo
,
775 media_object_GetOutputStreamInfo
,
776 media_object_GetInputType
,
777 media_object_GetOutputType
,
778 media_object_SetInputType
,
779 media_object_SetOutputType
,
780 media_object_GetInputCurrentType
,
781 media_object_GetOutputCurrentType
,
782 media_object_GetInputSizeInfo
,
783 media_object_GetOutputSizeInfo
,
784 media_object_GetInputMaxLatency
,
785 media_object_SetInputMaxLatency
,
787 media_object_Discontinuity
,
788 media_object_AllocateStreamingResources
,
789 media_object_FreeStreamingResources
,
790 media_object_GetInputStatus
,
791 media_object_ProcessInput
,
792 media_object_ProcessOutput
,
796 static inline struct wma_decoder
*impl_from_IPropertyBag(IPropertyBag
*iface
)
798 return CONTAINING_RECORD(iface
, struct wma_decoder
, IPropertyBag_iface
);
801 static HRESULT WINAPI
property_bag_QueryInterface(IPropertyBag
*iface
, REFIID iid
, void **out
)
803 struct wma_decoder
*filter
= impl_from_IPropertyBag(iface
);
804 return IUnknown_QueryInterface(filter
->outer
, iid
, out
);
807 static ULONG WINAPI
property_bag_AddRef(IPropertyBag
*iface
)
809 struct wma_decoder
*filter
= impl_from_IPropertyBag(iface
);
810 return IUnknown_AddRef(filter
->outer
);
813 static ULONG WINAPI
property_bag_Release(IPropertyBag
*iface
)
815 struct wma_decoder
*filter
= impl_from_IPropertyBag(iface
);
816 return IUnknown_Release(filter
->outer
);
819 static HRESULT WINAPI
property_bag_Read(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
,
820 IErrorLog
*error_log
)
822 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface
, debugstr_w(prop_name
), value
, error_log
);
826 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
)
828 FIXME("iface %p, prop_name %s, value %p stub!\n", iface
, debugstr_w(prop_name
), value
);
832 static const IPropertyBagVtbl property_bag_vtbl
=
834 property_bag_QueryInterface
,
836 property_bag_Release
,
841 HRESULT
wma_decoder_create(IUnknown
*outer
, IUnknown
**out
)
843 static const struct wg_format output_format
=
845 .major_type
= WG_MAJOR_TYPE_AUDIO
,
848 .format
= WG_AUDIO_FORMAT_F32LE
,
854 static const struct wg_format input_format
= {.major_type
= WG_MAJOR_TYPE_AUDIO_WMA
};
855 struct wg_transform_attrs attrs
= {0};
856 wg_transform_t transform
;
857 struct wma_decoder
*decoder
;
860 TRACE("outer %p, out %p.\n", outer
, out
);
862 if (!(transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
864 ERR_(winediag
)("GStreamer doesn't support WMA decoding, please install appropriate plugins\n");
867 wg_transform_destroy(transform
);
869 if (!(decoder
= calloc(1, sizeof(*decoder
))))
870 return E_OUTOFMEMORY
;
872 if (FAILED(hr
= wg_sample_queue_create(&decoder
->wg_sample_queue
)))
878 decoder
->IUnknown_inner
.lpVtbl
= &unknown_vtbl
;
879 decoder
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
880 decoder
->IMediaObject_iface
.lpVtbl
= &media_object_vtbl
;
881 decoder
->IPropertyBag_iface
.lpVtbl
= &property_bag_vtbl
;
882 decoder
->refcount
= 1;
883 decoder
->outer
= outer
? outer
: &decoder
->IUnknown_inner
;
885 decoder
->input_info
.cbAlignment
= 1;
886 decoder
->output_info
.cbAlignment
= 1;
888 *out
= &decoder
->IUnknown_inner
;
889 TRACE("Created decoder %p\n", *out
);