fix clippy warnings
[nihav.git] / nihav-codec-support / src / test / dec_video.rs
CommitLineData
fb8e3177 1//! Routines for testing decoders.
379fd781 2use std::fs::File;
b4d5b851
KS
3use nihav_core::frame::*;
4use nihav_core::codecs::*;
5use nihav_core::demuxers::*;
6//use nihav_core::io::byteio::*;
8424ddfd 7//use nihav_core::scale::*;
366d60cc 8use nihav_core::reorder::MTFrameReorderer;
379fd781 9use super::wavwriter::WavWriter;
eca0802b 10use super::md5::MD5;
8424ddfd 11use crate::imgwrite::write_pnm;
eca0802b 12pub use super::ExpectedTestResult;
379fd781 13
8424ddfd 14const OUTPUT_PREFIX: &str = "assets/test_out/";
a191f568 15
379fd781
KS
16/*fn open_wav_out(pfx: &str, strno: usize) -> WavWriter {
17 let name = format!("assets/{}out{:02}.wav", pfx, strno);
18 let mut file = File::create(name).unwrap();
19 let mut fw = FileWriter::new_write(&mut file);
20 let mut wr = ByteWriter::new(&mut fw);
21 WavWriter::new(&mut wr)
22}*/
23
fb8e3177
KS
24/// Tests decoding of provided file and optionally outputs video frames as PNM (PPM for RGB video, PGM for YUV).
25///
26/// This function expects the following arguments:
27/// * `demuxer` - container format name (used to find proper demuxer for it)
28/// * `name` - input file name
29/// * `limit` - optional PTS value after which decoding is stopped
30/// * `decode_video`/`decode_audio` - flags for enabling video/audio decoding
31/// * `video_pfx` - prefix for video frames written as pictures (if enabled then output picture names should look like `<crate_name>/assets/test_out/PFXout00_000000.ppm`
32/// * `dmx_reg` and `dec_reg` - registered demuxers and decoders that should contain demuxer and decoder(s) needed to decode the provided file.
33///
34/// Since the function is intended for tests, it will panic instead of returning an error.
379fd781
KS
35pub fn test_file_decoding(demuxer: &str, name: &str, limit: Option<u64>,
36 decode_video: bool, decode_audio: bool,
4f6124ac
KS
37 video_pfx: Option<&str>,
38 dmx_reg: &RegisteredDemuxers, dec_reg: &RegisteredDecoders) {
39 let dmx_f = dmx_reg.find_demuxer(demuxer).unwrap();
379fd781
KS
40 let mut file = File::open(name).unwrap();
41 let mut fr = FileReader::new_read(&mut file);
42 let mut br = ByteReader::new(&mut fr);
bcfeae48 43 let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
379fd781 44
6011e201 45 let mut decs: Vec<Option<(Box<NADecoderSupport>, Box<dyn NADecoder>)>> = Vec::new();
379fd781
KS
46 for i in 0..dmx.get_num_streams() {
47 let s = dmx.get_stream(i).unwrap();
48 let info = s.get_info();
4f6124ac 49 let decfunc = dec_reg.find_decoder(info.get_name());
379fd781
KS
50 if let Some(df) = decfunc {
51 if (decode_video && info.is_video()) || (decode_audio && info.is_audio()) {
52 let mut dec = (df)();
01613464
KS
53 let mut dsupp = Box::new(NADecoderSupport::new());
54 dec.init(&mut dsupp, info).unwrap();
55 decs.push(Some((dsupp, dec)));
379fd781
KS
56 } else {
57 decs.push(None);
58 }
59 } else {
60 decs.push(None);
61 }
62 }
63
64 loop {
65 let pktres = dmx.get_frame();
66 if let Err(e) = pktres {
67 if e == DemuxerError::EOF { break; }
68 panic!("error");
69 }
70 let pkt = pktres.unwrap();
379fd781 71 let streamno = pkt.get_stream().get_id() as usize;
01613464 72 if let Some((ref mut dsupp, ref mut dec)) = decs[streamno] {
d5f4d49e
KS
73 if let (Some(lim), Some(ppts)) = (limit, pkt.get_pts()) {
74 if ppts > lim { break; }
75 }
01613464 76 let frm = dec.decode(dsupp, &pkt).unwrap();
171860fc 77 if pkt.get_stream().get_info().is_video() && video_pfx.is_some() && frm.get_frame_type() != FrameType::Skip {
e243ceb4 78 let pts = if let Some(fpts) = frm.get_pts() { fpts } else { pkt.get_pts().unwrap() };
8424ddfd
KS
79 let pfx = OUTPUT_PREFIX.to_owned() + video_pfx.unwrap_or("") + "out";
80 write_pnm(pfx.as_str(), streamno, pts, frm).unwrap();
379fd781
KS
81 }
82 }
83 }
84}
85
fb8e3177
KS
86/// Tests audio decoder with the content in the provided file and optionally outputs decoded audio.
87///
88/// The syntax is very similar to [`test_file_decoding`] except that it is intended for testing audio codecs.
89///
90/// Since the function is intended for tests, it will panic instead of returning an error.
91///
92/// [`test_file_decoding`]: ./fn.test_file_decoding.html
5580b11b 93pub fn test_decode_audio(demuxer: &str, name: &str, limit: Option<u64>, audio_pfx: Option<&str>,
4f6124ac
KS
94 dmx_reg: &RegisteredDemuxers, dec_reg: &RegisteredDecoders) {
95 let dmx_f = dmx_reg.find_demuxer(demuxer).unwrap();
379fd781
KS
96 let mut file = File::open(name).unwrap();
97 let mut fr = FileReader::new_read(&mut file);
98 let mut br = ByteReader::new(&mut fr);
bcfeae48 99 let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
379fd781 100
6011e201 101 let mut decs: Vec<Option<(Box<NADecoderSupport>, Box<dyn NADecoder>)>> = Vec::new();
379fd781
KS
102 for i in 0..dmx.get_num_streams() {
103 let s = dmx.get_stream(i).unwrap();
104 let info = s.get_info();
4f6124ac 105 let decfunc = dec_reg.find_decoder(info.get_name());
379fd781
KS
106 if let Some(df) = decfunc {
107 if info.is_audio() {
108 let mut dec = (df)();
01613464
KS
109 let mut dsupp = Box::new(NADecoderSupport::new());
110 dec.init(&mut dsupp, info).unwrap();
111 decs.push(Some((dsupp, dec)));
379fd781
KS
112 } else {
113 decs.push(None);
114 }
115 } else {
116 decs.push(None);
117 }
118 }
119
d24468d9 120 if let Some(audio_pfx) = audio_pfx {
92754149 121 let name = format!("{}/{}out.wav", OUTPUT_PREFIX, audio_pfx);
5580b11b
KS
122 let file = File::create(name).unwrap();
123 let mut fw = FileWriter::new_write(file);
124 let mut wr = ByteWriter::new(&mut fw);
125 let mut wwr = WavWriter::new(&mut wr);
126 let mut wrote_header = false;
379fd781 127
5580b11b
KS
128 loop {
129 let pktres = dmx.get_frame();
130 if let Err(e) = pktres {
131 if e == DemuxerError::EOF { break; }
132 panic!("error");
133 }
134 let pkt = pktres.unwrap();
135 if limit.is_some() && pkt.get_pts().is_some() && pkt.get_pts().unwrap() > limit.unwrap() {
136 break;
137 }
138 let streamno = pkt.get_stream().get_id() as usize;
139 if let Some((ref mut dsupp, ref mut dec)) = decs[streamno] {
140 let frm = dec.decode(dsupp, &pkt).unwrap();
141 if frm.get_info().is_audio() {
142 if !wrote_header {
143 wwr.write_header(frm.get_info().as_ref().get_properties().get_audio_info().unwrap()).unwrap();
144 wrote_header = true;
145 }
146 wwr.write_frame(frm.get_buffer()).unwrap();
379fd781 147 }
5580b11b
KS
148 }
149 }
150 } else {
151 loop {
152 let pktres = dmx.get_frame();
153 if let Err(e) = pktres {
154 if e == DemuxerError::EOF { break; }
155 panic!("error");
156 }
157 let pkt = pktres.unwrap();
158 if limit.is_some() && pkt.get_pts().is_some() && pkt.get_pts().unwrap() > limit.unwrap() {
159 break;
160 }
161 let streamno = pkt.get_stream().get_id() as usize;
162 if let Some((ref mut dsupp, ref mut dec)) = decs[streamno] {
163 let _ = dec.decode(dsupp, &pkt).unwrap();
379fd781
KS
164 }
165 }
166 }
167}
eca0802b
KS
168
169fn frame_checksum(md5: &mut MD5, frm: NAFrameRef) {
170 match frm.get_buffer() {
171 NABufferType::Video(ref vb) => {
172 md5.update_hash(vb.get_data());
173 },
174 NABufferType::Video16(ref vb) => {
175 let mut samp = [0u8; 2];
176 let data = vb.get_data();
177 for el in data.iter() {
178 samp[0] = (*el >> 8) as u8;
179 samp[1] = (*el >> 0) as u8;
180 md5.update_hash(&samp);
181 }
182 },
183 NABufferType::Video32(ref vb) => {
184 let mut samp = [0u8; 4];
185 let data = vb.get_data();
186 for el in data.iter() {
187 samp[0] = (*el >> 24) as u8;
188 samp[1] = (*el >> 16) as u8;
189 samp[2] = (*el >> 8) as u8;
190 samp[3] = (*el >> 0) as u8;
191 md5.update_hash(&samp);
192 }
193 },
194 NABufferType::VideoPacked(ref vb) => {
195 md5.update_hash(vb.get_data());
196 },
197 NABufferType::AudioU8(ref ab) => {
198 md5.update_hash(ab.get_data());
199 },
200 NABufferType::AudioI16(ref ab) => {
201 let mut samp = [0u8; 2];
202 let data = ab.get_data();
203 for el in data.iter() {
204 samp[0] = (*el >> 8) as u8;
205 samp[1] = (*el >> 0) as u8;
206 md5.update_hash(&samp);
207 }
208 },
209 NABufferType::AudioI32(ref ab) => {
210 let mut samp = [0u8; 4];
211 let data = ab.get_data();
212 for el in data.iter() {
213 samp[0] = (*el >> 24) as u8;
214 samp[1] = (*el >> 16) as u8;
215 samp[2] = (*el >> 8) as u8;
216 samp[3] = (*el >> 0) as u8;
217 md5.update_hash(&samp);
218 }
219 },
220 NABufferType::AudioF32(ref ab) => {
221 let mut samp = [0u8; 4];
222 let data = ab.get_data();
223 for el in data.iter() {
224 let bits = el.to_bits();
225 samp[0] = (bits >> 24) as u8;
226 samp[1] = (bits >> 16) as u8;
227 samp[2] = (bits >> 8) as u8;
228 samp[3] = (bits >> 0) as u8;
229 md5.update_hash(&samp);
230 }
231 },
232 NABufferType::AudioPacked(ref ab) => {
233 md5.update_hash(ab.get_data());
234 },
235 NABufferType::Data(ref db) => {
236 md5.update_hash(db.as_ref());
237 },
238 NABufferType::None => {},
239 };
240}
241
fb8e3177
KS
242/// Tests decoder for requested codec in provided file.
243///
244/// This functions tries to decode a stream corresponding to `dec_name` codec in input file and validate the results against expected ones.
245///
246/// Since the function is intended for tests, it will panic instead of returning an error.
247///
248/// # Examples
249///
250/// Test RealVideo 4 decoder in test stream:
251/// ```no_run
b4d5b851
KS
252/// use nihav_codec_support::test::ExpectedTestResult;
253/// use nihav_codec_support::test::dec_video::test_decoding;
fb8e3177
KS
254/// use nihav_core::codecs::RegisteredDecoders;
255/// use nihav_core::demuxers::RegisteredDemuxers;
256///
257/// let mut dmx_reg = RegisteredDemuxers::new();
258/// let mut dec_reg = RegisteredDecoders::new();
259/// // ... register RealMedia demuxers and RealVideo decoders ...
260/// test_decoding("realmedia", "rv40", "assets/test_file.rmvb", None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5([0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f]));
261/// ```
d24468d9 262pub fn test_decoding(demuxer: &str, dec_name: &str, filename: &str, limit: Option<u64>,
eca0802b
KS
263 dmx_reg: &RegisteredDemuxers, dec_reg: &RegisteredDecoders,
264 test: ExpectedTestResult) {
265 let dmx_f = dmx_reg.find_demuxer(demuxer).unwrap();
266 let mut file = File::open(filename).unwrap();
267 let mut fr = FileReader::new_read(&mut file);
268 let mut br = ByteReader::new(&mut fr);
269 let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
270
271 let mut decs: Vec<Option<(Box<NADecoderSupport>, Box<dyn NADecoder>)>> = Vec::new();
272 let mut found = false;
273 for i in 0..dmx.get_num_streams() {
274 let s = dmx.get_stream(i).unwrap();
275 let info = s.get_info();
276println!("stream {} codec {} / {}", i, info.get_name(), dec_name);
277 if !found && (info.get_name() == dec_name) {
278 let decfunc = dec_reg.find_decoder(info.get_name());
279 if let Some(df) = decfunc {
280 let mut dec = (df)();
281 let mut dsupp = Box::new(NADecoderSupport::new());
282 dec.init(&mut dsupp, info).unwrap();
283 decs.push(Some((dsupp, dec)));
284 found = true;
285 } else {
286 decs.push(None);
287 }
288 } else {
289 decs.push(None);
290 }
291 }
292
293 let mut md5 = MD5::new();
294 let mut frameiter = if let ExpectedTestResult::MD5Frames(ref vec) = test {
295 Some(vec.iter())
296 } else {
297 None
298 };
299 loop {
300 let pktres = dmx.get_frame();
301 if let Err(e) = pktres {
302 if e == DemuxerError::EOF { break; }
303 panic!("error");
304 }
305 let pkt = pktres.unwrap();
306 let streamno = pkt.get_stream().get_id() as usize;
307 if let Some((ref mut dsupp, ref mut dec)) = decs[streamno] {
308 if limit.is_some() && pkt.get_pts().is_some() && pkt.get_pts().unwrap() > limit.unwrap() {
309 break;
310 }
311 let frm = dec.decode(dsupp, &pkt).unwrap();
312 match &test {
313 ExpectedTestResult::Decodes => {},
314 ExpectedTestResult::MD5(_) => { frame_checksum(&mut md5, frm); },
315 ExpectedTestResult::MD5Frames(_) => {
316 md5 = MD5::new();
317 frame_checksum(&mut md5, frm);
318 md5.finish();
319 if let Some(ref mut iter) = frameiter {
320 let ret = iter.next();
321 if ret.is_none() { break; }
322 let ref_hash = ret.unwrap();
323 let mut hash = [0u32; 4];
324 md5.get_hash(&mut hash);
325println!("frame pts {:?} hash {}", pkt.get_pts(), md5);
326 assert_eq!(&hash, ref_hash);
327 }
328 },
329 ExpectedTestResult::GenerateMD5Frames => {
330 md5 = MD5::new();
331 frame_checksum(&mut md5, frm);
332 md5.finish();
96eff47e
KS
333 let mut hash = [0u32; 4];
334 md5.get_hash(&mut hash);
335println!("frame pts {:?} hash [0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x}],", pkt.get_pts(), hash[0], hash[1], hash[2], hash[3]);
eca0802b
KS
336 },
337 };
338 }
339 }
340 if let ExpectedTestResult::MD5(ref ref_hash) = test {
366d60cc
KS
341 md5.finish();
342 let mut hash = [0u32; 4];
343 md5.get_hash(&mut hash);
344println!("full hash {}", md5);
345 assert_eq!(&hash, ref_hash);
346 }
347 if let ExpectedTestResult::GenerateMD5Frames = test {
348 panic!("generated hashes");
349 }
350}
351
352const THREADS: usize = 3;
353
354fn check_frame(frm: NAFrameRef, test: &ExpectedTestResult, glbl_md5: &mut MD5, frameiter: &mut Option<std::slice::Iter<[u32; 4]>>, last_ts: &mut Option<u64>) -> bool {
355 let frm_pts = frm.get_pts();
356 let frm_dts = frm.get_dts();
357 if let (Some(lts), Some(cts)) = (*last_ts, frm_dts) {
358 assert!(lts < cts);
359 }
360 *last_ts = frm_dts;
361 match test {
362 ExpectedTestResult::Decodes => {},
363 ExpectedTestResult::MD5(_) => { frame_checksum(glbl_md5, frm); },
364 ExpectedTestResult::MD5Frames(_) => {
365 let mut loc_md5 = MD5::new();
366 frame_checksum(&mut loc_md5, frm);
367 loc_md5.finish();
368 if let Some(ref mut iter) = frameiter {
369 let ret = iter.next();
370 if ret.is_none() {
371 return true;
372 }
373 let ref_hash = ret.unwrap();
374 let mut hash = [0u32; 4];
375 loc_md5.get_hash(&mut hash);
376println!("frame pts {:?} dts {:?} hash {}", frm_pts, frm_dts, loc_md5);
377 assert_eq!(&hash, ref_hash);
378 }
379 },
380 ExpectedTestResult::GenerateMD5Frames => {
381 let mut loc_md5 = MD5::new();
382 frame_checksum(&mut loc_md5, frm);
383 loc_md5.finish();
384 let mut hash = [0u32; 4];
385 loc_md5.get_hash(&mut hash);
386println!("frame pts {:?} dts {:?} hash [0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x}],", frm_pts, frm_dts, hash[0], hash[1], hash[2], hash[3]);
387 },
388 };
389 false
390}
391
392/// Tests multi-threaded decoder for requested codec in provided file.
393///
394/// The syntax is very similar to [`test_file_decoding`] except that it tests multi-threaded decoders instead.
395///
396/// [`test_file_decoding`]: ./fn.test_file_decoding.html
397pub fn test_mt_decoding(demuxer: &str, dec_name: &str, filename: &str, limit: Option<u64>,
398 dmx_reg: &RegisteredDemuxers, dec_reg: &RegisteredMTDecoders,
399 test: ExpectedTestResult) {
400 let mut dec_threads = THREADS;
401 for (key, value) in std::env::vars_os() {
402 if key == "MT_THREADS" {
403 if let Some(val) = value.to_str() {
404 dec_threads = val.parse::<usize>().unwrap_or(THREADS);
405 break;
406 }
407 }
408 }
409
410 let dmx_f = dmx_reg.find_demuxer(demuxer).expect("demuxer is not found");
411 let mut file = File::open(filename).expect("input file should be present");
412 let mut fr = FileReader::new_read(&mut file);
413 let mut br = ByteReader::new(&mut fr);
414 let mut dmx = create_demuxer(dmx_f, &mut br).expect("demuxer can't be created");
415
416 let mut decs: Vec<Option<(Box<NADecoderSupport>, Box<dyn NADecoderMT>)>> = Vec::new();
417 let mut found = false;
418 for i in 0..dmx.get_num_streams() {
419 let s = dmx.get_stream(i).unwrap();
420 let info = s.get_info();
421println!("stream {} codec {} / {}", i, info.get_name(), dec_name);
422 if !found && (info.get_name() == dec_name) {
423 let decfunc = dec_reg.find_decoder(info.get_name());
424 if let Some(df) = decfunc {
425 let mut dec = (df)();
426 let mut dsupp = Box::new(NADecoderSupport::new());
427 dec.init(&mut dsupp, info, dec_threads).unwrap();
428 decs.push(Some((dsupp, dec)));
429 found = true;
430 } else {
431 decs.push(None);
432 }
433 } else {
434 decs.push(None);
435 }
436 }
437
438 let mut md5 = MD5::new();
439 let mut frameiter = if let ExpectedTestResult::MD5Frames(ref vec) = test {
440 Some(vec.iter())
441 } else {
442 None
443 };
444 let mut reord = MTFrameReorderer::new();
445 let mut last_ts = None;
446 'dec_loop: loop {
447 let pktres = dmx.get_frame();
448 if let Err(e) = pktres {
449 if e == DemuxerError::EOF { break; }
450 panic!("error");
451 }
452 let pkt = pktres.expect("packet");
453 let streamno = pkt.get_stream().get_id() as usize;
454 if let Some((ref mut dsupp, ref mut dec)) = decs[streamno] {
455 if limit.is_some() && pkt.get_pts().is_some() && pkt.get_pts().unwrap() > limit.unwrap() {
456 break;
457 }
458 let queue_id = reord.register_frame();
459 match dec.queue_pkt(dsupp, &pkt, queue_id) {
460 Ok(true) => {},
461 Ok(false) => {
462 while !dec.can_take_input() || dec.has_output() {
463 match dec.get_frame() {
464 (Ok(frm), id) => {
465 reord.add_frame(frm, id);
466 while let Some(nfrm) = reord.get_frame() {
467 if check_frame(nfrm, &test, &mut md5, &mut frameiter, &mut last_ts) {
468 break 'dec_loop;
469 }
470 }
471 },
472 (Err(err), id) => {
473 reord.drop_frame(id);
474 panic!("frame {} decoding error {:?}", id, err);
475 },
476 };
477 }
478 match dec.queue_pkt(dsupp, &pkt, queue_id) {
479 Ok(true) => {},
480 Ok(false) => panic!("still can't queue frame!"),
481 Err(err) => panic!("queueing error {:?}", err),
482 };
483 },
484 Err(err) => panic!("queueing error {:?}", err),
485 };
486
487 }
488 }
e6aaad5c 489 'tail_loop: for (_, ref mut dec) in decs.iter_mut().flatten() {
366d60cc
KS
490 loop {
491 match dec.get_frame() {
492 (Ok(frm), id) => {
493 reord.add_frame(frm, id);
494 while let Some(nfrm) = reord.get_frame() {
495 if check_frame(nfrm, &test, &mut md5, &mut frameiter, &mut last_ts) {
496 break 'tail_loop;
497 }
498 }
499 },
500 (Err(DecoderError::NoFrame), _) => break,
501 (Err(err), id) => panic!("frame {} decoding error {:?}", id, err),
502 };
503 }
504 while let Some(nfrm) = reord.get_last_frames() {
505 if check_frame(nfrm, &test, &mut md5, &mut frameiter, &mut last_ts) {
506 break;
507 }
508 }
366d60cc
KS
509 }
510 if let ExpectedTestResult::MD5(ref ref_hash) = test {
eca0802b
KS
511 md5.finish();
512 let mut hash = [0u32; 4];
513 md5.get_hash(&mut hash);
514println!("full hash {}", md5);
515 assert_eq!(&hash, ref_hash);
516 }
517 if let ExpectedTestResult::GenerateMD5Frames = test {
518 panic!("generated hashes");
519 }
520}
995e421a
KS
521
522/// Tests decoding of provided file by outputting video frames as PNM (PPM for RGB video, PGM for YUV).
523///
524/// This function expects the following arguments:
525/// * `demuxer` - container format name (used to find proper demuxer for it)
526/// * `name` - input file name
527/// * `video_pfx` - prefix for video frames written as pictures (output picture names should look like `<crate_name>/assets/test_out/PFXout00_000000.ppm`
528/// * `limit` - optional PTS value after which decoding is stopped
529/// * `dmx_reg` and `dec_reg` - registered demuxers and decoders that should contain demuxer and decoder(s) needed to decode the provided file.
530///
531/// Since the function is intended for tests, it will panic instead of returning an error.
532pub fn test_decode_images(demuxer: &str, name: &str, video_pfx: &str, limit: Option<u64>,
533 dmx_reg: &RegisteredDemuxers, dec_reg: &RegisteredDecoders) {
534 let dmx_f = dmx_reg.find_demuxer(demuxer).unwrap();
535 let mut file = File::open(name).unwrap();
536 let mut fr = FileReader::new_read(&mut file);
537 let mut br = ByteReader::new(&mut fr);
538 let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
539
540 let mut decs: Vec<Option<(Box<NADecoderSupport>, Box<dyn NADecoder>)>> = Vec::new();
541 for i in 0..dmx.get_num_streams() {
542 let s = dmx.get_stream(i).unwrap();
543 let info = s.get_info();
544 let decfunc = dec_reg.find_decoder(info.get_name());
545 if let Some(df) = decfunc {
546 if info.is_video() {
547 let mut dec = (df)();
548 let mut dsupp = Box::new(NADecoderSupport::new());
549 dec.init(&mut dsupp, info).unwrap();
550 decs.push(Some((dsupp, dec)));
551 break;
552 } else {
553 decs.push(None);
554 }
555 } else {
556 decs.push(None);
557 }
558 }
559
560 loop {
561 let pktres = dmx.get_frame();
562 if let Err(e) = pktres {
563 if e == DemuxerError::EOF { break; }
564 panic!("error");
565 }
566 let pkt = pktres.unwrap();
567 let streamno = pkt.get_stream().get_id() as usize;
568 if streamno >= decs.len() { continue; }
569 if let Some((ref mut dsupp, ref mut dec)) = decs[streamno] {
570 if let (Some(lim), Some(ppts)) = (limit, pkt.get_pts()) {
571 if ppts > lim { break; }
572 }
573 let frm = dec.decode(dsupp, &pkt).unwrap();
574 if frm.get_frame_type() != FrameType::Skip {
575 let pts = if let Some(fpts) = frm.get_pts() { fpts } else { pkt.get_pts().unwrap() };
576 let pfx = OUTPUT_PREFIX.to_owned() + video_pfx + "out";
577 write_pnm(pfx.as_str(), streamno, pts, frm).unwrap();
578 }
579 }
580 }
581}