webrtc - Desktop duplication (DirectX) screen capture fails to give screen updates -


i'm working on application capture screen through desktop duplication apis (using directx 11) (only diff previous screen update) , render on window (the viewer might running on machine connected via lan). code improved version of sample provided in msdn. works fine except device did not give screen update though there 1 times in mid, happens around 10% of time on machines (mostly on windows 8/8.1 machines , on windows 10 machines). tried possible ways sort out problem. reduced number of device resets, provided me reliable output not work fine 100%.

the device fails provide initial screen (a full screen) times (this happens 60% of time on windows operating systems desktop duplication supported), came work around retried initial update device until provides 1 resulted in multiple issues, device might not give initial screen ever.

i have invested weeks of efforts fix problem did not figure out proper solution , there no forums know discusses these kind of issues. appreciated.

below code screen diff previous one, init device, populating adapters , monitors.

please bear me long code snippet, in advance.

to screen update:

int getchangedregions(int timeout, rectangles &dirtyrects, std::vector <move_rect> &moverects, uint &rect_count, rect screenrect) { uint diffarea           = 0; frame_data currentframedata;  bool istimeout          = false;  try {      m_lasterrorcode = m_duplicationmanager.getframe(&currentframedata, timeout, &istimeout);      if(succeeded(m_lasterrorcode) && (!istimeout))     {         if(currentframedata.frameinfo.totalmetadatabuffersize)         {              m_currentframetexture = currentframedata.frame;              if(currentframedata.movecount)             {                 dxgi_outdupl_move_rect* moverectarray = reinterpret_cast<dxgi_outdupl_move_rect*> (currentframedata.metadata);                  if (moverectarray)                 {                     for(uint index = 0; index < currentframedata.movecount; index++)                     {                         //webrtc                         // directx capturer api may randomly return unmoved move_rects, should                         // skipped avoid unnecessary wasting of differing , encoding                         // resources.                         // using testing application it2me_standalone_host_main, check                         // reduces average capture time 0.375% (4.07 -> 4.055), , average                         // encode time 0.313% (8.042 -> 8.016) without other impacts.                          if (moverectarray[index].sourcepoint.x != moverectarray[index].destinationrect.left || moverectarray[index].sourcepoint.y != moverectarray[index].destinationrect.top)                          {                              if(m_used3d11bitmapconversion)                             {                                 move_rect moverect;                                  moverect.sourcepoint.x =  moverectarray[index].sourcepoint.x * m_imagescalingfactor;                                 moverect.sourcepoint.y =  moverectarray[index].sourcepoint.y * m_imagescalingfactor;                                  moverect.destinationrect.left = moverectarray[index].destinationrect.left * m_imagescalingfactor;                                 moverect.destinationrect.top = moverectarray[index].destinationrect.top * m_imagescalingfactor;                                 moverect.destinationrect.bottom = moverectarray[index].destinationrect.bottom * m_imagescalingfactor;                                 moverect.destinationrect.right = moverectarray[index].destinationrect.right * m_imagescalingfactor;                                  moverects.push_back(moverect);                                 diffarea += abs((moverect.destinationrect.right - moverect.destinationrect.left) *                                          (moverect.destinationrect.bottom - moverect.destinationrect.top));                             }                             else                             {                                 moverects.push_back(moverectarray[index]);                                 diffarea += abs((moverectarray[index].destinationrect.right - moverectarray[index].destinationrect.left) *                                          (moverectarray[index].destinationrect.bottom - moverectarray[index].destinationrect.top));                             }                         }                     }                 }                 else                 {                     return -1;                 }             }              if(currentframedata.dirtycount)             {                 rect* dirtyrectarray = reinterpret_cast<rect*> (currentframedata.metadata + (currentframedata.movecount * sizeof(dxgi_outdupl_move_rect)));                  if (!dirtyrectarray)                 {                     return -1;                 }                  rect_count = currentframedata.dirtycount;                  for(uint index = 0; index < rect_count; index ++)                 {                      if(m_used3d11bitmapconversion)                     {                         rect dirtyrect;                          dirtyrect.bottom = dirtyrectarray[index].bottom * m_imagescalingfactor;                         dirtyrect.top = dirtyrectarray[index].top * m_imagescalingfactor;                         dirtyrect.left = dirtyrectarray[index].left * m_imagescalingfactor;                         dirtyrect.right = dirtyrectarray[index].right * m_imagescalingfactor;                          diffarea += abs((dirtyrect.right - dirtyrect.left) *                          (dirtyrect.bottom - dirtyrect.top));                          dirtyrects.push_back(dirtyrect);                     }                     else                     {                         diffarea += abs((dirtyrectarray[index].right - dirtyrectarray[index].left) *                          (dirtyrectarray[index].bottom - dirtyrectarray[index].top));                          dirtyrects.push_back(dirtyrectarray[index]);                     }                 }              }          }      return diffarea;  }  catch_all(e) {      log(critical) << _t("exception in getchangedregions"); } end_catch_all  return -1; } 

here code init device

       //     // initialize duplication interfaces     //     hresult cduplicationmanager::initdupl(_in_ id3d11device* device, _in_ idxgiadapter *_padapter, _in_ idxgioutput *_poutput, _in_ uint output)     {     hresult hr = e_fail;      if(!_poutput || !_padapter || !device)     {         return hr;     }      m_outputnumber = output;      // take reference on device     m_device = device;     m_device->addref();      /*     // dxgi device     idxgidevice* dxgidevice = nullptr;     hresult hr = m_device->queryinterface(__uuidof(idxgidevice), reinterpret_cast<void**>(&dxgidevice));     if (failed(hr))     {         return processfailure(nullptr, _t("failed qi dxgi device"), _t("error"), hr);     }      // dxgi adapter     idxgiadapter* dxgiadapter = nullptr;     hr = dxgidevice->getparent(__uuidof(idxgiadapter), reinterpret_cast<void**>(&dxgiadapter));     dxgidevice->release();     dxgidevice = nullptr;     if (failed(hr))     {         return processfailure(m_device, _t("failed parent dxgi adapter"), _t("error"), hr);//, systemtransitionsexpectederrors);     }      // output     idxgioutput* dxgioutput = nullptr;     hr = dxgiadapter->enumoutputs(output, &dxgioutput);     dxgiadapter->release();     dxgiadapter = nullptr;     if (failed(hr))     {         return processfailure(m_device, _t("failed specified output in duplicationmanager"), _t("error"), hr);//, enumoutputsexpectederrors);     }      dxgioutput->getdesc(&m_outputdesc);       idxgioutput1* dxgioutput1 = nullptr;     hr = dxgioutput->queryinterface(__uuidof(dxgioutput1), reinterpret_cast<void**>(&dxgioutput1));      */      _poutput->getdesc(&m_outputdesc);      // qi output 1     idxgioutput1* dxgioutput1 = nullptr;     hr = _poutput->queryinterface(__uuidof(dxgioutput1), reinterpret_cast<void**>(&dxgioutput1));      if (failed(hr))     {         return processfailure(nullptr, _t("failed qi dxgioutput1 in duplicationmanager"), _t("error"), hr);     }      // create desktop duplication     hr = dxgioutput1->duplicateoutput(m_device, &m_deskdupl);      dxgioutput1->release();     dxgioutput1 = nullptr;       if (failed(hr) || !m_deskdupl)     {         if (hr == dxgi_error_not_currently_available)         {             return processfailure(nullptr, _t("maximum number of applications using desktop duplication api"), _t("error"), hr);         }         return processfailure(m_device, _t("failed duplicate output in duplicationmanager"), _t("error"), hr);//, createduplicationexpectederrors);     }      return s_ok; } 

finally current frame , difference previous one:

   // // next frame , write data // _success_(*timeout == false && return == dupl_return_success) hresult cduplicationmanager::getframe(_out_ frame_data* data, int timeout, _out_ bool* timeout) {     idxgiresource* desktopresource = nullptr;     dxgi_outdupl_frame_info frameinfo;      try     {          // new frame         hresult hr = m_deskdupl->acquirenextframe(timeout, &frameinfo, &desktopresource);          if (hr == dxgi_error_wait_timeout)         {             *timeout = true;             return s_ok;         }          *timeout = false;          if (failed(hr))         {             return processfailure(m_device, _t("failed acquire next frame in duplicationmanager"), _t("error"), hr);//, frameinfoexpectederrors);         }          // if still holding old frame, destroy         if (m_acquireddesktopimage)         {             m_acquireddesktopimage->release();             m_acquireddesktopimage = nullptr;         }          if (desktopresource)         {             // qi idxgiresource             hr = desktopresource->queryinterface(__uuidof(id3d11texture2d), reinterpret_cast<void **>(&m_acquireddesktopimage));             desktopresource->release();             desktopresource = nullptr;         }          if (failed(hr))         {             return processfailure(nullptr, _t("failed qi id3d11texture2d acquired idxgiresource in duplicationmanager"), _t("error"), hr);         }          // metadata         if (frameinfo.totalmetadatabuffersize)         {             // old buffer small             if (frameinfo.totalmetadatabuffersize > m_metadatasize)             {                 if (m_metadatabuffer)                 {                     delete [] m_metadatabuffer;                     m_metadatabuffer = nullptr;                 }                  m_metadatabuffer = new (std::nothrow) byte[frameinfo.totalmetadatabuffersize];                  if (!m_metadatabuffer)                 {                     m_metadatasize = 0;                     data->movecount = 0;                     data->dirtycount = 0;                     return processfailure(nullptr, _t("failed allocate memory metadata in duplicationmanager"), _t("error"), e_outofmemory);                 }                  m_metadatasize = frameinfo.totalmetadatabuffersize;             }               uint bufsize = frameinfo.totalmetadatabuffersize;              // move rectangles               hr = m_deskdupl->getframemoverects(bufsize, reinterpret_cast<dxgi_outdupl_move_rect*>(m_metadatabuffer), &bufsize);              if (failed(hr))             {                 data->movecount = 0;                 data->dirtycount = 0;                 return processfailure(nullptr, l"failed frame move rects in duplicationmanager", l"error", hr);//, frameinfoexpectederrors);              }              data->movecount = bufsize / sizeof(dxgi_outdupl_move_rect);              byte* dirtyrects = m_metadatabuffer + bufsize;             bufsize = frameinfo.totalmetadatabuffersize - bufsize;              // dirty rectangles             hr = m_deskdupl->getframedirtyrects(bufsize, reinterpret_cast<rect*>(dirtyrects), &bufsize);              if (failed(hr))             {                 data->movecount = 0;                 data->dirtycount = 0;                 return processfailure(nullptr, _t("failed frame dirty rects in duplicationmanager"), _t("error"), hr);//, frameinfoexpectederrors);             }              data->dirtycount = bufsize / sizeof(rect);              data->metadata = m_metadatabuffer;         }          data->frame = m_acquireddesktopimage;         data->frameinfo = frameinfo;      }     catch (...)     {         return s_false;     }      return s_ok; } 

update :

failed acquire next frame in duplicationmanager getting printed whenever device has hung (that in mid of streaming screens, ex: continuously capturing video , sending other end)

// new frame     hresult hr = m_deskdupl->acquirenextframe(timeout, &frameinfo, &desktopresource);      if (hr == dxgi_error_wait_timeout)     {         *timeout = true;         return s_ok;     }      *timeout = false;      if (failed(hr))     {         return processfailure(m_device, _t("failed acquire next frame in duplicationmanager"), _t("error"), hr);//, frameinfoexpectederrors);     } 

here detailed error info :

id3d11duplicationmanager::processfailure - error: failed acquire next frame in duplicationmanager, detail: keyed mutex abandoned.

update 2 : have got error code whenever device failed give screen updates forever, , here same

id3d11duplicationmanager::processfailure - error: failed duplicate output in duplicationmanager, detail: access denied.

the error code e_accessdenied.

i not understand why getting error running in system mode , setthreaddesktop had been executed twice (one during init , after detecting failure)

this explanation of error on msdn : e_accessdenied if application not have access privilege current desktop image. example, application runs @ local_system can access secure desktop.

is there else result in kind of issue?


Comments

Popular posts from this blog

resizing Telegram inline keyboard -

command line - How can a Python program background itself? -

php - "cURL error 28: Resolving timed out" on Wordpress on Azure App Service on Linux -