static GstStateChangeReturn
gst_vaapi_decode_bin_change_state (GstElement * element,
    GstStateChange transition)
{
  GstVaapiDecodeBin *vaapidecbin = GST_VAAPI_DECODE_BIN (element);
  GstStateChangeReturn ret;

  switch (transition) {
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (gst_vaapi_decode_bin_parent_class)->change_state
      (element, transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      if (!gst_vaapi_decode_bin_configure (vaapidecbin))
        return GST_STATE_CHANGE_FAILURE;
      break;
    default:
      break;
  }

  return ret;
}
static void
gst_vaapi_decode_bin_get_property (GObject * object,
    guint prop_id, GValue * value, GParamSpec * pspec)
{
  GstVaapiDecodeBin *vaapidecbin = GST_VAAPI_DECODE_BIN (object);

  switch (prop_id) {
    case PROP_MAX_SIZE_BYTES:
      g_value_set_uint (value, vaapidecbin->max_size_bytes);
      break;
    case PROP_MAX_SIZE_BUFFERS:
      g_value_set_uint (value, vaapidecbin->max_size_buffers);
      break;
    case PROP_MAX_SIZE_TIME:
      g_value_set_uint64 (value, vaapidecbin->max_size_time);
      break;
    case PROP_DEINTERLACE_METHOD:
      g_value_set_enum (value, vaapidecbin->deinterlace_method);
      break;
    case PROP_DISABLE_VPP:
      g_value_set_boolean (value, vaapidecbin->disable_vpp);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static void
gst_vaapi_decode_bin_set_property (GObject * object,
    guint prop_id, const GValue * value, GParamSpec * pspec)
{
  GstVaapiDecodeBin *vaapidecbin = GST_VAAPI_DECODE_BIN (object);

  switch (prop_id) {
    case PROP_MAX_SIZE_BYTES:
      vaapidecbin->max_size_bytes = g_value_get_uint (value);
      g_object_set (G_OBJECT (vaapidecbin->queue), "max-size-bytes",
          vaapidecbin->max_size_bytes, NULL);
      break;
    case PROP_MAX_SIZE_BUFFERS:
      vaapidecbin->max_size_buffers = g_value_get_uint (value);
      g_object_set (G_OBJECT (vaapidecbin->queue), "max-size-buffers",
          vaapidecbin->max_size_buffers, NULL);
      break;
    case PROP_MAX_SIZE_TIME:
      vaapidecbin->max_size_time = g_value_get_uint64 (value);
      g_object_set (G_OBJECT (vaapidecbin->queue), "max-size-time",
          vaapidecbin->max_size_time, NULL);
      break;
    case PROP_DEINTERLACE_METHOD:
      vaapidecbin->deinterlace_method = g_value_get_enum (value);
      if (vaapidecbin->postproc)
        g_object_set (G_OBJECT (vaapidecbin->postproc), "deinterlace-method",
            vaapidecbin->deinterlace_method, NULL);
      break;
    case PROP_DISABLE_VPP:
    {
      gboolean disable_vpp;

      disable_vpp = g_value_get_boolean (value);
      if (!disable_vpp && !vaapidecbin->has_vpp)
        GST_WARNING_OBJECT (vaapidecbin,
            "Cannot enable VPP since the VA driver does not support it");
      else
        vaapidecbin->disable_vpp = disable_vpp;

      /* @TODO: Add run-time disabling support */
      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static void
gst_vaapi_decode_bin_handle_message (GstBin * bin, GstMessage * message)
{
  GstVaapiDecodeBin *vaapidecbin = GST_VAAPI_DECODE_BIN (bin);
  GstMessageType type;
  GstContext *context = NULL;
  const gchar *context_type;
  GstVaapiDisplay *display = NULL;

  type = GST_MESSAGE_TYPE (message);
  if (type != GST_MESSAGE_HAVE_CONTEXT)
    goto bail;
  gst_message_parse_have_context (message, &context);
  if (!context)
    goto bail;
  context_type = gst_context_get_context_type (context);
  if (g_strcmp0 (context_type, GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME) != 0)
    goto bail;
  if (!gst_vaapi_video_context_get_display (context, &display))
    goto bail;

  vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display) ?
    HAS_VPP_YES : HAS_VPP_NO;

  /* the underlying VA driver implementation doesn't support video
   * post-processing, hence we have to disable it */
  if (vaapidecbin->has_vpp != HAS_VPP_YES) {
    GST_WARNING_OBJECT (vaapidecbin, "VA driver doesn't support VPP");
    if (!vaapidecbin->disable_vpp) {
      vaapidecbin->disable_vpp = TRUE;
      g_object_notify_by_pspec (G_OBJECT (vaapidecbin),
          properties[PROP_DISABLE_VPP]);
    }
  }

bail:
  if (display)
    gst_vaapi_display_unref (display);

  if (context)
    gst_context_unref (context);

  GST_BIN_CLASS (gst_vaapi_decode_bin_parent_class)->handle_message (bin,
      message);
}