add PNM image sequence as possible input source
[nihav-encoder.git] / src / main.rs
CommitLineData
6dc69f51
KS
1extern crate nihav_core;
2extern crate nihav_codec_support;
3extern crate nihav_registry;
4extern crate nihav_allstuff;
5
6use std::fs::File;
5ec8115f 7use std::io::{BufReader, Write};
6dc69f51
KS
8use nihav_core::io::byteio::{FileReader, ByteReader};
9use nihav_core::frame::*;
10use nihav_core::options::*;
11use nihav_core::codecs::*;
12use nihav_core::demuxers::*;
13use nihav_core::muxers::*;
d9fe2b71 14use nihav_core::reorder::*;
6dc69f51 15use nihav_core::scale::*;
6dc69f51 16use nihav_registry::detect;
e6cb09af 17use nihav_registry::register;
6dc69f51 18use std::env;
5ec8115f 19use std::time::{Duration, Instant};
6dc69f51 20
91a15e39
KS
21mod demux;
22use crate::demux::*;
93521506 23mod null;
b0481c9e
KS
24mod acvt;
25use crate::acvt::*;
90683bc3
KS
26mod imgseq;
27use crate::imgseq::*;
93521506 28
6f6ba7bf
KS
29const SND_NO_FORMAT: NASoniton = NASoniton { bits: 0, be: false, packed: false, planar: false, float: false, signed: false };
30
5ec8115f
KS
31fn format_time(ms: u64) -> String {
32 let s = ms / 1000;
33 let ds = (ms % 1000) / 100;
34 let (min, s) = (s / 60, s % 60);
35 let (h, min) = (min / 60, min % 60);
36 if h == 0 {
37 if min == 0 {
38 format!("{}.{}", s, ds)
39 } else {
40 format!("{}:{:02}.{}", min, s, ds)
41 }
42 } else {
43 format!("{}:{:02}:{:02}.{}", h, min, s, ds)
44 }
45}
46
6dc69f51
KS
47fn print_options(name: &str, options: &[NAOptionDefinition]) {
48 if options.is_empty() {
49 println!("No custom options.");
50 } else {
51 println!("Options for '{}'", name);
52 for opt in options.iter() {
53 println!(" {}", opt);
54 }
55 }
56}
57
30611a63
KS
58fn parse_bitrate(strval: &str) -> Result<u32, ()> {
59 let mut val = 0;
60 let mut has_suffix = false;
61 for ch in strval.chars() {
62 match ch {
63 _ if has_suffix => return Err(()),
64 '0'..='9' => {
65 if val >= std::u32::MAX / 100 {
66 return Err(());
67 }
68 val = val * 10 + ch.to_digit(10).unwrap_or(0);
69 },
70 'k' | 'K' => {
71 if val >= std::u32::MAX / 1000 {
72 return Err(());
73 }
74 val *= 1000;
75 has_suffix = true;
76 },
77 'm' | 'M' => {
78 if val >= std::u32::MAX / 1000000 {
79 return Err(());
80 }
81 val *= 1000000;
82 has_suffix = true;
83 },
84 _ => return Err(()),
85 };
86 }
87 Ok(val)
88}
89
6dc69f51
KS
90struct OptionArgs {
91 name: String,
92 value: Option<String>,
93}
94
95struct InputStreamOptions {
96 id: u32,
97 drop: bool,
98 dec_opts: Vec<OptionArgs>,
99}
100
101struct OutputStreamOptions {
102 id: u32,
103 enc_params: EncodeParameters,
104 enc_name: String,
105 enc_opts: Vec<OptionArgs>,
106}
107
108enum OutputConvert {
109 Video(NAScale, NABufferType),
b0481c9e 110 Audio(AudioConverter),
6dc69f51
KS
111 None,
112}
113
86c54d88 114#[allow(clippy::large_enum_variant)]
6dc69f51
KS
115enum OutputMode {
116 Drop,
117 Copy(u32),
118 Encode(u32, Box<dyn NAEncoder>, OutputConvert),
119}
120
121#[derive(Default)]
86c54d88 122#[allow(clippy::type_complexity)]
6dc69f51
KS
123struct Transcoder {
124 input_name: String,
125 input_fmt: Option<String>,
126 output_name: String,
127 output_fmt: Option<String>,
128 demux_opts: Vec<OptionArgs>,
129 mux_opts: Vec<OptionArgs>,
130 istr_opts: Vec<InputStreamOptions>,
131 ostr_opts: Vec<OutputStreamOptions>,
df37d3b1 132 scale_opts: Vec<(String, String)>,
d9fe2b71 133 decoders: Vec<Option<(Box<NADecoderSupport>, Box<dyn NADecoder>, Box<dyn FrameReorderer>)>>,
6dc69f51
KS
134 encoders: Vec<OutputMode>,
135 no_video: bool,
136 no_audio: bool,
951916e8
KS
137 start: NATimePoint,
138 end: NATimePoint,
908ba48c 139 verbose: u8,
6dc69f51
KS
140}
141
142macro_rules! parse_and_apply_options {
143 ($obj: expr, $in_opts: expr, $name: expr) => {
144 let mut opts = Vec::with_capacity($in_opts.len());
145 let opt_def = $obj.get_supported_options();
146 for opt in $in_opts.iter() {
147 let mut found = false;
148 for opt_def in opt_def.iter() {
3e2a4e88
KS
149 let mut matches = opt.name == opt_def.name;
150 if !matches && opt.name.starts_with("no") {
151 let (_, name) = opt.name.split_at(2);
152 matches = name == opt_def.name;
153 }
154 if matches {
fd03a232 155 let arg = if let Some(ref strval) = opt.value { Some(strval) } else { None };
6dc69f51 156 let ret = opt_def.parse(&opt.name, arg);
86c54d88 157 if let Ok((val, _)) = ret {
6dc69f51 158 opts.push(val);
86c54d88
KS
159 } else {
160 println!("invalid option {} for {}", opt.name, $name);
6dc69f51
KS
161 }
162 found = true;
163 }
164 }
165 if !found {
166 println!(" ignoring option '{}' for {}", opt.name, $name);
167 }
168 }
169 $obj.set_options(opts.as_slice());
170 }
171}
172
173impl Transcoder {
174 fn new() -> Self { Self::default() }
175 fn parse_istream_options(&mut self, opt0: &str, opt1: &str) -> bool {
176 let (_, strno) = opt0.split_at(9);
177 let ret = strno.parse::<u32>();
178 if ret.is_err() { return false; }
179 let streamno = ret.unwrap();
180
fd03a232 181 let sidx = if let Some(idx) = self.istr_opts.iter().position(|el| el.id == streamno) {
6dc69f51
KS
182 idx
183 } else {
184 self.istr_opts.push(InputStreamOptions {id: streamno, drop: false, dec_opts: Vec::new() });
185 self.istr_opts.len() - 1
186 };
187 let istr = &mut self.istr_opts[sidx];
830c03a1 188
6dc69f51
KS
189 for opt in opt1.split(',') {
190 let oval: Vec<_> = opt.split('=').collect();
191 if oval.len() == 1 {
192 match oval[0] {
193 "drop" => { istr.drop = true; },
194 _ => {
195 istr.dec_opts.push(OptionArgs{ name: oval[0].to_string(), value: None });
196 },
197 };
198 } else if oval.len() == 2 {
199 istr.dec_opts.push(OptionArgs{ name: oval[0].to_string(), value: Some(oval[1].to_string()) });
200 } else {
201 println!("unrecognized option '{}'", opt);
202 }
203 }
204 true
205 }
206 fn parse_ostream_options(&mut self, opt0: &str, opt1: &str, enc_reg: &RegisteredEncoders) -> bool {
207 let (_, strno) = opt0.split_at(9);
208 let ret = strno.parse::<u32>();
209 if ret.is_err() { return false; }
210 let streamno = ret.unwrap();
211
fd03a232 212 let sidx = if let Some(idx) = self.ostr_opts.iter().position(|el| el.id == streamno) {
6dc69f51
KS
213 idx
214 } else {
215 self.ostr_opts.push(OutputStreamOptions {id: streamno, enc_name: String::new(), enc_params: EncodeParameters::default(), enc_opts: Vec::new() });
216 self.ostr_opts.len() - 1
217 };
218 let ostr = &mut self.ostr_opts[sidx];
830c03a1 219
6dc69f51
KS
220 for opt in opt1.split(',') {
221 let oval: Vec<_> = opt.split('=').collect();
222 if oval.len() == 1 {
223 match oval[0] {
224 "flip" => {
225 if ostr.enc_params.format == NACodecTypeInfo::None {
226 ostr.enc_params.format = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, YUV420_FORMAT));
227 }
228 if let NACodecTypeInfo::Video(ref mut vinfo) = ostr.enc_params.format {
229 vinfo.flipped = true;
230 } else {
231 println!("video option for audio stream");
232 }
233 },
234 "noflip" => {
235 if ostr.enc_params.format == NACodecTypeInfo::None {
236 ostr.enc_params.format = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, YUV420_FORMAT));
237 }
238 if let NACodecTypeInfo::Video(ref mut vinfo) = ostr.enc_params.format {
239 vinfo.flipped = false;
240 } else {
241 println!("video option for audio stream");
242 }
243 },
244 _ => {
245 ostr.enc_opts.push(OptionArgs{ name: oval[0].to_string(), value: None });
246 },
247 };
248 } else if oval.len() == 2 {
249//todo parse encoder options, store, init later
250 match oval[0] {
ca3b31d7
KS
251 "timebase" => {
252 let mut parts = oval[1].split('/');
253 let num = parts.next().unwrap();
254 let den = parts.next();
255 if let Some(den) = den {
256 let rnum = num.parse::<u32>();
257 let rden = den.parse::<u32>();
258 if let (Ok(num), Ok(den)) = (rnum, rden) {
259 ostr.enc_params.tb_num = num;
260 ostr.enc_params.tb_den = den;
261 } else {
262 println!("invalid timebase value");
263 }
264 } else {
265 println!("invalid timebase format (should be num/den)");
266 }
267 },
6dc69f51
KS
268 "encoder" => {
269 if enc_reg.find_encoder(oval[1]).is_some() {
270 ostr.enc_name = oval[1].to_string();
271 } else {
272 println!("unknown encoder '{}'", oval[1]);
c0052668 273 ostr.enc_name = oval[1].to_string();
6dc69f51
KS
274 }
275 },
276 "width" => {
277 if ostr.enc_params.format == NACodecTypeInfo::None {
278 ostr.enc_params.format = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, YUV420_FORMAT));
279 }
280 if let NACodecTypeInfo::Video(ref mut vinfo) = ostr.enc_params.format {
281 let ret = oval[1].parse::<usize>();
282 if let Ok(val) = ret {
283 vinfo.width = val;
284 } else {
285 println!("invalid width");
286 }
287 } else {
288 println!("video option for audio stream");
289 }
290 },
291 "height" => {
292 if ostr.enc_params.format == NACodecTypeInfo::None {
293 ostr.enc_params.format = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, YUV420_FORMAT));
294 }
295 if let NACodecTypeInfo::Video(ref mut vinfo) = ostr.enc_params.format {
296 let ret = oval[1].parse::<usize>();
297 if let Ok(val) = ret {
298 vinfo.height = val;
299 } else {
300 println!("invalid height");
301 }
302 } else {
303 println!("video option for audio stream");
304 }
305 },
e176bfee
KS
306 "pixfmt" => {
307 if ostr.enc_params.format == NACodecTypeInfo::None {
308 ostr.enc_params.format = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, YUV420_FORMAT));
309 }
310 if let NACodecTypeInfo::Video(ref mut vinfo) = ostr.enc_params.format {
311 let ret = oval[1].parse::<NAPixelFormaton>();
312 if let Ok(val) = ret {
313 vinfo.format = val;
314 } else {
315 println!("invalid pixel format");
316 }
317 } else {
318 println!("video option for audio stream");
319 }
320 },
6dc69f51
KS
321 "srate" => {
322 if ostr.enc_params.format == NACodecTypeInfo::None {
6f6ba7bf 323 ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0));
6dc69f51
KS
324 }
325 if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format {
326 let ret = oval[1].parse::<u32>();
327 if let Ok(val) = ret {
328 ainfo.sample_rate = val;
329 } else {
330 println!("invalid sampling rate");
331 }
332 } else {
333 println!("audio option for video stream");
334 }
335 },
336 "channels" => {
337 if ostr.enc_params.format == NACodecTypeInfo::None {
6f6ba7bf 338 ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0));
6dc69f51
KS
339 }
340 if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format {
341 let ret = oval[1].parse::<u8>();
342 if let Ok(val) = ret {
343 ainfo.channels = val;
344 } else {
345 println!("invalid number of channels");
346 }
347 } else {
348 println!("audio option for video stream");
349 }
350 },
351 "block_len" => {
352 if ostr.enc_params.format == NACodecTypeInfo::None {
6f6ba7bf 353 ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0));
6dc69f51
KS
354 }
355 if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format {
356 let ret = oval[1].parse::<usize>();
357 if let Ok(val) = ret {
358 ainfo.block_len = val;
359 } else {
360 println!("invalid block_length");
361 }
362 } else {
363 println!("audio option for video stream");
364 }
365 },
e176bfee
KS
366 "sfmt" => {
367 if ostr.enc_params.format == NACodecTypeInfo::None {
6f6ba7bf 368 ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0));
e176bfee
KS
369 }
370 if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format {
371 let ret = oval[1].parse::<NASoniton>();
372 if let Ok(val) = ret {
373 ainfo.format = val;
374 } else {
375 println!("invalid audio format");
376 }
377 } else {
378 println!("audio option for video stream");
379 }
380 },
381// todo channel map negotiation
382 /*"chmap" => {
383 if ostr.enc_params.format == NACodecTypeInfo::None {
6f6ba7bf 384 ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0));
e176bfee
KS
385 }
386 if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format {
387 let ret = oval[1].parse::<NAChannelMap>();
388 if let Ok(val) = ret {
389 ainfo.chmap = val;
390 } else {
391 println!("invalid channel map");
392 }
393 } else {
394 println!("audio option for video stream");
395 }
396 },*/
6dc69f51 397 "bitrate" => {
30611a63 398 let ret = parse_bitrate(oval[1]);
6dc69f51
KS
399 if let Ok(val) = ret {
400 ostr.enc_params.bitrate = val;
401 } else {
402 println!("invalid bitrate value");
403 }
404 },
405 "quality" => {
406 let ret = oval[1].parse::<u8>();
407 if let Ok(val) = ret {
408 ostr.enc_params.quality = val;
409 } else {
410 println!("invalid quality value");
411 }
412 },
413 _ => {
414 ostr.enc_opts.push(OptionArgs{ name: oval[0].to_string(), value: Some(oval[1].to_string()) });
415 },
416 }
417 } else {
418 println!("unrecognized option '{}'", opt);
419 }
420 }
421 true
422 }
423 fn parse_demuxer_options(&mut self, opts: &str, dmx_reg: &RegisteredDemuxers) -> bool {
424 for opt in opts.split(',') {
425 let oval: Vec<_> = opt.split('=').collect();
426 if oval.len() == 1 {
427 self.demux_opts.push(OptionArgs{ name: oval[0].to_string(), value: None });
428 } else if oval.len() == 2 {
429 if oval[0] == "format" {
430 if dmx_reg.find_demuxer(oval[1]).is_some() {
431 self.input_fmt = Some(oval[1].to_string());
432 } else {
433 println!("unknown demuxer format '{}'", oval[1]);
434 }
435 } else {
436 self.demux_opts.push(OptionArgs{ name: oval[0].to_string(), value: Some(oval[1].to_string()) });
437 }
438 } else {
439 println!("unrecognized option '{}'", opt);
440 }
441 }
442 true
443 }
444 fn parse_muxer_options(&mut self, opts: &str, mux_reg: &RegisteredMuxers) -> bool {
445 for opt in opts.split(',') {
446 let oval: Vec<_> = opt.split('=').collect();
447 if oval.len() == 1 {
448 self.mux_opts.push(OptionArgs{ name: oval[0].to_string(), value: None });
449 } else if oval.len() == 2 {
450 if oval[0] == "format" {
451 if mux_reg.find_muxer(oval[1]).is_some() {
452 self.output_fmt = Some(oval[1].to_string());
453 } else {
454 println!("unknown muxer format '{}'", oval[1]);
455 }
456 } else {
457 self.mux_opts.push(OptionArgs{ name: oval[0].to_string(), value: Some(oval[1].to_string()) });
458 }
459 } else {
460 println!("unrecognized option '{}'", opt);
461 }
462 }
463 true
464 }
df37d3b1
KS
465 fn parse_scale_options(&mut self, opts: &str) -> bool {
466 for opt in opts.split(',') {
467 let oval: Vec<_> = opt.split('=').collect();
468 if oval.len() == 1 {
469 self.scale_opts.push((oval[0].to_string(), "".to_string()));
470 } else if oval.len() == 2 {
471 self.scale_opts.push((oval[0].to_string(), oval[1].to_string()));
472 } else {
473 println!("unrecognized option '{}'", opt);
474 return false;
475 }
476 }
477 true
478 }
73f889bf 479 fn apply_decoder_options(&self, dec: &mut dyn NADecoder, str_id: u32) {
fd03a232 480 if let Some(str_idx) = self.istr_opts.iter().position(|el| el.id == str_id) {
6dc69f51
KS
481 let dec_opts = dec.get_supported_options();
482 if dec_opts.is_empty() { return; }
483 let name = format!("input stream {}", str_id);
484 parse_and_apply_options!(dec, &self.istr_opts[str_idx].dec_opts, name);
485 }
486 }
487 fn register_output_stream(&mut self, cname: &str, istr: NAStreamRef, out_sm: &mut StreamManager, enc_reg: &RegisteredEncoders) -> bool {
488 let out_id = out_sm.get_num_streams() as u32;
fd03a232 489 if let Some(str_idx) = self.istr_opts.iter().position(|el| el.id == (istr.get_num() as u32)) {
6dc69f51
KS
490 if self.istr_opts[str_idx].drop {
491 self.encoders.push(OutputMode::Drop);
492 return true;
493 }
494 }
495
fd03a232 496 if let Some(str_idx) = self.ostr_opts.iter().position(|el| el.id == out_id) {
6dc69f51 497 let oopts = &mut self.ostr_opts[str_idx];
a7b5f008 498 if oopts.enc_name.as_str() == "copy" && (cname == "any" || istr.get_info().get_name() == cname) {
86c54d88 499 out_sm.add_stream_ref(istr);
6dc69f51
KS
500 self.encoders.push(OutputMode::Copy(out_id));
501 } else if cname == "any" || oopts.enc_name.as_str() == cname {
502 let enc_create = enc_reg.find_encoder(oopts.enc_name.as_str());
503 if enc_create.is_none() {
504 println!("encoder '{}' not found", oopts.enc_name.as_str());
505 return false;
506 }
507 let mut encoder = (enc_create.unwrap())();
eb563e3d 508 let forced_out = oopts.enc_params.format != NACodecTypeInfo::None;
6f6ba7bf 509 let iformat = istr.get_info().get_properties();
6dc69f51
KS
510 if oopts.enc_params.format == NACodecTypeInfo::None {
511 oopts.enc_params.format = istr.get_info().get_properties();
6f6ba7bf
KS
512 } else {
513 match (&iformat, &mut oopts.enc_params.format) {
514 (NACodecTypeInfo::Video(svinfo), NACodecTypeInfo::Video(ref mut dvinfo)) => {
515 if dvinfo.width == 0 {
516 dvinfo.width = svinfo.width;
517 }
518 if dvinfo.height == 0 {
519 dvinfo.height = svinfo.height;
520 }
521 },
522 (NACodecTypeInfo::Audio(sainfo), NACodecTypeInfo::Audio(ref mut dainfo)) => {
523 if dainfo.sample_rate == 0 {
524 dainfo.sample_rate = sainfo.sample_rate;
525 }
526 if dainfo.format == SND_NO_FORMAT {
527 dainfo.format = sainfo.format;
528 }
529 if dainfo.channels == 0 {
530 dainfo.channels = sainfo.channels;
531 }
532 if dainfo.block_len == 0 {
533 dainfo.block_len = sainfo.block_len;
534 }
535 },
536 _ => {},
537 };
6dc69f51
KS
538 }
539 if oopts.enc_params.tb_num == 0 {
540 oopts.enc_params.tb_num = istr.tb_num;
541 oopts.enc_params.tb_den = istr.tb_den;
542 }
543 let ret_eparams = encoder.negotiate_format(&oopts.enc_params);
544 if ret_eparams.is_err() {
545 println!("cannot negotiate encoding parameters");
546 return false;
547 }
548 let ret_eparams = ret_eparams.unwrap();
549
550//todo check for params mismatch
6f6ba7bf 551 let cvt = match (&iformat, &ret_eparams.format) {
6dc69f51 552 (NACodecTypeInfo::Video(svinfo), NACodecTypeInfo::Video(dvinfo)) => {
eb563e3d 553 if svinfo == dvinfo && !forced_out {
6dc69f51
KS
554 OutputConvert::None
555 } else {
556 let ofmt = ScaleInfo { fmt: dvinfo.format, width: dvinfo.width, height: dvinfo.height };
df37d3b1 557 let ret = NAScale::new_with_options(ofmt, ofmt, &self.scale_opts);
6dc69f51
KS
558 if ret.is_err() {
559 println!("cannot create scaler");
560 return false;
561 }
562 let scaler = ret.unwrap();
563 let ret = alloc_video_buffer(*dvinfo, 4);
564 if ret.is_err() {
565 println!("cannot create scaler buffer");
566 return false;
567 }
568 let cvt_buf = ret.unwrap();
569 OutputConvert::Video(scaler, cvt_buf)
570 }
571 },
572 (NACodecTypeInfo::Audio(sainfo), NACodecTypeInfo::Audio(dainfo)) => {
573 if sainfo == dainfo {
574 OutputConvert::None
575 } else {
576 let dchmap = match dainfo.channels {
577 1 => NAChannelMap::from_ms_mapping(0x4),
578 2 => NAChannelMap::from_ms_mapping(0x3),
579 _ => {
580println!("can't generate default channel map for {} channels", dainfo.channels);
581 return false;
582 },
583 };
b0481c9e 584 let acvt = AudioConverter::new(sainfo, dainfo, dchmap);
6dc69f51 585//todo channelmap
b0481c9e 586 OutputConvert::Audio(acvt)
6dc69f51
KS
587 }
588 },
589 _ => OutputConvert::None,
590 };
591 let ret = encoder.init(out_id, ret_eparams);
592 if ret.is_err() {
593 println!("error initialising encoder");
594 return false;
595 }
596 out_sm.add_stream_ref(ret.unwrap());
597
598 let name = format!("output stream {}", out_id);
599 parse_and_apply_options!(encoder, &oopts.enc_opts, name);
600
601 self.encoders.push(OutputMode::Encode(out_id, encoder, cvt));
602 } else {
603println!("encoder {} is not supported by output (expected {})", istr.id, istr.get_info().get_name());
604 return false;
605 }
86c54d88
KS
606 } else if cname == "any" || istr.get_info().get_name() == cname {
607 out_sm.add_stream_ref(istr);
608 self.encoders.push(OutputMode::Copy(out_id));
6dc69f51 609 } else {
00b4c46f
KS
610 let mut oopts = OutputStreamOptions {id: out_id, enc_name: cname.to_owned(), enc_params: EncodeParameters::default(), enc_opts: Vec::new() };
611
612 let enc_create = enc_reg.find_encoder(cname);
613 if enc_create.is_none() {
614 println!("encoder '{}' not found", oopts.enc_name.as_str());
615 return false;
616 }
617 let mut encoder = (enc_create.unwrap())();
618 oopts.enc_params.format = istr.get_info().get_properties();
619 oopts.enc_params.tb_num = istr.tb_num;
620 oopts.enc_params.tb_den = istr.tb_den;
621 let ret_eparams = encoder.negotiate_format(&oopts.enc_params);
622 if ret_eparams.is_err() {
623 println!("cannot negotiate encoding parameters");
624 return false;
625 }
626 let ret_eparams = ret_eparams.unwrap();
627
628//todo check for params mismatch
629 let cvt = match (&oopts.enc_params.format, &ret_eparams.format) {
630 (NACodecTypeInfo::Video(svinfo), NACodecTypeInfo::Video(dvinfo)) => {
631 if svinfo == dvinfo {
632 OutputConvert::None
633 } else {
634 let ofmt = ScaleInfo { fmt: dvinfo.format, width: dvinfo.width, height: dvinfo.height };
635 let ret = NAScale::new_with_options(ofmt, ofmt, &self.scale_opts);
636 if ret.is_err() {
637 println!("cannot create scaler");
638 return false;
639 }
640 let scaler = ret.unwrap();
641 let ret = alloc_video_buffer(*dvinfo, 4);
642 if ret.is_err() {
643 println!("cannot create scaler buffer");
644 return false;
645 }
646 let cvt_buf = ret.unwrap();
647 OutputConvert::Video(scaler, cvt_buf)
648 }
649 },
650 (NACodecTypeInfo::Audio(sainfo), NACodecTypeInfo::Audio(dainfo)) => {
651 if sainfo == dainfo {
652 OutputConvert::None
653 } else {
654 let dchmap = match dainfo.channels {
655 1 => NAChannelMap::from_ms_mapping(0x4),
656 2 => NAChannelMap::from_ms_mapping(0x3),
657 _ => {
658println!("can't generate default channel map for {} channels", dainfo.channels);
659 return false;
660 },
661 };
662//todo channelmap
b0481c9e
KS
663 let acvt = AudioConverter::new(sainfo, dainfo, dchmap);
664 OutputConvert::Audio(acvt)
00b4c46f
KS
665 }
666 },
667 _ => OutputConvert::None,
668 };
669 let ret = encoder.init(out_id, ret_eparams);
670 if ret.is_err() {
671 println!("error initialising encoder");
672 return false;
673 }
674 out_sm.add_stream_ref(ret.unwrap());
675 self.encoders.push(OutputMode::Encode(out_id, encoder, cvt));
676 self.ostr_opts.push(oopts);
6dc69f51
KS
677 }
678 true
679 }
680 fn map_single(&mut self, cname: &str, ctype: StreamType, src_sm: &StreamManager, out_sm: &mut StreamManager, enc_reg: &RegisteredEncoders) -> bool {
681 let mut found_stream = false;
682 for istr in src_sm.iter() {
683 if istr.get_media_type() != ctype || found_stream {
684 self.encoders.push(OutputMode::Drop);
685 } else {
686 if !self.register_output_stream(cname, istr, out_sm, enc_reg) {
687 return false;
688 }
689 found_stream = true;
690 }
691 }
692 found_stream
693 }
694 fn negotiate_stream_map(&mut self, src_sm: &StreamManager, mux_caps: MuxerCapabilities, out_sm: &mut StreamManager, enc_reg: &RegisteredEncoders) -> bool {
695 match mux_caps {
696 MuxerCapabilities::SingleVideo(cname) => {
697 if self.no_video { return false; }
698 self.map_single(cname, StreamType::Video, src_sm, out_sm, enc_reg)
699 },
700 MuxerCapabilities::SingleAudio(cname) => {
701 if self.no_audio { return false; }
702 self.map_single(cname, StreamType::Audio, src_sm, out_sm, enc_reg)
703 },
704 MuxerCapabilities::SingleVideoAndAudio(vname, aname) => {
705 let mut found_vid = false;
706 let mut found_aud = false;
707 for istr in src_sm.iter() {
708 if istr.get_media_type() == StreamType::Video && !found_vid && !self.no_video {
709 if !self.register_output_stream(vname, istr, out_sm, enc_reg) {
710 return false;
711 }
712 found_vid = true;
713 } else if istr.get_media_type() == StreamType::Audio && !found_aud && !self.no_audio {
714 if !self.register_output_stream(aname, istr, out_sm, enc_reg) {
715 return false;
716 }
717 found_aud = true;
718 } else {
719 self.encoders.push(OutputMode::Drop);
720 }
721 }
722 found_vid | found_aud
723 },
724 MuxerCapabilities::OnlyVideo => {
725 if self.no_video { return false; }
726
727 let mut found_vid = false;
728 for istr in src_sm.iter() {
729 if istr.get_media_type() == StreamType::Video && !found_vid {
730 if !self.register_output_stream("any", istr, out_sm, enc_reg) {
731 return false;
732 }
733 found_vid = true;
734 } else {
735 self.encoders.push(OutputMode::Drop);
736 }
737 }
738 found_vid
739 },
740 MuxerCapabilities::OnlyAudio => {
741 if self.no_audio { return false; }
742
743 let mut found_aud = false;
744 for istr in src_sm.iter() {
745 if istr.get_media_type() == StreamType::Audio && !found_aud {
746 if !self.register_output_stream("any", istr, out_sm, enc_reg) {
747 return false;
748 }
749 found_aud = true;
750 } else {
751 self.encoders.push(OutputMode::Drop);
752 }
753 }
754 found_aud
755 },
756 MuxerCapabilities::Universal => {
757 for istr in src_sm.iter() {
758 if (istr.get_media_type() == StreamType::Video && self.no_video) ||
759 (istr.get_media_type() == StreamType::Audio && self.no_audio) {
760 self.encoders.push(OutputMode::Drop);
761 continue;
762 }
763 if !self.register_output_stream("any", istr, out_sm, enc_reg) {
764 return false;
765 }
766 }
767 true
768 },
769 }
770 }
771}
772
df37d3b1 773fn encode_frame(dst_id: u32, encoder: &mut Box<dyn NAEncoder>, cvt: &mut OutputConvert, frm: NAFrameRef, scale_opts: &[(String, String)]) -> bool {
d9fe2b71 774 let buf = frm.get_buffer();
637e4d45 775 let cbuf = if let NABufferType::None = buf {
343a59ec 776 if (encoder.get_capabilities() & ENC_CAPS_SKIPFRAME) == 0 {
b76448d9
KS
777 match cvt {
778 OutputConvert::Video(_, ref mut dbuf) => dbuf.clone(),
779 _ => {
780 println!("encoder does not support skip frames, skipping");
781 return true;
782 },
783 }
784 } else {
785 buf
343a59ec 786 }
637e4d45
KS
787 } else {
788 match cvt {
d9fe2b71
KS
789 OutputConvert::None => buf,
790 OutputConvert::Video(ref mut scaler, ref mut dbuf) => {
791 let cur_ifmt = get_scale_fmt_from_pic(&buf);
792 let last_ifmt = scaler.get_in_fmt();
793 if cur_ifmt != last_ifmt {
794 let ofmt = scaler.get_out_fmt();
df37d3b1 795 let ret = NAScale::new_with_options(cur_ifmt, ofmt, scale_opts);
d9fe2b71
KS
796 if ret.is_err() {
797 println!("error re-initialising scaler for {} -> {}", cur_ifmt, ofmt);
798 return false;
799 }
800 *scaler = ret.unwrap();
801 }
802 let ret = scaler.convert(&buf, dbuf);
803 if ret.is_err() {
804 println!("error converting frame for encoding");
805 return false;
806 }
807 dbuf.clone()
808 },
b0481c9e
KS
809 OutputConvert::Audio(ref mut acvt) => {
810 if !acvt.queue_frame(buf, frm.get_time_information()) {
d9fe2b71
KS
811 println!("error converting audio for stream {}", dst_id);
812 return false;
813 }
b0481c9e 814 return true;
d9fe2b71 815 },
637e4d45
KS
816 }
817 };
d9fe2b71
KS
818 let cfrm = NAFrame::new(frm.get_time_information(), frm.frame_type, frm.key, frm.get_info(), cbuf);
819 encoder.encode(&cfrm).unwrap();
820 true
821}
822
6dc69f51
KS
823macro_rules! next_arg {
824 ($args: expr, $arg_idx: expr) => {
825 if $arg_idx + 1 >= $args.len() {
826 println!("codec name is required");
827 }
828 $arg_idx += 1;
829 }
830}
831
86c54d88 832#[allow(clippy::single_match)]
6dc69f51
KS
833fn main() {
834 let args: Vec<_> = env::args().collect();
835
836 if args.len() == 1 {
071d353e
KS
837 println!("usage: nihav-encoder [options] --input inputfile --output outputfile");
838 println!(" use nihav-encoder --help to list all available options");
839 return;
840 }
841 if args.len() == 2 && (args[1] == "--help" || args[1] == "-h") {
842 println!("usage: nihav-encoder [options] --input inputfile --output outputfile");
843 println!(" query options:");
844 println!(" --list-{{decoders,encoders,demuxers,muxers}} - lists all available decoders/encoders/demuxers/muxers");
845 println!(" --query-{{decoder,encoder,demuxer,muxer}}-options name - lists all options recognized by that decoder/encoder/demuxer/muxer");
846 println!(" processing options:");
3e82df4a 847 println!(" --verbose - show time for the currently processed input");
071d353e
KS
848 println!(" --input inputfile - set input file");
849 println!(" --input-format fmt - force input format");
850 println!(" --demuxer-options options - set input demuxer options");
df37d3b1 851 println!(" --scale-options options - set scaler options");
071d353e
KS
852 println!(" --output outputfile - set output file");
853 println!(" --output-format fmt - force output format");
854 println!(" --muxer-options options - set output muxer options");
855 println!(" --no-audio - do not decode audio streams");
856 println!(" --no-video - do not decode video streams");
857 println!(" --start starttime - start decoding from given position");
858 println!(" --end endtime - end decoding at given position");
859 println!(" --istreamX options - set options for input stream X");
860 println!(" --ostreamX options - set options for output stream X");
861 println!();
862 println!(" (de)muxer and stream options are passed as comma-separated list e.g. --ostream0 width=320,height=240,flip");
6dc69f51
KS
863 return;
864 }
865
91a15e39 866 let full_reg = FullRegister::new();
6dc69f51
KS
867
868 let mut transcoder = Transcoder::new();
869
870 let mut arg_idx = 1;
5a8a7cdb 871 let mut printed_info = false;
6dc69f51
KS
872 while arg_idx < args.len() {
873 match args[arg_idx].as_str() {
e6cb09af 874 "--list-decoders" => {
91a15e39 875 if full_reg.dec_reg.iter().len() > 0 {
e6cb09af 876 println!("Registered decoders:");
91a15e39 877 for dec in full_reg.dec_reg.iter() {
e6cb09af
KS
878 let cdesc = register::get_codec_description(dec.name);
879 let full_name = if let Some(cd) = cdesc { cd.get_full_name() } else { "???" };
880 println!(" {} ({})", dec.name, full_name);
881 }
882 } else {
883 println!("No registered decoders.");
884 }
5a8a7cdb 885 printed_info = true;
e6cb09af
KS
886 },
887 "--list-encoders" => {
91a15e39 888 if full_reg.enc_reg.iter().len() > 0 {
e6cb09af 889 println!("Registered encoders:");
91a15e39 890 for enc in full_reg.enc_reg.iter() {
e6cb09af
KS
891 let cdesc = register::get_codec_description(enc.name);
892 let full_name = if let Some(cd) = cdesc { cd.get_full_name() } else { "???" };
893 println!(" {} ({})", enc.name, full_name);
894 }
895 } else {
896 println!("No registered encoders.");
897 }
5a8a7cdb 898 printed_info = true;
e6cb09af
KS
899 },
900 "--list-demuxers" => {
901 print!("Registered demuxers:");
91a15e39 902 for dmx in full_reg.dmx_reg.iter() {
e6cb09af
KS
903 print!(" {}", dmx.get_name());
904 }
905 println!();
5a8a7cdb 906 printed_info = true;
e6cb09af
KS
907 },
908 "--list-muxers" => {
909 print!("Registered muxers:");
91a15e39 910 for mux in full_reg.mux_reg.iter() {
e6cb09af
KS
911 print!(" {}", mux.get_name());
912 }
913 println!();
5a8a7cdb 914 printed_info = true;
e6cb09af 915 },
6dc69f51
KS
916 "--query-decoder-options" => {
917 next_arg!(args, arg_idx);
918 let cname = args[arg_idx].as_str();
91a15e39 919 if let Some(decfunc) = full_reg.dec_reg.find_decoder(cname) {
6dc69f51
KS
920 let dec = (decfunc)();
921 let opts = dec.get_supported_options();
922 print_options(cname, opts);
923 } else {
924 println!("codec {} is not found", cname);
925 }
5a8a7cdb 926 printed_info = true;
6dc69f51
KS
927 },
928 "--query-demuxer-options" => {
929 next_arg!(args, arg_idx);
930 let dname = args[arg_idx].as_str();
931 let mut mr = MemoryReader::new_read(&[]);
932 let mut br = ByteReader::new(&mut mr);
91a15e39 933 if let Some(dmx_creator) = full_reg.dmx_reg.find_demuxer(dname) {
6dc69f51
KS
934 let dmx = dmx_creator.new_demuxer(&mut br);
935 let opts = dmx.get_supported_options();
936 print_options(dname, opts);
937 } else {
938 println!("demuxer {} is not found", dname);
939 }
5a8a7cdb 940 printed_info = true;
6dc69f51
KS
941 },
942 "--query-encoder-options" => {
943 next_arg!(args, arg_idx);
944 let cname = args[arg_idx].as_str();
91a15e39 945 if let Some(encfunc) = full_reg.enc_reg.find_encoder(cname) {
6dc69f51
KS
946 let enc = (encfunc)();
947 let opts = enc.get_supported_options();
948 print_options(cname, opts);
949 } else {
950 println!("codec {} is not found", cname);
951 }
5a8a7cdb 952 printed_info = true;
6dc69f51
KS
953 },
954 "--query-muxer-options" => {
955 next_arg!(args, arg_idx);
956 let name = args[arg_idx].as_str();
957 let mut data = [];
958 let mut mw = MemoryWriter::new_write(&mut data);
959 let mut bw = ByteWriter::new(&mut mw);
91a15e39 960 if let Some(mux_creator) = full_reg.mux_reg.find_muxer(name) {
6dc69f51
KS
961 let mux = mux_creator.new_muxer(&mut bw);
962 let opts = mux.get_supported_options();
963 print_options(name, opts);
964 } else {
965 println!("muxer {} is not found", name);
966 }
5a8a7cdb 967 printed_info = true;
6dc69f51 968 },
4b5c61e2 969 "--input" | "-i" => {
6dc69f51
KS
970 next_arg!(args, arg_idx);
971 transcoder.input_name = args[arg_idx].clone();
972 },
973 "--input-format" => {
974 next_arg!(args, arg_idx);
975 transcoder.input_fmt = Some(args[arg_idx].clone());
976 },
4b5c61e2 977 "--output" | "-o" => {
6dc69f51
KS
978 next_arg!(args, arg_idx);
979 transcoder.output_name = args[arg_idx].clone();
980 },
981 "--output-format" => {
982 next_arg!(args, arg_idx);
983 transcoder.output_fmt = Some(args[arg_idx].clone());
984 },
985 "--demuxer-options" => {
986 next_arg!(args, arg_idx);
91a15e39 987 if !transcoder.parse_demuxer_options(&args[arg_idx], &full_reg.dmx_reg) {
6dc69f51
KS
988 println!("invalid demuxer option syntax");
989 return;
990 }
991 },
df37d3b1
KS
992 "--scale-options" => {
993 next_arg!(args, arg_idx);
994 if !transcoder.parse_scale_options(&args[arg_idx]) {
995 println!("invalid scale option syntax");
996 return;
997 }
998 },
4b5c61e2 999 "--no-video" | "-vn" => {
6dc69f51
KS
1000 transcoder.no_video = true;
1001 },
4b5c61e2 1002 "--no-audio" | "-an" => {
6dc69f51
KS
1003 transcoder.no_audio = true;
1004 },
951916e8
KS
1005 "--start" => {
1006 next_arg!(args, arg_idx);
1007 let ret = args[arg_idx].parse::<NATimePoint>();
1008 if let Ok(val) = ret {
1009 transcoder.start = val;
1010 } else {
1011 println!("invalid start time");
1012 return;
1013 }
1014 },
1015 "--end" => {
1016 next_arg!(args, arg_idx);
1017 let ret = args[arg_idx].parse::<NATimePoint>();
1018 if let Ok(val) = ret {
1019 transcoder.end = val;
1020 } else {
b0c51548 1021 println!("invalid end time");
951916e8
KS
1022 return;
1023 }
1024 },
6dc69f51
KS
1025 "--muxer-options" => {
1026 next_arg!(args, arg_idx);
91a15e39 1027 if !transcoder.parse_muxer_options(&args[arg_idx], &full_reg.mux_reg) {
6dc69f51
KS
1028 println!("invalid muxer option syntax");
1029 return;
1030 }
1031 },
908ba48c
KS
1032 "--verbose" | "-v" => transcoder.verbose = 1,
1033 "-vv" => transcoder.verbose = 2,
1034 "-v-" => transcoder.verbose = 0,
6dc69f51
KS
1035 _ => {
1036 if args[arg_idx].starts_with("--istream") {
1037 let opt0 = &args[arg_idx];
1038 next_arg!(args, arg_idx);
1039 if !transcoder.parse_istream_options(opt0, &args[arg_idx]) {
1040 println!("invalid input stream option syntax");
1041 return;
1042 }
1043 } else if args[arg_idx].starts_with("--ostream") {
1044 let opt0 = &args[arg_idx];
1045 next_arg!(args, arg_idx);
91a15e39 1046 if !transcoder.parse_ostream_options(opt0, &args[arg_idx], &full_reg.enc_reg) {
6dc69f51
KS
1047 println!("invalid output stream option syntax");
1048 return;
1049 }
1050 } else if args[arg_idx].starts_with("--") {
1051 println!("unknown option");
1052 } else {
1053 println!("unrecognized argument");
1054 }
1055 },
1056 };
1057 arg_idx += 1;
1058 }
1059
5a8a7cdb
KS
1060 if printed_info {
1061 return;
1062 }
1063
86c54d88 1064 if transcoder.input_name.is_empty() {
6dc69f51
KS
1065 println!("no input name provided");
1066 return;
1067 }
86c54d88 1068 if transcoder.output_name.is_empty() {
6dc69f51
KS
1069 println!("no output name provided");
1070 return;
1071 }
1072
90683bc3
KS
1073 if let Some("imgseq") = transcoder.input_fmt.as_deref() {
1074 let mut isdc = ImgSeqDemuxerCreator::new(transcoder.input_name.as_str());
1075 parse_and_apply_options!(isdc, &transcoder.demux_opts, "input");
1076 let isd = if let Ok(ctx) = isdc.open() {
1077 ctx
1078 } else {
1079 println!("failed to create image sequence demuxer!");
1080 return;
1081 };
1082 let mut dmx = DemuxerObject::create_imgseq(isd);
1083 transcode(transcoder, full_reg, &mut dmx);
1084 return;
1085 }
1086
6dc69f51
KS
1087 let res = File::open(transcoder.input_name.as_str());
1088 if res.is_err() {
1089 println!("error opening input");
1090 return;
1091 }
91a15e39
KS
1092 let file = res.unwrap();
1093 let file = BufReader::new(file);
1094 let mut fr = FileReader::new_read(file);
6dc69f51 1095 let mut br = ByteReader::new(&mut fr);
91a15e39
KS
1096 let (is_raw, start, end) = if transcoder.input_fmt.is_none() {
1097 detect_tags(&mut br)
6dc69f51 1098 } else {
91a15e39 1099 (false, 0, None)
6dc69f51 1100 };
91a15e39
KS
1101
1102 let mut nfr: Box<dyn ByteIO>;
1103 if start != 0 || end.is_some() {
1104 let file = fr.finish();
1105 nfr = Box::new(BoundedFileReader::new_read(file, start, end).unwrap());
1106 } else {
1107 nfr = Box::new(fr);
1108 }
1109 let mut br = ByteReader::new(nfr.as_mut());
1110
1111 let mut dmx = DemuxerObject::create(&mut br, &full_reg, transcoder.input_name.as_str(), &transcoder.input_fmt, is_raw);
1112 if dmx.is_none() {
1113 println!("cannot find demuxer for '{}'", transcoder.input_name.as_str());
6dc69f51
KS
1114 return;
1115 }
90683bc3
KS
1116 parse_and_apply_options!(dmx, &transcoder.demux_opts, "input");
1117 transcode(transcoder, full_reg, &mut dmx);
1118}
1119
1120fn transcode(mut transcoder: Transcoder, full_reg: FullRegister, dmx: &mut DemuxerObject) {
5ec8115f
KS
1121 let duration = dmx.get_duration();
1122 let duration_string = if duration != 0 { format_time(duration) } else { String::new() };
1123
6dc69f51
KS
1124 for i in 0..dmx.get_num_streams() {
1125 let s = dmx.get_stream(i).unwrap();
1126 let info = s.get_info();
91a15e39 1127 let decfunc = full_reg.dec_reg.find_decoder(info.get_name());
6dc69f51
KS
1128println!("stream {} - {} {}", i, s, info.get_name());
1129 let str_id = s.get_num() as u32;
1130 if let Some(create_dec) = decfunc {
1131 let mut dec = (create_dec)();
1132 let mut dsupp = Box::new(NADecoderSupport::new());
1133 let ret = dec.init(&mut dsupp, info.clone());
1134 if ret.is_err() {
1135 println!("Error initialising decoder '{}' for stream {}", info.get_name(), str_id);
1136 return;
1137 }
1138 transcoder.apply_decoder_options(dec.as_mut(), str_id);
d9fe2b71
KS
1139 let desc = register::get_codec_description(info.get_name());
1140 let has_b = if let Some(desc) = desc {
1141 desc.has_reorder()
1142 } else {
1143 println!("No codec description found, using B-frame reorderer.");
1144 true
1145 };
1146 let reord: Box<dyn FrameReorderer> = if has_b { Box::new(IPBReorderer::new()) } else { Box::new(NoReorderer::new()) };
1147 transcoder.decoders.push(Some((dsupp, dec, reord)));
6dc69f51
KS
1148 } else {
1149 println!("No decoder for stream {} ({}) is found", str_id, info.get_name());
1150 transcoder.decoders.push(None);
1151 }
1152 }
951916e8
KS
1153 if transcoder.start != NATimePoint::None {
1154 let ret = dmx.seek(transcoder.start);
1155 if ret.is_err() {
1156 println!(" failed to seek to {} error {:?}", transcoder.start, ret.err().unwrap());
1157 }
1158 }
6dc69f51 1159
fd03a232
KS
1160 let output_fmt = if let Some(ref fmtname) = transcoder.output_fmt {
1161 fmtname
c23d0c3a
KS
1162 } else if transcoder.output_name.as_str() == "/dev/null" {
1163 "null"
fd03a232
KS
1164 } else if let Some(fmtname) = detect::detect_format_by_name(transcoder.output_name.as_str()) {
1165 fmtname
6dc69f51 1166 } else {
86c54d88
KS
1167 println!("Cannot guess muxer for output");
1168 return;
6dc69f51 1169 };
91a15e39 1170 let ret = full_reg.mux_reg.find_muxer(output_fmt);
6dc69f51
KS
1171 let ofmt = output_fmt.to_string();
1172
1173 if ret.is_none() {
1174 println!("cannot find muxer '{}'", output_fmt);
1175 }
1176 let mux_creator = ret.unwrap();
1177
1178 let mux_caps = mux_creator.get_capabilities();
1179 let mut out_sm = StreamManager::new();
91a15e39 1180 if !transcoder.negotiate_stream_map(dmx.get_stream_manager(), mux_caps, &mut out_sm, &full_reg.enc_reg) {
6dc69f51
KS
1181 println!("cannot determine stream map");
1182 return;
1183 }
1184
1185 let ret = File::create(transcoder.output_name.as_str());
1186 if ret.is_err() {
1187 println!("cannot open output file");
1188 return;
1189 }
1190 let mut fw = FileWriter::new_write(ret.unwrap());
1191 let mut bw = ByteWriter::new(&mut fw);
1192 let ret = create_muxer(mux_creator, out_sm, &mut bw);
1193 if let Err(err) = ret {
1194 println!("cannot create muxer instance {:?}", err);
1195 return;
1196 }
1197 let mut mux = ret.unwrap();
1198 parse_and_apply_options!(mux, &transcoder.mux_opts, "output");
1199
1200 println!("Output {} muxer {}", transcoder.output_name, ofmt);
1201 for ostr in mux.get_streams() {
1202 println!(" #{}: {} {}", ostr.get_num(), ostr, ostr.get_info().get_name());
1203 }
1204
5ec8115f
KS
1205 let mut time = Instant::now();
1206 let show_interval = Duration::from_millis(100);
908ba48c
KS
1207 let mut adata_size = 0;
1208 let mut vdata_size = 0;
951916e8 1209 'main_loop: loop {
6dc69f51
KS
1210 let pktres = dmx.get_frame();
1211 if let Err(DemuxerError::EOF) = pktres { break; }
1212 if pktres.is_err() {
1213 println!("demuxing error");
1214 break;
1215 }
1216 let mut pkt = pktres.unwrap();
f88b8fb4 1217 if transcoder.start != NATimePoint::None && pkt.ts.less_than(transcoder.start) { continue; }
6dc69f51 1218 let src_id = pkt.get_stream().get_num();
908ba48c 1219 if transcoder.verbose > 0 && time.elapsed() >= show_interval {
5ec8115f
KS
1220 if let Some(pts) = pkt.get_pts() {
1221 let cur_time = format_time(NATimeInfo::ts_to_time(pts, 1000, pkt.ts.tb_num, pkt.ts.tb_den));
1222 print!(" {}", cur_time);
1223 } else {
1224 print!(" ???");
1225 }
1226 if !duration_string.is_empty() {
1227 print!(" / {}", duration_string);
1228 }
908ba48c
KS
1229 if transcoder.verbose > 1 {
1230 print!(" data sizes V: {} A: {}", vdata_size, adata_size);
1231 }
5ec8115f
KS
1232 print!("\r");
1233 std::io::stdout().flush().unwrap();
1234 time = Instant::now();
1235 }
6dc69f51
KS
1236 match transcoder.encoders[src_id] {
1237 OutputMode::Drop => {},
1238 OutputMode::Copy(dst_id) => {
1239 let dstr = mux.get_stream(dst_id as usize).unwrap();
1240 pkt.reassign(dstr, pkt.get_time_information());
951916e8 1241 if transcoder.end != NATimePoint::None && !pkt.ts.less_than(transcoder.end) { break 'main_loop; }
908ba48c
KS
1242 let pkt_size = pkt.get_buffer().len();
1243 match pkt.get_stream().get_media_type() {
1244 StreamType::Video => { vdata_size += pkt_size; },
1245 StreamType::Audio => { adata_size += pkt_size; },
1246 _ => {},
1247 };
6dc69f51
KS
1248 if mux.mux_frame(pkt).is_err() {
1249 println!("error muxing packet");
1250 break;
1251 }
1252 },
1253 OutputMode::Encode(dst_id, ref mut encoder, ref mut cvt) => {
d9fe2b71 1254 if let Some((ref mut dsupp, ref mut decoder, ref mut reorderer)) = transcoder.decoders[src_id] {
6dc69f51 1255 let ret = decoder.decode(dsupp, &pkt);
f88b8fb4
KS
1256 if let (true, Err(DecoderError::MissingReference)) = (transcoder.start != NATimePoint::None, &ret) {
1257 continue;
1258 }
6dc69f51
KS
1259 if ret.is_err() {
1260 println!("error decoding stream {}", src_id);
1261 break;
1262 }
1263 let frm = ret.unwrap();
b0481c9e 1264 let tinfo = frm.get_info();
d9fe2b71
KS
1265 reorderer.add_frame(frm);
1266 while let Some(frm) = reorderer.get_frame() {
df37d3b1 1267 if !encode_frame(dst_id, encoder, cvt, frm, &transcoder.scale_opts) {
d9fe2b71
KS
1268 break;
1269 }
1270 while let Ok(Some(pkt)) = encoder.get_packet() {
1271 if transcoder.end != NATimePoint::None && !pkt.ts.less_than(transcoder.end) { break 'main_loop; }
908ba48c
KS
1272 let pkt_size = pkt.get_buffer().len();
1273 match pkt.get_stream().get_media_type() {
1274 StreamType::Video => { vdata_size += pkt_size; },
1275 StreamType::Audio => { adata_size += pkt_size; },
1276 _ => {},
1277 };
d9fe2b71
KS
1278 mux.mux_frame(pkt).unwrap();
1279 }
6dc69f51 1280 }
b0481c9e
KS
1281 if let OutputConvert::Audio(ref mut acvt) = cvt {
1282 while let Some(ofrm) = acvt.get_frame(tinfo.clone()) {
1283 if encoder.encode(&ofrm).is_err() {
1284 break;
1285 }
1286 while let Ok(Some(pkt)) = encoder.get_packet() {
1287 if transcoder.end != NATimePoint::None && !pkt.ts.less_than(transcoder.end) { break 'main_loop; }
1288 let pkt_size = pkt.get_buffer().len();
1289 adata_size += pkt_size;
1290 mux.mux_frame(pkt).unwrap();
1291 }
1292 }
1293 }
6dc69f51
KS
1294 } else {
1295 println!("no decoder for stream {}", src_id);
1296 break;
1297 }
1298 },
1299 };
1300 }
fd03a232
KS
1301 'reord_flush_loop: for stream in dmx.get_streams() {
1302 let src_id = stream.get_num();
d9fe2b71
KS
1303 if let OutputMode::Encode(dst_id, ref mut encoder, ref mut cvt) = transcoder.encoders[src_id] {
1304 if let Some((_, _, ref mut reorderer)) = transcoder.decoders[src_id] {
1305 while let Some(frm) = reorderer.get_last_frames() {
df37d3b1 1306 if !encode_frame(dst_id, encoder, cvt, frm, &transcoder.scale_opts) {
d9fe2b71
KS
1307 break;
1308 }
1309 while let Ok(Some(pkt)) = encoder.get_packet() {
1310 if transcoder.end != NATimePoint::None && !pkt.ts.less_than(transcoder.end) { break 'reord_flush_loop; }
1311 mux.mux_frame(pkt).unwrap();
1312 }
1313 }
1314 }
1315 }
1316 }
6dc69f51
KS
1317 'flush_loop: for enc in transcoder.encoders.iter_mut() {
1318 match enc {
1319 OutputMode::Encode(str_id, ref mut encoder, _) => {
1320 let ret = encoder.flush();
1321 if ret.is_err() {
1322 println!("error flushing encoder for stream {}", str_id);
1323 break;
1324 } else {
1325 while let Ok(Some(pkt)) = encoder.get_packet() {
1326 if mux.mux_frame(pkt).is_err() {
1327 println!("error muxing packet");
1328 break 'flush_loop;
1329 }
1330 }
1331 }
1332 },
1333 _ => {},
1334 };
1335 }
908ba48c 1336 if transcoder.verbose > 0 {
5ec8115f
KS
1337 println!();
1338 }
6dc69f51
KS
1339
1340 let ret = mux.end();
1341 if ret.is_err() {
1342 println!("error at finalising muxing");
1343 }
1344}