[](https://crates.io/crates/mp4-atom)
[](https://docs.rs/mp4-atom)
[](https://discord.gg/FCYF3p99mr)
# mp4-atom
This library provides encoding for the ISO Base Media File Format (ISO/IEC 14496-12).
It's meant to be low level, performing encoding/decoding of the binary format without
validation or interpretation of the data. You have to know what boxes to expect!
## Atoms
MP4 files are made up of atoms, which are boxes of data.
They have an upfront size and a 4-byte code to identify the type of box.
Examples include `moov`, `mdat`, `trak`, etc.
Unfortunately, the specification is quite complex and often gated behind a paywall.
Using this library does require some additional knowledge of the format otherwise you should use a higher level library.
See the [documentation](https://docs.rs/mp4-atom).
## Examples
### Decoding/encoding a byte buffer
```rust
use bytes::{Bytes, BufMut};
use mp4_atom::{Any, Encode, Decode, Ftyp};
// A simple ftyp atom
let mut input = Bytes::from_static(b"\0\0\0\x14ftypiso6\0\0\x02\0mp41");
let atom = Any::decode(&mut input.clone())?;
// Make sure we got the right atom
assert_eq!(atom, Ftyp {
major_brand: b"iso6".into(),
minor_version: 512,
compatible_brands: vec![b"mp41".into()],
}.into());
// Encode it back
let mut output = BufMut::new();
atom.encode(&mut output)?;
assert_eq!(input, output.freeze());
```
### Synchronous IO
NOTE: reading a `Mdat` atom will read the entire contents into memory.
See the next example to avoid this.
```rust
use mp4_atom::{Any, ReadFrom, WriteTo, Ftyp};
let mut reader = std::io::stdin();
let atom = Any::read_from(&mut reader)?;
// Make sure we got the right atom
assert_eq!(atom, Ftyp {
major_brand: b"iso6".into(),
minor_version: 512,
compatible_brands: vec![b"mp41".into()],
}.into());
// Encode it back to a Write type
let writer = std::io::stdout();
atom.write_to(&mut writer)?;
```
### Handling large atoms
To avoid reading large files into memory, you can call `Header::read_from` manually:
```rust
use mp4_atom::{Atom, Any, Header, ReadFrom, ReadAtom, WriteTo, Ftyp, Moov};
let mut reader = std::io::stdin();
let header = Header::read_from(&mut reader)?;
match header.kind {
Ftyp::KIND => {
let ftyp = Ftyp::read_atom(&header, &mut reader)?;
// Make sure we got the right atom
assert_eq!(ftyp, Ftyp {
major_brand: b"iso6".into(),
minor_version: 512,
compatible_brands: vec![b"mp41".into()],
});
},
Moov::KIND => {
// Manually decode the moov
match header.size {
Some(size) => { /* read size bytes */ },
None => { /* read until EOF */ },
};
},
_ => {
// You can also use Any if you prefer
let any = Any::read_atom(&header, &mut reader)?;
println!("Unknown atom: {:?}", any);
}
};
```
### Asynchronous IO
Enable using the `tokio` feature.
It's the same as the above two but using the `AsyncReadFrom`, `AsyncWriteTo`, and `AsyncReadAtom` traits instead.
There's also the `bytes` features which enables encoding for `Bytes` and `BytesMut` from the `bytes` crate, often used with tokio.