code wiki / _hdl_build / nx_vcodec_timing_probe.nx
nx_vcodec_timing_probe.nx source
↩ module page · 63 lines · 3343 B
1import "nx_gate_base.nx"
2// nx_vcodec_timing_probe.nx -- where does the per-frame CPU go? Times vv_enc (incl deblock), vv_dec (incl
3// deblock), and vv_deblock ALONE, at the live geometries + qp, so the fps drop is diagnosed with numbers
4// not guesses. license_tier: ORIGINAL
5import "nx_syscalls.nx"
6import "nx_video_codec_wasm.nx"
7const K_MAGIC_262144: i64 = 262144
8const K_MAGIC_6016: i64 = 6016
9const K_MAGIC_1000000: i64 = 1000000
10
11func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
12" as *u8); return ok }
13func gn(v: i64) -> i64 {
14 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
15 let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}
16 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
17
18func fill(yuv: *u8, W: i64, H: i64, shift: i64) -> i64 {
19 let N: i64=W*H; let C: i64=(W/2)*(H/2)
20 var y: i64=0
21 while y<H { var x: i64=0
22 while x<W { let sx: i64=x+shift
23 var v: i64=(sx*255)/W + (((sx/2+y/3)%7)*20-60); if sx>W/2 { v=v+45 }
24 if v<0 {v=0} if v>255 {v=255}; yuv[y*W+x]=v as u8; x=x+1 } y=y+1 }
25 var i: i64=N; while i<N+2*C { yuv[i]=120 as u8; i=i+1 } return 0 }
26
27func run(W: i64, H: i64, q: i64) -> i64 {
28 let N: i64=W*H; let C: i64=(W/2)*(H/2); let sz: i64=N+2*C
29 let a: *u8=sys_mmap(sz); let b: *u8=sys_mmap(sz)
30 let pe: *u8=sys_mmap(sz); let re: *u8=sys_mmap(sz); let pd: *u8=sys_mmap(sz); let rd: *u8=sys_mmap(sz)
31 let stream: *u8=sys_mmap(K_MAGIC_262144); let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64
32 var i: i64=0; while i<sz { pe[i]=0 as u8; pd[i]=0 as u8; i=i+1 }
33 fill(a, W, H, 0); fill(b, W, H, 6)
34 // warm one keyframe so P-path is measured
35 let kb: i64 = vv_enc(a, pe, re, W, H, q, 1, K_MAGIC_6016, stream, K_MAGIC_262144, blk, mv)
36 vv_dec(pd, rd, W, H, q, stream, kb, blk, mv)
37 let ITER: i64 = 60
38 // encode (P) timing
39 let t0: i64 = sys_now_us(); var it: i64=0
40 while it < ITER { vv_enc(b, re, a, W, H, q, 0, K_MAGIC_6016, stream, K_MAGIC_262144, blk, mv); it=it+1 }
41 let encus: i64 = (sys_now_us()-t0)/ITER
42 let pkb: i64 = vv_enc(b, re, a, W, H, q, 0, K_MAGIC_6016, stream, K_MAGIC_262144, blk, mv)
43 // decode timing
44 let t1: i64 = sys_now_us(); it=0
45 while it < ITER { vv_dec(pd, rd, W, H, q, stream, pkb, blk, mv); it=it+1 }
46 let decus: i64 = (sys_now_us()-t1)/ITER
47 // deblock ALONE (all 3 planes)
48 let t2: i64 = sys_now_us(); it=0
49 while it < ITER { vv_deblock(rd, W, H, q); it=it+1 }
50 let dblus: i64 = (sys_now_us()-t2)/ITER
51 gw(" " as *u8); gn(W); gw("x" as *u8); gn(H); gw(" q=" as *u8); gn(q)
52 gw(" P-enc=" as *u8); gn(encus); gw("us dec=" as *u8); gn(decus); gw("us deblock-alone=" as *u8); gn(dblus)
53 gw("us Pbytes=" as *u8); gn(pkb); gw(" (enc caps ~" as *u8); gn(K_MAGIC_1000000/(encus+1)); gw("fps)\n" as *u8)
54 return 0 }
55
56func main() -> i64 {
57 gw("=== nx_vcodec_timing_probe: per-frame CPU (enc incl deblock / dec / deblock-alone) ===\n" as *u8)
58 run(256, 192, 10)
59 run(288, 224, 10)
60 run(288, 224, 24)
61 run(320, 240, 10)
62 gw("(deblock-alone shows what the filter costs; if enc caps >> 30fps the fps drop is elsewhere)\n" as *u8)
63 return 0 }