still some bugs

main
_ 2021-11-12 23:34:18 +00:00
parent ceb06dad16
commit a98fea30b4
4 changed files with 230 additions and 47 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/target /target
*.m4a *.m4a
*.ogg
*.opus *.opus

120
Cargo.lock generated
View File

@ -24,6 +24,15 @@ dependencies = [
"pkg-config", "pkg-config",
] ]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.45" version = "1.0.45"
@ -407,6 +416,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.4.1" version = "2.4.1"
@ -430,6 +448,8 @@ dependencies = [
"byteorder", "byteorder",
"cpal", "cpal",
"ffmpeg-next", "ffmpeg-next",
"tracing",
"tracing-subscriber",
] ]
[[package]] [[package]]
@ -602,6 +622,12 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "once_cell"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.11.2" version = "0.11.2"
@ -633,6 +659,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pin-project-lite"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.22" version = "0.3.22"
@ -694,6 +726,15 @@ dependencies = [
"regex-syntax", "regex-syntax",
] ]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax",
]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.25" version = "0.6.25"
@ -727,6 +768,15 @@ version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
[[package]]
name = "sharded-slab"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "0.1.1" version = "0.1.1"
@ -782,6 +832,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "thread_local"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
dependencies = [
"once_cell",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.8" version = "0.5.8"
@ -791,6 +850,67 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "tracing"
version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
dependencies = [
"cfg-if 1.0.0",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
dependencies = [
"lazy_static",
]
[[package]]
name = "tracing-log"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
dependencies = [
"lazy_static",
"log",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80a4ddde70311d8da398062ecf6fc2c309337de6b0f77d6c27aff8d53f6fca52"
dependencies = [
"ansi_term",
"lazy_static",
"matchers",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.2" version = "0.2.2"

View File

@ -10,3 +10,5 @@ anyhow = "1.0.45"
byteorder = "1.4.3" byteorder = "1.4.3"
cpal = "0.13.4" cpal = "0.13.4"
ffmpeg-next = "4.4.0" ffmpeg-next = "4.4.0"
tracing = "0.1.29"
tracing-subscriber = { version = "0.3.1", features = ["env-filter"] }

View File

@ -5,7 +5,11 @@ use std::{
Condvar, Condvar,
Mutex, Mutex,
}, },
thread, thread::{
self,
sleep,
},
time::Duration,
}; };
use anyhow::{ use anyhow::{
@ -74,31 +78,29 @@ impl PcmBuffers {
} }
fn main () -> Result <()> { fn main () -> Result <()> {
let host = cpal::default_host ();
let device = host.default_output_device ().ok_or_else (|| anyhow! ("can't open cpal device"))?;
let mut supported_configs_range = device.supported_output_configs ()?
.filter (|c| c.channels () == 2 && c.sample_format () == cpal::SampleFormat::F32);
let config = supported_configs_range.next ()
.ok_or_else (|| anyhow! ("can't get stereo f32 audio output"))?
.with_sample_rate (cpal::SampleRate (SAMPLE_RATE))
.config ();
#[derive (Default)] #[derive (Default)]
struct DecoderState { struct DecoderState {
pcm_buffers: PcmBuffers, pcm_buffers: PcmBuffers,
quit: bool, quit: bool,
} }
tracing_subscriber::fmt::init ();
tracing::error! ("frik");
let pair = Arc::new ((Mutex::new (DecoderState::default ()), Condvar::new ())); let pair = Arc::new ((Mutex::new (DecoderState::default ()), Condvar::new ()));
let pair2 = Arc::clone (&pair); let pair2 = Arc::clone (&pair);
let pair3 = Arc::clone (&pair); let pair3 = Arc::clone (&pair);
let args: Vec <_> = std::env::args ().collect ();
let filename = args.get (1)
.map (|s| s.to_string ())
.unwrap_or_else (|| "test-short.m4a".to_string ());
let thread_decoder = thread::spawn (move|| { let thread_decoder = thread::spawn (move|| {
let (lock, cvar) = &*pair2; let (lock, cvar) = &*pair2;
let mut input_ctx = ffmpeg_next::format::input (&"test.m4a")?; let mut input_ctx = ffmpeg_next::format::input (&filename)?;
let stream = input_ctx let stream = input_ctx
.streams () .streams ()
.best (ffmpeg_next::media::Type::Audio) .best (ffmpeg_next::media::Type::Audio)
@ -115,11 +117,12 @@ fn main () -> Result <()> {
)?; )?;
let mut frame_src = ffmpeg_next::util::frame::Audio::empty (); let mut frame_src = ffmpeg_next::util::frame::Audio::empty ();
let mut frame_resampled = ffmpeg_next::util::frame::Audio::empty (); let mut packets = input_ctx.packets ()
let mut packets = input_ctx.packets (); //.skip (15800)
;
'decoder_thread: loop { 'decoder_thread: loop {
// eprintln! ("decode thread parking"); // tracing::trace! ("decode thread parking");
let mut decoder_state = cvar.wait_while (lock.lock ().unwrap (), |decoder_state| { let mut decoder_state = cvar.wait_while (lock.lock ().unwrap (), |decoder_state| {
decoder_state.pcm_buffers.samples_available () >= 24_000 && decoder_state.pcm_buffers.samples_available () >= 24_000 &&
@ -135,21 +138,27 @@ fn main () -> Result <()> {
let pcm_buffers = &mut decoder_state.pcm_buffers; let pcm_buffers = &mut decoder_state.pcm_buffers;
'fill_buffer: while pcm_buffers.samples_available () < 48_000 { 'fill_buffer: while pcm_buffers.samples_available () < 48_000 {
//eprintln! ("Decoder is trying to work..."); // tracing::trace! ("Decoder is trying to work...");
match resampler.delay () { match resampler.delay () {
Some (x) if x.milliseconds > 500 => { Some (x) if x.milliseconds > 500 => {
eprintln! ("flushing resampler"); // tracing::trace! ("flushing resampler");
if let Some (_) = resampler.flush (&mut frame_resampled)? { let mut frame_resampled = ffmpeg_next::util::frame::Audio::empty ();
if resampler.flush (&mut frame_resampled).is_ok () {
pcm_buffers.produce_bytes (frame_resampled.data (0)); pcm_buffers.produce_bytes (frame_resampled.data (0));
continue 'fill_buffer; continue 'fill_buffer;
} }
else {
// tracing::warn! ("resampler flushed out a zero-length frame?");
}
}, },
_ => {}, _ => {},
} }
if decoder.receive_frame (&mut frame_src).is_ok () { if decoder.receive_frame (&mut frame_src).is_ok () {
//eprintln! ("decoder.receive_frame"); //eprintln! ("decoder.receive_frame");
let mut frame_resampled = ffmpeg_next::util::frame::Audio::empty ();
resampler.run (&frame_src, &mut frame_resampled)?; resampler.run (&frame_src, &mut frame_resampled)?;
pcm_buffers.produce_bytes (frame_resampled.data (0)); pcm_buffers.produce_bytes (frame_resampled.data (0));
continue 'fill_buffer; continue 'fill_buffer;
@ -168,22 +177,55 @@ fn main () -> Result <()> {
//eprintln! ("Decoder ran out of work"); //eprintln! ("Decoder ran out of work");
if resampler.delay ().is_some () { if resampler.delay ().is_some () {
eprintln! ("flushing resampler"); tracing::trace! ("flushing resampler");
if let Some (_) = resampler.flush (&mut frame_resampled)? { let mut frame_resampled = ffmpeg_next::util::frame::Audio::empty ();
if resampler.flush (&mut frame_resampled).is_ok () {
//eprintln! ("resampler.flush"); //eprintln! ("resampler.flush");
pcm_buffers.produce_bytes (frame_resampled.data (0)); pcm_buffers.produce_bytes (frame_resampled.data (0));
continue 'fill_buffer; continue 'fill_buffer;
} }
} }
break 'fill_buffer; tracing::info! ("Decoder thread is out of work, quitting");
break 'decoder_thread;
} }
} }
tracing::debug! ("Dropping resampler...");
drop (resampler);
sleep (Duration::from_secs (3));
tracing::debug! ("Dropping decoder...");
drop (decoder);
sleep (Duration::from_secs (3));
tracing::debug! ("Dropping input_ctx...");
drop (input_ctx);
sleep (Duration::from_secs (3));
Ok::<_, anyhow::Error> (()) Ok::<_, anyhow::Error> (())
}); });
{ let host = cpal::default_host ();
let device = host.default_output_device ().ok_or_else (|| anyhow! ("can't open cpal device"))?;
let mut supported_configs_range = device.supported_output_configs ()?
.filter (|c| c.channels () == 2 && c.sample_format () == cpal::SampleFormat::F32);
let config = supported_configs_range.next ()
.ok_or_else (|| anyhow! ("can't get stereo f32 audio output"))?
.with_sample_rate (cpal::SampleRate (SAMPLE_RATE))
.config ();
dbg! (config.clone ());
let pcm_quit = Arc::new ((Mutex::new (false), Condvar::new ()));
let pcm_quit2 = Arc::clone (&pcm_quit);
let stream = device.build_output_stream ( let stream = device.build_output_stream (
&config, &config,
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
@ -197,7 +239,16 @@ fn main () -> Result <()> {
let pcm_buffers = &mut decoder_state.pcm_buffers; let pcm_buffers = &mut decoder_state.pcm_buffers;
if ! pcm_buffers.consume_exact (data) { if ! pcm_buffers.consume_exact (data) {
eprintln! ("PCM buffer underflow"); // tracing::warn! ("PCM buffer underflow");
for x in data {
*x = 0.0;
}
let (lock, cvar) = &*pcm_quit;
let mut pcm_quit = lock.lock ().unwrap ();
*pcm_quit = true;
cvar.notify_one ();
} }
cvar.notify_one (); cvar.notify_one ();
@ -207,12 +258,13 @@ fn main () -> Result <()> {
}, },
); );
std::thread::sleep (std::time::Duration::from_millis (180_000)); let mut stream = Some (stream);
}
eprintln! ("Joining decoder thread"); // sleep (std::time::Duration::from_secs (3 * 60 + 40));
{ tracing::debug! ("Joining decoder thread...");
if false {
let mut decoder_state = pair3.0.lock ().unwrap (); let mut decoder_state = pair3.0.lock ().unwrap ();
decoder_state.quit = true; decoder_state.quit = true;
pair3.1.notify_one (); pair3.1.notify_one ();
@ -220,8 +272,16 @@ fn main () -> Result <()> {
thread_decoder.join ().unwrap ()?; thread_decoder.join ().unwrap ()?;
eprintln! ("Joined decoder thread"); tracing::debug! ("Joining PCM thread...");
let (lock, cvar) = &*pcm_quit2;
cvar.wait (lock.lock ().unwrap ());
stream = None;
sleep (Duration::from_secs (1));
tracing::info! ("Exiting cleanly.");
Ok (()) Ok (())
} }