Exemple #1
0
static int open_encoder(struct videnc_state *st, const struct vidsz *size)
{
	if (st->x265) {
		debug("h265: re-opening encoder\n");
		x265_encoder_close(st->x265);
	}

	st->param->sourceWidth  = size->w;
	st->param->sourceHeight = size->h;

	st->x265 = x265_encoder_open(st->param);
	if (!st->x265) {
		warning("h265: x265_encoder_open failed\n");
		return ENOMEM;
	}

	return 0;
}
bool Video_Encoder_H265::init(Video_Encoder::NALU_CB *cb, const Encoder_Param &param)
{
    //alloc & set param
    _x265_param = x265_param_alloc();
    if(_x265_param == NULL)
    {
        printf("x265_param_alloc error~\n");
        return false;
    }
//    x265_param_default(_x265_param);
    /* x265_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo", 0 };
     x265_tune_names[] = { "psnr", "ssim", "grain", "zerolatency", "fastdecode", 0 };*/

   int rc = x265_param_default_preset(_x265_param, x265_preset_names[4], x265_tune_names[3]);
   if(rc != 0)
   {
       //error...
       printf("x265_param_default_preset error~\n");
       return false;
   }
   /*x265_profile_names[] = { "main", "main10", "mainstillpicture", 0 };*/

   rc = x265_param_apply_profile(_x265_param, x265_profile_names[0]);
   if(rc != 0)
   {
       //error...
       printf("x265_param_apply_profile error~\n");
       return false;
   }

    _x265_param->sourceHeight = param.height;
    _x265_param->sourceWidth = param.width;

    /*The output of the encoder is a series of NAL packets, which are always returned concatenated in consecutive memory.
     * HEVC streams have SPS and PPS and VPS headers which describe how the following packets are to be decoded.
     * If you specified --repeat-headers then those headers will be output with every keyframe.
     * Otherwise you must explicitly query those headers using:int x265_encoder_headers(x265_encoder *, x265_nal **pp_nal, uint32_t *pi_nal);*/
    _x265_param->bRepeatHeaders = 1;
    _x265_param->internalCsp = X265_CSP_I420;
    _x265_param->fpsNum = param.fps;
    _x265_param->fpsDenom = 1;



//    x265_param_parse(_x265_param, const char *name, const char *value);

    /*******
    x265_encoder_parameters() may be used to get a copy of the param structure from the encoder after it has been opened,
       in order to see the changes made to the parameters for auto-detection and other reasons.
       x265_encoder_reconfig() may be used to reconfigure encoder parameters mid-encode:
       *********/

//    rc = x265_encoder_reconfig(_x265_encoder, _x265_param);

    _x265_picture = x265_picture_alloc();
    if(_x265_picture == NULL)
    {
        if(_x265_param)
        {
            x265_param_free(_x265_param);
        }
        printf("x265_picture_alloc error~\n");
        return false;
    }

    x265_picture_init(_x265_param, _x265_picture);

    //Analysis Buffers
//    rc = x265_alloc_analysis_data(_x265_picture);
//    if(rc == 0)
//    {
//        //error...
//    }
//    x265_free_analysis_data(_x265_picture);


    //
    _x265_encoder = x265_encoder_open(_x265_param);
    if(_x265_encoder == NULL)
    {
        if(_x265_param)
        {
            x265_param_free(_x265_param);
        }

        if(_x265_picture)
        {
            x265_picture_free(_x265_picture);
        }

        printf("x265_encoder_open error~\n");
        return false;
    }

    _callback = cb;

    gettimeofday(&_tv_start, NULL);

    return true;
}
Exemple #3
0
static av_cold int libx265_encode_init(AVCodecContext *avctx)
{
    libx265Context *ctx = avctx->priv_data;
    x265_nal *nal;
    char sar[12];
    int sar_num, sar_den;
    int nnal;

    if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL &&
        !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_w) {
        av_log(avctx, AV_LOG_ERROR,
               "4:2:2 and 4:4:4 support is not fully defined for HEVC yet. "
               "Set -strict experimental to encode anyway.\n");
        return AVERROR(ENOSYS);
    }

    avctx->coded_frame = av_frame_alloc();
    if (!avctx->coded_frame) {
        av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
        return AVERROR(ENOMEM);
    }

    ctx->params = x265_param_alloc();
    if (!ctx->params) {
        av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n");
        return AVERROR(ENOMEM);
    }

    if (x265_param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) {
        av_log(avctx, AV_LOG_ERROR, "Invalid preset or tune.\n");
        return AVERROR(EINVAL);
    }

    ctx->params->frameNumThreads = avctx->thread_count;
    ctx->params->fpsNum          = avctx->time_base.den;
    ctx->params->fpsDenom        = avctx->time_base.num * avctx->ticks_per_frame;
    ctx->params->sourceWidth     = avctx->width;
    ctx->params->sourceHeight    = avctx->height;

    if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) {
        av_reduce(&sar_num, &sar_den,
                  avctx->sample_aspect_ratio.num,
                  avctx->sample_aspect_ratio.den, 65535);
        snprintf(sar, sizeof(sar), "%d:%d", sar_num, sar_den);
        if (x265_param_parse(ctx->params, "sar", sar) == X265_PARAM_BAD_VALUE) {
            av_log(avctx, AV_LOG_ERROR, "Invalid SAR: %d:%d.\n", sar_num, sar_den);
            return AVERROR_INVALIDDATA;
        }
    }

    switch (avctx->pix_fmt) {
    case AV_PIX_FMT_YUV420P:
    case AV_PIX_FMT_YUV420P10:
        ctx->params->internalCsp = X265_CSP_I420;
        break;
    case AV_PIX_FMT_YUV422P:
    case AV_PIX_FMT_YUV422P10:
        ctx->params->internalCsp = X265_CSP_I422;
        break;
    case AV_PIX_FMT_YUV444P:
    case AV_PIX_FMT_YUV444P10:
        ctx->params->internalCsp = X265_CSP_I444;
        break;
    }

    if (avctx->bit_rate > 0) {
        ctx->params->rc.bitrate         = avctx->bit_rate / 1000;
        ctx->params->rc.rateControlMode = X265_RC_ABR;
    }

    if (!(avctx->flags & CODEC_FLAG_GLOBAL_HEADER))
        ctx->params->bRepeatHeaders = 1;

    if (ctx->x265_opts) {
        AVDictionary *dict    = NULL;
        AVDictionaryEntry *en = NULL;

        if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) {
            while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) {
                int parse_ret = x265_param_parse(ctx->params, en->key, en->value);

                switch (parse_ret) {
                case X265_PARAM_BAD_NAME:
                    av_log(avctx, AV_LOG_WARNING,
                          "Unknown option: %s.\n", en->key);
                    break;
                case X265_PARAM_BAD_VALUE:
                    av_log(avctx, AV_LOG_WARNING,
                          "Invalid value for %s: %s.\n", en->key, en->value);
                    break;
                default:
                    break;
                }
            }
            av_dict_free(&dict);
        }
    }

    ctx->encoder = x265_encoder_open(ctx->params);
    if (!ctx->encoder) {
        av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n");
        libx265_encode_close(avctx);
        return AVERROR_INVALIDDATA;
    }

    if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
        avctx->extradata_size = x265_encoder_headers(ctx->encoder, &nal, &nnal);
        if (avctx->extradata_size <= 0) {
            av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n");
            libx265_encode_close(avctx);
            return AVERROR_INVALIDDATA;
        }

        avctx->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
        if (!avctx->extradata) {
            av_log(avctx, AV_LOG_ERROR,
                   "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size);
            libx265_encode_close(avctx);
            return AVERROR(ENOMEM);
        }

        memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size);
    }

    return 0;
}
Exemple #4
0
static av_cold int libx265_encode_init(AVCodecContext *avctx)
{
    libx265Context *ctx = avctx->priv_data;
    x265_nal *nal;
    uint8_t *buf;
    int nnal;
    int ret;
    int i;

    avctx->coded_frame = av_frame_alloc();
    if (!avctx->coded_frame) {
        av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
        return AVERROR(ENOMEM);
    }

    ctx->params = x265_param_alloc();
    if (!ctx->params) {
        av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n");
        return AVERROR(ENOMEM);
    }

    x265_param_default(ctx->params);
    if (x265_param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) {
        av_log(avctx, AV_LOG_ERROR, "Invalid preset or tune.\n");
        return AVERROR(EINVAL);
    }

    ctx->params->frameNumThreads = avctx->thread_count;
    ctx->params->frameRate       = (int) (avctx->time_base.den / avctx->time_base.num);
    ctx->params->sourceWidth     = avctx->width;
    ctx->params->sourceHeight    = avctx->height;
    ctx->params->inputBitDepth   = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth_minus1 + 1;

    if (avctx->bit_rate > 0) {
        ctx->params->rc.bitrate         = avctx->bit_rate / 1000;
        ctx->params->rc.rateControlMode = X265_RC_ABR;
    }

    if (ctx->x265_opts) {
        AVDictionary *dict    = NULL;
        AVDictionaryEntry *en = NULL;

        if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) {
            while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) {
                int parse_ret = x265_param_parse(ctx->params, en->key, en->value);

                switch (parse_ret) {
                case X265_PARAM_BAD_NAME:
                    av_log(avctx, AV_LOG_WARNING,
                          "Unknown option: %s.\n", en->key);
                    break;
                case X265_PARAM_BAD_VALUE:
                    av_log(avctx, AV_LOG_WARNING,
                          "Invalid value for %s: %s.\n", en->key, en->value);
                    break;
                default:
                    break;
                }
            }
            av_dict_free(&dict);
        }
    }

    ctx->encoder = x265_encoder_open(ctx->params);
    if (!ctx->encoder) {
        av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n");
        libx265_encode_close(avctx);
        return AVERROR_INVALIDDATA;
    }

    ret = x265_encoder_headers(ctx->encoder, &nal, &nnal);
    if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n");
        libx265_encode_close(avctx);
        return AVERROR_INVALIDDATA;
    }

    for (i = 0; i < nnal; i++)
        ctx->header_size += nal[i].sizeBytes;

    ctx->header = av_malloc(ctx->header_size);
    if (!ctx->header) {
        av_log(avctx, AV_LOG_ERROR,
               "Cannot allocate HEVC header of size %d.\n", ctx->header_size);
        libx265_encode_close(avctx);
        return AVERROR(ENOMEM);
    }

    buf = ctx->header;
    for (i = 0; i < nnal; i++) {
        memcpy(buf, nal[i].payload, nal[i].sizeBytes);
        buf += nal[i].sizeBytes;
    }

    return 0;
}
Exemple #5
0
static av_cold int libx265_encode_init(AVCodecContext *avctx)
{
    libx265Context *ctx = avctx->priv_data;
    x265_nal *nal;
    uint8_t *buf;
    int sar_num, sar_den;
    int nnal;
    int ret;
    int i;

    if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL &&
        !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_w &&
        !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_h) {
        av_log(avctx, AV_LOG_ERROR,
               "4:4:4 support is not fully defined for HEVC yet. "
               "Set -strict experimental to encode anyway.\n");
        return AVERROR(ENOSYS);
    }

    avctx->coded_frame = av_frame_alloc();
    if (!avctx->coded_frame) {
        av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
        return AVERROR(ENOMEM);
    }

    ctx->params = x265_param_alloc();
    if (!ctx->params) {
        av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n");
        return AVERROR(ENOMEM);
    }

    if (x265_param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) {
        av_log(avctx, AV_LOG_ERROR, "Invalid preset or tune.\n");
        return AVERROR(EINVAL);
    }

    ctx->params->frameNumThreads = avctx->thread_count;
    ctx->params->fpsNum          = avctx->time_base.den;
    ctx->params->fpsDenom        = avctx->time_base.num * avctx->ticks_per_frame;
    ctx->params->sourceWidth     = avctx->width;
    ctx->params->sourceHeight    = avctx->height;

    av_reduce(&sar_num, &sar_den,
              avctx->sample_aspect_ratio.num,
              avctx->sample_aspect_ratio.den, 4096);
    ctx->params->vui.bEnableVuiParametersPresentFlag = 1;
    ctx->params->vui.bEnableAspectRatioIdc           = 1;
    ctx->params->vui.aspectRatioIdc                  = 255;
    ctx->params->vui.sarWidth                        = sar_num;
    ctx->params->vui.sarHeight                       = sar_den;

    if (x265_max_bit_depth == 8)
        ctx->params->internalBitDepth = 8;
    else if (x265_max_bit_depth == 12)
        ctx->params->internalBitDepth = 10;

    switch (avctx->pix_fmt) {
    case AV_PIX_FMT_YUV420P:
    case AV_PIX_FMT_YUV420P10:
        ctx->params->internalCsp = X265_CSP_I420;
        break;
    case AV_PIX_FMT_YUV444P:
    case AV_PIX_FMT_YUV444P10:
        ctx->params->internalCsp = X265_CSP_I444;
        break;
    }

    if (avctx->bit_rate > 0) {
        ctx->params->rc.bitrate         = avctx->bit_rate / 1000;
        ctx->params->rc.rateControlMode = X265_RC_ABR;
    }

    if (ctx->x265_opts) {
        AVDictionary *dict    = NULL;
        AVDictionaryEntry *en = NULL;

        if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) {
            while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) {
                int parse_ret = x265_param_parse(ctx->params, en->key, en->value);

                switch (parse_ret) {
                case X265_PARAM_BAD_NAME:
                    av_log(avctx, AV_LOG_WARNING,
                          "Unknown option: %s.\n", en->key);
                    break;
                case X265_PARAM_BAD_VALUE:
                    av_log(avctx, AV_LOG_WARNING,
                          "Invalid value for %s: %s.\n", en->key, en->value);
                    break;
                default:
                    break;
                }
            }
            av_dict_free(&dict);
        }
    }

    ctx->encoder = x265_encoder_open(ctx->params);
    if (!ctx->encoder) {
        av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n");
        libx265_encode_close(avctx);
        return AVERROR_INVALIDDATA;
    }

    ret = x265_encoder_headers(ctx->encoder, &nal, &nnal);
    if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n");
        libx265_encode_close(avctx);
        return AVERROR_INVALIDDATA;
    }

    for (i = 0; i < nnal; i++)
        ctx->header_size += nal[i].sizeBytes;

    ctx->header = av_malloc(ctx->header_size + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!ctx->header) {
        av_log(avctx, AV_LOG_ERROR,
               "Cannot allocate HEVC header of size %d.\n", ctx->header_size);
        libx265_encode_close(avctx);
        return AVERROR(ENOMEM);
    }

    buf = ctx->header;
    for (i = 0; i < nnal; i++) {
        memcpy(buf, nal[i].payload, nal[i].sizeBytes);
        buf += nal[i].sizeBytes;
    }

    if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
        avctx->extradata_size = ctx->header_size;
        avctx->extradata = ctx->header;
        ctx->header_size = 0;
        ctx->header = NULL;
    }

    return 0;
}
/**
    \fn setup
*/
bool x265Encoder::setup(void)
{
    ADM_info("=============x265, setting up==============\n");
    MMSET(param);

    x265_param_default( &param);
    firstIdr=true;
    image=new ADMImageDefault(getWidth(),getHeight());

    // -------------- preset, tune, idc ------------
    if(!x265Settings.useAdvancedConfiguration)
    {
        char tune[200] = {0};
        strcat(tune, x265Settings.general.tuning);
        x265_param_default_preset(&param, x265Settings.general.preset, tune);
    }
    param.logLevel=x265Settings.level;

    // Threads..
#if X265_BUILD < 47
    switch(x265Settings.general.poolThreads)
    {
    case 0:
    case 1:
    case 2:
        param.poolNumThreads = x265Settings.general.poolThreads;
        break;
    case 99:
        break; //auto
    default:
        ADM_error("UNKNOWN NB OF THREADS\n");
        break;
    }
#endif

    switch(x265Settings.general.frameThreads)
    {
    case 0:
    case 1:
    case 2:
        param.frameNumThreads = x265Settings.general.frameThreads;
        break;
    case 99:
        break; //auto
    default:
        ADM_error("UNKNOWN NB OF THREADS\n");
        break;
    }
    param.sourceWidth = getWidth();
    param.sourceHeight = getHeight();
    param.internalCsp = X265_CSP_I420;
    param.internalBitDepth = 8;
    param.logLevel=X265_LOG_INFO; //DEBUG; //INFO;

    //Framerate
    int n,d;
    uint64_t f=source->getInfo()->frameIncrement;
    usSecondsToFrac(f,&n,&d);
    param.fpsNum = d;
    param.fpsDenom = n;

    // -------------- vui------------
#undef MKPARAM
#undef MKPARAMD
#undef MKPARAMB
#define MKPARAM(x,y) {param.vui.x = x265Settings.vui.y;aprintf("[x265] vui."#x" = %d\n",param.vui.x);}
#define MKPARAMD(x,y) {param.vui.x = (double)x265Settings.vui.y; aprintf("[x265] vui."#x" = %.2f\n",param.vui.x);}
#define MKPARAMB(x,y) {param.vui.x = x265Settings.vui.y ;aprintf("[x265] vui."#x" = %s\n",TrueFalse[param.vui.x&1]);}
    MKPARAM (sarWidth,sar_width)
    MKPARAM (sarHeight,sar_height)

    // -------------- rate control------------
    switch(x265Settings.general.params.mode)
    {
    case COMPRESS_2PASS:
    case COMPRESS_2PASS_BITRATE:
        uint32_t bitrate;
        if(passNumber!=1 && passNumber!=2)
        {
            ADM_error("No pass number specified! (%d)\n",(int)passNumber);
            return false;
        }
        ADM_info("Starting pass :%d\n",passNumber);
        if(x265Settings.general.params.mode==COMPRESS_2PASS)
        {
            uint64_t duration=source->getInfo()->totalDuration; // in us
            ADM_info("Source duration :%s\n",ADM_us2plain(duration));
            ADM_info("Target size     :%d\n",(int)x265Settings.general.params.finalsize);
            uint32_t avg;
            if(false==ADM_computeAverageBitrateFromDuration(duration,
                    x265Settings.general.params.finalsize,
                    &avg))
            {
                ADM_error("[x265] No source duration!\n");
                return false;
            }
            bitrate=(uint32_t)avg;
        }
        else
            bitrate=x265Settings.general.params.avg_bitrate;
        ADM_info("Using average bitrate of %d kb/s\n",(int)bitrate);
        param.rc.rateControlMode = X265_RC_ABR;
        param.rc.bitrate =  bitrate;
        if(passNumber==1)
        {
            param.rc.bStatWrite=1;
            param.rc.bStatRead=0;
            param.rc.statFileName=strdup(logFile);

        } else
        {
            param.rc.bStatWrite=0;
            param.rc.bStatRead=1;
            param.rc.statFileName=strdup(logFile);
            if(!ADM_fileExist(logFile))
            {
                ADM_error("Logfile %s does not exist \n",logFile);
                return false;
            }
        }
        break;
    case COMPRESS_AQ:
        param.rc.rateControlMode = X265_RC_CRF;
        param.rc.rfConstant = x265Settings.general.params.qz;
        break;
    case COMPRESS_CQ:
        param.rc.rateControlMode = X265_RC_CQP;
        param.rc.qp = x265Settings.general.params.qz;
        break;

    case COMPRESS_CBR:
        param.rc.rateControlMode = X265_RC_ABR;
        param.rc.bitrate =  x265Settings.general.params.bitrate;
        param.rc.qp = 0;
        param.rc.rfConstant = 0;
        break;
    default:
        GUI_Error_HIG("Not coded","this mode has notbeen implemented\n");
        return false;
        break;

    }

    if(globalHeader)
        param.bRepeatHeaders=0;
    else
        param.bRepeatHeaders=1;

    if(x265Settings.useAdvancedConfiguration)
    {

#undef MKPARAM
#undef MKPARAMD
#undef MKPARAMB
#define MKPARAM(x,y) {param.x = x265Settings.y;aprintf("[x265] "#x" = %d\n",param.x);}
#define MKPARAMD(x,y) {param.x = (double)x265Settings.y; aprintf("[x265] "#x" = %.2f\n",param.x);}
#define MKPARAMB(x,y) {param.x = x265Settings.y ;aprintf("[x265] "#x" = %s\n",TrueFalse[param.x&1]);}
        MKPARAM(maxNumReferences,MaxRefFrames);
        MKPARAM(keyframeMin,MinIdr);
        MKPARAM(keyframeMax,MaxIdr);
        MKPARAM(scenecutThreshold,i_scenecut_threshold);
        MKPARAM(bframes,MaxBFrame);

        MKPARAM(bFrameAdaptive,i_bframe_adaptive);
        MKPARAM(bFrameBias,i_bframe_bias);
        MKPARAM(bBPyramid,i_bframe_pyramid);
        MKPARAMB(bEnableLoopFilter,b_deblocking_filter);
        MKPARAMB(interlaceMode,interlaced_mode);
        MKPARAMB(bEnableConstrainedIntra,constrained_intra);
        MKPARAM(lookaheadDepth,lookahead);

        MKPARAMB(bEnableWeightedBiPred,weighted_bipred)
        MKPARAM (bEnableWeightedPred,weighted_pred)
        MKPARAM (cbQpOffset,cb_chroma_offset)
        MKPARAM (crQpOffset,cr_chroma_offset)

        MKPARAM (searchMethod,me_method)
        MKPARAM (searchRange,me_range)
        MKPARAM (subpelRefine,subpel_refine)
        MKPARAM (bFrameAdaptive,trellis)
        MKPARAMB(bEnableEarlySkip,fast_pskip)
        MKPARAMB(bEnableTSkipFast,dct_decimate)
        MKPARAMD(psyRd,psy_rd)

#if X265_BUILD >= 40
        MKPARAM (noiseReductionIntra,noise_reduction_intra)
        MKPARAM (noiseReductionInter,noise_reduction_inter)
#else
        MKPARAM (noiseReduction,noise_reduction)
#endif

        //---------------- ratecontrol -------------------
#undef MKPARAM
#undef MKPARAMD
#undef MKPARAMB
#define MKPARAM(x,y)  {param.rc.x = x265Settings.ratecontrol.y;aprintf("[x265] rc."#x" = %d\n",param.rc.x);}
#define MKPARAMD(x,y) {param.rc.x = (double)x265Settings.ratecontrol.y; aprintf("[x265] rc."#x" = %.2f\n",param.rc.x);}
#define MKPARAMB(x,y) {param.rc.x = x265Settings.ratecontrol.y ;aprintf("[x265] rc."#x" = %s\n",TrueFalse[param.rc.x&1]);}

        MKPARAM(qpStep,qp_step);

#if X265_BUILD >= 41
        MKPARAMB(bStrictCbr,strict_cbr);
#else
        MKPARAM(rateTolerance,rate_tolerance);
#endif

        MKPARAM(ipFactor,ip_factor);
        MKPARAM(pbFactor,pb_factor);
        MKPARAMB(cuTree,cu_tree);
        MKPARAM(aqMode,aq_mode);
        MKPARAMD(aqStrength,aq_strength);
    }

    if(!param.bframes)  encoderDelay=0;
    else
    {
        if(2>=param.maxNumReferences)
        {
            encoderDelay=f*2*2;
        }
        else
        {
            encoderDelay=2*f*(x265Settings.MaxRefFrames-1);
        }
    }

    if(!x265Settings.useAdvancedConfiguration)
    {
        x265_param_apply_profile(&param, x265Settings.general.profile);
    }

    dumpx265Setup(&param);
    ADM_info("Creating x265 encoder\n");
    handle = x265_encoder_open (&param);
    if (!handle)
    {
        ADM_error("Cannot initialize x265\n");
        return 0;
    }


    ADM_info("x265, setup ok\n");
    if (globalHeader)
    {
        ADM_info("Creating global header\n");
        return createHeader ();
    } else
        ADM_info("No need for global header\n");

    return true;
}
Exemple #7
0
/***********************************************************************
 * hb_work_encx265_init
 ***********************************************************************
 *
 **********************************************************************/
