Merge branch 'master' into vr-devel

This commit is contained in:
Martin Pulec
2020-10-22 12:48:54 +02:00
37 changed files with 829 additions and 538 deletions

View File

@@ -5,21 +5,21 @@
ARCH=$1
BUILD_DIR=$2
sudo chroot $BUILD_DIR /bin/sh -c 'if grep -q Raspbian /etc/os-release; then sed -i s-http://deb.debian.org/debian-http://mirrordirector.raspbian.org/raspbian/- /etc/apt/sources.list && apt-get -y update; fi' # https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1670905 workaround
sudo chroot $BUILD_DIR /bin/sh -c 'apt-get -y install build-essential git pkg-config autoconf automake libtool'
sudo chroot $BUILD_DIR /bin/sh -c 'apt-get -y install portaudio19-dev libsdl2-dev libglib2.0-dev libglew-dev libcurl4-openssl-dev freeglut3-dev libssl-dev libjack-dev libasound2-dev'
sudo chroot $BUILD_DIR /bin/sh -ec 'if grep -q Raspbian /etc/os-release; then sed -i s-http://deb.debian.org/debian-http://mirrordirector.raspbian.org/raspbian/- /etc/apt/sources.list; apt-get -y update; fi' # https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1670905 workaround
sudo chroot $BUILD_DIR /bin/sh -ec 'apt-get -y install build-essential git pkg-config autoconf automake libtool'
sudo chroot $BUILD_DIR /bin/sh -ec 'apt-get -y install portaudio19-dev libsdl2-dev libglib2.0-dev libglew-dev libcurl4-openssl-dev freeglut3-dev libssl-dev libjack-dev libasound2-dev'
if [ $ARCH = armhf ]; then # Raspbian - build own FFmpeg with OMX camera patch
sudo chroot $BUILD_DIR /bin/sh -c "git clone --depth 1 https://github.com/raspberrypi/firmware.git firmware && mv firmware/* / && echo /opt/vc/lib > /etc/ld.so.conf.d/00-vmcs.conf && ldconfig"\
sudo chroot $BUILD_DIR /bin/sh -ec "git clone --depth 1 https://github.com/raspberrypi/firmware.git firmware && mv firmware/* / && echo /opt/vc/lib > /etc/ld.so.conf.d/00-vmcs.conf && ldconfig"\
"&& sed -i '/^deb /p;s/deb/deb-src/' /etc/apt/sources.list "\
"&& apt-get -y update && apt-get -y build-dep ffmpeg"\
"&& apt-get -y remove libavcodec58 && apt-get -y autoremove"\
"&& git clone --depth 1 https://github.com/FFmpeg/FFmpeg.git && cd FFmpeg"\
"&& git fetch --depth 2 https://github.com/Serveurperso/FFmpeg.git && git cherry-pick FETCH_HEAD"\
"&& ./configure --enable-gpl --disable-stripping --enable-libaom --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libspeex --enable-libvpx --enable-libwebp --enable-libx265 --enable-omx --enable-neon --enable-libx264 --enable-mmal --enable-omx-rpi --cpu=arm1176jzf-s --enable-shared --disable-static && make -j 3 && make install"\
"&& cd .. && rm -rf FFmpeg"
"&& cd .. && rm -rf FFmpeg || exit 1"
else
sudo chroot $BUILD_DIR /bin/sh -c 'apt-get -y install libavcodec-dev libavformat-dev libswscale-dev'
sudo chroot $BUILD_DIR /bin/sh -ec 'apt-get -y install libavcodec-dev libavformat-dev libswscale-dev'
fi
sudo chroot $BUILD_DIR /bin/sh -c 'apt-get -y install desktop-file-utils git-core libfuse-dev libcairo2-dev cmake wget zsync' # to build appimagetool
sudo chroot $BUILD_DIR /bin/sh -c 'git clone https://github.com/AppImage/AppImageKit.git && cd AppImageKit && ./build.sh && cd build && cmake -DAUXILIARY_FILES_DESTINATION= .. && make install'
sudo chroot $BUILD_DIR /bin/sh -c 'rm -rf AppImageKit; apt-get -y clean'
sudo chroot $BUILD_DIR /bin/sh -ec 'apt-get -y install desktop-file-utils git-core libfuse-dev libcairo2-dev cmake wget zsync' # to build appimagetool
sudo chroot $BUILD_DIR /bin/sh -ec 'git clone https://github.com/AppImage/AppImageKit.git && cd AppImageKit && ./build.sh && cd build && cmake -DAUXILIARY_FILES_DESTINATION= .. && make install || exit 1'
sudo chroot $BUILD_DIR /bin/sh -ec 'rm -rf AppImageKit; apt-get -y clean'

View File

@@ -1,7 +1,7 @@
#!/bin/sh -eux
export CPATH=/usr/local/include${CPATH:+":$CPATH"}
export EXTRA_LIB_PATH=/usr/local/cuda/lib64:/usr/local/lib
EXTRA_LIB_PATH=/usr/local/cuda/lib64:/usr/local/lib
export LIBRARY_PATH=$EXTRA_LIB_PATH${LIBRARY_PATH:+":$LIBRARY_PATH"}
export LD_LIBRARY_PATH=$EXTRA_LIB_PATH${LD_LIBRARY_PATH:+":$LD_LIBRARY_PATH"}
export PATH=/usr/local/bin:$PATH

View File

