From: Eric Pouech eric.pouech@gmail.com
The app I'm considering opens a video_processor on its own, with a NV12 format on input and a ARGB32 format on output.
Tested on Windows: the samples are flipped vertically. While Wine keeps them untouched.
So added a videoflip in the video processor to be activated when needed. Current activation is based on RGB vs non RGB input/output formats.
Set as draft as if somehow related to MR!2159. Comments welcomed.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/winegstreamer/wg_transform.c | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 65a34511284..b5439c7a639 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -52,6 +52,7 @@ struct wg_transform GstPad *their_sink, *their_src; GstSegment segment; GstQuery *drain_query; + GstElement *video_flip;
guint input_max_length; GstAtomicQueue *input_queue; @@ -347,6 +348,39 @@ static struct wg_sample *transform_request_sample(gsize size, void *context) return InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL); }
+static bool wg_video_format_is_rgb(enum wg_video_format format) +{ + switch (format) + { + case WG_VIDEO_FORMAT_BGRA: + case WG_VIDEO_FORMAT_BGRx: + case WG_VIDEO_FORMAT_BGR: + case WG_VIDEO_FORMAT_RGB15: + case WG_VIDEO_FORMAT_RGB16: + return true; + + case WG_VIDEO_FORMAT_AYUV: + case WG_VIDEO_FORMAT_I420: + case WG_VIDEO_FORMAT_NV12: + case WG_VIDEO_FORMAT_UYVY: + case WG_VIDEO_FORMAT_YUY2: + case WG_VIDEO_FORMAT_YV12: + case WG_VIDEO_FORMAT_YVYU: + case WG_VIDEO_FORMAT_UNKNOWN: + break; + } + + return false; +} + +static bool wg_format_need_video_flip(const struct wg_format *format1, const struct wg_format *format2) +{ + /* Assuming all RGB formats are bottom-up, and all the others top-down. */ + return format1->major_type == WG_MAJOR_TYPE_VIDEO + && format2->major_type == WG_MAJOR_TYPE_VIDEO + && wg_video_format_is_rgb(format1->u.video.format) != wg_video_format_is_rgb(format2->u.video.format); +} + NTSTATUS wg_transform_create(void *args) { struct wg_transform_create_params *params = args; @@ -377,6 +411,7 @@ NTSTATUS wg_transform_create(void *args) goto out; transform->input_max_length = 1; transform->output_plane_align = 0; + transform->video_flip = NULL;
if (!(src_caps = wg_format_to_caps(&input_format))) goto out; @@ -474,6 +509,10 @@ NTSTATUS wg_transform_create(void *args) goto out; /* Let GStreamer choose a default number of threads. */ gst_util_set_object_arg(G_OBJECT(element), "n-threads", "0"); + + if (!(transform->video_flip = create_element("videoflip", "base")) + || !transform_append_element(transform, transform->video_flip, &first, &last)) + goto out; break;
case WG_MAJOR_TYPE_AUDIO_MPEG1: @@ -488,6 +527,14 @@ NTSTATUS wg_transform_create(void *args) goto out; }
+ if (transform->video_flip) + { + if (wg_format_need_video_flip(&input_format, &output_format)) + gst_util_set_object_arg(G_OBJECT(transform->video_flip), "method", "vertical-flip"); + else + gst_util_set_object_arg(G_OBJECT(transform->video_flip), "method", "none"); + } + if (!(transform->their_sink = gst_element_get_static_pad(first, "sink"))) goto out; if (!(transform->their_src = gst_element_get_static_pad(last, "src"))) @@ -563,6 +610,7 @@ NTSTATUS wg_transform_set_output_format(void *args) struct wg_transform_set_output_format_params *params = args; struct wg_transform *transform = params->transform; const struct wg_format *format = params->format; + struct wg_format old_output_format; GstSample *sample; GstCaps *caps; gchar *str; @@ -585,9 +633,19 @@ NTSTATUS wg_transform_set_output_format(void *args) return STATUS_UNSUCCESSFUL; }
+ wg_format_from_caps(&old_output_format, transform->output_caps); gst_caps_unref(transform->output_caps); transform->output_caps = caps;
+ if (transform->video_flip && wg_format_need_video_flip(&old_output_format, format)) + { + gchar* prop; + g_object_get(G_OBJECT(transform->video_flip), "method", &prop, NULL); + gst_util_set_object_arg(G_OBJECT(transform->video_flip), "method", + (!prop || !strcmp(prop, "none")) ? "vertical-flip" : "none"); + g_free(prop); + } + if (!gst_pad_push_event(transform->my_sink, gst_event_new_reconfigure())) { GST_ERROR("Failed to reconfigure transform %p.", transform);