int encx265Init(hb_work_object_t *w, hb_job_t *job)
{
    hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t));
    pv->next_chapter_pts  = AV_NOPTS_VALUE;
    pv->delayed_chapters  = hb_list_init();
    pv->job               = job;
    w->private_data       = pv;
    int i, vrate, vrate_base;
    x265_nal *nal;
    uint32_t nnal;

    x265_param *param = pv->param = x265_param_alloc();

    if (x265_param_default_preset(param,
                                  job->encoder_preset, job->encoder_tune) < 0)
    {
        free(pv);
        pv = NULL;
        return 1;
    }

    /* If the PSNR or SSIM tunes are in use, enable the relevant metric */
    param->bEnablePsnr = param->bEnableSsim = 0;
    if (job->encoder_tune != NULL && *job->encoder_tune)
    {
        char *tmp = strdup(job->encoder_tune);
        char *tok = strtok(tmp,   ",./-+");
        do
        {
            if (!strncasecmp(tok, "psnr", 4))
            {
                param->bEnablePsnr = 1;
                break;
            }
            if (!strncasecmp(tok, "ssim", 4))
            {
                param->bEnableSsim = 1;
                break;
            }
        }
        while ((tok = strtok(NULL, ",./-+")) != NULL);
        free(tmp);
    }

    /*
     * Some HandBrake-specific defaults; users can override them
     * using the encoder_options string.
     */
    hb_reduce(&vrate, &vrate_base, job->vrate, job->vrate_base);
    param->fpsNum      = vrate;
    param->fpsDenom    = vrate_base;
    param->keyframeMin = (int)((double)vrate / (double)vrate_base + 0.5);
    param->keyframeMax = param->keyframeMin * 10;

    /* iterate through x265_opts and parse the options */
    hb_dict_entry_t *entry = NULL;
    hb_dict_t *x265_opts = hb_encopts_to_dict(job->encoder_options, job->vcodec);
    while ((entry = hb_dict_next(x265_opts, entry)) != NULL)
    {
        // here's where the strings are passed to libx265 for parsing
        int ret = x265_param_parse(param, entry->key, entry->value);
        // let x265 sanity check the options for us
        switch (ret)
        {
            case X265_PARAM_BAD_NAME:
                hb_log("encx265: unknown option '%s'", entry->key);
                break;
            case X265_PARAM_BAD_VALUE:
                hb_log("encx265: bad argument '%s=%s'", entry->key,
                       entry->value ? entry->value : "(null)");
                break;
            default:
                break;
        }
    }
    hb_dict_free(&x265_opts);

    /*
     * Settings which can't be overriden in the encodeer_options string
     * (muxer-specific settings, resolution, ratecontrol, etc.).
     */
    param->sourceWidth  = job->width;
    param->sourceHeight = job->height;

    if (job->vquality > 0)
    {
        param->rc.rateControlMode = X265_RC_CRF;
        param->rc.rfConstant      = job->vquality;
    }
    else
    {
        param->rc.rateControlMode = X265_RC_ABR;
        param->rc.bitrate         = job->vbitrate;
    }

    /* statsfile (but not 2-pass) */
    memset(pv->csvfn, 0, sizeof(pv->csvfn));
    if (param->logLevel >= X265_LOG_DEBUG)
    {
        if (param->csvfn == NULL)
        {
            hb_get_tempory_filename(job->h, pv->csvfn, "x265.csv");
            param->csvfn = pv->csvfn;
        }
        else
        {
            strncpy(pv->csvfn, param->csvfn, sizeof(pv->csvfn));
        }
    }

    /* Apply profile and level settings last. */
    if (x265_param_apply_profile(param, job->encoder_profile) < 0)
    {
        free(pv);
        pv = NULL;
        return 1;
    }

    /* we should now know whether B-frames are enabled */
    job->areBframes = (param->bframes > 0) + (param->bframes   > 0 &&
                                              param->bBPyramid > 0);

    pv->x265 = x265_encoder_open(param);
    if (pv->x265 == NULL)
    {
        hb_error("encx265: x265_encoder_open failed.");
        free(pv);
        pv = NULL;
        return 1;
    }

    if (x265_encoder_headers(pv->x265, &nal, &nnal) < 0)
    {
        hb_error("encx265: x265_encoder_headers failed.");
        free(pv);
        pv = NULL;
        return 1;
    }

    /*
     * x265's output (headers and bitstream) are in Annex B format.
     *
     * Write the header as is, and let the muxer reformat
     * the extradata and output bitstream properly for us.
     */
    w->config->h265.headers_length = 0;
    for (i = 0; i < nnal; i++)
    {
        if (w->config->h265.headers_length +
            nal[i].sizeBytes > HB_CONFIG_MAX_SIZE)
        {
            hb_error("encx265: bitstream headers too large");
            free(pv);
            pv = NULL;
            return 1;
        }
        memcpy(w->config->h265.headers +
               w->config->h265.headers_length,
               nal[i].payload, nal[i].sizeBytes);
        w->config->h265.headers_length += nal[i].sizeBytes;
    }

    return 0;
}
Exemple #8
0
/*
 * gst_x265_enc_init_encoder
 * @encoder:  Encoder which should be initialized.
 *
 * Initialize x265 encoder.
 *
 */
