/**
 * gst_vaapi_surface_new_with_format:
 * @display: a #GstVaapiDisplay
 * @format: the surface format
 * @width: the requested surface width
 * @height: the requested surface height
 *
 * Creates a new #GstVaapiSurface with the specified pixel format and
 * dimensions.
 *
 * Return value: the newly allocated #GstVaapiSurface object, or %NULL
 *   if creation of VA surface with explicit pixel format is not
 *   supported or failed.
 */
GstVaapiSurface *
gst_vaapi_surface_new_with_format (GstVaapiDisplay * display,
    GstVideoFormat format, guint width, guint height)
{
  GstVideoInfo vi;

  gst_video_info_set_format (&vi, format, width, height);
  return gst_vaapi_surface_new_full (display, &vi, 0);
}
GstAllocator *
gst_vaapi_dmabuf_allocator_new (GstVaapiDisplay * display,
    const GstVideoInfo * vip, guint flags)
{
  GstAllocator *allocator = NULL;
  GstVaapiSurface *surface = NULL;
  GstVaapiImage *image = NULL;
  GstVideoInfo alloc_info;

  g_return_val_if_fail (display != NULL, NULL);
  g_return_val_if_fail (vip != NULL, NULL);

  do {
    surface = gst_vaapi_surface_new_full (display, vip, flags);
    if (!surface)
      break;

    image = gst_vaapi_surface_derive_image (surface);
    if (!image || !gst_vaapi_image_map (image))
      break;

    gst_video_info_set_format (&alloc_info, GST_VIDEO_INFO_FORMAT (vip),
        GST_VIDEO_INFO_WIDTH (vip), GST_VIDEO_INFO_HEIGHT (vip));
    gst_video_info_update_from_image (&alloc_info, image);
    gst_vaapi_image_unmap (image);

    allocator = gst_dmabuf_allocator_new ();
    if (!allocator)
      break;
    gst_allocator_set_vaapi_video_info (allocator, &alloc_info, flags);
  } while (0);

  gst_vaapi_object_replace (&image, NULL);
  gst_vaapi_object_replace (&surface, NULL);
  return allocator;
}
GstMemory *
gst_vaapi_dmabuf_memory_new (GstAllocator * allocator, GstVaapiVideoMeta * meta)
{
  GstMemory *mem;
  GstVaapiDisplay *display;
  GstVaapiSurface *surface;
  GstVaapiSurfaceProxy *proxy;
  GstVaapiBufferProxy *dmabuf_proxy;
  gint dmabuf_fd;
  const GstVideoInfo *vip;
  guint flags;

  g_return_val_if_fail (allocator != NULL, NULL);
  g_return_val_if_fail (meta != NULL, NULL);

  vip = gst_allocator_get_vaapi_video_info (allocator, &flags);
  if (!vip)
    return NULL;

  display = gst_vaapi_video_meta_get_display (meta);
  if (!meta)
    return NULL;

  surface = gst_vaapi_surface_new_full (display, vip, flags);
  if (!surface)
    goto error_create_surface;

  proxy = gst_vaapi_surface_proxy_new (surface);
  if (!proxy)
    goto error_create_surface_proxy;

  dmabuf_proxy = gst_vaapi_surface_get_dma_buf_handle (surface);
  gst_vaapi_object_unref (surface);
  if (!dmabuf_proxy)
    goto error_create_dmabuf_proxy;

  gst_vaapi_video_meta_set_surface_proxy (meta, proxy);
  gst_vaapi_surface_proxy_unref (proxy);

  dmabuf_fd = gst_vaapi_buffer_proxy_get_handle (dmabuf_proxy);
  if (dmabuf_fd < 0 || (dmabuf_fd = dup (dmabuf_fd)) < 0)
    goto error_create_dmabuf_handle;

  mem = gst_dmabuf_allocator_alloc (allocator, dmabuf_fd,
      gst_vaapi_buffer_proxy_get_size (dmabuf_proxy));
  if (!mem)
    goto error_create_dmabuf_memory;

  gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem),
      GST_VAAPI_BUFFER_PROXY_QUARK, dmabuf_proxy,
      (GDestroyNotify) gst_vaapi_buffer_proxy_unref);
  return mem;

  /* ERRORS */
error_create_surface:
  {
    GST_ERROR ("failed to create VA surface (format:%s size:%ux%u)",
        gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (vip)),
        GST_VIDEO_INFO_WIDTH (vip), GST_VIDEO_INFO_HEIGHT (vip));
    return NULL;
  }
error_create_surface_proxy:
  {
    GST_ERROR ("failed to create VA surface proxy");
    gst_vaapi_object_unref (surface);
    return NULL;
  }
error_create_dmabuf_proxy:
  {
    GST_ERROR ("failed to export VA surface to DMABUF");
    gst_vaapi_surface_proxy_unref (proxy);
    return NULL;
  }
error_create_dmabuf_handle:
  {
    GST_ERROR ("failed to duplicate DMABUF handle");
    gst_vaapi_buffer_proxy_unref (dmabuf_proxy);
    return NULL;
  }
error_create_dmabuf_memory:
  {
    GST_ERROR ("failed to create DMABUF memory");
    gst_vaapi_buffer_proxy_unref (dmabuf_proxy);
    return NULL;
  }
}