tirtc-devtools-cli 0.0.15 → 0.1.1

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.
Files changed (64) hide show
  1. package/README.md +5 -1
  2. package/USAGE.md +6 -3
  3. package/dist/cli/src/index.js +19 -3
  4. package/dist/cli/src/media_assets.js +27 -6
  5. package/dist/cli/src/role_driver.js +8 -3
  6. package/package.json +1 -1
  7. package/vendor/devtools/driver/linux-x64/devtools_driver_probe +0 -0
  8. package/vendor/devtools/driver/macos-arm64/devtools_driver_probe +0 -0
  9. package/vendor/runtime/linux-x64/include/tirtc/audio.h +237 -0
  10. package/vendor/runtime/linux-x64/include/tirtc/audio_codec.h +23 -0
  11. package/vendor/runtime/linux-x64/include/tirtc/audio_frame.h +36 -0
  12. package/vendor/runtime/linux-x64/include/tirtc/audio_io.h +65 -0
  13. package/vendor/runtime/linux-x64/include/tirtc/audio_io_android.h +19 -0
  14. package/vendor/runtime/linux-x64/include/tirtc/audio_io_apple.h +19 -0
  15. package/vendor/runtime/linux-x64/include/tirtc/audio_io_harmony.h +19 -0
  16. package/vendor/runtime/linux-x64/include/tirtc/audio_io_windows.h +19 -0
  17. package/vendor/runtime/linux-x64/include/tirtc/audio_processing.h +56 -0
  18. package/vendor/runtime/linux-x64/include/tirtc/audio_sample_rate.h +18 -0
  19. package/vendor/runtime/linux-x64/include/tirtc/av.h +236 -0
  20. package/vendor/runtime/linux-x64/include/tirtc/error.h +102 -0
  21. package/vendor/runtime/linux-x64/include/tirtc/foundation/build_info.h +27 -0
  22. package/vendor/runtime/linux-x64/include/tirtc/http.h +57 -0
  23. package/vendor/runtime/linux-x64/include/tirtc/logging.h +55 -0
  24. package/vendor/runtime/linux-x64/include/tirtc/media_codec.h +21 -0
  25. package/vendor/runtime/linux-x64/include/tirtc/media_downlink.h +199 -0
  26. package/vendor/runtime/linux-x64/include/tirtc/media_uplink.h +120 -0
  27. package/vendor/runtime/linux-x64/include/tirtc/transport.h +445 -0
  28. package/vendor/runtime/linux-x64/include/tirtc/trp.h +187 -0
  29. package/vendor/runtime/linux-x64/include/tirtc/video_codec.h +112 -0
  30. package/vendor/runtime/linux-x64/include/tirtc/video_frame.h +55 -0
  31. package/vendor/runtime/linux-x64/include/tirtc/video_io.h +53 -0
  32. package/vendor/runtime/linux-x64/include/tirtc/video_io_android.h +34 -0
  33. package/vendor/runtime/linux-x64/include/tirtc/video_io_apple.h +47 -0
  34. package/vendor/runtime/linux-x64/include/tirtc/video_io_harmony.h +32 -0
  35. package/vendor/runtime/linux-x64/include/tirtc/video_io_windows.h +26 -0
  36. package/vendor/runtime/linux-x64/include/tirtc/video_processing.h +34 -0
  37. package/vendor/runtime/linux-x64/lib/libTiRTC.a +0 -0
  38. package/vendor/runtime/linux-x64/lib/libcrypto.a +0 -0
  39. package/vendor/runtime/linux-x64/lib/libmatrix_runtime_audio.a +0 -0
  40. package/vendor/runtime/linux-x64/lib/libmatrix_runtime_facade.a +0 -0
  41. package/vendor/runtime/linux-x64/lib/libmatrix_runtime_foundation_http.a +0 -0
  42. package/vendor/runtime/linux-x64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  43. package/vendor/runtime/linux-x64/lib/libmatrix_runtime_media.a +0 -0
  44. package/vendor/runtime/linux-x64/lib/libmatrix_runtime_transport.a +0 -0
  45. package/vendor/runtime/linux-x64/lib/libmatrix_runtime_video.a +0 -0
  46. package/vendor/runtime/linux-x64/lib/libssl.a +0 -0
  47. package/vendor/runtime/linux-x64/lib/libwebrtc_apm.a +0 -0
  48. package/vendor/runtime/linux-x64/lib/libxlog.a +0 -0
  49. package/vendor/runtime/linux-x64/manifest.txt +45 -0
  50. package/vendor/runtime/macos-arm64/include/tirtc/audio.h +21 -0
  51. package/vendor/runtime/macos-arm64/include/tirtc/av.h +28 -0
  52. package/vendor/runtime/macos-arm64/include/tirtc/error.h +41 -2
  53. package/vendor/runtime/macos-arm64/include/tirtc/media_downlink.h +45 -0
  54. package/vendor/runtime/macos-arm64/include/tirtc/video_codec.h +13 -0
  55. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_audio.a +0 -0
  56. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
  57. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_foundation_http.a +0 -0
  58. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  59. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
  60. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
  61. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
  62. package/vendor/runtime/macos-arm64/manifest.txt +13 -13
  63. package/vendor/runtime/script/prepare_runtime_media_dataset.sh +15 -0
  64. package/vendor/devtools/driver/macos-arm64/runtime_validation_client_bin +0 -0
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
  - 不提供长驻 Host、HTTP API、共享 session 或桌面 UI。
