XMBP — Xylolabs Metadata Binary Protocol 명세서¶
특허 출원 중 — XAP (Xylolabs Audio Protocol) / XMBP (Xylolabs Metadata Binary Protocol)는 Xylolabs Inc.의 독점 기술이다. 특허 출원이 진행 중이다. 무단 사용, 복제 또는 배포를 금한다.
목차¶
- 개요
- 배치 와이어 포맷
- 스트림 블록 포맷
- 샘플 레이아웃
- 값 타입 레지스트리
- 오디오 코덱 식별자
- 인코딩 API
- 디코딩 API
- 기능 플래그
- 전송
- 저장 포맷 (XMCH)
- 와이어 포맷 예제
- 관련 문서
- 법적 고지
1. 개요¶
XMBP (Xylolabs Metadata Binary Protocol)는 IoT 센서 및 모터 텔레메트리 데이터를 위한 컴팩트 이진 프레이밍 프로토콜이다. Xylolabs SDK 탑재 장치와 Xylolabs 인제스트 서버 사이에서 사용되는 온-와이어 포맷이다.
설계 목표:
- 제로 할당 인코딩. 인코더는 힙 할당 없이 호출자가 제공한 바이트 버퍼에 직접 쓴다. 메모리 할당자가 없는 베어메탈 마이크로컨트롤러(
no_std,alloc없음)에 적합하다. - 빅엔디언 바이트 순서. 모든 멀티바이트 정수와 IEEE 754 부동소수점은 네트워크 바이트 순서(빅엔디언, 최상위 바이트 먼저)로 전송된다.
- 마이크로초 타임스탬프. 모든 샘플은 애플리케이션이 정의한 에포크 이후 마이크로초 단위로 측정된
u64타임스탬프를 포함한다. - 멀티스트림 배칭. 단일 XMBP 배치는 각자의 타입과 샘플 수를 가진 여러 독립적인 센서 스트림의 샘플을 전송할 수 있다.
- 타입이 지정된 스트림. 각 스트림 블록은 단일
MetadataValueType을 선언하며, 디코더가 샘플별 타입 태그 없이 샘플을 파싱할 수 있도록 한다.
2. 배치 와이어 포맷¶
XMBP 배치는 연속적인 빅엔디언 바이트 시퀀스이다. 배치는 고정 길이 엔벨로프 헤더로 시작하고, 선택적 장치 ID 필드와 가변 길이 스트림 블록 시퀀스가 뒤따른다.
2.1 엔벨로프 레이아웃¶
Offset Size Field
------ ---- -----
0 4 magic 0x58 0x4D 0x42 0x50 (ASCII "XMBP")
4 1 version 0x01
5 1 flags bit field (see 2.2)
6 2 batch_seq u16 BE — monotonically increasing sequence number
[8] [4] device_id u32 BE — present only when flags & 0x01 != 0
8 or 12 2 stream_count u16 BE — number of stream blocks that follow
스트림 없이 장치 ID 없는 최소 배치는 10 바이트이다.
장치 ID가 있는 경우 최소 배치는 14 바이트이다.
2.2 flags 필드¶
| 비트 | 상수 | 16진수 | 의미 |
|---|---|---|---|
| 0 | FLAG_HAS_DEVICE_ID |
0x01 | 4바이트 device_id 필드가 batch_seq 바로 다음에 온다. |
| 1 | FLAG_ZSTD_COMPRESSED |
0x02 | 페이로드가 zstd 압축되어 있다. 예약됨. 아직 활성화되지 않았다. |
| 2-7 | — | — | 예약됨. 쓸 때 0이어야 한다. 읽을 때 무시해야 한다. |
2.3 필드 참조¶
| 필드 | 타입 | 크기 | 비고 |
|---|---|---|---|
| magic | u32 | 4 | 고정값 0x584D4250. 매직이 틀린 배치는 거부한다. |
| version | u8 | 1 | 현재 0x01. 알 수 없는 버전은 거부한다. |
| flags | u8 | 1 | 비트 필드. 위 표 참조. |
| batch_seq | u16 BE | 2 | 65535에서 래핑. 서버의 갭 감지에 사용된다. |
| device_id | u32 BE | 4 | 선택적. FLAG_HAS_DEVICE_ID가 설정된 경우 존재한다. |
| stream_count | u16 BE | 2 | 뒤따르는 StreamBlock 레코드의 수. |
2.4 바이트 레벨 다이어그램¶
Byte: 00 01 02 03 04 05 06 07 [08 09 0A 0B] [08|0C] [09|0D]
+-----------+---+---+------+[------------]+[------+-------]+---...
| 58 4D 42 | 01 | | |[ device_id ]| stream_count |
| 50 magic |ver |flg|b_seq |[ u32 BE opt ]| u16 BE | stream blocks...
+-----------+---+---+------+[------------]+[------+-------]+---...
괄호 [ ] 안의 바이트 오프셋은 FLAG_HAS_DEVICE_ID에 따라 조건부이다.
3. 스트림 블록 포맷¶
stream_count 바로 다음에 정확히 stream_count개의 스트림 블록이 순서대로 온다. 각 스트림 블록은 단일 값 타입의 샘플을 전송한다.
Offset Size Field
------ ---- -----
0 2 stream_id u16 BE — identifies the logical stream
2 1 value_type u8 — MetadataValueType wire tag (see Section 5)
3 2 sample_count u16 BE — number of samples in this block
5 var samples sample_count samples (see Section 4)
3.1 필드 참조¶
| 필드 | 타입 | 크기 | 비고 |
|---|---|---|---|
| stream_id | u16 BE | 2 | 인제스트 세션 정의의 스트림 인덱스와 매칭된다. |
| value_type | u8 | 1 | MetadataValueType의 와이어 태그. 5절 참조. |
| sample_count | u16 BE | 2 | 샘플 수. 블록당 최대 65535. 서버는 배치당 256개 스트림 블록으로 제한한다. |
| samples | — | var | 연결된 샘플들. 값 타입에 따른 레이아웃. 4절 참조. |
4. 샘플 레이아웃¶
모든 샘플은 8바이트 마이크로초 타임스탬프(u64 BE)로 시작하고, 인코딩된 값이 바로 뒤따른다. 값 인코딩은 스트림의 value_type에 따라 다르다.
4.1 고정 크기 타입¶
| 타입 | 타임스탬프 | 값 인코딩 | 샘플당 합계 |
|---|---|---|---|
| F64 | u64 BE (8) | IEEE 754 double, BE (8) | 16 바이트 |
| F32 | u64 BE (8) | IEEE 754 single, BE (4) | 12 바이트 |
| I64 | u64 BE (8) | signed 64-bit int, BE (8) | 16 바이트 |
| I32 | u64 BE (8) | signed 32-bit int, BE (4) | 12 바이트 |
| I16 | u64 BE (8) | signed 16-bit int, BE (2) | 10 바이트 |
| I8 | u64 BE (8) | signed 8-bit int (u8 cast to i8, 1) | 9 바이트 |
| Bool | u64 BE (8) | u8: 0=false, 1=true (1) | 9 바이트 |
4.2 가변 크기 타입¶
가변 길이 타입의 경우 각 샘플은 timestamp(8) + length_prefix + payload 형태이다.
| 타입 | 길이 접두사 | 페이로드 | 비고 |
|---|---|---|---|
| String | u16 BE (2) | UTF-8 인코딩된 바이트 | 최대 65535 바이트 |
| Bytes | u16 BE (2) | 원시 바이트 블롭 | 최대 65535 바이트 |
| F64Array | u16 BE (2) | N x IEEE 754 double BE (각 8 바이트) | 개수 최대 65535. 디코더는 4096으로 제한한다. |
| F32Array | u16 BE (2) | N x IEEE 754 single BE (각 4 바이트) | 개수 최대 65535. 디코더는 4096으로 제한한다. |
| I32Array | u16 BE (2) | N x signed 32-bit int BE (각 4) | 개수 최대 65535. 디코더는 4096으로 제한한다. |
| Json | u32 BE (4) | UTF-8 인코딩된 JSON 문자열 | 최대 약 4 GiB (u32). 드물게 사용한다. |
참고: Json은 u16이 아닌 4바이트(u32) 길이 접두사를 사용한다. 다른 모든 가변 타입은 2바이트(u16) 접두사를 사용한다.
4.3 샘플 바이트 다이어그램¶
F32 샘플 (12 바이트):
+--+--+--+--+--+--+--+--+--+--+--+--+
| timestamp_us (u64 BE, 8 bytes) | f32 BE (4B) |
+--+--+--+--+--+--+--+--+--+--+--+--+
Bool 샘플 (9 바이트):
+--+--+--+--+--+--+--+--+--+
| timestamp_us (u64 BE, 8 bytes) |v |
+--+--+--+--+--+--+--+--+--+
v = 0x00 (false) or 0x01 (true)
String 샘플 (가변):
+--+--+--+--+--+--+--+--+--+--+-- ... --+
| timestamp_us (u64 BE, 8 bytes) |len(u16)| UTF-8 bytes (len bytes) |
+--+--+--+--+--+--+--+--+--+--+-- ... --+
Json 샘플 (가변):
+--+--+--+--+--+--+--+--+--+--+--+--+-- ... --+
| timestamp_us (u64 BE, 8 bytes) | len(u32 BE, 4B) | UTF-8 JSON (len bytes) |
+--+--+--+--+--+--+--+--+--+--+--+--+-- ... --+
5. 값 타입 레지스트리¶
MetadataValueType 판별자는 각 스트림 블록 헤더에서 단일 바이트 와이어 태그로 전송된다.
| 와이어 태그 | Rust 변형 | 표시 이름 | 고정 값 크기 | 길이 접두사 | 비고 |
|---|---|---|---|---|---|
| 0x00 | F64 |
f64 |
8 바이트 | — | IEEE 754 배정밀도, BE |
| 0x01 | F32 |
f32 |
4 바이트 | — | IEEE 754 단정밀도, BE |
| 0x02 | I64 |
i64 |
8 바이트 | — | 부호 있는 64비트 정수, BE |
| 0x03 | I32 |
i32 |
4 바이트 | — | 부호 있는 32비트 정수, BE |
| 0x04 | Bool |
bool |
1 바이트 | — | 0x00=false, 0x01=true |
| 0x05 | String |
string |
가변 | u16 BE | UTF-8. 최대 65535 바이트 |
| 0x06 | Bytes |
bytes |
가변 | u16 BE | 원시 블롭. 최대 65535 바이트 |
| 0x07 | F64Array |
f64_array |
가변 | u16 BE | N x f64 BE |
| 0x08 | F32Array |
f32_array |
가변 | u16 BE | N x f32 BE |
| 0x09 | I32Array |
i32_array |
가변 | u16 BE | N x i32 BE |
| 0x0A | Json |
json |
가변 | u32 BE | UTF-8 JSON. 길이 접두사는 u32 |
| 0x0B | I16 |
i16 |
2 바이트 | — | 부호 있는 16비트 정수, BE |
| 0x0C | I8 |
i8 |
1 바이트 | — | 부호 있는 8비트 정수 (u8 cast to i8) |
와이어 태그 0x0D부터 0xFF는 예약되어 있다. 알 수 없는 태그를 받은 디코더는 오류(InvalidValueType)를 반환해야 한다.
6. 오디오 코덱 식별자¶
XMBP Bytes 스트림이 인코딩된 오디오를 전송할 때, 각 샘플 페이로드의 첫 번째 바이트는 코덱 식별자이다. 나머지 바이트는 코덱별 프레임 데이터이다.
| 코덱 ID | 상수 | 이름 | 설명 |
|---|---|---|---|
| 0x01 | CODEC_ID_RAW_PCM |
Raw PCM | 비압축 PCM 오디오 샘플 |
| 0x02 | CODEC_ID_ADPCM |
IMA-ADPCM | IMA Adaptive Differential PCM, 4:1 압축 |
| 0x03 | CODEC_ID_XAP |
XAP | Xylolabs Audio Protocol |
| 0x04 | CODEC_ID_OPUS |
Opus | Opus 코덱 (향후 사용을 위해 예약됨) |
XAP 파일 확장자는 .xap(XAP_FILE_EXTENSION)이다.
XAP 프레이밍, 코덱 파라미터, 성능 특성에 대한 상세 내용은 XAP-SPECIFICATION.md와 CODEC-ANALYSIS.md를 참조한다.
7. 인코딩 API¶
7.1 XmbpWriter¶
XmbpWriter는 제로 할당, no_std 호환 인코더이다. 호출자가 제공한 &mut [u8] 버퍼에 빅엔디언 인코딩 데이터를 직접 쓴다. 어느 시점에서든 버퍼가 요청된 쓰기를 수용할 수 없으면, 라이터는 오버플로우 상태로 진입하고 이후 모든 쓰기는 조용히 무시된다.
주요 메서드:
| 메서드 | 설명 |
|---|---|
XmbpWriter::new(buf: &mut [u8]) -> Self |
주어진 버퍼 위에 라이터를 생성한다. |
reset(&mut self) |
위치를 0으로 리셋하고 오버플로우 플래그를 초기화한다. |
len(&self) -> usize |
지금까지 쓴 바이트 수. |
is_ok(&self) -> bool |
오버플로우가 발생하지 않은 경우 true를 반환한다. |
write_batch_header(version: u8, flags: u8, batch_seq: u16) |
magic + version + flags + batch_seq를 쓴다 (8 바이트). |
write_device_id(device_id: u32) |
선택적 장치 ID 필드를 쓴다 (4 바이트). |
write_stream_count(count: u16) |
스트림 카운트를 쓴다 (2 바이트). |
begin_stream(stream_id: u16, value_type: MetadataValueType, sample_count: u16) |
스트림 블록 헤더를 쓴다 (5 바이트). |
write_sample_f32(timestamp_us: u64, value: f32) |
F32 샘플 하나를 쓴다 (12 바이트). |
write_sample_f64(timestamp_us: u64, value: f64) |
F64 샘플 하나를 쓴다 (16 바이트). |
write_sample_i32(timestamp_us: u64, value: i32) |
I32 샘플 하나를 쓴다 (12 바이트). |
write_sample_i64(timestamp_us: u64, value: i64) |
I64 샘플 하나를 쓴다 (16 바이트). |
write_sample_i16(timestamp_us: u64, value: i16) |
I16 샘플 하나를 쓴다 (10 바이트). |
write_sample_i8(timestamp_us: u64, value: i8) |
I8 샘플 하나를 쓴다 (9 바이트). |
write_sample_bool(timestamp_us: u64, value: bool) |
Bool 샘플 하나를 쓴다 (9 바이트). |
write_sample_string(timestamp_us: u64, s: &str) |
String 샘플 하나를 쓴다 (가변). |
write_sample_bytes(timestamp_us: u64, data: &[u8]) |
Bytes 샘플 하나를 쓴다 (가변). |
write_sample_f32_array(timestamp_us: u64, values: &[f32]) |
F32Array 샘플 하나를 쓴다 (가변). |
write_sample_f64_array(timestamp_us: u64, values: &[f64]) |
F64Array 샘플 하나를 쓴다 (가변). |
write_sample_i32_array(timestamp_us: u64, values: &[i32]) |
I32Array 샘플 하나를 쓴다 (가변). |
write_sample_json(timestamp_us: u64, json_str: &str) |
Json 샘플 하나를 쓴다 (가변. u32 길이 접두사). |
build_f32_batch(...) -> usize |
편의용: 단일 호출로 균일한 F32 배치 전체를 인코딩한다. |
7.2 인코딩 예제¶
use xylolabs_protocol::{XmbpWriter, MetadataValueType, constants};
let mut buf = [0u8; 256];
let mut w = XmbpWriter::new(&mut buf);
// Write batch header: version=1, no flags, sequence=0
w.write_batch_header(constants::XMBP_VERSION, 0, 0);
// Write stream count
w.write_stream_count(1);
// Begin stream 0: F32 type, 1 sample
w.begin_stream(0, MetadataValueType::F32, 1);
// Write sample: timestamp 1000 µs, value 23.5
w.write_sample_f32(1000, 23.5);
assert!(w.is_ok());
let len = w.len();
drop(w);
let encoded = &buf[..len]; // 22 bytes total
7.3 편의 빌더 (균일 F32 스트림)¶
use xylolabs_protocol::{XmbpWriter, constants};
let mut buf = [0u8; 512];
let mut w = XmbpWriter::new(&mut buf);
let timestamps = [1000u64, 2000, 3000];
let values = [1.0f32, 2.0, 3.0, // stream 0
4.0, 5.0, 6.0]; // stream 1
let size = w.build_f32_batch(
0, // batch_seq
0xABCD, // device_id (pass 0 to omit)
2, // num_streams
3, // samples_per_stream
×tamps,
&values,
3, // values_stride
);
assert!(size > 0);
values는 values[stream * values_stride + sample] 형태로 배치된다. device_id = 0을 전달하면 장치 ID 필드가 생략된다.
7.4 버퍼 크기 상수¶
constants 모듈은 컴파일 타임 크기 헬퍼를 제공한다:
| 상수 | 값 | 설명 |
|---|---|---|
BATCH_HEADER_BASE |
8 | magic(4) + version(1) + flags(1) + batch_seq(2) |
DEVICE_ID_SIZE |
4 | 선택적 device_id 필드 |
STREAM_COUNT_SIZE |
2 | stream_count 필드 |
STREAM_HEADER_SIZE |
5 | stream_id(2) + value_type(1) + sample_count(2) |
SAMPLE_F64_SIZE |
16 | timestamp(8) + f64(8) |
SAMPLE_F32_SIZE |
12 | timestamp(8) + f32(4) |
SAMPLE_I64_SIZE |
16 | timestamp(8) + i64(8) |
SAMPLE_I32_SIZE |
12 | timestamp(8) + i32(4) |
SAMPLE_I16_SIZE |
10 | timestamp(8) + i16(2) |
SAMPLE_I8_SIZE |
9 | timestamp(8) + i8(1) |
SAMPLE_BOOL_SIZE |
9 | timestamp(8) + bool(1) |
batch_size 컴파일 타임 헬퍼:
use xylolabs_protocol::constants;
// Buffer for 4 streams × 100 F32 samples, with device ID
let required = constants::batch_size(4, 100, constants::SAMPLE_F32_SIZE, true);
// = 8 + 4 + 2 + 4 * (5 + 100 * 12) = 14 + 4 * 1205 = 4834 bytes
8. 디코딩 API¶
8.1 XmbpReader¶
XmbpReader는 무상태 디코더이다. 원시 &[u8] 슬라이스에서 완전한 XMBP 배치를 구조화된 힙 할당 타입으로 디코딩한다. 디코더는 alloc 기능이 필요하다.
pub struct XmbpReader;
impl XmbpReader {
pub fn decode(data: &[u8]) -> Result<XmbpBatch, ProtocolError>;
}
디코딩된 타입:
| 타입 | 필드 |
|---|---|
XmbpBatch |
version: u8, flags: u8, batch_seq: u16, device_id: Option<u32>, stream_blocks: Vec<StreamBlock> |
StreamBlock |
stream_id: u16, value_type: MetadataValueType, samples: Vec<Sample> |
Sample |
timestamp_us: u64, value: SampleValue |
SampleValue |
열거형: F64(f64), F32(f32), I64(i64), I32(i32), Bool(bool), String(String), Bytes(Vec<u8>), F64Array(Vec<f64>), F32Array(Vec<f32>), I32Array(Vec<i32>), Json(String), I16(i16), I8(i8) |
오류 타입 (ProtocolError):
| 변형 | 의미 |
|---|---|
BufferOverflow |
할당 한계 초과 (스트림/배열 개수 제한) |
InvalidMagic |
매직 바이트가 0x584D4250과 일치하지 않는다. |
UnsupportedVersion |
버전 필드가 0x01이 아니다. |
InvalidValueType(u8) |
알 수 없는 값 타입 와이어 태그 |
UnexpectedEof |
예상된 바이트가 모두 읽히기 전에 입력이 끝났다. |
InvalidUtf8 |
String 또는 JSON 필드에 유효하지 않은 UTF-8이 포함되어 있다. |
디코더 안전 한계:
- 신뢰할 수 없는 데이터로부터 할당을 제한하기 위해
stream_count는 256으로 제한된다. - 배열 요소 개수(
F64Array,F32Array,I32Array)는 샘플당 4096으로 제한된다.
8.2 디코딩 예제¶
use xylolabs_protocol::{XmbpReader, SampleValue};
let batch = XmbpReader::decode(&encoded_bytes)?;
println!("batch seq={}, device={:?}", batch.batch_seq, batch.device_id);
for block in &batch.stream_blocks {
println!("stream {} ({:?}): {} samples", block.stream_id, block.value_type, block.samples.len());
for sample in &block.samples {
match &sample.value {
SampleValue::F32(v) => {
println!(" t={} us val={}", sample.timestamp_us, v);
}
SampleValue::F64(v) => {
println!(" t={} us val={}", sample.timestamp_us, v);
}
_ => {}
}
}
}
9. 기능 플래그¶
xylolabs-protocol 크레이트는 코드 크기와 의존성을 제어하기 위해 Cargo 기능 플래그를 사용한다.
| 기능 | 기본값 | 효과 |
|---|---|---|
alloc |
아니오 | decode 모듈 활성화: XmbpReader, XmbpBatch, StreamBlock, Sample, SampleValue |
std |
아니오 | alloc을 포함한다. ProtocolError에 std::error::Error 구현을 제공한다. |
serde |
아니오 | MetadataValueType에 Serialize / Deserialize를 파생시킨다. |
기능 플래그 없이는 XmbpWriter, MetadataValueType, ProtocolError, constants만 컴파일된다. 이것이 힙 할당이 불가능한 베어메탈 펌웨어에서 사용되는 설정이다.
10. 전송¶
10.1 API 키 검증 (Ping)¶
인제스트 세션을 시작하기 전에 펌웨어에서 API 키가 유효한지 간단히 확인할 수 있다:
키가 유효하면 200 OK와 {"pong": true, "api_key_name": "...", "facility_id": "..."}를 반환하고, 유효하지 않으면 401을 반환한다. 세션 리소스를 할당하기 전에 잘못된 키를 조기에 감지하는 데 사용한다.
10.2 인제스트 엔드포인트¶
XMBP 배치는 Xylolabs 인제스트 API에 HTTP/1.1 POST 요청으로 전달된다:
POST /api/v1/ingest/sessions/{session_id}/data
Host: api.xylolabs.com
Content-Type: application/octet-stream
X-API-Key: <device-api-key>
Content-Length: <byte count>
<raw XMBP batch bytes>
session_id는 활성 인제스트 세션을 식별하는 UUID이며, 세션 생성 엔드포인트에서 얻는다.X-API-Key헤더는 인증을 위한 장치 범위 API 키를 전달한다.- 요청 본문은 추가 프레이밍이나 인코딩 없는 원시 XMBP 배치이다.
10.3 배치 시퀀싱¶
batch_seq 필드(u16, 65535에서 래핑)는 송신자가 유지하는 단조 증가 카운터이다. 서버는 갭 감지에 이를 사용한다: 연속 수신 배치의 batch_seq 값이 순차적이지 않으면 서버는 갭 이벤트를 기록한다. 송신자는 각 전송 배치마다 batch_seq를 1씩 증가시킨다.
10.4 장치 ID¶
FLAG_HAS_DEVICE_ID가 설정된 경우, device_id 필드(u32)는 멀티 장치 배포에서 원본 하드웨어 단위를 식별한다. 서버는 배치를 매칭하는 등록된 장치 레코드와 연결한다.
11. 저장 포맷 (XMCH)¶
인제스트 후 서버는 XMCH (Xylolabs Metadata Chunk) 포맷으로 샘플을 저장한다. XMCH는 압축 개선을 위해 타임스탬프와 값을 분리하는 열 지향 레이아웃을 사용한다.
11.1 XMCH 헤더 (32 바이트, 고정)¶
Offset Size Field Value / Notes
------ ---- ----- ------
0 4 magic 0x58 0x4D 0x43 0x48 (ASCII "XMCH")
4 1 version 0x01
5 1 value_type MetadataValueType wire tag (same as XMBP)
6 2 reserved 0x0000
8 4 sample_count u32 BE — number of samples in this chunk
12 8 start_ts_us u64 BE — timestamp of first sample
20 8 end_ts_us u64 BE — timestamp of last sample
28 4 data_bytes u32 BE — byte count of the data section
총 헤더 크기: 32 바이트.
11.2 데이터 섹션 레이아웃¶
32바이트 헤더 바로 다음:
- 타임스탬프 열:
sample_countxu64 BE— 오름차순의 모든 타임스탬프. - 값 열: XMBP 샘플 값 인코딩과 동일하게 인코딩된
sample_count개의 값 (동일한 타입별 규칙, 동일한 바이트 순서). 단, 샘플별 타임스탬프 접두사는 없다.
가변 길이 타입(String, Bytes, F64Array, F32Array, I32Array)의 경우, 값 열의 각 값은 u32 BE 길이/개수 접두사를 사용한다 (XMBP 와이어 포맷의 u16과 다름).
Json의 경우, 값 열은 XMBP 와이어 포맷과 동일하게 u32 BE 길이 접두사를 사용한다.
11.3 압축¶
XMCH 청크는 zstd를 사용하여 압축 저장될 수 있다. 압축 해제하면 위에서 설명한 원시 32바이트 헤더 + 데이터 섹션 레이아웃이 생성된다. 서버는 압축 해제 폭탄 공격을 방지하기 위해 압축 해제 출력에 64 MiB 한계를 적용한다.
11.4 빈 청크¶
sample_count = 0인 청크는 data_bytes = 0인 32바이트 헤더만 포함한다. 타임스탬프와 데이터 섹션은 없다.
12. 와이어 포맷 예제¶
12.1 최소 배치 (10 바이트)¶
스트림 없이, 장치 ID 없이, 시퀀스 번호 42인 배치:
Offset Hex Description
------ --- -----------
0 58 magic[0] 'X'
1 4D magic[1] 'M'
2 42 magic[2] 'B'
3 50 magic[3] 'P'
4 01 version = 1
5 00 flags = 0 (no device ID)
6 00 batch_seq high byte
7 2A batch_seq low byte (= 42)
8 00 stream_count high byte
9 00 stream_count low byte (= 0)
합계: 10 바이트.
12.2 단일 F32 스트림 (29 바이트)¶
스트림 하나, F32 샘플 하나 (timestamp=1000 µs, value=23.5):
Offset Hex Description
------ --- -----------
0-3 58 4D 42 50 magic "XMBP"
4 01 version
5 00 flags (no device ID)
6-7 00 00 batch_seq = 0
8-9 00 01 stream_count = 1
--- stream block 0 ---
10-11 00 00 stream_id = 0
12 01 value_type = F32 (tag 0x01)
13-14 00 01 sample_count = 1
--- sample 0 ---
15-22 00 00 00 00 timestamp_us = 1000 µs
00 00 03 E8 (u64 BE: 0x00000000000003E8)
23-26 41 BC 00 00 f32 BE = 23.5 (IEEE 754: 0x41BC0000)
합계: 29 바이트.
12.3 장치 ID가 있는 멀티스트림 배치¶
F32 스트림 둘 (각 2개 샘플), device_id = 0x0000ABCD:
Offset Hex Description
------ --- -----------
0-3 58 4D 42 50 magic "XMBP"
4 01 version
5 01 flags = 0x01 (FLAG_HAS_DEVICE_ID)
6-7 00 05 batch_seq = 5
8-11 00 00 AB CD device_id = 0x0000ABCD
12-13 00 02 stream_count = 2
--- stream block 0 (stream_id=0, F32, 2 samples) ---
14-15 00 00 stream_id = 0
16 01 value_type = F32
17-18 00 02 sample_count = 2
19-30 [sample 0: 8-byte ts + 4-byte f32]
31-42 [sample 1: 8-byte ts + 4-byte f32]
--- stream block 1 (stream_id=1, F32, 2 samples) ---
43-44 00 01 stream_id = 1
45 01 value_type = F32
46-47 00 02 sample_count = 2
48-59 [sample 0: 8-byte ts + 4-byte f32]
60-71 [sample 1: 8-byte ts + 4-byte f32]
합계: 14 (헤더 + device_id) + 2 * (5 + 2 * 12) = 14 + 2 * 29 = 72 바이트.
13. 관련 문서¶
| 문서 | 설명 |
|---|---|
| XAP-SPECIFICATION.md | XAP (Xylolabs Audio Protocol) 프레이밍, 코덱 파라미터, 컨테이너 포맷 |
| CODEC-ANALYSIS.md | XMBP에서 지원하는 오디오 코덱의 비교 분석 |
| API.en.md | Xylolabs REST API 참조 (인제스트, 세션, 장치) |
| PERFORMANCE-EVALUATION.md | 프로토콜 처리량 및 지연 벤치마크 |
14. 법적 고지¶
XMBP (Xylolabs Metadata Binary Protocol)는 Xylolabs Inc.가 개발한 독점 기술이다.
XMBP 와이어 포맷, 인코딩 방법론 및 관련 시스템을 포함하는 특허 출원이 제출되었다. 모든 권리가 보유된다.
Xylolabs Inc.의 사전 서면 승인 없이 본 명세서 또는 그 구현의 전부 또는 일부를 무단으로 사용, 복제, 수정 또는 배포하는 것은 엄격히 금지된다.
Copyright (c) Xylolabs Inc. All rights reserved.