add YUV4MPEG muxer
[nihav.git] / nihav-commonfmt / src / muxers / y4m.rs
CommitLineData
1ee737a4
KS
1use nihav_core::muxers::*;
2
3struct Y4MMuxer<'a> {
4 bw: &'a mut ByteWriter<'a>,
5}
6
7impl<'a> Y4MMuxer<'a> {
8 fn new(bw: &'a mut ByteWriter<'a>) -> Self {
9 Self {
10 bw,
11 }
12 }
13}
14
15fn get_format_name(fmt: NAPixelFormaton) -> MuxerResult<&'static str> {
16 if fmt.model.is_yuv() && fmt.get_max_depth() == 8 {
17 match fmt.components {
18 1 => Ok("mono"),
19 3 => {
20 let uinfo = fmt.comp_info[1].unwrap();
21 let vinfo = fmt.comp_info[2].unwrap();
22 if uinfo.h_ss != vinfo.h_ss || uinfo.v_ss != vinfo.v_ss {
23 return Err(MuxerError::UnsupportedFormat);
24 }
25 match (uinfo.h_ss, vinfo.v_ss) {
26 (0, 0) => Ok("444"),
27 (1, 0) => Ok("422"),
28 (1, 1) => Ok("420"),
29 (2, 0) => Ok("411"),
30 _ => Err(MuxerError::UnsupportedFormat),
31 }
32 },
33 _ => Err(MuxerError::UnsupportedFormat),
34 }
35 } else {
36 Err(MuxerError::UnsupportedFormat)
37 }
38}
39
40impl<'a> MuxCore<'a> for Y4MMuxer<'a> {
41 fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
42 if strmgr.get_num_streams() != 1 {
43 return Err(MuxerError::InvalidArgument);
44 }
45 let vstr = strmgr.get_stream(0).unwrap();
46 if vstr.get_media_type() != StreamType::Video {
47 return Err(MuxerError::UnsupportedFormat);
48 }
49 let info = vstr.get_info();
50 let vinfo = info.get_properties().get_video_info().unwrap();
51 self.bw.write_buf(format!("YUV4MPEG2 W{} H{} F{}:{} C{}\n", vinfo.width, vinfo.height, vstr.tb_den, vstr.tb_num, get_format_name(vinfo.format)?).as_bytes())?;
52
53 Ok(())
54 }
55 fn mux_frame(&mut self, _strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()> {
56 if self.bw.tell() == 0 {
57 return Err(MuxerError::NotCreated);
58 }
59 let src = pkt.get_buffer();
60 self.bw.write_buf(b"FRAME\n")?;
61 self.bw.write_buf(&src)?;
62 Ok(())
63 }
64 fn flush(&mut self) -> MuxerResult<()> {
65 Ok(())
66 }
67 fn end(&mut self) -> MuxerResult<()> {
68 Ok(())
69 }
70}
71
72impl<'a> NAOptionHandler for Y4MMuxer<'a> {
73 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
74 fn set_options(&mut self, _options: &[NAOption]) { }
75 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
76}
77
78pub struct Y4MMuxerCreator {}
79
80impl MuxerCreator for Y4MMuxerCreator {
81 fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box<dyn MuxCore<'a> + 'a> {
82 Box::new(Y4MMuxer::new(bw))
83 }
84 fn get_name(&self) -> &'static str { "yuv4mpeg" }
85 fn get_capabilities(&self) -> MuxerCapabilities { MuxerCapabilities::SingleVideo("rawvideo") }
86}
87
88#[cfg(test)]
89mod test {
90 use nihav_core::codecs::*;
91 use nihav_core::demuxers::*;
92 use nihav_core::muxers::*;
93 use nihav_codec_support::test::enc_video::*;
94 use crate::*;
95
96 #[test]
97 fn test_y4m_muxer() {
98 let mut dmx_reg = RegisteredDemuxers::new();
99 generic_register_all_demuxers(&mut dmx_reg);
100 // sample: self-created with avconv
101 let dec_config = DecoderTestParams {
102 demuxer: "yuv4mpeg",
103 in_name: "assets/Misc/test.y4m",
104 limit: None,
105 stream_type: StreamType::None,
106 dmx_reg, dec_reg: RegisteredDecoders::new(),
107 };
108 let mut mux_reg = RegisteredMuxers::new();
109 generic_register_all_muxers(&mut mux_reg);
110 /*let enc_config = EncoderTestParams {
111 muxer: "yuv4mpeg",
112 enc_name: "",
113 out_name: "muxed.y4m",
114 mux_reg, enc_reg: RegisteredEncoders::new(),
115 };
116 test_remuxing(&dec_config, &enc_config);*/
117 test_remuxing_md5(&dec_config, "yuv4mpeg", &mux_reg,
118 [0x7586c1c5, 0x388209b8, 0xe08af8f8, 0x4b6b96c7]);
119 }
120}