Skip to content

Commit 863cf59

Browse files
authored
Version Update 1.9.0 (#509)
* [+] Support MoQ feature * [=] fix log format * [~] fix random diff * [~] fix github workflow failed on linux * [~] fix github workflow failed on codfeql
1 parent 84ef526 commit 863cf59

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+13667
-6
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
SSL_LIB_PATH_STR="${PWD}/third_party/boringssl/build/libssl.a;${PWD}/third_party/boringssl/build/libcrypto.a"
6262
mkdir -p build
6363
cd build
64-
cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_PRINT_SECRET=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DXQC_ENABLE_UNLIMITED=1 -DXQC_ENABLE_COPA=1 -DXQC_COMPAT_DUPLICATE=1 -DXQC_ENABLE_FEC=1 -DXQC_ENABLE_XOR=1 -DXQC_ENABLE_RSC=1 -DXQC_ENABLE_PKM=1 ..
64+
cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_PRINT_SECRET=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} -DXQC_ENABLE_UNLIMITED=1 -DXQC_ENABLE_COPA=1 -DXQC_COMPAT_DUPLICATE=1 -DXQC_ENABLE_FEC=1 -DXQC_ENABLE_XOR=1 -DXQC_ENABLE_RSC=1 -DXQC_ENABLE_PKM=1 ..
6565
make -j
6666
6767
- name: Test

.github/workflows/codeql-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
SSL_LIB_PATH_STR="${PWD}/third_party/boringssl/build/libssl.a;${PWD}/third_party/boringssl/build/libcrypto.a"
6161
mkdir -p build
6262
cd build
63-
cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_PRINT_SECRET=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DXQC_ENABLE_UNLIMITED=1 -DXQC_ENABLE_COPA=1 -DXQC_COMPAT_DUPLICATE=1 -DXQC_ENABLE_FEC=1 -DXQC_ENABLE_XOR=1 -DXQC_ENABLE_RSC=1 -DXQC_ENABLE_PKM=1 ..
63+
cmake -DGCOV=on -DCMAKE_BUILD_TYPE=Debug -DXQC_ENABLE_TESTING=1 -DXQC_PRINT_SECRET=1 -DXQC_SUPPORT_SENDMMSG_BUILD=1 -DXQC_ENABLE_EVENT_LOG=1 -DXQC_ENABLE_BBR2=1 -DXQC_ENABLE_RENO=1 -DSSL_TYPE=${SSL_TYPE_STR} -DSSL_PATH=${SSL_PATH_STR} -DSSL_INC_PATH=${SSL_INC_PATH_STR} -DSSL_LIB_PATH=${SSL_LIB_PATH_STR} -DXQC_ENABLE_UNLIMITED=1 -DXQC_ENABLE_COPA=1 -DXQC_COMPAT_DUPLICATE=1 -DXQC_ENABLE_FEC=1 -DXQC_ENABLE_XOR=1 -DXQC_ENABLE_RSC=1 -DXQC_ENABLE_PKM=1 ..
6464
make -j
6565
6666
- name: Perform CodeQL Analysis

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ if(XQC_ENABLE_TESTING)
177177
add_subdirectory(mini)
178178
endif(XQC_ENABLE_TESTING)
179179

180+
if(XQC_ENABLE_MOQ)
181+
add_subdirectory(moq)
182+
endif()
180183

