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