optimize tf out of the cursor shit and override to go up to 120 fps.
This commit is contained in:
@@ -68,10 +68,12 @@ func ensureH264EncoderLocked(width, height int) error {
|
|||||||
opts := &x264.Options{
|
opts := &x264.Options{
|
||||||
Width: width,
|
Width: width,
|
||||||
Height: height,
|
Height: height,
|
||||||
FrameRate: 25,
|
FrameRate: 120,
|
||||||
Tune: "zerolatency",
|
Tune: "zerolatency,fastdecode",
|
||||||
Preset: "ultrafast",
|
Preset: "ultrafast",
|
||||||
Profile: "baseline",
|
Profile: "baseline",
|
||||||
|
RateControl: "crf",
|
||||||
|
RateConstant: 30,
|
||||||
LogLevel: x264.LogError,
|
LogLevel: x264.LogError,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -686,7 +686,7 @@ func (s *duplicationState) capture(display int) (*image.RGBA, error) {
|
|||||||
|
|
||||||
var info dxgiOutDuplFrameInfo
|
var info dxgiOutDuplFrameInfo
|
||||||
var resource *iunknown
|
var resource *iunknown
|
||||||
hr := s.dup.AcquireNextFrame(50, &info, &resource)
|
hr := s.dup.AcquireNextFrame(5, &info, &resource)
|
||||||
if hr == dxgiErrorWaitTimeout {
|
if hr == dxgiErrorWaitTimeout {
|
||||||
if s.lastBase != nil {
|
if s.lastBase != nil {
|
||||||
img := s.composeFrame(s.lastBase)
|
img := s.composeFrame(s.lastBase)
|
||||||
@@ -756,14 +756,27 @@ func (s *duplicationState) composeFrame(base *image.RGBA) *image.RGBA {
|
|||||||
if base == nil {
|
if base == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
img := cloneRGBA(base)
|
userScale := captureScale()
|
||||||
|
withCursor := cursorCaptureEnabled.Load()
|
||||||
|
|
||||||
|
// Fast path: no cursor overlay and no scaling means we can reuse the raw
|
||||||
|
// frame without an extra clone/copy.
|
||||||
|
if !withCursor && userScale == 1 {
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
|
||||||
|
img := base
|
||||||
|
if withCursor {
|
||||||
|
img = cloneRGBA(base)
|
||||||
|
}
|
||||||
bounds := s.bounds
|
bounds := s.bounds
|
||||||
if bounds.Dx() != int(s.desc.ModeDesc.Width) || bounds.Dy() != int(s.desc.ModeDesc.Height) {
|
if bounds.Dx() != int(s.desc.ModeDesc.Width) || bounds.Dy() != int(s.desc.ModeDesc.Height) {
|
||||||
bounds = image.Rect(bounds.Min.X, bounds.Min.Y, bounds.Min.X+int(s.desc.ModeDesc.Width), bounds.Min.Y+int(s.desc.ModeDesc.Height))
|
bounds = image.Rect(bounds.Min.X, bounds.Min.Y, bounds.Min.X+int(s.desc.ModeDesc.Width), bounds.Min.Y+int(s.desc.ModeDesc.Height))
|
||||||
}
|
}
|
||||||
|
if withCursor {
|
||||||
drawCursorRotated(img, s.cursorBounds, bounds, s.desc.Rotation)
|
drawCursorRotated(img, s.cursorBounds, bounds, s.desc.Rotation)
|
||||||
|
}
|
||||||
|
|
||||||
userScale := captureScale()
|
|
||||||
rotW := img.Bounds().Dx()
|
rotW := img.Bounds().Dx()
|
||||||
rotH := img.Bounds().Dy()
|
rotH := img.Bounds().Dy()
|
||||||
dstW := int(float64(rotW) * userScale)
|
dstW := int(float64(rotW) * userScale)
|
||||||
@@ -1108,16 +1121,6 @@ func drawCursorRotated(img *image.RGBA, cursorBounds, captureBounds image.Rectan
|
|||||||
curX := ci.ptScreenPos.x
|
curX := ci.ptScreenPos.x
|
||||||
curY := ci.ptScreenPos.y
|
curY := ci.ptScreenPos.y
|
||||||
|
|
||||||
var icon iconInfo
|
|
||||||
ret, _, _ = procGetIconInfo.Call(ci.hCursor, uintptr(unsafe.Pointer(&icon)))
|
|
||||||
if ret != 0 {
|
|
||||||
if icon.hbmMask != 0 {
|
|
||||||
defer deleteObject(icon.hbmMask)
|
|
||||||
}
|
|
||||||
if icon.hbmColor != 0 {
|
|
||||||
defer deleteObject(icon.hbmColor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cursorBounds.Empty() {
|
if cursorBounds.Empty() {
|
||||||
cursorBounds = captureBounds
|
cursorBounds = captureBounds
|
||||||
}
|
}
|
||||||
@@ -1151,10 +1154,11 @@ func drawCursorRotated(img *image.RGBA, cursorBounds, captureBounds image.Rectan
|
|||||||
ry = localY
|
ry = localY
|
||||||
}
|
}
|
||||||
rotBounds := image.Rect(0, 0, img.Bounds().Dx(), img.Bounds().Dy())
|
rotBounds := image.Rect(0, 0, img.Bounds().Dx(), img.Bounds().Dy())
|
||||||
if !drawRealCursorOnImage(img, ci.hCursor, int32(rx), int32(ry), int32(icon.xHotspot), int32(icon.yHotspot)) {
|
|
||||||
|
// Performance-first cursor overlay for duplication path: avoid per-frame
|
||||||
|
// icon extraction/DC composition and draw a lightweight software cursor.
|
||||||
drawCursor(img, int32(rx), int32(ry), rotBounds)
|
drawCursor(img, int32(rx), int32(ry), rotBounds)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func drawRealCursorOnImage(img *image.RGBA, hCursor uintptr, hotX, hotY, xHotspot, yHotspot int32) bool {
|
func drawRealCursorOnImage(img *image.RGBA, hCursor uintptr, hotX, hotY, xHotspot, yHotspot int32) bool {
|
||||||
if img == nil || hCursor == 0 {
|
if img == nil || hCursor == 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user