static gboolean
gst_x265_enc_init_encoder (GstX265Enc * encoder)
{
  GstVideoInfo *info;

  if (!encoder->input_state) {
    GST_DEBUG_OBJECT (encoder, "Have no input state yet");
    return FALSE;
  }

  info = &encoder->input_state->info;

  /* make sure that the encoder is closed */
  gst_x265_enc_close_encoder (encoder);

  GST_OBJECT_LOCK (encoder);

  if (x265_param_default_preset (&encoder->x265param,
          x265_preset_names[encoder->speed_preset - 1],
          x265_tune_names[encoder->tune]) < 0) {
    GST_DEBUG_OBJECT (encoder, "preset or tune unrecognized");
    GST_OBJECT_UNLOCK (encoder);
    return FALSE;
  }

  /* set up encoder parameters */
  encoder->x265param.logLevel = encoder->log_level;
  encoder->x265param.internalCsp =
      gst_x265_enc_gst_to_x265_video_format (info->finfo->format, NULL);
  if (info->fps_d == 0 || info->fps_n == 0) {
  } else {
    encoder->x265param.fpsNum = info->fps_n;
    encoder->x265param.fpsDenom = info->fps_d;
  }
  encoder->x265param.sourceWidth = info->width;
  encoder->x265param.sourceHeight = info->height;
  if (info->par_d > 0) {
    encoder->x265param.vui.sarWidth = info->par_n;
    encoder->x265param.vui.sarHeight = info->par_d;
  }

  if (encoder->qp != -1) {
    /* CQP */
    encoder->x265param.rc.qp = encoder->qp;
    encoder->x265param.rc.rateControlMode = X265_RC_CQP;
  } else {
    /* ABR */
    encoder->x265param.rc.bitrate = encoder->bitrate;
    encoder->x265param.rc.rateControlMode = X265_RC_ABR;
  }

  /* apply option-string property */
  if (encoder->option_string_prop && encoder->option_string_prop->len) {
    GST_DEBUG_OBJECT (encoder, "Applying option-string: %s",
        encoder->option_string_prop->str);
    if (gst_x265_enc_parse_options (encoder,
            encoder->option_string_prop->str) == FALSE) {
      GST_DEBUG_OBJECT (encoder, "Your option-string contains errors.");
      GST_OBJECT_UNLOCK (encoder);
      return FALSE;
    }
  }

  encoder->reconfig = FALSE;

  /* good start, will be corrected if needed */
  encoder->dts_offset = 0;

  GST_OBJECT_UNLOCK (encoder);

  encoder->x265enc = x265_encoder_open (&encoder->x265param);
  if (!encoder->x265enc) {
    GST_ELEMENT_ERROR (encoder, STREAM, ENCODE,
        ("Can not initialize x265 encoder."), (NULL));
    return FALSE;
  }

  encoder->push_header = TRUE;

  return TRUE;
}
static av_cold int libx265_encode_init(AVCodecContext *avctx)
{
    libx265Context *ctx = avctx->priv_data;

    if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL &&
        !av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_w) {
        av_log(avctx, AV_LOG_ERROR,
               "4:2:2 and 4:4:4 support is not fully defined for HEVC yet. "
               "Set -strict experimental to encode anyway.\n");
        return AVERROR(ENOSYS);
    }

    avctx->coded_frame = av_frame_alloc();
    if (!avctx->coded_frame) {
        av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
        return AVERROR(ENOMEM);
    }

    ctx->params = x265_param_alloc();
    if (!ctx->params) {
        av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n");
        return AVERROR(ENOMEM);
    }

    if (x265_param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) {
        int i;

        av_log(avctx, AV_LOG_ERROR, "Error setting preset/tune %s/%s.\n", ctx->preset, ctx->tune);
        av_log(avctx, AV_LOG_INFO, "Possible presets:");
        for (i = 0; x265_preset_names[i]; i++)
            av_log(avctx, AV_LOG_INFO, " %s", x265_preset_names[i]);

        av_log(avctx, AV_LOG_INFO, "\n");
        av_log(avctx, AV_LOG_INFO, "Possible tunes:");
        for (i = 0; x265_tune_names[i]; i++)
            av_log(avctx, AV_LOG_INFO, " %s", x265_tune_names[i]);

        av_log(avctx, AV_LOG_INFO, "\n");

        return AVERROR(EINVAL);
    }

    ctx->params->frameNumThreads = avctx->thread_count;
    ctx->params->fpsNum          = avctx->time_base.den;
    ctx->params->fpsDenom        = avctx->time_base.num * avctx->ticks_per_frame;
    ctx->params->sourceWidth     = avctx->width;
    ctx->params->sourceHeight    = avctx->height;
    ctx->params->bEnablePsnr     = !!(avctx->flags & CODEC_FLAG_PSNR);

    if ((avctx->color_primaries <= AVCOL_PRI_BT2020 &&
         avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) ||
        (avctx->color_trc <= AVCOL_TRC_BT2020_12 &&
         avctx->color_trc != AVCOL_TRC_UNSPECIFIED) ||
        (avctx->colorspace <= AVCOL_SPC_BT2020_CL &&
         avctx->colorspace != AVCOL_SPC_UNSPECIFIED)) {

        ctx->params->vui.bEnableVideoSignalTypePresentFlag  = 1;
        ctx->params->vui.bEnableColorDescriptionPresentFlag = 1;

        // x265 validates the parameters internally
        ctx->params->vui.colorPrimaries          = avctx->color_primaries;
        ctx->params->vui.transferCharacteristics = avctx->color_trc;
        ctx->params->vui.matrixCoeffs            = avctx->colorspace;
    }

    if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) {
        char sar[12];
        int sar_num, sar_den;

        av_reduce(&sar_num, &sar_den,
                  avctx->sample_aspect_ratio.num,
                  avctx->sample_aspect_ratio.den, 65535);
        snprintf(sar, sizeof(sar), "%d:%d", sar_num, sar_den);
        if (x265_param_parse(ctx->params, "sar", sar) == X265_PARAM_BAD_VALUE) {
            av_log(avctx, AV_LOG_ERROR, "Invalid SAR: %d:%d.\n", sar_num, sar_den);
            return AVERROR_INVALIDDATA;
        }
    }

    switch (avctx->pix_fmt) {
    case AV_PIX_FMT_YUV420P:
    case AV_PIX_FMT_YUV420P10:
        ctx->params->internalCsp = X265_CSP_I420;
        break;
    case AV_PIX_FMT_YUV422P:
    case AV_PIX_FMT_YUV422P10:
        ctx->params->internalCsp = X265_CSP_I422;
        break;
    case AV_PIX_FMT_YUV444P:
    case AV_PIX_FMT_YUV444P10:
        ctx->params->internalCsp = X265_CSP_I444;
        break;
    }

    if (ctx->crf >= 0) {
        char crf[6];

        snprintf(crf, sizeof(crf), "%2.2f", ctx->crf);
        if (x265_param_parse(ctx->params, "crf", crf) == X265_PARAM_BAD_VALUE) {
            av_log(avctx, AV_LOG_ERROR, "Invalid crf: %2.2f.\n", ctx->crf);
            return AVERROR(EINVAL);
        }
    } else if (avctx->bit_rate > 0) {
        ctx->params->rc.bitrate         = avctx->bit_rate / 1000;
        ctx->params->rc.rateControlMode = X265_RC_ABR;
    }

    if (!(avctx->flags & CODEC_FLAG_GLOBAL_HEADER))
        ctx->params->bRepeatHeaders = 1;

    if (ctx->x265_opts) {
        AVDictionary *dict    = NULL;
        AVDictionaryEntry *en = NULL;

        if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) {
            while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) {
                int parse_ret = x265_param_parse(ctx->params, en->key, en->value);

                switch (parse_ret) {
                case X265_PARAM_BAD_NAME:
                    av_log(avctx, AV_LOG_WARNING,
                          "Unknown option: %s.\n", en->key);
                    break;
                case X265_PARAM_BAD_VALUE:
                    av_log(avctx, AV_LOG_WARNING,
                          "Invalid value for %s: %s.\n", en->key, en->value);
                    break;
                default:
                    break;
                }
            }
            av_dict_free(&dict);
        }
    }

    ctx->encoder = x265_encoder_open(ctx->params);
    if (!ctx->encoder) {
        av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n");
        libx265_encode_close(avctx);
        return AVERROR_INVALIDDATA;
    }

    if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
        x265_nal *nal;
        int nnal;

        avctx->extradata_size = x265_encoder_headers(ctx->encoder, &nal, &nnal);
        if (avctx->extradata_size <= 0) {
            av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n");
            libx265_encode_close(avctx);
            return AVERROR_INVALIDDATA;
        }

        avctx->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
        if (!avctx->extradata) {
            av_log(avctx, AV_LOG_ERROR,
                   "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size);
            libx265_encode_close(avctx);
            return AVERROR(ENOMEM);
        }

        memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size);
    }

    return 0;
}
Exemple #10
0
static HEVCEncoderContext *x265_open(const HEVCEncodeParams *params)
{
    HEVCEncoderContext *s;
    x265_param *p;
    int preset_index;
    const char *preset;

    s = malloc(sizeof(HEVCEncoderContext));
    memset(s, 0, sizeof(*s));

    if (params->bit_depth != x265_max_bit_depth) {
        fprintf(stderr, "x265 is compiled to support only %d bit depth. Use the '-b %d' option to force the bit depth.\n",
                x265_max_bit_depth, x265_max_bit_depth);
        return NULL;
    }
    if (params->chroma_format == BPG_FORMAT_GRAY) {
        fprintf(stderr, "x265 does not support monochrome (or alpha) data yet. Plase use the jctvc encoder.\n");
        return NULL;
    }

    p = x265_param_alloc();

    preset_index = params->compress_level; /* 9 is placebo */

    preset = x265_preset_names[preset_index];
    if (params->verbose)
        printf("Using x265 preset: %s\n", preset);
    
    x265_param_default_preset(p, preset, "ssim");

    p->bRepeatHeaders = 1;
    p->decodedPictureHashSEI = params->sei_decoded_picture_hash;
    p->sourceWidth = params->width;
    p->sourceHeight = params->height;
    switch(params->chroma_format) {
    case BPG_FORMAT_GRAY:
        p->internalCsp = X265_CSP_I400;
        break;
    case BPG_FORMAT_420:
        p->internalCsp = X265_CSP_I420;
        break;
    case BPG_FORMAT_422:
        p->internalCsp = X265_CSP_I422;
        break;
    case BPG_FORMAT_444:
        p->internalCsp = X265_CSP_I444;
        break;
    default:
        abort();
    }
    if (params->intra_only) {
        p->keyframeMax = 1; /* only I frames */
        p->totalFrames = 1;
    } else {
        p->keyframeMax = 250;
        p->totalFrames = 0;
        p->maxNumReferences = 1;
        p->bframes = 0;
    }
    p->bEnableRectInter = 1;
    p->bEnableAMP = 1; /* cannot use 0 due to header restriction */
    p->internalBitDepth = params->bit_depth;
    p->bEmitInfoSEI = 0;
    if (params->verbose)
        p->logLevel = X265_LOG_INFO;
    else
        p->logLevel = X265_LOG_NONE;
        
    /* dummy frame rate */
    p->fpsNum = 25;
    p->fpsDenom = 1;

    p->rc.rateControlMode = X265_RC_CQP;
    /* XXX: why do we need this offset to match the JCTVC quality ? */
    if (params->bit_depth == 10)
        p->rc.qp = params->qp + 7;
    else
        p->rc.qp = params->qp + 1;
    p->bLossless = params->lossless;

    s->enc = x265_encoder_open(p);

    s->pic = x265_picture_alloc();
    x265_picture_init(p, s->pic);

    s->pic->colorSpace = p->internalCsp;

    x265_param_free(p);

    return s;
}
bool VideoEncoderX265::reconfigure(VideoFrame* orgFrame, VideoFrame* dstFrame)
{
    int colorspace;

    if (!needsConfig && orgFrame->getWidth() == xparams->sourceWidth &&
        orgFrame->getHeight() == xparams->sourceHeight && orgFrame->getPixelFormat() == inPixFmt) {
        return true;
    }

    inPixFmt = orgFrame->getPixelFormat();
    switch (inPixFmt) {
        case YUV420P:
            libavInPixFmt = AV_PIX_FMT_YUV420P;
            colorspace = X265_CSP_I420;
            break;
        /*TODO X265_CSP_I422 not supported yet. Continue checking x265 library releases for its support.
        case YUV422P:
            libavInPixFmt = AV_PIX_FMT_YUV422P;
            colorspace = X265_CSP_I422;
            break;*/
        case YUV444P:
            libavInPixFmt = AV_PIX_FMT_YUV444P;
            colorspace = X265_CSP_I444;
            break;
        default:
            utils::debugMsg("Uncompatibe input pixel format");
            libavInPixFmt = AV_PIX_FMT_NONE;
            /*TODO X265_CSP_NONE is not implemented. Continue checking x265 library releases for its support*/
            colorspace = -1;
            return false;
            break;
    }

    picIn->colorSpace = colorspace;
    x265_param_default_preset(xparams, preset.c_str(), NULL);
    /*TODO check with NULL profile*/
    x265_param_apply_profile(xparams, "main");

    x265_param_parse(xparams, "keyint", std::to_string(gop).c_str());
    x265_param_parse(xparams, "fps", std::to_string(fps).c_str());
    x265_param_parse(xparams, "input-res", (std::to_string(orgFrame->getWidth()) + 'x' + std::to_string(orgFrame->getHeight())).c_str());

    //TODO check same management for intra-refresh like x264
    //x265_param_parse(xparams, "intra-refresh", std::to_string(0).c_str());

    x265_param_parse(xparams, "frame-threads", std::to_string(threads).c_str());
    x265_param_parse(xparams, "aud", std::to_string(1).c_str());
    x265_param_parse(xparams, "bitrate", std::to_string(bitrate).c_str());
    x265_param_parse(xparams, "bframes", std::to_string(0).c_str());
    x265_param_parse(xparams, "repeat-headers", std::to_string(0).c_str());
    x265_param_parse(xparams, "vbv-maxrate", std::to_string(bitrate*1.05).c_str());
    x265_param_parse(xparams, "vbv-bufsize", std::to_string(bitrate*2).c_str());
    x265_param_parse(xparams, "rc-lookahead", std::to_string(lookahead).c_str());
    x265_param_parse(xparams, "annexb", std::to_string(1).c_str());
    x265_param_parse(xparams, "scenecut", std::to_string(0).c_str());


    if (annexB) {
        x265_param_parse(xparams, "repeat-headers", std::to_string(1).c_str());
    }

    if (!encoder) {
        encoder = x265_encoder_open(xparams);
    } else {
        /*TODO reimplement it when a reconfigure method appear*/
        x265_encoder_close(encoder);
        encoder = x265_encoder_open(xparams);
    }

    if (!encoder) {
        utils::errorMsg("Error reconfiguring x265 encoder. At this point encoder should not be NULL...");
        return false;
    }

    x265_picture_init(xparams, picIn);
    x265_picture_init(xparams, picOut);

    needsConfig = false;

    if (!annexB) {
        return encodeHeadersFrame(dstFrame);
    }

    return true;
}
Exemple #12
0
static int  Open (vlc_object_t *p_this)
{
    encoder_t     *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;

    if (p_enc->fmt_out.i_codec != VLC_CODEC_HEVC && !p_enc->b_force)
        return VLC_EGENERIC;

    p_enc->fmt_out.i_cat = VIDEO_ES;
    p_enc->fmt_out.i_codec = VLC_CODEC_HEVC;
    p_enc->p_sys = p_sys = malloc(sizeof(encoder_sys_t));
    if (!p_sys)
        return VLC_ENOMEM;

    p_enc->fmt_in.i_codec = VLC_CODEC_I420;

    x265_param *param = &p_sys->param;
    x265_param_default(param);

    param->frameNumThreads = vlc_GetCPUCount();
    param->bEnableWavefront = 0; // buggy in x265, use frame threading for now
    param->maxCUSize = 16; /* use smaller macroblock */

#if X265_BUILD >= 6
    param->fpsNum = p_enc->fmt_in.video.i_frame_rate;
    param->fpsDenom = p_enc->fmt_in.video.i_frame_rate_base;
    if (!param->fpsNum) {
        param->fpsNum = 25;
        param->fpsDenom = 1;
    }
#else
    if (p_enc->fmt_in.video.i_frame_rate_base) {
        param->frameRate = p_enc->fmt_in.video.i_frame_rate /
            p_enc->fmt_in.video.i_frame_rate_base;
    } else {
        param->frameRate = 25;
    }
#endif
    param->sourceWidth = p_enc->fmt_in.video.i_visible_width;
    param->sourceHeight = p_enc->fmt_in.video.i_visible_height;

    if (param->sourceWidth & (param->maxCUSize - 1)) {
        msg_Err(p_enc, "Width (%d) must be a multiple of %d",
            param->sourceWidth, param->maxCUSize);
        free(p_sys);
        return VLC_EGENERIC;
    }
    if (param->sourceHeight & 7) {
        msg_Err(p_enc, "Height (%d) must be a multiple of 8", param->sourceHeight);
        free(p_sys);
        return VLC_EGENERIC;
    }

    if (p_enc->fmt_out.i_bitrate > 0) {
        param->rc.bitrate = p_enc->fmt_out.i_bitrate / 1000;
        param->rc.rateControlMode = X265_RC_ABR;
    }

    p_sys->h = x265_encoder_open(param);
    if (p_sys->h == NULL) {
        msg_Err(p_enc, "cannot open x265 encoder");
        free(p_sys);
        return VLC_EGENERIC;
    }

    x265_nal *nal;
    uint32_t i_nal;
    if (x265_encoder_headers(p_sys->h, &nal, &i_nal) < 0) {
        msg_Err(p_enc, "cannot get x265 headers");
        Close(VLC_OBJECT(p_enc));
        return VLC_EGENERIC;
    }

    size_t i_extra = 0;
    for (uint32_t i = 0; i < i_nal; i++)
        i_extra += nal[i].sizeBytes;

    p_enc->fmt_out.i_extra = i_extra;

    uint8_t *p_extra = p_enc->fmt_out.p_extra = malloc(i_extra);
    if (!p_extra) {
        Close(VLC_OBJECT(p_enc));
        return VLC_ENOMEM;
    }

    for (uint32_t i = 0; i < i_nal; i++) {
        memcpy(p_extra, nal[i].payload, nal[i].sizeBytes);
        p_extra += nal[i].sizeBytes;
    }

    p_sys->dts = 0;
    p_sys->initial_date = 0;
    p_sys->i_initial_delay = 0;

    p_enc->pf_encode_video = Encode;
    p_enc->pf_encode_audio = NULL;

    return VLC_SUCCESS;
}