From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/Makefile.in | 2 +- dlls/winegstreamer/color_convert.c | 55 +++++++++++++++++++++++++++- dlls/winegstreamer/gst_private.h | 23 ++++++++++++ dlls/winegstreamer/video_processor.c | 22 +++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 447c2c74cf3..63ca3f61fdf 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -1,7 +1,7 @@ MODULE = winegstreamer.dll UNIXLIB = winegstreamer.so IMPORTLIB = winegstreamer -IMPORTS = strmbase ole32 oleaut32 msdmo msvcrt +IMPORTS = strmbase ole32 oleaut32 msdmo msvcrt user32 DELAYIMPORTS = mfplat mf UNIX_CFLAGS = $(GSTREAMER_CFLAGS) UNIX_LIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS) diff --git a/dlls/winegstreamer/color_convert.c b/dlls/winegstreamer/color_convert.c index 21d2aa67e64..a95410bd546 100644 --- a/dlls/winegstreamer/color_convert.c +++ b/dlls/winegstreamer/color_convert.c @@ -95,9 +95,56 @@ static inline struct color_convert *impl_from_IUnknown(IUnknown *iface) return CONTAINING_RECORD(iface, struct color_convert, IUnknown_inner); }
+static void update_video_aperture(MFVideoInfo *input_info, MFVideoInfo *output_info) +{ + RECT input_rect, output_rect; + + get_mf_video_content_rect(input_info, &input_rect); + get_mf_video_content_rect(output_info, &output_rect); + IntersectRect(&input_rect, &input_rect, &output_rect); + + input_info->MinimumDisplayAperture.OffsetX.value = input_rect.left; + input_info->MinimumDisplayAperture.OffsetY.value = input_rect.top; + input_info->MinimumDisplayAperture.Area.cx = input_rect.right - input_rect.left; + input_info->MinimumDisplayAperture.Area.cy = input_rect.bottom - input_rect.top; + output_info->MinimumDisplayAperture = input_info->MinimumDisplayAperture; +} + +static HRESULT normalize_media_types(IMFMediaType **input_type, IMFMediaType **output_type) +{ + MFVIDEOFORMAT *input_format, *output_format; + UINT32 size; + HRESULT hr; + + if (FAILED(hr = MFCreateMFVideoFormatFromMFMediaType(*input_type, &input_format, &size))) + return hr; + if (FAILED(hr = MFCreateMFVideoFormatFromMFMediaType(*output_type, &output_format, &size))) + { + CoTaskMemFree(input_format); + return hr; + } + + update_video_aperture(&input_format->videoInfo, &output_format->videoInfo); + + if (FAILED(hr = MFCreateVideoMediaType(input_format, (IMFVideoMediaType **)input_type))) + goto done; + if (FAILED(hr = MFCreateVideoMediaType(output_format, (IMFVideoMediaType **)output_type))) + { + IMFMediaType_Release(*input_type); + *input_type = NULL; + } + +done: + CoTaskMemFree(input_format); + CoTaskMemFree(output_format); + return hr; +} + static HRESULT try_create_wg_transform(struct color_convert *impl) { + IMFMediaType *input_type = impl->input_type, *output_type = impl->output_type; struct wg_transform_attrs attrs = {0}; + HRESULT hr;
if (impl->wg_transform) { @@ -105,7 +152,13 @@ static HRESULT try_create_wg_transform(struct color_convert *impl) impl->wg_transform = 0; }
- return wg_transform_create_mf(impl->input_type, impl->output_type, &attrs, &impl->wg_transform); + if (FAILED(hr = normalize_media_types(&input_type, &output_type))) + return hr; + hr = wg_transform_create_mf(input_type, output_type, &attrs, &impl->wg_transform); + IMFMediaType_Release(output_type); + IMFMediaType_Release(input_type); + + return hr; }
static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 142de9bce9f..0f7d945ba37 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -43,6 +43,29 @@ bool array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
#define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000)
+static inline BOOL is_mf_video_area_empty(const MFVideoArea *area) +{ + return !area->OffsetX.value && !area->OffsetY.value && !area->Area.cx && !area->Area.cy; +} + +static inline void get_mf_video_content_rect(const MFVideoInfo *info, RECT *rect) +{ + if (!is_mf_video_area_empty(&info->MinimumDisplayAperture)) + { + rect->left = info->MinimumDisplayAperture.OffsetX.value; + rect->top = info->MinimumDisplayAperture.OffsetY.value; + rect->right = rect->left + info->MinimumDisplayAperture.Area.cx; + rect->bottom = rect->top + info->MinimumDisplayAperture.Area.cy; + } + else + { + rect->left = 0; + rect->top = 0; + rect->right = info->dwWidth; + rect->bottom = info->dwHeight; + } +} + struct wg_sample_queue;
HRESULT wg_sample_queue_create(struct wg_sample_queue **out); diff --git a/dlls/winegstreamer/video_processor.c b/dlls/winegstreamer/video_processor.c index 5555cef8303..3cb2c1a5bc6 100644 --- a/dlls/winegstreamer/video_processor.c +++ b/dlls/winegstreamer/video_processor.c @@ -91,6 +91,26 @@ struct video_processor IMFVideoSampleAllocatorEx *allocator; };
+static void update_video_aperture(MFVideoInfo *input_info, MFVideoInfo *output_info) +{ + RECT input_rect, output_rect; + + get_mf_video_content_rect(input_info, &input_rect); + get_mf_video_content_rect(output_info, &output_rect); + + if (!EqualRect(&input_rect, &output_rect)) + { + FIXME("Mismatched content size %s vs %s\n", wine_dbgstr_rect(&input_rect), + wine_dbgstr_rect(&output_rect)); + } + + input_info->MinimumDisplayAperture.OffsetX.value = input_rect.left; + input_info->MinimumDisplayAperture.OffsetY.value = input_rect.top; + input_info->MinimumDisplayAperture.Area.cx = input_rect.right - input_rect.left; + input_info->MinimumDisplayAperture.Area.cy = input_rect.bottom - input_rect.top; + output_info->MinimumDisplayAperture = input_info->MinimumDisplayAperture; +} + static HRESULT normalize_media_types(BOOL bottom_up, IMFMediaType **input_type, IMFMediaType **output_type) { MFVIDEOFORMAT *input_format, *output_format; @@ -114,6 +134,8 @@ static HRESULT normalize_media_types(BOOL bottom_up, IMFMediaType **input_type, if (bottom_up && normalize_output) output_format->videoInfo.VideoFlags |= MFVideoFlag_BottomUpLinearRep;
+ update_video_aperture(&input_format->videoInfo, &output_format->videoInfo); + if (FAILED(hr = MFCreateVideoMediaType(input_format, (IMFVideoMediaType **)input_type))) goto done; if (FAILED(hr = MFCreateVideoMediaType(output_format, (IMFVideoMediaType **)output_type)))