mirror of
https://github.com/alfg/mp4-rust.git
synced 2025-01-03 00:48:40 +00:00
More tx3g box parsing/writing and update tests.
This commit is contained in:
parent
05e20124e0
commit
421d9e7606
5 changed files with 118 additions and 2 deletions
|
@ -4,7 +4,16 @@ use std::io::prelude::*;
|
|||
use std::io::{self, BufReader, BufWriter};
|
||||
use std::path::Path;
|
||||
|
||||
use mp4::{AacConfig, AvcConfig, HevcConfig, MediaConfig, MediaType, Mp4Config, Result, TrackConfig};
|
||||
use mp4::{
|
||||
AacConfig,
|
||||
AvcConfig,
|
||||
HevcConfig,
|
||||
TtxtConfig,
|
||||
MediaConfig,
|
||||
MediaType,
|
||||
Mp4Config,
|
||||
Result,
|
||||
TrackConfig};
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
@ -58,6 +67,7 @@ fn copy<P: AsRef<Path>>(src_filename: &P, dst_filename: &P) -> Result<()> {
|
|||
freq_index: track.sample_freq_index()?,
|
||||
chan_conf: track.channel_config()?,
|
||||
}),
|
||||
MediaType::TTXT => MediaConfig::TtxtConfig(TtxtConfig {}),
|
||||
};
|
||||
|
||||
let track_conf = TrackConfig {
|
||||
|
|
|
@ -23,8 +23,12 @@ impl StsdBox {
|
|||
let mut size = HEADER_SIZE + HEADER_EXT_SIZE + 4;
|
||||
if let Some(ref avc1) = self.avc1 {
|
||||
size += avc1.box_size();
|
||||
} else if let Some(ref hev1) = self.hev1 {
|
||||
size += hev1.box_size();
|
||||
} else if let Some(ref mp4a) = self.mp4a {
|
||||
size += mp4a.box_size();
|
||||
} else if let Some(ref tx3g) = self.tx3g {
|
||||
size += tx3g.box_size();
|
||||
}
|
||||
size
|
||||
}
|
||||
|
|
|
@ -6,12 +6,37 @@ use crate::mp4box::*;
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Tx3gBox {
|
||||
pub data_reference_index: u16,
|
||||
pub display_flags: u32,
|
||||
pub horizontal_justification: i8,
|
||||
pub vertical_justification: i8,
|
||||
pub bg_color_rgba: RgbaColor,
|
||||
pub box_record: [i16; 4],
|
||||
pub style_record: [u8; 12],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct RgbaColor {
|
||||
pub red: u8,
|
||||
pub green: u8,
|
||||
pub blue: u8,
|
||||
pub alpha: u8
|
||||
}
|
||||
|
||||
impl Default for Tx3gBox {
|
||||
fn default() -> Self {
|
||||
Tx3gBox {
|
||||
data_reference_index: 0,
|
||||
display_flags: 0,
|
||||
horizontal_justification: 1,
|
||||
vertical_justification: -1,
|
||||
bg_color_rgba: RgbaColor{
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 0,
|
||||
alpha: 255,
|
||||
},
|
||||
box_record: [0, 0, 0, 0],
|
||||
style_record: [0, 0, 0, 0, 0, 1, 0, 16, 255, 255, 255, 255],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +47,7 @@ impl Tx3gBox {
|
|||
}
|
||||
|
||||
pub fn get_size(&self) -> u64 {
|
||||
HEADER_SIZE + 8
|
||||
HEADER_SIZE + 6 + 32
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,10 +69,46 @@ impl<R: Read + Seek> ReadBox<&mut R> for Tx3gBox {
|
|||
reader.read_u16::<BigEndian>()?; // reserved
|
||||
let data_reference_index = reader.read_u16::<BigEndian>()?;
|
||||
|
||||
let display_flags = reader.read_u32::<BigEndian>()?;
|
||||
let horizontal_justification = reader.read_i8()?;
|
||||
let vertical_justification = reader.read_i8()?;
|
||||
let bg_color_rgba = RgbaColor {
|
||||
red: reader.read_u8()?,
|
||||
green: reader.read_u8()?,
|
||||
blue: reader.read_u8()?,
|
||||
alpha: reader.read_u8()?,
|
||||
};
|
||||
let box_record: [i16; 4] = [
|
||||
reader.read_i16::<BigEndian>()?,
|
||||
reader.read_i16::<BigEndian>()?,
|
||||
reader.read_i16::<BigEndian>()?,
|
||||
reader.read_i16::<BigEndian>()?,
|
||||
];
|
||||
let style_record: [u8; 12] = [
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
reader.read_u8()?,
|
||||
];
|
||||
|
||||
skip_bytes_to(reader, start + size)?;
|
||||
|
||||
Ok(Tx3gBox {
|
||||
data_reference_index,
|
||||
display_flags,
|
||||
horizontal_justification,
|
||||
vertical_justification,
|
||||
bg_color_rgba,
|
||||
box_record,
|
||||
style_record,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +121,19 @@ impl<W: Write> WriteBox<&mut W> for Tx3gBox {
|
|||
writer.write_u32::<BigEndian>(0)?; // reserved
|
||||
writer.write_u16::<BigEndian>(0)?; // reserved
|
||||
writer.write_u16::<BigEndian>(self.data_reference_index)?;
|
||||
writer.write_u32::<BigEndian>(self.display_flags)?;
|
||||
writer.write_i8(self.horizontal_justification)?;
|
||||
writer.write_i8(self.vertical_justification)?;
|
||||
writer.write_u8(self.bg_color_rgba.red)?;
|
||||
writer.write_u8(self.bg_color_rgba.green)?;
|
||||
writer.write_u8(self.bg_color_rgba.blue)?;
|
||||
writer.write_u8(self.bg_color_rgba.alpha)?;
|
||||
for n in 0..4 {
|
||||
writer.write_i16::<BigEndian>(self.box_record[n])?;
|
||||
}
|
||||
for n in 0..12 {
|
||||
writer.write_u8(self.style_record[n])?;
|
||||
}
|
||||
|
||||
Ok(size)
|
||||
}
|
||||
|
@ -75,6 +149,17 @@ mod tests {
|
|||
fn test_tx3g() {
|
||||
let src_box = Tx3gBox {
|
||||
data_reference_index: 1,
|
||||
display_flags: 0,
|
||||
horizontal_justification: 1,
|
||||
vertical_justification: -1,
|
||||
bg_color_rgba: RgbaColor{
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 0,
|
||||
alpha: 255,
|
||||
},
|
||||
box_record: [0, 0, 0, 0],
|
||||
style_record: [0, 0, 0, 0, 0, 1, 0, 16, 255, 255, 255, 255],
|
||||
};
|
||||
let mut buf = Vec::new();
|
||||
src_box.write_box(&mut buf).unwrap();
|
||||
|
|
13
src/track.rs
13
src/track.rs
|
@ -35,6 +35,7 @@ impl From<MediaConfig> for TrackConfig {
|
|||
MediaConfig::AvcConfig(avc_conf) => Self::from(avc_conf),
|
||||
MediaConfig::HevcConfig(hevc_conf) => Self::from(hevc_conf),
|
||||
MediaConfig::AacConfig(aac_conf) => Self::from(aac_conf),
|
||||
MediaConfig::TtxtConfig(ttxt_conf) => Self::from(ttxt_conf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +73,17 @@ impl From<AacConfig> for TrackConfig {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<TtxtConfig> for TrackConfig {
|
||||
fn from(txtt_conf: TtxtConfig) -> Self {
|
||||
Self {
|
||||
track_type: TrackType::Subtitle,
|
||||
timescale: 1000, // XXX
|
||||
language: String::from("und"), // XXX
|
||||
media_conf: MediaConfig::TtxtConfig(txtt_conf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Mp4Track {
|
||||
pub trak: TrakBox,
|
||||
|
@ -497,6 +509,7 @@ impl Mp4TrackWriter {
|
|||
let mp4a = Mp4aBox::new(aac_config);
|
||||
trak.mdia.minf.stbl.stsd.mp4a = Some(mp4a);
|
||||
}
|
||||
MediaConfig::TtxtConfig(ref _ttxt_config) => {}
|
||||
}
|
||||
Ok(Mp4TrackWriter {
|
||||
trak,
|
||||
|
|
|
@ -493,11 +493,15 @@ impl Default for AacConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Default)]
|
||||
pub struct TtxtConfig {}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum MediaConfig {
|
||||
AvcConfig(AvcConfig),
|
||||
HevcConfig(HevcConfig),
|
||||
AacConfig(AacConfig),
|
||||
TtxtConfig(TtxtConfig),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
Loading…
Reference in a new issue