static gboolean gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { GstWaylandSink *sink = GST_WAYLAND_SINK (bsink); GstBufferPool *pool = NULL; GstStructure *config; GstCaps *caps; guint size; gboolean need_pool; gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) goto no_caps; if (sink->pool) pool = gst_object_ref (sink->pool); if (pool != NULL) { GstCaps *pcaps; /* we had a pool, check caps */ config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); if (!gst_caps_is_equal (caps, pcaps)) { /* different caps, we can't use this pool */ gst_object_unref (pool); pool = NULL; } gst_structure_free (config); } if (pool == NULL && need_pool) { GstVideoInfo info; if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; GST_DEBUG_OBJECT (sink, "create new pool"); pool = gst_wayland_buffer_pool_new (sink->display); /* the normal size of a frame */ size = info.size; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, 2, 0); if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; } if (pool) { gst_query_add_allocation_pool (query, pool, size, 2, 0); gst_object_unref (pool); } return TRUE; /* ERRORS */ no_caps: { GST_DEBUG_OBJECT (bsink, "no caps specified"); return FALSE; } invalid_caps: { GST_DEBUG_OBJECT (bsink, "invalid caps specified"); return FALSE; } config_failed: { GST_DEBUG_OBJECT (bsink, "failed setting config"); gst_object_unref (pool); return FALSE; } }
static gboolean gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstWaylandSink *sink; GstBufferPool *newpool; GstVideoInfo info; enum wl_shm_format format; GArray *formats; gint i; GstStructure *structure; static GstAllocationParams params = { 0, 0, 0, 15, }; sink = GST_WAYLAND_SINK (bsink); GST_DEBUG_OBJECT (sink, "set caps %" GST_PTR_FORMAT, caps); /* extract info from caps */ if (!gst_video_info_from_caps (&info, caps)) goto invalid_format; format = gst_video_format_to_wayland_format (GST_VIDEO_INFO_FORMAT (&info)); if ((gint) format == -1) goto invalid_format; /* verify we support the requested format */ formats = sink->display->formats; for (i = 0; i < formats->len; i++) { if (g_array_index (formats, uint32_t, i) == format) break; } if (i >= formats->len) goto unsupported_format; /* create a new pool for the new configuration */ newpool = gst_wayland_buffer_pool_new (sink->display); if (!newpool) goto pool_failed; structure = gst_buffer_pool_get_config (newpool); gst_buffer_pool_config_set_params (structure, caps, info.size, 2, 0); gst_buffer_pool_config_set_allocator (structure, NULL, ¶ms); if (!gst_buffer_pool_set_config (newpool, structure)) goto config_failed; /* store the video info */ sink->video_info = info; sink->video_info_changed = TRUE; gst_object_replace ((GstObject **) & sink->pool, (GstObject *) newpool); gst_object_unref (newpool); return TRUE; invalid_format: { GST_DEBUG_OBJECT (sink, "Could not locate image format from caps %" GST_PTR_FORMAT, caps); return FALSE; } unsupported_format: { GST_DEBUG_OBJECT (sink, "Format %s is not available on the display", gst_wayland_format_to_string (format)); return FALSE; } pool_failed: { GST_DEBUG_OBJECT (sink, "Failed to create new pool"); return FALSE; } config_failed: { GST_DEBUG_OBJECT (bsink, "failed setting config"); return FALSE; } }
static gboolean gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) { GstV4l2Src *src; GstV4l2Object *obj; GstBufferPool *pool; guint size, min, max; gboolean update; src = GST_V4L2SRC (bsrc); obj = src->v4l2object; if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); update = TRUE; } else { pool = NULL; min = max = 0; size = 0; update = FALSE; } GST_DEBUG_OBJECT (src, "allocation: size:%u min:%u max:%u pool:%" GST_PTR_FORMAT, size, min, max, pool); if (min != 0) { /* if there is a min-buffers suggestion, use it. We add 1 because we need 1 * buffer extra to capture while the other two buffers are downstream */ min += 1; } else { min = 2; } /* select a pool */ switch (obj->mode) { case GST_V4L2_IO_RW: if (pool == NULL) { /* no downstream pool, use our own then */ GST_DEBUG_OBJECT (src, "read/write mode: no downstream pool, using our own"); pool = GST_BUFFER_POOL_CAST (obj->pool); size = obj->sizeimage; } else { /* in READ/WRITE mode, prefer a downstream pool because our own pool * doesn't help much, we have to write to it as well */ GST_DEBUG_OBJECT (src, "read/write mode: using downstream pool"); /* use the bigest size, when we use our own pool we can't really do any * other size than what the hardware gives us but for downstream pools * we can try */ size = MAX (size, obj->sizeimage); } break; case GST_V4L2_IO_MMAP: case GST_V4L2_IO_USERPTR: case GST_V4L2_IO_DMABUF: /* in streaming mode, prefer our own pool */ pool = GST_BUFFER_POOL_CAST (obj->pool); size = obj->sizeimage; GST_DEBUG_OBJECT (src, "streaming mode: using our own pool %" GST_PTR_FORMAT, pool); break; case GST_V4L2_IO_AUTO: default: GST_WARNING_OBJECT (src, "unhandled mode"); break; } if (pool) { GstStructure *config; GstCaps *caps; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL); gst_buffer_pool_config_set_params (config, caps, size, min, max); /* if downstream supports video metadata, add this to the pool config */ if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) { GST_DEBUG_OBJECT (pool, "activate Video Meta"); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); } gst_buffer_pool_set_config (pool, config); } if (update) gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); else gst_query_add_allocation_pool (query, pool, size, min, max); return GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query); }
static gboolean gst_imx_v4l2src_decide_allocation(GstBaseSrc *bsrc, GstQuery *query) { GstImxV4l2VideoSrc *v4l2src = GST_IMX_V4L2SRC(bsrc); struct v4l2_format fmt; GstBufferPool *pool; guint size, min, max; gboolean update; GstStructure *config; GstCaps *caps; gst_query_parse_allocation(query, &caps, NULL); /* Determine min and max */ if (gst_query_get_n_allocation_pools(query) > 0) { gst_query_parse_nth_allocation_pool(query, 0, NULL, NULL, &min, &max); update = TRUE; } else { min = max = 0; update = FALSE; } if (min != 0) /* Need an extra buffer to capture while other buffers * are downstream */ min += 1; else min = v4l2src->queue_size; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(GST_IMX_FD_OBJECT_GET_FD(v4l2src->fd_obj_v4l), VIDIOC_G_FMT, &fmt) < 0) { GST_ERROR_OBJECT(v4l2src, "VIDIOC_G_FMT failed"); return FALSE; } size = fmt.fmt.pix.sizeimage; /* no repooling; leads to stream off situation due to pool start/stop */ pool = gst_base_src_get_buffer_pool(bsrc); if (!pool) { pool = gst_imx_v4l2_buffer_pool_new(v4l2src->fd_obj_v4l, v4l2src->metaCropX, v4l2src->metaCropY, v4l2src->metaCropWidth, v4l2src->metaCropHeight); config = gst_buffer_pool_get_config(pool); gst_buffer_pool_config_set_params(config, caps, size, min, max); gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META); gst_buffer_pool_set_config(pool, config); } if (update) gst_query_set_nth_allocation_pool(query, 0, pool, size, min, max); else gst_query_add_allocation_pool(query, pool, size, min, max); gst_object_unref(pool); return TRUE; }
/** * gst_vaapi_plugin_base_decide_allocation: * @plugin: a #GstVaapiPluginBase * @query: the allocation query to parse * @feature: the desired #GstVaapiCapsFeature, or zero to find the * preferred one * * Decides allocation parameters for the downstream elements. * * Returns: %TRUE if successful, %FALSE otherwise. */ gboolean gst_vaapi_plugin_base_decide_allocation (GstVaapiPluginBase * plugin, GstQuery * query, guint feature) { GstCaps *caps = NULL; GstBufferPool *pool; GstStructure *config; GstVideoInfo vi; guint size, min, max; gboolean update_pool = FALSE; gboolean has_video_meta = FALSE; gboolean has_video_alignment = FALSE; #if (USE_GLX || USE_EGL) gboolean has_texture_upload_meta = FALSE; guint idx; #endif g_return_val_if_fail (plugin->display != NULL, FALSE); gst_query_parse_allocation (query, &caps, NULL); /* We don't need any GL context beyond this point if not requested so explicitly through GstVideoGLTextureUploadMeta */ gst_object_replace (&plugin->gl_context, NULL); if (!caps) goto error_no_caps; if (!feature) feature = gst_vaapi_find_preferred_caps_feature (plugin->srcpad, GST_VIDEO_FORMAT_ENCODED, NULL); has_video_meta = gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); #if (USE_GLX || USE_EGL) has_texture_upload_meta = gst_query_find_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, &idx) && (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META); #if USE_GST_GL_HELPERS if (has_texture_upload_meta) { const GstStructure *params; GstObject *gl_context; gst_query_parse_nth_allocation_meta (query, idx, ¶ms); if (params) { if (gst_structure_get (params, "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, &gl_context, NULL) && gl_context) { gst_vaapi_plugin_base_set_gl_context (plugin, gl_context); gst_object_unref (gl_context); } } } #endif #endif /* Make sure the display we pass down to the buffer pool is actually the expected one, especially when the downstream element requires a GLX or EGL display */ if (!gst_vaapi_plugin_base_ensure_display (plugin)) goto error_ensure_display; gst_video_info_init (&vi); gst_video_info_from_caps (&vi, caps); if (GST_VIDEO_INFO_FORMAT (&vi) == GST_VIDEO_FORMAT_ENCODED) gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_I420, GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi)); if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); update_pool = TRUE; size = MAX (size, vi.size); if (pool) { /* Check whether downstream element proposed a bufferpool but did not provide a correct propose_allocation() implementation */ has_video_alignment = gst_buffer_pool_has_option (pool, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); } } else { pool = NULL; size = vi.size; min = max = 0; } /* GstVaapiVideoMeta is mandatory, and this implies VA surface memory */ if (!pool || !gst_buffer_pool_has_option (pool, GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) { GST_INFO_OBJECT (plugin, "%s. Making a new pool", pool == NULL ? "No pool" : "Pool hasn't GstVaapiVideoMeta"); if (pool) gst_object_unref (pool); pool = gst_vaapi_video_buffer_pool_new (plugin->display); if (!pool) goto error_create_pool; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, min, max); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META); if (!gst_buffer_pool_set_config (pool, config)) { config = gst_buffer_pool_get_config (pool); if (!gst_buffer_pool_config_validate_params (config, caps, size, min, max)) { gst_structure_free (config); goto config_failed; } if (!gst_buffer_pool_set_config (pool, config)) goto config_failed; } } /* Check whether GstVideoMeta, or GstVideoAlignment, is needed (raw video) */ if (has_video_meta) { if (!gst_vaapi_plugin_base_set_pool_config (pool, GST_BUFFER_POOL_OPTION_VIDEO_META)) goto config_failed; } else if (has_video_alignment) { if (!gst_vaapi_plugin_base_set_pool_config (pool, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) goto config_failed; } /* GstVideoGLTextureUploadMeta (OpenGL) */ #if (USE_GLX || USE_EGL) if (has_texture_upload_meta) { if (!gst_vaapi_plugin_base_set_pool_config (pool, GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META)) goto config_failed; } #endif if (update_pool) gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); else gst_query_add_allocation_pool (query, pool, size, min, max); g_clear_object (&plugin->srcpad_buffer_pool); plugin->srcpad_buffer_pool = pool; return TRUE; /* ERRORS */ error_no_caps: { GST_ERROR_OBJECT (plugin, "no caps specified"); return FALSE; } error_ensure_display: { GST_ERROR_OBJECT (plugin, "failed to ensure display of type %d", plugin->display_type_req); return FALSE; } error_create_pool: { GST_ERROR_OBJECT (plugin, "failed to create buffer pool"); return FALSE; } config_failed: { if (pool) gst_object_unref (pool); GST_ELEMENT_ERROR (plugin, RESOURCE, SETTINGS, ("Failed to configure the buffer pool"), ("Configuration is most likely invalid, please report this issue.")); return FALSE; } }