Switch to native glbox implementation
Not loading Python
- lower memory footprint for native apps
- faster process loads
On Excelsior pyopengl also have compatibility issues, this
effectively works around those.
Bug: 168133392
Change-Id: I6d6f8d94a4a6ca06f06c03f7b5462f595ddbb182
diff --git a/debian/changelog b/debian/changelog
index ff2cdaf..1eee24a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+edgetpuvision (6-4) mendel-eagle; urgency=medium
+
+ * Switch to native glbox.
+
+ -- Coral Team <coral-support@google.com> Thu, 29 Oct 2020 13:04:30 -0700
+
edgetpuvision (6-3) mendel-eagle; urgency=medium
* Update support for the mipi camera pipeline.
diff --git a/debian/control b/debian/control
index be6b4b6..06da349 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@
Maintainer: Coral <coral-support@google.com>
Section: python
Priority: optional
-Build-Depends: dh-python, python3-setuptools, python3-all, debhelper (>= 9), libgstreamer1.0-dev, pkg-config
+Build-Depends: dh-python, python3-setuptools, python3-all, debhelper (>= 9), libgstreamer-plugins-base1.0-dev, pkg-config
Standards-Version: 3.9.8
Homepage: https://coral.ai/
@@ -20,6 +20,7 @@
gstreamer1.0-plugins-good,
gstreamer1.0-plugins-ugly,
gstreamer1.0-python3-plugin-loader,
+ gstreamer1.0-plugins-coral,
mdpd,
python3-cairo,
python3-edgetpu,
@@ -34,3 +35,12 @@
Description: EdgeTPU camera API
API to run inference on image data coming from the camera.
+Package: gstreamer1.0-plugins-coral
+Architecture: any
+Multi-Arch: same
+Section: libs
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends},
+ ${misc:Depends},
+Description: Coral GStreamer plugins.
+ Coral specific GStreamer plugins.
diff --git a/debian/rules b/debian/rules
index fb65e3f..187cf7a 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,13 +1,22 @@
#!/usr/bin/make -f
+include /usr/share/dpkg/pkg-info.mk
PLUGINSDIR := $(shell pkg-config --variable=pluginsdir gstreamer-1.0)
-DESTDIR := debian/python3-edgetpuvision/$(PLUGINSDIR)/python
+PY_DESTDIR := debian/python3-edgetpuvision/$(PLUGINSDIR)/python
+SO_DESTDIR := debian/gstreamer1.0-plugins-coral/$(PLUGINSDIR)
+SO_SRCS := plugins/gstglbox.c plugins/gstcoral.c
+SO_DEST := $(SO_DESTDIR)/libgstcoral.so
+SO_DEPS := gstreamer-plugins-base-1.0 gstreamer-video-1.0 gstreamer-gl-1.0
export PYBUILD_NAME=edgetpuvision
+
%:
dh $@ --with python3 --buildsystem=pybuild
override_dh_install:
dh_install
- install -d $(DESTDIR)
- install -g 0 -o 0 plugins/python/*.py $(DESTDIR)
+ install -d $(PY_DESTDIR)
+ install -g 0 -o 0 plugins/python/*.py $(PY_DESTDIR)
+
+ install -d $(SO_DESTDIR)
+ $(DEB_HOST_GNU_TYPE)-gcc `$(DEB_HOST_GNU_TYPE)-pkg-config --libs --cflags $(SO_DEPS)` $(CFLAGS) -shared -o $(SO_DEST) -DCORAL_VERSION=$(DEB_VERSION) $(SO_SRCS)
diff --git a/plugins/gstcoral.c b/plugins/gstcoral.c
new file mode 100644
index 0000000..7b6cac6
--- /dev/null
+++ b/plugins/gstcoral.c
@@ -0,0 +1,48 @@
+/*
+ * # Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstglbox.h"
+
+#define CORAL_LICENSE GST_LICENSE_UNKNOWN /* Apache not supported */
+#define ORIGIN "https://coral.ai"
+#define PACKAGE "GstCoral"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+
+ if (!gst_element_register (plugin, "glbox",
+ GST_RANK_NONE, gst_gl_box_get_type ())) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (
+ GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ coral,
+ "Coral plugin",
+ plugin_init,
+ G_STRINGIFY (CORAL_VERSION),
+ CORAL_LICENSE,
+ PACKAGE,
+ ORIGIN);
diff --git a/plugins/gstglbox.c b/plugins/gstglbox.c
new file mode 100644
index 0000000..a390d8a
--- /dev/null
+++ b/plugins/gstglbox.c
@@ -0,0 +1,241 @@
+/*
+ * # Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gl/gstglfuncs.h>
+#include <gst/video/gstvideosink.h>
+
+#include "gstglbox.h"
+
+#define GST_CAT_DEFAULT gst_gl_box_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+ PROP_0,
+ PROP_X,
+ PROP_Y,
+ PROP_WIDTH,
+ PROP_HEIGHT,
+};
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_gl_box_debug, "glbox", 0, "glbox element");
+#define gst_gl_box_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstGLBox, gst_gl_box,
+ GST_TYPE_GL_FILTER, DEBUG_INIT);
+
+static void gst_gl_box_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_gl_box_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static gboolean gst_gl_box_gl_start (GstGLBaseFilter * base_filter);
+static void gst_gl_box_gl_stop (GstGLBaseFilter * base_filter);
+static gboolean gst_gl_box_gl_set_caps (GstGLBaseFilter * bt,
+ GstCaps * incaps, GstCaps * outcaps);
+
+static gboolean gst_gl_box_filter_texture (GstGLFilter * filter,
+ GstGLMemory * in_tex, GstGLMemory * out_tex);
+
+static void
+gst_gl_box_class_init (GstGLBoxClass * klass)
+{
+ gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass));
+
+ ((GObjectClass *) klass)->set_property = gst_gl_box_set_property;
+ ((GObjectClass *) klass)->get_property = gst_gl_box_get_property;
+
+ gst_element_class_set_metadata (GST_ELEMENT_CLASS (klass),
+ "OpenGL box",
+ "Filter/Effect/Video",
+ "Colorspace convert and scale with retained aspect ratio",
+ "Coral <coral-support@google.com>");
+
+ GST_BASE_TRANSFORM_CLASS (klass)->passthrough_on_same_caps = TRUE;
+ GST_GL_BASE_FILTER_CLASS (klass)->gl_start = GST_DEBUG_FUNCPTR (gst_gl_box_gl_start);
+ GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = GST_DEBUG_FUNCPTR (gst_gl_box_gl_stop);
+ GST_GL_BASE_FILTER_CLASS (klass)->gl_set_caps = gst_gl_box_gl_set_caps;
+ GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api =
+ GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2;
+ GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_box_filter_texture;
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_X,
+ g_param_spec_int ("x", "Frame X coordinate", "Frame X coordinate",
+ 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_Y,
+ g_param_spec_int ("y", "Frame Y coordinate", "Frame Y coordinate",
+ 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WIDTH,
+ g_param_spec_int ("width", "Frame width", "Frame width",
+ 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HEIGHT,
+ g_param_spec_int ("height", "Frame height", "Frame height",
+ 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gst_gl_box_init (GstGLBox * box)
+{
+ box->shader = NULL;
+ memset (&box->viewport, 0, sizeof (GstVideoRectangle));
+}
+
+static void
+gst_gl_box_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_gl_box_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstGLBox *box = GST_GL_BOX (object);
+
+ switch (prop_id) {
+ case PROP_X:
+ g_value_set_int (value, box->viewport.x);
+ break;
+ case PROP_Y:
+ g_value_set_int (value, box->viewport.y);
+ break;
+ case PROP_WIDTH:
+ g_value_set_int (value, box->viewport.w);
+ break;
+ case PROP_HEIGHT:
+ g_value_set_int (value, box->viewport.h);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gst_gl_box_gl_start (GstGLBaseFilter * base_filter)
+{
+ GstGLBox *box = GST_GL_BOX (base_filter);
+ GstGLFilter *filter = GST_GL_FILTER (base_filter);
+
+ box->shader = gst_gl_shader_new_default (base_filter->context, NULL);
+ if (!box->shader) {
+ GST_ERROR_OBJECT (box, "Failed to initialize shader");
+ return FALSE;
+ }
+
+
+ filter->draw_attr_position_loc =
+ gst_gl_shader_get_attribute_location (box->shader, "a_position");
+ filter->draw_attr_texture_loc =
+ gst_gl_shader_get_attribute_location (box->shader, "a_texcoord");
+
+ return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter);
+}
+
+static void
+gst_gl_box_gl_stop (GstGLBaseFilter * base_filter)
+{
+ GstGLBox *box = GST_GL_BOX (base_filter);
+
+ if (box->shader) {
+ gst_object_unref (box->shader);
+ box->shader = NULL;
+ }
+
+ GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter);
+}
+
+static gboolean
+gst_gl_box_gl_set_caps (GstGLBaseFilter * bt, GstCaps * incaps,
+ GstCaps * outcaps)
+{
+ GstGLBox *box = GST_GL_BOX (bt);
+ GstGLFilter *filter = GST_GL_FILTER (bt);
+ GstVideoRectangle src, dst, viewport;
+
+ src.x = 0;
+ src.y = 0;
+ src.w = GST_VIDEO_INFO_WIDTH (&filter->in_info);
+ src.h = GST_VIDEO_INFO_HEIGHT (&filter->in_info);
+
+ dst.x = 0;
+ dst.y = 0;
+ dst.w = GST_VIDEO_INFO_WIDTH (&filter->out_info);
+ dst.h = GST_VIDEO_INFO_HEIGHT (&filter->out_info);
+
+ gst_video_sink_center_rect (src, dst, &viewport, TRUE);
+
+ if (memcmp (&viewport, &box->viewport, sizeof (GstVideoRectangle))) {
+ GST_INFO_OBJECT (filter, "Scaling %dx%d -> %dx%d @ (%d, %d)", src.w, src.h,
+ viewport.w, viewport.h, viewport.x, viewport.y);
+ box->viewport = viewport;
+ }
+
+ return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_set_caps (
+ GST_GL_BASE_FILTER (filter), incaps, outcaps);
+}
+
+static gboolean
+gst_gl_box_draw (GstGLFilter * filter, GstGLMemory * in_tex,
+ gpointer user_data)
+{
+ GstGLBox *box = GST_GL_BOX (user_data);
+ const GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;
+
+ g_return_val_if_fail (box->shader, FALSE);
+
+ gl->ClearColor (0.0, 0.0, 0.0, 1.0);
+ gl->Clear (GL_COLOR_BUFFER_BIT);
+
+ gl->Viewport (box->viewport.x, box->viewport.y, box->viewport.w,
+ box->viewport.h);
+
+ gst_gl_shader_use (box->shader);
+ gst_gl_shader_set_uniform_1i (box->shader, "tex", 0);
+ gl->ActiveTexture (GL_TEXTURE0);
+ gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex));
+
+ gst_gl_filter_draw_fullscreen_quad (filter);
+
+ return TRUE;
+}
+
+static gboolean
+gst_gl_box_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
+ GstGLMemory * out_tex)
+{
+ GstGLBox *box = GST_GL_BOX (filter);
+
+ if (gst_gl_context_get_gl_api (GST_GL_BASE_FILTER (filter)->context)) {
+ gst_gl_filter_render_to_target (filter, in_tex, out_tex, gst_gl_box_draw,
+ filter);
+ }
+
+ return TRUE;
+}
diff --git a/plugins/gstglbox.h b/plugins/gstglbox.h
new file mode 100644
index 0000000..f6a738d
--- /dev/null
+++ b/plugins/gstglbox.h
@@ -0,0 +1,53 @@
+/*
+ * # Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _GST_GLBOX_H
+#define _GST_GLBOX_H
+
+#include <gst/gst.h>
+
+#include <gst/gl/gstglfilter.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_GL_BOX (gst_gl_box_get_type())
+#define GST_GL_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_BOX,GstGLBox))
+#define GST_IS_GL_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_BOX))
+#define GST_GL_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_BOX,GstGLBoxClass))
+#define GST_IS_GL_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_BOX))
+#define GST_GL_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_BOX,GstGLBoxClass))
+
+typedef struct _GstGLBox GstGLBox;
+typedef struct _GstGLBoxClass GstGLBoxClass;
+
+
+struct _GstGLBox
+{
+ GstGLFilter filter;
+ GstGLShader *shader;
+ GstVideoRectangle viewport;
+};
+
+struct _GstGLBoxClass
+{
+ GstGLFilterClass filter_class;
+};
+
+GType gst_gl_box_get_type (void);
+
+G_END_DECLS
+
+#endif /* _GST_GLBOX_H */
diff --git a/plugins/python/glbox.py b/plugins/python/glbox.py
deleted file mode 100644
index 5458a02..0000000
--- a/plugins/python/glbox.py
+++ /dev/null
@@ -1,287 +0,0 @@
-# Copyright 2019 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import numpy
-import os
-import time
-
-import gi
-gi.require_version('GLib', '2.0')
-gi.require_version('GObject', '2.0')
-gi.require_version('Gst', '1.0')
-gi.require_version('GstGL', '1.0')
-gi.require_version('GstVideo', '1.0')
-from gi.repository import GLib, GObject, Gst, GstGL, GstVideo
-
-from OpenGL.arrays.arraydatatype import ArrayDatatype
-from OpenGL.GLES3 import (
- glActiveTexture, glBindBuffer, glBindTexture, glBindVertexArray, glBufferData, glDeleteBuffers,
- glClear, glClearColor, glDeleteVertexArrays, glDrawElements, glEnableVertexAttribArray,
- glGenBuffers, glGenVertexArrays, glVertexAttribPointer)
-from OpenGL.GLES3 import (
- GL_ARRAY_BUFFER, GL_COLOR_BUFFER_BIT,GL_ELEMENT_ARRAY_BUFFER, GL_FALSE, GL_FLOAT,
- GL_STATIC_DRAW, GL_TEXTURE0, GL_TEXTURE_2D, GL_TRIANGLES, GL_UNSIGNED_SHORT, GL_VERTEX_SHADER)
-
-
-SINK_CAPS = 'video/x-raw(memory:GLMemory),format=RGBA,width=[1,{max_int}],height=[1,{max_int}],texture-target=2D'
-SINK_CAPS = Gst.Caps.from_string(SINK_CAPS.format(max_int=GLib.MAXINT))
-
-SRC_CAPS = 'video/x-raw(memory:GLMemory),format=RGBA,width=[1,{max_int}],height=[1,{max_int}],texture-target=2D'
-SRC_CAPS = Gst.Caps.from_string(SRC_CAPS.format(max_int=GLib.MAXINT))
-
-VERTEX_SHADER = '''
-attribute vec4 a_position;
-attribute vec2 a_texcoord;
-varying vec2 v_texcoord;
-uniform float u_scale_x;
-uniform float u_scale_y;
-void main()
-{
- v_texcoord = a_texcoord;
- gl_Position = vec4(a_position.x * u_scale_x, a_position.y * u_scale_y, a_position.zw);
-}
-'''
-
-POSITIONS = numpy.array([
- -1.0, -1.0,
- 1.0, -1.0,
- 1.0, 1.0,
- -1.0, 1.0,
- ], dtype=numpy.float32)
-
-TEXCOORDS = numpy.array([
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- ], dtype=numpy.float32)
-
-INDICES = numpy.array([
- 0, 1, 2, 0, 2, 3
- ], dtype=numpy.uint16)
-
-class GlBox(GstGL.GLFilter):
- __gstmetadata__ = ('GlBox',
- 'Filter/Converter/Video',
- 'Scale video preserving aspect ratio',
- 'Coral <coral-support@google.com>')
- __gsttemplates__ = (Gst.PadTemplate.new('sink',
- Gst.PadDirection.SINK,
- Gst.PadPresence.ALWAYS,
- SINK_CAPS),
- Gst.PadTemplate.new('src',
- Gst.PadDirection.SRC,
- Gst.PadPresence.ALWAYS,
- SRC_CAPS))
- __gproperties__ = {
- 'x': (int,
- 'Frame x coordinate',
- 'Frame x coordinate',
- 0,
- GLib.MAXINT,
- 0,
- GObject.ParamFlags.READABLE),
- 'y': (int,
- 'Frame y coordinate',
- 'Frame y coordinate',
- 0,
- GLib.MAXINT,
- 0,
- GObject.ParamFlags.READABLE),
- 'width': (int,
- 'Frame width',
- 'Frame width',
- 0,
- GLib.MAXINT,
- 0,
- GObject.ParamFlags.READABLE),
- 'height': (int,
- 'Frame height',
- 'Frame height',
- 0,
- GLib.MAXINT,
- 0,
- GObject.ParamFlags.READABLE),
- 'scale-x': (float,
- 'Frame scaling factor x',
- 'Frame scaling factor x',
- 0,
- GLib.MAXFLOAT,
- 0,
- GObject.ParamFlags.READABLE),
- 'scale-y': (float,
- 'Frame scaling factor y',
- 'Frame scaling factor y',
- 0,
- GLib.MAXFLOAT,
- 0,
- GObject.ParamFlags.READABLE),
- }
-
- def __init__(self):
- GstGL.GLFilter.__init__(self)
- self.x, self.y, self.w, self.h = 0, 0, 0, 0
- self.scale_x, self.scale_y = 1.0, 1.0
-
- self.shader = None
- self.vao_id = 0
- self.positions_buffer = 0
- self.texcoords_buffer = 0
- self.vbo_indices_buffer = 0
- self.print_fps = int(os.environ.get('PRINT_FPS', '0'))
- self.fps_start = 0
- self.frames = 0
-
- def do_get_property(self, prop):
- if prop.name == 'x':
- return self.x
- elif prop.name == 'y':
- return self.y
- elif prop.name == 'width':
- return self.w
- elif prop.name == 'height':
- return self.h
- elif prop.name == 'scale-x':
- return self.scale_x
- elif prop.name == 'scale-y':
- return self.scale_y
- else:
- raise AttributeError('Unknown property %s' % prop.name)
-
- def do_transform_internal_caps(self, direction, caps, filter_caps):
- res = SINK_CAPS if direction == Gst.PadDirection.SRC else SRC_CAPS
-
- if filter_caps:
- res = res.intersect(filter_caps)
- return res
-
-
- def do_gl_start(self):
- frag_stage = GstGL.GLSLStage.new_default_fragment(self.context)
- vert_stage = GstGL.GLSLStage.new_with_string(self.context,
- GL_VERTEX_SHADER,
- GstGL.GLSLVersion.NONE,
- GstGL.GLSLProfile.COMPATIBILITY | GstGL.GLSLProfile.ES,
- VERTEX_SHADER)
-
- self.shader = GstGL.GLShader.new(self.context)
- self.shader.compile_attach_stage(vert_stage)
- self.shader.compile_attach_stage(frag_stage)
- self.shader.link()
-
- a_position = self.shader.get_attribute_location('a_position')
- a_texcoord = self.shader.get_attribute_location('a_texcoord')
-
- self.vao_id = glGenVertexArrays(1)
- glBindVertexArray(self.vao_id)
-
- self.positions_buffer = glGenBuffers(1)
- glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer)
- glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(POSITIONS), POSITIONS, GL_STATIC_DRAW)
-
- self.texcoords_buffer = glGenBuffers(1)
- glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer)
- glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(TEXCOORDS), TEXCOORDS, GL_STATIC_DRAW)
-
- self.vbo_indices_buffer = glGenBuffers(1)
- glBindBuffer(GL_ARRAY_BUFFER, self.vbo_indices_buffer)
- glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(INDICES), INDICES, GL_STATIC_DRAW)
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_indices_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer);
- glVertexAttribPointer.wrappedOperation(a_position, 2, GL_FLOAT, GL_FALSE, 0, None)
- glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer);
- glVertexAttribPointer.wrappedOperation(a_texcoord, 2, GL_FLOAT, GL_FALSE, 0, None)
- glEnableVertexAttribArray(a_position)
- glEnableVertexAttribArray(a_texcoord)
-
- glBindVertexArray(0)
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
- glBindBuffer(GL_ARRAY_BUFFER, 0)
-
- return True
-
- def do_gl_stop(self):
- self.shader = None
- glDeleteVertexArrays(1, [self.vao_id])
- self.vao_id = None
- glDeleteBuffers(1, [self.positions_buffer])
- self.positions_buffer = None
- glDeleteBuffers(1, [self.texcoords_buffer])
- self.texcoords_buffer = None
- glDeleteBuffers(1, [self.vbo_indices_buffer])
- self.vbo_indices_buffer = None
-
- def do_gst_gl_filter_set_caps(self, in_caps, out_caps):
- in_info = GstVideo.VideoInfo()
- in_info.from_caps(in_caps)
-
- out_info = GstVideo.VideoInfo()
- out_info.from_caps(out_caps)
-
- in_ratio = in_info.width / in_info.height
- out_ratio = out_info.width / out_info.height
-
- if in_ratio > out_ratio:
- w = out_info.width
- h = out_info.width / in_ratio
- x = 0
- y = (out_info.height - h) / 2
- elif in_ratio < out_ratio:
- w = out_info.height * in_ratio
- h = out_info.height
- x = (out_info.width - w) / 2
- y = 0
- else:
- w = out_info.width
- h = out_info.height
- x = 0
- y = 0
-
- self.x = int(x)
- self.y = int(y)
- self.w = int(w)
- self.h = int(h)
- self.scale_x = self.w / out_info.width
- self.scale_y = self.h / out_info.height
- return True
-
- def do_filter_texture(self, in_tex, out_tex):
- self.render_to_target(in_tex, out_tex, self.do_render)
- self.frames += 1
- if not self.fps_start:
- self.fps_start = time.monotonic()
-
- elapsed = time.monotonic() - self.fps_start
- if self.print_fps and elapsed > self.print_fps:
- print('glbox: out {} ({:.2f} fps)'.format(
- self.frames, self.frames / elapsed))
- self.fps_start = time.monotonic()
- self.frames = 0
- return True
-
- def do_render(self, filter, in_tex):
- # Black borders.
- glClearColor(0.0, 0.0, 0.0, 0.0)
- glClear(GL_COLOR_BUFFER_BIT)
-
- glBindVertexArray(self.vao_id)
- glActiveTexture(GL_TEXTURE0)
- glBindTexture(GL_TEXTURE_2D, in_tex.tex_id)
- self.shader.use()
- self.shader.set_uniform_1f('u_scale_x', self.scale_x)
- self.shader.set_uniform_1f('u_scale_y', self.scale_y)
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, None)
-
-__gstelementfactory__ = ("glbox", Gst.Rank.NONE, GlBox)