x265在FFmpeg中的应用

通常建议直接用x265,应用方便和参数设置方便;

这里仅仅为了说明x265在FFmpeg中应用设置;

和x264差不多;

一:在FFmpeg中实现:

主要实现文件是:libx265.c文件中;

 

二:关于编码速度和profile的设置:

在x265中,x265.h:

 

static const char * const x265_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo", 0 };

 

static const char * const x265_tune_names[] = { "psnr", "ssim", "grain", "zerolatency", "fastdecode", 0 };

static const cha

r * const x265_profile_names[] = {
    /* HEVC v1 */
    "main", "main10", "mainstillpicture", /* alias */ "msp",

    /* HEVC v2 (Range Extensions) */
    "main-intra", "main10-intra",
    "main444-8",  "main444-intra", "main444-stillpicture",

    "main422-10", "main422-10-intra",
    "main444-10", "main444-10-intra",

    "main12",     "main12-intra",
    "main422-12", "main422-12-intra",
    "main444-12", "main444-12-intra",

    "main444-16-intra", "main444-16-stillpicture", /* Not Supported! */
    0
};

 

在FFmpeg中,可以这么设置:

        av_opt_set(c->priv_data, "preset", "ultrafast", 0);
        av_opt_set(c->priv_data, "tune", "zerolatency", 0);

        av_opt_set(c->priv_data, "profile", "main", 0);

也可以直接通过FFmpeg参数赋值profile:

c->profile = FF_PROFILE_HEVC_MAIN;

 

 

三:关于c->priv_data

更多细节可以参考:static av_cold int libx265_encode_init(AVCodecContext *avctx);

 

 

先看这个函数的实现:

typedef struct libx265Context {
    const AVClass *class;

    x265_encoder *encoder;
    x265_param   *params;
    const x265_api *api;

    float crf;
    int   forced_idr;
    char *preset;
    char *tune;
    char *profile;
    char *x265_opts;
} libx265Context;

static av_cold int libx265_encode_init(AVCodecContext *avctx)
{

//这个priv_data就是libx265Context 结构体;所以,具体的参数设置都在这里;

//怎么设置:就是这个函数:av_opt_set
    libx265Context *ctx = avctx->priv_data;

 

}

 

四:更多参数设置:

通过源码,可以看出:

这样,应该可以设置相关的参数了;

static const AVOption options[] = {
    { "crf",         "set the x265 crf",                                                            OFFSET(crf),       AV_OPT_TYPE_FLOAT,  { .dbl = -1 }, -1, FLT_MAX, VE },
    { "forced-idr",  "if forcing keyframes, force them as IDR frames",                              OFFSET(forced_idr),AV_OPT_TYPE_BOOL,   { .i64 =  0 },  0,       1, VE },
    { "preset",      "set the x265 preset",                                                         OFFSET(preset),    AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
    { "tune",        "set the x265 tune parameter",                                                 OFFSET(tune),      AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
    { "profile",     "set the x265 profile",                                                        OFFSET(profile),   AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
    { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
    { NULL }
};

 

注意:在FFmpeg中,每一个codec都会对应一个static const AVOption options[];可以从这里查看可以选择的参数;

更多具体用法可以参考FFmpeg中的av_opt_set;

 

五:再看:struct  libx265Context         每一个参数都很重要;

typedef struct libx265Context {
    const AVClass *class; //FFmpeg中的类;

    x265_encoder *encoder; //x265中的struct;
    x265_param   *params; //x265中的param,很重要;
    const x265_api *api; //x265的接口,可以获取,但是不建议,设置参数就可以了;

    float crf;
    int   forced_idr;  //输出IDR;
    char *preset; 
    char *tune;
    char *profile;
    char *x265_opts;
} libx265Context;

 

前面已经看到,可以通过av_opt_set的相关函数设置,可以设置,很多参数;

但是比较麻烦;

 

示例:

1:设置输出IDR;

在FFmpeg输出 I 帧是: frame->pict_type = AV_PICTURE_TYPE_I;

如果要设置输出IDR,还要同时设置forced_idr = 1;

通常建议还是用这两个函数参考的AVOption options参数设置:av_opt_set 和 av_opt_set_int设置:

            av_opt_set(c->priv_data, "forced-idr", "1", 0);

            //或者
            av_opt_set_int(c->priv_data, "forced-idr", 1, 0);

 

那就直接用结构体赋值:

为了简单,简单修改一下结构体:将指针类型修改为 void * ;

typedef struct libx265Context {
    const void *class;

    void *encoder;
    void   *params;
    const void *api;

    float crf;
    int   forced_idr;
    char *preset;
    char *tune;
    char *profile;
    char *x265_opts;
} libx265Context;

 

libx265Context * plibx265Context = (libx265Context*)c->priv_data;
plibx265Context->forced_idr = 1;

//一般这么写:av_opt_set(c->priv_data, "forced-idr", "1", 0);

encode_video_x265(...);

这样就可以输出IDR packet了;

 

2:为了更方便的设置,可以直接从相应的x265.h赋值到自己的工程中,然后就可以设置x265_param中的任何参数了;

 

 

 

 

更多av_opt_set的文章可以参考:

https://blog.csdn.net/leixiaohua1020/article/details/46890739

https://blog.csdn.net/xiaojun111111/article/details/53764903

AVOption (AVClass)
AVOption是FFmpeg的选项设置工具。与AVOption最相关的选项设置函数就是av_opt_set()了。AVOption的核心概念就是“根据字符串操作结构体的属性值”。例如下面代码中“#if”和“#else”之间代码的作用和“#else”和“#endif”之间代码的作用是一样的。
#if TEST_OPT
    av_opt_set(pCodecCtx,"b","400000",0);        //bitrate
    //Another method
    //av_opt_set_int(pCodecCtx,"b",400000,0);    //bitrate
 
    av_opt_set(pCodecCtx,"time_base","1/25",0);    //time_base
    av_opt_set(pCodecCtx,"bf","5",0);            //max b frame
    av_opt_set(pCodecCtx,"g","25",0);            //gop
    av_opt_set(pCodecCtx,"qmin","10",0);        //qmin/qmax
    av_opt_set(pCodecCtx,"qmax","51",0);
#else
    pCodecCtx->time_base.num = 1;  
    pCodecCtx->time_base.den = 25;  
    pCodecCtx->max_b_frames=5;
    pCodecCtx->bit_rate = 400000;  
    pCodecCtx->gop_size=25;
    pCodecCtx->qmin = 10;
    pCodecCtx->qmax = 51;
#endif

 

 

你可能感兴趣的:(FFmpeg)