diff --git a/multimedia/ffmpeg/Makefile b/multimedia/ffmpeg/Makefile index 15966071adc0..626f08570496 100644 --- a/multimedia/ffmpeg/Makefile +++ b/multimedia/ffmpeg/Makefile @@ -1,643 +1,643 @@ # Created by: Martin Matuska PORTNAME= ffmpeg PORTVERSION= 4.4.1 -PORTREVISION= 6 +PORTREVISION= 7 PORTEPOCH= 1 CATEGORIES= multimedia audio net MASTER_SITES= https://ffmpeg.org/releases/ MAINTAINER= multimedia@FreeBSD.org COMMENT= Realtime audio/video encoder/converter and streaming server LICENSE= GPLv2+ LGPL21+ LICENSE_COMB= multi BUILD_DEPENDS= ${BUILD_DEPENDS_${ARCH}} BUILD_DEPENDS_aarch64= as:devel/binutils BUILD_DEPENDS_amd64= nasm:devel/nasm BUILD_DEPENDS_armv6= as:devel/binutils BUILD_DEPENDS_armv7= as:devel/binutils BUILD_DEPENDS_i386= nasm:devel/nasm BUILD_DEPENDS_powerpc64=as:devel/binutils BUILD_DEPENDS_powerpc= as:devel/binutils HAS_CONFIGURE= yes CONFIGURE_LOG= ffbuild/config.log USES= compiler:c11 cpe gmake localbase:ldflags perl5 \ pkgconfig shebangfix tar:xz USE_LDCONFIG= yes USE_PERL5= build SHEBANG_FILES= doc/texi2pod.pl NOPRECIOUSMAKEVARS= yes # ARCH PORTSCOUT= limit:^4\. # Option CHROMAPRINT disabled, it cannot work and people are baffled. OPTIONS_DEFINE= ALSA AMR_NB AMR_WB AOM ARIBB24 ASM ASS BS2B CACA CDIO \ CODEC2 DAV1D DAVS2 DC1394 DEBUG DOCS DRM FDK_AAC FLITE \ FONTCONFIG FREETYPE FREI0R FRIBIDI GLSLANG GME GSM ICONV ILBC \ JACK KLVANC KVAZAAR LADSPA LAME LENSFUN LIBBLURAY LIBRSVG2 \ LIBXML2 LTO LV2 MFX MODPLUG MYSOFA OPENAL OPENCL OPENGL \ OPENH264 OPENJPEG OPENMPT OPENVINO OPTIMIZED_CFLAGS OPUS POCKETSPHINX \ PULSEAUDIO RAV1E RABBITMQ RIST RTCPU RUBBERBAND SDL SMB SNAPPY \ SNDIO SOXR SPEEX SRT SSH SVTAV1 SVTHEVC SVTVP9 TENSORFLOW \ TESSERACT THEORA TWOLAME UAVS3D V4L VAAPI VAPOURSYNTH VDPAU VIDSTAB \ VMAF VO_AMRWBENC VORBIS VPX VULKAN WEBP X264 X265 \ XAVS2 XCB XVID XVIDEO ZIMG ZMQ ZVBI OPTIONS_DEFAULT= AOM ASM ASS DAV1D DRM FONTCONFIG FREETYPE FREI0R GMP \ GNUTLS ICONV LAME LIBXML2 OPTIMIZED_CFLAGS OPUS RTCPU \ THEORA V4L VAAPI VDPAU VMAF VORBIS VPX X264 X265 XCB XVID # i386 is too register-starved for LTO (PR257124) OPTIONS_EXCLUDE_i386= LTO .if !exists(${.CURDIR:H:H}/multimedia/davs2) # https://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff/5985a1bf7233 OPTIONS_EXCLUDE+= DAVS2 .endif .if !exists(${.CURDIR:H:H}/multimedia/uavs3d) # https://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff/c952db9d68d3 OPTIONS_EXCLUDE+= UAVS3D .endif .if !exists(${.CURDIR:H:H}/multimedia/xavs2) # https://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff/85a921f4618 OPTIONS_EXCLUDE+= XAVS2 .endif .if !exists(${.CURDIR:H:H}/multimedia/klvanc) # https://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff/8732dfa9954 OPTIONS_EXCLUDE+= KLVANC .endif .if !exists(${.CURDIR:H:H}/science/openvino) # https://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff/ff37ebaf30e6 OPTIONS_EXCLUDE+= OPENVINO .endif .if !exists(${.CURDIR:H:H}/science/tensorflow) # https://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff/d8c0bbb0aa4 OPTIONS_EXCLUDE+= TENSORFLOW .endif OPTIONS_RADIO= RTMP SSL OPTIONS_RADIO_RTMP= GCRYPT GMP LIBRTMP OPTIONS_RADIO_SSL= GNUTLS MBEDTLS OPENSSL OPTIONS_GROUP= LICENSE OPTIONS_GROUP_LICENSE= GPL3 NONFREE ASS_DESC= Subtitles rendering via libass AOM_DESC= AV1 video encoding/decoding via libaom ARIBB24_DESC= ARIB text and caption decoding via libaribb24 BS2B_DESC= Bauer Stereophonic-to-Binaural filter CHROMAPRINT_DESC= Audio fingerprinting with chromaprint CODEC2_DESC= Codec 2 audio encoding/decoding via libcodec2 DAV1D_DESC= AV1 video decoding via libdav1d DAVS2_DESC= AVS2 decoding via libdavs2 DC1394_DESC= IIDC-1394 grabbing using libdc1394 DRM_DESC= KMS grabbing using libdrm FDK_AAC_DESC= AAC audio encoding via Fraunhofer FDK FLITE_DESC= Voice synthesis support via libflite GLSLANG_DESC= GLSL->SPIRV compilation via libglslang GME_DESC= Game Music Emu demuxer GPL3_DESC= Allow (L)GPL version 3 code(cs) ILBC_DESC= Internet Low Bit Rate codec KLVANC_DESC= Kernel Labs VANC processing KVAZAAR_DESC= H.265 video codec support via Kvazaar LICENSE_DESC= Licensing options LV2_DESC= LV2 audio filtering MFX_DESC= Intel MediaSDK (aka Quick Sync Video) MYSOFA_DESC= SOFAlizer binaural filter NONFREE_DESC= Allow use of nonfree code OPENMPT_DESC= Decoding tracked files via libopenmpt OPENH264_DESC= H.264 video codec support via OpenH264 OPENVINO_DESC= OpenVINO as a DNN module backend for DNN based filters like dnn_processing POCKETSPHINX_DESC= Automatic Speech Recognition via PocketSphinx RAV1E_DESC= AV1 encoding via librav1e RABBITMQ_DESC= AMQP 0-9-1 protocol via RabbitMQ RIST_DESC= Reliable Internet Stream Transport protocol via librist RUBBERBAND_DESC=Time-stretching and pitch-shifting with librubberband RTCPU_DESC= Detect CPU capabilities at runtime RTMP_DESC= RTMP(T)E protocol support SRT_DESC= Haivision SRT protocol via libsrt SVTAV1_DESC= AV1 encoding via SVT-AV1 SVTHEVC_DESC= HEVC encoding via SVT-HEVC SVTVP9_DESC= VP9 encoding via SVT-VP9 LIBRTMP_DESC= ${RTMP_DESC} via librtmp TENSORFLOW_DESC=TensorFlow as a DNN module backend for DNN based filters like sr TESSERACT_DESC= Optical Character Recognition via Tesseract UAVS3D_DESC= AVS3 decoding via libuavs3d VAPOURSYNTH_DESC= VapourSynth demuxer VIDSTAB_DESC= Video stabilization filter VMAF_DESC= VMAF filter via libvmaf VULKAN_DESC= Vulkan filters XAVS2_DESC= AVS2 encoding via libxavs2 XCB_DESC= X11 grabbing using XCB ZIMG_DESC= "z" library video scaling filter ZMQ_DESC= Message passing via libzmq${ZMQ_VERSION} ZVBI_DESC= Teletext support via libzvbi OPTIONS_SUB= yes # alsa ALSA_LIB_DEPENDS= libasound.so:audio/alsa-lib ALSA_CONFIGURE_ENABLE= alsa # Opencore AMR NB AMR_NB_LIB_DEPENDS= libopencore-amrnb.so:audio/opencore-amr AMR_NB_CONFIGURE_ENABLE= libopencore-amrnb AMR_NB_IMPLIES= GPL3 # Opencore AMR WB AMR_WB_LIB_DEPENDS= libopencore-amrwb.so:audio/opencore-amr AMR_WB_CONFIGURE_ENABLE= libopencore-amrwb AMR_WB_IMPLIES= GPL3 # aom AOM_LIB_DEPENDS= libaom.so:multimedia/aom AOM_CONFIGURE_ENABLE= libaom # arib ARIBB24_LIB_DEPENDS= libaribb24.so:multimedia/aribb24 ARIBB24_CONFIGURE_ENABLE= libaribb24 # asm support ASM_CONFIGURE_ENABLE= asm # ass ASS_LIB_DEPENDS= libass.so:multimedia/libass ASS_CONFIGURE_ENABLE= libass # bs2b BS2B_LIB_DEPENDS= libbs2b.so:audio/libbs2b BS2B_CONFIGURE_ENABLE= libbs2b # caca CACA_LIB_DEPENDS= libcaca.so:graphics/libcaca CACA_CONFIGURE_ENABLE= libcaca # cdio CDIO_LIB_DEPENDS= libcdio_paranoia.so:sysutils/libcdio-paranoia CDIO_CONFIGURE_ENABLE= libcdio # chromaprint CHROMAPRINT_BROKEN= Dependency loop CHROMAPRINT_LIB_DEPENDS= libchromaprint.so:audio/chromaprint CHROMAPRINT_CONFIGURE_ENABLE= chromaprint # codec2 CODEC2_LIB_DEPENDS= libcodec2.so:audio/codec2 CODEC2_CONFIGURE_ENABLE= libcodec2 # dav1d DAV1D_LIB_DEPENDS= libdav1d.so:multimedia/dav1d DAV1D_CONFIGURE_ENABLE= libdav1d # davs2 DAVS2_LIB_DEPENDS= libdavs2.so:multimedia/davs2 DAVS2_CONFIGURE_ENABLE= libdavs2 # dc1394 DC1394_LIB_DEPENDS= libdc1394.so:multimedia/libdc1394 DC1394_CONFIGURE_ENABLE= libdc1394 # debugging DEBUG_CONFIGURE_ON= --disable-stripping DEBUG_CONFIGURE_OFF= --disable-debug # docs DOCS_BUILD_DEPENDS= texi2html:textproc/texi2html DOCS_CONFIGURE_ENABLE= htmlpages # drm DRM_LIB_DEPENDS= libdrm.so:graphics/libdrm DRM_CONFIGURE_ENABLE= libdrm # fdk_aac FDK_AAC_LIB_DEPENDS= libfdk-aac.so:audio/fdk-aac FDK_AAC_CONFIGURE_ENABLE= libfdk-aac FDK_AAC_IMPLIES= NONFREE # flite FLITE_LIB_DEPENDS= libflite.so:audio/flite FLITE_CONFIGURE_ENABLE= libflite # fontconfig FONTCONFIG_LIB_DEPENDS= libfontconfig.so:x11-fonts/fontconfig FONTCONFIG_CONFIGURE_ENABLE= fontconfig # freetype FREETYPE_LIB_DEPENDS= libfreetype.so:print/freetype2 FREETYPE_CONFIGURE_ENABLE= libfreetype # frei0r FREI0R_BUILD_DEPENDS= ${LOCALBASE}/include/frei0r.h:graphics/frei0r FREI0R_CONFIGURE_ENABLE= frei0r # fribidi FRIBIDI_LIB_DEPENDS= libfribidi.so:converters/fribidi FRIBIDI_CONFIGURE_ENABLE= libfribidi # gcrypt GCRYPT_LIB_DEPENDS= libgcrypt.so:security/libgcrypt GCRYPT_CONFIGURE_ENABLE= gcrypt # glslang GLSLANG_BUILD_DEPENDS= glslang>0:graphics/glslang \ spirv-tools>0:graphics/spirv-tools GLSLANG_CONFIGURE_ENABLE= libglslang GLSLANG_LDFLAGS= -lm # gnutls GNUTLS_LIB_DEPENDS= libgnutls.so:security/gnutls GNUTLS_CONFIGURE_ENABLE= gnutls # gme GME_LIB_DEPENDS= libgme.so:audio/libgme GME_CONFIGURE_ENABLE= libgme # gmp GMP_LIB_DEPENDS= libgmp.so:math/gmp GMP_CONFIGURE_ENABLE= gmp GMP_IMPLIES= GPL3 # gsm GSM_LIB_DEPENDS= libgsm.so:audio/gsm GSM_CONFIGURE_ENABLE= libgsm # iconv ICONV_USES= iconv ICONV_CONFIGURE_ENABLE= iconv # ilbc ILBC_LIB_DEPENDS= libilbc.so:net/libilbc ILBC_CONFIGURE_ENABLE= libilbc # jack JACK_LIB_DEPENDS= libjack.so:audio/jack JACK_CONFIGURE_ENABLE= libjack # klvanc KLVANC_LIB_DEPENDS= libklvanc.so:multimedia/libklvanc KLVANC_CONFIGURE_ENABLE= libklvanc # kvazaar KVAZAAR_LIB_DEPENDS= libkvazaar.so:multimedia/kvazaar KVAZAAR_CONFIGURE_ENABLE= libkvazaar # ladspa LADSPA_BUILD_DEPENDS= ${LOCALBASE}/include/ladspa.h:audio/ladspa LADSPA_RUN_DEPENDS= ${LOCALBASE}/lib/ladspa/amp.so:audio/ladspa LADSPA_CONFIGURE_ENABLE= ladspa # lame LAME_LIB_DEPENDS= libmp3lame.so:audio/lame LAME_CONFIGURE_ENABLE= libmp3lame # lensfun LENSFUN_LIB_DEPENDS= liblensfun.so:graphics/lensfun LENSFUN_CONFIGURE_ENABLE= liblensfun # libbluray LIBBLURAY_LIB_DEPENDS= libbluray.so:multimedia/libbluray LIBBLURAY_CONFIGURE_ENABLE= libbluray # librsvg LIBRSVG2_USES= gnome LIBRSVG2_USE= GNOME=cairo,librsvg2 LIBRSVG2_CONFIGURE_ENABLE= librsvg # libxml LIBXML2_LIB_DEPENDS= libxml2.so:textproc/libxml2 LIBXML2_CONFIGURE_ENABLE= libxml2 # lto LTO_CONFIGURE_ENABLE= lto # lv2 LV2_BUILD_DEPENDS= lv2>0:audio/lv2 LV2_LIB_DEPENDS= liblilv-0.so:audio/lilv LV2_CONFIGURE_ENABLE= lv2 # libv4l V4L_BUILD_DEPENDS= v4l_compat>0:multimedia/v4l_compat V4L_LIB_DEPENDS= libv4l2.so:multimedia/libv4l V4L_CONFIGURE_ENABLE= libv4l2 V4L_CONFIGURE_OFF= --disable-indev=v4l2 \ --disable-outdev=v4l2 # mbedtls MBEDTLS_LIB_DEPENDS= libmbedtls.so:security/mbedtls MBEDTLS_CONFIGURE_ENABLE= mbedtls # mfx MFX_LIB_DEPENDS= libmfx.so:multimedia/intel-media-sdk MFX_CONFIGURE_ENABLE= libmfx # modplug MODPLUG_LIB_DEPENDS= libmodplug.so:audio/libmodplug MODPLUG_CONFIGURE_ENABLE= libmodplug # mysofa MYSOFA_LIB_DEPENDS= libmysofa.so:audio/libmysofa MYSOFA_CONFIGURE_ENABLE= libmysofa # OpenAL OPENAL_LIB_DEPENDS= libopenal.so:audio/openal-soft OPENAL_CONFIGURE_ENABLE= openal # opencl OPENCL_BUILD_DEPENDS= ${LOCALBASE}/include/CL/opencl.h:devel/opencl OPENCL_LIB_DEPENDS= libOpenCL.so:devel/ocl-icd OPENCL_CONFIGURE_ENABLE= opencl # opengl OPENGL_USES= gl OPENGL_USE= GL=gl OPENGL_CONFIGURE_ENABLE= opengl # openh264 OPENH264_LIB_DEPENDS= libopenh264.so:multimedia/openh264 OPENH264_CONFIGURE_ENABLE= libopenh264 # openjpeg OPENJPEG_LIB_DEPENDS= libopenjp2.so:graphics/openjpeg OPENJPEG_CONFIGURE_ENABLE= libopenjpeg # openmpt OPENMPT_LIB_DEPENDS= libopenmpt.so:audio/libopenmpt OPENMPT_CONFIGURE_ENABLE= libopenmpt # openssl/libtls OPENSSL_USES= ssl OPENSSL_CONFIGURE_ENABLE= ${"${SSL_DEFAULT:Mlibressl*}"!="":?libtls:openssl} OPENSSL_IMPLIES= NONFREE # openvino OPENVINO_LIB_DEPENDS= libinference_engine_c_api.so:science/openvino OPENVINO_CONFIGURE_ENABLE= libopenvino # optimizations OPTIMIZED_CFLAGS_CONFIGURE_ENABLE= optimizations # opus OPUS_LIB_DEPENDS= libopus.so:audio/opus OPUS_CONFIGURE_ENABLE= libopus # pocketsphinx POCKETSPHINX_LIB_DEPENDS= libpocketsphinx.so:audio/pocketsphinx POCKETSPHINX_CONFIGURE_ENABLE= pocketsphinx POCKETSPHINX_BROKEN= pocketsphinx < 5prealpha is not supported # pulseaudio PULSEAUDIO_LIB_DEPENDS= libpulse.so:audio/pulseaudio PULSEAUDIO_CONFIGURE_ENABLE= libpulse # rav1e RAV1E_LIB_DEPENDS= librav1e.so:multimedia/librav1e RAV1E_CONFIGURE_ENABLE= librav1e # rabbitmq RABBITMQ_LIB_DEPENDS= librabbitmq.so:net/rabbitmq-c RABBITMQ_CONFIGURE_ENABLE= librabbitmq # rist RIST_LIB_DEPENDS= librist.so:multimedia/librist RIST_CONFIGURE_ENABLE= librist # rubberband RUBBERBAND_LIB_DEPENDS= librubberband.so:audio/rubberband RUBBERBAND_CONFIGURE_ENABLE= librubberband # rtcpu RTCPU_CONFIGURE_ENABLE= runtime-cpudetect # rtmp LIBRTMP_LIB_DEPENDS= librtmp.so:multimedia/librtmp LIBRTMP_CONFIGURE_ENABLE= librtmp # sdl SDL_USES= sdl SDL_USE= SDL=sdl2 SDL_CONFIGURE_ENABLE= sdl2 # smbclient SMB_USES= samba:lib SMB_CONFIGURE_ENABLE= libsmbclient SMB_IMPLIES= GPL3 # snappy SNAPPY_LIB_DEPENDS= libsnappy.so:archivers/snappy SNAPPY_CONFIGURE_ENABLE= libsnappy # sndio SNDIO_LIB_DEPENDS= libsndio.so:audio/sndio SNDIO_CONFIGURE_ENABLE= sndio # soxr SOXR_LIB_DEPENDS= libsoxr.so:audio/libsoxr SOXR_CONFIGURE_ENABLE= libsoxr # speex SPEEX_LIB_DEPENDS= libspeex.so:audio/speex SPEEX_CONFIGURE_ENABLE= libspeex # ssh SSH_LIB_DEPENDS= libssh.so:security/libssh SSH_CONFIGURE_ENABLE= libssh # srt SRT_LIB_DEPENDS= libsrt.so:www/srt SRT_CONFIGURE_ENABLE= libsrt # svt-av1 SVTAV1_LIB_DEPENDS= libSvtAv1Enc.so:multimedia/svt-av1 SVTAV1_CONFIGURE_ON= --enable-libsvtav1 # svt-hevc SVTHEVC_LIB_DEPENDS= libSvtHevcEnc.so:multimedia/svt-hevc SVTHEVC_CONFIGURE_ON= --enable-libsvthevc SVTHEVC_PATCH_SITES= https://github.com/OpenVisualCloud/SVT-HEVC/raw/v1.5.0-3-g86b58f77/ffmpeg_plugin/:svthevc SVTHEVC_PATCHFILES= 0001-lavc-svt_hevc-add-libsvt-hevc-encoder-wrapper.patch:-p1:svthevc \ 0002-doc-Add-libsvt_hevc-encoder-docs.patch:-p1:svthevc .if make(makesum) .MAKEFLAGS: WITH+=SVTHEVC .endif # svt-vp9 SVTVP9_LIB_DEPENDS= libSvtVp9Enc.so:multimedia/svt-vp9 SVTVP9_CONFIGURE_ON= --enable-libsvtvp9 SVTVP9_PATCH_SITES= https://github.com/OpenVisualCloud/SVT-VP9/raw/v0.3.0-4-gabd5c59/ffmpeg_plugin/:svtvp9 SVTVP9_PATCHFILES= master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch:-p1:svtvp9 .if make(makesum) .MAKEFLAGS: WITH+=SVTVP9 .endif # tensorflow TENSORFLOW_LIB_DEPENDS= libtensorflow.so:science/tensorflow TENSORFLOW_CONFIGURE_ENABLE= libtensorflow # tesseract TESSERACT_LIB_DEPENDS= libtesseract.so:graphics/tesseract TESSERACT_CONFIGURE_ENABLE= libtesseract # theora THEORA_LIB_DEPENDS= libtheora.so:multimedia/libtheora THEORA_CONFIGURE_ENABLE= libtheora # twolame TWOLAME_LIB_DEPENDS= libtwolame.so:audio/twolame TWOLAME_CONFIGURE_ENABLE= libtwolame # uavs3d UAVS3D_LIB_DEPENDS= libuavs3d.so:multimedia/uavs3d UAVS3D_CONFIGURE_ENABLE= libuavs3d # vaapi VAAPI_LIB_DEPENDS= libva.so:multimedia/libva VAAPI_CONFIGURE_ENABLE= vaapi # vapoursynth VAPOURSYNTH_LIB_DEPENDS= libvapoursynth-script.so:multimedia/vapoursynth VAPOURSYNTH_CONFIGURE_ENABLE= vapoursynth # vdpau VDPAU_USES= xorg VDPAU_USE= XORG=x11 VDPAU_LIB_DEPENDS= libvdpau.so:multimedia/libvdpau VDPAU_CONFIGURE_ENABLE= vdpau # vmaf VMAF_LIB_DEPENDS= libvmaf.so:multimedia/vmaf VMAF_CONFIGURE_ENABLE= libvmaf # vo-amrwbenc VO_AMRWBENC_LIB_DEPENDS= libvo-amrwbenc.so:audio/vo-amrwbenc VO_AMRWBENC_CONFIGURE_ENABLE= libvo-amrwbenc VO_AMRWBENC_IMPLIES= GPL3 # vid.stab VIDSTAB_LIB_DEPENDS= libvidstab.so:multimedia/vid.stab VIDSTAB_CONFIGURE_ENABLE= libvidstab # vorbis VORBIS_LIB_DEPENDS= libvorbisenc.so:audio/libvorbis VORBIS_CONFIGURE_ENABLE= libvorbis # vp8 VPX_LIB_DEPENDS= libvpx.so:multimedia/libvpx VPX_CONFIGURE_ENABLE= libvpx # vulkan VULKAN_BUILD_DEPENDS= vulkan-headers>0:graphics/vulkan-headers VULKAN_LIB_DEPENDS= libvulkan.so:graphics/vulkan-loader VULKAN_CONFIGURE_ENABLE= vulkan VULKAN_IMPLIES= GLSLANG # webp WEBP_LIB_DEPENDS= libwebp.so:graphics/webp WEBP_CONFIGURE_ENABLE= libwebp # x264 X264_LIB_DEPENDS= libx264.so:multimedia/libx264 X264_CONFIGURE_ENABLE= libx264 # x265 X265_LIB_DEPENDS= libx265.so:multimedia/x265 X265_CONFIGURE_ENABLE= libx265 # xavs2 XAVS2_LIB_DEPENDS= libxavs2.so:multimedia/xavs2 XAVS2_CONFIGURE_ENABLE= libxavs2 # xcb XCB_USES= xorg XCB_USE= XORG=xcb XCB_CONFIGURE_ENABLE= libxcb # xvid XVID_LIB_DEPENDS= libxvidcore.so:multimedia/xvid XVID_CONFIGURE_ENABLE= libxvid # xv XVIDEO_USES= xorg XVIDEO_USE= XORG=x11,xext,xv XVIDEO_CONFIGURE_OFF= --disable-outdev=xv # zimg ZIMG_LIB_DEPENDS= libzimg.so:graphics/sekrit-twc-zimg ZIMG_CONFIGURE_ENABLE= libzimg # zmq ZMQ_LIB_DEPENDS= libzmq.so:net/libzmq${ZMQ_VERSION} ZMQ_CONFIGURE_ENABLE= libzmq ZMQ_VERSION?= 4 # zvbi ZVBI_LIB_DEPENDS= libzvbi.so:devel/libzvbi ZVBI_CONFIGURE_ENABLE= libzvbi # License knobs GPL3_CONFIGURE_ENABLE= version3 GPL3_VARS= LICENSE="GPLv3+ LGPL3+" LICENSE_FILE_GPLv3+ = ${WRKSRC}/COPYING.GPLv3 LICENSE_FILE_LGPL3+ = ${WRKSRC}/COPYING.LGPLv3 NONFREE_CONFIGURE_ENABLE=nonfree INSTALL_TARGET= install-progs install-doc install-data \ install-libs install-headers install-examples DATADIR= ${PREFIX}/share/${PORTNAME}${PKGNAMESUFFIX} DOCSDIR= ${PREFIX}/share/doc/${PORTNAME}${PKGNAMESUFFIX} MAKE_ENV+= V=1 LDFLAGS_aarch64=-Wl,-z,notext LDFLAGS_armv6= -Wl,-z,notext LDFLAGS_armv7= -Wl,-z,notext LDFLAGS_i386= -Wl,-z,notext CONFIGURE_ARGS+=--prefix="${PREFIX}" \ --mandir="${PREFIX}/man" \ --datadir="${DATADIR}" \ --pkgconfigdir="${PREFIX}/libdata/pkgconfig" \ --disable-static \ --disable-libcelt \ --enable-shared \ --enable-pic \ --enable-gpl \ --enable-avresample \ --cc="${CC}" \ --cxx="${CXX}" DOC_FILES= Changelog CREDITS INSTALL.md LICENSE.md MAINTAINERS \ README.md RELEASE_NOTES # under doc subdirectory DOC_DOCFILES= APIchanges *.txt PORTDOCS= * .include .if ${PORT_OPTIONS:MNONFREE} LICENSE+= NONFREE LICENSE_COMB= multi LICENSE_NAME_NONFREE= Non free code LICENSE_TEXT_NONFREE= enabling OPENSSL or FDK_AAC restricts redistribution LICENSE_PERMS_NONFREE= auto-accept .endif .include .if ${ARCH} == powerpc64 && ${PORT_OPTIONS:MLTO} && ${CHOSEN_COMPILER_TYPE} == clang USE_GCC= yes .endif post-install: (cd ${WRKSRC} && ${COPYTREE_SHARE} \ "${DOC_FILES}" ${STAGEDIR}${DOCSDIR}) (cd ${WRKSRC}/doc && ${COPYTREE_SHARE} \ "${DOC_DOCFILES}" ${STAGEDIR}${DOCSDIR}) .include diff --git a/multimedia/ffmpeg/files/patch-vmaf b/multimedia/ffmpeg/files/patch-vmaf index b503561803c1..abe772274d3c 100644 --- a/multimedia/ffmpeg/files/patch-vmaf +++ b/multimedia/ffmpeg/files/patch-vmaf @@ -1,828 +1,951 @@ -https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2021-June/281878.html +https://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff/3d29724c008d --- configure.orig 2021-10-24 20:47:11 UTC +++ configure -@@ -3663,7 +3663,7 @@ uspp_filter_deps="gpl avcodec" +@@ -3663,7 +3663,7 @@ vidstabtransform_filter_deps="libvidstab" vaguedenoiser_filter_deps="gpl" vidstabdetect_filter_deps="libvidstab" vidstabtransform_filter_deps="libvidstab" -libvmaf_filter_deps="libvmaf pthreads" +libvmaf_filter_deps="libvmaf" zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" -@@ -6441,7 +6441,7 @@ enabled libtwolame && require libtwolame twolam +@@ -6441,7 +6441,7 @@ enabled libvidstab && require_pkg_config libvid enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit -enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf +enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 2.0.0" libvmaf.h vmaf_init enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init && require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init --- doc/filters.texi.orig 2021-10-24 20:47:07 UTC +++ doc/filters.texi -@@ -13867,66 +13867,37 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Cano +@@ -13867,66 +13867,58 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Cano @section libvmaf -Obtain the VMAF (Video Multi-Method Assessment Fusion) -score between two input videos. +Calulate the VMAF (Video Multi-Method Assessment Fusion) score for a +reference/distorted pair of input videos. The obtained VMAF score is printed through the logging system. It requires Netflix's vmaf library (libvmaf) as a pre-requisite. After installing the library it can be enabled using: @code{./configure --enable-libvmaf}. -If no model path is specified it uses the default model: @code{vmaf_v0.6.1.pkl}. The filter has following options: @table @option --@item model_path --Set the model path which is to be used for SVM. --Default value: @code{"/usr/local/share/model/vmaf_v0.6.1.pkl"} +@item model +A `|` delimited list of vmaf models. Each model can be configured with a number of parameters. +Default value: @code{"version=vmaf_v0.6.1"} - -+@item feature -+A `|` delimited list of features. Each feature can be configured with a number of parameters. + - @item log_path --Set the file path to be used to store logs. -+Set the file path to be used to store log files. + @item model_path +-Set the model path which is to be used for SVM. +-Default value: @code{"/usr/local/share/model/vmaf_v0.6.1.pkl"} ++Deprecated, use model='path=...'. - @item log_fmt +-@item log_path +-Set the file path to be used to store logs. +- +-@item log_fmt -Set the format of the log file (csv, json or xml). -+Set the format of the log file (xml, json, csv, or sub). - --@item enable_transform +- + @item enable_transform -This option can enable/disable the @code{score_transform} applied to the final predicted VMAF score, -if you have specified score_transform option in the input parameter file passed to @code{run_vmaf_training.py} -Default value: @code{false} -- --@item phone_model ++Deprecated, use model='enable_transform=true'. + + @item phone_model -Invokes the phone model which will generate VMAF scores higher than in the -regular model, which is more suitable for laptop, TV, etc. viewing conditions. -Default value: @code{false} -- --@item psnr ++Deprecated, use model='enable_transform=true'. + ++@item enable_conf_interval ++Deprecated, use model='enable_conf_interval=true'. ++ ++@item feature ++A `|` delimited list of features. Each feature can be configured with a number of parameters. ++ + @item psnr -Enables computing psnr along with vmaf. -Default value: @code{false} -- --@item ssim ++Deprecated, use feature='name=psnr'. + + @item ssim -Enables computing ssim along with vmaf. -Default value: @code{false} -- --@item ms_ssim ++Deprecated, use feature='name=ssim'. + + @item ms_ssim -Enables computing ms_ssim along with vmaf. -Default value: @code{false} -- ++Deprecated, use feature='name=ms_ssim'. + -@item pool -Set the pool method to be used for computing vmaf. -Options are @code{min}, @code{harmonic_mean} or @code{mean} (default). -- ++@item log_path ++Set the file path to be used to store log files. + ++@item log_fmt ++Set the format of the log file (xml, json, csv, or sub). ++ @item n_threads -Set number of threads to be used when computing vmaf. -Default value: @code{0}, which makes use of all available logical processors. +Set number of threads to be used when initializing libvmaf. +Default value: @code{0}, no threads. @item n_subsample -Set interval for frame subsampling used when computing vmaf. -Default value: @code{1} - -@item enable_conf_interval -Enables confidence interval. -Default value: @code{false} +Set frame subsampling interval to be used. @end table This filter also supports the @ref{framesync} options. -@@ -13934,23 +13905,31 @@ This filter also supports the @ref{framesync} options. +@@ -13934,23 +13926,31 @@ This filter also supports the @ref{framesync} options. @subsection Examples @itemize @item -On the below examples the input file @file{main.mpg} being processed is -compared with the reference file @file{ref.mpg}. +In the examples below, a distorted video @file{distorted.mpg} is +compared with a reference file @file{reference.mpg}. +@item +Basic usage: @example -ffmpeg -i main.mpg -i ref.mpg -lavfi libvmaf -f null - +ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf=log_path=output.xml -f null - @end example @item -Example with options: +Example with multiple models: @example -ffmpeg -i main.mpg -i ref.mpg -lavfi libvmaf="psnr=1:log_fmt=json" -f null - -+ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='model=version=vmaf_v0.6.1\\:name=vmaf|version=vmaf_v0.6.1neg\\:name=vmaf_neg:log_path=output.xml' -f null - ++ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='model=version=vmaf_v0.6.1\\:name=vmaf|version=vmaf_v0.6.1neg\\:name=vmaf_neg' -f null - @end example @item +Example with multiple addtional features: +@example -+ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='feature=name=psnr|name=ciede:log_path=output.xml' -f null - ++ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='feature=name=psnr|name=ciede' -f null - +@end example + +@item Example with options and different containers: @example -ffmpeg -i main.mpg -i ref.mkv -lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]libvmaf=psnr=1:log_fmt=json" -f null - +ffmpeg -i distorted.mpg -i reference.mkv -lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]libvmaf=log_fmt=json:log_path=output.json" -f null - @end example @end itemize --- libavfilter/vf_libvmaf.c.orig 2021-10-24 20:47:07 UTC +++ libavfilter/vf_libvmaf.c @@ -24,8 +24,8 @@ * Calculate the VMAF between two input videos. */ -#include #include + #include "libavutil/avstring.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" -@@ -39,211 +39,372 @@ +@@ -39,23 +39,9 @@ typedef struct LIBVMAFContext { typedef struct LIBVMAFContext { const AVClass *class; FFFrameSync fs; - const AVPixFmtDescriptor *desc; - int width; - int height; - double vmaf_score; - int vmaf_thread_created; - pthread_t vmaf_thread; - pthread_mutex_t lock; - pthread_cond_t cond; - int eof; - AVFrame *gmain; - AVFrame *gref; - int frame_set; -- char *model_path; + char *model_path; char *log_path; char *log_fmt; - int disable_clip; - int disable_avx; -- int enable_transform; -- int phone_model; -- int psnr; -- int ssim; -- int ms_ssim; -- char *pool; + int enable_transform; + int phone_model; + int psnr; +@@ -65,185 +51,488 @@ typedef struct LIBVMAFContext { int n_threads; int n_subsample; -- int enable_conf_interval; + int enable_conf_interval; - int error; + char *model_cfg; + char *feature_cfg; + VmafContext *vmaf; + VmafModel **model; + unsigned model_cnt; + unsigned frame_cnt; + unsigned bpc; } LIBVMAFContext; #define OFFSET(x) offsetof(LIBVMAFContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption libvmaf_options[] = { - {"model_path", "Set the model to be used for computing vmaf.", OFFSET(model_path), AV_OPT_TYPE_STRING, {.str="/usr/local/share/model/vmaf_v0.6.1.pkl"}, 0, 1, FLAGS}, - {"log_path", "Set the file path to be used to store logs.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, - {"log_fmt", "Set the format of the log (csv, json or xml).", OFFSET(log_fmt), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, - {"enable_transform", "Enables transform for computing vmaf.", OFFSET(enable_transform), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"phone_model", "Invokes the phone model that will generate higher VMAF scores.", OFFSET(phone_model), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"psnr", "Enables computing psnr along with vmaf.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"ssim", "Enables computing ssim along with vmaf.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"ms_ssim", "Enables computing ms-ssim along with vmaf.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, -- {"pool", "Set the pool method to be used for computing vmaf.", OFFSET(pool), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, -- {"n_threads", "Set number of threads to be used when computing vmaf.", OFFSET(n_threads), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT_MAX, FLAGS}, -- {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, ++ {"model_path", "use model='path=...'.", OFFSET(model_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"log_path", "Set the file path to be used to write log.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, ++ {"log_fmt", "Set the format of the log (csv, json, xml, or sub).", OFFSET(log_fmt), AV_OPT_TYPE_STRING, {.str="xml"}, 0, 1, FLAGS}, ++ {"enable_transform", "use model='enable_transform=true'.", OFFSET(enable_transform), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"phone_model", "use model='enable_transform=true'.", OFFSET(phone_model), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"psnr", "use feature='name=psnr'.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"ssim", "use feature='name=ssim'.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"ms_ssim", "use feature='name=ms_ssim'.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, + {"pool", "Set the pool method to be used for computing vmaf.", OFFSET(pool), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, + {"n_threads", "Set number of threads to be used when computing vmaf.", OFFSET(n_threads), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT_MAX, FLAGS}, + {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, - {"enable_conf_interval", "Enables confidence interval.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, -+ {"model", "Set the model to be used for computing vmaf.", OFFSET(model_cfg), AV_OPT_TYPE_STRING, {.str="version=vmaf_v0.6.1"}, 0, 1, FLAGS}, -+ {"feature", "Set the feature to be used for computing vmaf.", OFFSET(feature_cfg), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, -+ {"log_path", "Set the file path to be used to write log.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, -+ {"log_fmt", "Set the format of the log (csv, json, xml, or sub).", OFFSET(log_fmt), AV_OPT_TYPE_STRING, {.str="xml"}, 0, 1, FLAGS}, -+ {"n_threads", "Set number of threads to be used when computing vmaf.", OFFSET(n_threads), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT_MAX, FLAGS}, -+ {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, ++ {"enable_conf_interval", "model='enable_conf_interval=true'.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, ++ {"model", "Set the model to be used for computing vmaf.", OFFSET(model_cfg), AV_OPT_TYPE_STRING, {.str="version=vmaf_v0.6.1"}, 0, 1, FLAGS}, ++ {"feature", "Set the feature to be used for computing vmaf.", OFFSET(feature_cfg), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, { NULL } }; FRAMESYNC_DEFINE_CLASS(libvmaf, LIBVMAFContext, fs); -#define read_frame_fn(type, bits) \ - static int read_frame_##bits##bit(float *ref_data, float *main_data, \ - float *temp_data, int stride, void *ctx) \ -{ \ - LIBVMAFContext *s = (LIBVMAFContext *) ctx; \ - int ret; \ - \ - pthread_mutex_lock(&s->lock); \ - \ - while (!s->frame_set && !s->eof) { \ - pthread_cond_wait(&s->cond, &s->lock); \ - } \ - \ - if (s->frame_set) { \ - int ref_stride = s->gref->linesize[0]; \ - int main_stride = s->gmain->linesize[0]; \ - \ - const type *ref_ptr = (const type *) s->gref->data[0]; \ - const type *main_ptr = (const type *) s->gmain->data[0]; \ - \ - float *ptr = ref_data; \ - float factor = 1.f / (1 << (bits - 8)); \ - \ - int h = s->height; \ - int w = s->width; \ - \ - int i,j; \ - \ - for (i = 0; i < h; i++) { \ - for ( j = 0; j < w; j++) { \ - ptr[j] = ref_ptr[j] * factor; \ - } \ - ref_ptr += ref_stride / sizeof(*ref_ptr); \ - ptr += stride / sizeof(*ptr); \ - } \ - \ - ptr = main_data; \ - \ - for (i = 0; i < h; i++) { \ - for (j = 0; j < w; j++) { \ - ptr[j] = main_ptr[j] * factor; \ - } \ - main_ptr += main_stride / sizeof(*main_ptr); \ - ptr += stride / sizeof(*ptr); \ - } \ - } \ - \ - ret = !s->frame_set; \ - \ - av_frame_unref(s->gref); \ - av_frame_unref(s->gmain); \ - s->frame_set = 0; \ - \ - pthread_cond_signal(&s->cond); \ - pthread_mutex_unlock(&s->lock); \ - \ - if (ret) { \ - return 2; \ - } \ - \ - return 0; \ +static enum VmafPixelFormat pix_fmt_map(enum AVPixelFormat av_pix_fmt) +{ + switch (av_pix_fmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV420P10LE: + case AV_PIX_FMT_YUV420P12LE: + case AV_PIX_FMT_YUV420P16LE: + return VMAF_PIX_FMT_YUV420P; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV422P10LE: + case AV_PIX_FMT_YUV422P12LE: + case AV_PIX_FMT_YUV422P16LE: + return VMAF_PIX_FMT_YUV422P; + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV444P10LE: + case AV_PIX_FMT_YUV444P12LE: + case AV_PIX_FMT_YUV444P16LE: + return VMAF_PIX_FMT_YUV444P; + default: + return VMAF_PIX_FMT_UNKNOWN; + } } -read_frame_fn(uint8_t, 8); -read_frame_fn(uint16_t, 10); +static int copy_picture_data(AVFrame *src, VmafPicture *dst, unsigned bpc) +{ + int err = vmaf_picture_alloc(dst, pix_fmt_map(src->format), bpc, + src->width, src->height); -+ if (err) return AVERROR(ENOMEM); ++ if (err) ++ return AVERROR(ENOMEM); -static void compute_vmaf_score(LIBVMAFContext *s) + for (unsigned i = 0; i < 3; i++) { + uint8_t *src_data = src->data[i]; + uint8_t *dst_data = dst->data[i]; + for (unsigned j = 0; j < dst->h[i]; j++) { + memcpy(dst_data, src_data, sizeof(*dst_data) * dst->w[i]); + src_data += src->linesize[i]; + dst_data += dst->stride[i]; + } + } + + return 0; +} + +static int do_vmaf(FFFrameSync *fs) { - int (*read_frame)(float *ref_data, float *main_data, float *temp_data, - int stride, void *ctx); - char *format; + AVFilterContext *ctx = fs->parent; + LIBVMAFContext *s = ctx->priv; ++ VmafPicture pic_ref, pic_dist; + AVFrame *ref, *dist; + int err = 0; - if (s->desc->comp[0].depth <= 8) { - read_frame = read_frame_8bit; - } else { - read_frame = read_frame_10bit; + int ret = ff_framesync_dualinput_get(fs, &dist, &ref); + if (ret < 0) + return ret; + if (ctx->is_disabled || !ref) + return ff_filter_frame(ctx->outputs[0], dist); + -+ VmafPicture pic_ref; + err = copy_picture_data(ref, &pic_ref, s->bpc); + if (err) { + av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); + return AVERROR(ENOMEM); } - format = (char *) s->desc->name; -+ VmafPicture pic_dist; + err = copy_picture_data(dist, &pic_dist, s->bpc); + if (err) { + av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); + vmaf_picture_unref(&pic_ref); + return AVERROR(ENOMEM); + } - s->error = compute_vmaf(&s->vmaf_score, format, s->width, s->height, - read_frame, s, s->model_path, s->log_path, - s->log_fmt, 0, 0, s->enable_transform, - s->phone_model, s->psnr, s->ssim, - s->ms_ssim, s->pool, - s->n_threads, s->n_subsample, s->enable_conf_interval); + err = vmaf_read_pictures(s->vmaf, &pic_ref, &pic_dist, s->frame_cnt++); + if (err) { + av_log(s, AV_LOG_ERROR, "problem during vmaf_read_pictures.\n"); + return AVERROR(EINVAL); + } + + return ff_filter_frame(ctx->outputs[0], dist); } -static void *call_vmaf(void *ctx) ++ +static AVDictionary **delimited_dict_parse(char *str, unsigned *cnt) { - LIBVMAFContext *s = (LIBVMAFContext *) ctx; - compute_vmaf_score(s); - if (!s->error) { - av_log(ctx, AV_LOG_INFO, "VMAF score: %f\n",s->vmaf_score); - } else { - pthread_mutex_lock(&s->lock); - pthread_cond_signal(&s->cond); - pthread_mutex_unlock(&s->lock); ++ AVDictionary **dict = NULL; ++ char *str_copy = NULL; ++ char *saveptr = NULL; ++ unsigned cnt2; + int err = 0; -+ if (!str) return NULL; + -+ *cnt = 1; ++ if (!str) ++ return NULL; ++ ++ cnt2 = 1; + for (char *p = str; *p; p++) { + if (*p == '|') -+ (*cnt)++; ++ cnt2++; } - pthread_exit(NULL); + -+ AVDictionary **dict = av_calloc(*cnt, sizeof(*dict)); -+ if (!dict) goto fail; ++ dict = av_calloc(cnt2, sizeof(*dict)); ++ if (!dict) ++ goto fail; + -+ char *str_copy = av_strdup(str); -+ if (!str_copy) goto fail; ++ str_copy = av_strdup(str); ++ if (!str_copy) ++ goto fail; + -+ char *saveptr = NULL; -+ for (unsigned i = 0; i < *cnt; i++) { ++ *cnt = 0; ++ for (unsigned i = 0; i < cnt2; i++) { + char *s = av_strtok(i == 0 ? str_copy : NULL, "|", &saveptr); -+ err = av_dict_parse_string(&dict[i], s, "=", ":", 0); -+ if (err) goto fail; ++ if (!s) ++ continue; ++ err = av_dict_parse_string(&dict[(*cnt)++], s, "=", ":", 0); ++ if (err) ++ goto fail; + } + + av_free(str_copy); + return dict; + +fail: + if (dict) { + for (unsigned i = 0; i < *cnt; i++) { + if (dict[i]) + av_dict_free(&dict[i]); + } + av_free(dict); + } -+ if (str_copy) -+ av_free(str_copy); ++ ++ av_free(str_copy); + *cnt = 0; return NULL; } -static int do_vmaf(FFFrameSync *fs) +static int parse_features(AVFilterContext *ctx) { - AVFilterContext *ctx = fs->parent; LIBVMAFContext *s = ctx->priv; - AVFrame *master, *ref; - int ret; -+ if (!s->feature_cfg) return 0; ++ AVDictionary **dict = NULL; ++ unsigned dict_cnt; ++ int err = 0; - ret = ff_framesync_dualinput_get(fs, &master, &ref); - if (ret < 0) - return ret; - if (!ref) - return ff_filter_frame(ctx->outputs[0], master); -+ int err = 0; ++ if (!s->feature_cfg) ++ return 0; - pthread_mutex_lock(&s->lock); -+ unsigned dict_cnt = 0; -+ AVDictionary **dict = delimited_dict_parse(s->feature_cfg, &dict_cnt); ++ dict = delimited_dict_parse(s->feature_cfg, &dict_cnt); + if (!dict) { + av_log(ctx, AV_LOG_ERROR, + "could not parse feature config: %s\n", s->feature_cfg); + return AVERROR(EINVAL); + } - while (s->frame_set && !s->error) { - pthread_cond_wait(&s->cond, &s->lock); + for (unsigned i = 0; i < dict_cnt; i++) { + char *feature_name = NULL; + VmafFeatureDictionary *feature_opts_dict = NULL; + AVDictionaryEntry *e = NULL; + + while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { + if (av_stristr(e->key, "name")) { + feature_name = e->value; + continue; + } + + err = vmaf_feature_dictionary_set(&feature_opts_dict, e->key, + e->value); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not set feature option: %s.%s=%s\n", + feature_name, e->key, e->value); + goto exit; + } + } + + err = vmaf_use_feature(s->vmaf, feature_name, feature_opts_dict); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem during vmaf_use_feature: %s\n", feature_name); + goto exit; + } } - if (s->error) { +exit: + for (unsigned i = 0; i < dict_cnt; i++) { + if (dict[i]) + av_dict_free(&dict[i]); + } + av_free(dict); + return err; +} + +static int parse_models(AVFilterContext *ctx) +{ + LIBVMAFContext *s = ctx->priv; -+ if (!s->model_cfg) return 0; -+ ++ AVDictionary **dict; ++ unsigned dict_cnt; + int err = 0; + -+ unsigned dict_cnt = 0; -+ AVDictionary **dict = delimited_dict_parse(s->model_cfg, &dict_cnt); ++ if (!s->model_cfg) return 0; ++ ++ dict_cnt = 0; ++ dict = delimited_dict_parse(s->model_cfg, &dict_cnt); + if (!dict) { av_log(ctx, AV_LOG_ERROR, - "libvmaf encountered an error, check log for details\n"); - pthread_mutex_unlock(&s->lock); + "could not parse model config: %s\n", s->model_cfg); return AVERROR(EINVAL); } - av_frame_ref(s->gref, ref); - av_frame_ref(s->gmain, master); + s->model_cnt = dict_cnt; + s->model = av_calloc(s->model_cnt, sizeof(*s->model)); -+ if (!s->model) return AVERROR(ENOMEM); ++ if (!s->model) ++ return AVERROR(ENOMEM); - s->frame_set = 1; + for (unsigned i = 0; i < dict_cnt; i++) { -+ VmafModelConfig model_cfg = {0}; ++ VmafModelConfig model_cfg = { 0 }; + AVDictionaryEntry *e = NULL; -+ char *version, *path; ++ char *version = NULL; ++ char *path = NULL; - pthread_cond_signal(&s->cond); - pthread_mutex_unlock(&s->lock); + while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { + if (av_stristr(e->key, "disable_clip")) { + model_cfg.flags |= av_stristr(e->value, "true") ? + VMAF_MODEL_FLAG_DISABLE_CLIP : 0; + continue; + } - return ff_filter_frame(ctx->outputs[0], master); + if (av_stristr(e->key, "enable_transform")) { + model_cfg.flags |= av_stristr(e->value, "true") ? + VMAF_MODEL_FLAG_ENABLE_TRANSFORM : 0; + continue; + } + + if (av_stristr(e->key, "name")) { + model_cfg.name = e->value; + continue; + } + + if (av_stristr(e->key, "version")) { + version = e->value; + continue; + } + + if (av_stristr(e->key, "path")) { + path = e->value; + continue; + } + } + + if (version) { + err = vmaf_model_load(&s->model[i], &model_cfg, version); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not load libvmaf model with version: %s\n", + version); + goto exit; + } + } + + if (path && !s->model[i]) { + err = vmaf_model_load_from_path(&s->model[i], &model_cfg, path); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not load libvmaf model with path: %s\n", -+ e->value); ++ path); + goto exit; + } + } + + if (!s->model[i]) { + av_log(ctx, AV_LOG_ERROR, + "could not load libvmaf model with config: %s\n", + s->model_cfg); + goto exit; + } + -+ e = NULL; + while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { ++ VmafFeatureDictionary *feature_opts_dict = NULL; + char *feature_opt = NULL; ++ + char *feature_name = av_strtok(e->key, ".", &feature_opt); -+ if (!feature_opt) continue; ++ if (!feature_opt) ++ continue; + -+ VmafFeatureDictionary *feature_opts_dict = NULL; + err = vmaf_feature_dictionary_set(&feature_opts_dict, + feature_opt, e->value); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not set feature option: %s.%s=%s\n", + feature_name, feature_opt, e->value); + err = AVERROR(EINVAL); + goto exit; + } + + err = vmaf_model_feature_overload(s->model[i], feature_name, + feature_opts_dict); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not overload feature: %s\n", feature_name); + err = AVERROR(EINVAL); + goto exit; + } + } + } + + for (unsigned i = 0; i < s->model_cnt; i++) { + err = vmaf_use_features_from_model(s->vmaf, s->model[i]); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem during vmaf_use_features_from_model\n"); + err = AVERROR(EINVAL); + goto exit; + } + } + +exit: + for (unsigned i = 0; i < dict_cnt; i++) { + if (dict[i]) + av_dict_free(&dict[i]); + } + av_free(dict); + return err; } +static enum VmafLogLevel log_level_map(int log_level) +{ + switch (log_level) { + case AV_LOG_QUIET: + return VMAF_LOG_LEVEL_NONE; + case AV_LOG_ERROR: + return VMAF_LOG_LEVEL_ERROR; + case AV_LOG_WARNING: + return VMAF_LOG_LEVEL_WARNING; + case AV_LOG_INFO: + return VMAF_LOG_LEVEL_INFO; + case AV_LOG_DEBUG: + return VMAF_LOG_LEVEL_DEBUG; + default: + return VMAF_LOG_LEVEL_INFO; + } +} ++ ++static int parse_deprecated_options(AVFilterContext *ctx) ++{ ++ LIBVMAFContext *s = ctx->priv; ++ VmafModel *model = NULL; ++ VmafModelCollection *model_collection = NULL; ++ enum VmafModelFlags flags = VMAF_MODEL_FLAGS_DEFAULT; ++ int err = 0; ++ ++ VmafModelConfig model_cfg = { ++ .name = "vmaf", ++ .flags = flags, ++ }; ++ ++ if (s->enable_transform || s->phone_model) ++ flags |= VMAF_MODEL_FLAG_ENABLE_TRANSFORM; ++ ++ if (!s->model_path) ++ goto extra_metrics_only; ++ ++ if (s->enable_conf_interval) { ++ err = vmaf_model_collection_load_from_path(&model, &model_collection, ++ &model_cfg, s->model_path); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading model file: %s\n", s->model_path); ++ goto exit; ++ } ++ ++ err = vmaf_use_features_from_model_collection(s->vmaf, model_collection); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractors from model file: %s\n", ++ s->model_path); ++ goto exit; ++ } ++ } else { ++ err = vmaf_model_load_from_path(&model, &model_cfg, s->model_path); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading model file: %s\n", s->model_path); ++ goto exit; ++ } ++ err = vmaf_use_features_from_model(s->vmaf, model); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractors from model file: %s\n", ++ s->model_path); ++ goto exit; ++ } ++ } ++ ++extra_metrics_only: ++ if (s->psnr) { ++ VmafFeatureDictionary *d = NULL; ++ vmaf_feature_dictionary_set(&d, "enable_chroma", "false"); ++ ++ err = vmaf_use_feature(s->vmaf, "psnr", d); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractor: psnr\n"); ++ goto exit; ++ } ++ } ++ ++ if (s->ssim) { ++ err = vmaf_use_feature(s->vmaf, "float_ssim", NULL); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractor: ssim\n"); ++ goto exit; ++ } ++ } ++ ++ if (s->ms_ssim) { ++ err = vmaf_use_feature(s->vmaf, "float_ms_ssim", NULL); ++ if (err) { ++ av_log(ctx, AV_LOG_ERROR, ++ "problem loading feature extractor: ms_ssim\n"); ++ goto exit; ++ } ++ } ++ ++exit: ++ return err; ++} + static av_cold int init(AVFilterContext *ctx) { LIBVMAFContext *s = ctx->priv; + int err = 0; - s->gref = av_frame_alloc(); - s->gmain = av_frame_alloc(); - if (!s->gref || !s->gmain) - return AVERROR(ENOMEM); + VmafConfiguration cfg = { + .log_level = log_level_map(av_log_get_level()), + .n_subsample = s->n_subsample, + .n_threads = s->n_threads, + }; - s->error = 0; + err = vmaf_init(&s->vmaf, cfg); -+ if (err) return AVERROR(EINVAL); ++ if (err) ++ return AVERROR(EINVAL); - s->vmaf_thread_created = 0; - pthread_mutex_init(&s->lock, NULL); - pthread_cond_init (&s->cond, NULL); -+ err = parse_models(ctx); -+ if (err) return err; ++ err = parse_deprecated_options(ctx); ++ if (err) ++ return err; ++ err = parse_models(ctx); ++ if (err) ++ return err; ++ + err = parse_features(ctx); -+ if (err) return err; ++ if (err) ++ return err; + s->fs.on_event = do_vmaf; return 0; } -@@ -251,8 +412,9 @@ static av_cold int init(AVFilterContext *ctx) - static int query_formats(AVFilterContext *ctx) - { - static const enum AVPixelFormat pix_fmts[] = { -- AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, -- AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV422P10LE, AV_PIX_FMT_YUV420P10LE, -+ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16LE, -+ AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P16LE, -+ AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P16LE, - AV_PIX_FMT_NONE - }; - -@@ -262,33 +424,32 @@ static int query_formats(AVFilterContext *ctx) - return ff_set_common_formats(ctx, fmts_list); - } +@@ -265,31 +554,36 @@ static int config_input_ref(AVFilterLink *inlink) -- static int config_input_ref(AVFilterLink *inlink) { - AVFilterContext *ctx = inlink->dst; + AVFilterContext *ctx = inlink->dst; LIBVMAFContext *s = ctx->priv; - int th; ++ const AVPixFmtDescriptor *desc; ++ int err = 0; - if (ctx->inputs[0]->w != ctx->inputs[1]->w || - ctx->inputs[0]->h != ctx->inputs[1]->h) { - av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n"); - return AVERROR(EINVAL); -+ int err = 0; -+ + if (ctx->inputs[0]->w != ctx->inputs[1]->w) { + av_log(ctx, AV_LOG_ERROR, "input width must match.\n"); + err |= AVERROR(EINVAL); } -+ -+ if (ctx->inputs[0]->h != ctx->inputs[1]->h) { -+ av_log(ctx, AV_LOG_ERROR, "input height must match.\n"); -+ err |= AVERROR(EINVAL); -+ } -+ if (ctx->inputs[0]->format != ctx->inputs[1]->format) { -- av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n"); -- return AVERROR(EINVAL); -+ av_log(ctx, AV_LOG_ERROR, "input pix_fmt must match.\n"); -+ err |= AVERROR(EINVAL); + av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n"); + return AVERROR(EINVAL); } - s->desc = av_pix_fmt_desc_get(inlink->format); - s->width = ctx->inputs[0]->w; - s->height = ctx->inputs[0]->h; -+ if (err) return err; ++ if (ctx->inputs[0]->h != ctx->inputs[1]->h) { ++ av_log(ctx, AV_LOG_ERROR, "input height must match.\n"); ++ err |= AVERROR(EINVAL); ++ } - th = pthread_create(&s->vmaf_thread, NULL, call_vmaf, (void *) s); - if (th) { - av_log(ctx, AV_LOG_ERROR, "Thread creation failed.\n"); - return AVERROR(EINVAL); -- } ++ if (ctx->inputs[0]->format != ctx->inputs[1]->format) { ++ av_log(ctx, AV_LOG_ERROR, "input pix_fmt must match.\n"); ++ err |= AVERROR(EINVAL); + } - s->vmaf_thread_created = 1; -+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); -+ s->bpc = desc->comp[0].depth; ++ if (err) ++ return err; ++ ++ desc = av_pix_fmt_desc_get(inlink->format); ++ s->bpc = desc->comp[0].depth; ++ return 0; } -@@ -320,35 +481,72 @@ static int activate(AVFilterContext *ctx) + +@@ -320,28 +614,80 @@ static int activate(AVFilterContext *ctx) return ff_framesync_activate(&s->fs); } +static enum VmafOutputFormat log_fmt_map(const char *log_fmt) +{ -+ if (av_stristr(log_fmt, "xml")) -+ return VMAF_OUTPUT_FORMAT_XML; -+ if (av_stristr(log_fmt, "json")) -+ return VMAF_OUTPUT_FORMAT_JSON; -+ if (av_stristr(log_fmt, "csv")) -+ return VMAF_OUTPUT_FORMAT_CSV; -+ if (av_stristr(log_fmt, "sub")) -+ return VMAF_OUTPUT_FORMAT_SUB; ++ if (log_fmt) { ++ if (av_stristr(log_fmt, "xml")) ++ return VMAF_OUTPUT_FORMAT_XML; ++ if (av_stristr(log_fmt, "json")) ++ return VMAF_OUTPUT_FORMAT_JSON; ++ if (av_stristr(log_fmt, "csv")) ++ return VMAF_OUTPUT_FORMAT_CSV; ++ if (av_stristr(log_fmt, "sub")) ++ return VMAF_OUTPUT_FORMAT_SUB; ++ } + + return VMAF_OUTPUT_FORMAT_XML; +} ++ ++static enum VmafPoolingMethod pool_method_map(const char *pool_method) ++{ ++ if (pool_method) { ++ if (av_stristr(pool_method, "min")) ++ return VMAF_POOL_METHOD_MIN; ++ if (av_stristr(pool_method, "mean")) ++ return VMAF_POOL_METHOD_MEAN; ++ if (av_stristr(pool_method, "harmonic_mean")) ++ return VMAF_POOL_METHOD_HARMONIC_MEAN; ++ } ++ ++ return VMAF_POOL_METHOD_MEAN; ++} + static av_cold void uninit(AVFilterContext *ctx) { LIBVMAFContext *s = ctx->priv; - + int err = 0; -+ + ff_framesync_uninit(&s->fs); - pthread_mutex_lock(&s->lock); - s->eof = 1; - pthread_cond_signal(&s->cond); - pthread_mutex_unlock(&s->lock); -+ if (!s->frame_cnt) goto clean_up; ++ if (!s->frame_cnt) ++ goto clean_up; - if (s->vmaf_thread_created) - { - pthread_join(s->vmaf_thread, NULL); - s->vmaf_thread_created = 0; + err = vmaf_read_pictures(s->vmaf, NULL, NULL, 0); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem flushing libvmaf context.\n"); } - av_frame_free(&s->gref); - av_frame_free(&s->gmain); + for (unsigned i = 0; i < s->model_cnt; i++) { + double vmaf_score; -+ err = vmaf_score_pooled(s->vmaf, s->model[i], VMAF_POOL_METHOD_MEAN, ++ err = vmaf_score_pooled(s->vmaf, s->model[i], pool_method_map(s->pool), + &vmaf_score, 0, s->frame_cnt - 1); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem getting pooled vmaf score.\n"); + } - pthread_mutex_destroy(&s->lock); - pthread_cond_destroy(&s->cond); + av_log(ctx, AV_LOG_INFO, "VMAF score: %f\n", vmaf_score); + } + + if (s->vmaf) { + if (s->log_path && !err) + vmaf_write_output(s->vmaf, s->log_path, log_fmt_map(s->log_fmt)); + } + +clean_up: + if (s->model) { + for (unsigned i = 0; i < s->model_cnt; i++) { + if (s->model[i]) + vmaf_model_destroy(s->model[i]); + } + av_free(s->model); + } + + if (s->vmaf) + vmaf_close(s->vmaf); } static const AVFilterPad libvmaf_inputs[] = { - { - .name = "main", - .type = AVMEDIA_TYPE_VIDEO, -- },{ -+ }, -+ { - .name = "reference", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_input_ref,