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"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
31 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
35 const GUID
*const guid
;
37 } aac_decoder_input_types
[] =
39 {&MFAudioFormat_AAC
, 0},
40 {&MFAudioFormat_RAW_AAC
, -1},
41 {&MFAudioFormat_AAC
, 1},
42 {&MFAudioFormat_AAC
, 3},
43 {&MFAudioFormat_ADTS
, -1},
45 static const GUID
*const aac_decoder_output_types
[] =
53 IMFTransform IMFTransform_iface
;
55 IMFMediaType
*input_type
;
56 IMFMediaType
*output_type
;
58 struct wg_transform
*wg_transform
;
59 struct wg_sample_queue
*wg_sample_queue
;
62 static struct aac_decoder
*impl_from_IMFTransform(IMFTransform
*iface
)
64 return CONTAINING_RECORD(iface
, struct aac_decoder
, IMFTransform_iface
);
67 static HRESULT
try_create_wg_transform(struct aac_decoder
*decoder
)
69 struct wg_format input_format
, output_format
;
70 struct wg_transform_attrs attrs
= {0};
72 if (decoder
->wg_transform
)
73 wg_transform_destroy(decoder
->wg_transform
);
74 decoder
->wg_transform
= NULL
;
76 mf_media_type_to_wg_format(decoder
->input_type
, &input_format
);
77 if (input_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
78 return MF_E_INVALIDMEDIATYPE
;
80 mf_media_type_to_wg_format(decoder
->output_type
, &output_format
);
81 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
82 return MF_E_INVALIDMEDIATYPE
;
84 if (!(decoder
->wg_transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
90 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
92 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
94 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
96 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IMFTransform
))
97 *out
= &decoder
->IMFTransform_iface
;
101 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
102 return E_NOINTERFACE
;
105 IUnknown_AddRef((IUnknown
*)*out
);
109 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
111 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
112 ULONG refcount
= InterlockedIncrement(&decoder
->refcount
);
113 TRACE("iface %p increasing refcount to %lu.\n", decoder
, refcount
);
117 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
119 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
120 ULONG refcount
= InterlockedDecrement(&decoder
->refcount
);
122 TRACE("iface %p decreasing refcount to %lu.\n", decoder
, refcount
);
126 if (decoder
->wg_transform
)
127 wg_transform_destroy(decoder
->wg_transform
);
128 if (decoder
->input_type
)
129 IMFMediaType_Release(decoder
->input_type
);
130 if (decoder
->output_type
)
131 IMFMediaType_Release(decoder
->output_type
);
132 wg_sample_queue_destroy(decoder
->wg_sample_queue
);
139 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
140 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
142 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
143 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
144 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
148 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
150 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
151 *inputs
= *outputs
= 1;
155 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
156 DWORD output_size
, DWORD
*outputs
)
158 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
159 input_size
, inputs
, output_size
, outputs
);
163 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
165 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
168 return MF_E_INVALIDSTREAMNUMBER
;
170 memset(info
, 0, sizeof(*info
));
171 info
->dwFlags
= MFT_INPUT_STREAM_WHOLE_SAMPLES
| MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
172 | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE
| MFT_INPUT_STREAM_HOLDS_BUFFERS
;
177 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
179 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
182 return MF_E_INVALIDSTREAMNUMBER
;
184 memset(info
, 0, sizeof(*info
));
185 info
->dwFlags
= MFT_INPUT_STREAM_WHOLE_SAMPLES
;
186 info
->cbSize
= 0xc000;
191 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
193 TRACE("iface %p, attributes %p.\n", iface
, attributes
);
197 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
199 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
203 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
205 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
209 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
211 TRACE("iface %p, id %#lx.\n", iface
, id
);
215 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
217 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
221 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
224 IMFMediaType
*media_type
;
228 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
231 return MF_E_INVALIDSTREAMNUMBER
;
234 if (index
>= ARRAY_SIZE(aac_decoder_input_types
))
235 return MF_E_NO_MORE_TYPES
;
236 subtype
= aac_decoder_input_types
[index
].guid
;
238 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
241 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
)))
243 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
246 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, 32)))
248 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, 6)))
250 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, 24)))
252 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000)))
254 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 1152000)))
256 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_PREFER_WAVEFORMATEX
, 1)))
258 if (IsEqualGUID(subtype
, &MFAudioFormat_AAC
))
260 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION
, 0)))
262 if (aac_decoder_input_types
[index
].payload_type
!= -1
263 && FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AAC_PAYLOAD_TYPE
,
264 aac_decoder_input_types
[index
].payload_type
)))
270 IMFMediaType_AddRef((*type
= media_type
));
272 IMFMediaType_Release(media_type
);
276 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
279 UINT32 channel_count
, sample_size
, sample_rate
, block_alignment
;
280 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
281 IMFMediaType
*media_type
;
282 const GUID
*output_type
;
285 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
288 return MF_E_INVALIDSTREAMNUMBER
;
289 if (!decoder
->input_type
)
290 return MF_E_TRANSFORM_TYPE_NOT_SET
;
294 if (index
>= ARRAY_SIZE(aac_decoder_output_types
))
295 return MF_E_NO_MORE_TYPES
;
296 index
= ARRAY_SIZE(aac_decoder_output_types
) - index
- 1;
297 output_type
= aac_decoder_output_types
[index
];
299 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
302 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
)))
304 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, output_type
)))
307 if (IsEqualGUID(output_type
, &MFAudioFormat_Float
))
309 else if (IsEqualGUID(output_type
, &MFAudioFormat_PCM
))
313 FIXME("Subtype %s not implemented!\n", debugstr_guid(output_type
));
318 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, sample_size
)))
321 if (FAILED(hr
= IMFMediaType_GetUINT32(decoder
->input_type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channel_count
)))
323 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, channel_count
)))
326 if (FAILED(hr
= IMFMediaType_GetUINT32(decoder
->input_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &sample_rate
)))
328 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, sample_rate
)))
331 block_alignment
= sample_size
* channel_count
/ 8;
332 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, block_alignment
)))
334 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, sample_rate
* block_alignment
)))
337 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, 1)))
339 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, 1)))
341 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_PREFER_WAVEFORMATEX
, 1)))
346 IMFMediaType_AddRef((*type
= media_type
));
348 IMFMediaType_Release(media_type
);
352 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
354 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
355 MF_ATTRIBUTE_TYPE item_type
;
360 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
363 return MF_E_INVALIDSTREAMNUMBER
;
365 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)))
368 if (!IsEqualGUID(&major
, &MFMediaType_Audio
)
369 || FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
370 return MF_E_INVALIDMEDIATYPE
;
372 for (i
= 0; i
< ARRAY_SIZE(aac_decoder_input_types
); ++i
)
373 if (IsEqualGUID(&subtype
, aac_decoder_input_types
[i
].guid
))
375 if (i
== ARRAY_SIZE(aac_decoder_input_types
))
376 return MF_E_INVALIDMEDIATYPE
;
378 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &item_type
))
379 || item_type
!= MF_ATTRIBUTE_UINT32
)
380 return MF_E_INVALIDMEDIATYPE
;
381 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_USER_DATA
, &item_type
))
382 || item_type
!= MF_ATTRIBUTE_BLOB
)
383 return MF_E_INVALIDMEDIATYPE
;
384 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
387 if (!decoder
->input_type
&& FAILED(hr
= MFCreateMediaType(&decoder
->input_type
)))
390 if (decoder
->output_type
)
392 IMFMediaType_Release(decoder
->output_type
);
393 decoder
->output_type
= NULL
;
396 return IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)decoder
->input_type
);
399 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
401 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
402 MF_ATTRIBUTE_TYPE item_type
;
407 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
410 return MF_E_INVALIDSTREAMNUMBER
;
411 if (!decoder
->input_type
)
412 return MF_E_TRANSFORM_TYPE_NOT_SET
;
414 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
))
415 || FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
418 if (!IsEqualGUID(&major
, &MFMediaType_Audio
))
419 return MF_E_INVALIDMEDIATYPE
;
421 for (i
= 0; i
< ARRAY_SIZE(aac_decoder_output_types
); ++i
)
422 if (IsEqualGUID(&subtype
, aac_decoder_output_types
[i
]))
424 if (i
== ARRAY_SIZE(aac_decoder_output_types
))
425 return MF_E_INVALIDMEDIATYPE
;
427 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &item_type
))
428 || item_type
!= MF_ATTRIBUTE_UINT32
)
429 return MF_E_INVALIDMEDIATYPE
;
430 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &item_type
))
431 || item_type
!= MF_ATTRIBUTE_UINT32
)
432 return MF_E_INVALIDMEDIATYPE
;
433 if (FAILED(IMFMediaType_GetItemType(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &item_type
))
434 || item_type
!= MF_ATTRIBUTE_UINT32
)
435 return MF_E_INVALIDMEDIATYPE
;
436 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
439 if (!decoder
->output_type
&& FAILED(hr
= MFCreateMediaType(&decoder
->output_type
)))
442 if (FAILED(hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)decoder
->output_type
)))
445 if (FAILED(hr
= try_create_wg_transform(decoder
)))
451 IMFMediaType_Release(decoder
->output_type
);
452 decoder
->output_type
= NULL
;
456 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**out
)
458 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
462 TRACE("iface %p, id %#lx, out %p.\n", iface
, id
, out
);
465 return MF_E_INVALIDSTREAMNUMBER
;
466 if (!decoder
->input_type
)
467 return MF_E_TRANSFORM_TYPE_NOT_SET
;
469 if (FAILED(hr
= MFCreateMediaType(&type
)))
471 if (SUCCEEDED(hr
= IMFMediaType_CopyAllItems(decoder
->input_type
, (IMFAttributes
*)type
)))
472 IMFMediaType_AddRef(*out
= type
);
473 IMFMediaType_Release(type
);
478 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**out
)
480 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
484 TRACE("iface %p, id %#lx, out %p.\n", iface
, id
, out
);
487 return MF_E_INVALIDSTREAMNUMBER
;
488 if (!decoder
->output_type
)
489 return MF_E_TRANSFORM_TYPE_NOT_SET
;
491 if (FAILED(hr
= MFCreateMediaType(&type
)))
493 if (SUCCEEDED(hr
= IMFMediaType_CopyAllItems(decoder
->output_type
, (IMFAttributes
*)type
)))
494 IMFMediaType_AddRef(*out
= type
);
495 IMFMediaType_Release(type
);
500 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
502 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
506 TRACE("iface %p, id %#lx, flags %p.\n", iface
, id
, flags
);
508 if (!decoder
->wg_transform
)
509 return MF_E_TRANSFORM_TYPE_NOT_SET
;
511 if (FAILED(hr
= wg_transform_get_status(decoder
->wg_transform
, &accepts_input
)))
514 *flags
= accepts_input
? MFT_INPUT_STATUS_ACCEPT_DATA
: 0;
518 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
520 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
524 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
526 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
530 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
532 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
536 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
538 FIXME("iface %p, message %#x, param %p stub!\n", iface
, message
, (void *)param
);
542 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
544 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
546 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
548 if (!decoder
->wg_transform
)
549 return MF_E_TRANSFORM_TYPE_NOT_SET
;
551 return wg_transform_push_mf(decoder
->wg_transform
, sample
, decoder
->wg_sample_queue
);
554 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
555 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
557 struct aac_decoder
*decoder
= impl_from_IMFTransform(iface
);
558 MFT_OUTPUT_STREAM_INFO info
;
561 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface
, flags
, count
, samples
, status
);
566 if (!decoder
->wg_transform
)
567 return MF_E_TRANSFORM_TYPE_NOT_SET
;
569 *status
= samples
->dwStatus
= 0;
570 if (!samples
->pSample
)
573 if (FAILED(hr
= IMFTransform_GetOutputStreamInfo(iface
, 0, &info
)))
576 if (SUCCEEDED(hr
= wg_transform_read_mf(decoder
->wg_transform
, samples
->pSample
,
577 info
.cbSize
, NULL
, &samples
->dwStatus
)))
578 wg_sample_queue_flush(decoder
->wg_sample_queue
, false);
580 samples
->dwStatus
= MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
;
585 static const IMFTransformVtbl transform_vtbl
=
587 transform_QueryInterface
,
590 transform_GetStreamLimits
,
591 transform_GetStreamCount
,
592 transform_GetStreamIDs
,
593 transform_GetInputStreamInfo
,
594 transform_GetOutputStreamInfo
,
595 transform_GetAttributes
,
596 transform_GetInputStreamAttributes
,
597 transform_GetOutputStreamAttributes
,
598 transform_DeleteInputStream
,
599 transform_AddInputStreams
,
600 transform_GetInputAvailableType
,
601 transform_GetOutputAvailableType
,
602 transform_SetInputType
,
603 transform_SetOutputType
,
604 transform_GetInputCurrentType
,
605 transform_GetOutputCurrentType
,
606 transform_GetInputStatus
,
607 transform_GetOutputStatus
,
608 transform_SetOutputBounds
,
609 transform_ProcessEvent
,
610 transform_ProcessMessage
,
611 transform_ProcessInput
,
612 transform_ProcessOutput
,
615 HRESULT
aac_decoder_create(REFIID riid
, void **ret
)
617 static const struct wg_format output_format
=
619 .major_type
= WG_MAJOR_TYPE_AUDIO
,
622 .format
= WG_AUDIO_FORMAT_F32LE
,
628 static const struct wg_format input_format
= {.major_type
= WG_MAJOR_TYPE_AUDIO_MPEG4
};
629 struct wg_transform_attrs attrs
= {0};
630 struct wg_transform
*transform
;
631 struct aac_decoder
*decoder
;
634 TRACE("riid %s, ret %p.\n", debugstr_guid(riid
), ret
);
636 if (!(transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
638 ERR_(winediag
)("GStreamer doesn't support WMA decoding, please install appropriate plugins\n");
641 wg_transform_destroy(transform
);
643 if (!(decoder
= calloc(1, sizeof(*decoder
))))
644 return E_OUTOFMEMORY
;
646 if (FAILED(hr
= wg_sample_queue_create(&decoder
->wg_sample_queue
)))
652 decoder
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
653 decoder
->refcount
= 1;
655 *ret
= &decoder
->IMFTransform_iface
;
656 TRACE("Created decoder %p\n", *ret
);