Browse Source

Fix audio streaming and mac semaphores

...The reason why audio didn't work was because I overwrote the bitrate
values.

As for semaphores, mac doesn't support unnamed semaphores without using
mach semaphores.  So, I just implemented a semaphore wrapper for each
OS.
jp9000 11 years ago
parent
commit
585fd8f969

+ 5 - 5
libobs/media-io/audio-io.c

@@ -80,7 +80,7 @@ struct audio_output {
 	size_t                     planes;
 
 	pthread_t                  thread;
-	event_t                    stop_event;
+	os_event_t                 stop_event;
 
 	DARRAY(uint8_t)            mix_buffers[MAX_AV_PLANES];
 
@@ -437,7 +437,7 @@ static void *audio_thread(void *param)
 	uint64_t prev_time = os_gettime_ns() - buffer_time;
 	uint64_t audio_time;
 
-	while (event_try(audio->stop_event) == EAGAIN) {
+	while (os_event_try(audio->stop_event) == EAGAIN) {
 		os_sleep_ms(AUDIO_WAIT_TIME);
 
 		pthread_mutex_lock(&audio->line_mutex);
@@ -590,7 +590,7 @@ int audio_output_open(audio_t *audio, struct audio_output_info *info)
 		goto fail;
 	if (pthread_mutex_init(&out->input_mutex, NULL) != 0)
 		goto fail;
-	if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0)
+	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;
@@ -613,7 +613,7 @@ void audio_output_close(audio_t audio)
 		return;
 
 	if (audio->initialized) {
-		event_signal(audio->stop_event);
+		os_event_signal(audio->stop_event);
 		pthread_join(audio->thread, &thread_ret);
 	}
 
@@ -631,7 +631,7 @@ void audio_output_close(audio_t audio)
 		da_free(audio->mix_buffers[i]);
 
 	da_free(audio->inputs);
-	event_destroy(audio->stop_event);
+	os_event_destroy(audio->stop_event);
 	pthread_mutex_destroy(&audio->line_mutex);
 	bfree(audio);
 }

+ 12 - 12
libobs/media-io/video-io.c

@@ -50,13 +50,13 @@ struct video_output {
 
 	pthread_t                  thread;
 	pthread_mutex_t            data_mutex;
-	event_t                    stop_event;
+	os_event_t                 stop_event;
 
 	struct video_data          cur_frame;
 	struct video_data          next_frame;
 	bool                       new_frame;
 
-	event_t                    update_event;
+	os_event_t                 update_event;
 	uint64_t                   frame_time;
 	volatile uint64_t          cur_video_time;
 
@@ -125,13 +125,13 @@ static void *video_thread(void *param)
 	struct video_output *video = param;
 	uint64_t cur_time = os_gettime_ns();
 
-	while (event_try(video->stop_event) == EAGAIN) {
+	while (os_event_try(video->stop_event) == EAGAIN) {
 		/* wait half a frame, update frame */
 		cur_time += (video->frame_time/2);
 		os_sleepto_ns(cur_time);
 
 		video->cur_video_time = cur_time;
-		event_signal(video->update_event);
+		os_event_signal(video->update_event);
 
 		/* wait another half a frame, swap and output frames */
 		cur_time += (video->frame_time/2);
@@ -174,9 +174,9 @@ int video_output_open(video_t *video, struct video_output_info *info)
 		goto fail;
 	if (pthread_mutex_init(&out->input_mutex, NULL) != 0)
 		goto fail;
-	if (event_init(&out->stop_event, EVENT_TYPE_MANUAL) != 0)
+	if (os_event_init(&out->stop_event, OS_EVENT_TYPE_MANUAL) != 0)
 		goto fail;
-	if (event_init(&out->update_event, EVENT_TYPE_AUTO) != 0)
+	if (os_event_init(&out->update_event, OS_EVENT_TYPE_AUTO) != 0)
 		goto fail;
 	if (pthread_create(&out->thread, NULL, video_thread, out) != 0)
 		goto fail;
@@ -201,8 +201,8 @@ void video_output_close(video_t video)
 		video_input_free(&video->inputs.array[i]);
 	da_free(video->inputs);
 
-	event_destroy(video->update_event);
-	event_destroy(video->stop_event);
+	os_event_destroy(video->update_event);
+	os_event_destroy(video->stop_event);
 	pthread_mutex_destroy(&video->data_mutex);
 	pthread_mutex_destroy(&video->input_mutex);
 	bfree(video);
@@ -342,8 +342,8 @@ bool video_output_wait(video_t video)
 {
 	if (!video) return false;
 
-	event_wait(video->update_event);
-	return event_try(video->stop_event) == EAGAIN;
+	os_event_wait(video->update_event);
+	return os_event_try(video->stop_event) == EAGAIN;
 }
 
 uint64_t video_getframetime(video_t video)
@@ -364,8 +364,8 @@ void video_output_stop(video_t video)
 		return;
 
 	if (video->initialized) {
-		event_signal(video->stop_event);
+		os_event_signal(video->stop_event);
 		pthread_join(video->thread, &thread_ret);
-		event_signal(video->update_event);
+		os_event_signal(video->update_event);
 	}
 }

+ 85 - 1
libobs/util/threading-posix.c

@@ -16,6 +16,9 @@
 
 #ifdef __APPLE__
 #include <sys/time.h>
+#include <mach/semaphore.h>
+#else
+#include <semaphore.h>
 #endif
 
 #include "bmem.h"
@@ -45,7 +48,7 @@ int event_init(event_t *event, enum event_type type)
 		return code;
 	}
 
-	data->manual = (type == EVENT_TYPE_MANUAL);
+	data->manual = (type == OS_EVENT_TYPE_MANUAL);
 	data->signalled = false;
 	*event = data;
 
@@ -149,3 +152,84 @@ void event_reset(event_t event)
 	event->signalled = false;
 	pthread_mutex_unlock(&event->mutex);
 }
+
+#ifdef __APPLE__
+
+struct os_sem_data {
+	semaphore_t sem;
+	task_t      task;
+};
+
+int  os_sem_init(os_sem_t *sem, int value)
+{
+	semaphore_t new_sem;
+	task_t      task = mach_task_self();
+
+	if (semaphore_create(task, &new_sem, 0, value) != KERN_SUCCESS)
+		return -1;
+
+	*sem = bzalloc(sizeof(struct os_sem_data));
+	(*sem)->sem  = new_sem;
+	(*sem)->task = task;
+	return 0;
+}
+
+void os_sem_destroy(os_sem_t sem)
+{
+	if (sem) {
+		semaphore_destroy(sem->task, sem->sem);
+		bfree(sem);
+	}
+}
+
+int  os_sem_post(os_sem_t sem)
+{
+	if (!sem) return -1;
+	return (semaphore_signal(sem->sem) == KERN_SUCCESS) ? 0 : -1;
+}
+
+int  os_sem_wait(os_sem_t sem)
+{
+	if (!sem) return -1;
+	return (semaphore_wait(sem->sem) == KERN_SUCCESS) ? 0 : -1;
+}
+
+#else
+
+struct os_sem_data {
+	sem_t sem;
+};
+
+int  os_sem_init(os_sem_t *sem, int value)
+{
+	sem_t new_sem;
+	int ret = sem_init(&new_sem, 0, value);
+	if (ret != 0)
+		return ret;
+
+	*sem = bzalloc(sizeof(struct os_sem_data));
+	(*sem)->sem = new_sem;
+	return 0;
+}
+
+void os_sem_destroy(os_sem_t sem)
+{
+	if (sem) {
+		semaphore_destroy(&sem->sem);
+		bfree(sem);
+	}
+}
+
+int  os_sem_post(os_sem_t sem)
+{
+	if (!sem) return -1;
+	return sem_post(&sem->sem);
+}
+
+int  os_sem_wait(os_sem_t sem)
+{
+	if (!sem) return -1;
+	return sem_wait(&sem->sem);
+}
+
+#endif

+ 49 - 11
libobs/util/threading-windows.c

@@ -20,27 +20,31 @@
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
-struct event_data {
+struct os_event_data {
 	HANDLE handle;
 };
 
-int event_init(event_t *event, enum event_type type)
+struct os_sem_data {
+	HANDLE handle;
+};
+
+int os_event_init(os_event_t *event, enum os_event_type type)
 {
 	HANDLE handle;
-	struct event_data *data;
+	struct os_event_data *data;
 
-	handle = CreateEvent(NULL, (type == EVENT_TYPE_MANUAL), FALSE, NULL);
+	handle = CreateEvent(NULL, (type == OS_EVENT_TYPE_MANUAL), FALSE, NULL);
 	if (!handle)
 		return -1;
 
-	data = bmalloc(sizeof(struct event_data));
+	data = bmalloc(sizeof(struct os_event_data));
 	data->handle = handle;
 
 	*event = data;
 	return 0;
 }
 
-void event_destroy(event_t event)
+void os_event_destroy(os_event_t event)
 {
 	if (event) {
 		CloseHandle(event->handle);
@@ -48,7 +52,7 @@ void event_destroy(event_t event)
 	}
 }
 
-int event_wait(event_t event)
+int os_event_wait(os_event_t event)
 {
 	DWORD code;
 
@@ -62,7 +66,7 @@ int event_wait(event_t event)
 	return 0;
 }
 
-int event_timedwait(event_t event, unsigned long milliseconds)
+int os_event_timedwait(os_event_t event, unsigned long milliseconds)
 {
 	DWORD code;
 
@@ -78,7 +82,7 @@ int event_timedwait(event_t event, unsigned long milliseconds)
 	return 0;
 }
 
-int event_try(event_t event)
+int os_event_try(os_event_t event)
 {
 	DWORD code;
 
@@ -94,7 +98,7 @@ int event_try(event_t event)
 	return 0;
 }
 
-int event_signal(event_t event)
+int os_event_signal(os_event_t event)
 {
 	if (!event)
 		return EINVAL;
@@ -105,10 +109,44 @@ int event_signal(event_t event)
 	return 0;
 }
 
-void event_reset(event_t event)
+void os_event_reset(os_event_t event)
 {
 	if (!event)
 		return;
 
 	ResetEvent(event->handle);
 }
+
+int  os_sem_init(os_sem_t *sem, int value)
+{
+	HANDLE handle = CreateSemaphore(NULL, (LONG)value, 0x7FFFFFFF, NULL);
+	if (!handle)
+		return -1;
+
+	*sem = bzalloc(sizeof(struct os_sem_data));
+	(*sem)->handle = handle;
+	return 0;
+}
+
+void os_sem_destroy(os_sem_t sem)
+{
+	if (sem) {
+		CloseHandle(sem->handle);
+		bfree(sem);
+	}
+}
+
+int  os_sem_post(os_sem_t sem)
+{
+	if (!sem) return -1;
+	return ReleaseSemaphore(sem->handle, 1, NULL) ? 0 : -1;
+}
+
+int  os_sem_wait(os_sem_t sem)
+{
+	DWORD ret;
+
+	if (!sem) return -1;
+	ret = WaitForSingleObject(sem->handle, INFINITE);
+	return (ret == WAIT_OBJECT_0) ? 0 : -1;
+}

+ 19 - 14
libobs/util/threading.h

@@ -28,11 +28,9 @@
 
 #ifdef _MSC_VER
 #include "../../deps/w32-pthreads/pthread.h"
-#include "../../deps/w32-pthreads/semaphore.h"
 #else
 #include <errno.h>
 #include <pthread.h>
-#include <semaphore.h>
 #endif
 
 #ifdef __cplusplus
@@ -46,21 +44,28 @@ static inline void pthread_mutex_init_value(pthread_mutex_t *mutex)
 	*mutex = init_val;
 }
 
-enum event_type {
-	EVENT_TYPE_AUTO,
-	EVENT_TYPE_MANUAL
+enum os_event_type {
+	OS_EVENT_TYPE_AUTO,
+	OS_EVENT_TYPE_MANUAL
 };
 
-struct event_data;
-typedef struct event_data *event_t;
+struct os_event_data;
+struct os_sem_data;
+typedef struct os_event_data *os_event_t;
+typedef struct os_sem_data   *os_sem_t;
 
-EXPORT int  event_init(event_t *event, enum event_type type);
-EXPORT void event_destroy(event_t event);
-EXPORT int  event_wait(event_t event);
-EXPORT int  event_timedwait(event_t event, unsigned long milliseconds);
-EXPORT int  event_try(event_t event);
-EXPORT int  event_signal(event_t event);
-EXPORT void event_reset(event_t event);
+EXPORT int  os_event_init(os_event_t *event, enum os_event_type type);
+EXPORT void os_event_destroy(os_event_t event);
+EXPORT int  os_event_wait(os_event_t event);
+EXPORT int  os_event_timedwait(os_event_t event, unsigned long milliseconds);
+EXPORT int  os_event_try(os_event_t event);
+EXPORT int  os_event_signal(os_event_t event);
+EXPORT void os_event_reset(os_event_t event);
+
+EXPORT int  os_sem_init(os_sem_t *sem, int value);
+EXPORT void os_sem_destroy(os_sem_t sem);
+EXPORT int  os_sem_post(os_sem_t sem);
+EXPORT int  os_sem_wait(os_sem_t sem);
 
 
 #ifdef __cplusplus

+ 28 - 29
plugins/obs-ffmpeg/obs-ffmpeg-output.c

@@ -71,8 +71,8 @@ struct ffmpeg_output {
 	bool               write_thread_active;
 	pthread_mutex_t    write_mutex;
 	pthread_t          write_thread;
-	sem_t              write_sem;
-	event_t            stop_event;
+	os_sem_t           write_sem;
+	os_event_t         stop_event;
 
 	DARRAY(AVPacket)   packets;
 };
@@ -368,12 +368,15 @@ static void ffmpeg_data_free(struct ffmpeg_data *data)
 	memset(data, 0, sizeof(struct ffmpeg_data));
 }
 
-static bool ffmpeg_data_init(struct ffmpeg_data *data, const char *filename)
+static bool ffmpeg_data_init(struct ffmpeg_data *data, const char *filename,
+		int vbitrate, int abitrate)
 {
 	bool is_rtmp = false;
 
 	memset(data, 0, sizeof(struct ffmpeg_data));
 	data->filename_test = filename;
+	data->video_bitrate = vbitrate;
+	data->audio_bitrate = abitrate;
 
 	if (!filename || !*filename)
 		return false;
@@ -386,8 +389,10 @@ static bool ffmpeg_data_init(struct ffmpeg_data *data, const char *filename)
 	/* TODO: settings */
 	avformat_alloc_output_context2(&data->output, NULL,
 			is_rtmp ? "flv" : NULL, data->filename_test);
-	data->output->oformat->video_codec = AV_CODEC_ID_H264;
-	data->output->oformat->audio_codec = AV_CODEC_ID_AAC;
+	if (is_rtmp) {
+		data->output->oformat->video_codec = AV_CODEC_ID_H264;
+		data->output->oformat->audio_codec = AV_CODEC_ID_AAC;
+	}
 
 	if (!data->output) {
 		blog(LOG_WARNING, "Couldn't create avformat context");
@@ -435,9 +440,9 @@ static void *ffmpeg_output_create(obs_data_t settings, obs_output_t output)
 
 	if (pthread_mutex_init(&data->write_mutex, NULL) != 0)
 		goto fail;
-	if (event_init(&data->stop_event, EVENT_TYPE_AUTO) != 0)
+	if (os_event_init(&data->stop_event, OS_EVENT_TYPE_AUTO) != 0)
 		goto fail;
-	if (sem_init(&data->write_sem, 0, 0) != 0)
+	if (os_sem_init(&data->write_sem, 0) != 0)
 		goto fail;
 
 	signal_handler_add(obs_output_signalhandler(output),
@@ -450,7 +455,7 @@ static void *ffmpeg_output_create(obs_data_t settings, obs_output_t output)
 
 fail:
 	pthread_mutex_destroy(&data->write_mutex);
-	event_destroy(data->stop_event);
+	os_event_destroy(data->stop_event);
 	bfree(data);
 	return NULL;
 }
@@ -468,8 +473,8 @@ static void ffmpeg_output_destroy(void *data)
 		ffmpeg_output_stop(output);
 
 		pthread_mutex_destroy(&output->write_mutex);
-		sem_destroy(&output->write_sem);
-		event_destroy(output->stop_event);
+		os_sem_destroy(output->write_sem);
+		os_event_destroy(output->stop_event);
 		bfree(data);
 	}
 }
@@ -535,7 +540,7 @@ static void receive_video(void *param, const struct video_data *frame)
 		pthread_mutex_lock(&output->write_mutex);
 		da_push_back(output->packets, &packet);
 		pthread_mutex_unlock(&output->write_mutex);
-		sem_post(&output->write_sem);
+		os_sem_post(output->write_sem);
 
 	} else {
 		data->vframe->pts = data->total_frames;
@@ -559,7 +564,7 @@ static void receive_video(void *param, const struct video_data *frame)
 			pthread_mutex_lock(&output->write_mutex);
 			da_push_back(output->packets, &packet);
 			pthread_mutex_unlock(&output->write_mutex);
-			sem_post(&output->write_sem);
+			os_sem_post(output->write_sem);
 		} else {
 			ret = 0;
 		}
