diff --git a/common b/common
index 48a5d85..39ac2f5 160000
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 48a5d85ebf4a0bad1c997c83100f710fe2154fbf
+Subproject commit 39ac2f563e12d22100e320c95aaab8d8e5812ca9
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.c b/gst-libs/gst/vaapi/gstvaapidecoder.c
index ce9c065..7498dbc 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder.c
+++ b/gst-libs/gst/vaapi/gstvaapidecoder.c
@@ -1200,3 +1200,99 @@ gst_vaapi_decoder_update_caps (GstVaapiDecoder * decoder, GstCaps * caps)
 
   return FALSE;
 }
+
+/**
+ * gst_vaapi_decoder_props_ref:
+ * @props: a #GstVaapiDecoderProps
+ *
+ * Atomically increases the reference count of the given @props by one.
+ *
+ * Returns: The same @props argument
+ */
+GstVaapiDecoderProps *
+gst_vaapi_decoder_props_ref (GstVaapiDecoderProps * props)
+{
+  return gst_vaapi_object_ref (props);
+}
+
+/**
+ * gst_vaapi_decoder_props_unref:
+ * @props: a #GstVaapiDecoderProps
+ *
+ * Atomically decreases the reference count of the @props by one. If
+ * the reference count reaches zero, the decoder will be free'd.
+ */
+void
+gst_vaapi_decoder_props_unref (GstVaapiDecoderProps * props)
+{
+  gst_vaapi_object_unref (props);
+}
+
+/**
+ * gst_vaapi_decoder_props_replace:
+ * @old_props_ptr: a pointer to a #GstVaapiDecoderProps
+ * @new_props: a #GstVaapiDecoderProps
+ *
+ * Atomically replaces the decoder decoder held in @old_props_ptr
+ * with @new_props. This means that @old_props_ptr shall reference
+ * a valid props object. However, @new_props can be NULL.
+ */
+void
+gst_vaapi_decoder_props_replace (GstVaapiDecoderProps ** old_props_ptr,
+    GstVaapiDecoderProps * new_props)
+{
+  gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) old_props_ptr,
+      GST_VAAPI_MINI_OBJECT (new_props));
+}
+
+/**
+ * gst_vaapi_decoder_props_set_property
+ * @props: a #GstVaapiDecoderProps
+ * @prop_id: ID of the property to set
+ * @value: the value to set
+ * @pspec: the #GParamSpec of the property
+ *
+ * Sets the identified property to the given value
+ *
+ * Returns: %TRUE if the requested property was found
+ **/
+gboolean
+gst_vaapi_decoder_props_set_property (GstVaapiDecoderProps * props,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstVaapiDecoderPropsClass *const klass =
+      GST_VAAPI_DECODER_PROPS_GET_CLASS (props);
+  gboolean retval = FALSE;
+
+  if (klass->set_property) {
+    retval = klass->set_property (props, prop_id, value, pspec);
+  }
+
+  return retval;
+}
+
+/**
+ * gst_vaapi_decoder_props_get_property
+ * @props: a #GstVaapiDecoderProps
+ * @prop_id: ID of the property to get
+ * @value: a #GValue to return the property value in
+ * @pspec: the #GParamSpec of the property
+ *
+ * Gets the value of the identified property
+ *
+ * Returns: %TRUE if the requested property was found
+ **/
+gboolean
+gst_vaapi_decoder_props_get_property (GstVaapiDecoderProps * props,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstVaapiDecoderPropsClass *const klass =
+      GST_VAAPI_DECODER_PROPS_GET_CLASS (props);
+  gboolean retval = FALSE;
+
+  if (klass->get_property) {
+    retval = klass->get_property (props, prop_id, value, pspec);
+  }
+
+  return retval;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.h b/gst-libs/gst/vaapi/gstvaapidecoder.h
index 8b442b9..76c2314 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder.h
+++ b/gst-libs/gst/vaapi/gstvaapidecoder.h
@@ -35,6 +35,10 @@ G_BEGIN_DECLS
 #define GST_VAAPI_DECODER(obj) \
     ((GstVaapiDecoder *)(obj))
 
+typedef struct _GstVaapiDecoderProps GstVaapiDecoderProps;
+
+typedef GstVaapiDecoderProps * (*GstVaapiDecoderPropsConstructor)();
+
 typedef struct _GstVaapiDecoder GstVaapiDecoder;
 typedef void (*GstVaapiDecoderStateChangedFunc) (GstVaapiDecoder * decoder,
     const GstVideoCodecState * codec_state, gpointer user_data);
@@ -141,6 +145,24 @@ gst_vaapi_decoder_check_status (GstVaapiDecoder * decoder);
 gboolean
 gst_vaapi_decoder_update_caps (GstVaapiDecoder * decoder, GstCaps * caps);
 
+GstVaapiDecoderProps *
+gst_vaapi_decoder_props_ref (GstVaapiDecoderProps * props);
+
+void
+gst_vaapi_decoder_props_unref (GstVaapiDecoderProps * props);
+
+void
+gst_vaapi_decoder_props_replace (GstVaapiDecoderProps ** old_props_ptr,
+    GstVaapiDecoderProps * new_props_decoder);
+
+gboolean
+gst_vaapi_decoder_props_set_property (GstVaapiDecoderProps * props,
+        guint prop_id, const GValue * value, GParamSpec * pspec);
+
+gboolean
+gst_vaapi_decoder_props_get_property (GstVaapiDecoderProps * props,
+        guint prop_id, GValue * value, GParamSpec * pspec);
+
 G_END_DECLS
 
 #endif /* GST_VAAPI_DECODER_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c
index 0cf46da..7b3c8bc 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c
@@ -39,9 +39,20 @@
 #define DEBUG 1
 #include "gstvaapidebug.h"
 
+enum
+{
+  PROP_0,
+  PROP_LOW_LATENCY,
+  PROP_LAST
+};
+
+#define DEFAULT_LOW_LATENCY FALSE
+
 /* Defined to 1 if strict ordering of DPB is needed. Only useful for debug */
 #define USE_STRICT_DPB_ORDERING 0
 
+typedef struct _GstVaapiDecoderPropsH264Class GstVaapiDecoderPropsH264Class;
+
 typedef struct _GstVaapiDecoderH264Private GstVaapiDecoderH264Private;
 typedef struct _GstVaapiDecoderH264Class GstVaapiDecoderH264Class;
 typedef struct _GstVaapiFrameStore GstVaapiFrameStore;
@@ -452,6 +463,33 @@ gst_vaapi_frame_store_has_inter_view (GstVaapiFrameStore * fs)
         (GstVaapiMiniObject *)(new_fs))
 
 /* ------------------------------------------------------------------------- */
