Verpous / AlwaysShadow

Makes sure Shadowplay's Instant Replay feature is on.
GNU General Public License v3.0
136 stars 3 forks source link

Automatically detecting apps blocking Shadowplay #20

Open leumasme opened 3 months ago

leumasme commented 3 months ago

I did some research on why Shadowplay even turns off when viewing some content, in an effort to figure out if this could be circumvented. Shadowplay internally uses NvFBC (which is part of the Nvidia Capture SDK) to capture frames. NVIDIA Capture SDK Programming Guide.pdf Because of how NvFBC works, it would presumably be able to capture content that normally is not recordable

NvFBC will detect such "Protected Content" and refuse to capture frames if any is present, returning a NVFBC_ERROR_PROTECTED_CONTENT error.

Playback of protected content such as DVD or BluRay disks typically requires an
encrypted, secured path to the physical display output device. To prevent violation of
protected content license terms, NVFBC will not capture frames from the GPU
whenever a protected content session is active.
NVFBC indicates the presence of protected content by returning
NVFBC_ERROR_PROTECTED_CONTENT from calls to NVFBCEndGrabFrame(), and no frame
data is returned.

Logs about this happening can be found in C:\ProgramData\NVIDIA Corporation\ShadowPlay\CaptureCore.log, where ShadowPlay will log the Errors that NvFBC is returning

Exerpt from CaptureCore.log ```log CVideoCaptureFbc::CaptureFrame: CVideoFrameProvider::CaptureFrame failed 0XA CVideoCapture::Process: CaptureFrame failed 0XFFFFFFFC CVideoCapture::NvFBCH264GrabFrame: nvfbc grab frame failed CVideoCapture::Capture: NvFBCH264GrabFrame failed with error = NVFBC_ERROR_PROTECTED_CONTENT CCaptureCore::OnError: dwErrorType[121], uiErrorContext[0], hr[0X80004005], m_CaptureCoreCallback[0XAC97E7D2] CCaptureSession::HandleCapCoreCB: CAPCORE_CBTYPE_ERROR CCaptureSession::HandleErrorCB: error(0x00000079) CCaptureSession::HandleError: uiErrorType[121], uiSubType[0], hr[0X80004005] CCaptureSession::LogProtectedContentAppDetails: Protected Content is running by PID: 6060 App: CCaptureSession::IsDVRDisableRequired YES : err(121:0) hr(0X80004005) CCaptureSession::StopDVRCapture: IN CircularBufferManager::Release: 0 CVideoCaptureFbc::CaptureFrame: CVideoFrameProvider::CaptureFrame failed 0XA CVideoCapture::Process: CaptureFrame failed 0XFFFFFFFC CVideoCapture::NvFBCH264GrabFrame: nvfbc grab frame failed CVideoCapture::Capture: NvFBCH264GrabFrame failed with error = NVFBC_ERROR_PROTECTED_CONTENT ```

Note that this is also logging which PID contains the protected content

CCaptureSession::LogProtectedContentAppDetails: Protected Content is running by PID: 6060 App:

This means that it should be possible to detect the application that is blocking ShadowPlay, notify the user about it (of course resolve PID to something more readable first), and automatically whitelist it (optional). As a simple approach, this could be done by monitoring the logfile for log messages of the right format and parsing them.

Related references:

leumasme commented 3 months ago

From looking at _nvspcaps64.dll strings, the log message for DRM content should be CaptureSession::LogProtectedContentAppDetails : Protected content is played through secure channel eg. netflix in browser

Verpous commented 3 months ago

Impressive work, I'll look into it!