winegstreamer: Use an IMFMediaType for the internal stream type.

This commit is contained in:
Rémi Bernon 2023-05-25 13:39:33 +02:00 committed by Alexandre Julliard
parent 6184ac8c9f
commit 8caaca177e

View file

@ -57,8 +57,8 @@ struct h264_decoder
MFT_INPUT_STREAM_INFO input_info;
IMFMediaType *output_type;
MFT_OUTPUT_STREAM_INFO output_info;
IMFMediaType *stream_type;
struct wg_format wg_format;
struct wg_transform *wg_transform;
struct wg_sample_queue *wg_sample_queue;
@ -107,8 +107,8 @@ static HRESULT try_create_wg_transform(struct h264_decoder *decoder)
static HRESULT fill_output_media_type(struct h264_decoder *decoder, IMFMediaType *media_type)
{
IMFMediaType *default_type = decoder->output_type;
struct wg_format *wg_format = &decoder->wg_format;
UINT32 value, width, height;
MFVideoArea aperture;
UINT64 ratio;
GUID subtype;
HRESULT hr;
@ -118,7 +118,8 @@ static HRESULT fill_output_media_type(struct h264_decoder *decoder, IMFMediaType
if (FAILED(hr = IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &ratio)))
{
ratio = (UINT64)wg_format->u.video.width << 32 | wg_format->u.video.height;
if (FAILED(IMFMediaType_GetUINT64(decoder->stream_type, &MF_MT_FRAME_SIZE, &ratio)))
ratio = (UINT64)1920 << 32 | 1080;
if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ratio)))
return hr;
}
@ -127,14 +128,16 @@ static HRESULT fill_output_media_type(struct h264_decoder *decoder, IMFMediaType
if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_FRAME_RATE, NULL)))
{
ratio = (UINT64)wg_format->u.video.fps_n << 32 | wg_format->u.video.fps_d;
if (FAILED(IMFMediaType_GetUINT64(decoder->stream_type, &MF_MT_FRAME_RATE, &ratio)))
ratio = (UINT64)30000 << 32 | 1001;
if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, ratio)))
return hr;
}
if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_PIXEL_ASPECT_RATIO, NULL)))
{
ratio = (UINT64)1 << 32 | 1; /* FIXME: read it from format */
if (FAILED(IMFMediaType_GetUINT64(decoder->stream_type, &MF_MT_PIXEL_ASPECT_RATIO, &ratio)))
ratio = (UINT64)1 << 32 | 1;
if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_PIXEL_ASPECT_RATIO, ratio)))
return hr;
}
@ -188,17 +191,9 @@ static HRESULT fill_output_media_type(struct h264_decoder *decoder, IMFMediaType
}
if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL))
&& (wg_format->u.video.padding.left || wg_format->u.video.padding.right || wg_format->u.video.padding.top
|| wg_format->u.video.padding.bottom))
&& SUCCEEDED(hr = IMFMediaType_GetBlob(decoder->stream_type, &MF_MT_MINIMUM_DISPLAY_APERTURE,
(BYTE *)&aperture, sizeof(aperture), &value)))
{
MFVideoArea aperture =
{
.OffsetX = {.value = wg_format->u.video.padding.left},
.OffsetY = {.value = wg_format->u.video.padding.top},
.Area.cx = wg_format->u.video.width - wg_format->u.video.padding.right - wg_format->u.video.padding.left,
.Area.cy = wg_format->u.video.height - wg_format->u.video.padding.bottom - wg_format->u.video.padding.top,
};
if (FAILED(hr = IMFMediaType_SetBlob(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE,
(BYTE *)&aperture, sizeof(aperture))))
return hr;
@ -482,10 +477,9 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM
if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
{
decoder->wg_format.u.video.width = frame_size >> 32;
decoder->wg_format.u.video.height = (UINT32)frame_size;
decoder->output_info.cbSize = decoder->wg_format.u.video.width
* decoder->wg_format.u.video.height * 2;
if (FAILED(hr = IMFMediaType_SetUINT64(decoder->stream_type, &MF_MT_FRAME_SIZE, frame_size)))
WARN("Failed to update stream type frame size, hr %#lx\n", hr);
decoder->output_info.cbSize = (frame_size >> 32) * (UINT32)frame_size * 2;
}
return S_OK;
@ -494,8 +488,8 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM
static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
struct h264_decoder *decoder = impl_from_IMFTransform(iface);
UINT64 frame_size, stream_frame_size;
GUID major, subtype;
UINT64 frame_size;
HRESULT hr;
ULONG i;
@ -517,9 +511,10 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
if (i == ARRAY_SIZE(h264_decoder_output_types))
return MF_E_INVALIDMEDIATYPE;
if (FAILED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))
|| (frame_size >> 32) != decoder->wg_format.u.video.width
|| (UINT32)frame_size != decoder->wg_format.u.video.height)
if (FAILED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
return MF_E_INVALIDMEDIATYPE;
if (SUCCEEDED(IMFMediaType_GetUINT64(decoder->stream_type, &MF_MT_FRAME_SIZE, &stream_frame_size))
&& frame_size != stream_frame_size)
return MF_E_INVALIDMEDIATYPE;
if (flags & MFT_SET_TYPE_TEST_ONLY)
return S_OK;
@ -677,6 +672,28 @@ static HRESULT output_sample(struct h264_decoder *decoder, IMFSample **out, IMFS
return S_OK;
}
static HRESULT handle_stream_type_change(struct h264_decoder *decoder, const struct wg_format *format)
{
UINT64 frame_size, frame_rate;
HRESULT hr;
if (decoder->stream_type)
IMFMediaType_Release(decoder->stream_type);
if (!(decoder->stream_type = mf_media_type_from_wg_format(format)))
return E_OUTOFMEMORY;
if (SUCCEEDED(IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_RATE, &frame_rate))
&& FAILED(hr = IMFMediaType_SetUINT64(decoder->stream_type, &MF_MT_FRAME_RATE, frame_rate)))
WARN("Failed to update stream type frame size, hr %#lx\n", hr);
if (FAILED(hr = IMFMediaType_GetUINT64(decoder->stream_type, &MF_MT_FRAME_SIZE, &frame_size)))
return hr;
decoder->output_info.cbSize = (frame_size >> 32) * (UINT32)frame_size * 2;
uninit_allocator(decoder);
return MF_E_TRANSFORM_STREAM_CHANGE;
}
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
@ -684,7 +701,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
struct wg_format wg_format;
UINT32 sample_size;
IMFSample *sample;
UINT64 frame_rate;
UINT64 frame_size;
GUID subtype;
DWORD size;
HRESULT hr;
@ -703,8 +720,9 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
if (FAILED(hr = IMFMediaType_GetGUID(decoder->output_type, &MF_MT_SUBTYPE, &subtype)))
return hr;
if (FAILED(hr = MFCalculateImageSize(&subtype, decoder->wg_format.u.video.width,
decoder->wg_format.u.video.height, &sample_size)))
if (FAILED(hr = IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_SIZE, &frame_size)))
return hr;
if (FAILED(hr = MFCalculateImageSize(&subtype, frame_size >> 32, (UINT32)frame_size, &sample_size)))
return hr;
if (decoder->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES)
@ -734,21 +752,9 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
{
decoder->wg_format = wg_format;
decoder->output_info.cbSize = ALIGN_SIZE(decoder->wg_format.u.video.width, 0xf)
* ALIGN_SIZE(decoder->wg_format.u.video.height, 0xf) * 2;
/* keep the frame rate that was requested, GStreamer doesn't provide any */
if (SUCCEEDED(IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_RATE, &frame_rate)))
{
decoder->wg_format.u.video.fps_n = frame_rate >> 32;
decoder->wg_format.u.video.fps_d = (UINT32)frame_rate;
}
samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
*status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
uninit_allocator(decoder);
hr = handle_stream_type_change(decoder, &wg_format);
}
if (decoder->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES)
@ -822,11 +828,6 @@ HRESULT h264_decoder_create(REFIID riid, void **ret)
decoder->IMFTransform_iface.lpVtbl = &transform_vtbl;
decoder->refcount = 1;
decoder->wg_format.u.video.format = WG_VIDEO_FORMAT_UNKNOWN;
decoder->wg_format.u.video.width = 1920;
decoder->wg_format.u.video.height = 1080;
decoder->wg_format.u.video.fps_n = 30000;
decoder->wg_format.u.video.fps_d = 1001;
decoder->input_info.dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
| MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
@ -835,6 +836,8 @@ HRESULT h264_decoder_create(REFIID riid, void **ret)
| MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
decoder->output_info.cbSize = 1920 * 1088 * 2;
if (FAILED(hr = MFCreateMediaType(&decoder->stream_type)))
goto failed;
if (FAILED(hr = MFCreateAttributes(&decoder->attributes, 16)))
goto failed;
if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_LOW_LATENCY, 0)))
@ -863,6 +866,8 @@ failed:
IMFAttributes_Release(decoder->output_attributes);
if (decoder->attributes)
IMFAttributes_Release(decoder->attributes);
if (decoder->stream_type)
IMFMediaType_Release(decoder->stream_type);
free(decoder);
return hr;
}