+/* --- H.264 Decoder Props                                               --- */
+/* ------------------------------------------------------------------------- */
+/**
+ * GstVaapiDecoderPropsH264:
+ *
+ * gobject properties for GstVaapiDecoderH264
+ */
+struct _GstVaapiDecoderPropsH264
+{
+  /*< private > */
+  GstVaapiDecoderProps parent_instance;
+  gboolean low_latency_mode;
+};
+
+/**
+ * GstVaapiDecoderPropsH264Class:
+ *
+ * gobject properties class for GstVaapiDecoderH264
+ */
+struct _GstVaapiDecoderPropsH264Class
+{
+  /*< private > */
+  GstVaapiDecoderPropsClass parent_class;
+};
+
+
+/* ------------------------------------------------------------------------- */
 /* --- H.264 Decoder                                                     --- */
 /* ------------------------------------------------------------------------- */
 
@@ -490,6 +528,7 @@ struct _GstVaapiDecoderH264Private
   GstVaapiFrameStore **prev_ref_frames;
   GstVaapiFrameStore **prev_frames;
   guint prev_frames_alloc;
+  gboolean low_latency_mode;
   GstVaapiFrameStore **dpb;
   guint dpb_count;
   guint dpb_size;
@@ -1339,6 +1378,50 @@ gst_vaapi_decoder_h264_reset (GstVaapiDecoder * base_decoder)
   return GST_VAAPI_DECODER_STATUS_SUCCESS;
 }
 
