wrc: Store version and characteristics as simple integers.
[wine.git] / dlls / winegstreamer / wma_decoder.c
blob57b0f204f9e3be95892b30bce3c587ad7df370e0
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"
22 #include "mfapi.h"
23 #include "mferror.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);
33 static const GUID *const wma_decoder_input_types[] =
35 &MEDIASUBTYPE_MSAUDIO1,
36 &MFAudioFormat_WMAudioV8,
37 &MFAudioFormat_WMAudioV9,
38 &MFAudioFormat_WMAudio_Lossless,
40 static const GUID *const wma_decoder_output_types[] =
42 &MFAudioFormat_Float,
43 &MFAudioFormat_PCM,
46 struct wma_decoder
48 IUnknown IUnknown_inner;
49 IMFTransform IMFTransform_iface;
50 IMediaObject IMediaObject_iface;
51 IPropertyBag IPropertyBag_iface;
52 IUnknown *outer;
53 LONG refcount;
54 IMFMediaType *input_type;
55 IMFMediaType *output_type;
57 struct wg_transform *wg_transform;
60 static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
62 return CONTAINING_RECORD(iface, struct wma_decoder, IUnknown_inner);
65 static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
67 struct wg_format input_format, output_format;
69 if (decoder->wg_transform)
70 wg_transform_destroy(decoder->wg_transform);
71 decoder->wg_transform = NULL;
73 mf_media_type_to_wg_format(decoder->input_type, &input_format);
74 if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
75 return MF_E_INVALIDMEDIATYPE;
77 mf_media_type_to_wg_format(decoder->output_type, &output_format);
78 if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
79 return MF_E_INVALIDMEDIATYPE;
81 if (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format)))
82 return E_FAIL;
84 return S_OK;
87 static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out)
89 struct wma_decoder *decoder = impl_from_IUnknown(iface);
91 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
93 if (IsEqualGUID(iid, &IID_IUnknown))
94 *out = &decoder->IUnknown_inner;
95 else if (IsEqualGUID(iid, &IID_IMFTransform))
96 *out = &decoder->IMFTransform_iface;
97 else if (IsEqualGUID(iid, &IID_IMediaObject))
98 *out = &decoder->IMediaObject_iface;
99 else if (IsEqualIID(iid, &IID_IPropertyBag))
100 *out = &decoder->IPropertyBag_iface;
101 else
103 *out = NULL;
104 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
105 return E_NOINTERFACE;
108 IUnknown_AddRef((IUnknown *)*out);
109 return S_OK;
112 static ULONG WINAPI unknown_AddRef(IUnknown *iface)
114 struct wma_decoder *decoder = impl_from_IUnknown(iface);
115 ULONG refcount = InterlockedIncrement(&decoder->refcount);
117 TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount);
119 return refcount;
122 static ULONG WINAPI unknown_Release(IUnknown *iface)
124 struct wma_decoder *decoder = impl_from_IUnknown(iface);
125 ULONG refcount = InterlockedDecrement(&decoder->refcount);
127 TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount);
129 if (!refcount)
131 if (decoder->wg_transform)
132 wg_transform_destroy(decoder->wg_transform);
133 if (decoder->input_type)
134 IMFMediaType_Release(decoder->input_type);
135 if (decoder->output_type)
136 IMFMediaType_Release(decoder->output_type);
137 free(decoder);
140 return refcount;
143 static const IUnknownVtbl unknown_vtbl =
145 unknown_QueryInterface,
146 unknown_AddRef,
147 unknown_Release,
150 static struct wma_decoder *impl_from_IMFTransform(IMFTransform *iface)
152 return CONTAINING_RECORD(iface, struct wma_decoder, IMFTransform_iface);
155 static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out)
157 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
158 return IUnknown_QueryInterface(decoder->outer, iid, out);
161 static ULONG WINAPI transform_AddRef(IMFTransform *iface)
163 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
164 return IUnknown_AddRef(decoder->outer);
167 static ULONG WINAPI transform_Release(IMFTransform *iface)
169 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
170 return IUnknown_Release(decoder->outer);
173 static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
174 DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
176 FIXME("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p stub!\n",
177 iface, input_minimum, input_maximum, output_minimum, output_maximum);
178 return E_NOTIMPL;
181 static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
183 FIXME("iface %p, inputs %p, outputs %p stub!\n", iface, inputs, outputs);
184 return E_NOTIMPL;
187 static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
188 DWORD output_size, DWORD *outputs)
190 FIXME("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p stub!\n", iface,
191 input_size, inputs, output_size, outputs);
192 return E_NOTIMPL;
195 static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
197 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
198 UINT32 block_alignment;
199 HRESULT hr;
201 TRACE("iface %p, id %lu, info %p.\n", iface, id, info);
203 if (!decoder->input_type || !decoder->output_type)
204 return MF_E_TRANSFORM_TYPE_NOT_SET;
206 if (FAILED(hr = IMFMediaType_GetUINT32(decoder->input_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment)))
207 return hr;
209 info->hnsMaxLatency = 0;
210 info->dwFlags = 0;
211 info->cbSize = block_alignment;
212 info->cbMaxLookahead = 0;
213 info->cbAlignment = 1;
215 return S_OK;
218 static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
220 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
221 UINT32 channel_count, block_alignment;
222 HRESULT hr;
224 TRACE("iface %p, id %lu, info %p.\n", iface, id, info);
226 if (!decoder->input_type || !decoder->output_type)
227 return MF_E_TRANSFORM_TYPE_NOT_SET;
229 if (FAILED(hr = IMFMediaType_GetUINT32(decoder->output_type, &MF_MT_AUDIO_NUM_CHANNELS, &channel_count)))
230 return hr;
231 if (FAILED(hr = IMFMediaType_GetUINT32(decoder->output_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment)))
232 return hr;
234 info->dwFlags = 0;
235 info->cbSize = 1024 * block_alignment * channel_count;
236 info->cbAlignment = 1;
238 return S_OK;
241 static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
243 FIXME("iface %p, attributes %p stub!\n", iface, attributes);
244 return E_NOTIMPL;
247 static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
249 FIXME("iface %p, id %lu, attributes %p stub!\n", iface, id, attributes);
250 return E_NOTIMPL;
253 static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes)
255 FIXME("iface %p, id %lu, attributes %p stub!\n", iface, id, attributes);
256 return E_NOTIMPL;
259 static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id)
261 FIXME("iface %p, id %lu stub!\n", iface, id);
262 return E_NOTIMPL;
265 static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
267 FIXME("iface %p, streams %lu, ids %p stub!\n", iface, streams, ids);
268 return E_NOTIMPL;
271 static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
272 IMFMediaType **type)
274 FIXME("iface %p, id %lu, index %lu, type %p stub!\n", iface, id, index, type);
275 return E_NOTIMPL;
278 static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
279 IMFMediaType **type)
281 UINT32 channel_count, sample_size, sample_rate, block_alignment;
282 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
283 IMFMediaType *media_type;
284 const GUID *output_type;
285 HRESULT hr;
287 TRACE("iface %p, id %lu, index %lu, type %p.\n", iface, id, index, type);
289 if (!decoder->input_type)
290 return MF_E_TRANSFORM_TYPE_NOT_SET;
292 *type = NULL;
294 if (index >= ARRAY_SIZE(wma_decoder_output_types))
295 return MF_E_NO_MORE_TYPES;
296 output_type = wma_decoder_output_types[index];
298 if (FAILED(hr = MFCreateMediaType(&media_type)))
299 return hr;
301 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio)))
302 goto done;
303 if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, output_type)))
304 goto done;
306 if (IsEqualGUID(output_type, &MFAudioFormat_Float))
307 sample_size = 32;
308 else if (IsEqualGUID(output_type, &MFAudioFormat_PCM))
309 sample_size = 16;
310 else
312 FIXME("Subtype %s not implemented!\n", debugstr_guid(output_type));
313 hr = E_NOTIMPL;
314 goto done;
317 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, sample_size)))
318 goto done;
320 if (FAILED(hr = IMFMediaType_GetUINT32(decoder->input_type, &MF_MT_AUDIO_NUM_CHANNELS, &channel_count)))
321 goto done;
322 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, channel_count)))
323 goto done;
325 if (FAILED(hr = IMFMediaType_GetUINT32(decoder->input_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &sample_rate)))
326 goto done;
327 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, sample_rate)))
328 goto done;
330 block_alignment = sample_size * channel_count / 8;
331 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, block_alignment)))
332 goto done;
333 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, sample_rate * block_alignment)))
334 goto done;
336 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1)))
337 goto done;
338 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1)))
339 goto done;
340 if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1)))
341 goto done;
343 done:
344 if (SUCCEEDED(hr))
345 IMFMediaType_AddRef((*type = media_type));
347 IMFMediaType_Release(media_type);
348 return hr;
351 static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
353 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
354 MF_ATTRIBUTE_TYPE item_type;
355 GUID major, subtype;
356 HRESULT hr;
357 ULONG i;
359 TRACE("iface %p, id %lu, type %p, flags %#lx.\n", iface, id, type, flags);
361 if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
362 FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
363 return hr;
365 if (!IsEqualGUID(&major, &MFMediaType_Audio))
366 return MF_E_INVALIDMEDIATYPE;
368 for (i = 0; i < ARRAY_SIZE(wma_decoder_input_types); ++i)
369 if (IsEqualGUID(&subtype, wma_decoder_input_types[i]))
370 break;
371 if (i == ARRAY_SIZE(wma_decoder_input_types))
372 return MF_E_INVALIDMEDIATYPE;
374 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_USER_DATA, &item_type)) ||
375 item_type != MF_ATTRIBUTE_BLOB)
376 return MF_E_INVALIDMEDIATYPE;
377 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &item_type)) ||
378 item_type != MF_ATTRIBUTE_UINT32)
379 return MF_E_INVALIDMEDIATYPE;
380 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &item_type)) ||
381 item_type != MF_ATTRIBUTE_UINT32)
382 return MF_E_INVALIDMEDIATYPE;
383 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_NUM_CHANNELS, &item_type)) ||
384 item_type != MF_ATTRIBUTE_UINT32)
385 return MF_E_INVALIDMEDIATYPE;
387 if (!decoder->input_type && FAILED(hr = MFCreateMediaType(&decoder->input_type)))
388 return hr;
390 if (decoder->output_type)
392 IMFMediaType_Release(decoder->output_type);
393 decoder->output_type = NULL;
396 if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)decoder->input_type)))
398 IMFMediaType_Release(decoder->input_type);
399 decoder->input_type = NULL;
402 return hr;
405 static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
407 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
408 MF_ATTRIBUTE_TYPE item_type;
409 ULONG i, sample_size;
410 GUID major, subtype;
411 HRESULT hr;
413 TRACE("iface %p, id %lu, type %p, flags %#lx.\n", iface, id, type, flags);
415 if (!decoder->input_type)
416 return MF_E_TRANSFORM_TYPE_NOT_SET;
418 if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
419 FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
420 return hr;
422 if (!IsEqualGUID(&major, &MFMediaType_Audio))
423 return MF_E_INVALIDMEDIATYPE;
425 for (i = 0; i < ARRAY_SIZE(wma_decoder_output_types); ++i)
426 if (IsEqualGUID(&subtype, wma_decoder_output_types[i]))
427 break;
428 if (i == ARRAY_SIZE(wma_decoder_output_types))
429 return MF_E_INVALIDMEDIATYPE;
431 if (IsEqualGUID(&subtype, &MFAudioFormat_Float))
432 sample_size = 32;
433 else if (IsEqualGUID(&subtype, &MFAudioFormat_PCM))
434 sample_size = 16;
435 else
437 FIXME("Subtype %s not implemented!\n", debugstr_guid(&subtype));
438 hr = E_NOTIMPL;
439 return hr;
442 if (FAILED(IMFMediaType_SetUINT32(decoder->input_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, sample_size)))
443 return MF_E_INVALIDMEDIATYPE;
445 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &item_type)) ||
446 item_type != MF_ATTRIBUTE_UINT32)
447 return MF_E_INVALIDMEDIATYPE;
448 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &item_type)) ||
449 item_type != MF_ATTRIBUTE_UINT32)
450 return MF_E_INVALIDMEDIATYPE;
451 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_NUM_CHANNELS, &item_type)) ||
452 item_type != MF_ATTRIBUTE_UINT32)
453 return MF_E_INVALIDMEDIATYPE;
454 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &item_type)) ||
455 item_type != MF_ATTRIBUTE_UINT32)
456 return MF_E_INVALIDMEDIATYPE;
457 if (FAILED(IMFMediaType_GetItemType(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &item_type)) ||
458 item_type != MF_ATTRIBUTE_UINT32)
459 return MF_E_INVALIDMEDIATYPE;
461 if (!decoder->output_type && FAILED(hr = MFCreateMediaType(&decoder->output_type)))
462 return hr;
464 if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)decoder->output_type)))
465 goto failed;
467 if (FAILED(hr = try_create_wg_transform(decoder)))
468 goto failed;
470 return S_OK;
472 failed:
473 IMFMediaType_Release(decoder->output_type);
474 decoder->output_type = NULL;
475 return hr;
478 static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
480 FIXME("iface %p, id %lu, type %p stub!\n", iface, id, type);
481 return E_NOTIMPL;
484 static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
486 FIXME("iface %p, id %lu, type %p stub!\n", iface, id, type);
487 return E_NOTIMPL;
490 static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
492 FIXME("iface %p, id %lu, flags %p stub!\n", iface, id, flags);
493 return E_NOTIMPL;
496 static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags)
498 FIXME("iface %p, flags %p stub!\n", iface, flags);
499 return E_NOTIMPL;
502 static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
504 FIXME("iface %p, lower %s, upper %s stub!\n", iface, wine_dbgstr_longlong(lower),
505 wine_dbgstr_longlong(upper));
506 return E_NOTIMPL;
509 static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
511 FIXME("iface %p, id %lu, event %p stub!\n", iface, id, event);
512 return E_NOTIMPL;
515 static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
517 FIXME("iface %p, message %#x, param %p stub!\n", iface, message, (void *)param);
518 return S_OK;
521 static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
523 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
524 struct wg_sample *wg_sample;
525 MFT_INPUT_STREAM_INFO info;
526 HRESULT hr;
528 TRACE("iface %p, id %lu, sample %p, flags %#lx.\n", iface, id, sample, flags);
530 if (!decoder->wg_transform)
531 return MF_E_TRANSFORM_TYPE_NOT_SET;
533 if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info)))
534 return hr;
536 if (FAILED(hr = mf_create_wg_sample(sample, &wg_sample)))
537 return hr;
539 /* WMA transform uses fixed size input samples and ignores samples with invalid sizes */
540 if (wg_sample->size % info.cbSize)
541 hr = S_OK;
542 else
543 hr = wg_transform_push_data(decoder->wg_transform, wg_sample);
545 mf_destroy_wg_sample(wg_sample);
546 return hr;
549 static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
550 MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
552 struct wma_decoder *decoder = impl_from_IMFTransform(iface);
553 MFT_OUTPUT_STREAM_INFO info;
554 struct wg_sample *wg_sample;
555 HRESULT hr;
557 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
559 if (count > 1)
560 return E_INVALIDARG;
562 if (!decoder->wg_transform)
563 return MF_E_TRANSFORM_TYPE_NOT_SET;
565 if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
566 return hr;
568 *status = 0;
569 samples[0].dwStatus = 0;
570 if (!samples[0].pSample)
572 samples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE;
573 return MF_E_TRANSFORM_NEED_MORE_INPUT;
576 if (FAILED(hr = mf_create_wg_sample(samples[0].pSample, &wg_sample)))
577 return hr;
579 wg_sample->size = 0;
580 if (wg_sample->max_size < info.cbSize)
581 hr = MF_E_BUFFERTOOSMALL;
582 else if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, wg_sample)))
584 if (wg_sample->flags & WG_SAMPLE_FLAG_INCOMPLETE)
585 samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_INCOMPLETE;
588 mf_destroy_wg_sample(wg_sample);
589 return hr;
592 static const IMFTransformVtbl transform_vtbl =
594 transform_QueryInterface,
595 transform_AddRef,
596 transform_Release,
597 transform_GetStreamLimits,
598 transform_GetStreamCount,
599 transform_GetStreamIDs,
600 transform_GetInputStreamInfo,
601 transform_GetOutputStreamInfo,
602 transform_GetAttributes,
603 transform_GetInputStreamAttributes,
604 transform_GetOutputStreamAttributes,
605 transform_DeleteInputStream,
606 transform_AddInputStreams,
607 transform_GetInputAvailableType,
608 transform_GetOutputAvailableType,
609 transform_SetInputType,
610 transform_SetOutputType,
611 transform_GetInputCurrentType,
612 transform_GetOutputCurrentType,
613 transform_GetInputStatus,
614 transform_GetOutputStatus,
615 transform_SetOutputBounds,
616 transform_ProcessEvent,
617 transform_ProcessMessage,
618 transform_ProcessInput,
619 transform_ProcessOutput,
622 static inline struct wma_decoder *impl_from_IMediaObject(IMediaObject *iface)
624 return CONTAINING_RECORD(iface, struct wma_decoder, IMediaObject_iface);
627 static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
629 struct wma_decoder *decoder = impl_from_IMediaObject(iface);
630 return IUnknown_QueryInterface(decoder->outer, iid, obj);
633 static ULONG WINAPI media_object_AddRef(IMediaObject *iface)
635 struct wma_decoder *decoder = impl_from_IMediaObject(iface);
636 return IUnknown_AddRef(decoder->outer);
639 static ULONG WINAPI media_object_Release(IMediaObject *iface)
641 struct wma_decoder *decoder = impl_from_IMediaObject(iface);
642 return IUnknown_Release(decoder->outer);
645 static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
647 FIXME("iface %p, input %p, output %p semi-stub!\n", iface, input, output);
648 *input = *output = 1;
649 return S_OK;
652 static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
654 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
655 return E_NOTIMPL;
658 static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
660 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
661 return E_NOTIMPL;
664 static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index,
665 DMO_MEDIA_TYPE *type)
667 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type);
668 return E_NOTIMPL;
671 static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index,
672 DMO_MEDIA_TYPE *type)
674 FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type);
675 return E_NOTIMPL;
678 static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index,
679 const DMO_MEDIA_TYPE *type, DWORD flags)
681 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags);
682 return E_NOTIMPL;
685 static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index,
686 const DMO_MEDIA_TYPE *type, DWORD flags)
688 FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags);
689 return E_NOTIMPL;
692 static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
694 FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type);
695 return E_NOTIMPL;
698 static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
700 FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type);
701 return E_NOTIMPL;
704 static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size,
705 DWORD *lookahead, DWORD *alignment)
707 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size,
708 lookahead, alignment);
709 return E_NOTIMPL;
712 static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment)
714 FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface, index, size, alignment);
715 return E_NOTIMPL;
718 static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency)
720 FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency);
721 return E_NOTIMPL;
724 static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency)
726 FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency));
727 return E_NOTIMPL;
730 static HRESULT WINAPI media_object_Flush(IMediaObject *iface)
732 FIXME("iface %p stub!\n", iface);
733 return E_NOTIMPL;
736 static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index)
738 FIXME("iface %p, index %lu stub!\n", iface, index);
739 return E_NOTIMPL;
742 static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface)
744 FIXME("iface %p stub!\n", iface);
745 return E_NOTIMPL;
748 static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface)
750 FIXME("iface %p stub!\n", iface);
751 return E_NOTIMPL;
754 static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags)
756 FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags);
757 return E_NOTIMPL;
760 static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index,
761 IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength)
763 FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface,
764 index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength));
765 return E_NOTIMPL;
768 static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count,
769 DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
771 FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface, flags, count, buffers, status);
772 return E_NOTIMPL;
775 static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock)
777 FIXME("iface %p, lock %ld stub!\n", iface, lock);
778 return E_NOTIMPL;
781 static const IMediaObjectVtbl media_object_vtbl =
783 media_object_QueryInterface,
784 media_object_AddRef,
785 media_object_Release,
786 media_object_GetStreamCount,
787 media_object_GetInputStreamInfo,
788 media_object_GetOutputStreamInfo,
789 media_object_GetInputType,
790 media_object_GetOutputType,
791 media_object_SetInputType,
792 media_object_SetOutputType,
793 media_object_GetInputCurrentType,
794 media_object_GetOutputCurrentType,
795 media_object_GetInputSizeInfo,
796 media_object_GetOutputSizeInfo,
797 media_object_GetInputMaxLatency,
798 media_object_SetInputMaxLatency,
799 media_object_Flush,
800 media_object_Discontinuity,
801 media_object_AllocateStreamingResources,
802 media_object_FreeStreamingResources,
803 media_object_GetInputStatus,
804 media_object_ProcessInput,
805 media_object_ProcessOutput,
806 media_object_Lock,
809 static inline struct wma_decoder *impl_from_IPropertyBag(IPropertyBag *iface)
811 return CONTAINING_RECORD(iface, struct wma_decoder, IPropertyBag_iface);
814 static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out)
816 struct wma_decoder *filter = impl_from_IPropertyBag(iface);
817 return IUnknown_QueryInterface(filter->outer, iid, out);
820 static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface)
822 struct wma_decoder *filter = impl_from_IPropertyBag(iface);
823 return IUnknown_AddRef(filter->outer);
826 static ULONG WINAPI property_bag_Release(IPropertyBag *iface)
828 struct wma_decoder *filter = impl_from_IPropertyBag(iface);
829 return IUnknown_Release(filter->outer);
832 static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value,
833 IErrorLog *error_log)
835 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log);
836 return E_NOTIMPL;
839 static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value)
841 FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value);
842 return S_OK;
845 static const IPropertyBagVtbl property_bag_vtbl =
847 property_bag_QueryInterface,
848 property_bag_AddRef,
849 property_bag_Release,
850 property_bag_Read,
851 property_bag_Write,
854 HRESULT wma_decoder_create(IUnknown *outer, IUnknown **out)
856 struct wma_decoder *decoder;
858 TRACE("outer %p, out %p.\n", outer, out);
860 if (!(decoder = calloc(1, sizeof(*decoder))))
861 return E_OUTOFMEMORY;
863 decoder->IUnknown_inner.lpVtbl = &unknown_vtbl;
864 decoder->IMFTransform_iface.lpVtbl = &transform_vtbl;
865 decoder->IMediaObject_iface.lpVtbl = &media_object_vtbl;
866 decoder->IPropertyBag_iface.lpVtbl = &property_bag_vtbl;
867 decoder->refcount = 1;
868 decoder->outer = outer ? outer : &decoder->IUnknown_inner;
870 *out = &decoder->IUnknown_inner;
871 TRACE("Created decoder %p\n", *out);
872 return S_OK;