videometa: Add Region Of Interest meta
authorMiguel Casas-Sanchez <miguelecasassanchez@gmail.com>
Tue, 16 Jul 2013 08:04:00 +0000 (10:04 +0200)
committerSebastian Dröge <slomo@circular-chaos.org>
Tue, 16 Jul 2013 08:04:00 +0000 (10:04 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=704070

gst-libs/gst/video/gstvideometa.c
gst-libs/gst/video/gstvideometa.h

index 33d17ac..48ce7db 100644 (file)
@@ -528,3 +528,143 @@ gst_video_gl_texture_upload_meta_upload (GstVideoGLTextureUploadMeta * meta,
 
   return meta->upload (meta, texture_id);
 }
+
+/* Region of Interest Meta implementation *******************************************/
+
+GType
+gst_video_region_of_interest_meta_api_get_type (void)
+{
+  static volatile GType type;
+  static const gchar *tags[] = { "orientation", " size", NULL };
+
+  if (g_once_init_enter (&type)) {
+    GType _type =
+        gst_meta_api_type_register ("GstVideoRegionOfInterestMetaAPI", tags);
+    GST_INFO ("registering");
+    g_once_init_leave (&type, _type);
+  }
+  return type;
+}
+
+
+static gboolean
+gst_video_region_of_interest_meta_transform (GstBuffer * dest, GstMeta * meta,
+    GstBuffer * buffer, GQuark type, gpointer data)
+{
+  GstVideoRegionOfInterestMeta *dmeta, *smeta;
+
+  if (GST_META_TRANSFORM_IS_COPY (type)) {
+    smeta = (GstVideoRegionOfInterestMeta *) meta;
+
+    GST_DEBUG ("copy region of interest metadata");
+    dmeta =
+        gst_buffer_add_video_region_of_interest_meta_from_quark (dest,
+        smeta->roi_type, smeta->x, smeta->y, smeta->w, smeta->h);
+    dmeta->id = smeta->id;
+    dmeta->parent_id = smeta->parent_id;
+  } else if (GST_VIDEO_META_TRANSFORM_IS_SCALE (type)) {
+    GstVideoMetaTransform *trans = data;
+    gint ow, oh, nw, nh;
+    ow = GST_VIDEO_INFO_WIDTH (trans->in_info);
+    nw = GST_VIDEO_INFO_WIDTH (trans->out_info);
+    oh = GST_VIDEO_INFO_HEIGHT (trans->in_info);
+    nh = GST_VIDEO_INFO_HEIGHT (trans->out_info);
+    GST_DEBUG ("scaling region of interest metadata %dx%d -> %dx%d", ow, oh, nw,
+        nh);
+
+    smeta = (GstVideoRegionOfInterestMeta *) meta;
+    dmeta =
+        gst_buffer_add_video_region_of_interest_meta_from_quark (dest,
+        smeta->roi_type, (smeta->x * nw) / ow, (smeta->y * nh) / oh,
+        (smeta->w * nw) / ow, (smeta->h * nh) / oh);
+    dmeta->id = smeta->id;
+    dmeta->parent_id = smeta->parent_id;
+
+    GST_DEBUG ("region of interest (id:%d, parent id:%d) offset %dx%d -> %dx%d",
+        smeta->id, smeta->parent_id, smeta->x, smeta->y, dmeta->x, dmeta->y);
+    GST_DEBUG ("region of interest size   %dx%d -> %dx%d", smeta->w, smeta->h,
+        dmeta->w, dmeta->h);
+  }
+  return TRUE;
+}
+
+static gboolean
+gst_video_region_of_interest_meta_init (GstMeta * meta, gpointer params,
+    GstBuffer * buffer)
+{
+  GstVideoRegionOfInterestMeta *emeta = (GstVideoRegionOfInterestMeta *) meta;
+  emeta->id = 0;
+  emeta->parent_id = 0;
+  emeta->x = emeta->y = emeta->w = emeta->h = 0;
+
+  return TRUE;
+}
+
+static void
+gst_video_region_of_interest_meta_free (GstMeta * meta, GstBuffer * buffer)
+{
+  // nothing to do
+}
+
+const GstMetaInfo *
+gst_video_region_of_interest_meta_get_info (void)
+{
+  static const GstMetaInfo *meta_info = NULL;
+
+  if (g_once_init_enter (&meta_info)) {
+    const GstMetaInfo *mi =
+        gst_meta_register (GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE,
+        "GstVideoRegionOfInterestMeta",
+        sizeof (GstVideoRegionOfInterestMeta),
+        gst_video_region_of_interest_meta_init,
+        gst_video_region_of_interest_meta_free,
+        gst_video_region_of_interest_meta_transform);
+    g_once_init_leave (&meta_info, mi);
+  }
+  return meta_info;
+}
+
+GstVideoRegionOfInterestMeta *
+gst_buffer_get_video_region_of_interest_meta_id (GstBuffer * buffer, gint id)
+{
+  gpointer state = NULL;
+  GstMeta *meta;
+  const GstMetaInfo *info = GST_VIDEO_META_INFO;
+
+  while ((meta = gst_buffer_iterate_meta (buffer, &state))) {
+    if (meta->info->api == info->api) {
+      GstVideoRegionOfInterestMeta *vmeta =
+          (GstVideoRegionOfInterestMeta *) meta;
+      if (vmeta->id == id)
+        return vmeta;
+    }
+  }
+  return NULL;
+}
+
+GstVideoRegionOfInterestMeta *
+gst_buffer_add_video_region_of_interest_meta_by_name (GstBuffer * buffer,
+    const gchar * roi_type, guint x, guint y, guint w, guint h)
+{
+  return gst_buffer_add_video_region_of_interest_meta_from_quark (buffer,
+      g_quark_from_string (roi_type), x, y, w, h);
+}
+
+GstVideoRegionOfInterestMeta *
+gst_buffer_add_video_region_of_interest_meta_from_quark (GstBuffer * buffer,
+    GQuark roi_type, guint x, guint y, guint w, guint h)
+{
+  GstVideoRegionOfInterestMeta *meta;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+
+  meta = (GstVideoRegionOfInterestMeta *) gst_buffer_add_meta (buffer,
+      GST_VIDEO_REGION_OF_INTEREST_META_INFO, NULL);
+  meta->roi_type = roi_type;
+  meta->x = x;
+  meta->y = y;
+  meta->w = w;
+  meta->h = h;
+
+  return meta;
+}
index c747b25..de78615 100644 (file)
@@ -232,6 +232,50 @@ GstVideoGLTextureUploadMeta *
 gboolean  gst_video_gl_texture_upload_meta_upload     (GstVideoGLTextureUploadMeta *meta,
                                                        guint texture_id[4]);
 
+
+/**
+ * GstVideoRegionOfInterestMeta: a Bounding Box describing the inner part of a rectangle inside a video frame.
+ * @meta: parent #GstMeta
+ * @roi_type: GQuark describing the semantic of the Roi (f.i. a face, a pedestrian)
+ * @id: identifier of this particular ROI
+ * @parent_id: identifier of its parent ROI, used f.i. for ROI hierarchisation.
+ * @x: x component of upper-left corner
+ * @y: y component of upper-left corner
+ * @width: bounding box width
+ * @height: bounding box height
+ *
+ * Extra buffer metadata describing an image region of interest
+ */
+typedef struct
+{
+  GstMeta meta;
+  GQuark roi_type;
+  gint id;
+  gint parent_id;
+
+  guint x;
+  guint y;
+  guint w;
+  guint h;
+}GstVideoRegionOfInterestMeta;;
+
+GType              gst_video_region_of_interest_meta_api_get_type (void);
+#define GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE (gst_video_region_of_interest_meta_api_get_type())
+const GstMetaInfo *gst_video_region_of_interest_meta_get_info (void);
+#define GST_VIDEO_REGION_OF_INTEREST_META_INFO (gst_video_region_of_interest_meta_get_info())
+
+#define gst_buffer_get_video_region_of_interest_meta(b) \
+        ((GstVideoRegionOfInterestMeta*)gst_buffer_get_meta((b),GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE))
+GstVideoRegionOfInterestMeta *gst_buffer_get_video_region_of_interest_meta_id (GstBuffer *buffer, gint id);
+GstVideoRegionOfInterestMeta *gst_buffer_add_video_region_of_interest_meta_by_name (GstBuffer * buffer,
+                                                                           const gchar * roi_type,
+                                                                           guint x, guint y, 
+                                                                           guint w, guint h);
+GstVideoRegionOfInterestMeta *gst_buffer_add_video_region_of_interest_meta_from_quark (GstBuffer * buffer, 
+                                                                           GQuark roi_type,
+                                                                           guint x, guint y, 
+                                                                           guint w, guint h);
+
 G_END_DECLS
 
 #endif /* __GST_VIDEO_META_H__ */