Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audible AAX support #99

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions src/mp4box/adrm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};

use serde::Serialize;
use std::io::{Read, Seek, Write};

use crate::mp4box::*;

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct AdrmBox {
#[serde(serialize_with = "<[_]>::serialize")]
pub drm_blob: [u8; 48],
pub file_checksum: [u8; 20],
#[serde(serialize_with = "<[_]>::serialize")]
pub unknown0: [u8; 60],
}

impl Mp4Box for AdrmBox {
fn box_type(&self) -> BoxType {
BoxType::AdrmBox
}

fn box_size(&self) -> u64 {
156
}

fn to_json(&self) -> Result<String> {
Ok(serde_json::to_string(&self).unwrap())
}

fn summary(&self) -> Result<String> {
let mut s = String::with_capacity(49);
s.push_str("checksum=");
for b in self.file_checksum.iter() {
s.push_str(&format!("{:02x}", b));
}
Ok(s)
}
}

impl<R: Read + Seek> ReadBox<&mut R> for AdrmBox {
fn read_box(reader: &mut R, size: u64) -> Result<Self> {
let start = box_start(reader)?;

let mut result = AdrmBox {
drm_blob: [0u8; 48],
file_checksum: [0u8; 20],
unknown0: [0u8; 60],
};

reader.read_u32::<BigEndian>()?; // 56
reader.read_u32::<BigEndian>()?; // 1
reader.read_exact(&mut result.drm_blob)?;
reader.read_u32::<BigEndian>()?; // 0
reader.read_u32::<BigEndian>()?; // 1
reader.read_u32::<BigEndian>()?; // 0
reader.read_exact(&mut result.file_checksum)?;
reader.read_exact(&mut result.unknown0)?;

assert_eq!(reader.stream_position()?, start + size);

Ok(result)
}
}

impl<W: Write> WriteBox<&mut W> for AdrmBox {
fn write_box(&self, writer: &mut W) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(self.box_type(), size).write(writer)?;

writer.write_u32::<BigEndian>(56)?;
writer.write_u32::<BigEndian>(1)?;
writer.write_all(&self.drm_blob)?;
writer.write_u32::<BigEndian>(0)?;
writer.write_u32::<BigEndian>(1)?;
writer.write_u32::<BigEndian>(0)?;
writer.write_all(&self.file_checksum)?;
writer.write_all(&self.unknown0)?;

Ok(size)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::mp4box::BoxHeader;
use std::io::Cursor;

#[test]
fn test_adrm() {
let src_box = AdrmBox {
drm_blob: [29u8; 48],
file_checksum: [244u8; 20],
unknown0: [113u8; 60],
};

let mut buf = Vec::new();
src_box.write_box(&mut buf).unwrap();
assert_eq!(buf.len(), src_box.box_size() as usize);

let mut reader = Cursor::new(&buf);
let header = BoxHeader::read(&mut reader).unwrap();
assert_eq!(header.name, BoxType::AdrmBox);
assert_eq!(src_box.box_size(), header.size);

let dst_box = AdrmBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}
}
2 changes: 2 additions & 0 deletions src/mp4box/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ use std::io::{Read, Seek, SeekFrom, Write};

use crate::*;

pub(crate) mod adrm;
pub(crate) mod avc1;
pub(crate) mod co64;
pub(crate) mod ctts;
Expand Down Expand Up @@ -237,6 +238,7 @@ boxtype! {
DayBox => 0xa9646179,
CovrBox => 0x636f7672,
DescBox => 0x64657363,
AdrmBox => 0x6164726d,
WideBox => 0x77696465
}

Expand Down
28 changes: 22 additions & 6 deletions src/mp4box/mp4a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use serde::Serialize;
use std::io::{Read, Seek, Write};

use crate::mp4box::*;
use crate::{adrm::AdrmBox, mp4box::*};

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Mp4aBox {
Expand All @@ -12,6 +12,7 @@ pub struct Mp4aBox {

#[serde(with = "value_u32")]
pub samplerate: FixedPointU16,
pub adrm: Option<AdrmBox>,
pub esds: Option<EsdsBox>,
}

Expand All @@ -22,6 +23,7 @@ impl Default for Mp4aBox {
channelcount: 2,
samplesize: 16,
samplerate: FixedPointU16::new(48000),
adrm: None,
esds: Some(EsdsBox::default()),
}
}
Expand All @@ -34,6 +36,7 @@ impl Mp4aBox {
channelcount: config.chan_conf as u16,
samplesize: 16,
samplerate: FixedPointU16::new(config.freq_index.freq() as u16),
adrm: None,
esds: Some(EsdsBox::new(config)),
}
}
Expand Down Expand Up @@ -89,9 +92,10 @@ impl<R: Read + Seek> ReadBox<&mut R> for Mp4aBox {
reader.read_u32::<BigEndian>()?; // pre-defined, reserved
let samplerate = FixedPointU16::new_raw(reader.read_u32::<BigEndian>()?);

let mut adrm = None;
let mut esds = None;
let current = reader.stream_position()?;
if current < start + size {
let mut current = reader.stream_position()?;
while current < start + size {
let header = BoxHeader::read(reader)?;
let BoxHeader { name, size: s } = header;
if s > size {
Expand All @@ -100,17 +104,27 @@ impl<R: Read + Seek> ReadBox<&mut R> for Mp4aBox {
));
}

if name == BoxType::EsdsBox {
esds = Some(EsdsBox::read_box(reader, s)?);
match name {
BoxType::AdrmBox => {
adrm = Some(AdrmBox::read_box(reader, s)?);
}
BoxType::EsdsBox => {
esds = Some(EsdsBox::read_box(reader, s)?);
}
_ => {
skip_box(reader, s)?;
}
}
skip_bytes_to(reader, start + size)?;

current = reader.stream_position()?;
}

Ok(Mp4aBox {
data_reference_index,
channelcount,
samplesize,
samplerate,
adrm,
esds,
})
}
Expand Down Expand Up @@ -605,6 +619,7 @@ mod tests {
channelcount: 2,
samplesize: 16,
samplerate: FixedPointU16::new(48000),
adrm: None,
esds: Some(EsdsBox {
version: 0,
flags: 0,
Expand Down Expand Up @@ -647,6 +662,7 @@ mod tests {
channelcount: 2,
samplesize: 16,
samplerate: FixedPointU16::new(48000),
adrm: None,
esds: None,
};
let mut buf = Vec::new();
Expand Down
4 changes: 4 additions & 0 deletions src/mp4box/stsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ impl<R: Read + Seek> ReadBox<&mut R> for StsdBox {
BoxType::Tx3gBox => {
tx3g = Some(Tx3gBox::read_box(reader, s)?);
}
// aavd
BoxType::UnknownBox(0x61617664) => {
mp4a = Some(Mp4aBox::read_box(reader, s)?);
}
_ => {}
}

Expand Down
Loading