rsplit/
webm.rs

1use std::fs::File;
2use std::io;
3use std::io::Write;
4use std::io::{Error, ErrorKind};
5use std::ffi::CString;
6use std::os::raw::c_void;
7use std::slice;
8
9#[link(name = "nestegg")]
10extern "C" {
11    fn vpx_init(filename: *const i8) -> *mut c_void;
12    fn vpx_read(input: *mut c_void, length: *mut u32) -> *const u8;
13    fn vpx_destroy(input: *mut c_void);
14}
15
16pub struct Webm {
17    pub input: String,
18    pub output: String,
19    pub frame_num: usize,
20    pub vp9: bool,
21}
22
23impl Webm {
24    pub fn helper() {
25        println!("Usage: rsplit webm input.webm output.ivf frame_num vp8|vp9")
26    }
27
28    pub fn new(args: &[String]) -> Result<Webm, &'static str> {
29        let l = args.len() as usize;
30        if l < 6 {
31            return Err("too less arguments for rsplit webm mode");
32        }
33
34        let input = args[2].clone();
35        let output = args[3].clone();
36        let frame_num_opt = args[4].clone().parse::<usize>();
37        let frame_num = match frame_num_opt {
38            Ok(frame_num) => frame_num,
39            Err(_) => {
40                return Err("can't parse frame_num as usize");
41            }
42        };
43        let vp9 = match args[5].to_lowercase().as_ref() {
44            "vp9" => true,
45            "vp8" => false,
46            _ => {
47                return Err("only support vp8 and vp9");
48            }
49        };
50
51        Ok(Webm {
52            input: input,
53            output: output,
54            frame_num: frame_num,
55            vp9: vp9,
56        })
57    }
58
59    pub fn run(&self) -> io::Result<()> {
60        println!("Convert {} into {}", self.input, self.output);
61        let c_input_string =
62            unsafe { CString::from_vec_unchecked(self.input.clone().into_bytes()) };
63        let input_ctx = unsafe { vpx_init(c_input_string.as_ptr()) };
64
65        let mut fo = try!(File::create(self.output.clone()));
66        let mut ivf_seq_header = [0u8; 32];
67        let mut ivf_frame_header = [0u8; 12];
68
69        ivf_seq_header[0] = 'D' as u8;
70        ivf_seq_header[1] = 'K' as u8;
71        ivf_seq_header[2] = 'I' as u8;
72        ivf_seq_header[3] = 'F' as u8;
73        ivf_seq_header[4] = 0; //version[0]
74        ivf_seq_header[5] = 0; //version[1]
75        ivf_seq_header[6] = 32; //length[0]
76        ivf_seq_header[7] = 0; //length[1]
77        ivf_seq_header[8] = 'V' as u8; //fourcc[0]
78        ivf_seq_header[9] = 'P' as u8; //fourcc[1]
79        if self.vp9 {
80            ivf_seq_header[10] = '9' as u8; //fourcc[2]
81        } else {
82            ivf_seq_header[10] = '8' as u8; //fourcc[2]
83        }
84        ivf_seq_header[11] = '0' as u8; //fourcc[3]
85        ivf_seq_header[12] = 0; //width[0]
86        ivf_seq_header[13] = 0; //width[1]
87        ivf_seq_header[14] = 0; //height[0]
88        ivf_seq_header[15] = 0; //height[1]
89        ivf_seq_header[16] = 0xE8; //frame_rate[0]
90        ivf_seq_header[17] = 0x03; //frame_rate[1]
91        ivf_seq_header[18] = 0x00; //frame_rate[2]
92        ivf_seq_header[19] = 0x00; //frame_rate[3]
93        ivf_seq_header[20] = 0x01; //time_scale[0]
94        ivf_seq_header[21] = 0x00; //time_scale[1]
95        ivf_seq_header[22] = 0x00; //time_scale[2]
96        ivf_seq_header[23] = 0x00; //time_scale[3]
97        ivf_seq_header[24] = ((self.frame_num >> 0) & 0xFF) as u8; //framenum[0]
98        ivf_seq_header[25] = ((self.frame_num >> 8) & 0xFF) as u8; //framenum[1]
99        ivf_seq_header[26] = ((self.frame_num >> 16) & 0xFF) as u8; //framenum[2]
100        ivf_seq_header[27] = ((self.frame_num >> 24) & 0xFF) as u8; //framenum[3]
101        ivf_seq_header[28] = 0; //unused[0]
102        ivf_seq_header[29] = 0; //unused[1]
103        ivf_seq_header[30] = 0; //unused[2]
104        ivf_seq_header[31] = 0; //unused[3]
105
106        let bytes_write = fo.write(&ivf_seq_header).unwrap();
107        if bytes_write != 32 {
108            return Err(Error::new(ErrorKind::Other, "bytes write is not expected ..."));
109        }
110
111        let mut frame_no = 0;
112        while frame_no < self.frame_num {
113            let mut len = 0;
114            let ptr = unsafe { vpx_read(input_ctx, &mut len) };
115            let buffer = unsafe { slice::from_raw_parts(ptr, len as usize) };
116
117            if len != 0 {
118                println!("Frame {:04}: {:8} bytes", frame_no, len);
119            } else {
120                break;
121            }
122            frame_no += 1;
123
124            ivf_frame_header[0] = ((len >> 0) & 0xFF) as u8; //frameSize[0]
125            ivf_frame_header[1] = ((len >> 8) & 0xFF) as u8; //frameSize[1]
126            ivf_frame_header[2] = ((len >> 16) & 0xFF) as u8; //frameSize[2]
127            ivf_frame_header[3] = ((len >> 24) & 0xFF) as u8; //frameSize[3]
128            let bytes_write = fo.write(&ivf_frame_header).unwrap();
129            if bytes_write != 12 {
130                return Err(Error::new(ErrorKind::Other, "bytes write is not expected ..."));
131            }
132            let bytes_write = fo.write(&buffer[0..(len as usize)]).unwrap();
133            if bytes_write != (len as usize) {
134                return Err(Error::new(ErrorKind::Other, "bytes write is not expected ..."));
135            }
136        }
137
138        unsafe { vpx_destroy(input_ctx) };
139
140        Ok(())
141    }
142}