Activate user-selected audio devices

- Fix a bug where the initial audio data insertion would cause all
   audio data to unintentionally clear (mixed up < and > operators, damn
   human error)

 - Fixed a potential interdependant lock scenario with channel mutex
   locks and graphics mutex locks.  The main video thread could lock the
   graphics mutex and then while in the graphics mutex could lock the
   channels mutex.  Meanwhile in another thread, the channel mutex could
   get locked, and then the graphics mutex would get locked, causing a
   deadlock.

   The best way to deal with this is to not let mutexes lock within
   other mutexes, but sometimes it's difficult to avoid such as in the
   main video thread.

 - Audio devices should now be functional, and the devices in the audio
   settings can now be changed as desired.
This commit is contained in:
jp9000 2014-03-07 17:03:34 -07:00
parent 2c3a3f4e65
commit f2ee950746
9 changed files with 96 additions and 21 deletions

View file

@ -144,21 +144,23 @@ static inline uint64_t conv_frames_to_time(audio_t audio, uint32_t frames)
/* ------------------------------------------------------------------------- */
/* this only really happens with the very initial data insertion. can be
* ignored safely. */
static inline void clear_excess_audio_data(struct audio_line *line,
uint64_t prev_time)
{
size_t size = ts_diff_bytes(line->audio, prev_time,
line->base_timestamp);
blog(LOG_WARNING, "Excess audio data for audio line '%s', somehow "
"audio data went back in time by %"PRIu32" bytes. "
"prev_time: %"PRIu64", line->base_timestamp: %"PRIu64,
line->name, (uint32_t)size,
prev_time, line->base_timestamp);
/*blog(LOG_DEBUG, "Excess audio data for audio line '%s', somehow "
"audio data went back in time by %"PRIu32" bytes. "
"prev_time: %"PRIu64", line->base_timestamp: %"PRIu64,
line->name, (uint32_t)size,
prev_time, line->base_timestamp);*/
for (size_t i = 0; i < line->audio->planes; i++) {
size_t clear_size = (size > line->buffers[i].size) ?
(size_t)size : line->buffers[i].size;
size_t clear_size = (size < line->buffers[i].size) ?
size : line->buffers[i].size;
circlebuf_pop_front(&line->buffers[i], NULL, clear_size);
}

View file

@ -94,20 +94,20 @@ void obs_view_setsource(obs_view_t view, uint32_t channel,
pthread_mutex_lock(&view->channels_mutex);
obs_source_addref(source);
prev_source = view->channels[channel];
view->channels[channel] = source;
if (source) {
obs_source_addref(source);
pthread_mutex_unlock(&view->channels_mutex);
if (source)
obs_source_activate(source, AUX_VIEW);
}
if (prev_source) {
obs_source_deactivate(prev_source, AUX_VIEW);
obs_source_release(prev_source);
}
pthread_mutex_unlock(&view->channels_mutex);
}
void obs_view_render(obs_view_t view)

View file

@ -727,6 +727,8 @@ void obs_set_output_source(uint32_t channel, obs_source_t source)
pthread_mutex_lock(&view->channels_mutex);
obs_source_addref(source);
prev_source = view->channels[channel];
calldata_setint(&params, "channel", channel);
@ -738,17 +740,15 @@ void obs_set_output_source(uint32_t channel, obs_source_t source)
view->channels[channel] = source;
if (source) {
obs_source_addref(source);
pthread_mutex_unlock(&view->channels_mutex);
if (source)
obs_source_activate(source, MAIN_VIEW);
}
if (prev_source) {
obs_source_deactivate(prev_source, MAIN_VIEW);
obs_source_release(prev_source);
}
pthread_mutex_unlock(&view->channels_mutex);
}
void obs_enum_outputs(bool (*enum_proc)(void*, obs_output_t), void *param)

View file

