extern crate byteorder;
pub mod frame;
pub mod frames;
use self::frames::Frames;
use byteorder::{ByteOrder, LittleEndian};
use std::fs::File;
use std::io::prelude::*;
use std::io::Cursor;
use std::io::Read;
use std::io::Result as IoResult;
use std::io::SeekFrom;
use std::io::{Error, ErrorKind};
use std::path::Path;
pub struct AVI {
pub frames: Frames,
}
impl AVI {
pub fn new<P: AsRef<Path>>(path: P) -> IoResult<Self> {
let mut f = File::open(path)?;
let mut buf: Vec<u8> = Vec::new();
f.read_to_end(&mut buf)?;
is_formatted(&buf)?;
let frames = Frames::new(&buf)?;
Ok(Self { frames })
}
pub fn output<P: AsRef<Path>>(&mut self, path: P) -> IoResult<()> {
let io = self.frames.make_framedata()?;
self.frames.overwrite(&io);
let mut f = File::create(path)?;
f.write_all(&self.frames.stream)?;
Ok(())
}
}
fn is_formatted(file: &Vec<u8>) -> IoResult<()> {
let mut reader = Cursor::new(&file);
let mut buf = [0u8; 4];
reader.read_exact(&mut buf)?;
if buf != *b"RIFF" {
return Err(Error::new(
ErrorKind::InvalidData,
format!(
"Malformed AVI, missing RIFF at expected position 0x{:x}",
reader.position()
),
));
}
reader.seek(SeekFrom::Current(4))?;
reader.read_exact(&mut buf)?;
if buf != *b"AVI " {
return Err(Error::new(
ErrorKind::InvalidData,
format!(
"Malformed AVI, missing AVI at expected position 0x{:x}",
reader.position()
),
));
}
reader.read_exact(&mut buf)?;
while buf == *b"LIST" || buf == *b"JUNK" {
reader.read_exact(&mut buf)?;
let s = LittleEndian::read_u32(&buf);
reader.seek(SeekFrom::Current(s.into()))?;
reader.read_exact(&mut buf)?;
}
if buf != *b"idx1" {
return Err(Error::new(
ErrorKind::InvalidData,
format!(
"Malformed AVI, missing idx1 at expected position 0x{:x}",
reader.position()
),
));
}
Ok(())
}