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

HEVC encoding SyncOperation MFX_ERR_NOT_ENOUGH_BUFFER

sverdlov__andrey
888 Views

Hello

I'm trying to figure out why my HEVC encoder fails to convert 4K input video frames. There is no problem with 720p or 1080p encoding. But once I tried to encode the 4K video(big buck bunny 2160p 30 fps) in Release configuration it fails in this way: process starts, successully encodes part of the input video(5-20% of the total video duration) and then fails with error. This is the Release build, so I checked the SDK tracer generated logs. The SyncOperation returned the MFX_ERR_NOT_ENOUGH_BUFFER error code. According to docs(http://kavi.hotar.ru/system/files/private/media_server_studio_sdk_release_notes.pdf pages 17 and 18) MFX_ERR_NOT_ENOUGH_BUFFER is a possible error for HEVC encoding case. The buffer size is computed as in the tutorial:

const size_t uTaskMaxDataLength = selectedParameters.mfx.BufferSizeInKB * 1000;

I decided to increase the task data and multiplied it by 2000, so the task data became 2 times larger. With this change the problem has gone.

So, to avoid memory consumption, this should be OK to allocate larger buffer when error occured and try to Sync one more time. So, I've implemented this logic:

            status = pSession->SyncOperation(pTask->syncPoint, 60000); // Synchronize. Wait until encoded frame is ready

            // Handle Buffer size error first. In this case we need to allocate larger buffer and try again
            while (status == MFX_ERR_NOT_ENOUGH_BUFFER) {
               if (!AllocateLargerBufferForTask(*pTask)) return false;
               // Try to encode the frame again with new allocated buufer
               status = pSession->SyncOperation(pTask->syncPoint, 60000);
            }

bool AllocateLargerBufferForTask(LMFXTask& task)
{
   const uint32_t uNewBufferSize = task.saData.GetSize() * 3 / 2;
   task.saData.SetArrayCapacityLarge(uNewBufferSize);
   if (!task.saData.IsValid()) {
      LFDEBUG("Can't allocate enough memory for task");
      return false;
   }
   task.saData.SetSize(uNewBufferSize);
   // Update the bitstream members with new buffer size and data pointer
   task.mfxBS.MaxLength = uNewBufferSize;
   task.mfxBS.Data = task.saData.get();
   return true;
}

You can see the buffer would be increased until it would have enough size to get the bitstream data. But the problem it didn't worked. So, I can't handle the error and try to increase the buffer size. Also, I'm unable to compute the buffer size in the beginning, because there is no guarantee that the multiplication by 2000 instead of 1000 would never fail with the same bug. Also multiplication by 2000 consumes additional memory per each task(I set the async depth to 4).

Could you provide any advice how to solve this issue ? The logic

if (codec == HEVC) taskDataSize *= 2;

Looks wrong and I don't like to use it in the code.

Logs:

 

18552 2019-11-22 11:13:3:362 function: MFXVideoCORE_SyncOperation(mfxSession session=0118E488, mfxSyncPoint syncp=000CE400, mfxU32 wait=60000) +
18552 2019-11-22 11:13:3:362     mfxSession session=0AAD714C
18552 2019-11-22 11:13:3:362     mfxSyncPoint* syncp=000CE400
18552 2019-11-22 11:13:3:362     mfxU32 wait=60000
18552 2019-11-22 11:13:3:364 >> MFXVideoCORE_SyncOperation called
18552 2019-11-22 11:13:3:364     mfxSession session=0AAD714C
18552 2019-11-22 11:13:3:364     mfxSyncPoint* syncp=000CE400
18552 2019-11-22 11:13:3:364     mfxU32 wait=60000
18552 2019-11-22 11:13:3:364 function: MFXVideoCORE_SyncOperation(1.4252 msec, status=MFX_ERR_NONE) - 


18552 2019-11-22 11:13:3:368 function: MFXVideoENCODE_EncodeFrameAsync(mfxSession session=0118E488, mfxEncodeCtrl *ctrl=00000000, mfxFrameSurface1 *surface=0A8B6878, mfxBitstream *bs=0AAD76C0, mfxSyncPoint *syncp=0AAD7700) +
18552 2019-11-22 11:13:3:368     mfxSession session=0AAD714C

...

18552 2019-11-22 11:13:3:371     mfxSyncPoint* syncp=000CF400
18552 2019-11-22 11:13:3:371 function: MFXVideoENCODE_EncodeFrameAsync(0.028 msec, status=MFX_ERR_NONE) - 


18552 2019-11-22 11:13:3:383 function: MFXVideoCORE_SyncOperation(mfxSession session=0118E488, mfxSyncPoint syncp=000CE803, mfxU32 wait=60000) +
18552 2019-11-22 11:13:3:383     mfxSession session=0AAD714C
18552 2019-11-22 11:13:3:383     mfxSyncPoint* syncp=000CE803
18552 2019-11-22 11:13:3:384     mfxU32 wait=60000
18552 2019-11-22 11:13:3:408 >> MFXVideoCORE_SyncOperation called
18552 2019-11-22 11:13:3:408     mfxSession session=0AAD714C
18552 2019-11-22 11:13:3:409     mfxSyncPoint* syncp=000CE803
18552 2019-11-22 11:13:3:409     mfxU32 wait=60000
18552 2019-11-22 11:13:3:409 function: MFXVideoCORE_SyncOperation(24.7706 msec, status=MFX_ERR_NOT_ENOUGH_BUFFER) - 

0 Kudos
1 Solution
sverdlov__andrey
888 Views

Hello

I've created the YUV input file from the H264 video with ffmpeg and used simple_encode_hevc10 tutorial(changed 10 bit settings to 8 bit) and encoding succeeded.

Also, The problem is not reproducible after I set the GOP options. So, I think the problem is solved. Thanks!

View solution in original post

0 Kudos
4 Replies
Mark_L_Intel1
Moderator
888 Views

Hi Andrey,

Could you run sampe_encode with this input stream and check if it has the same error?

https://github.com/Intel-Media-SDK/MediaSDK/tree/master/samples

If sample_encode works, you can check if simple_3_encode in our tutorial works; by default, it was coded as H.264, you can change it to HEVC for your input.

https://github.com/Intel-Media-SDK/MediaSDK/tree/master/tutorials

If the tutorial works, you can copy this code to yours.

Mark

0 Kudos
sverdlov__andrey
888 Views

Hello

No, I can't check sample_encode tutorial, because it takes raw YUV input stream and I have an input h264 video. Is it possible to get the YUV stream from the H264 encoded video ?

Also, I'm using async encoding with async depth = 4 + video memory. and the sample_encode uses system memory without async mode.

Anyway, I took the sample_encode as a reference to start implementing the encoder. The encoder works fine with AVC for any input video(720p, 1080p or 4K). But for HEVC encoder, 4K input video and task buffer size == BufferSizeInKB * 1000 I got this problem. No issue for Hevc and 4K input video in case task buffer size == BufferSizeInKB * 1000 * 2.

0 Kudos
sverdlov__andrey
889 Views

Hello

I've created the YUV input file from the H264 video with ffmpeg and used simple_encode_hevc10 tutorial(changed 10 bit settings to 8 bit) and encoding succeeded.

Also, The problem is not reproducible after I set the GOP options. So, I think the problem is solved. Thanks!

0 Kudos
Mark_L_Intel1
Moderator
888 Views

Hi Andrey,

Thanks so much for the update and apologized for not responding.

It looks like our documents is good enough to solve the problem but might not organized very well. If you agree, could you give us some suggestions?

Mark

0 Kudos
Reply