nvidia quick sync
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
//go:build windows && cgo && !no_qsv
|
||||
|
||||
package capture
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"overlord-client/cmd/agent/capture/qsvbridge"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type qsvD3D11TextureBackend struct {
|
||||
encoder *qsvbridge.Encoder
|
||||
device unsafe.Pointer
|
||||
inputWidth, inputHeight, encodeWidth, encodeHeight, fps int
|
||||
dxgiFormat uint32
|
||||
output []byte
|
||||
forceIDR atomic.Bool
|
||||
}
|
||||
|
||||
func newQSVD3D11TextureBackend() h264D3D11TextureBackend {
|
||||
return &qsvD3D11TextureBackend{output: make([]byte, 1024*1024)}
|
||||
}
|
||||
|
||||
func (b *qsvD3D11TextureBackend) Name() string { return "Intel Quick Sync (oneVPL)" }
|
||||
|
||||
func (b *qsvD3D11TextureBackend) matches(req h264D3D11TextureRequest) bool {
|
||||
return b.encoder != nil && b.device == req.Device && b.inputWidth == req.InputWidth &&
|
||||
b.inputHeight == req.InputHeight && b.encodeWidth == req.EncodeWidth &&
|
||||
b.encodeHeight == req.EncodeHeight && b.fps == req.FPS && b.dxgiFormat == req.DXGIFormat
|
||||
}
|
||||
|
||||
func (b *qsvD3D11TextureBackend) Encode(req h264D3D11TextureRequest) ([]byte, error) {
|
||||
if !b.matches(req) {
|
||||
b.Reset()
|
||||
encoder, err := qsvbridge.Create(req.Device, req.InputWidth, req.InputHeight, req.EncodeWidth,
|
||||
req.EncodeHeight, req.FPS, req.DXGIFormat, targetH264Bitrate(req.EncodeWidth, req.EncodeHeight, req.FPS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.encoder = encoder
|
||||
b.device, b.inputWidth, b.inputHeight = req.Device, req.InputWidth, req.InputHeight
|
||||
b.encodeWidth, b.encodeHeight, b.fps, b.dxgiFormat = req.EncodeWidth, req.EncodeHeight, req.FPS, req.DXGIFormat
|
||||
}
|
||||
forceIDR := req.ForceIDR || b.forceIDR.Swap(false)
|
||||
for attempts := 0; attempts < 2; attempts++ {
|
||||
result, size, err := b.encoder.Encode(req.Texture, forceIDR, b.output)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result == 2 {
|
||||
if size <= 0 || size > 64*1024*1024 {
|
||||
return nil, fmt.Errorf("oneVPL returned invalid output size %d", size)
|
||||
}
|
||||
b.output = make([]byte, size)
|
||||
forceIDR = false
|
||||
continue
|
||||
}
|
||||
if size == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
out := make([]byte, size)
|
||||
copy(out, b.output[:size])
|
||||
return out, nil
|
||||
}
|
||||
return nil, fmt.Errorf("oneVPL output buffer resize retry failed")
|
||||
}
|
||||
|
||||
func (b *qsvD3D11TextureBackend) RequestKeyframe() { b.forceIDR.Store(true) }
|
||||
func (b *qsvD3D11TextureBackend) Reset() {
|
||||
if b.encoder != nil {
|
||||
b.encoder.Close()
|
||||
}
|
||||
b.encoder, b.device = nil, nil
|
||||
b.forceIDR.Store(false)
|
||||
}
|
||||
|
||||
func probeQSVD3D11() (bool, string) { return qsvbridge.Probe() }
|
||||
Reference in New Issue
Block a user