mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-14 06:32:33 +00:00
Fix writing to opus
This commit is contained in:
parent
d0c84cf028
commit
1491ba55f0
2 changed files with 69 additions and 36 deletions
|
@ -4,7 +4,7 @@ version = "0.1.1"
|
||||||
authors = ["Serial <69764315+Serial-ATA@users.noreply.github.com>", "Tianyi <ShiTianyi2001@outlook.com>"]
|
authors = ["Serial <69764315+Serial-ATA@users.noreply.github.com>", "Tianyi <ShiTianyi2001@outlook.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "Fork of https://github.com/TianyiShi2001/audiotags, adding support for more file types and (optionally) duration"
|
description = "Unified IO for different types of audio metadata"
|
||||||
repository = "https://github.com/Serial-ATA/lofty-rs"
|
repository = "https://github.com/Serial-ATA/lofty-rs"
|
||||||
keywords = ["tags", "audio", "metadata"]
|
keywords = ["tags", "audio", "metadata"]
|
||||||
categories = ["accessibility", "multimedia::audio"]
|
categories = ["accessibility", "multimedia::audio"]
|
||||||
|
|
|
@ -53,26 +53,61 @@ where
|
||||||
Ok(c.into_inner())
|
Ok(c.into_inner())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Page {
|
||||||
|
pub size_idx: usize,
|
||||||
|
pub content: Vec<u8>,
|
||||||
|
pub header_type: u8,
|
||||||
|
pub start: usize,
|
||||||
|
pub end: usize,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn opus<T>(mut data: T, packet: &[u8]) -> Result<Vec<u8>>
|
pub(crate) fn opus<T>(mut data: T, packet: &[u8]) -> Result<Vec<u8>>
|
||||||
where
|
where
|
||||||
T: Read + Seek,
|
T: Read + Seek,
|
||||||
{
|
{
|
||||||
let mut beginning_sig = [0; 4];
|
fn read_page<V>(mut data: V) -> Result<Page>
|
||||||
data.read_exact(&mut beginning_sig)?;
|
where
|
||||||
|
V: Read + Seek,
|
||||||
|
{
|
||||||
|
let mut sig = [0; 4];
|
||||||
|
data.read_exact(&mut sig)?;
|
||||||
|
|
||||||
if &beginning_sig != b"OggS" {
|
if &sig != b"OggS" {
|
||||||
return Err(Error::UnknownFormat);
|
return Err(Error::UnknownFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut first_page = [0; 23];
|
let mut info = [0; 2];
|
||||||
data.read_exact(&mut first_page)?;
|
data.read_exact(&mut info)?;
|
||||||
|
|
||||||
let mut segment_table = vec![0; first_page[22] as usize];
|
let header_type = info[1];
|
||||||
|
|
||||||
|
let mut page = [0; 21];
|
||||||
|
data.read_exact(&mut page)?;
|
||||||
|
|
||||||
|
let size_idx = data.seek(SeekFrom::Current(0))? as usize;
|
||||||
|
|
||||||
|
let mut segment_table = vec![0; page[20] as usize];
|
||||||
data.read_exact(&mut segment_table)?;
|
data.read_exact(&mut segment_table)?;
|
||||||
|
|
||||||
let mut head = vec![0; segment_table.iter().map(|&b| b as usize).sum()];
|
let start = data.seek(SeekFrom::Current(0))? as usize;
|
||||||
data.read_exact(&mut head)?;
|
|
||||||
|
|
||||||
|
let mut content = vec![0; segment_table.iter().map(|&b| b as usize).sum()];
|
||||||
|
data.read_exact(&mut content)?;
|
||||||
|
|
||||||
|
let end = data.seek(SeekFrom::Current(0))? as usize;
|
||||||
|
|
||||||
|
Ok(Page {
|
||||||
|
size_idx,
|
||||||
|
content,
|
||||||
|
header_type,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_page = read_page(&mut data)?;
|
||||||
|
|
||||||
|
let head = first_page.content;
|
||||||
let (ident, head) = head.split_at(8);
|
let (ident, head) = head.split_at(8);
|
||||||
|
|
||||||
if ident != b"OpusHead" {
|
if ident != b"OpusHead" {
|
||||||
|
@ -87,40 +122,38 @@ where
|
||||||
data.read_exact(&mut channel_mapping)?;
|
data.read_exact(&mut channel_mapping)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut sig = [0; 4];
|
let second_page = read_page(&mut data)?;
|
||||||
data.read_exact(&mut sig)?;
|
let tags = second_page.content;
|
||||||
|
let size_pos = second_page.size_idx;
|
||||||
if &sig != b"OggS" {
|
let start = second_page.start;
|
||||||
return Err(Error::UnknownFormat);
|
let end = second_page.end;
|
||||||
}
|
|
||||||
|
|
||||||
let mut second_page = [0; 23];
|
|
||||||
data.read_exact(&mut second_page)?;
|
|
||||||
|
|
||||||
let size_pos = data.seek(SeekFrom::Current(0))? as usize;
|
|
||||||
|
|
||||||
let mut segment_table = vec![0; second_page[22] as usize];
|
|
||||||
data.read_exact(&mut segment_table)?;
|
|
||||||
|
|
||||||
let start = data.seek(SeekFrom::Current(0))? as usize;
|
|
||||||
|
|
||||||
let mut tags = vec![0; segment_table.iter().map(|&b| b as usize).sum()];
|
|
||||||
data.read_exact(&mut tags)?;
|
|
||||||
|
|
||||||
let end = data.seek(SeekFrom::Current(0))? as usize;
|
|
||||||
|
|
||||||
if &tags[0..8] != b"OpusTags" {
|
if &tags[0..8] != b"OpusTags" {
|
||||||
return Err(Error::UnknownFormat);
|
return Err(Error::UnknownFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let last_len = (packet.len() % 255) as u8;
|
||||||
|
let needed = (packet.len() / 255) + 1;
|
||||||
|
|
||||||
|
let mut segments = Vec::with_capacity(needed);
|
||||||
|
|
||||||
|
for i in 0..needed {
|
||||||
|
if i + 1 < needed {
|
||||||
|
segments.push(255)
|
||||||
|
} else {
|
||||||
|
segments.push(last_len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data.seek(SeekFrom::Start(0))?;
|
data.seek(SeekFrom::Start(0))?;
|
||||||
|
|
||||||
let mut content = Vec::new();
|
let mut content = Vec::new();
|
||||||
data.read_to_end(&mut content)?;
|
data.read_to_end(&mut content)?;
|
||||||
|
|
||||||
content.splice(start..end, packet.to_vec());
|
content.splice(start..end, packet.to_vec());
|
||||||
content.insert(size_pos, (packet.len() % 255) as u8);
|
content.insert(size_pos - 1, needed as u8);
|
||||||
content.remove(size_pos + 1);
|
content.remove(size_pos);
|
||||||
|
content.splice(size_pos..start, segments);
|
||||||
|
|
||||||
Ok(content)
|
Ok(content)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue