mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-05-11 21:12:54 +00:00
Compare commits
23 commits
ecc57fd216
...
209621552a
Author | SHA1 | Date | |
---|---|---|---|
209621552a | |||
d7eeb62f38 | |||
753aeccde7 | |||
7074849c5c | |||
f0ef33d018 | |||
1f8accbc8d | |||
7f47dba299 | |||
1f080391ed | |||
18c32272bd | |||
668b395a38 | |||
547e2899d1 | |||
7eb08feeee | |||
8737b9ca84 | |||
ff7b41ac86 | |||
be7ba5ac51 | |||
4ac46ce82b | |||
364d0ff45d | |||
e7598ed521 | |||
49f9a1e224 | |||
83694a1094 | |||
472d1b52d3 | |||
d2c8593b2e | |||
118e673165 |
|
@ -33,6 +33,7 @@ variables:
|
|||
value: ""
|
||||
|
||||
FEDORA_AMD64_SUFFIX: 'amd64/fedora'
|
||||
DEBIAN_AMD64_SUFFIX: 'amd64/debian'
|
||||
INDENT_AMD64_SUFFIX: 'amd64/gst-indent'
|
||||
COMMITLINT_AMD64_SUFFIX: 'amd64/commitlint'
|
||||
WINDOWS_AMD64_SUFFIX: 'amd64/windows'
|
||||
|
@ -124,6 +125,7 @@ trigger:
|
|||
|
||||
.fedora image:
|
||||
variables:
|
||||
CCACHE_DIR: '/cache/gstreamer/gstreamer/ccache/'
|
||||
FDO_BASE_IMAGE: 'registry.fedoraproject.org/fedora-toolbox:34'
|
||||
FDO_DISTRIBUTION_VERSION: '34'
|
||||
FDO_REPO_SUFFIX: "$FEDORA_AMD64_SUFFIX"
|
||||
|
@ -140,6 +142,25 @@ fedora amd64 docker:
|
|||
# (which has faster network connectivity to the registry).
|
||||
tags: [ 'placeholder-job' ]
|
||||
|
||||
.debian image:
|
||||
variables:
|
||||
CCACHE_DIR: '/cache/gstreamer/gstreamer/ccache_debian/'
|
||||
FDO_BASE_IMAGE: "quay.io/toolbx-images/debian-toolbox:12"
|
||||
FDO_DISTRIBUTION_VERSION: '12'
|
||||
FDO_REPO_SUFFIX: "$DEBIAN_AMD64_SUFFIX"
|
||||
FDO_DISTRIBUTION_TAG: "$DEBIAN_TAG-$GST_UPSTREAM_BRANCH"
|
||||
FDO_DISTRIBUTION_EXEC: 'GIT_BRANCH=$CI_COMMIT_REF_NAME GIT_URL=$CI_REPOSITORY_URL bash ci/docker/debian/prepare.sh'
|
||||
|
||||
debian amd64 docker:
|
||||
extends:
|
||||
- '.debian image'
|
||||
- '.fdo.container-build@debian'
|
||||
stage: 'preparation'
|
||||
needs: []
|
||||
# Note: assumption is that placeholder jobs run on a packet runner
|
||||
# (which has faster network connectivity to the registry).
|
||||
tags: [ 'placeholder-job' ]
|
||||
|
||||
.gst-indent image:
|
||||
tags: [ 'placeholder-job' ]
|
||||
variables:
|
||||
|
@ -264,7 +285,6 @@ commitlint:
|
|||
CCACHE_COMPILERCHECK: 'content'
|
||||
CCACHE_COMPRESS: 'true'
|
||||
CCACHE_BASEDIR: '/cache/gstreamer/gstreamer'
|
||||
CCACHE_DIR: '/cache/gstreamer/gstreamer/ccache/'
|
||||
# shared across everything really
|
||||
CCACHE_MAXSIZE: '10G'
|
||||
|
||||
|
@ -329,15 +349,10 @@ commitlint:
|
|||
- changes:
|
||||
- subprojects/gstreamer-vaapi/**/*
|
||||
|
||||
.build fedora x86_64:
|
||||
.build simple:
|
||||
extends:
|
||||
- '.fedora image'
|
||||
- '.fdo.suffixed-image@fedora'
|
||||
- '.build'
|
||||
- '.build_ccache_vars'
|
||||
needs:
|
||||
- "trigger"
|
||||
- "fedora amd64 docker"
|
||||
variables:
|
||||
GST_WERROR: "true"
|
||||
MESON_ARGS: "${SIMPLE_BUILD}"
|
||||
|
@ -350,6 +365,15 @@ commitlint:
|
|||
- meson install --destdir $CI_PROJECT_DIR/destdir -C build
|
||||
- rm -rf $CI_PROJECT_DIR/destdir
|
||||
|
||||
.build fedora x86_64:
|
||||
extends:
|
||||
- '.fedora image'
|
||||
- '.fdo.suffixed-image@fedora'
|
||||
- '.build simple'
|
||||
needs:
|
||||
- "trigger"
|
||||
- "fedora amd64 docker"
|
||||
|
||||
build fedora gcc:
|
||||
extends: '.build fedora x86_64'
|
||||
variables:
|
||||
|
@ -405,6 +429,18 @@ build fedora clang:
|
|||
-Dgstreamer-sharp:tests=disabled
|
||||
--force-fallback-for=glib
|
||||
|
||||
build debian x86_64:
|
||||
extends:
|
||||
- '.debian image'
|
||||
- '.fdo.suffixed-image@debian'
|
||||
- '.build simple'
|
||||
needs:
|
||||
- "trigger"
|
||||
- "debian amd64 docker"
|
||||
variables:
|
||||
BUILD_TYPE: "--default-library=shared"
|
||||
BUILD_GST_DEBUG: "-Dgstreamer:gst_debug=true"
|
||||
|
||||
.build windows:
|
||||
image: $WINDOWS_IMAGE
|
||||
stage: 'build'
|
||||
|
|
|
@ -5,7 +5,9 @@ variables:
|
|||
# If you are hacking on them or need a them to rebuild, its enough
|
||||
# to change any part of the string of the image you want.
|
||||
###
|
||||
FEDORA_TAG: '2024-04-10.0'
|
||||
FEDORA_TAG: '2024-04-22.4'
|
||||
|
||||
DEBIAN_TAG: '2024-04-22.4'
|
||||
|
||||
INDENT_TAG: '2023-08-24.3'
|
||||
|
||||
|
|
283
ci/docker/debian/deps.txt
Normal file
283
ci/docker/debian/deps.txt
Normal file
|
@ -0,0 +1,283 @@
|
|||
apertium-regtest
|
||||
appstream-util
|
||||
autopoint
|
||||
bash-completion
|
||||
bat
|
||||
bison
|
||||
bubblewrap
|
||||
busybox
|
||||
ccache
|
||||
clang
|
||||
clang-tools
|
||||
cmake
|
||||
coinor-libcgl-dev
|
||||
curl
|
||||
desktop-file-utils
|
||||
docutils-common
|
||||
doxygen
|
||||
dwz
|
||||
elfutils
|
||||
emscripten
|
||||
ffmpeg
|
||||
flex
|
||||
flite1-dev
|
||||
g++
|
||||
gcc
|
||||
gdb
|
||||
gettext
|
||||
git
|
||||
git-lfs
|
||||
glslc
|
||||
googletest
|
||||
graphviz
|
||||
gtk-doc-tools
|
||||
guile-cairo-dev
|
||||
iproute2
|
||||
iso-codes
|
||||
itstool
|
||||
ladspa-sdk
|
||||
liba52-0.7.4-dev
|
||||
libaa1-dev
|
||||
liballeggl4-dev
|
||||
libaom-dev
|
||||
libasound2-dev
|
||||
libass-dev
|
||||
libatk1.0-dev
|
||||
libavahi-client-dev
|
||||
libavahi-common-dev
|
||||
libavc1394-dev
|
||||
libavcodec-dev
|
||||
libavdevice-dev
|
||||
libavfilter-dev
|
||||
libavformat-dev
|
||||
libavif-dev
|
||||
libavutil-dev
|
||||
libbluetooth-dev
|
||||
libboost-system-dev
|
||||
libbs2b-dev
|
||||
libcaca-dev
|
||||
libcairo2-dev
|
||||
libcamera-dev
|
||||
libcanberra-dev
|
||||
libcap-dev
|
||||
libcdio-dev
|
||||
libcdparanoia-dev
|
||||
libchromaprint-dev
|
||||
libclang-dev
|
||||
libcoap3-dev
|
||||
libcurl4-openssl-dev
|
||||
libdbus-glib2.0-cil-dev
|
||||
libdca-dev
|
||||
libde265-dev
|
||||
libdirectfb-dev
|
||||
libdrm-dev
|
||||
libdrumstick-dev
|
||||
libdv4-dev
|
||||
libdvdnav-dev
|
||||
libdvdread-dev
|
||||
libdw-dev
|
||||
libebur128-dev
|
||||
libegl-dev
|
||||
libespeak-ng-dev
|
||||
libespeak-ng-libespeak-dev
|
||||
libevdev-dev
|
||||
libevent-dev
|
||||
libexempi-dev
|
||||
libexif-dev
|
||||
libfaad-dev
|
||||
libfftw3-bin
|
||||
libfftw3-dev
|
||||
libflac-dev
|
||||
libfluidsynth-dev
|
||||
libframe-dev
|
||||
libfreeaptx-dev
|
||||
libftgl-dev
|
||||
libgbm-dev
|
||||
libgdk-pixbuf-2.0-dev
|
||||
libgeocode-glib-dev
|
||||
libgirepository1.0-dev
|
||||
libgl-dev
|
||||
libgl1-mesa-dev
|
||||
libgles-dev
|
||||
libglib2.0-dev
|
||||
libglib2.0-doc
|
||||
libglx-dev
|
||||
libgme-dev
|
||||
libgnutls28-dev
|
||||
libgraphene-1.0-dev
|
||||
libgridsite-dev
|
||||
libgsl-dev
|
||||
libgsm1-dev
|
||||
libgssdp-1.6-dev
|
||||
libgtest-dev
|
||||
libgtk-3-dev
|
||||
libgtk-4-dev
|
||||
libgtkmm-3.0-dev
|
||||
libgudev-1.0-dev
|
||||
libgupnp-igd-1.0-dev
|
||||
libiec61883-dev
|
||||
libinput-dev
|
||||
libiptcdata0-dev
|
||||
libjack-jackd2-dev
|
||||
libjpeg62-turbo-dev
|
||||
libjson-glib-dev
|
||||
libjwt-gnutls-dev
|
||||
libkate-dev
|
||||
liblc3-dev
|
||||
liblcms2-dev
|
||||
libldacbt-abr-dev
|
||||
libldacbt-enc-dev
|
||||
liblilv-dev
|
||||
liblogg4-dev
|
||||
libltc-dev
|
||||
liblttng-ust-dev
|
||||
liblxi-dev
|
||||
libmfx-dev
|
||||
libmjpegtools-dev
|
||||
libmodplug-dev
|
||||
libmono-cil-dev
|
||||
libmp3lame-dev
|
||||
libmpcdec-dev
|
||||
libmpeg2-4-dev
|
||||
libmpeg3-dev
|
||||
libmpg123-dev
|
||||
libneon27-dev
|
||||
libngtcp2-crypto-gnutls-dev
|
||||
libnice-dev
|
||||
libnx-x11-dev
|
||||
libogg-dev
|
||||
libopenal-dev
|
||||
libopencore-amrnb-dev
|
||||
libopencore-amrwb-dev
|
||||
libopencv-dev
|
||||
libopenexr-dev
|
||||
libopengl-dev
|
||||
libopenh264-dev
|
||||
libopenjp2-7-dev
|
||||
libopenmpt-dev
|
||||
libopenni2-dev
|
||||
libopus-dev
|
||||
libpango1.0-dev
|
||||
libpng-dev
|
||||
libpolkit-gobject-1-dev
|
||||
libpulse-dev
|
||||
libpython3-all-dev
|
||||
libqrencode-dev
|
||||
libqt5waylandclient5-dev
|
||||
libqt5x11extras5-dev
|
||||
libraw1394-dev
|
||||
librsvg2-dev
|
||||
librtmp-dev
|
||||
librust-wayland-protocols-dev
|
||||
libsbc-dev
|
||||
libsdl2-dev
|
||||
libshaderc1
|
||||
libshout-dev
|
||||
libsidplay1-dev
|
||||
libsigc++-2.0-dev
|
||||
libsndfile1-dev
|
||||
libsndifsdl2-dev
|
||||
libsoundtouch-dev
|
||||
libsoup-3.0-dev
|
||||
libsoup2.4-dev
|
||||
libspandsp-dev
|
||||
libspeex-dev
|
||||
libsphinxbase-dev
|
||||
libspice-client-glib-2.0-dev
|
||||
libsrt-openssl-dev
|
||||
libsrtp2-dev
|
||||
libssh2-1-dev
|
||||
libssl-dev
|
||||
libsvtav1-dev
|
||||
libsvtav1dec-dev
|
||||
libsvtav1enc-dev
|
||||
libsysprof-4-dev
|
||||
libtag1-dev
|
||||
libtaoframework-openal-cil-dev
|
||||
libtaoframework-opengl-cil-dev
|
||||
libtheora-dev
|
||||
libtwolame-dev
|
||||
libudev-dev
|
||||
libunwind-dev
|
||||
liburcu-dev
|
||||
libusb-1.0-0-dev
|
||||
libv4l-dev
|
||||
libva-dev
|
||||
libvisual-0.4-dev
|
||||
libvo-aacenc-dev
|
||||
libvo-amrwbenc-dev
|
||||
libvorbis-dev
|
||||
libvpx-dev
|
||||
libvulkan-dev
|
||||
libwacom-dev
|
||||
libwavpack-dev
|
||||
libwayland-dev
|
||||
libwebp-dev
|
||||
libwebrtc-audio-processing-dev
|
||||
libwildmidi-dev
|
||||
libwpe-1.0-dev
|
||||
libwpebackend-fdo-1.0-dev
|
||||
libwpewebkit-1.1-dev
|
||||
libx11-dev
|
||||
libx11-xcb-dev
|
||||
libx264-dev
|
||||
libx265-dev
|
||||
libxcb-dri3-dev
|
||||
libxcb-glx0-dev
|
||||
libxcb-xfixes0-dev
|
||||
libxcb-xv0-dev
|
||||
libxcb1-dev
|
||||
libxdamage-dev
|
||||
libxext-dev
|
||||
libxfixes-dev
|
||||
libxi-dev
|
||||
libxkbcommon-dev
|
||||
libxkbcommon-x11-dev
|
||||
libxml2-dev
|
||||
libxmlsec1-dev
|
||||
libxrandr-dev
|
||||
libxslt1-dev
|
||||
libxtst-dev
|
||||
libxv-dev
|
||||
libxvidcore-dev
|
||||
libyajl-dev
|
||||
libyaml-dev
|
||||
libz-mingw-w64-dev
|
||||
libzbar-dev
|
||||
libzita-convolver-dev
|
||||
libzvbi-dev
|
||||
libzxing-dev
|
||||
libzxingcore-dev
|
||||
llvm-dev
|
||||
lua-zlib-dev
|
||||
make
|
||||
modemmanager-dev
|
||||
mono-complete
|
||||
mono-devel
|
||||
nasm
|
||||
nettle-dev
|
||||
ninja-build
|
||||
patch
|
||||
python-gi-dev
|
||||
python3-all-dev
|
||||
python3-cairo-dev
|
||||
python3-dev
|
||||
python3-pip
|
||||
qconf
|
||||
qt5-qmake
|
||||
qtbase5-dev
|
||||
qtbase5-private-dev
|
||||
qtdeclarative5-dev
|
||||
qtdeclarative5-dev-tools
|
||||
qttools5-dev-tools
|
||||
sudo
|
||||
svt-av1
|
||||
valgrind
|
||||
wayland-protocols
|
||||
x11-xserver-utils
|
||||
xdg-utils
|
||||
xfonts-jmk
|
||||
xfonts-kaname
|
||||
xvfb
|
||||
yasm
|
||||
zlib1g-dev
|
10
ci/docker/debian/install-deps.sh
Normal file
10
ci/docker/debian/install-deps.sh
Normal file
|
@ -0,0 +1,10 @@
|
|||
#! /bin/bash
|
||||
|
||||
set -eux
|
||||
|
||||
apt update -y && apt full-upgrade -y
|
||||
apt install -y $(<./ci/docker/debian/deps.txt)
|
||||
|
||||
pip3 install --break-system-packages meson hotdoc python-gitlab tomli junitparser
|
||||
|
||||
apt clean all
|
13
ci/docker/debian/prepare.sh
Normal file
13
ci/docker/debian/prepare.sh
Normal file
|
@ -0,0 +1,13 @@
|
|||
#! /bin/bash
|
||||
|
||||
set -eux
|
||||
|
||||
bash ./ci/docker/debian/install-deps.sh
|
||||
|
||||
bash ./ci/scripts/install-rust.sh
|
||||
|
||||
# Configure git for various usage
|
||||
git config --global user.email "gstreamer@gstreamer.net"
|
||||
git config --global user.name "Gstbuild Runner"
|
||||
|
||||
bash ./ci/scripts/create-subprojects-cache.sh
|
|
@ -32,7 +32,7 @@ dnf builddep -y gstreamer1 \
|
|||
python3-gstreamer1
|
||||
|
||||
dnf remove -y meson -x ninja-build
|
||||
pip3 install meson==1.2.3 hotdoc==0.16 python-gitlab tomli junitparser
|
||||
pip3 install meson hotdoc python-gitlab tomli junitparser
|
||||
|
||||
# Remove gst-devel packages installed by builddep above
|
||||
dnf remove -y "gstreamer1*devel"
|
||||
|
|
|
@ -12,8 +12,8 @@ bash ./ci/docker/fedora/install-gdk-pixbuf.sh
|
|||
|
||||
bash ./ci/docker/fedora/install-wayland-protocols.sh
|
||||
|
||||
bash ./ci/docker/fedora/install-rust.sh
|
||||
bash ./ci/scripts/install-rust.sh
|
||||
|
||||
bash ./ci/docker/fedora/virtme-fluster-setup.sh
|
||||
|
||||
bash ./ci/docker/fedora/create-subprojects-cache.sh
|
||||
bash ./ci/scripts/create-subprojects-cache.sh
|
||||
|
|
|
@ -30985,7 +30985,10 @@ of the peer sink pad, if present.</doc>
|
|||
</parameters>
|
||||
</method>
|
||||
<method name="set_offset" c:identifier="gst_pad_set_offset">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstpad.c">Set the offset that will be applied to the running time of @pad.</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstpad.c">Set the offset that will be applied to the running time of @pad. Upon next
|
||||
buffer, every sticky events (notably segment) will be pushed again with
|
||||
their running time adjusted. For that reason this is only reliable on
|
||||
source pads.</doc>
|
||||
<source-position filename="../subprojects/gstreamer/gst/gstpad.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<type name="none" c:type="void"/>
|
||||
|
|
|
@ -1314,21 +1314,6 @@ need to use this function.</doc>
|
|||
<record name="VulkanCommandPoolPrivate" c:type="GstVulkanCommandPoolPrivate" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<record name="VulkanDecoder" c:type="GstVulkanDecoder" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<record name="VulkanDecoderClass" c:type="GstVulkanDecoderClass" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<union name="VulkanDecoderParameters" c:type="GstVulkanDecoderParameters">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</union>
|
||||
<record name="VulkanDecoderPicture" c:type="GstVulkanDecoderPicture" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<record name="VulkanDecoderPrivate" c:type="GstVulkanDecoderPrivate" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<class name="VulkanDescriptorCache" c:symbol-prefix="vulkan_descriptor_cache" c:type="GstVulkanDescriptorCache" version="1.18" parent="VulkanHandlePool" glib:type-name="GstVulkanDescriptorCache" glib:get-type="gst_vulkan_descriptor_cache_get_type" glib:type-struct="VulkanDescriptorCacheClass">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkdescriptorcache.h"/>
|
||||
<constructor name="new" c:identifier="gst_vulkan_descriptor_cache_new" version="1.18">
|
||||
|
@ -5178,24 +5163,6 @@ surrounding elements of @element.</doc>
|
|||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="create_decoder" c:identifier="gst_vulkan_queue_create_decoder" version="1.24" introspectable="0">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.c">Creates a #GstVulkanDecoder object if @codec decoding is supported by @queue</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.h"/>
|
||||
<return-value transfer-ownership="full" nullable="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.c">the #GstVulkanDecoder object</doc>
|
||||
<type name="VulkanDecoder" c:type="GstVulkanDecoder*"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="queue" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.c">a #GstVulkanQueue</doc>
|
||||
<type name="VulkanQueue" c:type="GstVulkanQueue*"/>
|
||||
</instance-parameter>
|
||||
<parameter name="codec" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.c">the VkVideoCodecOperationFlagBitsKHR to decode</doc>
|
||||
<type name="guint" c:type="guint"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_device" c:identifier="gst_vulkan_queue_get_device" version="1.18">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.h"/>
|
||||
<return-value transfer-ownership="full" nullable="1">
|
||||
|
|
|
@ -19449,23 +19449,6 @@
|
|||
"GstVulkanCommandPool.pool",
|
||||
"GstVulkanCommandPool.queue",
|
||||
"GstVulkanCommandPoolClass.parent_class",
|
||||
"GstVulkanDecoder",
|
||||
"GstVulkanDecoder.codec",
|
||||
"GstVulkanDecoder.dedicated_dpb",
|
||||
"GstVulkanDecoder.input_buffer",
|
||||
"GstVulkanDecoder.layered_buffer",
|
||||
"GstVulkanDecoder.layered_dpb",
|
||||
"GstVulkanDecoder.parent",
|
||||
"GstVulkanDecoder.profile",
|
||||
"GstVulkanDecoder.queue",
|
||||
"GstVulkanDecoderClass.parent",
|
||||
"GstVulkanDecoderPicture",
|
||||
"GstVulkanDecoderPicture.dpb",
|
||||
"GstVulkanDecoderPicture.img_view_out",
|
||||
"GstVulkanDecoderPicture.img_view_ref",
|
||||
"GstVulkanDecoderPicture.out",
|
||||
"GstVulkanDecoderPicture.refs",
|
||||
"GstVulkanDecoderPicture.slice_offs",
|
||||
"GstVulkanDescriptorCache",
|
||||
"GstVulkanDescriptorCache.parent",
|
||||
"GstVulkanDescriptorCache.pool",
|
||||
|
@ -44795,22 +44778,6 @@
|
|||
"gst_vulkan_command_pool_lock",
|
||||
"gst_vulkan_command_pool_unlock",
|
||||
"gst_vulkan_create_shader",
|
||||
"gst_vulkan_decoder_append_slice",
|
||||
"gst_vulkan_decoder_caps",
|
||||
"gst_vulkan_decoder_create_dpb_pool",
|
||||
"gst_vulkan_decoder_decode",
|
||||
"gst_vulkan_decoder_flush",
|
||||
"gst_vulkan_decoder_is_started",
|
||||
"gst_vulkan_decoder_out_format",
|
||||
"gst_vulkan_decoder_picture_create_view",
|
||||
"gst_vulkan_decoder_picture_init",
|
||||
"gst_vulkan_decoder_picture_release",
|
||||
"gst_vulkan_decoder_profile_caps",
|
||||
"gst_vulkan_decoder_start",
|
||||
"gst_vulkan_decoder_stop",
|
||||
"gst_vulkan_decoder_update_video_session_parameters",
|
||||
"gst_vulkan_decoder_update_ycbcr_sampler",
|
||||
"gst_vulkan_decoder_wait",
|
||||
"gst_vulkan_descriptor_cache_acquire",
|
||||
"gst_vulkan_descriptor_cache_new",
|
||||
"gst_vulkan_descriptor_pool_create",
|
||||
|
@ -44965,7 +44932,6 @@
|
|||
"gst_vulkan_physical_device_type_to_string",
|
||||
"gst_vulkan_present_mode_to_string",
|
||||
"gst_vulkan_queue_create_command_pool",
|
||||
"gst_vulkan_queue_create_decoder",
|
||||
"gst_vulkan_queue_flags_to_string",
|
||||
"gst_vulkan_queue_get_device",
|
||||
"gst_vulkan_queue_handle_context_query",
|
||||
|
|
|
@ -7997,6 +7997,33 @@
|
|||
},
|
||||
"rank": "none"
|
||||
},
|
||||
"h264ccextractor": {
|
||||
"author": "Seungha Yang <seungha@centricular.com>",
|
||||
"description": "Extract GstVideoCaptionMeta from input H.264 stream",
|
||||
"hierarchy": [
|
||||
"GstH264CCExtractor",
|
||||
"GstH264Decoder",
|
||||
"GstVideoDecoder",
|
||||
"GstElement",
|
||||
"GstObject",
|
||||
"GInitiallyUnowned",
|
||||
"GObject"
|
||||
],
|
||||
"klass": "Codec/Video/Filter",
|
||||
"pad-templates": {
|
||||
"sink": {
|
||||
"caps": "video/x-h264:\n alignment: au\n parsed: true\n",
|
||||
"direction": "sink",
|
||||
"presence": "always"
|
||||
},
|
||||
"src": {
|
||||
"caps": "closedcaption/x-cea-608:\n format: { raw, s334-1a }\nclosedcaption/x-cea-708:\n format: { cc_data, cdp }\n",
|
||||
"direction": "src",
|
||||
"presence": "always"
|
||||
}
|
||||
},
|
||||
"rank": "none"
|
||||
},
|
||||
"line21decoder": {
|
||||
"author": "Edward Hervey <edward@centricular.com>",
|
||||
"description": "Extract line21 CC from SD video streams",
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "gstceaccoverlay.h"
|
||||
#include "gstline21enc.h"
|
||||
#include "ccutils.h"
|
||||
#include "gsth264ccextractor.h"
|
||||
|
||||
static gboolean
|
||||
closedcaption_init (GstPlugin * plugin)
|
||||
|
@ -49,6 +50,7 @@ closedcaption_init (GstPlugin * plugin)
|
|||
ret |= GST_ELEMENT_REGISTER (line21decoder, plugin);
|
||||
ret |= GST_ELEMENT_REGISTER (cc708overlay, plugin);
|
||||
ret |= GST_ELEMENT_REGISTER (line21encoder, plugin);
|
||||
ret |= GST_ELEMENT_REGISTER (h264ccextractor, plugin);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,451 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2024 Seungha Yang <seungha@centricular.com>
|
||||
*
|
||||
* 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; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
|
||||
#include "gsth264ccextractor.h"
|
||||
#include <gst/base/gstqueuearray.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_h264_cc_extractor_debug);
|
||||
#define GST_CAT_DEFAULT gst_h264_cc_extractor_debug
|
||||
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("video/x-h264, alignment=(string) au, "
|
||||
"parsed=(boolean) true"));
|
||||
|
||||
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS
|
||||
("closedcaption/x-cea-608,format={ (string) raw, (string) s334-1a}; "
|
||||
"closedcaption/x-cea-708,format={ (string) cc_data, (string) cdp }"));
|
||||
|
||||
static void gst_h264_cc_extractor_finalize (GObject * object);
|
||||
|
||||
static gboolean gst_h264_cc_extractor_set_format (GstVideoDecoder * decoder,
|
||||
GstVideoCodecState * state);
|
||||
static gboolean gst_h264_cc_extractor_negotiate (GstVideoDecoder * decoder);
|
||||
static gboolean gst_h264_cc_extractor_transform_meta (GstVideoDecoder * decoder,
|
||||
GstVideoCodecFrame * frame, GstMeta * meta);
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_handle_frame (GstVideoDecoder * decoder,
|
||||
GstVideoCodecFrame * frame);
|
||||
static GstFlowReturn gst_h264_cc_extractor_finish (GstVideoDecoder * decoder);
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_new_sequence (GstH264Decoder * decoder,
|
||||
const GstH264SPS * sps, gint max_dpb_size);
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_new_picture (GstH264Decoder * decoder,
|
||||
GstVideoCodecFrame * frame, GstH264Picture * picture);
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_new_field_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * first_field, GstH264Picture * second_field);
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_start_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb);
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_decode_slice (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice, GArray * ref_pic_list0,
|
||||
GArray * ref_pic_list1);
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_output_picture (GstH264Decoder * decoder,
|
||||
GstVideoCodecFrame * frame, GstH264Picture * picture);
|
||||
|
||||
typedef struct _CaptionData
|
||||
{
|
||||
GstVideoCaptionType caption_type;
|
||||
GstBuffer *buffer;
|
||||
} CaptionData;
|
||||
|
||||
struct _GstH264CCExtractor
|
||||
{
|
||||
GstH264Decoder parent;
|
||||
|
||||
GstVideoCaptionType caption_type;
|
||||
GstQueueArray *cur_data;
|
||||
GstQueueArray *out_data;
|
||||
gboolean on_eos;
|
||||
gint fps_n;
|
||||
gint fps_d;
|
||||
};
|
||||
|
||||
#define gst_h264_cc_extractor_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstH264CCExtractor, gst_h264_cc_extractor,
|
||||
GST_TYPE_H264_DECODER);
|
||||
|
||||
GST_ELEMENT_REGISTER_DEFINE (h264ccextractor, "h264ccextractor",
|
||||
GST_RANK_NONE, GST_TYPE_H264_CC_EXTRACTOR);
|
||||
|
||||
static void
|
||||
gst_h264_cc_extractor_class_init (GstH264CCExtractorClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
|
||||
GstH264DecoderClass *h264_class = GST_H264_DECODER_CLASS (klass);
|
||||
|
||||
object_class->finalize = gst_h264_cc_extractor_finalize;
|
||||
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"H.264 Closed Caption Extractor",
|
||||
"Codec/Video/Filter",
|
||||
"Extract GstVideoCaptionMeta from input H.264 stream",
|
||||
"Seungha Yang <seungha@centricular.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
|
||||
decoder_class->set_format =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_set_format);
|
||||
decoder_class->negotiate =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_negotiate);
|
||||
decoder_class->transform_meta =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_transform_meta);
|
||||
decoder_class->handle_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_handle_frame);
|
||||
decoder_class->finish = GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_finish);
|
||||
|
||||
h264_class->new_sequence =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_new_sequence);
|
||||
h264_class->new_picture =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_new_picture);
|
||||
h264_class->new_field_picture =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_new_field_picture);
|
||||
h264_class->start_picture =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_start_picture);
|
||||
h264_class->decode_slice =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_decode_slice);
|
||||
h264_class->output_picture =
|
||||
GST_DEBUG_FUNCPTR (gst_h264_cc_extractor_output_picture);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_h264_cc_extractor_debug, "h264ccextractor",
|
||||
0, "h264ccextractor");
|
||||
}
|
||||
|
||||
static void
|
||||
caption_data_clear_func (CaptionData * data)
|
||||
{
|
||||
data->caption_type = GST_VIDEO_CAPTION_TYPE_UNKNOWN;
|
||||
gst_clear_buffer (&data->buffer);
|
||||
}
|
||||
|
||||
static GstQueueArray *
|
||||
caption_data_queue_new (void)
|
||||
{
|
||||
GstQueueArray *array =
|
||||
gst_queue_array_new_for_struct (sizeof (CaptionData), 2);
|
||||
gst_queue_array_set_clear_func (array,
|
||||
(GDestroyNotify) caption_data_clear_func);
|
||||
return array;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h264_cc_extractor_init (GstH264CCExtractor * self)
|
||||
{
|
||||
self->cur_data = caption_data_queue_new ();
|
||||
self->out_data = gst_queue_array_new_for_struct (sizeof (CaptionData), 2);
|
||||
self->caption_type = GST_VIDEO_CAPTION_TYPE_UNKNOWN;
|
||||
self->fps_n = 0;
|
||||
self->fps_d = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h264_cc_extractor_finalize (GObject * object)
|
||||
{
|
||||
GstH264CCExtractor *self = GST_H264_CC_EXTRACTOR (object);
|
||||
|
||||
if (self->cur_data)
|
||||
gst_queue_array_free (self->cur_data);
|
||||
|
||||
gst_queue_array_free (self->out_data);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h264_cc_extractor_set_format (GstVideoDecoder * decoder,
|
||||
GstVideoCodecState * state)
|
||||
{
|
||||
GstH264CCExtractor *self = GST_H264_CC_EXTRACTOR (decoder);
|
||||
GstVideoCodecState *out_state;
|
||||
GstCaps *caps;
|
||||
gboolean ret;
|
||||
|
||||
/* Assume caption type is cea708 raw which is common cc type
|
||||
* embedded in SEI */
|
||||
if (self->caption_type == GST_VIDEO_CAPTION_TYPE_UNKNOWN)
|
||||
self->caption_type = GST_VIDEO_CAPTION_TYPE_CEA708_RAW;
|
||||
|
||||
/* Create dummy output state. Otherwise decoder baseclass will try to create
|
||||
* video caps on GAP event */
|
||||
out_state = gst_video_decoder_set_output_state (decoder,
|
||||
GST_VIDEO_FORMAT_NV12, state->info.width, state->info.height, NULL);
|
||||
caps = gst_video_caption_type_to_caps (self->caption_type);
|
||||
gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
|
||||
state->info.fps_n, state->info.fps_d, NULL);
|
||||
out_state->caps = caps;
|
||||
gst_video_codec_state_unref (out_state);
|
||||
|
||||
ret = GST_VIDEO_DECODER_CLASS (parent_class)->set_format (decoder, state);
|
||||
|
||||
gst_video_decoder_negotiate (decoder);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h264_cc_extractor_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstH264CCExtractor *self = GST_H264_CC_EXTRACTOR (decoder);
|
||||
GstCaps *caps = gst_video_caption_type_to_caps (self->caption_type);
|
||||
|
||||
gst_caps_set_simple (caps,
|
||||
"framerate", GST_TYPE_FRACTION, self->fps_n, self->fps_d, NULL);
|
||||
|
||||
gst_pad_set_caps (decoder->srcpad, caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h264_cc_extractor_transform_meta (GstVideoDecoder * decoder,
|
||||
GstVideoCodecFrame * frame, GstMeta * meta)
|
||||
{
|
||||
/* do not copy any meta */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_handle_frame (GstVideoDecoder * decoder,
|
||||
GstVideoCodecFrame * frame)
|
||||
{
|
||||
GstH264CCExtractor *self = GST_H264_CC_EXTRACTOR (decoder);
|
||||
GstVideoTimeCodeMeta *tc_meta;
|
||||
GstVideoCaptionMeta *cc_meta;
|
||||
gpointer iter = NULL;
|
||||
GstFlowReturn ret;
|
||||
|
||||
if (self->cur_data)
|
||||
gst_queue_array_clear (self->cur_data);
|
||||
|
||||
tc_meta = gst_buffer_get_video_time_code_meta (frame->input_buffer);
|
||||
|
||||
while ((cc_meta = (GstVideoCaptionMeta *)
|
||||
gst_buffer_iterate_meta_filtered (frame->input_buffer, &iter,
|
||||
GST_VIDEO_CAPTION_META_API_TYPE))) {
|
||||
CaptionData data;
|
||||
data.caption_type = cc_meta->caption_type;
|
||||
data.buffer = gst_buffer_new_memdup (cc_meta->data, cc_meta->size);
|
||||
GST_BUFFER_DTS (data.buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_PTS (data.buffer) = GST_BUFFER_PTS (frame->input_buffer);
|
||||
GST_BUFFER_DURATION (data.buffer) =
|
||||
GST_BUFFER_DURATION (frame->input_buffer);
|
||||
|
||||
if (tc_meta)
|
||||
gst_buffer_add_video_time_code_meta (data.buffer, &tc_meta->tc);
|
||||
|
||||
if (!self->cur_data)
|
||||
self->cur_data = caption_data_queue_new ();
|
||||
|
||||
gst_queue_array_push_tail_struct (self->cur_data, &data);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Queued captions %u",
|
||||
self->cur_data ? gst_queue_array_get_length (self->cur_data) : 0);
|
||||
|
||||
ret = GST_VIDEO_DECODER_CLASS (parent_class)->handle_frame (decoder, frame);
|
||||
|
||||
if (self->cur_data)
|
||||
gst_queue_array_clear (self->cur_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_finish (GstVideoDecoder * decoder)
|
||||
{
|
||||
GST_VIDEO_DECODER_CLASS (parent_class)->finish (decoder);
|
||||
|
||||
/* baseclass will post error message if there was no output buffer
|
||||
* and subclass returns OK. Return flow EOS to avoid the error message */
|
||||
return GST_FLOW_EOS;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_new_sequence (GstH264Decoder * decoder,
|
||||
const GstH264SPS * sps, gint max_dpb_size)
|
||||
{
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_new_picture (GstH264Decoder * decoder,
|
||||
GstVideoCodecFrame * frame, GstH264Picture * picture)
|
||||
{
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_new_field_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * first_field, GstH264Picture * second_field)
|
||||
{
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_start_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb)
|
||||
{
|
||||
GstH264CCExtractor *self = GST_H264_CC_EXTRACTOR (decoder);
|
||||
GstH264Picture *target_pic = picture;
|
||||
GstQueueArray *pic_data;
|
||||
|
||||
GST_LOG_OBJECT (self, "Start %s field picture", picture->second_field ?
|
||||
"second" : "first");
|
||||
|
||||
if (!self->cur_data || !gst_queue_array_get_length (self->cur_data))
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* Baseclass will output only the first field's codec frame.
|
||||
* If this second field picture's codec frame is different from
|
||||
* the first one, attach */
|
||||
if (picture->second_field && picture->other_field &&
|
||||
GST_CODEC_PICTURE_FRAME_NUMBER (picture) !=
|
||||
GST_CODEC_PICTURE_FRAME_NUMBER (picture->other_field)) {
|
||||
target_pic = picture->other_field;
|
||||
GST_DEBUG_OBJECT (self, "Found second field picture");
|
||||
}
|
||||
|
||||
pic_data = gst_h264_picture_get_user_data (target_pic);
|
||||
if (!pic_data) {
|
||||
GST_DEBUG_OBJECT (self, "Creating new picture data, caption size: %u",
|
||||
gst_queue_array_get_length (self->cur_data));
|
||||
gst_h264_picture_set_user_data (target_pic,
|
||||
g_steal_pointer (&self->cur_data),
|
||||
(GDestroyNotify) gst_queue_array_free);
|
||||
} else {
|
||||
gpointer caption_data;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Appending %u caption buffers, prev size: %u",
|
||||
gst_queue_array_get_length (self->cur_data),
|
||||
gst_queue_array_get_length (pic_data));
|
||||
|
||||
while ((caption_data = gst_queue_array_pop_head_struct (self->cur_data)))
|
||||
gst_queue_array_push_tail_struct (pic_data, caption_data);
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_decode_slice (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice, GArray * ref_pic_list0,
|
||||
GArray * ref_pic_list1)
|
||||
{
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_h264_cc_extractor_output_picture (GstH264Decoder * decoder,
|
||||
GstVideoCodecFrame * frame, GstH264Picture * picture)
|
||||
{
|
||||
GstVideoDecoder *videodec = GST_VIDEO_DECODER (decoder);
|
||||
GstH264CCExtractor *self = GST_H264_CC_EXTRACTOR (decoder);
|
||||
gint fps_n = 0;
|
||||
gint fps_d = 1;
|
||||
gboolean updated = FALSE;
|
||||
GstCodecPicture *codec_pic = GST_CODEC_PICTURE (picture);
|
||||
GstQueueArray *pic_data;
|
||||
CaptionData *caption_data = NULL;
|
||||
GstBuffer *front_buf = NULL;
|
||||
GstClockTime pts, dur;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
||||
pic_data = gst_h264_picture_get_user_data (picture);
|
||||
|
||||
/* Move caption buffer to our temporary storage */
|
||||
if (pic_data) {
|
||||
while ((caption_data = gst_queue_array_pop_head_struct (pic_data)))
|
||||
gst_queue_array_push_tail_struct (self->out_data, caption_data);
|
||||
}
|
||||
|
||||
fps_n = decoder->input_state->info.fps_n;
|
||||
fps_d = decoder->input_state->info.fps_d;
|
||||
|
||||
if (codec_pic->discont_state) {
|
||||
fps_n = codec_pic->discont_state->info.fps_n;
|
||||
fps_d = codec_pic->discont_state->info.fps_d;
|
||||
}
|
||||
|
||||
if (fps_n != self->fps_n || fps_d != self->fps_d) {
|
||||
updated = TRUE;
|
||||
self->fps_n = fps_n;
|
||||
self->fps_d = fps_d;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "picture is holding %u caption buffers",
|
||||
gst_queue_array_get_length (self->out_data));
|
||||
|
||||
if (gst_queue_array_get_length (self->out_data)) {
|
||||
caption_data = gst_queue_array_pop_head_struct (self->out_data);
|
||||
front_buf = caption_data->buffer;
|
||||
if (caption_data->caption_type != self->caption_type) {
|
||||
GST_DEBUG_OBJECT (self, "Caption type changed, need new caps");
|
||||
self->caption_type = caption_data->caption_type;
|
||||
updated = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (updated)
|
||||
gst_video_decoder_negotiate (videodec);
|
||||
|
||||
gst_h264_picture_unref (picture);
|
||||
|
||||
pts = GST_BUFFER_PTS (frame->input_buffer);
|
||||
dur = GST_BUFFER_DURATION (frame->input_buffer);
|
||||
|
||||
if (!front_buf) {
|
||||
GstEvent *gap;
|
||||
|
||||
GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame);
|
||||
ret = gst_video_decoder_finish_frame (videodec, frame);
|
||||
gap = gst_event_new_gap (pts, dur);
|
||||
gst_pad_push_event (videodec->srcpad, gap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
frame->output_buffer = front_buf;
|
||||
ret = gst_video_decoder_finish_frame (videodec, frame);
|
||||
|
||||
/* Drain other caption data */
|
||||
while ((caption_data = gst_queue_array_pop_head_struct (self->out_data))) {
|
||||
if (ret == GST_FLOW_OK)
|
||||
ret = gst_pad_push (videodec->srcpad, caption_data->buffer);
|
||||
else
|
||||
gst_buffer_unref (caption_data->buffer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2024 Seungha Yang <seungha@centricular.com>
|
||||
*
|
||||
* 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; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/codecs/gsth264decoder.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_H264_CC_EXTRACTOR (gst_h264_cc_extractor_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstH264CCExtractor, gst_h264_cc_extractor,
|
||||
GST, H264_CC_EXTRACTOR, GstH264Decoder);
|
||||
|
||||
GST_ELEMENT_REGISTER_DECLARE (h264ccextractor);
|
||||
|
||||
G_END_DECLS
|
|
@ -9,15 +9,30 @@ zvbi_sources = [
|
|||
'io-sim.c',
|
||||
]
|
||||
|
||||
closedcaption_sources = [
|
||||
'gstcccombiner.c',
|
||||
'gstccextractor.c',
|
||||
'gstccconverter.c',
|
||||
'gstcea608mux.c',
|
||||
'gstclosedcaption.c',
|
||||
'gstline21dec.c',
|
||||
'gstcea708decoder.c',
|
||||
'gstceaccoverlay.c',
|
||||
'gstline21enc.c',
|
||||
'ccutils.c',
|
||||
'gsth264ccextractor.c',
|
||||
]
|
||||
|
||||
extra_args = ['-DGST_USE_UNSTABLE_API']
|
||||
|
||||
if closedcaption_dep.found()
|
||||
gstclosedcaption = library('gstclosedcaption',
|
||||
'gstcccombiner.c', 'gstccextractor.c', 'gstccconverter.c', 'gstcea608mux.c', 'gstclosedcaption.c',
|
||||
'gstline21dec.c', 'gstcea708decoder.c', 'gstceaccoverlay.c', 'gstline21enc.c', 'ccutils.c',
|
||||
zvbi_sources,
|
||||
c_args : gst_plugins_bad_args,
|
||||
closedcaption_sources, zvbi_sources,
|
||||
c_args : gst_plugins_bad_args + extra_args,
|
||||
link_args : noseh_link_args,
|
||||
include_directories : [configinc],
|
||||
dependencies : [gstvideo_dep, gstbase_dep, gst_dep, closedcaption_dep, libm],
|
||||
dependencies : [gstvideo_dep, gstbase_dep, gst_dep, closedcaption_dep, libm,
|
||||
gstcodecs_dep],
|
||||
install : true,
|
||||
install_dir : plugins_install_dir,
|
||||
)
|
||||
|
|
|
@ -145,12 +145,8 @@ gst_rsvg_decode_image (GstRsvgDec * rsvg, GstBuffer * buffer,
|
|||
cairo_surface_t *surface;
|
||||
RsvgHandle *handle;
|
||||
GError *error = NULL;
|
||||
#if LIBRSVG_MAJOR_VERSION > (2) || (LIBRSVG_MAJOR_VERSION == (2) && LIBRSVG_MINOR_VERSION > (52))
|
||||
RsvgRectangle viewport;
|
||||
#else
|
||||
RsvgDimensionData dimension;
|
||||
gdouble scalex, scaley;
|
||||
#endif
|
||||
GstRsvgDimension dimension;
|
||||
GstMapInfo minfo;
|
||||
GstVideoFrame vframe;
|
||||
GstVideoCodecState *output_state;
|
||||
|
@ -167,12 +163,10 @@ gst_rsvg_decode_image (GstRsvgDec * rsvg, GstBuffer * buffer,
|
|||
g_error_free (error);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
#if LIBRSVG_MAJOR_VERSION > (2) || (LIBRSVG_MAJOR_VERSION == (2) && LIBRSVG_MINOR_VERSION > (52))
|
||||
rsvg_handle_get_intrinsic_size_in_pixels (handle, &dimension.width,
|
||||
&dimension.height);
|
||||
#else
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
rsvg_handle_get_dimensions (handle, &dimension);
|
||||
#endif
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
output_state = gst_video_decoder_get_output_state (decoder);
|
||||
if ((output_state == NULL)
|
||||
|
@ -188,9 +182,8 @@ gst_rsvg_decode_image (GstRsvgDec * rsvg, GstBuffer * buffer,
|
|||
gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (rsvg), templ_caps);
|
||||
|
||||
GST_DEBUG_OBJECT (rsvg,
|
||||
"Trying to negotiate for SVG resolution %" G_GUINT64_FORMAT "x %"
|
||||
G_GUINT64_FORMAT " with downstream caps %" GST_PTR_FORMAT,
|
||||
(guint64) dimension.width, (guint64) dimension.height, peer_caps);
|
||||
"Trying to negotiate for SVG resolution %ux%u with downstream caps %"
|
||||
GST_PTR_FORMAT, dimension.width, dimension.height, peer_caps);
|
||||
|
||||
source_caps = gst_caps_make_writable (g_steal_pointer (&templ_caps));
|
||||
gst_caps_set_simple (source_caps, "width", G_TYPE_INT, dimension.width,
|
||||
|
@ -272,21 +265,6 @@ gst_rsvg_decode_image (GstRsvgDec * rsvg, GstBuffer * buffer,
|
|||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
#if LIBRSVG_MAJOR_VERSION > (2) || (LIBRSVG_MAJOR_VERSION == (2) && LIBRSVG_MINOR_VERSION > (52))
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.width = GST_VIDEO_INFO_WIDTH (&output_state->info);
|
||||
viewport.height = GST_VIDEO_INFO_HEIGHT (&output_state->info);
|
||||
if (!rsvg_handle_render_document (handle, cr, &viewport, &error)) {
|
||||
GST_ERROR_OBJECT (rsvg, "Failed to render SVG image: %s", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (handle);
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_destroy (surface);
|
||||
gst_video_codec_state_unref (output_state);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
#else
|
||||
scalex = scaley = 1.0;
|
||||
if (GST_VIDEO_INFO_WIDTH (&output_state->info) != dimension.width) {
|
||||
scalex =
|
||||
|
@ -300,8 +278,9 @@ gst_rsvg_decode_image (GstRsvgDec * rsvg, GstBuffer * buffer,
|
|||
}
|
||||
|
||||
cairo_scale (cr, scalex, scaley);
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
rsvg_handle_render_cairo (handle, cr);
|
||||
#endif
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
g_object_unref (handle);
|
||||
cairo_destroy (cr);
|
||||
|
|
|
@ -44,15 +44,6 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstRsvgDec GstRsvgDec;
|
||||
typedef struct _GstRsvgDecClass GstRsvgDecClass;
|
||||
|
||||
#if LIBRSVG_MAJOR_VERSION > (2) || (LIBRSVG_MAJOR_VERSION == (2) && LIBRSVG_MINOR_VERSION > (52))
|
||||
typedef struct
|
||||
{
|
||||
gdouble width, height;
|
||||
} GstRsvgDimension;
|
||||
#else
|
||||
typedef RsvgDimensionData GstRsvgDimension;
|
||||
#endif
|
||||
|
||||
struct _GstRsvgDec
|
||||
{
|
||||
GstVideoDecoder decoder;
|
||||
|
@ -66,7 +57,7 @@ struct _GstRsvgDec
|
|||
guint64 frame_count;
|
||||
|
||||
GstVideoCodecState *input_state;
|
||||
GstRsvgDimension dimension;
|
||||
RsvgDimensionData dimension;
|
||||
|
||||
GstSegment segment;
|
||||
gboolean need_newsegment;
|
||||
|
|
|
@ -163,7 +163,9 @@ gst_rsvg_overlay_set_svg_data (GstRsvgOverlay * overlay, const gchar * data,
|
|||
} else {
|
||||
/* Get SVG dimension. */
|
||||
RsvgDimensionData svg_dimension;
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
rsvg_handle_get_dimensions (overlay->handle, &svg_dimension);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
overlay->svg_width = svg_dimension.width;
|
||||
overlay->svg_height = svg_dimension.height;
|
||||
gst_base_transform_set_passthrough (btrans, FALSE);
|
||||
|
@ -421,7 +423,9 @@ gst_rsvg_overlay_transform_frame_ip (GstVideoFilter * vfilter,
|
|||
cairo_scale (cr, (double) applied_width / overlay->svg_width,
|
||||
(double) applied_height / overlay->svg_height);
|
||||
}
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
rsvg_handle_render_cairo (overlay->handle, cr);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
GST_RSVG_UNLOCK (overlay);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <gst/video/video.h>
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
|
||||
#include "gst/vulkan/gstvkdecoder-private.h"
|
||||
#include "gstvulkanelements.h"
|
||||
|
||||
typedef struct _GstVulkanH264Decoder GstVulkanH264Decoder;
|
||||
|
@ -161,7 +162,7 @@ gst_vulkan_h264_decoder_open (GstVideoDecoder * decoder)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
self->decoder = gst_vulkan_queue_create_decoder (self->decode_queue,
|
||||
self->decoder = gst_vulkan_decoder_new_from_queue (self->decode_queue,
|
||||
VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
|
||||
if (!self->decoder) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
#include "gst/vulkan/gstvkdecoder-private.h"
|
||||
|
||||
#include "gstvulkanelements.h"
|
||||
|
||||
|
@ -219,7 +220,7 @@ gst_vulkan_h265_decoder_open (GstVideoDecoder * decoder)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
self->decoder = gst_vulkan_queue_create_decoder (self->decode_queue,
|
||||
self->decoder = gst_vulkan_decoder_new_from_queue (self->decode_queue,
|
||||
VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
|
||||
if (!self->decoder) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
|
||||
|
|
|
@ -1327,7 +1327,7 @@ static inline gboolean
|
|||
_is_old_mesa (GstVaAllocator * va_allocator)
|
||||
{
|
||||
return GST_VA_DISPLAY_IS_IMPLEMENTATION (va_allocator->display, MESA_GALLIUM)
|
||||
&& !gst_va_display_check_version (va_allocator->display, 23, 2);
|
||||
&& !gst_va_display_check_version (va_allocator->display, 23, 3);
|
||||
}
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
|
@ -1376,13 +1376,15 @@ _update_image_info (GstVaAllocator * va_allocator,
|
|||
}
|
||||
va_allocator->use_derived = FALSE;
|
||||
#else
|
||||
/* XXX: Derived in Mesa <23.3 can't use derived images for P010 format
|
||||
/* XXX: Derived in radeonsi Mesa <23.3 can't use derived images for several
|
||||
* cases
|
||||
* https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24381
|
||||
* https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26174
|
||||
*/
|
||||
if (va_allocator->img_format == GST_VIDEO_FORMAT_P010_10LE
|
||||
&& _is_old_mesa (va_allocator)) {
|
||||
if (_is_old_mesa (va_allocator)) {
|
||||
if (feat_use_derived != GST_VA_FEATURE_DISABLED) {
|
||||
GST_INFO_OBJECT (va_allocator, "Disable image derive on old Mesa.");
|
||||
GST_INFO_OBJECT (va_allocator,
|
||||
"Disable image derive on old Mesa (< 23.3).");
|
||||
feat_use_derived = GST_VA_FEATURE_DISABLED;
|
||||
}
|
||||
va_allocator->use_derived = FALSE;
|
||||
|
|
|
@ -23,9 +23,6 @@
|
|||
#endif
|
||||
|
||||
#include "gstvavideoformat.h"
|
||||
#ifndef G_OS_WIN32
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#define GST_CAT_DEFAULT gst_va_display_debug
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_va_display_debug);
|
||||
|
@ -38,73 +35,62 @@ static struct FormatMap
|
|||
GstVideoFormat format;
|
||||
guint va_rtformat;
|
||||
VAImageFormat va_format;
|
||||
/* The drm fourcc may have different definition from VA */
|
||||
guint drm_fourcc;
|
||||
} format_map[] = {
|
||||
#ifndef G_OS_WIN32
|
||||
#define F(format, drm, fourcc, rtformat, order, bpp, depth, r, g, b, a) { \
|
||||
#define F(format, fourcc, rtformat, order, bpp, depth, r, g, b, a) { \
|
||||
G_PASTE (GST_VIDEO_FORMAT_, format), \
|
||||
G_PASTE (VA_RT_FORMAT_, rtformat), \
|
||||
{ VA_FOURCC fourcc, G_PASTE (G_PASTE (VA_, order), _FIRST), \
|
||||
bpp, depth, r, g, b, a }, G_PASTE (DRM_FORMAT_, drm) }
|
||||
#else
|
||||
#define F(format, drm, fourcc, rtformat, order, bpp, depth, r, g, b, a) { \
|
||||
G_PASTE (GST_VIDEO_FORMAT_, format), \
|
||||
G_PASTE (VA_RT_FORMAT_, rtformat), \
|
||||
{ VA_FOURCC fourcc, G_PASTE (G_PASTE (VA_, order), _FIRST), \
|
||||
bpp, depth, r, g, b, a }, 0 /* DRM_FORMAT_INVALID */ }
|
||||
#endif
|
||||
#define G(format, drm, fourcc, rtformat, order, bpp) \
|
||||
F (format, drm, fourcc, rtformat, order, bpp, 0, 0, 0 ,0, 0)
|
||||
G (NV12, NV12, ('N', 'V', '1', '2'), YUV420, NSB, 12),
|
||||
G (NV21, NV21, ('N', 'V', '2', '1'), YUV420, NSB, 21),
|
||||
G (VUYA, AYUV, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
|
||||
F (RGBA, RGBA8888, ('R', 'G', 'B', 'A'), RGB32, LSB, 32, 32, 0x000000ff,
|
||||
bpp, depth, r, g, b, a } }
|
||||
#define G(format, fourcc, rtformat, order, bpp) \
|
||||
F (format, fourcc, rtformat, order, bpp, 0, 0, 0 ,0, 0)
|
||||
G (NV12, ('N', 'V', '1', '2'), YUV420, NSB, 12),
|
||||
G (NV21, ('N', 'V', '2', '1'), YUV420, NSB, 21),
|
||||
G (VUYA, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
|
||||
F (RGBA, ('R', 'G', 'B', 'A'), RGB32, LSB, 32, 32, 0x000000ff,
|
||||
0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
F (RGBx, RGBX8888, ('R', 'G', 'B', 'X'), RGB32, LSB, 32, 24, 0x000000ff,
|
||||
F (RGBx, ('R', 'G', 'B', 'X'), RGB32, LSB, 32, 24, 0x000000ff,
|
||||
0x0000ff00, 0x00ff0000, 0x00000000),
|
||||
F (BGRA, BGRA8888, ('B', 'G', 'R', 'A'), RGB32, LSB, 32, 32, 0x00ff0000,
|
||||
F (BGRA, ('B', 'G', 'R', 'A'), RGB32, LSB, 32, 32, 0x00ff0000,
|
||||
0x0000ff00, 0x000000ff, 0xff000000),
|
||||
F (ARGB, ARGB8888, ('A', 'R', 'G', 'B'), RGB32, LSB, 32, 32, 0x0000ff00,
|
||||
F (ARGB, ('A', 'R', 'G', 'B'), RGB32, LSB, 32, 32, 0x0000ff00,
|
||||
0x00ff0000, 0xff000000, 0x000000ff),
|
||||
F (xRGB, XRGB8888, ('X', 'R', 'G', 'B'), RGB32, LSB, 32, 24, 0x0000ff00,
|
||||
F (xRGB, ('X', 'R', 'G', 'B'), RGB32, LSB, 32, 24, 0x0000ff00,
|
||||
0x00ff0000, 0xff000000, 0x00000000),
|
||||
F (ABGR, ABGR8888, ('A', 'B', 'G', 'R'), RGB32, LSB, 32, 32, 0xff000000,
|
||||
F (ABGR, ('A', 'B', 'G', 'R'), RGB32, LSB, 32, 32, 0xff000000,
|
||||
0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
F (xBGR, XBGR8888, ('X', 'B', 'G', 'R'), RGB32, LSB, 32, 24, 0xff000000,
|
||||
F (xBGR, ('X', 'B', 'G', 'R'), RGB32, LSB, 32, 24, 0xff000000,
|
||||
0x00ff0000, 0x0000ff00, 0x00000000),
|
||||
F (BGRx, BGRX8888, ('B', 'G', 'R', 'X'), RGB32, LSB, 32, 24, 0x00ff0000,
|
||||
F (BGRx, ('B', 'G', 'R', 'X'), RGB32, LSB, 32, 24, 0x00ff0000,
|
||||
0x0000ff00, 0x000000ff, 0x00000000),
|
||||
G (UYVY, UYVY, ('U', 'Y', 'V', 'Y'), YUV422, NSB, 16),
|
||||
G (YUY2, YUYV, ('Y', 'U', 'Y', '2'), YUV422, NSB, 16),
|
||||
G (AYUV, AYUV, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
|
||||
G (UYVY, ('U', 'Y', 'V', 'Y'), YUV422, NSB, 16),
|
||||
G (YUY2, ('Y', 'U', 'Y', '2'), YUV422, NSB, 16),
|
||||
G (AYUV, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
|
||||
/* F (????, NV11), */
|
||||
G (YV12, YVU420, ('Y', 'V', '1', '2'), YUV420, NSB, 12),
|
||||
G (YV12, ('Y', 'V', '1', '2'), YUV420, NSB, 12),
|
||||
/* F (????, P208), */
|
||||
G (I420, YUV420, ('I', '4', '2', '0'), YUV420, NSB, 12),
|
||||
G (I420, ('I', '4', '2', '0'), YUV420, NSB, 12),
|
||||
/* F (????, YV24), */
|
||||
/* F (????, YV32), */
|
||||
/* F (????, Y800), */
|
||||
/* F (????, IMC3), */
|
||||
/* F (????, 411P), */
|
||||
/* F (????, 411R), */
|
||||
G (Y42B, YUV422, ('4', '2', '2', 'H'), YUV422, LSB, 16),
|
||||
G (Y42B, ('4', '2', '2', 'H'), YUV422, LSB, 16),
|
||||
/* F (????, 422V), */
|
||||
/* F (????, 444P), */
|
||||
/* No RGBP support in drm fourcc */
|
||||
G (RGBP, INVALID, ('R', 'G', 'B', 'P'), RGBP, LSB, 8),
|
||||
G (RGBP, ('R', 'G', 'B', 'P'), RGBP, LSB, 8),
|
||||
/* F (????, BGRP), */
|
||||
/* F (????, RGB565), */
|
||||
/* F (????, BGR565), */
|
||||
G (Y210, Y210, ('Y', '2', '1', '0'), YUV422_10, NSB, 32),
|
||||
G (Y210, ('Y', '2', '1', '0'), YUV422_10, NSB, 32),
|
||||
/* F (????, Y216), */
|
||||
G (Y410, Y410, ('Y', '4', '1', '0'), YUV444_10, NSB, 32),
|
||||
G (Y212_LE, Y212, ('Y', '2', '1', '2'), YUV422_12, NSB, 32),
|
||||
G (Y412_LE, Y412, ('Y', '4', '1', '2'), YUV444_12, NSB, 32),
|
||||
G (Y410, ('Y', '4', '1', '0'), YUV444_10, NSB, 32),
|
||||
G (Y212_LE, ('Y', '2', '1', '2'), YUV422_12, NSB, 32),
|
||||
G (Y412_LE, ('Y', '4', '1', '2'), YUV444_12, NSB, 32),
|
||||
/* F (????, Y416), */
|
||||
/* F (????, YV16), */
|
||||
G (P010_10LE, P010, ('P', '0', '1', '0'), YUV420_10, NSB, 24),
|
||||
G (P012_LE, P012, ('P', '0', '1', '2'), YUV420_12, NSB, 24),
|
||||
G (P010_10LE, ('P', '0', '1', '0'), YUV420_10, NSB, 24),
|
||||
G (P012_LE, ('P', '0', '1', '2'), YUV420_12, NSB, 24),
|
||||
/* F (P016_LE, P016, ????), */
|
||||
/* F (????, I010), */
|
||||
/* F (????, IYUV), */
|
||||
|
@ -112,20 +98,19 @@ static struct FormatMap
|
|||
/* F (????, A2B10G10R10), */
|
||||
/* F (????, X2R10G10B10), */
|
||||
/* F (????, X2B10G10R10), */
|
||||
/* No GRAY8 support in drm fourcc */
|
||||
G (GRAY8, INVALID, ('Y', '8', '0', '0'), YUV400, NSB, 8),
|
||||
G (Y444, YUV444, ('4', '4', '4', 'P'), YUV444, NSB, 24),
|
||||
G (GRAY8, ('Y', '8', '0', '0'), YUV400, NSB, 8),
|
||||
G (Y444, ('4', '4', '4', 'P'), YUV444, NSB, 24),
|
||||
/* F (????, Y16), */
|
||||
/* G (VYUY, VYUY, YUV422), */
|
||||
/* G (YVYU, YVYU, YUV422), */
|
||||
/* F (ARGB64, ARGB64, ????), */
|
||||
/* F (????, ABGR64), */
|
||||
F (RGB16, RGB565, ('R', 'G', '1', '6'), RGB16, NSB, 16, 16, 0x0000f800,
|
||||
F (RGB16, ('R', 'G', '1', '6'), RGB16, NSB, 16, 16, 0x0000f800,
|
||||
0x000007e0, 0x0000001f, 0x00000000),
|
||||
F (RGB, RGB888, ('R', 'G', '2', '4'), RGB32, NSB, 32, 24, 0x00ff0000,
|
||||
F (RGB, ('R', 'G', '2', '4'), RGB32, NSB, 32, 24, 0x00ff0000,
|
||||
0x0000ff00, 0x000000ff, 0x00000000),
|
||||
F (BGR10A2_LE, ARGB2101010, ('A', 'R', '3', '0'), RGB32, LSB, 32, 30,
|
||||
0x3ff00000, 0x000ffc00, 0x000003ff, 0x30000000),
|
||||
F (BGR10A2_LE, ('A', 'R', '3', '0'), RGB32, LSB, 32, 30, 0x3ff00000,
|
||||
0x000ffc00, 0x000003ff, 0x30000000),
|
||||
#undef F
|
||||
#undef G
|
||||
};
|
||||
|
@ -133,54 +118,47 @@ static struct FormatMap
|
|||
static const struct RBG32FormatMap
|
||||
{
|
||||
GstVideoFormat format;
|
||||
guint drm_fourcc;
|
||||
VAImageFormat va_format[2];
|
||||
} rgb32_format_map[] = {
|
||||
#define F(fourcc, order, bpp, depth, r, g, b, a) \
|
||||
{ VA_FOURCC fourcc, G_PASTE (G_PASTE (VA_, order), _FIRST), bpp, depth, r, g, b, a }
|
||||
#define A(fourcc, order, r, g, b, a) F (fourcc, order, 32, 32, r, g, b, a)
|
||||
#define X(fourcc, order, r, g, b) F (fourcc, order, 32, 24, r, g, b, 0x0)
|
||||
#ifndef G_OS_WIN32
|
||||
#define D(format, drm_fourcc) G_PASTE (GST_VIDEO_FORMAT_, format), G_PASTE (DRM_FORMAT_, drm_fourcc)
|
||||
#else
|
||||
#define D(format, drm_fourcc) G_PASTE (GST_VIDEO_FORMAT_, format), 0 /* DRM_FORMAT_INVALID */
|
||||
#endif
|
||||
{ D (ARGB, BGRA8888), {
|
||||
{ GST_VIDEO_FORMAT_ARGB, {
|
||||
A (('B', 'G', 'R', 'A'), LSB, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff),
|
||||
A (('A', 'R', 'G', 'B'), MSB, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
|
||||
} },
|
||||
{ D (RGBA, ABGR8888), {
|
||||
{ GST_VIDEO_FORMAT_RGBA, {
|
||||
A (('A', 'B', 'G', 'R'), LSB, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
A (('R', 'G', 'B', 'A'), MSB, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
} },
|
||||
{ D (ABGR, RGBA8888), {
|
||||
{ GST_VIDEO_FORMAT_ABGR, {
|
||||
A (('R', 'G', 'B', 'A'), LSB, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
A (('A', 'B', 'G', 'R'), MSB, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
} },
|
||||
{ D (BGRA, ARGB8888), {
|
||||
{ GST_VIDEO_FORMAT_BGRA, {
|
||||
A (('A', 'R', 'G', 'B'), LSB, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
|
||||
A (('B', 'G', 'R', 'A'), MSB, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff),
|
||||
} },
|
||||
{ D (xRGB, BGRX8888), {
|
||||
{ GST_VIDEO_FORMAT_xRGB, {
|
||||
X (('B', 'G', 'R', 'X'), LSB, 0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
X (('X', 'R', 'G', 'B'), MSB, 0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
} },
|
||||
{ D (RGBx, XBGR8888), {
|
||||
{ GST_VIDEO_FORMAT_RGBx, {
|
||||
X (('X', 'B', 'G', 'R'), LSB, 0x000000ff, 0x0000ff00, 0x00ff0000),
|
||||
X (('R', 'G', 'B', 'X'), MSB, 0xff000000, 0x00ff0000, 0x0000ff00),
|
||||
} },
|
||||
{ D (xBGR, RGBX8888), {
|
||||
{ GST_VIDEO_FORMAT_xBGR, {
|
||||
X (('R', 'G', 'B', 'X'), LSB, 0xff000000, 0x00ff0000, 0x0000ff00),
|
||||
X (('X', 'B', 'G', 'R'), MSB, 0x000000ff, 0x0000ff00, 0x00ff0000),
|
||||
} },
|
||||
{ D (BGRx, XRGB8888), {
|
||||
{ GST_VIDEO_FORMAT_BGRx, {
|
||||
X (('X', 'R', 'G', 'B'), LSB, 0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
X (('B', 'G', 'R', 'X'), MSB, 0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
} },
|
||||
#undef X
|
||||
#undef A
|
||||
#undef F
|
||||
#undef D
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
@ -201,9 +179,11 @@ static const struct FormatMap *
|
|||
get_format_map_from_drm_fourcc (guint drm_fourcc)
|
||||
{
|
||||
int i;
|
||||
GstVideoFormat format;
|
||||
|
||||
format = gst_video_dma_drm_fourcc_to_format (drm_fourcc);
|
||||
for (i = 0; i < G_N_ELEMENTS (format_map); i++) {
|
||||
if (format_map[i].drm_fourcc == drm_fourcc)
|
||||
if (format_map[i].format == format)
|
||||
return &format_map[i];
|
||||
}
|
||||
|
||||
|
@ -263,6 +243,20 @@ get_format_map_from_va_image_format (const VAImageFormat * va_format)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX: there are two potentially different fourcc: the VA and the DRM.
|
||||
*
|
||||
* Normally they should be the same, but there are a couple formats where VA's
|
||||
* fourcc is different from the DRM's fourcc. One example is
|
||||
* GST_VIDEO_FORMAT_I420, where VA's fourcc is ('I', '4', '2', '0') while DRM's
|
||||
* is ('Y', 'U', '1', '2').
|
||||
*
|
||||
* That's the reason there are two functions:
|
||||
* gst_va_video_format_from_va_fourcc() and
|
||||
* gst_va_video_format_from_drm_fourcc() They should be used depending where the
|
||||
* value is going to be used: for VA concerns the first should be used, for
|
||||
* DMABuf exportation, the last.
|
||||
*/
|
||||
GstVideoFormat
|
||||
gst_va_video_format_from_va_fourcc (guint fourcc)
|
||||
{
|
||||
|
@ -292,7 +286,7 @@ gst_va_drm_fourcc_from_video_format (GstVideoFormat format)
|
|||
{
|
||||
const struct FormatMap *map = get_format_map_from_video_format (format);
|
||||
|
||||
return map ? map->drm_fourcc : 0;
|
||||
return map ? gst_video_dma_drm_fourcc_from_format (format) : 0;
|
||||
}
|
||||
|
||||
guint
|
||||
|
@ -406,15 +400,13 @@ gst_va_dma_drm_info_to_video_info (const GstVideoInfoDmaDrm * drm_info,
|
|||
}
|
||||
|
||||
static GstVideoFormat
|
||||
find_gst_video_format_in_rgb32_map (VAImageFormat * image_format,
|
||||
guint * drm_fourcc)
|
||||
find_gst_video_format_in_rgb32_map (VAImageFormat * image_format)
|
||||
{
|
||||
guint i, j;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (rgb32_format_map); i++) {
|
||||
for (j = 0; j < G_N_ELEMENTS (rgb32_format_map[i].va_format); j++) {
|
||||
if (va_format_is_same (&rgb32_format_map[i].va_format[j], image_format)) {
|
||||
*drm_fourcc = rgb32_format_map[i].drm_fourcc;
|
||||
return rgb32_format_map[i].format;
|
||||
}
|
||||
}
|
||||
|
@ -436,14 +428,13 @@ fix_map (gpointer data)
|
|||
GstVideoFormat format;
|
||||
VAImageFormat *image_format;
|
||||
struct FormatMap *map;
|
||||
guint drm_fourcc = 0;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < args->len; i++) {
|
||||
image_format = &args->image_formats[i];
|
||||
if (!va_format_is_rgb (image_format))
|
||||
continue;
|
||||
format = find_gst_video_format_in_rgb32_map (image_format, &drm_fourcc);
|
||||
format = find_gst_video_format_in_rgb32_map (image_format);
|
||||
if (format == GST_VIDEO_FORMAT_UNKNOWN)
|
||||
continue;
|
||||
map = get_format_map_from_video_format (format);
|
||||
|
@ -453,14 +444,11 @@ fix_map (gpointer data)
|
|||
continue;
|
||||
|
||||
map->va_format = *image_format;
|
||||
map->drm_fourcc = drm_fourcc;
|
||||
|
||||
GST_INFO ("GST_VIDEO_FORMAT_%s => { fourcc %" GST_FOURCC_FORMAT ", "
|
||||
"drm fourcc %" GST_FOURCC_FORMAT ", %s, bpp %d, depth %d, "
|
||||
"R %#010x, G %#010x, B %#010x, A %#010x }",
|
||||
gst_video_format_to_string (map->format),
|
||||
GST_INFO ("GST_VIDEO_FORMAT_%s => { fourcc %"
|
||||
GST_FOURCC_FORMAT ", %s, bpp %d, depth %d, R %#010x, G %#010x, "
|
||||
"B %#010x, A %#010x }", gst_video_format_to_string (map->format),
|
||||
GST_FOURCC_ARGS (map->va_format.fourcc),
|
||||
GST_FOURCC_ARGS (map->drm_fourcc),
|
||||
(map->va_format.byte_order == 1) ? "LSB" : "MSB",
|
||||
map->va_format.bits_per_pixel, map->va_format.depth,
|
||||
map->va_format.red_mask, map->va_format.green_mask,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstvkdecoder.h"
|
||||
#include "gstvkdecoder-private.h"
|
||||
|
||||
#include "gstvkoperation.h"
|
||||
#include "gstvkphysicaldevice-private.h"
|
||||
|
@ -39,6 +39,7 @@
|
|||
* Since: 1.24
|
||||
*/
|
||||
|
||||
typedef struct _GstVulkanDecoderPrivate GstVulkanDecoderPrivate;
|
||||
struct _GstVulkanDecoderPrivate
|
||||
{
|
||||
GstVulkanHandle *empty_params;
|
||||
|
@ -1309,3 +1310,72 @@ gst_vulkan_decoder_wait (GstVulkanDecoder * self)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_decoder_new_from_queue:
|
||||
* @queue: a #GstVulkanQueue
|
||||
* @codec: (type guint): the VkVideoCodecOperationFlagBitsKHR to decode
|
||||
*
|
||||
* Creates a #GstVulkanDecoder object if @codec decoding is supported by @queue
|
||||
*
|
||||
* Returns: (transfer full) (nullable): the #GstVulkanDecoder object
|
||||
*/
|
||||
GstVulkanDecoder *
|
||||
gst_vulkan_decoder_new_from_queue (GstVulkanQueue * queue, guint codec)
|
||||
{
|
||||
GstVulkanPhysicalDevice *device;
|
||||
GstVulkanDecoder *decoder;
|
||||
guint flags, expected_flag, supported_video_ops;
|
||||
const char *extension;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VULKAN_QUEUE (queue), NULL);
|
||||
|
||||
device = queue->device->physical_device;
|
||||
expected_flag = VK_QUEUE_VIDEO_DECODE_BIT_KHR;
|
||||
flags = device->queue_family_props[queue->family].queueFlags;
|
||||
supported_video_ops = device->queue_family_ops[queue->family].video;
|
||||
|
||||
if (device->properties.apiVersion < VK_MAKE_VERSION (1, 3, 238)) {
|
||||
GST_WARNING_OBJECT (queue,
|
||||
"Driver API version [%d.%d.%d] doesn't support Video extensions",
|
||||
VK_VERSION_MAJOR (device->properties.apiVersion),
|
||||
VK_VERSION_MINOR (device->properties.apiVersion),
|
||||
VK_VERSION_PATCH (device->properties.apiVersion));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (codec) {
|
||||
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
|
||||
extension = VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME;
|
||||
break;
|
||||
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
|
||||
extension = VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME;
|
||||
break;
|
||||
default:
|
||||
GST_WARNING_OBJECT (queue, "Unsupported codec %u", codec);
|
||||
return NULL;
|
||||
}
|
||||
if ((flags & expected_flag) != expected_flag) {
|
||||
GST_WARNING_OBJECT (queue, "Queue doesn't support decoding");
|
||||
return NULL;
|
||||
}
|
||||
if ((supported_video_ops & codec) != codec) {
|
||||
GST_WARNING_OBJECT (queue, "Queue doesn't support codec %u decoding",
|
||||
codec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(gst_vulkan_device_is_extension_enabled (queue->device,
|
||||
VK_KHR_VIDEO_QUEUE_EXTENSION_NAME)
|
||||
&& gst_vulkan_device_is_extension_enabled (queue->device,
|
||||
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME)
|
||||
&& gst_vulkan_device_is_extension_enabled (queue->device, extension)))
|
||||
return NULL;
|
||||
|
||||
decoder = g_object_new (GST_TYPE_VULKAN_DECODER, NULL);
|
||||
gst_object_ref_sink (decoder);
|
||||
decoder->queue = gst_object_ref (queue);
|
||||
decoder->codec = codec;
|
||||
|
||||
return decoder;
|
||||
}
|
|
@ -21,7 +21,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <gst/vulkan/gstvkqueue.h>
|
||||
#include <gst/vulkan/gstvkvideoutils.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -34,6 +33,11 @@ G_BEGIN_DECLS
|
|||
GST_VULKAN_API
|
||||
GType gst_vulkan_decoder_get_type (void);
|
||||
|
||||
typedef struct _GstVulkanDecoder GstVulkanDecoder;
|
||||
typedef struct _GstVulkanDecoderClass GstVulkanDecoderClass;
|
||||
typedef struct _GstVulkanDecoderPicture GstVulkanDecoderPicture;
|
||||
typedef union _GstVulkanDecoderParameters GstVulkanDecoderParameters;
|
||||
|
||||
/**
|
||||
* GstVulkanDecoderPicture:
|
||||
* @out: output buffer
|
||||
|
@ -132,6 +136,9 @@ union _GstVulkanDecoderParameters
|
|||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstVulkanDecoder, gst_object_unref)
|
||||
|
||||
GST_VULKAN_API
|
||||
GstVulkanDecoder * gst_vulkan_decoder_new_from_queue (GstVulkanQueue * queue,
|
||||
guint codec);
|
||||
GST_VULKAN_API
|
||||
gboolean gst_vulkan_decoder_start (GstVulkanDecoder * self,
|
||||
GstVulkanVideoProfile * profile,
|
|
@ -23,6 +23,9 @@
|
|||
#endif
|
||||
|
||||
#include "gstvkqueue.h"
|
||||
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
|
||||
#include "gstvkdecoder-private.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:vkqueue
|
||||
|
@ -154,81 +157,6 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_queue_create_decoder:
|
||||
* @queue: a #GstVulkanQueue
|
||||
* @codec: (type guint): the VkVideoCodecOperationFlagBitsKHR to decode
|
||||
*
|
||||
* Creates a #GstVulkanDecoder object if @codec decoding is supported by @queue
|
||||
*
|
||||
* Returns: (transfer full) (nullable): the #GstVulkanDecoder object
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
GstVulkanDecoder *
|
||||
gst_vulkan_queue_create_decoder (GstVulkanQueue * queue, guint codec)
|
||||
{
|
||||
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
|
||||
GstVulkanPhysicalDevice *device;
|
||||
GstVulkanDecoder *decoder;
|
||||
guint flags, expected_flag, supported_video_ops;
|
||||
const char *extension;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VULKAN_QUEUE (queue), NULL);
|
||||
|
||||
device = queue->device->physical_device;
|
||||
expected_flag = VK_QUEUE_VIDEO_DECODE_BIT_KHR;
|
||||
flags = device->queue_family_props[queue->family].queueFlags;
|
||||
supported_video_ops = device->queue_family_ops[queue->family].video;
|
||||
|
||||
if (device->properties.apiVersion < VK_MAKE_VERSION (1, 3, 238)) {
|
||||
GST_WARNING_OBJECT (queue,
|
||||
"Driver API version [%d.%d.%d] doesn't support Video extensions",
|
||||
VK_VERSION_MAJOR (device->properties.apiVersion),
|
||||
VK_VERSION_MINOR (device->properties.apiVersion),
|
||||
VK_VERSION_PATCH (device->properties.apiVersion));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (codec) {
|
||||
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
|
||||
extension = VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME;
|
||||
break;
|
||||
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
|
||||
extension = VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME;
|
||||
break;
|
||||
default:
|
||||
GST_WARNING_OBJECT (queue, "Unsupported codec %u", codec);
|
||||
return NULL;
|
||||
}
|
||||
if ((flags & expected_flag) != expected_flag) {
|
||||
GST_WARNING_OBJECT (queue, "Queue doesn't support decoding");
|
||||
return NULL;
|
||||
}
|
||||
if ((supported_video_ops & codec) != codec) {
|
||||
GST_WARNING_OBJECT (queue, "Queue doesn't support codec %u decoding",
|
||||
codec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(gst_vulkan_device_is_extension_enabled (queue->device,
|
||||
VK_KHR_VIDEO_QUEUE_EXTENSION_NAME)
|
||||
&& gst_vulkan_device_is_extension_enabled (queue->device,
|
||||
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME)
|
||||
&& gst_vulkan_device_is_extension_enabled (queue->device, extension)))
|
||||
return NULL;
|
||||
|
||||
decoder = g_object_new (GST_TYPE_VULKAN_DECODER, NULL);
|
||||
gst_object_ref_sink (decoder);
|
||||
decoder->queue = gst_object_ref (queue);
|
||||
decoder->codec = codec;
|
||||
|
||||
return decoder;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_context_set_vulkan_queue:
|
||||
* @context: a #GstContext
|
||||
|
|
|
@ -23,9 +23,6 @@
|
|||
|
||||
#include <gst/vulkan/gstvkdevice.h>
|
||||
#include <gst/vulkan/gstvkcommandpool.h>
|
||||
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
|
||||
#include <gst/vulkan/gstvkdecoder.h>
|
||||
#endif
|
||||
|
||||
#define GST_TYPE_VULKAN_QUEUE (gst_vulkan_queue_get_type())
|
||||
#define GST_VULKAN_QUEUE(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_VULKAN_QUEUE, GstVulkanQueue))
|
||||
|
@ -83,15 +80,12 @@ struct _GstVulkanQueueClass
|
|||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstVulkanQueue, gst_object_unref)
|
||||
|
||||
GST_VULKAN_API
|
||||
GST_VULKAN_API
|
||||
GstVulkanDevice * gst_vulkan_queue_get_device (GstVulkanQueue * queue);
|
||||
|
||||
GST_VULKAN_API
|
||||
GstVulkanCommandPool * gst_vulkan_queue_create_command_pool (GstVulkanQueue * queue,
|
||||
GError ** error);
|
||||
GST_VULKAN_API
|
||||
GstVulkanDecoder * gst_vulkan_queue_create_decoder (GstVulkanQueue * queue,
|
||||
guint codec);
|
||||
|
||||
GST_VULKAN_API
|
||||
void gst_vulkan_queue_submit_lock (GstVulkanQueue * queue);
|
||||
|
|
|
@ -178,8 +178,18 @@ _get_function_table (GstVulkanSwapper * swapper)
|
|||
}
|
||||
|
||||
static VkColorSpaceKHR
|
||||
_vk_color_space_from_video_info (GstVideoInfo * v_info)
|
||||
_vk_color_space_from_vk_format (GstVulkanSwapper * swapper, VkFormat format)
|
||||
{
|
||||
GstVulkanSwapperPrivate *priv = GET_PRIV (swapper);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->n_surf_formats; i++) {
|
||||
if (format != priv->surf_formats[i].format)
|
||||
continue;
|
||||
return priv->surf_formats[i].colorSpace;
|
||||
}
|
||||
|
||||
GST_WARNING_OBJECT (swapper, "unsupported format for swapper's colospaces");
|
||||
return VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||
}
|
||||
|
||||
|
@ -790,7 +800,7 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps,
|
|||
}
|
||||
|
||||
format = gst_vulkan_format_from_video_info (&priv->v_info, 0);
|
||||
color_space = _vk_color_space_from_video_info (&priv->v_info);
|
||||
color_space = _vk_color_space_from_vk_format (swapper, format);
|
||||
|
||||
if ((priv->surf_props.supportedCompositeAlpha &
|
||||
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) != 0) {
|
||||
|
|
|
@ -333,12 +333,9 @@ static StdVideoH265PictureParameterSet h265_pps;
|
|||
endif
|
||||
if have_vk_video
|
||||
vulkan_conf.set('GST_VULKAN_HAVE_VIDEO_EXTENSIONS', 1)
|
||||
vulkan_priv_sources += files('gstvkvideo-private.c')
|
||||
vulkan_sources += files(
|
||||
'gstvkdecoder.c',
|
||||
)
|
||||
vulkan_headers += files(
|
||||
'gstvkdecoder.h'
|
||||
vulkan_priv_sources += files(
|
||||
'gstvkvideo-private.c',
|
||||
'gstvkdecoder-private.c',
|
||||
)
|
||||
elif get_option('vulkan-video').enabled()
|
||||
error('Vulkan Video extensions headers not found')
|
||||
|
@ -501,4 +498,3 @@ if enabled_vulkan_winsys.contains('wayland')
|
|||
sources : vulkan_wayland_gir)
|
||||
meson.override_dependency('gstreamer-vulkan-wayland-1.0', gstvulkanwayland_dep)
|
||||
endif
|
||||
|
||||
|
|
|
@ -119,12 +119,6 @@ typedef struct _GstVulkanOperation GstVulkanOperation;
|
|||
typedef struct _GstVulkanOperationClass GstVulkanOperationClass;
|
||||
typedef struct _GstVulkanOperationPrivate GstVulkanOperationPrivate;
|
||||
|
||||
typedef struct _GstVulkanDecoder GstVulkanDecoder;
|
||||
typedef struct _GstVulkanDecoderClass GstVulkanDecoderClass;
|
||||
typedef struct _GstVulkanDecoderPrivate GstVulkanDecoderPrivate;
|
||||
typedef union _GstVulkanDecoderParameters GstVulkanDecoderParameters;
|
||||
typedef struct _GstVulkanDecoderPicture GstVulkanDecoderPicture;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_VULKAN_FWD_H__ */
|
||||
|
|
|
@ -196,6 +196,9 @@ gst_wl_window_finalize (GObject * gobject)
|
|||
gst_wl_display_callback_destroy (priv->display, &priv->frame_callback);
|
||||
gst_wl_display_callback_destroy (priv->display, &priv->commit_callback);
|
||||
|
||||
if (priv->staged_buffer)
|
||||
gst_wl_buffer_unref_buffer (priv->staged_buffer);
|
||||
|
||||
g_cond_clear (&priv->configure_cond);
|
||||
g_mutex_clear (&priv->configure_mutex);
|
||||
g_mutex_clear (&priv->window_lock);
|
||||
|
|
|
@ -428,12 +428,22 @@ send_command_to_all (GstUnixFdSink * self, CommandType type, GUnixFDList * fds,
|
|||
}
|
||||
|
||||
static GstClockTime
|
||||
calculate_timestamp (GstClockTime timestamp, GstClockTime base_time,
|
||||
GstClockTime latency, GstClockTimeDiff clock_diff)
|
||||
to_monotonic (GstClockTime timestamp, const GstSegment * segment,
|
||||
GstClockTime base_time, GstClockTime latency, GstClockTimeDiff clock_diff)
|
||||
{
|
||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||
/* Convert running time to pipeline clock time */
|
||||
timestamp += base_time;
|
||||
gint res =
|
||||
gst_segment_to_running_time_full (segment, GST_FORMAT_TIME, timestamp,
|
||||
×tamp);
|
||||
if (res == 0)
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
else if (res > 0)
|
||||
timestamp += base_time;
|
||||
else if (base_time > timestamp)
|
||||
timestamp = base_time - timestamp;
|
||||
else
|
||||
timestamp = 0;
|
||||
if (GST_CLOCK_TIME_IS_VALID (latency))
|
||||
timestamp += latency;
|
||||
/* Convert to system monotonic clock time */
|
||||
|
@ -485,11 +495,11 @@ gst_unix_fd_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
* id so we know which buffer to unref. */
|
||||
new_buffer->id = (guint64) buffer;
|
||||
new_buffer->pts =
|
||||
calculate_timestamp (GST_BUFFER_PTS (buffer), base_time, latency,
|
||||
clock_diff);
|
||||
to_monotonic (GST_BUFFER_PTS (buffer),
|
||||
&GST_BASE_SINK_CAST (self)->segment, base_time, latency, clock_diff);
|
||||
new_buffer->dts =
|
||||
calculate_timestamp (GST_BUFFER_DTS (buffer), base_time, latency,
|
||||
clock_diff);
|
||||
to_monotonic (GST_BUFFER_DTS (buffer),
|
||||
&GST_BASE_SINK_CAST (self)->segment, base_time, latency, clock_diff);
|
||||
new_buffer->duration = GST_BUFFER_DURATION (buffer);
|
||||
new_buffer->offset = GST_BUFFER_OFFSET (buffer);
|
||||
new_buffer->offset_end = GST_BUFFER_OFFSET_END (buffer);
|
||||
|
@ -498,6 +508,15 @@ gst_unix_fd_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
new_buffer->n_memory = n_memory;
|
||||
new_buffer->n_meta = n_meta;
|
||||
|
||||
if ((GST_BUFFER_PTS_IS_VALID (buffer)
|
||||
&& !GST_CLOCK_TIME_IS_VALID (new_buffer->pts))
|
||||
|| (GST_BUFFER_DTS_IS_VALID (buffer)
|
||||
&& !GST_CLOCK_TIME_IS_VALID (new_buffer->dts))) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Could not convert buffer timestamp to running time");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
gboolean dmabuf_count = 0;
|
||||
GUnixFDList *fds = g_unix_fd_list_new ();
|
||||
for (int i = 0; i < n_memory; i++) {
|
||||
|
|
|
@ -89,31 +89,34 @@ typedef struct
|
|||
guint n_memory;
|
||||
} BufferContext;
|
||||
|
||||
static void
|
||||
release_buffer (GstUnixFdSrc * self, guint64 id)
|
||||
{
|
||||
/* Notify that we are not using this buffer anymore */
|
||||
ReleaseBufferPayload payload = { id };
|
||||
GError *error = NULL;
|
||||
if (!gst_unix_fd_send_command (self->socket, COMMAND_TYPE_RELEASE_BUFFER,
|
||||
NULL, (guint8 *) & payload, sizeof (payload), &error)) {
|
||||
GST_WARNING_OBJECT (self, "Failed to send release-buffer command: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
memory_weak_ref_cb (GstUnixFdSrc * self, GstMemory * mem)
|
||||
{
|
||||
GST_OBJECT_LOCK (self);
|
||||
|
||||
BufferContext *ctx = g_hash_table_lookup (self->memories, mem);
|
||||
if (ctx == NULL)
|
||||
goto out;
|
||||
|
||||
if (--ctx->n_memory == 0) {
|
||||
/* Notify that we are not using this buffer anymore */
|
||||
ReleaseBufferPayload payload = { ctx->id };
|
||||
GError *error = NULL;
|
||||
if (!gst_unix_fd_send_command (self->socket, COMMAND_TYPE_RELEASE_BUFFER,
|
||||
NULL, (guint8 *) & payload, sizeof (payload), &error)) {
|
||||
GST_WARNING_OBJECT (self, "Failed to send release-buffer command: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
if (ctx != NULL) {
|
||||
if (--ctx->n_memory == 0) {
|
||||
release_buffer (self, ctx->id);
|
||||
g_free (ctx);
|
||||
}
|
||||
g_free (ctx);
|
||||
g_hash_table_remove (self->memories, mem);
|
||||
}
|
||||
|
||||
g_hash_table_remove (self->memories, mem);
|
||||
|
||||
out:
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
}
|
||||
|
||||
|
@ -279,7 +282,7 @@ gst_unix_fd_src_unlock_stop (GstBaseSrc * bsrc)
|
|||
}
|
||||
|
||||
static GstClockTime
|
||||
calculate_timestamp (GstClockTime timestamp, GstClockTime base_time,
|
||||
from_monotonic (GstClockTime timestamp, GstClockTime base_time,
|
||||
GstClockTimeDiff clock_diff)
|
||||
{
|
||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||
|
@ -295,6 +298,14 @@ calculate_timestamp (GstClockTime timestamp, GstClockTime base_time,
|
|||
return timestamp;
|
||||
}
|
||||
|
||||
static void
|
||||
close_and_free_fds (gint * fds, gint fds_len)
|
||||
{
|
||||
for (int i = 0; i < fds_len; i++)
|
||||
g_close (fds[i], NULL);
|
||||
g_free (fds);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_unix_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
|
||||
{
|
||||
|
@ -335,33 +346,26 @@ again:
|
|||
goto on_error;
|
||||
}
|
||||
|
||||
if (fds == NULL) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Received new buffer command without file descriptors");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
if (g_unix_fd_list_get_length (fds) != new_buffer->n_memory) {
|
||||
gint fds_arr_len = 0;
|
||||
gint *fds_arr =
|
||||
(fds != NULL) ? g_unix_fd_list_steal_fds (fds, &fds_arr_len) : NULL;
|
||||
if (fds_arr_len != new_buffer->n_memory) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Received new buffer command with %d file descriptors instead of "
|
||||
"%d", g_unix_fd_list_get_length (fds), new_buffer->n_memory);
|
||||
"%d", fds_arr_len, new_buffer->n_memory);
|
||||
ret = GST_FLOW_ERROR;
|
||||
close_and_free_fds (fds_arr, fds_arr_len);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if (new_buffer->type >= MEMORY_TYPE_LAST) {
|
||||
GST_ERROR_OBJECT (self, "Unknown buffer type %d", new_buffer->type);
|
||||
ret = GST_FLOW_ERROR;
|
||||
close_and_free_fds (fds_arr, fds_arr_len);
|
||||
goto on_error;
|
||||
}
|
||||
GstAllocator *allocator = self->allocators[new_buffer->type];
|
||||
|
||||
gint *fds_arr = g_unix_fd_list_steal_fds (fds, NULL);
|
||||
|
||||
BufferContext *ctx = g_new0 (BufferContext, 1);
|
||||
ctx->id = new_buffer->id;
|
||||
ctx->n_memory = new_buffer->n_memory;
|
||||
|
||||
*outbuf = gst_buffer_new ();
|
||||
|
||||
GstClockTime base_time =
|
||||
|
@ -373,9 +377,9 @@ again:
|
|||
}
|
||||
|
||||
GST_BUFFER_PTS (*outbuf) =
|
||||
calculate_timestamp (new_buffer->pts, base_time, clock_diff);
|
||||
from_monotonic (new_buffer->pts, base_time, clock_diff);
|
||||
GST_BUFFER_DTS (*outbuf) =
|
||||
calculate_timestamp (new_buffer->dts, base_time, clock_diff);
|
||||
from_monotonic (new_buffer->dts, base_time, clock_diff);
|
||||
GST_BUFFER_DURATION (*outbuf) = new_buffer->duration;
|
||||
GST_BUFFER_OFFSET (*outbuf) = new_buffer->offset;
|
||||
GST_BUFFER_OFFSET_END (*outbuf) = new_buffer->offset_end;
|
||||
|
@ -388,24 +392,35 @@ again:
|
|||
if (consumed == 0) {
|
||||
GST_ERROR_OBJECT (self, "Malformed meta serialization");
|
||||
ret = GST_FLOW_ERROR;
|
||||
close_and_free_fds (fds_arr, fds_arr_len);
|
||||
gst_clear_buffer (outbuf);
|
||||
goto on_error;
|
||||
}
|
||||
payload_off += consumed;
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
for (int i = 0; i < new_buffer->n_memory; i++) {
|
||||
GstMemory *mem = gst_fd_allocator_alloc (allocator, fds_arr[i],
|
||||
new_buffer->memories[i].size, GST_FD_MEMORY_FLAG_NONE);
|
||||
gst_memory_resize (mem, new_buffer->memories[i].offset,
|
||||
new_buffer->memories[i].size);
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_READONLY);
|
||||
if (new_buffer->n_memory > 0) {
|
||||
BufferContext *ctx = g_new0 (BufferContext, 1);
|
||||
ctx->id = new_buffer->id;
|
||||
ctx->n_memory = new_buffer->n_memory;
|
||||
for (int i = 0; i < new_buffer->n_memory; i++) {
|
||||
GstMemory *mem = gst_fd_allocator_alloc (allocator, fds_arr[i],
|
||||
new_buffer->memories[i].size, GST_FD_MEMORY_FLAG_NONE);
|
||||
gst_memory_resize (mem, new_buffer->memories[i].offset,
|
||||
new_buffer->memories[i].size);
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_READONLY);
|
||||
|
||||
g_hash_table_insert (self->memories, mem, ctx);
|
||||
gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (mem),
|
||||
(GstMiniObjectNotify) memory_weak_ref_cb, self);
|
||||
g_hash_table_insert (self->memories, mem, ctx);
|
||||
gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (mem),
|
||||
(GstMiniObjectNotify) memory_weak_ref_cb, self);
|
||||
|
||||
gst_buffer_append_memory (*outbuf, mem);
|
||||
gst_buffer_append_memory (*outbuf, mem);
|
||||
}
|
||||
} else {
|
||||
/* This buffer has no memories, we can release it immediately otherwise
|
||||
* it gets leaked. */
|
||||
release_buffer (self, new_buffer->id);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -777,11 +777,13 @@ gst_d3d12_screen_capture_src_decide_allocation (GstBaseSrc * bsrc,
|
|||
if (!params) {
|
||||
params = gst_d3d12_allocation_params_new (self->device, &vinfo,
|
||||
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags,
|
||||
D3D12_HEAP_FLAG_NONE);
|
||||
D3D12_HEAP_FLAG_SHARED);
|
||||
} else {
|
||||
gst_d3d12_allocation_params_set_resource_flags (params, resource_flags);
|
||||
gst_d3d12_allocation_params_unset_resource_flags (params,
|
||||
D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
|
||||
gst_d3d12_allocation_params_set_heap_flags (params,
|
||||
D3D12_HEAP_FLAG_SHARED);
|
||||
}
|
||||
|
||||
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
|
||||
|
@ -815,7 +817,7 @@ gst_d3d12_screen_capture_src_decide_allocation (GstBaseSrc * bsrc,
|
|||
|
||||
auto params = gst_d3d12_allocation_params_new (self->device, &vinfo,
|
||||
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags,
|
||||
D3D12_HEAP_FLAG_NONE);
|
||||
D3D12_HEAP_FLAG_SHARED);
|
||||
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
|
||||
gst_d3d12_allocation_params_free (params);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/app/app.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
static void
|
||||
|
@ -134,6 +135,92 @@ GST_START_TEST (test_unixfd_videotestsrc)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_unixfd_segment)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
/* Ensure we don't have socket from previous failed test */
|
||||
gchar *socket_path =
|
||||
g_strdup_printf ("%s/unixfd-test-socket", g_get_user_runtime_dir ());
|
||||
if (g_file_test (socket_path, G_FILE_TEST_EXISTS)) {
|
||||
g_unlink (socket_path);
|
||||
}
|
||||
|
||||
GstCaps *caps = gst_caps_new_empty_simple ("video/x-raw");
|
||||
|
||||
/* Setup service */
|
||||
gchar *pipeline_str =
|
||||
g_strdup_printf
|
||||
("appsrc name=src format=time handle-segment-change=true ! unixfdsink socket-path=%s sync=false async=false",
|
||||
socket_path);
|
||||
GstElement *pipeline_service = gst_parse_launch (pipeline_str, &error);
|
||||
g_assert_no_error (error);
|
||||
fail_unless (gst_element_set_state (pipeline_service,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
|
||||
GstElement *appsrc = gst_bin_get_by_name (GST_BIN (pipeline_service), "src");
|
||||
gst_object_unref (appsrc);
|
||||
g_free (pipeline_str);
|
||||
|
||||
/* Setup client */
|
||||
pipeline_str =
|
||||
g_strdup_printf
|
||||
("unixfdsrc socket-path=%s ! appsink name=sink sync=false async=false",
|
||||
socket_path);
|
||||
GstElement *pipeline_client = gst_parse_launch (pipeline_str, &error);
|
||||
g_assert_no_error (error);
|
||||
fail_unless (gst_element_set_state (pipeline_client,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
|
||||
GstElement *appsink = gst_bin_get_by_name (GST_BIN (pipeline_client), "sink");
|
||||
gst_object_unref (appsink);
|
||||
g_free (pipeline_str);
|
||||
|
||||
/* Send a buffer with PTS=30s */
|
||||
GstSegment segment;
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
GstBuffer *buf = gst_buffer_new ();
|
||||
GST_BUFFER_PTS (buf) = 30 * GST_SECOND;
|
||||
GstSample *sample = gst_sample_new (buf, caps, &segment, NULL);
|
||||
gst_app_src_push_sample (GST_APP_SRC (appsrc), sample);
|
||||
gst_sample_unref (sample);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
/* Wait for it */
|
||||
sample = gst_app_sink_pull_sample (GST_APP_SINK (appsink));
|
||||
buf = gst_sample_get_buffer (sample);
|
||||
GstClockTime first_pts = GST_BUFFER_PTS (buf);
|
||||
gst_sample_unref (sample);
|
||||
|
||||
/* Send a buffer with PTS=1s but with 30s offset in the segment */
|
||||
segment.base = 30 * GST_SECOND;
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_PTS (buf) = 1 * GST_SECOND;
|
||||
sample = gst_sample_new (buf, caps, &segment, NULL);
|
||||
gst_app_src_push_sample (GST_APP_SRC (appsrc), sample);
|
||||
gst_sample_unref (sample);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
/* Wait for it */
|
||||
sample = gst_app_sink_pull_sample (GST_APP_SINK (appsink));
|
||||
buf = gst_sample_get_buffer (sample);
|
||||
GstClockTime second_pts = GST_BUFFER_PTS (buf);
|
||||
gst_sample_unref (sample);
|
||||
|
||||
/* They should be 1s appart */
|
||||
fail_unless_equals_uint64 (second_pts - first_pts, GST_SECOND);
|
||||
|
||||
/* Teardown */
|
||||
fail_unless (gst_element_set_state (pipeline_client,
|
||||
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
|
||||
fail_unless (gst_element_set_state (pipeline_service,
|
||||
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
|
||||
gst_object_unref (pipeline_service);
|
||||
gst_object_unref (pipeline_client);
|
||||
g_free (socket_path);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
unixfd_suite (void)
|
||||
{
|
||||
|
@ -142,6 +229,7 @@ unixfd_suite (void)
|
|||
|
||||
suite_add_tcase (s, tc);
|
||||
tcase_add_test (tc, test_unixfd_videotestsrc);
|
||||
tcase_add_test (tc, test_unixfd_segment);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
|
||||
#include "gst/vulkan/gstvkdecoder-private.h"
|
||||
|
||||
static GstVulkanInstance *instance;
|
||||
static GstVulkanDevice *device;
|
||||
static GstVulkanQueue *video_queue = NULL;
|
||||
|
@ -327,7 +329,7 @@ GST_START_TEST (test_h264_decoder)
|
|||
return;
|
||||
}
|
||||
|
||||
dec = gst_vulkan_queue_create_decoder (video_queue,
|
||||
dec = gst_vulkan_decoder_new_from_queue (video_queue,
|
||||
VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
|
||||
if (!dec) {
|
||||
GST_WARNING ("Unable to create a vulkan decoder");
|
||||
|
@ -495,7 +497,7 @@ GST_START_TEST (test_h265_decoder)
|
|||
return;
|
||||
}
|
||||
|
||||
dec = gst_vulkan_queue_create_decoder (video_queue,
|
||||
dec = gst_vulkan_decoder_new_from_queue (video_queue,
|
||||
VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
|
||||
if (!dec) {
|
||||
GST_WARNING ("Unable to create a vulkan decoder");
|
||||
|
|
|
@ -65,6 +65,25 @@ typedef struct _GstExifWriter GstExifWriter;
|
|||
typedef struct _GstExifReader GstExifReader;
|
||||
typedef struct _GstExifTagData GstExifTagData;
|
||||
|
||||
#define GST_CAT_DEFAULT gst_exif_tag_ensure_debug_category()
|
||||
|
||||
static GstDebugCategory *
|
||||
gst_exif_tag_ensure_debug_category (void)
|
||||
{
|
||||
static gsize cat_gonce = 0;
|
||||
|
||||
if (g_once_init_enter (&cat_gonce)) {
|
||||
GstDebugCategory *cat = NULL;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (cat, "exif-tags", 0, "EXIF tag parsing");
|
||||
|
||||
g_once_init_leave (&cat_gonce, (gsize) cat);
|
||||
}
|
||||
|
||||
return (GstDebugCategory *) cat_gonce;
|
||||
}
|
||||
|
||||
|
||||
typedef void (*GstExifSerializationFunc) (GstExifWriter * writer,
|
||||
const GstTagList * taglist, const GstExifTagMatch * exiftag);
|
||||
|
||||
|
|
|
@ -2614,25 +2614,38 @@ reconfigure_output (GstPlayBin3 * playbin)
|
|||
GST_DEBUG_OBJECT (playbin, "Stream type '%s' is now requested",
|
||||
gst_stream_type_get_name (combine->stream_type));
|
||||
|
||||
g_assert (combine->sinkpad == NULL);
|
||||
if (combine->sinkpad) {
|
||||
/* This was previously an assert but is now just a WARNING
|
||||
*
|
||||
* This *theoretically* should never happen, but there is the
|
||||
* possibility where there was a failure within (uri)decodebin3 where
|
||||
* the collection was posted (by demuxer for ex) but the decoding failed
|
||||
* (no decoder, bad stream, etc...).
|
||||
*
|
||||
* in that case, we could have a combiner already prepared for that type
|
||||
* but never got activated.
|
||||
**/
|
||||
GST_WARNING_OBJECT (playbin, "Combiner already configured");
|
||||
} else {
|
||||
|
||||
/* Request playsink sink pad */
|
||||
combine->sinkpad =
|
||||
gst_play_sink_request_pad (playbin->playsink,
|
||||
gst_play_sink_type_from_stream_type (combine->stream_type));
|
||||
gst_object_ref (combine->sinkpad);
|
||||
/* Create combiner if needed and link it */
|
||||
create_combiner (playbin, combine);
|
||||
if (combine->combiner) {
|
||||
res = gst_pad_link (combine->srcpad, combine->sinkpad);
|
||||
GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d",
|
||||
gst_stream_type_get_name (combine->stream_type), res);
|
||||
if (res != GST_PAD_LINK_OK) {
|
||||
GST_ELEMENT_ERROR (playbin, CORE, PAD,
|
||||
("Internal playbin error."),
|
||||
("Failed to link combiner to sink. Error %d", res));
|
||||
}
|
||||
|
||||
/* Request playsink sink pad */
|
||||
combine->sinkpad =
|
||||
gst_play_sink_request_pad (playbin->playsink,
|
||||
gst_play_sink_type_from_stream_type (combine->stream_type));
|
||||
gst_object_ref (combine->sinkpad);
|
||||
/* Create combiner if needed and link it */
|
||||
create_combiner (playbin, combine);
|
||||
if (combine->combiner) {
|
||||
res = gst_pad_link (combine->srcpad, combine->sinkpad);
|
||||
GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d",
|
||||
gst_stream_type_get_name (combine->stream_type), res);
|
||||
if (res != GST_PAD_LINK_OK) {
|
||||
GST_ELEMENT_ERROR (playbin, CORE, PAD,
|
||||
("Internal playbin error."),
|
||||
("Failed to link combiner to sink. Error %d", res));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1202,7 +1202,7 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
|
|||
/* now owned by the loop */
|
||||
g_main_context_unref (ctx);
|
||||
|
||||
src->session->thread = g_thread_try_new ("souphttpsrc-thread",
|
||||
src->session->thread = g_thread_try_new ("souphttpsrc",
|
||||
thread_func, src, NULL);
|
||||
|
||||
if (!src->session->thread) {
|
||||
|
|
|
@ -45,35 +45,53 @@ pylib_loc = get_option('libpython-dir')
|
|||
fsmod = import('fs')
|
||||
pylib_prefix = 'lib'
|
||||
pylib_suffix = 'so'
|
||||
pylib_ver = python_dep.version()
|
||||
pylib_locs = []
|
||||
if host_system == 'windows'
|
||||
if cc.get_argument_syntax() == 'msvc'
|
||||
pylib_prefix = ''
|
||||
endif
|
||||
pylib_suffix = 'dll'
|
||||
pylib_ver = pylib_ver.replace('.', '')
|
||||
elif host_system == 'darwin'
|
||||
pylib_suffix = 'dylib'
|
||||
endif
|
||||
pylib_fnames = []
|
||||
# Library name with soversion, non-devel package
|
||||
pylib_fnames += python.get_variable('INSTSONAME', [])
|
||||
if python.has_variable('INSTSONAME')
|
||||
# For example, libpython3.12.so.1.0 (Linux), libpython3.11.dll.a (MSYS2), etc.
|
||||
pylib_fnames += python.get_variable('INSTSONAME')
|
||||
endif
|
||||
# Library name without soversion, devel package, framework, etc.
|
||||
pylib_fnames += python.get_variable('LDLIBRARY', [])
|
||||
if python.has_variable('LDLIBRARY')
|
||||
# For example, libpython3.12.so (Linux), libpython3.11.dll.a (MSYS2), etc.
|
||||
pylib_fnames += python.get_variable('LDLIBRARY')
|
||||
endif
|
||||
# Manually construct name as a fallback
|
||||
pylib_fnames += [
|
||||
pylib_prefix + 'python' + python_dep.version() + python_abi_flags + '.' + pylib_suffix
|
||||
pylib_prefix + 'python' + pylib_ver + python_abi_flags + '.' + pylib_suffix
|
||||
]
|
||||
if pylib_loc != ''
|
||||
pylib_locs = [pylib_loc]
|
||||
else
|
||||
pylib_locs = [
|
||||
python.get_variable('LIBDIR', ''),
|
||||
python.get_variable('LIBPL', ''),
|
||||
]
|
||||
if python.has_variable('LIBDIR')
|
||||
pylib_locs += python.get_variable('LIBDIR')
|
||||
endif
|
||||
if python.has_variable('LIBPL')
|
||||
pylib_locs += python.get_variable('LIBPL')
|
||||
endif
|
||||
# On Windows, python312.dll is in the rootdir where Python is installed,
|
||||
# which is configured as the "prefix" in sysconfig.
|
||||
if host_system == 'windows'
|
||||
pylib_locs += python.get_variable('prefix')
|
||||
endif
|
||||
endif
|
||||
pylib_fname = ''
|
||||
foreach loc: pylib_locs
|
||||
foreach fname: pylib_fnames
|
||||
if fsmod.exists(loc / fname)
|
||||
fpath = loc / fname
|
||||
debug(f'Looking for Python library at: @fpath@')
|
||||
if fsmod.exists(fpath)
|
||||
pylib_fname = fname
|
||||
message(f'PY_LIB_FNAME = @fname@ (@loc@)')
|
||||
break
|
||||
|
@ -81,12 +99,7 @@ foreach loc: pylib_locs
|
|||
endforeach
|
||||
endforeach
|
||||
if pylib_fname == ''
|
||||
error_msg = 'Could not find python library to load'
|
||||
if python_opt.enabled()
|
||||
error(error_msg)
|
||||
else
|
||||
message(error_msg)
|
||||
endif
|
||||
message('Could not find python library to load, will try loading at runtime')
|
||||
endif
|
||||
|
||||
pygi_override_dir = get_option('pygi-overrides-dir')
|
||||
|
|
|
@ -4014,13 +4014,24 @@ mark_event_not_received (GstPad * pad, PadEvent * ev, gpointer user_data)
|
|||
* @pad: a #GstPad
|
||||
* @offset: the offset
|
||||
*
|
||||
* Set the offset that will be applied to the running time of @pad.
|
||||
* Set the offset that will be applied to the running time of @pad. Upon next
|
||||
* buffer, every sticky events (notably segment) will be pushed again with
|
||||
* their running time adjusted. For that reason this is only reliable on
|
||||
* source pads.
|
||||
*/
|
||||
void
|
||||
gst_pad_set_offset (GstPad * pad, gint64 offset)
|
||||
{
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
|
||||
/* Setting pad offset on a sink pad does not work reliably:
|
||||
* https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6464 */
|
||||
if (GST_PAD_IS_SINK (pad)) {
|
||||
/* Make it non fatal warning for backward compatibility. */
|
||||
GST_WARNING_OBJECT (pad,
|
||||
"Setting pad offset only works reliably on source pads");
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (pad);
|
||||
/* if nothing changed, do nothing */
|
||||
if (pad->offset == offset)
|
||||
|
|
Loading…
Reference in a new issue