IDXGIOutputDuplication::AcquireNextFrame no return

Mingkun Ma 1 Reputation point
2021-12-08T03:39:54.533+00:00

System Version: Win10

Describe:
Hello, I have a problem, I create a new IDXGIOutputDuplication object on the main thread, and then call IDXGIOutputDuplication::AcquireNextFrame in a separate thread. Before each call, it will ReleaseFrame, but after receiving the first few frames, IDXGIOutputDuplication::AcquireNextFrame does not return a value and keeps blocking, like a deadlock.

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,523 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Xiaopo Yang - MSFT 12,231 Reputation points Microsoft Vendor
    2021-12-08T06:24:51.18+00:00

    I cannot reproduce the problem based on the screen_capture sample. The following is my test procedure. Or Could you please show a minimal, reproducible sample without private information?

    /* -*-c++-*-
    
       Experimenting with the ScreenCapture using a Win8 Window. 
       ---------------------------------------------------------
    
       This file contains a test where we use the 'ScreenCapture' API
       to enable screencapturing and create a Windows SDK based window.
       This test was created so we can inspect the D3D11 context using 
       e.g. RenderDoc. It seems that the test in 'test_api.cpp' makes
       RenderDoc crash; propably because it's a pure console app. 
    
    
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <windows.h>
    #include <screencapture/ScreenCapture.h>
    
    /* ------------------------------------------------------------------------------------------------ */
    static void frame_callback(sc::PixelBuffer& buf);
    LRESULT CALLBACK WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
    static bool quit = false;
    DWORD WINAPI MyThreadFunction(LPVOID lpParam)
    {
        sc::ScreenCapture* capture = (sc::ScreenCapture*)lpParam;
        while (!quit)
        {
            capture->update();
        }
        return 0;
    }
    /* ------------------------------------------------------------------------------------------------ */
    
    int WINAPI WinMain(HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int nCmdShow)  
    {
    
      HWND wnd;
      WNDCLASSEX wc;
    
      /* Define our window props. */
      ZeroMemory(&wc, sizeof(wc));
    
      wc.cbSize = sizeof(wc);
      wc.style = CS_HREDRAW | CS_VREDRAW;
      wc.lpfnWndProc = WindowProc;
      wc.hInstance = hInstance;
      wc.hCursor = LoadCursor(NULL, IDC_ARROW);
      wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
      wc.lpszClassName = TEXT("WindowClass1");
    
      RegisterClassEx(&wc);
    
      /* 
         We use 'AdjustWindowRect' to make sure that the 
         client size will be what we requested. The windows (including
         the border may be a bit bigger).
      */
      RECT wr = { 0, 0, 800, 600 };
      AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
    
      /* Create the window. */
      wnd = CreateWindowEx(NULL,
          TEXT("WindowClass1"),                            /* Name of the window class. */
          TEXT("Windows 8.1 based Screen Capure"),         /* Title. */
                           WS_OVERLAPPEDWINDOW,                       /* Window style. */
                           10,                                        /* X position. */
                           10,                                        /* Y position. */
                           wr.right - wr.left,                        /* Width. */
                           wr.bottom - wr.top,                        /* Height. */
                           NULL,                                      /* Parent window. */
                           NULL,                                      /* No menus. */
                           hInstance,                                 /* Application handle. */
                           NULL);                                     /* Multiple windows. */
    
      /* And show it! */
      ShowWindow(wnd, nCmdShow);
    
      /* Init the screen capture. */
      sc::ScreenCapture capture(frame_callback);
      sc::Settings settings;
    
      settings.pixel_format = SC_BGRA;
      settings.display = 0;
      settings.output_width = 1280;
      settings.output_height = 720;
    
      if (0 != capture.init()) {
        exit(EXIT_FAILURE);
      }
    
      if (0 != capture.configure(settings)) {
        exit(EXIT_FAILURE);
      }
    
      if (0 != capture.start()) {
        exit(EXIT_FAILURE);
      }
    
      HANDLE h = CreateThread(
          NULL,                   // default security attributes
          0,                      // use default stack size  
          MyThreadFunction,       // thread function name
          (LPVOID)&capture,          // argument to thread function 
          0,                      // use default creation flags 
          NULL);   // returns the thread identifier 
    
      /* Main loop. */
      MSG msg;
      while (true) { 
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
          TranslateMessage(&msg); /* Translates keystroke messages into the right format */
          DispatchMessage(&msg);  /* Sends the messages to the WindProc function. */
          if (WM_QUIT == msg.message) {
              quit = true;
              break;
          }
        }
        //capture.update();    
        //    renderFrame();
      }
    
      WaitForSingleObject(h, INFINITE);
    
      capture.shutdown();
    
      return 0;
    }
    
    LRESULT CALLBACK WindowProc(HWND wnd,
                                UINT message, 
                                WPARAM wparam,
                                LPARAM lparam)
    {
      switch (message) {
        case WM_DESTROY: {
          PostQuitMessage(0);
          return 0;
        }
        default: {
          printf("Warning: unhandled message %u\n", message);
          break;
        }
      }
    
      /* Pass on messages we didn't handle. */
      return DefWindowProc(wnd, message, wparam, lparam);
    }
    
    static void frame_callback(sc::PixelBuffer& buf) {
    
      printf("Got frame!\n");
    }