winks: Fix RGB frame flipping and postprocessing
authorJan Schmidt <jan@centricular.com>
Mon, 15 Aug 2016 06:37:44 +0000 (16:37 +1000)
committerJan Schmidt <jan@centricular.com>
Mon, 15 Aug 2016 14:43:39 +0000 (00:43 +1000)
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
sys/winks/gstksvideodevice.h
sys/winks/gstksvideosrc.c
sys/winks/ksvideohelpers.c
sys/winks/ksvideohelpers.h

index d00b6a7..8f89d51 100644 (file)
@@ -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;
 }
index 649faaa..4c135ea 100644 (file)
@@ -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);
 
index 98f0b4c..0854b29 100644 (file)
@@ -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;
index 20da75b..8f51e50 100644 (file)
@@ -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);
   }
 
index 3aa0c38..9215284 100644 (file)
@@ -49,6 +49,7 @@ struct _KsVideoMediaType
   guint sample_size;
 
   GstCaps * translated_caps;
+  gboolean is_rgb;
 };
 
 typedef struct DVINFO {