181184
# http3/qpack source
182185
set(

cmake/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ include_directories(
146146
${CMAKE_CURRENT_BINARY_DIR}/include
147147
)
148148

149-
149+
if(XQC_ENABLE_MOQ)
150+
add_subdirectory(moq)
151+
endif()
152+
150153
# http3/qpack source
151154
set(
152155
HTTP3_SOURCES

cmake/FindSSL.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ endif()
3333
# find ssl static library
3434
find_library(SSL_LIBRARY_STATIC NAMES ${SSL_LIBRARY_STATIC_NAME}
3535
PATHS ${SSL_DIR}
36-
PATH_SUFFIXES lib64 lib build build/${CMAKE_BUILD_TYPE}
36+
PATH_SUFFIXES lib64 lib build/ssl build/ssl/${CMAKE_BUILD_TYPE}
3737
NO_DEFAULT_PATH)
3838

3939
# find crypto static library
4040
find_library(CRYPTO_LIBRARY_STATIC NAMES ${CRYPTO_LIBRARY_STATIC_NAME}
4141
PATHS ${SSL_DIR}
42-
PATH_SUFFIXES lib64 lib build build/${CMAKE_BUILD_TYPE}
42+
PATH_SUFFIXES lib64 lib build/crypto build/crypto/${CMAKE_BUILD_TYPE}
4343
NO_DEFAULT_PATH)
4444

4545
include (FindPackageHandleStandardArgs)

include/moq/xqc_moq.h

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
#ifndef _XQC_MOQ_H_INCLUDED_
2+
#define _XQC_MOQ_H_INCLUDED_
3+
4+
#include <xquic/xquic.h>
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
#define XQC_ALPN_MOQ_QUIC "moq-quic"
11+
#define XQC_ALPN_MOQ_WEBTRANSPORT "moq-wt"
12+
13+
typedef enum {
14+
XQC_MOQ_VIDEO_KEY,
15+
XQC_MOQ_VIDEO_DELTA,
16+
} xqc_moq_video_frame_type_t;
17+
18+
typedef struct {
19+
xqc_moq_video_frame_type_t type;
20+
uint64_t seq_num;
21+
uint64_t timestamp_us;
22+
uint8_t *video_data;
23+
uint64_t video_len;
24+
} xqc_moq_video_frame_t;
25+
26+
typedef struct {
27+
uint64_t seq_num;
28+
uint64_t timestamp_us;
29+
uint8_t *audio_data;
30+
uint64_t audio_len;
31+
} xqc_moq_audio_frame_t;
32+
33+
typedef enum {
34+
XQC_MOQ_CONTAINER_LOC,
35+
XQC_MOQ_CONTAINER_CMAF,
36+
XQC_MOQ_CONTAINER_NONE,
37+
} xqc_moq_container_t;
38+
39+
typedef enum {
40+
XQC_MOQ_TRACK_VIDEO,
41+
XQC_MOQ_TRACK_AUDIO,
42+
XQC_MOQ_TRACK_CATALOG,
43+
XQC_MOQ_TRACK_DATACHANNEL,
44+
} xqc_moq_track_type_t;
45+
46+
typedef enum {
47+
XQC_MOQ_TRACK_FOR_PUB,
48+
XQC_MOQ_TRACK_FOR_SUB,
49+
} xqc_moq_track_role_t;
50+
51+
typedef struct {
52+
/* Common */
53+
char *codec; /* Required */
54+
char *mime_type; /* Required */
55+
xqc_int_t bitrate; /* Required */
56+
char *lang; /* Optional */
57+
/* Video */
58+
xqc_int_t framerate; /* Required */
59+
xqc_int_t width; /* Required */
60+
xqc_int_t height; /* Required */
61+
xqc_int_t display_width; /* Optional */
62+
xqc_int_t display_height; /* Optional */
63+
/* Audio */
64+
xqc_int_t samplerate; /* Required */
65+
char *channel_config; /* Optional */
66+
} xqc_moq_selection_params_t;
67+
68+
typedef struct {
69+
char *track_namespace;
70+
char *track_name;
71+
xqc_moq_track_type_t track_type;
72+
xqc_moq_selection_params_t selection_params;
73+
} xqc_moq_track_info_t;
74+
75+
typedef enum {
76+
XQC_MOQ_TRANSPORT_WEBTRANSPORT,
77+
XQC_MOQ_TRANSPORT_QUIC,
78+
} xqc_moq_transport_type_t;
79+
80+
typedef enum {
81+
XQC_MOQ_PUBLISHER = 0x01,
82+
XQC_MOQ_SUBSCRIBER = 0x02,
83+
XQC_MOQ_PUBSUB = 0x03,
84+
} xqc_moq_role_t;
85+
86+
typedef enum {
87+
XQC_MOQ_FILTER_LAST_GROUP = 0x1,
88+
XQC_MOQ_FILTER_LAST_OBJECT = 0x2,
89+
XQC_MOQ_FILTER_ABSOLUTE_START = 0x3,
90+
XQC_MOQ_FILTER_ABSOLUTE_RANGE = 0x4,
91+
} xqc_moq_filter_type_t;
92+
93+
typedef struct xqc_moq_session_s xqc_moq_session_t;
94+
typedef struct xqc_moq_stream_s xqc_moq_stream_t;
95+
typedef struct xqc_moq_track_s xqc_moq_track_t;
96+
typedef struct xqc_moq_object_s xqc_moq_object_t;
97+
typedef struct xqc_moq_catalog_s xqc_moq_catalog_t;
98+
typedef struct xqc_moq_subscribe_s xqc_moq_subscribe_t;
99+
typedef struct xqc_moq_subscribe_msg_s xqc_moq_subscribe_msg_t;
100+
typedef struct xqc_moq_subscribe_ok_msg_s xqc_moq_subscribe_ok_msg_t;
101+
typedef struct xqc_moq_subscribe_error_msg_s xqc_moq_subscribe_error_msg_t;
102+
typedef struct xqc_moq_subscribe_update_msg_s xqc_moq_subscribe_update_msg_t;
103+
typedef struct xqc_moq_announce_msg_s xqc_moq_announce_msg_t;
104+
typedef struct xqc_moq_announce_ok_msg_s xqc_moq_announce_ok_msg_t;
105+
typedef struct xqc_moq_announce_error_msg_s xqc_moq_announce_error_msg_t;
106+
typedef struct xqc_moq_unannounce_msg_s xqc_moq_unannounce_msg_t;
107+
typedef struct xqc_moq_unsubscribe_msg_s xqc_moq_unsubscribe_msg_t;
108+
typedef struct xqc_moq_subscribe_done_msg_s xqc_moq_subscribe_done_msg_t;
109+
typedef struct xqc_moq_goaway_msg_s xqc_moq_goaway_msg_t;
110+
typedef struct xqc_moq_client_setup_msg_s xqc_moq_client_setup_msg_t;
111+
typedef struct xqc_moq_server_setup_msg_s xqc_moq_server_setup_msg_t;
112+
typedef struct xqc_moq_stream_header_track_msg_s xqc_moq_stream_header_track_msg_t;
113+
typedef struct xqc_moq_stream_header_group_msg_s xqc_moq_stream_header_group_msg_t;
114+
typedef struct xqc_moq_decode_msg_ctx_s xqc_moq_decode_msg_ctx_t;
115+
typedef struct xqc_moq_user_session_s {
116+
xqc_moq_session_t *session;
117+
uint8_t data[0];
118+
} xqc_moq_user_session_t;
119+
120+
typedef enum {
121+
XQC_MOQ_MSG_OBJECT_STREAM = 0x0,
122+
XQC_MOQ_MSG_OBJECT_DATAGRAM = 0x1,
123+
XQC_MOQ_MSG_SUBSCRIBE_UPDATE = 0x2,
124+
XQC_MOQ_MSG_SUBSCRIBE = 0x3,
125+
XQC_MOQ_MSG_SUBSCRIBE_OK = 0x4,
126+
XQC_MOQ_MSG_SUBSCRIBE_ERROR = 0x5,
127+
XQC_MOQ_MSG_ANNOUNCE = 0x6,
128+
XQC_MOQ_MSG_ANNOUNCE_OK = 0x7,
129+
XQC_MOQ_MSG_ANNOUNCE_ERROR = 0x8,
130+
XQC_MOQ_MSG_UNANNOUNCE = 0x9,
131+
XQC_MOQ_MSG_UNSUBSCRIBE = 0xA,
132+
XQC_MOQ_MSG_SUBSCRIBE_DONE = 0xB,
133+
XQC_MOQ_MSG_ANNOUNCE_CANCEL = 0xC,
134+
XQC_MOQ_MSG_TRACK_STATUS_REQUEST = 0xD,
135+
XQC_MOQ_MSG_TRACK_STATUS = 0xE,
136+
XQC_MOQ_MSG_GOAWAY = 0x10,
137+
XQC_MOQ_MSG_CLIENT_SETUP = 0x40,
138+
XQC_MOQ_MSG_SERVER_SETUP = 0x41,
139+
XQC_MOQ_MSG_STREAM_HEADER_TRACK = 0x50,
140+
XQC_MOQ_MSG_STREAM_HEADER_GROUP = 0x51,
141+
/* Phony message types */
142+
XQC_MOQ_MSG_TRACK_STREAM_OBJECT = 0xA0,
143+
XQC_MOQ_MSG_GROUP_STREAM_OBJECT = 0xA1,
144+
} xqc_moq_msg_type_t;
145+
146+
typedef struct {
147+
uint64_t type;
148+
uint64_t length;
149+
uint8_t *value;
150+
} xqc_moq_message_parameter_t;
151+
152+
typedef struct xqc_moq_msg_base_s {
153+
xqc_moq_msg_type_t (*type)();
154+
xqc_int_t (*encode_len)(struct xqc_moq_msg_base_s *msg_base);
155+
xqc_int_t (*encode)(struct xqc_moq_msg_base_s *msg_base, uint8_t *buf, size_t buf_cap);
156+
xqc_int_t (*decode)(uint8_t *buf, size_t buf_len, uint8_t stream_fin, struct xqc_moq_decode_msg_ctx_s *msg_ctx,
157+
struct xqc_moq_msg_base_s *msg_base, xqc_int_t *finish, xqc_int_t *wait_more_data);
158+
void (*on_msg)(struct xqc_moq_session_s *session, struct xqc_moq_stream_s *moq_stream, struct xqc_moq_msg_base_s *msg_base);
159+
} xqc_moq_msg_base_t;
160+
161+
typedef struct xqc_moq_subscribe_msg_s {
162+
xqc_moq_msg_base_t msg_base;
163+
uint64_t subscribe_id;
164+
uint64_t track_alias;
165+
char *track_namespace;
166+
size_t track_namespace_len;
167+
char *track_name;
168+
size_t track_name_len;
169+
uint64_t filter_type;
170+
uint64_t start_group_id;
171+
uint64_t start_object_id;
172+
uint64_t end_group_id;
173+
uint64_t end_object_id;
174+
uint64_t params_num;
175+
xqc_moq_message_parameter_t *params;
176+
} xqc_moq_subscribe_msg_t;
177+
178+
typedef struct xqc_moq_subscribe_ok_msg_s {
179+
xqc_moq_msg_base_t msg_base;
180+
uint64_t subscribe_id;
181+
uint64_t expire_ms;
182+
uint64_t content_exist;
183+
uint64_t largest_group_id;
184+
uint64_t largest_object_id;
185+
} xqc_moq_subscribe_ok_msg_t;
186+
187+
typedef struct xqc_moq_subscribe_error_msg_s {
188+
xqc_moq_msg_base_t msg_base;
189+
uint64_t subscribe_id;
190+
uint64_t error_code;
191+
char *reason_phrase;
192+
size_t reason_phrase_len;
193+
uint64_t track_alias;
194+
} xqc_moq_subscribe_error_msg_t;
195+
196+
typedef void (*xqc_moq_on_session_setup_pt)(xqc_moq_user_session_t *user_session, char *extdata);
197+
198+
typedef void (*xqc_moq_on_datachannel_pt)(xqc_moq_user_session_t *user_session);
199+
200+
typedef void (*xqc_moq_on_datachannel_msg_pt)(xqc_moq_user_session_t *user_session, uint8_t *msg, size_t msg_len);
201+
202+
typedef void (*xqc_moq_on_subscribe_pt)(xqc_moq_user_session_t *user_session, uint64_t subscribe_id,
203+
xqc_moq_track_t *track, xqc_moq_subscribe_msg_t *msg);
204+
205+
typedef void (*xqc_moq_on_request_keyframe_pt)(xqc_moq_user_session_t *user_session, uint64_t subscribe_id,
206+
xqc_moq_track_t *track);
207+
208+
typedef void (*xqc_moq_on_subscribe_ok_pt)(xqc_moq_user_session_t *user_session,
209+
xqc_moq_subscribe_ok_msg_t *subscribe_ok);
210+
211+
typedef void (*xqc_moq_on_subscribe_error_pt)(xqc_moq_user_session_t *user_session,
212+
xqc_moq_subscribe_error_msg_t *subscribe_error);
213+
214+
typedef void (*xqc_moq_on_catalog_pt)(xqc_moq_user_session_t *user_session, xqc_moq_track_info_t **track_info_array,
215+
xqc_int_t array_size);
216+
217+
typedef void (*xqc_moq_on_video_frame_pt)(xqc_moq_user_session_t *user_session, uint64_t subscribe_id,
218+
xqc_moq_video_frame_t *video_frame);
219+
220+
typedef void (*xqc_moq_on_audio_frame_pt)(xqc_moq_user_session_t *user_session, uint64_t subscribe_id,
221+
xqc_moq_audio_frame_t *audio_frame);
222+
223+
/**
224+
* @brief There are two ways to get the target bitrate.
225+
* 1. Call xqc_moq_target_bitrate before encoding.
226+
* 2. Register the xqc_moq_on_bitrate_change_pt callback. A callback notification occurs when the target bitrate changes
227+
*/
228+
typedef void (*xqc_moq_on_bitrate_change_pt)(xqc_moq_user_session_t *user_session, uint64_t bitrate);
229+
230+
typedef struct {
231+
xqc_moq_on_session_setup_pt on_session_setup; /* Required */
232+
xqc_moq_on_datachannel_pt on_datachannel; /* Required */
233+
xqc_moq_on_datachannel_msg_pt on_datachannel_msg; /* Required */
234+
/* For Publisher */
235+
xqc_moq_on_subscribe_pt on_subscribe; /* Required */
236+
xqc_moq_on_request_keyframe_pt on_request_keyframe; /* Required */
237+
xqc_moq_on_bitrate_change_pt on_bitrate_change; /* Optional */
238+
/* For Subscriber */
239+
xqc_moq_on_subscribe_ok_pt on_subscribe_ok; /* Required */
240+
xqc_moq_on_subscribe_error_pt on_subscribe_error; /* Required */
241+
xqc_moq_on_catalog_pt on_catalog; /* Required */
242+
xqc_moq_on_video_frame_pt on_video; /* Required */
243+
xqc_moq_on_audio_frame_pt on_audio; /* Required */
244+
} xqc_moq_session_callbacks_t;
245+
246+
XQC_EXPORT_PUBLIC_API
247+
void xqc_moq_init_alpn(xqc_engine_t *engine, xqc_conn_callbacks_t *conn_cbs, xqc_moq_transport_type_t transport_type);
248+
249+
/**
250+
* @param extdata The client can send extdata when creating a session.
251+
* This extdata will be received by the server in the on_session_setup callback.
252+
*/
253+
XQC_EXPORT_PUBLIC_API
254+
xqc_moq_session_t *xqc_moq_session_create(void *conn, xqc_moq_user_session_t *user_session,
255+
xqc_moq_transport_type_t type, xqc_moq_role_t role, xqc_moq_session_callbacks_t, char *extdata);
256+
257+
XQC_EXPORT_PUBLIC_API
258+
void xqc_moq_session_destroy(xqc_moq_session_t *session);
259+
260+
/**
261+
* @brief Set application error code and close the connection
262+
* @param code in range 0x700 ~ 0x7FF
263+
*/
264+
XQC_EXPORT_PUBLIC_API
265+
void xqc_moq_session_app_error(xqc_moq_session_t *session, uint64_t code);
266+
267+
/**
268+
* @brief Get session error code in conn_closing or conn_close_notify
269+
*/
270+
XQC_EXPORT_PUBLIC_API
271+
uint64_t xqc_moq_session_get_error(xqc_moq_session_t *session);
272+
273+
/**
274+
* @brief Call it after xqc_moq_session_create
275+
* Configure bitrate in bps
276+
*/
277+
XQC_EXPORT_PUBLIC_API
278+
void xqc_moq_configure_bitrate(xqc_moq_session_t *session, uint64_t init_bitrate, uint64_t max_bitrate, uint64_t min_bitrate);
279+
280+
/**
281+
* @brief There are two ways to get the target bitrate.
282+
* 1. Call xqc_moq_target_bitrate before encoding.
283+
* 2. Register the xqc_moq_on_bitrate_change_pt callback. A callback notification occurs when the target bitrate changes
284+
* @return Encode bitrate in bits per second (bps)
285+
*/
286+
XQC_EXPORT_PUBLIC_API
287+
uint64_t xqc_moq_target_bitrate(xqc_moq_session_t *session);
288+
289+
XQC_EXPORT_PUBLIC_API
290+
xqc_moq_track_t *xqc_moq_track_create(xqc_moq_session_t *session, char *track_namespace, char *track_name,
291+
xqc_moq_track_type_t track_type, xqc_moq_selection_params_t *params, xqc_moq_container_t container, xqc_moq_track_role_t role);
292+
293+
XQC_EXPORT_PUBLIC_API
294+
xqc_int_t xqc_moq_subscribe(xqc_moq_session_t *session, const char *track_namespace, const char *track_name,
295+
xqc_moq_filter_type_t filter_type, uint64_t start_group_id, uint64_t start_object_id,
296+
uint64_t end_group_id, uint64_t end_object_id, char *authinfo);
297+
298+
XQC_EXPORT_PUBLIC_API
299+
xqc_int_t xqc_moq_subscribe_latest(xqc_moq_session_t *session, const char *track_namespace, const char *track_name);
300+
301+
XQC_EXPORT_PUBLIC_API
302+
xqc_int_t xqc_moq_request_keyframe(xqc_moq_session_t *session, uint64_t subscribe_id);
303+
304+
XQC_EXPORT_PUBLIC_API
305+
xqc_int_t xqc_moq_write_subscribe_ok(xqc_moq_session_t *session, xqc_moq_subscribe_ok_msg_t *subscribe_ok);
306+
307+
XQC_EXPORT_PUBLIC_API
308+
xqc_int_t xqc_moq_write_subscribe_error(xqc_moq_session_t *session, xqc_moq_subscribe_error_msg_t *subscribe_error);
309+
310+
XQC_EXPORT_PUBLIC_API
311+
xqc_int_t xqc_moq_write_datachannel(xqc_moq_session_t *session, uint8_t *msg, size_t msg_len);
312+
313+
XQC_EXPORT_PUBLIC_API
314+
xqc_int_t xqc_moq_write_video_frame(xqc_moq_session_t *session, uint64_t subscribe_id,
315+
xqc_moq_track_t *track, xqc_moq_video_frame_t *video_frame);
316+
317+
XQC_EXPORT_PUBLIC_API
318+
xqc_int_t xqc_moq_write_audio_frame(xqc_moq_session_t *session, uint64_t subscribe_id,
319+
xqc_moq_track_t *track, xqc_moq_audio_frame_t *audio_frame);
320+
321+
#ifdef __cplusplus
322+
}
323+
#endif
324+
325+
#endif /* _XQC_MOQ_H_INCLUDED_ */

0 commit comments

Comments
 (0)