From 4a835a2a1473188ae03bd7e495c8569c373de550 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sat, 19 Aug 2023 18:02:09 +0200 Subject: [PATCH] allow encoder to work with multiple inputs --- src/demux.rs | 102 +++++++----- src/main.rs | 434 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 354 insertions(+), 182 deletions(-) diff --git a/src/demux.rs b/src/demux.rs index 61ddbaf..9f6739d 100644 --- a/src/demux.rs +++ b/src/demux.rs @@ -7,6 +7,7 @@ use nihav_core::io::byteio::ByteReader; use nihav_allstuff::*; use crate::null::*; use crate::imgseq::*; +use crate::{SBBox, SelfBorrow}; pub struct FullRegister { pub dmx_reg: RegisteredDemuxers, @@ -53,16 +54,19 @@ impl<'a> RawStreamCtx<'a> { } } +type ReaderBox<'a> = SBBox, ByteReader<'a>>; + pub enum DemuxerObject<'a> { None, - Normal(Demuxer<'a>), - Raw(RawDemuxer<'a>, Vec>>, bool), - RawStream(RawStreamCtx<'a>), + Normal(SBBox, Demuxer<'a>>), + Raw(SBBox, RawDemuxer<'a>>, Vec>>, bool), + RawStream(SBBox, RawStreamCtx<'a>>), ImageSequence(ImgSeqDemuxer), } impl<'a> DemuxerObject<'a> { - pub fn create(br: &'a mut ByteReader<'a>, reg: &FullRegister, name: &str, ifmt: &Option, is_raw: bool) -> DemuxerObject<'a> { + pub fn create(mut brb: ReaderBox<'a>, reg: &FullRegister, name: &str, ifmt: &Option, is_raw: bool) -> DemuxerObject<'a> { + let br = brb.get_object_mut(); if !is_raw { let dmx_name = if let Some(ref dname) = ifmt { dname.as_str() @@ -76,7 +80,12 @@ impl<'a> DemuxerObject<'a> { println!("trying demuxer {} on {}", dmx_name, name); if let Some(dmx_fact) = reg.dmx_reg.find_demuxer(dmx_name) { br.seek(SeekFrom::Start(0)).unwrap(); - let dmx = create_demuxer(dmx_fact, br).unwrap(); + + let dmx = SelfBorrow::new(brb, |br_| { + unsafe { + create_demuxer(dmx_fact, br_.as_mut().unwrap().get_object_mut()).unwrap() + } + }); return DemuxerObject::Normal(dmx); } } @@ -87,9 +96,13 @@ impl<'a> DemuxerObject<'a> { println!("trying raw demuxer {} on {}", dmx_name, name); if let Some(rdmx_fact) = reg.rdmx_reg.find_demuxer(dmx_name) { br.seek(SeekFrom::Start(0)).unwrap(); - let dmx = create_raw_demuxer(rdmx_fact, br).unwrap(); + let dmx = SelfBorrow::new(brb, |br_| { + unsafe { + create_raw_demuxer(rdmx_fact, br_.as_mut().unwrap().get_object_mut()).unwrap() + } + }); let mut pkts = Vec::new(); - for stream in dmx.get_streams() { + for stream in dmx.get_object().get_streams() { if let Some(pcreate) = reg.pkt_reg.find_packetiser(stream.get_info().get_name()) { let packetiser = (pcreate)(); pkts.push(Some(packetiser)); @@ -104,9 +117,13 @@ impl<'a> DemuxerObject<'a> { if rdmx.check_format(br) { println!("detected {} as {}", name, rdmx.get_name()); br.seek(SeekFrom::Start(0)).unwrap(); - let dmx = create_raw_demuxer(*rdmx, br).unwrap(); + let dmx = SelfBorrow::new(brb, |br_| { + unsafe { + create_raw_demuxer(*rdmx, br_.as_mut().unwrap().get_object_mut()).unwrap() + } + }); let mut pkts = Vec::new(); - for stream in dmx.get_streams() { + for stream in dmx.get_object().get_streams() { if let Some(pcreate) = reg.pkt_reg.find_packetiser(stream.get_info().get_name()) { let packetiser = (pcreate)(); pkts.push(Some(packetiser)); @@ -134,11 +151,16 @@ impl<'a> DemuxerObject<'a> { if !pname.is_empty() { println!("found raw stream of type {} for {}", pname, name); let pcreate = reg.pkt_reg.find_packetiser(pname).unwrap(); - let mut packetiser = (pcreate)(); - packetiser.add_data(&buf[..size]); - let stream = packetiser.parse_stream(0).unwrap(); - packetiser.reset(); - DemuxerObject::RawStream(RawStreamCtx::new(stream, packetiser, br)) + let rctx = SelfBorrow::new(brb, |br_| { + unsafe { + let mut packetiser = (pcreate)(); + packetiser.add_data(&buf[..size]); + let stream = packetiser.parse_stream(0).unwrap(); + packetiser.reset(); + RawStreamCtx::new(stream, packetiser, br_.as_mut().unwrap().get_object_mut()) + } + }); + DemuxerObject::RawStream(rctx) } else { DemuxerObject::None } @@ -151,10 +173,10 @@ impl<'a> DemuxerObject<'a> { } pub fn get_duration(&self) -> u64 { match *self { - DemuxerObject::Normal(ref dmx) => dmx.get_duration(), - DemuxerObject::Raw(ref dmx, _, _) => dmx.get_duration(), + DemuxerObject::Normal(ref dmx) => dmx.get_object().get_duration(), + DemuxerObject::Raw(ref dmx, _, _) => dmx.get_object().get_duration(), DemuxerObject::RawStream(ref ctx) => { - NATimeInfo::ts_to_time(ctx.stream.duration, 1000, ctx.stream.tb_num, ctx.stream.tb_den) + NATimeInfo::ts_to_time(ctx.get_object().stream.duration, 1000, ctx.get_object().stream.tb_num, ctx.get_object().stream.tb_den) }, _ => 0, } @@ -162,43 +184,44 @@ impl<'a> DemuxerObject<'a> { pub fn get_num_streams(&self) -> usize { match *self { DemuxerObject::None => 0, - DemuxerObject::Normal(ref dmx) => dmx.get_num_streams(), - DemuxerObject::Raw(ref dmx, _, _) => dmx.get_num_streams(), + DemuxerObject::Normal(ref dmx) => dmx.get_object().get_num_streams(), + DemuxerObject::Raw(ref dmx, _, _) => dmx.get_object().get_num_streams(), DemuxerObject::RawStream(_) => 1, DemuxerObject::ImageSequence(_) => 1, } } pub fn get_stream(&self, idx: usize) -> Option { match *self { - DemuxerObject::Normal(ref dmx) => dmx.get_stream(idx), - DemuxerObject::Raw(ref dmx, _, _) => dmx.get_stream(idx), - DemuxerObject::RawStream(ref ctx) if idx == 0 => Some(ctx.stream.clone()), + DemuxerObject::Normal(ref dmx) => dmx.get_object().get_stream(idx), + DemuxerObject::Raw(ref dmx, _, _) => dmx.get_object().get_stream(idx), + DemuxerObject::RawStream(ref ctx) if idx == 0 => Some(ctx.get_object().stream.clone()), DemuxerObject::ImageSequence(ref ctx) if idx == 0 => Some(ctx.stream.clone()), _ => None, } } - pub fn get_streams(&self) -> StreamIter { + /*pub fn get_streams(&self) -> StreamIter { match *self { - DemuxerObject::Normal(ref dmx) => dmx.get_streams(), - DemuxerObject::Raw(ref dmx, _, _) => dmx.get_streams(), - DemuxerObject::RawStream(ref ctx) => ctx.sm.iter(), + DemuxerObject::Normal(ref dmx) => dmx.get_object().get_streams(), + DemuxerObject::Raw(ref dmx, _, _) => dmx.get_object().get_streams(), + DemuxerObject::RawStream(ref ctx) => ctx.get_object().sm.iter(), DemuxerObject::ImageSequence(ref ctx) => ctx.sm.iter(), _ => unreachable!(), } - } + }*/ pub fn get_stream_manager(&self) -> &StreamManager { match *self { - DemuxerObject::Normal(ref dmx) => dmx.get_stream_manager(), - DemuxerObject::Raw(ref dmx, _, _) => dmx.get_stream_manager(), - DemuxerObject::RawStream(ref ctx) => &ctx.sm, + DemuxerObject::Normal(ref dmx) => dmx.get_object().get_stream_manager(), + DemuxerObject::Raw(ref dmx, _, _) => dmx.get_object().get_stream_manager(), + DemuxerObject::RawStream(ref ctx) => &ctx.get_object().sm, DemuxerObject::ImageSequence(ref ctx) => &ctx.sm, _ => unreachable!(), } } pub fn get_frame(&mut self) -> DemuxerResult { match *self { - DemuxerObject::Normal(ref mut dmx) => dmx.get_frame(), + DemuxerObject::Normal(ref mut dmx) => dmx.get_object_mut().get_frame(), DemuxerObject::Raw(ref mut dmx, ref mut packetisers, ref mut eof) => { + let dmx = dmx.get_object_mut(); loop { let mut has_some = false; for (stream, p) in dmx.get_streams().zip(packetisers.iter_mut()) { @@ -237,6 +260,7 @@ impl<'a> DemuxerObject<'a> { } }, DemuxerObject::RawStream(ref mut ctx) => { + let ctx = ctx.get_object_mut(); let mut buf = [0; 65536]; loop { match ctx.packetiser.get_packet(ctx.stream.clone()) { @@ -277,8 +301,8 @@ impl<'a> DemuxerObject<'a> { } pub fn seek(&mut self, seek_time: NATimePoint) -> DemuxerResult<()> { match *self { - DemuxerObject::Normal(ref mut dmx) => dmx.seek(seek_time), - DemuxerObject::Raw(ref mut dmx, _, _) => dmx.seek(seek_time), + DemuxerObject::Normal(ref mut dmx) => dmx.get_object_mut().seek(seek_time), + DemuxerObject::Raw(ref mut dmx, _, _) => dmx.get_object_mut().seek(seek_time), DemuxerObject::ImageSequence(ref mut ctx) => ctx.seek(seek_time), _ => Err(DemuxerError::NotImplemented), } @@ -288,24 +312,24 @@ impl<'a> DemuxerObject<'a> { impl<'a> NAOptionHandler for DemuxerObject<'a> { fn get_supported_options(&self) -> &[NAOptionDefinition] { match *self { - DemuxerObject::Normal(ref dmx) => dmx.get_supported_options(), - DemuxerObject::Raw(ref dmx, _, _) => dmx.get_supported_options(), + DemuxerObject::Normal(ref dmx) => dmx.get_object().get_supported_options(), + DemuxerObject::Raw(ref dmx, _, _) => dmx.get_object().get_supported_options(), DemuxerObject::ImageSequence(ref ctx) => ctx.get_supported_options(), _ => &[], } } fn set_options(&mut self, options: &[NAOption]) { match *self { - DemuxerObject::Normal(ref mut dmx) => dmx.set_options(options), - DemuxerObject::Raw(ref mut dmx, _, _) => dmx.set_options(options), + DemuxerObject::Normal(ref mut dmx) => dmx.get_object_mut().set_options(options), + DemuxerObject::Raw(ref mut dmx, _, _) => dmx.get_object_mut().set_options(options), DemuxerObject::ImageSequence(ref mut ctx) => ctx.set_options(options), _ => {}, } } fn query_option_value(&self, name: &str) -> Option { match *self { - DemuxerObject::Normal(ref dmx) => dmx.query_option_value(name), - DemuxerObject::Raw(ref dmx, _, _) => dmx.query_option_value(name), + DemuxerObject::Normal(ref dmx) => dmx.get_object().query_option_value(name), + DemuxerObject::Raw(ref dmx, _, _) => dmx.get_object().query_option_value(name), DemuxerObject::ImageSequence(ref ctx) => ctx.query_option_value(name), _ => None, } diff --git a/src/main.rs b/src/main.rs index 97be1e2..9694836 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ extern crate nihav_allstuff; use std::fs::File; use std::io::{BufReader, Write}; +use std::pin::Pin; use nihav_core::io::byteio::{FileReader, ByteReader}; use nihav_core::frame::*; use nihav_core::options::*; @@ -26,6 +27,54 @@ use crate::acvt::*; mod imgseq; use crate::imgseq::*; +#[derive(Clone,Copy,Default,PartialEq)] +enum RegisterResult { + #[default] + Ok, + Ignored, + Failed, +} + +pub struct SelfBorrow { + bval: T, + dst: Option, +} + +impl SelfBorrow { + pub fn new(src: T, create: F) -> Pin> + where F: Fn(*mut T) -> U { + let mut obj = Box::pin(Self{ + bval: src, + dst: None, + }); + let ptr = &mut obj.bval as *mut T; + obj.dst = Some(create(ptr)); + obj + } + fn get_object(&self) -> &U { + if let Some(ref dst) = self.dst { + dst + } else { + unreachable!() + } + } + fn get_object_mut(&mut self) -> &mut U { + if let Some(ref mut dst) = self.dst { + dst + } else { + unreachable!() + } + } +} + +impl Drop for SelfBorrow { + fn drop(&mut self) { + self.dst = None; + } +} + +pub type SBBox = Pin>>; + const SND_NO_FORMAT: NASoniton = NASoniton { bits: 0, be: false, packed: false, planar: false, float: false, signed: false }; fn format_time(ms: u64) -> String { @@ -121,11 +170,11 @@ enum OutputMode { #[derive(Default)] #[allow(clippy::type_complexity)] struct Transcoder { - input_name: String, - input_fmt: Option, + input_name: [Option; 16], + input_fmt: [Option; 16], output_name: String, output_fmt: Option, - demux_opts: Vec, + demux_opts: [Vec; 16], mux_opts: Vec, istr_opts: Vec, ostr_opts: Vec, @@ -420,20 +469,20 @@ impl Transcoder { } true } - fn parse_demuxer_options(&mut self, opts: &str, dmx_reg: &RegisteredDemuxers) -> bool { + fn parse_demuxer_options(&mut self, opts: &str, dmx_reg: &RegisteredDemuxers, input_no: usize) -> bool { for opt in opts.split(',') { let oval: Vec<_> = opt.split('=').collect(); if oval.len() == 1 { - self.demux_opts.push(OptionArgs{ name: oval[0].to_string(), value: None }); + self.demux_opts[input_no].push(OptionArgs{ name: oval[0].to_string(), value: None }); } else if oval.len() == 2 { if oval[0] == "format" { if dmx_reg.find_demuxer(oval[1]).is_some() { - self.input_fmt = Some(oval[1].to_string()); + self.input_fmt[input_no] = Some(oval[1].to_string()); } else { println!("unknown demuxer format '{}'", oval[1]); } } else { - self.demux_opts.push(OptionArgs{ name: oval[0].to_string(), value: Some(oval[1].to_string()) }); + self.demux_opts[input_no].push(OptionArgs{ name: oval[0].to_string(), value: Some(oval[1].to_string()) }); } } else { println!("unrecognized option '{}'", opt); @@ -484,25 +533,25 @@ impl Transcoder { parse_and_apply_options!(dec, &self.istr_opts[str_idx].dec_opts, name); } } - fn register_output_stream(&mut self, cname: &str, istr: NAStreamRef, out_sm: &mut StreamManager, enc_reg: &RegisteredEncoders) -> bool { + fn register_output_stream(&mut self, cname: &str, istr: NAStreamRef, out_sm: &mut StreamManager, enc_reg: &RegisteredEncoders) -> RegisterResult { let out_id = out_sm.get_num_streams() as u32; if let Some(str_idx) = self.istr_opts.iter().position(|el| el.id == (istr.get_num() as u32)) { if self.istr_opts[str_idx].drop { self.encoders.push(OutputMode::Drop); - return true; + return RegisterResult::Ignored; } } if let Some(str_idx) = self.ostr_opts.iter().position(|el| el.id == out_id) { let oopts = &mut self.ostr_opts[str_idx]; if oopts.enc_name.as_str() == "copy" && (cname == "any" || istr.get_info().get_name() == cname) { - out_sm.add_stream_ref(istr); + out_sm.add_stream((*istr).clone()); self.encoders.push(OutputMode::Copy(out_id)); } else if cname == "any" || oopts.enc_name.as_str() == cname { let enc_create = enc_reg.find_encoder(oopts.enc_name.as_str()); if enc_create.is_none() { println!("encoder '{}' not found", oopts.enc_name.as_str()); - return false; + return RegisterResult::Failed; } let mut encoder = (enc_create.unwrap())(); let forced_out = oopts.enc_params.format != NACodecTypeInfo::None; @@ -543,7 +592,7 @@ impl Transcoder { let ret_eparams = encoder.negotiate_format(&oopts.enc_params); if ret_eparams.is_err() { println!("cannot negotiate encoding parameters"); - return false; + return RegisterResult::Failed; } let ret_eparams = ret_eparams.unwrap(); @@ -557,13 +606,13 @@ impl Transcoder { let ret = NAScale::new_with_options(ofmt, ofmt, &self.scale_opts); if ret.is_err() { println!("cannot create scaler"); - return false; + return RegisterResult::Failed; } let scaler = ret.unwrap(); let ret = alloc_video_buffer(*dvinfo, 4); if ret.is_err() { println!("cannot create scaler buffer"); - return false; + return RegisterResult::Failed; } let cvt_buf = ret.unwrap(); OutputConvert::Video(scaler, cvt_buf) @@ -578,7 +627,7 @@ impl Transcoder { 2 => NAChannelMap::from_ms_mapping(0x3), _ => { println!("can't generate default channel map for {} channels", dainfo.channels); - return false; + return RegisterResult::Failed; }, }; let acvt = AudioConverter::new(sainfo, dainfo, dchmap); @@ -591,7 +640,7 @@ println!("can't generate default channel map for {} channels", dainfo.channels); let ret = encoder.init(out_id, ret_eparams); if ret.is_err() { println!("error initialising encoder"); - return false; + return RegisterResult::Failed; } out_sm.add_stream_ref(ret.unwrap()); @@ -601,10 +650,10 @@ println!("can't generate default channel map for {} channels", dainfo.channels); self.encoders.push(OutputMode::Encode(out_id, encoder, cvt)); } else { println!("encoder {} is not supported by output (expected {})", istr.id, istr.get_info().get_name()); - return false; + return RegisterResult::Failed; } } else if cname == "any" || istr.get_info().get_name() == cname { - out_sm.add_stream_ref(istr); + out_sm.add_stream((*istr).clone()); self.encoders.push(OutputMode::Copy(out_id)); } else { let mut oopts = OutputStreamOptions {id: out_id, enc_name: cname.to_owned(), enc_params: EncodeParameters::default(), enc_opts: Vec::new() }; @@ -612,7 +661,7 @@ println!("encoder {} is not supported by output (expected {})", istr.id, istr.ge let enc_create = enc_reg.find_encoder(cname); if enc_create.is_none() { println!("encoder '{}' not found", oopts.enc_name.as_str()); - return false; + return RegisterResult::Failed; } let mut encoder = (enc_create.unwrap())(); oopts.enc_params.format = istr.get_info().get_properties(); @@ -621,7 +670,7 @@ println!("encoder {} is not supported by output (expected {})", istr.id, istr.ge let ret_eparams = encoder.negotiate_format(&oopts.enc_params); if ret_eparams.is_err() { println!("cannot negotiate encoding parameters"); - return false; + return RegisterResult::Failed; } let ret_eparams = ret_eparams.unwrap(); @@ -635,13 +684,13 @@ println!("encoder {} is not supported by output (expected {})", istr.id, istr.ge let ret = NAScale::new_with_options(ofmt, ofmt, &self.scale_opts); if ret.is_err() { println!("cannot create scaler"); - return false; + return RegisterResult::Failed; } let scaler = ret.unwrap(); let ret = alloc_video_buffer(*dvinfo, 4); if ret.is_err() { println!("cannot create scaler buffer"); - return false; + return RegisterResult::Failed; } let cvt_buf = ret.unwrap(); OutputConvert::Video(scaler, cvt_buf) @@ -656,7 +705,7 @@ println!("encoder {} is not supported by output (expected {})", istr.id, istr.ge 2 => NAChannelMap::from_ms_mapping(0x3), _ => { println!("can't generate default channel map for {} channels", dainfo.channels); - return false; + return RegisterResult::Failed; }, }; //todo channelmap @@ -669,13 +718,13 @@ println!("can't generate default channel map for {} channels", dainfo.channels); let ret = encoder.init(out_id, ret_eparams); if ret.is_err() { println!("error initialising encoder"); - return false; + return RegisterResult::Failed; } out_sm.add_stream_ref(ret.unwrap()); self.encoders.push(OutputMode::Encode(out_id, encoder, cvt)); self.ostr_opts.push(oopts); } - true + RegisterResult::Ok } fn map_single(&mut self, cname: &str, ctype: StreamType, src_sm: &StreamManager, out_sm: &mut StreamManager, enc_reg: &RegisteredEncoders) -> bool { let mut found_stream = false; @@ -683,10 +732,11 @@ println!("can't generate default channel map for {} channels", dainfo.channels); if istr.get_media_type() != ctype || found_stream { self.encoders.push(OutputMode::Drop); } else { - if !self.register_output_stream(cname, istr, out_sm, enc_reg) { - return false; - } - found_stream = true; + match self.register_output_stream(cname, istr, out_sm, enc_reg) { + RegisterResult::Ok => found_stream = true, + RegisterResult::Failed => return false, + RegisterResult::Ignored => {}, + }; } } found_stream @@ -706,15 +756,17 @@ println!("can't generate default channel map for {} channels", dainfo.channels); let mut found_aud = false; for istr in src_sm.iter() { if istr.get_media_type() == StreamType::Video && !found_vid && !self.no_video { - if !self.register_output_stream(vname, istr, out_sm, enc_reg) { - return false; - } - found_vid = true; + match self.register_output_stream(vname, istr, out_sm, enc_reg) { + RegisterResult::Ok => found_vid = true, + RegisterResult::Failed => return false, + RegisterResult::Ignored => {}, + }; } else if istr.get_media_type() == StreamType::Audio && !found_aud && !self.no_audio { - if !self.register_output_stream(aname, istr, out_sm, enc_reg) { - return false; - } - found_aud = true; + match self.register_output_stream(aname, istr, out_sm, enc_reg) { + RegisterResult::Ok => found_aud = true, + RegisterResult::Failed => return false, + RegisterResult::Ignored => {}, + }; } else { self.encoders.push(OutputMode::Drop); } @@ -727,10 +779,11 @@ println!("can't generate default channel map for {} channels", dainfo.channels); let mut found_vid = false; for istr in src_sm.iter() { if istr.get_media_type() == StreamType::Video && !found_vid { - if !self.register_output_stream("any", istr, out_sm, enc_reg) { - return false; - } - found_vid = true; + match self.register_output_stream("any", istr, out_sm, enc_reg) { + RegisterResult::Ok => found_vid = true, + RegisterResult::Failed => return false, + RegisterResult::Ignored => {}, + }; } else { self.encoders.push(OutputMode::Drop); } @@ -743,10 +796,11 @@ println!("can't generate default channel map for {} channels", dainfo.channels); let mut found_aud = false; for istr in src_sm.iter() { if istr.get_media_type() == StreamType::Audio && !found_aud { - if !self.register_output_stream("any", istr, out_sm, enc_reg) { - return false; - } - found_aud = true; + match self.register_output_stream("any", istr, out_sm, enc_reg) { + RegisterResult::Ok => found_aud = true, + RegisterResult::Failed => return false, + RegisterResult::Ignored => {}, + }; } else { self.encoders.push(OutputMode::Drop); } @@ -760,7 +814,7 @@ println!("can't generate default channel map for {} channels", dainfo.channels); self.encoders.push(OutputMode::Drop); continue; } - if !self.register_output_stream("any", istr, out_sm, enc_reg) { + if self.register_output_stream("any", istr, out_sm, enc_reg) == RegisterResult::Failed { return false; } } @@ -829,6 +883,24 @@ macro_rules! next_arg { } } +macro_rules! parse_id { + ($val: expr, $stype: expr, $maxval: expr) => { + if $val.is_empty() { + 0 + } else if let Ok(val) = $val.parse::() { + if val < $maxval { + val + } else { + println!("{} number should be below {}", $stype, $maxval); + return; + } + } else { + println!("invalid {} number '{}'", $stype, $val); + return; + } + } +} + #[allow(clippy::single_match)] fn main() { let args: Vec<_> = env::args().collect(); @@ -966,14 +1038,6 @@ fn main() { } printed_info = true; }, - "--input" | "-i" => { - next_arg!(args, arg_idx); - transcoder.input_name = args[arg_idx].clone(); - }, - "--input-format" => { - next_arg!(args, arg_idx); - transcoder.input_fmt = Some(args[arg_idx].clone()); - }, "--output" | "-o" => { next_arg!(args, arg_idx); transcoder.output_name = args[arg_idx].clone(); @@ -982,13 +1046,6 @@ fn main() { next_arg!(args, arg_idx); transcoder.output_fmt = Some(args[arg_idx].clone()); }, - "--demuxer-options" => { - next_arg!(args, arg_idx); - if !transcoder.parse_demuxer_options(&args[arg_idx], &full_reg.dmx_reg) { - println!("invalid demuxer option syntax"); - return; - } - }, "--scale-options" => { next_arg!(args, arg_idx); if !transcoder.parse_scale_options(&args[arg_idx]) { @@ -1047,6 +1104,25 @@ fn main() { println!("invalid output stream option syntax"); return; } + } else if args[arg_idx].starts_with("--input-format") { + let id = parse_id!(&args[arg_idx][14..], "input format", transcoder.input_fmt.len()); + next_arg!(args, arg_idx); + transcoder.input_fmt[id] = Some(args[arg_idx].clone()); + } else if args[arg_idx].starts_with("--input") { // should be after --input-format + let id = parse_id!(&args[arg_idx][7..], "input", transcoder.input_name.len()); + next_arg!(args, arg_idx); + transcoder.input_name[id] = Some(args[arg_idx].clone()); + } else if args[arg_idx].starts_with("-i") { + let id = parse_id!(&args[arg_idx][2..], "input", transcoder.input_name.len()); + next_arg!(args, arg_idx); + transcoder.input_name[id] = Some(args[arg_idx].clone()); + } else if args[arg_idx].starts_with("--demuxer-options") { + let id = parse_id!(&args[arg_idx][17..], "input options", transcoder.demux_opts.len()); + next_arg!(args, arg_idx); + if !transcoder.parse_demuxer_options(&args[arg_idx], &full_reg.dmx_reg, id) { + println!("invalid demuxer option syntax"); + return; + } } else if args[arg_idx].starts_with("--") { println!("unknown option"); } else { @@ -1061,8 +1137,8 @@ fn main() { return; } - if transcoder.input_name.is_empty() { - println!("no input name provided"); + if transcoder.input_name.iter().flatten().count() == 0 { + println!("no input name(s) provided"); return; } if transcoder.output_name.is_empty() { @@ -1070,90 +1146,137 @@ fn main() { return; } - if let Some("imgseq") = transcoder.input_fmt.as_deref() { - let mut isdc = ImgSeqDemuxerCreator::new(transcoder.input_name.as_str()); - parse_and_apply_options!(isdc, &transcoder.demux_opts, "input"); - let isd = if let Ok(ctx) = isdc.open() { - ctx - } else { - println!("failed to create image sequence demuxer!"); - return; - }; - let mut dmx = DemuxerObject::create_imgseq(isd); - transcode(transcoder, full_reg, &mut dmx); - return; - } - - let res = File::open(transcoder.input_name.as_str()); - if res.is_err() { - println!("error opening input"); - return; - } - let file = res.unwrap(); - let file = BufReader::new(file); - let mut fr = FileReader::new_read(file); - let mut br = ByteReader::new(&mut fr); - let (is_raw, start, end) = if transcoder.input_fmt.is_none() { - detect_tags(&mut br) - } else { - (false, 0, None) - }; + let mut demuxers = Vec::with_capacity(1); + let mut isn_start = 0; + for (i, (iname, ifmt)) in transcoder.input_name.iter().zip( + transcoder.input_fmt.iter()).enumerate() { + match (iname, ifmt.as_ref().map(|s| s.as_str())) { + (Some(name), Some("imgseq")) => { + println!("trying image sequence {}", name); + let mut isdc = ImgSeqDemuxerCreator::new(name.as_str()); + parse_and_apply_options!(isdc, &transcoder.demux_opts[i], "input"); + let isd = if let Ok(ctx) = isdc.open() { + ctx + } else { + println!("failed to create image sequence demuxer!"); + return; + }; + let dmx = DemuxerObject::create_imgseq(isd); + for i in 0..dmx.get_num_streams() { + let s = dmx.get_stream(i).unwrap(); + let info = s.get_info(); + println!(" stream {}({}) - {} {}", i, i + isn_start, s, info.get_name()); + } + isn_start += dmx.get_num_streams(); + demuxers.push((dmx, false)) + }, + (Some(name), _) => { + let res = File::open(name); + if res.is_err() { + println!("error opening input"); + return; + } + let file = res.unwrap(); + let file = BufReader::new(file); + let mut fr = FileReader::new_read(file); + let mut br = ByteReader::new(&mut fr); + let (is_raw, start, end) = if ifmt.is_none() { + detect_tags(&mut br) + } else { + (false, 0, None) + }; - let mut nfr: Box; - if start != 0 || end.is_some() { - let file = fr.finish(); - nfr = Box::new(BoundedFileReader::new_read(file, start, end).unwrap()); - } else { - nfr = Box::new(fr); - } - let mut br = ByteReader::new(nfr.as_mut()); + let nfr: Box = if start != 0 || end.is_some() { + let file = fr.finish(); + Box::new(BoundedFileReader::new_read(file, start, end).unwrap()) + } else { + Box::new(fr) + }; + let sb = SelfBorrow::new(nfr, |rd| { + unsafe { + ByteReader::new(rd.as_mut().unwrap().as_mut()) + } + }); - let mut dmx = DemuxerObject::create(&mut br, &full_reg, transcoder.input_name.as_str(), &transcoder.input_fmt, is_raw); - if dmx.is_none() { - println!("cannot find demuxer for '{}'", transcoder.input_name.as_str()); - return; + let mut dmx = DemuxerObject::create(sb, &full_reg, name, ifmt, is_raw); + if dmx.is_none() { + println!("cannot find demuxer for '{}'", name); + return; + } + parse_and_apply_options!(dmx, &transcoder.demux_opts[i], "input"); + for i in 0..dmx.get_num_streams() { + let s = dmx.get_stream(i).unwrap(); + let info = s.get_info(); + println!(" stream {}({}) - {} {}", i, i + isn_start, s, info.get_name()); + } + isn_start += dmx.get_num_streams(); + demuxers.push((dmx, false)); + }, + _ => {}, + }; } - parse_and_apply_options!(dmx, &transcoder.demux_opts, "input"); - transcode(transcoder, full_reg, &mut dmx); -} -fn transcode(mut transcoder: Transcoder, full_reg: FullRegister, dmx: &mut DemuxerObject) { - let duration = dmx.get_duration(); + let duration = demuxers.iter().fold(0u64, |mindur, (dmx, _)| { + let dur = dmx.get_duration(); + if dur > 0 { + mindur.min(dur) + } else { + mindur + } + }); let duration_string = if duration != 0 { format_time(duration) } else { String::new() }; - for i in 0..dmx.get_num_streams() { - let s = dmx.get_stream(i).unwrap(); - let info = s.get_info(); - let decfunc = full_reg.dec_reg.find_decoder(info.get_name()); -println!("stream {} - {} {}", i, s, info.get_name()); - let str_id = s.get_num() as u32; - if let Some(create_dec) = decfunc { - let mut dec = (create_dec)(); - let mut dsupp = Box::new(NADecoderSupport::new()); - let ret = dec.init(&mut dsupp, info.clone()); - if ret.is_err() { - println!("Error initialising decoder '{}' for stream {}", info.get_name(), str_id); - return; - } - transcoder.apply_decoder_options(dec.as_mut(), str_id); - let desc = register::get_codec_description(info.get_name()); - let has_b = if let Some(desc) = desc { - desc.has_reorder() - } else { - println!("No codec description found, using B-frame reorderer."); - true - }; - let reord: Box = if has_b { Box::new(IPBReorderer::new()) } else { Box::new(NoReorderer::new()) }; - transcoder.decoders.push(Some((dsupp, dec, reord))); - } else { - println!("No decoder for stream {} ({}) is found", str_id, info.get_name()); - transcoder.decoders.push(None); + let mut ism = StreamManager::new(); + let mut is_offset = Vec::with_capacity(demuxers.len()); + let mut start = 0; + let mut nstreams = 0; + for (dmx, _) in demuxers.iter() { + is_offset.push(nstreams); + let sm = dmx.get_stream_manager(); + let max_id = sm.iter().fold(0u32, |id, strm| id.max(strm.id)); + for stream in sm.iter() { + let mut newstream = (*stream).clone(); + newstream.id += start; + ism.add_stream(newstream); } + start += max_id + 1; + nstreams += sm.get_num_streams(); } - if transcoder.start != NATimePoint::None { - let ret = dmx.seek(transcoder.start); - if ret.is_err() { - println!(" failed to seek to {} error {:?}", transcoder.start, ret.err().unwrap()); + + for (&is_off, (dmx, _)) in is_offset.iter().zip(demuxers.iter_mut()) { + for i in 0..dmx.get_num_streams() { + let s = dmx.get_stream(i).unwrap(); + let info = s.get_info(); + let decfunc = full_reg.dec_reg.find_decoder(info.get_name()); + let str_id = (s.get_num() + is_off) as u32; + if let Some(create_dec) = decfunc { + let mut dec = (create_dec)(); + let mut dsupp = Box::new(NADecoderSupport::new()); + let ret = dec.init(&mut dsupp, info.clone()); + if ret.is_err() { + println!("Error initialising decoder '{}' for stream {}", info.get_name(), str_id); + return; + } + transcoder.apply_decoder_options(dec.as_mut(), str_id); + let desc = register::get_codec_description(info.get_name()); + let has_b = if let Some(desc) = desc { + desc.has_reorder() + } else { + println!("No codec description found, using B-frame reorderer."); + true + }; + let reord: Box = if has_b { Box::new(IPBReorderer::new()) } else { Box::new(NoReorderer::new()) }; + transcoder.decoders.push(Some((dsupp, dec, reord))); + } else { + println!("No decoder for stream {} ({}) is found", str_id, info.get_name()); + transcoder.decoders.push(None); + } + } + if transcoder.start != NATimePoint::None { + let ret = dmx.seek(transcoder.start); + if ret.is_err() { + println!(" failed to seek to {} error {:?}", transcoder.start, ret.err().unwrap()); + } } } @@ -1177,7 +1300,7 @@ println!("stream {} - {} {}", i, s, info.get_name()); let mux_caps = mux_creator.get_capabilities(); let mut out_sm = StreamManager::new(); - if !transcoder.negotiate_stream_map(dmx.get_stream_manager(), mux_caps, &mut out_sm, &full_reg.enc_reg) { + if !transcoder.negotiate_stream_map(&ism, mux_caps, &mut out_sm, &full_reg.enc_reg) { println!("cannot determine stream map"); return; } @@ -1206,8 +1329,29 @@ println!("stream {} - {} {}", i, s, info.get_name()); let show_interval = Duration::from_millis(100); let mut adata_size = 0; let mut vdata_size = 0; + let mut cur_dmx = 0; 'main_loop: loop { - let pktres = dmx.get_frame(); + let mut pktres = Err(DemuxerError::EOF); + let mut src_dmx = 0; + loop { + if !demuxers.iter().any(|(_, eof)| !eof) { + break; + } + let mut got_res = false; + if !demuxers[cur_dmx].1 { + pktres = demuxers[cur_dmx].0.get_frame(); + got_res = true; + src_dmx = cur_dmx; + } + cur_dmx += 1; + if cur_dmx >= demuxers.len() { + cur_dmx = 0; + } + if got_res { + break; + } + } + if let Err(DemuxerError::EOF) = pktres { break; } if pktres.is_err() { println!("demuxing error"); @@ -1215,7 +1359,11 @@ println!("stream {} - {} {}", i, s, info.get_name()); } let mut pkt = pktres.unwrap(); if transcoder.start != NATimePoint::None && pkt.ts.less_than(transcoder.start) { continue; } - let src_id = pkt.get_stream().get_num(); + let src_id = pkt.get_stream().get_num() + is_offset[src_dmx]; + let ts = pkt.ts; + let newstream = ism.get_stream(src_id).unwrap(); + pkt.reassign(newstream, ts); + if transcoder.verbose > 0 && time.elapsed() >= show_interval { if let Some(pts) = pkt.get_pts() { let cur_time = format_time(NATimeInfo::ts_to_time(pts, 1000, pkt.ts.tb_num, pkt.ts.tb_den)); @@ -1298,7 +1446,7 @@ println!("stream {} - {} {}", i, s, info.get_name()); }, }; } - 'reord_flush_loop: for stream in dmx.get_streams() { + 'reord_flush_loop: for stream in ism.iter() { let src_id = stream.get_num(); if let OutputMode::Encode(dst_id, ref mut encoder, ref mut cvt) = transcoder.encoders[src_id] { if let Some((_, _, ref mut reorderer)) = transcoder.decoders[src_id] { -- 2.39.5