//go:build windows package main import ( "encoding/json" "flag" "fmt" "os" "os/exec" "runtime" "strconv" "strings" "time" "overlord-client/cmd/agent/capture" "overlord-client/cmd/agent/sysinfo" ) type machineInfo struct { Hostname string `json:"hostname"` OS string `json:"os"` Arch string `json:"arch"` CPU string `json:"cpu"` GPU string `json:"gpu"` RAM string `json:"ram"` GeneratedAt string `json:"generated_at"` } type smokeReport struct { Machine machineInfo `json:"machine"` Findings []capture.H264MFTFinding `json:"media_foundation_findings"` FindingError string `json:"media_foundation_finding_error,omitempty"` H264 []capture.H264SmokeResult `json:"h264"` Capture []capture.CaptureSmokeResult `json:"capture,omitempty"` NVENC *capture.NVENCSmokeResult `json:"nvenc,omitempty"` AMF capture.AMFSmokeResult `json:"amf"` NVENCD3D11 []capture.NVENCD3D11SmokeResult `json:"nvenc_d3d11,omitempty"` Nvidia []string `json:"nvidia_smi,omitempty"` } func main() { var frames int var captureFrames int var captureDisplay int var captureFPS int var captureMaxHeight int var jsonOut bool var includeCapture bool var includeNVENC bool var includeNVENCD3D11 bool var resArg string var fpsArg string var providersArg string var reportPath string flag.IntVar(&frames, "frames", 30, "frames to feed each encoder case") flag.IntVar(&captureFrames, "capture-frames", 30, "frames to capture for each capture backend") flag.IntVar(&captureDisplay, "display", 0, "display index for capture smoke") flag.IntVar(&captureFPS, "capture-fps", 0, "target FPS for direct H.264 capture smoke") flag.IntVar(&captureMaxHeight, "capture-max-height", 0, "max capture output height; use -1 to bypass the resolution cap") flag.BoolVar(&jsonOut, "json", false, "print JSON instead of a table") flag.BoolVar(&includeCapture, "capture", false, "also time DXGI-preferred and BitBlt capture backends") flag.BoolVar(&includeNVENC, "nvenc", false, "also probe the native NVIDIA NVENC API and nvidia-smi") flag.BoolVar(&includeNVENCD3D11, "nvenc-d3d11", false, "also encode test frames through NVENC using a D3D11 NV12 texture") flag.StringVar(&resArg, "res", "1280x720,1920x1080,2560x1440,3840x2160", "comma-separated resolutions") flag.StringVar(&fpsArg, "fps", "30,60,120", "comma-separated requested FPS values") flag.StringVar(&providersArg, "providers", "hardware,software", "comma-separated providers: hardware,software") flag.StringVar(&reportPath, "report", "", "also write the complete JSON report to this file") flag.Parse() hostname, _ := os.Hostname() system := sysinfo.Collect() machine := machineInfo{Hostname: hostname, OS: sysinfo.OSName(), Arch: runtime.GOARCH, CPU: system.CPU, GPU: system.GPU, RAM: system.RAM, GeneratedAt: time.Now().Format(time.RFC3339)} findings, findingErr := capture.FindH264HardwareMFTs() amfResult := capture.RunAMFSmoke() opts := capture.DefaultH264SmokeOptions() opts.Frames = frames opts.Resolutions = parseResolutions(resArg) opts.FPS = parseInts(fpsArg) opts.Providers = parseStrings(providersArg) results := capture.RunH264Smoke(opts) var captureResults []capture.CaptureSmokeResult if includeCapture { captureResults = capture.RunCaptureSmoke(capture.CaptureSmokeOptions{Display: captureDisplay, Frames: captureFrames, FPS: captureFPS, MaxHeight: captureMaxHeight}) } var nvencResult *capture.NVENCSmokeResult var nvidiaSMI []string if includeNVENC { result := capture.RunNVENCSmoke() nvencResult = &result nvidiaSMI = queryNvidiaSMI() } var nvencD3D11Results []capture.NVENCD3D11SmokeResult if includeNVENCD3D11 { nvencD3D11Results = runNVENCD3D11SmokeCases(opts.Resolutions, opts.FPS, frames) if !includeNVENC { nvidiaSMI = queryNvidiaSMI() } } report := smokeReport{Machine: machine, Findings: findings, H264: results, Capture: captureResults, NVENC: nvencResult, AMF: amfResult, NVENCD3D11: nvencD3D11Results, Nvidia: nvidiaSMI} if findingErr != nil { report.FindingError = findingErr.Error() } if reportPath != "" { if err := writeJSONReport(reportPath, report); err != nil { fmt.Fprintf(os.Stderr, "write report failed: %v\n", err) os.Exit(1) } } if jsonOut { enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") if err := enc.Encode(report); err != nil { fmt.Fprintf(os.Stderr, "json encode failed: %v\n", err) os.Exit(1) } return } printMachine(machine) printMFTFindings(findings, findingErr) status := "unavailable" if amfResult.Available { status = "available" } fmt.Printf("AMD AMF runtime: %s (%s)\n", status, amfResult.Detail) fmt.Println() printTable(results) if includeCapture { fmt.Println() printCaptureTable(captureResults) } if includeNVENC { fmt.Println() printNVENCSummary(nvencResult, nvidiaSMI) } if includeNVENCD3D11 { fmt.Println() printNVENCD3D11Table(nvencD3D11Results) if !includeNVENC { for _, line := range nvidiaSMI { fmt.Println("nvidia-smi:", line) } } } } func writeJSONReport(path string, report smokeReport) error { f, err := os.Create(path) if err != nil { return err } defer f.Close() enc := json.NewEncoder(f) enc.SetIndent("", " ") return enc.Encode(report) } func printMachine(info machineInfo) { fmt.Println("Machine:") fmt.Printf(" Host: %s\n OS: %s (%s)\n CPU: %s\n GPU: %s\n RAM: %s\n Time: %s\n", info.Hostname, info.OS, info.Arch, info.CPU, info.GPU, info.RAM, info.GeneratedAt) } func printMFTFindings(findings []capture.H264MFTFinding, err error) { fmt.Println("Media Foundation hardware H.264 findings:") if err != nil { fmt.Printf(" ERROR: %v\n", err) return } if len(findings) == 0 { fmt.Println(" No hardware H.264 MFTs found.") return } for _, finding := range findings { status := "ok" if !finding.ActivationOK { status = "failed" } mode := "sync" if finding.Asynchronous { mode = "async" } fmt.Printf(" [%d] %s | activation=%s | mode=%s | d3d11=%t\n", finding.Index, finding.Name, status, mode, finding.D3D11Aware) if finding.HardwareURL != "" { fmt.Printf(" device: %s\n", finding.HardwareURL) } if finding.Error != "" { fmt.Printf(" error: %s\n", finding.Error) } } } func parseResolutions(raw string) []capture.H264SmokeResolution { parts := parseStrings(raw) out := make([]capture.H264SmokeResolution, 0, len(parts)) for _, part := range parts { fields := strings.Split(strings.ToLower(part), "x") if len(fields) != 2 { continue } w, werr := strconv.Atoi(strings.TrimSpace(fields[0])) h, herr := strconv.Atoi(strings.TrimSpace(fields[1])) if werr == nil && herr == nil { out = append(out, capture.H264SmokeResolution{Width: w, Height: h}) } } return out } func parseInts(raw string) []int { parts := parseStrings(raw) out := make([]int, 0, len(parts)) for _, part := range parts { if v, err := strconv.Atoi(part); err == nil { out = append(out, v) } } return out } func parseStrings(raw string) []string { fields := strings.Split(raw, ",") out := make([]string, 0, len(fields)) for _, field := range fields { field = strings.TrimSpace(field) if field != "" { out = append(out, field) } } return out } func printTable(results []capture.H264SmokeResult) { fmt.Printf("%-28s %-5s %-5s %9s %7s %7s %8s %9s %8s %7s %9s %9s %s\n", "provider", "mode", "input", "size", "reqfps", "cfgfps", "config", "first_ms", "avg_ms", "frames", "avg_bytes", "total", "error") for _, r := range results { status := "fail" if r.ConfigureOK && r.EncodeOK { status = "ok" } else if r.ConfigureOK { status = "no-data" } mode := "sync" if r.Asynchronous { mode = "async" } fmt.Printf("%-28s %-5s %-5s %4dx%-4d %7d %7d %8s %9.2f %8.2f %7d %9.0f %9d %s\n", r.Provider, mode, r.Input, r.Width, r.Height, r.RequestedFPS, r.ConfiguredFPS, status, r.FirstOutputMS, r.AvgEncodeMS, r.FramesTried, r.AvgBytes, r.TotalBytes, r.Error) } } func printCaptureTable(results []capture.CaptureSmokeResult) { fmt.Printf("%-18s %-6s %7s %7s %7s %9s %9s %9s %9s %9s %9s %9s %s\n", "backend", "format", "display", "ok", "attempt", "size", "avg_ms", "cap_ms", "enc_ms", "first_enc", "steady", "avg_bytes", "error") for _, r := range results { fmt.Printf("%-18s %-6s %7d %7d %7d %4dx%-4d %9.2f %9.2f %9.2f %9.2f %9.2f %9.0f %s\n", r.Backend, r.Format, r.Display, r.OK, r.Attempts, r.Width, r.Height, r.AvgMS, r.AvgCapMS, r.AvgEncMS, r.FirstEncMS, r.SteadyEncMS, r.AvgBytes, r.Error) } } func printNVENCSummary(result *capture.NVENCSmokeResult, smi []string) { if result == nil { return } status := "unavailable" if result.Available { status = fmt.Sprintf("available api=%d.%d raw=%d", result.APIMajor, result.APIMinor, result.RawAPI) } fmt.Printf("nvenc: %s dll=%s", status, result.DLL) if result.Error != "" { fmt.Printf(" error=%s", result.Error) } fmt.Println() for _, line := range smi { fmt.Println("nvidia-smi:", line) } } func runNVENCD3D11SmokeCases(resolutions []capture.H264SmokeResolution, fpsValues []int, frames int) []capture.NVENCD3D11SmokeResult { out := make([]capture.NVENCD3D11SmokeResult, 0, len(resolutions)*len(fpsValues)) for _, res := range resolutions { for _, fps := range fpsValues { out = append(out, capture.RunNVENCD3D11Smoke(capture.NVENCD3D11SmokeOptions{ Width: res.Width, Height: res.Height, FPS: fps, Frames: frames, })) } } return out } func printNVENCD3D11Table(results []capture.NVENCD3D11SmokeResult) { fmt.Printf("%-12s %9s %7s %7s %9s %8s %9s %9s %s\n", "nvenc-d3d11", "size", "fps", "frames", "first_ms", "avg_ms", "avg_bytes", "total", "error") for _, r := range results { status := "fail" if r.OK { status = "ok" } avgBytes := float64(0) if r.Frames > 0 { avgBytes = float64(r.TotalBytes) / float64(r.Frames) } fmt.Printf("%-12s %4dx%-4d %7d %7d %9.2f %8.2f %9.0f %9d %s\n", status, r.Width, r.Height, r.FPS, r.Frames, r.FirstMS, r.AvgMS, avgBytes, r.TotalBytes, r.Error) } } func queryNvidiaSMI() []string { cmd := exec.Command("nvidia-smi", "--query-gpu=name,driver_version,encoder.stats.sessionCount,encoder.stats.averageFps,encoder.stats.averageLatency", "--format=csv,noheader") out, err := cmd.Output() if err != nil { return []string{err.Error()} } lines := strings.Split(strings.TrimSpace(string(out)), "\n") result := make([]string, 0, len(lines)) for _, line := range lines { line = strings.TrimSpace(line) if line != "" { result = append(result, line) } } return result }