static gboolean gst_imx_v4l2_buffer_pool_set_config(GstBufferPool *bpool, GstStructure *config) { GstImxV4l2BufferPool *pool = GST_IMX_V4L2_BUFFER_POOL(bpool); GstVideoInfo info; GstCaps *caps; gsize size; guint min, max; struct v4l2_requestbuffers req; if (!gst_buffer_pool_config_get_params(config, &caps, &size, &min, &max)) { GST_ERROR_OBJECT(pool, "pool configuration invalid"); return FALSE; } if (caps == NULL) { GST_ERROR_OBJECT(pool, "configuration contains no caps"); return FALSE; } if (!gst_video_info_from_caps(&info, caps)) { GST_ERROR_OBJECT(pool, "caps cannot be parsed for video info"); return FALSE; } GST_DEBUG_OBJECT(pool, "set_config: size %d, min %d, max %d", size, min, max); memset(&req, 0, sizeof(req)); req.count = min; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (ioctl(GST_IMX_FD_OBJECT_GET_FD(pool->fd_obj_v4l), VIDIOC_REQBUFS, &req) < 0) { GST_ERROR_OBJECT(pool, "VIDIOC_REQBUFS failed: %s", g_strerror(errno)); return FALSE; } if (req.count != min) { min = req.count; GST_WARNING_OBJECT(pool, "using %u buffers", min); } pool->num_buffers = min; pool->video_info = info; pool->add_videometa = gst_buffer_pool_config_has_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META); gst_buffer_pool_config_set_params(config, caps, size, min, max); return GST_BUFFER_POOL_CLASS(gst_imx_v4l2_buffer_pool_parent_class)->set_config(bpool, config); }
/* XXXX: GStreamer 1.2 doesn't check, in gst_buffer_pool_set_config() if the config option is already set */ static inline gboolean gst_vaapi_plugin_base_set_pool_config (GstBufferPool * pool, const gchar * option) { GstStructure *config; config = gst_buffer_pool_get_config (pool); if (!gst_buffer_pool_config_has_option (config, option)) { gst_buffer_pool_config_add_option (config, option); return gst_buffer_pool_set_config (pool, config); } return TRUE; }
static gboolean gst_egl_image_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) { GstEGLImageBufferPool *pool = GST_EGL_IMAGE_BUFFER_POOL (bpool); GstCaps *caps; GstVideoInfo info; if (pool->allocator) gst_object_unref (pool->allocator); pool->allocator = NULL; if (!GST_BUFFER_POOL_CLASS (gst_egl_image_buffer_pool_parent_class)->set_config (bpool, config)) return FALSE; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL) || !caps) return FALSE; if (!gst_video_info_from_caps (&info, caps)) return FALSE; if (!gst_buffer_pool_config_get_allocator (config, &pool->allocator, &pool->params)) return FALSE; if (pool->allocator) gst_object_ref (pool->allocator); pool->add_metavideo = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); pool->want_eglimage = (pool->allocator && g_strcmp0 (pool->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0); pool->info = info; return TRUE; }
static gboolean gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstGLBufferPool *glpool = GST_GL_BUFFER_POOL_CAST (pool); GstGLBufferPoolPrivate *priv = glpool->priv; GstVideoInfo info; GstCaps *caps = NULL; guint min_buffers, max_buffers; guint max_align, n; GstAllocator *allocator = NULL; GstAllocationParams alloc_params; GstGLTextureTarget tex_target; gboolean ret = TRUE; gint p; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, &max_buffers)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); if (!gst_buffer_pool_config_get_allocator (config, &allocator, &alloc_params)) goto wrong_config; gst_caps_replace (&priv->caps, caps); if (priv->allocator) gst_object_unref (priv->allocator); if (allocator) { if (!GST_IS_GL_MEMORY_ALLOCATOR (allocator)) { gst_object_unref (allocator); goto wrong_allocator; } else { priv->allocator = gst_object_ref (allocator); } } else { priv->allocator = GST_ALLOCATOR (gst_gl_memory_allocator_get_default (glpool->context)); g_assert (priv->allocator); } priv->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); priv->add_glsyncmeta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); if (priv->gl_params) gst_gl_allocation_params_free ((GstGLAllocationParams *) priv->gl_params); priv->gl_params = (GstGLVideoAllocationParams *) gst_buffer_pool_config_get_gl_allocation_params (config); if (!priv->gl_params) priv->gl_params = gst_gl_video_allocation_params_new (glpool->context, &alloc_params, &info, -1, NULL, 0, 0); max_align = alloc_params.align; if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { priv->add_videometa = TRUE; gst_buffer_pool_config_get_video_alignment (config, priv->gl_params->valign); for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n) max_align |= priv->gl_params->valign->stride_align[n]; for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n) priv->gl_params->valign->stride_align[n] = max_align; gst_video_info_align (priv->gl_params->v_info, priv->gl_params->valign); gst_buffer_pool_config_set_video_alignment (config, priv->gl_params->valign); } if (alloc_params.align < max_align) { GST_WARNING_OBJECT (pool, "allocation params alignment %u is smaller " "than the max specified video stride alignment %u, fixing", (guint) alloc_params.align, max_align); alloc_params.align = max_align; gst_buffer_pool_config_set_allocator (config, allocator, &alloc_params); if (priv->gl_params->parent.alloc_params) gst_allocation_params_free (priv->gl_params->parent.alloc_params); priv->gl_params->parent.alloc_params = gst_allocation_params_copy (&alloc_params); } { GstStructure *s = gst_caps_get_structure (caps, 0); const gchar *target_str = gst_structure_get_string (s, "texture-target"); gboolean multiple_texture_targets = FALSE; tex_target = priv->gl_params->target; if (target_str) tex_target = gst_gl_texture_target_from_string (target_str); if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_2D) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_2D; } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_RECTANGLE) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_RECTANGLE; } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES)) { if (tex_target && tex_target != GST_GL_TEXTURE_TARGET_EXTERNAL_OES) multiple_texture_targets = TRUE; tex_target = GST_GL_TEXTURE_TARGET_EXTERNAL_OES; } if (!tex_target) tex_target = GST_GL_TEXTURE_TARGET_2D; if (multiple_texture_targets) { GST_WARNING_OBJECT (pool, "Multiple texture targets configured either " "through caps or buffer pool options"); ret = FALSE; } priv->gl_params->target = tex_target; } /* Recalulate the size and offset as we don't add padding between planes. */ priv->gl_params->v_info->size = 0; for (p = 0; p < GST_VIDEO_INFO_N_PLANES (priv->gl_params->v_info); p++) { priv->gl_params->v_info->offset[p] = priv->gl_params->v_info->size; priv->gl_params->v_info->size += gst_gl_get_plane_data_size (priv->gl_params->v_info, priv->gl_params->valign, p); } gst_buffer_pool_config_set_params (config, caps, priv->gl_params->v_info->size, min_buffers, max_buffers); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config) && ret; /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } wrong_allocator: { GST_WARNING_OBJECT (pool, "Incorrect allocator type for this pool"); return FALSE; } }
static gboolean gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) { GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool); GstV4l2Object *obj = pool->obj; GstCaps *caps; guint size, min_buffers, max_buffers, num_buffers, copy_threshold; GstAllocator *allocator; GstAllocationParams params; struct v4l2_requestbuffers breq; GST_DEBUG_OBJECT (pool, "set config"); pool->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); if (!pool->add_videometa) { gint stride; /* we don't have video metadata, see if the strides are compatible */ stride = GST_VIDEO_INFO_PLANE_STRIDE (&obj->info, 0); GST_DEBUG_OBJECT (pool, "no videometadata, checking strides %d and %u", stride, obj->bytesperline); if (stride != obj->bytesperline) goto missing_video_api; } /* parse the config and keep around */ if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) goto wrong_config; if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms)) goto wrong_config; GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config); switch (obj->mode) { case GST_V4L2_IO_RW: /* we preallocate 1 buffer, this value also instructs the latency * calculation to have 1 frame latency max */ num_buffers = 1; copy_threshold = 0; break; case GST_V4L2_IO_MMAP: { /* request a reasonable number of buffers when no max specified. We will * copy when we run out of buffers */ if (max_buffers == 0) num_buffers = 4; else num_buffers = max_buffers; /* first, lets request buffers, and see how many we can get: */ GST_DEBUG_OBJECT (pool, "starting, requesting %d MMAP buffers", num_buffers); memset (&breq, 0, sizeof (struct v4l2_requestbuffers)); breq.type = obj->type; breq.count = num_buffers; breq.memory = V4L2_MEMORY_MMAP; if (v4l2_ioctl (pool->video_fd, VIDIOC_REQBUFS, &breq) < 0) goto reqbufs_failed; GST_LOG_OBJECT (pool, " count: %u", breq.count); GST_LOG_OBJECT (pool, " type: %d", breq.type); GST_LOG_OBJECT (pool, " memory: %d", breq.memory); if (breq.count < GST_V4L2_MIN_BUFFERS) goto no_buffers; if (num_buffers != breq.count) { GST_WARNING_OBJECT (pool, "using %u buffers instead", breq.count); num_buffers = breq.count; } /* update min buffers with the amount of buffers we just reserved. We need * to configure this value in the bufferpool so that the default start * implementation calls our allocate function */ min_buffers = breq.count; if (max_buffers == 0 || num_buffers < max_buffers) { /* if we are asked to provide more buffers than we have allocated, start * copying buffers when we only have 2 buffers left in the pool */ copy_threshold = 2; } else { /* we are certain that we have enough buffers so we don't need to * copy */ copy_threshold = 0; } break; } case GST_V4L2_IO_USERPTR: default: num_buffers = 0; copy_threshold = 0; g_assert_not_reached (); break; } pool->size = size; pool->num_buffers = num_buffers; pool->copy_threshold = copy_threshold; if (pool->allocator) gst_allocator_unref (pool->allocator); if ((pool->allocator = allocator)) gst_allocator_ref (allocator); pool->params = params; gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config); /* ERRORS */ missing_video_api: { GST_ERROR_OBJECT (pool, "missing GstMetaVideo API in config, " "default stride: %d, wanted stride %u", GST_VIDEO_INFO_PLANE_STRIDE (&obj->info, 0), obj->bytesperline); return FALSE; } wrong_config: { GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config); return FALSE; } reqbufs_failed: { GST_ERROR_OBJECT (pool, "error requesting %d buffers: %s", num_buffers, g_strerror (errno)); return FALSE; } no_buffers: { GST_ERROR_OBJECT (pool, "we received %d from device '%s', we want at least %d", breq.count, obj->videodev, GST_V4L2_MIN_BUFFERS); return FALSE; } }
static gboolean xvimage_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstXvImageBufferPool *xvpool = GST_XVIMAGE_BUFFER_POOL_CAST (pool); GstVideoInfo info; GstCaps *caps; guint size, min_buffers, max_buffers; GstXvContext *context; if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); context = gst_xvimage_allocator_peek_context (xvpool->allocator); xvpool->im_format = gst_xvcontext_get_format_from_info (context, &info); if (xvpool->im_format == -1) goto unknown_format; if (xvpool->caps) gst_caps_unref (xvpool->caps); xvpool->caps = gst_caps_ref (caps); /* enable metadata based on config of the pool */ xvpool->add_metavideo = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); /* parse extra alignment info */ xvpool->need_alignment = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); if (xvpool->need_alignment) { gst_buffer_pool_config_get_video_alignment (config, &xvpool->align); GST_LOG_OBJECT (pool, "padding %u-%ux%u-%u", xvpool->align.padding_top, xvpool->align.padding_left, xvpool->align.padding_left, xvpool->align.padding_bottom); /* do padding and alignment */ gst_video_info_align (&info, &xvpool->align); gst_buffer_pool_config_set_video_alignment (config, &xvpool->align); /* we need the video metadata too now */ xvpool->add_metavideo = TRUE; } else { gst_video_alignment_reset (&xvpool->align); } /* add the padding */ xvpool->padded_width = GST_VIDEO_INFO_WIDTH (&info) + xvpool->align.padding_left + xvpool->align.padding_right; xvpool->padded_height = GST_VIDEO_INFO_HEIGHT (&info) + xvpool->align.padding_top + xvpool->align.padding_bottom; xvpool->info = info; xvpool->crop.x = xvpool->align.padding_left; xvpool->crop.y = xvpool->align.padding_top; xvpool->crop.w = xvpool->info.width; xvpool->crop.h = xvpool->info.height; gst_buffer_pool_config_set_params (config, caps, info.size, min_buffers, max_buffers); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config); /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } unknown_format: { GST_WARNING_OBJECT (pool, "failed to get format from caps %" GST_PTR_FORMAT, caps); return FALSE; } }
static gboolean gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstGLBufferPool *glpool = GST_GL_BUFFER_POOL_CAST (pool); GstGLBufferPoolPrivate *priv = glpool->priv; GstVideoInfo info; GstCaps *caps = NULL; guint min_buffers, max_buffers; GstAllocator *allocator = NULL; GstAllocationParams alloc_params; gboolean reset = TRUE; gint p; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, &max_buffers)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); if (!gst_buffer_pool_config_get_allocator (config, &allocator, &alloc_params)) goto wrong_config; if (priv->allocator) gst_object_unref (priv->allocator); if (!allocator) { gst_gl_memory_init (); priv->allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR); } else { priv->allocator = gst_object_ref (allocator); } priv->params = alloc_params; priv->im_format = GST_VIDEO_INFO_FORMAT (&info); if (priv->im_format == -1) goto unknown_format; if (priv->caps) reset = !gst_caps_is_equal (priv->caps, caps); gst_caps_replace (&priv->caps, caps); priv->info = info; priv->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); priv->add_uploadmeta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META); priv->add_glsyncmeta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); #if GST_GL_HAVE_PLATFORM_EGL g_assert (priv->allocator != NULL); priv->want_eglimage = (g_strcmp0 (priv->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0); #else priv->want_eglimage = FALSE; #endif if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { priv->add_videometa = TRUE; gst_buffer_pool_config_get_video_alignment (config, &priv->valign); gst_video_info_align (&priv->info, &priv->valign); gst_buffer_pool_config_set_video_alignment (config, &priv->valign); } else { gst_video_alignment_reset (&priv->valign); } if (reset) { if (glpool->upload) gst_object_unref (glpool->upload); glpool->upload = gst_gl_upload_meta_new (glpool->context); } /* Recalulate the size as we don't add padding between planes. */ priv->info.size = 0; for (p = 0; p < GST_VIDEO_INFO_N_PLANES (&priv->info); p++) { priv->info.size += gst_gl_get_plane_data_size (&priv->info, &priv->valign, p); } gst_buffer_pool_config_set_params (config, caps, priv->info.size, min_buffers, max_buffers); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config); /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } unknown_format: { GST_WARNING_OBJECT (glpool, "failed to get format from caps %" GST_PTR_FORMAT, caps); GST_ELEMENT_ERROR (glpool, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels", priv->info.width, priv->info.height), ("Invalid input caps %" GST_PTR_FORMAT, caps)); return FALSE; } }
static gboolean gst_gl_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstGLBufferPool *glpool = GST_GL_BUFFER_POOL_CAST (pool); GstGLBufferPoolPrivate *priv = glpool->priv; GstVideoInfo info; GstCaps *caps = NULL; guint min_buffers, max_buffers; guint max_align, n; GstAllocator *allocator = NULL; GstAllocationParams alloc_params; gboolean reset = TRUE, ret = TRUE; gint p; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, &max_buffers)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); if (!gst_buffer_pool_config_get_allocator (config, &allocator, &alloc_params)) goto wrong_config; if (priv->allocator) gst_object_unref (priv->allocator); if (!allocator) { gst_gl_memory_init (); priv->allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR); } else { priv->allocator = gst_object_ref (allocator); } priv->params = alloc_params; priv->im_format = GST_VIDEO_INFO_FORMAT (&info); if (priv->im_format == -1) goto unknown_format; if (priv->caps) reset = !gst_caps_is_equal (priv->caps, caps); gst_caps_replace (&priv->caps, caps); priv->info = info; priv->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); priv->add_uploadmeta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META); priv->add_glsyncmeta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); #if GST_GL_HAVE_PLATFORM_EGL g_assert (priv->allocator != NULL); priv->want_eglimage = (g_strcmp0 (priv->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0); #else priv->want_eglimage = FALSE; #endif max_align = alloc_params.align; if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { priv->add_videometa = TRUE; gst_buffer_pool_config_get_video_alignment (config, &priv->valign); for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n) max_align |= priv->valign.stride_align[n]; for (n = 0; n < GST_VIDEO_MAX_PLANES; ++n) priv->valign.stride_align[n] = max_align; gst_video_info_align (&priv->info, &priv->valign); gst_buffer_pool_config_set_video_alignment (config, &priv->valign); } else { gst_video_alignment_reset (&priv->valign); } if (alloc_params.align < max_align) { GST_WARNING_OBJECT (pool, "allocation params alignment %u is smaller " "than the max specified video stride alignment %u, fixing", (guint) alloc_params.align, max_align); alloc_params.align = max_align; gst_buffer_pool_config_set_allocator (config, allocator, &alloc_params); priv->params = alloc_params; } if (reset) { if (glpool->upload) gst_object_unref (glpool->upload); glpool->upload = gst_gl_upload_meta_new (glpool->context); } priv->tex_target = 0; { GstStructure *s = gst_caps_get_structure (caps, 0); const gchar *target_str = gst_structure_get_string (s, "texture-target"); gboolean multiple_texture_targets = FALSE; if (target_str) priv->tex_target = gst_gl_texture_target_from_string (target_str); if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_2D)) { if (priv->tex_target) multiple_texture_targets = TRUE; priv->tex_target = GST_GL_TEXTURE_TARGET_2D; } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_RECTANGLE)) { if (priv->tex_target) multiple_texture_targets = TRUE; priv->tex_target = GST_GL_TEXTURE_TARGET_RECTANGLE; } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_GL_TEXTURE_TARGET_EXTERNAL_OES)) { if (priv->tex_target) multiple_texture_targets = TRUE; priv->tex_target = GST_GL_TEXTURE_TARGET_EXTERNAL_OES; } if (!priv->tex_target) priv->tex_target = GST_GL_TEXTURE_TARGET_2D; if (multiple_texture_targets) { GST_WARNING_OBJECT (pool, "Multiple texture targets configured either " "through caps or buffer pool options"); ret = FALSE; } } /* Recalulate the size and offset as we don't add padding between planes. */ priv->info.size = 0; for (p = 0; p < GST_VIDEO_INFO_N_PLANES (&priv->info); p++) { priv->info.offset[p] = priv->info.size; priv->info.size += gst_gl_get_plane_data_size (&priv->info, &priv->valign, p); } gst_buffer_pool_config_set_params (config, caps, priv->info.size, min_buffers, max_buffers); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config) && ret; /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } unknown_format: { GST_WARNING_OBJECT (glpool, "failed to get format from caps %" GST_PTR_FORMAT, caps); GST_ELEMENT_ERROR (glpool, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels", priv->info.width, priv->info.height), ("Invalid input caps %" GST_PTR_FORMAT, caps)); return FALSE; } }
static gboolean gst_vaapi_video_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstVaapiVideoBufferPoolPrivate *const priv = GST_VAAPI_VIDEO_BUFFER_POOL (pool)->priv; GstCaps *caps; GstVideoInfo new_allocation_vinfo; const GstVideoInfo *allocator_vinfo; const GstVideoInfo *negotiated_vinfo; GstVideoAlignment align; GstAllocator *allocator; gboolean ret, updated = FALSE; guint size, min_buffers, max_buffers; guint surface_alloc_flags; GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config); caps = NULL; if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) goto error_invalid_config; if (!caps) goto error_no_caps; if (!gst_video_info_from_caps (&new_allocation_vinfo, caps)) goto error_invalid_caps; allocator = NULL; if (!gst_buffer_pool_config_get_allocator (config, &allocator, NULL)) goto error_invalid_allocator; /* it is a valid allocator? */ if (allocator && (g_strcmp0 (allocator->mem_type, GST_VAAPI_VIDEO_MEMORY_NAME) != 0 && g_strcmp0 (allocator->mem_type, GST_VAAPI_DMABUF_ALLOCATOR_NAME) != 0)) allocator = NULL; /* get the allocator properties */ if (allocator) { priv->use_dmabuf_memory = gst_vaapi_is_dmabuf_allocator (allocator); negotiated_vinfo = gst_allocator_get_vaapi_negotiated_video_info (allocator); allocator_vinfo = gst_allocator_get_vaapi_video_info (allocator, &surface_alloc_flags); } else { priv->use_dmabuf_memory = FALSE; negotiated_vinfo = NULL; allocator_vinfo = NULL; surface_alloc_flags = 0; } /* reset or update the allocator if video resolution changed */ if (allocator_vinfo && gst_video_info_changed (allocator_vinfo, &new_allocation_vinfo)) { gst_object_replace ((GstObject **) & priv->allocator, NULL); if (allocator && priv->use_dmabuf_memory) { gst_allocator_set_vaapi_video_info (allocator, &new_allocation_vinfo, surface_alloc_flags); } else { allocator = NULL; } } if (!gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) goto error_no_vaapi_video_meta_option; /* create a new allocator if needed */ if (!allocator) { if (priv->use_dmabuf_memory) { allocator = gst_vaapi_dmabuf_allocator_new (priv->display, &new_allocation_vinfo, /* FIXME: */ 0, GST_PAD_SRC); } else { allocator = gst_vaapi_video_allocator_new (priv->display, &new_allocation_vinfo, surface_alloc_flags, 0); } if (!allocator) goto error_no_allocator; if (negotiated_vinfo) { gst_allocator_set_vaapi_negotiated_video_info (allocator, negotiated_vinfo); } GST_INFO_OBJECT (pool, "created new allocator %" GST_PTR_FORMAT, allocator); gst_buffer_pool_config_set_allocator (config, allocator, NULL); gst_object_unref (allocator); } /* use the allocator and set the video info for the vmeta */ if (allocator) { if (priv->allocator) gst_object_unref (priv->allocator); if ((priv->allocator = allocator)) gst_object_ref (allocator); negotiated_vinfo = gst_allocator_get_vaapi_negotiated_video_info (priv->allocator); allocator_vinfo = gst_allocator_get_vaapi_video_info (allocator, NULL); priv->vmeta_vinfo = (negotiated_vinfo) ? *negotiated_vinfo : *allocator_vinfo; /* last resource to set the correct buffer size */ if (GST_VIDEO_INFO_SIZE (allocator_vinfo) != size) { gst_buffer_pool_config_set_params (config, caps, GST_VIDEO_INFO_SIZE (allocator_vinfo), min_buffers, max_buffers); } } if (!priv->allocator) goto error_no_allocator; priv->options = 0; if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META)) { priv->options |= GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_META; } else { gint i; for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&new_allocation_vinfo); i++) { if (GST_VIDEO_INFO_PLANE_OFFSET (&new_allocation_vinfo, i) != GST_VIDEO_INFO_PLANE_OFFSET (&priv->vmeta_vinfo, i) || GST_VIDEO_INFO_PLANE_STRIDE (&new_allocation_vinfo, i) != GST_VIDEO_INFO_PLANE_STRIDE (&priv->vmeta_vinfo, i)) { priv->options |= GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_META; gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); updated = TRUE; break; } } } if (gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { fill_video_alignment (GST_VAAPI_VIDEO_BUFFER_POOL (pool), &align); gst_buffer_pool_config_set_video_alignment (config, &align); } if (!priv->use_dmabuf_memory && gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META)) priv->options |= GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_GL_TEXTURE_UPLOAD; ret = GST_BUFFER_POOL_CLASS (gst_vaapi_video_buffer_pool_parent_class)->set_config (pool, config); return !updated && ret; /* ERRORS */ error_invalid_config: { GST_ERROR_OBJECT (pool, "invalid config"); return FALSE; } error_no_caps: { GST_ERROR_OBJECT (pool, "no caps in config"); return FALSE; } error_invalid_caps: { GST_ERROR_OBJECT (pool, "invalid caps %" GST_PTR_FORMAT, caps); return FALSE; } error_invalid_allocator: { GST_ERROR_OBJECT (pool, "no allocator in config"); return FALSE; } error_no_vaapi_video_meta_option: { GST_ERROR_OBJECT (pool, "no GstVaapiVideoMeta option in config"); return FALSE; } error_no_allocator: { GST_ERROR_OBJECT (pool, "no allocator defined"); return FALSE; } }
static gboolean xvimage_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstXvImageBufferPool *xvpool = GST_XVIMAGE_BUFFER_POOL_CAST (pool); GstXvImageBufferPoolPrivate *priv = xvpool->priv; GstVideoInfo info; GstCaps *caps; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); priv->im_format = gst_xvimagesink_get_format_from_info (xvpool->sink, &info); if (priv->im_format == -1) goto unknown_format; if (priv->caps) gst_caps_unref (priv->caps); priv->caps = gst_caps_ref (caps); /* enable metadata based on config of the pool */ priv->add_metavideo = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); /* parse extra alignment info */ priv->need_alignment = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); if (priv->need_alignment) { gst_buffer_pool_config_get_video_alignment (config, &priv->align); GST_LOG_OBJECT (pool, "padding %u-%ux%u-%u", priv->align.padding_top, priv->align.padding_left, priv->align.padding_left, priv->align.padding_bottom); /* do padding and alignment */ gst_video_info_align (&info, &priv->align); /* we need the video metadata too now */ priv->add_metavideo = TRUE; } else { gst_video_alignment_reset (&priv->align); } /* add the padding */ priv->padded_width = GST_VIDEO_INFO_WIDTH (&info) + priv->align.padding_left + priv->align.padding_right; priv->padded_height = GST_VIDEO_INFO_HEIGHT (&info) + priv->align.padding_top + priv->align.padding_bottom; priv->info = info; return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config); /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } unknown_format: { GST_WARNING_OBJECT (xvpool->sink, "failed to get format from caps %" GST_PTR_FORMAT, caps); GST_ELEMENT_ERROR (xvpool->sink, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels", priv->info.width, priv->info.height), ("Invalid input caps %" GST_PTR_FORMAT, caps)); return FALSE;; } }
static gboolean gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) { GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool); GstV4l2Object *obj = pool->obj; GstCaps *caps; guint size, min_buffers, max_buffers; GstAllocator *allocator; GstAllocationParams params; gboolean can_allocate = FALSE; gboolean updated = FALSE; gboolean ret; pool->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); /* parse the config and keep around */ if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) goto wrong_config; if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms)) goto wrong_config; GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config); if (pool->allocator) gst_object_unref (pool->allocator); pool->allocator = NULL; switch (obj->mode) { case GST_V4L2_IO_DMABUF: pool->allocator = gst_dmabuf_allocator_new (); can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP); break; case GST_V4L2_IO_MMAP: can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP); break; case GST_V4L2_IO_USERPTR: can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR); break; case GST_V4L2_IO_DMABUF_IMPORT: can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF); break; case GST_V4L2_IO_RW: pool->allocator = g_object_ref (allocator); pool->params = params; /* No need to change the configuration */ goto done; break; default: g_assert_not_reached (); break; } if (min_buffers < GST_V4L2_MIN_BUFFERS) { updated = TRUE; min_buffers = GST_V4L2_MIN_BUFFERS; GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers); } if (max_buffers > VIDEO_MAX_FRAME || max_buffers == 0) { updated = TRUE; max_buffers = VIDEO_MAX_FRAME; GST_INFO_OBJECT (pool, "reducing maximum buffers to %u", max_buffers); } if (min_buffers > max_buffers) { updated = TRUE; min_buffers = max_buffers; GST_INFO_OBJECT (pool, "reducing minimum buffers to %u", min_buffers); } else if (min_buffers != max_buffers) { if (!can_allocate) { updated = TRUE; max_buffers = min_buffers; GST_INFO_OBJECT (pool, "can't allocate, setting maximum to minimum"); } } if (!pool->add_videometa && obj->need_video_meta) { GST_INFO_OBJECT (pool, "adding needed video meta"); updated = TRUE; gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); } if (updated) gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers); /* keep a GstVideoInfo with defaults for the when we need to copy */ gst_video_info_from_caps (&pool->caps_info, caps); done: ret = GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config); /* If anything was changed documentation recommand to return FALSE */ return !updated && ret; /* ERRORS */ wrong_config: { GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config); return FALSE; } }
static gboolean gst_vlc_video_pool_set_config( GstBufferPool *p_pool, GstStructure *p_config ) { GstVlcVideoPool *p_vpool = GST_VLC_VIDEO_POOL_CAST( p_pool ); GstCaps *p_caps; GstVideoInfo info; guint size, min_buffers, max_buffers; GstAllocator *p_allocator; GstAllocationParams params; if( !gst_buffer_pool_config_get_params( p_config, &p_caps, &size, &min_buffers, &max_buffers )) goto wrong_config; if( p_caps == NULL ) goto no_caps; gst_buffer_pool_config_get_allocator( p_config, &p_allocator, ¶ms ); if( p_allocator ) { if( !GST_IS_VLC_PICTURE_PLANE_ALLOCATOR( p_allocator )) goto unsupported_allocator; else { if( p_vpool->p_allocator ) gst_object_unref( p_vpool->p_allocator ); p_vpool->p_allocator = gst_object_ref ( p_allocator ); } } /* now parse the caps from the config */ if ( !gst_video_info_from_caps( &info, p_caps )) goto wrong_caps; /* enable metadata based on config of the pool */ p_vpool->b_add_metavideo = gst_buffer_pool_config_has_option( p_config, GST_BUFFER_POOL_OPTION_VIDEO_META ); if( !gst_vlc_picture_plane_allocator_query_format( p_vpool->p_allocator, &info, p_caps)) goto unknown_format; if( p_vpool->p_caps ) gst_caps_unref( p_vpool->p_caps ); p_vpool->p_caps = gst_caps_ref( p_caps ); p_vpool->info = info; gst_buffer_pool_config_set_params( p_config, p_caps, info.size, min_buffers, max_buffers ); return GST_BUFFER_POOL_CLASS (parent_class)->set_config( p_pool, p_config ); /* ERRORS */ wrong_config: { msg_Err(p_vpool->p_dec, "wrong pool config" ); return FALSE; } no_caps: { msg_Err(p_vpool->p_dec, "no input caps in config" ); return FALSE; } wrong_caps: { msg_Err(p_vpool->p_dec, "invalid caps" ); return FALSE; } unknown_format: { msg_Err(p_vpool->p_dec, "format unsupported" ); return FALSE; } unsupported_allocator: { msg_Err(p_vpool->p_dec, "allocator unsupported" ); return FALSE; } }
static gboolean gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) { GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); GstCaps *caps; GST_OBJECT_LOCK (pool); if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)) goto wrong_config; if (caps == NULL) goto no_caps; if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo && pool->port->port_def.format.video.eCompressionFormat == OMX_VIDEO_CodingUnused) { GstVideoInfo info; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_video_caps; /* enable metadata based on config of the pool */ pool->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); pool->video_info = info; } if (pool->caps) gst_caps_unref (pool->caps); pool->caps = gst_caps_ref (caps); GST_OBJECT_UNLOCK (pool); return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config (bpool, config); /* ERRORS */ wrong_config: { GST_OBJECT_UNLOCK (pool); GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_OBJECT_UNLOCK (pool); GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_video_caps: { GST_OBJECT_UNLOCK (pool); GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } }
static gboolean ximage_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstXImageBufferPool *xpool = GST_XIMAGE_BUFFER_POOL_CAST (pool); GstXImageBufferPoolPrivate *priv = xpool->priv; GstVideoInfo info; GstCaps *caps; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); /* keep track of the width and height and caps */ if (priv->caps) gst_caps_unref (priv->caps); priv->caps = gst_caps_ref (caps); /* check for the configured metadata */ priv->add_metavideo = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); /* parse extra alignment info */ priv->need_alignment = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); if (priv->need_alignment) { gst_buffer_pool_config_get_video_alignment (config, &priv->align); GST_LOG_OBJECT (pool, "padding %u-%ux%u-%u", priv->align.padding_top, priv->align.padding_left, priv->align.padding_left, priv->align.padding_bottom); /* do padding and alignment */ gst_video_info_align (&info, &priv->align); /* we need the video metadata too now */ priv->add_metavideo = TRUE; } else { gst_video_alignment_reset (&priv->align); } /* add the padding */ priv->padded_width = GST_VIDEO_INFO_WIDTH (&info) + priv->align.padding_left + priv->align.padding_right; priv->padded_height = GST_VIDEO_INFO_HEIGHT (&info) + priv->align.padding_top + priv->align.padding_bottom; priv->info = info; return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config); /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } }
static gboolean video_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstVideoBufferPool *vpool = GST_VIDEO_BUFFER_POOL_CAST (pool); GstVideoBufferPoolPrivate *priv = vpool->priv; GstVideoInfo info; GstCaps *caps; guint size, min_buffers, max_buffers; gint width, height; GstAllocator *allocator; GstAllocationParams params; if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; if (size < info.size) goto wrong_size; if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms)) goto wrong_config; width = info.width; height = info.height; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, width, height, caps); if (priv->caps) gst_caps_unref (priv->caps); priv->caps = gst_caps_ref (caps); priv->params = params; if (priv->allocator) gst_object_unref (priv->allocator); if ((priv->allocator = allocator)) gst_object_ref (allocator); /* enable metadata based on config of the pool */ priv->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); /* parse extra alignment info */ priv->need_alignment = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); if (priv->need_alignment && priv->add_videometa) { /* get and apply the alignment to the info */ gst_buffer_pool_config_get_video_alignment (config, &priv->video_align); /* apply the alignment to the info */ if (!gst_video_info_align (&info, &priv->video_align)) goto failed_to_align; gst_buffer_pool_config_set_video_alignment (config, &priv->video_align); } info.size = MAX (size, info.size); priv->info = info; gst_buffer_pool_config_set_params (config, caps, info.size, min_buffers, max_buffers); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config); /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } wrong_size: { GST_WARNING_OBJECT (pool, "Provided size is to small for the caps: %u", size); return FALSE; } failed_to_align: { GST_WARNING_OBJECT (pool, "Failed to align"); return FALSE; } }
static gboolean gst_vdp_video_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstVdpVideoBufferPool *vdppool = GST_VDP_VIDEO_BUFFER_POOL_CAST (pool); GstVideoInfo info; GstCaps *caps; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)) goto wrong_config; if (caps == NULL) goto no_caps; /* now parse the caps from the config */ if (!gst_video_info_from_caps (&info, caps)) goto wrong_caps; GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height, caps); if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_UNKNOWN) goto unknown_format; vdppool->info = info; /* enable metadata based on config of the pool */ vdppool->add_videometa = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); /* parse extra alignment info */ vdppool->add_vdpmeta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VDP_VIDEO_META); return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config); /* ERRORS */ wrong_config: { GST_WARNING_OBJECT (pool, "invalid config"); return FALSE; } no_caps: { GST_WARNING_OBJECT (pool, "no caps in config"); return FALSE; } wrong_caps: { GST_WARNING_OBJECT (pool, "failed getting geometry from caps %" GST_PTR_FORMAT, caps); return FALSE; } unknown_format: { GST_WARNING_OBJECT (vdppool, "failed to get format from caps %" GST_PTR_FORMAT, caps); GST_ELEMENT_ERROR (vdppool, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels", info.width, info.height), ("Invalid input caps %" GST_PTR_FORMAT, caps)); return FALSE;; } }
static gboolean gst_vaapi_video_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { GstVaapiVideoBufferPoolPrivate *const priv = GST_VAAPI_VIDEO_BUFFER_POOL (pool)->priv; GstCaps *caps = NULL; GstVideoInfo *const cur_vip = &priv->video_info[priv->video_info_index]; GstVideoInfo *const new_vip = &priv->video_info[!priv->video_info_index]; GstVideoAlignment align; GstAllocator *allocator; gboolean changed_caps, use_dmabuf_memory, ret, updated = FALSE; if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)) goto error_invalid_config; if (!caps || !gst_video_info_from_caps (new_vip, caps)) goto error_no_caps; use_dmabuf_memory = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_DMABUF_MEMORY); if (priv->use_dmabuf_memory != use_dmabuf_memory) { priv->use_dmabuf_memory = use_dmabuf_memory; g_clear_object (&priv->allocator); } changed_caps = !priv->allocator || GST_VIDEO_INFO_FORMAT (cur_vip) != GST_VIDEO_INFO_FORMAT (new_vip) || GST_VIDEO_INFO_WIDTH (cur_vip) != GST_VIDEO_INFO_WIDTH (new_vip) || GST_VIDEO_INFO_HEIGHT (cur_vip) != GST_VIDEO_INFO_HEIGHT (new_vip); if (changed_caps) { const GstVideoInfo *alloc_vip; guint flags = 0; if (use_dmabuf_memory) { /* XXX: also needs fixed strides/offsets */ flags |= GST_VAAPI_SURFACE_ALLOC_FLAG_LINEAR_STORAGE; allocator = gst_vaapi_dmabuf_allocator_new (priv->display, new_vip, flags); } else { allocator = gst_vaapi_video_allocator_new (priv->display, new_vip, 0); } if (!allocator) goto error_create_allocator; gst_object_replace ((GstObject **) & priv->allocator, GST_OBJECT_CAST (allocator)); gst_object_unref (allocator); priv->video_info_index ^= 1; alloc_vip = gst_allocator_get_vaapi_video_info (allocator, NULL); if (!alloc_vip) goto error_create_allocator_info; priv->alloc_info = *alloc_vip; } if (!gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) goto error_no_vaapi_video_meta_option; priv->has_video_meta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); if (!priv->has_video_meta) { gint i; for (i = 0; i < GST_VIDEO_INFO_N_PLANES (new_vip); i++) { if (GST_VIDEO_INFO_PLANE_OFFSET (new_vip, i) != GST_VIDEO_INFO_PLANE_OFFSET (&priv->alloc_info, i) || GST_VIDEO_INFO_PLANE_STRIDE (new_vip, i) != GST_VIDEO_INFO_PLANE_STRIDE (&priv->alloc_info, i)) { priv->has_video_meta = TRUE; gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); updated = TRUE; break; } } } priv->has_video_alignment = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); if (priv->has_video_alignment) { fill_video_alignment (GST_VAAPI_VIDEO_BUFFER_POOL (pool), &align); gst_buffer_pool_config_set_video_alignment (config, &align); } priv->has_texture_upload_meta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META); ret = GST_BUFFER_POOL_CLASS (gst_vaapi_video_buffer_pool_parent_class)->set_config (pool, config); return !updated && ret; /* ERRORS */ error_invalid_config: { GST_ERROR ("invalid config"); return FALSE; } error_no_caps: { GST_ERROR ("no valid caps in config"); return FALSE; } error_create_allocator: { GST_ERROR ("failed to create GstVaapiVideoAllocator object"); return FALSE; } error_create_allocator_info: { GST_ERROR ("failed to create GstVaapiVideoAllocator `video-info'"); return FALSE; } error_no_vaapi_video_meta_option: { GST_ERROR ("no GstVaapiVideoMeta option"); return FALSE; } }