X-Git-Url: https://git.nihav.org/?p=nihav-tool.git;a=blobdiff_plain;f=src%2Fmain.rs;h=76e720ef3e46ed304522f592c918f07ef88e6c92;hp=4eafdcb9a96dc32af5c7a90dcc02298c32c2b216;hb=fabefb1bbbe0989b89e588a9409679cf3096d2d8;hpb=1e596ff31b7631a5ea3a8bce6aac073c10f2732b diff --git a/src/main.rs b/src/main.rs index 4eafdcb..76e720e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,20 @@ -extern crate nihav; +extern crate nihav_core; +extern crate nihav_codec_support; +extern crate nihav_registry; +extern crate nihav_allstuff; -use std::io::SeekFrom; +use std::io::{SeekFrom, Write}; use std::fs::File; use std::path::Path; -use nihav::io::byteio::{FileReader, ByteReader}; -use nihav::frame::*; -use nihav::codecs::*; -use nihav::demuxers::*; -use nihav::detect; +use nihav_core::io::byteio::{FileReader, ByteReader}; +use nihav_core::frame::*; +use nihav_core::codecs::*; +use nihav_core::demuxers::*; +use nihav_codec_support::imgwrite::*; +use nihav_registry::detect; +use nihav_allstuff::*; use std::env; -mod frmwriter; -use crate::frmwriter::*; - mod wavwriter; use crate::wavwriter::WavWriter; @@ -24,26 +26,22 @@ enum NumberMode { } struct FrameOutput { - prefix: &'static str, + prefix: String, streamno: usize, frameno: u64, nmode: NumberMode, } impl FrameOutput { - fn output_frame(&mut self, pkt: &NAPacket, frmref: NAFrameRef) { - let frm = frmref.borrow(); + fn output_frame(&mut self, pkt: &NAPacket, frm: NAFrameRef) { if frm.get_frame_type() != FrameType::Skip { let pts = match self.nmode { NumberMode::Counter => { self.frameno }, NumberMode::PktPTS => { pkt.get_pts().unwrap() }, NumberMode::FrmPTS => { if let Some(pt) = frm.get_pts() { pt } else { pkt.get_pts().unwrap() } }, }; - let frmbuf = frm.get_buffer().get_vbuf().unwrap(); - if frmbuf.get_info().get_format().is_paletted() { - write_palppm(self.prefix, self.streamno, pts, frm); - } else { - write_pgmyuv(self.prefix, self.streamno, pts, frm); + if let Err(_) = write_pnm(&self.prefix, self.streamno, pts, frm) { + println!("error writing output picture"); } } self.frameno += 1; @@ -56,13 +54,13 @@ struct AudioOutput { } impl AudioOutput { - fn new(name: &String) -> Self { Self { wwr: WavWriter::new(name), wrote_header: false } } + fn new(name: &str) -> Self { Self { wwr: WavWriter::new(name), wrote_header: false } } fn output_frame(&mut self, _pkt: &NAPacket, frm: NAFrameRef) { if !self.wrote_header { - self.wwr.write_header(frm.borrow().get_info().as_ref().get_properties().get_audio_info().unwrap()).unwrap(); + self.wwr.write_header(frm.get_info().as_ref().get_properties().get_audio_info().unwrap()).unwrap(); self.wrote_header = true; } - self.wwr.write_frame(frm.borrow().get_buffer()).unwrap(); + self.wwr.write_frame(frm.get_buffer()).unwrap(); } } @@ -79,14 +77,20 @@ fn main() { println!("usage: nihav-tool [-noout] [-vn] [-an] input [lastpts]"); return; } - let mut lastpts: Option = None; + let mut lastpts = NATimePoint::None; let mut cur_arg: usize = 1; let mut noout = false; let mut decode_video = true; let mut decode_audio = true; let mut nmode = NumberMode::FrmPTS; + let mut smode = FrameSkipMode::None; + let mut seek_time = NATimePoint::None; + let mut vpfx: Option = None; + let mut apfx: Option<&str> = None; + let mut ignore_errors = false; + let mut dump_frames = false; - while (cur_arg < args.len()) && (args[cur_arg].chars().next().unwrap() == '-') { + while (cur_arg < args.len()) && args[cur_arg].starts_with('-') { match args[cur_arg].as_str() { "--" => { break; }, "-noout" => { noout = true; }, @@ -95,6 +99,39 @@ fn main() { "-nm=count" => { nmode = NumberMode::Counter; }, "-nm=pktpts" => { nmode = NumberMode::PktPTS; }, "-nm=frmpts" => { nmode = NumberMode::FrmPTS; }, + "-skip=key" => { smode = FrameSkipMode::KeyframesOnly; }, + "-skip=intra" => { smode = FrameSkipMode::IntraOnly; }, + "-seek" => { + cur_arg += 1; + if cur_arg == args.len() { + println!("seek time missing"); + return; + } + let ret = args[cur_arg].parse::(); + if ret.is_err() { + println!("wrong seek time"); + return; + } + seek_time = ret.unwrap(); + }, + "-apfx" => { + cur_arg += 1; + if cur_arg == args.len() { + println!("name missing"); + return; + } + apfx = Some(&args[cur_arg]); + }, + "-vpfx" => { + cur_arg += 1; + if cur_arg == args.len() { + println!("name missing"); + return; + } + vpfx = Some(args[cur_arg].clone()); + }, + "-ignerr" => { ignore_errors = true; }, + "-dumpfrm" => { dump_frames = true; }, _ => { println!("unknown option {}", args[cur_arg]); return; }, } cur_arg += 1; @@ -102,7 +139,12 @@ fn main() { let name = args[cur_arg].as_str(); cur_arg += 1; if cur_arg < args.len() { - lastpts = Some(u64::from_str_radix(args[cur_arg].as_str(), 10).unwrap()); + let ret = args[cur_arg].parse::(); + if ret.is_err() { + println!("cannot parse end time"); + return; + } + lastpts = ret.unwrap(); } let path = Path::new(name); @@ -117,17 +159,31 @@ fn main() { } let (dmx_name, _) = res.unwrap(); println!("trying demuxer {} on {}", dmx_name, name); - dmx_fact = find_demuxer(dmx_name).unwrap(); + + let mut dmx_reg = RegisteredDemuxers::new(); + nihav_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + nihav_register_all_codecs(&mut dec_reg); + + dmx_fact = dmx_reg.find_demuxer(dmx_name).unwrap(); br.seek(SeekFrom::Start(0)).unwrap(); let mut dmx = create_demuxer(dmx_fact, &mut br).unwrap(); - let mut decs: Vec>> = Vec::new(); + if seek_time != NATimePoint::None { + let ret = dmx.seek(seek_time); + if ret.is_err() { +println!(" seek error {:?}", ret.err().unwrap()); + } + } + + let mut decs: Vec, Box)>> = Vec::new(); let mut sids: Vec = Vec::new(); let mut writers: Vec = Vec::new(); + let dec_opts = [NAOption{name: FRAME_SKIP_OPTION, value: NAValue::String(smode.to_string())}]; for i in 0..dmx.get_num_streams() { let s = dmx.get_stream(i).unwrap(); let info = s.get_info(); - let decfunc = find_decoder(info.get_name()); + let decfunc = dec_reg.find_decoder(info.get_name()); println!("stream {} - {} {}", i, s, info.get_name()); let str_id = s.get_id(); let mut has_out = false; @@ -139,10 +195,12 @@ println!("stream {} - {} {}", i, s, info.get_name()); return; } let mut dec = (decfunc.unwrap())(); - dec.init(info).unwrap(); - decs.push(Some(dec)); + let mut dsupp = Box::new(NADecoderSupport::new()); + dec.init(&mut dsupp, info).unwrap(); + dec.set_options(&dec_opts); + decs.push(Some((dsupp, dec))); if !noout { - writers.push(Outputter::Video(FrameOutput{prefix: "", streamno: i, frameno: 1, nmode: nmode})); + writers.push(Outputter::Video(FrameOutput{prefix: if let Some(ref str) = vpfx { str.clone() } else { "out".to_string() }, streamno: i, frameno: 1, nmode})); has_out = true; } } else { @@ -155,10 +213,15 @@ println!("stream {} - {} {}", i, s, info.get_name()); return; } let mut dec = (decfunc.unwrap())(); - dec.init(info).unwrap(); - decs.push(Some(dec)); + let mut dsupp = Box::new(NADecoderSupport::new()); + dec.init(&mut dsupp, info).unwrap(); + decs.push(Some((dsupp, dec))); if !noout { - let name = format!("out{:02}.wav", i); + let name = if let Some(apfx) = apfx { + format!("{}{:02}.wav", apfx, i) + } else { + format!("out{:02}.wav", i) + }; writers.push(Outputter::Audio(AudioOutput::new(&name))); has_out = true; } @@ -167,13 +230,13 @@ println!("stream {} - {} {}", i, s, info.get_name()); } } else { decs.push(None); -panic!("decoder {} not found", info.get_name()); } if !has_out { writers.push(Outputter::None); } } + let mut frmnum = 0; loop { let pktres = dmx.get_frame(); if let Err(e) = pktres { @@ -183,17 +246,35 @@ panic!("decoder {} not found", info.get_name()); let streamno = pkt.get_stream().get_id(); let sr = sids.iter().position(|x| *x == streamno); let idx = sr.unwrap(); - if let Some(ref mut dec) = decs[idx] { - let frm = dec.decode(&pkt).unwrap(); - if !noout { - match writers[idx] { - Outputter::Video(ref mut wr) => { wr.output_frame(&pkt, frm); }, - Outputter::Audio(ref mut wr) => { wr.output_frame(&pkt, frm); }, - _ => {}, - }; - } + if dump_frames { + let name = format!("out{:02}_{:08}.frm", streamno, pkt.get_pts().unwrap_or(frmnum)); + let mut ofile = File::create(name).unwrap(); + ofile.write(pkt.get_buffer().as_slice()).unwrap(); + frmnum += 1; + } + if let Some((ref mut dsupp, ref mut dec)) = decs[idx] { + match dec.decode(dsupp, &pkt) { + Ok(frm) => { + if !noout { + match writers[idx] { + Outputter::Video(ref mut wr) => { wr.output_frame(&pkt, frm); }, + Outputter::Audio(ref mut wr) => { wr.output_frame(&pkt, frm); }, + _ => {}, + }; + } + }, + Err(DecoderError::MissingReference) if seek_time != NATimePoint::None => { + println!("ignoring missing ref"); + }, + Err(reason) => { + println!("error decoding frame {:?}", reason); + if !ignore_errors { + break; + } + }, + }; + if pkt.get_pts() != None && lastpts != NATimePoint::None && !pkt.ts.less_than(lastpts) { break; } } - if pkt.get_pts() != None && lastpts.is_some() && pkt.get_pts() >= lastpts { break; } } //panic!("end"); }