A pure-Rust implementation of the GoPro GPMF™ (General Purpose Metadata Format) parser.
GPMF is a modified Key-Length-Value (KLV) solution used to store high-frequency sensor telemetry (accelerometer, gyroscope, GPS, etc.) inside GoPro MP4 files. This crate faithfully ports the original C library to idiomatic Rust — zero external dependencies, zero-copy buffer access, and full Result-based error handling.
- Parse GPMF structured metadata from raw
&[u32]buffers - Validate nested KLV structures with configurable recursion depth
- Navigate with
next(),find_next(),find_prev(),seek_to_samples() - Extract sensor data with automatic big-endian → native byte-swapping (
formatted_data) - Scale data by applying SCAL divisors (
scaled_data) - Modify KLV entries in-place via
GpmfStreamMut - Complex types — expand
"f[8]L"→"ffffffffL"and compute struct sizes - Decompression — codebook structure and direct-copy fallback for compressed payloads
use gpmf_parser::{GpmfStream, Levels, SampleType, keys, make_id};
// `raw` is a &[u32] buffer containing GPMF data (starting with DEVC).
let mut stream = GpmfStream::new(raw).expect("invalid GPMF");
// Validate structure
stream.validate(Levels::RECURSE).expect("bad structure");
// Find accelerometer data
let accl = make_id!(b'A', b'C', b'C', b'L');
stream.find_next(accl, Levels::RECURSE).unwrap();
println!("Type: {:?}, Elements: {}, Samples: {}",
stream.sample_type(),
stream.elements_in_struct(),
stream.repeat());
// Extract byte-swapped data
let size = stream.struct_size() as usize * stream.repeat() as usize;
let mut buf = vec![0u8; size];
stream.formatted_data(&mut buf, 0, stream.repeat()).unwrap();
// Or extract scaled floating-point values
let n = stream.elements_in_struct() as usize * stream.repeat() as usize;
let mut scaled = vec![0.0f64; n];
stream.scaled_data(&mut scaled, 0, stream.repeat()).unwrap();| Method | Description |
|---|---|
GpmfStream::new(buf) |
Initialize from a &[u32] buffer (must start with DEVC) |
reset_state() |
Reset cursor to the beginning |
clone() |
Snapshot all navigation state |
| Method | Description |
|---|---|
next(levels) |
Step to the next KLV entry |
find_next(fourcc, levels) |
Search forward for a FourCC |
find_prev(fourcc, levels) |
Search backward for a FourCC |
seek_to_samples() |
Jump to the last data entry in the current stream |
validate(levels) |
Check structural integrity |
| Method | Returns |
|---|---|
key() |
Current FourCC tag |
sample_type() |
Data type enum |
struct_size() |
Sample struct size in bytes |
repeat() |
Number of samples |
elements_in_struct() |
Elements per sample (e.g. 3 for XYZ) |
raw_data() |
&[u8] slice to raw payload |
nest_level() |
Current nesting depth |
device_id() / device_name() |
Auto-tracked device info |
| Method | Description |
|---|---|
formatted_data(buf, offset, count) |
Byte-swap from big-endian to native |
scaled_data(buf, offset, count) |
Apply SCAL divisor, output as f64 |
| Method | Description |
|---|---|
GpmfStreamMut::modify(...) |
In-place KLV overwrite (same aligned size) |
| Code | Type | Size |
|---|---|---|
b / B |
Signed / Unsigned byte | 1 |
s / S |
Signed / Unsigned short | 2 |
l / L |
Signed / Unsigned 32-bit int | 4 |
j / J |
Signed / Unsigned 64-bit int | 8 |
f |
Float (IEEE 754) | 4 |
d |
Double (IEEE 754) | 8 |
F |
FourCC tag | 4 |
c / u |
ASCII / UTF-8 string | 1 |
q / Q |
Q15.16 / Q31.32 fixed point | 4 / 8 |
U |
UTC date-time | 16 |
G |
GUID | 16 |
? |
Complex (uses TYPE descriptor) | varies |
# |
Compressed (Huffman) | varies |
cargo test --all44 tests: 35 unit tests across all modules + 9 integration tests with realistic multi-stream GPMF payloads.
Licensed under either of:
at your option.
This is the same dual-license scheme used by the original GoPro GPMF parser.
Based on the GoPro GPMF Parser — © GoPro Inc.