]> git.sesse.net Git - nageru/blobdiff - alsa_input.cpp
Support audio-only FFmpeg inputs. Somewhat wonky, though.
[nageru] / alsa_input.cpp
index 158bfaa32e0e914d50a1a29efe52a6cec5fb7bd3..08a67f7fa7837ccabeb18a414eeaacf61d404bb3 100644 (file)
@@ -12,6 +12,7 @@
 #include "timebase.h"
 
 using namespace std;
+using namespace std::chrono;
 using namespace std::placeholders;
 
 #define RETURN_ON_ERROR(msg, expr) do {                                                    \
@@ -100,6 +101,7 @@ bool ALSAInput::open_device()
        default:
                assert(false);
        }
+       audio_format.sample_rate = sample_rate;
        //printf("num_periods=%u period_size=%u buffer_frames=%u sample_rate=%u bits_per_sample=%d\n",
        //      num_periods, unsigned(period_size), unsigned(buffer_frames), sample_rate, audio_format.bits_per_sample);
 
@@ -156,13 +158,14 @@ ALSAInput::~ALSAInput()
 
 void ALSAInput::start_capture_thread()
 {
-       should_quit = false;
+       assert(!device.empty());
+       should_quit.unquit();
        capture_thread = thread(&ALSAInput::capture_thread_func, this);
 }
 
 void ALSAInput::stop_capture_thread()
 {
-       should_quit = true;
+       should_quit.quit();
        capture_thread.join();
 }
 
@@ -172,17 +175,19 @@ void ALSAInput::capture_thread_func()
 
        // If the device hasn't been opened already, we need to do so
        // before we can capture.
-       while (!should_quit && pcm_handle == nullptr) {
+       while (!should_quit.should_quit() && pcm_handle == nullptr) {
                if (!open_device()) {
                        fprintf(stderr, "[%s] Waiting one second and trying again...\n",
                                device.c_str());
-                       sleep(1);
+                       should_quit.sleep_for(seconds(1));
                }
        }
 
-       if (should_quit) {
+       if (should_quit.should_quit()) {
                // Don't call free_card(); that would be a deadlock.
-               WARN_ON_ERROR("snd_pcm_close()", snd_pcm_close(pcm_handle));
+               if (pcm_handle) {
+                       WARN_ON_ERROR("snd_pcm_close()", snd_pcm_close(pcm_handle));
+               }
                pcm_handle = nullptr;
                return;
        }
@@ -204,7 +209,7 @@ void ALSAInput::capture_thread_func()
                        parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::STARTING);
                        fprintf(stderr, "[%s] Sleeping one second and restarting capture...\n",
                                device.c_str());
-                       sleep(1);
+                       should_quit.sleep_for(seconds(1));
                        break;
                }
        }
@@ -217,7 +222,7 @@ ALSAInput::CaptureEndReason ALSAInput::do_capture()
        parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::RUNNING);
 
        uint64_t num_frames_output = 0;
-       while (!should_quit) {
+       while (!should_quit.should_quit()) {
                int ret = snd_pcm_wait(pcm_handle, /*timeout=*/100);
                if (ret == 0) continue;  // Timeout.
                if (ret == -EPIPE) {
@@ -243,10 +248,11 @@ ALSAInput::CaptureEndReason ALSAInput::do_capture()
 
                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();
                bool success;
                do {
-                       if (should_quit) return CaptureEndReason::REQUESTED_QUIT;
-                       success = audio_callback(buffer.get(), frames, audio_format, pts - prev_pts);
+                       if (should_quit.should_quit()) return CaptureEndReason::REQUESTED_QUIT;
+                       success = audio_callback(buffer.get(), frames, audio_format, pts - prev_pts, now);
                } while (!success);
                num_frames_output += frames;
        }