This commit is contained in:
KingKDot
2026-08-04 00:03:01 -05:00
parent dd06b573d0
commit fd2c2fdbfa
4 changed files with 81 additions and 21 deletions
@@ -38,6 +38,7 @@ const (
mftMessageNotifyEndStreaming = 0x10000001
mftOutputStreamProvidesSamples = 0x00000100
mftOutputStreamCanProvideSamples = 0x00000200
mfETransformNeedMoreInput = 0xC00D6D72
mfETransformStreamChange = 0xC00D6D61
@@ -1067,7 +1068,7 @@ func (e *mfH264Encoder) processOutput() ([]byte, error) {
}
var outSample *mfSample
if info.flags&mftOutputStreamProvidesSamples == 0 {
if !mftCanAllocateOutputSample(info.flags) {
size := int(info.cbSize)
minSize := e.width * e.height * 3 / 2
if size < minSize {
@@ -1098,7 +1099,11 @@ func (e *mfH264Encoder) processOutput() ([]byte, error) {
return nil, nil
default:
if failedHR(hr) {
return nil, fmt.Errorf("mf h264: ProcessOutput failed 0x%x", hr)
allocation := "transform"
if outSample != nil {
allocation = "caller"
}
return nil, fmt.Errorf("mf h264: ProcessOutput failed 0x%x stream_flags=0x%x output_sample=%s", hr, info.flags, allocation)
}
}
if output.sample == nil {
@@ -1110,6 +1115,10 @@ func (e *mfH264Encoder) processOutput() ([]byte, error) {
return sampleBytes(output.sample)
}
func mftCanAllocateOutputSample(flags uint32) bool {
return flags&(mftOutputStreamProvidesSamples|mftOutputStreamCanProvideSamples) != 0
}
func createVideoType(subtype windows.GUID, width, height, fps int) (*mfMediaType, error) {
var mt *mfMediaType
hr, _, _ := procMFCreateMediaType.Call(uintptr(unsafe.Pointer(&mt)))
@@ -0,0 +1,25 @@
//go:build windows
package capture
import "testing"
func TestMFTCanAllocateOutputSample(t *testing.T) {
tests := []struct {
name string
flags uint32
want bool
}{
{name: "caller must allocate", flags: 0, want: false},
{name: "transform provides samples", flags: mftOutputStreamProvidesSamples, want: true},
{name: "transform can provide samples", flags: mftOutputStreamCanProvideSamples, want: true},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if got := mftCanAllocateOutputSample(test.flags); got != test.want {
t.Fatalf("mftCanAllocateOutputSample(0x%x) = %t, want %t", test.flags, got, test.want)
}
})
}
}
@@ -1365,6 +1365,9 @@ func findOutput(factory *idxgiFactory1, desiredName string, desiredBounds image.
}
func createD3DDevice(adapter *idxgiAdapter1) (*d3d11Device, *d3d11DeviceContext, error) {
flags := d3d11DeviceCreationFlagCandidates()
var firstHR uintptr
for attempt, creationFlags := range flags {
var device *d3d11Device
var context *d3d11DeviceContext
var featureLevel uint32
@@ -1372,7 +1375,7 @@ func createD3DDevice(adapter *idxgiAdapter1) (*d3d11Device, *d3d11DeviceContext,
uintptr(unsafe.Pointer(adapter)),
uintptr(d3dDriverTypeUnknown),
0,
uintptr(d3d11CreateDeviceBgraSupport|d3d11CreateDeviceVideoSupport),
uintptr(creationFlags),
0,
0,
uintptr(d3d11SdkVersion),
@@ -1380,16 +1383,29 @@ func createD3DDevice(adapter *idxgiAdapter1) (*d3d11Device, *d3d11DeviceContext,
uintptr(unsafe.Pointer(&featureLevel)),
uintptr(unsafe.Pointer(&context)),
)
if hr != S_OK || device == nil || context == nil {
if hr == S_OK && device != nil && context != nil {
return device, context, nil
}
if context != nil {
context.Release()
}
if device != nil {
device.Release()
}
return nil, nil, fmt.Errorf("dxgi: D3D11CreateDevice failed 0x%x", hr)
if attempt == 0 {
firstHR = hr
continue
}
return nil, nil, fmt.Errorf("dxgi: D3D11CreateDevice failed video=0x%x fallback=0x%x", firstHR, hr)
}
return nil, nil, errors.New("dxgi: D3D11CreateDevice had no creation modes")
}
func d3d11DeviceCreationFlagCandidates() [2]uint32 {
return [2]uint32{
d3d11CreateDeviceBgraSupport | d3d11CreateDeviceVideoSupport,
d3d11CreateDeviceBgraSupport,
}
return device, context, nil
}
func convertBGRA(src []byte, pitch, width, height int, rotation uint32) *image.RGBA {
@@ -49,6 +49,16 @@ func TestDesktopDuplicationToggleResetsState(t *testing.T) {
}
}
func TestD3D11DeviceCreationFlagsFallBackWithoutVideoSupport(t *testing.T) {
flags := d3d11DeviceCreationFlagCandidates()
if flags[0] != d3d11CreateDeviceBgraSupport|d3d11CreateDeviceVideoSupport {
t.Fatalf("first D3D11 creation flags = 0x%x, want BGRA and video support", flags[0])
}
if flags[1] != d3d11CreateDeviceBgraSupport {
t.Fatalf("fallback D3D11 creation flags = 0x%x, want BGRA only", flags[1])
}
}
func TestCaptureDisplayDXGI(t *testing.T) {
if displayCount() == 0 {
t.Skip("no displays detected")