X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Falsa_input.cpp;h=511dda95738cd63b2dcdd30ff1ae67f5bc318ff6;hb=f9024d141398e69e7b4011becd3ebbe37eaa1776;hp=08a67f7fa7837ccabeb18a414eeaacf61d404bb3;hpb=9b7d691b4cc5db7dbfc18c82e86c1207fcac4722;p=nageru diff --git a/nageru/alsa_input.cpp b/nageru/alsa_input.cpp index 08a67f7..511dda9 100644 --- a/nageru/alsa_input.cpp +++ b/nageru/alsa_input.cpp @@ -9,7 +9,7 @@ #include "alsa_pool.h" #include "bmusb/bmusb.h" -#include "timebase.h" +#include "shared/timebase.h" using namespace std; using namespace std::chrono; @@ -111,6 +111,9 @@ bool ALSAInput::open_device() snd_pcm_sw_params_alloca(&sw_params); RETURN_FALSE_ON_ERROR("snd_pcm_sw_params_current()", snd_pcm_sw_params_current(pcm_handle, sw_params)); RETURN_FALSE_ON_ERROR("snd_pcm_sw_params_set_start_threshold", snd_pcm_sw_params_set_start_threshold(pcm_handle, sw_params, num_periods * period_size / 2)); + RETURN_FALSE_ON_ERROR("snd_pcm_sw_params_set_tstamp_mode", snd_pcm_sw_params_set_tstamp_mode(pcm_handle, sw_params, SND_PCM_TSTAMP_ENABLE)); + RETURN_FALSE_ON_ERROR("snd_pcm_sw_params_set_tstamp_type", snd_pcm_sw_params_set_tstamp_type(pcm_handle, sw_params, SND_PCM_TSTAMP_TYPE_MONOTONIC)); + RETURN_FALSE_ON_ERROR("snd_pcm_sw_params()", snd_pcm_sw_params(pcm_handle, sw_params)); RETURN_FALSE_ON_ERROR("snd_pcm_nonblock()", snd_pcm_nonblock(pcm_handle, 1)); @@ -171,6 +174,14 @@ void ALSAInput::stop_capture_thread() void ALSAInput::capture_thread_func() { + if (!done_init) { + char thread_name[16]; + snprintf(thread_name, sizeof(thread_name), "ALSA_C_%d", internal_dev_index); + pthread_setname_np(pthread_self(), thread_name); + + done_init = true; + } + parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::STARTING); // If the device hasn't been opened already, we need to do so @@ -221,7 +232,8 @@ ALSAInput::CaptureEndReason ALSAInput::do_capture() RETURN_ON_ERROR("snd_pcm_start()", snd_pcm_start(pcm_handle)); parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::RUNNING); - uint64_t num_frames_output = 0; + snd_pcm_status_t *status; + snd_pcm_status_alloca(&status); while (!should_quit.should_quit()) { int ret = snd_pcm_wait(pcm_handle, /*timeout=*/100); if (ret == 0) continue; // Timeout. @@ -233,7 +245,14 @@ ALSAInput::CaptureEndReason ALSAInput::do_capture() } RETURN_ON_ERROR("snd_pcm_wait()", ret); - snd_pcm_sframes_t frames = snd_pcm_readi(pcm_handle, buffer.get(), buffer_frames); + ret = snd_pcm_status(pcm_handle, status); + RETURN_ON_ERROR("snd_pcm_status()", ret); + + snd_pcm_sframes_t avail = snd_pcm_status_get_avail(status); + snd_htimestamp_t alsa_ts; + snd_pcm_status_get_htstamp(status, &alsa_ts); + + snd_pcm_sframes_t frames = snd_pcm_readi(pcm_handle, buffer.get(), avail); if (frames == -EPIPE) { fprintf(stderr, "[%s] ALSA overrun\n", device.c_str()); snd_pcm_prepare(pcm_handle); @@ -246,21 +265,13 @@ ALSAInput::CaptureEndReason ALSAInput::do_capture() } RETURN_ON_ERROR("snd_pcm_readi()", frames); - const int64_t prev_pts = frames_to_pts(num_frames_output); - const int64_t pts = frames_to_pts(num_frames_output + frames); - const steady_clock::time_point now = steady_clock::now(); + // NOTE: This assumes steady_clock::time_point is the same as clock_gettime(CLOCK_MONOTONIC). + const steady_clock::time_point ts = steady_clock::time_point(seconds(alsa_ts.tv_sec) + nanoseconds(alsa_ts.tv_nsec)); bool success; do { if (should_quit.should_quit()) return CaptureEndReason::REQUESTED_QUIT; - success = audio_callback(buffer.get(), frames, audio_format, pts - prev_pts, now); + success = audio_callback(buffer.get(), frames, audio_format, ts); } while (!success); - num_frames_output += frames; } return CaptureEndReason::REQUESTED_QUIT; } - -int64_t ALSAInput::frames_to_pts(uint64_t n) const -{ - return (n * TIMEBASE) / sample_rate; -} -