+static void
+gst_vaapi_decoder_props_h264_init (GstVaapiDecoderPropsH264 * props)
+{
+  props->low_latency_mode = DEFAULT_LOW_LATENCY;
+}
+
+static gboolean
+gst_vaapi_decoder_props_h264_set_property (GstVaapiDecoderProps * props,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstVaapiDecoderPropsH264 *decoder_props = (GstVaapiDecoderPropsH264 *) props;
+  gboolean retval = TRUE;
+
+  switch (prop_id) {
+    case PROP_LOW_LATENCY:
+      decoder_props->low_latency_mode = g_value_get_boolean (value);
+      break;
+    default:
+      retval = FALSE;
+      break;
+  }
+
+  return retval;
+}
+
+static gboolean
+gst_vaapi_decoder_props_h264_get_property (GstVaapiDecoderProps * props,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstVaapiDecoderPropsH264 *decoder_props = (GstVaapiDecoderPropsH264 *) props;
+  gboolean retval = TRUE;
+
+  switch (prop_id) {
+    case PROP_LOW_LATENCY:
+      g_value_set_boolean (value, decoder_props->low_latency_mode);
+      break;
+    default:
+      retval = FALSE;
+      break;
+  }
+
+  return retval;
+}
+
 /* Activates the supplied PPS */
 static GstH264PPS *
 ensure_pps (GstVaapiDecoderH264 * decoder, GstH264PPS * pps)
@@ -1725,9 +1808,10 @@ decode_current_picture (GstVaapiDecoderH264 * decoder)
     goto error;
 
   GST_DEBUG ("added %d to dpb", picture->base.poc);
-  /* TODO: only call the following if we're in optional
-     'low-latency' mode? */
-  send_ready_frames (decoder);
+
+  if (priv->low_latency_mode) {
+    send_ready_frames (decoder);
+  }
 
   gst_vaapi_picture_replace (&priv->current_picture, NULL);
   return GST_VAAPI_DECODER_STATUS_SUCCESS;
@@ -4801,10 +4885,68 @@ gst_vaapi_decoder_h264_set_alignment (GstVaapiDecoderH264 * decoder,
   decoder->priv.stream_alignment = alignment;
 }
 