@ -181,6 +181,27 @@ void OBSApp::OBSInit()
mainWindow->OBSInit();
}
#ifdef __APPLE__
#define INPUT_AUDIO_SOURCE "coreaudio_input_capture
#define OUTPUT_AUDIO_SOURCE "coreaudio_output_capture
#elif _WIN32
#define INPUT_AUDIO_SOURCE "wasapi_input_capture"
#define OUTPUT_AUDIO_SOURCE "wasapi_output_capture"
#else
#define INPUT_AUDIO_SOURCE ""
#define OUTPUT_AUDIO_SOURCE ""
#endif
const char *OBSApp::InputAudioSource() const
{
return INPUT_AUDIO_SOURCE;
}
const char *OBSApp::OutputAudioSource() const
{
return OUTPUT_AUDIO_SOURCE;
}
struct NoFocusFrameStyle : QProxyStyle
{
void drawControl(ControlElement element, const QStyleOption *option,

View file

@ -56,6 +56,9 @@ public:
return textLookup.GetString(lookupVal);
}
const char *InputAudioSource() const;
const char *OutputAudioSource() const;
const char *GetRenderModule() const;
};

View file

@ -144,6 +144,8 @@ void OBSBasic::OBSInit()
obs_load_module("win-wasapi");
obs_load_module("win-capture");
#endif
ResetAudioDevices();
}
OBSBasic::~OBSBasic()
@ -419,9 +421,48 @@ bool OBSBasic::ResetAudio()
return obs_reset_audio(&ai);
}
bool OBSBasic::ResetAudioDevices()
void OBSBasic::ResetAudioDevice(const char *sourceId, const char *deviceName,
int channel)
{
return false;
const char *deviceId = config_get_string(basicConfig, "Audio",
deviceName);
obs_source_t source;
obs_data_t settings;
bool same = false;
source = obs_get_output_source(channel);
if (source) {
settings = obs_source_getsettings(source);
const char *curId = obs_data_getstring(settings, "device_id");
same = (strcmp(curId, deviceId) == 0);
obs_data_release(settings);
obs_source_release(source);
}
if (!same)
obs_set_output_source(channel, nullptr);
if (!same && strcmp(deviceId, "disabled") != 0) {
obs_data_t settings = obs_data_create();
obs_data_setstring(settings, "device_id", deviceId);
source = obs_source_create(OBS_SOURCE_TYPE_INPUT,
sourceId, deviceName, settings);
obs_data_release(settings);
obs_set_output_source(channel, source);
obs_source_release(source);
}
}
void OBSBasic::ResetAudioDevices()
{
ResetAudioDevice(App()->OutputAudioSource(), "DesktopDevice1", 1);
ResetAudioDevice(App()->OutputAudioSource(), "DesktopDevice2", 2);
ResetAudioDevice(App()->InputAudioSource(), "AuxDevice1", 3);
ResetAudioDevice(App()->InputAudioSource(), "AuxDevice2", 4);
ResetAudioDevice(App()->InputAudioSource(), "AuxDevice3", 5);
}
void OBSBasic::ResizePreview(uint32_t cx, uint32_t cy)

View file

@ -82,7 +82,9 @@ public:
bool ResetVideo();
bool ResetAudio();
bool ResetAudioDevices();
void ResetAudioDevice(const char *sourceId, const char *deviceName,
int channel);
void ResetAudioDevices();
void NewProject();
void SaveProject();

View file

@ -481,7 +481,7 @@ void OBSBasicSettings::SaveAudioSettings()
QString desktopDevice2 = GetComboData(ui->desktopAudioDevice2);
QString auxDevice1 = GetComboData(ui->auxAudioDevice1);
QString auxDevice2 = GetComboData(ui->auxAudioDevice2);
QString auxDevice3 = GetComboData(ui->auxAudioDevice2);
QString auxDevice3 = GetComboData(ui->auxAudioDevice3);
const char *channelSetup;
if (channelSetupIdx == 0)
@ -509,6 +509,8 @@ void OBSBasicSettings::SaveAudioSettings()
QT_TO_UTF8(auxDevice2));
config_set_string(main->Config(), "Audio", "AuxDevice3",
QT_TO_UTF8(auxDevice3));
main->ResetAudioDevices();
}
void OBSBasicSettings::SaveSettings()

View file

@ -92,6 +92,10 @@ WASAPISource::WASAPISource(obs_data_t settings, obs_source_t source_,
inline WASAPISource::~WASAPISource()
{
if (active)
blog(LOG_INFO, "WASAPI: Device '%s' Terminated",
device_name.c_str());
SetEvent(stopSignal);
if (active)