@@ -618,7 +623,7 @@ static inline void encode_audio(struct ffmpeg_output *output,
 	pthread_mutex_lock(&output->write_mutex);
 	da_push_back(output->packets, &packet);
 	pthread_mutex_unlock(&output->write_mutex);
-	sem_post(&output->write_sem);
+	os_sem_post(output->write_sem);
 }
 
 static bool prepare_audio(struct ffmpeg_data *data,
@@ -680,7 +685,6 @@ static bool process_packet(struct ffmpeg_output *output)
 {
 	AVPacket packet;
 	bool new_packet = false;
-	uint64_t time1, time2;
 	int ret;
 
 	pthread_mutex_lock(&output->write_mutex);
@@ -694,7 +698,10 @@ static bool process_packet(struct ffmpeg_output *output)
 	if (!new_packet)
 		return true;
 
-	time1 = os_gettime_ns();
+	/*blog(LOG_DEBUG, "size = %d, flags = %lX, stream = %d, "
+			"packets queued: %lu",
+			packet.size, packet.flags,
+			packet.stream_index, output->packets.num);*/
 
 	ret = av_interleaved_write_frame(output->ff_data.output, &packet);
 	if (ret < 0) {
@@ -706,12 +713,6 @@ static bool process_packet(struct ffmpeg_output *output)
 		return false;
 	}
 
-	time2 = os_gettime_ns();
-	/*blog(LOG_DEBUG, "%llu, size = %d, flags = %lX, stream = %d, "
-			"packets queued: %lu: time1; %llu",
-			time2-time1, packet.size, packet.flags,
-			packet.stream_index, output->packets.num, time1);*/
-
 	return true;
 }
 
@@ -719,9 +720,9 @@ static void *write_thread(void *data)
 {
 	struct ffmpeg_output *output = data;
 
-	while (sem_wait(&output->write_sem) == 0) {
+	while (os_sem_wait(output->write_sem) == 0) {
 		/* check to see if shutting down */
-		if (event_try(output->stop_event) == 0)
+		if (os_event_try(output->stop_event) == 0)
 			break;
 
 		if (!process_packet(output)) {
@@ -758,10 +759,8 @@ static bool try_connect(struct ffmpeg_output *output)
 	if (!filename_test || !*filename_test)
 		return false;
 
-	output->ff_data.video_bitrate = video_bitrate;
-	output->ff_data.audio_bitrate = audio_bitrate;
-
-	if (!ffmpeg_data_init(&output->ff_data, filename_test))
+	if (!ffmpeg_data_init(&output->ff_data, filename_test,
+				video_bitrate, audio_bitrate))
 		return false;
 
 	struct audio_convert_info aci = {
@@ -827,8 +826,8 @@ static void ffmpeg_output_stop(void *data)
 		audio_output_disconnect(obs_audio(), receive_audio, data);
 
 		if (output->write_thread_active) {
-			event_signal(output->stop_event);
-			sem_post(&output->write_sem);
+			os_event_signal(output->stop_event);
+			os_sem_post(output->write_sem);
 			pthread_join(output->write_thread, NULL);
 			output->write_thread_active = false;
 		}

+ 5 - 5
test/test-input/test-sinewave.c

@@ -7,7 +7,7 @@
 struct sinewave_data {
 	bool         initialized_thread;
 	pthread_t    thread;
-	event_t      event;
+	os_event_t   event;
 	obs_source_t source;
 };
 
@@ -28,7 +28,7 @@ static void *sinewave_thread(void *pdata)
 	double cos_val = 0.0;
 	uint8_t bytes[480];
 
-	while (event_try(swd->event) == EAGAIN) {
+	while (os_event_try(swd->event) == EAGAIN) {
 		if (!os_sleepto_ns(last_time += 10000000))
 			last_time = os_gettime_ns();
 
@@ -71,11 +71,11 @@ static void sinewave_destroy(void *data)
 	if (swd) {
 		if (swd->initialized_thread) {
 			void *ret;
-			event_signal(swd->event);
+			os_event_signal(swd->event);
 			pthread_join(swd->thread, &ret);
 		}
 
-		event_destroy(swd->event);
+		os_event_destroy(swd->event);
 		bfree(swd);
 	}
 }
@@ -86,7 +86,7 @@ static void *sinewave_create(obs_data_t settings,
 	struct sinewave_data *swd = bzalloc(sizeof(struct sinewave_data));
 	swd->source = source;
 
-	if (event_init(&swd->event, EVENT_TYPE_MANUAL) != 0)
+	if (os_event_init(&swd->event, OS_EVENT_TYPE_MANUAL) != 0)
 		goto fail;
 	if (pthread_create(&swd->thread, NULL, sinewave_thread, swd) != 0)
 		goto fail;