GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, GstAllocator * dmabuf_allocator) { GstV4l2MemoryGroup *group; gint i; g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL); group = gst_v4l2_allocator_alloc (allocator); if (group == NULL) return NULL; for (i = 0; i < group->n_mem; i++) { GstV4l2Memory *mem; GstMemory *dma_mem; gint dmafd; if (group->mem[i] == NULL) { struct v4l2_exportbuffer expbuf = { 0 }; expbuf.type = allocator->type; expbuf.index = group->buffer.index; expbuf.plane = i; expbuf.flags = O_CLOEXEC | O_RDWR; if (v4l2_ioctl (allocator->video_fd, VIDIOC_EXPBUF, &expbuf) < 0) goto expbuf_failed; GST_LOG_OBJECT (allocator, "exported DMABUF as fd %i plane %d", expbuf.fd, i); group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator), NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, NULL, expbuf.fd, group); } else { /* Take back the allocator reference */ gst_object_ref (allocator); } g_assert (gst_is_v4l2_memory (group->mem[i])); mem = (GstV4l2Memory *) group->mem[i]; if ((dmafd = dup (mem->dmafd)) < 0) goto dup_failed; dma_mem = gst_dmabuf_allocator_alloc (dmabuf_allocator, dmafd, mem->mem.maxsize); gst_mini_object_set_qdata (GST_MINI_OBJECT (dma_mem), GST_V4L2_MEMORY_QUARK, mem, (GDestroyNotify) gst_memory_unref); group->mem[i] = dma_mem; group->mems_allocated++; } gst_v4l2_allocator_reset_size (allocator, group); return group; expbuf_failed: { GST_ERROR_OBJECT (allocator, "Failed to export DMABUF: %s", g_strerror (errno)); goto cleanup; } dup_failed: { GST_ERROR_OBJECT (allocator, "Failed to dup DMABUF descriptor: %s", g_strerror (errno)); goto cleanup; } cleanup: { _cleanup_failed_alloc (allocator, group); return NULL; } }
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; } }