void AudioMixer::reset_resampler(DeviceSpec device_spec)
{
- lock_guard<mutex> lock(audio_mutex);
+ lock_guard<timed_mutex> lock(audio_mutex);
reset_resampler_mutex_held(device_spec);
}
}
}
-void AudioMixer::add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, AudioFormat audio_format, int64_t frame_length)
+bool AudioMixer::add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, AudioFormat audio_format, int64_t frame_length)
{
AudioDevice *device = find_audio_device(device_spec);
- lock_guard<mutex> lock(audio_mutex);
+ unique_lock<timed_mutex> lock(audio_mutex, defer_lock);
+ if (!lock.try_lock_for(chrono::milliseconds(10))) {
+ return false;
+ }
if (device->resampling_queue == nullptr) {
// No buses use this device; throw it away.
- return;
+ return true;
}
unsigned num_channels = device->interesting_channels.size();
int64_t local_pts = device->next_local_pts;
device->resampling_queue->add_input_samples(local_pts / double(TIMEBASE), audio.data(), num_samples);
device->next_local_pts = local_pts + frame_length;
+ return true;
}
-void AudioMixer::add_silence(DeviceSpec device_spec, unsigned samples_per_frame, unsigned num_frames, int64_t frame_length)
+bool AudioMixer::add_silence(DeviceSpec device_spec, unsigned samples_per_frame, unsigned num_frames, int64_t frame_length)
{
AudioDevice *device = find_audio_device(device_spec);
- lock_guard<mutex> lock(audio_mutex);
+ unique_lock<timed_mutex> lock(audio_mutex, defer_lock);
+ if (!lock.try_lock_for(chrono::milliseconds(10))) {
+ return false;
+ }
if (device->resampling_queue == nullptr) {
// No buses use this device; throw it away.
- return;
+ return true;
}
unsigned num_channels = device->interesting_channels.size();
// is always the same.
device->next_local_pts += frame_length;
}
+ return true;
}
AudioMixer::AudioDevice *AudioMixer::find_audio_device(DeviceSpec device)
map<DeviceSpec, vector<float>> samples_card;
vector<float> samples_bus;
- lock_guard<mutex> lock(audio_mutex);
+ lock_guard<timed_mutex> lock(audio_mutex);
// Pick out all the interesting channels from all the cards.
// TODO: If the card has been hotswapped, the number of channels
map<DeviceSpec, DeviceInfo> AudioMixer::get_devices() const
{
- lock_guard<mutex> lock(audio_mutex);
+ lock_guard<timed_mutex> lock(audio_mutex);
return get_devices_mutex_held();
}
{
AudioDevice *device = find_audio_device(device_spec);
- lock_guard<mutex> lock(audio_mutex);
+ lock_guard<timed_mutex> lock(audio_mutex);
device->name = name;
}
void AudioMixer::set_input_mapping(const InputMapping &new_input_mapping)
{
- lock_guard<mutex> lock(audio_mutex);
+ lock_guard<timed_mutex> lock(audio_mutex);
map<DeviceSpec, set<unsigned>> interesting_channels;
for (const InputMapping::Bus &bus : new_input_mapping.buses) {
InputMapping AudioMixer::get_input_mapping() const
{
- lock_guard<mutex> lock(audio_mutex);
+ lock_guard<timed_mutex> lock(audio_mutex);
return input_mapping;
}
~AudioMixer();
void reset_resampler(DeviceSpec device_spec);
- // frame_length is in TIMEBASE units.
- void add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, bmusb::AudioFormat audio_format, int64_t frame_length);
- void add_silence(DeviceSpec device_spec, unsigned samples_per_frame, unsigned num_frames, int64_t frame_length);
+ // Add audio (or silence) to the given device's queue. Can return false if
+ // the lock wasn't successfully taken; if so, you should simply try again.
+ // (This is to avoid a deadlock where a card hangs on the mutex in add_audio()
+ // while we are trying to shut it down from another thread that also holds
+ // the mutex.) frame_length is in TIMEBASE units.
+ bool add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, bmusb::AudioFormat audio_format, int64_t frame_length);
+ bool add_silence(DeviceSpec device_spec, unsigned samples_per_frame, unsigned num_frames, int64_t frame_length);
+
std::vector<float> get_output(double pts, unsigned num_samples, ResamplingQueue::RateAdjustmentPolicy rate_adjustment_policy);
// See comments inside get_output().
unsigned num_cards;
- mutable std::mutex audio_mutex;
+ mutable std::timed_mutex audio_mutex;
AudioDevice video_cards[MAX_VIDEO_CARDS]; // Under audio_mutex.
fprintf(stderr, "Card %d dropped %d frame(s) (before timecode 0x%04x), inserting silence.\n",
card_index, dropped_frames, timecode);
- audio_mixer.add_silence(device, silence_samples, dropped_frames, frame_length);
+ bool success;
+ do {
+ success = audio_mixer.add_silence(device, silence_samples, dropped_frames, frame_length);
+ } while (!success);
}
audio_mixer.add_audio(device, audio_frame.data + audio_offset, num_samples, audio_format, frame_length);