17
17
  - 不替代业务鉴权系统;token 签发只服务 DevTools 联调与验收。
18
18
  - 不把 `bootstrap.json` 定义成移动端接入协议;它只是本机 CLI receive、sample smoke 和 validation automation 的交接产物。
19
- - 不宣称 Linux native send/receive 调试已支持;当前外部调试发布面先按 `macos-arm64` 收口。
19
+ - 不提供长驻 Linux 服务端;Linux 调试发布面是 `linux-x64` native CLI/driver,运行在 Linux host 或 `linux/amd64` container。
20
20
 
21
21
  ## 依赖方向
22
22
 
@@ -56,6 +56,10 @@ node products/cli/bin/tirtc-devtools-cli.js --json send start \
56
56
  --artifact-root .build/devtools-cli/send-movie-h264
57
57
  ```
58
58
 
59
+ `send start` 默认持续运行直到用户结束进程;需要自动化限时时再显式传
60
+ `--duration-ms <ms>`。prepared asset 会按完整音视频轨循环,任一轨到达源文件末尾时
61
+ audio/video 同步回到源头并保持 PTS 继续递增。
62
+
59
63
  打包入口:
60
64
 
61
65
  ```sh
package/USAGE.md CHANGED
@@ -16,9 +16,7 @@ node products/cli/bin/tirtc-devtools-cli.js --help
16
16
  ## Platform Support
17
17
 
18
18
  - `macos-arm64`: supported for token, assets prepare, send, receive, package smoke, and native send+receive qualification.
19
- - `linux-x64`: runtime package surface and cross-build are covered, but native send/receive qualification is not a supported external debugging path yet.
20
-
21
- Do not treat Linux send/receive as ready until the Linux headless receive driver or a containerized online runner is delivered.
19
+ - `linux-x64`: supported for token, assets prepare, send, receive, package smoke, and native driver packaging. Linux native send/receive runs through the packaged headless driver on Linux hosts or `linux/amd64` containers.
22
20
 
23
21
  ## Token
24
22
 
@@ -112,6 +110,11 @@ node products/cli/bin/tirtc-devtools-cli.js --json send start \
112
110
  --artifact-root .build/devtools-cli/send-movie-h264
