1 /* H264 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"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
30 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
32 #define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment)))
34 static const GUID
*const h264_decoder_input_types
[] =
37 &MFVideoFormat_H264_ES
,
39 static const GUID
*const h264_decoder_output_types
[] =
50 IMFTransform IMFTransform_iface
;
53 IMFAttributes
*attributes
;
54 IMFAttributes
*output_attributes
;
56 IMFMediaType
*input_type
;
57 MFT_INPUT_STREAM_INFO input_info
;
58 IMFMediaType
*output_type
;
59 MFT_OUTPUT_STREAM_INFO output_info
;
61 struct wg_format wg_format
;
62 struct wg_transform
*wg_transform
;
63 struct wg_sample_queue
*wg_sample_queue
;
66 static struct h264_decoder
*impl_from_IMFTransform(IMFTransform
*iface
)
68 return CONTAINING_RECORD(iface
, struct h264_decoder
, IMFTransform_iface
);
71 static HRESULT
try_create_wg_transform(struct h264_decoder
*decoder
)
73 struct wg_format input_format
;
74 struct wg_format output_format
;
76 if (decoder
->wg_transform
)
77 wg_transform_destroy(decoder
->wg_transform
);
78 decoder
->wg_transform
= NULL
;
80 mf_media_type_to_wg_format(decoder
->input_type
, &input_format
);
81 if (input_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
82 return MF_E_INVALIDMEDIATYPE
;
84 mf_media_type_to_wg_format(decoder
->output_type
, &output_format
);
85 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
86 return MF_E_INVALIDMEDIATYPE
;
88 /* Don't force any specific size, H264 streams already have the metadata for it
89 * and will generate a MF_E_TRANSFORM_STREAM_CHANGE result later.
91 output_format
.u
.video
.width
= 0;
92 output_format
.u
.video
.height
= 0;
93 output_format
.u
.video
.fps_d
= 0;
94 output_format
.u
.video
.fps_n
= 0;
96 if (!(decoder
->wg_transform
= wg_transform_create(&input_format
, &output_format
)))
102 static HRESULT
fill_output_media_type(struct h264_decoder
*decoder
, IMFMediaType
*media_type
)
104 IMFMediaType
*default_type
= decoder
->output_type
;
105 struct wg_format
*wg_format
= &decoder
->wg_format
;
106 UINT32 value
, width
, height
;
111 if (FAILED(hr
= IMFMediaType_GetGUID(media_type
, &MF_MT_SUBTYPE
, &subtype
)))
114 if (FAILED(hr
= IMFMediaType_GetUINT64(media_type
, &MF_MT_FRAME_SIZE
, &ratio
)))
116 ratio
= (UINT64
)wg_format
->u
.video
.width
<< 32 | wg_format
->u
.video
.height
;
117 if (FAILED(hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, ratio
)))
123 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_FRAME_RATE
, NULL
)))
125 ratio
= (UINT64
)wg_format
->u
.video
.fps_n
<< 32 | wg_format
->u
.video
.fps_d
;
126 if (FAILED(hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_RATE
, ratio
)))
130 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_PIXEL_ASPECT_RATIO
, NULL
)))
132 ratio
= (UINT64
)1 << 32 | 1; /* FIXME: read it from format */
133 if (FAILED(hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_PIXEL_ASPECT_RATIO
, ratio
)))
137 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_SAMPLE_SIZE
, NULL
)))
139 if (FAILED(hr
= MFCalculateImageSize(&subtype
, width
, height
, &value
)))
141 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_SAMPLE_SIZE
, value
)))
145 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_DEFAULT_STRIDE
, NULL
)))
147 if (FAILED(hr
= MFGetStrideForBitmapInfoHeader(subtype
.Data1
, width
, (LONG
*)&value
)))
149 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_DEFAULT_STRIDE
, value
)))
153 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_INTERLACE_MODE
, NULL
)))
155 if (!default_type
|| FAILED(hr
= IMFMediaType_GetUINT32(default_type
, &MF_MT_INTERLACE_MODE
, &value
)))
156 value
= MFVideoInterlace_MixedInterlaceOrProgressive
;
157 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_INTERLACE_MODE
, value
)))
161 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, NULL
)))
163 if (!default_type
|| FAILED(hr
= IMFMediaType_GetUINT32(default_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, &value
)))
165 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, value
)))
169 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_VIDEO_ROTATION
, NULL
)))
171 if (!default_type
|| FAILED(hr
= IMFMediaType_GetUINT32(default_type
, &MF_MT_VIDEO_ROTATION
, &value
)))
173 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_VIDEO_ROTATION
, value
)))
177 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, NULL
)))
179 if (!default_type
|| FAILED(hr
= IMFMediaType_GetUINT32(default_type
, &MF_MT_FIXED_SIZE_SAMPLES
, &value
)))
181 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, value
)))
185 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
, NULL
))
186 && (wg_format
->u
.video
.padding
.left
|| wg_format
->u
.video
.padding
.right
|| wg_format
->u
.video
.padding
.top
187 || wg_format
->u
.video
.padding
.bottom
))
189 MFVideoArea aperture
=
191 .OffsetX
= {.value
= wg_format
->u
.video
.padding
.left
},
192 .OffsetY
= {.value
= wg_format
->u
.video
.padding
.top
},
193 .Area
.cx
= wg_format
->u
.video
.width
- wg_format
->u
.video
.padding
.right
- wg_format
->u
.video
.padding
.left
,
194 .Area
.cy
= wg_format
->u
.video
.height
- wg_format
->u
.video
.padding
.bottom
- wg_format
->u
.video
.padding
.top
,
197 if (FAILED(hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
,
198 (BYTE
*)&aperture
, sizeof(aperture
))))
205 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
207 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
209 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
211 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
212 IsEqualGUID(iid
, &IID_IMFTransform
))
213 *out
= &decoder
->IMFTransform_iface
;
217 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
218 return E_NOINTERFACE
;
221 IUnknown_AddRef((IUnknown
*)*out
);
225 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
227 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
228 ULONG refcount
= InterlockedIncrement(&decoder
->refcount
);
230 TRACE("iface %p increasing refcount to %lu.\n", decoder
, refcount
);
235 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
237 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
238 ULONG refcount
= InterlockedDecrement(&decoder
->refcount
);
240 TRACE("iface %p decreasing refcount to %lu.\n", decoder
, refcount
);
244 if (decoder
->wg_transform
)
245 wg_transform_destroy(decoder
->wg_transform
);
246 if (decoder
->input_type
)
247 IMFMediaType_Release(decoder
->input_type
);
248 if (decoder
->output_type
)
249 IMFMediaType_Release(decoder
->output_type
);
250 if (decoder
->output_attributes
)
251 IMFAttributes_Release(decoder
->output_attributes
);
252 if (decoder
->attributes
)
253 IMFAttributes_Release(decoder
->attributes
);
255 wg_sample_queue_destroy(decoder
->wg_sample_queue
);
262 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
263 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
265 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
266 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
267 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
271 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
273 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
274 *inputs
= *outputs
= 1;
278 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
279 DWORD output_size
, DWORD
*outputs
)
281 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
282 input_size
, inputs
, output_size
, outputs
);
286 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
288 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
290 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
292 *info
= decoder
->input_info
;
296 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
298 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
300 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
302 *info
= decoder
->output_info
;
306 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
308 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
310 FIXME("iface %p, attributes %p semi-stub!\n", iface
, attributes
);
315 IMFAttributes_AddRef((*attributes
= decoder
->attributes
));
319 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
321 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
325 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
327 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
329 FIXME("iface %p, id %#lx, attributes %p semi-stub!\n", iface
, id
, attributes
);
334 return MF_E_INVALIDSTREAMNUMBER
;
336 IMFAttributes_AddRef((*attributes
= decoder
->output_attributes
));
340 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
342 TRACE("iface %p, id %#lx.\n", iface
, id
);
346 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
348 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
352 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
355 IMFMediaType
*media_type
;
359 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
363 if (index
>= ARRAY_SIZE(h264_decoder_input_types
))
364 return MF_E_NO_MORE_TYPES
;
365 subtype
= h264_decoder_input_types
[index
];
367 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
370 if (SUCCEEDED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)) &&
371 SUCCEEDED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
372 IMFMediaType_AddRef((*type
= media_type
));
374 IMFMediaType_Release(media_type
);
378 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
,
379 DWORD index
, IMFMediaType
**type
)
381 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
382 IMFMediaType
*media_type
;
383 const GUID
*output_type
;
386 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
388 if (!decoder
->input_type
)
389 return MF_E_TRANSFORM_TYPE_NOT_SET
;
393 if (index
>= ARRAY_SIZE(h264_decoder_output_types
))
394 return MF_E_NO_MORE_TYPES
;
395 output_type
= h264_decoder_output_types
[index
];
397 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
400 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)))
402 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, output_type
)))
405 hr
= fill_output_media_type(decoder
, media_type
);
409 IMFMediaType_AddRef((*type
= media_type
));
411 IMFMediaType_Release(media_type
);
415 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
417 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
423 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
425 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
426 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
429 if (!IsEqualGUID(&major
, &MFMediaType_Video
))
430 return MF_E_INVALIDMEDIATYPE
;
432 for (i
= 0; i
< ARRAY_SIZE(h264_decoder_input_types
); ++i
)
433 if (IsEqualGUID(&subtype
, h264_decoder_input_types
[i
]))
435 if (i
== ARRAY_SIZE(h264_decoder_input_types
))
436 return MF_E_INVALIDMEDIATYPE
;
437 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
440 if (decoder
->output_type
)
442 IMFMediaType_Release(decoder
->output_type
);
443 decoder
->output_type
= NULL
;
446 if (decoder
->input_type
)
447 IMFMediaType_Release(decoder
->input_type
);
448 IMFMediaType_AddRef((decoder
->input_type
= type
));
450 if (SUCCEEDED(IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
452 decoder
->wg_format
.u
.video
.width
= frame_size
>> 32;
453 decoder
->wg_format
.u
.video
.height
= (UINT32
)frame_size
;
454 decoder
->output_info
.cbSize
= decoder
->wg_format
.u
.video
.width
455 * decoder
->wg_format
.u
.video
.height
* 2;
461 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
463 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
469 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
471 if (!decoder
->input_type
)
472 return MF_E_TRANSFORM_TYPE_NOT_SET
;
474 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
475 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
478 if (!IsEqualGUID(&major
, &MFMediaType_Video
))
479 return MF_E_INVALIDMEDIATYPE
;
481 for (i
= 0; i
< ARRAY_SIZE(h264_decoder_output_types
); ++i
)
482 if (IsEqualGUID(&subtype
, h264_decoder_output_types
[i
]))
484 if (i
== ARRAY_SIZE(h264_decoder_output_types
))
485 return MF_E_INVALIDMEDIATYPE
;
487 if (FAILED(hr
= IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
))
488 || (frame_size
>> 32) != decoder
->wg_format
.u
.video
.width
489 || (UINT32
)frame_size
!= decoder
->wg_format
.u
.video
.height
)
490 return MF_E_INVALIDMEDIATYPE
;
491 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
494 if (decoder
->output_type
)
495 IMFMediaType_Release(decoder
->output_type
);
496 IMFMediaType_AddRef((decoder
->output_type
= type
));
498 if (decoder
->wg_transform
)
500 struct wg_format output_format
;
501 mf_media_type_to_wg_format(decoder
->output_type
, &output_format
);
503 /* Don't force any specific size, H264 streams already have the metadata for it
504 * and will generate a MF_E_TRANSFORM_STREAM_CHANGE result later.
506 output_format
.u
.video
.width
= 0;
507 output_format
.u
.video
.height
= 0;
508 output_format
.u
.video
.fps_d
= 0;
509 output_format
.u
.video
.fps_n
= 0;
511 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
512 || !wg_transform_set_output_format(decoder
->wg_transform
, &output_format
))
514 IMFMediaType_Release(decoder
->output_type
);
515 decoder
->output_type
= NULL
;
516 return MF_E_INVALIDMEDIATYPE
;
519 else if (FAILED(hr
= try_create_wg_transform(decoder
)))
521 IMFMediaType_Release(decoder
->output_type
);
522 decoder
->output_type
= NULL
;
528 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
530 FIXME("iface %p, id %#lx, type %p stub!\n", iface
, id
, type
);
534 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
536 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
539 FIXME("iface %p, id %#lx, type %p stub!\n", iface
, id
, type
);
541 if (!decoder
->output_type
)
542 return MF_E_TRANSFORM_TYPE_NOT_SET
;
544 if (FAILED(hr
= MFCreateMediaType(type
)))
547 return IMFMediaType_CopyAllItems(decoder
->output_type
, (IMFAttributes
*)*type
);
550 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
552 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
554 TRACE("iface %p, id %#lx, flags %p.\n", iface
, id
, flags
);
556 if (!decoder
->wg_transform
)
557 return MF_E_TRANSFORM_TYPE_NOT_SET
;
559 *flags
= MFT_INPUT_STATUS_ACCEPT_DATA
;
563 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
565 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
569 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
571 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
575 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
577 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
581 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
583 FIXME("iface %p, message %#x, param %Ix stub!\n", iface
, message
, param
);
587 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
589 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
591 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
593 if (!decoder
->wg_transform
)
594 return MF_E_TRANSFORM_TYPE_NOT_SET
;
596 return wg_transform_push_mf(decoder
->wg_transform
, sample
, decoder
->wg_sample_queue
);
599 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
600 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
602 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
603 struct wg_format wg_format
;
609 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface
, flags
, count
, samples
, status
);
614 if (!decoder
->wg_transform
)
615 return MF_E_TRANSFORM_TYPE_NOT_SET
;
617 *status
= samples
->dwStatus
= 0;
618 if (!samples
->pSample
)
621 if (FAILED(hr
= IMFMediaType_GetGUID(decoder
->output_type
, &MF_MT_SUBTYPE
, &subtype
)))
623 if (FAILED(hr
= MFCalculateImageSize(&subtype
, decoder
->wg_format
.u
.video
.width
,
624 decoder
->wg_format
.u
.video
.height
, &sample_size
)))
627 if (SUCCEEDED(hr
= wg_transform_read_mf(decoder
->wg_transform
, samples
->pSample
,
628 sample_size
, &wg_format
, &samples
->dwStatus
)))
629 wg_sample_queue_flush(decoder
->wg_sample_queue
, false);
631 if (hr
== MF_E_TRANSFORM_STREAM_CHANGE
)
633 decoder
->wg_format
= wg_format
;
634 decoder
->output_info
.cbSize
= ALIGN_SIZE(decoder
->wg_format
.u
.video
.width
, 0xf)
635 * ALIGN_SIZE(decoder
->wg_format
.u
.video
.height
, 0xf) * 2;
637 /* keep the frame rate that was requested, GStreamer doesn't provide any */
638 if (SUCCEEDED(IMFMediaType_GetUINT64(decoder
->output_type
, &MF_MT_FRAME_RATE
, &frame_rate
)))
640 decoder
->wg_format
.u
.video
.fps_n
= frame_rate
>> 32;
641 decoder
->wg_format
.u
.video
.fps_d
= (UINT32
)frame_rate
;
644 samples
[0].dwStatus
|= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
;
645 *status
|= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
;
651 static const IMFTransformVtbl transform_vtbl
=
653 transform_QueryInterface
,
656 transform_GetStreamLimits
,
657 transform_GetStreamCount
,
658 transform_GetStreamIDs
,
659 transform_GetInputStreamInfo
,
660 transform_GetOutputStreamInfo
,
661 transform_GetAttributes
,
662 transform_GetInputStreamAttributes
,
663 transform_GetOutputStreamAttributes
,
664 transform_DeleteInputStream
,
665 transform_AddInputStreams
,
666 transform_GetInputAvailableType
,
667 transform_GetOutputAvailableType
,
668 transform_SetInputType
,
669 transform_SetOutputType
,
670 transform_GetInputCurrentType
,
671 transform_GetOutputCurrentType
,
672 transform_GetInputStatus
,
673 transform_GetOutputStatus
,
674 transform_SetOutputBounds
,
675 transform_ProcessEvent
,
676 transform_ProcessMessage
,
677 transform_ProcessInput
,
678 transform_ProcessOutput
,
681 HRESULT
h264_decoder_create(REFIID riid
, void **ret
)
683 static const struct wg_format output_format
=
685 .major_type
= WG_MAJOR_TYPE_VIDEO
,
688 .format
= WG_VIDEO_FORMAT_I420
,
693 static const struct wg_format input_format
= {.major_type
= WG_MAJOR_TYPE_VIDEO_H264
};
694 struct wg_transform
*transform
;
695 struct h264_decoder
*decoder
;
698 TRACE("riid %s, ret %p.\n", debugstr_guid(riid
), ret
);
700 if (!(transform
= wg_transform_create(&input_format
, &output_format
)))
702 ERR_(winediag
)("GStreamer doesn't support H.264 decoding, please install appropriate plugins\n");
705 wg_transform_destroy(transform
);
707 if (!(decoder
= calloc(1, sizeof(*decoder
))))
708 return E_OUTOFMEMORY
;
710 decoder
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
711 decoder
->refcount
= 1;
712 decoder
->wg_format
.u
.video
.format
= WG_VIDEO_FORMAT_UNKNOWN
;
713 decoder
->wg_format
.u
.video
.width
= 1920;
714 decoder
->wg_format
.u
.video
.height
= 1080;
715 decoder
->wg_format
.u
.video
.fps_n
= 30000;
716 decoder
->wg_format
.u
.video
.fps_d
= 1001;
718 decoder
->input_info
.dwFlags
= MFT_INPUT_STREAM_WHOLE_SAMPLES
| MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
719 | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE
;
720 decoder
->input_info
.cbSize
= 0x1000;
721 decoder
->output_info
.dwFlags
= MFT_OUTPUT_STREAM_WHOLE_SAMPLES
| MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
722 | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE
;
723 decoder
->output_info
.cbSize
= 1920 * 1088 * 2;
725 if (FAILED(hr
= MFCreateAttributes(&decoder
->attributes
, 16)))
727 if (FAILED(hr
= IMFAttributes_SetUINT32(decoder
->attributes
, &MF_LOW_LATENCY
, 0)))
729 if (FAILED(hr
= IMFAttributes_SetUINT32(decoder
->attributes
, &MF_SA_D3D11_AWARE
, TRUE
)))
731 if (FAILED(hr
= MFCreateAttributes(&decoder
->output_attributes
, 0)))
733 if (FAILED(hr
= wg_sample_queue_create(&decoder
->wg_sample_queue
)))
736 *ret
= &decoder
->IMFTransform_iface
;
737 TRACE("Created decoder %p\n", *ret
);
741 if (decoder
->output_attributes
)
742 IMFAttributes_Release(decoder
->output_attributes
);
743 if (decoder
->attributes
)
744 IMFAttributes_Release(decoder
->attributes
);