@@ -1,18 +1,19 @@
#!/bin/bash -eux
install_svt() {
( git clone --depth 1 https://github.com/OpenVisualCloud/SVT-HEVC && cd SVT-HEVC/Build/linux && ./build.sh release && cd Release && make && sudo make install )
( git clone --depth 1 -b v0.8.4 https://github.com/OpenVisualCloud/SVT-AV1 && cd SVT-AV1 && cd Build && cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release && make -j $(nproc) && sudo make install )
( git clone --depth 1 https://github.com/OpenVisualCloud/SVT-HEVC && cd SVT-HEVC/Build/linux && ./build.sh release && cd Release && make && sudo make install || exit 1 )
( git clone --depth 1 -b v0.8.4 https://github.com/OpenVisualCloud/SVT-AV1 && cd SVT-AV1 && cd Build && cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release && make -j $(nproc) && sudo make install || exit 1 )
git apply SVT-HEVC/ffmpeg_plugin/0001*.patch
git apply SVT-AV1/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-av1.patch
}
git clone -b n4.3 --depth 1 https://git.ffmpeg.org/ffmpeg.git /var/tmp/ffmpeg # n4.3 is needed for SVT HEVC patch
cd /var/tmp/ffmpeg
( git clone --depth 1 -b nasm-2.13.xx https://github.com/sezero/nasm.git && cd nasm && ./autogen.sh && ./configure && make nasm.1 && make ndisasm.1 && make && sudo make install )
( git clone --depth 1 http://git.videolan.org/git/x264.git && cd x264 && ./configure --disable-static --enable-shared && make && sudo make install )
( git clone -b sdk/8.1 https://git.videolan.org/git/ffmpeg/nv-codec-headers.git && cd nv-codec-headers && make && sudo make install )
( git clone --depth 1 https://aomedia.googlesource.com/aom && mkdir -p aom/build && cd aom/build && cmake -DBUILD_SHARED_LIBS=1 .. && make && sudo make install )
sed -i '1,/sliceModeData = 1;/s/sliceModeData = 1;/sliceModeData = 8;/' libavcodec/nvenc.c # only first occurence - for H.264, not HEVC
( git clone --depth 1 -b nasm-2.13.xx https://github.com/sezero/nasm.git && cd nasm && ./autogen.sh && ./configure && make nasm.1 && make ndisasm.1 && make && sudo make install || exit 1 )
( git clone --depth 1 http://git.videolan.org/git/x264.git && cd x264 && ./configure --disable-static --enable-shared && make && sudo make install || exit 1 )
( git clone -b sdk/8.1 https://git.videolan.org/git/ffmpeg/nv-codec-headers.git && cd nv-codec-headers && make && sudo make install || exit 1 )
( git clone --depth 1 https://aomedia.googlesource.com/aom && mkdir -p aom/build && cd aom/build && cmake -DBUILD_SHARED_LIBS=1 .. && make && sudo make install || exit 1 )
install_svt
./configure --disable-static --enable-shared --enable-gpl --enable-libx264 --enable-libx265 --enable-libopus --enable-nonfree --enable-nvenc --enable-libaom --enable-libvpx --enable-libspeex --enable-libmp3lame --enable-libsvthevc --enable-libsvtav1
make

View File

@@ -1,17 +1,17 @@
#!/bin/bash -eux
echo "::set-env name=AJA_DIRECTORY::/var/tmp/ntv2sdk"
echo "::set-env name=CPATH::/usr/local/qt/include"
echo "::set-env name=LIBRARY_PATH::/usr/local/qt/lib"
echo "::set-env name=PKG_CONFIG_PATH::/usr/local/qt/lib/pkgconfig"
echo "::add-path::/usr/local/qt/bin"
echo "AJA_DIRECTORY=/var/tmp/ntv2sdk" >> $GITHUB_ENV
echo "CPATH=/usr/local/qt/include" >> $GITHUB_ENV
echo "LIBRARY_PATH=/usr/local/qt/lib" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=/usr/local/qt/lib/pkgconfig" >> $GITHUB_ENV
echo "/usr/local/qt/bin" >> $GITHUB_PATH
if command -v gcc-5; then
CUDA_HOST_COMPILER=gcc-5
else
CUDA_HOST_COMPILER=gcc-6
fi
echo "::set-env name=CUDA_HOST_COMPILER::$CUDA_HOST_COMPILER"
echo "CUDA_HOST_COMPILER=$CUDA_HOST_COMPILER" >> $GITHUB_ENV
sudo sed -n 'p; /^deb /s/^deb /deb-src /p' -i /etc/apt/sources.list # for build-dep ffmpeg
sudo apt update
@@ -24,13 +24,13 @@ sudo apt install portaudio19-dev libjack-jackd2-dev libasound-dev libv4l-dev
# for FFmpeg
sudo apt build-dep ffmpeg
sudo apt-get remove 'libx264*' nasm
sudo apt-get -y remove 'libavcodec*' 'libavutil*' 'libswscale*' 'libx264*' nasm
sudo apt --no-install-recommends install asciidoc xmlto
sudo apt install libopencv-dev
sudo apt install libglib2.0-dev libcurl4-nss-dev
( mkdir gpujpeg/build && cd gpujpeg/build && CC=$CUDA_HOST_COMPILER cmake .. && make && sudo make install && sudo ldconfig )
( sudo apt install uuid-dev && cd cineform-sdk/ && cmake -DBUILD_TOOLS=OFF . && make CFHDCodecStatic )
( mkdir gpujpeg/build && cd gpujpeg/build && CC=$CUDA_HOST_COMPILER cmake .. && make && sudo make install && sudo ldconfig || exit 1 )
( sudo apt install uuid-dev && cd cineform-sdk/ && cmake -DBUILD_TOOLS=OFF . && make CFHDCodecStatic || exit 1 )
sudo apt install qtbase5-dev
sudo chmod 777 /usr/local

View File

@@ -16,7 +16,7 @@ if (-Not $version) {
throw "Cannot get MSVS version"
}
$version = $version.Trim()
echo "::add-path::$installDir\VC\Tools\MSVC\$version\bin\HostX64\x64" # cl
echo "::add-path::$installDir\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin"
echo "::add-path::$installDir\MSBuild\Current\Bin"
echo "$installDir\VC\Tools\MSVC\$version\bin\HostX64\x64" >> ${env:GITHUB_PATH} # cl
echo "$installDir\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin" >> ${env:GITHUB_PATH}
echo "$installDir\MSBuild\Current\Bin" >> ${env:GITHUB_PATH}

View File

@@ -9,7 +9,7 @@ if (!${env:no_cuda}) {
Invoke-WebRequest https://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda_10.2.89_441.22_win10.exe -OutFile cuda_inst.exe
Start-Process -FilePath "cuda_inst.exe" -ArgumentList "-s nvcc_10.2" -Wait -NoNewWindow
Remove-Item cuda_inst.exe
echo "::add-path::C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\bin"
echo "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\bin" >> ${env:GITHUB_PATH}
}
# Install XIMEA
@@ -28,7 +28,7 @@ if (${env:SDK_URL} -and ${env:GITHUB_REF} -eq "refs/heads/ndi-build") {
Start-Process -FilePath "C:\ndi.exe" -ArgumentList "/VERYSILENT"
Sleep 10
$sdk=(dir "C:\Program Files\NewTek" -Filter *SDK -Name)
echo "::add-path::C:\Program Files\NewTek\$sdk\Bin\x64"
echo "C:\Program Files\NewTek\$sdk\Bin\x64" >> ${env:GITHUB_PATH}
#Remove-Item C:\ndi.exe
}

View File

@@ -71,8 +71,8 @@ data/scripts/build_spout64.sh src/SpoutSDK/VS2012/x64/Release
wget --no-verbose https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-full-shared.7z && 7z x ffmpeg-release-full-shared.7z && cp -r ffmpeg-*build-shared/{bin,lib,include} /usr/local && rm -rf ffmpeg-* || exit 1
# Install GPUJPEG
( wget --no-verbose https://github.com/CESNET/GPUJPEG/releases/download/continuous/GPUJPEG.zip && unzip GPUJPEG.zip && cp -r GPUJPEG/* /usr/local )
( wget --no-verbose https://github.com/CESNET/GPUJPEG/releases/download/continuous/GPUJPEG.zip && unzip GPUJPEG.zip && cp -r GPUJPEG/* /usr/local || exit 1 )
# Build CineForm
( git submodule update --init cineform-sdk && cd cineform-sdk && cmake -DBUILD_STATIC=false -DBUILD_TOOLS=false -A x64 && MSBuild.exe CineFormSDK.sln -property:Configuration=Release && cp Release/CFHDCodec.dll /usr/local/bin && cp Release/CFHDCodec.lib /usr/local/lib && cp Common/* /usr/local/include && cp libcineformsdk.pc /usr/local/lib/pkgconfig )
( git submodule update --init cineform-sdk && cd cineform-sdk && cmake -DBUILD_STATIC=false -DBUILD_TOOLS=false -A x64 && MSBuild.exe CineFormSDK.sln -property:Configuration=Release && cp Release/CFHDCodec.dll /usr/local/bin && cp Release/CFHDCodec.lib /usr/local/lib && cp Common/* /usr/local/include && cp libcineformsdk.pc /usr/local/lib/pkgconfig || exit 1 )

View File

@@ -13,5 +13,5 @@ fi
export VERSION TAG
echo "::set-env name=VERSION::$VERSION"
echo "::set-env name=TAG::$TAG"
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "TAG=$TAG" >> $GITHUB_ENV

View File

@@ -5,19 +5,19 @@ TEMP_INST=/tmp/install
CPATH=/usr/local/include:/usr/local/opt/qt/include
LIBRARY_PATH=/usr/local/lib:/usr/local/opt/qt/lib
echo "::set-env name=AJA_DIRECTORY::$AJA_INST"
echo "::set-env name=UG_SKIP_NET_TESTS::1"
echo "::set-env name=CPATH::$CPATH"
echo "::set-env name=LIBRARY_PATH::$LIBRARY_PATH"
echo "AJA_DIRECTORY=$AJA_INST" >> $GITHUB_ENV
echo "UG_SKIP_NET_TESTS=1" >> $GITHUB_ENV
echo "CPATH=$CPATH" >> $GITHUB_ENV
echo "LIBRARY_PATH=$LIBRARY_PATH" >> $GITHUB_ENV
# libcrypto.pc (and other libcrypto files) is not linked to /usr/local/{lib,include} because conflicting with system libcrypto
echo "::set-env name=PKG_CONFIG_PATH::/usr/local/lib/pkgconfig:/usr/local/opt/qt/lib/pkgconfig:/usr/local/opt/openssl/lib/pkgconfig"
echo "::add-path::/usr/local/opt/qt/bin"
echo "PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/opt/qt/lib/pkgconfig:/usr/local/opt/openssl/lib/pkgconfig" >> $GITHUB_ENV
echo "/usr/local/opt/qt/bin" >> $GITHUB_PATH
brew install autoconf automake cppunit libtool pkg-config
brew install ffmpeg portaudio sdl2
brew install imagemagick jack opencv openssl
brew install ossp-uuid # for cineform
( cd cineform-sdk/ && cmake -DBUILD_TOOLS=OFF . && make CFHDCodecStatic )
( cd cineform-sdk/ && cmake -DBUILD_TOOLS=OFF . && make CFHDCodecStatic || exit 1 )
brew install qt
.github/scripts/macOS/install_dylibbundler_v2.sh
@@ -57,10 +57,10 @@ if [ -f /var/tmp/sdks/NDISDK_Apple.pkg ]; then
export DYLIBBUNDLER_FLAGS="${DYLIBBUNDLER_FLAGS:+$DYLIBBUNDLER_FLAGS }-s /Library/NDI/lib/x64"
export LIBRARY_PATH=${LIBRARY_PATH:+"$LIBRARY_PATH:"}/Library/NDI/lib/x64
export MY_DYLD_LIBRARY_PATH="${MY_DYLD_LIBRARY_PATH:+$MY_DYLD_LIBRARY_PATH:}/Library/NDI/lib/x64"
echo "::set-env name=CPATH::$CPATH"
echo "::set-env name=DYLIBBUNDLER_FLAGS::$DYLIBBUNDLER_FLAGS"
echo "::set-env name=LIBRARY_PATH::$LIBRARY_PATH"
echo "::set-env name=MY_DYLD_LIBRARY_PATH::$MY_DYLD_LIBRARY_PATH"
echo "CPATH=$CPATH" >> $GITHUB_ENV
echo "DYLIBBUNDLER_FLAGS=$DYLIBBUNDLER_FLAGS" >> $GITHUB_ENV
echo "LIBRARY_PATH=$LIBRARY_PATH" >> $GITHUB_ENV
echo "MY_DYLD_LIBRARY_PATH=$MY_DYLD_LIBRARY_PATH" >> $GITHUB_ENV
cd $TEMP_INST
fi

View File

@@ -81,19 +81,14 @@ jobs:
uses: actions/cache@v1
with:
path: '/var/tmp/ffmpeg'
key: cache-ffmpeg-8
key: cache-ffmpeg-9
- name: Build FFmpeg
if: steps.cache-ffmpeg.outputs.cache-hit != 'true'
run: .github/scripts/Linux/download_build_ffmpeg.sh
- name: Install FFmpeg
run: .github/scripts/Linux/install_ffmpeg.sh
- name: configure
env:
CC: clang-9
CXX: clang++-9
CPP: clang-cpp-9
LDFLAGS: -static-libstdc++
run: "[ ${{ github.ref }} != refs/heads/ndi-build ] && NDI=-disable-ndi; ./autogen.sh --enable-qt --with-cuda-host-compiler=$CUDA_HOST_COMPILER --enable-plugins --enable-jack-transport=force --with-live555=/usr/local $NDI"
run: "[ ${{ github.ref }} != refs/heads/ndi-build ] && NDI=-disable-ndi; ./autogen.sh --enable-qt --with-cuda-host-compiler=$CUDA_HOST_COMPILER --enable-plugins --with-live555=/usr/local $NDI"
- name: make
run: make -j4
- name: make check
@@ -245,7 +240,7 @@ jobs:
- name: bootsrap MSYS2
run: C:\msys64\usr\bin\bash -cel '$GITHUB_WORKSPACE/.github/scripts/Windows/prepare_msys.sh'
- name: configure
run: C:\msys64\usr\bin\bash -cel '[ ${{ github.ref }} != refs/heads/ndi-build ] && NDI=-disable-ndi; ./autogen.sh --enable-qt $NDI --with-live555=/usr/local'
run: C:\msys64\usr\bin\bash -cel '[ ${{ github.ref }} != refs/heads/ndi-build ] && NDI=-disable-ndi; ./autogen.sh --prefix=/ --bindir=/ --docdir=/doc --enable-qt $NDI --with-live555=/usr/local'
- name: make
run: C:\msys64\usr\bin\bash -cel "make -j4"
- name: make check
@@ -255,11 +250,11 @@ jobs:
C:\msys64\usr\bin\bash -cel '
cp gui/QT/uv-qt.exe bin
rm bin/run_tests.exe
IFS=\"|\"; for exe in bin/*exe; do for n in `data/scripts/get_dll_depends.sh \"$exe\" | tr \"\n\" \"|\"`; do cp \"$n\" bin; done; done
windeployqt bin/uv-qt.exe
cp data/update.ps1 bin
mkdir build
mv bin build/UltraGrid-$VERSION-win64'
export DESTDIR=build/UltraGrid-$VERSION-win64
make install
IFS=\"|\"; for exe in $DESTDIR/*exe; do for n in `data/scripts/get_dll_depends.sh \"$exe\" | tr \"\n\" \"|\"`; do cp \"$n\" $DESTDIR; done; done
windeployqt $DESTDIR/uv-qt.exe
cp data/update.ps1 $DESTDIR'
- name: make dist-check
run: C:\msys64\usr\bin\bash -cel 'PATH=
/usr/bin/make distcheck TARGET=build/UltraGrid-$VERSION-win64/uv.exe GUI_EXE=build/UltraGrid-$VERSION-win64/uv-qt.exe'

View File

@@ -18,7 +18,7 @@ way or extend this document.
## Resources
- [Adding modules HOWTO](ADDING-MODULES.md)
- [Adding modules HOWTO](doc/ADDING-MODULES.md)
- [Doxygen](https://frakira.fi.muni.cz/~xpulec/ultragrid-doxygen/html/)
- [GitHub devel page](https://github.com/CESNET/UltraGrid/wiki/Developer-Documentation)
- [Trello board](https://trello.com/b/PjZW4sas/ultragrid-development) tracking the development
@@ -27,7 +27,7 @@ way or extend this document.
You can either fill an issue at GitHub or contact our development team directly
with the e-mail or use a chat. If you suspect that the issue may not be always
replicable, you can use a script `ultragrid-bugreport-collect.sh` to collect
data about a computer and attach its result. See also [here](REPORTING-BUGS.md).
data about a computer and attach its result. See also [here](doc/REPORTING-BUGS.md).
Especially for various questions about UltraGrid usage you may also use our Matrix chat
[![@ultragrid:matrix.org](https://img.shields.io/badge/Matrix-chat-black)](https://matrix.to/#/!IrTYOLJOmZIoTBiITI:matrix.org?via=matrix.org).

74
MODS
View File

@@ -1,74 +0,0 @@
MODIFICATIONS FILE
------------------
$Revision: 1.1 $
$Date: 2007/11/08 09:48:58 $
Copyright (c) 2001-2004 University of Southern California
Copyright (c) 2003-2004 University of Glasgow
All rights reserved.
This software is distributed under license, see the file COPYRIGHT for full
terms and conditions.
v0.0.1 - Initial version, HDTV receiver
* 14 August 2002
v0.0.2 - Fix builds with --enable-debug
- Update display code
- Update capture code
* 26 August 2002
v0.0.3 - Add "-d <display>" option to select display device
- Add "-t <capture>" option to select capture device, and enable transmit
- Reduce RTCP housekeeping frequency
- Disable UI for now
* 27 August 2002
v0.1.0 - Add "-m <mtu>" option to select transmit MTU
- Add TFRC code
- Display in a window using Xvideo (not cleanly implemented)
- Initial test suite (incomplete)
* 8 October 2002
v0.1.1 - Performance optimizations for Xvideo display device
* 28 November 2002 (demonstrated at SuperComputing 2002)
v0.2.0 - Source code reorganization; add audio code (unused)
* 18 August 2003
v0.2.1 - Cleanup configure script, removing duplicate tests
- Update configure script to explicitly test for sched_setscheduler()
since some platforms (e.g. MacOS X) don't have it.
- Update configure script and video display routines to partially
support the case where X11 is not present.
- Fix -v option
- Rewrite playout buffer code
- Rewrite video display probing
- Removing scatter-read from the RTP code
- Framerate now tunable using "-f <rate>"
* 2 May 2004
v0.2.2 - Check reported loss fraction, and abort if excessive
- Playout buffer now uses a fixed 32ms playout delay, equivalent
to 2 frames at 60fps, instead of decoding frames immediately.
* 10 May 2004
v0.3.0 - Update documentation
- Add initial FireWire/DV support
- Add initial video codec API
- Add initial MacOS X audio driver (contributed to rat by Juraj Sucik)
- Add initial AccessGrid service plugins
- Add initial participant database framework, to eventually allow
multiple participants
* 13 August 2004
v0.3.1 - Fix crash in RTP code if getpwuid() fails (patch contributed to
rat by <Grant.Likely@gdcanada.com>, and adapted for UltraGrid)
- Update AES code code to rijndael-fst-3.0.zip, taken from:
http://www.esat.kuleuven.ac.be/~rijmen/rijndael/
This now passes the official NIST AES test suite (included).
- Add initial TFRC code to RTP library
- Update ALSA code with Steve Smith's ALSA 0.9+/final audio driver
* 26 October 2004

View File

@@ -13,10 +13,9 @@ CXXFLAGS = @CXXFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE
MKDIR_P = mkdir -p
CUDA_FLAGS = @CUDA_FLAGS@ @CUDA_COMPUTE_ARGS@
LDFLAGS = @LDFLAGS@
LIBS += @LIBS@ @JACK_TRANS_LIB@ @MATHLIBS@ -lm -pthread
LIBS += @LIBS@ @MATHLIBS@ -lm -pthread
INC = -Isrc -I$(srcdir) -I$(srcdir)/src -I$(srcdir)/test -Idxt_compress \
@JACK_TRANS_INC@ @SPEEX_INC@ \
@CUDA_INC@ @INC@
@SPEEX_INC@ @CUDA_INC@ @INC@
DECKLINK_PATH = @DECKLINK_PATH@
DYLIBBUNDLER = @DYLIBBUNDLER@
DYLIBBUNDLER_FLAGS += @DYLIBBUNDLER_FLAGS@
@@ -28,13 +27,13 @@ GUI_BUNDLE = gui/QT/uv-qt.app
DXT_GLSL_CFLAGS = @DXT_GLSL_CFLAGS@
CUDA_COMPILER = @CUDA_COMPILER@
SYSTEM = @system@
APPEXT = @APPEXT@
GUI_EXE = @GUI_EXE@
GUI_TARGET = @GUI_TARGET@
REFLECTOR_TARGET = bin/hd-rum-transcode$(EXEEXT)
TEST_TARGET = bin/run_tests$(EXEEXT)
PACKAGE_TARNAME ?= @PACKAGE_TARNAME@
PREFIX = @prefix@
prefix = $(PREFIX)
exec_prefix = @exec_prefix@
@@ -43,14 +42,13 @@ bindir = @bindir@
libdir = @libdir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@/ultragrid
uv_datadir = @datadir@/ultragrid
docdir = @docdir@
mandir = @mandir@
man1dir = @mandir@/man1
srcdir = @srcdir@
VPATH = @srcdir@
DOCS = $(srcdir)/CONTRIBUTING.md $(srcdir)/README.md $(srcdir)/REPORTING-BUGS.md
DOCS = $(srcdir)/CONTRIBUTING.md $(srcdir)/README.md $(wildcard $(srcdir)/doc/*)
# autogenerated headers
GENERATED_HEADERS = @GENERATED_HEADERS@
@@ -464,7 +462,7 @@ dxt_compress/dxt_glsl.h:dxt_compress/compress_vp.glsl \
#cat dxt_compress/rgba_to_yuv422_vp.glsl | sed 's/\(.*\)/ \"\1\\n\"/' >> $@
#echo ";" >> $@
gui/QT/uv-qt$(APPEXT): $(wildcard $(srcdir)/gui/QT/*.cpp $(srcdir)/gui/QT/*.hpp) $(srcdir)/src/shared_mem_frame.cpp $(srcdir)/tools/astat.h
$(GUI_TARGET): $(wildcard $(srcdir)/gui/QT/*.cpp $(srcdir)/gui/QT/*.hpp) $(srcdir)/src/shared_mem_frame.cpp $(srcdir)/tools/astat.h
$(MKDIR_P) $(dir $@)
if test -z "$(QMAKE)"; then echo "Reconfigure with '--enable-qt'"; exit 1; fi
cd gui/QT && $(QMAKE) "DESTDIR+=./" $(srcdir)/../../gui/QT && make -j 4
@@ -667,12 +665,11 @@ install: all
$(INSTALL) -d -m 755 $(DESTDIR)$(libdir)/ultragrid;\
$(INSTALL) -m 755 @MODULES@ $(DESTDIR)$(libdir)/ultragrid;\
fi
$(INSTALL) -d -m 755 $(DESTDIR)$(uv_datadir)
$(INSTALL) -m 755 $(srcdir)/data/ultragrid-bugreport-collect.sh $(DESTDIR)$(uv_datadir)
$(INSTALL) -d -m 755 $(DESTDIR)$(docdir)
$(INSTALL) -m 644 $(DOCS) $(DESTDIR)$(docdir)
$(INSTALL) -m 644 $(srcdir)/COPYRIGHT $(DESTDIR)$(docdir)
$(INSTALL) -m 644 $(srcdir)/CONTRIBUTING.md $(srcdir)/COPYRIGHT $(srcdir)/INSTALL $(srcdir)/NEWS $(srcdir)/README.md $(DESTDIR)$(docdir)
$(CP) $(srcdir)/speex-1.2rc1/COPYING $(DESTDIR)$(docdir)/COPYING.speex
$(INSTALL) -m 755 $(srcdir)/data/ultragrid-bugreport-collect.sh $(DESTDIR)$(docdir)
$(INSTALL) -d -m 755 $(DESTDIR)$(man1dir)
$(INSTALL) -m 644 $(srcdir)/data/uv.1 $(srcdir)/data/hd-rum-transcode.1 $(DESTDIR)$(man1dir)
if [ -n '@DLL_LIBS@' ]; then $(INSTALL) -m 644 @DLL_LIBS@ $(DESTDIR)$(bindir); fi
@@ -681,11 +678,10 @@ uninstall:
$(RM) $(DESTDIR)$(bindir)/uv
$(RM) $(DESTDIR)$(bindir)/hd-rum-transcode
if [ -n "@MODULES@" ]; then for n in @MODULES@; do $(RM) $(DESTDIR)$(libdir)/ultragrid/`basename $$n`; done; fi
$(RM) $(DESTDIR)$(uv_datadir)/ultragrid-bugreport-collect.sh
for n in $(DOCS); do $(RM) $(DESTDIR)$(docdir)$$n; done;
$(RM) $(DESTDIR)$(docdir)COPYRIGHT
$(RM) $(DESTDIR)$(docdir)COPYING.speex
$(RM) $(DESTDIR)$(uv_datadir)ultragrid-bugreport-collect.sh
$(RM) $(DESTDIR)$(docdir)/CONTRIBUTING.md $(DESTDIR)$(docdir)/COPYRIGHT $(DESTDIR)$(docdir)/INSTALL $(DESTDIR)$(docdir)/NEWS $(DESTDIR)$(docdir)/README.md
$(RM) $(DESTDIR)$(docdir)/COPYING.speex
$(RM) $(DESTDIR)$(docdir)/ultragrid-bugreport-collect.sh
if [ -f "$(GUI_TARGET)" ]; then \
$(RM) $(DESTDIR)$(bindir)/`basename $(GUI_TARGET)`;\
$(RM) $(DESTDIR)$(datadir)/applications/uv-qt.desktop;\

82
NEWS
View File

@@ -146,3 +146,85 @@ next
target system has installed CUDA Toolkit.
* format detection for DVS cards
* DVS support for Mac OS X
0.3.1
=====
* Fix crash in RTP code if getpwuid() fails (patch contributed to
rat by <Grant.Likely@gdcanada.com>, and adapted for UltraGrid)
* Update AES code code to rijndael-fst-3.0.zip, taken from:
http://www.esat.kuleuven.ac.be/~rijmen/rijndael/
This now passes the official NIST AES test suite (included).
* Add initial TFRC code to RTP library
* Update ALSA code with Steve Smith's ALSA 0.9+/final audio driver
* 26 October 2004
0.3.0
=====
* Update documentation
* Add initial FireWire/DV support
* Add initial video codec API
* Add initial MacOS X audio driver (contributed to rat by Juraj Sucik)
* Add initial AccessGrid service plugins
* Add initial participant database framework, to eventually allow
multiple participants
* 13 August 2004
0.2.2
=====
* Check reported loss fraction, and abort if excessive
* Playout buffer now uses a fixed 32ms playout delay, equivalent
to 2 frames at 60fps, instead of decoding frames immediately.
* 10 May 2004
v0.2.1
======
* Cleanup configure script, removing duplicate tests
* Update configure script to explicitly test for sched_setscheduler()
since some platforms (e.g. MacOS X) don't have it.
* Update configure script and video display routines to partially
support the case where X11 is not present.
* Fix -v option
* Rewrite playout buffer code
* Rewrite video display probing
* Removing scatter-read from the RTP code
* Framerate now tunable using "-f <rate>"
* 2 May 2004
0.2.0
=====
* Source code reorganization; add audio code (unused)
* 18 August 2003
0.1.1
=====
* Performance optimizations for Xvideo display device
* 28 November 2002 (demonstrated at SuperComputing 2002)
0.1.0
=====
* Add "-m <mtu>" option to select transmit MTU
* Add TFRC code
* Display in a window using Xvideo (not cleanly implemented)
* Initial test suite (incomplete)
* 8 October 2002
0.0.3
=====
* Add "-d <display>" option to select display device
* Add "-t <capture>" option to select capture device, and enable transmit
* Reduce RTCP housekeeping frequency
* Disable UI for now
* 27 August 2002
0.0.2
=====
* Fix builds with --enable-debug
* Update display code
* Update capture code
* 26 August 2002
0.0.1
=====
* Initial version, HDTV receiver
* 14 August 2002

127
README.md
View File

@@ -20,6 +20,15 @@ UltraGrid - A High Definition Collaboratory
[COPYRIGHT](COPYRIGHT) for full terms and conditions.
Contents
--------
- [About UltraGrid](#about-ultragrid)
- [Hardware and Software Requirements](#hardware-and-software-requirements)
* [Required Software Preliminaries](#required-software-preliminaries)
- [Using the UltraGrid System](#using-the-ultragrid-system)
- [Documentation](#documentation)
About UltraGrid
---------------
@@ -63,8 +72,8 @@ About UltraGrid
INSTALL Installation instructions
NEWS Change log and modification history
README.md This file
REPORTING-BUGS.md Recommendations for reporting bugs
bin/ Compiled binaries
doc/ Documentation
src/ Source code for the UltraGrid system
test/ Source code and binaries for test routines
Makefile.in Build script
@@ -150,109 +159,23 @@ Using the UltraGrid System
Using different supported compression schemes, the needed network capacity
can be as low as 10 Megabits per second for a high definition video.
Documentation
-------------
Documentation can be found either _offline_ (apart from this document) and
_online_. The online documentation is more comprehensive and up-to-date,
offline is rather complementary.
Performance Tuning: Network
---------------------------
The **online** documentation is available in our GitHub
[wiki](https://github.com/CESNET/UltraGrid/wiki).
If transmitting *uncompressed video* stream to achieve optimal performance
with high definition video, it may be necessary to tune your system's
network parameters to more aggressive values than used by default.
UltraGrid _built-in_ documentation can be found in [doc](doc) subdirectory,
these documents are available:
A key factor affecting performance is the path MTU. It is unlikely that
the system will sustain gigabit rates with the 1500 octet Ethernet MTU.
If using a gigabit Ethernet you may be able to improve performance by
setting an 8192 octet MTU on the interface, provided all intermediate
hops on the path from sender to receiver support the large MTU.
UltraGrid attempts to increase the UDP receive socket buffer from the
default value (typically 64 kilobytes) to 4/6 megabytes. If successful,
this will make the system more robust to scheduling variations and
better able to accept bursty packet arrivals. UltraGrid will notify
you if it cannot increase buffers. You should follow those instructions
and set your system according to it.
Interrupt processing load on the receiver host may be significant when
running at high rates. Depending on your network interface hardware it
may be possible to coalesce interrupts to reduce this load, although
the settings to do this are highly driver dependent. On FreeBSD, the
use of network device polling may also help performance: see the man
page for "polling" in section 4 of the manual.
In many cases, the performance of your network interface card may be
limited by host bus performance (this is particularly an issue at high
rates, for example when using HD format video).
- [Adding modules](doc/ADDING-MODULES.md) (**developers only**) - information
how to add new UltraGrid modules
- [Performance tuning](doc/PERFORMANCE-TUNING.md) - various tweaks to improve
UltraGrid performance
- [Reporting bugs](doc/REPORTING_BUGS.md) - recommended steps for reporting
bugs
Performance Tuning: Display devices
-----------------------------------
If using a HW grabbing card (eg. DVS) as a display device, the
key factor limiting performance is PCI bus contention. Ensure that
the grabbing card is on a separate PCI bus to the network card --
this typically requires a server class motherboard. On Linux, the
PCI bus topology can be displayed using "lspci -tv", for example:
[root@ormal root]# lspci -tv
-+-[03]---06.0 Xilinx, Inc.: Unknown device d150
+-[01]-+-02.0-[02]--+-04.0 Adaptec 7899P
| | \-04.1 Adaptec 7899P
| \-0e.0 3Com Corporation 3c985 1000BaseSX
\-[00]-+-00.0 ServerWorks CNB20HE
+-00.1 ServerWorks CNB20HE
+-00.2 ServerWorks: Unknown device 0006
+-00.3 ServerWorks: Unknown device 0006
+-04.0 Intel Corporation 82557 [Ethernet Pro 100]
+-0e.0 ATI Technologies Inc Rage XL
+-0f.0 ServerWorks OSB4
\-0f.1 ServerWorks: Unknown device 0211
[root@ormal root]#
showing an DVS card on PCI bus [03] (the card shows as a Xilinx
device) and a gigabit Ethernet card on PCI bus [02] (the 3Com entry).
For software display, you can use SDL or OpenGL display. Both are
accelerated (Mac and Linux) if you have properly configured video
drivers. On Linux, basic operability can be checked with following
commands. If configured properly, both should display driver
properties:
[root@ormal root]# glxinfo
<-- output omitted -->
and for SDL (accelerated through XVideo:
[root@ormal root]# xvinfo
<-- output omitted -->
If you intend to use some of DXT compressions, recommended driver
is OpenGL, which can display it natively. When using other display
drivers, decompression is still done throught OpenGL and then displayed
with requested video driver.
Performance Tuning: Other Factors
---------------------------------
The UltraGrid system will attempt to enable POSIX real-time scheduling
to improve performance. This behaviour is disabled by default now, because
it can occupy the whole system when enabled, but it can be stil enabled by
'--enable-rt' configure option. If you see the message:
WARNING: Unable to set real-time scheduling
when starting the application, this means that the operating system did
not permit it to enable real-time scheduling. The application will run,
but with reduced performance. The most likely reason for failure to set
realtime scheduling is that the application has insufficient privilege:
it should either be run by root, or be made setuid root. A similar
message:
WARNING: System does not support real-time scheduling
indicates that your operating system does not support POSIX real-time
scheduling. The application will still run, but performance may be less
than desired.
You can find more operating system tweaks at this page:
https://github.com/CESNET/UltraGrid/wiki/OS-Setup-UltraGrid
- * -

View File

@@ -132,9 +132,9 @@ if expr "$host_os" : ".*darwin.*" > /dev/null; then
system=MacOSX
AC_DEFINE([HAVE_MACOSX], [1], [This is Mac X OS])
APPEXT=.app
AC_SUBST(APPEXT)
elif expr "$host_os" : ".*mingw32.*" > /dev/null || expr "$host_os" : ".*msys.*" > /dev/null; then
system=Windows
APPEXT=.exe
AC_DEFINE([WIN32], [1], [This is an Windows OS])
else
system=Linux
@@ -2290,10 +2290,10 @@ fi
# -------------------------------------------------------------------------------------------------
gpujpeg_to_dxt=no
AC_ARG_ENABLE(gpujpeg_to_dxt,
[ --disable-jpeg-to-dxt disable GPUJPEG DXT transcoder (default is auto)]
[ --disable-jpeg-to-dxt disable GPUJPEG DXT transcoder (default is disable)]
[ Requires: CUDA libgpujpeg],
[gpujpeg_to_dxt_req=$enableval],
[gpujpeg_to_dxt_req=$build_default])
[gpujpeg_to_dxt_req=no])
if test $gpujpeg_to_dxt_req != no -a $FOUND_CUDA = yes -a \
"$found_gpujpeg" = yes
@@ -2302,7 +2302,7 @@ then
DEFINE_CUDA_DXT
gpujpeg_to_dxt=yes
GPUJPEG_TO_DXT_INC=" $CUDA_INC"
GPUJPEG_TO_DXT_LIB="$CUDA_DXT_COMMON_LIB $CUDA_COMMON_LIB $CUDA_LIB $JPEG_LIB"
GPUJPEG_TO_DXT_LIB="$CUDA_DXT_COMMON_LIB $CUDA_COMMON_LIB $CUDA_LIB $GPUJPEG_LIB"
GPUJPEG_TO_DXT_OBJ="src/video_decompress/gpujpeg_to_dxt.o $CUDA_COMMON_OBJ $CUDA_DXT_COMMON_OBJ"
ADD_MODULE("vdecompress_gpujpeg_to_dxt", $GPUJPEG_TO_DXT_OBJ, "$GPUJPEG_TO_DXT_LIB")
AC_DEFINE([HAVE_GPUJPEG_TO_DXT], [1], [Build with GPUJPEG DXT transcode support])
@@ -2444,35 +2444,21 @@ jack_trans=no
jack=no
AC_ARG_ENABLE(jack-transport,
[ --enable-jack-transport[=force] enable JACK transport (default is auto; disabled in modular build, can be forced)]
[ --enable-jack-transport[=force] enable JACK transport (default is auto)]
[ Requires: jack],
[jack_trans_req=$enableval],
[jack_trans_req=$build_default])
if test $jack_trans_req = yes -a $build_libraries = yes
then
AC_MSG_ERROR([JACK transport is currently incompatible with modular build]);
fi
AC_CHECK_HEADER(jack/jack.h, FOUND_JACK_H=yes, FOUND_JACK_H=no)
AC_CHECK_LIB(jack, jack_client_new, [FOUND_JACK_L=yes]
[JACK_LIB=-ljack], FOUND_JACK_L=no)
if test $FOUND_JACK_L = no; then
# Windows
AC_CHECK_LIB(libjack64, jack_client_new, [FOUND_JACK_L=yes]
[JACK_LIB=-llibjack64], FOUND_JACK_L=no)
fi
if test $jack_trans_req != no -a $FOUND_JACK_H = yes -a $FOUND_JACK_L = yes -a \( $build_libraries = no -o $jack_trans_req = force \)
if test $jack_trans_req != no -a $FOUND_JACK_H = yes
then
JACK_TRANS_OBJ="src/audio/jack.o"
JACK_TRANS_LIB="$JACK_LIB"
AC_DEFINE([HAVE_JACK_TRANS], [1], [Build with JACK transport support])
jack_trans=yes
fi
AC_SUBST(JACK_TRANS_OBJ)
AC_SUBST(JACK_TRANS_LIB)
AC_SUBST(JACK_TRANS_INC)
# sound system
AC_ARG_ENABLE(jack,
@@ -2481,14 +2467,14 @@ AC_ARG_ENABLE(jack,
[jack_req=$enableval],
[jack_req=$build_default])
if test $jack_req != no -a $FOUND_JACK_H = yes -a $FOUND_JACK_L = yes
if test $jack_req != no -a $FOUND_JACK_H = yes
then
JACK_CAP_OBJ="src/audio/capture/jack.o"
JACK_PLAY_OBJ="src/audio/playback/jack.o"
AC_DEFINE([HAVE_JACK], [1], [Build with JACK support])
jack=yes
ADD_MODULE("acap_jack", "$JACK_CAP_OBJ", "$JACK_LIB")
ADD_MODULE("aplay_jack", "$JACK_PLAY_OBJ", "$JACK_LIB")
ADD_MODULE("acap_jack", "$JACK_CAP_OBJ", "")
ADD_MODULE("aplay_jack", "$JACK_PLAY_OBJ", "")
fi
if test $jack = yes -a $speex = no

View File

@@ -44,9 +44,6 @@ while read -r x; do
continue
fi
NAME=$(echo "$x" | awk '{ print $1 }')
if [ "$NAME" = libjack.so.0 ]; then # JACK is currently handled in AppRun
continue
fi
EXCLUDE_LIST="$EXCLUDE_LIST $NAME"
done < excludelist
for n in $EXCLUDE_LIST; do

View File

@@ -2,40 +2,10 @@
set -u
get_loader() {
LOADERS='/lib64/ld-linux-*so* /lib/ld-linux-*so* /lib*/ld-linux-*so*'
for n in $LOADERS; do
for m in `ls $n`; do
if [ -x $m ]; then
echo $m
return
fi
done
done
}
set_ld_preload() {
if [ ! -f $DIR/lib/ultragrid/ultragrid_aplay_jack.so ]; then
return
fi
local LOADER=$(get_loader)
if [ ! -x "$LOADER" ]; then
return
fi
S_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
LD_LIBRARY_PATH=
JACK_LIB=$(LD_TRACE_LOADED_OBJECTS=1 $LOADER $DIR/lib/ultragrid/ultragrid_aplay_jack.so | grep libjack | grep -v 'not found' | awk '{print $3}')
LD_LIBRARY_PATH=$S_LD_LIBRARY_PATH
if [ -n "$JACK_LIB" ]; then
export LD_PRELOAD=$JACK_LIB${LD_PRELOAD:+" $LD_PRELOAD"}
fi
}
DIR=`dirname $0`
export LD_LIBRARY_PATH=$DIR/lib${LD_LIBRARY_PATH:+":$LD_LIBRARY_PATH"}
# there is an issue with running_from_path() which evaluates this executable
# as being system-installed
#export PATH=$DIR/bin:$PATH
set_ld_preload
exec $DIR/bin/uv "$@"

111
doc/PERFORMANCE-TUNING.md Normal file
View File

@@ -0,0 +1,111 @@
Performance Tuning
==================
Network
-------
If transmitting *uncompressed video* stream to achieve optimal performance
with high definition video, it may be necessary to tune your system's
network parameters to more aggressive values than used by default.
A key factor affecting performance is the path MTU. It is unlikely that
the system will sustain gigabit rates with the 1500 octet Ethernet MTU.
If using a gigabit Ethernet you may be able to improve performance by
setting an 8192 octet MTU on the interface, provided all intermediate
hops on the path from sender to receiver support the large MTU.
UltraGrid attempts to increase the UDP receive socket buffer from the
default value (typically 64 kilobytes) to 4/6 megabytes. If successful,
this will make the system more robust to scheduling variations and
better able to accept bursty packet arrivals. UltraGrid will notify
you if it cannot increase buffers. You should follow those instructions
and set your system according to it.
Interrupt processing load on the receiver host may be significant when
running at high rates. Depending on your network interface hardware it
may be possible to coalesce interrupts to reduce this load, although
the settings to do this are highly driver dependent. On FreeBSD, the
use of network device polling may also help performance: see the man
page for "polling" in section 4 of the manual.
In many cases, the performance of your network interface card may be
limited by host bus performance (this is particularly an issue at high
rates, for example when using HD format video).
Display devices
---------------
If using a HW grabbing card (eg. DVS) as a display device, the
key factor limiting performance is PCI bus contention. Ensure that
the grabbing card is on a separate PCI bus to the network card --
this typically requires a server class motherboard. On Linux, the
PCI bus topology can be displayed using "lspci -tv", for example:
[root@ormal root]# lspci -tv
-+-[03]---06.0 Xilinx, Inc.: Unknown device d150
+-[01]-+-02.0-[02]--+-04.0 Adaptec 7899P
| | \-04.1 Adaptec 7899P
| \-0e.0 3Com Corporation 3c985 1000BaseSX
\-[00]-+-00.0 ServerWorks CNB20HE
+-00.1 ServerWorks CNB20HE
+-00.2 ServerWorks: Unknown device 0006
+-00.3 ServerWorks: Unknown device 0006
+-04.0 Intel Corporation 82557 [Ethernet Pro 100]
+-0e.0 ATI Technologies Inc Rage XL
+-0f.0 ServerWorks OSB4
\-0f.1 ServerWorks: Unknown device 0211
[root@ormal root]#
showing an DVS card on PCI bus [03] (the card shows as a Xilinx
device) and a gigabit Ethernet card on PCI bus [02] (the 3Com entry).
For software display, you can use SDL or OpenGL display. Both are
accelerated (Mac and Linux) if you have properly configured video
drivers. On Linux, basic operability can be checked with following
commands. If configured properly, both should display driver
properties:
[root@ormal root]# glxinfo
<-- output omitted -->
and for SDL (accelerated through XVideo:
[root@ormal root]# xvinfo
<-- output omitted -->
If you intend to use some of DXT compressions, recommended driver
is OpenGL, which can display it natively. When using other display
drivers, decompression is still done throught OpenGL and then displayed
with requested video driver.
Other Factors
-------------
**Note:** This is left only as a legacy behavior - currently UltraGrid
is intended to run without _real-time_ priority (although still being
able to compiled with it). This may not be recommended in a general case,
however.
The UltraGrid system will attempt to enable POSIX real-time scheduling
to improve performance. This behaviour is disabled by default now, because
it can occupy the whole system when enabled, but it can be stil enabled by
'--enable-rt' configure option. If you see the message:
WARNING: Unable to set real-time scheduling
when starting the application, this means that the operating system did
not permit it to enable real-time scheduling. The application will run,
but with reduced performance. The most likely reason for failure to set
realtime scheduling is that the application has insufficient privilege:
it should either be run by root, or be made setuid root. A similar
message:
WARNING: System does not support real-time scheduling
indicates that your operating system does not support POSIX real-time
scheduling. The application will still run, but performance may be less
than desired.
You can find more operating system tweaks at this page:
https://github.com/CESNET/UltraGrid/wiki/OS-Setup-UltraGrid

View File

@@ -1,35 +1,26 @@
/**
* @file audio/capture/jack.c
* @author Martin Pulec <pulec@cesnet.cz>
*/
/*
* FILE: audio/capture/jack.c
* AUTHORS: Martin Benes <martinbenesh@gmail.com>
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
* Petr Holub <hopet@ics.muni.cz>
* Milos Liska <xliska@fi.muni.cz>
* Jiri Matela <matela@ics.muni.cz>
* Dalibor Matura <255899@mail.muni.cz>
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
*
* Copyright (c) 2005-2010 CESNET z.s.p.o.
* Copyright (c) 2012-2020 CESNET z.s.p.o.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
*
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
*
* This product includes software developed by CESNET z.s.p.o.
*
* 4. Neither the name of CESNET nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
*
* 3. Neither the name of CESNET nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
@@ -42,8 +33,6 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*/
#ifdef HAVE_CONFIG_H
@@ -51,6 +40,10 @@
#include "config_unix.h"
#include "config_win32.h"
#endif
#define MAX_PORTS 64
#define MOD_NAME "[JACK capture] "
#include "debug.h"
#include "host.h"
@@ -65,13 +58,12 @@
#include <stdio.h>
#include <string.h>
#define MAX_PORTS 64
#define MOD_NAME "[JACK capture] "
static int jack_samplerate_changed_callback(jack_nframes_t nframes, void *arg);
static int jack_process_callback(jack_nframes_t nframes, void *arg);
struct state_jack_capture {
struct libjack_connection *libjack;
struct audio_frame frame;
jack_client_t *client;
jack_port_t *input_ports[MAX_PORTS];
@@ -103,7 +95,7 @@ static int jack_process_callback(jack_nframes_t nframes, void *arg)
}
for (i = 0; i < s->frame.ch_count; ++i) {
jack_default_audio_sample_t *in = jack_port_get_buffer(s->input_ports[i], nframes);
jack_default_audio_sample_t *in = s->libjack->port_get_buffer(s->input_ports[i], nframes);
mux_channel(s->tmp, (char *) in, sizeof(int32_t), channel_size, s->frame.ch_count, i, 1.0);
}
@@ -160,6 +152,11 @@ static void * audio_cap_jack_init(const char *cfg)
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to allocate memory.\n");
return NULL;
}
s->libjack = open_libjack();
if (s->libjack == NULL) {
free(s);
return NULL;
}
char *dup = strdup(cfg);
assert(dup != NULL);
@@ -191,13 +188,13 @@ static void * audio_cap_jack_init(const char *cfg)
free(dup);
dup = NULL;
s->client = jack_client_open(client_name, JackNullOption, &status);
s->client = s->libjack->client_open(client_name, JackNullOption, &status);
if(status & JackFailure) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Opening JACK client failed.\n");
goto error;
}
ports = jack_get_ports(s->client, source_name, NULL, JackPortIsOutput);
ports = s->libjack->get_ports(s->client, source_name, NULL, JackPortIsOutput);
if(ports == NULL) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to output ports matching \"%s\".\n", source_name);
goto release_client;
@@ -218,7 +215,7 @@ static void * audio_cap_jack_init(const char *cfg)
if (audio_capture_sample_rate) {
log_msg(LOG_LEVEL_WARNING, "[JACK capture] Ignoring user specified sample rate!\n");
}
s->frame.sample_rate = jack_get_sample_rate (s->client);
s->frame.sample_rate = s->libjack->get_sample_rate (s->client);
s->frame.max_size = s->frame.ch_count * s->frame.bps * s->frame.sample_rate;
s->frame.data = malloc(s->frame.max_size);
@@ -226,17 +223,17 @@ static void * audio_cap_jack_init(const char *cfg)
s->data = ring_buffer_init(s->frame.max_size);
if(jack_set_sample_rate_callback(s->client, jack_samplerate_changed_callback, (void *) s)) {
if (s->libjack->set_sample_rate_callback(s->client, jack_samplerate_changed_callback, (void *) s)) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Registring callback problem.\n");
goto release_client;
}
if(jack_set_process_callback(s->client, jack_process_callback, (void *) s) != 0) {
if (s->libjack->set_process_callback(s->client, jack_process_callback, (void *) s) != 0) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Process callback registration problem.\n");
goto release_client;
}
if(jack_activate(s->client)) {
if (s->libjack->activate(s->client)) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot activate client.\n");
goto release_client;
}
@@ -247,9 +244,9 @@ static void * audio_cap_jack_init(const char *cfg)
for(port = 0; port < s->frame.ch_count; port++) {
snprintf(name, 32, "capture_%02u", port);
s->input_ports[port] = jack_port_register(s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
s->input_ports[port] = s->libjack->port_register(s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
/* attach ports */
if(jack_connect(s->client, ports[port], jack_port_name(s->input_ports[port]))) {
if (s->libjack->connect(s->client, ports[port], s->libjack->port_name(s->input_ports[port]))) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot connect input ports.\n");
}
}
@@ -262,8 +259,9 @@ static void * audio_cap_jack_init(const char *cfg)
return s;
release_client:
jack_client_close(s->client);
s->libjack->client_close(s->client);
error:
close_libjack(s->libjack);
free(dup);
free(s);
return NULL;
@@ -286,10 +284,11 @@ static void audio_cap_jack_done(void *state)
{
struct state_jack_capture *s = (struct state_jack_capture *) state;
jack_client_close(s->client);
s->libjack->client_close(s->client);
free(s->tmp);
ring_buffer_destroy(s->data);
free(s->frame.data);
close_libjack(s->libjack);
free(s);
}

View File

@@ -3,7 +3,7 @@
* @author Martin Pulec <pulec@cesnet.cz>
*/
/*
* Copyright (c) 2011-2019 CESNET, z. s. p. o.
* Copyright (c) 2011-2020 CESNET, z. s. p. o.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,11 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @todo
* It looks like there is no jack_stop()?
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -49,6 +54,7 @@
#include "audio/audio.h"
#include "audio/jack.h"
#include "jack_common.h"
#include "pthread.h"
#include "rtp/rtp.h"
#include "rtp/pbuf.h"
@@ -57,8 +63,11 @@
#define BUFF_ELEM (1<<16)
#define BUFF_SIZE (BUFF_ELEM * sizeof(float))
#define MAX_PORTS 8
#define MOD_NAME "[JACK trans.] "
struct state_jack {
struct libjack_connection *libjack;
unsigned int sender:1,
receiver:1;
@@ -102,7 +111,7 @@ int jack_process_callback(jack_nframes_t nframes, void *arg) {
int to_end = BUFF_SIZE - s->play_buffer_start;
jack_default_audio_sample_t *out =
jack_port_get_buffer (s->output_port[i], nframes);
s->libjack->port_get_buffer (s->output_port[i], nframes);
if(to_end > send_b) {
memcpy (out, s->play_buffer[i] + s->play_buffer_start,
send_b);
@@ -119,7 +128,7 @@ int jack_process_callback(jack_nframes_t nframes, void *arg) {
for(i = 0; i < s->record.ch_count; ++i) {
int j;
jack_default_audio_sample_t *in =
jack_port_get_buffer (s->input_port[i], nframes);
s->libjack->port_get_buffer (s->input_port[i], nframes);
for(j = 0; j < (int) nframes; ++j) {
*(int *)(void *)(s->rec_buffer + ((s->rec_buffer_end + (j * s->record.ch_count + i) * sizeof(int32_t)) % BUFF_SIZE)) =
in[j] * INT_MAX;
@@ -146,13 +155,13 @@ void reconfigure_send_ch_count(struct state_jack *s, int ch_count)
s->out_channel_count = s->out_channel_count_req = ch_count;
if ((ports = jack_get_ports (s->client, s->out_port_pattern, NULL, JackPortIsInput)) == NULL) {
fprintf(stderr, "Cannot find any ports matching pattern '%s'\n", s->out_port_pattern);
if ((ports = s->libjack->get_ports (s->client, s->out_port_pattern, NULL, JackPortIsInput)) == NULL) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot find any ports matching pattern '%s'\n", s->out_port_pattern);
s->out_channel_count = 0;
return;
}
for (i = 0; i < s->record.ch_count; ++i) {
jack_disconnect(s->client, jack_port_name (s->output_port[i]), ports[i]);
s->libjack->disconnect(s->client, s->libjack->port_name (s->output_port[i]), ports[i]);
free(s->play_buffer[i]);
}
@@ -160,21 +169,20 @@ void reconfigure_send_ch_count(struct state_jack *s, int ch_count)
while (ports[i]) ++i;
if(i < s->out_channel_count) {
fprintf(stderr, "Not enought output ports found matching pattern '%s': "
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Not enought output ports found matching pattern '%s': "
"%d requested, %d found\n", s->out_port_pattern, s->record.ch_count, i);
fprintf(stderr, "Reducing port count to %d\n", i);
log_msg(LOG_LEVEL_WARNING, MOD_NAME "Reducing port count to %d\n", i);
s->out_channel_count = i;
}
for(i = 0; i < s->out_channel_count; ++i) {
fprintf(stderr, "%s\n\n\n", ports[i]);
if (jack_connect (s->client, jack_port_name (s->output_port[i]), ports[i])) {
fprintf (stderr, "cannot connect output ports\n");
if (s->libjack->connect (s->client, s->libjack->port_name (s->output_port[i]), ports[i])) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot connect output ports: %s\n", ports[i]);
}
s->play_buffer[i] = malloc(BUFF_SIZE);
}
fprintf(stderr, "[JACK] Sending %d output audio streams (ports).\n", s->out_channel_count);
log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Sending %d output audio streams (ports).\n", s->out_channel_count);
free (ports);
}
@@ -234,21 +242,21 @@ static int attach_input_ports(struct state_jack *s)
{
int i = 0;
const char **ports;
if ((ports = jack_get_ports (s->client, s->in_port_pattern, NULL, JackPortIsOutput)) == NULL) {
fprintf(stderr, "Cannot find any ports matching pattern '%s'\n", s->in_port_pattern);
if ((ports = s->libjack->get_ports (s->client, s->in_port_pattern, NULL, JackPortIsOutput)) == NULL) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot find any ports matching pattern '%s'\n", s->in_port_pattern);
return FALSE;
}
while (ports[i]) ++i;
if(i < s->record.ch_count) {
fprintf(stderr, "Not enought input ports found matching pattern '%s': "
"%d requested, %d found\n", s->in_port_pattern, s->record.ch_count, i);
fprintf(stderr, "Reducing port count to %d\n", i);
s->record.ch_count = i;
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Not enought input ports found matching pattern '%s': "
"%d requested, %d found\n", s->in_port_pattern, s->record.ch_count, i);
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Reducing port count to %d\n", i);
s->record.ch_count = i;
}
for(i = 0; i < s->in_ch_count; ++i) {
if (jack_connect (s->client, ports[i], jack_port_name (s->input_port[i]))) {
if (s->libjack->connect (s->client, ports[i], s->libjack->port_name (s->input_port[i]))) {
fprintf (stderr, "cannot connect input ports\n");
}
}
@@ -262,6 +270,12 @@ void * jack_start(const char *cfg)
struct state_jack *s;
s = (struct state_jack *) malloc(sizeof(struct state_jack));
assert (s != NULL);
s->libjack = open_libjack();
if (s->libjack == NULL) {
free(s);
return NULL;
}
s->in_port_pattern = NULL;
s->out_port_pattern = NULL;
@@ -276,25 +290,23 @@ void * jack_start(const char *cfg)
int ret = settings_init(s, cfg_copy);
free(cfg_copy);
if (ret != 0) {
fprintf(stderr, "Setting JACK failed. Check configuration ('-j' option).\n");
free(s);
return NULL;
}
if(!s->sender && !s->receiver) {
free(s);
return NULL;
}
s->client = jack_client_open(CLIENT_NAME, JackNullOption, NULL);
if(jack_set_process_callback(s->client, jack_process_callback, (void *) s) != 0) {
fprintf(stderr, "[jack] Callback initialization problem.\n");
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Setting JACK failed. Check configuration ('-j' option).\n");
goto error;
}
if(jack_set_sample_rate_callback(s->client,
if(!s->sender && !s->receiver) {
goto error;
}
s->client = s->libjack->client_open(CLIENT_NAME, JackNullOption, NULL);
if(s->libjack->set_process_callback(s->client, jack_process_callback, (void *) s) != 0) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Callback initialization problem.\n");
goto error;
}
if(s->libjack->set_sample_rate_callback(s->client,
jack_samplerate_changed_callback, (void *) s)) {
fprintf(stderr, "[jack] Callback initialization problem.\n");
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Sample rate callback initialization problem.\n");
goto error;
}
@@ -306,7 +318,7 @@ void * jack_start(const char *cfg)
for(i = 0; i < MAX_PORTS; ++i) {
snprintf(name, 30, "out_%02u", i);
s->output_port[i] = jack_port_register (s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
s->output_port[i] = s->libjack->port_register (s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
s->out_channel_count = s->out_channel_count_req = 0;
@@ -318,16 +330,16 @@ void * jack_start(const char *cfg)
for(i = 0; i < s->in_ch_count; ++i) {
snprintf(name, 30, "in_%02u", i);
s->input_port[i] = jack_port_register (s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
s->input_port[i] = s->libjack->port_register (s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
}
s->record.sample_rate = jack_get_sample_rate (s->client);
s->record.sample_rate = s->libjack->get_sample_rate (s->client);
s->record.bps = sizeof(int32_t);
s->record.ch_count = s->in_ch_count;
s->rec_buffer = s->record.data = (void *) malloc(BUFF_SIZE);
}
if (jack_activate (s->client)) {
if (s->libjack->activate (s->client)) {
fprintf (stderr, "cannot activate client");
goto error;
}
@@ -338,7 +350,9 @@ void * jack_start(const char *cfg)
}
return s;
error:
error:
close_libjack(s->libjack);
free(s);
return NULL;
}

View File

@@ -3,7 +3,7 @@
* @author Martin Pulec <pulec@cesnet.cz>
*/
/*
* Copyright (c) 2012-2019 CESNET z.s.p.o.
* Copyright (c) 2012-2020 CESNET z.s.p.o.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,11 @@
#include "config_win32.h"
#endif
#define DEFAULT_AUDIO_BUF_LEN_MS 50
#define MAX_LEN_MS 1000
#define MAX_PORTS 64
#define MOD_NAME "[JACK playback] "
#include "audio/audio.h"
#include "audio/audio_playback.h"
#include "audio/utils.h"
@@ -56,13 +61,9 @@
#include <stdio.h>
#include <string.h>
#define DEFAULT_AUDIO_BUF_LEN_MS 50
#define MAX_LEN_MS 1000
#define MAX_PORTS 64
#define MOD_NAME "[JACK playback] "
struct state_jack_playback {
struct libjack_connection *libjack;
char *jack_ports_pattern;
int jack_sample_rate;
jack_client_t *client;
@@ -116,7 +117,7 @@ static int jack_process_callback(jack_nframes_t nframes, void *arg)
for (int i = 0; i < s->desc.ch_count; ++i) {
jack_default_audio_sample_t *out =
jack_port_get_buffer (s->output_port[i], nframes_available);
s->libjack->port_get_buffer (s->output_port[i], nframes_available);
assert(out != NULL);
demux_channel((char *) out, s->tmp, sizeof(float), len, s->desc.ch_count, i);
}
@@ -172,6 +173,12 @@ static void * audio_play_jack_init(const char *cfg)
return NULL;
}
s->libjack = open_libjack();
if (s->libjack == NULL) {
free(s);
return NULL;
}
char *dup = strdup(cfg);
assert(dup != NULL);
char *tmp = dup, *item, *save_ptr;
@@ -203,28 +210,28 @@ static void * audio_play_jack_init(const char *cfg)
s->jack_ports_pattern = strdup(source_name);
s->client = jack_client_open(client_name, JackNullOption, &status);
s->client = s->libjack->client_open(client_name, JackNullOption, &status);
if(status & JackFailure) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Opening JACK client failed.\n");
goto error;
}
if(jack_set_sample_rate_callback(s->client, jack_samplerate_changed_callback, (void *) s)) {
if (s->libjack->set_sample_rate_callback(s->client, jack_samplerate_changed_callback, (void *) s)) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Registering callback problem.\n");
goto release_client;
}
if(jack_set_process_callback(s->client, jack_process_callback, (void *) s) != 0) {
if (s->libjack->set_process_callback(s->client, jack_process_callback, (void *) s) != 0) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Process callback registration problem.\n");
goto release_client;
}
s->jack_sample_rate = jack_get_sample_rate (s->client);
s->jack_sample_rate = s->libjack->get_sample_rate (s->client);
log_msg(LOG_LEVEL_INFO, "JACK sample rate: %d\n", s->jack_sample_rate);
ports = jack_get_ports(s->client, s->jack_ports_pattern, NULL, JackPortIsInput);
ports = s->libjack->get_ports(s->client, s->jack_ports_pattern, NULL, JackPortIsInput);
if(ports == NULL) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to input ports matching %s.\n", s->jack_ports_pattern);
goto release_client;
@@ -240,7 +247,7 @@ static void * audio_play_jack_init(const char *cfg)
for(i = 0; i < MAX_PORTS; ++i) {
snprintf(name, 30, "playback_%02u", i);
s->output_port[i] = jack_port_register (s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
s->output_port[i] = s->libjack->port_register (s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
}
@@ -248,8 +255,9 @@ static void * audio_play_jack_init(const char *cfg)
return s;
release_client:
jack_client_close(s->client);
s->libjack->client_close(s->client);
error:
close_libjack(s->libjack);
free(dup);
free(s);
return NULL;
@@ -296,9 +304,9 @@ static int audio_play_jack_reconfigure(void *state, struct audio_desc desc)
assert(desc.bps == 4 && desc.sample_rate == s->jack_sample_rate && desc.codec == AC_PCM);
jack_deactivate(s->client);
s->libjack->deactivate(s->client);
ports = jack_get_ports(s->client, s->jack_ports_pattern, NULL, JackPortIsInput);
ports = s->libjack->get_ports(s->client, s->jack_ports_pattern, NULL, JackPortIsInput);
if(ports == NULL) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to input ports matching %s.\n", s->jack_ports_pattern);
return FALSE;
@@ -335,7 +343,7 @@ static int audio_play_jack_reconfigure(void *state, struct audio_desc desc)
/* for all channels previously connected */
for(i = 0; i < desc.ch_count; ++i) {
jack_disconnect(s->client, jack_port_name (s->output_port[i]), ports[i]);
s->libjack->disconnect(s->client, s->libjack->port_name (s->output_port[i]), ports[i]);
log_msg(LOG_LEVEL_INFO, MOD_NAME "Port %d: %s\n", i, ports[i]);
}
free(s->tmp);
@@ -348,13 +356,13 @@ static int audio_play_jack_reconfigure(void *state, struct audio_desc desc)
s->tmp = malloc(s->max_channel_len);
s->converted = malloc(desc.ch_count * s->max_channel_len);
if(jack_activate(s->client)) {
if (s->libjack->activate(s->client)) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot activate client.\n");
return FALSE;
}
for(i = 0; i < desc.ch_count; ++i) {
if (jack_connect (s->client, jack_port_name (s->output_port[i]), ports[i])) {
if (s->libjack->connect (s->client, s->libjack->port_name (s->output_port[i]), ports[i])) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot connect output port: %d.\n", i);
return FALSE;
}
@@ -383,7 +391,7 @@ static void audio_play_jack_done(void *state)
{
struct state_jack_playback *s = (struct state_jack_playback *) state;
jack_client_close(s->client);
s->libjack->client_close(s->client);
free(s->tmp);
free(s->converted);
free(s->jack_ports_pattern);
@@ -391,6 +399,8 @@ static void audio_play_jack_done(void *state)
s->buffer_fns->destroy(s->data);
}
close_libjack(s->libjack);
free(s);
}

View File

@@ -39,11 +39,117 @@
#ifndef JACK_COMMON_H
#define JACK_COMMON_H
#include <stdio.h>
#ifndef _WIN32
#include <dlfcn.h>
#endif
#include <jack/jack.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "lib_common.h"
#include "types.h"
typedef int (*jack_activate_t)(jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;
typedef int (*jack_client_close_t)(jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;
typedef jack_client_t *(*jack_client_open_t)(const char *client_name,
jack_options_t options,
jack_status_t *status, ...) JACK_OPTIONAL_WEAK_EXPORT;
typedef int (*jack_connect_t)(jack_client_t *client,
const char *source_port,
const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT;
typedef int (*jack_deactivate_t)(jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;
typedef int (*jack_disconnect_t)(jack_client_t *client,
const char *source_port,
const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT;
typedef void (*jack_free_t)(void* ptr) JACK_OPTIONAL_WEAK_EXPORT;
typedef const char **(*jack_get_ports_t)(jack_client_t *client,
const char *port_name_pattern,
const char *type_name_pattern,
unsigned long flags) JACK_OPTIONAL_WEAK_EXPORT;
typedef jack_nframes_t (*jack_get_sample_rate_t)(jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT;
typedef void * (*jack_port_get_buffer_t)(jack_port_t *port, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT;
typedef const char * (*jack_port_name_t)(const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT;
typedef jack_port_t * (*jack_port_register_t)(jack_client_t *client,
const char *port_name,
const char *port_type,
unsigned long flags,
unsigned long buffer_size) JACK_OPTIONAL_WEAK_EXPORT;
typedef int (*jack_set_process_callback_t)(jack_client_t *client,
JackProcessCallback process_callback,
void *arg) JACK_OPTIONAL_WEAK_EXPORT;
typedef int (*jack_set_sample_rate_callback_t)(jack_client_t *client,
JackSampleRateCallback srate_callback,
void *arg) JACK_OPTIONAL_WEAK_EXPORT;
struct libjack_connection {
LIB_HANDLE libjack; ///< lib connection
jack_activate_t activate;
jack_client_close_t client_close;
jack_client_open_t client_open;
jack_connect_t connect;
jack_deactivate_t deactivate;
jack_disconnect_t disconnect;
jack_free_t free;
jack_get_ports_t get_ports;
jack_get_sample_rate_t get_sample_rate;
jack_port_get_buffer_t port_get_buffer;
jack_port_name_t port_name;
jack_port_register_t port_register;
jack_set_process_callback_t set_process_callback;
jack_set_sample_rate_callback_t set_sample_rate_callback;
};
static void close_libjack(struct libjack_connection *s)
{
if (s == NULL) {
return;
}
dlclose(s->libjack);
free(s);
}
#define JACK_DLSYM(sym) s->sym = (void *) dlsym(s->libjack, "jack_" #sym); if (s->sym == NULL) { log_msg(LOG_LEVEL_ERROR, "JACK symbol %s not found: %s\n", "jack_" #sym, dlerror()); close_libjack(s); return NULL; }
static struct libjack_connection *open_libjack(void)
{
struct libjack_connection *s = calloc(1, sizeof(struct libjack_connection));
const char *shlib =
#ifdef _WIN32
"C:/Windows/libjack64.dll";
#elif defined (__APPLE__)
"libjack.dylib";
#elif defined (__linux__)
"libjack.so";
#else
"";
#endif
s->libjack = dlopen(shlib, RTLD_NOW);
if (s->libjack == NULL) {
log_msg(LOG_LEVEL_ERROR, "JACK library \"%s\" opening failed: %s\n", shlib, dlerror());
free(s);
return NULL;
}
JACK_DLSYM(activate);
JACK_DLSYM(client_close)
JACK_DLSYM(client_open)
JACK_DLSYM(connect);
JACK_DLSYM(deactivate);
JACK_DLSYM(disconnect);
JACK_DLSYM(free)
JACK_DLSYM(get_ports)
JACK_DLSYM(get_sample_rate);
JACK_DLSYM(set_sample_rate_callback);
JACK_DLSYM(port_get_buffer);
JACK_DLSYM(port_name);
JACK_DLSYM(port_register);
JACK_DLSYM(set_process_callback);
return s;
}
static inline struct device_info *audio_jack_probe(const char *client_name,
unsigned long port_flags,
int *count)
@@ -52,29 +158,33 @@ static inline struct device_info *audio_jack_probe(const char *client_name,
jack_status_t status;
char *last_name = NULL;
int i;
int channel_count;
const char **ports;
int port_count = 0;
struct device_info *available_devices = NULL;
*count = 0;
client = jack_client_open(client_name, JackNullOption, &status);
if(status & JackFailure) {
fprintf(stderr, "[JACK playback] Opening JACK client failed.\n");
struct libjack_connection *libjack = open_libjack();
if (!libjack) {
return NULL;
}
ports = jack_get_ports(client, NULL, NULL, port_flags);
*count = 0;
client = libjack->client_open(client_name, JackNullOption, &status);
if(status & JackFailure) {
log_msg(LOG_LEVEL_ERROR, "Opening JACK client failed.\n");
close_libjack(libjack);
return NULL;
}
ports = libjack->get_ports(client, NULL, NULL, port_flags);
if(ports == NULL) {
fprintf(stderr, "[JACK playback] Unable to enumerate ports.\n");
log_msg(LOG_LEVEL_ERROR, "Unable to enumerate JACK ports.\n");
close_libjack(libjack);
return NULL;
}
for(port_count = 0; ports[port_count] != NULL; port_count++);
available_devices = calloc(port_count, sizeof(struct device_info));
struct device_info *available_devices = port_count > 0 ? calloc(port_count, sizeof(struct device_info)) : NULL;
channel_count = 0;
int channel_count = 0;
for(i = 0; ports[i] != NULL; i++) {
char *item = strdup(ports[i]);
assert(item != NULL);
@@ -104,8 +214,9 @@ static inline struct device_info *audio_jack_probe(const char *client_name,
(*count)++;
}
free(last_name);
jack_free(ports);
jack_client_close(client);
libjack->free(ports);
libjack->client_close(client);
close_libjack(libjack);
return available_devices;
}

View File

@@ -38,8 +38,36 @@
#ifndef LIB_COMMON_H
#define LIB_COMMON_H
#include "config_unix.h"
#include "config_win32.h"
#include "host.h" // UNIQUE_NAME
#ifdef _WIN32
#define LIB_HANDLE HMODULE
#define dlopen(name, flags) LoadLibraryA(name)
#define dlsym GetProcAddress
#define dlclose FreeLibrary
#if !defined __cplusplus && !defined thread_local
#define thread_local _Thread_local
#endif
static char *dlerror(void) ATTRIBUTE(unused);
static char *dlerror(void) {
thread_local static char buf[1024] = "(unknown)";
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // flags
NULL, // lpsource
GetLastError(), // message id
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // languageid
buf, // output buffer
sizeof buf, // size of msgbuf, bytes
NULL); // va_list of arguments
return buf;
}
#else // ! defined _WIN32
#define LIB_HANDLE void *
#endif // defined _WIN32
/** @brief This macro causes that this module will be statically linked with UltraGrid. */
#define MK_STATIC(A) A, NULL
#define MK_STATIC_REF(A) &A, NULL

View File

@@ -1624,6 +1624,29 @@ static void yuv444p_to_uyvy(char * __restrict dst_buffer, AVFrame * __restrict i
}
}
static void yuv444p16le_to_uyvy(char * __restrict dst_buffer, AVFrame * __restrict in_frame,
int width, int height, int pitch, int * __restrict rgb_shift)
{
UNUSED(rgb_shift);
for(int y = 0; y < height; ++y) {
unsigned char *src_y = (unsigned char *) in_frame->data[0] + in_frame->linesize[0] * y + 1;
unsigned char *src_cb = (unsigned char *) in_frame->data[1] + in_frame->linesize[1] * y + 1;
unsigned char *src_cr = (unsigned char *) in_frame->data[2] + in_frame->linesize[2] * y + 1;
unsigned char *dst = (unsigned char *) dst_buffer + pitch * y;
OPTIMIZED_FOR (int x = 0; x < width / 2; ++x) {
*dst++ = (*src_cb + *(src_cb + 2)) / 2;
src_cb += 4;
*dst++ = *src_y;
src_y += 2;
*dst++ = (*src_cr + *(src_cr + 2)) / 2;
src_cr += 4;
*dst++ = *src_y;
src_y += 2;
}
}
}
static void yuv444p_to_v210(char * __restrict dst_buffer, AVFrame * __restrict in_frame,
int width, int height, int pitch, int * __restrict rgb_shift)
{
@@ -1667,7 +1690,6 @@ static void yuv444p_to_v210(char * __restrict dst_buffer, AVFrame * __restrict i
}
}
/**
* Changes pixel format from planar YUV 422 to packed RGB/A.
* Color space is assumed ITU-T Rec. 609. YUV is expected to be full scale (aka in JPEG).
@@ -2314,19 +2336,19 @@ static void p010le_to_uyvy(char * __restrict dst_buffer, AVFrame * __restrict in
OPTIMIZED_FOR (int x = 0; x < width / 2; ++x) {
uint8_t tmp;
// U
tmp = *src_cbcr++ >> 2;
tmp = *src_cbcr++ >> 8;
*dst1++ = tmp;
*dst2++ = tmp;
// Y
*dst1++ = *src_y1++ >> 2;
*dst2++ = *src_y2++ >> 2;
*dst1++ = *src_y1++ >> 8;
*dst2++ = *src_y2++ >> 8;
// V
tmp = *src_cbcr++ >> 2;
tmp = *src_cbcr++ >> 8;
*dst1++ = tmp;
*dst2++ = tmp;
// Y
*dst1++ = *src_y1++ >> 2;
*dst2++ = *src_y2++ >> 2;
*dst1++ = *src_y1++ >> 8;
*dst2++ = *src_y2++ >> 8;
}
}
}
@@ -2376,8 +2398,8 @@ const struct uv_to_av_conversion *get_uv_to_av_conversions() {
{ R10k, AV_PIX_FMT_YUV444P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p10le },
{ R10k, AV_PIX_FMT_YUV444P12LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p12le },
{ R10k, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p16le },
{ R12L, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p10le },
{ R12L, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p12le },
{ R12L, AV_PIX_FMT_YUV444P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p10le },
{ R12L, AV_PIX_FMT_YUV444P12LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p12le },
{ R12L, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p16le },
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 15, 100) // FFMPEG commit c2869b4640f
{ v210, AV_PIX_FMT_P010LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_p010le },
@@ -2443,12 +2465,11 @@ const struct av_to_uv_conversion *get_av_to_uv_conversions() {
{AV_PIX_FMT_YUV422P10LE, RGB, yuv422p10le_to_rgb24, false},
{AV_PIX_FMT_YUV422P10LE, RGBA, yuv422p10le_to_rgb32, false},
{AV_PIX_FMT_YUV444P10LE, v210, yuv444p10le_to_v210, true},
{AV_PIX_FMT_YUV444P16LE, v210, yuv444p16le_to_v210, true},
{AV_PIX_FMT_YUV444P10LE, UYVY, yuv444p10le_to_uyvy, false},
{AV_PIX_FMT_YUV444P10LE, R10k, yuv444p10le_to_r10k, false},
{AV_PIX_FMT_YUV444P10LE, RGB, yuv444p10le_to_rgb24, false},
{AV_PIX_FMT_YUV444P10LE, RGBA, yuv444p10le_to_rgb32, false},
{AV_PIX_FMT_YUV444P16LE, R12L, yuv444p10le_to_r12l, false},
{AV_PIX_FMT_YUV444P10LE, R12L, yuv444p10le_to_r12l, false},
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 15, 100) // FFMPEG commit c2869b4640f
{AV_PIX_FMT_P010LE, v210, p010le_to_v210, true},
{AV_PIX_FMT_P010LE, UYVY, p010le_to_uyvy, true},
@@ -2484,13 +2505,15 @@ const struct av_to_uv_conversion *get_av_to_uv_conversions() {
// 8-bit YUV (NV12)
{AV_PIX_FMT_NV12, UYVY, nv12_to_uyvy, true},
{AV_PIX_FMT_NV12, RGB, nv12_to_rgb24, false},
{AV_PIX_FMT_NV12, RGB, nv12_to_rgb32, false},
{AV_PIX_FMT_NV12, RGBA, nv12_to_rgb32, false},
// 12-bit YUV
{AV_PIX_FMT_YUV444P12LE, R10k, yuv444p12le_to_r10k, false},
{AV_PIX_FMT_YUV444P16LE, R12L, yuv444p12le_to_r12l, false},
{AV_PIX_FMT_YUV444P12LE, R12L, yuv444p12le_to_r12l, false},
// 16-bit YUV
{AV_PIX_FMT_YUV444P16LE, R10k, yuv444p16le_to_r10k, false},
{AV_PIX_FMT_YUV444P16LE, R12L, yuv444p16le_to_r12l, false},
{AV_PIX_FMT_YUV444P16LE, UYVY, yuv444p16le_to_uyvy, false},
{AV_PIX_FMT_YUV444P16LE, v210, yuv444p16le_to_v210, false},
// RGB
{AV_PIX_FMT_GBRP, RGB, gbrp_to_rgb, true},
{AV_PIX_FMT_GBRP, RGBA, gbrp_to_rgba, true},
@@ -2539,14 +2562,17 @@ av_to_uv_convert_p get_av_to_uv_conversion(int av_codec, codec_t uv_codec) {
*/
struct SwsContext *getSwsContext(unsigned int SrcW, unsigned int SrcH, enum AVPixelFormat SrcFormat, unsigned int DstW, unsigned int DstH, enum AVPixelFormat DstFormat, int64_t Flags) {
struct SwsContext *Context = sws_alloc_context();
// 0 = limited range, 1 = full range
int SrcRange = 1;
int DstRange = 1;
if (!Context) {
return 0;
}
const struct AVPixFmtDescriptor *SrcFormatDesc = av_pix_fmt_desc_get(SrcFormat);
const struct AVPixFmtDescriptor *DstFormatDesc = av_pix_fmt_desc_get(DstFormat);
// 0 = limited range, 1 = full range
int SrcRange = SrcFormatDesc != NULL && (SrcFormatDesc->flags & AV_PIX_FMT_FLAG_RGB) != 0 ? 1 : 0;
int DstRange = DstFormatDesc != NULL && (DstFormatDesc->flags & AV_PIX_FMT_FLAG_RGB) != 0 ? 1 : 0;
av_opt_set_int(Context, "sws_flags", Flags, 0);
av_opt_set_int(Context, "srcw", SrcW, 0);
av_opt_set_int(Context, "srch", SrcH, 0);

View File

@@ -292,7 +292,7 @@ static void crash_signal_handler(int sig)
*ptr++ = PACKAGE_BUGREPORT[i];
}
*ptr++ = '.'; *ptr++ = '\n';
const char message3[] = "You may find some tips how to report bugs in file REPORTING-BUGS distributed with ";
const char message3[] = "You may find some tips how to report bugs in file doc/reporting_bugs.md distributed with ";
for (size_t i = 0; i < sizeof message3 - 1; ++i) {
*ptr++ = message3[i];
}

View File

@@ -526,6 +526,7 @@ int
pbuf_decode(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time,
decode_frame_t decode_func, void *data)
{
using namespace std::chrono_literals;
/* Find the first complete frame that has reached it's playout */
/* time, and decode it into the framebuffer. Mark the frame as */
/* decoded, but otherwise leave it in the playout buffer. */
@@ -545,6 +546,9 @@ pbuf_decode(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_p
curr->decoded = 1;
return ret;
} else {
if (curr_time > curr->playout_time + 1s) {
curr->completed = true;
}
debug_msg
("Unable to decode frame due to missing data (RTP TS=%u)\n",
curr->rtp_timestamp);

View File

@@ -64,24 +64,15 @@
#define MOD_NAME "[XIMEA] "
#define MICROSEC_IN_SEC 1000000.0
#ifdef WIN32
#define LIB_HANDLE HINSTANCE
#define dlopen(name, flags) LoadLibraryA(name)
#define dlsym GetProcAddress
#define dlclose FreeLibrary
#else
#define LIB_HANDLE void *
#endif
struct ximea_functions {
XIAPI XI_RETURN __cdecl (*xiGetNumberDevices)(OUT PDWORD pNumberDevices);
XIAPI XI_RETURN __cdecl (*xiGetDeviceInfoString)(IN DWORD DevId, const char* prm, char* value, DWORD value_size);
XIAPI XI_RETURN __cdecl (*xiOpenDevice)(IN DWORD DevId, OUT PHANDLE hDevice);
XIAPI XI_RETURN __cdecl (*xiSetParamInt)(IN HANDLE hDevice, const char* prm, const int val);
XIAPI XI_RETURN __cdecl (*xiStartAcquisition)(IN HANDLE hDevice);
XIAPI XI_RETURN __cdecl (*xiGetImage)(IN HANDLE hDevice, IN DWORD timeout, OUT LPXI_IMG img);
XIAPI XI_RETURN __cdecl (*xiStopAcquisition)(IN HANDLE hDevice);
XIAPI XI_RETURN __cdecl (*xiCloseDevice)(IN HANDLE hDevice);
XI_RETURN __cdecl (*xiGetNumberDevices)(OUT PDWORD pNumberDevices);
XI_RETURN __cdecl (*xiGetDeviceInfoString)(IN DWORD DevId, const char* prm, char* value, DWORD value_size);
XI_RETURN __cdecl (*xiOpenDevice)(IN DWORD DevId, OUT PHANDLE hDevice);
XI_RETURN __cdecl (*xiSetParamInt)(IN HANDLE hDevice, const char* prm, const int val);
XI_RETURN __cdecl (*xiStartAcquisition)(IN HANDLE hDevice);
XI_RETURN __cdecl (*xiGetImage)(IN HANDLE hDevice, IN DWORD timeout, OUT LPXI_IMG img);
XI_RETURN __cdecl (*xiStopAcquisition)(IN HANDLE hDevice);
XI_RETURN __cdecl (*xiCloseDevice)(IN HANDLE hDevice);
LIB_HANDLE handle;
};
@@ -95,9 +86,9 @@ struct state_vidcap_ximea {
};
#define GET_SYMBOL(sym) do {\
f->sym = dlsym(f->handle, #sym);\
f->sym = (void *) dlsym(f->handle, #sym);\
if (f->sym == NULL) {\
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to find symbol %s\n", #sym);\
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to find symbol %s: %s\n", #sym, dlerror());\
return false;\
}\
} while(0)

View File

@@ -143,6 +143,9 @@ static void deconfigure(struct state_libavcodec_decompress *s)
#ifdef HAVE_SWSCALE
s->sws.ctx = NULL;
sws_freeContext(s->sws.ctx);
if (s->sws.frame) {
av_freep(s->sws.frame->data);
}
av_frame_free(&s->sws.frame);
#endif // defined HAVE_SWSCALE
}
@@ -423,6 +426,13 @@ static int libavcodec_decompress_reconfigure(void *state, struct video_desc desc
}
static bool has_conversion(enum AVPixelFormat pix_fmt, codec_t *ug_pix_fmt) {
{
codec_t mapped_pix_fmt = get_av_to_ug_pixfmt(pix_fmt);
if (mapped_pix_fmt != VIDEO_CODEC_NONE) {
*ug_pix_fmt = mapped_pix_fmt;
return true;
}
}
for (const struct av_to_uv_conversion *c = get_av_to_uv_conversions(); c->uv_codec != VIDEO_CODEC_NONE; c++) {
if (c->av_codec != pix_fmt) { // this conversion is not valid
@@ -497,8 +507,21 @@ static enum AVPixelFormat get_format_callback(struct AVCodecContext *s __attribu
}
#endif
// directly mapped UG codecs
for (const enum AVPixelFormat *fmt_it = fmt; *fmt_it != AV_PIX_FMT_NONE; fmt_it++) {
codec_t mapped_pix_fmt = get_av_to_ug_pixfmt(*fmt_it);
if (mapped_pix_fmt != VIDEO_CODEC_NONE) {
if (state->out_codec == VIDEO_CODEC_NONE) { // just probing internal format
state->internal_codec = mapped_pix_fmt;
return AV_PIX_FMT_NONE;
}
if (state->out_codec == mapped_pix_fmt) {
state->internal_codec = mapped_pix_fmt;
return *fmt_it;
}
}
}
bool use_native[] = { true, false }; // try native first
for (const bool *use_native_it = use_native; use_native_it !=
use_native + sizeof use_native / sizeof use_native[0]; ++use_native_it) {
for (const enum AVPixelFormat *fmt_it = fmt; *fmt_it != AV_PIX_FMT_NONE; fmt_it++) {
@@ -542,40 +565,56 @@ static enum AVPixelFormat get_format_callback(struct AVCodecContext *s __attribu
}
#ifdef HAVE_SWSCALE
static bool lavd_sws_convert_reconfigure(struct state_libavcodec_decompress_sws *sws, enum AVPixelFormat sws_in_codec,
enum AVPixelFormat sws_out_codec, int width, int height)
{
if (sws->width == width && sws->height == height && sws->in_codec == sws_in_codec && sws->ctx != NULL) {
return true;
}
log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Using swscale to convert from %s to %s.\n",
av_get_pix_fmt_name(sws_in_codec), av_get_pix_fmt_name(sws_out_codec));
sws_freeContext(sws->ctx);
if (sws->frame) {
av_freep(sws->frame->data);
}
av_frame_free(&sws->frame);
sws->ctx = getSwsContext(width, height, sws_in_codec,
width, height, sws_out_codec,
SWS_POINT);
if(!sws->ctx){
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to init sws context.\n");
return false;
}
sws->frame = av_frame_alloc();
if (!sws->frame) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Could not allocate sws frame\n");
return false;
}
sws->frame->width = width;
sws->frame->height = height;
sws->frame->format = sws_out_codec;
int ret = av_image_alloc(sws->frame->data, sws->frame->linesize,
sws->frame->width, sws->frame->height,
sws_out_codec, 32);
if (ret < 0) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Could not allocate raw picture buffer for sws\n");
return false;
}
sws->width = width;
sws->height = height;
sws->in_codec = sws_in_codec;
sws->out_codec = sws_out_codec;
return true;
}
static bool lavd_sws_convert(struct state_libavcodec_decompress_sws *sws, enum AVPixelFormat sws_in_codec,
enum AVPixelFormat sws_out_codec, int width, int height, AVFrame *in_frame)
{
if (sws->width != width || sws->height != height|| sws->in_codec != sws_in_codec || sws->ctx == NULL) {
log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Attempting to use swscale to convert.\n");
sws_freeContext(sws->ctx);
av_frame_free(&sws->frame);
sws->ctx = getSwsContext(width, height, sws_in_codec,
width, height, sws_out_codec,
SWS_POINT);
if(!sws->ctx){
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to init sws context.\n");
return false;
}
sws->frame = av_frame_alloc();
if (!sws->frame) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Could not allocate sws frame\n");
return false;
}
sws->frame->width = width;
sws->frame->height = height;
sws->frame->format = sws_out_codec;
int ret = av_image_alloc(sws->frame->data, sws->frame->linesize,
sws->frame->width, sws->frame->height,
sws_out_codec, 32);
if (ret < 0) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Could not allocate raw picture buffer for sws\n");
return false;
}
sws->width = width;
sws->height = height;
sws->in_codec = sws_in_codec;
sws->out_codec = sws_out_codec;
if (!lavd_sws_convert_reconfigure(sws, sws_in_codec, sws_out_codec, width, height)) {
return false;
}
sws_scale(sws->ctx,
(const uint8_t * const *) in_frame->data,
in_frame->linesize,
@@ -584,6 +623,36 @@ static bool lavd_sws_convert(struct state_libavcodec_decompress_sws *sws, enum A
sws->frame->data,
sws->frame->linesize);
return true;
}
/// @brief Converts directly to out_buffer (instead to sws->frame). This is used for directly mapped
/// UltraGrid pixel formats that can be decoded directly to framebuffer.
static bool lavd_sws_convert_to_buffer(struct state_libavcodec_decompress_sws *sws, enum AVPixelFormat sws_in_codec,
enum AVPixelFormat sws_out_codec, int width, int height, AVFrame *in_frame, char *out_buffer)
{
if (!lavd_sws_convert_reconfigure(sws, sws_in_codec, sws_out_codec, width, height)) {
return false;
}
struct AVFrame *out = av_frame_alloc();
codec_t ug_out_pixfmt = get_av_to_ug_pixfmt(sws_out_codec);
if (codec_is_planar(ug_out_pixfmt)) {
buf_get_planes(width, height, ug_out_pixfmt, out_buffer, (char **) out->data);
buf_get_linesizes(width, ug_out_pixfmt, out->linesize);
} else {
out->data[0] = (unsigned char *) out_buffer;
out->linesize[0] = vc_get_linesize(width, ug_out_pixfmt);
}
sws_scale(sws->ctx,
(const uint8_t * const *) in_frame->data,
in_frame->linesize,
0,
in_frame->height,
out->data,
out->linesize);
av_frame_free(&out);
return true;
}
#endif
@@ -608,6 +677,15 @@ static int change_pixfmt(AVFrame *frame, unsigned char *dst, int av_codec, codec
int pitch, int rgb_shift[static restrict 3], struct state_libavcodec_decompress_sws *sws) {
av_to_uv_convert_p convert = NULL;
if (get_av_to_ug_pixfmt(av_codec) == out_codec) {
if (!codec_is_planar(out_codec)) {
memcpy(dst, frame->data[0], vc_get_datalen(width, height, out_codec));
return TRUE;
}
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Planar pixfmts not support here, please report a bug!\n");
return FALSE;
}
for (const struct av_to_uv_conversion *c = get_av_to_uv_conversions(); c->uv_codec != VIDEO_CODEC_NONE; c++) {
if (c->av_codec == av_codec && c->uv_codec == out_codec) {
convert = c->convert;
@@ -620,8 +698,14 @@ static int change_pixfmt(AVFrame *frame, unsigned char *dst, int av_codec, codec
}
#ifdef HAVE_SWSCALE
if (get_ug_to_av_pixfmt(out_codec) != AV_PIX_FMT_NONE) {
lavd_sws_convert_to_buffer(sws, av_codec, get_ug_to_av_pixfmt(out_codec), width, height, frame, (char *) dst);
return TRUE;
}
// else try to find swscale
enum AVPixelFormat sws_out_codec = 0;
bool native[2] = { true, false };
for (int n = 0; n < 2; n++) {
for (const struct av_to_uv_conversion *c = get_av_to_uv_conversions(); c->uv_codec != VIDEO_CODEC_NONE; c++) {

View File

@@ -207,7 +207,7 @@ static int display_ndi_putf(void *state, struct video_frame *frame, int flag)
NDI_video_frame.p_data = (uint8_t *) frame->tiles[0].data;
NDI_video_frame.frame_rate_N = get_framerate_n(frame->fps);
NDI_video_frame.frame_rate_D = get_framerate_d(frame->fps);
NDI_video_frame.frame_format_type = frame->interlacing = PROGRESSIVE ? NDIlib_frame_format_type_progressive : NDIlib_frame_format_type_interleaved;
NDI_video_frame.frame_format_type = frame->interlacing == PROGRESSIVE ? NDIlib_frame_format_type_progressive : NDIlib_frame_format_type_interleaved;
NDI_video_frame.timecode = NDIlib_send_timecode_synthesize;
NDIlib_send_send_video_v2(s->pNDI_send, &NDI_video_frame);

View File

@@ -68,8 +68,8 @@
#include <SDL2/SDL.h>
#include <cstdint>
#include <condition_variable>
#include <cstdint>
#include <list>
#include <mutex>
#include <queue>
@@ -377,7 +377,8 @@ static int display_sdl2_reconfigure(void *state, struct video_desc desc)
return 1;
}
static const unordered_map<codec_t, uint32_t, hash<int>> pf_mapping = {
struct ug_to_sdl_pf { codec_t first; uint32_t second; };
static const ug_to_sdl_pf pf_mapping[] = {
{ I420, SDL_PIXELFORMAT_IYUV },
{ UYVY, SDL_PIXELFORMAT_UYVY },
{ YUYV, SDL_PIXELFORMAT_YUY2 },
@@ -390,19 +391,42 @@ static const unordered_map<codec_t, uint32_t, hash<int>> pf_mapping = {
#endif
};
static bool create_texture(struct state_sdl2 *s, struct video_desc desc) {
uint32_t format;
auto it = pf_mapping.find(desc.color_spec);
if (it == pf_mapping.end()) {
abort();
static uint32_t get_ug_to_sdl_format(codec_t ug_codec) {
if (ug_codec == R10k) {
return SDL_PIXELFORMAT_ARGB2101010;
}
format = it->second;
const auto *it = find_if(begin(pf_mapping), end(pf_mapping), [ug_codec](const ug_to_sdl_pf &u) { return u.first == ug_codec; });
if (it == end(pf_mapping)) {
LOG(LOG_LEVEL_ERROR) << MOD_NAME << "Wrong codec: " << get_codec_name(ug_codec) << "\n";
return SDL_PIXELFORMAT_UNKNOWN;
}
return it->second;
}
ADD_TO_PARAM("sdl2-r10k",
"* sdl2-r10k\n"
" Enable 10-bit RGB support for SDL2 (EXPERIMENTAL)\n");
static auto get_supported_pfs() {
vector<codec_t> codecs;
codecs.reserve(sizeof pf_mapping / sizeof pf_mapping[0]);
for (auto item : pf_mapping) {
codecs.push_back(item.first);
}
if (get_commandline_param("sdl2-r10k") != nullptr) {
codecs.push_back(R10k);
}
return codecs;
}
static bool create_texture(struct state_sdl2 *s, struct video_desc desc) {
if (s->texture) {
SDL_DestroyTexture(s->texture);
}
s->texture = SDL_CreateTexture(s->renderer, format, SDL_TEXTUREACCESS_STREAMING, desc.width, desc.height);
s->texture = SDL_CreateTexture(s->renderer, get_ug_to_sdl_format(desc.color_spec), SDL_TEXTUREACCESS_STREAMING, desc.width, desc.height);
if (!s->texture) {
log_msg(LOG_LEVEL_ERROR, "[SDL] Unable to create texture: %s\n", SDL_GetError());
return false;
@@ -693,18 +717,14 @@ static int display_sdl2_putf(void *state, struct video_frame *frame, int nonbloc
static int display_sdl2_get_property(void *state, int property, void *val, size_t *len)
{
UNUSED(state);
codec_t codecs[pf_mapping.size()];
int i = 0;
for (auto item : pf_mapping) {
codecs[i++] = item.first;
}
auto codecs = get_supported_pfs();
size_t codecs_len = codecs.size() * sizeof(codec_t);
switch (property) {
case DISPLAY_PROPERTY_CODECS:
if (sizeof(codecs) <= *len) {
memcpy(val, codecs, sizeof(codecs));
*len = sizeof(codecs);
if (codecs_len <= *len) {
memcpy(val, codecs.data(), codecs_len);
*len = codecs_len;
} else {
return FALSE;
}

View File

@@ -456,3 +456,15 @@ void buf_get_planes(int width, int height, codec_t color_spec, char *data, char
}
}
void buf_get_linesizes(int width, codec_t color_spec, int *linesize)
{
int sub[8];
codec_get_planes_subsampling(color_spec, sub);
for (int i = 0; i < 4; ++i) {
if (sub[2 * i] == 0) {
break;
}
linesize[i] = (width + sub[2 * i] - 1) / sub[2 * i];
}
}

View File

@@ -206,6 +206,7 @@ unsigned int vf_get_data_len(struct video_frame *f);
* Works with planar pixel formats only.
*/
void buf_get_planes(int width, int height, codec_t color_spec, char *data, char **planes);
void buf_get_linesizes(int width, codec_t color_spec, int *linesize);
/** @name Video Flags
* @deprecated use rather video_frame or video_desc members

View File

@@ -51,22 +51,22 @@ ff_codec_conversions_test::tearDown()
#define TIMER(t) struct timeval t{}; gettimeofday(&(t), nullptr)
void
ff_codec_conversions_test::test_yuv444p16le_from_to_r10k()
ff_codec_conversions_test::test_yuv444pXXle_from_to_r10k()
{
using namespace std::string_literals;
constexpr int width = 1920;
constexpr int height = 1080;
constexpr int width = 320;
constexpr int height = 240;
vector <unsigned char> rgba_buf(width * height * 4);
/// @todo Use 10-bit natively
auto test_pattern = [&] {
auto test_pattern = [&](AVPixelFormat avfmt) {
vector <unsigned char> r10k_buf(width * height * 4);
copy(rgba_buf.begin(), rgba_buf.end(), r10k_buf.begin());
toR10k(r10k_buf.data(), width, height);
AVFrame frame;
frame.format = AV_PIX_FMT_YUV444P16LE;
frame.format = avfmt;
frame.width = width;
frame.height = height;
@@ -112,36 +112,38 @@ ff_codec_conversions_test::test_yuv444p16le_from_to_r10k()
CPPUNIT_ASSERT_MESSAGE("Maximal allowed difference 1, found "s + to_string(max_diff), max_diff <= 1);
};
int i = 0;
for_each(rgba_buf.begin(), rgba_buf.end(), [&](unsigned char & c) { c = (i++ / 4) % 0x100; });
test_pattern();
for (auto f : { AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV444P16LE }) {
int i = 0;
for_each(rgba_buf.begin(), rgba_buf.end(), [&](unsigned char & c) { c = (i++ / 4) % 0x100; });
test_pattern(f);
array<unsigned char, 4> pattern{ 0xFFU, 0, 0, 0xFFU };
for_each(rgba_buf.begin(), rgba_buf.end(), [&](unsigned char & c) { c = pattern[i++ % 4]; });
test_pattern();
array<unsigned char, 4> pattern{ 0xFFU, 0, 0, 0xFFU };
for_each(rgba_buf.begin(), rgba_buf.end(), [&](unsigned char & c) { c = pattern[i++ % 4]; });
test_pattern(f);
default_random_engine rand_gen;
for_each(rgba_buf.begin(), rgba_buf.end(), [&](unsigned char & c) { c = rand_gen() % 0x100; });
test_pattern();
default_random_engine rand_gen;
for_each(rgba_buf.begin(), rgba_buf.end(), [&](unsigned char & c) { c = rand_gen() % 0x100; });
test_pattern(f);
}
}
void
ff_codec_conversions_test::test_yuv444p16le_from_to_r12l()
ff_codec_conversions_test::test_yuv444pXXle_from_to_r12l()
{
using namespace std::string_literals;
constexpr int width = 1920;
constexpr int height = 1080;
constexpr int width = 320;
constexpr int height = 240;
vector <unsigned char> rgb_buf(width * height * 3);
/// @todo Use 12-bit natively
auto test_pattern = [&] {
auto test_pattern = [&](AVPixelFormat avfmt) {
vector <unsigned char> r12l_buf(vc_get_datalen(width, height, R12L));
decoder_t rgb_to_r12l = get_decoder_from_to(RGB, R12L, true);
rgb_to_r12l(r12l_buf.data(), rgb_buf.data(), vc_get_datalen(width, height, R12L), 0, 8, 16);
AVFrame frame;
frame.format = AV_PIX_FMT_YUV444P16LE;
frame.format = avfmt;
frame.width = width;
frame.height = height;
@@ -186,17 +188,19 @@ ff_codec_conversions_test::test_yuv444p16le_from_to_r12l()
CPPUNIT_ASSERT_MESSAGE("Maximal allowed difference 1, found "s + to_string(max_diff), max_diff <= 1);
};
int i = 0;
array<unsigned char, 3> pattern{ 0xFFU, 0, 0 };
for_each(rgb_buf.begin(), rgb_buf.end(), [&](unsigned char & c) { c = pattern[i++ % 3]; });
test_pattern();
for (auto f : { AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV444P16LE }) {
int i = 0;
array<unsigned char, 3> pattern{ 0xFFU, 0, 0 };
for_each(rgb_buf.begin(), rgb_buf.end(), [&](unsigned char & c) { c = pattern[i++ % 3]; });
test_pattern(f);
for_each(rgb_buf.begin(), rgb_buf.end(), [&](unsigned char & c) { c = (i++ / 3) % 0x100; });
test_pattern();
for_each(rgb_buf.begin(), rgb_buf.end(), [&](unsigned char & c) { c = (i++ / 3) % 0x100; });
test_pattern(f);
default_random_engine rand_gen;
for_each(rgb_buf.begin(), rgb_buf.end(), [&](unsigned char & c) { c = rand_gen() % 0x100; });
test_pattern();
default_random_engine rand_gen;
for_each(rgb_buf.begin(), rgb_buf.end(), [&](unsigned char & c) { c = rand_gen() % 0x100; });
test_pattern(f);
}
}
#endif // defined HAVE_CPPUNIT && HAVE_LAVC

View File

@@ -10,8 +10,8 @@
class ff_codec_conversions_test : public CPPUNIT_NS::TestFixture
{
CPPUNIT_TEST_SUITE( ff_codec_conversions_test );
CPPUNIT_TEST( test_yuv444p16le_from_to_r10k );
CPPUNIT_TEST( test_yuv444p16le_from_to_r12l );
CPPUNIT_TEST( test_yuv444pXXle_from_to_r10k );
CPPUNIT_TEST( test_yuv444pXXle_from_to_r12l );
CPPUNIT_TEST_SUITE_END();
public:
@@ -20,8 +20,8 @@ public:
void setUp();
void tearDown();
void test_yuv444p16le_from_to_r10k();
void test_yuv444p16le_from_to_r12l();
void test_yuv444pXXle_from_to_r10k();
void test_yuv444pXXle_from_to_r12l();
};
#endif // defined HAVE_LAVC