replicas-computer 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -7
- package/assets/desktop/replicas-chrome +7 -0
- package/dist/index.js +519 -422
- package/dist/stream-viewer.js +18 -3
- package/native/go.mod +3 -0
- package/native/internal/capture/fixture.go +130 -0
- package/native/internal/capture/native.go +462 -0
- package/native/internal/capture/native.h +31 -0
- package/native/internal/capture/native_test.go +22 -0
- package/native/internal/capture/options.go +7 -0
- package/native/internal/capture/yuv.go +55 -0
- package/native/internal/capture/yuv_fallback.go +23 -0
- package/native/main.go +105 -0
- package/native/options.go +52 -0
- package/package.json +11 -3
- package/patches/libjuice-ice-role-presence.patch +96 -0
- package/patches/libyuv-chroma-rounding.patch +83 -0
- package/scripts/build-capture.sh +30 -0
- package/scripts/build-webrtc.sh +1 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//go:build libyuv && capturetest
|
|
2
|
+
|
|
3
|
+
package capture
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"fmt"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
func TestPartialCapture(t *testing.T) {
|
|
11
|
+
for _, size := range [][2]int{{128, 96}, {94, 66}} {
|
|
12
|
+
for _, i420 := range []bool{true, false} {
|
|
13
|
+
for _, bt709 := range []bool{true, false} {
|
|
14
|
+
t.Run(fmt.Sprintf("%dx%d/i420=%t/bt709=%t", size[0], size[1], i420, bt709), func(t *testing.T) {
|
|
15
|
+
if err := checkPartialCapture(size[0], size[1], i420, bt709); err != nil {
|
|
16
|
+
t.Fatal(err)
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//go:build libyuv
|
|
2
|
+
|
|
3
|
+
package capture
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <X11/Xlib.h>
|
|
8
|
+
#include <libavutil/frame.h>
|
|
9
|
+
#include <libyuv/convert.h>
|
|
10
|
+
#include <libyuv/convert_from_argb.h>
|
|
11
|
+
#include <libyuv/row.h>
|
|
12
|
+
*/
|
|
13
|
+
import "C"
|
|
14
|
+
|
|
15
|
+
import (
|
|
16
|
+
"errors"
|
|
17
|
+
"unsafe"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const hasLibyuv = true
|
|
21
|
+
|
|
22
|
+
type colorMatrix struct{ pointer *C.struct_ArgbConstants }
|
|
23
|
+
|
|
24
|
+
func newColorMatrix(bt709 bool) (colorMatrix, error) {
|
|
25
|
+
var pointer unsafe.Pointer
|
|
26
|
+
if C.posix_memalign(&pointer, 64, C.sizeof_struct_ArgbConstants) != 0 {
|
|
27
|
+
return colorMatrix{}, errors.New("cannot allocate color matrix")
|
|
28
|
+
}
|
|
29
|
+
m := colorMatrix{(*C.struct_ArgbConstants)(pointer)}
|
|
30
|
+
*m.pointer = C.kArgbI601Constants
|
|
31
|
+
if bt709 {
|
|
32
|
+
*m.pointer = C.kArgbH709Constants
|
|
33
|
+
}
|
|
34
|
+
for i := range m.pointer.kAddUV {
|
|
35
|
+
m.pointer.kAddUV[i] += 128
|
|
36
|
+
}
|
|
37
|
+
return m, nil
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func (m colorMatrix) close() { C.free(unsafe.Pointer(m.pointer)) }
|
|
41
|
+
|
|
42
|
+
func (m colorMatrix) convert(im *C.XImage, f *C.AVFrame, x, y int) error {
|
|
43
|
+
chroma := 0
|
|
44
|
+
if f.format == C.AV_PIX_FMT_YUV420P {
|
|
45
|
+
chroma = 1
|
|
46
|
+
}
|
|
47
|
+
// The clipped, aligned region stays inside these native-owned image planes.
|
|
48
|
+
py := (*C.uint8_t)(unsafe.Add(unsafe.Pointer(f.data[0]), y*int(f.linesize[0])+x))
|
|
49
|
+
pu := (*C.uint8_t)(unsafe.Add(unsafe.Pointer(f.data[1]), (y>>chroma)*int(f.linesize[1])+(x>>chroma)))
|
|
50
|
+
pv := (*C.uint8_t)(unsafe.Add(unsafe.Pointer(f.data[2]), (y>>chroma)*int(f.linesize[2])+(x>>chroma)))
|
|
51
|
+
if chroma != 0 {
|
|
52
|
+
return avCheck(C.ARGBToI420Matrix((*C.uint8_t)(unsafe.Pointer(im.data)), im.bytes_per_line, py, f.linesize[0], pu, f.linesize[1], pv, f.linesize[2], m.pointer, im.width, im.height))
|
|
53
|
+
}
|
|
54
|
+
return avCheck(C.ARGBToI444Matrix((*C.uint8_t)(unsafe.Pointer(im.data)), im.bytes_per_line, py, f.linesize[0], pu, f.linesize[1], pv, f.linesize[2], m.pointer, im.width, im.height))
|
|
55
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//go:build !libyuv
|
|
2
|
+
|
|
3
|
+
package capture
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
#include <X11/Xlib.h>
|
|
7
|
+
#include <libavutil/frame.h>
|
|
8
|
+
*/
|
|
9
|
+
import "C"
|
|
10
|
+
|
|
11
|
+
import "errors"
|
|
12
|
+
|
|
13
|
+
const hasLibyuv = false
|
|
14
|
+
|
|
15
|
+
type colorMatrix struct{}
|
|
16
|
+
|
|
17
|
+
func newColorMatrix(bool) (colorMatrix, error) {
|
|
18
|
+
return colorMatrix{}, errors.New("libyuv unavailable")
|
|
19
|
+
}
|
|
20
|
+
func (colorMatrix) close() {}
|
|
21
|
+
func (colorMatrix) convert(*C.XImage, *C.AVFrame, int, int) error {
|
|
22
|
+
return errors.New("libyuv unavailable")
|
|
23
|
+
}
|
package/native/main.go
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"os"
|
|
6
|
+
"os/signal"
|
|
7
|
+
"syscall"
|
|
8
|
+
|
|
9
|
+
"github.com/replicas-group/replicas/computer-use/native/internal/capture"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func run(o capture.Options) error {
|
|
13
|
+
stop := make(chan os.Signal, 1)
|
|
14
|
+
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
|
|
15
|
+
defer signal.Stop(stop)
|
|
16
|
+
stream, err := capture.Open(o)
|
|
17
|
+
if err != nil {
|
|
18
|
+
return err
|
|
19
|
+
}
|
|
20
|
+
defer stream.Close()
|
|
21
|
+
started := capture.NowMicros()
|
|
22
|
+
last, lastKeyframe, reportAt := started-1000000, started-1000000, started
|
|
23
|
+
interval := int64((1000000 + o.FPS - 1) / o.FPS)
|
|
24
|
+
busyUS, captureUS, scaleUS, encodeUS, previousPTS := int64(0), int64(0), int64(0), int64(0), int64(-1)
|
|
25
|
+
dirty := true
|
|
26
|
+
number, changedFrames, sentFrames := 0, 0, 0
|
|
27
|
+
for {
|
|
28
|
+
select {
|
|
29
|
+
case <-stop:
|
|
30
|
+
return nil
|
|
31
|
+
default:
|
|
32
|
+
}
|
|
33
|
+
changed, err := stream.Changed()
|
|
34
|
+
if err != nil {
|
|
35
|
+
return err
|
|
36
|
+
}
|
|
37
|
+
dirty = dirty || changed
|
|
38
|
+
now := capture.NowMicros()
|
|
39
|
+
idleDue := last + max(interval, 200000)
|
|
40
|
+
if o.IntraRefresh == 0 {
|
|
41
|
+
idleDue = min(idleDue, lastKeyframe+int64(o.KeyframeMS)*1000)
|
|
42
|
+
}
|
|
43
|
+
due := max(last+interval, idleDue)
|
|
44
|
+
if dirty || number <= o.Warmup || number < 3 {
|
|
45
|
+
due = last + interval
|
|
46
|
+
}
|
|
47
|
+
if now < due {
|
|
48
|
+
if err = stream.Wait(due - now); err != nil {
|
|
49
|
+
return err
|
|
50
|
+
}
|
|
51
|
+
continue
|
|
52
|
+
}
|
|
53
|
+
copied, converted := now, now
|
|
54
|
+
if dirty {
|
|
55
|
+
copied, converted, err = stream.Capture(number == 0)
|
|
56
|
+
if err != nil {
|
|
57
|
+
return err
|
|
58
|
+
}
|
|
59
|
+
changedFrames++
|
|
60
|
+
dirty = false
|
|
61
|
+
}
|
|
62
|
+
pts := max(previousPTS+1, (now-started)*90/1000)
|
|
63
|
+
previousPTS = pts
|
|
64
|
+
keyframe := number == 0 || (o.Warmup > 0 && number == o.Warmup) || (o.IntraRefresh == 0 && now-lastKeyframe >= int64(o.KeyframeMS)*1000)
|
|
65
|
+
if keyframe {
|
|
66
|
+
lastKeyframe = now
|
|
67
|
+
}
|
|
68
|
+
if err = stream.Send(pts, keyframe); err != nil {
|
|
69
|
+
return err
|
|
70
|
+
}
|
|
71
|
+
ended := capture.NowMicros()
|
|
72
|
+
captureUS += copied - now
|
|
73
|
+
scaleUS += converted - copied
|
|
74
|
+
encodeUS += ended - converted
|
|
75
|
+
busyUS += ended - now
|
|
76
|
+
sentFrames++
|
|
77
|
+
number++
|
|
78
|
+
if now-last < interval*2 {
|
|
79
|
+
last += interval
|
|
80
|
+
} else {
|
|
81
|
+
last = now
|
|
82
|
+
}
|
|
83
|
+
if ended-reportAt >= 1000000 {
|
|
84
|
+
_, err = fmt.Fprintf(os.Stdout, "{\"elapsedMs\":%.3f,\"busyMs\":%.3f,\"captureMs\":%.3f,\"scaleMs\":%.3f,\"encodeMs\":%.3f,\"frames\":%d,\"changedFrames\":%d}\n", float64(ended-reportAt)/1000, float64(busyUS)/1000, float64(captureUS)/1000, float64(scaleUS)/1000, float64(encodeUS)/1000, sentFrames, changedFrames)
|
|
85
|
+
if err != nil {
|
|
86
|
+
return err
|
|
87
|
+
}
|
|
88
|
+
reportAt = ended
|
|
89
|
+
busyUS, captureUS, scaleUS, encodeUS = 0, 0, 0, 0
|
|
90
|
+
changedFrames, sentFrames = 0, 0
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
func main() {
|
|
96
|
+
o, err := parseOptions()
|
|
97
|
+
if err != nil {
|
|
98
|
+
fmt.Fprintln(os.Stderr, "capture:", err)
|
|
99
|
+
os.Exit(2)
|
|
100
|
+
}
|
|
101
|
+
if err = run(o); err != nil {
|
|
102
|
+
fmt.Fprintln(os.Stderr, "capture:", err)
|
|
103
|
+
os.Exit(1)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"errors"
|
|
5
|
+
"flag"
|
|
6
|
+
"fmt"
|
|
7
|
+
"os"
|
|
8
|
+
|
|
9
|
+
"github.com/replicas-group/replicas/computer-use/native/internal/capture"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func parseOptions() (capture.Options, error) {
|
|
13
|
+
o := capture.Options{}
|
|
14
|
+
f := flag.NewFlagSet("capture", flag.ContinueOnError)
|
|
15
|
+
numbers := []struct {
|
|
16
|
+
name string
|
|
17
|
+
value *int
|
|
18
|
+
initial, low, high int
|
|
19
|
+
}{
|
|
20
|
+
{"width", &o.Width, 0, 2, 8192}, {"height", &o.Height, 0, 2, 8192},
|
|
21
|
+
{"fps", &o.FPS, 60, 1, 240}, {"threads", &o.Threads, 4, 1, 16},
|
|
22
|
+
{"crf", &o.CRF, 14, 0, 51}, {"kbps", &o.Kbps, 20000, 1, 1000000},
|
|
23
|
+
{"keyframe-ms", &o.KeyframeMS, 1000, 1, 10000}, {"intra-refresh", &o.IntraRefresh, 1, 0, 1},
|
|
24
|
+
{"chroma-qp", &o.ChromaQP, 0, -12, 12}, {"warmup", &o.Warmup, 0, 0, 60},
|
|
25
|
+
{"payload", &o.Payload, 96, 0, 127}, {"bt709", &o.BT709, 1, 0, 1},
|
|
26
|
+
}
|
|
27
|
+
for _, n := range numbers {
|
|
28
|
+
f.IntVar(n.value, n.name, n.initial, "")
|
|
29
|
+
}
|
|
30
|
+
f.StringVar(&o.Preset, "preset", "superfast", "")
|
|
31
|
+
f.StringVar(&o.Profile, "profile", "main", "")
|
|
32
|
+
f.StringVar(&o.URL, "url", "", "")
|
|
33
|
+
f.StringVar(&o.SSRC, "ssrc", "", "")
|
|
34
|
+
if err := f.Parse(os.Args[1:]); err != nil {
|
|
35
|
+
return o, err
|
|
36
|
+
}
|
|
37
|
+
var invalid error
|
|
38
|
+
f.Visit(func(f *flag.Flag) {
|
|
39
|
+
for _, n := range numbers {
|
|
40
|
+
if n.name == f.Name && (*n.value < n.low || *n.value > n.high) {
|
|
41
|
+
invalid = fmt.Errorf("invalid --%s", n.name)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
if invalid != nil {
|
|
46
|
+
return o, invalid
|
|
47
|
+
}
|
|
48
|
+
if f.NArg() != 0 || o.Width == 0 || o.Height == 0 || o.URL == "" || o.SSRC == "" || o.Width%2 != 0 || o.Height%2 != 0 {
|
|
49
|
+
return o, errors.New("width, height, url and ssrc are required; dimensions must be even")
|
|
50
|
+
}
|
|
51
|
+
return o, nil
|
|
52
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "replicas-computer",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "Replicas workspace computer-use runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,14 +12,22 @@
|
|
|
12
12
|
"assets",
|
|
13
13
|
"scripts/build-webrtc.sh",
|
|
14
14
|
"patches/libdatachannel-dtls-bio.patch",
|
|
15
|
-
"patches/libdatachannel-nack-duplicates.patch"
|
|
15
|
+
"patches/libdatachannel-nack-duplicates.patch",
|
|
16
|
+
"patches/libjuice-ice-role-presence.patch",
|
|
17
|
+
"scripts/build-capture.sh",
|
|
18
|
+
"patches/libyuv-chroma-rounding.patch",
|
|
19
|
+
"native/go.mod",
|
|
20
|
+
"native/*.go",
|
|
21
|
+
"native/internal"
|
|
16
22
|
],
|
|
17
23
|
"scripts": {
|
|
18
24
|
"build": "bun run typecheck && tsup",
|
|
19
25
|
"typecheck": "tsc --noEmit",
|
|
20
26
|
"dev": "bun run src/index.ts",
|
|
21
27
|
"dev-pack": "bun run build && npm pack --pack-destination /tmp",
|
|
22
|
-
"prepublishOnly": "bun run build"
|
|
28
|
+
"prepublishOnly": "bun run build",
|
|
29
|
+
"build:capture": "bash scripts/build-capture.sh",
|
|
30
|
+
"test:capture": "bash scripts/build-capture.sh test"
|
|
23
31
|
},
|
|
24
32
|
"keywords": [
|
|
25
33
|
"replicas",
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
diff --git a/src/agent.c b/src/agent.c
|
|
2
|
+
--- a/src/agent.c
|
|
3
|
+
+++ b/src/agent.c
|
|
4
|
+
@@ -1437,7 +1437,7 @@
|
|
5
|
+
return -1;
|
|
6
|
+
|
|
7
|
+
ice_candidate_pair_t *pair = entry->pair;
|
|
8
|
+
- if (msg->ice_controlling == msg->ice_controlled) {
|
|
9
|
+
+ if (msg->has_ice_controlling == msg->has_ice_controlled) {
|
|
10
|
+
JLOG_WARN("Controlling and controlled attributes mismatch in request");
|
|
11
|
+
agent_send_stun_binding(agent, entry, STUN_CLASS_RESP_ERROR, 400, msg->transaction_id,
|
|
12
|
+
NULL);
|
|
13
|
+
@@ -1451,7 +1451,7 @@
|
|
14
|
+
// ERROR-CODE attribute with a value of 487 (Role Conflict) but retains its role.
|
|
15
|
+
// * If the agent's tiebreaker value is less than the contents of the ICE-CONTROLLING
|
|
16
|
+
// attribute, the agent switches to the controlled role.
|
|
17
|
+
- if (agent->mode == AGENT_MODE_CONTROLLING && msg->ice_controlling) {
|
|
18
|
+
+ if (agent->mode == AGENT_MODE_CONTROLLING && msg->has_ice_controlling) {
|
|
19
|
+
JLOG_WARN("ICE role conflict (both controlling)");
|
|
20
|
+
if (agent->ice_tiebreaker >= msg->ice_controlling) {
|
|
21
|
+
JLOG_DEBUG("Asking remote peer to switch roles");
|
|
22
|
+
@@ -1471,7 +1471,7 @@
|
|
23
|
+
// * If the agent's tiebreaker value is less than the contents of the ICE-CONTROLLED
|
|
24
|
+
// attribute, the agent generates a Binding error response and includes an ERROR-CODE
|
|
25
|
+
// attribute with a value of 487 (Role Conflict) but retains its role.
|
|
26
|
+
- if (agent->mode == AGENT_MODE_CONTROLLED && msg->ice_controlled) {
|
|
27
|
+
+ if (agent->mode == AGENT_MODE_CONTROLLED && msg->has_ice_controlled) {
|
|
28
|
+
JLOG_WARN("ICE role conflict (both controlled)");
|
|
29
|
+
if (agent->ice_tiebreaker >= msg->ice_controlling) {
|
|
30
|
+
JLOG_DEBUG("Switching to controlling role");
|
|
31
|
+
@@ -1485,7 +1485,7 @@
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
if (msg->use_candidate) {
|
|
35
|
+
- if (!msg->ice_controlling) {
|
|
36
|
+
+ if (!msg->has_ice_controlling) {
|
|
37
|
+
JLOG_WARN("STUN message use_candidate missing ice_controlling attribute");
|
|
38
|
+
agent_send_stun_binding(agent, entry, STUN_CLASS_RESP_ERROR, 400,
|
|
39
|
+
msg->transaction_id, NULL);
|
|
40
|
+
@@ -1715,6 +1715,8 @@
|
|
41
|
+
password = agent->remote.ice_pwd;
|
|
42
|
+
msg.ice_controlling = agent->mode == AGENT_MODE_CONTROLLING ? agent->ice_tiebreaker : 0;
|
|
43
|
+
msg.ice_controlled = agent->mode == AGENT_MODE_CONTROLLED ? agent->ice_tiebreaker : 0;
|
|
44
|
+
+ msg.has_ice_controlling = agent->mode == AGENT_MODE_CONTROLLING;
|
|
45
|
+
+ msg.has_ice_controlled = agent->mode == AGENT_MODE_CONTROLLED;
|
|
46
|
+
|
|
47
|
+
// RFC 8445 7.1.1. PRIORITY
|
|
48
|
+
// The PRIORITY attribute MUST be included in a Binding request and be set to the value
|
|
49
|
+
diff --git a/src/stun.c b/src/stun.c
|
|
50
|
+
--- a/src/stun.c
|
|
51
|
+
+++ b/src/stun.c
|
|
52
|
+
@@ -157,14 +157,14 @@
|
|
53
|
+
goto overflow;
|
|
54
|
+
pos += len;
|
|
55
|
+
}
|
|
56
|
+
- if (msg->ice_controlling) {
|
|
57
|
+
+ if (msg->has_ice_controlling || msg->ice_controlling) {
|
|
58
|
+
uint64_t ice_controlling = htonll(msg->ice_controlling);
|
|
59
|
+
len = stun_write_attr(pos, end - pos, STUN_ATTR_ICE_CONTROLLING, &ice_controlling, 8);
|
|
60
|
+
if (len <= 0)
|
|
61
|
+
goto overflow;
|
|
62
|
+
pos += len;
|
|
63
|
+
}
|
|
64
|
+
- if (msg->ice_controlled) {
|
|
65
|
+
+ if (msg->has_ice_controlled || msg->ice_controlled) {
|
|
66
|
+
uint64_t ice_controlled = htonll(msg->ice_controlled);
|
|
67
|
+
len = stun_write_attr(pos, end - pos, STUN_ATTR_ICE_CONTROLLED, &ice_controlled, 8);
|
|
68
|
+
if (len <= 0)
|
|
69
|
+
@@ -916,6 +916,7 @@
|
|
70
|
+
}
|
|
71
|
+
uint32_t *value32 = (uint32_t *)attr->value;
|
|
72
|
+
msg->ice_controlling = ((uint64_t)ntohl(value32[0]) << 32) | ntohl(value32[1]);
|
|
73
|
+
+ msg->has_ice_controlling = true;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case STUN_ATTR_ICE_CONTROLLED: {
|
|
77
|
+
@@ -926,6 +927,7 @@
|
|
78
|
+
}
|
|
79
|
+
uint32_t *value32 = (uint32_t *)attr->value;
|
|
80
|
+
msg->ice_controlled = ((uint64_t)ntohl(value32[0]) << 32) | ntohl(value32[1]);
|
|
81
|
+
+ msg->has_ice_controlled = true;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case STUN_ATTR_CHANNEL_NUMBER: {
|
|
85
|
+
diff --git a/src/stun.h b/src/stun.h
|
|
86
|
+
--- a/src/stun.h
|
|
87
|
+
+++ b/src/stun.h
|
|
88
|
+
@@ -319,6 +319,8 @@
|
|
89
|
+
uint32_t priority;
|
|
90
|
+
uint64_t ice_controlling;
|
|
91
|
+
uint64_t ice_controlled;
|
|
92
|
+
+ bool has_ice_controlling;
|
|
93
|
+
+ bool has_ice_controlled;
|
|
94
|
+
bool use_candidate;
|
|
95
|
+
addr_record_t mapped;
|
|
96
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
diff --git a/source/row_gcc.cc b/source/row_gcc.cc
|
|
2
|
+
index 90d6786..f52e61b 100644
|
|
3
|
+
--- a/source/row_gcc.cc
|
|
4
|
+
+++ b/source/row_gcc.cc
|
|
5
|
+
@@ -1969,8 +1969,7 @@ void ARGBToUV444MatrixRow_SSSE3(const uint8_t* src_argb,
|
|
6
|
+
int width,
|
|
7
|
+
const struct ArgbConstants* c) {
|
|
8
|
+
asm volatile(
|
|
9
|
+
- "pcmpeqb %%xmm5,%%xmm5 \n" // 0x8000
|
|
10
|
+
- "psllw $15,%%xmm5 \n"
|
|
11
|
+
+ "movdqa 0x80(%4),%%xmm5 \n"
|
|
12
|
+
"movdqa 0x20(%4),%%xmm3 \n" // kRGBToU
|
|
13
|
+
"movdqa 0x40(%4),%%xmm4 \n" // kRGBToV
|
|
14
|
+
"sub %1,%2 \n"
|
|
15
|
+
@@ -2042,8 +2041,7 @@ void ARGBToUV444MatrixRow_AVX2(const uint8_t* src_argb,
|
|
16
|
+
asm volatile(
|
|
17
|
+
"vmovdqa 0x20(%4),%%ymm3 \n" // kRGBToU
|
|
18
|
+
"vmovdqa 0x40(%4),%%ymm4 \n" // kRGBToV
|
|
19
|
+
- "vpcmpeqb %%ymm5,%%ymm5,%%ymm5 \n" // 0x8000
|
|
20
|
+
- "vpsllw $15,%%ymm5,%%ymm5 \n"
|
|
21
|
+
+ "vmovdqa 0x80(%4),%%ymm5 \n"
|
|
22
|
+
"vmovdqa %5,%%ymm7 \n"
|
|
23
|
+
"sub %1,%2 \n"
|
|
24
|
+
|
|
25
|
+
@@ -2115,7 +2113,7 @@ void ARGBToUV444MatrixRow_AVX512BW(const uint8_t* src_argb,
|
|
26
|
+
"vbroadcasti32x4 0x20(%4),%%zmm3 \n" // kRGBToU
|
|
27
|
+
"vbroadcasti32x4 0x40(%4),%%zmm4 \n" // kRGBToV
|
|
28
|
+
"vpternlogd $0xff,%%zmm16,%%zmm16,%%zmm16 \n" // -1
|
|
29
|
+
- "vpsllw $15,%%zmm16,%%zmm5 \n" // 0x8000
|
|
30
|
+
+ "vbroadcasti32x4 0x80(%4),%%zmm5 \n"
|
|
31
|
+
"vmovups %5,%%zmm17 \n"
|
|
32
|
+
"sub %1,%2 \n"
|
|
33
|
+
|
|
34
|
+
@@ -2135,8 +2133,8 @@ void ARGBToUV444MatrixRow_AVX512BW(const uint8_t* src_argb,
|
|
35
|
+
"vpmaddwd %%zmm16,%%zmm18,%%zmm18 \n"
|
|
36
|
+
"vpackssdw %%zmm1,%%zmm0,%%zmm0 \n" // mutates
|
|
37
|
+
"vpackssdw %%zmm18,%%zmm2,%%zmm2 \n"
|
|
38
|
+
- "vpsubw %%zmm5,%%zmm0,%%zmm0 \n"
|
|
39
|
+
- "vpsubw %%zmm5,%%zmm2,%%zmm2 \n"
|
|
40
|
+
+ "vpaddw %%zmm5,%%zmm0,%%zmm0 \n"
|
|
41
|
+
+ "vpaddw %%zmm5,%%zmm2,%%zmm2 \n"
|
|
42
|
+
"vpsrlw $0x8,%%zmm0,%%zmm0 \n"
|
|
43
|
+
"vpsrlw $0x8,%%zmm2,%%zmm2 \n"
|
|
44
|
+
"vpackuswb %%zmm2,%%zmm0,%%zmm0 \n" // mutates
|
|
45
|
+
@@ -2157,8 +2155,8 @@ void ARGBToUV444MatrixRow_AVX512BW(const uint8_t* src_argb,
|
|
46
|
+
"vpmaddwd %%zmm16,%%zmm18,%%zmm18 \n"
|
|
47
|
+
"vpackssdw %%zmm1,%%zmm0,%%zmm0 \n" // mutates
|
|
48
|
+
"vpackssdw %%zmm18,%%zmm2,%%zmm2 \n"
|
|
49
|
+
- "vpsubw %%zmm5,%%zmm0,%%zmm0 \n"
|
|
50
|
+
- "vpsubw %%zmm5,%%zmm2,%%zmm2 \n"
|
|
51
|
+
+ "vpaddw %%zmm5,%%zmm0,%%zmm0 \n"
|
|
52
|
+
+ "vpaddw %%zmm5,%%zmm2,%%zmm2 \n"
|
|
53
|
+
"vpsrlw $0x8,%%zmm0,%%zmm0 \n"
|
|
54
|
+
"vpsrlw $0x8,%%zmm2,%%zmm2 \n"
|
|
55
|
+
"vpackuswb %%zmm2,%%zmm0,%%zmm0 \n" // mutates
|
|
56
|
+
@@ -2230,8 +2228,7 @@ void ARGBToUVMatrixRow_SSSE3(const uint8_t* src_argb,
|
|
57
|
+
"pavgw %%xmm2,%%xmm1 \n"
|
|
58
|
+
"packuswb %%xmm1,%%xmm0 \n" // mutates
|
|
59
|
+
|
|
60
|
+
- "movdqa %%xmm6,%%xmm2 \n"
|
|
61
|
+
- "psllw $15,%%xmm2 \n" // 0x8000
|
|
62
|
+
+ "movdqa 0x80(%5),%%xmm2 \n"
|
|
63
|
+
"movdqa %%xmm0,%%xmm1 \n"
|
|
64
|
+
"pmaddubsw %%xmm5,%%xmm1 \n" // 4 V
|
|
65
|
+
"pmaddubsw %%xmm4,%%xmm0 \n" // 4 U
|
|
66
|
+
@@ -2305,7 +2302,7 @@ void ARGBToUVMatrixRow_AVX2(const uint8_t* src_argb,
|
|
67
|
+
"vpackuswb %%ymm1,%%ymm0,%%ymm0 \n" // mutates
|
|
68
|
+
"vpermq $0xd8,%%ymm0,%%ymm0 \n" // 8 ARGB Pixels
|
|
69
|
+
|
|
70
|
+
- "vpsllw $15,%%ymm6,%%ymm2 \n" // 0x8000
|
|
71
|
+
+ "vmovdqa 0x80(%5),%%ymm2 \n"
|
|
72
|
+
"vpmaddubsw %%ymm5,%%ymm0,%%ymm1 \n" // 8 V
|
|
73
|
+
"vpmaddubsw %%ymm4,%%ymm0,%%ymm0 \n" // 8 U
|
|
74
|
+
"vphaddw %%ymm1,%%ymm0,%%ymm0 \n" // uuuuvvvv uuuuvvvv
|
|
75
|
+
@@ -2362,7 +2359,7 @@ void ARGBToUVMatrixRow_AVX512BW(const uint8_t* src_argb,
|
|
76
|
+
"vbroadcasti32x4 0x40(%5),%%zmm5 \n" // RGBToV
|
|
77
|
+
"vpternlogd $0xff,%%zmm16,%%zmm16,%%zmm16 \n"
|
|
78
|
+
"vpabsb %%zmm16,%%zmm20 \n" // 0x0101
|
|
79
|
+
- "vpsllw $15,%%zmm16,%%zmm17 \n" // 0x8000
|
|
80
|
+
+ "vbroadcasti32x4 0x80(%5),%%zmm17 \n"
|
|
81
|
+
"vbroadcasti32x4 %6,%%zmm21 \n" // kShuffleAARRGGBB
|
|
82
|
+
"vmovups %7,%%zmm18 \n" // kPermdARGBToY_AVX512BW
|
|
83
|
+
"vmovups %8,%%zmm19 \n" // kPermdARGBToUV_AVX512BW
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
package_dir="$(cd "$(dirname "$0")/.." && pwd)"
|
|
4
|
+
mkdir -p "$package_dir/dist"
|
|
5
|
+
export GOTOOLCHAIN=go1.27.1 CGO_ENABLED=1
|
|
6
|
+
build_tags=()
|
|
7
|
+
case "$("${CC:-cc}" -dumpmachine)" in
|
|
8
|
+
x86_64-*)
|
|
9
|
+
build_root="$(mktemp -d)"
|
|
10
|
+
trap 'rm -rf -- "$build_root"' EXIT
|
|
11
|
+
git init -q "$build_root/source"
|
|
12
|
+
git -C "$build_root/source" fetch --depth 1 https://chromium.googlesource.com/libyuv/libyuv 2dd4257364d39c38d79465c4ddc4b93137fe729b
|
|
13
|
+
git -C "$build_root/source" checkout -q --detach FETCH_HEAD
|
|
14
|
+
git -C "$build_root/source" apply "$package_dir/patches/libyuv-chroma-rounding.patch"
|
|
15
|
+
cmake -S "$build_root/source" -B "$build_root/build" -DCMAKE_BUILD_TYPE=Release -DLIBYUV_DISABLE_JPEG=ON -DUNIT_TEST=OFF
|
|
16
|
+
cmake --build "$build_root/build" --target yuv -j 2
|
|
17
|
+
export CGO_CFLAGS="${CGO_CFLAGS:--O2 -g} -I$build_root/source/include"
|
|
18
|
+
export CGO_LDFLAGS="${CGO_LDFLAGS:-} $build_root/build/libyuv.a -lstdc++ -lm"
|
|
19
|
+
build_tags=(-tags libyuv)
|
|
20
|
+
cp "$build_root/source/LICENSE" "$package_dir/dist/libyuv-LICENSE"
|
|
21
|
+
;;
|
|
22
|
+
esac
|
|
23
|
+
cd "$package_dir/native"
|
|
24
|
+
if [[ "${1:-}" == test ]]; then
|
|
25
|
+
[[ ${#build_tags[@]} -gt 0 ]] || { echo 'Partial capture tests require x86-64 libyuv' >&2; exit 1; }
|
|
26
|
+
GOEXPERIMENT=cgocheck2 xvfb-run -a -s '-screen 0 128x96x24 -nolisten tcp' go test -count=1 -tags libyuv,capturetest ./...
|
|
27
|
+
exit
|
|
28
|
+
fi
|
|
29
|
+
go build -mod=readonly -trimpath -ldflags='-s -w' "${build_tags[@]}" -o "$package_dir/dist/replicas-capture.new" .
|
|
30
|
+
mv "$package_dir/dist/replicas-capture.new" "$package_dir/dist/replicas-capture"
|
package/scripts/build-webrtc.sh
CHANGED
|
@@ -19,6 +19,7 @@ git -C "$source_dir" checkout -q --detach FETCH_HEAD
|
|
|
19
19
|
git -C "$source_dir" submodule update --init --recursive --depth 1
|
|
20
20
|
git -C "$source_dir" apply "$script_dir/../patches/libdatachannel-dtls-bio.patch"
|
|
21
21
|
git -C "$source_dir" apply "$script_dir/../patches/libdatachannel-nack-duplicates.patch"
|
|
22
|
+
git -C "$source_dir/deps/libjuice" apply "$script_dir/../patches/libjuice-ice-role-presence.patch"
|
|
22
23
|
|
|
23
24
|
cmake -S "$build_root" -B "$build_root/build" -G Ninja \
|
|
24
25
|
-DCMAKE_BUILD_TYPE=Release \
|