int audio_output_open(audio_t *audio, media_t media, struct audio_info *info) { struct audio_output *out; if (!valid_audio_params(info)) return AUDIO_OUTPUT_INVALIDPARAM; out = bmalloc(sizeof(struct audio_output)); memset(out, 0, sizeof(struct audio_output)); memcpy(&out->info, info, sizeof(struct audio_info)); pthread_mutex_init_value(&out->line_mutex); out->media = media; out->block_size = get_audio_channels(info->speakers) * get_audio_bytes_per_channel(info->format); if (pthread_mutex_init(&out->line_mutex, NULL) != 0) goto fail; if (event_init(&out->stop_event, true) != 0) goto fail; if (!ao_add_to_media(out)) goto fail; if (pthread_create(&out->thread, NULL, audio_thread, out) != 0) goto fail; out->initialized = true; *audio = out; return AUDIO_OUTPUT_SUCCESS; fail: audio_output_close(out); return AUDIO_OUTPUT_FAIL; }
/* * Create a new pulse audio stream and connect to it * * Return a negative value on error */ static int pulse_connect_stream(struct pulse_data *data) { pa_sample_spec spec; spec.format = data->format; spec.rate = data->samples_per_sec; spec.channels = get_audio_channels(data->speakers); if (!pa_sample_spec_valid(&spec)) { blog(LOG_ERROR, "pulse-input: Sample spec is not valid"); return -1; } data->bytes_per_frame = pa_frame_size(&spec); blog(LOG_DEBUG, "pulse-input: %u bytes per frame", (unsigned int) data->bytes_per_frame); pa_buffer_attr attr; attr.fragsize = get_buffer_size(data, 250); attr.maxlength = (uint32_t) -1; attr.minreq = (uint32_t) -1; attr.prebuf = (uint32_t) -1; attr.tlength = (uint32_t) -1; data->stream = pa_stream_new_with_proplist(data->context, obs_source_getname(data->source), &spec, NULL, data->props); if (!data->stream) { blog(LOG_ERROR, "pulse-input: Unable to create stream"); return -1; } pa_stream_flags_t flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY; if (pa_stream_connect_record(data->stream, NULL, &attr, flags) < 0) { blog(LOG_ERROR, "pulse-input: Unable to connect to stream"); return -1; } for (;;) { pulse_iterate(data); pa_stream_state_t state = pa_stream_get_state(data->stream); if (state == PA_STREAM_READY) { blog(LOG_DEBUG, "pulse-input: Stream ready"); break; } if (!PA_STREAM_IS_GOOD(state)) { blog(LOG_ERROR, "pulse-input: Stream connect failed"); return -1; } } return 0; }
int audio_output_open(audio_t *audio, struct audio_output_info *info) { struct audio_output *out; pthread_mutexattr_t attr; bool planar = is_audio_planar(info->format); if (!valid_audio_params(info)) return AUDIO_OUTPUT_INVALIDPARAM; out = bzalloc(sizeof(struct audio_output)); if (!out) goto fail; memcpy(&out->info, info, sizeof(struct audio_output_info)); pthread_mutex_init_value(&out->line_mutex); out->channels = get_audio_channels(info->speakers); out->planes = planar ? out->channels : 1; out->block_size = (planar ? 1 : out->channels) * get_audio_bytes_per_channel(info->format); if (pthread_mutexattr_init(&attr) != 0) goto fail; if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) goto fail; if (pthread_mutex_init(&out->line_mutex, &attr) != 0) goto fail; if (pthread_mutex_init(&out->input_mutex, NULL) != 0) goto fail; if (os_event_init(&out->stop_event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; if (pthread_create(&out->thread, NULL, audio_thread, out) != 0) goto fail; out->initialized = true; *audio = out; return AUDIO_OUTPUT_SUCCESS; fail: audio_output_close(out); return AUDIO_OUTPUT_FAIL; }
int set_audio_config(int fd_audio, FILE * file) { int tmp, format, frequency, channels; tmp = format = (int)get_audio_bits(file); ioctl(fd_audio, SNDCTL_DSP_SETFMT, &format); if (tmp != format) return -1; tmp = frequency = get_audio_frq(file); ioctl(fd_audio, SOUND_PCM_WRITE_RATE, &frequency); if (tmp != frequency) return -1; tmp = channels = get_audio_channels(file); ioctl(fd_audio, SNDCTL_DSP_CHANNELS, &channels); if (tmp != channels) return -1; printf("Configuration : %d %d %d\n", format, frequency, channels); return 0; }