From 08311c51bed71003faf7c06946a6aa930e69605c Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 15 Aug 2016 16:37:44 +1000 Subject: [PATCH] winks: Fix RGB frame flipping and postprocessing Uncompressed RGB frames can be (usually are) bottom-up layout in DirectShow, and the code to flip them wasn't properly ported from 0.10. Fix it. Fix post-processing of RGB buffers. We need a writable buffer, but the requests pool is holding an extra ref. This could use more fixing to use a buffer pool --- sys/winks/gstksvideodevice.c | 10 ++++++++-- sys/winks/gstksvideodevice.h | 2 +- sys/winks/gstksvideosrc.c | 2 +- sys/winks/ksvideohelpers.c | 31 +++++++++++++++++++++---------- sys/winks/ksvideohelpers.h | 1 + 5 files changed, 32 insertions(+), 14 deletions(-) diff --git a/sys/winks/gstksvideodevice.c b/sys/winks/gstksvideodevice.c index d00b6a756d..8f89d51d1f 100644 --- a/sys/winks/gstksvideodevice.c +++ b/sys/winks/gstksvideodevice.c @@ -796,7 +796,7 @@ gst_ks_video_device_set_caps (GstKsVideoDevice * self, GstCaps * caps) priv->fps_n = fps_n; priv->fps_d = fps_d; - if (gst_structure_has_name (s, "video/x-raw-rgb")) + if (media_type->is_rgb) priv->rgb_swap_buf = g_malloc (media_type->sample_size / priv->height); else priv->rgb_swap_buf = NULL; @@ -1176,9 +1176,10 @@ error_get_result: } gboolean -gst_ks_video_device_postprocess_frame (GstKsVideoDevice * self, GstBuffer * buf) +gst_ks_video_device_postprocess_frame (GstKsVideoDevice * self, GstBuffer ** bufptr) { GstKsVideoDevicePrivate *priv = GST_KS_VIDEO_DEVICE_GET_PRIVATE (self); + GstBuffer *buf = *bufptr; /* If it's RGB we need to flip the image */ if (priv->rgb_swap_buf != NULL) { @@ -1186,6 +1187,10 @@ gst_ks_video_device_postprocess_frame (GstKsVideoDevice * self, GstBuffer * buf) gint stride, line; guint8 *dst, *src; + /* Need to make the buffer writable because + * the pseudo-bufferpool of requests keeps a ref */ + buf = gst_buffer_make_writable (buf); + if (!gst_buffer_map (buf, &info, GST_MAP_READWRITE)) return FALSE; @@ -1205,6 +1210,7 @@ gst_ks_video_device_postprocess_frame (GstKsVideoDevice * self, GstBuffer * buf) gst_buffer_unmap (buf, &info); } + *bufptr = buf; return TRUE; } diff --git a/sys/winks/gstksvideodevice.h b/sys/winks/gstksvideodevice.h index 649faaa663..4c135eac41 100644 --- a/sys/winks/gstksvideodevice.h +++ b/sys/winks/gstksvideodevice.h @@ -77,7 +77,7 @@ GstClockTime gst_ks_video_device_get_duration (GstKsVideoDevice * self); gboolean gst_ks_video_device_get_latency (GstKsVideoDevice * self, GstClockTime * min_latency, GstClockTime * max_latency); GstFlowReturn gst_ks_video_device_read_frame (GstKsVideoDevice * self, GstBuffer ** buf, GstClockTime * presentation_time, gulong * error_code, gchar ** error_str); -gboolean gst_ks_video_device_postprocess_frame (GstKsVideoDevice * self, GstBuffer *buf); +gboolean gst_ks_video_device_postprocess_frame (GstKsVideoDevice * self, GstBuffer **buf); void gst_ks_video_device_cancel (GstKsVideoDevice * self); void gst_ks_video_device_cancel_stop (GstKsVideoDevice * self); diff --git a/sys/winks/gstksvideosrc.c b/sys/winks/gstksvideosrc.c index 98f0b4cfb4..0854b29407 100644 --- a/sys/winks/gstksvideosrc.c +++ b/sys/winks/gstksvideosrc.c @@ -927,7 +927,7 @@ gst_ks_video_src_create (GstPushSrc * pushsrc, GstBuffer ** buf) if (G_UNLIKELY (priv->do_stats)) gst_ks_video_src_update_statistics (self); - if (!gst_ks_video_device_postprocess_frame (priv->device, *buf)) { + if (!gst_ks_video_device_postprocess_frame (priv->device, buf)) { GST_ELEMENT_ERROR (self, RESOURCE, FAILED, ("Postprocessing failed"), ("Postprocessing failed")); return GST_FLOW_ERROR; diff --git a/sys/winks/ksvideohelpers.c b/sys/winks/ksvideohelpers.c index 20da75bfe2..8f51e50596 100644 --- a/sys/winks/ksvideohelpers.c +++ b/sys/winks/ksvideohelpers.c @@ -125,10 +125,13 @@ ks_video_device_list_sort_cameras_first (GList * devices) } static GstStructure * -ks_video_format_to_structure (GUID subtype_guid, GUID format_guid) +ks_video_format_to_structure (GUID subtype_guid, GUID format_guid, + gboolean * p_is_rgb) { GstStructure *structure = NULL; const gchar *media_type = NULL, *format = NULL; + /* RGB formats can be bottom-up (upside down) DIB */ + gboolean is_rgb = FALSE; if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_MJPG) || IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_TVMJ) || /* FIXME: NOT tested */ IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_WAKE) || /* FIXME: NOT tested */ @@ -138,18 +141,23 @@ ks_video_format_to_structure (GUID subtype_guid, GUID format_guid) } else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB555)) { media_type = "video/x-raw"; format = "RGB15"; + is_rgb = TRUE; } else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB565)) { media_type = "video/x-raw"; format = "RGB16"; + is_rgb = TRUE; } else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB24)) { - format = "BGR"; media_type = "video/x-raw"; + format = "BGR"; + is_rgb = TRUE; } else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_RGB32)) { media_type = "video/x-raw"; format = "BGRx"; + is_rgb = TRUE; } else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB32)) { media_type = "video/x-raw"; format = "BGRA"; + is_rgb = TRUE; } else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB1555)) { GST_WARNING ("Unsupported video format ARGB15555"); } else if (IsEqualGUID (&subtype_guid, &MEDIASUBTYPE_ARGB4444)) { @@ -177,6 +185,9 @@ ks_video_format_to_structure (GUID subtype_guid, GUID format_guid) if (format) { gst_structure_set (structure, "format", G_TYPE_STRING, format, NULL); } + if (p_is_rgb) { + *p_is_rgb = is_rgb; + } } if (!structure) { @@ -527,7 +538,7 @@ ks_video_probe_filter_for_caps (HANDLE filter_handle) media_structure = ks_video_format_to_structure (range->SubFormat, - range->Specifier); + range->Specifier, &entry->is_rgb); if (media_structure == NULL) { g_warning ("ks_video_format_to_structure returned NULL"); @@ -678,22 +689,22 @@ ks_video_get_all_caps (void) /* RGB formats */ structure = ks_video_append_var_video_fields (ks_video_format_to_structure - (MEDIASUBTYPE_RGB555, FORMAT_VideoInfo)); + (MEDIASUBTYPE_RGB555, FORMAT_VideoInfo, NULL)); gst_caps_append_structure (caps, structure); structure = ks_video_append_var_video_fields (ks_video_format_to_structure - (MEDIASUBTYPE_RGB565, FORMAT_VideoInfo)); + (MEDIASUBTYPE_RGB565, FORMAT_VideoInfo, NULL)); gst_caps_append_structure (caps, structure); structure = ks_video_append_var_video_fields (ks_video_format_to_structure - (MEDIASUBTYPE_RGB24, FORMAT_VideoInfo)); + (MEDIASUBTYPE_RGB24, FORMAT_VideoInfo, NULL)); gst_caps_append_structure (caps, structure); structure = ks_video_append_var_video_fields (ks_video_format_to_structure - (MEDIASUBTYPE_RGB32, FORMAT_VideoInfo)); + (MEDIASUBTYPE_RGB32, FORMAT_VideoInfo, NULL)); gst_caps_append_structure (caps, structure); /* YUV formats */ @@ -705,16 +716,16 @@ ks_video_get_all_caps (void) /* Other formats */ structure = ks_video_append_var_video_fields (ks_video_format_to_structure - (MEDIASUBTYPE_MJPG, FORMAT_VideoInfo)); + (MEDIASUBTYPE_MJPG, FORMAT_VideoInfo, NULL)); gst_caps_append_structure (caps, structure); structure = ks_video_append_var_video_fields (ks_video_format_to_structure - (MEDIASUBTYPE_dvsd, FORMAT_VideoInfo)); + (MEDIASUBTYPE_dvsd, FORMAT_VideoInfo, NULL)); gst_caps_append_structure (caps, structure); structure = /* no variable video fields (width, height, framerate) */ - ks_video_format_to_structure (MEDIASUBTYPE_dvsd, FORMAT_DvInfo); + ks_video_format_to_structure (MEDIASUBTYPE_dvsd, FORMAT_DvInfo, NULL); gst_caps_append_structure (caps, structure); } diff --git a/sys/winks/ksvideohelpers.h b/sys/winks/ksvideohelpers.h index 3aa0c388bd..92152847ee 100644 --- a/sys/winks/ksvideohelpers.h +++ b/sys/winks/ksvideohelpers.h @@ -49,6 +49,7 @@ struct _KsVideoMediaType guint sample_size; GstCaps * translated_caps; + gboolean is_rgb; }; typedef struct DVINFO {