diff --git a/enable_decoders b/enable_decoders index 7bc2b8f..cbc1ca2 100644 --- a/enable_decoders +++ b/enable_decoders @@ -35,6 +35,7 @@ libcelt # celt, opus libcodec2 # codec2 libdav1d # av1 libgsm # libgsm +libopenh264 # openh264_dlopen libopenjpeg # openjpeg libopus # opus libschroedinger # schroedinger diff --git a/enable_encoders b/enable_encoders index 4a6b3d5..96311fc 100644 --- a/enable_encoders +++ b/enable_encoders @@ -28,6 +28,7 @@ libaom_av1 # libaom libcodec2 # codec2 libgsm # libgsm libmp3lame # lame +libopenh264 # openh264_dlopen libopenjpeg # openjpeg libopus # opus librav1e # rav1e diff --git a/ffmpeg-dlopen-openh264.patch b/ffmpeg-dlopen-openh264.patch new file mode 100644 index 0000000..7b7cc22 --- /dev/null +++ b/ffmpeg-dlopen-openh264.patch @@ -0,0 +1,311 @@ +From 23c6bb2850b82c473e67df111333479805b0ba4b Mon Sep 17 00:00:00 2001 +From: Neal Gompa +Date: Tue, 15 Feb 2022 10:29:05 -0500 +Subject: [PATCH] avcodec/openh264: Add the ability to dlopen() OpenH264 + +We can't directly depend on OpenH264, but we can weakly link to it +and gracefully expose the capability. + +Co-authored-by: Andreas Schneider +Co-authored-by: Neal Gompa + +Signed-off-by: Neal Gompa +--- + configure | 3 + + libavcodec/libopenh264.c | 11 +++ + libavcodec/libopenh264_dlopen.h | 164 ++++++++++++++++++++++++++++++++ + libavcodec/libopenh264dec.c | 9 ++ + libavcodec/libopenh264enc.c | 9 ++ + 5 files changed, 196 insertions(+) + create mode 100644 libavcodec/libopenh264_dlopen.h + +diff --git a/configure b/configure +index 6b5ef6332e..f08e566e98 100755 +--- a/configure ++++ b/configure +@@ -250,6 +250,7 @@ External library support: + --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no] + --enable-libopencv enable video filtering via libopencv [no] + --enable-libopenh264 enable H.264 encoding via OpenH264 [no] ++ --enable-libopenh264-dlopen enable H.264 encoding via dlopen()'ed OpenH264 [no] + --enable-libopenjpeg enable JPEG 2000 de/encoding via OpenJPEG [no] + --enable-libopenmpt enable decoding tracked files via libopenmpt [no] + --enable-libopenvino enable OpenVINO as a DNN module backend +@@ -1839,6 +1840,7 @@ EXTERNAL_LIBRARY_LIST=" + libmysofa + libopencv + libopenh264 ++ libopenh264_dlopen + libopenjpeg + libopenmpt + libopenvino +@@ -6575,6 +6577,7 @@ enabled libopencv && { check_headers opencv2/core/core_c.h && + require libopencv opencv2/core/core_c.h cvCreateImageHeader -lopencv_core -lopencv_imgproc; } || + require_pkg_config libopencv opencv opencv/cxcore.h cvCreateImageHeader; } + enabled libopenh264 && require_pkg_config libopenh264 openh264 wels/codec_api.h WelsGetCodecVersion ++enabled libopenh264_dlopen && enable libopenh264 && add_cppflags "-I$(dirname `readlink -f $0`)/ffdlopenhdrs/include -DCONFIG_LIBOPENH264_DLOPEN=1" + enabled libopenjpeg && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version || + { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } } + enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++" +diff --git a/libavcodec/libopenh264.c b/libavcodec/libopenh264.c +index 59c61a3a4c..382a34562a 100644 +--- a/libavcodec/libopenh264.c ++++ b/libavcodec/libopenh264.c +@@ -20,8 +20,13 @@ + */ + + #include ++ ++#ifdef CONFIG_LIBOPENH264_DLOPEN ++#include "libopenh264_dlopen.h" ++#else + #include + #include ++#endif + + #include "libavutil/log.h" + +@@ -52,6 +57,12 @@ int ff_libopenh264_check_version(void *logctx) + // function (for functions returning larger structs), thus skip the check in those + // configurations. + #if !defined(_WIN32) || !defined(__GNUC__) || !ARCH_X86_32 || AV_GCC_VERSION_AT_LEAST(4, 7) ++ ++#ifdef CONFIG_LIBOPENH264_DLOPEN ++ if (loadLibOpenH264(logctx)) ++ return -1; ++#endif ++ + OpenH264Version libver = WelsGetCodecVersion(); + if (memcmp(&libver, &g_stCodecVersion, sizeof(libver))) { + av_log(logctx, AV_LOG_ERROR, "Incorrect library version loaded\n"); +diff --git a/libavcodec/libopenh264_dlopen.h b/libavcodec/libopenh264_dlopen.h +new file mode 100644 +index 0000000000..c58fcd704d +--- /dev/null ++++ b/libavcodec/libopenh264_dlopen.h +@@ -0,0 +1,164 @@ ++/*! ++ *@page License ++ * ++ * \copy ++ * Copyright (c) 2022, Andreas Schneider ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 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 CONFIG_LIBOPENH264_DLOPEN ++ ++#include ++ ++#include ++#include ++ ++#include "avcodec.h" ++/* ++ * The symbol binding makes sure we do not run into strict aliasing issues which ++ * can lead into segfaults. ++ */ ++typedef int (*__oh264_WelsCreateSVCEncoder)(ISVCEncoder **); ++typedef void (*__oh264_WelsDestroySVCEncoder)(ISVCEncoder *); ++typedef int (*__oh264_WelsGetDecoderCapability)(SDecoderCapability *); ++typedef long (*__oh264_WelsCreateDecoder)(ISVCDecoder **); ++typedef void (*__oh264_WelsDestroyDecoder)(ISVCDecoder *); ++typedef OpenH264Version (*__oh264_WelsGetCodecVersion)(void); ++typedef void (*__oh264_WelsGetCodecVersionEx)(OpenH264Version *); ++ ++#define OH264_SYMBOL_ENTRY(i) \ ++ union { \ ++ __oh264_##i f; \ ++ void *obj; \ ++ } _oh264_##i ++ ++struct oh264_symbols { ++ OH264_SYMBOL_ENTRY(WelsCreateSVCEncoder); ++ OH264_SYMBOL_ENTRY(WelsDestroySVCEncoder); ++ OH264_SYMBOL_ENTRY(WelsGetDecoderCapability); ++ OH264_SYMBOL_ENTRY(WelsCreateDecoder); ++ OH264_SYMBOL_ENTRY(WelsDestroyDecoder); ++ OH264_SYMBOL_ENTRY(WelsGetCodecVersion); ++ OH264_SYMBOL_ENTRY(WelsGetCodecVersionEx); ++}; ++ ++/* Symbols are bound by loadLibOpenH264() */ ++static struct oh264_symbols openh264_symbols; ++ ++static int oh264_WelsCreateSVCEncoder(ISVCEncoder **ppEncoder) { ++ return openh264_symbols._oh264_WelsCreateSVCEncoder.f(ppEncoder); ++} ++#define WelsCreateSVCEncoder oh264_WelsCreateSVCEncoder ++ ++static void oh264_WelsDestroySVCEncoder(ISVCEncoder *pEncoder) { ++ return openh264_symbols._oh264_WelsDestroySVCEncoder.f(pEncoder); ++} ++#define WelsDestroySVCEncoder oh264_WelsDestroySVCEncoder ++ ++static int oh264_WelsGetDecoderCapability(SDecoderCapability *pDecCapability) { ++ return openh264_symbols._oh264_WelsGetDecoderCapability.f(pDecCapability); ++} ++#define WelsGetDecoderCapability oh264_WelsGetDecoderCapability ++ ++static long oh264_WelsCreateDecoder(ISVCDecoder **ppDecoder) { ++ return openh264_symbols._oh264_WelsCreateDecoder.f(ppDecoder); ++} ++#define WelsCreateDecoder oh264_WelsCreateDecoder ++ ++static void oh264_WelsDestroyDecoder(ISVCDecoder *pDecoder) { ++ return openh264_symbols._oh264_WelsDestroyDecoder.f(pDecoder); ++} ++#define WelsDestroyDecoder oh264_WelsDestroyDecoder ++ ++static OpenH264Version oh264_WelsGetCodecVersion(void) { ++ return openh264_symbols._oh264_WelsGetCodecVersion.f(); ++} ++#define WelsGetCodecVersion oh264_WelsGetCodecVersion ++ ++static void oh264_WelsGetCodecVersionEx(OpenH264Version *pVersion) { ++ openh264_symbols._oh264_WelsGetCodecVersionEx.f(pVersion); ++} ++#define WelsGetCodecVersionEx oh264_WelsGetCodecVersionEx ++ ++static void *_oh264_bind_symbol(AVCodecContext *avctx, ++ void *handle, ++ const char *sym_name) { ++ void *sym = NULL; ++ ++ sym = dlsym(handle, sym_name); ++ if (sym == NULL) { ++ const char *err = dlerror(); ++ av_log(avctx, ++ AV_LOG_WARNING, ++ "%s: Failed to bind %s\n", ++ err, ++ sym_name); ++ return NULL; ++ } ++ ++ return sym; ++} ++ ++#define oh264_bind_symbol(avctx, handle, sym_name) \ ++ if (openh264_symbols._oh264_##sym_name.obj == NULL) { \ ++ openh264_symbols._oh264_##sym_name.obj = _oh264_bind_symbol(avctx, handle, #sym_name); \ ++ if (openh264_symbols._oh264_##sym_name.obj == NULL) { \ ++ return 1; \ ++ } \ ++ } ++ ++static int loadLibOpenH264(AVCodecContext *avctx) { ++ void *libopenh264 = NULL; ++ const char *err = NULL; ++ ++#define OPENH264_LIB "libopenh264.so.6" ++ libopenh264 = dlopen(OPENH264_LIB, RTLD_LAZY); ++ err = dlerror(); ++ if (err != NULL) { ++ av_log(avctx, AV_LOG_WARNING, ++ "%s: %s is missing, openh264 support will be disabled\n", err, ++ OPENH264_LIB); ++ if (libopenh264) { ++ dlclose(libopenh264); ++ } ++ return 1; ++ } ++ ++ oh264_bind_symbol(avctx, libopenh264, WelsCreateSVCEncoder); ++ oh264_bind_symbol(avctx, libopenh264, WelsDestroySVCEncoder); ++ oh264_bind_symbol(avctx, libopenh264, WelsGetDecoderCapability); ++ oh264_bind_symbol(avctx, libopenh264, WelsCreateDecoder); ++ oh264_bind_symbol(avctx, libopenh264, WelsDestroyDecoder); ++ oh264_bind_symbol(avctx, libopenh264, WelsGetCodecVersion); ++ oh264_bind_symbol(avctx, libopenh264, WelsGetCodecVersionEx); ++ ++ return 0; ++} ++ ++#endif // CONFIG_LIBOPENH264_DLOPEN +diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c +index 7f5e85402a..281e43c3c0 100644 +--- a/libavcodec/libopenh264dec.c ++++ b/libavcodec/libopenh264dec.c +@@ -19,8 +19,12 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef CONFIG_LIBOPENH264_DLOPEN ++#include "libopenh264_dlopen.h" ++#else + #include + #include ++#endif + + #include "libavutil/common.h" + #include "libavutil/fifo.h" +@@ -55,6 +59,11 @@ static av_cold int svc_decode_init(AVCodecContext *avctx) + int log_level; + WelsTraceCallback callback_function; + ++#ifdef CONFIG_LIBOPENH264_DLOPEN ++ if (loadLibOpenH264(avctx)) ++ return -1; ++#endif ++ + if ((err = ff_libopenh264_check_version(avctx)) < 0) + return err; + +diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c +index de4b85c411..555351982e 100644 +--- a/libavcodec/libopenh264enc.c ++++ b/libavcodec/libopenh264enc.c +@@ -19,8 +19,12 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef CONFIG_LIBOPENH264_DLOPEN ++#include "libopenh264_dlopen.h" ++#else + #include + #include ++#endif + + #include "libavutil/attributes.h" + #include "libavutil/common.h" +@@ -136,6 +140,11 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) + WelsTraceCallback callback_function; + AVCPBProperties *props; + ++#ifdef CONFIG_LIBOPENH264_DLOPEN ++ if (loadLibOpenH264(avctx)) ++ return -1; ++#endif ++ + if ((err = ff_libopenh264_check_version(avctx)) < 0) + return err; + +-- +2.34.1 + diff --git a/ffmpeg.spec b/ffmpeg.spec index ebf5a77..bed6917 100644 --- a/ffmpeg.spec +++ b/ffmpeg.spec @@ -52,6 +52,10 @@ %global _lto_cflags %{nil} %endif +%if "%{__isa_bits}" == "64" +%global lib64_suffix ()(64bit) +%endif + %global av_codec_soversion 59 %global av_device_soversion 59 %global av_filter_soversion 8 @@ -65,18 +69,24 @@ Name: ffmpeg %global pkg_name %{name}%{?pkg_suffix} Version: 5.0 -Release: 3%{?dist} +Release: 4%{?dist} Summary: A complete solution to record, convert and stream audio and video License: GPLv3+ URL: https://ffmpeg.org/ Source0: ffmpeg%{?pkg_suffix}-%{version}.tar.xz -Source1: https://ffmpeg.org/releases/ffmpeg-%{version}.tar.xz.asc +Source1: ffmpeg-dlopen-headers.tar.xz +Source2: https://ffmpeg.org/releases/ffmpeg-%{version}.tar.xz.asc # https://ffmpeg.org/ffmpeg-devel.asc # gpg2 --import --import-options import-export,import-minimal ffmpeg-devel.asc > ./ffmpeg.keyring -Source2: ffmpeg.keyring -Source3: ffmpeg_free_sources +Source3: ffmpeg.keyring +Source4: ffmpeg_free_sources Source20: enable_decoders Source21: enable_encoders +# Scripts for generating tarballs +Source90: ffmpeg_update_free_sources.sh +Source91: ffmpeg_gen_free_tarball.sh +Source92: ffmpeg_get_dlopen_headers.sh + # Change path from /usr/local to /usr Patch1: fix-vmaf-model-path.patch # Some header cleanup @@ -94,6 +104,9 @@ Patch6: ffmpeg-fix-gnutls-priority.patch # https://ffmpeg.org/pipermail/ffmpeg-devel/2021-September/285401.html Patch7: ffmpeg-support-chromium.patch +# Set up dlopen for openh264 +Patch1001: ffmpeg-dlopen-openh264.patch + Requires: libavcodec%{?pkg_suffix}%{_isa} = %{version}-%{release} Requires: libavdevice%{?pkg_suffix}%{_isa} = %{version}-%{release} Requires: libavfilter%{?pkg_suffix}%{_isa} = %{version}-%{release} @@ -291,6 +304,8 @@ break compatibility without any notice. Summary: FFmpeg codec library Requires: libavutil%{?pkg_suffix}%{_isa} = %{version}-%{release} Requires: libswresample%{?pkg_suffix}%{_isa} = %{version}-%{release} +# We dlopen() openh264, so weak-depend on it... +Recommends: libopenh264.so.6%{?lib64_suffix} %description -n libavcodec%{?pkg_suffix} The libavcodec library provides a generic encoding/decoding framework @@ -497,10 +512,10 @@ This subpackage contains the headers for FFmpeg libswscale. %prep %if %{with upstream_tarball} -gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0} +gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE2} %{SOURCE0} %endif -%autosetup -p1 +%autosetup -a1 -p1 install -m 0644 %{SOURCE20} enable_decoders install -m 0644 %{SOURCE21} enable_encoders # fix -O3 -g in host_cflags @@ -556,6 +571,7 @@ cp -a doc/examples/{*.c,Makefile,README} _doc/examples/ --enable-libjack \ --enable-libmp3lame \ --enable-libmysofa \ + --enable-libopenh264-dlopen \ --enable-libopenjpeg \ --enable-libopenmpt \ --enable-libopus \ @@ -800,6 +816,10 @@ rm -rf %{buildroot}%{_datadir}/%{name}/examples %{_mandir}/man3/libswscale.3* %changelog +* Tue Feb 15 2022 Neal Gompa - 5.0-4 +- Add support for dlopening OpenH264 +- Add tarball scripts as sources + * Sun Feb 13 2022 Neal Gompa - 5.0-3 - Enable more QSV and V4L2M2M codecs diff --git a/ffmpeg_free_sources b/ffmpeg_free_sources index 361bc0d..76984b6 100644 --- a/ffmpeg_free_sources +++ b/ffmpeg_free_sources @@ -682,6 +682,10 @@ libavcodec/libfdk-aacenc.c libavcodec/libgsmdec.c libavcodec/libgsmenc.c libavcodec/libmp3lame.c +libavcodec/libopenh264.c +libavcodec/libopenh264.h +libavcodec/libopenh264dec.c +libavcodec/libopenh264enc.c libavcodec/libopenjpegdec.c libavcodec/libopenjpegenc.c libavcodec/libopus.c diff --git a/ffmpeg_get_dlopen_headers.sh b/ffmpeg_get_dlopen_headers.sh new file mode 100755 index 0000000..da221d5 --- /dev/null +++ b/ffmpeg_get_dlopen_headers.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Script to grab headers from existing packages to support dlopen() codec libraries +# Requires: bash, coreutils, curl, bsdtar, dnf, dnf-plugins-core, tar +# Author: Neal Gompa +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +echo "Setting up..." +# Get local directory +LOCALDIR=$(realpath $(dirname $0)) + +# Create working area +TMPDIR=$(mktemp -d /tmp/mmheadersXXXXXX) +mkdir -pv $TMPDIR + +echo "Fetching headers..." +# Get OpenH264 headers +OPENH264_DEVEL=$(dnf -q download --url 'pkgconfig(openh264)') +curl -L $OPENH264_DEVEL | bsdtar -xvf - --include "./usr/include/*" -C $TMPDIR + +echo "Generating tarball..." +# Prep tarball tree +mv -v ${TMPDIR}/usr ${TMPDIR}/ffdlopenhdrs +# Generate tarball +tar --transform "s|^${TMPDIR#?}/||" -cJvf ${LOCALDIR}/ffmpeg-dlopen-headers.tar.xz ${TMPDIR}/ffdlopenhdrs +# Clean up +echo "Cleaning up..." +rm -rfv ${TMPDIR} + +echo "Tarball created: ${LOCALDIR}/ffmpeg-dlopen-headers.tar.xz" diff --git a/sources b/sources index 71b0847..2904f8a 100644 --- a/sources +++ b/sources @@ -1,3 +1,4 @@ -SHA512 (ffmpeg-free-5.0.tar.xz) = f6fe84b072041f5dee150d5a4b4d29b747fd60d7ce83fd6f83eaf71bc5d2214e980729281bed8fe2d949cd30d69e50a719d5ca0b3d900b4a559f6598dc5fe8f1 +SHA512 (ffmpeg-free-5.0.tar.xz) = 6444ff05eb80544c8ab5f3a713c0765b953b447731ab24559549b2440ccee8888f45a379efd2975850f3ee32d78afe81ed4e639fddc7928d78248d70172a4eb3 SHA512 (ffmpeg-5.0.tar.xz.asc) = 9238fcdc849895147a26669ac90fec94002af86e81270128f6eb0448d74487d8ba06ee08d10686a7a6e204689716ee744bfffc2a39466940940609cfcd7dfa85 +SHA512 (ffmpeg-dlopen-headers.tar.xz) = ef47b5a8b5ef5c8c57b2372170ccda3fd6897572ab5aff5e3cd1dd3bbe1f892e42d9f89d1c159c79052a8ac57c42d4a2ebc8636d6f932df00b57f8010c5bfd3b SHA512 (ffmpeg.keyring) = 9b36506835db36f776b7ddb53ad6fa9e915e6ca2f9c7cfebe8eb45513e1036a985283590a840ca313a111bf35dc3731f68885aaafb1fb7011ec433cc119e5165