+static void
+gst_vaapi_decoder_props_h264_class_init (GstVaapiDecoderPropsH264Class * klass)
+{
+  GstVaapiMiniObjectClass *const object_class =
+      GST_VAAPI_MINI_OBJECT_CLASS (klass);
+  GstVaapiDecoderPropsClass *const props_class =
+      GST_VAAPI_DECODER_PROPS_CLASS (klass);
+
+  object_class->size = sizeof (GstVaapiDecoderPropsH264);
+  object_class->finalize = NULL;
+
+  props_class->set_property = gst_vaapi_decoder_props_h264_set_property;
+  props_class->get_property = gst_vaapi_decoder_props_h264_get_property;
+}
+
+static inline const GstVaapiDecoderPropsClass *
+gst_vaapi_decoder_props_h264_class (void)
+{
+  static GstVaapiDecoderPropsH264Class g_class;
+  static gsize g_class_init = FALSE;
+
+  if (g_once_init_enter (&g_class_init)) {
+    gst_vaapi_decoder_props_h264_class_init (&g_class);
+    g_once_init_leave (&g_class_init, TRUE);
+  }
+  return GST_VAAPI_DECODER_PROPS_CLASS (&g_class);
+}
+
+static GstVaapiDecoderPropsH264 *
+gst_vaapi_decoder_props_h264_new (void)
+{
+  GstVaapiDecoderPropsH264 *props = (GstVaapiDecoderPropsH264 *)
+      gst_vaapi_mini_object_new (GST_VAAPI_MINI_OBJECT_CLASS
+      (gst_vaapi_decoder_props_h264_class ()));
+  gst_vaapi_decoder_props_h264_init (props);
+  return props;
+}
+
+GstVaapiDecoderPropsConstructor
+gst_vaapi_decoder_h264_install_properties (GObjectClass * object_class)
+{
+  g_object_class_install_property (object_class, PROP_LOW_LATENCY,
+      g_param_spec_boolean ("low-latency", "Low latency",
+          "Enable low-latency mode, where decoded frames are released"
+          " downstream as soon as possible.  For some video sources"
+          " (particularly those that fail to set certain optional VUI header"
+          " fields) this can avoid a display delay of up to 16 frames. "
+          "However, this mode is not strictly compliant to the spec, and "
+          "can result in dropped frames at the beginning of streams that "
+          "use unusual GOP structures, such as \"IBB...\"",
+          DEFAULT_LOW_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  // return ptr to GstVaapiDecoderPropsH264 creation function
+  return (GstVaapiDecoderPropsConstructor) gst_vaapi_decoder_props_h264_new;
+}
+
 /**
  * gst_vaapi_decoder_h264_new:
  * @display: a #GstVaapiDisplay
  * @caps: a #GstCaps holding codec information
+ * @props: a #GstVaapiDecoderPropsH264 object holding H264 decoder properties.
+ *         Can be NULL to use default property values.
  *
  * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
  * hold extra information like codec-data and pictured coded size.
@@ -4812,7 +4954,20 @@ gst_vaapi_decoder_h264_set_alignment (GstVaapiDecoderH264 * decoder,
  * Return value: the newly allocated #GstVaapiDecoder object
  */
 GstVaapiDecoder *
-gst_vaapi_decoder_h264_new (GstVaapiDisplay * display, GstCaps * caps)
-{
-  return gst_vaapi_decoder_new (gst_vaapi_decoder_h264_class (), display, caps);
+gst_vaapi_decoder_h264_new (GstVaapiDisplay * display, GstCaps * caps,
+    GstVaapiDecoderProps * props)
+{
+  GstVaapiDecoderH264 *decoder = (GstVaapiDecoderH264 *)
+      gst_vaapi_decoder_new (gst_vaapi_decoder_h264_class (), display, caps);
+
+  if (props != NULL) {
+    if (GST_VAAPI_MINI_OBJECT_GET_CLASS (props) ==
+        gst_vaapi_decoder_props_h264_class ()) {
+      GstVaapiDecoderPropsH264 *propsh264 = (GstVaapiDecoderPropsH264 *)
+          props;
+      decoder->priv.low_latency_mode = propsh264->low_latency_mode;
+    }
+  }
+
+  return GST_VAAPI_DECODER (decoder);
 }
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h264.h b/gst-libs/gst/vaapi/gstvaapidecoder_h264.h
index f9949dd..4a433d9 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder_h264.h
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_h264.h
@@ -30,6 +30,7 @@ G_BEGIN_DECLS
 #define GST_VAAPI_DECODER_H264(decoder) \
     ((GstVaapiDecoderH264 *)(decoder))
 
+typedef struct _GstVaapiDecoderPropsH264        GstVaapiDecoderPropsH264;
 typedef struct _GstVaapiDecoderH264             GstVaapiDecoderH264;
 
 /**
@@ -49,7 +50,13 @@ typedef enum {
 } GstVaapiStreamAlignH264;
 
 GstVaapiDecoder *
-gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps);
+gst_vaapi_decoder_h264_new (GstVaapiDisplay *display, GstCaps *caps,
+        GstVaapiDecoderProps *props);
+
+typedef GstVaapiDecoderPropsH264 * (*GstVaapiDecoderPropsConstructorH264)();
+
+GstVaapiDecoderPropsConstructor
+gst_vaapi_decoder_h264_install_properties(GObjectClass * object_class);
 
 void
 gst_vaapi_decoder_h264_set_alignment(GstVaapiDecoderH264 *decoder,
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h
index c80db0f..5ded81b 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h
@@ -33,6 +33,49 @@
 
 G_BEGIN_DECLS
 
+
+#define GST_VAAPI_DECODER_PROPS_CAST(decoder) \
+    ((GstVaapiDecoderProps *)(decoder))
+
+#define GST_VAAPI_DECODER_PROPS_CLASS(klass) \
+    ((GstVaapiDecoderPropsClass *)(klass))
+
+#define GST_VAAPI_IS_DECODER_PROPS_CLASS(klass) \
+    ((klass) != NULL))
+
+#define GST_VAAPI_DECODER_PROPS_GET_CLASS(obj) \
+    GST_VAAPI_DECODER_PROPS_CLASS(GST_VAAPI_MINI_OBJECT_GET_CLASS(obj))
+
+typedef struct _GstVaapiDecoderPropsClass GstVaapiDecoderPropsClass;
+
+/**
+ * GstVaapiDecoder:
+ *
+ * A VA decoder props base instance.
+ */
+struct _GstVaapiDecoderProps
+{
+  /*< private >*/
+  GstVaapiMiniObject parent_instance;
+};
+
+/**
+ * GstVaapiDecoderPropsClass:
+ *
+ * A VA decoder props base class.
+ */
+struct _GstVaapiDecoderPropsClass
+{
+  /*< private >*/
+  GstVaapiMiniObjectClass parent_class;
+
+  gboolean (*set_property) (GstVaapiDecoderProps * props,
+      guint prop_id, const GValue * value, GParamSpec * pspec);
+  gboolean (*get_property) (GstVaapiDecoderProps * props,
+      guint prop_id, GValue * value, GParamSpec * pspec);
+};
+
+
 #define GST_VAAPI_DECODER_CAST(decoder) \
     ((GstVaapiDecoder *)(decoder))
 
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c
index 9492396..ffec641 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c
+++ b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c
@@ -2160,7 +2160,9 @@ ensure_misc_params (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
   GstVaapiEncMiscParam *misc = NULL;
   VAEncMiscParameterRateControl *rate_control;
+#if VA_CHECK_VERSION(0,39,1)
   guint num_roi;
+#endif
 
   /* HRD params */
   misc = GST_VAAPI_ENC_MISC_PARAM_NEW (HRD, encoder);
@@ -2207,9 +2209,9 @@ ensure_misc_params (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
   }
 
   /* region-of-interest params */
+#if VA_CHECK_VERSION(0,39,1)
   num_roi = base_encoder->roi_regions ?
       g_list_length (base_encoder->roi_regions) : 0;
-#if VA_CHECK_VERSION(0,39,1)
   if (num_roi > 0) {
     /* ROI(Region of Interest) params */
     VAEncMiscParameterBufferROI *roi_param;
diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c
index 1b31259..fa28947 100644
--- a/gst/vaapi/gstvaapidecode.c
+++ b/gst/vaapi/gstvaapidecode.c
@@ -103,31 +103,33 @@ struct _GstVaapiDecoderMap
   guint rank;
   const gchar *name;
   const gchar *caps_str;
+    GstVaapiDecoderPropsConstructor (*install_props) (GObjectClass *);
 };
 
 static const GstVaapiDecoderMap vaapi_decode_map[] = {
 #if USE_JPEG_DECODER
-  {GST_VAAPI_CODEC_JPEG, GST_RANK_MARGINAL, "jpeg", "image/jpeg"},
+  {GST_VAAPI_CODEC_JPEG, GST_RANK_MARGINAL, "jpeg", "image/jpeg", NULL},
 #endif
   {GST_VAAPI_CODEC_MPEG2, GST_RANK_PRIMARY, "mpeg2",
-      "video/mpeg, mpegversion=2, systemstream=(boolean)false"},
+      "video/mpeg, mpegversion=2, systemstream=(boolean)false", NULL},
   {GST_VAAPI_CODEC_MPEG4, GST_RANK_PRIMARY, "mpeg4",
-      "video/mpeg, mpegversion=4"},
-  {GST_VAAPI_CODEC_H263, GST_RANK_PRIMARY, "h263", "video/x-h263"},
-  {GST_VAAPI_CODEC_H264, GST_RANK_PRIMARY, "h264", "video/x-h264"},
+      "video/mpeg, mpegversion=4", NULL},
+  {GST_VAAPI_CODEC_H263, GST_RANK_PRIMARY, "h263", "video/x-h263", NULL},
+  {GST_VAAPI_CODEC_H264, GST_RANK_PRIMARY, "h264", "video/x-h264",
+      gst_vaapi_decoder_h264_install_properties},
   {GST_VAAPI_CODEC_VC1, GST_RANK_PRIMARY, "vc1",
-      "video/x-wmv, wmvversion=3, format={WMV3,WVC1}"},
+      "video/x-wmv, wmvversion=3, format={WMV3,WVC1}", NULL},
 #if USE_VP8_DECODER
-  {GST_VAAPI_CODEC_VP8, GST_RANK_PRIMARY, "vp8", "video/x-vp8"},
+  {GST_VAAPI_CODEC_VP8, GST_RANK_PRIMARY, "vp8", "video/x-vp8", NULL},
 #endif
 #if USE_VP9_DECODER
-  {GST_VAAPI_CODEC_VP9, GST_RANK_PRIMARY, "vp9", "video/x-vp9"},
+  {GST_VAAPI_CODEC_VP9, GST_RANK_PRIMARY, "vp9", "video/x-vp9", NULL},
 #endif
 #if USE_H265_DECODER
-  {GST_VAAPI_CODEC_H265, GST_RANK_PRIMARY, "h265", "video/x-h265"},
+  {GST_VAAPI_CODEC_H265, GST_RANK_PRIMARY, "h265", "video/x-h265", NULL},
 #endif
   {0 /* the rest */ , GST_RANK_PRIMARY + 1, NULL,
-      gst_vaapidecode_sink_caps_str},
+      gst_vaapidecode_sink_caps_str, NULL},
 };
 
 static GstElementClass *parent_class = NULL;
