On 2020-08-05 9:07, Steve Lhomme wrote:
When used aggressively, calling SubmitDecoderBuffers() just after
ReleaseDecoderBuffer() may have the buffers not used properly and created

*creates

decoding artifacts.
It's likely due to the time to copy the submitted buffer in CPU mapped memory
to GPU memory. SubmitDecoderBuffers() doesn't appear to wait for the state
of the buffer submitted to become "ready".

I noticed this behaviour on a 48 threads machine. In VLC we use a lot of threads for lavc, even with D3D11. And the more threads I added, the more artifacts I got. Adding this code solved the issue. The decoder is now guaranteed to have all the buffers in the GPU when submitting them for decoding.

For now it's not supported in the legacy API using AVD3D11VAContext, we need to
add a ID3D11DeviceContext in there as it cannot be derived from the other
interfaces we provide (ID3D11VideoContext is not a kind of ID3D11DeviceContext).
---
  libavcodec/dxva2.c          | 32 ++++++++++++++++++++++++++++++++
  libavcodec/dxva2_internal.h |  2 ++
  2 files changed, 34 insertions(+)

diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index 32416112bf..dbbad8ed00 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -692,6 +692,12 @@ int ff_dxva2_decode_init(AVCodecContext *avctx)
          d3d11_ctx->surface       = sctx->d3d11_views;
          d3d11_ctx->workaround    = sctx->workaround;
          d3d11_ctx->context_mutex = INVALID_HANDLE_VALUE;
+
+        D3D11_QUERY_DESC query = { 0 };
+        query.Query = D3D11_QUERY_EVENT;
+        if (FAILED(ID3D11Device_CreateQuery(device_hwctx->device, &query,
+                                            
(ID3D11Query**)&sctx->wait_copies)))
+            sctx->wait_copies = NULL;
      }
  #endif
@@ -729,6 +735,8 @@ int ff_dxva2_decode_uninit(AVCodecContext *avctx)
      av_buffer_unref(&sctx->decoder_ref);
#if CONFIG_D3D11VA
+    if (sctx->wait_copies)
+        ID3D11Asynchronous_Release(sctx->wait_copies);
      for (i = 0; i < sctx->nb_d3d11_views; i++) {
          if (sctx->d3d11_views[i])
              ID3D11VideoDecoderOutputView_Release(sctx->d3d11_views[i]);
@@ -932,6 +940,13 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, 
AVFrame *frame,
#if CONFIG_D3D11VA
      if (ff_dxva2_is_d3d11(avctx)) {
+        if (sctx->wait_copies)
+        {
+            AVHWFramesContext *frames_ctx = 
(AVHWFramesContext*)avctx->hw_frames_ctx->data;
+            AVD3D11VADeviceContext *device_hwctx = 
frames_ctx->device_ctx->hwctx;
+            ID3D11DeviceContext_Begin(device_hwctx->device_context, 
sctx->wait_copies);
+        }
+
          buffer = &buffer11[buffer_count];
          type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
      }
@@ -1005,9 +1020,26 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, 
AVFrame *frame,
#if CONFIG_D3D11VA
      if (ff_dxva2_is_d3d11(avctx))
+    {
+        int maxWait = 10;
+        /* wait until all the buffer release is done copying data to the GPU
+         * before doing the submit command */
+        if (sctx->wait_copies)
+        {
+            AVHWFramesContext *frames_ctx = 
(AVHWFramesContext*)avctx->hw_frames_ctx->data;
+            AVD3D11VADeviceContext *device_hwctx = 
frames_ctx->device_ctx->hwctx;
+            ID3D11DeviceContext_End(device_hwctx->device_context, 
sctx->wait_copies);
+
+            while (maxWait-- && S_FALSE ==
+                   ID3D11DeviceContext_GetData(device_hwctx->device_context,
+                                               sctx->wait_copies, NULL, 0, 0))
+                SleepEx(2, TRUE);

And just as I submit this I realize it should be unlocking the device context while waiting.

+        }
+
          hr = 
ID3D11VideoContext_SubmitDecoderBuffers(D3D11VA_CONTEXT(ctx)->video_context,
                                                       
D3D11VA_CONTEXT(ctx)->decoder,
                                                       buffer_count, buffer11);
+    }
  #endif
  #if CONFIG_DXVA2
      if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h
index b822af59cd..c44e8e09b0 100644
--- a/libavcodec/dxva2_internal.h
+++ b/libavcodec/dxva2_internal.h
@@ -81,6 +81,8 @@ typedef struct FFDXVASharedContext {
      ID3D11VideoDecoderOutputView  **d3d11_views;
      int                          nb_d3d11_views;
      ID3D11Texture2D                *d3d11_texture;
+
+    ID3D11Asynchronous             *wait_copies;
  #endif
#if CONFIG_DXVA2
--
2.26.2

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to