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.
3058 Discussions

problem when retrieving buffered encoded frames (MFX_ERR_NOT_ENOUGH_BUFFER)

jwregme
Beginner
334 Views

I'm testing my live video encoding with simulated video streams. The frames that are passed for encoding are already in NV12 format.
With a 1280x1024 stream I had no issues at all. However, with a 512x512 stream I encountered a very weird issue...

The encoding works absolutely fine if I keep the amount of frames for encoding to about 35'000. If I encode more frames (40'000+) I get an error while retrieving buffered encoded frames when finishing the encoding. With the 1280x1024 stream I can encode 130k+ without any problems...

The error (MFX_ERR_NOT_ENOUGH_BUFFER) is returned in the second MSDK_CHECK_RESULT after the while loop in the following code:

[cpp]

// retrieve the buffered encoded frames
while (MFX_ERR_NONE <= context->sts)
{   
   for (;;)
   { 

      // Encode a frame asychronously (returns immediately)
      context->sts = context->mfxVideoENC->EncodeFrameAsync(NULL, NULL, &context->mfxBS, &context->syncp);

      if (MFX_ERR_NONE < context->sts && !context->syncp) // Repeat the call if warning and no output
      {
         if (MFX_WRN_DEVICE_BUSY == context->sts)
            Sleep(1); // Wait if device is busy, then repeat the same call
         }
         else if (MFX_ERR_NONE < context->sts && context->syncp)
         {
            context->sts = MFX_ERR_NONE; // Ignore warnings if output is available
            break;
         }
         else
            break;
   }

   if(MFX_ERR_NONE == context->sts)
   {
       context->sts = context->mfxVideoSession.SyncOperation(context->syncp, 60000); // Synchronize. Wait until encoded frame is ready
       MSDK_CHECK_RESULT(context->sts, MFX_ERR_NONE, context->sts);

      context->sts = WriteBitStreamFrame(&context->mfxBS, context->fSink);
       MSDK_BREAK_ON_ERROR(context->sts);
    }
}

// MFX_ERR_MORE_DATA indicates that there are no more buffered frames, exit in case of other errors
MSDK_IGNORE_MFX_STS(context->sts, MFX_ERR_MORE_DATA);
MSDK_CHECK_RESULT(context->sts, MFX_ERR_NONE, context->sts);

// Clean up resources

context->mfxVideoENC->Close();
// mfxSession closed automatically on destruction

for (int i = 0; i < context->nEncSurfNum; i++)
   delete context->pEncSurfaces;
MSDK_SAFE_DELETE_ARRAY(context->pEncSurfaces);
MSDK_SAFE_DELETE_ARRAY(context->mfxBS.Data);

fclose(context->fSink);

return MFX_ERR_NONE;

[/cpp]

The number of allocated buffers is 3 (as suggested by IMSDK) and software implementation 1.6 is used. If the encoding succeeds I can see that WriteBitStreamFrame is called twice (so 2 buffered encoded frames are retrieved), however when the error occurs WriteBitStreamFrame is never called.

Here's the code for setting up the encoder:

[cpp]

mfxEncParams.mfx.CodecId = MFX_CODEC_AVC;
mfxEncParams.mfx.TargetUsage = BALANCED;
mfxEncParams.mfx.TargetKbps = 2000;
mfxEncParams.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
mfxEncParams.mfx.FrameInfo.FrameRateExtN = 10;
mfxEncParams.mfx.FrameInfo.FrameRateExtD = 1;
mfxEncParams.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
mfxEncParams.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
mfxEncParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
mfxEncParams.mfx.FrameInfo.CropX = 0;
mfxEncParams.mfx.FrameInfo.CropY = 0;
mfxEncParams.mfx.FrameInfo.CropW = inputWidth;
mfxEncParams.mfx.FrameInfo.CropH = inputHeight;
mfxEncParams.mfx.FrameInfo.Width = MSDK_ALIGN16(inputWidth);
mfxEncParams.mfx.FrameInfo.Height = (MFX_PICSTRUCT_PROGRESSIVE == mfxEncParams.mfx.FrameInfo.PicStruct)?
MSDK_ALIGN16(inputHeight) : MSDK_ALIGN32(inputHeight);

mfxEncParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;

mfxEncParams.mfx.GopOptFlag = MFX_GOP_STRICT; // strictly follow the GOP structure
mfxEncParams.mfx.IdrInterval = 0; // every I-Frame is an IDR-Frame (vital for jumping within video)
mfxEncParams.mfx.GopPicSize = 12; // group of pictures (GOP) size
mfxEncParams.mfx.GopRefDist = 3; // every third frame is a P-Frame

[/cpp]

I'm a bit confused that the error MFX_ERR_NOT_ENOUGH_BUFFER occurs at the very end. Also it is peculiar that the error depends on the number of frames that are passed to the encoder.
I believe a simple way to fix this problem is to simply clean up the encoder after this error happens (so the file handle gets closed). This way I still have the encoded stream, even though with a few frames missing. However, I'd like to find out what the problem is to ensure that I will not encounter further problems when encoding other video streams. (simply allocating more buffers will not give me more insight into the problem either)

I'd appreciate any help and would like to thank you in advance for providing me with some ideas! 

0 Kudos
1 Reply
Petter_L_Intel
Employee
334 Views

Hi,

From the error code status it looks like you do not have enough space in the bitstream buffer (mfxBS) to store the encoded frame. Make sure the allocated size is enough to store individual compressed frames. Based on how you have implemented bitstream buffer you may also have also run into DataOffset "drift". If you store data using the offset, then make sure the offset does not prevent you from storing enough data.

Regards,
Petter 

0 Kudos
Reply