1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
extern crate byteorder;

pub mod frame;
pub mod frames;

use std::fs::File;
use std::io::Result as IoResult;
use std::io::{Error, ErrorKind};
use std::io::Cursor;
use std::io::SeekFrom;
use std::io::prelude::*;
use std::io::Read;
use byteorder::{ByteOrder, LittleEndian};
use self::frames::Frames;


pub struct AVI {
    pub frames: Frames,
}

impl AVI {
    pub fn new(filename: &str) -> IoResult<AVI> {
        let mut f = File::open(filename)?;
        let mut buf: Vec<u8> = Vec::new();
        f.read_to_end(&mut buf)?;
        is_formatted(&buf)?;
        let frames = Frames::new(buf)?;
        Ok(AVI {
            frames: frames,
        })
    }

    pub fn output(&mut self, filename: &str) -> IoResult<()> {
        let io = self.frames.make_framedata()?;
        self.frames.overwrite(io);
        let mut f = File::create(filename)?;
        f.write(&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, "Malformed AVI"));
    }
    reader.seek(SeekFrom::Current(4))?;
    reader.read_exact(&mut buf)?;
    if buf != *b"AVI " {
        return Err(Error::new(ErrorKind::InvalidData, "Malformed AVI"));
    }
    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, "Malformed AVI"));
    }
    Ok(())
}