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 static const GUID
*const h264_decoder_input_types
[] =
35 &MFVideoFormat_H264_ES
,
37 static const GUID
*const h264_decoder_output_types
[] =
48 IMFTransform IMFTransform_iface
;
50 IMFMediaType
*input_type
;
51 IMFMediaType
*output_type
;
53 struct wg_format wg_format
;
54 struct wg_transform
*wg_transform
;
55 struct wg_sample_queue
*wg_sample_queue
;
58 static struct h264_decoder
*impl_from_IMFTransform(IMFTransform
*iface
)
60 return CONTAINING_RECORD(iface
, struct h264_decoder
, IMFTransform_iface
);
63 static HRESULT
try_create_wg_transform(struct h264_decoder
*decoder
)
65 struct wg_format input_format
;
66 struct wg_format output_format
;
68 if (decoder
->wg_transform
)
69 wg_transform_destroy(decoder
->wg_transform
);
70 decoder
->wg_transform
= NULL
;
72 mf_media_type_to_wg_format(decoder
->input_type
, &input_format
);
73 if (input_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
74 return MF_E_INVALIDMEDIATYPE
;
76 mf_media_type_to_wg_format(decoder
->output_type
, &output_format
);
77 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
)
78 return MF_E_INVALIDMEDIATYPE
;
80 /* Don't force any specific size, H264 streams already have the metadata for it
81 * and will generate a MF_E_TRANSFORM_STREAM_CHANGE result later.
83 output_format
.u
.video
.width
= 0;
84 output_format
.u
.video
.height
= 0;
85 output_format
.u
.video
.fps_d
= 0;
86 output_format
.u
.video
.fps_n
= 0;
88 if (!(decoder
->wg_transform
= wg_transform_create(&input_format
, &output_format
)))
94 static HRESULT
fill_output_media_type(struct h264_decoder
*decoder
, IMFMediaType
*media_type
)
96 IMFMediaType
*default_type
= decoder
->output_type
;
97 struct wg_format
*wg_format
= &decoder
->wg_format
;
98 UINT32 value
, width
, height
;
103 if (FAILED(hr
= IMFMediaType_GetGUID(media_type
, &MF_MT_SUBTYPE
, &subtype
)))
106 if (FAILED(hr
= IMFMediaType_GetUINT64(media_type
, &MF_MT_FRAME_SIZE
, &ratio
)))
108 ratio
= (UINT64
)wg_format
->u
.video
.width
<< 32 | wg_format
->u
.video
.height
;
109 if (FAILED(hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, ratio
)))
115 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_FRAME_RATE
, NULL
)))
117 ratio
= (UINT64
)wg_format
->u
.video
.fps_n
<< 32 | wg_format
->u
.video
.fps_d
;
118 if (FAILED(hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_RATE
, ratio
)))
122 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_PIXEL_ASPECT_RATIO
, NULL
)))
124 ratio
= (UINT64
)1 << 32 | 1; /* FIXME: read it from format */
125 if (FAILED(hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_PIXEL_ASPECT_RATIO
, ratio
)))
129 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_SAMPLE_SIZE
, NULL
)))
131 if (FAILED(hr
= MFCalculateImageSize(&subtype
, width
, height
, &value
)))
133 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_SAMPLE_SIZE
, value
)))
137 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_DEFAULT_STRIDE
, NULL
)))
139 if (FAILED(hr
= MFGetStrideForBitmapInfoHeader(subtype
.Data1
, width
, (LONG
*)&value
)))
141 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_DEFAULT_STRIDE
, value
)))
145 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_INTERLACE_MODE
, NULL
)))
147 if (!default_type
|| FAILED(hr
= IMFMediaType_GetUINT32(default_type
, &MF_MT_INTERLACE_MODE
, &value
)))
148 value
= MFVideoInterlace_MixedInterlaceOrProgressive
;
149 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_INTERLACE_MODE
, value
)))
153 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, NULL
)))
155 if (!default_type
|| FAILED(hr
= IMFMediaType_GetUINT32(default_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, &value
)))
157 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, value
)))
161 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_VIDEO_ROTATION
, NULL
)))
163 if (!default_type
|| FAILED(hr
= IMFMediaType_GetUINT32(default_type
, &MF_MT_VIDEO_ROTATION
, &value
)))
165 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_VIDEO_ROTATION
, value
)))
169 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, NULL
)))
171 if (!default_type
|| FAILED(hr
= IMFMediaType_GetUINT32(default_type
, &MF_MT_FIXED_SIZE_SAMPLES
, &value
)))
173 if (FAILED(hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, value
)))
177 if (FAILED(hr
= IMFMediaType_GetItem(media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
, NULL
))
178 && !IsRectEmpty(&wg_format
->u
.video
.padding
))
180 MFVideoArea aperture
=
182 .OffsetX
= {.value
= wg_format
->u
.video
.padding
.left
},
183 .OffsetY
= {.value
= wg_format
->u
.video
.padding
.top
},
184 .Area
.cx
= wg_format
->u
.video
.width
- wg_format
->u
.video
.padding
.right
- wg_format
->u
.video
.padding
.left
,
185 .Area
.cy
= wg_format
->u
.video
.height
- wg_format
->u
.video
.padding
.bottom
- wg_format
->u
.video
.padding
.top
,
188 if (FAILED(hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
,
189 (BYTE
*)&aperture
, sizeof(aperture
))))
196 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
198 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
200 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
202 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
203 IsEqualGUID(iid
, &IID_IMFTransform
))
204 *out
= &decoder
->IMFTransform_iface
;
208 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
209 return E_NOINTERFACE
;
212 IUnknown_AddRef((IUnknown
*)*out
);
216 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
218 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
219 ULONG refcount
= InterlockedIncrement(&decoder
->refcount
);
221 TRACE("iface %p increasing refcount to %lu.\n", decoder
, refcount
);
226 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
228 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
229 ULONG refcount
= InterlockedDecrement(&decoder
->refcount
);
231 TRACE("iface %p decreasing refcount to %lu.\n", decoder
, refcount
);
235 if (decoder
->wg_transform
)
236 wg_transform_destroy(decoder
->wg_transform
);
237 if (decoder
->input_type
)
238 IMFMediaType_Release(decoder
->input_type
);
239 if (decoder
->output_type
)
240 IMFMediaType_Release(decoder
->output_type
);
242 wg_sample_queue_destroy(decoder
->wg_sample_queue
);
249 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
250 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
252 FIXME("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p stub!\n",
253 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
257 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
259 FIXME("iface %p, inputs %p, outputs %p stub!\n", iface
, inputs
, outputs
);
263 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
,
264 DWORD
*inputs
, DWORD output_size
, DWORD
*outputs
)
266 FIXME("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p stub!\n", iface
,
267 input_size
, inputs
, output_size
, outputs
);
271 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
273 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
275 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
277 if (!decoder
->input_type
)
278 return MF_E_TRANSFORM_TYPE_NOT_SET
;
280 info
->hnsMaxLatency
= 0;
281 info
->dwFlags
= MFT_INPUT_STREAM_WHOLE_SAMPLES
| MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
| MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE
;
282 info
->cbSize
= 0x1000;
283 info
->cbMaxLookahead
= 0;
284 info
->cbAlignment
= 0;
289 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
291 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
292 UINT32 actual_width
, actual_height
;
294 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
296 actual_width
= (decoder
->wg_format
.u
.video
.width
+ 15) & ~15;
297 actual_height
= (decoder
->wg_format
.u
.video
.height
+ 15) & ~15;
299 info
->dwFlags
= MFT_OUTPUT_STREAM_WHOLE_SAMPLES
| MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
| MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE
;
300 info
->cbSize
= actual_width
* actual_height
* 2;
301 info
->cbAlignment
= 0;
306 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
308 FIXME("iface %p, attributes %p stub!\n", iface
, attributes
);
309 return MFCreateAttributes(attributes
, 0);
312 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
314 FIXME("iface %p, id %#lx, attributes %p stub!\n", iface
, id
, attributes
);
318 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
,
319 IMFAttributes
**attributes
)
321 FIXME("iface %p, id %#lx, attributes %p stub!\n", iface
, id
, attributes
);
325 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
327 FIXME("iface %p, id %#lx stub!\n", iface
, id
);
331 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
333 FIXME("iface %p, streams %lu, ids %p stub!\n", iface
, streams
, ids
);
337 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
340 IMFMediaType
*media_type
;
344 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
348 if (index
>= ARRAY_SIZE(h264_decoder_input_types
))
349 return MF_E_NO_MORE_TYPES
;
350 subtype
= h264_decoder_input_types
[index
];
352 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
355 if (SUCCEEDED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)) &&
356 SUCCEEDED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
357 IMFMediaType_AddRef((*type
= media_type
));
359 IMFMediaType_Release(media_type
);
363 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
,
364 DWORD index
, IMFMediaType
**type
)
366 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
367 IMFMediaType
*media_type
;
368 const GUID
*output_type
;
371 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
373 if (!decoder
->input_type
)
374 return MF_E_TRANSFORM_TYPE_NOT_SET
;
378 if (index
>= ARRAY_SIZE(h264_decoder_output_types
))
379 return MF_E_NO_MORE_TYPES
;
380 output_type
= h264_decoder_output_types
[index
];
382 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
385 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)))
387 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, output_type
)))
390 hr
= fill_output_media_type(decoder
, media_type
);
394 IMFMediaType_AddRef((*type
= media_type
));
396 IMFMediaType_Release(media_type
);
400 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
402 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
408 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
410 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
411 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
414 if (!IsEqualGUID(&major
, &MFMediaType_Video
))
415 return MF_E_INVALIDMEDIATYPE
;
417 for (i
= 0; i
< ARRAY_SIZE(h264_decoder_input_types
); ++i
)
418 if (IsEqualGUID(&subtype
, h264_decoder_input_types
[i
]))
420 if (i
== ARRAY_SIZE(h264_decoder_input_types
))
421 return MF_E_INVALIDMEDIATYPE
;
422 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
425 if (decoder
->output_type
)
427 IMFMediaType_Release(decoder
->output_type
);
428 decoder
->output_type
= NULL
;
431 if (decoder
->input_type
)
432 IMFMediaType_Release(decoder
->input_type
);
433 IMFMediaType_AddRef((decoder
->input_type
= type
));
435 if (SUCCEEDED(IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
437 decoder
->wg_format
.u
.video
.width
= frame_size
>> 32;
438 decoder
->wg_format
.u
.video
.height
= (UINT32
)frame_size
;
444 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
446 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
452 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
454 if (!decoder
->input_type
)
455 return MF_E_TRANSFORM_TYPE_NOT_SET
;
457 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
458 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
461 if (!IsEqualGUID(&major
, &MFMediaType_Video
))
462 return MF_E_INVALIDMEDIATYPE
;
464 for (i
= 0; i
< ARRAY_SIZE(h264_decoder_output_types
); ++i
)
465 if (IsEqualGUID(&subtype
, h264_decoder_output_types
[i
]))
467 if (i
== ARRAY_SIZE(h264_decoder_output_types
))
468 return MF_E_INVALIDMEDIATYPE
;
470 if (FAILED(hr
= IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
))
471 || (frame_size
>> 32) != decoder
->wg_format
.u
.video
.width
472 || (UINT32
)frame_size
!= decoder
->wg_format
.u
.video
.height
)
473 return MF_E_INVALIDMEDIATYPE
;
474 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
477 if (decoder
->output_type
)
478 IMFMediaType_Release(decoder
->output_type
);
479 IMFMediaType_AddRef((decoder
->output_type
= type
));
481 if (decoder
->wg_transform
)
483 struct wg_format output_format
;
484 mf_media_type_to_wg_format(decoder
->output_type
, &output_format
);
486 /* Don't force any specific size, H264 streams already have the metadata for it
487 * and will generate a MF_E_TRANSFORM_STREAM_CHANGE result later.
489 output_format
.u
.video
.width
= 0;
490 output_format
.u
.video
.height
= 0;
491 output_format
.u
.video
.fps_d
= 0;
492 output_format
.u
.video
.fps_n
= 0;
494 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
495 || !wg_transform_set_output_format(decoder
->wg_transform
, &output_format
))
497 IMFMediaType_Release(decoder
->output_type
);
498 decoder
->output_type
= NULL
;
499 return MF_E_INVALIDMEDIATYPE
;
502 else if (FAILED(hr
= try_create_wg_transform(decoder
)))
504 IMFMediaType_Release(decoder
->output_type
);
505 decoder
->output_type
= NULL
;
511 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
513 FIXME("iface %p, id %#lx, type %p stub!\n", iface
, id
, type
);
517 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
519 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
522 FIXME("iface %p, id %#lx, type %p stub!\n", iface
, id
, type
);
524 if (!decoder
->output_type
)
525 return MF_E_TRANSFORM_TYPE_NOT_SET
;
527 if (FAILED(hr
= MFCreateMediaType(type
)))
530 return IMFMediaType_CopyAllItems(decoder
->output_type
, (IMFAttributes
*)*type
);
533 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
535 FIXME("iface %p, id %#lx, flags %p stub!\n", iface
, id
, flags
);
539 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
541 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
545 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
547 FIXME("iface %p, lower %I64d, upper %I64d stub!\n", iface
, lower
, upper
);
551 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
553 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
557 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
559 FIXME("iface %p, message %#x, param %Ix stub!\n", iface
, message
, param
);
563 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
565 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
566 struct wg_sample
*wg_sample
;
567 MFT_INPUT_STREAM_INFO info
;
570 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
572 if (FAILED(hr
= IMFTransform_GetInputStreamInfo(iface
, 0, &info
)))
575 if (!decoder
->wg_transform
)
576 return MF_E_TRANSFORM_TYPE_NOT_SET
;
578 if (FAILED(hr
= wg_sample_create_mf(sample
, &wg_sample
)))
581 return wg_transform_push_mf(decoder
->wg_transform
, wg_sample
, decoder
->wg_sample_queue
);
584 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
585 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
587 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
588 struct wg_sample
*wg_sample
;
589 struct wg_format wg_format
;
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
;
604 samples
[0].dwStatus
= 0;
605 if (!samples
[0].pSample
) return E_INVALIDARG
;
607 if (FAILED(hr
= IMFMediaType_GetGUID(decoder
->output_type
, &MF_MT_SUBTYPE
, &subtype
)))
609 if (FAILED(hr
= MFCalculateImageSize(&subtype
, decoder
->wg_format
.u
.video
.width
,
610 decoder
->wg_format
.u
.video
.height
, &sample_size
)))
613 if (FAILED(hr
= wg_sample_create_mf(samples
[0].pSample
, &wg_sample
)))
616 if (wg_sample
->max_size
< sample_size
)
618 wg_sample_release(wg_sample
);
619 return MF_E_BUFFERTOOSMALL
;
622 if (SUCCEEDED(hr
= wg_transform_read_mf(decoder
->wg_transform
, wg_sample
, &wg_format
)))
623 wg_sample_queue_flush(decoder
->wg_sample_queue
, false);
624 wg_sample_release(wg_sample
);
626 if (hr
== MF_E_TRANSFORM_STREAM_CHANGE
)
628 decoder
->wg_format
= wg_format
;
630 /* keep the frame rate that was requested, GStreamer doesn't provide any */
631 if (SUCCEEDED(IMFMediaType_GetUINT64(decoder
->output_type
, &MF_MT_FRAME_RATE
, &frame_rate
)))
633 decoder
->wg_format
.u
.video
.fps_n
= frame_rate
>> 32;
634 decoder
->wg_format
.u
.video
.fps_d
= (UINT32
)frame_rate
;
637 samples
[0].dwStatus
|= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
;
638 *status
|= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
;
644 static const IMFTransformVtbl transform_vtbl
=
646 transform_QueryInterface
,
649 transform_GetStreamLimits
,
650 transform_GetStreamCount
,
651 transform_GetStreamIDs
,
652 transform_GetInputStreamInfo
,
653 transform_GetOutputStreamInfo
,
654 transform_GetAttributes
,
655 transform_GetInputStreamAttributes
,
656 transform_GetOutputStreamAttributes
,
657 transform_DeleteInputStream
,
658 transform_AddInputStreams
,
659 transform_GetInputAvailableType
,
660 transform_GetOutputAvailableType
,
661 transform_SetInputType
,
662 transform_SetOutputType
,
663 transform_GetInputCurrentType
,
664 transform_GetOutputCurrentType
,
665 transform_GetInputStatus
,
666 transform_GetOutputStatus
,
667 transform_SetOutputBounds
,
668 transform_ProcessEvent
,
669 transform_ProcessMessage
,
670 transform_ProcessInput
,
671 transform_ProcessOutput
,
674 HRESULT
h264_decoder_create(REFIID riid
, void **ret
)
676 static const struct wg_format output_format
=
678 .major_type
= WG_MAJOR_TYPE_VIDEO
,
681 .format
= WG_VIDEO_FORMAT_I420
,
686 static const struct wg_format input_format
= {.major_type
= WG_MAJOR_TYPE_H264
};
687 struct wg_transform
*transform
;
688 struct h264_decoder
*decoder
;
691 TRACE("riid %s, ret %p.\n", debugstr_guid(riid
), ret
);
693 if (!(transform
= wg_transform_create(&input_format
, &output_format
)))
695 ERR_(winediag
)("GStreamer doesn't support H.264 decoding, please install appropriate plugins\n");
698 wg_transform_destroy(transform
);
700 if (!(decoder
= calloc(1, sizeof(*decoder
))))
701 return E_OUTOFMEMORY
;
703 decoder
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
704 decoder
->refcount
= 1;
705 decoder
->wg_format
.u
.video
.format
= WG_VIDEO_FORMAT_UNKNOWN
;
706 decoder
->wg_format
.u
.video
.width
= 1920;
707 decoder
->wg_format
.u
.video
.height
= 1080;
708 decoder
->wg_format
.u
.video
.fps_n
= 30000;
709 decoder
->wg_format
.u
.video
.fps_d
= 1001;
711 if (FAILED(hr
= wg_sample_queue_create(&decoder
->wg_sample_queue
)))
717 *ret
= &decoder
->IMFTransform_iface
;
718 TRACE("Created decoder %p\n", *ret
);