summaryrefslogtreecommitdiffstats
path: root/libhb/enc_qsv.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/enc_qsv.c')
-rw-r--r--libhb/enc_qsv.c211
1 files changed, 151 insertions, 60 deletions
diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c
index 3b745744a..c3129b749 100644
--- a/libhb/enc_qsv.c
+++ b/libhb/enc_qsv.c
@@ -56,6 +56,7 @@ struct hb_work_private_s
hb_qsv_param_t param;
av_qsv_space enc_space;
+ hb_qsv_info_t *qsv_info;
mfxEncodeCtrl force_keyframe;
hb_list_t *delayed_chapters;
@@ -361,6 +362,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
pv->job = job;
pv->is_sys_mem = !hb_qsv_decode_is_enabled(job);
+ pv->qsv_info = hb_qsv_info_get(job->vcodec);
pv->delayed_processing = hb_list_init();
pv->last_start = INT64_MIN;
pv->frames_in = 0;
@@ -381,7 +383,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
// default encoding parameters
if (hb_qsv_param_default_preset(&pv->param, &pv->enc_space.m_mfxVideoParam,
- job->encoder_preset))
+ pv->qsv_info, job->encoder_preset))
{
hb_error("encqsvInit: hb_qsv_param_default_preset failed");
return -1;
@@ -434,8 +436,8 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
options_list = hb_encopts_to_dict(job->encoder_options, job->vcodec);
while ((option = hb_dict_next(options_list, option)) != NULL)
{
- switch (hb_qsv_param_parse(&pv->param,
- option->key, option->value, job->vcodec))
+ switch (hb_qsv_param_parse(&pv->param, pv->qsv_info,
+ option->key, option->value))
{
case HB_QSV_PARAM_OK:
break;
@@ -551,7 +553,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
hb_error("encqsvInit: bad level %s", job->encoder_level);
return -1;
}
- else if (hb_qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6)
+ else if (pv->qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6)
{
pv->param.videoParam->mfx.CodecLevel = HB_QSV_CLIP3(MFX_LEVEL_AVC_1,
MFX_LEVEL_AVC_52,
@@ -587,46 +589,91 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
}
}
- // set rate control paremeters
- if (job->vquality >= 0)
+ // sanitize ICQ
+ if (!(pv->qsv_info->capabilities & HB_QSV_CAP_RATECONTROL_ICQ))
{
- // introduced in API 1.1
- pv->param.videoParam->mfx.RateControlMethod = MFX_RATECONTROL_CQP;
- pv->param.videoParam->mfx.QPI = HB_QSV_CLIP3(0, 51, job->vquality + pv->param.rc.cqp_offsets[0]);
- pv->param.videoParam->mfx.QPP = HB_QSV_CLIP3(0, 51, job->vquality + pv->param.rc.cqp_offsets[1]);
- pv->param.videoParam->mfx.QPB = HB_QSV_CLIP3(0, 51, job->vquality + pv->param.rc.cqp_offsets[2]);
- // CQP + ExtBRC can cause bad output
- pv->param.codingOption2.ExtBRC = MFX_CODINGOPTION_OFF;
+ // ICQ not supported
+ pv->param.rc.icq = 0;
}
- else if (job->vbitrate > 0)
+ else
+ {
+ pv->param.rc.icq = !!pv->param.rc.icq;
+ }
+
+ // sanitize lookahead
+ if (!(pv->qsv_info->capabilities & HB_QSV_CAP_RATECONTROL_LA))
+ {
+ // lookahead not supported
+ pv->param.rc.lookahead = 0;
+ }
+ else if ((pv->param.rc.lookahead) &&
+ (pv->qsv_info->capabilities & HB_QSV_CAP_RATECONTROL_LAi) == 0 &&
+ (pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE))
{
- // sanitize lookahead
- if (!(hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD))
+ // lookahead enabled but we can't use it
+ hb_log("encqsvInit: LookAhead not used (LookAhead is progressive-only)");
+ pv->param.rc.lookahead = 0;
+ }
+ else
+ {
+ pv->param.rc.lookahead = !!pv->param.rc.lookahead;
+ }
+
+ // set VBV here (this will be overridden for CQP and ignored for LA)
+ // only set BufferSizeInKB, InitialDelayInKB and MaxKbps if we have
+ // them - otheriwse Media SDK will pick values for us automatically
+ if (pv->param.rc.vbv_buffer_size > 0)
+ {
+ if (pv->param.rc.vbv_buffer_init > 1.0)
+ {
+ pv->param.videoParam->mfx.InitialDelayInKB = (pv->param.rc.vbv_buffer_init / 8);
+ }
+ else if (pv->param.rc.vbv_buffer_init > 0.0)
{
- // lookahead not supported
- pv->param.rc.lookahead = 0;
+ pv->param.videoParam->mfx.InitialDelayInKB = (pv->param.rc.vbv_buffer_size *
+ pv->param.rc.vbv_buffer_init / 8);
}
- else if (pv->param.rc.lookahead &&
- pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
+ pv->param.videoParam->mfx.BufferSizeInKB = (pv->param.rc.vbv_buffer_size / 8);
+ }
+ if (pv->param.rc.vbv_max_bitrate > 0)
+ {
+ pv->param.videoParam->mfx.MaxKbps = pv->param.rc.vbv_max_bitrate;
+ }
+
+ // set rate control paremeters
+ if (job->vquality >= 0)
+ {
+ if (pv->param.rc.icq)
{
- // lookahead enabled but we can't use it
- hb_log("encqsvInit: MFX_RATECONTROL_LA not used (LookAhead is progressive-only)");
- pv->param.rc.lookahead = 0;
+ // introduced in API 1.8
+ if (pv->param.rc.lookahead)
+ {
+ pv->param.videoParam->mfx.RateControlMethod = MFX_RATECONTROL_LA_ICQ;
+ }
+ else
+ {
+ pv->param.videoParam->mfx.RateControlMethod = MFX_RATECONTROL_ICQ;
+ }
+ pv->param.videoParam->mfx.ICQQuality = HB_QSV_CLIP3(1, 51, job->vquality);
}
else
{
- pv->param.rc.lookahead = !!pv->param.rc.lookahead;
+ // introduced in API 1.1
+ pv->param.videoParam->mfx.RateControlMethod = MFX_RATECONTROL_CQP;
+ pv->param.videoParam->mfx.QPI = HB_QSV_CLIP3(0, 51, job->vquality + pv->param.rc.cqp_offsets[0]);
+ pv->param.videoParam->mfx.QPP = HB_QSV_CLIP3(0, 51, job->vquality + pv->param.rc.cqp_offsets[1]);
+ pv->param.videoParam->mfx.QPB = HB_QSV_CLIP3(0, 51, job->vquality + pv->param.rc.cqp_offsets[2]);
+ // CQP + ExtBRC can cause bad output
+ pv->param.codingOption2.ExtBRC = MFX_CODINGOPTION_OFF;
}
+ }
+ else if (job->vbitrate > 0)
+ {
if (pv->param.rc.lookahead)
{
// introduced in API 1.7
pv->param.videoParam->mfx.RateControlMethod = MFX_RATECONTROL_LA;
pv->param.videoParam->mfx.TargetKbps = job->vbitrate;
- if (pv->param.rc.vbv_max_bitrate > 0 ||
- pv->param.rc.vbv_buffer_size > 0)
- {
- hb_log("encqsvInit: MFX_RATECONTROL_LA, ignoring VBV");
- }
// ignored, but some drivers will change AsyncDepth because of it
pv->param.codingOption2.ExtBRC = MFX_CODINGOPTION_OFF;
}
@@ -641,25 +688,6 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
{
pv->param.videoParam->mfx.RateControlMethod = MFX_RATECONTROL_VBR;
}
- // only set BufferSizeInKB, InitialDelayInKB and MaxKbps if we have
- // them - otheriwse Media SDK will pick values for us automatically
- if (pv->param.rc.vbv_buffer_size > 0)
- {
- if (pv->param.rc.vbv_buffer_init > 1.0)
- {
- pv->param.videoParam->mfx.InitialDelayInKB = (pv->param.rc.vbv_buffer_init / 8);
- }
- else if (pv->param.rc.vbv_buffer_init > 0.0)
- {
- pv->param.videoParam->mfx.InitialDelayInKB = (pv->param.rc.vbv_buffer_size *
- pv->param.rc.vbv_buffer_init / 8);
- }
- pv->param.videoParam->mfx.BufferSizeInKB = (pv->param.rc.vbv_buffer_size / 8);
- }
- if (pv->param.rc.vbv_max_bitrate > 0)
- {
- pv->param.videoParam->mfx.MaxKbps = pv->param.rc.vbv_max_bitrate;
- }
pv->param.videoParam->mfx.TargetKbps = job->vbitrate;
}
}
@@ -670,6 +698,23 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
return -1;
}
+ // if VBV is enabled but ignored, log it
+ if (pv->param.rc.vbv_max_bitrate > 0 || pv->param.rc.vbv_buffer_size > 0)
+ {
+ switch (pv->param.videoParam->mfx.RateControlMethod)
+ {
+ case MFX_RATECONTROL_LA:
+ case MFX_RATECONTROL_LA_ICQ:
+ hb_log("encqsvInit: LookAhead enabled, ignoring VBV");
+ break;
+ case MFX_RATECONTROL_ICQ:
+ hb_log("encqsvInit: ICQ rate control, ignoring VBV");
+ break;
+ default:
+ break;
+ }
+ }
+
// set B-pyramid
if (pv->param.gop.b_pyramid < 0)
{
@@ -733,7 +778,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
pv->param.rc.lookahead ? 60 : 0);
}
- if ((hb_qsv_info->capabilities & HB_QSV_CAP_H264_BPYRAMID) &&
+ if ((pv->qsv_info->capabilities & HB_QSV_CAP_B_REF_PYRAMID) &&
(pv->param.videoParam->mfx.CodecProfile != MFX_PROFILE_AVC_BASELINE &&
pv->param.videoParam->mfx.CodecProfile != MFX_PROFILE_AVC_CONSTRAINED_HIGH &&
pv->param.videoParam->mfx.CodecProfile != MFX_PROFILE_AVC_CONSTRAINED_BASELINE))
@@ -838,7 +883,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
mfxExtCodingOptionSPSPPS sps_pps_buf, *sps_pps = &sps_pps_buf;
version.Major = HB_QSV_MINVERSION_MAJOR;
version.Minor = HB_QSV_MINVERSION_MINOR;
- err = MFXInit(hb_qsv_impl_get_preferred(), &version, &session);
+ err = MFXInit(pv->qsv_info->implementation, &version, &session);
if (err != MFX_ERR_NONE)
{
hb_error("encqsvInit: MFXInit failed (%d)", err);
@@ -886,7 +931,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
memset(option2, 0, sizeof(mfxExtCodingOption2));
option2->Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
option2->Header.BufferSz = sizeof(mfxExtCodingOption2);
- if (hb_qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6)
+ if (pv->qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6)
{
// attach to get the final output mfxExtCodingOption2 settings
videoParam.ExtParam[videoParam.NumExtParam++] = (mfxExtBuffer*)option2;
@@ -949,7 +994,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
// let the muxer know whether to expect B-frames or not
job->areBframes = !!pv->bfrm_delay;
// check whether we need to generate DTS ourselves (MSDK API < 1.6 or VFR)
- pv->bfrm_workaround = job->cfr != 1 || !(hb_qsv_info->capabilities &
+ pv->bfrm_workaround = job->cfr != 1 || !(pv->qsv_info->capabilities &
HB_QSV_CAP_MSDK_API_1_6);
if (pv->bfrm_delay && pv->bfrm_workaround)
{
@@ -969,7 +1014,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
videoParam.mfx.TargetUsage, videoParam.AsyncDepth);
hb_log("encqsvInit: GopRefDist %"PRIu16" GopPicSize %"PRIu16" NumRefFrame %"PRIu16"",
videoParam.mfx.GopRefDist, videoParam.mfx.GopPicSize, videoParam.mfx.NumRefFrame);
- if (hb_qsv_info->capabilities & HB_QSV_CAP_H264_BPYRAMID)
+ if (pv->qsv_info->capabilities & HB_QSV_CAP_B_REF_PYRAMID)
{
hb_log("encqsvInit: BFrames %s BPyramid %s",
pv->bfrm_delay ? "on" : "off",
@@ -979,6 +1024,20 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
{
hb_log("encqsvInit: BFrames %s", pv->bfrm_delay ? "on" : "off");
}
+ if (pv->qsv_info->capabilities & HB_QSV_CAP_OPTION2_IB_ADAPT)
+ {
+ if (pv->bfrm_delay > 0)
+ {
+ hb_log("encqsvInit: AdaptiveI %s AdaptiveB %s",
+ hb_qsv_codingoption_get_name(option2->AdaptiveI),
+ hb_qsv_codingoption_get_name(option2->AdaptiveB));
+ }
+ else
+ {
+ hb_log("encqsvInit: AdaptiveI %s",
+ hb_qsv_codingoption_get_name(option2->AdaptiveI));
+ }
+ }
if (videoParam.mfx.RateControlMethod == MFX_RATECONTROL_CQP)
{
char qpi[7], qpp[9], qpb[9];
@@ -997,6 +1056,14 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
hb_log("encqsvInit: RateControlMethod LA TargetKbps %"PRIu16" LookAheadDepth %"PRIu16"",
videoParam.mfx.TargetKbps, option2->LookAheadDepth);
break;
+ case MFX_RATECONTROL_LA_ICQ:
+ hb_log("encqsvInit: RateControlMethod LA_ICQ ICQQuality %"PRIu16" LookAheadDepth %"PRIu16"",
+ videoParam.mfx.ICQQuality, option2->LookAheadDepth);
+ break;
+ case MFX_RATECONTROL_ICQ:
+ hb_log("encqsvInit: RateControlMethod ICQ ICQQuality %"PRIu16"",
+ videoParam.mfx.ICQQuality);
+ break;
case MFX_RATECONTROL_CBR:
case MFX_RATECONTROL_VBR:
hb_log("encqsvInit: RateControlMethod %s TargetKbps %"PRIu16" MaxKbps %"PRIu16" BufferSizeInKB %"PRIu16" InitialDelayInKB %"PRIu16"",
@@ -1010,6 +1077,30 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
return -1;
}
}
+ if ((pv->qsv_info->capabilities & HB_QSV_CAP_OPTION2_LA_DOWNS) &&
+ (videoParam.mfx.RateControlMethod == MFX_RATECONTROL_LA ||
+ videoParam.mfx.RateControlMethod == MFX_RATECONTROL_LA_ICQ))
+ {
+ switch (option2->LookAheadDS)
+ {
+ case MFX_LOOKAHEAD_DS_UNKNOWN:
+ hb_log("encqsvInit: LookAheadDS unknown (auto)");
+ break;
+ case MFX_LOOKAHEAD_DS_OFF:
+ hb_log("encqsvInit: LookAheadDS off");
+ break;
+ case MFX_LOOKAHEAD_DS_2x:
+ hb_log("encqsvInit: LookAheadDS 2x");
+ break;
+ case MFX_LOOKAHEAD_DS_4x:
+ hb_log("encqsvInit: LookAheadDS 4x");
+ break;
+ default:
+ hb_log("encqsvInit: invalid LookAheadDS value 0x%"PRIx16"",
+ option2->LookAheadDS);
+ break;
+ }
+ }
switch (videoParam.mfx.FrameInfo.PicStruct)
{
// quiet, most people don't care
@@ -1029,22 +1120,22 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
}
hb_log("encqsvInit: CAVLC %s",
hb_qsv_codingoption_get_name(option1->CAVLC));
- if (videoParam.mfx.RateControlMethod != MFX_RATECONTROL_LA &&
+ if (pv->param.rc.lookahead == 0 &&
videoParam.mfx.RateControlMethod != MFX_RATECONTROL_CQP)
{
// LA/CQP and ExtBRC/MBBRC are mutually exclusive
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_EXTBRC)
+ if (pv->qsv_info->capabilities & HB_QSV_CAP_OPTION2_EXTBRC)
{
hb_log("encqsvInit: ExtBRC %s",
hb_qsv_codingoption_get_name(option2->ExtBRC));
}
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_MBBRC)
+ if (pv->qsv_info->capabilities & HB_QSV_CAP_OPTION2_MBBRC)
{
hb_log("encqsvInit: MBBRC %s",
hb_qsv_codingoption_get_name(option2->MBBRC));
}
}
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_TRELLIS)
+ if (pv->qsv_info->capabilities & HB_QSV_CAP_OPTION2_TRELLIS)
{
switch (option2->Trellis)
{
@@ -1453,9 +1544,9 @@ int encqsvWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
buf->s.duration = duration;
if (pv->bfrm_delay)
{
- if ((pv->frames_out == 0) &&
- (hb_qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6) &&
- (hb_qsv_info->capabilities & HB_QSV_CAP_H264_BPYRAMID))
+ if ((pv->frames_out == 0) &&
+ (pv->qsv_info->capabilities & HB_QSV_CAP_MSDK_API_1_6) &&
+ (pv->qsv_info->capabilities & HB_QSV_CAP_B_REF_PYRAMID))
{
// with B-pyramid, the delay may be more than 1 frame,
// so compute the actual delay based on the initial DTS