# gpmf
## Parser and Writer for GoPro Metadata Format (GPMF)
WIP: Currently successfully parses all raw test data and logs the results.
## Design Goals
* Linux Philosophy, each tool does one thing and does it well
* Can be integrated in other tools, and in other languages than Rust
* Focus on clean, easy to understand code (no macros)
* Performant (but not at the expense of the previous item)
* Easy to read detailed log in order to be able to debug problems
* Memory safe parser
* Zero security vulnerabilities. Avoid problems found in other tools e.g.: [GoPro GPMF-parser Vulnerabilities](https://blog.inhq.net/posts/gopro-gpmf-parser-vuln-1/)
* Never generate exceptions, i.e.: Should never panic.
* Should pass fuzz tests i.e.: handle corrupt or junk data
* Should avoid DOS attacks. Possibly Add max buffer lengths.
* Gracefully recover from errors
* Handle unknown tags
* Roundtrip sensor data (without loss of precision or changing data type)
## Reporting Issues
If you have a file that is not handled please submit an issue, attaching the raw metadata file
## Feature Roadmap
* [x] Parser (WIP) at present just prints out data
* [ ] Create a structure to hold data
* [ ] Handle Scale
* [ ] Handle multiple sensor data 'mp4 boxes/atoms', as contained in mp4 file
* [ ] Return data in chronological order using Iterator and Tournament Tree
* [ ] Extract metadata from Live Stream via WiFi and Rtmp Url in realtime
* [ ] Handle exif data in images
* [ ] Writer
* [ ] Roundtrip sensor data
## Example
```rust
use std::path::Path;
use gpmf::byteorder_gpmf::parse_gpmf;
fn main() -> anyhow::Result<()> {
let path = Path::new("samples/karma.raw");
let text = std::fs::read(path)?;
let res=parse_gpmf(text.as_slice())?;
println!("{:?}",res);
Ok(())
}
```
## Example with Logging
```rust
use std::path::Path;
use gpmf::byteorder_gpmf::parse_gpmf;
use tracing::Level;
use tracing_subscriber::FmtSubscriber;
fn main() -> anyhow::Result<()> {
let subscriber = FmtSubscriber::builder()
.with_max_level(Level::DEBUG)
.finish();
tracing::subscriber::set_global_default(subscriber)?;
let path = Path::new("samples/Fusion.raw");
let text = std::fs::read(path)?;
let res=parse_gpmf(text.as_slice())?;
println!("{:?}",res);
Ok(())
}
```
License: MIT OR Apache-2.0