1package capi
2
3import (
4 "unsafe"
5
6 "github.com/bnema/purego"
7)
8
9// The generated bindings call C through purego.RegisterLibFunc, whose
10// reflect-based wrappers allocate on every call. The calls made once per
11// video frame (and once per loop iteration) must not allocate, so they go
12// through purego.Syscall6 instead: the methods below shadow the generated
13// adapter methods of the same name on defaultCAPI. Everything else keeps using
14// the generated bindings.
15//
16// All hot-path functions take only pointers/integers and return an integer
17// (or nothing), which is what Syscall6 supports.
18var (
19 symLoopGetFd uintptr
20 symLoopEnter uintptr
21 symLoopLeave uintptr
22 symLoopIterate uintptr
23 symStreamDequeueBuffer uintptr
24 symStreamQueueBuffer uintptr
25 symStreamReturnBuffer uintptr
26 symStreamTrigger uintptr
27)
28
29func registerVideoFast(handle uintptr) error {
30 for _, s := range []struct {
31 dst *uintptr
32 name string
33 }{
34 {&symLoopGetFd, "pw_loop_get_fd"},
35 {&symLoopEnter, "pw_loop_enter"},
36 {&symLoopLeave, "pw_loop_leave"},
37 {&symLoopIterate, "pw_loop_iterate"},
38 {&symStreamDequeueBuffer, "pw_stream_dequeue_buffer"},
39 {&symStreamQueueBuffer, "pw_stream_queue_buffer"},
40 {&symStreamReturnBuffer, "pw_stream_return_buffer"},
41 {&symStreamTrigger, "pw_stream_trigger_process"},
42 } {
43 addr, err := purego.Dlsym(handle, s.name)
44 if err != nil {
45 return err
46 }
47 *s.dst = addr
48 }
49 return nil
50}
51
52// uptr converts a C pointer returned as an integer without a
53// uintptr-to-unsafe.Pointer conversion (the memory is owned by C).
54func uptr(v uintptr) unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&v)) }
55
56func (*defaultCAPI) PWLoopGetFd(loop unsafe.Pointer) int32 {
57 r, _, _ := purego.Syscall6(symLoopGetFd, uintptr(loop), 0, 0, 0, 0, 0)
58 return int32(r)
59}
60
61func (*defaultCAPI) PWLoopEnter(loop unsafe.Pointer) {
62 purego.Syscall6(symLoopEnter, uintptr(loop), 0, 0, 0, 0, 0)
63}
64
65func (*defaultCAPI) PWLoopLeave(loop unsafe.Pointer) {
66 purego.Syscall6(symLoopLeave, uintptr(loop), 0, 0, 0, 0, 0)
67}
68
69func (*defaultCAPI) PWLoopIterate(loop unsafe.Pointer, timeout int32) int32 {
70 r, _, _ := purego.Syscall6(symLoopIterate, uintptr(loop), uintptr(uint32(timeout)), 0, 0, 0, 0)
71 return int32(r)
72}
73
74func (*defaultCAPI) PWStreamDequeueBuffer(stream unsafe.Pointer) unsafe.Pointer {
75 r, _, _ := purego.Syscall6(symStreamDequeueBuffer, uintptr(stream), 0, 0, 0, 0, 0)
76 return uptr(r)
77}
78
79func (*defaultCAPI) PWStreamQueueBuffer(stream unsafe.Pointer, buffer unsafe.Pointer) int32 {
80 r, _, _ := purego.Syscall6(symStreamQueueBuffer, uintptr(stream), uintptr(buffer), 0, 0, 0, 0)
81 return int32(r)
82}
83
84func (*defaultCAPI) PWStreamReturnBuffer(stream unsafe.Pointer, buffer unsafe.Pointer) int32 {
85 r, _, _ := purego.Syscall6(symStreamReturnBuffer, uintptr(stream), uintptr(buffer), 0, 0, 0, 0)
86 return int32(r)
87}
88
89func (*defaultCAPI) PWStreamTriggerProcess(stream unsafe.Pointer) int32 {
90 r, _, _ := purego.Syscall6(symStreamTrigger, uintptr(stream), 0, 0, 0, 0, 0)
91 return int32(r)
92}