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 && !IsRectEmpty(&wg_format
->u
.video
.padding
))
188 MFVideoArea aperture
=
190 .OffsetX
= {.value
= wg_format
->u
.video
.padding
.left
},
191 .OffsetY
= {.value
= wg_format
->u
.video
.padding
.top
},
192 .Area
.cx
= wg_format
->u
.video
.width
- wg_format
->u
.video
.padding
.right
- wg_format
->u
.video
.padding
.left
,
193 .Area
.cy
= wg_format
->u
.video
.height
- wg_format
->u
.video
.padding
.bottom
- wg_format
->u
.video
.padding
.top
,
196 if (FAILED(hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
,
197 (BYTE
*)&aperture
, sizeof(aperture
))))
204 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
206 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
208 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
210 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
211 IsEqualGUID(iid
, &IID_IMFTransform
))
212 *out
= &decoder
->IMFTransform_iface
;
216 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
217 return E_NOINTERFACE
;
220 IUnknown_AddRef((IUnknown
*)*out
);
224 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
226 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
227 ULONG refcount
= InterlockedIncrement(&decoder
->refcount
);
229 TRACE("iface %p increasing refcount to %lu.\n", decoder
, refcount
);
234 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
236 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
237 ULONG refcount
= InterlockedDecrement(&decoder
->refcount
);
239 TRACE("iface %p decreasing refcount to %lu.\n", decoder
, refcount
);
243 if (decoder
->wg_transform
)
244 wg_transform_destroy(decoder
->wg_transform
);
245 if (decoder
->input_type
)
246 IMFMediaType_Release(decoder
->input_type
);
247 if (decoder
->output_type
)
248 IMFMediaType_Release(decoder
->output_type
);
249 if (decoder
->output_attributes
)
250 IMFAttributes_Release(decoder
->output_attributes
);
251 if (decoder
->attributes
)
252 IMFAttributes_Release(decoder
->attributes
);
254 wg_sample_queue_destroy(decoder
->wg_sample_queue
);
261 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
262 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
264 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
265 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
266 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
270 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
272 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
273 *inputs
= *outputs
= 1;
277 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
278 DWORD output_size
, DWORD
*outputs
)
280 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
281 input_size
, inputs
, output_size
, outputs
);
285 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
287 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
289 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
291 *info
= decoder
->input_info
;
295 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
297 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
299 TRACE("iface %p, id %#lx, info %p.\n", iface
, id
, info
);
301 *info
= decoder
->output_info
;
305 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
307 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
309 FIXME("iface %p, attributes %p semi-stub!\n", iface
, attributes
);
314 IMFAttributes_AddRef((*attributes
= decoder
->attributes
));
318 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
320 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
324 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
326 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
328 FIXME("iface %p, id %#lx, attributes %p semi-stub!\n", iface
, id
, attributes
);
333 return MF_E_INVALIDSTREAMNUMBER
;
335 IMFAttributes_AddRef((*attributes
= decoder
->output_attributes
));
339 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
341 TRACE("iface %p, id %#lx.\n", iface
, id
);
345 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
347 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
351 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
354 IMFMediaType
*media_type
;
358 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
362 if (index
>= ARRAY_SIZE(h264_decoder_input_types
))
363 return MF_E_NO_MORE_TYPES
;
364 subtype
= h264_decoder_input_types
[index
];
366 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
369 if (SUCCEEDED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)) &&
370 SUCCEEDED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, subtype
)))
371 IMFMediaType_AddRef((*type
= media_type
));
373 IMFMediaType_Release(media_type
);
377 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
,
378 DWORD index
, IMFMediaType
**type
)
380 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
381 IMFMediaType
*media_type
;
382 const GUID
*output_type
;
385 TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface
, id
, index
, type
);
387 if (!decoder
->input_type
)
388 return MF_E_TRANSFORM_TYPE_NOT_SET
;
392 if (index
>= ARRAY_SIZE(h264_decoder_output_types
))
393 return MF_E_NO_MORE_TYPES
;
394 output_type
= h264_decoder_output_types
[index
];
396 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
399 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
)))
401 if (FAILED(hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, output_type
)))
404 hr
= fill_output_media_type(decoder
, media_type
);
408 IMFMediaType_AddRef((*type
= media_type
));
410 IMFMediaType_Release(media_type
);
414 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
416 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
422 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
424 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
425 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
428 if (!IsEqualGUID(&major
, &MFMediaType_Video
))
429 return MF_E_INVALIDMEDIATYPE
;
431 for (i
= 0; i
< ARRAY_SIZE(h264_decoder_input_types
); ++i
)
432 if (IsEqualGUID(&subtype
, h264_decoder_input_types
[i
]))
434 if (i
== ARRAY_SIZE(h264_decoder_input_types
))
435 return MF_E_INVALIDMEDIATYPE
;
436 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
439 if (decoder
->output_type
)
441 IMFMediaType_Release(decoder
->output_type
);
442 decoder
->output_type
= NULL
;
445 if (decoder
->input_type
)
446 IMFMediaType_Release(decoder
->input_type
);
447 IMFMediaType_AddRef((decoder
->input_type
= type
));
449 if (SUCCEEDED(IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
451 decoder
->wg_format
.u
.video
.width
= frame_size
>> 32;
452 decoder
->wg_format
.u
.video
.height
= (UINT32
)frame_size
;
453 decoder
->output_info
.cbSize
= decoder
->wg_format
.u
.video
.width
454 * decoder
->wg_format
.u
.video
.height
* 2;
460 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
462 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
468 TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface
, id
, type
, flags
);
470 if (!decoder
->input_type
)
471 return MF_E_TRANSFORM_TYPE_NOT_SET
;
473 if (FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_MAJOR_TYPE
, &major
)) ||
474 FAILED(hr
= IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
477 if (!IsEqualGUID(&major
, &MFMediaType_Video
))
478 return MF_E_INVALIDMEDIATYPE
;
480 for (i
= 0; i
< ARRAY_SIZE(h264_decoder_output_types
); ++i
)
481 if (IsEqualGUID(&subtype
, h264_decoder_output_types
[i
]))
483 if (i
== ARRAY_SIZE(h264_decoder_output_types
))
484 return MF_E_INVALIDMEDIATYPE
;
486 if (FAILED(hr
= IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
))
487 || (frame_size
>> 32) != decoder
->wg_format
.u
.video
.width
488 || (UINT32
)frame_size
!= decoder
->wg_format
.u
.video
.height
)
489 return MF_E_INVALIDMEDIATYPE
;
490 if (flags
& MFT_SET_TYPE_TEST_ONLY
)
493 if (decoder
->output_type
)
494 IMFMediaType_Release(decoder
->output_type
);
495 IMFMediaType_AddRef((decoder
->output_type
= type
));
497 if (decoder
->wg_transform
)
499 struct wg_format output_format
;
500 mf_media_type_to_wg_format(decoder
->output_type
, &output_format
);
502 /* Don't force any specific size, H264 streams already have the metadata for it
503 * and will generate a MF_E_TRANSFORM_STREAM_CHANGE result later.
505 output_format
.u
.video
.width
= 0;
506 output_format
.u
.video
.height
= 0;
507 output_format
.u
.video
.fps_d
= 0;
508 output_format
.u
.video
.fps_n
= 0;
510 if (output_format
.major_type
== WG_MAJOR_TYPE_UNKNOWN
511 || !wg_transform_set_output_format(decoder
->wg_transform
, &output_format
))
513 IMFMediaType_Release(decoder
->output_type
);
514 decoder
->output_type
= NULL
;
515 return MF_E_INVALIDMEDIATYPE
;
518 else if (FAILED(hr
= try_create_wg_transform(decoder
)))
520 IMFMediaType_Release(decoder
->output_type
);
521 decoder
->output_type
= NULL
;
527 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
529 FIXME("iface %p, id %#lx, type %p stub!\n", iface
, id
, type
);
533 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
535 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
538 FIXME("iface %p, id %#lx, type %p stub!\n", iface
, id
, type
);
540 if (!decoder
->output_type
)
541 return MF_E_TRANSFORM_TYPE_NOT_SET
;
543 if (FAILED(hr
= MFCreateMediaType(type
)))
546 return IMFMediaType_CopyAllItems(decoder
->output_type
, (IMFAttributes
*)*type
);
549 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
551 FIXME("iface %p, id %#lx, flags %p stub!\n", iface
, id
, flags
);
555 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
557 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
561 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
563 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
567 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
569 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
573 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
575 FIXME("iface %p, message %#x, param %Ix stub!\n", iface
, message
, param
);
579 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
581 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
583 TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface
, id
, sample
, flags
);
585 if (!decoder
->wg_transform
)
586 return MF_E_TRANSFORM_TYPE_NOT_SET
;
588 return wg_transform_push_mf(decoder
->wg_transform
, sample
, decoder
->wg_sample_queue
);
591 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
592 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
594 struct h264_decoder
*decoder
= impl_from_IMFTransform(iface
);
595 struct wg_format wg_format
;
601 TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface
, flags
, count
, samples
, status
);
606 if (!decoder
->wg_transform
)
607 return MF_E_TRANSFORM_TYPE_NOT_SET
;
609 *status
= samples
->dwStatus
= 0;
610 if (!samples
->pSample
)
613 if (FAILED(hr
= IMFMediaType_GetGUID(decoder
->output_type
, &MF_MT_SUBTYPE
, &subtype
)))
615 if (FAILED(hr
= MFCalculateImageSize(&subtype
, decoder
->wg_format
.u
.video
.width
,
616 decoder
->wg_format
.u
.video
.height
, &sample_size
)))
619 if (SUCCEEDED(hr
= wg_transform_read_mf(decoder
->wg_transform
, samples
->pSample
,
620 sample_size
, &wg_format
, &samples
->dwStatus
)))
621 wg_sample_queue_flush(decoder
->wg_sample_queue
, false);
623 if (hr
== MF_E_TRANSFORM_STREAM_CHANGE
)
625 decoder
->wg_format
= wg_format
;
626 decoder
->output_info
.cbSize
= ALIGN_SIZE(decoder
->wg_format
.u
.video
.width
, 0xf)
627 * ALIGN_SIZE(decoder
->wg_format
.u
.video
.height
, 0xf) * 2;
629 /* keep the frame rate that was requested, GStreamer doesn't provide any */
630 if (SUCCEEDED(IMFMediaType_GetUINT64(decoder
->output_type
, &MF_MT_FRAME_RATE
, &frame_rate
)))
632 decoder
->wg_format
.u
.video
.fps_n
= frame_rate
>> 32;
633 decoder
->wg_format
.u
.video
.fps_d
= (UINT32
)frame_rate
;
636 samples
[0].dwStatus
|= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
;
637 *status
|= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
;
643 static const IMFTransformVtbl transform_vtbl
=
645 transform_QueryInterface
,
648 transform_GetStreamLimits
,
649 transform_GetStreamCount
,
650 transform_GetStreamIDs
,
651 transform_GetInputStreamInfo
,
652 transform_GetOutputStreamInfo
,
653 transform_GetAttributes
,
654 transform_GetInputStreamAttributes
,
655 transform_GetOutputStreamAttributes
,
656 transform_DeleteInputStream
,
657 transform_AddInputStreams
,
658 transform_GetInputAvailableType
,
659 transform_GetOutputAvailableType
,
660 transform_SetInputType
,
661 transform_SetOutputType
,
662 transform_GetInputCurrentType
,
663 transform_GetOutputCurrentType
,
664 transform_GetInputStatus
,
665 transform_GetOutputStatus
,
666 transform_SetOutputBounds
,
667 transform_ProcessEvent
,
668 transform_ProcessMessage
,
669 transform_ProcessInput
,
670 transform_ProcessOutput
,
673 HRESULT
h264_decoder_create(REFIID riid
, void **ret
)
675 static const struct wg_format output_format
=
677 .major_type
= WG_MAJOR_TYPE_VIDEO
,
680 .format
= WG_VIDEO_FORMAT_I420
,
685 static const struct wg_format input_format
= {.major_type
= WG_MAJOR_TYPE_VIDEO_H264
};
686 struct wg_transform
*transform
;
687 struct h264_decoder
*decoder
;
690 TRACE("riid %s, ret %p.\n", debugstr_guid(riid
), ret
);
692 if (!(transform
= wg_transform_create(&input_format
, &output_format
)))
694 ERR_(winediag
)("GStreamer doesn't support H.264 decoding, please install appropriate plugins\n");
697 wg_transform_destroy(transform
);
699 if (!(decoder
= calloc(1, sizeof(*decoder
))))
700 return E_OUTOFMEMORY
;
702 decoder
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
703 decoder
->refcount
= 1;
704 decoder
->wg_format
.u
.video
.format
= WG_VIDEO_FORMAT_UNKNOWN
;
705 decoder
->wg_format
.u
.video
.width
= 1920;
706 decoder
->wg_format
.u
.video
.height
= 1080;
707 decoder
->wg_format
.u
.video
.fps_n
= 30000;
708 decoder
->wg_format
.u
.video
.fps_d
= 1001;
710 decoder
->input_info
.dwFlags
= MFT_INPUT_STREAM_WHOLE_SAMPLES
| MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
711 | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE
;
712 decoder
->input_info
.cbSize
= 0x1000;
713 decoder
->output_info
.dwFlags
= MFT_OUTPUT_STREAM_WHOLE_SAMPLES
| MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
714 | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE
;
715 decoder
->output_info
.cbSize
= 1920 * 1088 * 2;
717 if (FAILED(hr
= MFCreateAttributes(&decoder
->attributes
, 16)))
719 if (FAILED(hr
= IMFAttributes_SetUINT32(decoder
->attributes
, &MF_LOW_LATENCY
, 0)))
721 if (FAILED(hr
= MFCreateAttributes(&decoder
->output_attributes
, 0)))
723 if (FAILED(hr
= wg_sample_queue_create(&decoder
->wg_sample_queue
)))
726 *ret
= &decoder
->IMFTransform_iface
;
727 TRACE("Created decoder %p\n", *ret
);
731 if (decoder
->output_attributes
)
732 IMFAttributes_Release(decoder
->output_attributes
);
733 if (decoder
->attributes
)
734 IMFAttributes_Release(decoder
->attributes
);