Media (Intel® Video Processing Library, Intel Media SDK)
Access community support with transcoding, decoding, and encoding in applications using media tools like Intel® oneAPI Video Processing Library and Intel® Media SDK
Announcements
The Intel Media SDK project is no longer active. For continued support and access to new features, Intel Media SDK users are encouraged to read the transition guide on upgrading from Intel® Media SDK to Intel® Video Processing Library (VPL), and to move to VPL as soon as possible.
For more information, see the VPL website.

MFX_PICSTRUCT_FIELD_TFF breaks my encoder

cedronius__anders
New Contributor I
1,004 Views

Hi,

I'm trying to initialise my encoder for field/interlace encoding. The only parameter I change is PicStruct from MFX_PICSTRUCT_PROGRESSIVE to MFX_PICSTRUCT_FIELD_TFF, however doing that results in mfxENC->Query returning MFX_WRN_INCOMPATIBLE_VIDEO_PARAM. But setting the PicStruct to progressive works just fine.

What apart from setting PicStruct to MFX_PICSTRUCT_FIELD_TFF do I need to configure for QSV to accept my settings?

Is there a simpler way of setting the parameters, or any helper methods that I can use?..

See my code below and thanks for helping.

 

/Anders

 

 // Initialize encoder parameters
    mfxVideoParam mfxEncParams;
    memset(&mfxEncParams, 0, sizeof (mfxEncParams));
    if (encParamFieldCount == 1) {
        mfxEncParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
    } else if (encParamFieldCount == 2) {
        mfxEncParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF;
    } else {
        std::cout << "Failed init.. Encoding field structure unknown." << std::endl;
        return;
    }
    mfxU16 adjustedVideoWidth = MSDK_ALIGN16(videoWidth);
    mfxU16 adjustedVideoHeight = (MFX_PICSTRUCT_PROGRESSIVE == mfxEncParams.mfx.FrameInfo.PicStruct) ? MSDK_ALIGN16(videoHeight) : MSDK_ALIGN32(videoHeight);
    mfxEncParams.mfx.FrameInfo.Width = adjustedVideoWidth;
    mfxEncParams.mfx.FrameInfo.Height = adjustedVideoHeight;
    mfxEncParams.mfx.CodecId = MFX_CODEC_AVC;
    mfxEncParams.mfx.CodecProfile = MFX_PROFILE_AVC_HIGH;
    mfxEncParams.mfx.CodecLevel = MFX_LEVEL_AVC_42;
    mfxEncParams.mfx.GopPicSize = videoFPS;
    mfxEncParams.mfx.GopRefDist = 1; //I and P frames only
    mfxEncParams.mfx.TargetUsage = MFX_TARGETUSAGE_BEST_SPEED; //TODO test quality and see if speed is at all changed
    mfxEncParams.mfx.TargetKbps = 4000;
    mfxEncParams.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
    mfxEncParams.mfx.FrameInfo.FrameRateExtN = videoFPS;
    mfxEncParams.mfx.FrameInfo.FrameRateExtD = 1;
    mfxEncParams.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
    mfxEncParams.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
    mfxEncParams.mfx.FrameInfo.CropX = 0;
    mfxEncParams.mfx.FrameInfo.CropY = 0;
    mfxEncParams.mfx.FrameInfo.CropW = videoWidth;
    mfxEncParams.mfx.FrameInfo.CropH = videoHeight;
    mfxEncParams.mfx.FrameInfo.BitDepthLuma = 8;
    mfxEncParams.mfx.FrameInfo.BitDepthChroma = 8;
    mfxEncParams.mfx.FrameInfo.Shift = 0;
    
    mfxEncParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
    mfxEncParams.AsyncDepth = 1;

    mfxExtCodingOption extendedCodingOptions;
    memset(&extendedCodingOptions, 0, sizeof (extendedCodingOptions));
    extendedCodingOptions.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
    extendedCodingOptions.Header.BufferSz = sizeof (extendedCodingOptions);
    extendedCodingOptions.MaxDecFrameBuffering = 1;
    mfxExtBuffer * extendedBuffers[1];
    extendedBuffers[0] = (mfxExtBuffer*) & extendedCodingOptions;
    mfxEncParams.ExtParam = extendedBuffers;
    mfxEncParams.NumExtParam = 1;

    // Create Media SDK encoder
    // MFXVideoENCODE* mfxENC = new MFXVideoENCODE(mfxSES);

    mfxENC = std::shared_ptr<MFXVideoENCODE>(new MFXVideoENCODE(mfxSES));
    if (mfxENC == nullptr) {
        std::cout << "Creating a MFXVideoENCODE returned nullptr." << std::endl;
        return;
    }
    std::cout << "QSV Video encoder created." << std::endl;

    //Probe to see if the encoder parameters are valid
    sts = mfxENC->Query(&mfxEncParams, &mfxEncParams);
    if (sts != MFX_ERR_NONE) {
        std::cout << __LINE__ << ": QSV Got error " << sts << std::endl;
        return;
    }
    std::cout << "QSV Video encoder accepted encoding parameters." << std::endl;

 

0 Kudos
1 Reply
Dmitry_E_Intel
Employee
1,004 Views

Hi Anders,

 

This is expected. Table A-4 of AVC spec says that for levels >=4.2 frame_mbs_only flag must be 1, on other words levels >=4.2 don't support interlace encode (without spec violation of course) . 
If app specifies level 4.2, MSDK detects incompatibility and forces PicStruct to MFX_PICSTRUCT_PROGRESSIVE to give a priority to the level, not to PicStruct. 
If application didn't specify particular level (4.2 in our case), then MSDK would calculate minimal possible level from Init params and would encode steam as interlace.

https://github.com/Intel-Media-SDK/MediaSDK/blob/1e7b8c287346065a31da94fa500bd18af70d988b/_studio/mfx_lib/shared/src/mfx_h264_enc_common_hw.cpp#L1912

 

Regards,

Dmitry

0 Kudos
Reply