From 9d6e808a23445053aad9e0b75b575712d8de6b5e Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 26 Oct 2020 15:57:19 +0100 Subject: [PATCH] Add ffmpeg-custom replacing existing ffmpeg-* packages --- ffmpeg/custom/016-ffmpeg-srt-1.4.2-fix.patch | 50 + .../custom/017-ffmpeg-glslang-11.0-fix.patch | 27 + .../020-ffmpeg-add-svt-hevc-1.5.0.patch | 647 ++++++++++++ .../030-ffmpeg-add-svt-hevc-docs-1.5.0.patch | 198 ++++ .../custom/040-ffmpeg-add-svt-av1-0.8.4.patch | 671 ++++++++++++ .../custom/050-ffmpeg-add-svt-vp9-0.3.0.patch | 961 ++++++++++++++++++ ffmpeg/{libfdk_aac => custom}/PKGBUILD | 77 +- .../vmaf-model-path.patch | 0 ffmpeg/full-nvenc/PKGBUILD | 234 ----- ffmpeg/full-nvenc/UNREDISTRIBUTABLE.txt | 2 - ffmpeg/libfdk_aac-git/PKGBUILD | 98 -- 11 files changed, 2616 insertions(+), 349 deletions(-) create mode 100644 ffmpeg/custom/016-ffmpeg-srt-1.4.2-fix.patch create mode 100644 ffmpeg/custom/017-ffmpeg-glslang-11.0-fix.patch create mode 100644 ffmpeg/custom/020-ffmpeg-add-svt-hevc-1.5.0.patch create mode 100644 ffmpeg/custom/030-ffmpeg-add-svt-hevc-docs-1.5.0.patch create mode 100644 ffmpeg/custom/040-ffmpeg-add-svt-av1-0.8.4.patch create mode 100644 ffmpeg/custom/050-ffmpeg-add-svt-vp9-0.3.0.patch rename ffmpeg/{libfdk_aac => custom}/PKGBUILD (54%) rename ffmpeg/{libfdk_aac => custom}/vmaf-model-path.patch (100%) delete mode 100644 ffmpeg/full-nvenc/PKGBUILD delete mode 100644 ffmpeg/full-nvenc/UNREDISTRIBUTABLE.txt delete mode 100644 ffmpeg/libfdk_aac-git/PKGBUILD diff --git a/ffmpeg/custom/016-ffmpeg-srt-1.4.2-fix.patch b/ffmpeg/custom/016-ffmpeg-srt-1.4.2-fix.patch new file mode 100644 index 00000000..fcb73f34 --- /dev/null +++ b/ffmpeg/custom/016-ffmpeg-srt-1.4.2-fix.patch @@ -0,0 +1,50 @@ +From 7c59e1b0f285cd7c7b35fcd71f49c5fd52cf9315 Mon Sep 17 00:00:00 2001 +From: Jun Zhao +Date: Sun, 12 Jul 2020 13:48:48 +0800 +Subject: [PATCH] lavf/srt: fix build fail when used the libsrt 1.4.1 + +libsrt changed the: +SRTO_SMOOTHER -> SRTO_CONGESTION +SRTO_STRICTENC -> SRTO_ENFORCEDENCRYPTION +and removed the front of deprecated options (SRTO_SMOOTHER/SRTO_STRICTENC) +in the header, it's lead to build fail + +fix #8760 + +Signed-off-by: Jun Zhao +--- + libavformat/libsrt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c +index 4de575b..4719ce0 100644 +--- a/libavformat/libsrt.c ++++ b/libavformat/libsrt.c +@@ -313,8 +313,12 @@ static int libsrt_set_options_pre(URLContext *h, int fd) + (s->pbkeylen >= 0 && libsrt_setsockopt(h, fd, SRTO_PBKEYLEN, "SRTO_PBKEYLEN", &s->pbkeylen, sizeof(s->pbkeylen)) < 0) || + (s->passphrase && libsrt_setsockopt(h, fd, SRTO_PASSPHRASE, "SRTO_PASSPHRASE", s->passphrase, strlen(s->passphrase)) < 0) || + #if SRT_VERSION_VALUE >= 0x010302 ++#if SRT_VERSION_VALUE >= 0x010401 ++ (s->enforced_encryption >= 0 && libsrt_setsockopt(h, fd, SRTO_ENFORCEDENCRYPTION, "SRTO_ENFORCEDENCRYPTION", &s->enforced_encryption, sizeof(s->enforced_encryption)) < 0) || ++#else + /* SRTO_STRICTENC == SRTO_ENFORCEDENCRYPTION (53), but for compatibility, we used SRTO_STRICTENC */ + (s->enforced_encryption >= 0 && libsrt_setsockopt(h, fd, SRTO_STRICTENC, "SRTO_STRICTENC", &s->enforced_encryption, sizeof(s->enforced_encryption)) < 0) || ++#endif + (s->kmrefreshrate >= 0 && libsrt_setsockopt(h, fd, SRTO_KMREFRESHRATE, "SRTO_KMREFRESHRATE", &s->kmrefreshrate, sizeof(s->kmrefreshrate)) < 0) || + (s->kmpreannounce >= 0 && libsrt_setsockopt(h, fd, SRTO_KMPREANNOUNCE, "SRTO_KMPREANNOUNCE", &s->kmpreannounce, sizeof(s->kmpreannounce)) < 0) || + #endif +@@ -333,7 +337,11 @@ static int libsrt_set_options_pre(URLContext *h, int fd) + (s->lossmaxttl >= 0 && libsrt_setsockopt(h, fd, SRTO_LOSSMAXTTL, "SRTO_LOSSMAXTTL", &s->lossmaxttl, sizeof(s->lossmaxttl)) < 0) || + (s->minversion >= 0 && libsrt_setsockopt(h, fd, SRTO_MINVERSION, "SRTO_MINVERSION", &s->minversion, sizeof(s->minversion)) < 0) || + (s->streamid && libsrt_setsockopt(h, fd, SRTO_STREAMID, "SRTO_STREAMID", s->streamid, strlen(s->streamid)) < 0) || ++#if SRT_VERSION_VALUE >= 0x010401 ++ (s->smoother && libsrt_setsockopt(h, fd, SRTO_CONGESTION, "SRTO_CONGESTION", s->smoother, strlen(s->smoother)) < 0) || ++#else + (s->smoother && libsrt_setsockopt(h, fd, SRTO_SMOOTHER, "SRTO_SMOOTHER", s->smoother, strlen(s->smoother)) < 0) || ++#endif + (s->messageapi >= 0 && libsrt_setsockopt(h, fd, SRTO_MESSAGEAPI, "SRTO_MESSAGEAPI", &s->messageapi, sizeof(s->messageapi)) < 0) || + (s->payload_size >= 0 && libsrt_setsockopt(h, fd, SRTO_PAYLOADSIZE, "SRTO_PAYLOADSIZE", &s->payload_size, sizeof(s->payload_size)) < 0) || + ((h->flags & AVIO_FLAG_WRITE) && libsrt_setsockopt(h, fd, SRTO_SENDER, "SRTO_SENDER", &yes, sizeof(yes)) < 0)) { +-- +2.7.4 + diff --git a/ffmpeg/custom/017-ffmpeg-glslang-11.0-fix.patch b/ffmpeg/custom/017-ffmpeg-glslang-11.0-fix.patch new file mode 100644 index 00000000..4d7e340c --- /dev/null +++ b/ffmpeg/custom/017-ffmpeg-glslang-11.0-fix.patch @@ -0,0 +1,27 @@ +From 4dab04622a6cf2a31da26a51dedb60ec44ac89a4 Mon Sep 17 00:00:00 2001 +From: Ben Clayton +Date: Fri, 10 Jul 2020 16:53:12 +0100 +Subject: [PATCH] libavfilter/glslang: Remove unused header + +The include was not used, and revision.h has +been removed from glslang master. +See: https://github.com/KhronosGroup/glslang/pull/2277 +--- + libavfilter/glslang.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/libavfilter/glslang.cpp b/libavfilter/glslang.cpp +index 497df6e..125eb5c 100644 +--- a/libavfilter/glslang.cpp ++++ b/libavfilter/glslang.cpp +@@ -24,7 +24,6 @@ extern "C" { + } + + #include +-#include + #include + #include + +-- +2.7.4 + diff --git a/ffmpeg/custom/020-ffmpeg-add-svt-hevc-1.5.0.patch b/ffmpeg/custom/020-ffmpeg-add-svt-hevc-1.5.0.patch new file mode 100644 index 00000000..f72977f5 --- /dev/null +++ b/ffmpeg/custom/020-ffmpeg-add-svt-hevc-1.5.0.patch @@ -0,0 +1,647 @@ +From 297c9a0309c8ba06f9f746d7685dceaef7c0b690 Mon Sep 17 00:00:00 2001 +From: Jing Sun +Date: Wed, 21 Nov 2018 11:33:04 +0800 +Subject: [PATCH] lavc/svt_hevc: add libsvt hevc encoder wrapper + +Signed-off-by: Zhengxu Huang +Signed-off-by: Hassene Tmar +Signed-off-by: Jun Zhao +Signed-off-by: Jing Sun +Signed-off-by: Austin Hu +Signed-off-by: Guo Jiansheng +--- + configure | 4 + + libavcodec/Makefile | 1 + + libavcodec/allcodecs.c | 1 + + libavcodec/libsvt_hevc.c | 559 +++++++++++++++++++++++++++++++++++++++ + 4 files changed, 565 insertions(+) + create mode 100644 libavcodec/libsvt_hevc.c + +diff --git a/configure b/configure +index 09bda9b408..454cf65a90 100755 +--- a/configure ++++ b/configure +@@ -267,6 +267,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] +@@ -1801,6 +1802,7 @@ EXTERNAL_LIBRARY_LIST=" + libspeex + libsrt + libssh ++ libsvthevc + libtensorflow + libtesseract + libtheora +@@ -3229,6 +3231,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" +@@ -6344,6 +6347,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 c1c9a44f2b..dd9b930b9b 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -1008,6 +1008,7 @@ OBJS-$(CONFIG_LIBRAV1E_ENCODER) += librav1e.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 b3184af954..41994e31b3 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -720,6 +720,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 0000000000..fce27a06ea +--- /dev/null ++++ b/libavcodec/libsvt_hevc.c +@@ -0,0 +1,559 @@ ++/* ++* 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; ++ int high_dynamic_range; ++ int unrestricted_motion_vector; ++ int tile_row_count; ++ int tile_col_count; ++ int tile_slice_mode; ++} 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; ++ param->vbvMaxrate = avctx->rc_max_rate; ++ param->vbvBufsize = avctx->rc_buffer_size; ++ ++ 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; ++ param->highDynamicRangeInput = svt_enc->high_dynamic_range; ++ 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; ++ ++ if (svt_enc->unrestricted_motion_vector == 0 || svt_enc->unrestricted_motion_vector == 1) { ++ param->unrestrictedMotionVector = svt_enc->unrestricted_motion_vector; ++ } else { ++ av_log(avctx, AV_LOG_ERROR, "Unrestricted Motion Vector should be set 0 or 1\n"); ++ return EB_ErrorBadParameter; ++ } ++ ++ if(svt_enc->tile_row_count >= 1 && svt_enc->tile_row_count <= 16) { ++ param->tileRowCount = svt_enc->tile_row_count; ++ } else { ++ av_log(avctx, AV_LOG_ERROR, "Tile Row Count should between 1-16\n"); ++ return EB_ErrorBadParameter; ++ } ++ ++ if(svt_enc->tile_col_count >= 1 && svt_enc->tile_col_count <= 16) { ++ param->tileColumnCount = svt_enc->tile_col_count; ++ } else { ++ av_log(avctx, AV_LOG_ERROR, "Tile Column Count should between 1-16\n"); ++ return EB_ErrorBadParameter; ++ } ++ ++ if(svt_enc->tile_slice_mode == 0 || svt_enc->tile_slice_mode == 1) { ++ param->tileSliceMode = svt_enc->tile_slice_mode; ++ } else { ++ av_log(avctx, AV_LOG_ERROR, "Tile Slice Mode should be set 0 or 1\n"); ++ return EB_ErrorBadParameter; ++ } ++ 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; ++ } else if (svt_ret == EB_ErrorMax) { ++ *got_packet = 0; ++ av_log(avctx, AV_LOG_ERROR, "Received NULL packet with error code 0x%X\n", header_ptr->nFlags); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ 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" }, ++ { "hdr", "High dynamic range input (HDR10)", OFFSET(high_dynamic_range), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 1, VE, "hdr" }, ++ { "umv", "Enables or disables unrestricted motion vectors", OFFSET(unrestricted_motion_vector), ++ AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, ++ { "tile_row_cnt", "tile count in the row", OFFSET(tile_row_count), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 16, VE }, ++ { "tile_col_cnt", "tile count in the column", OFFSET(tile_col_count), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 16, VE }, ++ { "tile_slice_mode", "per slice per tile, only valid for multi-tile", OFFSET(tile_slice_mode), ++ AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, ++ {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", ++}; +-- +2.17.1 + diff --git a/ffmpeg/custom/030-ffmpeg-add-svt-hevc-docs-1.5.0.patch b/ffmpeg/custom/030-ffmpeg-add-svt-hevc-docs-1.5.0.patch new file mode 100644 index 00000000..b1e14880 --- /dev/null +++ b/ffmpeg/custom/030-ffmpeg-add-svt-hevc-docs-1.5.0.patch @@ -0,0 +1,198 @@ +From 6b0a4fd63454e3c2185efe741e50e80df5c9a4a4 Mon Sep 17 00:00:00 2001 +From: Jing Sun +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 +Signed-off-by: Zhengxu Huang +Signed-off-by: Hassene Tmar +Signed-off-by: Jing Sun +--- + 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/custom/040-ffmpeg-add-svt-av1-0.8.4.patch b/ffmpeg/custom/040-ffmpeg-add-svt-av1-0.8.4.patch new file mode 100644 index 00000000..01d8050e --- /dev/null +++ b/ffmpeg/custom/040-ffmpeg-add-svt-av1-0.8.4.patch @@ -0,0 +1,671 @@ +From 726a9def395d40aa0d8a4b8fe5ebc1af13015dbb Mon Sep 17 00:00:00 2001 +From: Daryl Seah +Date: Fri, 18 Jan 2019 02:11:38 +0000 +Subject: [PATCH] Add ability for ffmpeg to run svt-av1 + +Change-Id: I37ee5414fdd99e0b3f112a6e5ede166f3e48d819 +Signed-off-by: Daryl Seah +Signed-off-by: Jing SUN +Signed-off-by: ZhiZhen Tang +Signed-off-by: Zhong Li +Signed-off-by: Xu Guangxin +--- + configure | 4 + + libavcodec/Makefile | 1 + + libavcodec/allcodecs.c | 1 + + libavcodec/libsvt_av1.c | 583 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 589 insertions(+) + create mode 100644 libavcodec/libsvt_av1.c + +diff --git a/configure b/configure +index 7495f35faa..e0a466b968 100755 +--- a/configure ++++ b/configure +@@ -249,6 +249,7 @@ External library support: + --enable-libmp3lame enable MP3 encoding via libmp3lame [no] + --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no] + --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no] ++ --enable-libsvtav1 enable AV1 encoding via svt [no] + --enable-libopencv enable video filtering via libopencv [no] + --enable-libopenh264 enable H.264 encoding via OpenH264 [no] + --enable-libopenjpeg enable JPEG 2000 de/encoding via OpenJPEG [no] +@@ -1786,6 +1787,7 @@ EXTERNAL_LIBRARY_LIST=" + libmodplug + libmp3lame + libmysofa ++ libsvtav1 + libopencv + libopenh264 + libopenjpeg +@@ -3223,6 +3225,7 @@ libopencore_amrnb_decoder_deps="libopencore_amrnb" + libopencore_amrnb_encoder_deps="libopencore_amrnb" + libopencore_amrnb_encoder_select="audio_frame_queue" + libopencore_amrwb_decoder_deps="libopencore_amrwb" ++libsvt_av1_encoder_deps="libsvtav1" + libopenh264_decoder_deps="libopenh264" + libopenh264_decoder_select="h264_mp4toannexb_bsf" + libopenh264_encoder_deps="libopenh264" +@@ -6342,6 +6345,7 @@ enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig - + die "ERROR: libnpp not found"; } + enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb + enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb ++enabled libsvtav1 && require_pkg_config libsvtav1 SvtAv1Enc EbSvtAv1Enc.h svt_av1_enc_init_handle + enabled libopencv && { check_headers opencv2/core/core_c.h && + { check_pkg_config libopencv opencv opencv2/core/core_c.h cvCreateImageHeader || + require libopencv opencv2/core/core_c.h cvCreateImageHeader -lopencv_core -lopencv_imgproc; } || +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 5a6ea59715..b4dbca54d5 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -971,6 +971,7 @@ OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o + OBJS-$(CONFIG_ELBG_FILTER) += elbg.o + + # external codec libraries ++OBJS-$(CONFIG_LIBSVT_AV1_ENCODER) += libsvt_av1.o + OBJS-$(CONFIG_AAC_AT_DECODER) += audiotoolboxdec.o + OBJS-$(CONFIG_AC3_AT_DECODER) += audiotoolboxdec.o + OBJS-$(CONFIG_ADPCM_IMA_QT_AT_DECODER) += audiotoolboxdec.o +diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c +index fa0c08d42e..ec1e0d48ba 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -716,6 +716,7 @@ extern AVCodec ff_libmp3lame_encoder; + extern AVCodec ff_libopencore_amrnb_encoder; + extern AVCodec ff_libopencore_amrnb_decoder; + extern AVCodec ff_libopencore_amrwb_decoder; ++extern AVCodec ff_libsvt_av1_encoder; + extern AVCodec ff_libopenjpeg_encoder; + extern AVCodec ff_libopenjpeg_decoder; + extern AVCodec ff_libopus_encoder; +diff --git a/libavcodec/libsvt_av1.c b/libavcodec/libsvt_av1.c +new file mode 100644 +index 0000000000..541ba228fa +--- /dev/null ++++ b/libavcodec/libsvt_av1.c +@@ -0,0 +1,583 @@ ++ ++/* ++* 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 ++#include "EbSvtAv1ErrorCodes.h" ++#include "EbSvtAv1Enc.h" ++ ++#include "libavutil/common.h" ++#include "libavutil/frame.h" ++#include "libavutil/opt.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/avassert.h" ++ ++#include "internal.h" ++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 93, 100) ++#include "encode.h" ++#endif ++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 90, 100) ++#include "packet_internal.h" ++#endif ++#include "avcodec.h" ++ ++typedef enum eos_status { ++ EOS_NOT_REACHED = 0, ++ EOS_SENT, ++ EOS_RECEIVED ++}EOS_STATUS; ++ ++typedef struct SvtContext { ++ AVClass *class; ++ ++ EbSvtAv1EncConfiguration enc_params; ++ EbComponentType *svt_handle; ++ ++ EbBufferHeaderType *in_buf; ++ int raw_size; ++ int max_tu_size; ++ ++ AVFrame *frame; ++ ++ AVBufferPool* pool; ++ ++ EOS_STATUS eos_flag; ++ ++ // User options. ++ int hierarchical_level; ++ int la_depth; ++ int enc_mode; ++ int rc_mode; ++ int scd; ++ int qp; ++ ++ int forced_idr; ++ ++ int tier; ++ int level; ++ int profile; ++ ++ int tile_columns; ++ int tile_rows; ++} SvtContext; ++ ++static const struct { ++ EbErrorType eb_err; ++ int av_err; ++ const char *desc; ++} svt_errors[] = { ++ { EB_ErrorNone, 0, "success" }, ++ { EB_ErrorInsufficientResources, AVERROR(ENOMEM), "insufficient resources" }, ++ { EB_ErrorUndefined, AVERROR(EINVAL), "undefined error" }, ++ { EB_ErrorInvalidComponent, AVERROR(EINVAL), "invalid component" }, ++ { EB_ErrorBadParameter, AVERROR(EINVAL), "bad parameter" }, ++ { EB_ErrorDestroyThreadFailed, AVERROR_EXTERNAL, "failed to destory thread" }, ++ { EB_ErrorSemaphoreUnresponsive, AVERROR_EXTERNAL, "semaphore unresponsive" }, ++ { EB_ErrorDestroySemaphoreFailed, AVERROR_EXTERNAL, "semaphore unresponsive" }, ++ { EB_ErrorCreateMutexFailed, AVERROR_EXTERNAL, "failed to creat mutex" }, ++ { EB_ErrorMutexUnresponsive, AVERROR_EXTERNAL, "mutex unresponsive" }, ++ { EB_ErrorDestroyMutexFailed, AVERROR_EXTERNAL, "failed to destory muxtex" }, ++ { EB_NoErrorEmptyQueue, AVERROR(EAGAIN), "empty queue" }, ++}; ++ ++static int svt_map_error(EbErrorType eb_err, const char **desc) ++{ ++ int i; ++ ++ av_assert0(desc); ++ for (i = 0; i < FF_ARRAY_ELEMS(svt_errors); i++) { ++ if (svt_errors[i].eb_err == eb_err) { ++ *desc = svt_errors[i].desc; ++ return svt_errors[i].av_err; ++ } ++ } ++ *desc = "unknown error"; ++ return AVERROR_UNKNOWN; ++} ++ ++static int svt_print_error(void *log_ctx, EbErrorType err, ++ const char *error_string) ++{ ++ const char *desc; ++ int ret; ++ ret = svt_map_error(err, &desc); ++ av_log(log_ctx, AV_LOG_ERROR, "%s: %s (0x%x)\n", error_string, desc, err); ++ return ret; ++} ++ ++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); ++ } ++ av_buffer_pool_uninit(&svt_enc->pool); ++} ++ ++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) ++ return AVERROR(ENOMEM); ++ ++ svt_enc->in_buf->p_buffer = (unsigned char *)av_mallocz(sizeof(*in_data)); ++ if (!svt_enc->in_buf->p_buffer) ++ return AVERROR(ENOMEM); ++ ++ svt_enc->in_buf->size = sizeof(*svt_enc->in_buf); ++ svt_enc->in_buf->p_app_private = NULL; ++ ++ return 0; ++ ++} ++ ++static int config_enc_params(EbSvtAv1EncConfiguration *param, ++ AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ const AVPixFmtDescriptor *desc; ++ ++ param->source_width = avctx->width; ++ param->source_height = avctx->height; ++ ++ desc = av_pix_fmt_desc_get(avctx->pix_fmt); ++ param->encoder_bit_depth = desc->comp[0].depth; ++ av_log(avctx, AV_LOG_DEBUG , "Encoder %d bits depth input\n", param->encoder_bit_depth); ++ ++ if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1) ++ param->encoder_color_format = EB_YUV420; ++ else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 0) ++ param->encoder_color_format = EB_YUV422; ++ else if (!desc->log2_chroma_w && !desc->log2_chroma_h) ++ param->encoder_color_format = EB_YUV444; ++ else { ++ av_log(avctx, AV_LOG_ERROR , "Unsupported pixel format\n"); ++ return AVERROR(EINVAL); ++ } ++ av_log(avctx, AV_LOG_DEBUG , "Encoder color format is %d \n", param->encoder_color_format); ++ ++ param->profile = svt_enc->profile; ++ ++ if ((param->encoder_color_format == EB_YUV422 || param->encoder_bit_depth > 10) ++ && param->profile != PROFESSIONAL_PROFILE ) { ++ av_log(avctx, AV_LOG_WARNING, "Force to be professional profile \n"); ++ param->profile = PROFESSIONAL_PROFILE; ++ } else if (param->encoder_color_format == EB_YUV444 && param->profile != HIGH_PROFILE) { ++ av_log(avctx, AV_LOG_WARNING, "Force to be high profile \n"); ++ param->profile = HIGH_PROFILE; ++ } ++ ++ // 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->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 = svt_enc->forced_idr + 1; ++ ++ if (svt_enc->la_depth != -1) ++ param->look_ahead_distance = svt_enc->la_depth; ++ ++ param->tile_columns = svt_enc->tile_columns; ++ param->tile_rows = svt_enc->tile_rows; ++ ++ return 0; ++} ++ ++static void read_in_data(const AVFrame *frame, ++ EbBufferHeaderType *header_ptr) ++{ ++ EbSvtIOFormat *in_data = (EbSvtIOFormat *)header_ptr->p_buffer; ++ const AVPixFmtDescriptor *desc; ++ int i, bytes_shift, plane_h; ++ ++ desc = av_pix_fmt_desc_get(frame->format); ++ bytes_shift = desc->comp[0].depth > 8 ? 1 : 0; ++ ++ in_data->luma = frame->data[0]; ++ in_data->cb = frame->data[1]; ++ in_data->cr = frame->data[2]; ++ ++ in_data->y_stride = AV_CEIL_RSHIFT(frame->linesize[0], bytes_shift); ++ in_data->cb_stride = AV_CEIL_RSHIFT(frame->linesize[1], bytes_shift); ++ in_data->cr_stride = AV_CEIL_RSHIFT(frame->linesize[2], bytes_shift); ++ ++ for (i = 0; i < desc->nb_components; i++) { ++ plane_h = frame->height; ++ if (i > 0) ++ plane_h = AV_CEIL_RSHIFT(plane_h, desc->log2_chroma_h); ++ header_ptr->n_filled_len += frame->linesize[i] * plane_h; ++ } ++} ++ ++static av_cold int eb_enc_init(AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EbErrorType svt_ret; ++ int ret; ++ ++ svt_enc->eos_flag = EOS_NOT_REACHED; ++ ++ svt_ret = svt_av1_enc_init_handle(&svt_enc->svt_handle, svt_enc, &svt_enc->enc_params); ++ if (svt_ret != EB_ErrorNone) { ++ return svt_print_error(avctx, svt_ret, "Error init encoder handle"); ++ } ++ ++ ret = config_enc_params(&svt_enc->enc_params, avctx); ++ if (ret < 0) { ++ av_log(avctx, AV_LOG_ERROR, "Error configure encoder parameters\n"); ++ return ret; ++ } ++ ++ svt_ret = svt_av1_enc_set_parameter(svt_enc->svt_handle, &svt_enc->enc_params); ++ if (svt_ret != EB_ErrorNone) { ++ return svt_print_error(avctx, svt_ret, "Error setting encoder parameters"); ++ } ++ ++ svt_ret = svt_av1_enc_init(svt_enc->svt_handle); ++ if (svt_ret != EB_ErrorNone) { ++ svt_av1_enc_deinit_handle(svt_enc->svt_handle); ++ svt_enc->svt_handle = NULL; ++ return svt_print_error(avctx, svt_ret, "Error init encoder"); ++ } ++ ++ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { ++ EbBufferHeaderType *headerPtr = NULL; ++ ++ svt_ret = svt_av1_enc_stream_header(svt_enc->svt_handle, &headerPtr); ++ if (svt_ret != EB_ErrorNone) { ++ return svt_print_error(avctx, svt_ret, "Error when build stream header"); ++ } ++ ++ 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); ++ return AVERROR(ENOMEM); ++ } ++ ++ memcpy(avctx->extradata, headerPtr->p_buffer, avctx->extradata_size); ++ ++ svt_ret = svt_av1_enc_stream_header_release(headerPtr); ++ if (svt_ret != EB_ErrorNone) { ++ return svt_print_error(avctx, svt_ret, "Error when destroy stream header"); ++ } ++ } ++ ++ svt_enc->frame = av_frame_alloc(); ++ if (!svt_enc->frame) ++ return AVERROR(ENOMEM); ++ ++ ret = alloc_buffer(&svt_enc->enc_params, svt_enc); ++ if (ret < 0) ++ return ret; ++ return 0; ++ ++} ++ ++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; ++ ++ if (svt_enc->eos_flag == EOS_SENT) ++ return 0; ++ ++ 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; ++ ++ svt_av1_enc_send_picture(svt_enc->svt_handle, &headerPtrLast); ++ svt_enc->eos_flag = EOS_SENT; ++ av_log(avctx, AV_LOG_DEBUG, "Finish sending frames!!!\n"); ++ return 0; ++ } ++ ++ read_in_data(frame, headerPtr); ++ ++ headerPtr->flags = 0; ++ headerPtr->p_app_private = NULL; ++ headerPtr->pts = frame->pts; ++ ++ svt_av1_enc_send_picture(svt_enc->svt_handle, headerPtr); ++ ++ return 0; ++} ++ ++static AVBufferRef* get_output_ref(AVCodecContext *avctx, SvtContext *svt_enc, int filled_len) ++{ ++ if (filled_len > svt_enc->max_tu_size) { ++ const int MAX_FRAMES = 8; ++ int max_tu_size; ++ if (filled_len > svt_enc->raw_size * MAX_FRAMES) { ++ av_log(avctx, AV_LOG_ERROR, "something wrong in libsvtav1, the tu size > %d raw frame size.\n", MAX_FRAMES); ++ return NULL; ++ } ++ max_tu_size = 1 << av_ceil_log2(filled_len); ++ av_buffer_pool_uninit(&svt_enc->pool); ++ svt_enc->pool = av_buffer_pool_init(max_tu_size, NULL); ++ if (!svt_enc->pool) { ++ return NULL; ++ } ++ svt_enc->max_tu_size = max_tu_size; ++ } ++ if (!svt_enc->pool) { ++ av_log(avctx, AV_LOG_ERROR, "bug, no buffer pool.\n"); ++ return NULL; ++ } ++ return av_buffer_pool_get(svt_enc->pool); ++} ++ ++static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ EbBufferHeaderType *headerPtr; ++ AVFrame *frame = svt_enc->frame; ++ EbErrorType svt_ret; ++ int ret = 0, pict_type; ++ AVBufferRef* ref; ++ ++ if (svt_enc->eos_flag == EOS_RECEIVED) ++ return AVERROR_EOF; ++ ++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 93, 100) ++ ret = ff_encode_get_frame(avctx, frame); ++ if (ret < 0 && ret != AVERROR_EOF) ++ return ret; ++ if (ret == AVERROR_EOF) ++ frame = NULL; ++ ++ eb_send_frame(avctx, frame); ++ av_frame_unref(svt_enc->frame); ++#endif ++ ++ svt_ret = svt_av1_enc_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag); ++ if (svt_ret == EB_NoErrorEmptyQueue) ++ return AVERROR(EAGAIN); ++ ++ ref = get_output_ref(avctx, svt_enc, headerPtr->n_filled_len); ++ if (!ref) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); ++ svt_av1_enc_release_out_buffer(&headerPtr); ++ return AVERROR(ENOMEM); ++ } ++ pkt->buf = ref; ++ pkt->data = ref->data; ++ ++ 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; ++ pict_type = AV_PICTURE_TYPE_I; ++ } else if (headerPtr->pic_type == EB_AV1_INTRA_ONLY_PICTURE) { ++ pict_type = AV_PICTURE_TYPE_I; ++ } else if (headerPtr->pic_type == EB_AV1_INVALID_PICTURE) { ++ pict_type = AV_PICTURE_TYPE_NONE; ++ } else ++ pict_type = AV_PICTURE_TYPE_P; ++ ++ if (headerPtr->pic_type == EB_AV1_NON_REF_PICTURE) ++ pkt->flags |= AV_PKT_FLAG_DISPOSABLE; ++ ++ if (headerPtr->flags & EB_BUFFERFLAG_EOS) ++ svt_enc->eos_flag = EOS_RECEIVED; ++ ++ ff_side_data_set_encoder_stats(pkt, headerPtr->qp * FF_QP2LAMBDA, NULL, 0, pict_type); ++ ++ svt_av1_enc_release_out_buffer(&headerPtr); ++ ++ return 0; ++} ++ ++static av_cold int eb_enc_close(AVCodecContext *avctx) ++{ ++ SvtContext *svt_enc = avctx->priv_data; ++ ++ if (svt_enc) { ++ if (svt_enc->svt_handle) { ++ svt_av1_enc_deinit(svt_enc->svt_handle); ++ svt_av1_enc_deinit_handle(svt_enc->svt_handle); ++ } ++ ++ av_frame_free(&svt_enc->frame); ++ ++ free_buffer(svt_enc); ++ svt_enc = 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[] = { ++ { "hielevel", "Hierarchical prediction levels setting", OFFSET(hierarchical_level), ++ AV_OPT_TYPE_INT, { .i64 = 4 }, 3, 4, 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, 120]", OFFSET(la_depth), ++ AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 120, VE }, ++ ++ { "preset", "Encoding preset [0, 8]", ++ OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = MAX_ENC_PRESET }, 0, MAX_ENC_PRESET, VE }, ++ ++ { "profile", "Set profile restrictions", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = MAIN_PROFILE}, MAIN_PROFILE, PROFESSIONAL_PROFILE, VE, "profile" }, ++ { "main" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MAIN_PROFILE}, INT_MIN, INT_MAX, VE, "profile" }, ++ { "high" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = HIGH_PROFILE}, INT_MIN, INT_MAX, VE, "profile" }, ++ { "professional", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PROFESSIONAL_PROFILE }, INT_MIN, INT_MAX, VE, "profile" }, ++ ++ { "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, 0x1f, VE, "level" }, ++ ++#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ ++ { .i64 = value }, 0, 0, VE, "level" ++ { LEVEL("2.0", 20) }, ++ { LEVEL("2.1", 21) }, ++ { LEVEL("2.2", 22) }, ++ { LEVEL("2.3", 23) }, ++ { LEVEL("3.0", 30) }, ++ { LEVEL("3.1", 31) }, ++ { LEVEL("3.2", 32) }, ++ { LEVEL("3.3", 33) }, ++ { LEVEL("4.0", 40) }, ++ { LEVEL("4.1", 41) }, ++ { LEVEL("4.2", 42) }, ++ { LEVEL("4.3", 43) }, ++ { LEVEL("5.0", 50) }, ++ { LEVEL("5.1", 51) }, ++ { LEVEL("5.2", 52) }, ++ { LEVEL("5.3", 53) }, ++ { LEVEL("6.0", 60) }, ++ { LEVEL("6.1", 61) }, ++ { LEVEL("6.2", 62) }, ++ { LEVEL("6.3", 63) }, ++ { LEVEL("7.0", 70) }, ++ { LEVEL("7.1", 71) }, ++ { LEVEL("7.2", 72) }, ++ { LEVEL("7.3", 73) }, ++#undef LEVEL ++ ++ { "rc", "Bit rate control mode", OFFSET(rc_mode), ++ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, VE , "rc"}, ++ { "cqp", "Const Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "rc" }, ++ { "vbr", "Variable Bit Rate, use a target bitrate for the entire stream", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "rc" }, ++ { "cvbr", "Constrained Variable Bit Rate, use a target bitrate for each GOP", 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 = 50 }, 0, 63, VE }, ++ ++ { "sc_detection", "Scene change detection", OFFSET(scd), ++ 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 = 1 }, 0, 1, VE }, ++ { "tile-columns", "Log2 of number of tile columns to use", OFFSET(tile_columns), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, VE}, ++ { "tile-rows", "Log2 of number of tile rows to use", OFFSET(tile_rows), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 6, 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" }, ++ { "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, ++#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 93, 100) ++ .send_frame = eb_send_frame, ++#endif ++ .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_YUV420P10, ++ AV_PIX_FMT_NONE }, ++ .priv_class = &class, ++ .defaults = eb_enc_defaults, ++ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, ++ .wrapper_name = "libsvt_av1", ++}; +-- +2.17.1 + diff --git a/ffmpeg/custom/050-ffmpeg-add-svt-vp9-0.3.0.patch b/ffmpeg/custom/050-ffmpeg-add-svt-vp9-0.3.0.patch new file mode 100644 index 00000000..1fb38fc2 --- /dev/null +++ b/ffmpeg/custom/050-ffmpeg-add-svt-vp9-0.3.0.patch @@ -0,0 +1,961 @@ +From 213cabc3d23724beae998e473660702fe30aaad1 Mon Sep 17 00:00:00 2001 +From: hassene +Date: Fri, 15 Feb 2019 17:43:54 -0800 +Subject: [PATCH] Add ability for ffmpeg to run svt vp9 + +Signed-off-by: hassene +Signed-off-by: Jing Sun +Signed-off-by: Austin Hu +Signed-off-by: Guo Jiansheng +--- + configure | 4 + + libavcodec/Makefile | 1 + + libavcodec/allcodecs.c | 1 + + libavcodec/avcodec.h | 4 + + libavcodec/libsvt_vp9.c | 509 ++++++++++++++++++++++++++++++++++++++ + libavformat/dashenc.c | 49 +++- + libavformat/ivfenc.c | 30 ++- + libavformat/matroskaenc.c | 104 +++++++- + libavformat/movenc.c | 42 +++- + 9 files changed, 733 insertions(+), 11 deletions(-) + create mode 100644 libavcodec/libsvt_vp9.c + +diff --git a/configure b/configure +index bdfd731602..fbe6f838df 100755 +--- a/configure ++++ b/configure +@@ -283,6 +283,7 @@ External library support: + --enable-libvorbis enable Vorbis en/decoding via libvorbis, + native implementation exists [no] + --enable-libvpx enable VP8 and VP9 de/encoding via libvpx [no] ++ --enable-libsvtvp9 enable VP9 encoding via svt [no] + --enable-libwavpack enable wavpack encoding via libwavpack [no] + --enable-libwebp enable WebP encoding via libwebp [no] + --enable-libx264 enable H.264 encoding via x264 [no] +@@ -1800,6 +1801,7 @@ EXTERNAL_LIBRARY_LIST=" + librtmp + libshine + libsmbclient ++ libsvtvp9 + libsnappy + libsoxr + libspeex +@@ -3253,6 +3255,7 @@ libvpx_vp8_decoder_deps="libvpx" + libvpx_vp8_encoder_deps="libvpx" + libvpx_vp9_decoder_deps="libvpx" + libvpx_vp9_encoder_deps="libvpx" ++libsvt_vp9_encoder_deps="libsvtvp9" + libwavpack_encoder_deps="libwavpack" + libwavpack_encoder_select="audio_frame_queue" + libwebp_encoder_deps="libwebp" +@@ -6412,6 +6415,7 @@ enabled libvpx && { + fi + } + ++enabled libsvtvp9 && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle + enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack + enabled libwebp && { + enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion +diff --git a/libavcodec/Makefile b/libavcodec/Makefile +index 18353da549..230660ea27 100644 +--- a/libavcodec/Makefile ++++ b/libavcodec/Makefile +@@ -1035,6 +1035,7 @@ OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o + OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o + OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o + OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o ++OBJS-$(CONFIG_LIBSVT_VP9_ENCODER) += libsvt_vp9.o + OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o + OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o + OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o +diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c +index a5048290f7..c34ef96fb9 100644 +--- a/libavcodec/allcodecs.c ++++ b/libavcodec/allcodecs.c +@@ -735,6 +735,7 @@ extern AVCodec ff_libvpx_vp8_encoder; + extern AVCodec ff_libvpx_vp8_decoder; + extern AVCodec ff_libvpx_vp9_encoder; + extern AVCodec ff_libvpx_vp9_decoder; ++extern AVCodec ff_libsvt_vp9_encoder; + extern AVCodec ff_libwavpack_encoder; + /* preferred over libwebp */ + extern AVCodec ff_libwebp_anim_encoder; +diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h +index c91b2fd169..10cdb7b0d9 100644 +--- a/libavcodec/avcodec.h ++++ b/libavcodec/avcodec.h +@@ -405,6 +405,10 @@ typedef struct RcOverride{ + * Export encoder Producer Reference Time through packet side data + */ + #define AV_CODEC_EXPORT_DATA_PRFT (1 << 1) ++ ++#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 ++ + /** + * Decoding only. + * Export the AVVideoEncParams structure through frame side data. +diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c +new file mode 100644 +index 0000000000..a557019c9b +--- /dev/null ++++ b/libavcodec/libsvt_vp9.c +@@ -0,0 +1,509 @@ ++/* ++* 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 ++#include "EbSvtVp9ErrorCodes.h" ++#include "EbSvtVp9Enc.h" ++ ++#include "libavutil/common.h" ++#include "libavutil/frame.h" ++#include "libavutil/opt.h" ++ ++#include "internal.h" ++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 93, 100) ++#include "encode.h" ++#endif ++#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; ++ ++ AVFrame *frame; ++ ++ AVBufferPool* pool; ++ ++ 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); ++ } ++ av_buffer_pool_uninit(&svt_enc->pool); ++} ++ ++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; ++ ++ ++ svt_enc->in_buf->p_buffer = (unsigned char *)av_mallocz(sizeof(*in_data)); ++ if (!svt_enc->in_buf->p_buffer) ++ goto failed; ++ ++ svt_enc->in_buf->size = sizeof(*svt_enc->in_buf); ++ svt_enc->in_buf->p_app_private = NULL; ++ ++ svt_enc->pool = av_buffer_pool_init(svt_enc->raw_size, NULL); ++ if (!svt_enc->pool) ++ goto failed; ++ ++ 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; ++ } ++ ++ 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; ++ } ++ ++ svt_enc->frame = av_frame_alloc(); ++ if (!svt_enc->frame) ++ return AVERROR(ENOMEM); ++ ++ // 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) { ++ if (svt_enc->eos_flag == EOS_REACHED) ++ return 0; ++ ++ 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; ++ AVBufferRef *ref; ++ ++ if (EOS_TOTRIGGER == svt_enc->eos_flag) { ++ pkt = NULL; ++ return AVERROR_EOF; ++ } ++ ++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 93, 100) ++ AVFrame *frame = svt_enc->frame; ++ int ret = ff_encode_get_frame(avctx, frame); ++ if (ret < 0 && ret != AVERROR_EOF) ++ return ret; ++ if (ret == AVERROR_EOF) ++ frame = NULL; ++ ++ eb_send_frame(avctx, frame); ++ av_frame_unref(svt_enc->frame); ++#endif ++ ++ svt_ret = eb_vp9_svt_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag); ++ if (svt_ret == EB_NoErrorEmptyQueue) ++ return AVERROR(EAGAIN); ++ ++ ref = av_buffer_pool_get(svt_enc->pool); ++ if (!ref) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); ++ eb_vp9_svt_release_out_buffer(&headerPtr); ++ return AVERROR(ENOMEM); ++ } ++ pkt->buf = ref; ++ pkt->data = ref->data; ++ ++ 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); ++ ++ av_frame_free(&svt_enc->frame); ++ ++ 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, ++#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 93, 100) ++ .send_frame = eb_send_frame, ++#endif ++ .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/dashenc.c b/libavformat/dashenc.c +index dc3306a56a..13c8a92268 100644 +--- a/libavformat/dashenc.c ++++ b/libavformat/dashenc.c +@@ -2270,6 +2270,48 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) + return ret; + } + ++static int dash_write_packet_vp9(AVFormatContext *s, AVPacket *pkt) ++{ ++ int ret; ++ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { ++ uint8_t *saved_data = pkt->data; ++ int saved_size = pkt->size; ++ int64_t saved_pts = pkt->pts; ++ ++ // Main frame ++ pkt->data = saved_data; ++ pkt->size = saved_size - 4; ++ pkt->pts = saved_pts; ++ ret = dash_write_packet(s, pkt); ++ ++ // Latter 4 one-byte repeated frames ++ pkt->data = saved_data + saved_size - 4; ++ pkt->size = 1; ++ pkt->pts = saved_pts - 2; ++ ret = dash_write_packet(s, pkt); ++ ++ pkt->data = saved_data + saved_size - 3; ++ pkt->size = 1; ++ pkt->pts = saved_pts - 1; ++ ret = dash_write_packet(s, pkt); ++ ++ pkt->data = saved_data + saved_size - 2; ++ pkt->size = 1; ++ pkt->pts = saved_pts; ++ ret = dash_write_packet(s, pkt); ++ ++ pkt->data = saved_data + saved_size - 1; ++ pkt->size = 1; ++ pkt->pts = saved_pts + 1; ++ ret = dash_write_packet(s, pkt); ++ } ++ else{ ++ ret = dash_write_packet(s, pkt); ++ } ++ ++ return ret; ++} ++ + static int dash_write_trailer(AVFormatContext *s) + { + DASHContext *c = s->priv_data; +@@ -2317,6 +2359,11 @@ static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt + DASHContext *c = s->priv_data; + OutputStream *os = &c->streams[avpkt->stream_index]; + AVFormatContext *oc = os->ctx; ++ ++ if ((avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || ++ (avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) ++ return 0; ++ + if (oc->oformat->check_bitstream) { + int ret; + AVPacket pkt = *avpkt; +@@ -2404,7 +2451,7 @@ AVOutputFormat ff_dash_muxer = { + .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE, + .init = dash_init, + .write_header = dash_write_header, +- .write_packet = dash_write_packet, ++ .write_packet = dash_write_packet_vp9, + .write_trailer = dash_write_trailer, + .deinit = dash_free, + .check_bitstream = dash_check_bitstream, +diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c +index 0951f56c92..3a49097e9a 100644 +--- a/libavformat/ivfenc.c ++++ b/libavformat/ivfenc.c +@@ -81,9 +81,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++; +diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c +index 233c472b8f..00e6ccc8b5 100644 +--- a/libavformat/matroskaenc.c ++++ b/libavformat/matroskaenc.c +@@ -142,6 +142,9 @@ typedef struct MatroskaMuxContext { + unsigned nb_attachments; + int have_video; + ++ int simple_block_timecode; ++ int accumulated_cluster_timecode; ++ + int wrote_chapters; + int wrote_tags; + +@@ -2084,7 +2087,13 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, + put_ebml_id(pb, blockid); + put_ebml_length(pb, size + track->track_num_size + 3, 0); + put_ebml_num(pb, track_number, track->track_num_size); +- avio_wb16(pb, ts - mkv->cluster_pts); ++ ++ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || ++ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) ++ avio_wb16(pb, mkv->simple_block_timecode); ++ else ++ avio_wb16(pb, ts - mkv->cluster_pts); ++ + avio_w8(pb, (blockid == MATROSKA_ID_SIMPLEBLOCK && keyframe) ? (1 << 7) : 0); + avio_write(pb, data + offset, size); + if (data != pkt->data) +@@ -2268,7 +2277,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) + return 0; + } + +-static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) ++static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) + { + MatroskaMuxContext *mkv = s->priv_data; + AVIOContext *pb; +@@ -2279,6 +2288,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) + int ret; + int64_t ts = track->write_dts ? pkt->dts : pkt->pts; + int64_t relative_packet_pos; ++ double fps = 0; ++ int pts_interval = 0; + + if (ts == AV_NOPTS_VALUE) { + av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); +@@ -2296,6 +2307,11 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) + } + } + ++ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { ++ fps = av_q2d(s->streams[pkt->stream_index]->avg_frame_rate); ++ pts_interval = 1000 / fps; ++ } ++ + if (mkv->cluster_pos == -1) { + ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv); + if (ret < 0) +@@ -2313,7 +2329,67 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) + relative_packet_pos = avio_tell(pb); + + if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { +- ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); ++ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { ++ uint8_t *saved_data = pkt->data; ++ int saved_size = pkt->size; ++ int64_t saved_pts = pkt->pts; ++ // Main frame ++ pkt->data = saved_data; ++ pkt->size = saved_size - 4; ++ pkt->pts = saved_pts; ++ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); ++ ++ // Latter 4 one-byte repeated frames ++ pkt->data = saved_data + saved_size - 4; ++ pkt->size = 1; ++ pkt->pts = saved_pts - 2; ++ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); ++ mkv->simple_block_timecode += pts_interval; ++ ++ pkt->data = saved_data + saved_size - 3; ++ pkt->size = 1; ++ pkt->pts = saved_pts - 1; ++ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); ++ mkv->simple_block_timecode += pts_interval; ++ ++ pkt->data = saved_data + saved_size - 2; ++ pkt->size = 1; ++ pkt->pts = saved_pts; ++ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); ++ mkv->simple_block_timecode += pts_interval; ++ ++ pkt->data = saved_data + saved_size - 1; ++ pkt->size = 1; ++ pkt->pts = saved_pts + 1; ++ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); ++ mkv->simple_block_timecode += pts_interval; ++ } else { ++ ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); ++ if (ret < 0) return ret; ++ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF) { ++ GetBitContext gb; ++ int invisible, profile; ++ ++ if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0) ++ return ret; ++ ++ get_bits(&gb, 2); // frame marker ++ profile = get_bits1(&gb); ++ profile |= get_bits1(&gb) << 1; ++ if (profile == 3) profile += get_bits1(&gb); ++ ++ if (get_bits1(&gb)) { ++ invisible = 0; ++ } else { ++ get_bits1(&gb); // keyframe ++ invisible = !get_bits1(&gb); ++ } ++ ++ if (!invisible) ++ mkv->simple_block_timecode += pts_interval; ++ } ++ } ++ + if (ret < 0) + return ret; + if (keyframe && IS_SEEKABLE(s->pb, mkv) && +@@ -2377,8 +2453,14 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt) + if (mkv->cluster_pos != -1) { + if (mkv->tracks[pkt->stream_index].write_dts) + cluster_time = pkt->dts - mkv->cluster_pts; +- else +- cluster_time = pkt->pts - mkv->cluster_pts; ++ else { ++ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || ++ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) ++ cluster_time = mkv->accumulated_cluster_timecode - mkv->cluster_pts; ++ else ++ cluster_time = pkt->pts - mkv->cluster_pts; ++ } ++ + cluster_time += mkv->tracks[pkt->stream_index].ts_offset; + + cluster_size = avio_tell(mkv->cluster_bc); +@@ -2402,7 +2484,13 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt) + start_new_cluster = 0; + + if (start_new_cluster) { +- ret = mkv_end_cluster(s); ++ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || ++ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { ++ // Reset Timecode for new cluster. ++ mkv->accumulated_cluster_timecode += mkv->simple_block_timecode; ++ mkv->simple_block_timecode = 0; ++ } ++ ret = mkv_end_cluster(s); + if (ret < 0) + return ret; + } +@@ -2739,6 +2827,10 @@ static int mkv_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_AAC) { + if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) + ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); +diff --git a/libavformat/movenc.c b/libavformat/movenc.c +index 7db2e28840..a1f0b3a943 100644 +--- a/libavformat/movenc.c ++++ b/libavformat/movenc.c +@@ -5853,7 +5853,43 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) + } + } + +- return ff_mov_write_packet(s, pkt); ++ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { ++ uint8_t *saved_data = pkt->data; ++ int saved_size = pkt->size; ++ int64_t saved_pts = pkt->pts; ++ ++ // Main frame ++ pkt->data = saved_data; ++ pkt->size = saved_size - 4; ++ pkt->pts = saved_pts; ++ ret = ff_mov_write_packet(s, pkt); ++ ++ // Latter 4 one-byte repeated frames ++ pkt->data = saved_data + saved_size - 4; ++ pkt->size = 1; ++ pkt->pts = saved_pts - 2; ++ ret = ff_mov_write_packet(s, pkt); ++ ++ pkt->data = saved_data + saved_size - 3; ++ pkt->size = 1; ++ pkt->pts = saved_pts - 1; ++ ret = ff_mov_write_packet(s, pkt); ++ ++ pkt->data = saved_data + saved_size - 2; ++ pkt->size = 1; ++ pkt->pts = saved_pts; ++ ret = ff_mov_write_packet(s, pkt); ++ ++ pkt->data = saved_data + saved_size - 1; ++ pkt->size = 1; ++ pkt->pts = saved_pts + 1; ++ ret = ff_mov_write_packet(s, pkt); ++ } ++ else{ ++ ret = ff_mov_write_packet(s, pkt); ++ } ++ ++ return ret; + } + + static int mov_write_subtitle_end_packet(AVFormatContext *s, +@@ -7013,6 +7049,10 @@ static int mov_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_AAC) { + if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) + ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); +-- +2.17.1 + diff --git a/ffmpeg/libfdk_aac/PKGBUILD b/ffmpeg/custom/PKGBUILD similarity index 54% rename from ffmpeg/libfdk_aac/PKGBUILD rename to ffmpeg/custom/PKGBUILD index f27fca00..bb921a80 100644 --- a/ffmpeg/libfdk_aac/PKGBUILD +++ b/ffmpeg/custom/PKGBUILD @@ -1,18 +1,21 @@ -# Maintainer: Ben Widawsky +# Maintainer: Martchus +# Contributor: Ben Widawsky # Contributor: Rob McCathie # Contributor: Ionut Biru # Contributor: Bartomiej Piotrowski # Contributor: Maxime Gauduin # Contributor: Tom Newsom # Contributor: Paul Mattal -# Contributor: Martchus _name=ffmpeg -pkgname=ffmpeg-libfdk_aac +pkgname=ffmpeg-custom pkgver=4.3.1 -pkgrel=2 +_svt_hevc_ver='1.5.0' +_svt_av1_ver='0.8.4' +_svt_vp9_ver='0.3.0' +pkgrel=1 epoch=1 -pkgdesc='Complete solution to record, convert and stream audio and video (with librsvg and libfdk-aac support)' +pkgdesc='Complete solution to record, convert and stream audio and video (with more features enabled than regular ffmpeg)' arch=('x86_64') url='https://ffmpeg.org/' license=('GPL3' 'custom:libfdk-aac') @@ -73,6 +76,12 @@ depends=( libfdk-aac librsvg + svt-av1 + glslang + svt-hevc + svt-av1 + svt-vp9 + vulkan-icd-loader ) makedepends=( avisynthplus @@ -80,6 +89,11 @@ makedepends=( git ladspa nasm + amf-headers + vulkan-headers + opencl-clhpp + ocl-icd + openal ) optdepends=( 'avisynthplus: AviSynthPlus support' @@ -104,22 +118,45 @@ conflicts=("$_name") _tag=6b6b9e593dd4d3aaf75f48d40a13ef03bdef9fdb source=( git+https://git.ffmpeg.org/ffmpeg.git#tag=${_tag} - vmaf-model-path.patch -) -sha256sums=( - SKIP - 8dff51f84a5f7460f8893f0514812f5d2bd668c3276ef7ab7713c99b71d7bd8d + 'vmaf-model-path.patch' + '016-ffmpeg-srt-1.4.2-fix.patch'::'https://git.ffmpeg.org/gitweb/ffmpeg.git/patch/7c59e1b0f285cd7c7b35fcd71f49c5fd52cf9315' + '017-ffmpeg-glslang-11.0-fix.patch'::'https://git.ffmpeg.org/gitweb/ffmpeg.git/patch/4dab04622a6cf2a31da26a51dedb60ec44ac89a4' + "020-ffmpeg-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" + "030-ffmpeg-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" + "040-ffmpeg-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.patch" + "050-ffmpeg-add-svt-vp9-${_svt_vp9_ver}.patch"::"https://raw.githubusercontent.com/OpenVisualCloud/SVT-VP9/v${_svt_vp9_ver}/ffmpeg_plugin/n4.3.1-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch" ) +sha256sums=('SKIP' + '8dff51f84a5f7460f8893f0514812f5d2bd668c3276ef7ab7713c99b71d7bd8d' + '960fd930955cd126e33c543eb5bf300fc050efdd4238626ee4aad2a50d353fa7' + '5b6815fc088d4acdc046eb223350a964bc998b0759aef90acf0591f65e7c98cb' + 'b37d43d5d8692599347c6f1f316c13b9a9addc66d3ceb7e6e02341c494af7cdc' + '1499e419dda72b1604dc5e3959668f3843292ff56bfba78734e31510ba576de0' + '5e960b4dab495437082d0838a40a8cae9b67d1cef1ffd57da960afaa2bfd3719' + 'b74be6d805672210e226e7c0b403f88b0ee8a53c732c9bdc873c4b44aeb75c96') -pkgver() { - cd ffmpeg - - git describe --tags | sed 's/^n//' -} +#pkgver() { +# cd ffmpeg +# +# git describe --tags | sed 's/^n//' +#} prepare() { cd ffmpeg + # fix compilation against libsrt 1.4.2 + patch -Np1 -i "${srcdir}/016-ffmpeg-srt-1.4.2-fix.patch" + + # fix glslang + patch -Np1 -i "${srcdir}/017-ffmpeg-glslang-11.0-fix.patch" + + # add support for svt libraries + rm -f libavcodec/libsvt_{hevc,av1,vp9}.c + patch -Np1 -i "${srcdir}/020-ffmpeg-add-svt-hevc-${_svt_hevc_ver}.patch" + patch -Np1 -i "${srcdir}/030-ffmpeg-add-svt-hevc-docs-${_svt_hevc_ver}.patch" + patch -Np1 -i "${srcdir}/040-ffmpeg-add-svt-av1-${_svt_av1_ver}.patch" + patch -Np1 -i "${srcdir}/050-ffmpeg-add-svt-vp9-${_svt_vp9_ver}.patch" + patch -Np1 -i "${srcdir}"/vmaf-model-path.patch } @@ -178,6 +215,16 @@ build() { --enable-version3 \ --enable-librsvg \ --enable-libfdk_aac \ + --enable-libsvtav1 \ + --enable-libsvthevc \ + --enable-libsvtvp9 \ + --enable-amf \ + --enable-vaapi \ + --enable-vdpau \ + --enable-opencl \ + --enable-openal \ + --enable-libglslang \ + --enable-vulkan \ --enable-nonfree make diff --git a/ffmpeg/libfdk_aac/vmaf-model-path.patch b/ffmpeg/custom/vmaf-model-path.patch similarity index 100% rename from ffmpeg/libfdk_aac/vmaf-model-path.patch rename to ffmpeg/custom/vmaf-model-path.patch diff --git a/ffmpeg/full-nvenc/PKGBUILD b/ffmpeg/full-nvenc/PKGBUILD deleted file mode 100644 index f5bb9348..00000000 --- a/ffmpeg/full-nvenc/PKGBUILD +++ /dev/null @@ -1,234 +0,0 @@ -# Maintainer: Dmitry Kharitonov -# Contributor: Daniel Bermond < yahoo-com: danielbermond > -# Contributor: rcpoison -# Contributor: Gerad Munsch -# Contributor: Rudolf Polzer -# Contributor: Ionut Biru -# Contributor: Tom Newsom -# Contributor: Paul Mattal - -# If you don't want CUDA/CUVID support, you can remove -# depends_x86_64=('cuda') line and -# $_cuda \, $_cuvid \, $_libnpp \ lines from PKGBUILD -# -# Replace "--disable-libsrt" with "--enable-libsrt" -# and add 'srt' to depends array if you need the support -# for Haivision Open SRT (Secure Reliable Transport). -# Enabling it is known to cause segfaults with OBS, -# that's why it's disabled by default. -# -# Add "--enable-decklink \" to configure flags -# if you have decklink-sdk installed -# Add "--enable-libndi_newtek \" to configure flags -# if you have ndi-sdk installed - -pkgname=ffmpeg-full-nvenc -_pkgbasename=ffmpeg -pkgver=4.1.3 -pkgrel=1 -epoch=1 -pkgdesc="Record, convert, and stream audio and video (all codecs including Nvidia NVENC)" -arch=('i686' 'x86_64') -url="http://ffmpeg.org/" -license=('custom: nonfree and unredistributable') -depends=('alsa-lib' 'aom' 'bzip2' 'celt' 'chromaprint-fftw' 'codec2' 'davs2' 'fontconfig' - 'ffnvcodec-headers' 'frei0r-plugins' 'fribidi' 'glibc' 'gsm' 'jack' 'kvazaar' - 'ladspa' 'lame' 'lensfun' 'libass' 'libavc1394' 'libbluray' 'libbs2b' 'libcaca' - 'libcdio-paranoia' 'libdc1394' 'libfdk-aac' 'libgme' 'libiec61883' - 'libilbc' 'libmodplug' 'libomxil-bellagio' 'libmysofa' 'libpulse' - 'librsvg' 'libsoxr' 'libssh' 'libtheora' 'libva' 'libvdpau' 'libxcb' - 'libxext' 'libwebp' 'libxml2' 'libxv' 'lilv' 'libgl' 'lv2' 'ndi-sdk' 'openal' - 'opencore-amr' 'opencl-driver' 'opencl-icd-loader' 'openh264' - 'openjpeg2' 'libklvanc-git' 'libopenmpt-svn' 'opus' 'rockchip-mpp' 'rubberband' - 'rtmpdump' 'sdl2' 'speex' 'shine' 'tensorflow' 'tesseract' - 'twolame' 'v4l-utils' 'vapoursynth' 'vid.stab' 'vo-amrwbenc' 'xavs2-git' - 'xvidcore' 'xz' 'wavpack' 'zeromq' 'zimg' 'zlib' 'zvbi' 'libvorbisenc.so' - 'libvorbis.so' 'libvpx.so' 'libx264.so' 'libx265.so' 'snappy' 'sndio' 'xavs') -depends_x86_64=('cuda') -makedepends=('flite' 'ffnvcodec-headers' 'libmfx' 'libvdpau' 'nasm' 'opencl-headers') -makedepends_x86_64=('vmaf') -optdepends=('avxsynth-git: for Avisynth support' - 'blackmagic-decklink-sdk: for Blackmagic DeckLink support; need to add --enable-decklink option in this PKGBUILD') -optdepends_x86_64=('intel-media-sdk: for Intel QSV support (Experimental! See PKGBUILD of that package for additional info)') -conflicts=('ffmpeg') -provides=('libavcodec.so' 'libavdevice.so' 'libavfilter.so' 'libavformat.so' - 'libavutil.so' 'libpostproc.so' 'libswresample.so' - 'libswscale.so' 'ffmpeg') -source=(https://ffmpeg.org/releases/$_pkgbasename-$pkgver.tar.xz{,.asc} - 'UNREDISTRIBUTABLE.txt') -validpgpkeys=('FCF986EA15E6E293A5644F10B4322F04D67658D8') -sha256sums=('b95f0ae44798ab1434155ac7f81f30a7e9760a02282e4b5898372c22a335347b' - 'SKIP' - 'e0c1b126862072a71e18b9580a6b01afc76a54aa6e642d2c413ba0ac9d3010c4') - -build() { - cd "$_pkgbasename-$pkgver" - - # Add x86_64 (opt)depends to the build - if [ "$CARCH" = "x86_64" ] - then - local _libvmaf='--enable-libvmaf' - local _cudasdk='--enable-cuda-sdk' - local _libmfx='--enable-libmfx' - local _libnpp='--enable-libnpp' - local _cflags='-I/opt/cuda/include' - # '-L/usr/lib/nvidia' (for cuda_sdk) needs to be enabled only on - # systems with nvidia-340xx-utils or nvidia-304xx-utils - if pacman -Qqs '^nvidia-340xx-utils$' | grep -q '^nvidia-340xx-utils$' || - pacman -Qqs '^nvidia-304xx-utils$' | grep -q '^nvidia-304xx-utils$' - then - local _nvidia_340xx_ldflags='-L/usr/lib/nvidia' - fi - local _ldflags="-L/opt/cuda/lib64 ${_nvidia_340xx_ldflags}" - local _ldflags="${_ldflags} -Wl,-rpath -Wl,/opt/intel/mediasdk/lib64:/opt/intel/mediasdk/plugins" - - # strictly specifying nvcc path is needed if package is installing - # cuda for the first time (nvcc path will be in $PATH only after relogin) - sed -i "s@^nvcc_default=.*@nvcc_default='/opt/cuda/bin/nvcc'@" configure - fi - - msg "Starting configure..." - - ## Add "--enable-decklink \" - ## if you have decklink-sdk installed - ./configure \ - --prefix=/usr \ - --extra-cflags="${_cflags}" \ - --extra-ldflags="${_ldflags}" \ - \ - --toolchain=hardened \ - \ - --disable-rpath \ - --enable-gpl \ - --enable-version3 \ - --enable-nonfree \ - --disable-static \ - --disable-stripping \ - --enable-shared \ - --enable-swresample \ - \ - \ - $_cuda \ - $_cudasdk \ - $_cuvid \ - $_libnpp \ - $_libmfx \ - \ - --enable-ffnvcodec \ - --enable-libdrm \ - --enable-libmfx \ - --enable-nvenc \ - --enable-nvdec \ - --enable-omx \ - --enable-omx-rpi \ - \ - \ - --enable-alsa \ - --enable-avisynth \ - --enable-chromaprint \ - --enable-decoder=atrac3 \ - --enable-decoder=atrac3p \ - --enable-bzlib \ - --enable-fontconfig \ - --enable-frei0r \ - --enable-gpl \ - --enable-gray \ - --enable-iconv \ - --enable-ladspa \ - --enable-libaom \ - --enable-libass \ - --enable-libcodec2 \ - --enable-libbluray \ - --enable-libbs2b \ - --enable-libcaca \ - --enable-libcdio \ - --enable-libcelt \ - --enable-libcodec2 \ - --enable-libdavs2 \ - --enable-libdc1394 \ - --enable-libfdk-aac \ - --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-libmysofa \ - --enable-libndi_newtek \ - --enable-libopencore-amrnb \ - --enable-libopencore-amrwb \ - --disable-libopencv \ - --enable-libopenh264 \ - --enable-libopenjpeg \ - --enable-libopenmpt \ - --enable-libopus \ - --enable-libpulse \ - --enable-librsvg \ - --enable-librubberband \ - --enable-librtmp \ - --enable-libshine \ - --enable-libsnappy \ - --enable-libsoxr \ - --enable-libspeex \ - --disable-libsrt \ - --enable-libssh \ - --enable-libtensorflow \ - --enable-libtesseract \ - --enable-libtheora \ - --enable-libtwolame \ - --enable-libv4l2 \ - --enable-libvidstab \ - --disable-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-openal \ - --enable-opencl \ - --enable-opengl \ - --enable-openssl \ - --enable-rkmpp \ - --enable-sndio \ - --enable-sdl2 \ - --enable-vapoursynth \ - --enable-v4l2-m2m \ - --enable-vaapi \ - --enable-vdpau \ - --enable-xlib \ - --enable-zlib - - - msg "Starting make" - make - make tools/qt-faststart - make doc/ff{mpeg,play}.1 -} - -package() { - cd "$_pkgbasename-$pkgver" - make DESTDIR="$pkgdir" install install-man - install -Dm 755 tools/qt-faststart "${pkgdir}/usr/bin" - install -Dm 644 "$srcdir"/UNREDISTRIBUTABLE.txt "$pkgdir/usr/share/licenses/${pkgname}" -} diff --git a/ffmpeg/full-nvenc/UNREDISTRIBUTABLE.txt b/ffmpeg/full-nvenc/UNREDISTRIBUTABLE.txt deleted file mode 100644 index ec737d95..00000000 --- a/ffmpeg/full-nvenc/UNREDISTRIBUTABLE.txt +++ /dev/null @@ -1,2 +0,0 @@ -This package, although built from GPL sources, is linked against non-GPL -libraries and thus cannot be redistributed in binary form. diff --git a/ffmpeg/libfdk_aac-git/PKGBUILD b/ffmpeg/libfdk_aac-git/PKGBUILD deleted file mode 100644 index 53070dd2..00000000 --- a/ffmpeg/libfdk_aac-git/PKGBUILD +++ /dev/null @@ -1,98 +0,0 @@ -_name=ffmpeg -pkgname=ffmpeg-libfdk_aac-git -pkgver=r74550.907373e -pkgrel=2 -epoch=1 -pkgdesc='Complete solution to record, convert and stream audio and video (with libfdk-aac support)' -arch=('i686' 'x86_64') -url='https://ffmpeg.org/' -license=('GPL3' 'custom:libfdk-aac') -depends=('alsa-lib' 'bzip2' 'fontconfig' 'fribidi' 'glibc' 'gmp' 'gnutls' 'gsm' - 'jack' 'lame' 'libavc1394' 'libiec61883' 'libmodplug' 'libpulse' - 'libraw1394' 'libsoxr' 'libssh' 'libtheora' 'libva' 'libvdpau' - 'libwebp' 'libx11' 'libxcb' 'libxml2' 'opencore-amr' 'openjpeg2' 'opus' - 'sdl2' 'speex' 'v4l-utils' 'xz' 'zlib' - 'libass.so' 'libbluray.so' 'libfreetype.so' - 'libvidstab.so' 'libvorbisenc.so' 'libvorbis.so' 'libvpx.so' - 'libx264.so' 'libx265.so' 'libxvidcore.so' - 'libfdk-aac') -makedepends=('ladspa' 'libvdpau' 'yasm') -optdepends=('ladspa: LADSPA filters') -provides=('libavcodec.so' 'libavdevice.so' 'libavfilter.so' 'libavformat.so' - 'libavutil.so' 'libpostproc.so' 'libswresample.so' 'libswscale.so' - "ffmpeg=$pkgver") -conflicts=("$_name") -source=("$pkgname"::'git://source.ffmpeg.org/ffmpeg.git') -sha256sums=('SKIP') - -pkgver() { - cd "$srcdir/$pkgname" - printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" -} - -build() { - cd "$srcdir/$pkgname" - - ./configure \ - --prefix=/usr \ - --disable-debug \ - --disable-static \ - --disable-stripping \ - --enable-avisynth \ - --enable-fontconfig \ - --enable-gmp \ - --enable-gnutls \ - --enable-gpl \ - --enable-ladspa \ - --enable-libass \ - --enable-libbluray \ - --enable-libfreetype \ - --enable-libfribidi \ - --enable-libgsm \ - --enable-libmodplug \ - --enable-libmp3lame \ - --enable-libopencore_amrnb \ - --enable-libopencore_amrwb \ - --enable-libopenjpeg \ - --enable-libopus \ - --enable-libpulse \ - --enable-libschroedinger \ - --enable-libsoxr \ - --enable-libspeex \ - --enable-libssh \ - --enable-libtheora \ - --enable-libv4l2 \ - --enable-libvorbis \ - --enable-libvpx \ - --enable-libwebp \ - --enable-libx264 \ - --enable-libx265 \ - --enable-libxcb \ - --enable-libxml2 \ - --enable-libxvid \ - --enable-nvdec \ - --enable-nvenc \ - --enable-omx \ - --enable-shared \ - --enable-version3 \ - --enable-x11grab \ - --enable-libfdk_aac \ - --enable-nonfree - - make - make tools/qt-faststart - make doc/ff{mpeg,play}.1 - - cp /usr/share/licenses/libfdk-aac/NOTICE . -} - -package() { - cd "$srcdir/$pkgname" - - make DESTDIR="$pkgdir" install install-man - install -Dm755 tools/qt-faststart "$pkgdir"/usr/bin/qt-faststart - - - install -d "$pkgdir/usr/share/licenses/$pkgname" - install -m 0644 NOTICE "$pkgdir/usr/share/licenses/$pkgname/NOTICE" -}