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); }
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; } }