tirtc-devtools-cli 0.2.4 → 0.3.0
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 +9 -2
- package/USAGE.md +14 -0
- package/dist/cli/src/index.js +7 -0
- package/dist/cli/src/role_driver.js +88 -16
- package/dist/cli/src/role_live_log.d.ts +17 -0
- package/dist/cli/src/role_live_log.js +305 -0
- package/package.json +1 -1
- package/vendor/devtools/driver/linux-x64/devtools_driver_probe +0 -0
- package/vendor/devtools/driver/macos-arm64/devtools_driver_probe +0 -0
- package/vendor/runtime/linux-x64/include/tirtc/audio.h +1 -1
- package/vendor/runtime/linux-x64/include/tirtc/transport.h +0 -11
- package/vendor/runtime/linux-x64/include/tirtc/trp.h +3 -10
- package/vendor/runtime/linux-x64/include/tirtc/video_io_apple.h +14 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_facade.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_foundation_logging.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_media.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_transport.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_video.a +0 -0
- package/vendor/runtime/linux-x64/manifest.txt +10 -10
- package/vendor/runtime/macos-arm64/include/tirtc/audio.h +1 -1
- package/vendor/runtime/macos-arm64/include/tirtc/transport.h +0 -11
- package/vendor/runtime/macos-arm64/include/tirtc/trp.h +3 -10
- package/vendor/runtime/macos-arm64/include/tirtc/video_io_apple.h +14 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_audio.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_foundation_http.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_foundation_logging.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
- package/vendor/runtime/macos-arm64/manifest.txt +12 -12
package/README.md
CHANGED
|
@@ -57,8 +57,10 @@ node products/cli/bin/tirtc-devtools-cli.js --json device start \
|
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
`device start` 默认持续运行直到用户结束进程;需要自动化限时时再显式传
|
|
60
|
-
`--duration-ms <ms
|
|
61
|
-
|
|
60
|
+
`--duration-ms <ms>`。运行期间 CLI 会把启动、listener ready、client 连接 / 断开、
|
|
61
|
+
首个音视频包与周期运行状态写到 stderr;`--json` 的结构化 envelope 仍只写 stdout。
|
|
62
|
+
prepared asset 会按完整音视频轨循环,任一轨到达源文件末尾时 audio/video 同步回到
|
|
63
|
+
源头并保持 PTS 继续递增。
|
|
62
64
|
|
|
63
65
|
`device start` 的启动成功条件是 device listener 已就绪;客户端是否已经扫码连接不属于
|
|
64
66
|
device 启动失败条件。没有 client 时命令会继续常驻,直到用户结束进程或显式
|
|
@@ -70,6 +72,11 @@ native role 失败时,`reason_code` 与 `failed_stage` 仍是主失败事实
|
|
|
70
72
|
只说明失败现场日志是否已上传。上传成功时,CLI JSON 与 `summary.json` 会包含
|
|
71
73
|
可用于后续抓取的 `log_id`。
|
|
72
74
|
|
|
75
|
+
`device start` 与 `client start` 启动的 native role 默认 echo 收到的 command:
|
|
76
|
+
收到任意 command 后,用同一个 command id 与同一 payload 原样回发。CLI 不新增
|
|
77
|
+
额外控制命令或开关;`summary.json` 与 `--json` envelope 会包含 `command_echo`
|
|
78
|
+
evidence,用于确认 command 收发面已被覆盖。
|
|
79
|
+
|
|
73
80
|
打包入口:
|
|
74
81
|
|
|
75
82
|
```sh
|
package/USAGE.md
CHANGED
|
@@ -131,6 +131,11 @@ By default `device start` keeps running until the process is stopped. Use
|
|
|
131
131
|
full audio/video source cycle; when either track reaches the source end, both
|
|
132
132
|
tracks restart from offset 0 while PTS keeps increasing.
|
|
133
133
|
|
|
134
|
+
While the device process is running, CLI writes human-readable lifecycle logs to
|
|
135
|
+
stderr: startup, listener readiness, client connect/disconnect, first audio/video
|
|
136
|
+
packet, and periodic running status. With `--json`, the final machine-readable
|
|
137
|
+
envelope remains on stdout.
|
|
138
|
+
|
|
134
139
|
`device start` is considered started once the device listener is ready. A
|
|
135
140
|
missing client is not a device startup failure. Without a connected client, the
|
|
136
141
|
process remains resident until it is stopped or an explicit `--duration-ms`
|
|
@@ -141,6 +146,10 @@ provided. That file is a local handoff artifact for CLI client, runtime sample
|
|
|
141
146
|
smoke, and validation automation. The token in that bootstrap is intended for
|
|
142
147
|
one client connection.
|
|
143
148
|
|
|
149
|
+
`device start` starts a native role that echoes every received command with the
|
|
150
|
+
same command id and payload. No extra CLI command or option is required.
|
|
151
|
+
`summary.json` and the `--json` envelope include `command_echo` evidence.
|
|
152
|
+
|
|
144
153
|
`bootstrap.json` is not a mobile SDK connection protocol. For phone debugging,
|
|
145
154
|
use token/license QR today; a full session QR or deeplink is a separate product
|
|
146
155
|
slice.
|
|
@@ -155,6 +164,11 @@ node products/cli/bin/tirtc-devtools-cli.js --json client start \
|
|
|
155
164
|
|
|
156
165
|
Client writes `summary.json`, `events.jsonl`, runtime logs, and `render/first-video-frame.*` for `frame_dump`.
|
|
157
166
|
|
|
167
|
+
The native client role also echoes every received command with the same command
|
|
168
|
+
id and payload. `summary.json` and the `--json` envelope include `command_echo`
|
|
169
|
+
evidence, so command receive and reply coverage is visible in normal CLI
|
|
170
|
+
artifacts.
|
|
171
|
+
|
|
158
172
|
`client start --bootstrap` is meant for the local computer-to-computer DevTools
|
|
159
173
|
flow. Mobile clients should not be required to fetch a local JSON file from the
|
|
160
174
|
developer machine.
|
package/dist/cli/src/index.js
CHANGED
|
@@ -139,6 +139,10 @@ Missing flags are read from TIRTC_DEVICE_ID, TIRTC_DEVICE_SECRET_KEY, and TIRTC_
|
|
|
139
139
|
|
|
140
140
|
device start succeeds once the device listener is ready. It keeps running without a client until
|
|
141
141
|
the process is stopped or an explicit --duration-ms deadline is reached.
|
|
142
|
+
Runtime lifecycle logs are written to stderr. With --json, the final envelope remains on stdout.
|
|
143
|
+
|
|
144
|
+
The native device role echoes every received command with the same command id and payload.
|
|
145
|
+
summary.json and the --json envelope include command_echo evidence.
|
|
142
146
|
|
|
143
147
|
bootstrap.json is a local handoff artifact for client/sample/validation automation.
|
|
144
148
|
It is only written when --client-token-json is provided.
|
|
@@ -170,6 +174,9 @@ Examples:
|
|
|
170
174
|
|
|
171
175
|
bootstrap.json is expected to come from a local device start run.
|
|
172
176
|
For mobile device debugging, use token/license QR or a future session QR/deeplink.
|
|
177
|
+
|
|
178
|
+
The native client role echoes every received command with the same command id and payload.
|
|
179
|
+
summary.json and the --json envelope include command_echo evidence.
|
|
173
180
|
`)
|
|
174
181
|
.action((commandOptions) => {
|
|
175
182
|
runAndExit((0, role_driver_1.runClientStart)(commandOptions, getCliOptions()));
|
|
@@ -11,6 +11,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
11
11
|
const os_1 = __importDefault(require("os"));
|
|
12
12
|
const path_1 = __importDefault(require("path"));
|
|
13
13
|
const embedded_paths_1 = require("./embedded_paths");
|
|
14
|
+
const role_live_log_1 = require("./role_live_log");
|
|
14
15
|
const defaultAudioStreamId = 10;
|
|
15
16
|
const defaultVideoStreamId = 11;
|
|
16
17
|
const defaultConnectTimeoutMs = 10000;
|
|
@@ -166,7 +167,11 @@ function redactRequestValue(value) {
|
|
|
166
167
|
}
|
|
167
168
|
const result = {};
|
|
168
169
|
for (const [key, child] of Object.entries(value)) {
|
|
169
|
-
if (key === 'license' ||
|
|
170
|
+
if (key === 'license' ||
|
|
171
|
+
key === 'token' ||
|
|
172
|
+
key === 'client_token' ||
|
|
173
|
+
key === 'device_secret_key' ||
|
|
174
|
+
key === 'secret_key') {
|
|
170
175
|
result[key] = '[REDACTED]';
|
|
171
176
|
}
|
|
172
177
|
else {
|
|
@@ -312,8 +317,8 @@ function buildDeviceRequest(roots, artifactRoot, options) {
|
|
|
312
317
|
role: 'device',
|
|
313
318
|
endpoint: deviceIdentity.endpoint,
|
|
314
319
|
identity: {
|
|
315
|
-
license: deviceIdentity.deviceId + ',' + deviceIdentity.deviceSecretKey,
|
|
316
320
|
device_id: deviceIdentity.deviceId,
|
|
321
|
+
device_secret_key: deviceIdentity.deviceSecretKey,
|
|
317
322
|
},
|
|
318
323
|
bootstrap,
|
|
319
324
|
streams: {
|
|
@@ -402,7 +407,58 @@ function buildClientRequest(roots, artifactRoot, options) {
|
|
|
402
407
|
probe: { app_id: appId },
|
|
403
408
|
};
|
|
404
409
|
}
|
|
405
|
-
function
|
|
410
|
+
function installSignalForwarding(child, liveLog) {
|
|
411
|
+
const signals = ['SIGINT', 'SIGTERM'];
|
|
412
|
+
const removers = [];
|
|
413
|
+
let forwardedCount = 0;
|
|
414
|
+
for (const signal of signals) {
|
|
415
|
+
const handler = () => {
|
|
416
|
+
forwardedCount += 1;
|
|
417
|
+
liveLog.signalForwarded(signal);
|
|
418
|
+
if (!child.killed) {
|
|
419
|
+
child.kill(forwardedCount > 1 ? 'SIGKILL' : signal);
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
process.on(signal, handler);
|
|
423
|
+
removers.push(() => process.off(signal, handler));
|
|
424
|
+
}
|
|
425
|
+
return () => {
|
|
426
|
+
for (const remove of removers) {
|
|
427
|
+
remove();
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
function spawnDriverProcess(driverPath, args, stdoutFd, stderrFd, liveLog) {
|
|
432
|
+
return new Promise((resolve) => {
|
|
433
|
+
let child;
|
|
434
|
+
try {
|
|
435
|
+
child = child_process_1.default.spawn(driverPath, args, {
|
|
436
|
+
stdio: ['ignore', stdoutFd, stderrFd],
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
catch (error) {
|
|
440
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
441
|
+
liveLog.processError(normalized);
|
|
442
|
+
resolve({
|
|
443
|
+
status: null,
|
|
444
|
+
signal: null,
|
|
445
|
+
error: normalized,
|
|
446
|
+
});
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
let spawnError;
|
|
450
|
+
const removeSignalHandlers = installSignalForwarding(child, liveLog);
|
|
451
|
+
child.once('error', (error) => {
|
|
452
|
+
spawnError = error;
|
|
453
|
+
liveLog.processError(error);
|
|
454
|
+
});
|
|
455
|
+
child.once('close', (code, signal) => {
|
|
456
|
+
removeSignalHandlers();
|
|
457
|
+
resolve({ status: code, signal, error: spawnError });
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
async function runDriver(role, request, artifactRoot, roots) {
|
|
406
462
|
const platform = resolveRuntimePlatform();
|
|
407
463
|
const driverPath = resolveDriverPath(roots, platform);
|
|
408
464
|
const runtimeRoot = resolveRuntimeRoot(roots, platform);
|
|
@@ -428,26 +484,41 @@ function runDriver(request, artifactRoot, roots) {
|
|
|
428
484
|
}
|
|
429
485
|
const requestTempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'tirtc-devtools-cli-request-'));
|
|
430
486
|
const requestPath = path_1.default.join(requestTempDir, 'request.json');
|
|
487
|
+
const summaryPath = path_1.default.join(artifactRoot, 'summary.json');
|
|
488
|
+
fs_1.default.rmSync(summaryPath, { force: true });
|
|
489
|
+
fs_1.default.rmSync(path_1.default.join(artifactRoot, 'events.jsonl'), { force: true });
|
|
431
490
|
writeJson(requestPath, request);
|
|
432
491
|
writeJson(path_1.default.join(artifactRoot, 'request.redacted.json'), redactRequestValue(request));
|
|
433
492
|
const stdoutFd = fs_1.default.openSync(path_1.default.join(artifactRoot, 'stdout.log'), 'w');
|
|
434
493
|
const stderrFd = fs_1.default.openSync(path_1.default.join(artifactRoot, 'stderr.log'), 'w');
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
stdio: ['ignore', stdoutFd, stderrFd],
|
|
494
|
+
const liveLog = (0, role_live_log_1.startRoleLiveLog)({
|
|
495
|
+
role,
|
|
496
|
+
artifactRoot,
|
|
497
|
+
request,
|
|
498
|
+
runtimeRoot,
|
|
499
|
+
assetRoot,
|
|
442
500
|
});
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
501
|
+
let result = { status: null, signal: null };
|
|
502
|
+
try {
|
|
503
|
+
result = await spawnDriverProcess(driverPath, [
|
|
504
|
+
'--request', requestPath,
|
|
505
|
+
'--runtime-root', runtimeRoot,
|
|
506
|
+
'--asset-root', assetRoot,
|
|
507
|
+
'--artifact-root', artifactRoot,
|
|
508
|
+
], stdoutFd, stderrFd, liveLog);
|
|
509
|
+
liveLog.processExit(result.status, result.signal);
|
|
510
|
+
}
|
|
511
|
+
finally {
|
|
512
|
+
fs_1.default.closeSync(stdoutFd);
|
|
513
|
+
fs_1.default.closeSync(stderrFd);
|
|
514
|
+
fs_1.default.rmSync(requestTempDir, { recursive: true, force: true });
|
|
515
|
+
liveLog.stop();
|
|
516
|
+
}
|
|
447
517
|
if (!pathExists(summaryPath)) {
|
|
448
518
|
const message = result.error instanceof Error
|
|
449
519
|
? result.error.message
|
|
450
|
-
: 'driver exited without summary: status=' + String(result.status)
|
|
520
|
+
: 'driver exited without summary: status=' + String(result.status) +
|
|
521
|
+
' signal=' + String(result.signal ?? 'none');
|
|
451
522
|
if (result.error) {
|
|
452
523
|
throw new RoleCommandError('artifact_write_failed', 'artifact', roleFailedExitCode, message);
|
|
453
524
|
}
|
|
@@ -472,7 +543,7 @@ async function runRole(role, commandOptions, options) {
|
|
|
472
543
|
const request = role === 'device' ?
|
|
473
544
|
buildDeviceRequest(roots, artifactRoot, commandOptions) :
|
|
474
545
|
buildClientRequest(roots, artifactRoot, commandOptions);
|
|
475
|
-
const summary = runDriver(request, artifactRoot, roots);
|
|
546
|
+
const summary = await runDriver(role, request, artifactRoot, roots);
|
|
476
547
|
const summaryPath = path_1.default.join(artifactRoot, 'summary.json');
|
|
477
548
|
const data = {
|
|
478
549
|
status: summary.status,
|
|
@@ -486,6 +557,7 @@ async function runRole(role, commandOptions, options) {
|
|
|
486
557
|
failed_stage: failedStage(summary),
|
|
487
558
|
log_id: summary.log_upload?.log_id,
|
|
488
559
|
log_upload: summary.log_upload,
|
|
560
|
+
command_echo: summary.command_echo,
|
|
489
561
|
};
|
|
490
562
|
if (summary.exit_code === 0 && summary.status === 'completed') {
|
|
491
563
|
printEnvelope(options, 0, 'OK', data);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type RoleLiveLogOptions = {
|
|
2
|
+
role: 'device' | 'client';
|
|
3
|
+
artifactRoot: string;
|
|
4
|
+
request: Record<string, unknown>;
|
|
5
|
+
runtimeRoot: string;
|
|
6
|
+
assetRoot: string;
|
|
7
|
+
heartbeatIntervalMs?: number;
|
|
8
|
+
pollIntervalMs?: number;
|
|
9
|
+
emit?: (message: string) => void;
|
|
10
|
+
};
|
|
11
|
+
export type RoleLiveLogHandle = {
|
|
12
|
+
processError(error: Error): void;
|
|
13
|
+
processExit(code: number | null, signal: NodeJS.Signals | null): void;
|
|
14
|
+
signalForwarded(signal: NodeJS.Signals): void;
|
|
15
|
+
stop(): void;
|
|
16
|
+
};
|
|
17
|
+
export declare function startRoleLiveLog(options: RoleLiveLogOptions): RoleLiveLogHandle;
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.startRoleLiveLog = startRoleLiveLog;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const defaultHeartbeatIntervalMs = 5000;
|
|
10
|
+
const defaultPollIntervalMs = 500;
|
|
11
|
+
function asRecord(value) {
|
|
12
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
13
|
+
? value
|
|
14
|
+
: {};
|
|
15
|
+
}
|
|
16
|
+
function nestedRecord(root, key) {
|
|
17
|
+
return asRecord(root[key]);
|
|
18
|
+
}
|
|
19
|
+
function nestedString(root, first, second) {
|
|
20
|
+
const value = second === undefined ? root[first] : nestedRecord(root, first)[second];
|
|
21
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
22
|
+
}
|
|
23
|
+
function nestedNumber(root, first, second) {
|
|
24
|
+
const value = second === undefined ? root[first] : nestedRecord(root, first)[second];
|
|
25
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
26
|
+
}
|
|
27
|
+
function payloadString(payload, key) {
|
|
28
|
+
const value = payload[key];
|
|
29
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
30
|
+
}
|
|
31
|
+
function payloadNumber(payload, key) {
|
|
32
|
+
const value = payload[key];
|
|
33
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
34
|
+
}
|
|
35
|
+
function payloadBoolean(payload, key) {
|
|
36
|
+
const value = payload[key];
|
|
37
|
+
return typeof value === 'boolean' ? value : undefined;
|
|
38
|
+
}
|
|
39
|
+
function formatDurationMs(ms) {
|
|
40
|
+
if (ms < 1000) {
|
|
41
|
+
return String(ms) + 'ms';
|
|
42
|
+
}
|
|
43
|
+
return (ms / 1000).toFixed(1) + 's';
|
|
44
|
+
}
|
|
45
|
+
function formatDurationUs(us) {
|
|
46
|
+
if (us === undefined) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
return formatDurationMs(Math.round(us / 1000));
|
|
50
|
+
}
|
|
51
|
+
function sessionIndex(payload) {
|
|
52
|
+
return payloadNumber(payload, 'session_index');
|
|
53
|
+
}
|
|
54
|
+
function appendField(parts, name, value) {
|
|
55
|
+
if (value !== undefined) {
|
|
56
|
+
parts.push(name + '=' + String(value));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function makeNoopHandle() {
|
|
60
|
+
return {
|
|
61
|
+
processError: () => undefined,
|
|
62
|
+
processExit: () => undefined,
|
|
63
|
+
signalForwarded: () => undefined,
|
|
64
|
+
stop: () => undefined,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function startRoleLiveLog(options) {
|
|
68
|
+
if (options.role !== 'device') {
|
|
69
|
+
return makeNoopHandle();
|
|
70
|
+
}
|
|
71
|
+
const emit = options.emit ?? ((message) => console.error(message));
|
|
72
|
+
const startedAt = Date.now();
|
|
73
|
+
const eventsPath = path_1.default.join(options.artifactRoot, 'events.jsonl');
|
|
74
|
+
const summaryPath = path_1.default.join(options.artifactRoot, 'summary.json');
|
|
75
|
+
const request = options.request;
|
|
76
|
+
const stats = {
|
|
77
|
+
listenerReady: false,
|
|
78
|
+
sessionsStarted: 0,
|
|
79
|
+
sessionsEnded: 0,
|
|
80
|
+
firstAudioSessions: new Set(),
|
|
81
|
+
firstVideoSessions: new Set(),
|
|
82
|
+
};
|
|
83
|
+
let processedLineCount = 0;
|
|
84
|
+
let stopped = false;
|
|
85
|
+
const log = (message) => {
|
|
86
|
+
emit('[device] ' + message);
|
|
87
|
+
};
|
|
88
|
+
const media = nestedRecord(request, 'media');
|
|
89
|
+
const codec = payloadString(nestedRecord(media, 'video'), 'codec') ??
|
|
90
|
+
nestedString(request, 'video_codec') ?? 'unknown';
|
|
91
|
+
const sourcePath = payloadString(nestedRecord(media, 'source'), 'path') ?? options.assetRoot;
|
|
92
|
+
const durationMs = nestedNumber(request, 'run', 'duration_ms');
|
|
93
|
+
const deviceId = nestedString(request, 'identity', 'device_id') ?? 'unknown';
|
|
94
|
+
const endpoint = nestedString(request, 'endpoint') ?? 'unknown';
|
|
95
|
+
log('starting device driver device_id=' + deviceId +
|
|
96
|
+
' endpoint=' + endpoint +
|
|
97
|
+
' codec=' + codec +
|
|
98
|
+
' artifact_root=' + options.artifactRoot);
|
|
99
|
+
log('source=' + sourcePath + ' runtime_root=' + options.runtimeRoot);
|
|
100
|
+
if (durationMs === undefined) {
|
|
101
|
+
log('resident mode enabled; waiting for client connections until the process is stopped');
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
log('bounded mode enabled duration=' + formatDurationMs(durationMs));
|
|
105
|
+
}
|
|
106
|
+
const emitHeartbeat = () => {
|
|
107
|
+
const elapsed = Date.now() - startedAt;
|
|
108
|
+
const parts = [
|
|
109
|
+
'running',
|
|
110
|
+
'elapsed=' + formatDurationMs(elapsed),
|
|
111
|
+
'listener=' + (stats.listenerReady ? 'ready' : 'starting'),
|
|
112
|
+
'sessions=' + String(stats.sessionsStarted) + '/' + String(stats.sessionsEnded),
|
|
113
|
+
'active_session=' + (stats.activeSession ?? 'none'),
|
|
114
|
+
'first_audio_sessions=' + String(stats.firstAudioSessions.size),
|
|
115
|
+
'first_video_sessions=' + String(stats.firstVideoSessions.size),
|
|
116
|
+
];
|
|
117
|
+
appendField(parts, 'last_event', stats.lastEventKind);
|
|
118
|
+
log(parts.join(' '));
|
|
119
|
+
};
|
|
120
|
+
const emitEventLog = (event) => {
|
|
121
|
+
const kind = typeof event.kind === 'string' ? event.kind : undefined;
|
|
122
|
+
if (!kind) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const payload = asRecord(event.payload);
|
|
126
|
+
stats.lastEventKind = kind;
|
|
127
|
+
if (event.level === 'error') {
|
|
128
|
+
const reason = payloadString(payload, 'reason_code') ?? 'unknown';
|
|
129
|
+
log('driver event failed kind=' + kind + ' reason_code=' + reason);
|
|
130
|
+
}
|
|
131
|
+
switch (kind) {
|
|
132
|
+
case 'connection.listen.done':
|
|
133
|
+
stats.listenerReady = true;
|
|
134
|
+
log('listener ready; waiting for client connections');
|
|
135
|
+
break;
|
|
136
|
+
case 'bootstrap.write.done':
|
|
137
|
+
log('bootstrap written path=' + (payloadString(payload, 'path') ?? 'unknown'));
|
|
138
|
+
break;
|
|
139
|
+
case 'connection.connect.done': {
|
|
140
|
+
const session = sessionIndex(payload);
|
|
141
|
+
if (session !== undefined) {
|
|
142
|
+
stats.sessionsStarted = Math.max(stats.sessionsStarted, session);
|
|
143
|
+
stats.activeSession = session;
|
|
144
|
+
}
|
|
145
|
+
log('client connected session=' + (session ?? 'unknown'));
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
case 'connection.session.start': {
|
|
149
|
+
const session = sessionIndex(payload);
|
|
150
|
+
if (session !== undefined) {
|
|
151
|
+
stats.activeSession = session;
|
|
152
|
+
}
|
|
153
|
+
log('media session started session=' + (session ?? 'unknown'));
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case 'media.audio_send.start': {
|
|
157
|
+
const parts = ['audio input started'];
|
|
158
|
+
appendField(parts, 'session', sessionIndex(payload));
|
|
159
|
+
appendField(parts, 'stream_id', payloadNumber(payload, 'stream_id'));
|
|
160
|
+
appendField(parts, 'codec', payloadString(payload, 'codec'));
|
|
161
|
+
appendField(parts, 'sample_rate_hz', payloadNumber(payload, 'sample_rate_hz'));
|
|
162
|
+
log(parts.join(' '));
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case 'media.video_send.start': {
|
|
166
|
+
const parts = ['video input started'];
|
|
167
|
+
appendField(parts, 'session', sessionIndex(payload));
|
|
168
|
+
appendField(parts, 'stream_id', payloadNumber(payload, 'stream_id'));
|
|
169
|
+
appendField(parts, 'codec', payloadString(payload, 'codec'));
|
|
170
|
+
log(parts.join(' '));
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case 'media.asset_cycle.config': {
|
|
174
|
+
const parts = ['asset cycle ready'];
|
|
175
|
+
appendField(parts, 'session', sessionIndex(payload));
|
|
176
|
+
appendField(parts, 'audio_packets', payloadNumber(payload, 'audio_packet_count'));
|
|
177
|
+
appendField(parts, 'video_packets', payloadNumber(payload, 'video_packet_count'));
|
|
178
|
+
appendField(parts, 'cycle_duration', formatDurationUs(payloadNumber(payload, 'cycle_duration_us')));
|
|
179
|
+
log(parts.join(' '));
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case 'media.audio_send.session_first_packet': {
|
|
183
|
+
const session = sessionIndex(payload);
|
|
184
|
+
if (session !== undefined) {
|
|
185
|
+
stats.firstAudioSessions.add(session);
|
|
186
|
+
}
|
|
187
|
+
const parts = ['first audio packet sent'];
|
|
188
|
+
appendField(parts, 'session', session);
|
|
189
|
+
appendField(parts, 'pts_us', payloadNumber(payload, 'pts_us'));
|
|
190
|
+
appendField(parts, 'bytes', payloadNumber(payload, 'bytes'));
|
|
191
|
+
log(parts.join(' '));
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
case 'media.video_send.session_first_packet': {
|
|
195
|
+
const session = sessionIndex(payload);
|
|
196
|
+
if (session !== undefined) {
|
|
197
|
+
stats.firstVideoSessions.add(session);
|
|
198
|
+
}
|
|
199
|
+
const parts = ['first video packet sent'];
|
|
200
|
+
appendField(parts, 'session', session);
|
|
201
|
+
appendField(parts, 'codec', payloadString(payload, 'codec'));
|
|
202
|
+
appendField(parts, 'key_frame', payloadBoolean(payload, 'is_key_frame'));
|
|
203
|
+
appendField(parts, 'pts_us', payloadNumber(payload, 'pts_us'));
|
|
204
|
+
appendField(parts, 'bytes', payloadNumber(payload, 'bytes'));
|
|
205
|
+
log(parts.join(' '));
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
case 'connection.session.end': {
|
|
209
|
+
const session = sessionIndex(payload);
|
|
210
|
+
if (session !== undefined) {
|
|
211
|
+
stats.sessionsEnded = Math.max(stats.sessionsEnded, session);
|
|
212
|
+
if (stats.activeSession === session) {
|
|
213
|
+
stats.activeSession = undefined;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const disconnected = payloadBoolean(payload, 'disconnected');
|
|
217
|
+
const elapsed = payloadNumber(payload, 'elapsed_ms');
|
|
218
|
+
const parts = [disconnected ? 'client disconnected' : 'client session ended'];
|
|
219
|
+
appendField(parts, 'session', session);
|
|
220
|
+
appendField(parts, 'first_audio', payloadBoolean(payload, 'sent_first_audio'));
|
|
221
|
+
appendField(parts, 'first_video', payloadBoolean(payload, 'sent_first_video'));
|
|
222
|
+
appendField(parts, 'elapsed', elapsed === undefined ? undefined : formatDurationMs(elapsed));
|
|
223
|
+
log(parts.join(' '));
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
case 'connection.wait.no_client': {
|
|
227
|
+
const reason = payloadString(payload, 'reason') ?? 'unknown';
|
|
228
|
+
const elapsed = payloadNumber(payload, 'elapsed_ms');
|
|
229
|
+
log('no client connected before stop reason=' + reason +
|
|
230
|
+
(elapsed === undefined ? '' : ' elapsed=' + formatDurationMs(elapsed)));
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case 'driver.execution.finished': {
|
|
234
|
+
const status = payloadString(payload, 'status') ?? 'unknown';
|
|
235
|
+
const exitCode = payloadNumber(payload, 'exit_code');
|
|
236
|
+
const reason = payloadString(payload, 'reason_code') ?? 'unknown';
|
|
237
|
+
log('driver finished status=' + status +
|
|
238
|
+
' exit_code=' + String(exitCode ?? 'unknown') +
|
|
239
|
+
' reason_code=' + reason);
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
default:
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const pollEvents = (flushPartial = false) => {
|
|
247
|
+
if (!fs_1.default.existsSync(eventsPath)) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
let text = '';
|
|
251
|
+
try {
|
|
252
|
+
text = fs_1.default.readFileSync(eventsPath, 'utf8');
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const lines = text.split(/\r?\n/);
|
|
258
|
+
const completeLineCount = text.endsWith('\n')
|
|
259
|
+
? lines.length - 1
|
|
260
|
+
: (flushPartial ? lines.length : lines.length - 1);
|
|
261
|
+
for (let index = processedLineCount; index < completeLineCount; index += 1) {
|
|
262
|
+
const line = lines[index]?.trim();
|
|
263
|
+
if (!line) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
emitEventLog(JSON.parse(line));
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
if (flushPartial) {
|
|
271
|
+
log('skipped malformed driver event line=' + String(index + 1));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
processedLineCount = Math.max(processedLineCount, completeLineCount);
|
|
276
|
+
};
|
|
277
|
+
const pollTimer = setInterval(() => pollEvents(false), options.pollIntervalMs ?? defaultPollIntervalMs);
|
|
278
|
+
const heartbeatTimer = setInterval(emitHeartbeat, options.heartbeatIntervalMs ?? defaultHeartbeatIntervalMs);
|
|
279
|
+
return {
|
|
280
|
+
processError: (error) => {
|
|
281
|
+
pollEvents(true);
|
|
282
|
+
log('driver process error message=' + error.message);
|
|
283
|
+
},
|
|
284
|
+
processExit: (code, signal) => {
|
|
285
|
+
pollEvents(true);
|
|
286
|
+
const elapsed = Date.now() - startedAt;
|
|
287
|
+
log('process exited code=' + String(code ?? 'null') +
|
|
288
|
+
' signal=' + String(signal ?? 'none') +
|
|
289
|
+
' elapsed=' + formatDurationMs(elapsed) +
|
|
290
|
+
' summary=' + summaryPath);
|
|
291
|
+
},
|
|
292
|
+
signalForwarded: (signal) => {
|
|
293
|
+
log('forwarding signal=' + signal + ' to native driver');
|
|
294
|
+
},
|
|
295
|
+
stop: () => {
|
|
296
|
+
if (stopped) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
stopped = true;
|
|
300
|
+
clearInterval(pollTimer);
|
|
301
|
+
clearInterval(heartbeatTimer);
|
|
302
|
+
pollEvents(true);
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -101,7 +101,7 @@ typedef struct TirtcAudioOutputMetricsSnapshot {
|
|
|
101
101
|
*
|
|
102
102
|
* The snapshot is a caller-owned value copy. Zero-initialized fields mean the output has not yet
|
|
103
103
|
* observed a matching runtime fact or only cached zero-state is available. This diagnostic API is
|
|
104
|
-
* intended for UI/debug visibility and logs, not for
|
|
104
|
+
* intended for UI/debug visibility and logs, not for output control decisions.
|
|
105
105
|
*/
|
|
106
106
|
typedef struct TirtcAudioOutputDebugSnapshot {
|
|
107
107
|
TirtcMediaCodec codec;
|
|
@@ -289,17 +289,6 @@ typedef struct TirtcTransportConnCallbacks {
|
|
|
289
289
|
*/
|
|
290
290
|
TirtcError tirtc_transport_init(void);
|
|
291
291
|
|
|
292
|
-
/**
|
|
293
|
-
* @brief Enable/disable transport debug mode.
|
|
294
|
-
*
|
|
295
|
-
* When enabled, transport backend sets verbose vendor SDK log level during runtime init
|
|
296
|
-
* and applies it immediately if runtime is already initialized.
|
|
297
|
-
*
|
|
298
|
-
* @param enabled Non-zero to enable debug mode, zero to disable.
|
|
299
|
-
* @return Operation status.
|
|
300
|
-
*/
|
|
301
|
-
TirtcError tirtc_transport_enable_debug(uint8_t enabled);
|
|
302
|
-
|
|
303
292
|
/**
|
|
304
293
|
* @brief Uninitialize transport runtime.
|
|
305
294
|
*
|
|
@@ -25,19 +25,12 @@ typedef struct TirtcInitOptions {
|
|
|
25
25
|
|
|
26
26
|
} TirtcInitOptions;
|
|
27
27
|
|
|
28
|
-
typedef enum TirtcMediaSendPolicy {
|
|
29
|
-
|
|
30
|
-
TIRTC_MEDIA_SEND_POLICY_ON_REQUEST = 0,
|
|
31
|
-
|
|
32
|
-
TIRTC_MEDIA_SEND_POLICY_AUTO_ON_CONNECTED = 1,
|
|
33
|
-
} TirtcMediaSendPolicy;
|
|
34
|
-
|
|
35
28
|
typedef struct TirtcConnServiceStartOptions {
|
|
36
|
-
const char*
|
|
29
|
+
const char* device_id;
|
|
37
30
|
|
|
38
|
-
|
|
31
|
+
const char* device_secret_key;
|
|
39
32
|
|
|
40
|
-
|
|
33
|
+
uint32_t max_connections;
|
|
41
34
|
} TirtcConnServiceStartOptions;
|
|
42
35
|
|
|
43
36
|
typedef struct TirtcConnConnectOptions {
|
|
@@ -20,8 +20,17 @@ typedef enum TirtcVideoAppleWindowSlot {
|
|
|
20
20
|
TIRTC_VIDEO_APPLE_WINDOW_SLOT_RIGHT = 2,
|
|
21
21
|
} TirtcVideoAppleWindowSlot;
|
|
22
22
|
|
|
23
|
+
typedef enum TirtcVideoAppleCameraFacing {
|
|
24
|
+
TIRTC_VIDEO_APPLE_CAMERA_FACING_FRONT = 0,
|
|
25
|
+
TIRTC_VIDEO_APPLE_CAMERA_FACING_BACK = 1,
|
|
26
|
+
} TirtcVideoAppleCameraFacing;
|
|
27
|
+
|
|
23
28
|
typedef int (*TirtcVideoAppleOnPixelBufferFn)(void* pixel_buffer, void* user_data);
|
|
24
29
|
|
|
30
|
+
typedef struct TirtcVideoAppleAvFoundationVinOptions {
|
|
31
|
+
TirtcVideoAppleCameraFacing camera_facing;
|
|
32
|
+
} TirtcVideoAppleAvFoundationVinOptions;
|
|
33
|
+
|
|
25
34
|
typedef struct TirtcVideoAppleCoreVideoVoutOptions {
|
|
26
35
|
TirtcVideoAppleVoutTarget target;
|
|
27
36
|
TirtcVideoAppleOnPixelBufferFn on_pixel_buffer;
|
|
@@ -35,6 +44,11 @@ typedef struct TirtcVideoAppleCoreVideoVoutOptions {
|
|
|
35
44
|
uint32_t window_height;
|
|
36
45
|
} TirtcVideoAppleCoreVideoVoutOptions;
|
|
37
46
|
|
|
47
|
+
TirtcError tirtc_video_apple_create_avfoundation_vin(TirtcVideoVin** out_vin);
|
|
48
|
+
TirtcError tirtc_video_apple_avfoundation_vin_set_options(
|
|
49
|
+
TirtcVideoVin* vin, const TirtcVideoAppleAvFoundationVinOptions* options);
|
|
50
|
+
TirtcError tirtc_video_apple_avfoundation_vin_get_actual_facing(
|
|
51
|
+
TirtcVideoVin* vin, TirtcVideoAppleCameraFacing* out_camera_facing);
|
|
38
52
|
TirtcError tirtc_video_apple_create_core_video_vout(TirtcVideoVout** out_vout);
|
|
39
53
|
TirtcError tirtc_video_apple_core_video_vout_set_options(
|
|
40
54
|
TirtcVideoVout* vout, const TirtcVideoAppleCoreVideoVoutOptions* options);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
platform=linux-x64
|
|
2
2
|
profile=full
|
|
3
|
-
staged_at_utc=2026-05-
|
|
3
|
+
staged_at_utc=2026-05-07T08:43:43Z
|
|
4
4
|
source_sdk=/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.build/sdk/linux-x64
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
59ba10e0b7cc679d625d3e8c536e3e234b3173091b9859956252fe3dd631b774 include/tirtc/audio.h
|
|
7
7
|
6d972ccfe150a3b4f2d7f18fa92b3ade9210c1c8bb754d061ac6b7997b59e2cb include/tirtc/audio_codec.h
|
|
8
8
|
7bacbdb2d8bb10d6444036a8fef42f2a8e3ea34dfc38e165ee678d61f189db41 include/tirtc/audio_frame.h
|
|
9
9
|
fb8ea35263167c33487bd3aa503c26ed2dfbf97877f7bda92c10065cd5c97c13 include/tirtc/audio_io.h
|
|
@@ -21,25 +21,25 @@ ae805545a9515edc9b94262e72ad2c7b7d649288166f4daeb450d8a55e82ae0b include/tirtc/
|
|
|
21
21
|
7e2f7f81afe37e22f5414d9db32438edd948ff775230c3a0a17ff9ac1a0b560e include/tirtc/media_codec.h
|
|
22
22
|
ca63fe4fa0c787f20923e264e116fa6d7cb8194a227c03be4e9843d0ce5a9864 include/tirtc/media_downlink.h
|
|
23
23
|
e64191a39004165cdcd11b2ca824af34d4bfe02f7ec3c3101fa9291f56488c30 include/tirtc/media_uplink.h
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
93b85272f8fa606e048e40c0bd353440a46459180afcdaddd15b9a028dc26173 include/tirtc/transport.h
|
|
25
|
+
b932f3e930057843751e66d6b4eb9d8440ecdfd6634fd941abbe260eccfa056c include/tirtc/trp.h
|
|
26
26
|
92b3db6e2cb02265ad5db01881edce9d4e095b1dadf449dce5d8bb5362957e33 include/tirtc/video_codec.h
|
|
27
27
|
e51379666c199588cc33279ccf52248035d1cae3d1d468b1615ebf29f0b39c9c include/tirtc/video_frame.h
|
|
28
28
|
2a02645d82c58d433c7306a9f0bcd31d0f3e560b63822f7e80919761b81a6284 include/tirtc/video_io.h
|
|
29
29
|
9930dce5e8e2b12a1ab28ee91f3fb46f6cf3487e515ea2b4ec0e00009bd5f070 include/tirtc/video_io_android.h
|
|
30
|
-
|
|
30
|
+
f22127424d5978ab0644209b6c25c24e19e320dd2fbda6634e6344597ff7e2be include/tirtc/video_io_apple.h
|
|
31
31
|
cae0bbeb884e5466a56da15182c78cc22baab6c743f349a58d3595f623333585 include/tirtc/video_io_harmony.h
|
|
32
32
|
65b5d24fe3a6bc2a299a2220148a153ba4eb0955a49c1c3baabf1fdfed8aabdd include/tirtc/video_io_windows.h
|
|
33
33
|
8cd6b66bea14890a665cc317f8572429b2c3e4463773f8b77c1e4dc30a4a8747 include/tirtc/video_processing.h
|
|
34
34
|
ceb7cdd45efae57e5bd53d4177cb20c4a0cb9917fcdd23127b050d69c8b919ac lib/libTiRTC.a
|
|
35
35
|
b1f4135025cb8e8520a14268d831b9998920a4239f84bb6b409d0e4909fd5bee lib/libcrypto.a
|
|
36
36
|
296ba0b5efa9d2ac49e3bf278c5d467b31436e73fbc608b736e974bcf9759bde lib/libmatrix_runtime_audio.a
|
|
37
|
-
|
|
37
|
+
695c398eabef4f4227f1e7d7c8a46f3854b66e90d981d2580b664bf244977417 lib/libmatrix_runtime_facade.a
|
|
38
38
|
ec7bbf8e8744c6645a441a28e24e0645906152cc987d6fcca16af3c3badba940 lib/libmatrix_runtime_foundation_http.a
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
e41012346b8200eb6a722afc2e916f6365d32698768e1d176874a23add644b2c lib/libmatrix_runtime_foundation_logging.a
|
|
40
|
+
357a15ebff6afcf0c97073d19624434e62454ed463212d0d0298af2f370a7742 lib/libmatrix_runtime_media.a
|
|
41
|
+
41baae4526a1798e154c0e158a9539adc417d06e0e8193adab0c1a85cf784501 lib/libmatrix_runtime_transport.a
|
|
42
|
+
59476bb5dc78b9c89cb0663fe4490ad260625332fdc68cd83a3d52abf0f31b10 lib/libmatrix_runtime_video.a
|
|
43
43
|
511d521f7972df3993e5976d6e2dbcad7a6fbce9be15071274d0cbd9d51157f5 lib/libssl.a
|
|
44
44
|
a67ec9034848ef24a1b17671e444daa62a8f9e6b8319a1e932593908720ff2a1 lib/libwebrtc_apm.a
|
|
45
45
|
700e455255897e3cffab13ca593a6e4d9d11383ae609215cbbd6043a63d47161 lib/libxlog.a
|
|
@@ -101,7 +101,7 @@ typedef struct TirtcAudioOutputMetricsSnapshot {
|
|
|
101
101
|
*
|
|
102
102
|
* The snapshot is a caller-owned value copy. Zero-initialized fields mean the output has not yet
|
|
103
103
|
* observed a matching runtime fact or only cached zero-state is available. This diagnostic API is
|
|
104
|
-
* intended for UI/debug visibility and logs, not for
|
|
104
|
+
* intended for UI/debug visibility and logs, not for output control decisions.
|
|
105
105
|
*/
|
|
106
106
|
typedef struct TirtcAudioOutputDebugSnapshot {
|
|
107
107
|
TirtcMediaCodec codec;
|
|
@@ -289,17 +289,6 @@ typedef struct TirtcTransportConnCallbacks {
|
|
|
289
289
|
*/
|
|
290
290
|
TirtcError tirtc_transport_init(void);
|
|
291
291
|
|
|
292
|
-
/**
|
|
293
|
-
* @brief Enable/disable transport debug mode.
|
|
294
|
-
*
|
|
295
|
-
* When enabled, transport backend sets verbose vendor SDK log level during runtime init
|
|
296
|
-
* and applies it immediately if runtime is already initialized.
|
|
297
|
-
*
|
|
298
|
-
* @param enabled Non-zero to enable debug mode, zero to disable.
|
|
299
|
-
* @return Operation status.
|
|
300
|
-
*/
|
|
301
|
-
TirtcError tirtc_transport_enable_debug(uint8_t enabled);
|
|
302
|
-
|
|
303
292
|
/**
|
|
304
293
|
* @brief Uninitialize transport runtime.
|
|
305
294
|
*
|
|
@@ -25,19 +25,12 @@ typedef struct TirtcInitOptions {
|
|
|
25
25
|
|
|
26
26
|
} TirtcInitOptions;
|
|
27
27
|
|
|
28
|
-
typedef enum TirtcMediaSendPolicy {
|
|
29
|
-
|
|
30
|
-
TIRTC_MEDIA_SEND_POLICY_ON_REQUEST = 0,
|
|
31
|
-
|
|
32
|
-
TIRTC_MEDIA_SEND_POLICY_AUTO_ON_CONNECTED = 1,
|
|
33
|
-
} TirtcMediaSendPolicy;
|
|
34
|
-
|
|
35
28
|
typedef struct TirtcConnServiceStartOptions {
|
|
36
|
-
const char*
|
|
29
|
+
const char* device_id;
|
|
37
30
|
|
|
38
|
-
|
|
31
|
+
const char* device_secret_key;
|
|
39
32
|
|
|
40
|
-
|
|
33
|
+
uint32_t max_connections;
|
|
41
34
|
} TirtcConnServiceStartOptions;
|
|
42
35
|
|
|
43
36
|
typedef struct TirtcConnConnectOptions {
|
|
@@ -20,8 +20,17 @@ typedef enum TirtcVideoAppleWindowSlot {
|
|
|
20
20
|
TIRTC_VIDEO_APPLE_WINDOW_SLOT_RIGHT = 2,
|
|
21
21
|
} TirtcVideoAppleWindowSlot;
|
|
22
22
|
|
|
23
|
+
typedef enum TirtcVideoAppleCameraFacing {
|
|
24
|
+
TIRTC_VIDEO_APPLE_CAMERA_FACING_FRONT = 0,
|
|
25
|
+
TIRTC_VIDEO_APPLE_CAMERA_FACING_BACK = 1,
|
|
26
|
+
} TirtcVideoAppleCameraFacing;
|
|
27
|
+
|
|
23
28
|
typedef int (*TirtcVideoAppleOnPixelBufferFn)(void* pixel_buffer, void* user_data);
|
|
24
29
|
|
|
30
|
+
typedef struct TirtcVideoAppleAvFoundationVinOptions {
|
|
31
|
+
TirtcVideoAppleCameraFacing camera_facing;
|
|
32
|
+
} TirtcVideoAppleAvFoundationVinOptions;
|
|
33
|
+
|
|
25
34
|
typedef struct TirtcVideoAppleCoreVideoVoutOptions {
|
|
26
35
|
TirtcVideoAppleVoutTarget target;
|
|
27
36
|
TirtcVideoAppleOnPixelBufferFn on_pixel_buffer;
|
|
@@ -35,6 +44,11 @@ typedef struct TirtcVideoAppleCoreVideoVoutOptions {
|
|
|
35
44
|
uint32_t window_height;
|
|
36
45
|
} TirtcVideoAppleCoreVideoVoutOptions;
|
|
37
46
|
|
|
47
|
+
TirtcError tirtc_video_apple_create_avfoundation_vin(TirtcVideoVin** out_vin);
|
|
48
|
+
TirtcError tirtc_video_apple_avfoundation_vin_set_options(
|
|
49
|
+
TirtcVideoVin* vin, const TirtcVideoAppleAvFoundationVinOptions* options);
|
|
50
|
+
TirtcError tirtc_video_apple_avfoundation_vin_get_actual_facing(
|
|
51
|
+
TirtcVideoVin* vin, TirtcVideoAppleCameraFacing* out_camera_facing);
|
|
38
52
|
TirtcError tirtc_video_apple_create_core_video_vout(TirtcVideoVout** out_vout);
|
|
39
53
|
TirtcError tirtc_video_apple_core_video_vout_set_options(
|
|
40
54
|
TirtcVideoVout* vout, const TirtcVideoAppleCoreVideoVoutOptions* options);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
platform=macos-arm64
|
|
2
2
|
profile=full
|
|
3
|
-
staged_at_utc=2026-05-
|
|
3
|
+
staged_at_utc=2026-05-07T08:41:46Z
|
|
4
4
|
source_sdk=/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.build/sdk/macos-arm64
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
59ba10e0b7cc679d625d3e8c536e3e234b3173091b9859956252fe3dd631b774 include/tirtc/audio.h
|
|
7
7
|
6d972ccfe150a3b4f2d7f18fa92b3ade9210c1c8bb754d061ac6b7997b59e2cb include/tirtc/audio_codec.h
|
|
8
8
|
7bacbdb2d8bb10d6444036a8fef42f2a8e3ea34dfc38e165ee678d61f189db41 include/tirtc/audio_frame.h
|
|
9
9
|
fb8ea35263167c33487bd3aa503c26ed2dfbf97877f7bda92c10065cd5c97c13 include/tirtc/audio_io.h
|
|
@@ -21,13 +21,13 @@ ae805545a9515edc9b94262e72ad2c7b7d649288166f4daeb450d8a55e82ae0b include/tirtc/
|
|
|
21
21
|
7e2f7f81afe37e22f5414d9db32438edd948ff775230c3a0a17ff9ac1a0b560e include/tirtc/media_codec.h
|
|
22
22
|
ca63fe4fa0c787f20923e264e116fa6d7cb8194a227c03be4e9843d0ce5a9864 include/tirtc/media_downlink.h
|
|
23
23
|
e64191a39004165cdcd11b2ca824af34d4bfe02f7ec3c3101fa9291f56488c30 include/tirtc/media_uplink.h
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
93b85272f8fa606e048e40c0bd353440a46459180afcdaddd15b9a028dc26173 include/tirtc/transport.h
|
|
25
|
+
b932f3e930057843751e66d6b4eb9d8440ecdfd6634fd941abbe260eccfa056c include/tirtc/trp.h
|
|
26
26
|
92b3db6e2cb02265ad5db01881edce9d4e095b1dadf449dce5d8bb5362957e33 include/tirtc/video_codec.h
|
|
27
27
|
e51379666c199588cc33279ccf52248035d1cae3d1d468b1615ebf29f0b39c9c include/tirtc/video_frame.h
|
|
28
28
|
2a02645d82c58d433c7306a9f0bcd31d0f3e560b63822f7e80919761b81a6284 include/tirtc/video_io.h
|
|
29
29
|
9930dce5e8e2b12a1ab28ee91f3fb46f6cf3487e515ea2b4ec0e00009bd5f070 include/tirtc/video_io_android.h
|
|
30
|
-
|
|
30
|
+
f22127424d5978ab0644209b6c25c24e19e320dd2fbda6634e6344597ff7e2be include/tirtc/video_io_apple.h
|
|
31
31
|
cae0bbeb884e5466a56da15182c78cc22baab6c743f349a58d3595f623333585 include/tirtc/video_io_harmony.h
|
|
32
32
|
65b5d24fe3a6bc2a299a2220148a153ba4eb0955a49c1c3baabf1fdfed8aabdd include/tirtc/video_io_windows.h
|
|
33
33
|
8cd6b66bea14890a665cc317f8572429b2c3e4463773f8b77c1e4dc30a4a8747 include/tirtc/video_processing.h
|
|
@@ -35,13 +35,13 @@ cae0bbeb884e5466a56da15182c78cc22baab6c743f349a58d3595f623333585 include/tirtc/
|
|
|
35
35
|
8db86d6714264047e8fd4086ddd7315722d675749719e6175f89eb5a636b48a1 lib/libTiRTC.a
|
|
36
36
|
b39daee6a3d39bf0ca20c45084601133c4198de8dca848dcff6dd9c70ae99016 lib/libcrypto.a
|
|
37
37
|
c052857ef315e3d61db9c862cad10709a3a6b2487dc41799cbe4d74a805de875 lib/libcrypto.dylib
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
accd2ae1d507620e79a137fb3251bda8e4fd6323053c520d43cd4b2e8ae6b845 lib/libmatrix_runtime_audio.a
|
|
39
|
+
22063c50d962a70929ab890ce53c4b66dc166e6e4855b77346619d6547080f1e lib/libmatrix_runtime_facade.a
|
|
40
|
+
77f99950767a60f8b950acae0988ecc4c835a599f530ad1a158de32d2131f61d lib/libmatrix_runtime_foundation_http.a
|
|
41
|
+
182c56ff2263a8c5e392e1a49adc367a438cfda61d35b93db3861689fc03ca4c lib/libmatrix_runtime_foundation_logging.a
|
|
42
|
+
fc95129eabfb9cb46e17276cf1814e60d47f67991ea97128a32e6520b5b23674 lib/libmatrix_runtime_media.a
|
|
43
|
+
1d9ef883017e5a489191b02744aa81a74d4bc7ea2f1379e7e0c593b1e23ac731 lib/libmatrix_runtime_transport.a
|
|
44
|
+
339c27670947c3a546eedc1464f3d88998ba74434ce8ec0d0090f28bd0a140a3 lib/libmatrix_runtime_video.a
|
|
45
45
|
c11c65d373a127028350c41fa58cd2d1223f2b5d70a84e13b115d90daaba25ca lib/libssl.a
|
|
46
46
|
ef1c1104bbdd2528ed7b958fb7252bd6249875f92300b0c9577d6c4bd6c0d88a lib/libssl.dylib
|
|
47
47
|
e14e846e43d64e240fa0e5745bf4e702b79d0f2442e7f768beb990610735c71b lib/libtgrtc.dylib
|