static int set_params(struct videnc_state *st, unsigned fps, unsigned bitrate) { st->param = x265_param_alloc(); if (!st->param) { warning("h265: x265_param_alloc failed\n"); return ENOMEM; } x265_param_default(st->param); if (0 != x265_param_apply_profile(st->param, "main")) { warning("h265: x265_param_apply_profile failed\n"); return EINVAL; } if (0 != x265_param_default_preset(st->param, "ultrafast", "zerolatency")) { warning("h265: x265_param_default_preset error\n"); return EINVAL; } st->param->fpsNum = fps; st->param->fpsDenom = 1; /* VPS, SPS and PPS headers should be output with each keyframe */ st->param->bRepeatHeaders = 1; /* Rate Control */ st->param->rc.rateControlMode = X265_RC_CRF; st->param->rc.bitrate = bitrate / 1000; st->param->rc.vbvMaxBitrate = bitrate / 1000; st->param->rc.vbvBufferSize = 2 * bitrate / fps; return 0; }
bool Video_Encoder_H265::init(Video_Encoder::NALU_CB *cb, const Encoder_Param ¶m) { //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; }
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; }
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; }
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( ¶m); 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(¶m, 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(¶m, x265Settings.general.profile); } dumpx265Setup(¶m); ADM_info("Creating x265 encoder\n"); handle = x265_encoder_open (¶m); 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; }
/*********************************************************************** * 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; }
/* * 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; }
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; }