@@ -840,7 +842,8 @@ gst_vaapidecode_create (GstVaapiDecode * decode, GstCaps * caps)
       decode->decoder = gst_vaapi_decoder_mpeg4_new (dpy, caps);
       break;
     case GST_VAAPI_CODEC_H264:
-      decode->decoder = gst_vaapi_decoder_h264_new (dpy, caps);
+      decode->decoder = gst_vaapi_decoder_h264_new (dpy, caps,
+          decode->decoder_props);
 
       /* Set the stream buffer alignment for better optimizations */
       if (decode->decoder && caps) {
@@ -981,10 +984,48 @@ gst_vaapidecode_finalize (GObject * object)
   g_cond_clear (&decode->surface_ready);
   g_mutex_clear (&decode->surface_ready_mutex);
 
+  gst_vaapi_decoder_props_replace (&decode->decoder_props, NULL);
+
   gst_vaapi_plugin_base_finalize (GST_VAAPI_PLUGIN_BASE (object));
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static void
+gst_vaapidecode_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+  GstVaapiDecode *decode = GST_VAAPIDECODE (object);
+  gboolean property_found = FALSE;
+
+  if (decode->decoder_props) {
+    property_found =
+        gst_vaapi_decoder_props_set_property (decode->decoder_props, prop_id,
+        value, pspec);
+  }
+
+  if (!property_found) {
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+gst_vaapidecode_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstVaapiDecode *decode = (GstVaapiDecode *) object;
+  gboolean property_found = FALSE;
+
+  if (decode->decoder_props) {
+    property_found =
+        gst_vaapi_decoder_props_get_property (decode->decoder_props, prop_id,
+        value, pspec);
+  }
+
+  if (!property_found) {
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
 static gboolean
 gst_vaapidecode_open (GstVideoDecoder * vdec)
 {
@@ -1318,6 +1359,9 @@ gst_vaapidecode_class_init (GstVaapiDecodeClass * klass)
 
   gst_vaapi_plugin_base_class_init (GST_VAAPI_PLUGIN_BASE_CLASS (klass));
 
+  object_class->set_property = GST_DEBUG_FUNCPTR (gst_vaapidecode_set_property);
+  object_class->get_property = GST_DEBUG_FUNCPTR (gst_vaapidecode_get_property);
+
   object_class->finalize = gst_vaapidecode_finalize;
 
   vdec_class->open = GST_DEBUG_FUNCPTR (gst_vaapidecode_open);
@@ -1350,6 +1394,11 @@ gst_vaapidecode_class_init (GstVaapiDecodeClass * klass)
     description = g_strdup (GST_PLUGIN_DESC);
   }
 
+  /* optionally install class-specific properties */
+  if (map->install_props) {
+    klass->create_props = map->install_props (object_class);
+  }
+
   element_class->set_context = gst_vaapi_base_set_context;
   gst_element_class_set_static_metadata (element_class, longname,
       "Codec/Decoder/Video", description,
@@ -1377,9 +1426,15 @@ static void
 gst_vaapidecode_init (GstVaapiDecode * decode)
 {
   GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode);
+  GstVaapiDecodeClass *const klass = (GstVaapiDecodeClass *)
+      G_OBJECT_GET_CLASS (decode);
 
   gst_vaapi_plugin_base_init (GST_VAAPI_PLUGIN_BASE (decode), GST_CAT_DEFAULT);
 
+  if (klass->create_props) {
+    decode->decoder_props = klass->create_props ();
+  }
+
   g_mutex_init (&decode->surface_ready_mutex);
   g_cond_init (&decode->surface_ready);
 
diff --git a/gst/vaapi/gstvaapidecode.h b/gst/vaapi/gstvaapidecode.h
index 8c84190..067167a 100644
--- a/gst/vaapi/gstvaapidecode.h
+++ b/gst/vaapi/gstvaapidecode.h
@@ -42,6 +42,7 @@ struct _GstVaapiDecode {
     GstCaps            *sinkpad_caps;
     GstCaps            *srcpad_caps;
     GstVideoInfo        decoded_info;
+    GstVaapiDecoderProps *decoder_props;
     GstVaapiDecoder    *decoder;
     GMutex              surface_ready_mutex;
     GCond               surface_ready;
@@ -62,6 +63,7 @@ struct _GstVaapiDecode {
 struct _GstVaapiDecodeClass {
     /*< private >*/
     GstVaapiPluginBaseClass parent_class;
+    GstVaapiDecoderPropsConstructor create_props;
 };
 
 gboolean gst_vaapidecode_register (GstPlugin * plugin, GArray * decoders);
diff --git a/tests/decoder.c b/tests/decoder.c
index 6679cc1..db3bf1d 100644
--- a/tests/decoder.c
+++ b/tests/decoder.c
@@ -107,7 +107,7 @@ decoder_new (GstVaapiDisplay * display, const gchar * codec_name)
 
   switch (gst_vaapi_profile_get_codec (info.profile)) {
     case GST_VAAPI_CODEC_H264:
-      decoder = gst_vaapi_decoder_h264_new (display, caps);
+      decoder = gst_vaapi_decoder_h264_new (display, caps, NULL);
       break;
 #if USE_JPEG_DECODER
     case GST_VAAPI_CODEC_JPEG:
diff --git a/tests/simple-decoder.c b/tests/simple-decoder.c
index 52aab38..ef373c3 100644
--- a/tests/simple-decoder.c
+++ b/tests/simple-decoder.c
@@ -371,7 +371,7 @@ start_decoder (App * app)
   caps = caps_from_codec (app->codec);
   switch (app->codec) {
     case GST_VAAPI_CODEC_H264:
-      app->decoder = gst_vaapi_decoder_h264_new (app->display, caps);
+      app->decoder = gst_vaapi_decoder_h264_new (app->display, caps, NULL);
       break;
 #if USE_JPEG_DECODER
     case GST_VAAPI_CODEC_JPEG:
