一 编译集成
Files · v2.3.0 · Alliance for Open Media / SVT-AV1 · GitLab
cd /SVT-AV1/Build/linux/
./build.sh
make install
GitHub - FFmpeg/FFmpeg: Mirror of https://git.ffmpeg.org/ffmpeg.git
./configure --enable-libsvtav1 --enable-gpl --extra-ldflags='-L/usr/local/lib' --extra-libs='-lSvtAv1Enc -lz -lm -lstdc++ -ldl -lpthread' --extra-cflags='-I/usr/local/include/'
make && make install
./ffmpeg -codecs|grep av1
DEV.L. av1 Alliance for Open Media AV1 (decoders: libdav1d av1 av1_cuvid ) (encoders: libsvtav1 )
二 SVT-AV1视频编码命令行
ffmpeg -i input.mp4 -c:v libsvtav1 -crf 30 -preset 4 -y output.mp4
三 ffmpeg 接入wrapper代码review
#include <stdint.h> //标准头文件
#include <EbSvtAv1ErrorCodes.h> //SVT编码错误信息头文件
#include <EbSvtAv1Enc.h> //SVT编码API头文件
//以下是ffmpeg自己的头文件
#include "libavutil/common.h"
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/avassert.h"
typedef enum eos_status {
EOS_NOT_REACHED = 0,
EOS_SEND,
EOS_RECEIVED
} EOS_STATUS;
typedef struct SvtContext {
const AVClass *class;
EbSvtAv1EncConfiguration enc_params; //SVT-AV1编码器的配置参数
EbComponentType *svt_handle;//SVT-AV1 编码器的句柄
EbBufferHeaderType *in_buf; //输入缓冲区
int raw_size;//原始数据大
int max_tu_size;//最大传输单元大小
AVFrame *frame;//当前处理的视频帧
AVBufferPool *pool;//缓冲池,用于管理编码输出
EOS_STATUS eos_flag;//结束状态标志
//用户选项
int hierarchial_level; //层次预测级别
int la_depth; //前瞻深度
int enc_mode;//编码模式
int rc_mode ;// 码率控制模式
int scd;//场景变化监测
int qp;//固定量化参数
int tier;//操作点层级
int tile_columns;//tile列数
int tile_rows;//tile行数
} SvtContext;
static const struct {
EbErrorType eb_err; // SVT-AV1错误码
int av_err; // FFmpeg错误码
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 destroy thread" },
{ EB_ErrorSemaphoreUnresponsive, AVERROR_EXTERNAL, "semaphore unresponsive" },
{ EB_ErrorDestroySemaphoreFailed, AVERROR_EXTERNAL, "failed to destroy semaphore"},
{ EB_ErrorCreateMutexFailed, AVERROR_EXTERNAL, "failed to create mutex" },
{ EB_ErrorMutexUnresponsive, AVERROR_EXTERNAL, "mutex unresponsive" },
{ EB_ErrorDestroyMutexFailed, AVERROR_EXTERNAL, "failed to destroy mutex" },
{ 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 = svt_map_error(err, &desc);
av_log(log_ctx, AV_LOG_ERROR, "%s: %s (0x%x)\n", error_string, desc, err);
return ret;
}
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; //定一个变量,pack_mode_10bit, 用于判断是否需要对10位编码进行特殊处理
//如果编码器的位深大于8位,并且compressed_ten_bit_format. 为0, 则设置为1,表示需要特殊处理
//否则设置为0
const size_t luma_size_8bit = config->source_width * config->source_height 分别是输入视频的宽度和高度
1 << pack_mode_10bit 如果pack_mode_10bit 为1,则乘以2,否则乘以1,这用语计算10位编码时的额外数据大小
const size_t luma_size_10bit = (config->encoder_bit_depth > 8 && pack_mode_10bit == 0) ? luma_size_8bit: 0;
//计算10位亮度分量的大小
如果编码器的位深度大于8位,并且pack_mode_10bit, 为0,则使用与8位相同的大小,否则设置为0,表示不使用10位编码。
EbSvtIOFormat *in_data; //声明一个指向EbSvtIOFormat 的指针in_data, 用于表示输入数据的格式
svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3/2;
//对于YUV420格式,总大小为亮度分量大小乘以1.5

最低0.47元/天 解锁文章
1825

被折叠的 条评论
为什么被折叠?



