From 8a1fc4ab4e14a8d35b033962ea4a809148fd84a8 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Sat, 30 May 2015 02:15:51 +1000 Subject: [PATCH] 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. --- gst-libs/gst/gl/gstglcolorconvert.c | 79 ++++++++---- gst-libs/gst/gl/gstgldownload.c | 188 +++++++++++++++++++++------- gst-libs/gst/gl/gstgldownload.h | 2 + gst-libs/gst/gl/gstglmemory.c | 31 +++-- gst-libs/gst/gl/gstglupload.c | 78 ++++++++---- 5 files changed, 276 insertions(+), 102 deletions(-) diff --git a/gst-libs/gst/gl/gstglcolorconvert.c b/gst-libs/gst/gl/gstglcolorconvert.c index 62e938c0f5..da903f4d71 100644 --- a/gst-libs/gst/gl/gstglcolorconvert.c +++ b/gst-libs/gst/gl/gstglcolorconvert.c @@ -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 (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)) g_assert_not_reached (); @@ -1507,38 +1510,27 @@ _init_convert_fbo (GstGLColorConvert * convert) return TRUE; } -/* Called by the idle function in the gl thread */ -void -_do_convert (GstGLContext * context, GstGLColorConvert * convert) +static gboolean +_do_convert_one_view (GstGLContext * context, GstGLColorConvert * convert, + guint view_num) { guint in_width, in_height, out_width, out_height; struct ConvertInfo *c_info = &convert->priv->convert_info; GstMapInfo out_info[GST_VIDEO_MAX_PLANES], in_info[GST_VIDEO_MAX_PLANES]; gboolean res = TRUE; 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_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info); in_width = GST_VIDEO_INFO_WIDTH (&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++) { 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])) { GST_ERROR_OBJECT (convert, "input must be GstGLMemory"); res = FALSE; @@ -1555,7 +1547,8 @@ _do_convert (GstGLContext * context, GstGLColorConvert * convert) for (j = 0; j < c_info->out_n_textures; j++) { 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; if (!gst_is_gl_memory ((GstMemory *) out_tex)) { @@ -1608,7 +1601,8 @@ _do_convert (GstGLContext * context, GstGLColorConvert * convert) out: for (j--; j >= 0; j--) { 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; 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 */ if (GST_VIDEO_INFO_FORMAT (&convert->out_info) == GST_VIDEO_FORMAT_YV12) { - GstMemory *mem1 = gst_buffer_get_memory (convert->outbuf, 1); - GstMemory *mem2 = gst_buffer_get_memory (convert->outbuf, 2); + GstMemory *mem1 = + 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, 2, mem1); + gst_buffer_replace_memory (convert->outbuf, 1 + out_plane_offset, mem2); + gst_buffer_replace_memory (convert->outbuf, 2 + out_plane_offset, mem1); } for (i--; i >= 0; 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) { gst_buffer_unref (convert->outbuf); convert->outbuf = NULL; diff --git a/gst-libs/gst/gl/gstgldownload.c b/gst-libs/gst/gl/gstgldownload.c index 1ae49b8afb..4bb00599c5 100644 --- a/gst-libs/gst/gl/gstgldownload.c +++ b/gst-libs/gst/gl/gstgldownload.c @@ -43,8 +43,7 @@ #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)) -static gboolean _do_download (GstGLDownload * download, guint texture_id, - gpointer data[GST_VIDEO_MAX_PLANES]); +static gboolean _do_download (GstGLDownload * download, GstBuffer * inbuf); static gboolean _init_download (GstGLDownload * download); static gboolean _gst_gl_download_perform_with_data_unlocked (GstGLDownload * 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); /* *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 { @@ -61,7 +63,12 @@ struct _GstGLDownloadPrivate const gchar *ARGB; 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); @@ -138,13 +145,9 @@ gst_gl_download_finalize (GObject * object) static void gst_gl_download_reset (GstGLDownload * download) { - guint i; - - for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { - if (download->priv->in_tex[i]) { - gst_memory_unref ((GstMemory *) download->priv->in_tex[i]); - download->priv->in_tex[i] = NULL; - } + if (download->priv->in_tex) { + gst_memory_unref ((GstMemory *) download->priv->in_tex); + download->priv->in_tex = NULL; } } @@ -250,7 +253,9 @@ gst_gl_download_transform_caps (GstGLContext * context, * @data: (out): where the downloaded data should go * * 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 */ @@ -272,12 +277,16 @@ gst_gl_download_perform_with_data (GstGLDownload * download, return ret; } +/* This method only supports one input texture */ static gboolean _gst_gl_download_perform_with_data_unlocked (GstGLDownload * download, GLuint texture_id, GLuint texture_target, gpointer data[GST_VIDEO_MAX_PLANES]) { guint i; + gboolean res; + GstBuffer *inbuf; + guint out_width, out_height; g_return_val_if_fail (download != NULL, 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); } - if (!download->priv->in_tex[0]) { + if (!download->priv->in_tex) { GstVideoInfo temp_info; gst_video_info_set_format (&temp_info, GST_VIDEO_FORMAT_RGBA, GST_VIDEO_INFO_WIDTH (&download->info), GST_VIDEO_INFO_HEIGHT (&download->info)); - download->priv->in_tex[0] = + download->priv->in_tex = gst_gl_memory_wrapped_texture (download->context, 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 _init_download (GstGLDownload * download) { GstVideoFormat v_format; - guint out_width, out_height; - GstVideoInfo in_info; GstCaps *in_caps, *out_caps; - GstCapsFeatures *in_gl_features, *out_gl_features; + GstCapsFeatures *out_gl_features; gboolean res; 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) 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 = gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY); out_caps = gst_video_info_to_caps (&download->info); 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); gst_caps_unref (in_caps); @@ -357,35 +380,38 @@ _init_download (GstGLDownload * download) } static gboolean -_do_download (GstGLDownload * download, guint texture_id, - gpointer data[GST_VIDEO_MAX_PLANES]) +_do_download (GstGLDownload * download, GstBuffer * inbuf) { - guint out_width, out_height; - GstBuffer *inbuf, *outbuf; + GstBuffer *outbuf; GstMapInfo map_info; gboolean ret = TRUE; gint i; - - out_width = GST_VIDEO_INFO_WIDTH (&download->info); - out_height = GST_VIDEO_INFO_HEIGHT (&download->info); + GstVideoInfo *info; + guint views, out_planes; + gpointer *data = download->priv->out_data; if (!download->initted) { - if (!_init_download (download)) + if (!_init_download (download)) { + GST_DEBUG_OBJECT (download, "Failed to initialise"); 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); - if (!outbuf) + if (!outbuf) { + GST_DEBUG_OBJECT (download, "Failed to colour convert for output"); 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); gpointer temp_data = ((GstGLMemory *) out_mem)->data; ((GstGLMemory *) out_mem)->data = data[i]; @@ -400,8 +426,80 @@ _do_download (GstGLDownload * download, guint texture_id, ((GstGLMemory *) out_mem)->data = temp_data; } - gst_buffer_unref (inbuf); gst_buffer_unref (outbuf); 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; +} diff --git a/gst-libs/gst/gl/gstgldownload.h b/gst-libs/gst/gl/gstgldownload.h index 2eeccf476e..d476854d58 100644 --- a/gst-libs/gst/gl/gstgldownload.h +++ b/gst-libs/gst/gl/gstgldownload.h @@ -81,6 +81,8 @@ GstCaps * gst_gl_download_transform_caps (GstGLContext * convert, gboolean gst_gl_download_perform_with_data (GstGLDownload * download, GLuint texture_id, GLuint texture_target, gpointer data[GST_VIDEO_MAX_PLANES]); +gboolean gst_gl_download_perform (GstGLDownload * download, + GstBuffer *inbuf, GstBuffer *outbuf); G_END_DECLS diff --git a/gst-libs/gst/gl/gstglmemory.c b/gst-libs/gst/gl/gstglmemory.c index b93ad5ef86..2deede49f2 100644 --- a/gst-libs/gst/gl/gstglmemory.c +++ b/gst-libs/gst/gl/gstglmemory.c @@ -1422,23 +1422,32 @@ gst_gl_memory_setup_buffer (GstGLContext * context, GstVideoAlignment * valign, GstBuffer * buffer) { 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); - 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; + if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) == + GST_VIDEO_MULTIVIEW_MODE_SEPARATED) + views = info->views; + else + 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; } diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c index e5f1ff0efd..e089a13c4a 100644 --- a/gst-libs/gst/gl/gstglupload.c +++ b/gst-libs/gst/gl/gstglupload.c @@ -50,6 +50,9 @@ GST_DEBUG_CATEGORY_STATIC (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; struct _GstGLUploadPrivate @@ -162,12 +165,18 @@ _gl_memory_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps, return FALSE; if (buffer) { - if (gst_buffer_n_memory (buffer) != - GST_VIDEO_INFO_N_PLANES (&upload->upload->priv->in_info)) + GstVideoInfo *in_info = &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; - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->upload->priv->in_info); - i++) { + for (i = 0; i < expected_memories; i++) { GstMemory *mem = gst_buffer_peek_memory (buffer, i); if (!gst_is_gl_memory (mem)) @@ -250,9 +259,10 @@ _gl_memory_upload_perform (gpointer impl, GstBuffer * buffer, { struct GLMemoryUpload *upload = impl; 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); gl_mem = (GstGLMemory *) mem; @@ -357,12 +367,18 @@ _egl_image_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps, return FALSE; if (buffer) { - if (gst_buffer_n_memory (buffer) != - GST_VIDEO_INFO_N_PLANES (&image->upload->priv->in_info)) + GstVideoInfo *in_info = &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; - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&image->upload->priv->in_info); - i++) { + for (i = 0; i < expected_memories; i++) { GstMemory *mem = gst_buffer_peek_memory (buffer, i); if (!gst_is_egl_image_memory (mem)) @@ -395,14 +411,15 @@ static void _egl_image_upload_perform_gl_thread (GstGLContext * context, struct EGLImageUpload *image) { - guint i; + guint i, n; /* FIXME: buffer pool */ *image->outbuf = gst_buffer_new (); gst_gl_memory_setup_buffer (image->upload->context, 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); GstGLMemory *out_gl_mem = (GstGLMemory *) gst_buffer_peek_memory (*image->outbuf, i); @@ -474,7 +491,7 @@ struct GLUploadMeta gboolean result; GstVideoGLTextureUploadMeta *meta; - guint texture_ids[GST_VIDEO_MAX_PLANES]; + guint texture_ids[GST_GL_UPLOAD_MAX_PLANES]; }; static gpointer @@ -606,6 +623,13 @@ _upload_meta_upload_perform (gpointer impl, GstBuffer * buffer, { struct GLUploadMeta *upload = impl; 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"); @@ -616,10 +640,10 @@ _upload_meta_upload_perform (gpointer impl, GstBuffer * buffer, gst_gl_memory_setup_buffer (upload->upload->context, 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; - if (i < GST_VIDEO_INFO_N_PLANES (&upload->upload->priv->in_info)) { + if (i < max_planes) { GstMemory *mem = gst_buffer_peek_memory (*outbuf, i); tex_id = ((GstGLMemory *) mem)->tex_id; } @@ -627,9 +651,12 @@ _upload_meta_upload_perform (gpointer impl, GstBuffer * buffer, upload->texture_ids[i] = tex_id; } - GST_LOG ("Uploading with GLTextureUploadMeta with textures %i,%i,%i,%i", - upload->texture_ids[0], upload->texture_ids[1], upload->texture_ids[2], - upload->texture_ids[3]); + GST_LOG ("Uploading with GLTextureUploadMeta with textures " + "%i,%i,%i,%i / %i,%i,%i,%i", + 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, (GstGLContextThreadFunc) _do_upload_with_meta, upload); @@ -653,7 +680,7 @@ _upload_meta_upload_free (gpointer impl) 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]) gst_gl_context_del_texture (upload->upload->context, &upload->texture_ids[i]); @@ -750,14 +777,21 @@ static GstGLUploadReturn _raw_data_upload_perform (gpointer impl, GstBuffer * buffer, GstBuffer ** outbuf) { - GstGLMemory *in_tex[GST_VIDEO_MAX_PLANES] = { 0, }; + GstGLMemory *in_tex[GST_GL_UPLOAD_MAX_PLANES] = { 0, }; struct RawUpload *raw = impl; 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, &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]) { in_tex[i]->data = raw->in_frame.data[i]; 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 (); - 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]); }