WGPU is coming
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log"
|
||||
flowdef "mxl-pattern-generator/internal/flow-def"
|
||||
"mxl-pattern-generator/internal/generator"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/qvest-digital/go-mxl/mxl"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var width, height uint = 1920, 1080
|
||||
var fps_num, fps_den uint = 25, 1
|
||||
flowUUID := "5fbec3b1-1b0f-417d-9059-8b94a47197ed"
|
||||
log.Printf("Go Pattern Gen")
|
||||
log.Printf("Video: %dx%dp%d/%d", width, height, fps_num, fps_den)
|
||||
log.Printf("UUID: %s", flowUUID)
|
||||
domain := "/dev/shm/mxl"
|
||||
|
||||
inst, err := mxl.NewInstance(domain, "")
|
||||
if err != nil {
|
||||
log.Fatalf("MXL Init Failed: %v", err)
|
||||
}
|
||||
defer inst.Close()
|
||||
|
||||
flowDef, err := flowdef.NewFlowDefJSON(
|
||||
flowdef.TYPE_VIDEO,
|
||||
flowUUID,
|
||||
width,
|
||||
height,
|
||||
fps_num,
|
||||
fps_den,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not create Flow Definition: %v", err)
|
||||
}
|
||||
writer, isCreated, err := inst.NewWriter(flowDef)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create MXL writer: %v", err)
|
||||
}
|
||||
if !isCreated {
|
||||
log.Printf("reusing existing flow: %s, domain: %s", flowUUID, domain)
|
||||
}
|
||||
defer writer.Close()
|
||||
|
||||
var gen *generator.OpenCLGenerator
|
||||
gen, err = generator.NewOpenCLGenerator(width, height, "/home/itten/codeproj/go-mxl-pattern-gen/kernels/v210_pack.cl")
|
||||
gen, err = generator.NewOpenCLGenerator(width, height, "/home/itten/codeproj/go-mxl-pattern-gen/kernels/v210_pack.cl")
|
||||
if err != nil {
|
||||
log.Fatalf("OpenCL init failed: %v", err)
|
||||
}
|
||||
defer gen.Close()
|
||||
gen.SetText(generator.TextConfig{
|
||||
Str: "MXL PATTERN GEN",
|
||||
X: 0, Y: 0, Scale: 8,
|
||||
FG: [3]uint32{940, 512, 512},
|
||||
BG: [3]uint32{64, 512, 512},
|
||||
Boxed: true,
|
||||
})
|
||||
|
||||
flowCfg := writer.Config()
|
||||
rate := flowCfg.Common.GrainRate
|
||||
idx := mxl.CurrentIndex(rate)
|
||||
log.Printf("writing flow grainRate=%d/%d starting at idx=%d", rate.Num, rate.Den, idx)
|
||||
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
var written int64
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
log.Printf("stopping after %d grains", written)
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
gwa, err := writer.OpenGrain(idx)
|
||||
if err != nil {
|
||||
log.Fatalf("OpenGrain(%d): %v", idx, err)
|
||||
}
|
||||
// fillGrainRamp(gwa.Payload, idx)
|
||||
// smpteBars(gwa.Payload)
|
||||
gen.GenerateFrame(gwa.Payload, int(idx))
|
||||
// if err != nil {
|
||||
// log.Fatalf("Frame Generator: %v", err)
|
||||
// }
|
||||
if err := gwa.Commit(gwa.TotalSlices, 0); err != nil {
|
||||
log.Fatalf("Commit(%d): %v", idx, err)
|
||||
}
|
||||
|
||||
written++
|
||||
idx++
|
||||
if written%100 == 0 {
|
||||
log.Printf("grains written=%d, index=%d", written, idx)
|
||||
}
|
||||
// Pace ourselves to roughly the grain rate
|
||||
mxl.SleepNs(mxl.NsUntilIndex(idx, rate))
|
||||
}
|
||||
}
|
||||
|
||||
// fillGrainRamp writes byte((i+start)&0xFF) across buf. A matching reader
|
||||
// uses the same pattern to verify grain continuit
|
||||
func fillGrainRamp(buf []byte, start uint64) {
|
||||
for i := range buf {
|
||||
buf[i] = byte((uint64(i) + start) & 0xFF)
|
||||
}
|
||||
}
|
||||
|
||||
func smpteBars(dest []byte) {
|
||||
const width = 1920
|
||||
|
||||
// SMPTE 75% bars, Rec.709, 10-bit Y'CbCr: {Y, Cb, Cr}
|
||||
bars := [7][3]uint32{
|
||||
{721, 512, 512}, // 75% white
|
||||
{674, 176, 543}, // 75% yellow
|
||||
{581, 589, 176}, // 75% cyan
|
||||
{534, 253, 207}, // 75% green
|
||||
{251, 771, 817}, // 75% magenta
|
||||
{204, 435, 848}, // 75% red
|
||||
{111, 848, 481}, // 75% blue
|
||||
}
|
||||
|
||||
barIdx := func(x int) int {
|
||||
idx := x * len(bars) / width
|
||||
if idx >= len(bars) {
|
||||
return len(bars) - 1
|
||||
}
|
||||
return idx
|
||||
}
|
||||
|
||||
// v210: each 16-byte block carries 6 pixels (Y0..Y5, chroma co-sited at 0/2/4)
|
||||
for block := 0; block*16+16 <= len(dest); block++ {
|
||||
baseX := (block * 6) % width
|
||||
|
||||
var y [6]uint32
|
||||
for i := range y {
|
||||
y[i] = bars[barIdx(baseX+i)][0]
|
||||
}
|
||||
cb0, cr0 := bars[barIdx(baseX)][1], bars[barIdx(baseX)][2]
|
||||
cb2, cr2 := bars[barIdx(baseX+2)][1], bars[barIdx(baseX+2)][2]
|
||||
cb4, cr4 := bars[barIdx(baseX+4)][1], bars[barIdx(baseX+4)][2]
|
||||
|
||||
w0 := (cb0 & 0x3FF) | ((y[0] & 0x3FF) << 10) | ((cr0 & 0x3FF) << 20)
|
||||
w1 := (y[1] & 0x3FF) | ((cb2 & 0x3FF) << 10) | ((y[2] & 0x3FF) << 20)
|
||||
w2 := (cr2 & 0x3FF) | ((y[3] & 0x3FF) << 10) | ((cb4 & 0x3FF) << 20)
|
||||
w3 := (y[4] & 0x3FF) | ((cr4 & 0x3FF) << 10) | ((y[5] & 0x3FF) << 20)
|
||||
|
||||
byteIdx := block * 16
|
||||
binary.LittleEndian.PutUint32(dest[byteIdx+0:], w0)
|
||||
binary.LittleEndian.PutUint32(dest[byteIdx+4:], w1)
|
||||
binary.LittleEndian.PutUint32(dest[byteIdx+8:], w2)
|
||||
binary.LittleEndian.PutUint32(dest[byteIdx+12:], w3)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user