diff --git a/gst-libs/gst/video/gstvideometa.c b/gst-libs/gst/video/gstvideometa.c
index 33d17ac..681a853 100644
--- a/gst-libs/gst/video/gstvideometa.c
+++ b/gst-libs/gst/video/gstvideometa.c
@@ -1,4 +1,4 @@
-/* GStreamer
+/*
  * Copyright (C) <2011> Wim Taymans <wim.taymans@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -528,3 +528,160 @@ gst_video_gl_texture_upload_meta_upload (GstVideoGLTextureUploadMeta * meta,
 
   return meta->upload (meta, texture_id);
 }
+
+/* Region of Interest Meta implementation *******************************************/
+GQuark
+gst_video_region_of_interest_meta_bounding_box_get_quark (void)
+{
+  static GQuark _value = 0;
+
+  if (_value == 0) {
+    _value = g_quark_from_static_string ("gst-video-region-of-interest-bounding-box");
+  }
+  return _value;
+}
+
+GType
+gst_video_region_of_interest_meta_api_get_type (void)
+{
+  static volatile GType type;
+  static const gchar *tags[] = { "location", " 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_by_quark (dest, smeta->roi_type,
+                   smeta->x, smeta->y,
+                   smeta->w, smeta->h);
+  } else if (GST_VIDEO_META_TRANSFORM_IS_SCALE (type)) {
+    GstVideoMetaTransform *trans = data;
+    gint ow, oh, nw, nh;
+
+    smeta = (GstVideoRegionOfInterestMeta *) meta;
+
+    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);
+    dmeta = gst_buffer_add_video_region_of_interest_meta_by_quark (dest, smeta->roi_type,
+                   (smeta->x * nw) / ow,
+                   (smeta->y * nh) / oh,
+                   (smeta->w * nw) / ow,
+                   (smeta->h * nh) / oh);
+    GST_DEBUG ("region of interest offset %dx%d -> %dx%d", 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->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,
+						      gchar * 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 = g_quark_from_string  (roi_type);
+  meta->x = x;
+  meta->y = y;
+  meta->w = w;
+  meta->h = h;
+
+  return meta;
+}
+
+GstVideoRegionOfInterestMeta *
+gst_buffer_add_video_region_of_interest_meta_by_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;
+}
diff --git a/gst-libs/gst/video/gstvideometa.h b/gst-libs/gst/video/gstvideometa.h
index c747b25..5ca4737 100644
--- a/gst-libs/gst/video/gstvideometa.h
+++ b/gst-libs/gst/video/gstvideometa.h
@@ -36,6 +36,10 @@ typedef struct _GstVideoMeta GstVideoMeta;
 #define GST_VIDEO_CROP_META_INFO  (gst_video_crop_meta_get_info())
 typedef struct _GstVideoCropMeta GstVideoCropMeta;
 
+#define GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE (gst_video_region_of_interest_meta_api_get_type())
+#define GST_VIDEO_REGION_OF_INTEREST_META_INFO (gst_video_region_of_interest_meta_get_info())
+typedef struct _GstVideoRegionOfInterestMeta GstVideoRegionOfInterestMeta;
+
 /**
  * GstVideoMeta:
  * @meta: parent #GstMeta
@@ -232,6 +236,49 @@ GstVideoGLTextureUploadMeta *
 gboolean  gst_video_gl_texture_upload_meta_upload     (GstVideoGLTextureUploadMeta *meta,
                                                        guint texture_id[4]);
 
+
+/**
+ * GstVideoRegionOfInterestMeta:
+ * @meta: parent #GstMeta
+ * @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 an image region of interest
+ */
+struct _GstVideoRegionOfInterestMeta
+{
+  GstMeta meta;
+  GQuark roi_type;
+  gint id;
+  gint parent_id;
+
+  guint x;
+  guint y;
+  guint w;
+  guint h;
+};
+
+GQuark             gst_video_region_of_interest_meta_bounding_box_get_quark (void);
+#define GST_VIDEO_REGION_OF_INTEREST_META_IS_BOUNDING_BOX(type) \
+        ((type) == gst_video_region_of_interest_meta_bounding_box_get_quark())
+
+GType              gst_video_region_of_interest_meta_api_get_type (void);
+const GstMetaInfo *gst_video_region_of_interest_meta_get_info (void);
+
+#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,
+									    gchar * roi_type,
+									    guint x, guint y, 
+									    guint w, guint h);
+GstVideoRegionOfInterestMeta *gst_buffer_add_video_region_of_interest_meta_by_quark (GstBuffer * buffer, 
+									    GQuark roi_type,
+									    guint x, guint y, 
+									    guint w, guint h);
+
 G_END_DECLS
 
 #endif /* __GST_VIDEO_META_H__ */
