1use super::meta;
7use crate::disc::DiscTitle;
8use std::io::{self, Write};
9
10pub struct StdioStream {
13 disc_title: DiscTitle,
14 reader: Option<io::Stdin>,
15 writer: Option<io::BufWriter<io::Stdout>>,
16 header_written: bool,
17 header_read: bool,
18 stored_codec_privates: Vec<Option<Vec<u8>>>,
19}
20
21impl StdioStream {
22 pub fn input() -> Self {
24 Self {
25 disc_title: DiscTitle::empty(),
26 reader: Some(io::stdin()),
27 writer: None,
28 header_written: false,
29 header_read: false,
30 stored_codec_privates: Vec::new(),
31 }
32 }
33
34 pub fn output(title: &DiscTitle) -> Self {
36 Self {
37 disc_title: title.clone(),
38 reader: None,
39 writer: Some(io::BufWriter::new(io::stdout())),
40 header_written: false,
41 header_read: false,
42 stored_codec_privates: Vec::new(),
43 }
44 }
45
46 fn ensure_header_read(&mut self) -> io::Result<()> {
48 if self.header_read {
49 return Ok(());
50 }
51 self.header_read = true;
52 if let Some(ref mut r) = self.reader {
53 if let Ok(Some(m)) = meta::read_header(r) {
54 let title = m.to_title();
55 self.stored_codec_privates = title.codec_privates.clone();
56 self.disc_title = title;
57 }
58 }
59 Ok(())
60 }
61}
62
63impl crate::pes::Stream for StdioStream {
64 fn read(&mut self) -> io::Result<Option<crate::pes::PesFrame>> {
65 self.ensure_header_read()?;
66 match &mut self.reader {
67 Some(r) => crate::pes::PesFrame::deserialize(r),
68 None => Err(crate::error::Error::StreamWriteOnly.into()),
69 }
70 }
71 fn write(&mut self, frame: &crate::pes::PesFrame) -> io::Result<()> {
72 match &mut self.writer {
73 Some(ref mut w) => {
74 if !self.header_written {
75 if !self.disc_title.streams.is_empty() {
76 let m = meta::M2tsMeta::from_title(&self.disc_title);
77 meta::write_header(w, &m)?;
78 }
79 self.header_written = true;
80 }
81 frame.serialize(w)
82 }
83 None => Err(crate::error::Error::StreamReadOnly.into()),
84 }
85 }
86 fn finish(&mut self) -> io::Result<()> {
87 if let Some(w) = &mut self.writer {
88 w.flush()?;
89 }
90 Ok(())
91 }
92 fn info(&self) -> &DiscTitle {
93 &self.disc_title
94 }
95
96 fn codec_private(&self, track: usize) -> Option<Vec<u8>> {
97 self.stored_codec_privates
98 .get(track)
99 .and_then(|c| c.clone())
100 }
101
102 fn headers_ready(&self) -> bool {
103 self.header_read || self.writer.is_some()
105 }
106}