job->anamorphic.par_width,
job->anamorphic.par_height, UINT16_MAX);
+ // some encoding parameters are used by filters to configure their output
+ if (pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
+ {
+ job->qsv_enc_info.align_height = AV_QSV_ALIGN32(job->height);
+ }
+ else
+ {
+ job->qsv_enc_info.align_height = AV_QSV_ALIGN16(job->height);
+ }
+ job->qsv_enc_info.align_width = AV_QSV_ALIGN16(job->width);
+ job->qsv_enc_info.pic_struct = pv->param.videoParam->mfx.FrameInfo.PicStruct;
+ job->qsv_enc_info.is_init_done = 1;
+
// encode to H.264 and set FrameInfo
pv->param.videoParam->mfx.CodecId = MFX_CODEC_AVC;
pv->param.videoParam->mfx.CodecLevel = MFX_LEVEL_UNKNOWN;
pv->param.videoParam->mfx.FrameInfo.CropY = 0;
pv->param.videoParam->mfx.FrameInfo.CropW = job->width;
pv->param.videoParam->mfx.FrameInfo.CropH = job->height;
- pv->param.videoParam->mfx.FrameInfo.Width = AV_QSV_ALIGN16(job->width);
- pv->param.videoParam->mfx.FrameInfo.Height = AV_QSV_ALIGN16(job->height);
- pv->param.videoParam->mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
- /*
- * Note: interlaced encoding with the QSV H.264 encoder is explicitly
- * unsupported for now.
- *
- * Unlike libx264, QSV requires that the input buffers be already padded to
- * the coding width and height (the latter has to divide cleanly by 32 in
- * the interlaced case). This would require:
- *
- * - detecting that interlaced encoding will be used early
- * - padding VPP buffers so that the output height divides cleanly by 32
- * - force-enabling VPP when there is no crop & scale but interlaced is on
- *
- * Also note that MFX_RATECONTROL_LA is progressive-only.
- */
+ pv->param.videoParam->mfx.FrameInfo.PicStruct = job->qsv_enc_info.pic_struct;
+ pv->param.videoParam->mfx.FrameInfo.Width = job->qsv_enc_info.align_width;
+ pv->param.videoParam->mfx.FrameInfo.Height = job->qsv_enc_info.align_height;
// set H.264 profile and level
if (job->h264_profile != NULL && job->h264_profile[0] != '\0' &&
}
}
+ // interlaced encoding is not always possible
+ if (pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
+ {
+ if (pv->param.videoParam->mfx.CodecProfile == MFX_PROFILE_AVC_CONSTRAINED_BASELINE ||
+ pv->param.videoParam->mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE ||
+ pv->param.videoParam->mfx.CodecProfile == MFX_PROFILE_AVC_PROGRESSIVE_HIGH)
+ {
+ hb_error("encqsvInit: profile %s doesn't support interlaced encoding",
+ qsv_h264_profile_xlat(pv->param.videoParam->mfx.CodecProfile));
+ return -1;
+ }
+ if ((pv->param.videoParam->mfx.CodecLevel >= MFX_LEVEL_AVC_1b &&
+ pv->param.videoParam->mfx.CodecLevel <= MFX_LEVEL_AVC_2) ||
+ (pv->param.videoParam->mfx.CodecLevel >= MFX_LEVEL_AVC_42))
+ {
+ hb_error("encqsvInit: level %s doesn't support interlaced encoding",
+ qsv_h264_level_xlat(pv->param.videoParam->mfx.CodecLevel));
+ return -1;
+ }
+ }
+
// set rate control paremeters
if (job->vquality >= 0)
{
}
else if (job->vbitrate > 0)
{
- if (hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD)
+ // sanitize lookahead
+ if (!(hb_qsv_info->capabilities & HB_QSV_CAP_OPTION2_LOOKAHEAD))
+ {
+ // lookahead not supported
+ pv->param.rc.lookahead = 0;
+ }
+ else if (pv->param.rc.lookahead > 0 &&
+ pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
{
- if (pv->param.rc.lookahead < 0)
+ // user force-enabled lookahead but we can't use it
+ hb_log("encqsvInit: MFX_RATECONTROL_LA not used (LookAhead is progressive-only)");
+ pv->param.rc.lookahead = 0;
+ }
+ else if (pv->param.rc.lookahead < 0)
+ {
+ if (pv->param.rc.vbv_max_bitrate > 0 ||
+ pv->param.videoParam->mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
{
- if (pv->param.rc.vbv_max_bitrate > 0)
- {
- // lookahead RC doesn't support VBV
- pv->param.rc.lookahead = 0;
- }
- else
- {
- // set automatically based on target usage
- pv->param.rc.lookahead = (pv->param.videoParam->mfx.TargetUsage <= MFX_TARGETUSAGE_2);
- }
+ // lookahead doesn't support VBV or interlaced encoding
+ pv->param.rc.lookahead = 0;
}
else
{
- // user force-enabled or force-disabled lookahead RC
- pv->param.rc.lookahead = !!pv->param.rc.lookahead;
+ // set automatically based on target usage
+ pv->param.rc.lookahead = (pv->param.videoParam->mfx.TargetUsage <= MFX_TARGETUSAGE_2);
}
}
else
{
- // lookahead RC not supported
- pv->param.rc.lookahead = 0;
+ // user force-enabled or force-disabled lookahead
+ pv->param.rc.lookahead = !!pv->param.rc.lookahead;
}
if (pv->param.rc.lookahead)
{
else
{
pv->param.videoParam->mfx.InitialDelayInKB = (pv->param.rc.vbv_buffer_size *
- pv->param.rc.vbv_buffer_init / 8);
+ pv->param.rc.vbv_buffer_init / 8);
}
pv->param.videoParam->mfx.BufferSizeInKB = (pv->param.rc.vbv_buffer_size / 8);
}
else
{
pv->param.videoParam->mfx.InitialDelayInKB = (pv->param.rc.vbv_buffer_size *
- pv->param.rc.vbv_buffer_init / 8);
+ pv->param.rc.vbv_buffer_init / 8);
}
pv->param.videoParam->mfx.BufferSizeInKB = (pv->param.rc.vbv_buffer_size / 8);
}
return -1;
}
}
+ switch (videoParam.mfx.FrameInfo.PicStruct)
+ {
+ case MFX_PICSTRUCT_PROGRESSIVE:
+ hb_log("encqsvInit: PicStruct progressive");
+ break;
+ case MFX_PICSTRUCT_FIELD_TFF:
+ hb_log("encqsvInit: PicStruct top field first");
+ break;
+ case MFX_PICSTRUCT_FIELD_BFF:
+ hb_log("encqsvInit: PicStruct bottom field first");
+ break;
+ default:
+ hb_error("encqsvInit: invalid PicStruct value 0x%"PRIx16"",
+ videoParam.mfx.FrameInfo.PicStruct);
+ return -1;
+ }
const char *cavlc, *rdopt;
switch (option1->CAVLC)
{
// don't let 'work_loop' put a chapter mark on the wrong buffer
in->s.new_chap = 0;
}
+
+ /*
+ * If interlaced encoding is requested during encoder initialization,
+ * but the input mfxFrameSurface1 is flagged as progressive here,
+ * the output bitstream will be progressive (according to MediaInfo).
+ *
+ * Assume the user knows what he's doing (say he is e.g. encoding a
+ * progressive-flagged source using interlaced compression - he may
+ * well have a good reason to do so; mis-flagged sources do exist).
+ */
+ work_surface->Info.PicStruct = pv->enc_space.m_mfxVideoParam.mfx.FrameInfo.PicStruct;
}
else{
work_surface = NULL;
if(!qsv->dec_space || !qsv->dec_space->is_init_done) return 2;
+ // we need to know final output settings before we can properly configure
+ if (!pv->job->qsv_enc_info.is_init_done)
+ {
+ return 2;
+ }
+
av_qsv_add_context_usage(qsv,HAVE_THREADS);
// see params needed like at mediasdk-man.pdf:"Appendix A: Configuration Parameter Constraints"
av_qsv_space *qsv_vpp = pv->vpp_space;
AV_QSV_ZERO_MEMORY(qsv_vpp->m_mfxVideoParam);
+ if (pv->deinterlace)
+ {
+ /*
+ * Input may be progressive, interlaced or even mixed, so init with
+ * MFX_PICSTRUCT_UNKNOWN and use per-frame field order information
+ * (mfxFrameSurface1.Info.PicStruct)
+ */
+ qsv_vpp->m_mfxVideoParam.vpp.In.PicStruct = MFX_PICSTRUCT_UNKNOWN;
+ qsv_vpp->m_mfxVideoParam.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
+ }
+ else
+ {
+ /* Same PicStruct in/out: no filtering */
+ qsv_vpp->m_mfxVideoParam.vpp.In.PicStruct = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.PicStruct;
+ qsv_vpp->m_mfxVideoParam.vpp.Out.PicStruct = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.PicStruct;
+ }
+
// FrameRate is important for VPP to start with
if( qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.FrameRateExtN == 0 &&
qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.FrameRateExtD == 0 ){
qsv_vpp->m_mfxVideoParam.vpp.In.ChromaFormat = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.ChromaFormat;
qsv_vpp->m_mfxVideoParam.vpp.In.CropX = pv->crop[2];
qsv_vpp->m_mfxVideoParam.vpp.In.CropY = pv->crop[0];
- qsv_vpp->m_mfxVideoParam.vpp.In.CropW = pv->width_in - pv->crop[3] - pv->crop[2];
+ qsv_vpp->m_mfxVideoParam.vpp.In.CropW = pv-> width_in - pv->crop[3] - pv->crop[2];
qsv_vpp->m_mfxVideoParam.vpp.In.CropH = pv->height_in - pv->crop[1] - pv->crop[0];
- qsv_vpp->m_mfxVideoParam.vpp.In.PicStruct = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.PicStruct;
qsv_vpp->m_mfxVideoParam.vpp.In.FrameRateExtN = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.FrameRateExtN;
qsv_vpp->m_mfxVideoParam.vpp.In.FrameRateExtD = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.FrameRateExtD;
qsv_vpp->m_mfxVideoParam.vpp.In.AspectRatioW = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.AspectRatioW;
qsv_vpp->m_mfxVideoParam.vpp.In.AspectRatioH = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.AspectRatioH;
- qsv_vpp->m_mfxVideoParam.vpp.In.Width = AV_QSV_ALIGN16(pv->width_in);
- qsv_vpp->m_mfxVideoParam.vpp.In.Height = (MFX_PICSTRUCT_PROGRESSIVE == qsv_vpp->m_mfxVideoParam.vpp.In.PicStruct)?
- AV_QSV_ALIGN16(pv->height_in) : AV_QSV_ALIGN32(pv->height_in);
+ qsv_vpp->m_mfxVideoParam.vpp.In.Width = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.Width;
+ qsv_vpp->m_mfxVideoParam.vpp.In.Height = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.Height;
qsv_vpp->m_mfxVideoParam.vpp.Out.FourCC = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.FourCC;
qsv_vpp->m_mfxVideoParam.vpp.Out.ChromaFormat = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.ChromaFormat;
qsv_vpp->m_mfxVideoParam.vpp.Out.CropY = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.CropY;
qsv_vpp->m_mfxVideoParam.vpp.Out.CropW = pv->width_out;
qsv_vpp->m_mfxVideoParam.vpp.Out.CropH = pv->height_out;
- qsv_vpp->m_mfxVideoParam.vpp.Out.PicStruct = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.PicStruct;
qsv_vpp->m_mfxVideoParam.vpp.Out.FrameRateExtN = pv->job->vrate;
qsv_vpp->m_mfxVideoParam.vpp.Out.FrameRateExtD = pv->job->vrate_base;
qsv_vpp->m_mfxVideoParam.vpp.Out.AspectRatioW = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.AspectRatioW;
qsv_vpp->m_mfxVideoParam.vpp.Out.AspectRatioH = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.AspectRatioH;
- qsv_vpp->m_mfxVideoParam.vpp.Out.Width = AV_QSV_ALIGN16(pv->width_out);
- qsv_vpp->m_mfxVideoParam.vpp.Out.Height = (MFX_PICSTRUCT_PROGRESSIVE == qsv_vpp->m_mfxVideoParam.vpp.Out.PicStruct)?
- AV_QSV_ALIGN16(pv->height_out) : AV_QSV_ALIGN32(pv->height_out);
+ qsv_vpp->m_mfxVideoParam.vpp.Out.Width = pv->job->qsv_enc_info.align_width;
+ qsv_vpp->m_mfxVideoParam.vpp.Out.Height = pv->job->qsv_enc_info.align_height;
qsv_vpp->m_mfxVideoParam.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
qsv_vpp->p_ext_params[1] = (mfxExtBuffer*)&pv->frc_config;
}
- if (pv->deinterlace)
- {
- qsv_vpp->m_mfxVideoParam.vpp.In.PicStruct = qsv->dec_space->m_mfxVideoParam.mfx.FrameInfo.PicStruct;
- qsv_vpp->m_mfxVideoParam.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
- }
sts = MFXVideoVPP_Init(qsv->mfx_session, &qsv_vpp->m_mfxVideoParam);
AV_QSV_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);