diff options
author | Arley Henostroza | 2019-12-09 14:54:08 -0500 |
---|---|---|
committer | Arley Henostroza | 2019-12-09 14:54:08 -0500 |
commit | 0014f5d3263c7021fd5527f1c0708c133452bea9 (patch) | |
tree | 36d90a7cb947228733db1ec22664b76284370b17 | |
download | aur-0014f5d3263c7021fd5527f1c0708c133452bea9.tar.gz |
init commit
-rw-r--r-- | .SRCINFO | 142 | ||||
-rw-r--r-- | LICENSE | 9 | ||||
-rw-r--r-- | PKGBUILD | 218 | ||||
-rw-r--r-- | ffmpeg-full-git-add-svt-av1-0.6.0.patch | 569 | ||||
-rw-r--r-- | ffmpeg-full-git-add-svt-hevc-1.4.1.patch | 601 | ||||
-rw-r--r-- | ffmpeg-full-git-add-svt-hevc-docs-1.4.1.patch | 198 | ||||
-rw-r--r-- | ffmpeg-full-git-add-svt-vp9-gce24589.patch | 624 |
7 files changed, 2361 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..51d8faa79a1a --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,142 @@ +pkgbase = ffmpeg-full-git + pkgdesc = Complete solution to record, convert and stream audio and video (all possible features including nvenc, qsv and libfdk-aac; git version) + pkgver = 4.3.r95713.g0e49560806 + pkgrel = 1 + url = https://www.ffmpeg.org/ + arch = x86_64 + license = custom: nonfree and unredistributable + makedepends = git + makedepends = nasm + makedepends = vmaf + makedepends = opencl-headers + makedepends = ffnvcodec-headers + makedepends = blackmagic-decklink-sdk + makedepends = amf-headers-git + depends = glibc + depends = alsa-lib + depends = jack + depends = libpng + depends = bzip2 + depends = frei0r-plugins + depends = libgcrypt + depends = gmp + depends = gnutls + depends = ladspa + depends = libass + depends = aom + depends = aribb24 + depends = libbluray + depends = libbs2b + depends = libcaca + depends = celt + depends = libcdio-paranoia + depends = codec2 + depends = dav1d + depends = libdc1394 + depends = libavc1394 + depends = libfdk-aac + depends = fontconfig + depends = freetype2 + depends = fribidi + depends = libgme + depends = gsm + depends = libilbc + depends = libiec61883 + depends = kvazaar + depends = lensfun + depends = libmodplug + depends = lame + depends = opencore-amr + depends = openjpeg2 + depends = opus + depends = pulseaudio + depends = librsvg + depends = rubberband + depends = rtmpdump + depends = snappy + depends = libsoxr + depends = speex + depends = srt + depends = libssh + depends = tensorflow + depends = tesseract + depends = libtheora + depends = twolame + depends = v4l-utils + depends = vid.stab + depends = libvorbis + depends = libvpx + depends = wavpack + depends = libwebp + depends = libx264.so + depends = x265 + depends = libxcb + depends = xvidcore + depends = libxml2 + depends = zimg + depends = zeromq + depends = zvbi + depends = lv2 + depends = lilv + depends = xz + depends = libmysofa + depends = openal + depends = ocl-icd + depends = libgl + depends = sndio + depends = sdl2 + depends = vapoursynth + depends = libxv + depends = libx11 + depends = libxext + depends = zlib + depends = cuda + depends = libomxil-bellagio + depends = libdrm + depends = intel-media-sdk + depends = libva + depends = libvdpau + depends = svt-hevc + depends = svt-av1 + depends = chromaprint-fftw + depends = davs2 + depends = flite1-patched + depends = libklvanc-git + depends = openh264 + depends = libopenmpt-svn + depends = rav1e + depends = shine + depends = vo-amrwbenc + depends = xavs + depends = xavs2 + depends = pocketsphinx + depends = rockchip-mpp + depends = svt-vp9-git + provides = libavcodec.so + provides = libavdevice.so + provides = libavfilter.so + provides = libavformat.so + provides = libavutil.so + provides = libpostproc.so + provides = libavresample.so + provides = libswscale.so + provides = libswresample.so + provides = ffmpeg + provides = ffmpeg-full + provides = ffmpeg-git + conflicts = ffmpeg + source = git+https://git.ffmpeg.org/ffmpeg.git + source = ffmpeg-full-git-add-svt-hevc-1.4.1.patch::https://raw.githubusercontent.com/OpenVisualCloud/SVT-HEVC/v1.4.1/ffmpeg_plugin/0001-lavc-svt_hevc-add-libsvt-hevc-encoder-wrapper.patch + source = ffmpeg-full-git-add-svt-hevc-docs-1.4.1.patch::https://raw.githubusercontent.com/OpenVisualCloud/SVT-HEVC/v1.4.1/ffmpeg_plugin/0002-doc-Add-libsvt_hevc-encoder-docs.patch + source = ffmpeg-full-git-add-svt-av1-0.6.0.patch::https://raw.githubusercontent.com/OpenVisualCloud/SVT-AV1/v0.6.0/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-av1-with-svt-hevc.patch + source = ffmpeg-full-git-add-svt-vp9-gce24589.patch::https://raw.githubusercontent.com/OpenVisualCloud/SVT-VP9/ce245894c6fc1c5d1439c41a7dda8d6dc61784c4/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-svt-hevc-av1.patch + source = LICENSE + sha256sums = SKIP + sha256sums = d2db0acbdb0773f3883746cd25996905ff0a3f539d9b434fe314f883856ad883 + sha256sums = 1499e419dda72b1604dc5e3959668f3843292ff56bfba78734e31510ba576de0 + sha256sums = 102a70c5c453875f5806ce02cc83fdc74e53c078cf5be2657f3dd1dd4438868c + sha256sums = 7690a4f6bdc4a57e35c7ff5b6e87f2fe6d056d452eff9e767eaccff41832f4d7 + sha256sums = 04a7176400907fd7db0d69116b99de49e582a6e176b3bfb36a03e50a4cb26a36 + +pkgname = ffmpeg-full-git + diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..b0bb658ca78c --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +This software is nonfree and unredistributable. + +The end-user must compile this software for himself in order to be allowed to use it. + +This software cannot be redistributed. + +This software cannot be used commercially. + +Due to the libraries used to compile this software, the resulting binaries and libraries are under a complex and restrictive license mix. diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..33261ac9b474 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,218 @@ +# Maintainer: Arley Henostroza < arllk at gmail dot com > +# Contributor: Daniel Bermond < gmail-com: danielbermond > + +_svt_hevc_ver='1.4.1' +_svt_av1_ver='0.6.0' +_svt_vp9_ver='ce245894c6fc1c5d1439c41a7dda8d6dc61784c4' + +pkgname=ffmpeg-intel-full-git +pkgver=4.3.r95997.g9f7b2b37e3 +pkgrel=1 +pkgdesc='Complete solution to record, convert and stream audio and video (all possible features for intel; git version)' +arch=('x86_64') +url='https://www.ffmpeg.org/' +license=('custom: nonfree and unredistributable') +depends=( + # official repositories: + 'glibc' 'alsa-lib' 'jack' 'libpng' + 'bzip2' 'frei0r-plugins' 'libgcrypt' 'gmp' 'gnutls' 'ladspa' 'libass' 'aom' + 'aribb24' 'libbluray' 'libbs2b' 'libcaca' 'celt' 'libcdio-paranoia' 'codec2' + 'dav1d' 'libdc1394' 'libavc1394' 'libfdk-aac' 'fontconfig' 'freetype2' 'fribidi' + 'libgme' 'gsm' 'libilbc' 'libiec61883' 'kvazaar' 'lensfun' 'libmodplug' 'lame' + 'opencore-amr' 'openjpeg2' 'opus' 'pulseaudio' 'librsvg' 'rubberband' 'rtmpdump' + 'snappy' 'libsoxr' 'speex' 'srt' 'libssh' 'tensorflow' 'tesseract' 'libtheora' + 'twolame' 'v4l-utils' 'vid.stab' 'libvorbis' 'libvpx' 'wavpack' 'libwebp' + 'libx264.so' 'x265' 'libxcb' 'xvidcore' 'libxml2' 'zimg' 'zeromq' 'zvbi' 'lv2' + 'lilv' 'xz' 'libmysofa' 'openal' 'ocl-icd' 'libgl' 'sndio' 'sdl2' 'vapoursynth' + 'libxv' 'libx11' 'libxext' 'zlib' 'libomxil-bellagio' 'libdrm' + 'intel-media-sdk' 'libva' 'libvdpau' 'svt-hevc' 'svt-av1' + # AUR: + 'chromaprint-fftw' 'davs2' 'flite1-patched' 'libklvanc-git' 'openh264' + 'libopenmpt-svn' 'rav1e' 'shine' 'vo-amrwbenc' 'xavs' 'xavs2' 'pocketsphinx' + 'svt-vp9-git' +) +makedepends=( + # official repositories: + 'git' 'nasm' 'vmaf' 'opencl-headers' + # AUR: + 'blackmagic-decklink-sdk' +) +provides=('libavcodec.so' 'libavdevice.so' 'libavfilter.so' 'libavformat.so' + 'libavutil.so' 'libpostproc.so' 'libavresample.so' 'libswscale.so' + 'libswresample.so' 'ffmpeg' 'ffmpeg-full' 'ffmpeg-git' 'ffmpeg-intel') +conflicts=('ffmpeg') +source=('git+https://git.ffmpeg.org/ffmpeg.git' + "ffmpeg-full-git-add-svt-hevc-${_svt_hevc_ver}.patch"::"https://raw.githubusercontent.com/OpenVisualCloud/SVT-HEVC/v${_svt_hevc_ver}/ffmpeg_plugin/0001-lavc-svt_hevc-add-libsvt-hevc-encoder-wrapper.patch" + "ffmpeg-full-git-add-svt-hevc-docs-${_svt_hevc_ver}.patch"::"https://raw.githubusercontent.com/OpenVisualCloud/SVT-HEVC/v${_svt_hevc_ver}/ffmpeg_plugin/0002-doc-Add-libsvt_hevc-encoder-docs.patch" + "ffmpeg-full-git-add-svt-av1-${_svt_av1_ver}.patch"::"https://raw.githubusercontent.com/OpenVisualCloud/SVT-AV1/v${_svt_av1_ver}/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-av1-with-svt-hevc.patch" + "ffmpeg-full-git-add-svt-vp9-g${_svt_vp9_ver:0:7}.patch"::"https://raw.githubusercontent.com/OpenVisualCloud/SVT-VP9/${_svt_vp9_ver}/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-svt-hevc-av1.patch" + 'LICENSE') +sha256sums=('SKIP' + 'd2db0acbdb0773f3883746cd25996905ff0a3f539d9b434fe314f883856ad883' + '1499e419dda72b1604dc5e3959668f3843292ff56bfba78734e31510ba576de0' + '102a70c5c453875f5806ce02cc83fdc74e53c078cf5be2657f3dd1dd4438868c' + '7690a4f6bdc4a57e35c7ff5b6e87f2fe6d056d452eff9e767eaccff41832f4d7' + '04a7176400907fd7db0d69116b99de49e582a6e176b3bfb36a03e50a4cb26a36') + +prepare() { + cd ffmpeg + + # add svt codec support for hevc, av1 and vp9 + git apply --index "${srcdir}/ffmpeg-full-git-add-svt-hevc-${_svt_hevc_ver}.patch" + patch -Np1 -i "${srcdir}/ffmpeg-full-git-add-svt-hevc-docs-${_svt_hevc_ver}.patch" + git apply --index "${srcdir}/ffmpeg-full-git-add-svt-av1-${_svt_av1_ver}.patch" + git apply --index "${srcdir}/ffmpeg-full-git-add-svt-vp9-g${_svt_vp9_ver:0:7}.patch" +} + +pkgver() { + cd ffmpeg + + local _version + local _revision + local _shorthash + + _version="$( git describe --tags --long | awk -F'-' '{ sub(/^n/, "", $1); print $1 }')" + _revision="$( git describe --tags --match 'N' | awk -F'-' '{ print $2 }')" + _shorthash="$(git rev-parse --short HEAD)" + + printf '%s.r%s.g%s' "$_version" "$_revision" "$_shorthash" +} + +build() { + cd ffmpeg + + export PKG_CONFIG_PATH="${PKG_CONFIG_PATH:+${PKG_CONFIG_PATH}:}/opt/intel/mediasdk/lib/pkgconfig" + + printf '%s\n' ' -> Running ffmpeg configure script...' + + ./configure \ + --prefix='/usr' \ + --extra-cflags='-I/usr/include/tensorflow' \ + \ + --disable-rpath \ + --enable-gpl \ + --enable-version3 \ + --enable-nonfree \ + --enable-shared \ + --disable-static \ + --disable-stripping \ + --enable-gray \ + --enable-avresample \ + \ + --enable-alsa \ + --enable-avisynth \ + --enable-bzlib \ + --enable-chromaprint \ + --enable-frei0r \ + --enable-gcrypt \ + --enable-gmp \ + --enable-gnutls \ + --enable-iconv \ + --enable-ladspa \ + --enable-libaom \ + --enable-libaribb24 \ + --enable-libass \ + --enable-libbluray \ + --enable-libbs2b \ + --enable-libcaca \ + --enable-libcelt \ + --enable-libcdio \ + --enable-libcodec2 \ + --enable-libdav1d \ + --enable-libdavs2 \ + --enable-libdc1394 \ + --enable-libfdk-aac \ + --enable-libflite \ + --enable-fontconfig \ + --enable-libfreetype \ + --enable-libfribidi \ + --enable-libgme \ + --enable-libgsm \ + --enable-libiec61883 \ + --enable-libilbc \ + --enable-libjack \ + --enable-libklvanc \ + --enable-libkvazaar \ + --enable-liblensfun \ + --enable-libmodplug \ + --enable-libmp3lame \ + --enable-libopencore-amrnb \ + --enable-libopencore-amrwb \ + --disable-libopencv \ + --enable-libopenh264 \ + --enable-libopenjpeg \ + --enable-libopenmpt \ + --enable-libopus \ + --enable-libpulse \ + --enable-librav1e \ + --enable-librsvg \ + --enable-librubberband \ + --enable-librtmp \ + --enable-libshine \ + --disable-libsmbclient \ + --enable-libsnappy \ + --enable-libsoxr \ + --enable-libspeex \ + --enable-libsrt \ + --enable-libssh \ + --enable-libsvthevc \ + --enable-libsvtav1 \ + --enable-libsvtvp9 \ + --enable-libtensorflow \ + --enable-libtesseract \ + --enable-libtheora \ + --disable-libtls \ + --enable-libtwolame \ + --enable-libv4l2 \ + --enable-libvidstab \ + --enable-libvmaf \ + --enable-libvo-amrwbenc \ + --enable-libvorbis \ + --enable-libvpx \ + --enable-libwavpack \ + --enable-libwebp \ + --enable-libx264 \ + --enable-libx265 \ + --enable-libxavs \ + --enable-libxavs2 \ + --enable-libxcb \ + --enable-libxcb-shm \ + --enable-libxcb-xfixes \ + --enable-libxcb-shape \ + --enable-libxvid \ + --enable-libxml2 \ + --enable-libzimg \ + --enable-libzmq \ + --enable-libzvbi \ + --enable-lv2 \ + --enable-lzma \ + --enable-decklink \ + --disable-mbedtls \ + --enable-libmysofa \ + --enable-openal \ + --enable-opencl \ + --enable-opengl \ + --disable-openssl \ + --enable-pocketsphinx \ + --enable-sndio \ + --enable-sdl2 \ + --enable-vapoursynth \ + --enable-xlib \ + --enable-zlib \ + \ + --enable-libdrm \ + --enable-libmfx \ + --enable-omx \ + --enable-v4l2-m2m \ + --enable-vaapi \ + --enable-vdpau + + make + make tools/qt-faststart +} + +package() { + make -C ffmpeg DESTDIR="$pkgdir" install + install -D -m755 ffmpeg/tools/qt-faststart -t "${pkgdir}/usr/bin" + install -D -m644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}" +} diff --git a/ffmpeg-full-git-add-svt-av1-0.6.0.patch b/ffmpeg-full-git-add-svt-av1-0.6.0.patch new file mode 100644 index 000000000000..35b47610ce18 --- /dev/null +++ b/ffmpeg-full-git-add-svt-av1-0.6.0.patch @@ -0,0 +1,569 @@ +From 64932c76e3dd36f010b1643a70abcceae7fdfca8 Mon Sep 17 00:00:00 2001 +From: Daryl Seah <daryl.seah@intel.com> +Date: Fri, 18 Jan 2019 02:11:38 +0000 +Subject: [PATCH] Add ability for ffmpeg to run svt-av1 with svt-hevc + +Change-Id: I37ee5414fdd99e0b3f112a6e5ede166f3e48d819 +Signed-off-by: Daryl Seah <daryl.seah@intel.com> +Signed-off-by: Jing SUN <jing.a.sun@intel.com> +--- + configure | 4 + + libavcodec/Makefile | 1 + + libavcodec/allcodecs.c | 1 + + libavcodec/libsvt_av1.c | 484 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 490 insertions(+) + create mode 100644 libavcodec/libsvt_av1.c + +diff --git a/configure b/configure +index 2f61c8296e..87e6696523 100755 +--- a/configure ++++ b/configure +@@ -263,6 +263,7 @@ External library support: + --enable-libsrt enable Haivision SRT protocol via libsrt [no] + --enable-libssh enable SFTP protocol via libssh [no] + --enable-libsvthevc enable HEVC encoding via svt [no] ++ --enable-libsvtav1 enable AV1 encoding via svt [no] + --enable-libtensorflow enable TensorFlow as a DNN module backend + for DNN based filters like sr [no] + --enable-libtesseract enable Tesseract, needed for ocr filter [no] +@@ -1745,6 +1746,7 @@ EXTERNAL_LIBRARY_LIST=" + libsrt + libssh + libsvthevc ++ libsvtav1 + libtensorflow + libtesseract + libtheora +@@ -3128,6 +3130,7 @@ libspeex_decoder_deps="libspeex" + libspeex_encoder_deps="libspeex" + libspeex_encoder_select="audio_frame_queue" + libsvt_hevc_encoder_deps="libsvthevc" ++libsvt_av1_encoder_deps="libsvtav1" + libtheora_encoder_deps="libtheora" + libtwolame_encoder_deps="libtwolame" + libvo_amrwbenc_encoder_deps="libvo_amrwbenc" +@@ -6139,6 +6142,7 @@ enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp + enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init + enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket + enabled libsvthevc && require_pkg_config libsvthevc SvtHevcEnc EbApi.h EbInitHandle ++enabled libsvtav1 && require_pkg_config libsvtav1 SvtAv1Enc EbSvtAv1Enc.h eb_init_handle + enabled libtensorflow && require libtensorflow tensorflow/c/c_api.h TF_Version -ltensorflow + enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate + enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 728503be9c..a524f34d9c 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -982,6 +982,7 @@ OBJS-$(CONFIG_LIBSHINE_ENCODER) += libshine.o + OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o + OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o + OBJS-$(CONFIG_LIBSVT_HEVC_ENCODER) += libsvt_hevc.o ++OBJS-$(CONFIG_LIBSVT_AV1_ENCODER) += libsvt_av1.o + OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o + OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o + OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o +diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c +index 5739d53329..98f0c99883 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -698,6 +698,7 @@ extern AVCodec ff_libshine_encoder; + extern AVCodec ff_libspeex_encoder; + extern AVCodec ff_libspeex_decoder; + extern AVCodec ff_libsvt_hevc_encoder; ++extern AVCodec ff_libsvt_av1_encoder; + extern AVCodec ff_libtheora_encoder; + extern AVCodec ff_libtwolame_encoder; + extern AVCodec ff_libvo_amrwbenc_encoder; +diff --git a/libavcodec/libsvt_av1.c b/libavcodec/libsvt_av1.c +new file mode 100644 +index 0000000000..a044c1eac5 +--- /dev/null ++++ b/libavcodec/libsvt_av1.c +@@ -0,0 +1,484 @@ ++/* ++* Scalable Video Technology for AV1 encoder library plugin ++* ++* Copyright (c) 2018 Intel Corporation ++* ++* This file is part of FFmpeg. ++* ++* FFmpeg is free software; you can redistribute it and/or ++* modify it under the terms of the GNU Lesser General Public ++* License as published by the Free Software Foundation; either ++* version 2.1 of the License, or (at your option) any later version. ++* ++* FFmpeg is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++* Lesser General Public License for more details. ++* ++* You should have received a copy of the GNU Lesser General Public ++* License along with this program; if not, write to the Free Software ++* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++*/ ++ ++#include <stdint.h> ++#include "EbSvtAv1ErrorCodes.h" ++#include "EbSvtAv1Enc.h" ++ ++#include "libavutil/common.h" ++#include "libavutil/frame.h" ++#include "libavutil/opt.h" ++ ++#include "internal.h" ++#include "avcodec.h" ++ ++typedef struct SvtContext { ++ AVClass *class; ++ ++ EbSvtAv1EncConfiguration enc_params; ++ EbComponentType *svt_handle; ++ ++ EbBufferHeaderType *in_buf; ++ int raw_size; ++ ++ int eos_flag; ++ ++ // User options. ++ int hierarchical_level; ++ int la_depth; ++ int enc_mode; ++ int rc_mode; ++ int scd; ++ int qp; ++ ++ int forced_idr; ++ ++ int aud; ++ ++ int tier; ++ int level; ++ ++ int base_layer_switch_mode; ++} SvtContext; ++ ++static int error_mapping(EbErrorType svt_ret) ++{ ++ int err; ++ ++ switch (svt_ret) { ++ case EB_ErrorInsufficientResources: ++ err = AVERROR(ENOMEM); ++ break; ++ ++ case EB_ErrorUndefined: ++ case EB_ErrorInvalidComponent: ++ case EB_ErrorBadParameter: ++ err = AVERROR(EINVAL); ++ break; ++ ++ case EB_ErrorDestroyThreadFailed: ++ case EB_ErrorSemaphoreUnresponsive: ++ case EB_ErrorDestroySemaphoreFailed: ++ case EB_ErrorCreateMutexFailed: ++ case EB_ErrorMutexUnresponsive: ++ case EB_ErrorDestroyMutexFailed: ++ err = AVERROR_EXTERNAL; ++ break; ++ ++ case EB_NoErrorEmptyQueue: ++ err = AVERROR(EAGAIN); ++ ++ case EB_ErrorNone: ++ err = 0; ++ break; ++ ++ default: ++ err = AVERROR_UNKNOWN; ++ } ++ ++ return err; ++} ++ ++static void free_buffer(SvtContext *svt_enc) ++{ ++ if (svt_enc->in_buf) { ++ EbSvtIOFormat *in_data = (EbSvtIOFormat *)svt_enc->in_buf->p_buffer; ++ av_freep(&in_data); ++ av_freep(&svt_enc->in_buf); ++ } ++} ++ ++static int alloc_buffer(EbSvtAv1EncConfiguration *config, SvtContext *svt_enc) ++{ ++ const int pack_mode_10bit = ++ (config->encoder_bit_depth > 8) && (config->compressed_ten_bit_format == 0) ? 1 : 0; ++ const size_t luma_size_8bit = ++ config->source_width * config->source_height * (1 << pack_mode_10bit); ++ const size_t luma_size_10bit = ++ (config->encoder_bit_depth > 8 && pack_mode_10bit == 0) ? luma_size_8bit : 0; ++ ++ EbSvtIOFormat *in_data; ++ ++ svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2; ++ ++ // allocate buffer for in and out ++ svt_enc->in_buf = av_mallocz(sizeof(*svt_enc->in_buf)); ++ if (!svt_enc->in_buf) ++ goto failed; ++ ++ in_data = av_mallocz(sizeof(*in_data)); ++ if (!in_data) ++ goto failed; ++ svt_enc->in_buf->p_buffer = (unsigned char *)in_data; ++ ++ svt_enc->in_buf->size = sizeof(*svt_enc->in_buf); ++ svt_enc->in_buf->p_app_private = NULL; ++ ++ return 0; ++ ++failed: ++ free_buffer(svt_enc); ++ return AVERROR(ENOMEM); ++} ++ ++static int config_enc_params(EbSvtAv1EncConfiguration *param, ++ AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ int ret; ++ int ten_bits = 0; ++ ++ param->source_width = avctx->width; ++ param->source_height = avctx->height; ++ ++ if (avctx->pix_fmt == AV_PIX_FMT_YUV420P10LE) { ++ av_log(avctx, AV_LOG_DEBUG , "Encoder 10 bits depth input\n"); ++ // Disable Compressed 10-bit format default ++ // ++ // SVT-AV1 support a compressed 10-bit format allowing the ++ // software to achieve a higher speed and channel density levels. ++ // The conversion between the 10-bit yuv420p10le and the compressed ++ // 10-bit format is a lossless operation. But in FFmpeg, we usually ++ // didn't use this format ++ param->compressed_ten_bit_format = 0; ++ ten_bits = 1; ++ } ++ ++ // Update param from options ++ param->hierarchical_levels = svt_enc->hierarchical_level; ++ param->enc_mode = svt_enc->enc_mode; ++ param->tier = svt_enc->tier; ++ param->level = svt_enc->level; ++ param->rate_control_mode = svt_enc->rc_mode; ++ param->scene_change_detection = svt_enc->scd; ++ param->base_layer_switch_mode = svt_enc->base_layer_switch_mode; ++ param->qp = svt_enc->qp; ++ ++ ++ param->target_bit_rate = avctx->bit_rate; ++ if (avctx->gop_size > 0) ++ param->intra_period_length = avctx->gop_size - 1; ++ ++ if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { ++ param->frame_rate_numerator = avctx->framerate.num; ++ param->frame_rate_denominator = avctx->framerate.den * avctx->ticks_per_frame; ++ } else { ++ param->frame_rate_numerator = avctx->time_base.den; ++ param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; ++ } ++ ++ if (param->rate_control_mode) { ++ param->max_qp_allowed = avctx->qmax; ++ param->min_qp_allowed = avctx->qmin; ++ } ++ ++ param->intra_refresh_type = ++ !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) + 1; ++ ++ if (svt_enc->la_depth != -1) ++ param->look_ahead_distance = svt_enc->la_depth; ++ ++ if (ten_bits) { ++ param->encoder_bit_depth = 10; ++ } ++ ++ ret = alloc_buffer(param, svt_enc); ++ ++ return ret; ++} ++ ++static void read_in_data(EbSvtAv1EncConfiguration *config, ++ const AVFrame *frame, ++ EbBufferHeaderType *headerPtr) ++{ ++ uint8_t is16bit = config->encoder_bit_depth > 8; ++ uint64_t luma_size = ++ (uint64_t)config->source_width * config->source_height<< is16bit; ++ EbSvtIOFormat *in_data = (EbSvtIOFormat *)headerPtr->p_buffer; ++ ++ // support yuv420p and yuv420p010 ++ in_data->luma = frame->data[0]; ++ in_data->cb = frame->data[1]; ++ in_data->cr = frame->data[2]; ++ ++ // stride info ++ in_data->y_stride = frame->linesize[0] >> is16bit; ++ in_data->cb_stride = frame->linesize[1] >> is16bit; ++ in_data->cr_stride = frame->linesize[2] >> is16bit; ++ ++ headerPtr->n_filled_len += luma_size * 3/2u; ++} ++ ++static av_cold int eb_enc_init(AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EbErrorType svt_ret; ++ ++ svt_enc->eos_flag = 0; ++ ++ svt_ret = eb_init_handle(&svt_enc->svt_handle, svt_enc, &svt_enc->enc_params); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error init encoder handle\n"); ++ goto failed; ++ } ++ ++ svt_ret = config_enc_params(&svt_enc->enc_params, avctx); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error configure encoder parameters\n"); ++ goto failed_init_handle; ++ } ++ ++ svt_ret = eb_svt_enc_set_parameter(svt_enc->svt_handle, &svt_enc->enc_params); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error setting encoder parameters\n"); ++ goto failed_init_handle; ++ } ++ ++ svt_ret = eb_init_encoder(svt_enc->svt_handle); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error init encoder\n"); ++ goto failed_init_handle; ++ } ++ ++ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { ++ EbBufferHeaderType *headerPtr = NULL; ++ ++ svt_ret = eb_svt_enc_stream_header(svt_enc->svt_handle, &headerPtr); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error when build stream header.\n"); ++ goto failed_init_enc; ++ } ++ ++ avctx->extradata_size = headerPtr->n_filled_len; ++ avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); ++ if (!avctx->extradata) { ++ av_log(avctx, AV_LOG_ERROR, ++ "Cannot allocate AV1 header of size %d.\n", avctx->extradata_size); ++ svt_ret = EB_ErrorInsufficientResources; ++ goto failed_init_enc; ++ } ++ ++ memcpy(avctx->extradata, headerPtr->p_buffer, avctx->extradata_size); ++ ++ svt_ret = eb_svt_release_enc_stream_header(headerPtr); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error when destroy stream header.\n"); ++ goto failed_init_enc; ++ } ++ } ++ ++ return 0; ++ ++failed_init_enc: ++ eb_deinit_encoder(svt_enc->svt_handle); ++failed_init_handle: ++ eb_deinit_handle(svt_enc->svt_handle); ++failed: ++ free_buffer(svt_enc); ++ return error_mapping(svt_ret); ++} ++ ++static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EbBufferHeaderType *headerPtr = svt_enc->in_buf; ++ ++ if (!frame) { ++ EbBufferHeaderType headerPtrLast; ++ headerPtrLast.n_alloc_len = 0; ++ headerPtrLast.n_filled_len = 0; ++ headerPtrLast.n_tick_count = 0; ++ headerPtrLast.p_app_private = NULL; ++ headerPtrLast.p_buffer = NULL; ++ headerPtrLast.flags = EB_BUFFERFLAG_EOS; ++ ++ eb_svt_enc_send_picture(svt_enc->svt_handle, &headerPtrLast); ++ svt_enc->eos_flag = 1; ++ av_log(avctx, AV_LOG_DEBUG, "Finish sending frames!!!\n"); ++ return 0; ++ } ++ ++ read_in_data(&svt_enc->enc_params, frame, headerPtr); ++ ++ headerPtr->flags = 0; ++ headerPtr->p_app_private = NULL; ++ headerPtr->pts = frame->pts; ++ switch (frame->pict_type) { ++ case AV_PICTURE_TYPE_I: ++ headerPtr->pic_type = svt_enc->forced_idr > 0 ? EB_AV1_KEY_PICTURE : EB_AV1_INTRA_ONLY_PICTURE; ++ break; ++ case AV_PICTURE_TYPE_P: ++ headerPtr->pic_type = EB_AV1_ALT_REF_PICTURE; ++ break; ++ case AV_PICTURE_TYPE_B: ++ headerPtr->pic_type = EB_AV1_INTER_PICTURE; ++ break; ++ default: ++ headerPtr->pic_type = EB_AV1_INVALID_PICTURE; ++ break; ++ } ++ eb_svt_enc_send_picture(svt_enc->svt_handle, headerPtr); ++ ++ return 0; ++} ++ ++static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EbBufferHeaderType *headerPtr; ++ EbErrorType svt_ret; ++ int ret; ++ ++ if ((ret = ff_alloc_packet2(avctx, pkt, svt_enc->raw_size, 0)) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); ++ return ret; ++ } ++ svt_ret = eb_svt_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag); ++ if (svt_ret == EB_NoErrorEmptyQueue) ++ return AVERROR(EAGAIN); ++ ++ memcpy(pkt->data, headerPtr->p_buffer, headerPtr->n_filled_len); ++ pkt->size = headerPtr->n_filled_len; ++ pkt->pts = headerPtr->pts; ++ pkt->dts = headerPtr->dts; ++ if (headerPtr->pic_type == EB_AV1_KEY_PICTURE) ++ pkt->flags |= AV_PKT_FLAG_KEY; ++ if (headerPtr->pic_type == EB_AV1_NON_REF_PICTURE) ++ pkt->flags |= AV_PKT_FLAG_DISPOSABLE; ++ ++ ret = (headerPtr->flags & EB_BUFFERFLAG_EOS) ? AVERROR_EOF : 0; ++ ++ eb_svt_release_out_buffer(&headerPtr); ++ ++ return ret; ++} ++ ++static av_cold int eb_enc_close(AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ ++ eb_deinit_encoder(svt_enc->svt_handle); ++ eb_deinit_handle(svt_enc->svt_handle); ++ ++ free_buffer(svt_enc); ++ ++ return 0; ++} ++ ++#define OFFSET(x) offsetof(SvtContext, x) ++#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM ++static const AVOption options[] = { ++ { "aud", "Include AUD", OFFSET(aud), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, ++ ++ { "hielevel", "Hierarchical prediction levels setting", OFFSET(hierarchical_level), ++ AV_OPT_TYPE_INT, { .i64 = 4 }, 3, 4, VE , "hielevel"}, ++ { "flat", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "hielevel" }, ++ { "2level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "hielevel" }, ++ { "3level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "hielevel" }, ++ { "4level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 4 }, INT_MIN, INT_MAX, VE, "hielevel" }, ++ ++ { "la_depth", "Look ahead distance [0, 256]", OFFSET(la_depth), ++ AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 256, VE }, ++ ++ { "preset", "Encoding preset [0, 7]", ++ OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = MAX_ENC_PRESET }, 0, MAX_ENC_PRESET, VE }, ++ ++ { "tier", "Set tier (general_tier_flag)", OFFSET(tier), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "tier" }, ++ { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "tier" }, ++ { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "tier" }, ++ ++ { "level", "Set level (level_idc)", OFFSET(level), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xff, VE, "level" }, ++ ++#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ ++ { .i64 = value }, 0, 0, VE, "level" ++ { LEVEL("1", 10) }, ++ { LEVEL("2", 20) }, ++ { LEVEL("2.1", 21) }, ++ { LEVEL("3", 30) }, ++ { LEVEL("3.1", 31) }, ++ { LEVEL("4", 40) }, ++ { LEVEL("4.1", 41) }, ++ { LEVEL("5", 50) }, ++ { LEVEL("5.1", 51) }, ++ { LEVEL("5.2", 52) }, ++ { LEVEL("6", 60) }, ++ { LEVEL("6.1", 61) }, ++ { LEVEL("6.2", 62) }, ++#undef LEVEL ++ ++ { "rc", "Bit rate control mode", OFFSET(rc_mode), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE , "rc"}, ++ { "cqp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "rc" }, ++ { "vbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "rc" }, ++ ++ { "qp", "QP value for intra frames", OFFSET(qp), ++ AV_OPT_TYPE_INT, { .i64 = 50 }, 0, 63, VE }, ++ ++ { "sc_detection", "Scene change detection", OFFSET(scd), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, ++ ++ { "bl_mode", "Random Access Prediction Structure type setting", OFFSET(base_layer_switch_mode), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, ++ ++ { "forced-idr", "If forcing keyframes, force them as IDR frames.", OFFSET(forced_idr), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, ++ ++ {NULL}, ++}; ++ ++static const AVClass class = { ++ .class_name = "libsvt_av1", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++}; ++ ++static const AVCodecDefault eb_enc_defaults[] = { ++ { "b", "7M" }, ++ { "g", "-2" }, ++ { "flags", "-cgop" }, ++ { "qmin", "0" }, ++ { "qmax", "63" }, ++ { NULL }, ++}; ++ ++AVCodec ff_libsvt_av1_encoder = { ++ .name = "libsvt_av1", ++ .long_name = NULL_IF_CONFIG_SMALL("SVT-AV1(Scalable Video Technology for AV1) encoder"), ++ .priv_data_size = sizeof(SvtContext), ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_AV1, ++ .init = eb_enc_init, ++ .send_frame = eb_send_frame, ++ .receive_packet = eb_receive_packet, ++ .close = eb_enc_close, ++ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, ++ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, ++ AV_PIX_FMT_NONE }, ++ .priv_class = &class, ++ .defaults = eb_enc_defaults, ++ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, ++ .wrapper_name = "libsvt_av1", ++}; +-- +2.20.1 + diff --git a/ffmpeg-full-git-add-svt-hevc-1.4.1.patch b/ffmpeg-full-git-add-svt-hevc-1.4.1.patch new file mode 100644 index 000000000000..ec55044854f2 --- /dev/null +++ b/ffmpeg-full-git-add-svt-hevc-1.4.1.patch @@ -0,0 +1,601 @@ +From 3248aee7fc94304cd5f41afa8dc502d92ae080ef Mon Sep 17 00:00:00 2001 +From: Jing Sun <jing.a.sun@intel.com> +Date: Wed, 21 Nov 2018 11:33:04 +0800 +Subject: [PATCH 1/1] lavc/svt_hevc: add libsvt hevc encoder wrapper + +Signed-off-by: Zhengxu Huang <zhengxu.huang@intel.com> +Signed-off-by: Hassene Tmar <hassene.tmar@intel.com> +Signed-off-by: Jun Zhao <jun.zhao@intel.com> +Signed-off-by: Jing Sun <jing.a.sun@intel.com> +--- + configure | 4 + + libavcodec/Makefile | 1 + + libavcodec/allcodecs.c | 1 + + libavcodec/libsvt_hevc.c | 515 +++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 521 insertions(+) + create mode 100644 libavcodec/libsvt_hevc.c + +diff --git a/configure b/configure +index c09c842..648ea80 100755 +--- a/configure ++++ b/configure +@@ -264,6 +264,7 @@ External library support: + --enable-libspeex enable Speex de/encoding via libspeex [no] + --enable-libsrt enable Haivision SRT protocol via libsrt [no] + --enable-libssh enable SFTP protocol via libssh [no] ++ --enable-libsvthevc enable HEVC encoding via svt [no] + --enable-libtensorflow enable TensorFlow as a DNN module backend + for DNN based filters like sr [no] + --enable-libtesseract enable Tesseract, needed for ocr filter [no] +@@ -1793,6 +1794,7 @@ EXTERNAL_LIBRARY_LIST=" + libspeex + libsrt + libssh ++ libsvthevc + libtensorflow + libtesseract + libtheora +@@ -3194,6 +3196,7 @@ libshine_encoder_select="audio_frame_queue" + libspeex_decoder_deps="libspeex" + libspeex_encoder_deps="libspeex" + libspeex_encoder_select="audio_frame_queue" ++libsvt_hevc_encoder_deps="libsvthevc" + libtheora_encoder_deps="libtheora" + libtwolame_encoder_deps="libtwolame" + libvo_amrwbenc_encoder_deps="libvo_amrwbenc" +@@ -6269,6 +6272,7 @@ enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr + enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp_init + enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init + enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket ++enabled libsvthevc && require_pkg_config libsvthevc SvtHevcEnc EbApi.h EbInitHandle + enabled libtensorflow && require libtensorflow tensorflow/c/c_api.h TF_Version -ltensorflow + enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate + enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 3cd73fb..d39f568 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -991,6 +991,7 @@ OBJS-$(CONFIG_LIBOPUS_ENCODER) += libopusenc.o libopus.o \ + OBJS-$(CONFIG_LIBSHINE_ENCODER) += libshine.o + OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o + OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o ++OBJS-$(CONFIG_LIBSVT_HEVC_ENCODER) += libsvt_hevc.o + OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o + OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o + OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o +diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c +index d2f9a39..d8788a7 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -707,6 +707,7 @@ extern AVCodec ff_librsvg_decoder; + extern AVCodec ff_libshine_encoder; + extern AVCodec ff_libspeex_encoder; + extern AVCodec ff_libspeex_decoder; ++extern AVCodec ff_libsvt_hevc_encoder; + extern AVCodec ff_libtheora_encoder; + extern AVCodec ff_libtwolame_encoder; + extern AVCodec ff_libvo_amrwbenc_encoder; +diff --git a/libavcodec/libsvt_hevc.c b/libavcodec/libsvt_hevc.c +new file mode 100644 +index 0000000..77eae48 +--- /dev/null ++++ b/libavcodec/libsvt_hevc.c +@@ -0,0 +1,515 @@ ++/* ++* Scalable Video Technology for HEVC encoder library plugin ++* ++* Copyright (c) 2019 Intel Corporation ++* ++* This file is part of FFmpeg. ++* ++* FFmpeg is free software; you can redistribute it and/or ++* modify it under the terms of the GNU Lesser General Public ++* License as published by the Free Software Foundation; either ++* version 2.1 of the License, or (at your option) any later version. ++* ++* FFmpeg is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++* Lesser General Public License for more details. ++* ++* You should have received a copy of the GNU Lesser General Public ++* License along with this program; if not, write to the Free Software ++* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++*/ ++ ++#include "EbApi.h" ++ ++#include "libavutil/common.h" ++#include "libavutil/frame.h" ++#include "libavutil/opt.h" ++ ++#include "internal.h" ++#include "avcodec.h" ++ ++typedef enum eos_status { ++ EOS_NOT_REACHED = 0, ++ EOS_SENT, ++ EOS_RECEIVED ++}EOS_STATUS; ++ ++typedef struct SvtContext { ++ AVClass *class; ++ ++ EB_H265_ENC_CONFIGURATION enc_params; ++ EB_COMPONENTTYPE *svt_handle; ++ EB_BUFFERHEADERTYPE in_buf; ++ uint8_t *in_data; ++ EOS_STATUS eos_flag; ++ ++ // User options. ++ int profile; ++ int hierarchical_level; ++ int enc_mode; ++ int tier; ++ int level; ++ int rc_mode; ++ int scd; ++ int tune; ++ int base_layer_switch_mode; ++ int qp; ++ int aud; ++ int asm_type; ++ int forced_idr; ++ int la_depth; ++ int thread_count; ++} SvtContext; ++ ++static int error_mapping(EB_ERRORTYPE svt_ret) ++{ ++ switch (svt_ret) { ++ case EB_ErrorInsufficientResources: ++ return AVERROR(ENOMEM); ++ ++ case EB_ErrorUndefined: ++ case EB_ErrorInvalidComponent: ++ case EB_ErrorBadParameter: ++ return AVERROR(EINVAL); ++ ++ case EB_ErrorDestroyThreadFailed: ++ case EB_ErrorSemaphoreUnresponsive: ++ case EB_ErrorDestroySemaphoreFailed: ++ case EB_ErrorCreateMutexFailed: ++ case EB_ErrorMutexUnresponsive: ++ case EB_ErrorDestroyMutexFailed: ++ return AVERROR_EXTERNAL; ++ ++ case EB_NoErrorEmptyQueue: ++ return AVERROR(EAGAIN); ++ ++ case EB_ErrorNone: ++ return 0; ++ ++ default: ++ return AVERROR_UNKNOWN; ++ } ++} ++ ++static void free_buffer(SvtContext *svt_enc) ++{ ++ if (svt_enc && svt_enc->in_data) { ++ av_freep(&svt_enc->in_data); ++ svt_enc->in_data = NULL; ++ } ++} ++ ++static EB_ERRORTYPE alloc_buffer(SvtContext *svt_enc) ++{ ++ EB_BUFFERHEADERTYPE *in_buf = &svt_enc->in_buf; ++ EB_H265_ENC_INPUT *in_data = NULL; ++ ++ memset(in_buf, 0, sizeof(*in_buf)); ++ in_buf->nSize = sizeof(*in_buf); ++ in_buf->sliceType = EB_INVALID_PICTURE; ++ ++ in_data = (EB_H265_ENC_INPUT *)av_mallocz(sizeof(*in_data)); ++ if (in_data) { ++ svt_enc->in_data = in_buf->pBuffer = (uint8_t *)in_data; ++ return EB_ErrorNone; ++ } else { ++ return EB_ErrorInsufficientResources; ++ } ++} ++ ++static int config_enc_params(EB_H265_ENC_CONFIGURATION *param, ++ AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ ++ param->sourceWidth = avctx->width; ++ param->sourceHeight = avctx->height; ++ ++ if ((avctx->pix_fmt == AV_PIX_FMT_YUV420P10) || ++ (avctx->pix_fmt == AV_PIX_FMT_YUV422P10) || ++ (avctx->pix_fmt == AV_PIX_FMT_YUV444P10)) { ++ av_log(avctx, AV_LOG_DEBUG, "Set 10 bits depth input\n"); ++ param->encoderBitDepth = 10; ++ } else { ++ av_log(avctx, AV_LOG_DEBUG, "Set 8 bits depth input\n"); ++ param->encoderBitDepth = 8; ++ } ++ ++ if ((avctx->pix_fmt == AV_PIX_FMT_YUV420P) || ++ (avctx->pix_fmt == AV_PIX_FMT_YUV420P10)) ++ param->encoderColorFormat = EB_YUV420; ++ else if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P) || ++ (avctx->pix_fmt == AV_PIX_FMT_YUV422P10)) ++ param->encoderColorFormat = EB_YUV422; ++ else ++ param->encoderColorFormat = EB_YUV444; ++ ++ param->profile = svt_enc->profile; ++ ++ if (FF_PROFILE_HEVC_MAIN_STILL_PICTURE == param->profile) { ++ av_log(avctx, AV_LOG_ERROR, "Main Still Picture Profile not supported\n"); ++ return EB_ErrorBadParameter; ++ } ++ ++ if ((param->encoderColorFormat >= EB_YUV422) && ++ (param->profile != FF_PROFILE_HEVC_REXT)) { ++ av_log(avctx, AV_LOG_WARNING, "Rext Profile forced for 422 or 444\n"); ++ param->profile = FF_PROFILE_HEVC_REXT; ++ } ++ ++ if ((FF_PROFILE_HEVC_MAIN == param->profile) && ++ (param->encoderBitDepth > 8)) { ++ av_log(avctx, AV_LOG_WARNING, "Main10 Profile forced for 10 bits\n"); ++ param->profile = FF_PROFILE_HEVC_MAIN_10; ++ } ++ ++ param->targetBitRate = avctx->bit_rate; ++ ++ if (avctx->gop_size > 0) ++ param->intraPeriodLength = avctx->gop_size - 1; ++ ++ if ((avctx->framerate.num > 0) && (avctx->framerate.den > 0)) { ++ param->frameRateNumerator = avctx->framerate.num; ++ param->frameRateDenominator = ++ avctx->framerate.den * avctx->ticks_per_frame; ++ } else { ++ param->frameRateNumerator = avctx->time_base.den; ++ param->frameRateDenominator = ++ avctx->time_base.num * avctx->ticks_per_frame; ++ } ++ ++ param->hierarchicalLevels = svt_enc->hierarchical_level; ++ param->encMode = svt_enc->enc_mode; ++ param->tier = svt_enc->tier; ++ param->level = svt_enc->level; ++ param->rateControlMode = svt_enc->rc_mode; ++ param->sceneChangeDetection = svt_enc->scd; ++ param->tune = svt_enc->tune; ++ param->baseLayerSwitchMode = svt_enc->base_layer_switch_mode; ++ param->qp = svt_enc->qp; ++ param->accessUnitDelimiter = svt_enc->aud; ++ param->asmType = svt_enc->asm_type; ++ param->intraRefreshType = svt_enc->forced_idr; ++ ++ if (param->rateControlMode) { ++ param->maxQpAllowed = avctx->qmax; ++ param->minQpAllowed = avctx->qmin; ++ } ++ ++ if (svt_enc->la_depth != -1) ++ param->lookAheadDistance = svt_enc->la_depth; ++ ++ if ((svt_enc->thread_count > 0) && ++ (svt_enc->thread_count < (EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR))) { ++ param->threadCount = EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR; ++ av_log(avctx, AV_LOG_WARNING, "Thread count is set too small, forced to %"PRId32"\n", ++ param->threadCount); ++ } else if (svt_enc->thread_count % EB_THREAD_COUNT_MIN_CORE) { ++ param->threadCount = (svt_enc->thread_count + EB_THREAD_COUNT_MIN_CORE - 1) ++ / EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_MIN_CORE; ++ av_log(avctx, AV_LOG_DEBUG, "Thread count is rounded to %"PRId32"\n", ++ param->threadCount); ++ } else { ++ param->threadCount = svt_enc->thread_count; ++ } ++ ++ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ++ param->codeVpsSpsPps = 0; ++ else ++ param->codeVpsSpsPps = 1; ++ ++ param->codeEosNal = 1; ++ ++ return EB_ErrorNone; ++} ++ ++static void read_in_data(EB_H265_ENC_CONFIGURATION *config, ++ const AVFrame *frame, ++ EB_BUFFERHEADERTYPE *header_ptr) ++{ ++ uint8_t is16bit; ++ uint64_t frame_size; ++ EB_H265_ENC_INPUT *in_data = (EB_H265_ENC_INPUT *)header_ptr->pBuffer; ++ ++ is16bit = config->encoderBitDepth > 8; ++ frame_size = (uint64_t)(config->sourceWidth * config->sourceHeight) << is16bit; ++ ++ in_data->luma = frame->data[0]; ++ in_data->cb = frame->data[1]; ++ in_data->cr = frame->data[2]; ++ ++ in_data->yStride = frame->linesize[0] >> is16bit; ++ in_data->cbStride = frame->linesize[1] >> is16bit; ++ in_data->crStride = frame->linesize[2] >> is16bit; ++ ++ if (config->encoderColorFormat == EB_YUV420) ++ frame_size *= 3/2u; ++ else if (config->encoderColorFormat == EB_YUV422) ++ frame_size *= 2u; ++ else ++ frame_size *= 3u; ++ ++ header_ptr->nFilledLen += frame_size; ++} ++ ++static av_cold int eb_enc_init(AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EB_ERRORTYPE svt_ret; ++ ++ svt_enc->eos_flag = EOS_NOT_REACHED; ++ ++ svt_ret = EbInitHandle(&svt_enc->svt_handle, svt_enc, &svt_enc->enc_params); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to init handle\n"); ++ return error_mapping(svt_ret); ++ } ++ ++ svt_ret = config_enc_params(&svt_enc->enc_params, avctx); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to config parameters\n"); ++ goto failed_init_handle; ++ } ++ ++ svt_ret = EbH265EncSetParameter(svt_enc->svt_handle, &svt_enc->enc_params); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to set parameters\n"); ++ goto failed_init_handle; ++ } ++ ++ svt_ret = EbInitEncoder(svt_enc->svt_handle); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to init encoder\n"); ++ goto failed_init_handle; ++ } ++ ++ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { ++ EB_BUFFERHEADERTYPE *header_ptr = NULL; ++ ++ svt_ret = EbH265EncStreamHeader(svt_enc->svt_handle, &header_ptr); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to build stream header\n"); ++ goto failed_init_encoder; ++ } ++ ++ avctx->extradata_size = header_ptr->nFilledLen; ++ avctx->extradata = av_malloc(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); ++ if (!avctx->extradata) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate extradata\n"); ++ svt_ret = EB_ErrorInsufficientResources; ++ goto failed_init_encoder; ++ } ++ memcpy(avctx->extradata, header_ptr->pBuffer, avctx->extradata_size); ++ memset(avctx->extradata+avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); ++ } ++ ++ svt_ret = alloc_buffer(svt_enc); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to alloc data buffer\n"); ++ goto failed_init_encoder; ++ } ++ return 0; ++ ++failed_init_encoder: ++ EbDeinitEncoder(svt_enc->svt_handle); ++failed_init_handle: ++ EbDeinitHandle(svt_enc->svt_handle); ++ svt_enc->svt_handle = NULL; ++ svt_enc = NULL; ++ return error_mapping(svt_ret); ++} ++ ++static int eb_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ++ const AVFrame *frame, int *got_packet) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EB_BUFFERHEADERTYPE *header_ptr = &svt_enc->in_buf; ++ EB_ERRORTYPE svt_ret; ++ int av_ret; ++ ++ if (EOS_RECEIVED == svt_enc->eos_flag) { ++ *got_packet = 0; ++ return 0; ++ } ++ ++ if (!frame) { ++ if (!svt_enc->eos_flag) { ++ svt_enc->eos_flag = EOS_SENT; ++ ++ header_ptr->nAllocLen = 0; ++ header_ptr->nFilledLen = 0; ++ header_ptr->nTickCount = 0; ++ header_ptr->nFlags = EB_BUFFERFLAG_EOS; ++ header_ptr->pBuffer = NULL; ++ ++ EbH265EncSendPicture(svt_enc->svt_handle, header_ptr); ++ ++ av_log(avctx, AV_LOG_DEBUG, "Sent EOS\n"); ++ } ++ } else { ++ read_in_data(&svt_enc->enc_params, frame, header_ptr); ++ header_ptr->pts = frame->pts; ++ ++ EbH265EncSendPicture(svt_enc->svt_handle, header_ptr); ++ ++ av_log(avctx, AV_LOG_DEBUG, "Sent PTS %"PRId64"\n", header_ptr->pts); ++ } ++ ++ header_ptr = NULL; ++ svt_ret = EbH265GetPacket(svt_enc->svt_handle, &header_ptr, svt_enc->eos_flag); ++ ++ if (svt_ret == EB_NoErrorEmptyQueue) { ++ *got_packet = 0; ++ av_log(avctx, AV_LOG_DEBUG, "Received none\n"); ++ return 0; ++ } ++ ++ av_log(avctx, AV_LOG_DEBUG, "Received PTS %"PRId64" packet\n", header_ptr->pts); ++ ++ av_ret = ff_alloc_packet2(avctx, pkt, header_ptr->nFilledLen, 0); ++ if (av_ret) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate a packet\n"); ++ EbH265ReleaseOutBuffer(&header_ptr); ++ return av_ret; ++ } ++ ++ memcpy(pkt->data, header_ptr->pBuffer, header_ptr->nFilledLen); ++ pkt->size = header_ptr->nFilledLen; ++ pkt->pts = header_ptr->pts; ++ pkt->dts = header_ptr->dts; ++ ++ if ((header_ptr->sliceType == EB_IDR_PICTURE) || ++ (header_ptr->sliceType == EB_I_PICTURE)) ++ pkt->flags |= AV_PKT_FLAG_KEY; ++ if (header_ptr->sliceType == EB_NON_REF_PICTURE) ++ pkt->flags |= AV_PKT_FLAG_DISPOSABLE; ++ ++ EbH265ReleaseOutBuffer(&header_ptr); ++ ++ *got_packet = 1; ++ ++ if (EB_BUFFERFLAG_EOS == header_ptr->nFlags) ++ svt_enc->eos_flag = EOS_RECEIVED; ++ ++ return 0; ++} ++ ++static av_cold int eb_enc_close(AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ ++ if (svt_enc) { ++ free_buffer(svt_enc); ++ ++ if (svt_enc->svt_handle) { ++ EbDeinitEncoder(svt_enc->svt_handle); ++ EbDeinitHandle(svt_enc->svt_handle); ++ svt_enc->svt_handle = NULL; ++ } ++ } ++ ++ return 0; ++} ++ ++#define OFFSET(x) offsetof(SvtContext, x) ++#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM ++static const AVOption options[] = { ++ { "asm_type", "Assembly instruction set type [0: C Only, 1: Auto]", OFFSET(asm_type), ++ AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, ++ ++ { "aud", "Include Access Unit Delimiter", OFFSET(aud), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, ++ ++ { "bl_mode", "Random Access Prediction Structure type setting", OFFSET(base_layer_switch_mode), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, ++ ++ { "forced-idr", "If forcing keyframes, force them as IDR frames.", OFFSET(forced_idr), ++ AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, ++ ++ { "hielevel", "Hierarchical prediction levels setting", OFFSET(hierarchical_level), ++ AV_OPT_TYPE_INT, { .i64 = 3 }, 0, 3, VE , "hielevel"}, ++ { "flat", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "hielevel" }, ++ { "1 level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "hielevel" }, ++ { "2 level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "hielevel" }, ++ { "3 level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "hielevel" }, ++ ++ { "la_depth", "Look ahead distance [0, 256]", OFFSET(la_depth), ++ AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 256, VE }, ++ ++ { "level", "Set level (level_idc)", OFFSET(level), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xff, VE, "level" }, ++ ++ { "preset", "Encoding preset [0, 12]", ++ OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = 7 }, 0, 12, VE }, ++ ++ { "profile", "Profile setting, Main Still Picture Profile not supported", OFFSET(profile), ++ AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_HEVC_MAIN }, FF_PROFILE_HEVC_MAIN, FF_PROFILE_HEVC_REXT, VE, "profile"}, ++ ++ { "qp", "QP value for intra frames", OFFSET(qp), ++ AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE }, ++ ++ { "rc", "Bit rate control mode", OFFSET(rc_mode), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE , "rc"}, ++ { "cqp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "rc" }, ++ { "vbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "rc" }, ++ ++ { "sc_detection", "Scene change detection", OFFSET(scd), ++ AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, ++ ++ { "thread_count", "Number of threads [0: Auto, 96: Min]", OFFSET(thread_count), ++ AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE }, ++ ++ { "tier", "Set tier (general_tier_flag)", OFFSET(tier), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "tier" }, ++ { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "tier" }, ++ { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "tier" }, ++ ++ { "tune", "Quality tuning mode", OFFSET(tune), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 2, VE, "tune" }, ++ { "sq", "Visually optimized mode", 0, ++ AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "tune" }, ++ { "oq", "PSNR / SSIM optimized mode", 0, ++ AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "tune" }, ++ { "vmaf", "VMAF optimized mode", 0, ++ AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "tune" }, ++ ++ {NULL}, ++}; ++ ++static const AVClass class = { ++ .class_name = "libsvt_hevc", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++}; ++ ++static const AVCodecDefault eb_enc_defaults[] = { ++ { "b", "7M" }, ++ { "qmin", "10" }, ++ { "qmax", "48" }, ++ { "g", "-2" }, ++ { NULL }, ++}; ++ ++AVCodec ff_libsvt_hevc_encoder = { ++ .name = "libsvt_hevc", ++ .long_name = NULL_IF_CONFIG_SMALL("SVT-HEVC(Scalable Video Technology for HEVC) encoder"), ++ .priv_data_size = sizeof(SvtContext), ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_HEVC, ++ .init = eb_enc_init, ++ .encode2 = eb_encode_frame, ++ .close = eb_enc_close, ++ .capabilities = AV_CODEC_CAP_DELAY, ++ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, ++ AV_PIX_FMT_YUV420P10, ++ AV_PIX_FMT_YUV422P, ++ AV_PIX_FMT_YUV422P10, ++ AV_PIX_FMT_YUV444P, ++ AV_PIX_FMT_YUV444P10, ++ AV_PIX_FMT_NONE }, ++ .priv_class = &class, ++ .defaults = eb_enc_defaults, ++ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, ++ .wrapper_name = "libsvt_hevc", ++}; +-- +1.8.3.1 + diff --git a/ffmpeg-full-git-add-svt-hevc-docs-1.4.1.patch b/ffmpeg-full-git-add-svt-hevc-docs-1.4.1.patch new file mode 100644 index 000000000000..b1e14880b9af --- /dev/null +++ b/ffmpeg-full-git-add-svt-hevc-docs-1.4.1.patch @@ -0,0 +1,198 @@ +From 6b0a4fd63454e3c2185efe741e50e80df5c9a4a4 Mon Sep 17 00:00:00 2001 +From: Jing Sun <jing.a.sun@intel.com> +Date: Tue, 5 Mar 2019 15:04:58 +0800 +Subject: [PATCH 2/2] doc: Add libsvt_hevc encoder docs + +Add docs for libsvt_hevc encoder in encoders.texi and general.texi + +Signed-off-by: Jun Zhao <jun.zhao@intel.com> +Signed-off-by: Zhengxu Huang <zhengxu.huang@intel.com> +Signed-off-by: Hassene Tmar <hassene.tmar@intel.com> +Signed-off-by: Jing Sun <jing.a.sun@intel.com> +--- + doc/encoders.texi | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + doc/general.texi | 8 +++ + 2 files changed, 157 insertions(+) + +diff --git a/doc/encoders.texi b/doc/encoders.texi +index eefd124..81debda 100644 +--- a/doc/encoders.texi ++++ b/doc/encoders.texi +@@ -1640,6 +1640,155 @@ Set maximum NAL size in bytes. + Allow skipping frames to hit the target bitrate if set to 1. + @end table + ++@section libsvt_hevc ++ ++Scalable Video Technology for HEVC (SVT-HEVC) encoder wrapper. ++ ++This encoder requires the presence of the headers and ++library during configuration. You need to explicitly configure the ++build with @code{--enable-libsvthevc}. The library is detected using ++@command{pkg-config}. ++ ++For more information about the library see ++@url{https://github.com/intel/SVT-HEVC.git}. ++ ++@subsection Options ++ ++The following FFmpeg global options affect the configurations of the ++libsvt_hevc encoder: ++ ++@table @option ++@item b (@emph{bitrate}) ++Set the bitrate (as a number of bits per second). Default is 7M. ++ ++@item g / @option{gop_size} ++Set the GOP size. Default is -2 (unspecified). ++ ++@item flags +cgop ++Enable closed GOP. ++ ++@item qmin (@emph{min-q}) ++Default is 10 ++ ++@item qmax (@emph{max-q}) ++Default is 48 ++ ++Set minimum/maximum quantisation values. Valid range is from 0 to 51 ++(Only used when bit rate control mode @option{rc} is set to 1(vbr) mode. ++It is required that qmax >= qmin). ++ ++@item profile (@emph{profile}) ++Set profile restrictions. Can assume one of the following possible values: ++ ++@table @samp ++@item main ++main profile ++@item main10 ++main10 profile ++@item rext ++rext profile ++@end table ++ ++Default is 1 (main). ++ ++@item level (@emph{level}) ++ ++@option{level} sets the value of @emph{level}. ++Set level (level_idc). Default is 0 (to be determined by the encoder). ++ ++@end table ++ ++The encoder also has its own specific options: ++ ++@table @option ++@item aud (@emph{aud}) ++Enable use of access unit delimiters when set to 1. Default is 0 (Off). ++ ++@item hielevel ++Set hierarchical levels. Can assume one of the following possible values: ++ ++@table @samp ++@item flat ++flat more ++@item 1 level ++Minigop size is 2^1 ++@item 2 level ++Minigop size is 2^2 ++@item 3 level ++Minigop size is 2^3 ++@end table ++ ++Default is 3 level. ++ ++@item la_depth ++Set look-ahead depth, depending on @option{rc}: for @var{vbr}, it's recommended ++to unset it and use the default value (the intra period); for @var{cqp}, better ++specify the look-ahead depth. ++ ++The range is @var{-1-256}. Default is -1 (unset and the default value to be used). ++ ++@item preset ++Set the quality vs density tradeoff point at which the encoding is to be performed. ++Higher perset value, higher density and lower quality. ++ ++The range is @var{0-12}. Default is 9. ++ ++@item tier ++Set @emph{general_tier_flag}. This may affect the level chosen for the stream ++if it is not explicitly specified. Can assume one of the following possible values: ++ ++@table @samp ++@item main ++main tier ++@item high ++high tier ++@end table ++ ++Default is 1 (main). ++ ++@item rc ++Set bit rate control mode. Can assume one of the following possible values: ++ ++@table @samp ++@item cqp ++Constant QP (CQP) mode ++@item vbr ++Variable Bit Rate (VBR) mode ++@end table ++ ++Default is 0 (cqp). ++ ++@item forced_idr ++Force keyframes to be IDR if set to >=0 (the value sets headers insertion interval). Default is -1 (CRA). ++ ++@item asm_type ++Auto select highest supported asm if set to 1 or C only if 0. Default is 1. ++ ++@item qp ++Initial quantization parameter for the intra pictures used when ++@option{rc} is cqp mode. The range is from @var{0-51}. Default is 32. ++ ++@item sc_detection ++Enables or disables the scene change detection algorithm. Default is 0 (disabled). ++ ++@item tune ++Set quality tuning mode. Can assume one of the following possible values: ++ ++@table @samp ++@item sq ++Visually optimized mode ++@item oq ++PSNR / SSIM optimized mode ++@item vmaf ++VMAF optimized mode ++@end table ++ ++Default is 1 (oq). ++ ++@item bl_mode ++Enables or disables Random Access Prediction. Default is 0 (disabled). ++@end table ++ + @section libtheora + + libtheora Theora encoder wrapper. +diff --git a/doc/general.texi b/doc/general.texi +index 3c0c803..fa9cd31 100644 +--- a/doc/general.texi ++++ b/doc/general.texi +@@ -243,6 +243,14 @@ FFmpeg can use the OpenJPEG libraries for decoding/encoding J2K videos. Go to + instructions. To enable using OpenJPEG in FFmpeg, pass @code{--enable-libopenjpeg} to + @file{./configure}. + ++@section Scalable Video Technology for HEVC ++ ++FFmpeg can make use of the SVT-HEVC library for HEVC encoding. ++ ++Go to @url{https://github.com/intel/SVT-HEVC.git} and follow the instructions ++for installing the library. Pass @code{--enable-libsvthevc} to configure to ++enable it. ++ + @section TwoLAME + + FFmpeg can make use of the TwoLAME library for MP2 encoding. +-- +1.8.3.1 + diff --git a/ffmpeg-full-git-add-svt-vp9-gce24589.patch b/ffmpeg-full-git-add-svt-vp9-gce24589.patch new file mode 100644 index 000000000000..cddcd43737c8 --- /dev/null +++ b/ffmpeg-full-git-add-svt-vp9-gce24589.patch @@ -0,0 +1,624 @@ +From 7876bb6fa6f782dc283633d00d49cccc436ab89d Mon Sep 17 00:00:00 2001 +From: Jing Sun <jing.a.sun@intel.com> +Date: Mon, 1 Apr 2019 17:17:00 +0800 +Subject: [PATCH 1/1] Add ability for ffmpeg to run svt vp9 with hevc & av1 + +Signed-off-by: hassene <hassene.tmar@intel.com> +Signed-off-by: Jing Sun <jing.a.sun@intel.com> +--- + configure | 4 + + libavcodec/Makefile | 1 + + libavcodec/allcodecs.c | 1 + + libavcodec/avcodec.h | 2 + + libavcodec/libsvt_vp9.c | 474 ++++++++++++++++++++++++++++++++++++++++++++++++ + libavformat/ivfenc.c | 34 +++- + 6 files changed, 513 insertions(+), 3 deletions(-) + create mode 100644 libavcodec/libsvt_vp9.c + +diff --git a/configure b/configure +index 5a54eb4..45f250a 100755 +--- a/configure ++++ b/configure +@@ -266,6 +266,7 @@ External library support: + --enable-libssh enable SFTP protocol via libssh [no] + --enable-libsvthevc enable HEVC encoding via svt [no] + --enable-libsvtav1 enable AV1 encoding via svt [no] ++ --enable-libsvtvp9 enable VP9 encoding via svt [no] + --enable-libtensorflow enable TensorFlow as a DNN module backend + for DNN based filters like sr [no] + --enable-libtesseract enable Tesseract, needed for ocr filter [no] +@@ -1788,6 +1789,7 @@ EXTERNAL_LIBRARY_LIST=" + libssh + libsvthevc + libsvtav1 ++ libsvtvp9 + libtensorflow + libtesseract + libtheora +@@ -3179,6 +3181,7 @@ libspeex_encoder_deps="libspeex" + libspeex_encoder_select="audio_frame_queue" + libsvt_hevc_encoder_deps="libsvthevc" + libsvt_av1_encoder_deps="libsvtav1" ++libsvt_vp9_encoder_deps="libsvtvp9" + libtheora_encoder_deps="libtheora" + libtwolame_encoder_deps="libtwolame" + libvo_amrwbenc_encoder_deps="libvo_amrwbenc" +@@ -6217,6 +6220,7 @@ enabled libspeex && require_pkg_config libspeex speex speex/speex.h spe + enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket + enabled libsvthevc && require_pkg_config libsvthevc SvtHevcEnc EbApi.h EbInitHandle + enabled libsvtav1 && require_pkg_config libsvtav1 SvtAv1Enc EbSvtAv1Enc.h eb_init_handle ++enabled libsvtvp9 && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle + enabled libtensorflow && require libtensorflow tensorflow/c/c_api.h TF_Version -ltensorflow + enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate + enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index dd1b848..cfcd6f0 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -989,6 +989,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o + OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o + OBJS-$(CONFIG_LIBSVT_HEVC_ENCODER) += libsvt_hevc.o + OBJS-$(CONFIG_LIBSVT_AV1_ENCODER) += libsvt_av1.o ++OBJS-$(CONFIG_LIBSVT_VP9_ENCODER) += libsvt_vp9.o + OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o + OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o + OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o +diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c +index c6c203e..3d20d9c 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -705,6 +705,7 @@ extern AVCodec ff_libspeex_encoder; + extern AVCodec ff_libspeex_decoder; + extern AVCodec ff_libsvt_hevc_encoder; + extern AVCodec ff_libsvt_av1_encoder; ++extern AVCodec ff_libsvt_vp9_encoder; + extern AVCodec ff_libtheora_encoder; + extern AVCodec ff_libtwolame_encoder; + extern AVCodec ff_libvo_amrwbenc_encoder; +diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h +index b749946..1f504af 100644 +--- a/libavcodec/avcodec.h ++++ b/libavcodec/avcodec.h +@@ -1526,6 +1526,8 @@ typedef struct AVPacket { + */ + #define AV_PKT_FLAG_DISPOSABLE 0x0010 + ++#define AV_PKT_FLAG_SVT_VP9_EXT_ON 0x10000 // Indicating SVT VP9 frame header ext on ++#define AV_PKT_FLAG_SVT_VP9_EXT_OFF 0x20000 // Indicating SVT VP9 frame header ext off + + enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, +diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c +new file mode 100644 +index 0000000..f7e3bc3 +--- /dev/null ++++ b/libavcodec/libsvt_vp9.c +@@ -0,0 +1,474 @@ ++/* ++* Scalable Video Technology for VP9 encoder library plugin ++* ++* Copyright (c) 2018 Intel Corporation ++* ++* This file is part of FFmpeg. ++* ++* FFmpeg is free software; you can redistribute it and/or ++* modify it under the terms of the GNU Lesser General Public ++* License as published by the Free Software Foundation; either ++* version 2.1 of the License, or (at your option) any later version. ++* ++* FFmpeg is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++* Lesser General Public License for more details. ++* ++* You should have received a copy of the GNU Lesser General Public ++* License along with this program; if not, write to the Free Software ++* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++*/ ++ ++#include <stdint.h> ++#include "EbSvtVp9ErrorCodes.h" ++#include "EbSvtVp9Time.h" ++#include "EbSvtVp9Enc.h" ++ ++#include "libavutil/common.h" ++#include "libavutil/frame.h" ++#include "libavutil/opt.h" ++ ++#include "internal.h" ++#include "avcodec.h" ++ ++typedef enum eos_status { ++ EOS_NOT_REACHED = 0, ++ EOS_REACHED, ++ EOS_TOTRIGGER ++}EOS_STATUS; ++ ++typedef struct SvtContext { ++ AVClass *class; ++ ++ EbSvtVp9EncConfiguration enc_params; ++ EbComponentType *svt_handle; ++ ++ EbBufferHeaderType *in_buf; ++ int raw_size; ++ ++ EOS_STATUS eos_flag; ++ ++ // User options. ++ int enc_mode; ++ int rc_mode; ++ int tune; ++ int qp; ++ ++ int forced_idr; ++ ++ int level; ++ ++ int base_layer_switch_mode; ++} SvtContext; ++ ++static int error_mapping(EbErrorType svt_ret) ++{ ++ int err; ++ ++ switch (svt_ret) { ++ case EB_ErrorInsufficientResources: ++ err = AVERROR(ENOMEM); ++ break; ++ ++ case EB_ErrorUndefined: ++ case EB_ErrorInvalidComponent: ++ case EB_ErrorBadParameter: ++ err = AVERROR(EINVAL); ++ break; ++ ++ case EB_ErrorDestroyThreadFailed: ++ case EB_ErrorSemaphoreUnresponsive: ++ case EB_ErrorDestroySemaphoreFailed: ++ case EB_ErrorCreateMutexFailed: ++ case EB_ErrorMutexUnresponsive: ++ case EB_ErrorDestroyMutexFailed: ++ err = AVERROR_EXTERNAL; ++ break; ++ ++ case EB_NoErrorEmptyQueue: ++ err = AVERROR(EAGAIN); ++ ++ case EB_ErrorNone: ++ err = 0; ++ break; ++ ++ default: ++ err = AVERROR_UNKNOWN; ++ } ++ ++ return err; ++} ++ ++static void free_buffer(SvtContext *svt_enc) ++{ ++ if (svt_enc->in_buf) { ++ EbSvtEncInput *in_data = (EbSvtEncInput *)svt_enc->in_buf->p_buffer; ++ av_freep(&in_data); ++ av_freep(&svt_enc->in_buf); ++ } ++} ++ ++static int alloc_buffer(EbSvtVp9EncConfiguration *config, SvtContext *svt_enc) ++{ ++ const size_t luma_size_8bit = ++ config->source_width * config->source_height; ++ const size_t luma_size_10bit = ++ (config->encoder_bit_depth > 8) ? luma_size_8bit : 0; ++ ++ EbSvtEncInput *in_data; ++ ++ svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2; ++ ++ // allocate buffer for in and out ++ svt_enc->in_buf = av_mallocz(sizeof(*svt_enc->in_buf)); ++ if (!svt_enc->in_buf) ++ goto failed; ++ ++ in_data = av_mallocz(sizeof(*in_data)); ++ if (!in_data) ++ goto failed; ++ svt_enc->in_buf->p_buffer = (unsigned char *)in_data; ++ ++ svt_enc->in_buf->size = sizeof(*svt_enc->in_buf); ++ svt_enc->in_buf->p_app_private = NULL; ++ ++ return 0; ++ ++failed: ++ free_buffer(svt_enc); ++ return AVERROR(ENOMEM); ++} ++ ++static int config_enc_params(EbSvtVp9EncConfiguration *param, ++ AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ int ret; ++ int ten_bits = 0; ++ ++ param->source_width = avctx->width; ++ param->source_height = avctx->height; ++ ++ if (avctx->pix_fmt == AV_PIX_FMT_YUV420P10LE) { ++ av_log(avctx, AV_LOG_DEBUG , "Encoder 10 bits depth input\n"); ++ // Disable Compressed 10-bit format default ++ ten_bits = 1; ++ } ++ ++ // Update param from options ++ param->enc_mode = svt_enc->enc_mode; ++ param->level = svt_enc->level; ++ param->rate_control_mode = svt_enc->rc_mode; ++ param->tune = svt_enc->tune; ++ param->base_layer_switch_mode = svt_enc->base_layer_switch_mode; ++ param->qp = svt_enc->qp; ++ ++ param->target_bit_rate = avctx->bit_rate; ++ if (avctx->gop_size > 0) ++ param->intra_period = avctx->gop_size - 1; ++ ++ if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { ++ param->frame_rate_numerator = avctx->framerate.num; ++ param->frame_rate_denominator = avctx->framerate.den * avctx->ticks_per_frame; ++ } else { ++ param->frame_rate_numerator = avctx->time_base.den; ++ param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; ++ } ++ ++ if (param->rate_control_mode) { ++ param->max_qp_allowed = avctx->qmax; ++ param->min_qp_allowed = avctx->qmin; ++ } ++ ++ param->intra_refresh_type = ++ !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) + 1; ++ ++ if (ten_bits) { ++ param->encoder_bit_depth = 10; ++ } ++ ++ ret = alloc_buffer(param, svt_enc); ++ ++ return ret; ++} ++ ++static void read_in_data(EbSvtVp9EncConfiguration *config, ++ const AVFrame *frame, ++ EbBufferHeaderType *headerPtr) ++{ ++ uint8_t is16bit = config->encoder_bit_depth > 8; ++ uint64_t luma_size = ++ (uint64_t)config->source_width * config->source_height<< is16bit; ++ EbSvtEncInput *in_data = (EbSvtEncInput *)headerPtr->p_buffer; ++ ++ // support yuv420p and yuv420p010 ++ in_data->luma = frame->data[0]; ++ in_data->cb = frame->data[1]; ++ in_data->cr = frame->data[2]; ++ ++ // stride info ++ in_data->y_stride = frame->linesize[0] >> is16bit; ++ in_data->cb_stride = frame->linesize[1] >> is16bit; ++ in_data->cr_stride = frame->linesize[2] >> is16bit; ++ ++ headerPtr->n_filled_len += luma_size * 3/2u; ++} ++ ++static av_cold int eb_enc_init(AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EbErrorType svt_ret; ++ ++ svt_enc->eos_flag = EOS_NOT_REACHED; ++ ++ svt_ret = eb_vp9_svt_init_handle(&svt_enc->svt_handle, svt_enc, &svt_enc->enc_params); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error init encoder handle\n"); ++ goto failed; ++ } ++ ++ svt_ret = config_enc_params(&svt_enc->enc_params, avctx); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error configure encoder parameters\n"); ++ goto failed_init_handle; ++ } ++ ++ svt_ret = eb_vp9_svt_enc_set_parameter(svt_enc->svt_handle, &svt_enc->enc_params); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error setting encoder parameters\n"); ++ goto failed_init_handle; ++ } ++ ++ svt_ret = eb_vp9_init_encoder(svt_enc->svt_handle); ++ if (svt_ret != EB_ErrorNone) { ++ av_log(avctx, AV_LOG_ERROR, "Error init encoder\n"); ++ goto failed_init_handle; ++ } ++ ++ // if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { ++ // EbBufferHeaderType* headerPtr; ++ // headerPtr->size = sizeof(headerPtr); ++ // headerPtr->n_filled_len = 0; /* in/out */ ++ // headerPtr->p_buffer = av_malloc(10 * 1024 * 1024); ++ // headerPtr->n_alloc_len = (10 * 1024 * 1024); ++ // ++ // if (!headerPtr->p_buffer) { ++ // av_log(avctx, AV_LOG_ERROR, ++ // "Cannot allocate buffer size %d.\n", headerPtr->n_alloc_len); ++ // svt_ret = EB_ErrorInsufficientResources; ++ // goto failed_init_enc; ++ // } ++ // ++ // svt_ret = eb_svt_enc_stream_header(svt_enc->svt_handle, &headerPtr); ++ // if (svt_ret != EB_ErrorNone) { ++ // av_log(avctx, AV_LOG_ERROR, "Error when build stream header.\n"); ++ // av_freep(&headerPtr->p_buffer); ++ // goto failed_init_enc; ++ // } ++ // ++ // avctx->extradata_size = headerPtr->n_filled_len; ++ // avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); ++ // if (!avctx->extradata) { ++ // av_log(avctx, AV_LOG_ERROR, ++ // "Cannot allocate VP9 header of size %d.\n", avctx->extradata_size); ++ // av_freep(&headerPtr->p_buffer); ++ // svt_ret = EB_ErrorInsufficientResources; ++ // goto failed_init_enc; ++ // } ++ // memcpy(avctx->extradata, headerPtr->p_buffer, avctx->extradata_size); ++ // ++ // av_freep(&headerPtr->p_buffer); ++ // } ++ return 0; ++ ++//failed_init_enc: ++// eb_deinit_encoder(svt_enc->svt_handle); ++failed_init_handle: ++ eb_vp9_deinit_handle(svt_enc->svt_handle); ++failed: ++ free_buffer(svt_enc); ++ return error_mapping(svt_ret); ++} ++ ++static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EbBufferHeaderType *headerPtr = svt_enc->in_buf; ++ ++ if (!frame) { ++ EbBufferHeaderType headerPtrLast; ++ headerPtrLast.n_alloc_len = 0; ++ headerPtrLast.n_filled_len = 0; ++ headerPtrLast.n_tick_count = 0; ++ headerPtrLast.p_app_private = NULL; ++ headerPtrLast.p_buffer = NULL; ++ headerPtrLast.flags = EB_BUFFERFLAG_EOS; ++ ++ eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, &headerPtrLast); ++ svt_enc->eos_flag = EOS_REACHED; ++ av_log(avctx, AV_LOG_DEBUG, "Finish sending frames!!!\n"); ++ return 0; ++ } ++ ++ read_in_data(&svt_enc->enc_params, frame, headerPtr); ++ ++ headerPtr->flags = 0; ++ headerPtr->p_app_private = NULL; ++ headerPtr->pts = frame->pts; ++ switch (frame->pict_type) { ++ case AV_PICTURE_TYPE_I: ++ headerPtr->pic_type = svt_enc->forced_idr > 0 ? EB_IDR_PICTURE : EB_I_PICTURE; ++ break; ++ case AV_PICTURE_TYPE_P: ++ headerPtr->pic_type = EB_P_PICTURE; ++ break; ++ case AV_PICTURE_TYPE_B: ++ headerPtr->pic_type = EB_B_PICTURE; ++ break; ++ default: ++ headerPtr->pic_type = EB_INVALID_PICTURE; ++ break; ++ } ++ eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, headerPtr); ++ ++ return 0; ++} ++ ++static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EbBufferHeaderType *headerPtr; ++ EbErrorType svt_ret; ++ int ret; ++ ++ if (EOS_TOTRIGGER == svt_enc->eos_flag) { ++ pkt = NULL; ++ return AVERROR_EOF; ++ } ++ ++ svt_ret = eb_vp9_svt_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag); ++ if (svt_ret == EB_NoErrorEmptyQueue) ++ return AVERROR(EAGAIN); ++ ++ if ((ret = ff_alloc_packet2(avctx, pkt, headerPtr->n_filled_len, 0)) < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); ++ return ret; ++ } ++ ++ memcpy(pkt->data, headerPtr->p_buffer, headerPtr->n_filled_len); ++ pkt->size = headerPtr->n_filled_len; ++ pkt->pts = headerPtr->pts; ++ pkt->dts = headerPtr->dts; ++ if (headerPtr->pic_type == EB_IDR_PICTURE) ++ pkt->flags |= AV_PKT_FLAG_KEY; ++ if (headerPtr->pic_type == EB_NON_REF_PICTURE) ++ pkt->flags |= AV_PKT_FLAG_DISPOSABLE; ++ ++ if (headerPtr->flags & EB_BUFFERFLAG_SHOW_EXT) ++ pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_ON; ++ else ++ pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_OFF; ++ ++ if (EB_BUFFERFLAG_EOS == headerPtr->flags) ++ svt_enc->eos_flag = EOS_TOTRIGGER; ++ ++ eb_vp9_svt_release_out_buffer(&headerPtr); ++ return 0; ++} ++ ++static av_cold int eb_enc_close(AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ ++ eb_vp9_deinit_encoder(svt_enc->svt_handle); ++ eb_vp9_deinit_handle(svt_enc->svt_handle); ++ ++ free_buffer(svt_enc); ++ ++ return 0; ++} ++ ++#define OFFSET(x) offsetof(SvtContext, x) ++#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM ++static const AVOption options[] = { ++ { "preset", "Encoding preset [1, 1]", ++ OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = 9 }, 0, 9, VE }, ++ ++ { "level", "Set level (level_idc)", OFFSET(level), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xff, VE, "level" }, ++ ++#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ ++ { .i64 = value }, 0, 0, VE, "level" ++ { LEVEL("1", 10) }, ++ { LEVEL("2", 20) }, ++ { LEVEL("2.1", 21) }, ++ { LEVEL("3", 30) }, ++ { LEVEL("3.1", 31) }, ++ { LEVEL("4", 40) }, ++ { LEVEL("4.1", 41) }, ++ { LEVEL("5", 50) }, ++ { LEVEL("5.1", 51) }, ++ { LEVEL("5.2", 52) }, ++ { LEVEL("6", 60) }, ++ { LEVEL("6.1", 61) }, ++ { LEVEL("6.2", 62) }, ++#undef LEVEL ++ ++ { "tune", "Tune mode", OFFSET(tune), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE , "tune"}, ++ { "vq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "tune" }, ++ { "ssim", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "tune" }, ++ { "vmaf", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "tune" }, ++ ++ { "rc", "Bit rate control mode", OFFSET(rc_mode), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE , "rc"}, ++ { "cqp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "rc" }, ++ { "vbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "rc" }, ++ { "cbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "rc" }, ++ ++ { "qp", "QP value for intra frames", OFFSET(qp), ++ AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE }, ++ ++ { "bl_mode", "Random Access Prediction Structure type setting", OFFSET(base_layer_switch_mode), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, ++ ++ { "forced-idr", "If forcing keyframes, force them as IDR frames.", OFFSET(forced_idr), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, ++ ++ {NULL}, ++}; ++ ++static const AVClass class = { ++ .class_name = "libsvt_vp9", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++}; ++ ++static const AVCodecDefault eb_enc_defaults[] = { ++ { "b", "7M" }, ++ { "flags", "-cgop" }, ++ { "qmin", "10" }, ++ { "qmax", "48" }, ++ { NULL }, ++}; ++ ++AVCodec ff_libsvt_vp9_encoder = { ++ .name = "libsvt_vp9", ++ .long_name = NULL_IF_CONFIG_SMALL("SVT-VP9(Scalable Video Technology for VP9) encoder"), ++ .priv_data_size = sizeof(SvtContext), ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_VP9, ++ .init = eb_enc_init, ++ .send_frame = eb_send_frame, ++ .receive_packet = eb_receive_packet, ++ .close = eb_enc_close, ++ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, ++ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, ++ AV_PIX_FMT_NONE }, ++ .priv_class = &class, ++ .defaults = eb_enc_defaults, ++ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, ++ .wrapper_name = "libsvt_vp9", ++}; +diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c +index adf7211..05f0813 100644 +--- a/libavformat/ivfenc.c ++++ b/libavformat/ivfenc.c +@@ -63,9 +63,33 @@ static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt) + AVIOContext *pb = s->pb; + IVFEncContext *ctx = s->priv_data; + +- avio_wl32(pb, pkt->size); +- avio_wl64(pb, pkt->pts); +- avio_write(pb, pkt->data, pkt->size); ++ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { ++ avio_wl32(pb, pkt->size - 4); ++ avio_wl64(pb, pkt->pts); ++ avio_write(pb, pkt->data, pkt->size - 4); ++ ++ avio_wl32(pb, 1); ++ avio_wl64(pb, pkt->pts - 2); ++ avio_write(pb, pkt->data + pkt->size - 4, 1); ++ ++ avio_wl32(pb, 1); ++ avio_wl64(pb, pkt->pts - 1); ++ avio_write(pb, pkt->data + pkt->size - 3, 1); ++ ++ avio_wl32(pb, 1); ++ avio_wl64(pb, pkt->pts); ++ avio_write(pb, pkt->data + pkt->size - 2, 1); ++ ++ avio_wl32(pb, 1); ++ avio_wl64(pb, pkt->pts + 1); ++ avio_write(pb, pkt->data + pkt->size - 1, 1); ++ } ++ else { ++ avio_wl32(pb, pkt->size); ++ avio_wl64(pb, pkt->pts); ++ avio_write(pb, pkt->data, pkt->size); ++ } ++ + if (ctx->frame_cnt) + ctx->sum_delta_pts += pkt->pts - ctx->last_pts; + ctx->frame_cnt++; +@@ -95,6 +119,10 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) + int ret = 1; + AVStream *st = s->streams[pkt->stream_index]; + ++ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || ++ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) ++ return 0; ++ + if (st->codecpar->codec_id == AV_CODEC_ID_VP9) + ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL); + else if (st->codecpar->codec_id == AV_CODEC_ID_AV1) +-- +1.8.3.1 |