113
111
  ```
114
112
 
113
+ By default `send start` keeps running until the process is stopped. Use
114
+ `--duration-ms <ms>` only for bounded automation. Prepared assets loop over the
115
+ full audio/video source cycle; when either track reaches the source end, both
116
+ tracks restart from offset 0 while PTS keeps increasing.
117
+
115
118
  The send role writes `bootstrap.json`. That file is a local handoff artifact for
116
119
  CLI receive, runtime sample smoke, and validation automation. The token in that
117
120
  bootstrap is intended for one receive connection.
@@ -1,10 +1,26 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  const commander_1 = require("commander");
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const embedded_paths_1 = require("./embedded_paths");
4
10
  const media_assets_1 = require("./media_assets");
5
11
  const token_command_1 = require("./token_command");
6
12
  const role_driver_1 = require("./role_driver");
7
- const cliVersion = '0.0.14';
13
+ function resolveCliVersion() {
14
+ try {
15
+ const packageRoot = (0, embedded_paths_1.resolveCliPackageRoot)(__dirname);
16
+ const packageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(packageRoot, 'package.json'), 'utf8'));
17
+ return typeof packageJson.version === 'string' ? packageJson.version : 'unknown';
18
+ }
19
+ catch {
20
+ return 'unknown';
21
+ }
22
+ }
23
+ const cliVersion = resolveCliVersion();
8
24
  if (process.argv.includes('--version') || process.argv.includes('-V')) {
9
25
  console.log('CLI Version: ' + cliVersion);
10
26
  console.log('DevTools Driver Contract: 1');
@@ -101,7 +117,7 @@ send.command('start')
101
117
  .option('--remote-id <id>', 'server remote id;默认读取 TIRTC_DEVICE_ID')
102
118
  .option('--source <path>', 'prepared asset root、manifest_path 或 encoded track;MP4 先运行 assets prepare')
103
119
  .option('--video-codec <codec>', 'h264|h265|mjpeg', 'h264')
104
- .option('--duration-ms <ms>', 'role active 时长')
120
+ .option('--duration-ms <ms>', '可选自动结束时长;默认持续运行直到用户结束进程')
105
121
  .option('--connect-timeout-ms <ms>', 'service ready / connect 最大等待')
106
122
  .option('--first-packet-timeout-ms <ms>', '首包最大等待')
107
123
  .option('--bootstrap-token-json <path>', 'script/issue_devtools_token.sh --json 输出文件')
@@ -127,7 +143,7 @@ receive.command('start')
127
143
  .option('--video-stream-id <id>', '视频 stream id')
128
144
  .option('--consumer <consumer>', 'packet_dump|frame_dump', 'frame_dump')
129
145
  .option('--frame-limit <count>', 'frame_dump 帧数上限')
130
- .option('--duration-ms <ms>', 'role active 时长')
146
+ .option('--duration-ms <ms>', '可选自动结束时长;默认由输出条件或用户结束进程')
131
147
  .option('--connect-timeout-ms <ms>', 'connect 最大等待')
132
148
  .option('--first-packet-timeout-ms <ms>', '首包最大等待')
133
149
  .option('--first-output-timeout-ms <ms>', '首帧输出最大等待')
@@ -10,6 +10,14 @@ const path_1 = __importDefault(require("path"));
10
10
  const util_1 = require("util");
11
11
  const embedded_paths_1 = require("./embedded_paths");
12
12
  const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
13
+ class PrepareMediaAssetsError extends Error {
14
+ reasonCode;
15
+ constructor(message, reasonCode) {
16
+ super(message);
17
+ this.name = 'PrepareMediaAssetsError';
18
+ this.reasonCode = reasonCode;
19
+ }
20
+ }
13
21
  function resolveRepoRoot(fromDir) {
14
22
  const candidates = [
15
23
  path_1.default.resolve(fromDir, '../../..'),
@@ -36,23 +44,35 @@ function resolvePrepareScript(repoRoot) {
36
44
  }
37
45
  return path_1.default.join(repoRoot, 'runtime/script/prepare_runtime_media_dataset.sh');
38
46
  }
47
+ function normalizeExecErrorMessage(message) {
48
+ const prefix = '[prepare_runtime_media_dataset] error: ';
49
+ const normalized = message.startsWith(prefix) ? message.slice(prefix.length).trim() : message;
50
+ const reasonMatch = normalized.match(/^([a-z][a-z0-9_]*):\s*(.+)$/);
51
+ if (reasonMatch) {
52
+ return {
53
+ reasonCode: reasonMatch[1],
54
+ message: reasonMatch[2],
55
+ };
56
+ }
57
+ return { message: normalized };
58
+ }
39
59
  function parseExecError(error) {
40
60
  if (!error || typeof error !== 'object') {
41
- return String(error);
61
+ return normalizeExecErrorMessage(String(error));
42
62
  }
43
63
  const typed = error;
44
64
  const stderr = typeof typed.stderr === 'string' ? typed.stderr.trim() : typed.stderr?.toString('utf8').trim();
45
65
  if (stderr && stderr.length > 0) {
46
- return stderr;
66
+ return normalizeExecErrorMessage(stderr);
47
67
  }
48
68
  const stdout = typeof typed.stdout === 'string' ? typed.stdout.trim() : typed.stdout?.toString('utf8').trim();
49
69
  if (stdout && stdout.length > 0) {
50
- return stdout;
70
+ return normalizeExecErrorMessage(stdout);
51
71
  }
52
72
  if (typed.message && typed.message.length > 0) {
53
- return typed.message;
73
+ return normalizeExecErrorMessage(typed.message);
54
74
  }
55
- return 'process failed';
75
+ return { message: 'process failed' };
56
76
  }
57
77
  function assertPrepareRequest(request) {
58
78
  if (!request.source || request.source.trim().length === 0) {
@@ -99,7 +119,8 @@ async function prepareMediaAssets(request, options = {}) {
99
119
  stdout = String(result.stdout ?? '').trim();
100
120
  }
101
121
  catch (error) {
102
- throw new Error(parseExecError(error));
122
+ const parsed = parseExecError(error);
123
+ throw new PrepareMediaAssetsError(parsed.message, parsed.reasonCode);
103
124
  }
104
125
  let parsed;
105
126
  try {
@@ -14,7 +14,6 @@ const embedded_paths_1 = require("./embedded_paths");
14
14
  const token_tool_1 = require("./token_tool");
15
15
  const defaultAudioStreamId = 10;
16
16
  const defaultVideoStreamId = 11;
17
- const defaultDurationMs = 10000;
18
17
  const defaultConnectTimeoutMs = 10000;
19
18
  const defaultFirstPacketTimeoutMs = 10000;
20
19
  const defaultFirstOutputTimeoutMs = 12000;
@@ -137,6 +136,12 @@ function parsePositiveInt(raw, fallback, name) {
137
136
  }
138
137
  return parsed;
139
138
  }
139
+ function parseOptionalPositiveInt(raw, name) {
140
+ if (raw === undefined) {
141
+ return undefined;
142
+ }
143
+ return parsePositiveInt(raw, 1, name);
144
+ }
140
145
  function requireEnv(name) {
141
146
  const value = process.env[name]?.trim();
142
147
  if (!value) {
@@ -338,7 +343,7 @@ async function buildSendRequest(roots, artifactRoot, options) {
338
343
  },
339
344
  output: { consumer: 'frame_dump', video: { frame_limit: defaultFrameLimit } },
340
345
  run: {
341
- duration_ms: parsePositiveInt(options.durationMs, defaultDurationMs, '--duration-ms'),
346
+ duration_ms: parseOptionalPositiveInt(options.durationMs, '--duration-ms'),
342
347
  connect_timeout_ms: parsePositiveInt(options.connectTimeoutMs, defaultConnectTimeoutMs, '--connect-timeout-ms'),
343
348
  first_packet_timeout_ms: parsePositiveInt(options.firstPacketTimeoutMs, defaultFirstPacketTimeoutMs, '--first-packet-timeout-ms'),
344
349
  first_output_timeout_ms: defaultFirstOutputTimeoutMs,
@@ -386,7 +391,7 @@ function buildReceiveRequest(roots, artifactRoot, options) {
386
391
  video: { frame_limit: parsePositiveInt(options.frameLimit, defaultFrameLimit, '--frame-limit') },
387
392
  },
388
393
  run: {
389
- duration_ms: parsePositiveInt(options.durationMs, defaultDurationMs, '--duration-ms'),
394
+ duration_ms: parseOptionalPositiveInt(options.durationMs, '--duration-ms'),
390
395
  connect_timeout_ms: parsePositiveInt(options.connectTimeoutMs, defaultConnectTimeoutMs, '--connect-timeout-ms'),
391
396
  first_packet_timeout_ms: parsePositiveInt(options.firstPacketTimeoutMs, defaultFirstPacketTimeoutMs, '--first-packet-timeout-ms'),
392
397
  first_output_timeout_ms: parsePositiveInt(options.firstOutputTimeoutMs, defaultFirstOutputTimeoutMs, '--first-output-timeout-ms'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirtc-devtools-cli",
3
- "version": "0.0.15",
3
+ "version": "0.1.1",
4
4
  "private": false,
5
5
  "main": "dist/cli/src/index.js",
6
6
  "types": "dist/cli/src/index.d.ts",
@@ -0,0 +1,237 @@
1
+ #ifndef TIRTC_FACADE_AUDIO_H_
2
+ #define TIRTC_FACADE_AUDIO_H_
3
+
4
+ #include <stdint.h>
5
+
6
+ #include "tirtc/audio_frame.h"
7
+ #include "tirtc/audio_io.h"
8
+ #include "tirtc/audio_processing.h"
9
+ #include "tirtc/media_codec.h"
10
+ #include "tirtc/trp.h"
11
+
12
+ #ifdef __cplusplus
13
+ extern "C" {
14
+ #endif
15
+
16
+ typedef struct TirtcAudioInput TirtcAudioInput;
17
+
18
+ typedef struct TirtcAudioEncodedInput TirtcAudioEncodedInput;
19
+
20
+ typedef struct TirtcAudioOutput TirtcAudioOutput;
21
+
22
+ typedef enum TirtcInputState {
23
+
24
+ TIRTC_INPUT_STATE_IDLE = 0,
25
+
26
+ TIRTC_INPUT_STATE_RUNNING = 1,
27
+
28
+ TIRTC_INPUT_STATE_STOPPED = 2,
29
+
30
+ TIRTC_INPUT_STATE_FAILED = 3,
31
+ } TirtcInputState;
32
+
33
+ typedef enum TirtcAudioOutputState {
34
+
35
+ TIRTC_AUDIO_OUTPUT_STATE_IDLE = 0,
36
+
37
+ TIRTC_AUDIO_OUTPUT_STATE_BUFFERING = 1,
38
+
39
+ TIRTC_AUDIO_OUTPUT_STATE_PLAYING = 2,
40
+
41
+ TIRTC_AUDIO_OUTPUT_STATE_FAILED = 3,
42
+ } TirtcAudioOutputState;
43
+
44
+ typedef struct TirtcAudioInputOptions {
45
+ TirtcAudioSampleRate sample_rate;
46
+
47
+ TirtcAudioAecMode aec_mode;
48
+
49
+ TirtcAudioAgcLevel agc_level;
50
+
51
+ TirtcAudioAnsLevel ans_level;
52
+ } TirtcAudioInputOptions;
53
+
54
+ /**
55
+ * Options for a facade audio encoded input.
56
+ *
57
+ * The encoded input does not own or create an audio source. Callers submit already-encoded audio
58
+ * frames with `tirtc_audio_encoded_input_submit_frame()`. Non-NONE fields constrain submitted
59
+ * frames and reject mismatched packets with `TIRTC_ERROR_INVALID_ARGUMENT`.
60
+ */
61
+ typedef struct TirtcAudioEncodedInputOptions {
62
+ TirtcMediaCodec codec;
63
+
64
+ TirtcAudioSampleRate sample_rate;
65
+ } TirtcAudioEncodedInputOptions;
66
+
67
+ typedef struct TirtcAudioOutputOptions {
68
+ uint32_t volume_percent;
69
+
70
+ TirtcAudioAgcLevel agc_level;
71
+
72
+ TirtcAudioAnsLevel ans_level;
73
+ } TirtcAudioOutputOptions;
74
+
75
+ typedef struct TirtcOutputStutterMetrics {
76
+ int session_started;
77
+ uint64_t session_duration_ms;
78
+ uint64_t session_stutter_total_ms;
79
+ uint32_t session_stutter_count;
80
+ uint64_t session_stutter_peak_ms;
81
+ double session_stutter_ratio;
82
+ uint32_t recent_window_duration_ms;
83
+ uint64_t recent_window_stutter_total_ms;
84
+ uint32_t recent_window_stutter_count;
85
+ uint64_t recent_window_stutter_peak_ms;
86
+ double recent_window_stutter_ratio;
87
+ } TirtcOutputStutterMetrics;
88
+
89
+ typedef struct TirtcPendingDurationMetrics {
90
+ uint64_t undecoded_duration_ms;
91
+ uint64_t decoded_duration_ms;
92
+ } TirtcPendingDurationMetrics;
93
+
94
+ typedef struct TirtcAudioOutputMetricsSnapshot {
95
+ TirtcOutputStutterMetrics stutter;
96
+ TirtcPendingDurationMetrics pending;
97
+ } TirtcAudioOutputMetricsSnapshot;
98
+
99
+ /**
100
+ * Diagnostic facts currently known for an audio output.
101
+ *
102
+ * The snapshot is a caller-owned value copy. Zero-initialized fields mean the output has not yet
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 playback control decisions.
105
+ */
106
+ typedef struct TirtcAudioOutputDebugSnapshot {
107
+ TirtcMediaCodec codec;
108
+ } TirtcAudioOutputDebugSnapshot;
109
+
110
+ /**
111
+ * Audio input observer.
112
+ *
113
+ * `owned_message` is allocated by facade for this callback dispatch. Consumers must release it
114
+ * with `tirtc_owned_string_release()` after copying or converting the string they need.
115
+ */
116
+ typedef struct TirtcAudioInputObserver {
117
+ void (*on_state_changed)(TirtcAudioInput* input, TirtcInputState state, void* user_data);
118
+
119
+ void (*on_error)(TirtcAudioInput* input, TirtcError error, TirtcOwnedString* owned_message,
120
+ void* user_data);
121
+ } TirtcAudioInputObserver;
122
+
123
+ /**
124
+ * Audio encoded input observer.
125
+ *
126
+ * State callbacks report only facade input lifecycle changes. They do not mean a remote consumer
127
+ * has subscribed to, decoded, or rendered the stream. `owned_message` is allocated by facade for
128
+ * this callback dispatch; consumers must release it with `tirtc_owned_string_release()`.
129
+ */
130
+ typedef struct TirtcAudioEncodedInputObserver {
131
+ void (*on_state_changed)(TirtcAudioEncodedInput* input, TirtcInputState state, void* user_data);
132
+
133
+ void (*on_error)(TirtcAudioEncodedInput* input, TirtcError error, TirtcOwnedString* owned_message,
134
+ void* user_data);
135
+ } TirtcAudioEncodedInputObserver;
136
+
137
+ /**
138
+ * Audio output observer.
139
+ *
140
+ * `owned_message` is allocated by facade for this callback dispatch. Consumers must release it
141
+ * with `tirtc_owned_string_release()` after copying or converting the string they need.
142
+ */
143
+ typedef struct TirtcAudioOutputObserver {
144
+ void (*on_state_changed)(TirtcAudioOutput* output, TirtcAudioOutputState state, void* user_data);
145
+
146
+ void (*on_error)(TirtcAudioOutput* output, TirtcError error, TirtcOwnedString* owned_message,
147
+ void* user_data);
148
+ } TirtcAudioOutputObserver;
149
+
150
+ TirtcError tirtc_conn_subscribe_audio(TirtcConn* connection, uint8_t stream_id);
151
+
152
+ TirtcError tirtc_conn_unsubscribe_audio(TirtcConn* connection, uint8_t stream_id);
153
+
154
+ TirtcError tirtc_audio_input_create(TirtcAudioInput** out_input);
155
+
156
+ TirtcError tirtc_audio_input_set_ain(TirtcAudioInput* input, TirtcAudioAin* ain);
157
+
158
+ TirtcError tirtc_audio_input_set_options(TirtcAudioInput* input,
159
+ const TirtcAudioInputOptions* options);
160
+
161
+ TirtcError tirtc_audio_input_set_observer(TirtcAudioInput* input,
162
+ const TirtcAudioInputObserver* observer, void* user_data);
163
+
164
+ TirtcError tirtc_audio_input_start(TirtcAudioInput* input);
165
+
166
+ TirtcError tirtc_audio_input_stop(TirtcAudioInput* input);
167
+
168
+ TirtcError tirtc_audio_input_attach(TirtcAudioInput* input, TirtcConn* connection,
169
+ uint8_t stream_id);
170
+
171
+ TirtcError tirtc_audio_input_detach(TirtcAudioInput* input, TirtcConn* connection);
172
+
173
+ void tirtc_audio_input_destroy(TirtcAudioInput* input);
174
+
175
+ TirtcError tirtc_audio_encoded_input_create(TirtcAudioEncodedInput** out_input);
176
+
177
+ TirtcError tirtc_audio_encoded_input_set_options(TirtcAudioEncodedInput* input,
178
+ const TirtcAudioEncodedInputOptions* options);
179
+
180
+ TirtcError tirtc_audio_encoded_input_set_observer(TirtcAudioEncodedInput* input,
181
+ const TirtcAudioEncodedInputObserver* observer,
182
+ void* user_data);
183
+
184
+ TirtcError tirtc_audio_encoded_input_start(TirtcAudioEncodedInput* input);
185
+
186
+ TirtcError tirtc_audio_encoded_input_stop(TirtcAudioEncodedInput* input);
187
+
188
+ TirtcError tirtc_audio_encoded_input_attach(TirtcAudioEncodedInput* input, TirtcConn* connection,
189
+ uint8_t stream_id);
190
+
191
+ TirtcError tirtc_audio_encoded_input_detach(TirtcAudioEncodedInput* input, TirtcConn* connection);
192
+
193
+ TirtcError tirtc_audio_encoded_input_submit_frame(TirtcAudioEncodedInput* input,
194
+ const TirtcAudioEncodedFrame* frame);
195
+
196
+ void tirtc_audio_encoded_input_destroy(TirtcAudioEncodedInput* input);
197
+
198
+ TirtcError tirtc_audio_output_create(TirtcAudioOutput** out_output);
199
+
200
+ TirtcError tirtc_audio_output_set_aout(TirtcAudioOutput* output, TirtcAudioAout* aout);
201
+
202
+ TirtcError tirtc_audio_output_set_options(TirtcAudioOutput* output,
203
+ const TirtcAudioOutputOptions* options);
204
+
205
+ TirtcError tirtc_audio_output_set_observer(TirtcAudioOutput* output,
206
+ const TirtcAudioOutputObserver* observer,
207
+ void* user_data);
208
+
209
+ TirtcError tirtc_audio_output_attach(TirtcAudioOutput* output, TirtcConn* connection,
210
+ uint8_t stream_id);
211
+
212
+ TirtcError tirtc_audio_output_detach(TirtcAudioOutput* output);
213
+
214
+ void tirtc_audio_output_destroy(TirtcAudioOutput* output);
215
+
216
+ TirtcError tirtc_audio_output_start_raw_dump(TirtcAudioOutput* output);
217
+
218
+ TirtcError tirtc_audio_output_stop_raw_dump(TirtcAudioOutput* output);
219
+
220
+ TirtcError tirtc_metrics_audio_output_get_snapshot(TirtcAudioOutput* output,
221
+ TirtcAudioOutputMetricsSnapshot* out_snapshot);
222
+
223
+ /**
224
+ * Copies the current or cached audio output diagnostic snapshot.
225
+ *
226
+ * The output owns the underlying media downlink. Callers provide only `out_snapshot` storage and do
227
+ * not receive ownership of any runtime object. The function returns `TIRTC_ERROR_INVALID_ARGUMENT`
228
+ * for null arguments and does not emit output callbacks or change output state.
229
+ */
230
+ TirtcError tirtc_audio_output_get_debug_snapshot(TirtcAudioOutput* output,
231
+ TirtcAudioOutputDebugSnapshot* out_snapshot);
232
+
233
+ #ifdef __cplusplus
234
+ }
235
+ #endif
236
+
237
+ #endif
@@ -0,0 +1,23 @@
1
+ #ifndef TIRTC_AUDIO_CODEC_H_
2
+ #define TIRTC_AUDIO_CODEC_H_
3
+
4
+ #include <stddef.h>
5
+
6
+ #include "tirtc/audio_frame.h"
7
+ #include "tirtc/error.h"
8
+
9
+ #ifdef __cplusplus
10
+ extern "C" {
11
+ #endif
12
+
13
+ TirtcError tirtc_audio_g711a_encode(const TirtcAudioPcmFrame* pcm_frame, void* out_buffer,
14
+ size_t out_buffer_capacity, TirtcAudioEncodedFrame* out_frame);
15
+
16
+ TirtcError tirtc_audio_g711a_decode(const TirtcAudioEncodedFrame* in_frame, void* out_buffer,
17
+ size_t out_buffer_capacity, TirtcAudioPcmFrame* out_frame);
18
+
19
+ #ifdef __cplusplus
20
+ }
21
+ #endif
22
+
23
+ #endif // TIRTC_AUDIO_CODEC_H_
@@ -0,0 +1,36 @@
1
+ #ifndef TIRTC_AUDIO_FRAME_H_
2
+ #define TIRTC_AUDIO_FRAME_H_
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ #include "tirtc/audio_sample_rate.h"
8
+ #include "tirtc/media_codec.h"
9
+
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+ typedef struct TirtcAudioPcmFrame {
15
+ TirtcAudioSampleRate sample_rate;
16
+ uint32_t samples_per_channel;
17
+ int64_t pts_us;
18
+ /* Mutable PCM payload for capture, processing, and render-fill paths. */
19
+ void* data;
20
+ size_t data_bytes;
21
+ } TirtcAudioPcmFrame;
22
+
23
+ typedef struct TirtcAudioEncodedFrame {
24
+ TirtcMediaCodec codec;
25
+ TirtcAudioSampleRate sample_rate;
26
+ uint32_t samples_per_channel;
27
+ int64_t pts_us;
28
+ const void* data;
29
+ size_t data_bytes;
30
+ } TirtcAudioEncodedFrame;
31
+
32
+ #ifdef __cplusplus
33
+ }
34
+ #endif
35
+
36
+ #endif // TIRTC_AUDIO_FRAME_H_
@@ -0,0 +1,65 @@
1
+ #ifndef TIRTC_AUDIO_IO_H_
2
+ #define TIRTC_AUDIO_IO_H_
3
+
4
+ #include <stdint.h>
5
+
6
+ #include "tirtc/audio_frame.h"
7
+ #include "tirtc/error.h"
8
+
9
+ #ifdef __cplusplus
10
+ extern "C" {
11
+ #endif
12
+
13
+ typedef struct TirtcAudioAin TirtcAudioAin;
14
+ typedef struct TirtcAudioAout TirtcAudioAout;
15
+
16
+ typedef struct TirtcAudioIoConfig {
17
+ TirtcAudioSampleRate sample_rate;
18
+ /* AIN uses fixed 10 ms mono blocks; AOUT may use larger callback-sized multiples. */
19
+ uint32_t samples_per_buffer;
20
+ } TirtcAudioIoConfig;
21
+
22
+ typedef struct TirtcAudioHeadlessAoutOptions {
23
+ const char* first_output_json_path;
24
+ const char* pcm_path;
25
+ uint32_t max_capture_bytes;
26
+ } TirtcAudioHeadlessAoutOptions;
27
+
28
+ typedef void (*TirtcAudioAinOnFrameFn)(TirtcAudioAin* ain, const TirtcAudioPcmFrame* frame,
29
+ void* user_data);
30
+
31
+ /*
32
+ * AOUT pre-fills sample_rate, samples_per_channel, data, and data_bytes before
33
+ * calling render. The callback contract expects a non-negative rendered PCM
34
+ * byte count. Backends defensively clamp negative returns to zero and zero-fill
35
+ * any remaining buffer space.
36
+ *
37
+ * The render callback and user_data supplied at open-time must stay valid until
38
+ * close completes. Backends may invoke render without holding backend locks.
39
+ */
40
+ typedef int (*TirtcAudioAoutRenderFn)(TirtcAudioAout* aout, TirtcAudioPcmFrame* frame,
41
+ void* user_data);
42
+
43
+ TirtcError tirtc_audio_ain_open(TirtcAudioAin* ain, const TirtcAudioIoConfig* config,
44
+ TirtcAudioAinOnFrameFn on_frame, void* user_data);
45
+
46
+ TirtcError tirtc_audio_ain_close(TirtcAudioAin* ain);
47
+ void tirtc_audio_ain_destroy(TirtcAudioAin* ain);
48
+
49
+ TirtcError tirtc_audio_aout_open(TirtcAudioAout* aout, const TirtcAudioIoConfig* config,
50
+ TirtcAudioAoutRenderFn render, void* user_data);
51
+
52
+ TirtcError tirtc_audio_aout_create_headless_capture(const TirtcAudioHeadlessAoutOptions* options,
53
+ TirtcAudioAout** out_aout);
54
+
55
+ TirtcError tirtc_audio_aout_set_volume(TirtcAudioAout* aout, uint32_t volume_percent);
56
+ TirtcError tirtc_audio_aout_pause(TirtcAudioAout* aout, int pause_on);
57
+ TirtcError tirtc_audio_aout_flush(TirtcAudioAout* aout);
58
+ TirtcError tirtc_audio_aout_close(TirtcAudioAout* aout);
59
+ void tirtc_audio_aout_destroy(TirtcAudioAout* aout);
60
+
61
+ #ifdef __cplusplus
62
+ }
63
+ #endif
64
+
65
+ #endif // TIRTC_AUDIO_IO_H_
@@ -0,0 +1,19 @@
1
+ #ifndef TIRTC_AUDIO_IO_ANDROID_H_
2
+ #define TIRTC_AUDIO_IO_ANDROID_H_
3
+
4
+ #include "tirtc/audio_io.h"
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ #if defined(__ANDROID__)
11
+ TirtcError tirtc_audio_android_create_open_sl_ain(TirtcAudioAin** out_ain);
12
+ TirtcError tirtc_audio_android_create_open_sl_aout(TirtcAudioAout** out_aout);
13
+ #endif
14
+
15
+ #ifdef __cplusplus
16
+ }
17
+ #endif
18
+
19
+ #endif // TIRTC_AUDIO_IO_ANDROID_H_
@@ -0,0 +1,19 @@
1
+ #ifndef TIRTC_AUDIO_IO_APPLE_H_
2
+ #define TIRTC_AUDIO_IO_APPLE_H_
3
+
4
+ #include "tirtc/audio_io.h"
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ #if defined(__APPLE__)
11
+ TirtcError tirtc_audio_apple_create_audio_toolbox_ain(TirtcAudioAin** out_ain);
12
+ TirtcError tirtc_audio_apple_create_audio_queue_aout(TirtcAudioAout** out_aout);
13
+ #endif
14
+
15
+ #ifdef __cplusplus
16
+ }
17
+ #endif
18
+
19
+ #endif // TIRTC_AUDIO_IO_APPLE_H_
@@ -0,0 +1,19 @@
1
+ #ifndef TIRTC_AUDIO_IO_HARMONY_H_
2
+ #define TIRTC_AUDIO_IO_HARMONY_H_
3
+
4
+ #include "tirtc/audio_io.h"
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ #if defined(__OHOS__)
11
+ TirtcError tirtc_audio_harmony_create_open_sl_ain(TirtcAudioAin** out_ain);
12
+ TirtcError tirtc_audio_harmony_create_audio_render_aout(TirtcAudioAout** out_aout);
13
+ #endif
14
+
15
+ #ifdef __cplusplus
16
+ }
17
+ #endif
18
+
19
+ #endif // TIRTC_AUDIO_IO_HARMONY_H_
@@ -0,0 +1,19 @@
1
+ #ifndef TIRTC_AUDIO_IO_WINDOWS_H_
2
+ #define TIRTC_AUDIO_IO_WINDOWS_H_
3
+
4
+ #include "tirtc/audio_io.h"
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ #if defined(_WIN32)
11
+ TirtcError tirtc_audio_windows_create_wasapi_ain(TirtcAudioAin** out_ain);
12
+ TirtcError tirtc_audio_windows_create_wave_out_aout(TirtcAudioAout** out_aout);
13
+ #endif
14
+
15
+ #ifdef __cplusplus
16
+ }
17
+ #endif
18
+
19
+ #endif // TIRTC_AUDIO_IO_WINDOWS_H_