1 /* AAC Decoder 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"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
33 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
37 const GUID
*const guid
;
39 } aac_decoder_input_types
[] =
41 {&MFAudioFormat_AAC
, 0},
42 {&MFAudioFormat_RAW_AAC
, -1},
43 {&MFAudioFormat_AAC
, 1},
44 {&MFAudioFormat_AAC
, 3},
45 {&MFAudioFormat_ADTS
, -1},
47 static const GUID
*const aac_decoder_output_types
[] =
53 static const UINT32 default_channel_mask
[7] =
58 SPEAKER_FRONT_LEFT
| SPEAKER_FRONT_RIGHT
| SPEAKER_BACK_CENTER
,
60 KSAUDIO_SPEAKER_QUAD
| SPEAKER_FRONT_CENTER
,
61 KSAUDIO_SPEAKER_5POINT1
,
66 IMFTransform IMFTransform_iface
;
68 IMFMediaType
*input_type
;
69 IMFMediaType
*output_type
;
71 wg_transform_t wg_transform
;
72 struct wg_sample_queue
*wg_sample_queue
;
75 static struct aac_decoder
*impl_from_IMFTransform(IMFTransform
*iface
)
77 return CONTAINING_RECORD(iface
, struct aac_decoder
, IMFTransform_iface
);
80 static HRESULT
try_create_wg_transform(struct aac_decoder
*decoder
)
82 struct wg_format input_format
, output_format
;
83 struct wg_transform_attrs attrs
= {0};
85 if (decoder
->wg_transform
)
86 wg_transform_destroy(decoder
->wg_transform
);
87 decoder
->wg_transform
= 0;
89 mf_media_type_to_wg_format(decoder
->input_type
, &input_format
);
90 if (input_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
91 return MF_E_INVALIDMEDIATYPE
;
93 mf_media_type_to_wg_format(decoder
->output_type
, &output_format
);
94 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
95 return MF_E_INVALIDMEDIATYPE
;
97 if (!(decoder
->wg_transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
103 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
105 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
107 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
109 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IMFTransform
))
110 *out
= &decoder
->IMFTransform_iface
;
114 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
115 return E_NOINTERFACE
;
118 IUnknown_AddRef((IUnknown
*)*out
);
122 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
124 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
125 ULONG refcount
= InterlockedIncrement(&decoder
->refcount
);
126 TRACE("iface %p increasing refcount to %lu.\n", decoder
, refcount
);
130 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
132 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
133 ULONG refcount
= InterlockedDecrement(&decoder
->refcount
);
135 TRACE("iface %p decreasing refcount to %lu.\n", decoder
, refcount
);
139 if (decoder
->wg_transform
)
140 wg_transform_destroy(decoder
->wg_transform
);
141 if (decoder
->input_type
)
142 IMFMediaType_Release(decoder
->input_type
);
143 if (decoder
->output_type
)
144 IMFMediaType_Release(decoder
->output_type
);
145 wg_sample_queue_destroy(decoder
->wg_sample_queue
);
152 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
153 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
155 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
156 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
157 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
161 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
163 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
164 *inputs
= *outputs
= 1;
168 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
169 DWORD output_size
, DWORD
*outputs
)
171 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
172 input_size
, inputs
, output_size
, outputs
);
176 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
178 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
181 return MF_E_INVALIDSTREAMNUMBER
;
183 memset(info
, 0, sizeof(*info
));
184 info
->dwFlags
= MFT_INPUT_STREAM_WHOLE_SAMPLES
| MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
185 | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE
| MFT_INPUT_STREAM_HOLDS_BUFFERS
;
190 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
192 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
195 return MF_E_INVALIDSTREAMNUMBER
;
197 memset(info
, 0, sizeof(*info
));
198 info
->dwFlags
= MFT_INPUT_STREAM_WHOLE_SAMPLES
;
199 info
->cbSize
= 0xc000;
204 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
206 TRACE("iface %p, attributes %p.\n", iface
, attributes
);
210 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
212 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
216 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
218 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
222 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
224 TRACE("iface %p, id %#lx.\n", iface
, id
);
228 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
230 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
234 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
237 IMFMediaType
*media_type
;
241 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
244 return MF_E_INVALIDSTREAMNUMBER
;
247 if (index
>= ARRAY_SIZE(aac_decoder_input_types
))
248 return MF_E_NO_MORE_TYPES
;
249 subtype
= aac_decoder_input_types
[index
].guid
;
251 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
254 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
)))
256 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
259 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, 32)))
261 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, 6)))
263 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, 24)))
265 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000)))
267 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 1152000)))
269 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_PREFER_WAVEFORMATEX
, 1)))
271 if (IsEqualGUID(subtype
, &MFAudioFormat_AAC
))
273 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION
, 0)))
275 if (aac_decoder_input_types
[index
].payload_type
!= -1
276 && FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AAC_PAYLOAD_TYPE
,
277 aac_decoder_input_types
[index
].payload_type
)))
283 IMFMediaType_AddRef((*type
= media_type
));
285 IMFMediaType_Release(media_type
);
289 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
292 UINT32 channel_count
, sample_size
, sample_rate
, block_alignment
;
293 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
294 IMFMediaType
*media_type
;
295 const GUID
*output_type
;
298 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
301 return MF_E_INVALIDSTREAMNUMBER
;
302 if (!decoder
->input_type
)
303 return MF_E_TRANSFORM_TYPE_NOT_SET
;
307 if (FAILED(hr
= IMFMediaType_GetUINT32(decoder
->input_type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channel_count
))
311 if (channel_count
>= ARRAY_SIZE(default_channel_mask
))
312 return MF_E_INVALIDMEDIATYPE
;
314 if (channel_count
> 2 && index
>= ARRAY_SIZE(aac_decoder_output_types
))
316 /* If there are more than two channels in the input type GetOutputAvailableType additionally lists
317 * types with 2 channels. */
318 index
-= ARRAY_SIZE(aac_decoder_output_types
);
322 if (index
>= ARRAY_SIZE(aac_decoder_output_types
))
323 return MF_E_NO_MORE_TYPES
;
324 index
= ARRAY_SIZE(aac_decoder_output_types
) - index
- 1;
325 output_type
= aac_decoder_output_types
[index
];
327 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
330 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
)))
332 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, output_type
)))
335 if (IsEqualGUID(output_type
, &MFAudioFormat_Float
))
337 else if (IsEqualGUID(output_type
, &MFAudioFormat_PCM
))
341 FIXME("Subtype %s not implemented!\n", debugstr_guid(output_type
));
346 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, sample_size
)))
349 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, channel_count
)))
352 if (FAILED(hr
= IMFMediaType_GetUINT32(decoder
->input_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &sample_rate
)))
354 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, sample_rate
)))
357 block_alignment
= sample_size
* channel_count
/ 8;
358 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, block_alignment
)))
360 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, sample_rate
* block_alignment
)))
363 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, 1)))
365 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, 1)))
367 if (channel_count
< 3 && FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_PREFER_WAVEFORMATEX
, 1)))
369 if (channel_count
>= 3 && FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_CHANNEL_MASK
,
370 default_channel_mask
[channel_count
])))
375 IMFMediaType_AddRef((*type
= media_type
));
377 IMFMediaType_Release(media_type
);
381 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
383 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
384 MF_ATTRIBUTE_TYPE item_type
;
385 UINT32 channel_count
;
390 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
393 return MF_E_INVALIDSTREAMNUMBER
;
395 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)))
398 if (!IsEqualGUID(&major
, &MFMediaType_Audio
)
399 || FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
400 return MF_E_INVALIDMEDIATYPE
;
402 for (i
= 0; i
< ARRAY_SIZE(aac_decoder_input_types
); ++i
)
403 if (IsEqualGUID(&subtype
, aac_decoder_input_types
[i
].guid
))
405 if (i
== ARRAY_SIZE(aac_decoder_input_types
))
406 return MF_E_INVALIDMEDIATYPE
;
408 if (SUCCEEDED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channel_count
))
409 && channel_count
>= ARRAY_SIZE(default_channel_mask
))
410 return MF_E_INVALIDMEDIATYPE
;
412 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &item_type
))
413 || item_type
!= MF_ATTRIBUTE_UINT32
)
414 return MF_E_INVALIDMEDIATYPE
;
415 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_USER_DATA
, &item_type
))
416 || item_type
!= MF_ATTRIBUTE_BLOB
)
417 return MF_E_INVALIDMEDIATYPE
;
418 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
421 if (!decoder
->input_type
&& FAILED(hr
= MFCreateMediaType(&decoder
->input_type
)))
424 if (decoder
->output_type
)
426 IMFMediaType_Release(decoder
->output_type
);
427 decoder
->output_type
= NULL
;
430 return IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)decoder
->input_type
);
433 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
435 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
436 MF_ATTRIBUTE_TYPE item_type
;
441 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
444 return MF_E_INVALIDSTREAMNUMBER
;
445 if (!decoder
->input_type
)
446 return MF_E_TRANSFORM_TYPE_NOT_SET
;
448 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
))
449 || FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
452 if (!IsEqualGUID(&major
, &MFMediaType_Audio
))
453 return MF_E_INVALIDMEDIATYPE
;
455 for (i
= 0; i
< ARRAY_SIZE(aac_decoder_output_types
); ++i
)
456 if (IsEqualGUID(&subtype
, aac_decoder_output_types
[i
]))
458 if (i
== ARRAY_SIZE(aac_decoder_output_types
))
459 return MF_E_INVALIDMEDIATYPE
;
461 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &item_type
))
462 || item_type
!= MF_ATTRIBUTE_UINT32
)
463 return MF_E_INVALIDMEDIATYPE
;
464 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &item_type
))
465 || item_type
!= MF_ATTRIBUTE_UINT32
)
466 return MF_E_INVALIDMEDIATYPE
;
467 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &item_type
))
468 || item_type
!= MF_ATTRIBUTE_UINT32
)
469 return MF_E_INVALIDMEDIATYPE
;
470 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
473 if (!decoder
->output_type
&& FAILED(hr
= MFCreateMediaType(&decoder
->output_type
)))
476 if (FAILED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)decoder
->output_type
)))
479 if (FAILED(hr
= try_create_wg_transform(decoder
)))
485 IMFMediaType_Release(decoder
->output_type
);
486 decoder
->output_type
= NULL
;
490 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**out
)
492 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
496 TRACE("iface %p, id %#lx, out %p.\n", iface
, id
, out
);
499 return MF_E_INVALIDSTREAMNUMBER
;
500 if (!decoder
->input_type
)
501 return MF_E_TRANSFORM_TYPE_NOT_SET
;
503 if (FAILED(hr
= MFCreateMediaType(&type
)))
505 if (SUCCEEDED(hr
= IMFMediaType_CopyAllItems(decoder
->input_type
, (IMFAttributes
*)type
)))
506 IMFMediaType_AddRef(*out
= type
);
507 IMFMediaType_Release(type
);
512 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**out
)
514 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
518 TRACE("iface %p, id %#lx, out %p.\n", iface
, id
, out
);
521 return MF_E_INVALIDSTREAMNUMBER
;
522 if (!decoder
->output_type
)
523 return MF_E_TRANSFORM_TYPE_NOT_SET
;
525 if (FAILED(hr
= MFCreateMediaType(&type
)))
527 if (SUCCEEDED(hr
= IMFMediaType_CopyAllItems(decoder
->output_type
, (IMFAttributes
*)type
)))
528 IMFMediaType_AddRef(*out
= type
);
529 IMFMediaType_Release(type
);
534 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
536 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
540 TRACE("iface %p, id %#lx, flags %p.\n", iface
, id
, flags
);
542 if (!decoder
->wg_transform
)
543 return MF_E_TRANSFORM_TYPE_NOT_SET
;
545 if (FAILED(hr
= wg_transform_get_status(decoder
->wg_transform
, &accepts_input
)))
548 *flags
= accepts_input
? MFT_INPUT_STATUS_ACCEPT_DATA
: 0;
552 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
554 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
558 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
560 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
564 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
566 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
570 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
572 FIXME("iface %p, message %#x, param %p stub!\n", iface
, message
, (void *)param
);
576 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
578 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
580 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
582 if (!decoder
->wg_transform
)
583 return MF_E_TRANSFORM_TYPE_NOT_SET
;
585 return wg_transform_push_mf(decoder
->wg_transform
, sample
, decoder
->wg_sample_queue
);
588 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
589 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
591 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
592 MFT_OUTPUT_STREAM_INFO info
;
595 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface
, flags
, count
, samples
, status
);
600 if (!decoder
->wg_transform
)
601 return MF_E_TRANSFORM_TYPE_NOT_SET
;
603 *status
= samples
->dwStatus
= 0;
604 if (!samples
->pSample
)
607 if (FAILED(hr
= IMFTransform_GetOutputStreamInfo(iface
, 0, &info
)))
610 if (SUCCEEDED(hr
= wg_transform_read_mf(decoder
->wg_transform
, samples
->pSample
,
611 info
.cbSize
, NULL
, &samples
->dwStatus
)))
612 wg_sample_queue_flush(decoder
->wg_sample_queue
, false);
614 samples
->dwStatus
= MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
;
619 static const IMFTransformVtbl transform_vtbl
=
621 transform_QueryInterface
,
624 transform_GetStreamLimits
,
625 transform_GetStreamCount
,
626 transform_GetStreamIDs
,
627 transform_GetInputStreamInfo
,
628 transform_GetOutputStreamInfo
,
629 transform_GetAttributes
,
630 transform_GetInputStreamAttributes
,
631 transform_GetOutputStreamAttributes
,
632 transform_DeleteInputStream
,
633 transform_AddInputStreams
,
634 transform_GetInputAvailableType
,
635 transform_GetOutputAvailableType
,
636 transform_SetInputType
,
637 transform_SetOutputType
,
638 transform_GetInputCurrentType
,
639 transform_GetOutputCurrentType
,
640 transform_GetInputStatus
,
641 transform_GetOutputStatus
,
642 transform_SetOutputBounds
,
643 transform_ProcessEvent
,
644 transform_ProcessMessage
,
645 transform_ProcessInput
,
646 transform_ProcessOutput
,
649 HRESULT
aac_decoder_create(REFIID riid
, void **ret
)
651 static const struct wg_format output_format
=
653 .major_type
= WG_MAJOR_TYPE_AUDIO
,
656 .format
= WG_AUDIO_FORMAT_F32LE
,
662 static const struct wg_format input_format
= {.major_type
= WG_MAJOR_TYPE_AUDIO_MPEG4
};
663 struct wg_transform_attrs attrs
= {0};
664 wg_transform_t transform
;
665 struct aac_decoder
*decoder
;
668 TRACE("riid %s, ret %p.\n", debugstr_guid(riid
), ret
);
670 if (!(transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
672 ERR_(winediag
)("GStreamer doesn't support WMA decoding, please install appropriate plugins\n");
675 wg_transform_destroy(transform
);
677 if (!(decoder
= calloc(1, sizeof(*decoder
))))
678 return E_OUTOFMEMORY
;
680 if (FAILED(hr
= wg_sample_queue_create(&decoder
->wg_sample_queue
)))
686 decoder
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
687 decoder
->refcount
= 1;
689 *ret
= &decoder
->IMFTransform_iface
;
690 TRACE("Created decoder %p\n", *ret
);