Updating prebuilts and/or headers

f29a8e1083e2fe546c68761a196b6dfd5aed14f6 - gstegl_src/gst-egl/Makefile
f43858ce2d2f71d6de58ca59ff794fb026689a70 - gstegl_src/gst-egl/LICENSE.libgstnveglglessink
b8b167b1729c6e6d1341d9bc61689af8b1dd5064 - gstegl_src/gst-egl/gst-libs/gst/egl/egl.h
34174463c5aa7f9b7f84878cff2f38e41cce28ac - gstegl_src/gst-egl/gst-libs/gst/egl/LICENSE.libgstnvegl-1.0
1a0c41a27bfc4e15f352ceaf07a5c88dfc1924bf - gstegl_src/gst-egl/gst-libs/gst/egl/egl.c
9a83abc5044d31ea41387ac916231ec396665c34 - gstegl_src/gst-egl/pre-gen-source_64/config.h
70444c9d4bb4aa2e45c0fcf4bcd820334faaf506 - gstegl_src/gst-egl/ext/eglgles/video_platform_wrapper.c
58bcca7fbccaba6d911f18f84b8853cbe67ce7ab - gstegl_src/gst-egl/ext/eglgles/gstegladaptation.h
c0dc425a4ce56cdabf72ba965bf17b1c5c142cfb - gstegl_src/gst-egl/ext/eglgles/gsteglglessink.c
ba144260ea5c0b76692d05b4b062c1656293fba3 - gstegl_src/gst-egl/ext/eglgles/gstegljitter.h
708504be2620161f67d31223962344721fc2f8b8 - gstegl_src/gst-egl/ext/eglgles/gstegladaptation.c
dd43271cead3db0655d9aed7f066dc60d0259e8b - gstegl_src/gst-egl/ext/eglgles/video_platform_wrapper.h
a51f6031922757390f1c3ae485a2daed6ddb3ff0 - gstegl_src/gst-egl/ext/eglgles/gstegladaptation_egl.c
a420f8c656140307d3d3c614228f609b59583c05 - gstegl_src/gst-egl/ext/eglgles/gstegljitter.c
09da2dec0ce5336dddebcc69f444eeaf4fe32eba - gstegl_src/gst-egl/ext/eglgles/gsteglglessink.h

Change-Id: I39539d1d99d31ef6c1c3cb9ef0d90c886d5ec5d7
This commit is contained in:
svcmobrel-release
2025-01-21 05:24:50 -08:00
parent d28af6b787
commit 4be089e6fb
20 changed files with 8554 additions and 0 deletions

17
commitFile.txt Normal file
View File

@@ -0,0 +1,17 @@
Updating prebuilts and/or headers
f29a8e1083e2fe546c68761a196b6dfd5aed14f6 - gstegl_src/gst-egl/Makefile
f43858ce2d2f71d6de58ca59ff794fb026689a70 - gstegl_src/gst-egl/LICENSE.libgstnveglglessink
b8b167b1729c6e6d1341d9bc61689af8b1dd5064 - gstegl_src/gst-egl/gst-libs/gst/egl/egl.h
34174463c5aa7f9b7f84878cff2f38e41cce28ac - gstegl_src/gst-egl/gst-libs/gst/egl/LICENSE.libgstnvegl-1.0
1a0c41a27bfc4e15f352ceaf07a5c88dfc1924bf - gstegl_src/gst-egl/gst-libs/gst/egl/egl.c
9a83abc5044d31ea41387ac916231ec396665c34 - gstegl_src/gst-egl/pre-gen-source_64/config.h
70444c9d4bb4aa2e45c0fcf4bcd820334faaf506 - gstegl_src/gst-egl/ext/eglgles/video_platform_wrapper.c
58bcca7fbccaba6d911f18f84b8853cbe67ce7ab - gstegl_src/gst-egl/ext/eglgles/gstegladaptation.h
c0dc425a4ce56cdabf72ba965bf17b1c5c142cfb - gstegl_src/gst-egl/ext/eglgles/gsteglglessink.c
ba144260ea5c0b76692d05b4b062c1656293fba3 - gstegl_src/gst-egl/ext/eglgles/gstegljitter.h
708504be2620161f67d31223962344721fc2f8b8 - gstegl_src/gst-egl/ext/eglgles/gstegladaptation.c
dd43271cead3db0655d9aed7f066dc60d0259e8b - gstegl_src/gst-egl/ext/eglgles/video_platform_wrapper.h
a51f6031922757390f1c3ae485a2daed6ddb3ff0 - gstegl_src/gst-egl/ext/eglgles/gstegladaptation_egl.c
a420f8c656140307d3d3c614228f609b59583c05 - gstegl_src/gst-egl/ext/eglgles/gstegljitter.c
09da2dec0ce5336dddebcc69f444eeaf4fe32eba - gstegl_src/gst-egl/ext/eglgles/gsteglglessink.h

43
gstegl_src/README.txt Normal file
View File

@@ -0,0 +1,43 @@
This package contains the code for libgstnvegl-1.0.so library
DEPENDENCIES:
------------
(1) EGL
(2) OPENGLES2
(3) Gstreamer >= 1.2.3
(4) X11, Xext
The above target machine dependencies can be obtained from any standard
distribution (like https://launchpad.net/ubuntu) or can be self-built.
Above required packages can also be installed using the following command:
sudo apt-get install \
autoconf \
automake \
autopoint \
autotools-dev \
gtk-doc-tools \
libegl1-mesa-dev \
libgles2-mesa-dev \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libgtk2.0-dev \
libtool \
libx11-dev \
libxext-dev \
pkg-config
This package was built against the (above) libs present in Ubuntu 16.04.
INSTALLATION:
-------------
1) Untar the package and enter the dir
2) ./autogen.sh
3) ./configure
4) make
5) sudo make install
Note:
Pass the appropriate flags and toolchain path to "configure" for tha ARM build.

View File

