GstBuffer *
gst_vaapi_video_buffer_new_from_buffer (GstBuffer * buffer)
{
  GstVaapiVideoMeta *const meta = gst_buffer_get_vaapi_video_meta (buffer);

  return meta ? new_vbuffer (gst_vaapi_video_meta_ref (meta)) : NULL;
}
GstBuffer *
gst_vaapi_video_buffer_new (GstVaapiVideoMeta * meta)
{
  g_return_val_if_fail (meta != NULL, NULL);

  return new_vbuffer (gst_vaapi_video_meta_ref (meta));
}
GstMemory *
gst_vaapi_video_memory_new (GstAllocator * base_allocator,
    GstVaapiVideoMeta * meta)
{
  GstVaapiVideoAllocator *const allocator =
      GST_VAAPI_VIDEO_ALLOCATOR_CAST (base_allocator);
  const GstVideoInfo *vip;
  GstVaapiVideoMemory *mem;

  g_return_val_if_fail (GST_VAAPI_IS_VIDEO_ALLOCATOR (allocator), NULL);

  mem = g_slice_new (GstVaapiVideoMemory);
  if (!mem)
    return NULL;

  vip = &allocator->image_info;
  gst_memory_init (&mem->parent_instance, GST_MEMORY_FLAG_NO_SHARE,
      gst_object_ref (allocator), NULL, GST_VIDEO_INFO_SIZE (vip), 0,
      0, GST_VIDEO_INFO_SIZE (vip));

  mem->proxy = NULL;
  mem->surface_info = &allocator->surface_info;
  mem->surface = NULL;
  mem->image_info = &allocator->image_info;
  mem->image = NULL;
  mem->meta = meta ? gst_vaapi_video_meta_ref (meta) : NULL;
  mem->map_type = 0;
  mem->map_count = 0;
  mem->use_direct_rendering = allocator->has_direct_rendering;

  GST_VAAPI_VIDEO_MEMORY_FLAG_SET (mem,
      GST_VAAPI_VIDEO_MEMORY_FLAG_SURFACE_IS_CURRENT);
  return GST_MEMORY_CAST (mem);
}
void
gst_buffer_set_vaapi_video_meta (GstBuffer * buffer, GstVaapiVideoMeta * meta)
{
  GstMeta *m;

  g_return_if_fail (GST_IS_BUFFER (buffer));
  g_return_if_fail (GST_VAAPI_IS_VIDEO_META (meta));

  m = gst_buffer_add_meta (buffer, GST_VAAPI_VIDEO_META_INFO, NULL);
  if (m)
    GST_VAAPI_VIDEO_META_HOLDER (m)->meta = gst_vaapi_video_meta_ref (meta);
}
/**
 * gst_vaapi_video_meta_replace:
 * @old_meta_ptr: a pointer to a #GstVaapiVideoMeta
 * @new_meta: a #GstVaapiVideoMeta
 *
 * @new_meta. This means that @old_meta_ptr shall reference a valid
 * Atomically replaces the meta object held in @old_meta_ptr with
 * object. However, @new_meta can be NULL.
 */
void
gst_vaapi_video_meta_replace (GstVaapiVideoMeta ** old_meta_ptr,
    GstVaapiVideoMeta * new_meta)
{
  GstVaapiVideoMeta *old_meta;

  g_return_if_fail (old_meta_ptr != NULL);

  old_meta = g_atomic_pointer_get ((gpointer *) old_meta_ptr);

  if (old_meta == new_meta)
    return;

  if (new_meta)
    gst_vaapi_video_meta_ref (new_meta);

  while (!g_atomic_pointer_compare_and_exchange ((gpointer *) old_meta_ptr,
          old_meta, new_meta))
    old_meta = g_atomic_pointer_get ((gpointer *) old_meta_ptr);

  if (old_meta)
    gst_vaapi_video_meta_unref (old_meta);
}