static inline void
allocator_configure_image_info (GstVaapiDisplay * display,
    GstVaapiVideoAllocator * allocator)
{
  GstVaapiImage *image = NULL;
  const GstVideoInfo *vinfo;

  if (allocator->has_direct_rendering) {
    allocator->image_info = allocator->surface_info;
    return;
  }

  vinfo = &allocator->video_info;

  if (GST_VIDEO_INFO_FORMAT (vinfo) == GST_VIDEO_FORMAT_ENCODED)
    gst_video_info_set_format (&allocator->image_info, GST_VIDEO_FORMAT_I420,
        GST_VIDEO_INFO_WIDTH (vinfo), GST_VIDEO_INFO_HEIGHT (vinfo));
  else
      allocator->image_info = *vinfo;

  image = new_image (display, &allocator->image_info);
  if (!image)
    goto bail;
  if (!gst_vaapi_image_map (image))
    goto bail;

  gst_video_info_update_from_image (&allocator->image_info, image);
  gst_vaapi_image_unmap (image);

bail:
  if (image)
    gst_vaapi_object_unref (image);
}
Exemplo n.º 2
0
static gboolean
load_frame (App * app, GstVaapiImage * image)
{
  gboolean ret = FALSE;

  if (!gst_vaapi_image_map (image))
    return FALSE;

  ret = y4m_reader_load_image (app->parser, image);

  if (!gst_vaapi_image_unmap (image))
    return FALSE;

  return ret;
}
static inline void
allocator_configure_surface_info (GstVaapiDisplay * display,
    GstVaapiVideoAllocator * allocator)
{
  const GstVideoInfo *vinfo;
  GstVaapiSurface *surface = NULL;
  GstVaapiImage *image = NULL;
  gboolean updated;
  GstVideoFormat fmt;

  vinfo = &allocator->video_info;

  fmt = gst_vaapi_video_format_get_best_native (GST_VIDEO_INFO_FORMAT (vinfo));
  gst_video_info_set_format (&allocator->surface_info, fmt,
      GST_VIDEO_INFO_WIDTH (vinfo), GST_VIDEO_INFO_HEIGHT (vinfo));

  /* nothing to configure */
  if (USE_NATIVE_FORMATS ||
      GST_VIDEO_INFO_FORMAT (vinfo) == GST_VIDEO_FORMAT_ENCODED)
    return;

  surface = new_surface (display, vinfo);
  if (!surface)
    goto bail;
  image = gst_vaapi_surface_derive_image (surface);
  if (!image)
    goto bail;
  if (!gst_vaapi_image_map (image))
    goto bail;

  updated = gst_video_info_update_from_image (&allocator->surface_info, image);

  allocator->has_direct_rendering = !USE_NATIVE_FORMATS && updated &&
      (GST_VAAPI_IMAGE_FORMAT (image) == GST_VIDEO_INFO_FORMAT (vinfo));

  GST_INFO ("has direct-rendering for %s surfaces: %s",
      GST_VIDEO_INFO_FORMAT_STRING (&allocator->surface_info),
      allocator->has_direct_rendering ? "yes" : "no");

  gst_vaapi_image_unmap (image);

bail:
  if (surface)
    gst_vaapi_object_unref (surface);
  if (image)
    gst_vaapi_object_unref (image);
}
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;
}
static gpointer
gst_vaapi_video_memory_map (GstVaapiVideoMemory * mem, gsize maxsize,
    guint flags)
{
  gpointer data;

  g_return_val_if_fail (mem, NULL);
  g_return_val_if_fail (mem->meta, NULL);

  if (mem->map_count == 0) {
    switch (flags & GST_MAP_READWRITE) {
      case 0:
        // No flags set: return a GstVaapiSurfaceProxy
        gst_vaapi_surface_proxy_replace (&mem->proxy,
            gst_vaapi_video_meta_get_surface_proxy (mem->meta));
        if (!mem->proxy)
          goto error_no_surface_proxy;
        if (!ensure_surface_is_current (mem))
          goto error_no_current_surface;
        mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE;
        break;
      case GST_MAP_READ:
        // Only read flag set: return raw pixels
        if (!ensure_surface (mem))
          goto error_no_surface;
        if (!ensure_image (mem))
          goto error_no_image;
        if (!ensure_image_is_current (mem))
          goto error_no_current_image;
        if (!gst_vaapi_image_map (mem->image))
          goto error_map_image;
        mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_LINEAR;
        break;
      default:
        goto error_unsupported_map;
    }
  }

  switch (mem->map_type) {
    case GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE:
      if (!mem->proxy)
        goto error_no_surface_proxy;
      data = mem->proxy;
      break;
    case GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_LINEAR:
      if (!mem->image)
        goto error_no_image;
      data = get_image_data (mem->image);
      break;
    default:
      goto error_unsupported_map_type;
  }
  mem->map_count++;
  return data;

  /* ERRORS */
error_unsupported_map:
  GST_ERROR ("unsupported map flags (0x%x)", flags);
  return NULL;
error_unsupported_map_type:
  GST_ERROR ("unsupported map type (%d)", mem->map_type);
  return NULL;
error_no_surface_proxy:
  GST_ERROR ("failed to extract GstVaapiSurfaceProxy from video meta");
  return NULL;
error_no_surface:
  GST_ERROR ("failed to extract VA surface from video buffer");
  return NULL;
error_no_current_surface:
  GST_ERROR ("failed to make surface current");
  return NULL;
error_no_image:
  GST_ERROR ("failed to extract VA image from video buffer");
  return NULL;
error_no_current_image:
  GST_ERROR ("failed to make image current");
  return NULL;
error_map_image:
  GST_ERROR ("failed to map VA image");
  return NULL;
}
gboolean
gst_video_meta_map_vaapi_memory (GstVideoMeta * meta, guint plane,
    GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
{
  GstVaapiVideoMemory *const mem =
      GST_VAAPI_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));

  g_return_val_if_fail (mem, FALSE);
  g_return_val_if_fail (GST_VAAPI_IS_VIDEO_ALLOCATOR (mem->parent_instance.
          allocator), FALSE);
  g_return_val_if_fail (mem->meta, FALSE);

  if (mem->map_type && mem->map_type != GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR)
    goto error_incompatible_map;

  /* Map for writing */
  if (++mem->map_count == 1) {
    if (!ensure_surface (mem))
      goto error_ensure_surface;
    if (!ensure_image (mem))
      goto error_ensure_image;

    // Load VA image from surface
    if ((flags & GST_MAP_READ) && !ensure_image_is_current (mem))
      goto error_no_current_image;

    if (!gst_vaapi_image_map (mem->image))
      goto error_map_image;
    mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR;

    // Mark surface as dirty and expect updates from image
    if (flags & GST_MAP_WRITE)
      GST_VAAPI_VIDEO_MEMORY_FLAG_UNSET (mem,
          GST_VAAPI_VIDEO_MEMORY_FLAG_SURFACE_IS_CURRENT);
  }

  *data = gst_vaapi_image_get_plane (mem->image, plane);
  *stride = gst_vaapi_image_get_pitch (mem->image, plane);
  info->flags = flags;
  return TRUE;

  /* ERRORS */
error_incompatible_map:
  {
    GST_ERROR ("incompatible map type (%d)", mem->map_type);
    return FALSE;
  }
error_ensure_surface:
  {
    const GstVideoInfo *const vip = mem->surface_info;
    GST_ERROR ("failed to create %s surface of size %ux%u",
        GST_VIDEO_INFO_FORMAT_STRING (vip),
        GST_VIDEO_INFO_WIDTH (vip), GST_VIDEO_INFO_HEIGHT (vip));
    return FALSE;
  }
error_ensure_image:
  {
    const GstVideoInfo *const vip = mem->image_info;
    GST_ERROR ("failed to create %s image of size %ux%u",
        GST_VIDEO_INFO_FORMAT_STRING (vip),
        GST_VIDEO_INFO_WIDTH (vip), GST_VIDEO_INFO_HEIGHT (vip));
    return FALSE;
  }
error_map_image:
  {
    GST_ERROR ("failed to map image %" GST_VAAPI_ID_FORMAT,
        GST_VAAPI_ID_ARGS (gst_vaapi_image_get_id (mem->image)));
    return FALSE;
  }
error_no_current_image:
  {
    GST_ERROR ("failed to make image current");
    return FALSE;
  }
}