Files

87 lines
2.1 KiB
Go

package capture
import (
"image"
"testing"
)
func TestHEVCEncoderProducesAnnexBHeadersAndKeyframe(t *testing.T) {
if !hevcAvailable() {
t.Skipf("HEVC encoder unavailable: %s", hevcAvailabilityDetail())
}
resetHEVCEncoder()
t.Cleanup(resetHEVCEncoder)
frame := image.NewRGBA(image.Rect(0, 0, 1280, 720))
encoded, err := encodeHEVCFrame(frame)
if err != nil {
t.Fatalf("encode HEVC frame: %v", err)
}
if len(encoded) == 0 {
t.Fatal("HEVC encoder returned an empty frame")
}
nalTypes := hevcAnnexBNALTypes(encoded)
for _, required := range []byte{32, 33, 34} {
if !containsByte(nalTypes, required) {
t.Fatalf("HEVC frame missing NAL type %d; got %v", required, nalTypes)
}
}
hasIntra := false
for _, nalType := range nalTypes {
if nalType >= 16 && nalType <= 21 {
hasIntra = true
break
}
}
if !hasIntra {
t.Fatalf("HEVC first frame is not an IRAP keyframe; got NAL types %v", nalTypes)
}
}
func TestHEVCD3D11TexturePipeline(t *testing.T) {
if !hevcAvailable() {
t.Skipf("HEVC encoder unavailable: %s", hevcAvailabilityDetail())
}
result := RunNVENCD3D11Smoke(NVENCD3D11SmokeOptions{
Width: 1280, Height: 720, FPS: 60, Frames: 4, Codec: "hevc",
})
if !result.OK {
t.Fatalf("HEVC D3D11 texture pipeline failed: %+v", result)
}
if result.TotalBytes == 0 {
t.Fatal("HEVC D3D11 texture pipeline produced no output")
}
t.Logf("HEVC D3D11 texture pipeline: first=%.2fms avg=%.2fms bytes=%d", result.FirstMS, result.AvgMS, result.TotalBytes)
}
func hevcAnnexBNALTypes(data []byte) []byte {
types := make([]byte, 0, 8)
for i := 0; i+4 < len(data); i++ {
startCodeLen := 0
if data[i] == 0 && data[i+1] == 0 && data[i+2] == 1 {
startCodeLen = 3
} else if i+4 < len(data) && data[i] == 0 && data[i+1] == 0 && data[i+2] == 0 && data[i+3] == 1 {
startCodeLen = 4
}
if startCodeLen == 0 {
continue
}
nalIndex := i + startCodeLen
if nalIndex < len(data) {
types = append(types, (data[nalIndex]>>1)&0x3f)
i = nalIndex
}
}
return types
}
func containsByte(values []byte, wanted byte) bool {
for _, value := range values {
if value == wanted {
return true
}
}
return false
}