gl: Add support for multiple views in upload, colour convert and download

Support multiple attached views on input/output buffers
by processing each one, not just the first.
This commit is contained in:
Jan Schmidt 2015-05-30 02:15:51 +10:00 committed by Tim-Philipp Müller
parent 1f7025c585
commit 8a1fc4ab4e
5 changed files with 276 additions and 102 deletions

View file

@ -614,6 +614,9 @@ _gst_gl_color_convert_set_caps_unlocked (GstGLColorConvert * convert,
g_return_val_if_fail (in_caps, FALSE); g_return_val_if_fail (in_caps, FALSE);
g_return_val_if_fail (out_caps, FALSE); g_return_val_if_fail (out_caps, FALSE);
GST_LOG_OBJECT (convert, "Setting caps in %" GST_PTR_FORMAT
" out %" GST_PTR_FORMAT, in_caps, out_caps);
if (!gst_video_info_from_caps (&in_info, in_caps)) if (!gst_video_info_from_caps (&in_info, in_caps))
g_assert_not_reached (); g_assert_not_reached ();
@ -1507,38 +1510,27 @@ _init_convert_fbo (GstGLColorConvert * convert)
return TRUE; return TRUE;
} }
/* Called by the idle function in the gl thread */ static gboolean
void _do_convert_one_view (GstGLContext * context, GstGLColorConvert * convert,
_do_convert (GstGLContext * context, GstGLColorConvert * convert) guint view_num)
{ {
guint in_width, in_height, out_width, out_height; guint in_width, in_height, out_width, out_height;
struct ConvertInfo *c_info = &convert->priv->convert_info; struct ConvertInfo *c_info = &convert->priv->convert_info;
GstMapInfo out_info[GST_VIDEO_MAX_PLANES], in_info[GST_VIDEO_MAX_PLANES]; GstMapInfo out_info[GST_VIDEO_MAX_PLANES], in_info[GST_VIDEO_MAX_PLANES];
gboolean res = TRUE; gboolean res = TRUE;
gint i, j = 0; gint i, j = 0;
const gint in_plane_offset = view_num * c_info->in_n_textures;
const gint out_plane_offset = view_num * c_info->out_n_textures;
out_width = GST_VIDEO_INFO_WIDTH (&convert->out_info); out_width = GST_VIDEO_INFO_WIDTH (&convert->out_info);
out_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info); out_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info);
in_width = GST_VIDEO_INFO_WIDTH (&convert->in_info); in_width = GST_VIDEO_INFO_WIDTH (&convert->in_info);
in_height = GST_VIDEO_INFO_HEIGHT (&convert->in_info); in_height = GST_VIDEO_INFO_HEIGHT (&convert->in_info);
convert->outbuf = NULL;
if (!_init_convert (convert)) {
convert->priv->result = FALSE;
return;
}
convert->outbuf = gst_buffer_new ();
if (!gst_gl_memory_setup_buffer (convert->context, NULL, &convert->out_info,
NULL, convert->outbuf)) {
convert->priv->result = FALSE;
return;
}
for (i = 0; i < c_info->in_n_textures; i++) { for (i = 0; i < c_info->in_n_textures; i++) {
convert->priv->in_tex[i] = convert->priv->in_tex[i] =
(GstGLMemory *) gst_buffer_peek_memory (convert->inbuf, i); (GstGLMemory *) gst_buffer_peek_memory (convert->inbuf,
i + in_plane_offset);
if (!gst_is_gl_memory ((GstMemory *) convert->priv->in_tex[i])) { if (!gst_is_gl_memory ((GstMemory *) convert->priv->in_tex[i])) {
GST_ERROR_OBJECT (convert, "input must be GstGLMemory"); GST_ERROR_OBJECT (convert, "input must be GstGLMemory");
res = FALSE; res = FALSE;
@ -1555,7 +1547,8 @@ _do_convert (GstGLContext * context, GstGLColorConvert * convert)
for (j = 0; j < c_info->out_n_textures; j++) { for (j = 0; j < c_info->out_n_textures; j++) {
GstGLMemory *out_tex = GstGLMemory *out_tex =
(GstGLMemory *) gst_buffer_peek_memory (convert->outbuf, j); (GstGLMemory *) gst_buffer_peek_memory (convert->outbuf,
j + out_plane_offset);
gint mem_width, mem_height; gint mem_width, mem_height;
if (!gst_is_gl_memory ((GstMemory *) out_tex)) { if (!gst_is_gl_memory ((GstMemory *) out_tex)) {
@ -1608,7 +1601,8 @@ _do_convert (GstGLContext * context, GstGLColorConvert * convert)
out: out:
for (j--; j >= 0; j--) { for (j--; j >= 0; j--) {
GstGLMemory *out_tex = GstGLMemory *out_tex =
(GstGLMemory *) gst_buffer_peek_memory (convert->outbuf, j); (GstGLMemory *) gst_buffer_peek_memory (convert->outbuf,
j + out_plane_offset);
gint mem_width, mem_height; gint mem_width, mem_height;
gst_memory_unmap ((GstMemory *) convert->priv->out_tex[j], &out_info[j]); gst_memory_unmap ((GstMemory *) convert->priv->out_tex[j], &out_info[j]);
@ -1647,17 +1641,54 @@ out:
/* YV12 the same as I420 except planes 1+2 swapped */ /* YV12 the same as I420 except planes 1+2 swapped */
if (GST_VIDEO_INFO_FORMAT (&convert->out_info) == GST_VIDEO_FORMAT_YV12) { if (GST_VIDEO_INFO_FORMAT (&convert->out_info) == GST_VIDEO_FORMAT_YV12) {
GstMemory *mem1 = gst_buffer_get_memory (convert->outbuf, 1); GstMemory *mem1 =
GstMemory *mem2 = gst_buffer_get_memory (convert->outbuf, 2); gst_buffer_get_memory (convert->outbuf, 1 + out_plane_offset);
GstMemory *mem2 =
gst_buffer_get_memory (convert->outbuf, 2 + out_plane_offset);
gst_buffer_replace_memory (convert->outbuf, 1, mem2); gst_buffer_replace_memory (convert->outbuf, 1 + out_plane_offset, mem2);
gst_buffer_replace_memory (convert->outbuf, 2, mem1); gst_buffer_replace_memory (convert->outbuf, 2 + out_plane_offset, mem1);
} }
for (i--; i >= 0; i--) { for (i--; i >= 0; i--) {
gst_memory_unmap ((GstMemory *) convert->priv->in_tex[i], &in_info[i]); gst_memory_unmap ((GstMemory *) convert->priv->in_tex[i], &in_info[i]);
} }
return res;
}
/* Called by the idle function in the gl thread */
void
_do_convert (GstGLContext * context, GstGLColorConvert * convert)
{
GstVideoInfo *in_info = &convert->in_info;
gboolean res = TRUE;
gint views, v;
convert->outbuf = NULL;
if (!_init_convert (convert)) {
convert->priv->result = FALSE;
return;
}
convert->outbuf = gst_buffer_new ();
if (!gst_gl_memory_setup_buffer (convert->context, NULL, &convert->out_info,
NULL, convert->outbuf)) {
convert->priv->result = FALSE;
return;
}
if (GST_VIDEO_INFO_MULTIVIEW_MODE (in_info) ==
GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
views = GST_VIDEO_INFO_VIEWS (in_info);
else
views = 1;
/* Handle all views on input and output one at a time */
for (v = 0; res && v < views; v++)
res = _do_convert_one_view (context, convert, v);
if (!res) { if (!res) {
gst_buffer_unref (convert->outbuf); gst_buffer_unref (convert->outbuf);
convert->outbuf = NULL; convert->outbuf = NULL;

View file

@ -43,8 +43,7 @@
#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) #define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) #define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
static gboolean _do_download (GstGLDownload * download, guint texture_id, static gboolean _do_download (GstGLDownload * download, GstBuffer * inbuf);
gpointer data[GST_VIDEO_MAX_PLANES]);
static gboolean _init_download (GstGLDownload * download); static gboolean _init_download (GstGLDownload * download);
static gboolean _gst_gl_download_perform_with_data_unlocked (GstGLDownload * static gboolean _gst_gl_download_perform_with_data_unlocked (GstGLDownload *
download, GLuint texture_id, GLuint texture_target, download, GLuint texture_id, GLuint texture_target,
@ -52,6 +51,9 @@ static gboolean _gst_gl_download_perform_with_data_unlocked (GstGLDownload *
static void gst_gl_download_reset (GstGLDownload * download); static void gst_gl_download_reset (GstGLDownload * download);
/* *INDENT-ON* */ /* *INDENT-ON* */
/* Define the maximum number of planes we can handle - max 2 views per buffer */
#define GST_GL_DOWNLOAD_MAX_VIEWS 2
#define GST_GL_DOWNLOAD_MAX_PLANES (GST_VIDEO_MAX_PLANES * GST_GL_DOWNLOAD_MAX_VIEWS)
struct _GstGLDownloadPrivate struct _GstGLDownloadPrivate
{ {
@ -61,7 +63,12 @@ struct _GstGLDownloadPrivate
const gchar *ARGB; const gchar *ARGB;
const gchar *vert_shader; const gchar *vert_shader;
GstGLMemory *in_tex[GST_VIDEO_MAX_PLANES]; GstBuffer *inbuf;
/* Temporary wrapped texture for perform_with_data download */
GstGLMemory *in_tex;
/* Output data planes */
gpointer out_data[GST_GL_DOWNLOAD_MAX_PLANES];
}; };
GST_DEBUG_CATEGORY_STATIC (gst_gl_download_debug); GST_DEBUG_CATEGORY_STATIC (gst_gl_download_debug);
@ -138,13 +145,9 @@ gst_gl_download_finalize (GObject * object)
static void static void
gst_gl_download_reset (GstGLDownload * download) gst_gl_download_reset (GstGLDownload * download)
{ {
guint i; if (download->priv->in_tex) {
gst_memory_unref ((GstMemory *) download->priv->in_tex);
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { download->priv->in_tex = NULL;
if (download->priv->in_tex[i]) {
gst_memory_unref ((GstMemory *) download->priv->in_tex[i]);
download->priv->in_tex[i] = NULL;
}
} }
} }
@ -250,7 +253,9 @@ gst_gl_download_transform_caps (GstGLContext * context,
* @data: (out): where the downloaded data should go * @data: (out): where the downloaded data should go
* *
* Downloads @texture_id into @data. @data size and format is specified by * Downloads @texture_id into @data. @data size and format is specified by
* the #GstVideoFormat passed to gst_gl_download_set_format() * the #GstVideoFormat passed to gst_gl_download_set_format()
*
* This method can only be used for download a single view.
* *
* Returns: whether the download was successful * Returns: whether the download was successful
*/ */
@ -272,12 +277,16 @@ gst_gl_download_perform_with_data (GstGLDownload * download,
return ret; return ret;
} }
/* This method only supports one input texture */
static gboolean static gboolean
_gst_gl_download_perform_with_data_unlocked (GstGLDownload * download, _gst_gl_download_perform_with_data_unlocked (GstGLDownload * download,
GLuint texture_id, GLuint texture_target, GLuint texture_id, GLuint texture_target,
gpointer data[GST_VIDEO_MAX_PLANES]) gpointer data[GST_VIDEO_MAX_PLANES])
{ {
guint i; guint i;
gboolean res;
GstBuffer *inbuf;
guint out_width, out_height;
g_return_val_if_fail (download != NULL, FALSE); g_return_val_if_fail (download != NULL, FALSE);
g_return_val_if_fail (texture_id > 0, FALSE); g_return_val_if_fail (texture_id > 0, FALSE);
@ -290,36 +299,54 @@ _gst_gl_download_perform_with_data_unlocked (GstGLDownload * download,
g_return_val_if_fail (data[i] != NULL, FALSE); g_return_val_if_fail (data[i] != NULL, FALSE);
} }
if (!download->priv->in_tex[0]) { if (!download->priv->in_tex) {
GstVideoInfo temp_info; GstVideoInfo temp_info;
gst_video_info_set_format (&temp_info, GST_VIDEO_FORMAT_RGBA, gst_video_info_set_format (&temp_info, GST_VIDEO_FORMAT_RGBA,
GST_VIDEO_INFO_WIDTH (&download->info), GST_VIDEO_INFO_WIDTH (&download->info),
GST_VIDEO_INFO_HEIGHT (&download->info)); GST_VIDEO_INFO_HEIGHT (&download->info));
download->priv->in_tex[0] = download->priv->in_tex =
gst_gl_memory_wrapped_texture (download->context, gst_gl_memory_wrapped_texture (download->context,
texture_id, texture_target, &temp_info, 0, NULL, NULL, NULL); texture_id, texture_target, &temp_info, 0, NULL, NULL, NULL);
} }
download->priv->in_tex[0]->tex_id = texture_id;
return _do_download (download, texture_id, data); out_width = GST_VIDEO_INFO_WIDTH (&download->info);
out_height = GST_VIDEO_INFO_HEIGHT (&download->info);
GST_TRACE ("doing download of texture:%u (%ux%u)",
download->priv->in_tex->tex_id, out_width, out_height);
download->priv->in_tex->tex_id = texture_id;
inbuf = gst_buffer_new ();
gst_buffer_append_memory (inbuf,
gst_memory_ref ((GstMemory *) download->priv->in_tex));
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++)
download->priv->out_data[i] = data[i];
/* Clear remaining planes for safety */
while (i < GST_GL_DOWNLOAD_MAX_PLANES)
download->priv->out_data[i++] = NULL;
res = _do_download (download, inbuf);
download->priv->inbuf = NULL;
gst_buffer_unref (inbuf);
return res;
} }
static gboolean static gboolean
_init_download (GstGLDownload * download) _init_download (GstGLDownload * download)
{ {
GstVideoFormat v_format; GstVideoFormat v_format;
guint out_width, out_height;
GstVideoInfo in_info;
GstCaps *in_caps, *out_caps; GstCaps *in_caps, *out_caps;
GstCapsFeatures *in_gl_features, *out_gl_features; GstCapsFeatures *out_gl_features;
gboolean res; gboolean res;
v_format = GST_VIDEO_INFO_FORMAT (&download->info); v_format = GST_VIDEO_INFO_FORMAT (&download->info);
out_width = GST_VIDEO_INFO_WIDTH (&download->info);
out_height = GST_VIDEO_INFO_HEIGHT (&download->info);
if (download->initted) if (download->initted)
return TRUE; return TRUE;
@ -336,18 +363,14 @@ _init_download (GstGLDownload * download)
} }
} }
in_gl_features =
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
gst_video_info_set_format (&in_info, GST_VIDEO_FORMAT_RGBA, out_width,
out_height);
in_caps = gst_video_info_to_caps (&in_info);
gst_caps_set_features (in_caps, 0, in_gl_features);
out_gl_features = out_gl_features =
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY); gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
out_caps = gst_video_info_to_caps (&download->info); out_caps = gst_video_info_to_caps (&download->info);
gst_caps_set_features (out_caps, 0, out_gl_features); gst_caps_set_features (out_caps, 0, out_gl_features);
in_caps = gst_caps_copy (out_caps);
gst_caps_set_simple (in_caps, "format", G_TYPE_STRING, "RGBA", NULL);
res = gst_gl_color_convert_set_caps (download->convert, in_caps, out_caps); res = gst_gl_color_convert_set_caps (download->convert, in_caps, out_caps);
gst_caps_unref (in_caps); gst_caps_unref (in_caps);
@ -357,35 +380,38 @@ _init_download (GstGLDownload * download)
} }
static gboolean static gboolean
_do_download (GstGLDownload * download, guint texture_id, _do_download (GstGLDownload * download, GstBuffer * inbuf)
gpointer data[GST_VIDEO_MAX_PLANES])
{ {
guint out_width, out_height; GstBuffer *outbuf;
GstBuffer *inbuf, *outbuf;
GstMapInfo map_info; GstMapInfo map_info;
gboolean ret = TRUE; gboolean ret = TRUE;
gint i; gint i;
GstVideoInfo *info;
out_width = GST_VIDEO_INFO_WIDTH (&download->info); guint views, out_planes;
out_height = GST_VIDEO_INFO_HEIGHT (&download->info); gpointer *data = download->priv->out_data;
if (!download->initted) { if (!download->initted) {
if (!_init_download (download)) if (!_init_download (download)) {
GST_DEBUG_OBJECT (download, "Failed to initialise");
return FALSE; return FALSE;
}
} }
GST_TRACE ("doing download of texture:%u (%ux%u)",
download->priv->in_tex[0]->tex_id, out_width, out_height);
inbuf = gst_buffer_new ();
gst_buffer_append_memory (inbuf,
gst_memory_ref ((GstMemory *) download->priv->in_tex[0]));
outbuf = gst_gl_color_convert_perform (download->convert, inbuf); outbuf = gst_gl_color_convert_perform (download->convert, inbuf);
if (!outbuf) if (!outbuf) {
GST_DEBUG_OBJECT (download, "Failed to colour convert for output");
return FALSE; return FALSE;
}
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&download->info); i++) { info = &download->info;
if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) ==
GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
views = GST_VIDEO_INFO_VIEWS (info);
else
views = 1;
out_planes = GST_VIDEO_INFO_N_PLANES (info) * views;
for (i = 0; i < out_planes; i++) {
GstMemory *out_mem = gst_buffer_peek_memory (outbuf, i); GstMemory *out_mem = gst_buffer_peek_memory (outbuf, i);
gpointer temp_data = ((GstGLMemory *) out_mem)->data; gpointer temp_data = ((GstGLMemory *) out_mem)->data;
((GstGLMemory *) out_mem)->data = data[i]; ((GstGLMemory *) out_mem)->data = data[i];
@ -400,8 +426,80 @@ _do_download (GstGLDownload * download, guint texture_id,
((GstGLMemory *) out_mem)->data = temp_data; ((GstGLMemory *) out_mem)->data = temp_data;
} }
gst_buffer_unref (inbuf);
gst_buffer_unref (outbuf); gst_buffer_unref (outbuf);
return ret; return ret;
} }
static gboolean
_gst_gl_download_perform_unlocked (GstGLDownload * download,
GstBuffer * inbuf, GstBuffer * outbuf)
{
guint i;
gboolean res = FALSE;
guint out_width, out_height;
GstVideoFrame out_frame;
g_return_val_if_fail (download != NULL, FALSE);
g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (&download->info) !=
GST_VIDEO_FORMAT_UNKNOWN
&& GST_VIDEO_INFO_FORMAT (&download->info) != GST_VIDEO_FORMAT_ENCODED,
FALSE);
out_width = GST_VIDEO_INFO_WIDTH (&download->info);
out_height = GST_VIDEO_INFO_HEIGHT (&download->info);
GST_TRACE_OBJECT (download, "doing download of buffer %" GST_PTR_FORMAT
" (%ux%u)", inbuf, out_width, out_height);
/* FIXME: Map multiple views */
if (!gst_video_frame_map (&out_frame, &download->info, outbuf, GST_MAP_WRITE))
return FALSE;
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&download->info); i++) {
if (out_frame.data[i] == NULL)
goto fail;
download->priv->out_data[i] = out_frame.data[i];
}
while (i < GST_GL_DOWNLOAD_MAX_PLANES)
download->priv->out_data[i++] = NULL;
res = _do_download (download, inbuf);
fail:
gst_video_frame_unmap (&out_frame);
download->priv->inbuf = NULL;
return res;
}
/**
* gst_gl_download_perform:
* @download: a #GstGLDownload
* @inbuf: (transfer none): a #GstBuffer input buffer
* @outbuf: (transfer none) (out): a #GstBuffer output buffer
*
* Downloads the contents of @inbuf into @outbuf.
*
* The output buffer contents must match the #GstVideoFormat passed
* to gst_gl_download_set_format(), and the input buffer must
* contain #GstGLMemory memory items.
*
* This method supports downloading multiple views.
*
* Returns: whether the download was successful
*/
gboolean
gst_gl_download_perform (GstGLDownload * download,
GstBuffer * inbuf, GstBuffer * outbuf)
{
gboolean ret;
g_return_val_if_fail (download != NULL, FALSE);
GST_OBJECT_LOCK (download);
ret = _gst_gl_download_perform_unlocked (download, inbuf, outbuf);
GST_OBJECT_UNLOCK (download);
return ret;
}

View file

@ -81,6 +81,8 @@ GstCaps * gst_gl_download_transform_caps (GstGLContext * convert,
gboolean gst_gl_download_perform_with_data (GstGLDownload * download, gboolean gst_gl_download_perform_with_data (GstGLDownload * download,
GLuint texture_id, GLuint texture_target, GLuint texture_id, GLuint texture_target,
gpointer data[GST_VIDEO_MAX_PLANES]); gpointer data[GST_VIDEO_MAX_PLANES]);
gboolean gst_gl_download_perform (GstGLDownload * download,
GstBuffer *inbuf, GstBuffer *outbuf);
G_END_DECLS G_END_DECLS

View file

@ -1422,23 +1422,32 @@ gst_gl_memory_setup_buffer (GstGLContext * context,
GstVideoAlignment * valign, GstBuffer * buffer) GstVideoAlignment * valign, GstBuffer * buffer)
{ {
GstGLMemory *gl_mem[GST_VIDEO_MAX_PLANES] = { NULL, }; GstGLMemory *gl_mem[GST_VIDEO_MAX_PLANES] = { NULL, };
guint n_mem, i; guint n_mem, i, v, views;
n_mem = GST_VIDEO_INFO_N_PLANES (info); n_mem = GST_VIDEO_INFO_N_PLANES (info);
for (i = 0; i < n_mem; i++) { if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) ==
gl_mem[i] = GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
(GstGLMemory *) gst_gl_memory_alloc (context, params, info, i, valign); views = info->views;
if (gl_mem[i] == NULL) else
return FALSE; views = 1;
gst_buffer_append_memory (buffer, (GstMemory *) gl_mem[i]); for (v = 0; v < views; v++) {
for (i = 0; i < n_mem; i++) {
gl_mem[i] =
(GstGLMemory *) gst_gl_memory_alloc (context, params, info, i,
valign);
if (gl_mem[i] == NULL)
return FALSE;
gst_buffer_append_memory (buffer, (GstMemory *) gl_mem[i]);
}
gst_buffer_add_video_meta_full (buffer, v,
GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
GST_VIDEO_INFO_HEIGHT (info), n_mem, info->offset, info->stride);
} }
gst_buffer_add_video_meta_full (buffer, 0,
GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
GST_VIDEO_INFO_HEIGHT (info), n_mem, info->offset, info->stride);
return TRUE; return TRUE;
} }

View file

@ -50,6 +50,9 @@
GST_DEBUG_CATEGORY_STATIC (gst_gl_upload_debug); GST_DEBUG_CATEGORY_STATIC (gst_gl_upload_debug);
#define GST_CAT_DEFAULT gst_gl_upload_debug #define GST_CAT_DEFAULT gst_gl_upload_debug
/* Define the maximum number of planes we can upload - handle 2 views per buffer */
#define GST_GL_UPLOAD_MAX_PLANES (GST_VIDEO_MAX_PLANES * 2)
typedef struct _UploadMethod UploadMethod; typedef struct _UploadMethod UploadMethod;
struct _GstGLUploadPrivate struct _GstGLUploadPrivate
@ -162,12 +165,18 @@ _gl_memory_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
return FALSE; return FALSE;
if (buffer) { if (buffer) {
if (gst_buffer_n_memory (buffer) != GstVideoInfo *in_info = &upload->upload->priv->in_info;
GST_VIDEO_INFO_N_PLANES (&upload->upload->priv->in_info)) guint expected_memories = GST_VIDEO_INFO_N_PLANES (in_info);
/* Support stereo views for separated multiview mode */
if (GST_VIDEO_INFO_MULTIVIEW_MODE (in_info) ==
GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
expected_memories *= GST_VIDEO_INFO_VIEWS (in_info);
if (gst_buffer_n_memory (buffer) != expected_memories)
return FALSE; return FALSE;
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->upload->priv->in_info); for (i = 0; i < expected_memories; i++) {
i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i); GstMemory *mem = gst_buffer_peek_memory (buffer, i);
if (!gst_is_gl_memory (mem)) if (!gst_is_gl_memory (mem))
@ -250,9 +259,10 @@ _gl_memory_upload_perform (gpointer impl, GstBuffer * buffer,
{ {
struct GLMemoryUpload *upload = impl; struct GLMemoryUpload *upload = impl;
GstGLMemory *gl_mem; GstGLMemory *gl_mem;
int i; int i, n;
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->upload->priv->in_info); i++) { n = gst_buffer_n_memory (buffer);
for (i = 0; i < n; i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i); GstMemory *mem = gst_buffer_peek_memory (buffer, i);
gl_mem = (GstGLMemory *) mem; gl_mem = (GstGLMemory *) mem;
@ -357,12 +367,18 @@ _egl_image_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
return FALSE; return FALSE;
if (buffer) { if (buffer) {
if (gst_buffer_n_memory (buffer) != GstVideoInfo *in_info = &image->upload->priv->in_info;
GST_VIDEO_INFO_N_PLANES (&image->upload->priv->in_info)) guint expected_memories = GST_VIDEO_INFO_N_PLANES (in_info);
/* Support stereo views for separated multiview mode */
if (GST_VIDEO_INFO_MULTIVIEW_MODE (in_info) ==
GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
expected_memories *= GST_VIDEO_INFO_VIEWS (in_info);
if (gst_buffer_n_memory (buffer) != expected_memories)
return FALSE; return FALSE;
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&image->upload->priv->in_info); for (i = 0; i < expected_memories; i++) {
i++) {
GstMemory *mem = gst_buffer_peek_memory (buffer, i); GstMemory *mem = gst_buffer_peek_memory (buffer, i);
if (!gst_is_egl_image_memory (mem)) if (!gst_is_egl_image_memory (mem))
@ -395,14 +411,15 @@ static void
_egl_image_upload_perform_gl_thread (GstGLContext * context, _egl_image_upload_perform_gl_thread (GstGLContext * context,
struct EGLImageUpload *image) struct EGLImageUpload *image)
{ {
guint i; guint i, n;
/* FIXME: buffer pool */ /* FIXME: buffer pool */
*image->outbuf = gst_buffer_new (); *image->outbuf = gst_buffer_new ();
gst_gl_memory_setup_buffer (image->upload->context, gst_gl_memory_setup_buffer (image->upload->context,
NULL, &image->upload->priv->out_info, NULL, *image->outbuf); NULL, &image->upload->priv->out_info, NULL, *image->outbuf);
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&image->upload->priv->in_info); i++) { n = gst_buffer_n_memory (image->buffer);
for (i = 0; i < n; i++) {
GstMemory *mem = gst_buffer_peek_memory (image->buffer, i); GstMemory *mem = gst_buffer_peek_memory (image->buffer, i);
GstGLMemory *out_gl_mem = GstGLMemory *out_gl_mem =
(GstGLMemory *) gst_buffer_peek_memory (*image->outbuf, i); (GstGLMemory *) gst_buffer_peek_memory (*image->outbuf, i);
@ -474,7 +491,7 @@ struct GLUploadMeta
gboolean result; gboolean result;
GstVideoGLTextureUploadMeta *meta; GstVideoGLTextureUploadMeta *meta;
guint texture_ids[GST_VIDEO_MAX_PLANES]; guint texture_ids[GST_GL_UPLOAD_MAX_PLANES];
}; };
static gpointer static gpointer
@ -606,6 +623,13 @@ _upload_meta_upload_perform (gpointer impl, GstBuffer * buffer,
{ {
struct GLUploadMeta *upload = impl; struct GLUploadMeta *upload = impl;
int i; int i;
GstVideoInfo *in_info = &upload->upload->priv->in_info;
guint max_planes = GST_VIDEO_INFO_N_PLANES (in_info);
/* Support stereo views for separated multiview mode */
if (GST_VIDEO_INFO_MULTIVIEW_MODE (in_info) ==
GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
max_planes *= GST_VIDEO_INFO_VIEWS (in_info);
GST_LOG_OBJECT (upload, "Attempting upload with GstVideoGLTextureUploadMeta"); GST_LOG_OBJECT (upload, "Attempting upload with GstVideoGLTextureUploadMeta");
@ -616,10 +640,10 @@ _upload_meta_upload_perform (gpointer impl, GstBuffer * buffer,
gst_gl_memory_setup_buffer (upload->upload->context, gst_gl_memory_setup_buffer (upload->upload->context,
NULL, &upload->upload->priv->in_info, NULL, *outbuf); NULL, &upload->upload->priv->in_info, NULL, *outbuf);
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { for (i = 0; i < GST_GL_UPLOAD_MAX_PLANES; i++) {
guint tex_id = 0; guint tex_id = 0;
if (i < GST_VIDEO_INFO_N_PLANES (&upload->upload->priv->in_info)) { if (i < max_planes) {
GstMemory *mem = gst_buffer_peek_memory (*outbuf, i); GstMemory *mem = gst_buffer_peek_memory (*outbuf, i);
tex_id = ((GstGLMemory *) mem)->tex_id; tex_id = ((GstGLMemory *) mem)->tex_id;
} }
@ -627,9 +651,12 @@ _upload_meta_upload_perform (gpointer impl, GstBuffer * buffer,
upload->texture_ids[i] = tex_id; upload->texture_ids[i] = tex_id;
} }
GST_LOG ("Uploading with GLTextureUploadMeta with textures %i,%i,%i,%i", GST_LOG ("Uploading with GLTextureUploadMeta with textures "
upload->texture_ids[0], upload->texture_ids[1], upload->texture_ids[2], "%i,%i,%i,%i / %i,%i,%i,%i",
upload->texture_ids[3]); upload->texture_ids[0], upload->texture_ids[1],
upload->texture_ids[2], upload->texture_ids[3],
upload->texture_ids[4], upload->texture_ids[5],
upload->texture_ids[6], upload->texture_ids[7]);
gst_gl_context_thread_add (upload->upload->context, gst_gl_context_thread_add (upload->upload->context,
(GstGLContextThreadFunc) _do_upload_with_meta, upload); (GstGLContextThreadFunc) _do_upload_with_meta, upload);
@ -653,7 +680,7 @@ _upload_meta_upload_free (gpointer impl)
g_return_if_fail (impl != NULL); g_return_if_fail (impl != NULL);
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { for (i = 0; i < GST_GL_UPLOAD_MAX_PLANES; i++) {
if (upload->texture_ids[i]) if (upload->texture_ids[i])
gst_gl_context_del_texture (upload->upload->context, gst_gl_context_del_texture (upload->upload->context,
&upload->texture_ids[i]); &upload->texture_ids[i]);
@ -750,14 +777,21 @@ static GstGLUploadReturn
_raw_data_upload_perform (gpointer impl, GstBuffer * buffer, _raw_data_upload_perform (gpointer impl, GstBuffer * buffer,
GstBuffer ** outbuf) GstBuffer ** outbuf)
{ {
GstGLMemory *in_tex[GST_VIDEO_MAX_PLANES] = { 0, }; GstGLMemory *in_tex[GST_GL_UPLOAD_MAX_PLANES] = { 0, };
struct RawUpload *raw = impl; struct RawUpload *raw = impl;
int i; int i;
GstVideoInfo *in_info = &raw->upload->priv->in_info;
guint max_planes = GST_VIDEO_INFO_N_PLANES (in_info);
/* Support stereo views for separated multiview mode */
if (GST_VIDEO_INFO_MULTIVIEW_MODE (in_info) ==
GST_VIDEO_MULTIVIEW_MODE_SEPARATED)
max_planes *= GST_VIDEO_INFO_VIEWS (in_info);
gst_gl_memory_setup_wrapped (raw->upload->context, gst_gl_memory_setup_wrapped (raw->upload->context,
&raw->upload->priv->in_info, NULL, raw->in_frame.data, in_tex); &raw->upload->priv->in_info, NULL, raw->in_frame.data, in_tex);
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { for (i = 0; i < GST_GL_UPLOAD_MAX_PLANES; i++) {
if (in_tex[i]) { if (in_tex[i]) {
in_tex[i]->data = raw->in_frame.data[i]; in_tex[i]->data = raw->in_frame.data[i];
GST_GL_MEMORY_FLAG_SET (in_tex[i], GST_GL_MEMORY_FLAG_NEED_UPLOAD); GST_GL_MEMORY_FLAG_SET (in_tex[i], GST_GL_MEMORY_FLAG_NEED_UPLOAD);
@ -765,7 +799,7 @@ _raw_data_upload_perform (gpointer impl, GstBuffer * buffer,
} }
*outbuf = gst_buffer_new (); *outbuf = gst_buffer_new ();
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&raw->upload->priv->in_info); i++) { for (i = 0; i < max_planes; i++) {
gst_buffer_append_memory (*outbuf, (GstMemory *) in_tex[i]); gst_buffer_append_memory (*outbuf, (GstMemory *) in_tex[i]);
} }