static void gst_glimage_sink_get_times (GstBaseSink * bsink, GstBuffer * buf,
GstClockTime * start, GstClockTime * end);
static gboolean gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps);
+static GstCaps *gst_glimage_sink_get_caps (GstBaseSink * bsink,
+ GstCaps * filter);
static GstFlowReturn gst_glimage_sink_prepare (GstBaseSink * bsink,
GstBuffer * buf);
static GstFlowReturn gst_glimage_sink_show_frame (GstVideoSink * bsink,
gstelement_class->set_context = gst_glimage_sink_set_context;
gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_glimage_sink_query);
gstbasesink_class->set_caps = gst_glimage_sink_set_caps;
+ gstbasesink_class->get_caps = gst_glimage_sink_get_caps;
gstbasesink_class->get_times = gst_glimage_sink_get_times;
gstbasesink_class->prepare = gst_glimage_sink_prepare;
gstbasesink_class->propose_allocation = gst_glimage_sink_propose_allocation;
}
}
+/* copies the given caps */
+static GstCaps *
+gst_glimage_sink_caps_remove_format_info (GstCaps * caps)
+{
+ GstStructure *st;
+ GstCapsFeatures *f;
+ gint i, n;
+ GstCaps *res;
+
+ res = gst_caps_new_empty ();
+
+ n = gst_caps_get_size (caps);
+ for (i = 0; i < n; i++) {
+ st = gst_caps_get_structure (caps, i);
+ f = gst_caps_get_features (caps, i);
+
+ /* If this is already expressed by the existing caps
+ * skip this structure */
+ if (i > 0 && gst_caps_is_subset_structure_full (res, st, f))
+ continue;
+
+ st = gst_structure_copy (st);
+ /* Only remove format info for the cases when we can actually convert */
+ if (!gst_caps_features_is_any (f)
+ && gst_caps_features_is_equal (f,
+ GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))
+ gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site",
+ NULL);
+ gst_structure_remove_fields (st, "width", "height", NULL);
+
+ gst_caps_append_structure_full (res, st, gst_caps_features_copy (f));
+ }
+
+ return res;
+}
+
+static GstCaps *
+gst_glimage_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
+{
+ GstGLImageSink *gl_sink = GST_GLIMAGE_SINK (bsink);
+ GstCaps *tmp = NULL;
+ GstCaps *result = NULL;
+
+ tmp = gst_caps_from_string ("video/x-raw(memory:GLMemory),format=RGBA");
+
+ result = gst_glimage_sink_caps_remove_format_info (tmp);
+ gst_caps_unref (tmp);
+ tmp = result;
+ GST_DEBUG_OBJECT (bsink, "remove format returned caps %" GST_PTR_FORMAT, tmp);
+
+ result =
+ gst_gl_color_convert_transform_caps (gl_sink->context, GST_PAD_SRC, tmp,
+ NULL);
+ gst_caps_unref (tmp);
+ tmp = result;
+
+ result =
+ gst_gl_upload_transform_caps (gl_sink->context, GST_PAD_SRC, tmp, NULL);
+ gst_caps_unref (tmp);
+ tmp = result;
+ GST_DEBUG_OBJECT (bsink, "transfer returned caps %" GST_PTR_FORMAT, tmp);
+
+ if (filter) {
+ result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (tmp);
+ } else {
+ result = tmp;
+ }
+
+ GST_DEBUG_OBJECT (bsink, "returning caps: %" GST_PTR_FORMAT, result);
+
+ return result;
+}
+
static gboolean
gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
GstCaps *caps;
guint size;
gboolean need_pool;
- GstStructure *gl_context;
- gchar *platform, *gl_apis;
- gpointer handle;
- GstAllocator *allocator = NULL;
- GstAllocationParams params;
if (!_ensure_gl_setup (glimage_sink))
return FALSE;
gst_object_unref (pool);
}
- /* we also support various metadata */
- gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
+ gst_gl_upload_propose_allocation (glimage_sink->upload, NULL, query);
+
if (glimage_sink->context->gl_vtable->FenceSync)
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0);
- gl_apis =
- gst_gl_api_to_string (gst_gl_context_get_gl_api (glimage_sink->context));
- platform =
- gst_gl_platform_to_string (gst_gl_context_get_gl_platform
- (glimage_sink->context));
- handle = (gpointer) gst_gl_context_get_gl_context (glimage_sink->context);
-
- gl_context =
- gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext",
- GST_GL_TYPE_CONTEXT, glimage_sink->context, "gst.gl.context.handle",
- G_TYPE_POINTER, handle, "gst.gl.context.type", G_TYPE_STRING, platform,
- "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL);
- gst_query_add_allocation_meta (query,
- GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, gl_context);
-
- g_free (gl_apis);
- g_free (platform);
- gst_structure_free (gl_context);
-
- gst_allocation_params_init (¶ms);
-
- allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
- gst_query_add_allocation_param (query, allocator, ¶ms);
- gst_object_unref (allocator);
-
-#if GST_GL_HAVE_PLATFORM_EGL
- if (gst_gl_context_check_feature (glimage_sink->context,
- "EGL_KHR_image_base")) {
- allocator = gst_allocator_find (GST_EGL_IMAGE_MEMORY_TYPE);
- gst_query_add_allocation_param (query, allocator, ¶ms);
- gst_object_unref (allocator);
- }
-#endif
-
return TRUE;
/* ERRORS */
}
static void
+_init_upload (GstGLMixer * mix, GstGLMixerPad * pad)
+{
+ GstVideoAggregatorPad *vaggpad = GST_VIDEO_AGGREGATOR_PAD (pad);
+
+ if (!pad->upload) {
+ GstCaps *in_caps = gst_pad_get_current_caps (GST_PAD (pad));
+ GstCaps *upload_caps = gst_caps_copy (in_caps);
+ GstCapsFeatures *gl_features =
+ gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+
+ pad->upload = gst_gl_upload_new (mix->context);
+
+ gst_caps_set_features (upload_caps, 0,
+ gst_caps_features_copy (gl_features));
+ gst_gl_upload_set_caps (pad->upload, in_caps, upload_caps);
+ gst_caps_unref (in_caps);
+
+ if (!pad->convert) {
+ GstVideoInfo gl_info;
+ GstCaps *gl_caps;
+
+ gst_video_info_set_format (&gl_info,
+ GST_VIDEO_FORMAT_RGBA,
+ GST_VIDEO_INFO_WIDTH (&vaggpad->info),
+ GST_VIDEO_INFO_HEIGHT (&vaggpad->info));
+ gl_caps = gst_video_info_to_caps (&gl_info);
+ gst_caps_set_features (gl_caps, 0, gst_caps_features_copy (gl_features));
+
+ pad->convert = gst_gl_color_convert_new (mix->context);
+
+ gst_gl_color_convert_set_caps (pad->convert, upload_caps, gl_caps);
+ gst_caps_unref (gl_caps);
+ }
+
+ gst_caps_unref (upload_caps);
+ gst_caps_features_free (gl_features);
+ }
+}
+
+static void
gst_gl_mixer_pad_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
}
static gboolean
-gst_gl_mixer_propose_allocation (GstGLMixer * mix,
+gst_gl_mixer_propose_allocation (GstGLMixer * mix, GstGLMixerPad * pad,
GstQuery * decide_query, GstQuery * query)
{
GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
guint size = 0;
gboolean need_pool;
GError *error = NULL;
- GstStructure *gl_context;
- gchar *platform, *gl_apis;
- gpointer handle;
- GstAllocator *allocator = NULL;
- GstAllocationParams params;
gst_query_parse_allocation (query, &caps, &need_pool);
}
/* we also support various metadata */
- gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
if (mix->context->gl_vtable->FenceSync)
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0);
- gl_apis = gst_gl_api_to_string (gst_gl_context_get_gl_api (mix->context));
- platform =
- gst_gl_platform_to_string (gst_gl_context_get_gl_platform (mix->context));
- handle = (gpointer) gst_gl_context_get_gl_context (mix->context);
-
- gl_context =
- gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext",
- GST_GL_TYPE_CONTEXT, mix->context, "gst.gl.context.handle",
- G_TYPE_POINTER, handle, "gst.gl.context.type", G_TYPE_STRING, platform,
- "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL);
- gst_query_add_allocation_meta (query,
- GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, gl_context);
-
- g_free (gl_apis);
- g_free (platform);
- gst_structure_free (gl_context);
-
- gst_allocation_params_init (¶ms);
+ _init_upload (mix, pad);
- allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
- gst_query_add_allocation_param (query, allocator, ¶ms);
- gst_object_unref (allocator);
+ gst_gl_upload_propose_allocation (pad->upload, decide_query, query);
return TRUE;
gst_gl_mixer_set_caps_features (const GstCaps * caps,
const gchar * feature_name)
{
- GstCaps *tmp = gst_caps_copy (caps);
- guint n = gst_caps_get_size (tmp);
- guint i = 0;
-
- for (i = 0; i < n; i++) {
- GstCapsFeatures *features = gst_caps_get_features (tmp, i);
- if (features) {
- guint n_f = gst_caps_features_get_size (features);
- guint j = 0;
- for (j = 0; j < n_f; j++) {
- gst_caps_features_remove_id (features,
- gst_caps_features_get_nth_id (features, j));
- }
- }
-
- gst_caps_features_add (features, feature_name);
- gst_caps_set_simple (tmp, "format", G_TYPE_STRING, "RGBA", NULL);
- }
-
- return tmp;
+ GstCaps *ret = gst_gl_caps_replace_all_caps_features (caps, feature_name);
+ gst_caps_set_simple (ret, "format", G_TYPE_STRING, "RGBA", NULL);
+ return ret;
}
/* copies the given caps */
GstCaps *
gst_gl_mixer_update_caps (GstGLMixer * mix, GstCaps * caps)
{
- GstCaps *result = NULL;
- GstCaps *glcaps = gst_gl_mixer_set_caps_features (caps,
- GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
-#if GST_GL_HAVE_PLATFORM_EGL
- GstCaps *eglcaps = gst_gl_mixer_set_caps_features (caps,
- GST_CAPS_FEATURE_MEMORY_EGL_IMAGE);
-#endif
- GstCaps *uploadcaps = gst_gl_mixer_set_caps_features (caps,
- GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META);
- GstCaps *raw_caps =
- gst_caps_from_string (GST_VIDEO_CAPS_MAKE (GST_GL_COLOR_CONVERT_FORMATS));
+ GstCaps *result, *tmp, *gl_caps;
- result = gst_caps_new_empty ();
+ gl_caps = gst_caps_from_string ("video/x-raw(memory:GLMemory),format=RGBA");
- result = gst_caps_merge (result, glcaps);
-#if GST_GL_HAVE_PLATFORM_EGL
- result = gst_caps_merge (result, eglcaps);
-#endif
- result = gst_caps_merge (result, uploadcaps);
- result = gst_caps_merge (result, raw_caps);
+ result =
+ gst_gl_color_convert_transform_caps (mix->context, GST_PAD_SRC, gl_caps,
+ NULL);
+ tmp = result;
+ GST_DEBUG_OBJECT (mix, "convert returned caps %" GST_PTR_FORMAT, tmp);
- result = gst_caps_merge (result, gst_gl_mixer_caps_remove_format_info (caps));
+ result = gst_gl_mixer_caps_remove_format_info (tmp);
+ gst_caps_unref (tmp);
+ tmp = result;
+ GST_DEBUG_OBJECT (mix, "remove format returned caps %" GST_PTR_FORMAT, tmp);
- GST_DEBUG_OBJECT (mix, "returning %" GST_PTR_FORMAT, result);
+ result = gst_gl_upload_transform_caps (mix->context, GST_PAD_SRC, tmp, NULL);
+ gst_caps_unref (tmp);
+ tmp = result;
+ GST_DEBUG_OBJECT (mix, "transfer returned caps %" GST_PTR_FORMAT, tmp);
return result;
}
static GstCaps *
gst_gl_mixer_pad_sink_getcaps (GstPad * pad, GstGLMixer * mix, GstCaps * filter)
{
- GstCaps *srccaps;
+ GstCaps *sinkcaps;
GstCaps *template_caps;
GstCaps *filtered_caps;
GstCaps *returned_caps;
template_caps = gst_pad_get_pad_template_caps (pad);
- srccaps = gst_pad_get_current_caps (pad);
- if (srccaps == NULL) {
+ sinkcaps = gst_pad_get_current_caps (pad);
+ if (sinkcaps == NULL) {
had_current_caps = FALSE;
- srccaps = template_caps;
+ sinkcaps = template_caps;
} else {
- srccaps = gst_caps_merge (srccaps, gst_gl_mixer_update_caps (mix, srccaps));
+ sinkcaps =
+ gst_caps_merge (sinkcaps, gst_gl_mixer_update_caps (mix, sinkcaps));
}
- filtered_caps = srccaps;
+ filtered_caps = sinkcaps;
if (filter)
- filtered_caps = gst_caps_intersect (srccaps, filter);
+ filtered_caps = gst_caps_intersect (sinkcaps, filter);
returned_caps = gst_caps_intersect (filtered_caps, template_caps);
if (filter)
gboolean ret = FALSE;
GstGLMixer *mix = GST_GL_MIXER (agg);
GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
+ GstGLMixerPad *pad = GST_GL_MIXER_PAD (bpad);
GST_TRACE ("QUERY %" GST_PTR_FORMAT, query);
decide_query);
/* pass the query to the propose_allocation vmethod if any */
- ret = gst_gl_mixer_propose_allocation (mix, decide_query, query);
+ ret = gst_gl_mixer_propose_allocation (mix, pad, decide_query, query);
if (decide_query)
gst_query_unref (decide_query);
static gboolean
gst_gl_mixer_query_caps (GstPad * pad, GstAggregator * agg, GstQuery * query)
{
- GstCaps *filter, *current_caps, *retcaps;
+ GstGLMixer *mix = GST_GL_MIXER (agg);
+ GstCaps *filter, *current_caps, *retcaps, *gl_caps;
gst_query_parse_caps (query, &filter);
if (current_caps == NULL)
current_caps = gst_pad_get_pad_template_caps (agg->srcpad);
+ /* convert from current caps to GLMemory caps */
+ gl_caps =
+ gst_caps_merge (gst_caps_merge (gst_gl_mixer_set_caps_features
+ (current_caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY),
+ gst_gl_mixer_set_caps_features (current_caps,
+ GST_CAPS_FEATURE_MEMORY_EGL_IMAGE)),
+ gst_gl_mixer_set_caps_features (current_caps,
+ GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META));
+ retcaps =
+ gst_gl_download_transform_caps (mix->context, GST_PAD_SINK, current_caps,
+ NULL);
+ retcaps = gst_caps_merge (gl_caps, retcaps);
+ gst_caps_unref (current_caps);
+ current_caps = retcaps;
+
retcaps = gst_gl_mixer_caps_remove_format_info (current_caps);
gst_caps_unref (current_caps);
- if (filter)
- retcaps =
+ if (filter) {
+ current_caps =
gst_caps_intersect_full (filter, retcaps, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (retcaps);
+ retcaps = current_caps;
+ }
gst_query_set_caps_result (query, retcaps);
gst_caps_unref (retcaps);
GstVideoAggregatorPad *vaggpad = GST_VIDEO_AGGREGATOR_PAD (frame->pad);
GstGLMixerPad *pad = frame->pad;
GstBuffer *uploaded_buf, *gl_buffer;
- GstCaps *gl_caps;
- GstCapsFeatures *gl_features;
GstVideoInfo gl_info;
GstVideoFrame gl_frame;
GstGLSyncMeta *sync_meta;
GST_VIDEO_FORMAT_RGBA,
GST_VIDEO_INFO_WIDTH (&vaggpad->info),
GST_VIDEO_INFO_HEIGHT (&vaggpad->info));
- gl_features =
- gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
-
- gl_caps = gst_video_info_to_caps (&gl_info);
- gst_caps_set_features (gl_caps, 0, gst_caps_features_copy (gl_features));
-
- if (!pad->upload) {
- GstCaps *in_caps = gst_pad_get_current_caps (GST_PAD (pad));
- GstCaps *upload_caps = gst_caps_copy (in_caps);
-
- pad->upload = gst_gl_upload_new (mix->context);
-
- gst_caps_set_features (upload_caps, 0,
- gst_caps_features_copy (gl_features));
- gst_gl_upload_set_caps (pad->upload, in_caps, upload_caps);
-
- if (!pad->convert) {
- pad->convert = gst_gl_color_convert_new (mix->context);
-
- gst_gl_color_convert_set_caps (pad->convert, upload_caps, gl_caps);
- }
-
- gst_caps_unref (upload_caps);
- gst_caps_unref (in_caps);
- }
- gst_caps_features_free (gl_features);
- gst_caps_unref (gl_caps);
+ _init_upload (mix, pad);
sync_meta = gst_buffer_get_gl_sync_meta (vaggpad->buffer);
if (sync_meta)
static void gst_gl_test_src_dispose (GObject * object);
static gboolean gst_gl_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
+static GstCaps *gst_gl_test_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
static GstCaps *gst_gl_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
static gboolean gst_gl_test_src_is_seekable (GstBaseSrc * psrc);
element_class->set_context = gst_gl_test_src_set_context;
gstbasesrc_class->set_caps = gst_gl_test_src_setcaps;
+ gstbasesrc_class->get_caps = gst_gl_test_src_getcaps;
gstbasesrc_class->is_seekable = gst_gl_test_src_is_seekable;
gstbasesrc_class->do_seek = gst_gl_test_src_do_seek;
gstbasesrc_class->query = gst_gl_test_src_query;
}
}
+/* copies the given caps */
+static GstCaps *
+gst_gl_test_src_caps_remove_format_info (GstCaps * caps)
+{
+ GstStructure *st;
+ GstCapsFeatures *f;
+ gint i, n;
+ GstCaps *res;
+
+ res = gst_caps_new_empty ();
+
+ n = gst_caps_get_size (caps);
+ for (i = 0; i < n; i++) {
+ st = gst_caps_get_structure (caps, i);
+ f = gst_caps_get_features (caps, i);
+
+ /* If this is already expressed by the existing caps
+ * skip this structure */
+ if (i > 0 && gst_caps_is_subset_structure_full (res, st, f))
+ continue;
+
+ st = gst_structure_copy (st);
+ /* Only remove format info for the cases when we can actually convert */
+ if (!gst_caps_features_is_any (f)
+ && gst_caps_features_is_equal (f,
+ GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))
+ gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site",
+ NULL);
+ gst_structure_remove_fields (st, "width", "height", NULL);
+
+ gst_caps_append_structure_full (res, st, gst_caps_features_copy (f));
+ }
+
+ return res;
+}
+
+static GstCaps *
+gst_gl_test_src_set_caps_features (const GstCaps * caps,
+ const gchar * feature_name)
+{
+ GstCaps *ret = gst_gl_caps_replace_all_caps_features (caps, feature_name);
+ gst_caps_set_simple (ret, "format", G_TYPE_STRING, "RGBA", NULL);
+ return ret;
+}
+
+static GstCaps *
+gst_gl_test_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
+{
+ GstGLTestSrc *src = GST_GL_TEST_SRC (bsrc);
+ GstCaps *tmp = NULL;
+ GstCaps *result = NULL;
+ GstCaps *gl_caps;
+ GstCaps *caps =
+ gst_caps_from_string ("video/x-raw(memory:GLMemory),format=RGBA");
+
+ tmp = gst_gl_test_src_caps_remove_format_info (caps);
+ GST_DEBUG_OBJECT (bsrc, "remove format returned caps %" GST_PTR_FORMAT, tmp);
+
+ gl_caps =
+ gst_caps_merge (gst_caps_merge (gst_gl_test_src_set_caps_features (tmp,
+ GST_CAPS_FEATURE_MEMORY_GL_MEMORY),
+ gst_gl_test_src_set_caps_features (tmp,
+ GST_CAPS_FEATURE_MEMORY_EGL_IMAGE)),
+ gst_gl_test_src_set_caps_features (tmp,
+ GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META));
+ result =
+ gst_gl_download_transform_caps (src->context, GST_PAD_SINK, tmp, NULL);
+ result = gst_caps_merge (gl_caps, result);
+
+ gst_caps_unref (tmp);
+ tmp = result;
+ GST_DEBUG_OBJECT (bsrc, "transfer returned caps %" GST_PTR_FORMAT, tmp);
+
+ if (filter) {
+ result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (tmp);
+ } else {
+ result = tmp;
+ }
+
+ GST_DEBUG_OBJECT (bsrc, "returning caps: %" GST_PTR_FORMAT, result);
+
+ return result;
+}
+
static void
gst_gl_test_src_set_context (GstElement * element, GstContext * context)
{
return ret;
}
+GstCaps *
+gst_gl_color_convert_transform_caps (GstGLContext * convert,
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter)
+{
+ GstCaps *templ, *result, *tmp;
+
+ templ =
+ gst_caps_from_string (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+ (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, GST_GL_COLOR_CONVERT_FORMATS));
+
+ tmp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (templ);
+
+ if (filter) {
+ result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (tmp);
+ } else {
+ result = tmp;
+ }
+
+ return result;
+}
+
/**
* gst_gl_color_convert_perform:
* @convert: a #GstGLColorConvert
GstGLColorConvert * gst_gl_color_convert_new (GstGLContext * context);
+GstCaps * gst_gl_color_convert_transform_caps (GstGLContext * convert,
+ GstPadDirection direction,
+ GstCaps * caps,
+ GstCaps * filter);
gboolean gst_gl_color_convert_set_caps (GstGLColorConvert * convert,
GstCaps * in_caps,
GstCaps * out_caps);
GST_OBJECT_UNLOCK (download);
}
+static GstCaps *
+_set_caps_features (const GstCaps * caps, const gchar * feature_name)
+{
+ GstCaps *tmp = gst_caps_copy (caps);
+ guint n = gst_caps_get_size (tmp);
+ guint i = 0;
+
+ for (i = 0; i < n; i++) {
+ GstCapsFeatures *features = gst_caps_get_features (tmp, i);
+ if (features) {
+ guint n_f = gst_caps_features_get_size (features);
+ guint j = 0;
+ for (j = 0; j < n_f; j++) {
+ gst_caps_features_remove_id (features,
+ gst_caps_features_get_nth_id (features, j));
+ }
+ }
+
+ gst_caps_features_add (features, feature_name);
+ }
+
+ return tmp;
+}
+
+GstCaps *
+gst_gl_download_transform_caps (GstGLContext * context,
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter)
+{
+ GstCaps *gl_templ, *templ, *result, *tmp;
+
+ templ =
+ gst_caps_from_string (GST_VIDEO_CAPS_MAKE (GST_GL_COLOR_CONVERT_FORMATS));
+ gl_templ =
+ gst_caps_from_string (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+ (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, GST_GL_COLOR_CONVERT_FORMATS));
+
+ if (direction == GST_PAD_SRC) {
+ tmp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST);
+ result = _set_caps_features (tmp, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+ gst_caps_unref (tmp);
+ tmp = result;
+ } else {
+ tmp = gst_caps_ref (caps);
+ }
+
+ result =
+ gst_gl_color_convert_transform_caps (context, direction, tmp, filter);
+ gst_caps_unref (tmp);
+ tmp = result;
+
+ if (direction == GST_PAD_SINK) {
+ result = _set_caps_features (tmp, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
+ gst_caps_unref (tmp);
+ tmp = result;
+ result = gst_caps_intersect_full (tmp, templ, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (tmp);
+ tmp = result;
+ }
+
+ if (filter) {
+ result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (tmp);
+ } else {
+ result = tmp;
+ }
+ gst_caps_unref (templ);
+ gst_caps_unref (gl_templ);
+
+ return result;
+}
+
/**
* gst_gl_download_perform_with_data:
* @download: a #GstGLDownload
GstGLDownload * gst_gl_download_new (GstGLContext * context);
void gst_gl_download_set_format (GstGLDownload * download, GstVideoInfo * out_info);
+GstCaps * gst_gl_download_transform_caps (GstGLContext * convert,
+ GstPadDirection direction,
+ GstCaps * caps,
+ GstCaps * filter);
gboolean gst_gl_download_perform_with_data (GstGLDownload * download,
GLuint texture_id, GLuint texture_target,
return othercaps;
}
-
static GstCaps *
gst_gl_filter_set_caps_features (const GstCaps * caps,
const gchar * feature_name)
{
- GstCaps *tmp = gst_caps_copy (caps);
- guint n = gst_caps_get_size (tmp);
- guint i = 0;
-
- for (i = 0; i < n; i++) {
- GstCapsFeatures *features = gst_caps_get_features (tmp, i);
- if (features) {
- guint n_f = gst_caps_features_get_size (features);
- guint j = 0;
- for (j = 0; j < n_f; j++) {
- gst_caps_features_remove_id (features,
- gst_caps_features_get_nth_id (features, j));
- }
- }
-
- gst_caps_features_add (features, feature_name);
- gst_caps_set_simple (tmp, "format", G_TYPE_STRING, "RGBA", NULL);
- }
-
- return tmp;
+ GstCaps *ret = gst_gl_caps_replace_all_caps_features (caps, feature_name);
+ gst_caps_set_simple (ret, "format", G_TYPE_STRING, "RGBA", NULL);
+ return ret;
}
/* copies the given caps */
static GstCaps *
gst_gl_filter_transform_caps (GstBaseTransform * bt,
- GstPadDirection direction, GstCaps * caps, GstCaps * filter)
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter_caps)
{
+ GstGLFilter *filter = GST_GL_FILTER (bt);
GstCaps *tmp = NULL;
GstCaps *result = NULL;
- GstCaps *glcaps = gst_gl_filter_set_caps_features (caps,
- GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
-#if GST_GL_HAVE_PLATFORM_EGL
- GstCaps *eglcaps = gst_gl_filter_set_caps_features (caps,
- GST_CAPS_FEATURE_MEMORY_EGL_IMAGE);
-#endif
- GstCaps *uploadcaps = gst_gl_filter_set_caps_features (caps,
- GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META);
- GstCaps *raw_caps =
- gst_caps_from_string (GST_VIDEO_CAPS_MAKE (GST_GL_COLOR_CONVERT_FORMATS));
- tmp = gst_caps_new_empty ();
-
- tmp = gst_caps_merge (tmp, gst_gl_filter_caps_remove_format_info (glcaps));
-#if GST_GL_HAVE_PLATFORM_EGL
- tmp = gst_caps_merge (tmp, gst_gl_filter_caps_remove_format_info (eglcaps));
-#endif
- tmp =
- gst_caps_merge (tmp, gst_gl_filter_caps_remove_format_info (uploadcaps));
- tmp = gst_caps_merge (tmp, gst_gl_filter_caps_remove_format_info (raw_caps));
+ /* The following is the list of caps transformations performed. When
+ * direction == GST_PAD_SINK we start at the sinkpad and work toward the src
+ * pad and vice versa for direction == GST_PAD_SRC.
+ *
+ * sinkpad <-> (upload <-> convert) <-> filter (possible resize) <->
+ * (convert <-> download/output) <-> srcpad
+ */
+ if (direction == GST_PAD_SINK) {
+ result =
+ gst_gl_upload_transform_caps (filter->context, direction, caps, NULL);
+ tmp = result;
- tmp = gst_caps_merge (tmp, gst_gl_filter_caps_remove_format_info (caps));
+ result =
+ gst_gl_color_convert_transform_caps (filter->context, direction, tmp,
+ NULL);
+ gst_caps_unref (tmp);
+ } else {
+ GstCaps *gl_caps =
+ gst_caps_merge (gst_caps_merge (gst_gl_filter_set_caps_features (caps,
+ GST_CAPS_FEATURE_MEMORY_GL_MEMORY),
+ gst_gl_filter_set_caps_features (caps,
+ GST_CAPS_FEATURE_MEMORY_EGL_IMAGE)),
+ gst_gl_filter_set_caps_features (caps,
+ GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META));
+
+ result =
+ gst_gl_download_transform_caps (filter->context, direction, caps, NULL);
+
+ result = gst_caps_merge (gl_caps, result);
+ }
+ tmp = result;
+ GST_DEBUG_OBJECT (bt, "transfer returned caps %" GST_PTR_FORMAT, tmp);
+
+ result = gst_gl_filter_caps_remove_format_info (tmp);
+ gst_caps_unref (tmp);
+ tmp = result;
+ GST_DEBUG_OBJECT (bt, "remove format returned caps %" GST_PTR_FORMAT, tmp);
+
+ if (direction == GST_PAD_SRC) {
+ result =
+ gst_gl_color_convert_transform_caps (filter->context, direction, tmp,
+ NULL);
+ gst_caps_unref (tmp);
+ tmp = result;
+ result =
+ gst_gl_upload_transform_caps (filter->context, direction, tmp, NULL);
+ } else {
+ GstCaps *gl_caps =
+ gst_caps_merge (gst_caps_merge (gst_gl_filter_set_caps_features (tmp,
+ GST_CAPS_FEATURE_MEMORY_GL_MEMORY),
+ gst_gl_filter_set_caps_features (tmp,
+ GST_CAPS_FEATURE_MEMORY_EGL_IMAGE)),
+ gst_gl_filter_set_caps_features (tmp,
+ GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META));
+
+ result =
+ gst_gl_download_transform_caps (filter->context, direction, tmp, NULL);
+
+ result = gst_caps_merge (gl_caps, result);
+ }
+ gst_caps_unref (tmp);
+ tmp = result;
+ GST_DEBUG_OBJECT (bt, "transfer returned caps %" GST_PTR_FORMAT, tmp);
- if (filter) {
- result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
+ if (filter_caps) {
+ result =
+ gst_caps_intersect_full (filter_caps, tmp, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (tmp);
} else {
result = tmp;
GstQuery * decide_query, GstQuery * query)
{
GstGLFilter *filter = GST_GL_FILTER (trans);
- GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
GstBufferPool *pool;
GstStructure *config;
GstCaps *caps, *decide_caps;
guint size;
gboolean need_pool;
- GError *error = NULL;
- GstStructure *gl_context;
- gchar *platform, *gl_apis;
- gpointer handle;
- GstAllocator *allocator = NULL;
- GstAllocationParams params;
gst_query_parse_allocation (query, &caps, &need_pool);
gst_structure_free (config);
}
- if (!gst_gl_ensure_element_data (filter, &filter->display,
- &filter->other_context))
- return FALSE;
-
- gst_gl_display_filter_gl_api (filter->display,
- filter_class->supported_gl_api);
-
- if (!filter->context) {
- filter->context = gst_gl_context_new (filter->display);
- if (!gst_gl_context_create (filter->context, filter->other_context, &error))
- goto context_error;
- }
-
if (pool == NULL && need_pool) {
GstVideoInfo info;
GstBufferPool *decide_pool = NULL;
gst_object_unref (pool);
}
- /* we also support various metadata */
- gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
+ gst_gl_upload_propose_allocation (filter->upload, decide_query, query);
+
if (filter->context->gl_vtable->FenceSync)
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0);
- gl_apis = gst_gl_api_to_string (gst_gl_context_get_gl_api (filter->context));
- platform =
- gst_gl_platform_to_string (gst_gl_context_get_gl_platform
- (filter->context));
- handle = (gpointer) gst_gl_context_get_gl_context (filter->context);
-
- gl_context =
- gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext",
- GST_GL_TYPE_CONTEXT, filter->context, "gst.gl.context.handle",
- G_TYPE_POINTER, handle, "gst.gl.context.type", G_TYPE_STRING, platform,
- "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL);
- gst_query_add_allocation_meta (query,
- GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, gl_context);
-
- g_free (gl_apis);
- g_free (platform);
- gst_structure_free (gl_context);
-
- gst_allocation_params_init (¶ms);
-
- allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
- gst_query_add_allocation_param (query, allocator, ¶ms);
- gst_object_unref (allocator);
-
-#if GST_GL_HAVE_PLATFORM_EGL
- if (gst_gl_context_check_feature (filter->context, "EGL_KHR_image_base")) {
- allocator = gst_allocator_find (GST_EGL_IMAGE_MEMORY_TYPE);
- gst_query_add_allocation_param (query, allocator, ¶ms);
- gst_object_unref (allocator);
- }
-#endif
-
return TRUE;
/* ERRORS */
GST_DEBUG_OBJECT (trans, "failed setting config");
return FALSE;
}
-context_error:
- {
- GST_ELEMENT_ERROR (trans, RESOURCE, NOT_FOUND, ("%s", error->message),
- (NULL));
- return FALSE;
- }
}
static gboolean
guint in_width, in_height, out_width, out_height;
GstGLContext *other_context = NULL;
gboolean same_downstream_gl_context = FALSE;
+ GstCapsFeatures *uploaded_features;
+ GstCaps *uploaded_caps;
+ GstCapsFeatures *converted_features;
+ GstVideoInfo converted_info;
+
+ gst_query_parse_allocation (query, &caps, NULL);
+ if (!caps)
+ return FALSE;
if (!gst_gl_ensure_element_data (filter, &filter->display,
- &filter->other_context))
+ &filter->other_context)) {
return FALSE;
+ }
gst_gl_display_filter_gl_api (filter->display,
filter_class->supported_gl_api);
out_width = GST_VIDEO_INFO_WIDTH (&filter->out_info);
out_height = GST_VIDEO_INFO_HEIGHT (&filter->out_info);
+ if (!filter->upload) {
+ filter->upload = gst_gl_upload_new (filter->context);
+ }
+
+ uploaded_caps = gst_caps_copy (caps);
+ uploaded_features =
+ gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+ gst_caps_set_features (uploaded_caps, 0, uploaded_features);
+
+ if (!gst_gl_upload_set_caps (filter->upload, caps, uploaded_caps)) {
+ gst_caps_unref (uploaded_caps);
+ return FALSE;
+ }
+
+ if (!filter->in_convert) {
+ filter->in_convert = gst_gl_color_convert_new (filter->context);
+ }
+
+ gst_video_info_set_format (&converted_info, GST_VIDEO_FORMAT_RGBA,
+ in_width, in_height);
+ converted_features =
+ gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+
+ if (filter->in_converted_caps)
+ gst_caps_unref (filter->in_converted_caps);
+ filter->in_converted_caps = gst_video_info_to_caps (&converted_info);
+ gst_caps_set_features (filter->in_converted_caps, 0, converted_features);
+
+ if (!gst_gl_color_convert_set_caps (filter->in_convert, uploaded_caps,
+ filter->in_converted_caps)) {
+ gst_caps_unref (uploaded_caps);
+ return FALSE;
+ }
+ gst_caps_unref (uploaded_caps);
+
if (filter->fbo) {
gst_gl_context_del_fbo (filter->context, filter->fbo, filter->depthbuffer);
filter->fbo = 0;
goto error;
}
- gst_query_parse_allocation (query, &caps, NULL);
-
if (gst_query_get_n_allocation_pools (query) > 0) {
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
gst_buffer_pool_set_config (pool, config);
- if (filter->upload) {
- gst_object_unref (filter->upload);
- filter->upload = NULL;
- }
-
if (update_pool)
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
else
if (!filter->display)
return GST_FLOW_NOT_NEGOTIATED;
- if (!filter->upload) {
- GstCaps *in_caps =
- gst_pad_get_current_caps (GST_BASE_TRANSFORM_SINK_PAD (bt));
- GstCaps *uploaded_caps;
- GstCapsFeatures *out_features;
- GstVideoInfo out_info;
-
- gst_video_info_set_format (&out_info,
- GST_VIDEO_FORMAT_RGBA,
- GST_VIDEO_INFO_WIDTH (&filter->in_info),
- GST_VIDEO_INFO_HEIGHT (&filter->in_info));
- out_features =
- gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
-
- uploaded_caps = gst_caps_copy (in_caps);
- gst_caps_set_features (uploaded_caps, 0, out_features);
-
- filter->upload = gst_gl_upload_new (filter->context);
- if (!gst_gl_upload_set_caps (filter->upload, in_caps, uploaded_caps)) {
- gst_caps_unref (in_caps);
- return GST_FLOW_ERROR;
- }
-
- gst_caps_unref (in_caps);
-
- if (!filter->in_convert) {
- GstCapsFeatures *converted_features;
- GstVideoInfo converted_info;
-
- gst_video_info_set_format (&converted_info,
- GST_VIDEO_FORMAT_RGBA,
- GST_VIDEO_INFO_WIDTH (&filter->in_info),
- GST_VIDEO_INFO_HEIGHT (&filter->in_info));
- converted_features =
- gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
-
- if (filter->in_converted_caps)
- gst_caps_unref (filter->in_converted_caps);
- filter->in_converted_caps = gst_video_info_to_caps (&converted_info);
- gst_caps_set_features (filter->in_converted_caps, 0, converted_features);
-
- filter->in_convert = gst_gl_color_convert_new (filter->context);
- if (!gst_gl_color_convert_set_caps (filter->in_convert, uploaded_caps,
- filter->in_converted_caps)) {
- gst_caps_unref (uploaded_caps);
- return GST_FLOW_ERROR;
- }
- }
-
- gst_caps_unref (uploaded_caps);
- }
-
g_assert (filter_class->filter || filter_class->filter_texture);
in_sync_meta = gst_buffer_get_gl_sync_meta (inbuf);
GstBuffer *outbuf;
+ /* all method impl pointers */
+ gpointer *upload_impl;
+
+ /* current method */
const UploadMethod *method;
gpointer method_impl;
int method_i;
};
+static GstCaps *
+_set_caps_features (const GstCaps * caps, const gchar * feature_name)
+{
+ GstCaps *tmp = gst_caps_copy (caps);
+ guint n = gst_caps_get_size (tmp);
+ guint i = 0;
+
+ for (i = 0; i < n; i++) {
+ GstCapsFeatures *features = gst_caps_get_features (tmp, i);
+ if (features) {
+ guint n_f = gst_caps_features_get_size (features);
+ guint j = 0;
+ for (j = 0; j < n_f; j++) {
+ gst_caps_features_remove_id (features,
+ gst_caps_features_get_nth_id (features, j));
+ }
+ }
+
+ gst_caps_features_add (features, feature_name);
+ }
+
+ return tmp;
+}
+
typedef enum
{
METHOD_FLAG_CAN_SHARE_CONTEXT = 1,
GstGLUploadMethodFlags flags;
gpointer (*new) (GstGLUpload * upload);
+ GstCaps *(*transform_caps) (GstGLContext * context,
+ GstPadDirection direction, GstCaps * caps);
gboolean (*accept) (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
GstCaps * out_caps);
+ void (*propose_allocation) (gpointer impl, GstQuery * decide_query,
+ GstQuery * query);
GstGLUploadReturn (*perform) (gpointer impl, GstBuffer * buffer,
GstBuffer ** outbuf);
void (*release) (gpointer impl, GstBuffer * buffer);
return mem;
}
+static GstCaps *
+_gl_memory_upload_transform_caps (GstGLContext * context,
+ GstPadDirection direction, GstCaps * caps)
+{
+ return _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+}
+
static gboolean
_gl_memory_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
GstCaps * out_caps)
return TRUE;
}
+static void
+_gl_memory_upload_propose_allocation (gpointer impl, GstQuery * decide_query,
+ GstQuery * query)
+{
+ GstAllocationParams params;
+ GstAllocator *allocator;
+
+ gst_allocation_params_init (¶ms);
+
+ allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
+ gst_query_add_allocation_param (query, allocator, ¶ms);
+ gst_object_unref (allocator);
+}
+
static GstGLUploadReturn
_gl_memory_upload_perform (gpointer impl, GstBuffer * buffer,
GstBuffer ** outbuf)
"GLMemory",
METHOD_FLAG_CAN_SHARE_CONTEXT,
&_gl_memory_upload_new,
+ &_gl_memory_upload_transform_caps,
&_gl_memory_upload_accept,
+ &_gl_memory_upload_propose_allocation,
&_gl_memory_upload_perform,
&_gl_memory_upload_release,
&_gl_memory_upload_free
return image;
}
+static GstCaps *
+_egl_image_upload_transform_caps (GstGLContext * context,
+ GstPadDirection direction, GstCaps * caps)
+{
+ GstCaps *ret;
+
+ if (direction == GST_PAD_SINK) {
+ ret = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+ } else {
+ ret = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_EGL_IMAGE);
+ }
+
+ return ret;
+}
+
static gboolean
_egl_image_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
GstCaps * out_caps)
return TRUE;
}
+static void
+_egl_image_upload_propose_allocation (gpointer impl, GstQuery * decide_query,
+ GstQuery * query)
+{
+ struct EGLImageUpload *image = impl;
+ GstAllocationParams params;
+ GstAllocator *allocator;
+
+ gst_allocation_params_init (¶ms);
+
+ if (gst_gl_context_check_feature (image->upload->context,
+ "EGL_KHR_image_base")) {
+ allocator = gst_allocator_find (GST_EGL_IMAGE_MEMORY_TYPE);
+ gst_query_add_allocation_param (query, allocator, ¶ms);
+ gst_object_unref (allocator);
+ }
+}
+
static GstGLUploadReturn
_egl_image_upload_perform (gpointer impl, GstBuffer * buffer,
GstBuffer ** outbuf)
"EGLImage",
0,
&_egl_image_upload_new,
+ &_egl_image_upload_transform_caps,
&_egl_image_upload_accept,
+ &_egl_image_upload_propose_allocation,
&_egl_image_upload_perform,
&_egl_image_upload_release,
&_egl_image_upload_free
return meta;
}
+static GstCaps *
+_upload_meta_upload_transform_caps (GstGLContext * context,
+ GstPadDirection direction, GstCaps * caps)
+{
+ GstCaps *ret;
+
+ if (direction == GST_PAD_SINK) {
+ ret = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+ } else {
+ ret =
+ _set_caps_features (caps,
+ GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META);
+ }
+
+ return ret;
+}
+
static gboolean
_upload_meta_upload_accept (gpointer impl, GstBuffer * buffer,
GstCaps * in_caps, GstCaps * out_caps)
return TRUE;
}
+static void
+_upload_meta_upload_propose_allocation (gpointer impl, GstQuery * decide_query,
+ GstQuery * query)
+{
+ struct GLUploadMeta *upload = impl;
+ GstStructure *gl_context;
+ gchar *platform, *gl_apis;
+ gpointer handle;
+
+ gl_apis =
+ gst_gl_api_to_string (gst_gl_context_get_gl_api (upload->upload->
+ context));
+ platform =
+ gst_gl_platform_to_string (gst_gl_context_get_gl_platform (upload->
+ upload->context));
+ handle = (gpointer) gst_gl_context_get_gl_context (upload->upload->context);
+
+ gl_context =
+ gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext",
+ GST_GL_TYPE_CONTEXT, upload->upload->context, "gst.gl.context.handle",
+ G_TYPE_POINTER, handle, "gst.gl.context.type", G_TYPE_STRING, platform,
+ "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL);
+ gst_query_add_allocation_meta (query,
+ GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, gl_context);
+
+ g_free (gl_apis);
+ g_free (platform);
+ gst_structure_free (gl_context);
+}
+
/*
* Uploads using gst_video_gl_texture_upload_meta_upload().
* i.e. consumer of GstVideoGLTextureUploadMeta
"UploadMeta",
METHOD_FLAG_CAN_SHARE_CONTEXT,
&_upload_meta_upload_new,
+ &_upload_meta_upload_transform_caps,
&_upload_meta_upload_accept,
+ &_upload_meta_upload_propose_allocation,
&_upload_meta_upload_perform,
&_upload_meta_upload_release,
&_upload_meta_upload_free
return raw;
}
+static GstCaps *
+_raw_data_upload_transform_caps (GstGLContext * context,
+ GstPadDirection direction, GstCaps * caps)
+{
+ GstCaps *ret;
+
+ if (direction == GST_PAD_SINK) {
+ ret = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+ } else {
+ ret = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
+ }
+
+ return ret;
+}
+
static gboolean
_raw_data_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
GstCaps * out_caps)
return TRUE;
}
+static void
+_raw_data_upload_propose_allocation (gpointer impl, GstQuery * decide_query,
+ GstQuery * query)
+{
+ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
+}
+
static GstGLUploadReturn
_raw_data_upload_perform (gpointer impl, GstBuffer * buffer,
GstBuffer ** outbuf)
"Raw Data",
0,
&_raw_data_upload_new,
+ &_raw_data_upload_transform_caps,
&_raw_data_upload_accept,
+ &_raw_data_upload_propose_allocation,
&_raw_data_upload_perform,
&_raw_data_upload_release,
&_raw_data_upload_free
gst_gl_upload_new (GstGLContext * context)
{
GstGLUpload *upload = g_object_new (GST_TYPE_GL_UPLOAD, NULL);
+ gint i, n;
upload->context = gst_object_ref (context);
+ n = G_N_ELEMENTS (upload_methods);
+ upload->priv->upload_impl = g_malloc (sizeof (gpointer) * n);
+ for (i = 0; i < n; i++) {
+ upload->priv->upload_impl[i] = upload_methods[i]->new (upload);
+ }
+
return upload;
}
gst_gl_upload_finalize (GObject * object)
{
GstGLUpload *upload;
+ gint i, n;
upload = GST_GL_UPLOAD (object);
upload->priv->out_caps = NULL;
}
+ n = G_N_ELEMENTS (upload_methods);
+ for (i = 0; i < n; i++) {
+ if (upload->priv->upload_impl[i])
+ upload_methods[i]->free (upload->priv->upload_impl[i]);
+ }
+ g_free (upload->priv->upload_impl);
+
G_OBJECT_CLASS (gst_gl_upload_parent_class)->finalize (object);
}
+GstCaps *
+gst_gl_upload_transform_caps (GstGLContext * context, GstPadDirection direction,
+ GstCaps * caps, GstCaps * filter)
+{
+ GstCaps *result, *tmp;
+ gint i;
+
+ tmp = gst_caps_new_empty ();
+
+ for (i = 0; i < G_N_ELEMENTS (upload_methods); i++) {
+ GstCaps *tmp2 =
+ upload_methods[i]->transform_caps (context, direction, caps);
+
+ if (tmp2)
+ tmp = gst_caps_merge (tmp, tmp2);
+ }
+
+ if (filter) {
+ result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (tmp);
+ } else {
+ result = tmp;
+ }
+
+ return result;
+}
+
+/**
+ * gst_gl_upload_propose_allocation:
+ * @upload: a #GstGLUpload
+ * @decide_query: (allow-none): a #GstQuery from a decide allocation
+ * @query: the proposed allocation query
+ *
+ * Adds the required allocation parameters to support uploading.
+ */
+void
+gst_gl_upload_propose_allocation (GstGLUpload * upload, GstQuery * decide_query,
+ GstQuery * query)
+{
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (upload_methods); i++)
+ upload_methods[i]->propose_allocation (upload->priv->upload_impl[i],
+ decide_query, query);
+}
+
static gboolean
_gst_gl_upload_set_caps_unlocked (GstGLUpload * upload, GstCaps * in_caps,
GstCaps * out_caps)
GstObjectClass object_class;
};
-GstGLUpload * gst_gl_upload_new (GstGLContext * context);
-
-gboolean gst_gl_upload_set_caps (GstGLUpload * upload, GstCaps * in_caps, GstCaps * out_caps);
-void gst_gl_upload_get_caps (GstGLUpload * upload, GstCaps ** in_caps, GstCaps ** out_caps);
-
-GstGLUploadReturn gst_gl_upload_perform_with_buffer (GstGLUpload * upload, GstBuffer * buffer, GstBuffer ** outbuf);
-void gst_gl_upload_release_buffer (GstGLUpload * upload);
+GstGLUpload * gst_gl_upload_new (GstGLContext * context);
+
+GstCaps * gst_gl_upload_transform_caps (GstGLContext * context,
+ GstPadDirection direction,
+ GstCaps * caps,
+ GstCaps * filter);
+gboolean gst_gl_upload_set_caps (GstGLUpload * upload,
+ GstCaps * in_caps,
+ GstCaps * out_caps);
+void gst_gl_upload_get_caps (GstGLUpload * upload,
+ GstCaps ** in_caps,
+ GstCaps ** out_caps);
+void gst_gl_upload_propose_allocation (GstGLUpload * upload,
+ GstQuery * decide_query,
+ GstQuery * query);
+
+GstGLUploadReturn gst_gl_upload_perform_with_buffer (GstGLUpload * upload,
+ GstBuffer * buffer,
+ GstBuffer ** outbuf);
+void gst_gl_upload_release_buffer (GstGLUpload * upload);
G_END_DECLS
return plane_size;
}
+
+GstCaps *
+gst_gl_caps_replace_all_caps_features (const GstCaps * caps,
+ const gchar * feature_name)
+{
+ GstCaps *tmp = gst_caps_copy (caps);
+ guint n = gst_caps_get_size (tmp);
+ guint i = 0;
+
+ for (i = 0; i < n; i++) {
+ GstCapsFeatures *features = gst_caps_get_features (tmp, i);
+ if (features) {
+ guint n_f = gst_caps_features_get_size (features);
+ guint j = 0;
+ for (j = 0; j < n_f; j++) {
+ gst_caps_features_remove_id (features,
+ gst_caps_features_get_nth_id (features, j));
+ }
+ }
+
+ gst_caps_features_add (features, feature_name);
+ }
+
+ return tmp;
+}
gsize gst_gl_get_plane_data_size (GstVideoInfo * info, GstVideoAlignment * align,
guint plane);
+GstCaps * gst_gl_caps_replace_all_caps_features (const GstCaps * caps,
+ const gchar * feature_name);
G_END_DECLS