extern crate sdl2_sys;
extern crate nihav_core;
extern crate nihav_registry;
-extern crate nihav_allstuff;
use std::fs::File;
use std::io::prelude::*;
-use std::io::{BufReader, SeekFrom};
+use std::io::BufReader;
use std::sync::mpsc;
use std::time::Duration;
use std::thread;
use nihav_core::codecs::*;
use nihav_core::demuxers::*;
use nihav_core::soundcvt::*;
-use nihav_registry::detect;
-use nihav_allstuff::*;
+mod allreg;
mod command;
use command::*;
+mod demux;
+use demux::*;
struct Player {
ended: bool,
- dmx_reg: RegisteredDemuxers,
- dec_reg: RegisteredDecoders,
+ full_reg: allreg::FullRegister,
paused: bool,
mute: bool,
volume: u8,
}
}
+impl Drop for AudioDevice {
+ fn drop(&mut self) {
+ unsafe { sdl2_sys::SDL_CloseAudioDevice(self.device_id); }
+ }
+}
+
struct Decoder<'a> {
- demuxer: Demuxer<'a>,
+ demuxer: DemuxerObject<'a>,
decoder: Box<dyn NADecoder>,
dsupp: Box<NADecoderSupport>,
buf: &'a mut Vec<i16>,
fn output_vol_i16(device: &AudioDevice, tmp: &mut Vec<i16>, src: &[i16], mute: bool, volume: u8) {
if !mute {
- tmp.truncate(0);
+ tmp.clear();
tmp.reserve(src.len());
let vol = i32::from(volume);
for &sample in src.iter() {
tmp.push(nsamp.min(32767).max(-32768) as i16);
}
} else {
- tmp.truncate(0);
+ tmp.clear();
tmp.resize(src.len(), 0);
}
device.queue(&tmp);
fn output_vol_u8(device: &AudioDevice, tmp: &mut Vec<i16>, src: &[u8], mute: bool, volume: u8) {
if !mute {
- tmp.truncate(0);
+ tmp.clear();
tmp.reserve(src.len());
let vol = i32::from(volume);
for sample in src.chunks_exact(2) {
tmp.push(nsamp.min(32767).max(-32768) as i16);
}
} else {
- tmp.truncate(0);
+ tmp.clear();
tmp.resize(src.len() / 2, 0);
}
device.queue(&tmp);
match self.decoder.decode(&mut self.dsupp, &pkt) {
Ok(frm) => {
let buf = frm.get_buffer();
+ if let NABufferType::None = buf {
+ return false;
+ }
if let Some(pts) = frm.ts.get_pts() {
self.samplepos = NATimeInfo::ts_to_time(pts, u64::from(self.arate), frm.ts.tb_num, frm.ts.tb_den);
}
+ if buf.get_audio_length() == 0 {
+ return false;
+ }
let out_buf = convert_audio_frame(&buf, &self.dst_info, &self.dst_chmap).unwrap();
match out_buf {
NABufferType::AudioI16(abuf) => {
fn seek(&mut self, time: u64) -> bool {
let ret = self.demuxer.seek(NATimePoint::Milliseconds(time));
if ret.is_err() { println!(" seek error\n"); }
+ self.decoder.flush();
ret.is_ok()
}
}
impl Player {
fn new() -> Self {
- let mut dmx_reg = RegisteredDemuxers::new();
- nihav_register_all_demuxers(&mut dmx_reg);
- let mut dec_reg = RegisteredDecoders::new();
- nihav_register_all_decoders(&mut dec_reg);
+ let full_reg = allreg::FullRegister::new();
unsafe {
if sdl2_sys::SDL_Init(sdl2_sys::SDL_INIT_AUDIO) != 0 {
Self {
ended: false,
paused: false,
- dmx_reg, dec_reg,
+ full_reg,
volume: 100,
mute: false,
debug: false,
println!("error opening {}", name);
return;
}
- let mut file = ret.unwrap();
+ let file = ret.unwrap();
+ let file = BufReader::new(file);
- let mut fr = FileReader::new_read(&mut file);
+ let mut fr = FileReader::new_read(file);
let mut br = ByteReader::new(&mut fr);
- let res = detect::detect_format(name, &mut br);
- if res.is_none() {
- println!("cannot detect format for {}", name);
- return;
- }
- let (dmx_name, _) = res.unwrap();
- drop(br);
- drop(fr);
- let dmx_fact = self.dmx_reg.find_demuxer(dmx_name);
- if dmx_fact.is_none() {
- println!("no demuxer for format {}", dmx_name);
+ if br.peek_byte().is_err() {
+ println!("Cannot read {}", name);
return;
}
- let dmx_fact = dmx_fact.unwrap();
+ let (is_raw, start, end) = detect_tags(&mut br);
- file.seek(SeekFrom::Start(0)).unwrap();
- let mut file = BufReader::new(file);
- let mut fr = FileReader::new_read(&mut file);
- let mut br = ByteReader::new(&mut fr);
- let res = create_demuxer(dmx_fact, &mut br);
- if res.is_err() {
- println!("cannot create demuxer");
+ let mut nfr: Box<dyn ByteIO>;
+ if start != 0 || end.is_some() {
+ //println!(" limiting range to {:X}-{:X}", start, end.unwrap_or(0));
+ let file = fr.finish();
+ nfr = Box::new(BoundedFileReader::new_read(file, start, end).unwrap());
+ } else {
+ nfr = Box::new(fr);
+ }
+ let mut br = ByteReader::new(nfr.as_mut());
+ let dmx = DemuxerObject::create(&mut br, &self.full_reg, name, is_raw);
+ if dmx.is_none() {
+ println!("No demuxer found!");
return;
}
- let dmx = res.unwrap();
let mut ainfo = None;
let mut dec: Option<(Box<NADecoderSupport>, Box<dyn NADecoder>)> = None;
let s = dmx.get_stream(i).unwrap();
let info = s.get_info();
if info.is_audio() {
- let decfunc = self.dec_reg.find_decoder(info.get_name());
+ let decfunc = self.full_reg.dec_reg.find_decoder(info.get_name());
if decfunc.is_none() {
println!("no decoder for {}", info.get_name());
continue;
}
let (dsupp, decoder) = dec.unwrap();
- let ainfo = ainfo.unwrap().get_properties().get_audio_info().unwrap();
- let arate = if ainfo.sample_rate > 0 { ainfo.sample_rate } else { 44100 };
+ let info = ainfo.unwrap();
+ let ainfo = info.get_properties().get_audio_info().unwrap();
+ let sbr_hack = info.get_name() == "aac" && ainfo.sample_rate < 32000;
+ let arate = if ainfo.sample_rate > 0 {
+ if !sbr_hack {
+ ainfo.sample_rate
+ } else {
+ ainfo.sample_rate * 2
+ }
+ } else { 44100 };
let ch = ainfo.channels;
println!("Playing {} [{}Hz {}ch]", name, arate, ch);
- let ret = AudioDevice::open(arate, ch.max(2));
+ let ret = AudioDevice::open(arate, ch.min(2));
if ret.is_none() {
println!("cannot open output");
return;
}
}
std::io::stdout().flush().unwrap();
- if device.size() < underfill_limit && !self.paused && refill_limit < (1 << 20) {
+ if device.size() < underfill_limit && !self.paused && (refill_limit < (1 << 20)) & !eof {
if full_ms > 5000 {
println!("underrun!");
}