@@ -0,0 +1,41 @@
###############################################################################
#
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA Corporation and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA Corporation is strictly prohibited.
#
###############################################################################
Steps to compile the "gst-nveglglessink" sources:
1) Install gstreamer related packages using the command:
sudo apt-get install gstreamer1.0-tools gstreamer1.0-alsa \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
gstreamer1.0-libav libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev libegl1-mesa-dev
2) Install wayland related packages if not present:
sudo apt-get install libwayland-dev
3) Install CUDA Runtime 10.0+
4) Install Deepstream 6.0
5) Extract the package "gstegl_src.tbz2" as follow:
tar xvjf gstegl_src.tbz2`
6) cd "gstegl_src/gst_egl/"
7) Export the appropriate CUDA_VER using - "export CUDA_VER=<cuda-version>"
8) run "make" to create "libgstnveglglessink.so"
9) run "sudo make install" to install "libgstnveglglessink.so" in
"/usr/lib/aarch64-linux-gnu/gstreamer-1.0".

View File

@@ -0,0 +1,24 @@
GStreamer EGL/GLES Sink
Copyright (C) 2012 Collabora Ltd.
@author: Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
@author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,74 @@
###############################################################################
#
# Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA Corporation and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA Corporation is strictly prohibited.
#
###############################################################################
ifneq ($(MAKECMDGOALS),install)
ifeq ($(CUDA_VER),)
$(error "CUDA_VER is not set. Set it by running - "export CUDA_VER=<cuda-version>"")
endif
endif
SO_NAME := libgstnveglglessink.so
DEST_DIR ?= /usr/lib/aarch64-linux-gnu/gstreamer-1.0
SRCS := ext/eglgles/gstegladaptation.c \
ext/eglgles/gstegladaptation_egl.c \
ext/eglgles/gsteglglessink.c \
ext/eglgles/gstegljitter.c \
ext/eglgles/video_platform_wrapper.c \
gst-libs/gst/egl/egl.c
INCLUDES += -I./pre-gen-source_64/ \
-I./gst-libs \
-I./gst-libs/gst/egl \
-I/opt/nvidia/deepstream/deepstream-6.0/sources/includes/ \
-I/usr/local/include/gstreamer-1.0 \
-I/usr/local/cuda-$(CUDA_VER)/targets/aarch64-linux/include/ \
-I./
PKGS := glib-2.0 \
gstreamer-1.0 \
gstreamer-base-1.0 \
gstreamer-video-1.0
OBJS := $(SRCS:.c=.o)
CFLAGS := -fPIC \
-DHAVE_CONFIG_H \
-DG_THREADS_MANDATORY \
-DG_DISABLE_DEPRECATED \
-DUSE_EGL_TEGRA \
-DUSE_EGL_WAYLAND
CFLAGS += `pkg-config --cflags $(PKGS)`
LDFLAGS = -Wl,--no-undefined -L/usr/lib/aarch64-linux-gnu/tegra -L/usr/local/cuda-$(CUDA_VER)/targets/aarch64-linux/lib/
LIBS = -lnvbufsurface -lGLESv2 -lEGL -lX11 -lm -lcuda -lcudart -lwayland-client -lwayland-egl
LIBS += `pkg-config --libs $(PKGS)`
all: $(SO_NAME)
%.o: %.c
$(CC) -c $< $(CFLAGS) $(INCLUDES) -o $@
$(SO_NAME): $(OBJS)
$(CC) -shared -o $(SO_NAME) $(OBJS) $(LIBS) $(LDFLAGS)
.PHONY: install
install: $(SO_NAME)
cp -vp $(SO_NAME) $(DEST_DIR)
.PHONY: clean
clean:
rm -rf $(OBJS) $(SO_NAME)

View File

@@ -0,0 +1,41 @@
# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA Corporation and its licensors retain all intellectual property and
# proprietary rights in and to this software and related documentation. Any
# use, reproduction, disclosure or distribution of this software and related
# documentation without an express license agreement from NVIDIA Corporation
# is strictly prohibited.
#
# Source for this file: $(TEGRA_TOP)/tmake/artifacts/CommonRulesNvMake.tmk
ifeq ($(NV_BUILD_CONFIGURATION_LINUX_USERSPACE_IS_EMBEDDED),1)
ifeq ($(NV_BUILD_CONFIGURATION_IS_EXTERNAL),0)
NVCFG_PROFILE=tegragpu_unix_arm_embedded_profile
else ifeq ($(NV_BUILD_CONFIGURATION_IS_GNEXT),1)
NVCFG_PROFILE=tegragpu_unix_arm_embedded_gnext_profile
else
NVCFG_PROFILE=tegragpu_unix_arm_embedded_external_profile
endif
else ifeq ($(NV_BUILD_CONFIGURATION_LINUX_USERSPACE_IS_L4T),1)
ifneq ($(NV_BUILD_CONFIGURATION_IS_EXTERNAL),0)
ifeq ($(NV_BUILD_CONFIGURATION_IS_GNEXT),1)
NVCFG_PROFILE=l4t_global_gnext_profile
else
NVCFG_PROFILE=l4t_global_external_profile
endif
else
NVCFG_PROFILE=tegragpu_unix_arm_global_profile
endif
else ifeq ($(NV_BUILD_CONFIGURATION_OS_IS_QNX),1)
ifeq ($(NV_BUILD_CONFIGURATION_IS_EXTERNAL),0)
NVCFG_PROFILE=tegragpu_unix_arm_embedded_profile
else ifeq ($(NV_BUILD_CONFIGURATION_IS_GNEXT),1)
NVCFG_PROFILE=tegragpu_unix_arm_embedded_gnext_profile
else ifeq ($(NV_BUILD_CONFIGURATION_IS_SAFETY),1)
NVCFG_PROFILE=tegra_with_dgpu_embedded_safety_external_profile
else
NVCFG_PROFILE=tegragpu_unix_arm_embedded_external_profile
endif
else
$(error Unsupported OS)
endif

View File

@@ -0,0 +1,745 @@
/*
* GStreamer EGL/GLES Sink Adaptation
* Copyright (C) 2012-2013 Collabora Ltd.
* @author: Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
* @author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
* @author: Thiago Santos <thiago.sousa.santos@collabora.com>
* Copyright (c) 2015-2024, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "gstegladaptation.h"
#include <gst/video/video.h>
#include <string.h>
#define GST_CAT_DEFAULT egladaption_debug
GST_DEBUG_CATEGORY (egladaption_debug);
/* GLESv2 GLSL Shaders
*
* OpenGL ES Standard does not mandate YUV support. This is
* why most of these shaders deal with Packed/Planar YUV->RGB
* conversion.
*/
/* *INDENT-OFF* */
/* Direct vertex copy */
static const char *vert_COPY_prog = {
"attribute vec3 position;"
"attribute vec2 texpos;"
"varying vec2 opos;"
"void main(void)"
"{"
" opos = texpos;"
" gl_Position = vec4(position, 1.0);"
"}"
};
static const char *vert_COPY_prog_no_tex = {
"attribute vec3 position;"
"void main(void)"
"{"
" gl_Position = vec4(position, 1.0);"
"}"
};
/* Paint all black */
static const char *frag_BLACK_prog = {
"precision mediump float;"
"void main(void)"
"{"
" gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);"
"}"
};
/* Direct fragments copy with stride-scaling */
static const char *frag_COPY_prog = {
"precision mediump float;"
"varying vec2 opos;"
"uniform sampler2D tex;"
"uniform vec2 tex_scale0;"
"uniform vec2 tex_scale1;"
"uniform vec2 tex_scale2;"
"void main(void)"
"{"
" vec4 t = texture2D(tex, opos / tex_scale0);"
" gl_FragColor = vec4(t.rgb, 1.0);"
"}"
};
/* Direct fragments copy with stride-scaling */
static const char *frag_COPY_externel_oes_prog = {
"#extension GL_OES_EGL_image_external : require\n"
"precision mediump float;"
"varying vec2 opos;"
"uniform samplerExternalOES tex;"
"uniform vec2 tex_scale0;"
"uniform vec2 tex_scale1;"
"uniform vec2 tex_scale2;"
"void main(void)"
"{"
" gl_FragColor = texture2D(tex, opos / tex_scale0);"
"}"
};
/* Channel reordering for XYZ <-> ZYX conversion */
static const char *frag_REORDER_prog = {
"precision mediump float;"
"varying vec2 opos;"
"uniform sampler2D tex;"
"uniform vec2 tex_scale0;"
"uniform vec2 tex_scale1;"
"uniform vec2 tex_scale2;"
"void main(void)"
"{"
" vec4 t = texture2D(tex, opos / tex_scale0);"
" gl_FragColor = vec4(t.%c, t.%c, t.%c, 1.0);"
"}"
};
/* Packed YUV converters */
/** AYUV to RGB conversion */
static const char *frag_AYUV_prog = {
"precision mediump float;"
"varying vec2 opos;"
"uniform sampler2D tex;"
"uniform vec2 tex_scale0;"
"uniform vec2 tex_scale1;"
"uniform vec2 tex_scale2;"
"const vec3 offset = vec3(-0.0625, -0.5, -0.5);"
"const vec3 rcoeff = vec3(1.164, 0.000, 1.596);"
"const vec3 gcoeff = vec3(1.164,-0.391,-0.813);"
"const vec3 bcoeff = vec3(1.164, 2.018, 0.000);"
"void main(void) {"
" float r,g,b;"
" vec3 yuv;"
" yuv = texture2D(tex,opos / tex_scale0).gba;"
" yuv += offset;"
" r = dot(yuv, rcoeff);"
" g = dot(yuv, gcoeff);"
" b = dot(yuv, bcoeff);"
" gl_FragColor=vec4(r,g,b,1.0);"
"}"
};
/* Planar YUV converters */
/** YUV to RGB conversion */
static const char *frag_PLANAR_YUV_prog = {
"precision mediump float;"
"varying vec2 opos;"
"uniform sampler2D Ytex,Utex,Vtex;"
"uniform vec2 tex_scale0;"
"uniform vec2 tex_scale1;"
"uniform vec2 tex_scale2;"
"const vec3 offset = vec3(-0.0625, -0.5, -0.5);"
"const vec3 rcoeff = vec3(1.164, 0.000, 1.596);"
"const vec3 gcoeff = vec3(1.164,-0.391,-0.813);"
"const vec3 bcoeff = vec3(1.164, 2.018, 0.000);"
"void main(void) {"
" float r,g,b;"
" vec3 yuv;"
" yuv.x=texture2D(Ytex,opos / tex_scale0).r;"
" yuv.y=texture2D(Utex,opos / tex_scale1).r;"
" yuv.z=texture2D(Vtex,opos / tex_scale2).r;"
" yuv += offset;"
" r = dot(yuv, rcoeff);"
" g = dot(yuv, gcoeff);"
" b = dot(yuv, bcoeff);"
" gl_FragColor=vec4(r,g,b,1.0);"
"}"
};
/** NV12/NV21 to RGB conversion */
static const char *frag_NV12_NV21_prog = {
"precision mediump float;"
"varying vec2 opos;"
"uniform sampler2D Ytex,UVtex;"
"uniform vec2 tex_scale0;"
"uniform vec2 tex_scale1;"
"uniform vec2 tex_scale2;"
"const vec3 offset = vec3(-0.0625, -0.5, -0.5);"
"const vec3 rcoeff = vec3(1.164, 0.000, 1.596);"
"const vec3 gcoeff = vec3(1.164,-0.391,-0.813);"
"const vec3 bcoeff = vec3(1.164, 2.018, 0.000);"
"void main(void) {"
" float r,g,b;"
" vec3 yuv;"
" yuv.x=texture2D(Ytex,opos / tex_scale0).r;"
" yuv.yz=texture2D(UVtex,opos / tex_scale1).%c%c;"
" yuv += offset;"
" r = dot(yuv, rcoeff);"
" g = dot(yuv, gcoeff);"
" b = dot(yuv, bcoeff);"
" gl_FragColor=vec4(r,g,b,1.0);"
"}"
};
/* *INDENT-ON* */
void
gst_egl_adaption_init (void)
{
GST_DEBUG_CATEGORY_INIT (egladaption_debug, "egladaption", 0,
"EGL adaption layer");
}
static GstCaps *
_gst_video_format_new_template_caps (GstVideoFormat format)
{
return gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, gst_video_format_to_string (format),
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
}
GstCaps *
gst_egl_adaptation_fill_supported_fbuffer_configs (GstEglAdaptationContext *
ctx)
{
GstCaps *caps = NULL, *copy1, *copy2;
guint i, n;
GST_DEBUG_OBJECT (ctx->element,
"Building initial list of wanted eglattribs per format");
/* Init supported format/caps list */
if (_gst_egl_choose_config (ctx, TRUE, NULL)) {
caps = gst_caps_new_empty ();
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGBA));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_BGRA));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_ARGB));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_ABGR));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGBx));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_BGRx));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_xRGB));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_xBGR));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_AYUV));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_Y444));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_BGR));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_I420));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_YV12));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_NV12));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_NV21));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_Y42B));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_Y41B));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB16));
copy1 = gst_caps_copy (caps);
copy2 = gst_caps_copy (caps);
#ifndef HAVE_IOS
n = gst_caps_get_size (caps);
for (i = 0; i < n; i++) {
GstCapsFeatures *features =
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_EGL_IMAGE, NULL);
gst_caps_set_features (caps, i, features);
}
#endif
n = gst_caps_get_size (copy1);
for (i = 0; i < n; i++) {
GstCapsFeatures *features =
gst_caps_features_new
(GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL);
gst_caps_set_features (copy1, i, features);
}
gst_caps_append (caps, copy1);
gst_caps_append (caps, copy2);
n = gst_caps_get_size (caps);
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_BGRx));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGBA));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_I420));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_NV12));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB));
gst_caps_append (caps,
_gst_video_format_new_template_caps (GST_VIDEO_FORMAT_BGR));
for (i = n; i < n+6; i++) {
GstCapsFeatures *features =
gst_caps_features_new ("memory:NVMM", NULL);
gst_caps_set_features (caps, i, features);
}
} else {
GST_INFO_OBJECT (ctx->element,
"EGL display doesn't support RGBA8888 config");
}
return caps;
}
void
gst_egl_adaptation_cleanup (GstEglAdaptationContext * ctx)
{
gint i;
if (ctx->have_vbo) {
glDeleteBuffers (1, &ctx->position_buffer);
glDeleteBuffers (1, &ctx->index_buffer);
ctx->have_vbo = FALSE;
}
if (ctx->have_texture) {
glDeleteTextures (ctx->n_textures, ctx->texture);
ctx->have_texture = FALSE;
ctx->n_textures = 0;
}
for (i = 0; i < 2; i++) {
if (ctx->glslprogram[i]) {
glUseProgram (0);
glDetachShader (ctx->glslprogram[i], ctx->fragshader[i]);
glDetachShader (ctx->glslprogram[i], ctx->vertshader[i]);
glDeleteProgram (ctx->glslprogram[i]);
glDeleteShader (ctx->fragshader[i]);
glDeleteShader (ctx->vertshader[i]);
ctx->glslprogram[i] = 0;
ctx->fragshader[i] = 0;
ctx->vertshader[i] = 0;
}
}
gst_egl_adaptation_context_make_current (ctx, FALSE);
gst_egl_adaptation_destroy_surface (ctx);
gst_egl_adaptation_destroy_context (ctx);
}
gboolean
got_gl_error (const char *wtf)
{
GLuint error = GL_NO_ERROR;
if ((error = glGetError ()) != GL_NO_ERROR) {
GST_CAT_ERROR (GST_CAT_DEFAULT, "GL ERROR: %s returned 0x%04x", wtf, error);
return TRUE;
}
return FALSE;
}
static gboolean
create_shader_program (GstEglAdaptationContext * ctx, GLuint * prog,
GLuint * vert, GLuint * frag, const gchar * vert_text,
const gchar * frag_text)
{
GLint test;
GLchar *info_log;
/* Build shader program for video texture rendering */
*vert = glCreateShader (GL_VERTEX_SHADER);
GST_DEBUG_OBJECT (ctx->element, "Sending %s to handle %d", vert_text, *vert);
glShaderSource (*vert, 1, &vert_text, NULL);
if (got_gl_error ("glShaderSource vertex"))
goto HANDLE_ERROR;
glCompileShader (*vert);
if (got_gl_error ("glCompileShader vertex"))
goto HANDLE_ERROR;
glGetShaderiv (*vert, GL_COMPILE_STATUS, &test);
if (test != GL_FALSE)
GST_DEBUG_OBJECT (ctx->element, "Successfully compiled vertex shader");
else {
GST_ERROR_OBJECT (ctx->element, "Couldn't compile vertex shader");
glGetShaderiv (*vert, GL_INFO_LOG_LENGTH, &test);
info_log = g_new0 (GLchar, test);
glGetShaderInfoLog (*vert, test, NULL, info_log);
GST_INFO_OBJECT (ctx->element, "Compilation info log:\n%s", info_log);
g_free (info_log);
goto HANDLE_ERROR;
}
*frag = glCreateShader (GL_FRAGMENT_SHADER);
GST_DEBUG_OBJECT (ctx->element, "Sending %s to handle %d", frag_text, *frag);
glShaderSource (*frag, 1, &frag_text, NULL);
if (got_gl_error ("glShaderSource fragment"))
goto HANDLE_ERROR;
glCompileShader (*frag);
if (got_gl_error ("glCompileShader fragment"))
goto HANDLE_ERROR;
glGetShaderiv (*frag, GL_COMPILE_STATUS, &test);
if (test != GL_FALSE)
GST_DEBUG_OBJECT (ctx->element, "Successfully compiled fragment shader");
else {
GST_ERROR_OBJECT (ctx->element, "Couldn't compile fragment shader");
glGetShaderiv (*frag, GL_INFO_LOG_LENGTH, &test);
info_log = g_new0 (GLchar, test);
glGetShaderInfoLog (*frag, test, NULL, info_log);
GST_INFO_OBJECT (ctx->element, "Compilation info log:\n%s", info_log);
g_free (info_log);
goto HANDLE_ERROR;
}
*prog = glCreateProgram ();
if (got_gl_error ("glCreateProgram"))
goto HANDLE_ERROR;
glAttachShader (*prog, *vert);
if (got_gl_error ("glAttachShader vertices"))
goto HANDLE_ERROR;
glAttachShader (*prog, *frag);
if (got_gl_error ("glAttachShader fragments"))
goto HANDLE_ERROR;
glLinkProgram (*prog);
glGetProgramiv (*prog, GL_LINK_STATUS, &test);
if (test != GL_FALSE) {
GST_DEBUG_OBJECT (ctx->element, "GLES: Successfully linked program");
} else {
GST_ERROR_OBJECT (ctx->element, "Couldn't link program");
goto HANDLE_ERROR;
}
return TRUE;
HANDLE_ERROR:
{
if (*frag && *prog)
glDetachShader (*prog, *frag);
if (*vert && *prog)
glDetachShader (*prog, *vert);
if (*prog)
glDeleteProgram (*prog);
if (*frag)
glDeleteShader (*frag);
if (*vert)
glDeleteShader (*vert);
*prog = 0;
*frag = 0;
*vert = 0;
return FALSE;
}
}
gboolean
gst_egl_adaptation_init_surface (GstEglAdaptationContext * ctx,
GstVideoFormat format, gboolean tex_external_oes)
{
GLboolean ret;
const gchar *texnames[3] = { NULL, };
gchar *frag_prog = NULL;
gboolean free_frag_prog = FALSE;
gint i;
GLint target;
GST_DEBUG_OBJECT (ctx->element, "Enter EGL surface setup");
if (!gst_egl_adaptation_create_surface (ctx)) {
GST_ERROR_OBJECT (ctx->element, "Can't create surface");
goto HANDLE_ERROR_LOCKED;
}
if (!gst_egl_adaptation_context_make_current (ctx, TRUE))
goto HANDLE_ERROR_LOCKED;
gst_egl_adaptation_query_buffer_preserved (ctx);
gst_egl_adaptation_init_exts (ctx);
/* Save surface dims */
gst_egl_adaptation_update_surface_dimensions (ctx);
/* Save display's pixel aspect ratio
*
* DAR is reported as w/h * EGL_DISPLAY_SCALING wich is
* a constant with value 10000. This attribute is only
* supported if the EGL version is >= 1.2
* XXX: Setup this as a property.
* or some other one time check. Right now it's being called once
* per frame.
*/
gst_egl_adaptation_query_par (ctx);
/* We have a surface! */
ctx->have_surface = TRUE;
/* Init vertex and fragment GLSL shaders.
* Note: Shader compiler support is optional but we currently rely on it.
*/
glGetBooleanv (GL_SHADER_COMPILER, &ret);
if (ret == GL_FALSE) {
GST_ERROR_OBJECT (ctx->element, "Shader compiler support is unavailable!");
goto HANDLE_ERROR;
}
/* Build shader program for video texture rendering */
switch (format) {
case GST_VIDEO_FORMAT_AYUV:
frag_prog = (gchar *) frag_AYUV_prog;
free_frag_prog = FALSE;
ctx->n_textures = 1;
texnames[0] = "tex";
break;
case GST_VIDEO_FORMAT_Y444:
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
case GST_VIDEO_FORMAT_Y42B:
case GST_VIDEO_FORMAT_Y41B:
frag_prog = (gchar *) frag_PLANAR_YUV_prog;
free_frag_prog = FALSE;
ctx->n_textures = 3;
texnames[0] = "Ytex";
texnames[1] = "Utex";
texnames[2] = "Vtex";
break;
case GST_VIDEO_FORMAT_NV12:
frag_prog = g_strdup_printf (frag_NV12_NV21_prog, 'r', 'a');
free_frag_prog = TRUE;
ctx->n_textures = 2;
texnames[0] = "Ytex";
texnames[1] = "UVtex";
break;
case GST_VIDEO_FORMAT_NV21:
frag_prog = g_strdup_printf (frag_NV12_NV21_prog, 'a', 'r');
free_frag_prog = TRUE;
ctx->n_textures = 2;
texnames[0] = "Ytex";
texnames[1] = "UVtex";
break;
case GST_VIDEO_FORMAT_BGR:
case GST_VIDEO_FORMAT_BGRx:
case GST_VIDEO_FORMAT_BGRA:
frag_prog = g_strdup_printf (frag_REORDER_prog, 'b', 'g', 'r');
free_frag_prog = TRUE;
ctx->n_textures = 1;
texnames[0] = "tex";
break;
case GST_VIDEO_FORMAT_xRGB:
case GST_VIDEO_FORMAT_ARGB:
frag_prog = g_strdup_printf (frag_REORDER_prog, 'g', 'b', 'a');
free_frag_prog = TRUE;
ctx->n_textures = 1;
texnames[0] = "tex";
break;
case GST_VIDEO_FORMAT_xBGR:
case GST_VIDEO_FORMAT_ABGR:
frag_prog = g_strdup_printf (frag_REORDER_prog, 'a', 'b', 'g');
free_frag_prog = TRUE;
ctx->n_textures = 1;
texnames[0] = "tex";
break;
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_RGBx:
case GST_VIDEO_FORMAT_RGBA:
case GST_VIDEO_FORMAT_RGB16:
frag_prog = (gchar *) frag_COPY_prog;
free_frag_prog = FALSE;
ctx->n_textures = 1;
texnames[0] = "tex";
break;
default:
g_assert_not_reached ();
break;
}
if (tex_external_oes) {
frag_prog = (gchar *) frag_COPY_externel_oes_prog;
free_frag_prog = FALSE;
ctx->n_textures = 1;
texnames[0] = "tex";
}
if (!create_shader_program (ctx,
&ctx->glslprogram[0],
&ctx->vertshader[0],
&ctx->fragshader[0], vert_COPY_prog, frag_prog)) {
if (free_frag_prog)
g_free (frag_prog);
frag_prog = NULL;
goto HANDLE_ERROR;
}
if (free_frag_prog)
g_free (frag_prog);
frag_prog = NULL;
ctx->position_loc[0] = glGetAttribLocation (ctx->glslprogram[0], "position");
ctx->texpos_loc[0] = glGetAttribLocation (ctx->glslprogram[0], "texpos");
ctx->tex_scale_loc[0][0] =
glGetUniformLocation (ctx->glslprogram[0], "tex_scale0");
ctx->tex_scale_loc[0][1] =
glGetUniformLocation (ctx->glslprogram[0], "tex_scale1");
ctx->tex_scale_loc[0][2] =
glGetUniformLocation (ctx->glslprogram[0], "tex_scale2");
for (i = 0; i < ctx->n_textures; i++) {
ctx->tex_loc[0][i] =
glGetUniformLocation (ctx->glslprogram[0], texnames[i]);
}
if (!ctx->buffer_preserved) {
/* Build shader program for black borders */
if (!create_shader_program (ctx,
&ctx->glslprogram[1],
&ctx->vertshader[1],
&ctx->fragshader[1], vert_COPY_prog_no_tex, frag_BLACK_prog))
goto HANDLE_ERROR;
ctx->position_loc[1] =
glGetAttribLocation (ctx->glslprogram[1], "position");
}
/* Generate textures */
if (!ctx->have_texture) {
GST_INFO_OBJECT (ctx->element, "Performing initial texture setup");
if (tex_external_oes) {
target = GL_TEXTURE_EXTERNAL_OES;
} else {
target = GL_TEXTURE_2D;
}
glGenTextures (ctx->n_textures, ctx->texture);
if (got_gl_error ("glGenTextures"))
goto HANDLE_ERROR_LOCKED;
for (i = 0; i < ctx->n_textures; i++) {
glBindTexture (target, ctx->texture[i]);
if (got_gl_error ("glBindTexture"))
goto HANDLE_ERROR;
/* Set 2D resizing params */
glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* If these are not set the texture image unit will return
* (R, G, B, A) = black on glTexImage2D for non-POT width/height
* frames. For a deeper explanation take a look at the OpenGL ES
* documentation for glTexParameter */
glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (got_gl_error ("glTexParameteri"))
goto HANDLE_ERROR_LOCKED;
}
ctx->have_texture = TRUE;
}
glUseProgram (0);
return TRUE;
/* Errors */
HANDLE_ERROR_LOCKED:
HANDLE_ERROR:
GST_ERROR_OBJECT (ctx->element, "Couldn't setup EGL surface");
return FALSE;
}
gboolean
gst_egl_adaptation_choose_config (GstEglAdaptationContext * ctx)
{
gint egl_configs;
if (!_gst_egl_choose_config (ctx, FALSE, &egl_configs)) {
GST_ERROR_OBJECT (ctx->element, "eglChooseConfig failed");
goto HANDLE_ERROR;
}
if (egl_configs < 1) {
GST_ERROR_OBJECT (ctx->element,
"Could not find matching framebuffer config");
goto HANDLE_ERROR;
}
if (!gst_egl_adaptation_create_egl_context (ctx)) {
GST_ERROR_OBJECT (ctx->element, "Error getting context, eglCreateContext");
goto HANDLE_ERROR;
}
return TRUE;
/* Errors */
HANDLE_ERROR:
GST_ERROR_OBJECT (ctx->element, "Couldn't choose an usable config");
return FALSE;
}
GstEglAdaptationContext *
gst_egl_adaptation_context_new (GstElement * element)
{
GstEglAdaptationContext *ctx = g_new0 (GstEglAdaptationContext, 1);
ctx->element = gst_object_ref (element);
gst_egl_adaptation_init (ctx);
return ctx;
}
void
gst_egl_adaptation_context_free (GstEglAdaptationContext * ctx)
{
gst_egl_adaptation_deinit (ctx);
if (GST_OBJECT_REFCOUNT(ctx->element))
gst_object_unref (ctx->element);
g_free (ctx);
}
gboolean
gst_egl_adaptation_reset_window (GstEglAdaptationContext * ctx,
GstVideoFormat format, gboolean tex_external_oes)
{
if (!gst_egl_adaptation_context_make_current (ctx, FALSE))
return FALSE;
gst_egl_adaptation_destroy_surface (ctx);
ctx->used_window = ctx->window;
if (!gst_egl_adaptation_init_surface (ctx, format, tex_external_oes))
return FALSE;
if (!gst_egl_adaptation_context_make_current (ctx, TRUE))
return FALSE;
return TRUE;
}

View File

@@ -0,0 +1,202 @@
/*
* GStreamer EGL/GLES Sink Adaptation
* Copyright (C) 2012-2013 Collabora Ltd.
* @author: Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
* @author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
* @author: Thiago Santos <thiago.sousa.santos@collabora.com>
* Copyright (c) 2015-2024, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __GST_EGL_ADAPTATION_H__
#define __GST_EGL_ADAPTATION_H__
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gst/gst.h>
#include <gst/video/gstvideopool.h>
#if defined (USE_EGL_RPI) && defined(__GNUC__)
#ifndef __VCCOREVER__
#define __VCCOREVER__ 0x04000000
#endif
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC optimize ("gnu89-inline")
#endif
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#ifdef HAVE_IOS
#include <OpenGLES/ES2/gl.h>
#else
#include <gst/egl/egl.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#endif
#if defined (USE_EGL_RPI) && defined(__GNUC__)
#pragma GCC reset_options
#pragma GCC diagnostic pop
#endif
G_BEGIN_DECLS
typedef struct _GstEglAdaptationContext GstEglAdaptationContext;
typedef struct _GstEglGlesImageFmt GstEglGlesImageFmt;
#ifdef HAVE_IOS
typedef struct _GstEaglContext GstEaglContext;
#else
typedef struct _GstEglGlesRenderContext GstEglGlesRenderContext;
#endif
typedef struct _coord5
{
float x;
float y;
float z;
float a; /* texpos x */
float b; /* texpos y */
} coord5;
typedef struct
{
GLuint texture;
EGLDisplay display;
EGLContext eglcontext;
} GstEGLGLESImageData;
/*
* GstEglAdaptationContext:
* @have_vbo: Set if the GLES VBO setup has been performed
* @have_texture: Set if the GLES texture setup has been performed
* @have_surface: Set if the EGL surface setup has been performed
*
* The #GstEglAdaptationContext data structure.
*/
struct _GstEglAdaptationContext
{
GstElement *element;
#ifdef HAVE_IOS
GstEaglContext *eaglctx;
void * window, *used_window;
#else
GstEglGlesRenderContext *eglglesctx;
GstEGLDisplay *display, *set_display;
EGLNativeWindowType window, used_window;
#endif
GLuint fragshader[2]; /* frame, border */
GLuint vertshader[2]; /* frame, border */
GLuint glslprogram[2]; /* frame, border */
GLuint texture[4]; /* RGB/Y, U/UV, V */
/* shader vars */
GLuint position_loc[2]; /* frame, border */
GLuint texpos_loc[1]; /* frame */
GLuint tex_scale_loc[1][3]; /* [frame] RGB/Y, U/UV, V */
GLuint tex_loc[1][3]; /* [frame] RGB/Y, U/UV, V */
coord5 position_array[16]; /* 4 x Frame x-normal,y-normal, 4x Frame x-normal,y-flip, 4 x Border1, 4 x Border2 */
unsigned short index_array[4];
unsigned int position_buffer, index_buffer;
gint n_textures;
gint surface_width;
gint surface_height;
gint pixel_aspect_ratio_n;
gint pixel_aspect_ratio_d;
gboolean have_vbo;
gboolean have_texture;
gboolean have_surface;
gboolean buffer_preserved;
};
GST_DEBUG_CATEGORY_EXTERN (egladaption_debug);
void gst_egl_adaption_init (void);
GstEglAdaptationContext * gst_egl_adaptation_context_new (GstElement * element);
void gst_egl_adaptation_context_free (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_init (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_deinit (GstEglAdaptationContext * ctx);
gboolean gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_query_buffer_preserved (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_query_par (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_release_thread (void);
gboolean
gst_egl_adaptation_create_egl_context (GstEglAdaptationContext * ctx);
#ifndef HAVE_IOS
EGLContext gst_egl_adaptation_context_get_egl_context (GstEglAdaptationContext * ctx);
#endif
/* platform window */
gboolean gst_egl_adaptation_create_native_window (GstEglAdaptationContext
* ctx, gint width, gint height, gpointer * own_window_data, gchar* winsys);
void gst_egl_adaptation_destroy_native_window (GstEglAdaptationContext * ctx, gpointer * own_window_data, gchar* winsys);
GstCaps *gst_egl_adaptation_fill_supported_fbuffer_configs (GstEglAdaptationContext * ctx);
gboolean gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx, gchar* winsys);
gboolean gst_egl_adaptation_choose_config (GstEglAdaptationContext * ctx);
gboolean gst_egl_adaptation_init_surface (GstEglAdaptationContext * ctx, GstVideoFormat format, gboolean tex_external_oes);
void gst_egl_adaptation_init_exts (GstEglAdaptationContext * ctx);
gboolean gst_egl_adaptation_update_surface_dimensions (GstEglAdaptationContext * ctx);
gboolean _gst_egl_choose_config (GstEglAdaptationContext * ctx, gboolean try_only, gint * num_configs);
gboolean got_gl_error (const char *wtf);
gboolean got_egl_error (const char *wtf);
void gst_egl_adaptation_set_window (GstEglAdaptationContext * ctx, guintptr window);
gboolean gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx, gboolean bind);
void gst_egl_adaptation_cleanup (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_bind_API (GstEglAdaptationContext * ctx);
gboolean gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx, gchar* winsys, gpointer * own_window_data, GstBuffer *buf, gboolean show_latency);
gboolean gst_egl_adaptation_reset_window (GstEglAdaptationContext * ctx, GstVideoFormat format, gboolean tex_external_oes);
#ifndef HAVE_IOS
/* TODO: The goal is to move this function to gstegl lib (or
* splitted between gstegl lib and gstgl lib) in order to be used in
* webkitVideoSink
* So it has to be independent of GstEglAdaptationContext */
GstBuffer *
gst_egl_image_allocator_alloc_eglimage (GstAllocator * allocator,
GstEGLDisplay * display, EGLContext eglcontext, GstVideoFormat format,
gint width, gint height);
#endif
G_END_DECLS
#endif /* __GST_EGL_ADAPTATION_H__ */

View File

@@ -0,0 +1,970 @@
/*
* Copyright (C) 2012-2013 Collabora Ltd.
* @author: Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
* @author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
* @author: Thiago Santos <thiago.sousa.santos@collabora.com>
* Copyright (c) 2015-2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "gstegladaptation.h"
#include "gsteglglessink.h"
#include "video_platform_wrapper.h"
#include <string.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <gst/egl/egl.h>
#define GST_CAT_DEFAULT egladaption_debug
/* Some EGL implementations are reporting wrong
* values for the display's EGL_PIXEL_ASPECT_RATIO.
* They are required by the khronos specs to report
* this value as w/h * EGL_DISPLAY_SCALING (Which is
* a constant with value 10000) but at least the
* Galaxy SIII (Android) is reporting just 1 when
* w = h. We use these two to bound returned values to
* sanity.
*/
#define EGL_SANE_DAR_MIN ((EGL_DISPLAY_SCALING)/10)
#define EGL_SANE_DAR_MAX ((EGL_DISPLAY_SCALING)*10)
#define GST_EGLGLESSINK_EGL_MIN_VERSION 1
static const EGLint eglglessink_RGBA8888_attribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
/*
* GstEglGlesRenderContext:
* @config: Current EGL config
* @eglcontext: Current EGL context
* @egl_minor: EGL version (minor)
* @egl_major: EGL version (major)
*
* This struct holds the sink's EGL/GLES rendering context.
*/
struct _GstEglGlesRenderContext
{
EGLConfig config;
EGLContext eglcontext;
EGLSurface surface;
EGLint egl_minor, egl_major;
};
gboolean
got_egl_error (const char *wtf)
{
EGLint error;
if ((error = eglGetError ()) != EGL_SUCCESS) {
GST_CAT_DEBUG (GST_CAT_DEFAULT, "EGL ERROR: %s returned 0x%04x", wtf,
error);
return TRUE;
}
return FALSE;
}
/* Prints available EGL/GLES extensions
* If another rendering path is implemented this is the place
* where you want to check for the availability of its supporting
* EGL/GLES extensions.
*/
void
gst_egl_adaptation_init_exts (GstEglAdaptationContext * ctx)
{
#ifndef GST_DISABLE_GST_DEBUG
const char *eglexts;
unsigned const char *glexts;
eglexts = eglQueryString (gst_egl_display_get (ctx->display), EGL_EXTENSIONS);
glexts = glGetString (GL_EXTENSIONS);
GST_DEBUG_OBJECT (ctx->element, "Available EGL extensions: %s\n",
GST_STR_NULL (eglexts));
GST_DEBUG_OBJECT (ctx->element, "Available GLES extensions: %s\n",
GST_STR_NULL ((const char *) glexts));
#endif
return;
}
gboolean
gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx, gchar* winsys)
{
GstMessage *msg;
GstEglGlesSink *sink = (GstEglGlesSink *) ctx->element;
EGLDisplay display = EGL_NO_DISPLAY;
GST_DEBUG_OBJECT (ctx->element, "Enter EGL initial configuration");
if (!platform_wrapper_init ()) {
GST_ERROR_OBJECT (ctx->element, "Couldn't init EGL platform wrapper");
goto HANDLE_ERROR;
}
msg =
gst_message_new_need_context (GST_OBJECT_CAST (ctx->element),
GST_EGL_DISPLAY_CONTEXT_TYPE);
gst_element_post_message (GST_ELEMENT_CAST (ctx->element), msg);
GST_OBJECT_LOCK (ctx->element);
if (!ctx->set_display) {
GstContext *context;
GST_OBJECT_UNLOCK (ctx->element);
#ifdef USE_EGL_WAYLAND
if (g_strcmp0(winsys, "wayland") == 0) {
display = eglGetDisplay (platform_initialize_display_wayland());
}
#endif
#ifdef USE_EGL_X11
if (g_strcmp0(winsys, "x11") == 0) {
display = eglGetDisplay (sink->display);
}
#endif
if (display == EGL_NO_DISPLAY) {
GST_ERROR_OBJECT (ctx->element, "Could not get EGL display connection");
goto HANDLE_ERROR; /* No EGL error is set by eglGetDisplay() */
}
ctx->display = gst_egl_display_new (display, NULL);
context = gst_context_new_egl_display (ctx->display, FALSE);
msg = gst_message_new_have_context (GST_OBJECT (ctx->element), context);
gst_element_post_message (GST_ELEMENT_CAST (ctx->element), msg);
} else {
ctx->display = ctx->set_display;
GST_OBJECT_UNLOCK (ctx->element);
}
if (!eglInitialize (gst_egl_display_get (ctx->display),
&ctx->eglglesctx->egl_major, &ctx->eglglesctx->egl_minor)) {
got_egl_error ("eglInitialize");
GST_ERROR_OBJECT (ctx->element, "Could not init EGL display connection");
goto HANDLE_EGL_ERROR;
}
/* Check against required EGL version
* XXX: Need to review the version requirement in terms of the needed API
*/
if (ctx->eglglesctx->egl_major < GST_EGLGLESSINK_EGL_MIN_VERSION) {
GST_ERROR_OBJECT (ctx->element, "EGL v%d needed, but you only have v%d.%d",
GST_EGLGLESSINK_EGL_MIN_VERSION, ctx->eglglesctx->egl_major,
ctx->eglglesctx->egl_minor);
goto HANDLE_ERROR;
}
GST_INFO_OBJECT (ctx->element, "System reports supported EGL version v%d.%d",
ctx->eglglesctx->egl_major, ctx->eglglesctx->egl_minor);
eglBindAPI (EGL_OPENGL_ES_API);
return TRUE;
/* Errors */
HANDLE_EGL_ERROR:
GST_ERROR_OBJECT (ctx->element, "EGL call returned error %x", eglGetError ());
HANDLE_ERROR:
GST_ERROR_OBJECT (ctx->element, "Couldn't setup window/surface from handle");
return FALSE;
}
gboolean
gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx,
gboolean bind)
{
g_assert (ctx->display != NULL);
if (bind && ctx->eglglesctx->surface && ctx->eglglesctx->eglcontext) {
EGLContext *cur_ctx = eglGetCurrentContext ();
if (cur_ctx == ctx->eglglesctx->eglcontext) {
GST_DEBUG_OBJECT (ctx->element,
"Already attached the context to thread %p", g_thread_self ());
return TRUE;
}
GST_DEBUG_OBJECT (ctx->element, "Attaching context to thread %p",
g_thread_self ());
if (!eglMakeCurrent (gst_egl_display_get (ctx->display),
ctx->eglglesctx->surface, ctx->eglglesctx->surface,
ctx->eglglesctx->eglcontext)) {
got_egl_error ("eglMakeCurrent");
GST_ERROR_OBJECT (ctx->element, "Couldn't bind context");
return FALSE;
}
} else {
GST_DEBUG_OBJECT (ctx->element, "Detaching context from thread %p",
g_thread_self ());
if (!eglMakeCurrent (gst_egl_display_get (ctx->display),
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
got_egl_error ("eglMakeCurrent");
GST_ERROR_OBJECT (ctx->element, "Couldn't unbind context");
return FALSE;
}
}
return TRUE;
}
/* XXX: Lock eglgles context? */
gboolean
gst_egl_adaptation_update_surface_dimensions (GstEglAdaptationContext * ctx)
{
gint width, height;
/* Save surface dims */
eglQuerySurface (gst_egl_display_get (ctx->display),
ctx->eglglesctx->surface, EGL_WIDTH, &width);
eglQuerySurface (gst_egl_display_get (ctx->display),
ctx->eglglesctx->surface, EGL_HEIGHT, &height);
if (width != ctx->surface_width || height != ctx->surface_height) {
ctx->surface_width = width;
ctx->surface_height = height;
GST_INFO_OBJECT (ctx->element, "Got surface of %dx%d pixels", width,
height);
return TRUE;
}
return FALSE;
}
void
gst_egl_adaptation_bind_API (GstEglAdaptationContext * ctx)
{
eglBindAPI (EGL_OPENGL_ES_API);
}
gboolean
gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx, gchar* winsys,
gpointer * own_window_data, GstBuffer * buf, gboolean show_latency)
{
if (g_strcmp0(winsys, "wayland") == 0 && show_latency) {
register_presentation_feedback(own_window_data, buf);
}
gboolean ret = eglSwapBuffers (gst_egl_display_get (ctx->display),
ctx->eglglesctx->surface);
if (ret == EGL_FALSE) {
got_egl_error ("eglSwapBuffers");
}
return ret;
}
gboolean
_gst_egl_choose_config (GstEglAdaptationContext * ctx, gboolean try_only,
gint * num_configs)
{
EGLint cfg_number;
gboolean ret;
EGLConfig *config = NULL;
if (!try_only)
config = &ctx->eglglesctx->config;
ret = eglChooseConfig (gst_egl_display_get (ctx->display),
eglglessink_RGBA8888_attribs, config, 1, &cfg_number) != EGL_FALSE;
if (!ret)
got_egl_error ("eglChooseConfig");
else if (num_configs)
*num_configs = cfg_number;
return ret;
}
gboolean
gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx)
{
ctx->eglglesctx->surface =
eglCreateWindowSurface (gst_egl_display_get (ctx->display),
ctx->eglglesctx->config, ctx->used_window, NULL);
if (ctx->eglglesctx->surface == EGL_NO_SURFACE) {
got_egl_error ("eglCreateWindowSurface");
GST_ERROR_OBJECT (ctx->element, "Can't create surface");
return FALSE;
}
return TRUE;
}
void
gst_egl_adaptation_query_buffer_preserved (GstEglAdaptationContext * ctx)
{
EGLint swap_behavior;
ctx->buffer_preserved = FALSE;
if (eglQuerySurface (gst_egl_display_get (ctx->display),
ctx->eglglesctx->surface, EGL_SWAP_BEHAVIOR, &swap_behavior)) {
GST_DEBUG_OBJECT (ctx->element, "Buffer swap behavior %x", swap_behavior);
ctx->buffer_preserved = swap_behavior == EGL_BUFFER_PRESERVED;
} else {
GST_DEBUG_OBJECT (ctx->element, "Can't query buffer swap behavior");
}
}
void
gst_egl_adaptation_query_par (GstEglAdaptationContext * ctx)
{
EGLint display_par;
/* fixed value */
ctx->pixel_aspect_ratio_d = EGL_DISPLAY_SCALING;
/* Save display's pixel aspect ratio
*
* DAR is reported as w/h * EGL_DISPLAY_SCALING wich is
* a constant with value 10000. This attribute is only
* supported if the EGL version is >= 1.2
* XXX: Setup this as a property.
* or some other one time check. Right now it's being called once
* per frame.
*/
if (ctx->eglglesctx->egl_major == 1 && ctx->eglglesctx->egl_minor < 2) {
GST_DEBUG_OBJECT (ctx->element, "Can't query PAR. Using default: %dx%d",
EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING);
ctx->pixel_aspect_ratio_n = EGL_DISPLAY_SCALING;
} else {
eglQuerySurface (gst_egl_display_get (ctx->display),
ctx->eglglesctx->surface, EGL_PIXEL_ASPECT_RATIO, &display_par);
/* Fix for outbound DAR reporting on some implementations not
* honoring the 'should return w/h * EGL_DISPLAY_SCALING' spec
* requirement
*/
if (display_par == EGL_UNKNOWN || display_par < EGL_SANE_DAR_MIN ||
display_par > EGL_SANE_DAR_MAX) {
GST_DEBUG_OBJECT (ctx->element, "Nonsensical PAR value returned: %d. "
"Bad EGL implementation? "
"Will use default: %d/%d", ctx->pixel_aspect_ratio_n,
EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING);
ctx->pixel_aspect_ratio_n = EGL_DISPLAY_SCALING;
} else {
ctx->pixel_aspect_ratio_n = display_par;
}
}
}
gboolean
gst_egl_adaptation_create_egl_context (GstEglAdaptationContext * ctx)
{
EGLint con_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
ctx->eglglesctx->eglcontext =
eglCreateContext (gst_egl_display_get (ctx->display),
ctx->eglglesctx->config, EGL_NO_CONTEXT, con_attribs);
if (ctx->eglglesctx->eglcontext == EGL_NO_CONTEXT) {
GST_ERROR_OBJECT (ctx->element, "EGL call returned error %x",
eglGetError ());
return FALSE;
}
GST_DEBUG_OBJECT (ctx->element, "EGL Context: %p",
ctx->eglglesctx->eglcontext);
return TRUE;
}
EGLContext
gst_egl_adaptation_context_get_egl_context (GstEglAdaptationContext * ctx)
{
g_return_val_if_fail (ctx != NULL, EGL_NO_CONTEXT);
return ctx->eglglesctx->eglcontext;
}
static void
gst_egl_gles_image_data_free (GstEGLGLESImageData * data)
{
if (!eglMakeCurrent (data->display,
EGL_NO_SURFACE, EGL_NO_SURFACE, data->eglcontext)) {
got_egl_error ("eglMakeCurrent");
g_slice_free (GstEGLGLESImageData, data);
return;
}
glDeleteTextures (1, &data->texture);
g_slice_free (GstEGLGLESImageData, data);
}
GstBuffer *
gst_egl_image_allocator_alloc_eglimage (GstAllocator * allocator,
GstEGLDisplay * display, EGLContext eglcontext, GstVideoFormat format,
gint width, gint height)
{
GstEGLGLESImageData *data = NULL;
GstBuffer *buffer;
GstVideoInfo info;
guint i;
gint stride[GST_VIDEO_MAX_PLANES];
gsize offset[GST_VIDEO_MAX_PLANES];
GstMemory *mem[3] = { NULL, NULL, NULL };
guint n_mem;
GstMemoryFlags flags = 0;
memset (stride, 0, sizeof (stride));
memset (offset, 0, sizeof (offset));
if (!gst_egl_image_memory_is_mappable ())
flags |= GST_MEMORY_FLAG_NOT_MAPPABLE;
/* See https://bugzilla.gnome.org/show_bug.cgi?id=695203 */
flags |= GST_MEMORY_FLAG_NO_SHARE;
gst_video_info_set_format (&info, format, width, height);
switch (format) {
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_BGR:{
gsize size;
EGLImageKHR image;
mem[0] =
gst_egl_image_allocator_alloc (allocator, display,
GST_VIDEO_GL_TEXTURE_TYPE_RGB, GST_VIDEO_INFO_WIDTH (&info),
GST_VIDEO_INFO_HEIGHT (&info), &size);
if (mem[0]) {
stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info);
n_mem = 1;
GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE);
} else {
data = g_slice_new0 (GstEGLGLESImageData);
data->display = gst_egl_display_get (display);
data->eglcontext = eglcontext;
stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 3);
size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info);
glGenTextures (1, &data->texture);
if (got_gl_error ("glGenTextures"))
goto mem_error;
glBindTexture (GL_TEXTURE_2D, data->texture);
if (got_gl_error ("glBindTexture"))
goto mem_error;
/* Set 2D resizing params */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* If these are not set the texture image unit will return
* * (R, G, B, A) = black on glTexImage2D for non-POT width/height
* * frames. For a deeper explanation take a look at the OpenGL ES
* * documentation for glTexParameter */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (got_gl_error ("glTexParameteri"))
goto mem_error;
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB,
GST_VIDEO_INFO_WIDTH (&info),
GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
if (got_gl_error ("glTexImage2D"))
goto mem_error;
image =
gst_egl_display_image_create (display,
eglcontext, EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer) (uintptr_t) data->texture, NULL);
if (got_egl_error ("eglCreateImageKHR"))
goto mem_error;
mem[0] =
gst_egl_image_allocator_wrap (allocator, display,
image, GST_VIDEO_GL_TEXTURE_TYPE_RGB,
flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free);
n_mem = 1;
}
break;
}
case GST_VIDEO_FORMAT_RGB16:{
EGLImageKHR image;
gsize size;
mem[0] =
gst_egl_image_allocator_alloc (allocator, display,
GST_VIDEO_GL_TEXTURE_TYPE_RGB, GST_VIDEO_INFO_WIDTH (&info),
GST_VIDEO_INFO_HEIGHT (&info), &size);
if (mem[0]) {
stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info);
n_mem = 1;
GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE);
} else {
data = g_slice_new0 (GstEGLGLESImageData);
data->display = gst_egl_display_get (display);
data->eglcontext = eglcontext;
stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 2);
size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info);
glGenTextures (1, &data->texture);
if (got_gl_error ("glGenTextures"))
goto mem_error;
glBindTexture (GL_TEXTURE_2D, data->texture);
if (got_gl_error ("glBindTexture"))
goto mem_error;
/* Set 2D resizing params */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* If these are not set the texture image unit will return
* * (R, G, B, A) = black on glTexImage2D for non-POT width/height
* * frames. For a deeper explanation take a look at the OpenGL ES
* * documentation for glTexParameter */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (got_gl_error ("glTexParameteri"))
goto mem_error;
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB,
GST_VIDEO_INFO_WIDTH (&info),
GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
NULL);
if (got_gl_error ("glTexImage2D"))
goto mem_error;
image =
gst_egl_display_image_create (display,
eglcontext, EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer) (uintptr_t) data->texture, NULL);
if (got_egl_error ("eglCreateImageKHR"))
goto mem_error;
mem[0] =
gst_egl_image_allocator_wrap (allocator, display,
image, GST_VIDEO_GL_TEXTURE_TYPE_RGB,
flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free);
n_mem = 1;
}
break;
}
case GST_VIDEO_FORMAT_NV12:
case GST_VIDEO_FORMAT_NV21:{
EGLImageKHR image;
gsize size[2];
mem[0] =
gst_egl_image_allocator_alloc (allocator, display,
GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info,
0), GST_VIDEO_INFO_COMP_HEIGHT (&info, 0), &size[0]);
mem[1] =
gst_egl_image_allocator_alloc (allocator, display,
GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA,
GST_VIDEO_INFO_COMP_WIDTH (&info, 1),
GST_VIDEO_INFO_COMP_HEIGHT (&info, 1), &size[1]);
if (mem[0] && mem[1]) {
stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (&info);
offset[1] = size[0];
stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (&info);
n_mem = 2;
GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE);
GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE);
} else {
if (mem[0])
gst_memory_unref (mem[0]);
if (mem[1])
gst_memory_unref (mem[1]);
mem[0] = mem[1] = NULL;
stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 0));
stride[1] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 1) * 2);
offset[1] = stride[0] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 0);
size[0] = offset[1];
size[1] = stride[1] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 1);
for (i = 0; i < 2; i++) {
data = g_slice_new0 (GstEGLGLESImageData);
data->display = gst_egl_display_get (display);
data->eglcontext = eglcontext;
glGenTextures (1, &data->texture);
if (got_gl_error ("glGenTextures"))
goto mem_error;
glBindTexture (GL_TEXTURE_2D, data->texture);
if (got_gl_error ("glBindTexture"))
goto mem_error;
/* Set 2D resizing params */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* If these are not set the texture image unit will return
* * (R, G, B, A) = black on glTexImage2D for non-POT width/height
* * frames. For a deeper explanation take a look at the OpenGL ES
* * documentation for glTexParameter */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (got_gl_error ("glTexParameteri"))
goto mem_error;
if (i == 0)
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
GST_VIDEO_INFO_COMP_WIDTH (&info, i),
GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE,
GL_UNSIGNED_BYTE, NULL);
else
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
GST_VIDEO_INFO_COMP_WIDTH (&info, i),
GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE, NULL);
if (got_gl_error ("glTexImage2D"))
goto mem_error;
image =
gst_egl_display_image_create (display,
eglcontext, EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer) (uintptr_t) data->texture, NULL);
if (got_egl_error ("eglCreateImageKHR"))
goto mem_error;
mem[i] =
gst_egl_image_allocator_wrap (allocator, display,
image,
(i ==
0 ? GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE :
GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA),
flags, size[i], data,
(GDestroyNotify) gst_egl_gles_image_data_free);
}
n_mem = 2;
}
break;
}
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
case GST_VIDEO_FORMAT_Y444:
case GST_VIDEO_FORMAT_Y42B:
case GST_VIDEO_FORMAT_Y41B:{
EGLImageKHR image;
gsize size[3];
mem[0] =
gst_egl_image_allocator_alloc (allocator, display,
GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info,
0), GST_VIDEO_INFO_COMP_HEIGHT (&info, 0), &size[0]);
mem[1] =
gst_egl_image_allocator_alloc (allocator, display,
GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info,
1), GST_VIDEO_INFO_COMP_HEIGHT (&info, 1), &size[1]);
mem[2] =
gst_egl_image_allocator_alloc (allocator, display,
GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info,
2), GST_VIDEO_INFO_COMP_HEIGHT (&info, 2), &size[2]);
if (mem[0] && mem[1] && mem[2]) {
stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (&info);
offset[1] = size[0];
stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (&info);
offset[2] = size[1];
stride[2] = size[2] / GST_VIDEO_INFO_HEIGHT (&info);
n_mem = 3;
GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE);
GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE);
GST_MINI_OBJECT_FLAG_SET (mem[2], GST_MEMORY_FLAG_NO_SHARE);
} else {
if (mem[0])
gst_memory_unref (mem[0]);
if (mem[1])
gst_memory_unref (mem[1]);
if (mem[2])
gst_memory_unref (mem[2]);
mem[0] = mem[1] = mem[2] = NULL;
stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 0));
stride[1] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 1));
stride[2] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 2));
size[0] = stride[0] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 0);
size[1] = stride[1] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 1);
size[2] = stride[2] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 2);
offset[0] = 0;
offset[1] = size[0];
offset[2] = offset[1] + size[1];
for (i = 0; i < 3; i++) {
data = g_slice_new0 (GstEGLGLESImageData);
data->display = gst_egl_display_get (display);
data->eglcontext = eglcontext;
glGenTextures (1, &data->texture);
if (got_gl_error ("glGenTextures"))
goto mem_error;
glBindTexture (GL_TEXTURE_2D, data->texture);
if (got_gl_error ("glBindTexture"))
goto mem_error;
/* Set 2D resizing params */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* If these are not set the texture image unit will return
* * (R, G, B, A) = black on glTexImage2D for non-POT width/height
* * frames. For a deeper explanation take a look at the OpenGL ES
* * documentation for glTexParameter */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (got_gl_error ("glTexParameteri"))
goto mem_error;
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
GST_VIDEO_INFO_COMP_WIDTH (&info, i),
GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE,
GL_UNSIGNED_BYTE, NULL);
if (got_gl_error ("glTexImage2D"))
goto mem_error;
image =
gst_egl_display_image_create (display,
eglcontext, EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer) (uintptr_t) data->texture, NULL);
if (got_egl_error ("eglCreateImageKHR"))
goto mem_error;
mem[i] =
gst_egl_image_allocator_wrap (allocator, display,
image, GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE,
flags, size[i], data,
(GDestroyNotify) gst_egl_gles_image_data_free);
}
n_mem = 3;
}
break;
}
case GST_VIDEO_FORMAT_RGBA:
case GST_VIDEO_FORMAT_BGRA:
case GST_VIDEO_FORMAT_ARGB:
case GST_VIDEO_FORMAT_ABGR:
case GST_VIDEO_FORMAT_RGBx:
case GST_VIDEO_FORMAT_BGRx:
case GST_VIDEO_FORMAT_xRGB:
case GST_VIDEO_FORMAT_xBGR:
case GST_VIDEO_FORMAT_AYUV:{
gsize size;
EGLImageKHR image;
mem[0] =
gst_egl_image_allocator_alloc (allocator, display,
GST_VIDEO_GL_TEXTURE_TYPE_RGBA, GST_VIDEO_INFO_WIDTH (&info),
GST_VIDEO_INFO_HEIGHT (&info), &size);
if (mem[0]) {
stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info);
n_mem = 1;
GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE);
} else {
data = g_slice_new0 (GstEGLGLESImageData);
data->display = gst_egl_display_get (display);
data->eglcontext = eglcontext;
stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 4);
size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info);
glGenTextures (1, &data->texture);
if (got_gl_error ("glGenTextures"))
goto mem_error;
glBindTexture (GL_TEXTURE_2D, data->texture);
if (got_gl_error ("glBindTexture"))
goto mem_error;
/* Set 2D resizing params */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* If these are not set the texture image unit will return
* * (R, G, B, A) = black on glTexImage2D for non-POT width/height
* * frames. For a deeper explanation take a look at the OpenGL ES
* * documentation for glTexParameter */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (got_gl_error ("glTexParameteri"))
goto mem_error;
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
GST_VIDEO_INFO_WIDTH (&info),
GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (got_gl_error ("glTexImage2D"))
goto mem_error;
image =
gst_egl_display_image_create (display,
eglcontext, EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer) (uintptr_t) data->texture, NULL);
if (got_egl_error ("eglCreateImageKHR"))
goto mem_error;
mem[0] =
gst_egl_image_allocator_wrap (allocator, display,
image, GST_VIDEO_GL_TEXTURE_TYPE_RGBA,
flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free);
n_mem = 1;
}
break;
}
default:
g_assert_not_reached ();
break;
}
buffer = gst_buffer_new ();
gst_buffer_add_video_meta_full (buffer, 0, format, width, height,
GST_VIDEO_INFO_N_PLANES (&info), offset, stride);
for (i = 0; i < n_mem; i++)
gst_buffer_append_memory (buffer, mem[i]);
return buffer;
mem_error:
{
GST_ERROR_OBJECT (GST_CAT_DEFAULT, "Failed to create EGLImage");
if (data)
gst_egl_gles_image_data_free (data);
if (mem[0])
gst_memory_unref (mem[0]);
if (mem[1])
gst_memory_unref (mem[1]);
if (mem[2])
gst_memory_unref (mem[2]);
return NULL;
}
}
void
gst_egl_adaptation_destroy_native_window (GstEglAdaptationContext * ctx,
gpointer * own_window_data, gchar* winsys)
{
#ifdef USE_EGL_WAYLAND
if (g_strcmp0(winsys, "wayland") == 0) {
platform_destroy_native_window_wayland (gst_egl_display_get
(ctx->display), ctx->used_window, own_window_data);
platform_destroy_display_wayland();
}
#endif
#ifdef USE_EGL_X11
if (g_strcmp0(winsys, "x11") == 0) {
platform_destroy_native_window_x11 (gst_egl_display_get
(ctx->display), ctx->used_window, own_window_data);
}
#endif
}
gboolean
gst_egl_adaptation_create_native_window (GstEglAdaptationContext * ctx,
gint width, gint height, gpointer * own_window_data, gchar* winsys)
{
GstEglGlesSink *sink = (GstEglGlesSink *) ctx->element;
EGLNativeWindowType window = NULL;
#ifdef USE_EGL_WAYLAND
if (g_strcmp0(winsys, "wayland") == 0) {
window =
platform_create_native_window_wayland (sink->window_x,
sink->window_y,
width,
height,
sink->ivisurf_id,
own_window_data);
}
#endif
#ifdef USE_EGL_X11
if (g_strcmp0(winsys, "x11") == 0) {
window =
platform_create_native_window_x11 (sink->window_x,
sink->window_y,
width,
height,
own_window_data);
}
#endif
if (window)
gst_egl_adaptation_set_window (ctx, (uintptr_t) window);
GST_DEBUG_OBJECT (ctx->element, "Using window handle %p", (gpointer) window);
return window != 0;
}
void
gst_egl_adaptation_set_window (GstEglAdaptationContext * ctx, guintptr window)
{
ctx->window = (EGLNativeWindowType)(uintptr_t) window;
}
void
gst_egl_adaptation_init (GstEglAdaptationContext * ctx)
{
ctx->eglglesctx = g_new0 (GstEglGlesRenderContext, 1);
}
void
gst_egl_adaptation_deinit (GstEglAdaptationContext * ctx)
{
g_free (ctx->eglglesctx);
}
void
gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx)
{
if (ctx->eglglesctx->surface) {
eglDestroySurface (gst_egl_display_get (ctx->display),
ctx->eglglesctx->surface);
ctx->eglglesctx->surface = NULL;
ctx->have_surface = FALSE;
}
}
void
gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx)
{
if (ctx->eglglesctx->eglcontext) {
eglDestroyContext (gst_egl_display_get (ctx->display),
ctx->eglglesctx->eglcontext);
ctx->eglglesctx->eglcontext = NULL;
}
}
void
gst_egl_adaptation_release_thread ()
{
eglReleaseThread ();
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,168 @@
/*
* GStreamer EGL/GLES Sink
* Copyright (C) 2012 Collabora Ltd.
* @author: Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
* @author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
* Copyright (c) 2015-2024, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __GST_EGLGLESSINK_H__
#define __GST_EGLGLESSINK_H__
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/video/gstvideosink.h>
#include <gst/base/gstdataqueue.h>
#include <cuda.h>
#include <cudaGL.h>
#include <cuda_runtime.h>
#include "gstegladaptation.h"
#include "gstegljitter.h"
G_BEGIN_DECLS
#define GST_TYPE_EGLGLESSINK \
(gst_eglglessink_get_type())
#define GST_EGLGLESSINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EGLGLESSINK,GstEglGlesSink))
#define GST_EGLGLESSINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EGLGLESSINK,GstEglGlesSinkClass))
#define GST_IS_EGLGLESSINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EGLGLESSINK))
#define GST_IS_EGLGLESSINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EGLGLESSINK))
typedef struct _GstEglGlesSink GstEglGlesSink;
typedef struct _GstEglGlesSinkClass GstEglGlesSinkClass;
/*
* GstEglGlesSink:
* @format: Caps' video format field
* @display_region: Surface region to use as rendering canvas
* @sinkcaps: Full set of suported caps
* @current_caps: Current caps
* @rendering_path: Rendering path (Slow/Fast)
* @eglglesctx: Pointer to the associated EGL/GLESv2 rendering context
* @flow_lock: Simple concurrent access ward to the sink's runtime state
* @have_window: Set if the sink has access to a window to hold it's canvas
* @using_own_window: Set if the sink created its own window
* @egl_started: Set if the whole EGL setup has been performed
* @create_window: Property value holder to allow/forbid internal window creation
* @force_rendering_slow: Property value holder to force slow rendering path
* @force_aspect_ratio: Property value holder to consider PAR/DAR when scaling
*
* The #GstEglGlesSink data structure.
*/
struct _GstEglGlesSink
{
GstVideoSink videosink; /* Element hook */
/* Region of the surface that should be rendered */
GstVideoRectangle render_region;
gboolean render_region_changed;
gboolean render_region_user;
/* Region of render_region that should be filled
* with the video frames */
GstVideoRectangle display_region;
GstVideoRectangle crop;
gboolean crop_changed;
GstCaps *sinkcaps;
GstCaps *current_caps, *configured_caps;
GstVideoInfo configured_info;
gfloat stride[3];
GstVideoGLTextureOrientation orientation;
#ifndef HAVE_IOS
GstBufferPool *pool;
#endif
GstEglAdaptationContext *egl_context;
gint window_x;
gint window_y;
gint window_width;
gint window_height;
guint profile;
gint rows;
gint columns;
gint change_port;
/* Runtime flags */
gboolean have_window;
gboolean using_own_window;
gboolean egl_started;
gboolean is_closing;
gboolean using_cuda;
gboolean using_nvbufsurf;
gpointer own_window_data;
GMutex window_lock;
GThread *thread;
gboolean thread_running;
GstDataQueue *queue;
GCond render_exit_cond;
GCond render_cond;
GMutex render_lock;
GstFlowReturn last_flow;
GstMiniObject *dequeued_object;
GThread *event_thread;
GstBuffer *last_buffer;
EGLNativeDisplayType display;
GstEglJitterTool *pDeliveryJitter;
/* Properties */
gboolean create_window;
gboolean force_aspect_ratio;
gchar* winsys;
gboolean show_latency;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
GstBuffer *last_uploaded_buffer;
CUcontext cuContext;
CUgraphicsResource cuResource[3];
unsigned int gpu_id;
gboolean nvbuf_api_version_new;
unsigned int ivisurf_id;
/*
Pointer to a SW Buffer. This is needed in case of RGB/BGR as Cuda
doesn't support 3-channel formats. The cuda buffer (host or device)
is copied using cuMemCpy2D into this sw buffer and then fill the GL
texture from the SW buffer.
*/
uint8_t *swData;
};
struct _GstEglGlesSinkClass
{
GstVideoSinkClass parent_class;
};
GType gst_eglglessink_get_type (void);
G_END_DECLS
#endif /* __GST_EGLGLESSINK_H__ */

View File

@@ -0,0 +1,158 @@
/* Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an
* express license agreement from NVIDIA Corporation is strictly prohibited.
*/
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include "gstegljitter.h"
GstEglJitterTool *GstEglAllocJitterTool(const char *pName, guint nTicks)
{
GstEglJitterTool *pTool;
assert(pName);
assert(nTicks > 0);
pTool = malloc(sizeof(GstEglJitterTool));
if (!pTool)
return NULL;
memset(pTool, 0, sizeof(GstEglJitterTool));
pTool->pName = malloc(strlen(pName) + 1);
if (!pTool->pName)
{
free(pTool);
return NULL;
}
memcpy((char *)pTool->pName, pName, strlen(pName) + 1);
pTool->pTicks = malloc(sizeof(guint64) * nTicks);
if (!pTool->pTicks)
{
free(pTool->pName);
free(pTool);
return NULL;
}
pTool->nTicksMax = nTicks;
pTool->nTickCount = 0;
pTool->nLastTime = 0;
pTool->bShow = 0;
return pTool;
}
void GstEglFreeJitterTool(GstEglJitterTool *pTool)
{
if (!pTool)
return;
free(pTool->pName);
free(pTool->pTicks);
free(pTool);
}
void GstEglJitterToolAddPoint(GstEglJitterTool *pTool)
{
guint64 now;
assert(pTool);
static guint64 s_oldtime = 0;
static guint64 s_timedelta = 0;
struct timeval tv;
guint64 time;
(void)gettimeofday( &tv, 0 );
time = (guint64)( ( (guint64)tv.tv_sec * 1000 * 1000 ) + (guint64)tv.tv_usec );
if (time < s_oldtime)
s_timedelta += (s_oldtime - time);
s_oldtime = time;
time += s_timedelta;
now = time;
if (pTool->nLastTime == 0)
{
pTool->nLastTime = now;
return;
}
pTool->pTicks[pTool->nTickCount] = now - pTool->nLastTime;
pTool->nLastTime = now;
pTool->nTickCount++;
if (pTool->nTickCount < pTool->nTicksMax)
return;
{
double fAvg = 0;
double fStdDev = 0;
guint i;
for (i = 0; i < pTool->nTicksMax; i++)
fAvg += pTool->pTicks[i];
fAvg /= pTool->nTicksMax;
for (i = 0; i < pTool->nTicksMax; i++)
fStdDev += (fAvg - pTool->pTicks[i]) * (fAvg - pTool->pTicks[i]);
fStdDev = sqrt(fStdDev / (pTool->nTicksMax - 1));
if (pTool->bShow)
printf("%s: mean: %.2f std. dev: %.2f\n", pTool->pName,
fAvg, fStdDev);
if (pTool->nPos < MAX_JITTER_HISTORY)
{
pTool->fAvg[pTool->nPos] = fAvg;
pTool->fStdDev[pTool->nPos] = fStdDev;
pTool->nPos++;
}
}
pTool->nTickCount = 0;
}
void GstEglJitterToolSetShow(GstEglJitterTool *pTool, gboolean bShow)
{
pTool->bShow = bShow;
}
void GstEglJitterToolGetAvgs(GstEglJitterTool *pTool, double *pStdDev, double *pAvg,
double *pHighest)
{
guint i;
assert(pTool);
assert(pStdDev);
assert(pAvg);
assert(pHighest);
*pStdDev = 0;
*pAvg = 0;
*pHighest = 0;
if (pTool->nPos < 1)
return;
for (i = 1; i < pTool->nPos && i < MAX_JITTER_HISTORY; i++)
{
*pAvg = *pAvg + pTool->fAvg[i];
*pStdDev = *pStdDev + pTool->fStdDev[i];
if (pTool->fStdDev[i] > *pHighest)
*pHighest = pTool->fStdDev[i];
}
*pAvg = *pAvg / (pTool->nPos);
*pStdDev = *pStdDev / (pTool->nPos);
}

View File

@@ -0,0 +1,43 @@
/* Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an
* express license agreement from NVIDIA Corporation is strictly prohibited.
*/
#ifndef NVXJITTER_H_
#define NVXJITTER_H_
#include <gst/gst.h>
#include <stdio.h>
typedef struct GstEglJitterTool
{
gchar *pName;
guint64 *pTicks;
guint nTicksMax;
guint nTickCount;
guint64 nLastTime;
gboolean bShow;
#define MAX_JITTER_HISTORY 3000
double fAvg[MAX_JITTER_HISTORY];
double fStdDev[MAX_JITTER_HISTORY];
guint nPos;
} GstEglJitterTool;
GstEglJitterTool *GstEglAllocJitterTool(const char *pName, guint nTicks);
void GstEglFreeJitterTool(GstEglJitterTool *pTool);
void GstEglJitterToolAddPoint(GstEglJitterTool *pTool);
void GstEglJitterToolSetShow(GstEglJitterTool *pTool, gboolean bShow);
void GstEglJitterToolGetAvgs(GstEglJitterTool *pTool, double *pStdDev, double *pAvg,
double *pHighest);
#endif

View File

@@ -0,0 +1,955 @@
/*
* GStreamer Android Video Platform Wrapper
* Copyright (C) 2012 Collabora Ltd.
* @author: Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
* Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if defined (USE_EGL_RPI) && defined(__GNUC__)
#ifndef __VCCOREVER__
#define __VCCOREVER__ 0x04000000
#endif
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC optimize ("gnu89-inline")
#endif
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#if defined (USE_EGL_RPI) && defined(__GNUC__)
#pragma GCC reset_options
#pragma GCC diagnostic pop
#endif
#include <string.h>
#include <gst/gst.h>
#include "video_platform_wrapper.h"
GST_DEBUG_CATEGORY_STATIC (eglgles_platform_wrapper);
#define GST_CAT_DEFAULT eglgles_platform_wrapper
/* XXX: Likely to be removed */
gboolean
platform_wrapper_init (void)
{
GST_DEBUG_CATEGORY_INIT (eglgles_platform_wrapper,
"eglglessink-platform", 0,
"Platform dependent native-window utility routines for EglGles");
return TRUE;
}
#ifdef USE_EGL_X11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
EGLNativeWindowType
platform_create_native_window_x11 (gint x, gint y, gint width, gint height, gpointer * window_data)
{
Display *d;
Window w;
int s;
X11WindowData *data;
const gchar *app_name;
XSizeHints hints = {0};
hints.flags = PPosition ;
hints.x = x;
hints.y = y;
d = XOpenDisplay (NULL);
if (d == NULL) {
GST_ERROR ("Can't open X11 display");
return (EGLNativeWindowType) 0;
}
s = DefaultScreen (d);
w = XCreateSimpleWindow (d, RootWindow (d, s), hints.x, hints.y, width, height, 1,
BlackPixel (d, s), WhitePixel (d, s));
/* Prevent X from redrawing the background on ConfigureNotify.
Otherwise flickering is observed when resizing the window. */
XSetWindowBackgroundPixmap (d, w, None);
/* set application name as a title */
app_name = g_get_application_name ();
if (!app_name)
app_name = "eglglessink";
XStoreName (d, w, app_name);
XSetNormalHints(d, w, &hints);
XMapWindow (d, w);
Atom wmDeleteMessage = XInternAtom (d, "WM_DELETE_WINDOW", False);
if (wmDeleteMessage != None) {
XSetWMProtocols (d, w, &wmDeleteMessage, 1);
}
XFlush (d);
*window_data = data = g_slice_new0 (X11WindowData);
data->display = d;
return (EGLNativeWindowType) w;
}
gboolean
platform_destroy_native_window_x11 (EGLNativeDisplayType display,
EGLNativeWindowType window, gpointer * window_data)
{
X11WindowData *data = *window_data;
/* XXX: Should proly catch BadWindow */
XDestroyWindow (data->display, (Window) window);
XSync (data->display, FALSE);
XCloseDisplay (data->display);
g_slice_free (X11WindowData, data);
*window_data = NULL;
return TRUE;
}
#endif
#if USE_EGL_WAYLAND
WaylandDisplay *wayland_display;
volatile gint instance_count = 0;
volatile gint render_count = 0;
static void presentation_handle_clock_id (void *data, struct wp_presentation *presentation, uint32_t clk_id)
{
wayland_display->clock_id = clk_id;
};
static struct wp_presentation_listener presentation_listener = {
presentation_handle_clock_id
};
void global_registry_handler (void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version);
void global_registry_remover (void *data, struct wl_registry *registry, uint32_t id);
void global_registry_handler (void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)
{
if (strcmp (interface, "wl_compositor") == 0) {
wayland_display->compositor = wl_registry_bind (registry,
id,
&wl_compositor_interface,
1);
}
else if (strcmp (interface, "wl_shell") == 0) {
wayland_display->shell = wl_registry_bind (registry, id,
&wl_shell_interface, 1);
}
else if (strcmp (interface, wp_presentation_interface.name) == 0) {
wayland_display->presentation = wl_registry_bind (registry, id,
&wp_presentation_interface, 1);
wp_presentation_add_listener (wayland_display->presentation,
&presentation_listener, NULL);
}
else if (strcmp (interface, "ivi_application") == 0) {
wayland_display->ivi_application = wl_registry_bind (registry, id,
&ivi_application_interface, 1);
}
}
void global_registry_remover (void *data, struct wl_registry *registry, uint32_t id)
{
}
const struct wl_registry_listener registry_listener = {
global_registry_handler,
global_registry_remover
};
EGLNativeDisplayType platform_initialize_display_wayland (void)
{
wayland_display = g_slice_new0 (WaylandDisplay);
wayland_display->display = wl_display_connect (NULL);
if (wayland_display->display == NULL) {
GST_ERROR ("Can't connect to display");
return NULL;
}
wayland_display->registry = wl_display_get_registry (wayland_display->display);
wl_registry_add_listener (wayland_display->registry, &registry_listener, NULL);
wl_display_dispatch (wayland_display->display);
wl_display_roundtrip (wayland_display->display);
if (wayland_display->compositor == NULL ||
(wayland_display->shell == NULL && wayland_display->ivi_application == NULL)) {
GST_ERROR ("Can't find compositor or shell");
return NULL;
}
return (EGLNativeDisplayType) wayland_display->display;
}
EGLNativeWindowType
platform_create_native_window_wayland (gint x, gint y, gint width, gint height, guint ivisurf_id, gpointer * window_data)
{
WaylandWindowData *data;
*window_data = data = g_slice_new0 (WaylandWindowData);
data->surface = wl_compositor_create_surface (wayland_display->compositor);
if (data->surface == NULL) {
GST_ERROR ("Can't create surface");
return (EGLNativeWindowType) 0;
}
if (wayland_display->ivi_application){
data->ivi_surface = ivi_application_surface_create (wayland_display->ivi_application,
ivisurf_id, data->surface);
}
else {
data->shell_surface = wl_shell_get_shell_surface (wayland_display->shell, data->surface);
wl_shell_surface_set_toplevel (data->shell_surface);
}
data->egl_window = wl_egl_window_create (data->surface, width, height);
g_atomic_int_add(&instance_count, 1);
return (EGLNativeWindowType) data->egl_window;
}
gboolean platform_destroy_display_wayland (void)
{
if (g_atomic_int_compare_and_exchange(&instance_count, 0, 0)) {
if (wayland_display->compositor) {
wl_compositor_destroy (wayland_display->compositor);
wayland_display->compositor = NULL;
}
if (wayland_display->shell) {
wayland_display->shell = NULL;
}
if (wayland_display->presentation) {
wayland_display->presentation = NULL;
}
if (wayland_display->ivi_application) {
ivi_application_destroy (wayland_display->ivi_application);
wayland_display->ivi_application = NULL;
}
if (wayland_display->registry) {
wl_registry_destroy (wayland_display->registry);
wayland_display->registry = NULL;
}
if (wayland_display->display) {
wl_display_flush (wayland_display->display);
wl_display_disconnect (wayland_display->display);
wayland_display->display = NULL;
}
return TRUE;
}
return FALSE;
}
typedef struct {
GstBuffer *buf;
struct timespec tv;
} Feedback;
static void
timespec_from_proto(struct timespec *a, uint32_t tv_sec_hi,
uint32_t tv_sec_lo, uint32_t tv_nsec)
{
a->tv_sec = ((uint64_t)tv_sec_hi << 32) + tv_sec_lo;
a->tv_nsec = tv_nsec;
}
static int
timespec_diff_to_usec(const struct timespec *a, const struct timespec *b)
{
time_t secs = a->tv_sec - b->tv_sec;
long nsec = a->tv_nsec - b->tv_nsec;
return secs * 1000000 + nsec / 1000;
}
static void
feedback_sync_output(void *data,
struct wp_presentation_feedback *presentation_feedback,
struct wl_output *output)
{
/* not interested */
}
static void
feedback_presented(void *data,
struct wp_presentation_feedback *presentation_feedback,
uint32_t tv_sec_hi,
uint32_t tv_sec_lo,
uint32_t tv_nsec,
uint32_t refresh_nsec,
uint32_t seq_hi,
uint32_t seq_lo,
uint32_t flags)
{
Feedback *feedback = data;
GstBuffer *buf = feedback->buf;
struct timespec present_tv;
timespec_from_proto (&present_tv, tv_sec_hi, tv_sec_lo, tv_nsec);
double latency_ms = timespec_diff_to_usec (&present_tv, &feedback->tv) / 1000.0;
GST_DEBUG ("buffer PTS %lu is flipped, latency %.2f ms", buf->pts, latency_ms);
g_slice_free(Feedback, feedback);
}
static void
feedback_discarded(void *data,
struct wp_presentation_feedback *presentation_feedback)
{
/* not interested */
}
static struct wp_presentation_feedback_listener feedback_listener = {
feedback_sync_output,
feedback_presented,
feedback_discarded
};
gboolean register_presentation_feedback(gpointer * window_data, GstBuffer * buf)
{
WaylandWindowData *data = *window_data;
Feedback *feedback = g_slice_new0(Feedback);
feedback->buf = buf;
clock_gettime(wayland_display->clock_id, &feedback->tv);
struct wp_presentation_feedback *presentation_feedback = wp_presentation_feedback (wayland_display->presentation,
data->surface);
wp_presentation_feedback_add_listener (presentation_feedback, &feedback_listener, feedback);
if (render_count < 1) {
wl_display_flush (wayland_display->display);
}
else {
wl_display_dispatch (wayland_display->display);
wl_display_roundtrip (wayland_display->display);
}
g_atomic_int_add(&render_count, 1);
return TRUE;
}
gboolean platform_destroy_native_window_wayland (EGLNativeDisplayType display,
EGLNativeWindowType window, gpointer * window_data)
{
WaylandWindowData *data = *window_data;
if (data->egl_window) {
data->egl_window = NULL;
}
if (data->shell_surface) {
data->shell_surface = NULL;
}
if (data->surface) {
data->surface = NULL;
}
g_atomic_int_add(&instance_count, -1);
return TRUE;
}
#endif
#ifdef USE_EGL_MALI_FB
#include <EGL/fbdev_window.h>
EGLNativeWindowType
platform_create_native_window (gint x, gint y, gint width, gint height, gpointer * window_data)
{
fbdev_window *w = g_slice_new0 (fbdev_window);
w->width = width;
w->height = height;
return (EGLNativeWindowType) w;
}
gboolean
platform_destroy_native_window (EGLNativeDisplayType display,
EGLNativeWindowType window, gpointer * window_data)
{
g_slice_free (fbdev_window, ((fbdev_window *) window));
return TRUE;
}
/* FIXME: Move to gst-libs/gst/egl */
#if 0
#include <mali_egl_image.h>
#include <ump/ump.h>
#include <ump/ump_ref_drv.h>
#include <gst/video/video.h>
static gpointer
eglimage_map (GstMemory * gmem, gsize maxsize, GstMapFlags flags)
{
GstEGLImageMemory *mem;
gint i;
g_return_val_if_fail (strcmp (gmem->allocator->mem_type,
GST_EGL_IMAGE_MEMORY_NAME) == 0, FALSE);
mem = GST_EGL_IMAGE_MEMORY (gmem);
g_mutex_lock (&mem->lock);
for (i = 0; i < mem->n_textures; i++) {
if (mem->memory_refcount[i]) {
/* Only multiple READ maps are allowed */
if ((mem->memory_flags[i] & GST_MAP_WRITE)) {
g_mutex_unlock (&mem->lock);
return NULL;
}
}
}
if (!mem->mapped_memory_refcount) {
EGLint attribs[] = {
MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y,
MALI_EGL_IMAGE_ACCESS_MODE, MALI_EGL_IMAGE_ACCESS_READ_ONLY,
EGL_NONE
};
GstVideoInfo info;
mali_egl_image *mali_egl_image;
guint8 *plane_memory, *p;
gint stride, h;
gint j;
gst_video_info_set_format (&info, mem->format, mem->width, mem->height);
mem->mapped_memory = g_malloc (mem->parent.size);
for (i = 0; i < mem->n_textures; i++) {
mali_egl_image = mali_egl_image_lock_ptr (mem->image[i]);
if (!mali_egl_image) {
g_free (mem->mapped_memory);
GST_ERROR ("Failed to lock Mali EGL image: 0x%04x",
mali_egl_image_get_error ());
g_mutex_unlock (&mem->lock);
return NULL;
}
plane_memory = mali_egl_image_map_buffer (mali_egl_image, attribs);
if (!plane_memory) {
mali_egl_image_unlock_ptr (mem->image[i]);
g_free (mem->mapped_memory);
GST_ERROR ("Failed to lock Mali map image: 0x%04x",
mali_egl_image_get_error ());
g_mutex_unlock (&mem->lock);
return NULL;
}
p = ((guint8 *) mem->mapped_memory) + mem->offset[i];
stride = mem->stride[i];
h = GST_VIDEO_INFO_COMP_HEIGHT (&info, i);
for (j = 0; j < h; j++) {
memcpy (p, plane_memory, stride);
p += mem->stride[i];
plane_memory += mem->stride[i];
}
mali_egl_image_unmap_buffer (mem->image[i], attribs);
mali_egl_image_unlock_ptr (mem->image[i]);
}
} else {
/* Only multiple READ maps are allowed */
if ((mem->mapped_memory_flags & GST_MAP_WRITE)) {
g_mutex_unlock (&mem->lock);
return NULL;
}
}
mem->mapped_memory_refcount++;
g_mutex_unlock (&mem->lock);
return mem->mapped_memory;
}
static void
eglimage_unmap (GstMemory * gmem)
{
GstEGLImageMemory *mem;
gint i;
g_return_if_fail (strcmp (gmem->allocator->mem_type,
GST_EGL_IMAGE_MEMORY_NAME) == 0);
mem = GST_EGL_IMAGE_MEMORY (gmem);
g_return_if_fail (mem->mapped_memory);
g_mutex_lock (&mem->lock);
mem->mapped_memory_refcount--;
if (mem->mapped_memory_refcount > 0) {
g_mutex_unlock (&mem->lock);
return;
}
/* Write back */
if ((mem->mapped_memory_flags & GST_MAP_WRITE)) {
EGLint attribs[] = {
MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y,
MALI_EGL_IMAGE_ACCESS_MODE, MALI_EGL_IMAGE_ACCESS_WRITE_ONLY,
EGL_NONE
};
GstVideoInfo info;
mali_egl_image *mali_egl_image;
guint8 *plane_memory, *p;
gint stride, h;
gint j;
gst_video_info_set_format (&info, mem->format, mem->width, mem->height);
for (i = 0; i < mem->n_textures; i++) {
mali_egl_image = mali_egl_image_lock_ptr (mem->image[i]);
if (!mali_egl_image) {
g_free (mem->mapped_memory);
GST_ERROR ("Failed to lock Mali EGL image: 0x%04x",
mali_egl_image_get_error ());
g_mutex_unlock (&mem->lock);
return;
}
plane_memory = mali_egl_image_map_buffer (mali_egl_image, attribs);
if (!plane_memory) {
mali_egl_image_unlock_ptr (mem->image[i]);
g_free (mem->mapped_memory);
GST_ERROR ("Failed to lock Mali map image: 0x%04x",
mali_egl_image_get_error ());
g_mutex_unlock (&mem->lock);
return;
}
p = ((guint8 *) mem->mapped_memory) + mem->offset[i];
stride = mem->stride[i];
h = GST_VIDEO_INFO_COMP_HEIGHT (&info, i);
for (j = 0; j < h; j++) {
memcpy (plane_memory, p, stride);
p += mem->stride[i];
plane_memory += mem->stride[i];
}
mali_egl_image_unmap_buffer (mem->image[i], attribs);
mali_egl_image_unlock_ptr (mem->image[i]);
}
}
g_free (mem->mapped_memory);
g_mutex_unlock (&mem->lock);
}
static gboolean
eglimage_video_map (GstVideoMeta * meta, guint plane,
GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
{
GstMemory *gmem;
GstEGLImageMemory *mem;
GstVideoInfo vinfo;
if (gst_buffer_n_memory (meta->buffer) != 1)
return default_map_video (meta, plane, info, data, stride, flags);
gmem = gst_buffer_peek_memory (meta->buffer, 0);
if (strcmp (gmem->allocator->mem_type, GST_EGL_IMAGE_MEMORY_NAME) != 0)
return default_map_video (meta, plane, info, data, stride, flags);
mem = GST_EGL_IMAGE_MEMORY ((gmem->parent ? gmem->parent : gmem));
g_mutex_lock (&mem->lock);
if (mem->format == GST_VIDEO_FORMAT_YV12) {
if (plane == 1)
plane = 2;
else if (plane == 2)
plane = 1;
}
if (mem->mapped_memory_refcount) {
/* Only multiple READ maps are allowed */
if ((mem->mapped_memory_flags & GST_MAP_WRITE)) {
g_mutex_unlock (&mem->lock);
return FALSE;
}
}
if (!mem->memory_refcount[plane]) {
EGLint attribs[] = {
MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y,
MALI_EGL_IMAGE_ACCESS_MODE, MALI_EGL_IMAGE_ACCESS_READ_WRITE,
EGL_NONE
};
if ((flags & GST_MAP_READ) && (flags & GST_MAP_WRITE))
attribs[3] = MALI_EGL_IMAGE_ACCESS_READ_WRITE;
else if ((flags & GST_MAP_READ))
attribs[3] = MALI_EGL_IMAGE_ACCESS_READ_ONLY;
else if ((flags & GST_MAP_WRITE))
attribs[3] = MALI_EGL_IMAGE_ACCESS_WRITE_ONLY;
mem->memory_platform_data[plane] =
mali_egl_image_lock_ptr (mem->image[plane]);
if (!mem->memory_platform_data[plane]) {
GST_ERROR ("Failed to lock Mali EGL image: 0x%04x",
mali_egl_image_get_error ());
goto map_error;
}
mem->memory[plane] =
mali_egl_image_map_buffer (mem->memory_platform_data[plane], attribs);
if (!mem->memory[plane])
goto map_error;
mem->memory_flags[plane] = flags;
} else {
/* Only multiple READ maps are allowed */
if ((mem->memory_flags[plane] & GST_MAP_WRITE)) {
g_mutex_unlock (&mem->lock);
return FALSE;
}
}
mem->memory_refcount[plane]++;
gst_video_info_set_format (&vinfo, mem->format, mem->width, mem->height);
*data = mem->memory[plane];
*stride = mem->stride[plane];
g_mutex_unlock (&mem->lock);
return TRUE;
map_error:
{
EGLint attribs[] = {
MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y,
EGL_NONE
};
GST_ERROR ("Failed to map Mali EGL image: 0x%04x",
mali_egl_image_get_error ());
if (mem->memory_platform_data[plane]) {
mali_egl_image_unmap_buffer (mem->image[plane], attribs);
mali_egl_image_unlock_ptr (mem->image[plane]);
}
mem->memory[plane] = NULL;
mem->memory_platform_data[plane] = NULL;
g_mutex_unlock (&mem->lock);
return FALSE;
}
}
static gboolean
eglimage_video_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
{
GstMemory *gmem;
GstEGLImageMemory *mem;
EGLint attribs[] = {
MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y,
EGL_NONE
};
if (gst_buffer_n_memory (meta->buffer) != 1)
return default_unmap_video (meta, plane, info);
gmem = gst_buffer_peek_memory (meta->buffer, 0);
if (strcmp (gmem->allocator->mem_type, GST_EGL_IMAGE_MEMORY_NAME) != 0)
return default_unmap_video (meta, plane, info);
mem = GST_EGL_IMAGE_MEMORY ((gmem->parent ? gmem->parent : gmem));
g_mutex_lock (&mem->lock);
if (mem->format == GST_VIDEO_FORMAT_YV12) {
if (plane == 1)
plane = 2;
else if (plane == 2)
plane = 1;
}
if (!mem->memory_refcount[plane]) {
g_mutex_unlock (&mem->lock);
g_return_val_if_reached (FALSE);
}
mem->memory_refcount[plane]--;
if (mem->memory_refcount[plane] > 0) {
g_mutex_unlock (&mem->lock);
return TRUE;
}
/* Unmaps automatically */
if (mem->memory_platform_data[plane]) {
mali_egl_image_unmap_buffer (mem->image[plane], attribs);
mali_egl_image_unlock_ptr (mem->image[plane]);
}
mem->memory[plane] = NULL;
mem->memory_platform_data[plane] = NULL;
g_mutex_unlock (&mem->lock);
return TRUE;
}
gboolean
platform_can_map_eglimage (GstMemoryMapFunction * map,
GstMemoryUnmapFunction * unmap, PlatformMapVideo * video_map,
PlatformUnmapVideo * video_unmap)
{
*map = eglimage_map;
*unmap = eglimage_unmap;
*video_map = eglimage_video_map;
*video_unmap = eglimage_video_unmap;
return TRUE;
}
gboolean
platform_has_custom_eglimage_alloc (void)
{
return TRUE;
}
gboolean
platform_alloc_eglimage (EGLDisplay display, EGLContext context, GLint format,
GLint type, gint width, gint height, GLuint tex_id, EGLImageKHR * image,
gpointer * image_platform_data)
{
fbdev_pixmap pixmap;
pixmap.flags = FBDEV_PIXMAP_SUPPORTS_UMP;
pixmap.width = width;
pixmap.height = height;
switch (format) {
case GL_LUMINANCE:
g_return_val_if_fail (type == GL_UNSIGNED_BYTE, FALSE);
pixmap.red_size = 0;
pixmap.green_size = 0;
pixmap.blue_size = 0;
pixmap.alpha_size = 0;
pixmap.luminance_size = 8;
break;
case GL_LUMINANCE_ALPHA:
g_return_val_if_fail (type == GL_UNSIGNED_BYTE, FALSE);
pixmap.red_size = 0;
pixmap.green_size = 0;
pixmap.blue_size = 0;
pixmap.alpha_size = 8;
pixmap.luminance_size = 8;
break;
case GL_RGB:
if (type == GL_UNSIGNED_BYTE) {
pixmap.red_size = 8;
pixmap.green_size = 8;
pixmap.blue_size = 8;
pixmap.alpha_size = 0;
pixmap.luminance_size = 0;
} else if (type == GL_UNSIGNED_SHORT_5_6_5) {
pixmap.red_size = 5;
pixmap.green_size = 6;
pixmap.blue_size = 5;
pixmap.alpha_size = 0;
pixmap.luminance_size = 0;
} else {
g_return_val_if_reached (FALSE);
}
break;
case GL_RGBA:
g_return_val_if_fail (type == GL_UNSIGNED_BYTE, FALSE);
pixmap.red_size = 8;
pixmap.green_size = 8;
pixmap.blue_size = 8;
pixmap.alpha_size = 8;
pixmap.luminance_size = 0;
break;
default:
g_assert_not_reached ();
return FALSE;
}
pixmap.buffer_size =
pixmap.red_size + pixmap.green_size + pixmap.blue_size +
pixmap.alpha_size + pixmap.luminance_size;
pixmap.bytes_per_pixel = pixmap.buffer_size / 8;
pixmap.format = 0;
if (ump_open () != UMP_OK) {
GST_ERROR ("Failed to open UMP");
return FALSE;
}
pixmap.data =
ump_ref_drv_allocate (GST_ROUND_UP_4 (pixmap.width) * pixmap.height *
pixmap.bytes_per_pixel, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR);
if (pixmap.data == UMP_INVALID_MEMORY_HANDLE) {
GST_ERROR ("Failed to allocate pixmap data via UMP");
ump_close ();
return FALSE;
}
*image_platform_data = g_slice_dup (fbdev_pixmap, &pixmap);
*image =
eglCreateImageKHR (display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
(EGLClientBuffer) * image_platform_data, NULL);
if (!image) {
GST_ERROR ("Failed to create EGLImage for pixmap");
ump_reference_release ((ump_handle) pixmap.data);
ump_close ();
g_slice_free (fbdev_pixmap, *image_platform_data);
return FALSE;
}
return TRUE;
}
void
platform_free_eglimage (EGLDisplay display, EGLContext context, GLuint tex_id,
EGLImageKHR * image, gpointer * image_platform_data)
{
fbdev_pixmap *pixmap = *image_platform_data;
eglDestroyImageKHR (display, *image);
ump_reference_release ((ump_handle) pixmap->data);
ump_close ();
g_slice_free (fbdev_pixmap, *image_platform_data);
}
#endif
#endif
#ifdef USE_EGL_RPI
#include <bcm_host.h>
#include <gst/video/gstvideosink.h>
typedef struct
{
EGL_DISPMANX_WINDOW_T w;
DISPMANX_DISPLAY_HANDLE_T d;
} RPIWindowData;
EGLNativeWindowType
platform_create_native_window (gint x, gint y, gint width, gint height, gpointer * window_data)
{
DISPMANX_ELEMENT_HANDLE_T dispman_element;
DISPMANX_DISPLAY_HANDLE_T dispman_display;
DISPMANX_UPDATE_HANDLE_T dispman_update;
RPIWindowData *data;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
GstVideoRectangle src, dst, res;
uint32_t dp_height;
uint32_t dp_width;
int ret;
ret = graphics_get_display_size (0, &dp_width, &dp_height);
if (ret < 0) {
GST_ERROR ("Can't open display");
return (EGLNativeWindowType) 0;
}
GST_DEBUG ("Got display size: %dx%d\n", dp_width, dp_height);
GST_DEBUG ("Source size: %dx%d\n", width, height);
/* Center width*height frame inside dp_width*dp_height */
src.w = width;
src.h = height;
src.x = src.y = 0;
dst.w = dp_width;
dst.h = dp_height;
dst.x = dst.y = 0;
gst_video_sink_center_rect (src, dst, &res, TRUE);
dst_rect.x = res.x;
dst_rect.y = res.y;
dst_rect.width = res.w;
dst_rect.height = res.h;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = width << 16;
src_rect.height = height << 16;
dispman_display = vc_dispmanx_display_open (0);
dispman_update = vc_dispmanx_update_start (0);
dispman_element = vc_dispmanx_element_add (dispman_update,
dispman_display, 0, &dst_rect, 0, &src_rect,
DISPMANX_PROTECTION_NONE, 0, 0, 0);
*window_data = data = g_slice_new0 (RPIWindowData);
data->d = dispman_display;
data->w.element = dispman_element;
data->w.width = width;
data->w.height = height;
vc_dispmanx_update_submit_sync (dispman_update);
return (EGLNativeWindowType) data;
}
gboolean
platform_destroy_native_window (EGLNativeDisplayType display,
EGLNativeWindowType window, gpointer * window_data)
{
DISPMANX_DISPLAY_HANDLE_T dispman_display;
DISPMANX_UPDATE_HANDLE_T dispman_update;
RPIWindowData *data = *window_data;
dispman_display = data->d;
dispman_update = vc_dispmanx_update_start (0);
vc_dispmanx_element_remove (dispman_update, data->w.element);
vc_dispmanx_update_submit_sync (dispman_update);
vc_dispmanx_display_close (dispman_display);
g_slice_free (RPIWindowData, data);
*window_data = NULL;
return TRUE;
}
#endif
#if !defined(USE_EGL_X11) && !defined(USE_EGL_WAYLAND) && !defined(USE_EGL_MALI_FB) && !defined(USE_EGL_RPI)
/* Dummy functions for creating a native Window */
EGLNativeWindowType
platform_create_native_window (gint x, gint y, gint width, gint height, gpointer * window_data)
{
GST_ERROR ("Can't create native window");
return (EGLNativeWindowType) 0;
}
gboolean
platform_destroy_native_window (EGLNativeDisplayType display,
EGLNativeWindowType window, gpointer * window_data)
{
GST_ERROR ("Can't destroy native window");
return TRUE;
}
#endif

View File

@@ -0,0 +1,93 @@
/*
* GStreamer Android Video Platform Wrapper
* Copyright (C) 2012 Collabora Ltd.
* @author: Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* General idea is to have all platform dependent code here for easy
* tweaking and isolation from the main routines
*/
#ifndef __GST_VIDEO_PLATFORM_WRAPPER__
#define __GST_VIDEO_PLATFORM_WRAPPER__
#include <gst/gst.h>
#include <EGL/egl.h>
#ifdef USE_EGL_X11
#include <X11/Xlib.h>
typedef struct
{
Display *display;
} X11WindowData;
EGLNativeWindowType platform_create_native_window_x11 (gint x, gint y, gint width, gint height, gpointer * window_data);
gboolean platform_destroy_native_window_x11 (EGLNativeDisplayType display,
EGLNativeWindowType w, gpointer * window_data);
#endif
#ifdef USE_EGL_WAYLAND
#include <wayland-client.h>
#include <wayland-client-core.h>
#include "wayland-client-protocol.h"
#include "wayland-egl.h"
#include "presentation-time-client-protocol.h"
#include "ivi-application-client-protocol.h"
typedef struct
{
struct wl_egl_window *egl_window;
struct wl_shell_surface *shell_surface;
struct ivi_surface *ivi_surface;
struct wl_surface *surface;
} WaylandWindowData;
typedef struct
{
struct wl_display *display;
struct wl_compositor *compositor;
struct wl_shell *shell;
struct wp_presentation *presentation;
struct wp_presentation_feedback *presentation_feedback;
struct wl_registry *registry;
struct ivi_application *ivi_application;
guint32 clock_id;
} WaylandDisplay;
EGLNativeWindowType platform_create_native_window_wayland (gint x, gint y, gint width, gint height, guint ivisurf_id, gpointer * window_data);
EGLNativeDisplayType platform_initialize_display_wayland (void);
gboolean platform_destroy_native_window_wayland (EGLNativeDisplayType display,
EGLNativeWindowType w, gpointer * window_data);
gboolean platform_destroy_display_wayland (void);
gboolean register_frame_callback_wayland(gpointer * window_data, GstBuffer * buf);
gboolean register_presentation_feedback(gpointer * window_data, GstBuffer * buf);
#endif
gboolean platform_wrapper_init (void);
#if !defined(USE_EGL_X11) && !defined(USE_EGL_WAYLAND)
EGLNativeWindowType platform_create_native_window (gint x, gint y, gint width, gint height, gpointer * window_data);
gboolean platform_destroy_native_window (EGLNativeDisplayType display,
EGLNativeWindowType w, gpointer * window_data);
#endif
#endif

View File

@@ -0,0 +1,397 @@
The software listed below is licensed under the terms of the LGPLv2
(see below). To obtain source code, contact oss-requests@nvidia.com.
libgstnvegl-1.0.so.0
------------------------------------
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your freedom to share
and change it. By contrast, the GNU General Public Licenses are intended to
guarantee your freedom to share and change free software--to make sure the
software is free for all its users.
This license, the Library General Public License, applies to some specially
designated Free Software Foundation software, and to any other libraries whose
authors decide to use it. You can use it for your libraries, too.
When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom to
distribute copies of free software (and charge for this service if you wish),
that you receive source code or can get it if you want it, that you can change
the software or use pieces of it in new free programs; and that you know you can
do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny
you these rights or to ask you to surrender the rights. These restrictions
translate to certain responsibilities for you if you distribute copies of the
library, or if you modify it.
For example, if you distribute copies of the library, whether gratis or for a
fee, you must give the recipients all the rights that we gave you. You must make
sure that they, too, receive or can get the source code. If you link a program
with the library, you must provide complete object files to the recipients so
that they can relink them with the library, after making changes to the library
and recompiling it. And you must show them these terms so they know their
rights.
Our method of protecting your rights has two steps: (1) copyright the library,
and (2) offer you this license which gives you legal permission to copy,
distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain that everyone
understands that there is no warranty for this free library. If the library is
modified by someone else and passed on, we want its recipients to know that what
they have is not the original version, so that any problems introduced by others
will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish
to avoid the danger that companies distributing free software will individually
obtain patent licenses, thus in effect transforming the program into proprietary
software. To prevent this, we have made it clear that any patent must be
licensed for everyone's free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary GNU
General Public License, which was designed for utility programs. This license,
the GNU Library General Public License, applies to certain designated libraries.
This license is quite different from the ordinary one; be sure to read it in
full, and don't assume that anything in it is the same as in the ordinary
license.
The reason we have a separate public license for some libraries is that they
blur the distinction we usually make between modifying or adding to a program
and simply using it. Linking a program with a library, without changing the
library, is in some sense simply using the library, and is analogous to running
a utility program or application program. However, in a textual and legal sense,
the linked executable is a combined work, a derivative of the original library,
and the ordinary General Public License treats it as such.
Because of this blurred distinction, using the ordinary General Public License
for libraries did not effectively promote software sharing, because most
developers did not use the libraries. We concluded that weaker conditions might
promote sharing better.
However, unrestricted linking of non-free programs would deprive the users of
those programs of all benefit from the free status of the libraries themselves.
This Library General Public License is intended to permit developers of non-free
programs to use free libraries, while preserving your freedom as a user of such
programs to change the free libraries that are incorporated in them. (We have
not seen how to achieve this as regards changes in header files, but we have
achieved it as regards changes in the actual functions of the Library.) The hope
is that this will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and modification
follow. Pay close attention to the difference between a "work based on the
library" and a "work that uses the library". The former contains code derived
from the library, while the latter only works together with the library.
Note that it is possible for a library to be covered by the ordinary General
Public License rather than by this special one.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which contains a
notice placed by the copyright holder or other authorized party saying it may be
distributed under the terms of this Library General Public License (also called
"this License"). Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data prepared so as
to be conveniently linked with application programs (which use some of those
functions and data) to form executables.
The "Library", below, refers to any such software library or work which has been
distributed under these terms. A "work based on the Library" means either the
Library or any derivative work under copyright law: that is to say, a work
containing the Library or a portion of it, either verbatim or with modifications
and/or translated straightforwardly into another language. (Hereinafter,
translation is included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making
modifications to it. For a library, complete source code means all the source
code for all modules it contains, plus any associated interface definition
files, plus the scripts used to control compilation and installation of the
library.
Activities other than copying, distribution and modification are not covered by
this License; they are outside its scope. The act of running a program using the
Library is not restricted, and output from such a program is covered only if its
contents constitute a work based on the Library (independent of the use of the
Library in a tool for writing it). Whether that is true depends on what the
Library does and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this License
and to the absence of any warranty; and distribute a copy of this License along
with the Library.
You may charge a fee for the physical act of transferring a copy, and you may at
your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it, thus
forming a work based on the Library, and copy and distribute such modifications
or work under the terms of Section 1 above, provided that you also meet all of
these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating that
you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no charge to all
third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a table of
data to be supplied by an application program that uses the facility, other than
as an argument passed when the facility is invoked, then you must make a good
faith effort to ensure that, in the event an application does not supply such
function or table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has a purpose
that is entirely well-defined independent of the application. Therefore,
Subsection 2d requires that any application-supplied function or table used by
this function must be optional: if the application does not supply it, the
square root function must still compute square roots.)
These requirements apply to the modified work as a whole. If identifiable
sections of that work are not derived from the Library, and can be reasonably
considered independent and separate works in themselves, then this License, and
its terms, do not apply to those sections when you distribute them as separate
works. But when you distribute the same sections as part of a whole which is a
work based on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the entire whole,
and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your
rights to work written entirely by you; rather, the intent is to exercise the
right to control the distribution of derivative or collective works based on the
Library.
In addition, mere aggregation of another work not based on the Library with the
Library (or with a work based on the Library) on a volume of a storage or
distribution medium does not bring the other work under the scope of this
License.
3. You may opt to apply the terms of the ordinary GNU General Public License
instead of this License to a given copy of the Library. To do this, you must
alter all the notices that refer to this License, so that they refer to the
ordinary GNU General Public License, version 2, instead of to this License. (If
a newer version than version 2 of the ordinary GNU General Public License has
appeared, then you can specify that version instead if you wish.) Do not make
any other change in these notices.
Once this change is made in a given copy, it is irreversible for that copy, so
the ordinary GNU General Public License applies to all subsequent copies and
derivative works made from that copy.
This option is useful when you wish to copy part of the code of the Library into
a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of it,
under Section 2) in object code or executable form under the terms of Sections 1
and 2 above provided that you accompany it with the complete corresponding
machine-readable source code, which must be distributed under the terms of
Sections 1 and 2 above on a medium customarily used for software interchange.
If distribution of object code is made by offering access to copy from a
designated place, then offering equivalent access to copy the source code from
the same place satisfies the requirement to distribute the source code, even
though third parties are not compelled to copy the source along with the object
code.
5. A program that contains no derivative of any portion of the Library, but is
designed to work with the Library by being compiled or linked with it, is called
a "work that uses the Library". Such a work, in isolation, is not a derivative
work of the Library, and therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library creates an
executable that is a derivative of the Library (because it contains portions of
the Library), rather than a "work that uses the library". The executable is
therefore covered by this License. Section 6 states terms for distribution of
such executables.
When a "work that uses the Library" uses material from a header file that is
part of the Library, the object code for the work may be a derivative work of
the Library even though the source code is not. Whether this is true is
especially significant if the work can be linked without the Library, or if the
work is itself a library. The threshold for this to be true is not precisely
defined by law.
If such an object file uses only numerical parameters, data structure layouts
and accessors, and small macros and small inline functions (ten lines or less in
length), then the use of the object file is unrestricted, regardless of whether
it is legally a derivative work. (Executables containing this object code plus
portions of the Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute the
object code for the work under the terms of Section 6. Any executables
containing that work also fall under Section 6, whether or not they are linked
directly with the Library itself.
6. As an exception to the Sections above, you may also compile or link a "work
that uses the Library" with the Library to produce a work containing portions of
the Library, and distribute that work under terms of your choice, provided that
the terms permit modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the Library is
used in it and that the Library and its use are covered by this License. You
must supply a copy of this License. If the work during execution displays
copyright notices, you must include the copyright notice for the Library among
them, as well as a reference directing the user to the copy of this License.
Also, you must do one of these things:
a) Accompany the work with the complete corresponding machine-readable
source code for the Library including whatever changes were used in the work
(which must be distributed under Sections 1 and 2 above); and, if the work is an
executable linked with the Library, with the complete machine-readable "work
that uses the Library", as object code and/or source code, so that the user can
modify the Library and then relink to produce a modified executable containing
the modified Library. (It is understood that the user who changes the contents
of definitions files in the Library will not necessarily be able to recompile
the application to use the modified definitions.)
b) Accompany the work with a written offer, valid for at least three years,
to give the same user the materials specified in Subsection 6a, above, for a
charge no more than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy from a
designated place, offer equivalent access to copy the above specified materials
from the same place.
d) Verify that the user has already received a copy of these materials or
that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library" must
include any data and utility programs needed for reproducing the executable from
it. However, as a special exception, the source code distributed need not
include anything that is normally distributed (in either source or binary form)
with the major components (compiler, kernel, and so on) of the operating system
on which the executable runs, unless that component itself accompanies the
executable.
It may happen that this requirement contradicts the license restrictions of
other proprietary libraries that do not normally accompany the operating system.
Such a contradiction means you cannot use both them and the Library together in
an executable that you distribute.
7. You may place library facilities that are a work based on the Library
side-by-side in a single library together with other library facilities not
covered by this License, and distribute such a combined library, provided that
the separate distribution of the work based on the Library and of the other
library facilities is otherwise permitted, and provided that you do these two
things:
a) Accompany the combined library with a copy of the same work based on the
Library, uncombined with any other library facilities. This must be distributed
under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part of
it is a work based on the Library, and explaining where to find the accompanying
uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the Library
except as expressly provided under this License. Any attempt otherwise to copy,
modify, sublicense, link with, or distribute the Library is void, and will
automatically terminate your rights under this License. However, parties who
have received copies, or rights, from you under this License will not have their
licenses terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not signed it.
However, nothing else grants you permission to modify or distribute the Library
or its derivative works. These actions are prohibited by law if you do not
accept this License. Therefore, by modifying or distributing the Library (or any
work based on the Library), you indicate your acceptance of this License to do
so, and all its terms and conditions for copying, distributing or modifying the
Library or works based on it.
10. Each time you redistribute the Library (or any work based on the Library),
the recipient automatically receives a license from the original licensor to
copy, distribute, link with or modify the Library subject to these terms and
conditions. You may not impose any further restrictions on the recipients'
exercise of the rights granted herein. You are not responsible for enforcing
compliance by third parties to this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues), conditions
are imposed on you (whether by court order, agreement or otherwise) that
contradict the conditions of this License, they do not excuse you from the
conditions of this License. If you cannot distribute so as to satisfy
simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Library at all.
For example, if a patent license would not permit royalty-free redistribution of
the Library by all those who receive copies directly or indirectly through you,
then the only way you could satisfy both it and this License would be to refrain
entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply, and
the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or
other property right claims or to contest validity of any such claims; this
section has the sole purpose of protecting the integrity of the free software
distribution system which is implemented by public license practices. Many
people have made generous contributions to the wide range of software
distributed through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing to
distribute software through any other system and a licensee cannot impose that
choice.
This section is intended to make thoroughly clear what is believed to be a
consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain
countries either by patents or by copyrighted interfaces, the original copyright
holder who places the Library under this License may add an explicit
geographical distribution limitation excluding those countries, so that
distribution is permitted only in or among countries not thus excluded. In such
case, this License incorporates the limitation as if written in the body of this
License.
13. The Free Software Foundation may publish revised and/or new versions of the
Library General Public License from time to time. Such new versions will be
similar in spirit to the present version, but may differ in detail to address
new problems or concerns.
Each version is given a distinguishing version number. If the Library specifies
a version number of this License which applies to it and "any later version",
you have the option of following the terms and conditions either of that version
or of any later version published by the Free Software Foundation. If the
Library does not specify a license version number, you may choose any version
ever published by the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free programs
whose distribution conditions are incompatible with these, write to the author
to ask for permission. For software which is copyrighted by the Free Software
Foundation, write to the Free Software Foundation; we sometimes make exceptions
for this. Our decision will be guided by the two goals of preserving the free
status of all derivatives of our free software and of promoting the sharing and
reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE
LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED
IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS
IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY
TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

View File

@@ -0,0 +1,404 @@
/*
* GStreamer EGL Library
* Copyright (C) 2012 Collabora Ltd.
* @author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation;
* version 2 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined (USE_EGL_RPI) && defined(__GNUC__)
#ifndef __VCCOREVER__
#define __VCCOREVER__ 0x04000000
#endif
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC optimize ("gnu89-inline")
#endif
#define EGL_EGLEXT_PROTOTYPES
#include <gst/egl/egl.h>
#include <string.h>
#if defined (USE_EGL_RPI) && defined(__GNUC__)
#pragma GCC reset_options
#pragma GCC diagnostic pop
#endif
struct _GstEGLDisplay
{
EGLDisplay display;
volatile gint refcount;
GDestroyNotify destroy_notify;
PFNEGLCREATEIMAGEKHRPROC eglCreateImage;
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImage;
};
typedef struct
{
GstMemory parent;
GstEGLDisplay *display;
EGLImageKHR image;
GstVideoGLTextureType type;
GstVideoGLTextureOrientation orientation;
gpointer user_data;
GDestroyNotify user_data_destroy;
} GstEGLImageMemory;
#define GST_EGL_IMAGE_MEMORY(mem) ((GstEGLImageMemory*)(mem))
gboolean
gst_egl_image_memory_is_mappable (void)
{
return FALSE;
}
gboolean
gst_is_egl_image_memory (GstMemory * mem)
{
g_return_val_if_fail (mem != NULL, FALSE);
g_return_val_if_fail (mem->allocator != NULL, FALSE);
return g_strcmp0 (mem->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0;
}
EGLImageKHR
gst_egl_image_memory_get_image (GstMemory * mem)
{
g_return_val_if_fail (gst_is_egl_image_memory (mem), EGL_NO_IMAGE_KHR);
if (mem->parent)
mem = mem->parent;
return GST_EGL_IMAGE_MEMORY (mem)->image;
}
GstEGLDisplay *
gst_egl_image_memory_get_display (GstMemory * mem)
{
g_return_val_if_fail (gst_is_egl_image_memory (mem), NULL);
if (mem->parent)
mem = mem->parent;
return gst_egl_display_ref (GST_EGL_IMAGE_MEMORY (mem)->display);
}
GstVideoGLTextureType
gst_egl_image_memory_get_type (GstMemory * mem)
{
g_return_val_if_fail (gst_is_egl_image_memory (mem), -1);
if (mem->parent)
mem = mem->parent;
return GST_EGL_IMAGE_MEMORY (mem)->type;
}
GstVideoGLTextureOrientation
gst_egl_image_memory_get_orientation (GstMemory * mem)
{
g_return_val_if_fail (gst_is_egl_image_memory (mem),
GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL);
if (mem->parent)
mem = mem->parent;
return GST_EGL_IMAGE_MEMORY (mem)->orientation;
}
void
gst_egl_image_memory_set_orientation (GstMemory * mem,
GstVideoGLTextureOrientation orientation)
{
g_return_if_fail (gst_is_egl_image_memory (mem));
if (mem->parent)
mem = mem->parent;
GST_EGL_IMAGE_MEMORY (mem)->orientation = orientation;
}
static GstMemory *
gst_egl_image_allocator_alloc_vfunc (GstAllocator * allocator, gsize size,
GstAllocationParams * params)
{
g_warning
("Use gst_egl_image_allocator_alloc() to allocate from this allocator");
return NULL;
}
static void
gst_egl_image_allocator_free_vfunc (GstAllocator * allocator, GstMemory * mem)
{
GstEGLImageMemory *emem = (GstEGLImageMemory *) mem;
EGLDisplay display;
g_return_if_fail (gst_is_egl_image_memory (mem));
/* Shared memory should not destroy all the data */
if (!mem->parent) {
display = gst_egl_display_get (emem->display);
if (emem->display->eglDestroyImage)
emem->display->eglDestroyImage (display, emem->image);
if (emem->user_data_destroy)
emem->user_data_destroy (emem->user_data);
gst_egl_display_unref (emem->display);
}
g_slice_free (GstEGLImageMemory, emem);
}
static gpointer
gst_egl_image_mem_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
{
return NULL;
}
static void
gst_egl_image_mem_unmap (GstMemory * mem)
{
}
static GstMemory *
gst_egl_image_mem_share (GstMemory * mem, gssize offset, gssize size)
{
GstMemory *sub;
GstMemory *parent;
if (offset != 0)
return NULL;
if (size != -1 && size != (gssize)mem->size)
return NULL;
/* find the real parent */
if ((parent = mem->parent) == NULL)
parent = (GstMemory *) mem;
if (size == -1)
size = mem->size - offset;
sub = (GstMemory *) g_slice_new (GstEGLImageMemory);
/* the shared memory is always readonly */
gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) |
GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->allocator, parent,
mem->maxsize, mem->align, mem->offset + offset, size);
return sub;
}
static GstMemory *
gst_egl_image_mem_copy (GstMemory * mem, gssize offset, gssize size)
{
return NULL;
}
static gboolean
gst_egl_image_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset)
{
return FALSE;
}
typedef GstAllocator GstEGLImageAllocator;
typedef GstAllocatorClass GstEGLImageAllocatorClass;
GType gst_egl_image_allocator_get_type (void);
G_DEFINE_TYPE (GstEGLImageAllocator, gst_egl_image_allocator,
GST_TYPE_ALLOCATOR);
#define GST_TYPE_EGL_IMAGE_ALLOCATOR (gst_egl_image_mem_allocator_get_type())
#define GST_IS_EGL_IMAGE_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EGL_IMAGE_ALLOCATOR))
static void
gst_egl_image_allocator_class_init (GstEGLImageAllocatorClass * klass)
{
GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
allocator_class->alloc = gst_egl_image_allocator_alloc_vfunc;
allocator_class->free = gst_egl_image_allocator_free_vfunc;
}
static void
gst_egl_image_allocator_init (GstEGLImageAllocator * allocator)
{
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
alloc->mem_type = GST_EGL_IMAGE_MEMORY_TYPE;
alloc->mem_map = gst_egl_image_mem_map;
alloc->mem_unmap = gst_egl_image_mem_unmap;
alloc->mem_share = gst_egl_image_mem_share;
alloc->mem_copy = gst_egl_image_mem_copy;
alloc->mem_is_span = gst_egl_image_mem_is_span;
GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
}
static gpointer
gst_egl_image_allocator_init_instance (gpointer data)
{
return g_object_new (gst_egl_image_allocator_get_type (), NULL);
}
GstAllocator *
gst_egl_image_allocator_obtain (void)
{
GstAllocator *allocator;
allocator = gst_egl_image_allocator_init_instance(NULL);
return GST_ALLOCATOR (g_object_ref (allocator));
}
GstMemory *
gst_egl_image_allocator_alloc (GstAllocator * allocator,
GstEGLDisplay * display, GstVideoGLTextureType type, gint width,
gint height, gsize * size)
{
return NULL;
}
GstMemory *
gst_egl_image_allocator_wrap (GstAllocator * allocator,
GstEGLDisplay * display, EGLImageKHR image, GstVideoGLTextureType type,
GstMemoryFlags flags, gsize size, gpointer user_data,
GDestroyNotify user_data_destroy)
{
GstEGLImageMemory *mem;
g_return_val_if_fail (display != NULL, NULL);
g_return_val_if_fail (image != EGL_NO_IMAGE_KHR, NULL);
if (!allocator) {
allocator = gst_egl_image_allocator_obtain ();
}
mem = g_slice_new (GstEGLImageMemory);
gst_memory_init (GST_MEMORY_CAST (mem), flags,
allocator, NULL, size, 0, 0, size);
mem->display = gst_egl_display_ref (display);
mem->image = image;
mem->type = type;
mem->orientation = GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL;
mem->user_data = user_data;
mem->user_data_destroy = user_data_destroy;
return GST_MEMORY_CAST (mem);
}
GstContext *
gst_context_new_egl_display (GstEGLDisplay * display, gboolean persistent)
{
GstContext *context;
GstStructure *s;
context = gst_context_new (GST_EGL_DISPLAY_CONTEXT_TYPE, persistent);
s = gst_context_writable_structure (context);
gst_structure_set (s, "display", GST_TYPE_EGL_DISPLAY, display, NULL);
return context;
}
gboolean
gst_context_get_egl_display (GstContext * context, GstEGLDisplay ** display)
{
const GstStructure *s;
g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE);
g_return_val_if_fail (strcmp (gst_context_get_context_type (context),
GST_EGL_DISPLAY_CONTEXT_TYPE) == 0, FALSE);
s = gst_context_get_structure (context);
return gst_structure_get (s, "display", GST_TYPE_EGL_DISPLAY, display, NULL);
}
GstEGLDisplay *
gst_egl_display_new (EGLDisplay display, GDestroyNotify destroy_notify)
{
GstEGLDisplay *gdisplay;
gdisplay = g_slice_new (GstEGLDisplay);
gdisplay->display = display;
gdisplay->refcount = 1;
gdisplay->destroy_notify = destroy_notify;
gdisplay->eglCreateImage =
(PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress ("eglCreateImageKHR");
gdisplay->eglDestroyImage =
(PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR");
return gdisplay;
}
GstEGLDisplay *
gst_egl_display_ref (GstEGLDisplay * display)
{
g_return_val_if_fail (display != NULL, NULL);
g_atomic_int_inc (&display->refcount);
return display;
}
void
gst_egl_display_unref (GstEGLDisplay * display)
{
g_return_if_fail (display != NULL);
if (g_atomic_int_dec_and_test (&display->refcount)) {
if (display->destroy_notify)
display->destroy_notify (display->display);
g_slice_free (GstEGLDisplay, display);
}
}
EGLDisplay
gst_egl_display_get (GstEGLDisplay * display)
{
g_return_val_if_fail (display != NULL, EGL_NO_DISPLAY);
return display->display;
}
EGLImageKHR
gst_egl_display_image_create (GstEGLDisplay * display,
EGLContext ctx,
EGLenum target, EGLClientBuffer buffer, const EGLint * attrib_list)
{
if (!display->eglCreateImage)
return EGL_NO_IMAGE_KHR;
return display->eglCreateImage (gst_egl_display_get (display), ctx, target,
buffer, attrib_list);
}
G_DEFINE_BOXED_TYPE (GstEGLDisplay, gst_egl_display,
(GBoxedCopyFunc) gst_egl_display_ref,
(GBoxedFreeFunc) gst_egl_display_unref);

View File

@@ -0,0 +1,76 @@
/*
* GStreamer EGL Library
* Copyright (C) 2012 Collabora Ltd.
* @author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation;
* version 2 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_EGL_H__
#define __GST_EGL_H__
#include <gst/gst.h>
#include <gst/video/video.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
G_BEGIN_DECLS
#define GST_EGL_IMAGE_MEMORY_TYPE "EGLImage"
#define GST_CAPS_FEATURE_MEMORY_EGL_IMAGE "memory:EGLImage"
typedef struct _GstEGLDisplay GstEGLDisplay;
/* EGLImage GstMemory handling */
gboolean gst_egl_image_memory_is_mappable (void);
gboolean gst_is_egl_image_memory (GstMemory * mem);
EGLImageKHR gst_egl_image_memory_get_image (GstMemory * mem);
GstEGLDisplay *gst_egl_image_memory_get_display (GstMemory * mem);
GstVideoGLTextureType gst_egl_image_memory_get_type (GstMemory * mem);
GstVideoGLTextureOrientation gst_egl_image_memory_get_orientation (GstMemory * mem);
void gst_egl_image_memory_set_orientation (GstMemory * mem,
GstVideoGLTextureOrientation orientation);
/* Generic EGLImage allocator that doesn't support mapping, copying or anything */
GstAllocator *gst_egl_image_allocator_obtain (void);
GstMemory *gst_egl_image_allocator_alloc (GstAllocator * allocator,
GstEGLDisplay * display, GstVideoGLTextureType type, gint width, gint height,
gsize * size);
GstMemory *gst_egl_image_allocator_wrap (GstAllocator * allocator,
GstEGLDisplay * display, EGLImageKHR image, GstVideoGLTextureType type,
GstMemoryFlags flags, gsize size, gpointer user_data,
GDestroyNotify user_data_destroy);
#define GST_EGL_DISPLAY_CONTEXT_TYPE "gst.egl.EGLDisplay"
GstContext * gst_context_new_egl_display (GstEGLDisplay * display, gboolean persistent);
gboolean gst_context_get_egl_display (GstContext * context,
GstEGLDisplay ** display);
/* EGLDisplay wrapper with refcount, connection is closed after last ref is gone */
#define GST_TYPE_EGL_DISPLAY (gst_egl_display_get_type())
GType gst_egl_display_get_type (void);
GstEGLDisplay *gst_egl_display_new (EGLDisplay display, GDestroyNotify destroy_notify);
GstEGLDisplay *gst_egl_display_ref (GstEGLDisplay * display);
void gst_egl_display_unref (GstEGLDisplay * display);
EGLDisplay gst_egl_display_get (GstEGLDisplay * display);
EGLImageKHR gst_egl_display_image_create (GstEGLDisplay * display,
EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
const EGLint * attrib_list);
G_END_DECLS
#endif /* __GST_EGL_H__ */

View File

@@ -0,0 +1,663 @@
/* config.h. Generated from config.h.in by configure.
* config.h.in. Generated from configure.ac by autoheader.
*
* Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Default audio sink */
#define DEFAULT_AUDIOSINK "autoaudiosink"
/* Default audio source */
#define DEFAULT_AUDIOSRC "alsasrc"
/* Default video sink */
#define DEFAULT_VIDEOSINK "autovideosink"
/* Default video source */
#define DEFAULT_VIDEOSRC "v4l2src"
/* Default visualizer */
#define DEFAULT_VISUALIZER "goom"
/* Disable Orc */
#define DISABLE_ORC 1
/* Define if an old libdts is used */
/* #undef DTS_OLD */
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#define ENABLE_NLS 1
/* The x in 2.x */
/* #undef FAAD2_MINOR_VERSION */
/* Define if AAC is using new api prefix */
/* #undef FAAD_IS_NEAAC */
/* gettext package name */
#define GETTEXT_PACKAGE "gst-plugins-bad-1.0"
/* The GIO library directory. */
#define GIO_LIBDIR "/usr/lib/aarch64-linux-gnu"
/* The GIO modules directory. */
#define GIO_MODULE_DIR "/usr/lib/aarch64-linux-gnu/gio/modules"
/* Define if GSM header in gsm/ subdir */
/* #undef GSM_HEADER_IN_SUBDIR */
/* GStreamer API Version */
#define GST_API_VERSION "1.0"
/* Extra platform specific plugin suffix */
/* #undef GST_EXTRA_MODULE_SUFFIX */
/* Defined if gcov is enabled to force a rebuild due to config.h changing */
/* #undef GST_GCOV_ENABLED */
/* Defined when registry scanning through fork is unsafe */
/* #undef GST_HAVE_UNSAFE_FORK */
/* Default errorlevel to use */
#define GST_LEVEL_DEFAULT GST_LEVEL_NONE
/* GStreamer license */
#define GST_LICENSE "LGPL"
/* mjpegtools API evolution */
#define GST_MJPEGTOOLS_API 0
/* package name in plugins */
#define GST_PACKAGE_NAME "GStreamer Nvidia Bad Plug-ins source release"
/* package origin */
#define GST_PACKAGE_ORIGIN "Unknown package origin"
/* GStreamer package release date/time for plugins as YYYY-MM-DD */
#define GST_PACKAGE_RELEASE_DATETIME "2014-02-08"
/* Define if static plugins should be built */
/* #undef GST_PLUGIN_BUILD_STATIC */
/* Define to enable Windows ACM library (used by acm). */
/* #undef HAVE_ACM */
/* Define to enable Android Media (used by androidmedia). */
/* #undef HAVE_ANDROID_MEDIA */
/* Define to enable AirPort Express Wireless sink (used by apexsink). */
/* #undef HAVE_APEXSINK */
/* Define to enable Apple video (used by applemedia). */
/* #undef HAVE_APPLE_MEDIA */
/* Define to enable ASS/SSA renderer (used by assrender). */
/* #undef HAVE_ASSRENDER */
/* Define to enable AVC Video Services (used by avcsrc). */
/* #undef HAVE_AVC */
/* Define to enable Bluez (used by bluez). */
/* #undef HAVE_BLUEZ */
/* Define to enable bz2 library (used by bz2). */
/* #undef HAVE_BZ2 */
/* Define to enable cdaudio (used by cdaudio). */
/* #undef HAVE_CDAUDIO */
/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
CoreFoundation framework. */
/* #undef HAVE_CFLOCALECOPYCURRENT */
/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
the CoreFoundation framework. */
/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
/* Define to enable chromaprint (used by chromaprint). */
/* #undef HAVE_CHROMAPRINT */
/* Define if the target CPU is an Alpha */
/* #undef HAVE_CPU_ALPHA */
/* Define if the target CPU is an ARM */
#define HAVE_CPU_ARM 1
/* Define if the target CPU is a CRIS */
/* #undef HAVE_CPU_CRIS */
/* Define if the target CPU is a CRISv32 */
/* #undef HAVE_CPU_CRISV32 */
/* Define if the target CPU is a HPPA */
/* #undef HAVE_CPU_HPPA */
/* Define if the target CPU is an x86 */
/* #undef HAVE_CPU_I386 */
/* Define if the target CPU is a IA64 */
/* #undef HAVE_CPU_IA64 */
/* Define if the target CPU is a M68K */
/* #undef HAVE_CPU_M68K */
/* Define if the target CPU is a MIPS */
/* #undef HAVE_CPU_MIPS */
/* Define if the target CPU is a PowerPC */
/* #undef HAVE_CPU_PPC */
/* Define if the target CPU is a 64 bit PowerPC */
/* #undef HAVE_CPU_PPC64 */
/* Define if the target CPU is a S390 */
/* #undef HAVE_CPU_S390 */
/* Define if the target CPU is a SPARC */
/* #undef HAVE_CPU_SPARC */
/* Define if the target CPU is a x86_64 */
/* #undef HAVE_CPU_X86_64 */
/* Define to enable Curl plugin (used by curl). */
/* #undef HAVE_CURL */
/* Define to enable daala (used by daala). */
/* #undef HAVE_DAALA */
/* Define to enable DASH plug-in (used by dash). */
#define HAVE_DASH /**/
/* Define to enable libdc1394 (used by dc1394). */
/* #undef HAVE_DC1394 */
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
#define HAVE_DCGETTEXT 1
/* Define to enable decklink (used by decklink). */
#define HAVE_DECKLINK /**/
/* Define to enable Direct3D plug-in (used by direct3dsink). */
/* #undef HAVE_DIRECT3D */
/* Define to enable DirectDraw plug-in (used by directdrawsink). */
/* #undef HAVE_DIRECTDRAW */
/* Define to enable directfb (used by dfbvideosink ). */
/* #undef HAVE_DIRECTFB */
/* Define to enable DirectShow plug-in (used by winks). */
/* #undef HAVE_DIRECTSHOW */
/* Define to enable DirectSound (used by directsoundsrc). */
/* #undef HAVE_DIRECTSOUND */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* define for working do while(0) macros */
#define HAVE_DOWHILE_MACROS 1
/* Define to enable dts library (used by dtsdec). */
/* #undef HAVE_DTS */
/* Define to enable DVB Source (used by dvb). */
#define HAVE_DVB /**/
/* Define to enable eglgles sink (used by eglgles). */
#define HAVE_EGLGLES /**/
/* Define to enable building of experimental plug-ins. */
/* #undef HAVE_EXPERIMENTAL */
/* Define to enable building of plug-ins with external deps. */
#define HAVE_EXTERNAL /**/
/* Define to enable AAC encoder plug-in (used by faac). */
/* #undef HAVE_FAAC */
/* Define to enable AAC decoder plug-in (used by faad). */
/* #undef HAVE_FAAD */
/* Define to enable linux framebuffer (used by fbdevsink). */
#define HAVE_FBDEV /**/
/* Define to 1 if you have the <fcntl.h> header file. */
/* #undef HAVE_FCNTL_H */
/* FIONREAD ioctl found in sys/filio.h */
/* #undef HAVE_FIONREAD_IN_SYS_FILIO */
/* FIONREAD ioctl found in sys/ioclt.h */
#define HAVE_FIONREAD_IN_SYS_IOCTL 1
/* Define to enable Flite plugin (used by flite). */
/* #undef HAVE_FLITE */
/* Define to enable fluidsynth (used by fluidsynth). */
/* #undef HAVE_FLUIDSYNTH */
/* Define to 1 if you have the `getpagesize' function. */
#define HAVE_GETPAGESIZE 1
/* Define if the GNU gettext() function is already present or preinstalled. */
#define HAVE_GETTEXT 1
/* Define to enable gme decoder (used by gme). */
/* #undef HAVE_GME */
/* Define to 1 if you have the `gmtime_r' function. */
#define HAVE_GMTIME_R 1
/* Define to enable GSettings plugin (used by gsettings). */
/* #undef HAVE_GSETTINGS */
/* Define to enable GSM library (used by gsmenc gsmdec). */
/* #undef HAVE_GSM */
/* Define if gudev is installed */
/* #undef HAVE_GUDEV */
/* Define to 1 if you have the <highgui.h> header file. */
/* #undef HAVE_HIGHGUI_H */
/* Define to enable http live streaming plugin (used by hls). */
/* #undef HAVE_HLS */
/* Define if you have the iconv() function and it works. */
/* #undef HAVE_ICONV */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if building for Apple iOS */
/* #undef HAVE_IOS */
/* Define to enable Kate (used by kate). */
/* #undef HAVE_KATE */
/* Define to enable ladspa (used by ladspa). */
/* #undef HAVE_LADSPA */
/* Define if gme 0.5.6 or newer is available */
/* #undef HAVE_LIBGME_ACCURACY */
/* Define to enable mms protocol library (used by libmms). */
/* #undef HAVE_LIBMMS */
/* Define to 1 if you have the `nsl' library (-lnsl). */
/* #undef HAVE_LIBNSL */
/* Define to 1 if you have the `socket' library (-lsocket). */
/* #undef HAVE_LIBSOCKET */
/* Define if libusb 1.x is installed */
/* #undef HAVE_LIBUSB */
/* Define to enable Linear Systems SDI plugin (used by linsys). */
/* #undef HAVE_LINSYS */
/* Define if we have liblrdf */
/* #undef HAVE_LRDF */
/* Define to enable lv2 (used by lv2). */
/* #undef HAVE_LV2 */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to enable Multi Format Codec (used by mfc). */
#define HAVE_MFC /**/
/* Define to enable libmimic library (used by mimic). */
/* #undef HAVE_MIMIC */
/* Define to 1 if you have a working `mmap' system call. */
#define HAVE_MMAP 1
/* Define to enable modplug (used by modplug). */
/* #undef HAVE_MODPLUG */
/* Define to enable mpeg2enc (used by mpeg2enc). */
/* #undef HAVE_MPEG2ENC */
/* Define to enable mpg123 audio decoder (used by mpg123). */
/* #undef HAVE_MPG123 */
/* Define to enable mplex (used by mplex). */
/* #undef HAVE_MPLEX */
/* Define to 1 if you have the <msacm.h> header file. */
/* #undef HAVE_MSACM_H */
/* Define to enable musepackdec (used by musepack). */
/* #undef HAVE_MUSEPACK */
/* Define to enable MythTV client plugins (used by mythtvsrc). */
/* #undef HAVE_MYTHTV */
/* Define to enable nas plug-in (used by nassink). */
/* #undef HAVE_NAS */
/* Define to enable neon http client plugins (used by neonhttpsrc). */
/* #undef HAVE_NEON */
/* Define to 1 if you have the <netinet/in.h> header file. */
/* #undef HAVE_NETINET_IN_H */
/* Define to 1 if you have the <netinet/ip.h> header file. */
/* #undef HAVE_NETINET_IP_H */
/* Define to 1 if you have the <netinet/tcp.h> header file. */
/* #undef HAVE_NETINET_TCP_H */
/* Define to enable ofa plugins (used by ofa). */
/* #undef HAVE_OFA */
/* Define to enable OpenAL plugin (used by openal). */
/* #undef HAVE_OPENAL */
/* Define to enable opencv plugins (used by opencv). */
/* #undef HAVE_OPENCV */
/* Define to 1 if you have the <opencv2/highgui/highgui_c.h> header file. */
/* #undef HAVE_OPENCV2_HIGHGUI_HIGHGUI_C_H */
/* Define to enable openjpeg library (used by openjpeg). */
/* #undef HAVE_OPENJPEG */
/* Define to enable OpenSL ES (used by opensl). */
/* #undef HAVE_OPENSLES */
/* Define to enable opus (used by opus). */
/* #undef HAVE_OPUS */
/* Use Orc */
/* #undef HAVE_ORC */
/* Apple Mac OS X operating system detected */
/* #undef HAVE_OSX */
/* Define to enable OSX video (used by osxvideosrc). */
/* #undef HAVE_OSX_VIDEO */
/* Define to 1 if you have the <pthread.h> header file. */
#define HAVE_PTHREAD_H 1
/* Define to enable pvrvideosink (used by pvr). */
/* #undef HAVE_PVR */
/* Define to enable QuickTime wrapper (used by qtwrapper). */
/* #undef HAVE_QUICKTIME */
/* Define if RDTSC is available */
/* #undef HAVE_RDTSC */
/* Define to enable resindvd plugin (used by resindvd). */
/* #undef HAVE_RESINDVD */
/* Define to enable rsvg decoder (used by rsvg). */
/* #undef HAVE_RSVG */
/* Have RSVG 2.36.2 or newer */
/* #undef HAVE_RSVG_2_36_2 */
/* Define to enable rtmp library (used by rtmp). */
/* #undef HAVE_RTMP */
/* Define to enable SBC bluetooth audio codec (used by sbc). */
/* #undef HAVE_SBC */
/* Define to enable Schroedinger video codec (used by schro). */
/* #undef HAVE_SCHRO */
/* Define to enable SDL plug-in (used by sdlvideosink sdlaudiosink). */
/* #undef HAVE_SDL */
/* Define to enable POSIX shared memory source and sink (used by shm). */
#define HAVE_SHM /**/
/* Define to enable Smooth Streaming plug-in (used by smoothstreaming). */
#define HAVE_SMOOTHSTREAMING /**/
/* Define to enable sndfile plug-in (used by sfsrc sfsink). */
/* #undef HAVE_SNDFILE */
/* Define to enable sndio audio (used by sndio). */
/* #undef HAVE_SNDIO */
/* Define to enable soundtouch plug-in (used by soundtouch). */
/* #undef HAVE_SOUNDTOUCH */
/* Defined if the available libSoundTouch is >= 1.4 */
/* #undef HAVE_SOUNDTOUCH_1_4 */
/* Define to enable Spandsp (used by spandsp). */
/* #undef HAVE_SPANDSP */
/* Define to enable spc decoder (used by spc). */
/* #undef HAVE_SPC */
/* Define to enable srtp library (used by srtp). */
/* #undef HAVE_SRTP */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/utsname.h> header file. */
#define HAVE_SYS_UTSNAME_H 1
/* Define to enable Teletext decoder (used by teletextdec). */
/* #undef HAVE_TELETEXTDEC */
/* Define if libtiger is available */
/* #undef HAVE_TIGER */
/* Define to enable timidity midi soft synth plugin (used by timidity). */
/* #undef HAVE_TIMIDITY */
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to enable UVC H264 (used by uvch264). */
/* #undef HAVE_UVCH264 */
/* Define if valgrind should be used */
/* #undef HAVE_VALGRIND */
/* Define to enable Video CD (used by vcdsrc). */
/* #undef HAVE_VCD */
/* Define to enable VDPAU (used by vdpau). */
/* #undef HAVE_VDPAU */
/* Define to enable vo-aacenc library (used by vo-aacenc). */
/* #undef HAVE_VOAACENC */
/* Define to enable vo-amrwbenc library (used by vo-amrwbenc). */
/* #undef HAVE_VOAMRWBENC */
/* Define to enable WASAPI plug-in (used by wasapi). */
/* #undef HAVE_WASAPI */
/* Define to enable wayland sink (used by wayland ). */
#define HAVE_WAYLAND /**/
/* Define to enable WebP (used by webp ). */
/* #undef HAVE_WEBP */
/* Define to enable wildmidi midi soft synth plugin (used by wildmidi). */
/* #undef HAVE_WILDMIDI */
/* Have WildMidi 0.2.2 or earlier library */
/* #undef HAVE_WILDMIDI_0_2_2 */
/* Defined if compiling for Windows */
/* #undef HAVE_WIN32 */
/* Define to 1 if you have the <windows.h> header file. */
/* #undef HAVE_WINDOWS_H */
/* Define to enable Windows internet library (used by wininet). */
/* #undef HAVE_WININET */
/* Define to 1 if you have the <wininet.h> header file. */
/* #undef HAVE_WININET_H */
/* Define to enable winscreencap plug-in (used by winscreencap). */
/* #undef HAVE_WINSCREENCAP */
/* Define to 1 if you have the <winsock2.h> header file. */
/* #undef HAVE_WINSOCK2_H */
/* Define to 1 if you have the <ws2tcpip.h> header file. */
/* #undef HAVE_WS2TCPIP_H */
/* Define if you have X11 library */
#define HAVE_X11 1
/* Define to enable xvid plugins (used by xvid). */
/* #undef HAVE_XVID */
/* Define to enable ZBar barcode detector (used by zbar). */
/* #undef HAVE_ZBAR */
/* the host CPU */
#define HOST_CPU "aarch64"
/* library dir */
#define LIBDIR "/usr/lib"
/* gettext locale dir */
#define LOCALEDIR "/usr/share/locale"
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Define if the old MusePack API is used */
/* #undef MPC_IS_OLD_API */
/* opencv install prefix */
#define OPENCV_PREFIX ""
/* Name of package */
#define PACKAGE "gst-plugins-bad"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer"
/* Define to the full name of this package. */
#define PACKAGE_NAME "GStreamer Bad Plug-ins"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "GStreamer Bad Plug-ins 1.2.3"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "gst-plugins-bad"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.2.3"
/* directory where plugins are located */
#define PLUGINDIR "/usr/lib/gstreamer-1.0"
/* The size of `char', as computed by sizeof. */
/* #undef SIZEOF_CHAR */
/* The size of `int', as computed by sizeof. */
/* #undef SIZEOF_INT */
/* The size of `long', as computed by sizeof. */
/* #undef SIZEOF_LONG */
/* The size of `short', as computed by sizeof. */
/* #undef SIZEOF_SHORT */
/* The size of `void*', as computed by sizeof. */
/* #undef SIZEOF_VOIDP */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* the target CPU */
#define TARGET_CPU "aarch64"
/* Define location of timidity.cfg */
/* #undef TIMIDITY_CFG */
/* Use Mali FB EGL window system */
/* #undef USE_EGL_MALI_FB */
/* Use RPi EGL window system */
/* #undef USE_EGL_RPI */
/* Use X11 EGL window system */
#define USE_EGL_X11 1
/* Version number of package */
#define VERSION "1.2.3"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to 1 if the X Window System is missing or not being used. */
/* #undef X_DISPLAY_MISSING */
/* We need at least WinXP SP2 for __stat64 */
/* #undef __MSVCRT_VERSION__ */

1
push_info.txt Normal file
View File

@@ -0,0 +1 @@
jetson_36.4.3