private ScreenshotResource CaptureDirectX(IntPtr wnd) { if (!AttachHookToProcess()) { throw new ScreenshotCaptureException("Error attaching to DirectX"); } ScreenshotResource result = null; // Bitmap img = null; // captureProcess.BringProcessWindowToFront(); // Initiate the screenshot of the CaptureInterface, the appropriate event handler within the target process will take care of the rest if (captureConfig.Direct3DVersion == Direct3DVersion.Direct3D9 || captureConfig.Direct3DVersion == Direct3DVersion.Direct3D9Simple) { var start = DateTime.Now.Ticks; var task = Task<Screenshot>.Factory.FromAsync( (rect, timeout, callback, ctxt) => captureProcess.CaptureInterface.BeginGetScreenshot(rect, timeout, callback), captureProcess.CaptureInterface.EndGetScreenshot, emptyRect, waitForScreenshotTimeout, null); Screenshot screen = null; try { task.Wait(); screen = task.Result; var stop = DateTime.Now.Ticks; var proc = TimeSpan.FromTicks(stop - start).Milliseconds; TraceLog.Log("DX Capture speed: {0}", proc); if (screen == null && directxRetryCount == 0) { Log.Debug("No data received from DirectX hook, retrying once."); directxRetryCount++; return CaptureDirectX(wnd); } else if (screen == null) { Log.Debug("No data received from DirectX hook."); return null; } directxRetryCount = 0; task.Dispose(); try { var width = screen.Width; var height = screen.Height; var bitmapData = screen.CapturedBitmap; var img = new Bitmap(width, height, PixelFormat.Format32bppRgb); var bmpData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.WriteOnly, img.PixelFormat); Marshal.Copy(bitmapData, 0, bmpData.Scan0, bitmapData.Length); img.UnlockBits(bmpData); result = new ScreenshotResource(img); } catch (Exception ex) { Log.Debug(ex, "Error decoding DirectX pixels: {0}"); return null; } } finally { if (screen != null) { screen.Dispose(); } } } else if (captureConfig.Direct3DVersion == Direct3DVersion.Direct3D9SharedMem) { try { if (!hookReadyWaitHandle.WaitOne(2000)) { Log.Debug("Waiting for DirectX hook initialization."); return null; } captureDxWaitHandle.Set(); if (copyDataMem == null) { try { copyDataMem = MemoryMappedFile.OpenExisting("CaptureHookSharedMemData", MemoryMappedFileRights.Read); copyDataMemAccess = copyDataMem.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); copyDataMemAccess.SafeMemoryMappedViewHandle.AcquirePointer(ref copyDataMemPtr); } catch (FileNotFoundException) { // not hooked Log.Debug("Shared memory not found"); return null; } } if (copyDataMemAccess == null) { // not hooked Log.Debug("Shared memory not opened yet"); return null; } int lastRendered; var copyData = (*((CopyData*)copyDataMemPtr)); if (copyData.height <= 0 || copyData.textureId == Guid.Empty) { return null; } lastRendered = copyData.lastRendered; if (lastRendered != -1) { if (!sharedMemMutexes[lastRendered].WaitOne(1000)) { Log.Warn("Failed acquiring shared texture lock in time (1000)."); return null; } if (lastKnownTextureId != copyData.textureId) { for (var i = 0; i < 2; i++) { if (sharedTexturesAccess[i] != null) { sharedTexturesAccess[i].SafeMemoryMappedViewHandle.ReleasePointer(); sharedTexturesAccess[i].Dispose(); sharedTexturesAccess[i] = null; } if (sharedTextures[i] != null) { sharedTextures[i].Dispose(); sharedTextures[i] = null; } } } if (sharedTextures[lastRendered] == null) { sharedTextures[lastRendered] = MemoryMappedFile.OpenExisting(copyData.textureId.ToString() + lastRendered, MemoryMappedFileRights.ReadWrite); sharedTexturesAccess[lastRendered] = sharedTextures[lastRendered].CreateViewAccessor( 0, copyData.height * copyData.pitch, MemoryMappedFileAccess.ReadWrite); sharedTexturesAccess[lastRendered].SafeMemoryMappedViewHandle.AcquirePointer(ref sharedTexturesPtr[lastRendered]); } var img = new Bitmap( copyData.width, copyData.height, copyData.pitch, PixelFormat.Format32bppRgb, new IntPtr(sharedTexturesPtr[lastRendered])); lastKnownTextureId = copyData.textureId; result = new DxScreenshotResource(img, sharedMemMutexes[lastRendered]); } } catch (Exception ex) { Log.Error(ex); } } return result; }
private ScreenshotResource CaptureDirectX(IntPtr wnd) { if (!this.AttachHookToProcess()) { throw new ScreenshotCaptureException("Error attaching to DirectX"); } ScreenshotResource result = null; // Bitmap img = null; // captureProcess.BringProcessWindowToFront(); // Initiate the screenshot of the CaptureInterface, the appropriate event handler within the target process will take care of the rest if (this.captureConfig.Direct3DVersion == Direct3DVersion.Direct3D9 || this.captureConfig.Direct3DVersion == Direct3DVersion.Direct3D9Simple) { var start = DateTime.Now.Ticks; var task = Task <Screenshot> .Factory.FromAsync( (rect, timeout, callback, ctxt) => this.captureProcess.CaptureInterface.BeginGetScreenshot(rect, timeout, callback), this.captureProcess.CaptureInterface.EndGetScreenshot, emptyRect, waitForScreenshotTimeout, null); Screenshot screen = null; try { task.Wait(); screen = task.Result; var stop = DateTime.Now.Ticks; var proc = TimeSpan.FromTicks(stop - start).Milliseconds; TraceLog.Log("DX Capture speed: {0}", proc); if (screen == null && directxRetryCount == 0) { Log.Debug("No data received from DirectX hook, retrying once."); directxRetryCount++; return(CaptureDirectX(wnd)); } else if (screen == null) { Log.Debug("No data received from DirectX hook."); return(null); } directxRetryCount = 0; task.Dispose(); try { var width = screen.Width; var height = screen.Height; var bitmapData = screen.CapturedBitmap; var img = new Bitmap(width, height, PixelFormat.Format32bppRgb); var bmpData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.WriteOnly, img.PixelFormat); Marshal.Copy(bitmapData, 0, bmpData.Scan0, bitmapData.Length); img.UnlockBits(bmpData); result = new ScreenshotResource(img); } catch (Exception ex) { Log.Debug("Error decoding DirectX pixels: {0}", ex); return(null); } } finally { if (screen != null) { screen.Dispose(); } } } else if (this.captureConfig.Direct3DVersion == Direct3DVersion.Direct3D9SharedMem) { try { if (!hookReadyWaitHandle.WaitOne(2000)) { Log.Debug("Waiting for DirectX hook initialization."); return(null); } captureDxWaitHandle.Set(); if (this.copyDataMem == null) { try { this.copyDataMem = MemoryMappedFile.OpenExisting("CaptureHookSharedMemData", MemoryMappedFileRights.Read); this.copyDataMemAccess = this.copyDataMem.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); this.copyDataMemAccess.SafeMemoryMappedViewHandle.AcquirePointer(ref this.copyDataMemPtr); } catch (FileNotFoundException) { // not hooked Log.Debug("Shared memory not found"); return(null); } } if (copyDataMemAccess == null) { // not hooked Log.Debug("Shared memory not opened yet"); return(null); } int lastRendered; CopyData copyData = (*((CopyData *)this.copyDataMemPtr)); if (copyData.height <= 0 || copyData.textureId == Guid.Empty) { return(null); } lastRendered = copyData.lastRendered; if (lastRendered != -1) { if (!this.sharedMemMutexes[lastRendered].WaitOne(1000)) { Log.Warn("Failed acquiring shared texture lock in time (1000)."); return(null); } if (this.lastKnownTextureId != copyData.textureId) { for (int i = 0; i < 2; i++) { if (this.sharedTexturesAccess[i] != null) { this.sharedTexturesAccess[i].SafeMemoryMappedViewHandle.ReleasePointer(); this.sharedTexturesAccess[i].Dispose(); this.sharedTexturesAccess[i] = null; } if (this.sharedTextures[i] != null) { this.sharedTextures[i].Dispose(); this.sharedTextures[i] = null; } } } if (this.sharedTextures[lastRendered] == null) { this.sharedTextures[lastRendered] = MemoryMappedFile.OpenExisting(copyData.textureId.ToString() + lastRendered, MemoryMappedFileRights.ReadWrite); this.sharedTexturesAccess[lastRendered] = this.sharedTextures[lastRendered].CreateViewAccessor( 0, copyData.height * copyData.pitch, MemoryMappedFileAccess.ReadWrite); this.sharedTexturesAccess[lastRendered].SafeMemoryMappedViewHandle.AcquirePointer(ref sharedTexturesPtr[lastRendered]); } var img = new Bitmap( copyData.width, copyData.height, copyData.pitch, PixelFormat.Format32bppRgb, new IntPtr(sharedTexturesPtr[lastRendered])); this.lastKnownTextureId = copyData.textureId; result = new DxScreenshotResource(img, this.sharedMemMutexes[lastRendered]); } } catch (Exception ex) { Log.Error(ex); } } return(result); }